/* * ep - extended pipelining * * conf.c - command line and config file parsing implementation * ____________________________________________________________ * * Developed by Ondrej Jombik * and Lubomir Host * Copyright (c) 2000-2003 Platon SDG, http://platon.sk/ * All rights reserved. * * See README file for more information about this software. * See COPYING file for license information. * * Download the latest version from * http://platon.sk/projects/ep/ */ /* $Platon: ep/src/conf.c,v 1.40 2003/05/03 09:58:19 nepto Exp $ */ /* Includes {{{ */ #include #include #include #include #include #include "platon-str.h" #include "fd.h" #include "proctable.h" #include "proclink.h" #include "message.h" #include "conf.h" /* }}} */ /* Static variables {{{ */ static char *section_boundaries[2] = {"[", "]"}; static char *name_vs_stream_separator[4] = {".", "..", "-", NULL}; static char *global_str = "Global"; static char *process_str = "Process"; /* }}} */ /* Options structures (used only with libcfg+ context) {{{ */ static struct conf_struct_global global_cfg; static struct conf_struct_process process_cfg; /* }}} */ /* Options contexts {{{ */ static CFG_CONTEXT global_context = NULL; static CFG_CONTEXT process_context = NULL; /* }}} */ /* Global options {{{ */ static struct cfg_option global_options[] = { /* } */ { "help", 'h', NULL, CFG_BOOLEAN + CFG_MULTI, (void *) &(global_cfg.help), 0 }, {"quiet", 'q', "quiet", CFG_BOOLEAN, (void *) &(global_cfg.quiet), 0}, {"verbose", 'v', "verbose", CFG_BOOLEAN + CFG_MULTI, (void *) &(global_cfg.verbose), 0}, {"config-file", 'f', NULL, CFG_STRING + CFG_MULTI, (void *) &(global_cfg.config_file), 0}, {"disable-global-config",'\0',NULL,CFG_BOOLEAN,(void*)&(global_cfg.disable_global_config),0}, {"disable-user-config",'\0',NULL,CFG_BOOLEAN,(void*)&(global_cfg.disable_user_config),0}, {"case-insensitive-names",'\0',NULL,CFG_BOOLEAN,(void*)&(global_cfg.case_insensitive_names),0}, {"fast-data-transfer",'F',"fast data transfer",CFG_BOOLEAN,(void*)&(global_cfg.fast_data_transfer),0}, CFG_END_OF_LIST }; /* }}} */ /* Process options {{{ */ static struct cfg_option process_options[] = { /* } */ {"nice", 'N', "nice", CFG_INT, (void *) &(process_cfg.nice), 0}, {"name", 'n', "name", CFG_STRING+CFG_MULTI_SEPARATED, (void *) &(process_cfg.name), 0}, {"input", 'i', "input", CFG_STRING+CFG_MULTI_SEPARATED, (void *) &(process_cfg.fd_str[0]), 0}, {"output", 'o', "output", CFG_STRING+CFG_MULTI_SEPARATED, (void *)&(process_cfg.fd_str[1]),0}, {"errput", 'e', "errput", CFG_STRING+CFG_MULTI_SEPARATED, (void *)&(process_cfg.fd_str[2]),0}, {NULL, '\0', "command", CFG_LEFTOVER_ARGS+CFG_STRING+CFG_MULTI_SEPARATED, (void *)&(process_cfg.argv),0}, CFG_END_OF_LIST }; /* }}} */ /* Static function declarations {{{ */ static void print_cfg_error(const CFG_CONTEXT con); static int test_process_cfg_argv(const char *config_filename); static char *get_user_config_filename(void); static void clear_global_cfg(void); static void clear_process_cfg(void); static int check_context(CFG_CONTEXT *context, struct cfg_option options[]); static int is_cfgfile_section(char *section_str); static void free_global(struct conf_struct_global **global); static void free_processes(struct conf_struct_process ***processes); static int get_processes_index_by_name( struct conf_struct_process **processes, char *name); static int add_global_cfg_to_global(struct conf_struct_global **global); static int add_process_cfg_to_processes( struct conf_struct_process ***processes, int *size); static int add_processes_to_processes( struct conf_struct_process ***dest_processes, struct conf_struct_process **src_processes); static int add_processes_to_proctable( PROCTABLE *p_ptbl, struct conf_struct_process **processes, int start_idx_size, int *start_idx); /* }}} */ /* * Function definitions */ /* PARSING SCHEME (do not delete) {{{ * ------------------------------ * * conf_cmdline_parse_process(); * if (error) { * conf_cmdline_parse_global(); * if (err) { * fail; * } * * if (config_file) { * conf_cfgfile_parse_all(); * } * } * * while(1) { * * conf_cmdline_parse_process(); * * if (error) { * fail; * } * } */ /* }}} */ int conf_init(void) {/* {{{ */ return check_context(&global_context, global_options) && check_context(&process_context, process_options); } /* }}} */ void conf_destroy(void) { /* {{{ */ if (global_context != NULL) cfg_free_context(global_context); if (process_context != NULL) cfg_free_context(process_context); } /* }}} */ PROCTABLE conf_parse_all(argc, argv) int argc; char **argv; { /* {{{ */ register int ret, i; struct conf_struct_global *global; struct conf_struct_global *global_work; struct conf_struct_process **processes; struct conf_struct_process **processes_work; PROCTABLE ptbl; int *start_idx; int start_idx_size; global = NULL; processes = NULL; ret = conf_cmdline_parse(argc - 1, argv + 1, &global, &processes); if (ret != CFG_OK) { /* TODO: better error information */ /* print_cfg_error(con, ret); */ if (ret == CFG_ERR_NOMEM) msg_error_print("not enough memory for command line parsing\n"); /* XXX: free structures */ free_global(&global); free_processes(&processes); return NULL; } if (global->help) { msg_usage_print(); free_global(&global); free_processes(&processes); return NULL; } for (start_idx_size = 0; global->config_file != NULL && global->config_file[start_idx_size] != NULL; start_idx_size++) ; start_idx_size += 3; /* command line, global config, homedir config */ start_idx = (int *) malloc(start_idx_size * sizeof(int)); if (start_idx == NULL) { msg_error_print("not enough memory for parsing indexes\n"); /* XXX: free structures */ free_global(&global); free_processes(&processes); return NULL; } start_idx[0] = 0; for (i = 0; i < start_idx_size - 1; i++) { register char *filename; if ((i == 0 && global->disable_global_config) || (i == 1 && global->disable_user_config)) continue; filename = i <= 0 ? conf_global_filename : i == 1 ? get_user_config_filename() : global->config_file[i - 2]; if (/* i == 1 && */ filename == NULL) { msg_error_print("not enough memory for filename buffer\n"); /* XXX: free structures */ free(start_idx); free_global(&global); free_processes(&processes); return NULL; } #if DEBUG msg_debug_print("conf_parse_all(): parsing file '%s'\n", filename); #endif global_work = NULL; processes_work = NULL; ret = conf_cfgfile_parse(filename, &global_work, &processes_work); /* TODO: Progressive config file type reporting in error messages. There are three types: global, local/user, user defined. */ if (ret != CFG_OK && (i >= 2 || (i < 2 && ret != CFG_ERR_FILE_NOT_FOUND))) { /* TODO: better error information */ /* print_cfg_error(con, ret); */ if (ret == CFG_ERR_NOMEM) msg_error_print("not enough memory for config file parsing\n"); if (ret == CFG_ERR_FILE_NOT_FOUND) msg_error_print("file '%s' not found\n", filename); /* msg_error_print("config file '%s' parsing error %d\n", filename, ret); */ /* XXX: free structures */ if (i == 1) free(filename); free(start_idx); free_global(&global_work); free_processes(&processes_work); free_global(&global); free_processes(&processes); return NULL; } for (start_idx[i + 1] = 0; processes_work != NULL && processes_work[start_idx[i + 1]] != NULL; start_idx[i + 1]++) ; start_idx[i + 1] += start_idx[i]; if (! add_processes_to_processes(&processes, processes_work)) { msg_error_print("not enough memory for config file '%s'" "process table merging\n", filename); /* XXX: free structures */ if (i == 1) free(filename); free(start_idx); free_global(&global_work); free_processes(&processes_work); free_global(&global); free_processes(&processes); return NULL; } if (i == 1) free(filename); free(global_work); free(processes_work); } #if DEBUG { register int dbg_i; register char *names; register char *argvs; msg_debug_print("conf_parse_all(): ret = %d\n", ret); msg_debug_print("verbose = %d\n", global->verbose); for (dbg_i = 0; processes != NULL && processes[dbg_i] != NULL; dbg_i++) { if (processes[dbg_i]->name != NULL) names = PLATON_FUNC(strdyn_implode_str) (processes[dbg_i]->name, ", "); else names = strdup("-- N/A --"); if (processes[dbg_i]->argv != NULL) argvs = PLATON_FUNC(strdyn_implode_str) (processes[dbg_i]->argv, " "); else argvs = strdup("-- N/A --"); msg_debug_print("Process %d\n", dbg_i); msg_debug_print(" NAMES: %s\n", names); msg_debug_print(" ARGVS: %s\n", argvs); free(names); free(argvs); } msg_debug_print("Indexes:\n"); for (dbg_i = 0; dbg_i < start_idx_size; dbg_i++) msg_debug_print(" %d -> %d\n", dbg_i, start_idx[dbg_i]); } #endif /* * Here are proccesses going to be added into new PROCTABLE. */ if ((ptbl = proctable_create(0)) == NULL || proctable_add_std_process(&ptbl) < 0) { msg_error_print("not enough memory\n"); /* XXX: free structures */ free(start_idx); free_global(&global); free_processes(&processes); return NULL; } if (add_processes_to_proctable(&ptbl, processes, start_idx_size, start_idx) < 0) { /* msg_error_print("not enough memory\n"); */ /* XXX: free structures */ proctable_destroy(&ptbl); free(start_idx); free_global(&global); free_processes(&processes); return NULL; } cfg = *global; free(start_idx); free_global(&global); free_processes(&processes); return ptbl; } /* }}} */ int conf_cfgfile_parse(filename, global, processes) char *filename; struct conf_struct_global **global; struct conf_struct_process ***processes; { /* {{{ */ register int ret; int processes_size; CFG_CONTEXT cur_context; *processes = NULL; processes_size = 0; clear_global_cfg(); clear_process_cfg(); cfg_reset_context(global_context); cfg_reset_context(process_context); /* Start at first line (0) and parse to end (-1) */ cfg_set_cfgfile_context(global_context, 0, -1, filename); cfg_set_cfgfile_context(process_context, 0, -1, filename); for (cur_context = global_context; ; ) { ret = cfg_parse(cur_context); if (ret != CFG_ERR_STOP_STR) { #if DEBUG msg_debug_print("detected %s error %d in <%s>\n", cur_context == process_context ? "process" : "global", ret, cfg_get_cur_opt(cur_context)); #endif break; } else { /* Section boundaries detected */ register int section_no; register char *section_str; section_str = cfg_get_cur_opt(cur_context); section_no = is_cfgfile_section(section_str); if (section_no > 0) { if (cur_context == process_context) { if (! test_process_cfg_argv(filename)) { ret = CFG_ERROR_STOP_STR; cur_context = NULL; break; } /* Adding to processes array */ if (! add_process_cfg_to_processes(processes, &processes_size)) return CFG_ERR_NOMEM; clear_process_cfg(); } /* If section name is correct, set appropriate context and continue with parsing on next line (it is that '+ 1'). */ if (section_no == 1) { /* [Global] section */ cfg_set_cfgfile_context(global_context, cfg_get_cur_idx(cur_context) + 1, -1, NULL); cur_context = global_context; } else { /* [Process] section */ cfg_set_cfgfile_context(process_context, cfg_get_cur_idx(cur_context) + 1, -1, NULL); cur_context = process_context; } } else { msg_error_print("unknown section '%s' in config file '%s'\n", section_str, filename); ret = CFG_ERROR_STOP_STR; cur_context = NULL; break; } } } /* Set returning parameters. */ if (ret == CFG_OK) { if (cur_context == process_context) { if (! test_process_cfg_argv(filename)) ret = CFG_ERROR_STOP_STR; else if (! add_process_cfg_to_processes(processes, &processes_size)) return CFG_ERR_NOMEM; } } if (! add_global_cfg_to_global(global)) return CFG_ERR_NOMEM; switch (ret) { case CFG_OK: case CFG_ERR_NOMEM: case CFG_ERR_FILE_NOT_FOUND: case CFG_ERR_STOP_STR_FOUND: break; default: print_cfg_error(cur_context); break; }; return ret; } /* }}} */ int conf_cmdline_parse(argc, argv, global, processes) int argc; char **argv; struct conf_struct_global **global; struct conf_struct_process ***processes; { /* {{{ */ register int ret = CFG_OK, first_loop, index; int processes_size; CFG_CONTEXT cur_context; *processes = NULL; processes_size = 0; clear_global_cfg(); clear_process_cfg(); cfg_reset_context(global_context); cfg_reset_context(process_context); cfg_set_cmdline_context(global_context, 0, argc, argv); cfg_set_cmdline_context(process_context, 0, argc, argv); /* * Yokotasi intelligent parser. :-) */ for (cur_context = process_context, first_loop = 1, index = 0; index < argc; first_loop = 0) { ret = cfg_parse(cur_context); if (ret < 0 && ret != CFG_ERR_STOP_STR_FOUND) { if (! first_loop) break; cur_context = global_context; /* not needed: cfg_set_cmdline_context_by_argc(cur_context, argc, argv); */ continue; } else if (ret == CFG_ERR_STOP_STR_FOUND) { register int cur_idx = cfg_get_cur_idx(cur_context); if (cur_idx - index < 1 && ! first_loop) { msg_error_print("double process separator '--'" " on command line\n"); break; } if (cur_idx + 1 >= argc) { msg_error_print("misplaced process separator '--'" " at the end of command line\n"); break; } if (cur_context == process_context) { if (first_loop && process_cfg.argv == NULL) { /* empty global options (./ep -- ...) are allowed */ } else { if (! test_process_cfg_argv(NULL)) { ret = CFG_ERROR_STOP_STR; break; } /* Adding to processes array */ if (! add_process_cfg_to_processes(processes, &processes_size)) return CFG_ERR_NOMEM; } clear_process_cfg(); } index = cur_idx + 1; cur_context = process_context; cfg_set_cmdline_context(cur_context, index, argc - index, argv); } else { /* ret == CFG_OK */ break; } } /* Set returning parameters. */ if (cur_context == process_context && ret == CFG_OK && cfg_get_cur_idx(cur_context) > 0) { if (! test_process_cfg_argv(NULL)) ret = CFG_ERROR_STOP_STR; else if (! add_process_cfg_to_processes(processes, &processes_size)) return CFG_ERR_NOMEM; } if (! add_global_cfg_to_global(global)) return CFG_ERR_NOMEM; switch (ret) { case CFG_OK: case CFG_ERR_NOMEM: case CFG_ERR_STOP_STR_FOUND: break; default: print_cfg_error(cur_context); break; }; return ret; } /* }}} */ /* * Static function definitions */ static void print_cfg_error(con) const CFG_CONTEXT con; { /* {{{ */ register char *s; if ((s = cfg_get_error_str(con)) == NULL) { msg_error_print("not enough memory for error message creating\n"); return; } msg_error_print("%s\n", s); free(s); return; } /* }}} */ /* Test if argv was specified */ static int test_process_cfg_argv(config_filename) const char *config_filename; { /* {{{ */ if (process_cfg.argv == NULL) { if (process_cfg.name != NULL && process_cfg.name[0]) { /* At least one process name is defined in this case */ if (config_filename != NULL) msg_error_print("process '%s' has not" " 'command' clausule in config file '%s'\n", process_cfg.name[0], config_filename); else msg_error_print("process '%s' has not specified" " what to run on command line\n", process_cfg.name[0]); } else { /* No process name is defined in this case */ if (config_filename != NULL) msg_error_print("some process has not" " 'command' clausule in config file '%s'\n", config_filename); else msg_error_print("some process has not specified" " what to run on command line\n"); } return 0; } return 1; } /* }}} */ static char * get_user_config_filename(void) { /* {{{ */ register char *homedir, *filename; if ((homedir = getenv("HOME")) == NULL) return strdup(conf_user_filename); filename = (char *) malloc((strlen(homedir) + strlen(conf_user_filename) + 2) * sizeof(char)); if (filename == NULL) return NULL; strcpy(filename, homedir); if (strlen(filename) > 0 && filename[strlen(filename) - 1] != '/') strcpy(filename + strlen(filename), "/"); strcpy(filename + strlen(filename), conf_user_filename); return filename; } /* }}} */ static void clear_global_cfg(void) { /* {{{ */ memset((void *) &global_cfg, '\0', sizeof(struct conf_struct_global)); } /* }}} */ static void clear_process_cfg(void) { /* {{{ */ memset((void *) &process_cfg, '\0', sizeof(struct conf_struct_process)); } /* }}} */ static int check_context(context, options) CFG_CONTEXT *context; struct cfg_option options[]; { /* {{{ */ if (*context == NULL) { if ((*context = cfg_get_context(options)) == NULL) return 0; cfg_set_context_flag(*context, CFG_PROCESS_FIRST); cfg_clear_context_flag(*context, CFG_SKIP_FIRST); cfg_set_context_flag(*context, CFG_FILE_LINE_POS_USAGE); /* TODO: one call for multi vals properties */ cfg_clear_property(*context, CFG_LINE_STOP_STRING); cfg_clear_property(*context, CFG_MULTI_VALS_SEPARATOR); cfg_clear_property(*context, CFG_FILE_STOP_PREFIX); if (! cfg_add_property(*context, CFG_LINE_STOP_STRING, "--") || ! cfg_add_property(*context, CFG_NORMAL_MULTI_VALS_SEPARATOR, ",") || ! cfg_add_property(*context, CFG_FILE_LEFTOVER_MULTI_VALS_SEPARATOR, " ") || ! cfg_add_property(*context, CFG_FILE_STOP_PREFIX, section_boundaries[0])) return 0; } return 1; } /* }}} */ static int is_cfgfile_section(section_str) char *section_str; { /* {{{ */ register int secstr_size = strlen(section_str); register int secb0_size = strlen(section_boundaries[0]); register int secb1_size = strlen(section_boundaries[1]); register int ret = 0; if (secstr_size > secb0_size + secb1_size && ! strncmp(section_str, section_boundaries[0], secb0_size) && ! strncmp(section_str + secstr_size - secb1_size, section_boundaries[1], secb1_size)) { register char *pos = section_str + secb0_size; while (isspace(*pos)) pos++; if (! strncasecmp(global_str, pos, strlen(global_str))) { pos += strlen(global_str); ret = 1; } else if (! strncasecmp(process_str, pos, strlen(process_str))) { pos += strlen(process_str); ret = 2; } while (ret > 0 && pos < section_str + secstr_size - secb1_size) if (isspace(*pos)) pos++; else ret = 0; } return ret; } /* }}} */ static void free_global(global) struct conf_struct_global **global; { /* {{{ */ if (*global == NULL) return; PLATON_FUNC(strdyn_safe_free)((*global)->config_file); free(*global); *global = NULL; } /* }}} */ static void free_processes(processes) struct conf_struct_process ***processes; { /* {{{ */ register int i, j; if (*processes == NULL) return; for (i = 0; (*processes)[i] != NULL; i++) { PLATON_FUNC(strdyn_safe_free)((*processes)[i]->name); PLATON_FUNC(strdyn_safe_free)((*processes)[i]->argv); for (j = 0; j < N_FD; j++) PLATON_FUNC(strdyn_safe_free)((*processes)[i]->fd_str[j]); free((*processes)[i]); } free(*processes); *processes = NULL; } /* }}} */ static int get_processes_index_by_name(processes, name) struct conf_struct_process **processes; char *name; { /* {{{ */ register int i; for (i = 0; processes != NULL && processes[i] != NULL; i++) if (processes[i]->name != NULL && ! PLATON_FUNC(strdyn_casecmp)(processes[i]->name, name)) return i; return -1; } /* }}} */ static int add_global_cfg_to_global(global) struct conf_struct_global **global; { /* {{{ */ *global = (struct conf_struct_global *) malloc(sizeof(struct conf_struct_global)); if (*global == NULL) return 0; **global = global_cfg; return 1; } /* }}} */ static int add_process_cfg_to_processes(processes, size) struct conf_struct_process ***processes; int *size; { /* {{{ */ register int items; for (items = 0; *processes != NULL && (*processes)[items] != NULL; items++) ; if (items + 1 >= *size) { #if DEBUG /* minimum increment value is 2 */ *size += 2; #else *size += 10; #endif *processes = (struct conf_struct_process **) realloc(*processes, sizeof(struct conf_struct_process*) * (*size)); if (*processes == NULL) return 0; } (*processes)[items] = (struct conf_struct_process *) malloc(sizeof(struct conf_struct_process)); if ((*processes)[items] == NULL) return 0; *((*processes)[items]) = process_cfg; (*processes)[items + 1] = NULL; return 1; } /* }}} */ static int add_processes_to_processes(dest_processes, src_processes) struct conf_struct_process ***dest_processes; struct conf_struct_process **src_processes; { /* {{{ */ register int i, dest_size, src_size; if (dest_processes == NULL) return 0; for (i = 0; *dest_processes != NULL && (*dest_processes)[i] != NULL; i++) ; dest_size = i; for (i = 0; src_processes != NULL && src_processes[i] != NULL; i++) ; src_size = i; *dest_processes = (struct conf_struct_process **) realloc(*dest_processes, sizeof(struct conf_struct_process*) * (dest_size + src_size + 1)); if (*dest_processes == NULL) return 0; for (i = 0; i < src_size; i++) (*dest_processes)[dest_size + i] = src_processes[i]; (*dest_processes)[dest_size + src_size] = NULL; return 1; } /* }}} */ /* * XXX: TODO: FIXME: reindexing proctable! remove +1 above too */ static int add_processes_to_proctable(p_ptbl, processes, start_idx_size, start_idx) PROCTABLE *p_ptbl; struct conf_struct_process **processes; int start_idx_size; int *start_idx; { /* {{{ */ register int i, j, k, idx; register int resource_idx = 0; register int ptbl_size, new_ptbl_size; PROCTABLE new_ptbl; ptbl_size = proctable_get_size(*p_ptbl); for (new_ptbl_size = 0; processes != NULL && processes[new_ptbl_size] != NULL; new_ptbl_size++) ; #if DEBUG msg_debug_print("add_processes_to_proctable():" " ptbl_size = %d, new_ptbl_size = %d\n", ptbl_size, new_ptbl_size); #endif if ((new_ptbl = proctable_create(new_ptbl_size)) == NULL) { msg_error_print("not enough memory for process table creation\n"); return -1; } for (i = 0; i < new_ptbl_size; i++) { /* Counting resource_idx. */ while (resource_idx < start_idx_size - 1 && start_idx[resource_idx + 1] <= i) resource_idx++; /* Checking processes names. */ for (j = 0; processes[i]->name != NULL && processes[i]->name[j] != NULL; j++) { idx = proctable_get_process_index_by_name( *p_ptbl, processes[i]->name[j]); if (idx >= 0) { msg_error_print("process %d from resource %d (%s) already" " exists in process table with index %d\n", j - start_idx[resource_idx], resource_idx, processes[i]->name[j], idx); return -1; } } new_ptbl[i]->pid = 0; new_ptbl[i]->nice = processes[i]->nice; new_ptbl[i]->name = PLATON_FUNC(strdyn_safe_duplicate) (processes[i]->name); new_ptbl[i]->argv = PLATON_FUNC(strdyn_safe_duplicate) (processes[i]->argv); /* Converting filedescriptors strings to indexes. */ for (j = 0; j < N_FD; j++) { register int size = processes[i]->fd_str[j] == NULL ? 0 : PLATON_FUNC(strdyn_get_size)(processes[i]->fd_str[j]); new_ptbl[i]->fd[j].n_link = 0; new_ptbl[i]->fd[j].pipe[0] = 0; new_ptbl[i]->fd[j].pipe[1] = 0; for (k = 0; k < size; k++) { struct proclink link; char **ar; register char *fd_str = NULL, *char_in_name; if (strlen(processes[i]->fd_str[j][k]) <= 0) continue; ar = PLATON_FUNC(strdyn_explode2_ar)(processes[i]->fd_str[j][k], name_vs_stream_separator); if (ar == NULL) { msg_error_print("not enough memory" " for link argument exploding\n"); proctable_destroy(&new_ptbl); return -1; } switch (PLATON_FUNC(strdyn_get_size)(ar)) { case 1: link.proc_id = 0; fd_str = ar[0]; break; case 2: for (char_in_name = ar[0]; isdigit(*char_in_name); char_in_name++) ; fd_str = ar[1]; /* * Process link initialization by local number */ if (*char_in_name == '\0') { char *end; link.proc_id = (int) strtol(ar[0], &end, 0); if ((end && *end == '\0') && link.proc_id >= 0) { if (link.proc_id == 0) /* 0 is always valid */ break; if (link.proc_id > 0) { link.proc_id--; /* make real index */ if (link.proc_id <= start_idx[resource_idx + 1] - start_idx[resource_idx] - 1) { link.proc_id += ptbl_size; link.proc_id += start_idx[resource_idx]; break; } } } msg_error_print("bad process number '%s'\n", ar[0]); proctable_destroy(&new_ptbl); PLATON_FUNC(strdyn_free)(ar); return -1; } /* * Process link initialization by name */ /* Searching name in original (old) proctable. */ link.proc_id = proctable_get_process_index_by_name( *p_ptbl, ar[0]); if (link.proc_id >= 0) break; /* Searching name in existing new proctable. * THIS IS ABSOLUTELY WRONG! * You cannot search proctable which is not already * built! link.proc_id = proctable_get_process_index_by_name( new_ptbl, ar[0]); if (link.proc_id >= 0) { link.proc_id += ptbl_size; break; } */ /* Searching name in processes. */ link.proc_id = get_processes_index_by_name( processes, ar[0]); if (link.proc_id >= 0) { link.proc_id += ptbl_size; /* link.proc_id += start_idx[resource_idx]; */ break; } msg_error_print("bad process name '%s'\n", ar[0]); proctable_destroy(&new_ptbl); PLATON_FUNC(strdyn_free)(ar); return -1; default: msg_error_print("bad link specification: %s\n", processes[i]->fd_str[j][k]); proctable_destroy(&new_ptbl); PLATON_FUNC(strdyn_free)(ar); return -1; } link.fd_id = fd_str_to_fd_id(fd_str); PLATON_FUNC(strdyn_free)(ar); /* fd_str points to ar[] */ if (link.fd_id < 0) { msg_error_print("bad stream specification '%s'\n", fd_str); proctable_destroy(&new_ptbl); return -1; } if (! fd_add_proclink(&(new_ptbl[i]->fd[j]), &link)) { msg_error_print("not enought memory for" " process link addition\n"); proctable_destroy(&new_ptbl); return -1; } } } } if (! proctable_join(p_ptbl, new_ptbl)) { msg_error_print("not enought memory for process table resize\n"); proctable_destroy(&new_ptbl); return -1; } return 0; } /* }}} */ /* Modeline for ViM {{{ * vim:set ts=4: * vim600:fdm=marker fdl=0 fdc=0: * }}} */