Súbor: [Platon] / ep / src / conf.c (stiahnutie)
Revízia 1.41, Fri Nov 28 17:35:11 2003 UTC (21 years, 1 month ago) by nepto
Zmeny od 1.40: +3 -3
[lines]
Changed URL from www.platon.sk to platon.sk.
|
/*
* ep - extended pipelining
*
* conf.c - command line and config file parsing implementation
* ____________________________________________________________
*
* Developed by Ondrej Jombik <nepto@platon.sk>
* and Lubomir Host <rajo@platon.sk>
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <platon/cfg+.h>
#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:
* }}} */
Platon Group <platon@platon.sk> http://platon.sk/
|