aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2013-01-07 17:40:47 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2013-01-07 18:06:19 +0200
commite92cf71a8f4d51810de7c0f7a613402737d66168 (patch)
tree775bba0b6bfb026fc458e4c681744fb7661f349e /src
parent5d2eff82abf052d5edb8f201559cb6e17bbf158f (diff)
downloadpies-e92cf71a8f4d51810de7c0f7a613402737d66168.tar.gz
pies-e92cf71a8f4d51810de7c0f7a613402737d66168.tar.bz2
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.
Diffstat (limited to 'src')
-rw-r--r--src/limits.c11
-rw-r--r--src/pies.c105
-rw-r--r--src/pies.h16
-rw-r--r--src/progman.c7
-rw-r--r--src/sysvinit.c546
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)
@@ -1438,6 +1447,51 @@ component_create (const char *name)
}
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)
{
if (component_verify (comp, locus) == 0)
@@ -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;
+}
+

Return to:

Send suggestions and report system problems to the System administrator.