From e92cf71a8f4d51810de7c0f7a613402737d66168 Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Mon, 7 Jan 2013 17:40:47 +0200 Subject: Add function for parsing /etc/inittab. * src/limits.c (free_limits): New function. * src/pies.c (config_syntax): Move to pies.h (config_syntax_tab): New type "inittab" (free_action,component_free): New functions. (component_finish): Call component_free to discard the failed component. (main): In sysvinit mode, default to reading two configuration files: /etc/inittab and /etc/pies.init. Don't exit on configuration errors in this mode. * src/pies.h (str_to_config_syntax) (add_config,free_redirector) (component_free,free_limits) (inittab_parse): New protos. * src/progman.c (free_redirector): New function. * src/sysvinit.c (inittab_parse): New function. --- src/limits.c | 11 +- src/pies.c | 105 +++++++++-- src/pies.h | 16 ++ src/progman.c | 7 + src/sysvinit.c | 546 ++++++++++++++++++++++++++++++++++++++++----------------- 5 files changed, 506 insertions(+), 179 deletions(-) diff --git a/src/limits.c b/src/limits.c index 7b0f9be..6dadd6c 100644 --- a/src/limits.c +++ b/src/limits.c @@ -29,7 +29,8 @@ #define SET_LIMIT_LOGINS 0x0400 #define SET_LIMIT_PRIO 0x0800 -struct limits_rec { +struct limits_rec +{ unsigned set; rlim_t limit_as; rlim_t limit_cpu; @@ -296,3 +297,11 @@ parse_limits (limits_record_t *plrec, char *str, char **endp) return 0; } +void +free_limits (limits_record_t rec) +{ + if (rec) + free (rec); +} + + diff --git a/src/pies.c b/src/pies.c index beab6fa..2767d0a 100644 --- a/src/pies.c +++ b/src/pies.c @@ -60,13 +60,6 @@ struct obstack pp_stk; struct quoting_options *pp_qopt; -enum config_syntax - { - CONF_PIES, - CONF_META1, - CONF_INETD - }; - struct config_file { struct config_file *next; @@ -86,6 +79,7 @@ static struct config_syntax_descr config_syntax_tab[] = { { "pies" , CONF_PIES }, { "meta1", CONF_META1 }, { "inetd", CONF_INETD }, + { "inittab", CONF_INITTAB }, { NULL } }; @@ -328,6 +322,20 @@ static struct tokendef sig_tokendef[] = { #undef S +void +free_action (struct action *act) +{ + if (!act) + return; + if (act->nstat > 0) + free (act->status); + free (act->addr); + free (act->message); + free (act->command); + + free (act); +} + static struct action * create_action (struct component *comp, grecs_locus_t *locus, @@ -373,14 +381,14 @@ create_action (struct component *comp, continue; } } - else if (strtotok_ci (sig_tokendef, arg, &n)) + else if (strtotok_ci (sig_tokendef, arg, (int*) &n)) { grecs_error (locus, 0, _("%s: not a signal code"), arg); continue; } n |= STATUS_SIG_BIT; } - else if (strtotok_ci (ex_tokendef, arg, &n)) + else if (strtotok_ci (ex_tokendef, arg, (int *) &n)) { grecs_error (locus, 0, _("%s: not a return code"), arg); continue; @@ -1343,7 +1351,6 @@ component_verify (struct component *comp, grecs_locus_t *locus) { COMPERR (grecs_error, "%s", _("socket must be specified in this mode")); - /* FIXME: Memory leak */ return 1; } break; @@ -1369,9 +1376,11 @@ component_verify (struct component *comp, grecs_locus_t *locus) { COMPERR (grecs_error, "%s", _("socket must be specified in this mode")); - /* FIXME: Memory leak */ return 1; } + default: + /* FIXME: more checks perhaps */ + break; } if (comp->mode == pies_comp_inetd) @@ -1437,6 +1446,51 @@ component_create (const char *name) return comp; } +void +component_free (struct component *comp) +{ + size_t i; + + free (comp->tag); + free (comp->program); + if (comp->argv) + { + for (i = 0; i < comp->argc; i++) + free (comp->argv[i]); + free (comp->argv); + } + if (comp->env) + { + for (i = 0; comp->env[i]; i++) + free (comp->env[i]); + free (comp->env); + } + free (comp->dir); + grecs_list_free (comp->prereq); + grecs_list_free (comp->depend); + free (comp->rmfile); + free_limits (comp->limits); + free (comp->runlevels); + free (comp->service); + pies_url_destroy (&comp->socket_url); + free (comp->pass_fd_socket); + free (comp->tcpmux); + free (comp->access_denied_message); + free (comp->max_instances_message); + free (comp->max_ip_connections_message); + free_redirector (&comp->redir[0]); + free_redirector (&comp->redir[1]); + if (comp->act_head) + { + struct action *act; + + for (act = comp->act_head; act; act = act->next) + free_action (act); + } + + free (comp); +} + void component_finish (struct component *comp, grecs_locus_t *locus) { @@ -1447,6 +1501,8 @@ component_finish (struct component *comp, grecs_locus_t *locus) if (progman_lookup_component (comp->tag) == NULL) register_prog (comp); } + else + component_free (comp); } static int @@ -2115,6 +2171,13 @@ set_state_file_names (const char *base) qotdfile = mkfilename (statedir, base, ".qotd"); } +static void +config_error () +{ + if (!init_process) + exit (EX_CONFIG); +} + int main (int argc, char **argv) { @@ -2142,6 +2205,8 @@ main (int argc, char **argv) config_init (); if (init_process) { + add_config (CONF_INITTAB, "/etc/inittab"); + add_config (CONF_PIES, "/etc/pies.init"); for (index = 1; index < argc; index++) { if (!strcmp(argv[index], "single") || !strcmp(argv[index], "-s")) @@ -2162,9 +2227,7 @@ main (int argc, char **argv) #endif else if (strchr("0123456789sS", argv[index][0]) && !argv[index][1]) { - dfl_level = argv[index][0]; - if (dfl_level == 's') - dfl_level = 'S'; + dfl_level = toupper (argv[index][0]); } } } @@ -2182,7 +2245,8 @@ main (int argc, char **argv) log_tag = instance; - set_conf_file_names (instance); + if (!init_process) + set_conf_file_names (instance); if (init_process || !DEFAULT_PREPROCESSOR) grecs_preprocessor = NULL; @@ -2211,19 +2275,24 @@ main (int argc, char **argv) { struct grecs_node *tree = grecs_parse (file->name); if (!tree || grecs_tree_process (tree, pies_keywords)) - exit (EX_CONFIG); + config_error (); grecs_tree_free (tree); break; } case CONF_INETD: if (inetd_parse_conf (file->name)) - exit (EX_CONFIG); + config_error (); break; case CONF_META1: if (meta1_config_parse (file->name)) - exit (EX_CONFIG); + config_error (); + break; + + case CONF_INITTAB: + if (inittab_parse (file->name)) + config_error (); break; } } diff --git a/src/pies.h b/src/pies.h index ca50a26..28a27a7 100644 --- a/src/pies.h +++ b/src/pies.h @@ -278,6 +278,19 @@ extern char *console_device; extern int initdefault; extern int dfl_level; +enum config_syntax + { + CONF_PIES, + CONF_META1, + CONF_INETD, + CONF_INITTAB + }; + +int str_to_config_syntax (const char *str, enum config_syntax *psynt); +void add_config (enum config_syntax syntax, const char *name); + +void free_redirector (struct redirector *rp); + void register_prog (struct component *comp); int progman_running_p (void); size_t progman_running_count (void); @@ -335,6 +348,7 @@ int str_to_socket_type (const char *str, int *pret); int socket_type_to_str (int socket_type, const char **pres); struct component *component_create (const char *name); +void component_free (struct component *comp); void component_finish (struct component *comp, grecs_locus_t *locus); struct grecs_keyword *find_component_keyword (const char *ident); @@ -375,6 +389,7 @@ void enable_socket (int fd); int parse_limits (limits_record_t *plrec, char *str, char **endp); int set_limits (const char *name, limits_record_t lrec); +void free_limits (limits_record_t rec); void meta1_parser_set_debug (void); @@ -462,6 +477,7 @@ int is_comp_wait (struct component *comp); int is_valid_runlevel (int c); int console_open (int mode); int telinit (const char *arg); +int inittab_parse (const char *file); extern char *sysvinit_environ_hint[]; diff --git a/src/progman.c b/src/progman.c index 0463366..c9741d5 100644 --- a/src/progman.c +++ b/src/progman.c @@ -410,6 +410,13 @@ close_fds (fd_set *fdset) } } +void +free_redirector (struct redirector *rp) +{ + if (rp->type == redir_file) + free (rp->v.file); +} + int open_redirector (struct prog *master, int stream) { diff --git a/src/sysvinit.c b/src/sysvinit.c index 23cad9a..ca980b2 100644 --- a/src/sysvinit.c +++ b/src/sysvinit.c @@ -42,13 +42,13 @@ static int boot_trans_tab[max_boot_state][sizeof(valid_runlevels)-1] = { /* 0, 1, 2, 3, 4, */ /* 5, 6, 7, 8, 9, S */ /* sysinit */ { boot, boot, boot, boot, boot, - boot, boot, boot, boot, boot, single }, + boot, boot, boot, boot, boot, single }, /* boot */ { normal, normal, normal, normal, normal, - normal, normal, normal, normal, normal, normal }, + normal, normal, normal, normal, normal, normal }, /* single */ { boot, boot, boot, boot, boot, - boot, boot, boot, boot, boot, single }, + boot, boot, boot, boot, boot, single }, /* normal */ { normal, normal, normal, normal, normal, - normal, normal, normal, normal, normal, normal }, + normal, normal, normal, normal, normal, normal }, }; enum boot_state boot_state; @@ -67,10 +67,10 @@ console_open (int mode) { fd = open (console_device, mode | O_NONBLOCK); if (fd >= 0) - { - fcntl (fd, F_SETFL, mode); - return fd; - } + { + fcntl (fd, F_SETFL, mode); + return fd; + } } return -1; } @@ -92,28 +92,28 @@ console_stty () tty.c_cflag &= CBAUD|CBAUDEX|CSIZE|CSTOPB|PARENB|PARODD; tty.c_cflag |= HUPCL|CLOCAL|CREAD; - tty.c_cc[VINTR] = 3; /* ctrl('c') */ - tty.c_cc[VQUIT] = 28; /* ctrl('\\') */ + tty.c_cc[VINTR] = 3; /* ctrl('c') */ + tty.c_cc[VQUIT] = 28; /* ctrl('\\') */ tty.c_cc[VERASE] = 127; - tty.c_cc[VKILL] = 24; /* ctrl('x') */ - tty.c_cc[VEOF] = 4; /* ctrl('d') */ + tty.c_cc[VKILL] = 24; /* ctrl('x') */ + tty.c_cc[VEOF] = 4; /* ctrl('d') */ tty.c_cc[VTIME] = 0; tty.c_cc[VMIN] = 1; - tty.c_cc[VSTART] = 17; /* ctrl('q') */ - tty.c_cc[VSTOP] = 19; /* ctrl('s') */ - tty.c_cc[VSUSP] = 26; /* ctrl('z') */ + tty.c_cc[VSTART] = 17; /* ctrl('q') */ + tty.c_cc[VSTOP] = 19; /* ctrl('s') */ + tty.c_cc[VSUSP] = 26; /* ctrl('z') */ /* - * Set pre and post processing + * Set pre and post processing */ tty.c_iflag = IGNPAR|ICRNL|IXON|IXANY; tty.c_oflag = OPOST|ONLCR; tty.c_lflag = ISIG|ICANON|ECHO|ECHOCTL|ECHOPRT|ECHOKE; /* - * Now set the terminal line. - * We don't care about non-transmitted output data - * and non-read input data. + * Now set the terminal line. + * We don't care about non-transmitted output data + * and non-read input data. */ tcsetattr (fd, TCSANOW, &tty); tcflush(fd, TCIOFLUSH); @@ -136,50 +136,52 @@ askrunlevel () while (1) { if (srl == srl_init) - { - write (fd, prompt, sizeof (prompt) - 1); - if (read (fd, &lvl, 1) != 1) - return 'S'; - srl = srl_char; - } + { + write (fd, prompt, sizeof (prompt) - 1); + if (read (fd, &lvl, 1) != 1) + return 'S'; + srl = srl_char; + } else if (srl == srl_n) - { - if (is_valid_runlevel (lvl)) - break; - srl = srl_init; - } + { + if (is_valid_runlevel (lvl)) + break; + srl = srl_init; + } else - { - if (read (fd, &c, 1) != 1) - { - if (!is_valid_runlevel (lvl)) - lvl = 'S'; + { + if (read (fd, &c, 1) != 1) + { + if (!is_valid_runlevel (lvl)) + lvl = 'S'; + break; + } + + switch (srl) + { + case srl_char: + if (c == '\r') + srl = srl_r; + else if (c == '\n') + srl = srl_n; + else + srl = srl_skip; + break; + + case srl_r: + if (c == '\n') + srl = srl_n; + else + srl = srl_skip; + break; + + case srl_skip: + if (c == '\n') + srl = srl_init; + default: break; - } - - switch (srl) - { - case srl_char: - if (c == '\r') - srl = srl_r; - else if (c == '\n') - srl = srl_n; - else - srl = srl_skip; - break; - - case srl_r: - if (c == '\n') - srl = srl_n; - else - srl = srl_skip; - break; - - case srl_skip: - if (c == '\n') - srl = srl_init; - } - } + } + } } close (fd); return toupper (lvl); @@ -216,28 +218,30 @@ enablecomp (struct prog *prog, void *data) { case sysinit: return comp->mode == pies_comp_sysinit; - + case boot: return comp->mode == pies_comp_boot || comp->mode == pies_comp_bootwait; - + case single: case normal: switch (comp->mode) - { - case pies_comp_sysinit: - case pies_comp_boot: - case pies_comp_bootwait: - return 0; - case pies_comp_powerfail: - case pies_comp_powerwait: - case pies_comp_powerokwait: - case pies_comp_ctrlaltdel: - case pies_comp_ondemand: - case pies_comp_powerfailnow: - case pies_comp_kbrequest: - /* FIXME */ - return 0; - } + { + case pies_comp_sysinit: + case pies_comp_boot: + case pies_comp_bootwait: + return 0; + case pies_comp_powerfail: + case pies_comp_powerwait: + case pies_comp_powerokwait: + case pies_comp_ctrlaltdel: + case pies_comp_ondemand: + case pies_comp_powerfailnow: + case pies_comp_kbrequest: + /* FIXME */ + return 0; + default: + break; + } } rc = !!strchr (comp->runlevels, runlevel); if (!rc) @@ -247,10 +251,10 @@ enablecomp (struct prog *prog, void *data) if (wait) { if (comp->mode == pies_comp_wait) - { - *wait = 1; - return 1; - } + { + *wait = 1; + return 1; + } return 0; } return rc; @@ -263,14 +267,14 @@ runlevel_setup_prog (struct prog *prog, void *data) { int rc = enablecomp (prog, data); if (rc < 0) - return 0; + return 0; if (rc) - prog->v.p.status = status_enabled; + prog->v.p.status = status_enabled; else - prog->v.p.status = status_disabled; + prog->v.p.status = status_disabled; debug (1, ("%s: %s", prog->tag, - prog->v.p.status == status_enabled ? - "enabled" : "disabled")); + prog->v.p.status == status_enabled ? + "enabled" : "disabled")); } return 0; } @@ -320,23 +324,23 @@ envsetup () { char *str = sysvinit_environ_hint[i]; switch (i) - { - case ENVI_PREVLEVEL: - str[strlen (str) - 1] = prevlevel; - break; - - case ENVI_RUNLEVEL: - str[strlen (str) - 1] = - boot_state_str[boot_state] == ' ' ? - (runlevel ? runlevel : '#') : boot_state_str[boot_state]; - break; - - case ENVI_CONSOLE: - if (strlen (console_device) >= sizeof (ENVTMPL_CONSOLE)) - logmsg (LOG_ERR, "console device name too long"); - else - strcpy (str + sizeof (ENVAR_CONSOLE) - 1, console_device); - } + { + case ENVI_PREVLEVEL: + str[strlen (str) - 1] = prevlevel; + break; + + case ENVI_RUNLEVEL: + str[strlen (str) - 1] = + boot_state_str[boot_state] == ' ' ? + (runlevel ? runlevel : '#') : boot_state_str[boot_state]; + break; + + case ENVI_CONSOLE: + if (strlen (console_device) >= sizeof (ENVTMPL_CONSOLE)) + logmsg (LOG_ERR, "console device name too long"); + else + strcpy (str + sizeof (ENVAR_CONSOLE) - 1, console_device); + } } } @@ -352,6 +356,8 @@ sysvinit_stop_filter (struct prog *prog, void *data) prog_stop (prog, SIGTERM); prog->v.p.status = status_disabled; /* See FIXME, progman.c:2364 */ break; + default: + break; } return 0; } @@ -371,7 +377,7 @@ sysvinit_fifo_handler (int fd, void *data) if (rc == -1) { logmsg (LOG_ERR, _("error reading from %s: %s"), INIT_FIFO, - strerror (errno)); + strerror (errno)); size = 0; return 0; } @@ -390,26 +396,26 @@ sysvinit_fifo_handler (int fd, void *data) if (size == sizeof (struct sysvinit_request)) { if (buf.req.magic != INIT_MAGIC) - logmsg (LOG_ERR, _("got invalid initreq")); + logmsg (LOG_ERR, _("got invalid initreq")); else - { - debug (1, ("INITREQ: cmd=%d, runlevel=%d, sleeptime=%d", - buf.req.cmd, buf.req.runlevel, buf.req.sleeptime)); - switch (buf.req.cmd) - { - case INIT_CMD_RUNLVL: - buf.req.runlevel = toupper (buf.req.runlevel); - if (buf.req.runlevel != runlevel) - { - progman_stop (); - dfl_level = buf.req.runlevel; - inittrans (); - } - break; - - /* FIXME: react on other commands */ - } - } + { + debug (1, ("INITREQ: cmd=%d, runlevel=%d, sleeptime=%d", + buf.req.cmd, buf.req.runlevel, buf.req.sleeptime)); + switch (buf.req.cmd) + { + case INIT_CMD_RUNLVL: + buf.req.runlevel = toupper (buf.req.runlevel); + if (buf.req.runlevel != runlevel) + { + progman_stop (); + dfl_level = buf.req.runlevel; + inittrans (); + } + break; + + /* FIXME: react on other commands */ + } + } size = 0; } return 0; @@ -424,25 +430,25 @@ create_fifo () if (stat (INIT_FIFO, &st) < 0) { if (errno != ENOENT) - { - logmsg (LOG_ERR, "cannot stat fifo %s: %s", INIT_FIFO, - strerror (errno)); - return; - } + { + logmsg (LOG_ERR, "cannot stat fifo %s: %s", INIT_FIFO, + strerror (errno)); + return; + } else if (mkfifo (INIT_FIFO, 0600)) - { - logmsg (LOG_ERR, "cannot create fifo %s: %s", INIT_FIFO, - strerror (errno)); - return; - } + { + logmsg (LOG_ERR, "cannot create fifo %s: %s", INIT_FIFO, + strerror (errno)); + return; + } } else { if (!S_ISFIFO (st.st_mode)) - { - logmsg (LOG_ERR, "not a fifo: %s", INIT_FIFO); - return; - } + { + logmsg (LOG_ERR, "not a fifo: %s", INIT_FIFO); + return; + } chmod (INIT_FIFO, 0600); } @@ -451,10 +457,10 @@ create_fifo () { fstat (fd, &fst); if (fst.st_dev != st.st_dev || fst.st_ino != st.st_ino) - { - deregister_socket (fd); - close (fd); - } + { + deregister_socket (fd); + close (fd); + } debug (1, ("reopening %s", INIT_FIFO)); } @@ -466,7 +472,7 @@ create_fifo () if (fd == -1) { logmsg (LOG_ERR, "cannot open %s: %s", INIT_FIFO, - strerror (errno)); + strerror (errno)); return; } register_socket (fd, sysvinit_fifo_handler, NULL); @@ -482,16 +488,16 @@ set_console_dev () for (i = 0; i < ARRAY_SIZE (try_console); i++) { if (try_console[i]) - { - int fd = open (try_console[i], O_RDONLY|O_NONBLOCK); - - if (fd >= 0) - { - close (fd); - console_device = try_console[i]; - return; - } - } + { + int fd = open (try_console[i], O_RDONLY|O_NONBLOCK); + + if (fd >= 0) + { + close (fd); + console_device = try_console[i]; + return; + } + } } /* provide default */ console_device = "/dev/null"; @@ -534,7 +540,7 @@ inittrans () if (newstate != boot_state) { debug (1, ("STATE TRANS: %s -> %s", boot_state_name[boot_state], - boot_state_name[newstate])); + boot_state_name[newstate])); boot_state = newstate; trans = 1; wait = 0; @@ -559,7 +565,7 @@ inittrans () { debug (1, ("RL TRANS: %c -> %c", runlevel, newlevel)); sysvinit_acct (SYSV_ACCT_RUNLEVEL, "runlevel", "~~", - newlevel + 256 * runlevel, "~"); + newlevel + 256 * runlevel, "~"); mf_proctitle_format ("init [%c]", newlevel); prevlevel = runlevel ? runlevel : 'N'; runlevel = newlevel; @@ -572,11 +578,11 @@ inittrans () { envsetup (); if (wait == 0) - { - sysvinit_runlevel_setup (&wait); - if (wait) - return 1; - } + { + sysvinit_runlevel_setup (&wait); + if (wait) + return 1; + } sysvinit_runlevel_setup (NULL); wait = 0; } @@ -596,6 +602,8 @@ is_comp_wait (struct component *comp) case pies_comp_powerfailnow: case pies_comp_kbrequest: return 0; + default: + break; } return 1; } @@ -630,10 +638,228 @@ telinit (const char *arg) if (write (fd, &req, sizeof (req)) != sizeof (req)) { logmsg (LOG_ERR, _("error writing to %s: %s"), - INIT_FIFO, strerror (errno)); + INIT_FIFO, strerror (errno)); exit (EX_UNAVAILABLE); } alarm (0); close (fd); exit (0); } + +static char * +getfld (char *str, char **endp) +{ + char *p; + + if (str) + { + p = strchr (str, ':'); + if (p) + *p++ = 0; + *endp = p; + } + else + *endp = NULL; + return str; +} + +struct action_parser +{ + const char *action; + enum pies_comp_mode mode; + int (*parser) (struct component *comp, const char *file, unsigned line); +}; + +static struct action_parser action_tab[] = { + { "wait", pies_comp_wait }, + { "once", pies_comp_once }, + { "boot", pies_comp_boot }, + { "bootwait", pies_comp_bootwait }, + { "powerfail", pies_comp_powerfail }, + { "powerwait", pies_comp_powerwait }, + { "powerokwait", pies_comp_powerokwait }, + { "ctrlaltdel", pies_comp_ctrlaltdel }, + { "ondemand", pies_comp_ondemand }, + { "sysinit", pies_comp_sysinit }, + { "powerfailnow", pies_comp_powerfailnow }, + { "kbrequest", pies_comp_kbrequest }, + { "respawn", pies_comp_respawn }, + { NULL } +}; + +static struct action_parser * +find_action_parser (const char *action) +{ + struct action_parser *ap; + + for (ap = action_tab; ap->action; ap++) + if (strcmp (ap->action, action) == 0) + return ap; + return NULL; +} + +int +inittab_parse (const char *file) +{ + FILE *fp; + size_t size = 0; + char *buf = NULL; + unsigned line_no = 0; + int err = 0; + + fp = fopen (file, "r"); + if (!fp) + { + logmsg (LOG_ERR, + _("cannot open configuration file %s: %s"), + file, strerror (errno)); + return 1; + } + + while (getline (&buf, &size, fp) >= 0) + { + char *id, *runlevels, *action, *process, *p; + struct action_parser *ap; + struct component *comp; + struct wordsplit ws; + + line_no++; + for (p = buf; *p && c_isblank (*p); p++) + ; + + if (!p || *p == '\n') + continue; + + if (*p == '#') + { + if (wordsplit (p+1, &ws, WRDSF_DEFFLAGS)) + { + logmsg (LOG_ERR, "%s:%u: wordsplit: %s", file, line_no, + strerror (errno)); + err = 1; + } + /* pies pragma debug N */ + /* pies pragma next FORMAT FILE */ + /* pies pragma stop */ + if (ws.ws_wordc > 2 && strcmp (ws.ws_wordv[0], "pies") == 0 && + strcmp (ws.ws_wordv[1], "pragma") == 0) + { + if (strcmp (ws.ws_wordv[2], "debug") == 0) + { + if (ws.ws_wordc == 4) + debug_level = atoi (ws.ws_wordv[3]); + } + else if (strcmp (ws.ws_wordv[2], "next") == 0) + { + if (ws.ws_wordc >= 5) + { + enum config_syntax synt; + + if (str_to_config_syntax (ws.ws_wordv[3], &synt)) + logmsg (LOG_ERR, "%s:%u: %s", + file, line_no, _("unknown syntax type")); + else + add_config (synt, ws.ws_wordv[4]); + } + else if (ws.ws_wordc == 4) + add_config (CONF_PIES, ws.ws_wordv[3]); + } + else if (strcmp (ws.ws_wordv[2], "stop") == 0) + { + wordsplit_free (&ws); + break; + } + } + + wordsplit_free (&ws); + continue; + } + + id = getfld (p, &p); + runlevels = getfld (p, &p); + action = getfld (p, &p); + process = p; + + if (!id || !runlevels || !action || !process) + { + logmsg (LOG_ERR, "%s:%u: %s", + file, line_no, _("not enough fields")); + err = 1; + continue; + } + + if (strcmp (action, "initdefault") == 0) + { + if (!runlevels[0] || !is_valid_runlevel (runlevels[0])) + { + logmsg (LOG_ERR, "%s:%u: %s", + file, line_no, _("invalid runlevel")); + err = 1; + } + else + initdefault = toupper (runlevels[0]); + continue; + } + + ap = find_action_parser (action); + if (!ap) + { + logmsg (LOG_ERR, "%s:%u: %s", + file, line_no, _("unknown action")); + err = 1; + continue; + } + + comp = calloc (1, sizeof (*comp)); + if (!comp) + { + logmsg (LOG_ERR, "%s:%u: %s", file, line_no, + _("not enough memory")); + err = 1; + continue; + } + + comp->mode = ap->mode; + comp->tag = strdup (id); + comp->runlevels = strdup (runlevels); + + if (!comp->tag || !comp->runlevels) + { + component_free (comp); + logmsg (LOG_ERR, "%s:%u: %s", file, line_no, + _("not enough memory")); + err = 1; + continue; + } + + if (wordsplit (process, &ws, WRDSF_DEFFLAGS)) + { + component_free (comp); + logmsg (LOG_ERR, "%s:%u: wordsplit: %s", file, line_no, + strerror (errno)); + err = 1; + continue; + } + comp->argc = ws.ws_wordc; + comp->argv = ws.ws_wordv; + comp->program = strdup (ws.ws_wordv[0]); + ws.ws_wordc = 0; + ws.ws_wordv = NULL; + wordsplit_free (&ws); + + comp->flags |= CF_SIGGROUP; + + if (ap->parser && ap->parser (comp, file, line_no)) + { + component_free (comp); + err = 1; + continue; + } + register_prog (comp); + } + + free (buf); + fclose (fp); + return err; +} + -- cgit v1.2.1