From cf14c349fad774e477a80d1c5e6572f21f17ced1 Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Sun, 30 Dec 2012 15:36:56 +0200 Subject: Initial support for running as init process. * grecs: Upgrade. * lib/Makefile.am: Use AM_CPPFLAGS instead of INCLUDES. * src/Makefile.am: Likewise. * src/acl.c: Update grecs_keyword definitions. * src/inetd.c (inetd_conf_file): Bugfix. The ws structure could be free'd prior to initialization. * src/pies.c: Update grecs_keyword definitions. (init_process,initdefault,dfl_level): New globals. (modetab) : New keyword. (component_keywords): New keywords. (main): Initial support for init(8) mode. * src/pies.h (pies_comp_mode) : New constant. (component): New member. (init_process,console_device,initdefault): New externs. * src/progman.c (prog_status): New status. (prog): New member. (progman_running_p): New function. (prog_start): Special handling for init process mode. (progman_start): Likewise. Take into account runlevels. (progman_dump_stats): New flag 'f' for status_finished. --- src/pies.c | 509 +++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 346 insertions(+), 163 deletions(-) (limited to 'src/pies.c') diff --git a/src/pies.c b/src/pies.c index 85bd22d..ded1a10 100644 --- a/src/pies.c +++ b/src/pies.c @@ -26,6 +26,7 @@ int log_facility = LOG_USER; char *log_tag; struct pies_privs pies_privs; int foreground; +int init_process; enum pies_command { COM_START, @@ -38,6 +39,8 @@ enum pies_command { }; enum pies_command command; +int initdefault; /* Default runlevel */ +int dfl_level; char *statedir = DEFAULT_STATE_DIR; char *instance; char *pidfile; @@ -95,8 +98,8 @@ str_to_config_syntax (const char *str, enum config_syntax *psynt) for (p = config_syntax_tab; p->name; p++) if (strcmp (p->name, str) == 0) { - *psynt = p->type; - return 0; + *psynt = p->type; + return 0; } return 1; } @@ -131,7 +134,7 @@ add_pp_option (const char *opt, const char *arg) { char *qarg; size_t qlen; - + if (!pp_qopt) { pp_qopt = clone_quoting_options (NULL); @@ -158,19 +161,19 @@ stderr_closed_p () int assert_grecs_value_type (grecs_locus_t *locus, - const grecs_value_t *value, int type) + const grecs_value_t *value, int type) { if (GRECS_VALUE_EMPTY_P (value)) { grecs_error (locus, 0, _("expected %s"), - grecs_data_type_string (type)); + grecs_data_type_string (type)); return 1; } if (value->type != type) { grecs_error (locus, 0, _("expected %s, but found %s"), - grecs_data_type_string (type), - grecs_data_type_string (value->type)); + grecs_data_type_string (type), + grecs_data_type_string (value->type)); return 1; } return 0; @@ -190,8 +193,8 @@ assert_scalar_stmt (grecs_locus_t *locus, enum grecs_callback_command cmd) static int _cb_action (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, grecs_value_t *value, void *cb_data) + grecs_locus_t *locus, + void *varptr, grecs_value_t *value, void *cb_data) { enum return_action *pact = varptr; static struct tokendef actab[] = { @@ -219,24 +222,27 @@ struct grecs_keyword return_code_keywords[] = { N_("arg: {disable | restart}"), N_("Specifies action to take when a component finishes with this " "return code."), - grecs_type_string, NULL, offsetof (struct component, act_temp.act), + grecs_type_string, GRECS_DFLT, + NULL, offsetof (struct component, act_temp.act), _cb_action, }, {"notify", N_("arg: emails"), N_("Notify this address when a component terminates."), - grecs_type_string, NULL, offsetof (struct component, act_temp.addr) + grecs_type_string, GRECS_DFLT, + NULL, offsetof (struct component, act_temp.addr) }, {"message", NULL, N_("Notification message text (with headers)."), - grecs_type_string, NULL, offsetof (struct component, act_temp.message), + grecs_type_string, GRECS_DFLT, + NULL, offsetof (struct component, act_temp.message), NULL}, {"exec", NULL, N_("Execute this command."), - grecs_type_string, NULL, - offsetof (struct component, act_temp.command), + grecs_type_string, GRECS_DFLT, + NULL, offsetof (struct component, act_temp.command), NULL, }, {NULL} @@ -326,9 +332,9 @@ static struct tokendef sig_tokendef[] = { static struct action * create_action (struct component *comp, - grecs_locus_t *locus, - grecs_value_t *val, int argc, - const char *(*getarg) (grecs_value_t *, int, grecs_locus_t *)) + grecs_locus_t *locus, + grecs_value_t *val, int argc, + const char *(*getarg) (grecs_value_t *, int, grecs_locus_t *)) { int i; unsigned *retv; @@ -346,7 +352,7 @@ create_action (struct component *comp, unsigned n; const char *arg = getarg (val, i, locus); size_t len = strlen (arg); - + if (isdigit (arg[0])) { char *p; @@ -381,12 +387,12 @@ create_action (struct component *comp, grecs_error (locus, 0, _("%s: not a return code"), arg); continue; } - + /* Alles in ordnung */ retv[retc++] = n; } } - + if (retc == 0 && !allflag) { free (retv); @@ -442,9 +448,9 @@ _get_list_arg (grecs_value_t *val, int num, grecs_locus_t *locus) static int return_code_section_parser (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, - grecs_value_t *value, void *cb_data) + grecs_locus_t *locus, + void *varptr, + grecs_value_t *value, void *cb_data) { struct component *comp = varptr; size_t count; @@ -458,18 +464,18 @@ return_code_section_parser (enum grecs_callback_command cmd, grecs_error (locus, 0, _("missing tag")); return 1; } - + switch (value->type) { case GRECS_TYPE_STRING: act = create_action (comp, locus, value, 1, _get_string_arg); break; - + case GRECS_TYPE_ARRAY: act = create_action (comp, locus, value, value->v.arg.c, _get_array_arg); break; - + case GRECS_TYPE_LIST: count = grecs_list_size (value->v.list); act = create_action (comp, locus, value, count, _get_list_arg); @@ -479,7 +485,7 @@ return_code_section_parser (enum grecs_callback_command cmd, return 1; memset (&comp->act_temp, 0, sizeof (comp->act_temp)); break; - + case grecs_callback_section_end: act = comp->act_tail; act->act = comp->act_temp.act; @@ -500,7 +506,7 @@ config_array_to_argv (grecs_value_t *val, grecs_locus_t *locus, size_t *pargc) int i, j; int argc; char **argv; - + argc = val->v.arg.c; argv = xcalloc (argc + 1, sizeof (argv[0])); for (i = j = 0; i < argc; i++) @@ -517,8 +523,8 @@ config_array_to_argv (grecs_value_t *val, grecs_locus_t *locus, size_t *pargc) static int _cb_command (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, grecs_value_t *value, void *cb_data) + grecs_locus_t *locus, + void *varptr, grecs_value_t *value, void *cb_data) { struct component *comp = varptr; struct wordsplit ws; @@ -534,7 +540,7 @@ _cb_command (enum grecs_callback_command cmd, comp->argc = ws.ws_wordc; comp->argv = ws.ws_wordv; break; - + case GRECS_TYPE_ARRAY: comp->argv = config_array_to_argv (value, locus, &comp->argc); break; @@ -548,8 +554,8 @@ _cb_command (enum grecs_callback_command cmd, static int _cb_umask (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, grecs_value_t *value, void *cb_data) + grecs_locus_t *locus, + void *varptr, grecs_value_t *value, void *cb_data) { mode_t *pmode = varptr; char *p; @@ -570,8 +576,8 @@ _cb_umask (enum grecs_callback_command cmd, static int _cb_env (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, grecs_value_t *value, void *cb_data) + grecs_locus_t *locus, + void *varptr, grecs_value_t *value, void *cb_data) { int argc; char **argv; @@ -655,8 +661,8 @@ string_to_syslog_facility (const char *key, int *pres) static int cb_syslog_facility (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, grecs_value_t *value, void *cb_data) + grecs_locus_t *locus, + void *varptr, grecs_value_t *value, void *cb_data) { const char *str; @@ -680,8 +686,8 @@ cb_syslog_facility (enum grecs_callback_command cmd, static int _cb_redir (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, grecs_value_t *value, void *cb_data) + grecs_locus_t *locus, + void *varptr, grecs_value_t *value, void *cb_data) { struct redirector *rp = varptr; static struct tokendef redirtab[] = { @@ -691,7 +697,7 @@ _cb_redir (enum grecs_callback_command cmd, {NULL} }; int res; - + switch (value->type) { case GRECS_TYPE_STRING: @@ -708,7 +714,7 @@ _cb_redir (enum grecs_callback_command cmd, return 0; } break; - + case GRECS_TYPE_ARRAY: if (assert_grecs_value_type (locus, value->v.arg.v[0], GRECS_TYPE_STRING)) @@ -728,12 +734,12 @@ _cb_redir (enum grecs_callback_command cmd, if (assert_grecs_value_type (locus, value->v.arg.v[1], GRECS_TYPE_STRING)) return 0; - + switch (res) { case redir_null: break; - + case redir_syslog: if (string_to_syslog_priority (value->v.arg.v[1]->v.string, &rp->v.prio)) @@ -744,7 +750,7 @@ _cb_redir (enum grecs_callback_command cmd, return 0; } break; - + case redir_file: rp->v.file = xstrdup (value->v.arg.v[1]->v.string); break; @@ -753,18 +759,18 @@ _cb_redir (enum grecs_callback_command cmd, rp->type = res; } break; - + default: grecs_error (locus, 0, _("unexpected list")); } - + return 0; } static int _cb_url (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, grecs_value_t *value, void *cb_data) + grecs_locus_t *locus, + void *varptr, grecs_value_t *value, void *cb_data) { struct pies_url *url; @@ -774,7 +780,7 @@ _cb_url (enum grecs_callback_command cmd, if (pies_url_create (&url, value->v.string)) { grecs_error (locus, 0, _("%s: cannot create URL: %s"), - value->v.string, strerror (errno)); + value->v.string, strerror (errno)); return 0; } *(struct pies_url **) varptr = url; @@ -807,8 +813,8 @@ socket_type_to_str (int socket_type, const char **pres) static int _cb_socket_type (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, grecs_value_t *value, void *cb_data) + grecs_locus_t *locus, + void *varptr, grecs_value_t *value, void *cb_data) { if (assert_scalar_stmt (locus, cmd) || assert_grecs_value_type (locus, value, GRECS_TYPE_STRING)) @@ -822,6 +828,7 @@ _cb_socket_type (enum grecs_callback_command cmd, static struct tokendef modetab[] = { {"exec", pies_comp_exec}, {"wait", pies_comp_exec}, + {"once", pies_comp_once}, {"accept", pies_comp_accept}, {"inetd", pies_comp_inetd}, {"nostartaccept", pies_comp_inetd}, @@ -832,8 +839,8 @@ static struct tokendef modetab[] = { static int _cb_mode (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, grecs_value_t *value, void *cb_data) + grecs_locus_t *locus, + void *varptr, grecs_value_t *value, void *cb_data) { int res; @@ -849,8 +856,8 @@ _cb_mode (enum grecs_callback_command cmd, static int _cb_limits (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, grecs_value_t *value, void *cb_data) + grecs_locus_t *locus, + void *varptr, grecs_value_t *value, void *cb_data) { limits_record_t *plrec = varptr; char *p; @@ -882,7 +889,7 @@ str_to_cf (const char *string, int *flags) { "siggroup", CF_SIGGROUP }, { NULL } }; - + if (len > 2 && memcmp (string, "no", 2) == 0) { neg++; @@ -901,11 +908,11 @@ str_to_cf (const char *string, int *flags) static int _cb_flags (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, grecs_value_t *value, void *cb_data) + grecs_locus_t *locus, + void *varptr, grecs_value_t *value, void *cb_data) { int *flags = varptr; - + switch (value->type) { case GRECS_TYPE_STRING: @@ -915,11 +922,11 @@ _cb_flags (enum grecs_callback_command cmd, return 1; } break; - + case GRECS_TYPE_LIST: { struct grecs_list_entry *ep; - + for (ep = value->v.list->head; ep; ep = ep->next) { const grecs_value_t *vp = ep->data; @@ -934,7 +941,7 @@ _cb_flags (enum grecs_callback_command cmd, } } break; - + case GRECS_TYPE_ARRAY: grecs_error (locus, 0, _("too many arguments")); return 1; @@ -942,6 +949,53 @@ _cb_flags (enum grecs_callback_command cmd, return 0; } +static const char valid_runlevels[] = "0123456Ss"; + +static int +_cb_initdefault (enum grecs_callback_command cmd, + grecs_locus_t *locus, + void *varptr, grecs_value_t *value, void *cb_data) +{ + int *val = varptr; + + if (assert_grecs_value_type (locus, value, GRECS_TYPE_STRING)) + return 1; + if (strlen (value->v.string) != 1) + { + grecs_error (locus, 0, _("argument must be a single character")); + return 1; + } + if (!strchr (valid_runlevels, value->v.string[0])) + { + grecs_error (locus, 0, _("not a valid runlevel")); + return 1; + } + *val = toupper (value->v.string[0]); + return 0; +} + +static int +_cb_runlevels (enum grecs_callback_command cmd, + grecs_locus_t *locus, + void *varptr, grecs_value_t *value, void *cb_data) +{ + char **sptr = varptr, *p; + + if (assert_grecs_value_type (locus, value, GRECS_TYPE_STRING)) + return 1; + for (p = value->v.string; *p; p++) + { + if (!strchr (valid_runlevels, *p)) + { + grecs_error (locus, 0, _("not a valid runlevel: %c")); + return 1; + } + } + *sptr = grecs_strdup(value->v.string); + for (p = *sptr; *p; p++) + *p = toupper (*p); + return 0; +} struct grecs_keyword component_keywords[] = { {"mode", @@ -950,119 +1004,130 @@ struct grecs_keyword component_keywords[] = { N_ ("mode: {exec | wait | accept | inetd | nostartaccept | pass-fd | pass}"), N_("Component execution mode."), - grecs_type_string, NULL, offsetof (struct component, mode), + grecs_type_string, GRECS_DFLT, + NULL, offsetof (struct component, mode), _cb_mode, }, {"program", NULL, N_("Full name of the program."), - grecs_type_string, NULL, - offsetof (struct component, program), + grecs_type_string, GRECS_DFLT, + NULL, offsetof (struct component, program), NULL, }, {"command", NULL, N_("Command line."), - grecs_type_string, NULL, 0, + grecs_type_string, GRECS_DFLT, + NULL, 0, _cb_command, }, {"prerequisites", N_("list"), N_("List of prerequisites."), - grecs_type_string | GRECS_LIST, NULL, offsetof (struct component, prereq), + grecs_type_string, GRECS_LIST, NULL, offsetof (struct component, prereq), NULL, }, {"dependents", N_("list"), N_("List of components for which this one is a prerequisite."), - grecs_type_string | GRECS_LIST, NULL, offsetof (struct component, depend), + grecs_type_string, GRECS_LIST, NULL, offsetof (struct component, depend), NULL, }, {"flags", N_("list"), N_("List of flags."), - grecs_type_string | GRECS_LIST, NULL, offsetof (struct component, flags), + grecs_type_string, GRECS_LIST, NULL, offsetof (struct component, flags), _cb_flags }, + {"runlevels", + N_("chars"), + N_("Runlevels to start that component in."), + grecs_type_string, GRECS_DFLT, + NULL, offsetof (struct component, runlevels), + _cb_runlevels }, {"pass-fd-timeout", NULL, N_("Time to wait for pass-fd socket to become available."), - grecs_type_uint, NULL, - offsetof (struct component, pass_fd_timeout), + grecs_type_uint, GRECS_DFLT, + NULL, offsetof (struct component, pass_fd_timeout), NULL, }, {"max-instances", NULL, N_("Maximum number of running instances."), - grecs_type_size, NULL, - offsetof (struct component, max_instances), + grecs_type_size, GRECS_DFLT, + NULL, offsetof (struct component, max_instances), NULL }, {"max-instances-message", NULL, N_("Text to send back if max-instances is reached (inetd-components only)."), - grecs_type_string, NULL, - offsetof (struct component, max_instances_message), + grecs_type_string, GRECS_DFLT, + NULL, offsetof (struct component, max_instances_message), NULL }, {"max-ip-connections", NULL, N_("Maximum number of simultaneous connections per IP address (inetd only)."), - grecs_type_size, NULL, - offsetof (struct component, max_ip_connections), + grecs_type_size, GRECS_DFLT, + NULL, offsetof (struct component, max_ip_connections), NULL }, {"max-ip-connections-message", NULL, N_("Text to send back if max-ip-connections-message is reached (inetd only)."), - grecs_type_string, NULL, - offsetof (struct component, max_ip_connections_message), + grecs_type_string, GRECS_DFLT, + NULL, offsetof (struct component, max_ip_connections_message), NULL }, - + {"max-rate", NULL, N_("Maximum number of times an inetd component can be invoked in one minute."), - grecs_type_size, NULL, - offsetof (struct component, max_rate), + grecs_type_size, GRECS_DFLT, + NULL, offsetof (struct component, max_rate), NULL }, {"socket", N_("url: string"), N_("Listen on the given url."), - grecs_type_string, NULL, - offsetof (struct component, socket_url), + grecs_type_string, GRECS_DFLT, + NULL, offsetof (struct component, socket_url), _cb_url, }, {"socket-type", /* TRANSLATORS: words after `type:' are keywords. */ N_("type: {stream | dgram | raw | rdm | seqpacket}"), N_("Set socket type."), - grecs_type_int, NULL, - offsetof (struct component, socket_type), + grecs_type_int, GRECS_DFLT, + NULL, offsetof (struct component, socket_type), _cb_socket_type }, {"pass-fd-socket", N_("name"), N_("Pass fd through this socket."), - grecs_type_string, NULL, - offsetof (struct component, pass_fd_socket), + grecs_type_string, GRECS_DFLT, + NULL, offsetof (struct component, pass_fd_socket), NULL, }, {"acl", N_("name: string"), N_("Set ACL."), - grecs_type_section, NULL, offsetof (struct component, acl), + grecs_type_section, GRECS_DFLT, + NULL, offsetof (struct component, acl), acl_section_parser, NULL, acl_keywords}, {"access-denied-message", NULL, N_("Text to send back if access is denied (inetd-components only)."), - grecs_type_string, NULL, - offsetof (struct component, access_denied_message), + grecs_type_string, GRECS_DFLT, + NULL, offsetof (struct component, access_denied_message), NULL }, {"remove-file", N_("file"), N_("Remove file before starting the component."), - grecs_type_string, NULL, offsetof (struct component, rmfile), + grecs_type_string, GRECS_DFLT, + NULL, offsetof (struct component, rmfile), NULL, }, {"facility", N_("arg"), N_("Override default syslog facility for this component."), - grecs_type_string, NULL, offsetof (struct component, facility), + grecs_type_string, GRECS_DFLT, + NULL, offsetof (struct component, facility), cb_syslog_facility, }, {"stdout", @@ -1070,7 +1135,8 @@ struct grecs_keyword component_keywords[] = { N_("type: {file | syslog}> argv) COMPERR (grecs_error, "%s", _("missing command line")); - + if (ISCF_TCPMUX (comp->flags)) { comp->mode = pies_comp_inetd; @@ -1234,7 +1310,7 @@ component_verify (struct component *comp, grecs_locus_t *locus) COMPERR (grecs_error, "%s", _("socket ignored: wrong mode")); break; - + case pies_comp_pass_fd: if (!comp->pass_fd_socket) COMPERR (grecs_error, @@ -1253,7 +1329,7 @@ component_verify (struct component *comp, grecs_locus_t *locus) "file name or chdir must be specified")); } /* Fall through */ - + case pies_comp_accept: if (!comp->socket_url) { @@ -1306,7 +1382,7 @@ component_verify (struct component *comp, grecs_locus_t *locus) COMPERR (grecs_error, "%s", _("wait is useless in this mode")); comp->flags &= ~CF_WAIT; } - + if (comp->mode != pies_comp_exec && comp->redir[RETR_OUT].type != redir_null) { @@ -1314,7 +1390,7 @@ component_verify (struct component *comp, grecs_locus_t *locus) "%s", _("stdout translation invalid in this mode")); comp->redir[RETR_OUT].type = redir_null; } - + for (i = RETR_OUT; i <= RETR_ERR; i++) { if (comp->redir[i].type == redir_file @@ -1333,7 +1409,7 @@ component_verify (struct component *comp, grecs_locus_t *locus) comp->redir[i].v.file); } } - + return header; #undef COMPERR } @@ -1401,14 +1477,17 @@ static struct grecs_keyword syslog_kw[] = { N_("Set syslog facility. Arg is one of the following: user, daemon, " "auth, authpriv, mail, cron, local0 through local7 (case-insensitive), " "or a facility number."), - grecs_type_string, &log_facility, 0, cb_syslog_facility}, + grecs_type_string, GRECS_DFLT, + &log_facility, 0, cb_syslog_facility}, {"tag", N_("string"), N_("Tag syslog messages with this string"), - grecs_type_string, &log_tag}, + grecs_type_string, GRECS_DFLT, + &log_tag}, #if 0 /* This is reserved for future use */ { "print-priority", N_("arg"), N_("Prefix each message with its priority"), - grecs_type_bool, &syslog_include_prio}, + grecs_type_bool, GRECS_DFLT, + &syslog_include_prio}, #endif {NULL}, }; @@ -1441,124 +1520,153 @@ struct grecs_keyword pies_keywords[] = { {"component", N_("tag: string"), N_("Define a component"), - grecs_type_section, NULL, 0, + grecs_type_section, GRECS_DFLT, + NULL, 0, component_section_parser, NULL, component_keywords}, {"syslog", NULL, N_("Configure syslog logging"), - grecs_type_section, NULL, 0, NULL, NULL, syslog_kw}, + grecs_type_section, GRECS_DFLT, + NULL, 0, NULL, NULL, syslog_kw}, {"debug", NULL, N_("Set debug verbosity level."), - grecs_type_uint, &debug_level, 0, NULL}, + grecs_type_uint, GRECS_DFLT, + &debug_level, 0, NULL}, {"source-info", NULL, N_("Show source info with debugging messages."), - grecs_type_bool, &source_info_option, 0, NULL}, + grecs_type_bool, GRECS_DFLT, + &source_info_option, 0, NULL}, {"state-directory", NULL, N_("Full file name of the program state directory."), - grecs_type_string, &statedir, 0, NULL}, + grecs_type_string, GRECS_DFLT, + &statedir, 0, NULL}, {"pidfile", NULL, N_("Write PID to this file."), - grecs_type_string, &pidfile, 0, + grecs_type_string, GRECS_DFLT, + &pidfile, 0, NULL, }, {"control-file", NULL, N_("Set location of the control file."), - grecs_type_string, &ctlfile, 0, + grecs_type_string, GRECS_DFLT, + &ctlfile, 0, NULL, }, {"stat-file", NULL, N_("Set location of the statistics output file."), - grecs_type_string, &statfile, 0, + grecs_type_string, GRECS_DFLT, + &statfile, 0, NULL, }, {"qotd-file", NULL, N_("Set location of the QOTD file."), - grecs_type_string, &qotdfile, 0, + grecs_type_string, GRECS_DFLT, + &qotdfile, 0, NULL }, {"user", NULL, N_("Run with this user privileges."), - grecs_type_string, &pies_privs.user, 0, + grecs_type_string, GRECS_DFLT, + &pies_privs.user, 0, NULL, }, {"group", NULL, N_("Retain supplementary group."), - grecs_type_string | GRECS_LIST, &pies_privs.groups, 0, + grecs_type_string, GRECS_LIST, + &pies_privs.groups, 0, NULL, }, {"allgroups", NULL, N_("Retain all supplementary groups of which user is a member."), - grecs_type_bool, &pies_privs.allgroups, 0, + grecs_type_bool, GRECS_DFLT, + &pies_privs.allgroups, 0, NULL, }, {"umask", N_("arg: number"), N_("Force this umask."), - grecs_type_string, &pies_umask, 0, + grecs_type_string, GRECS_DFLT, + &pies_umask, 0, _cb_umask, }, {"limits", NULL, N_("Set global system limits."), - grecs_type_string, &pies_limits, 0, _cb_limits, + grecs_type_string, GRECS_DFLT, + &pies_limits, 0, _cb_limits, }, + {"initdefault", + N_("arg: char"), + N_("Default runlevel"), + grecs_type_string, GRECS_DFLT, + &initdefault, 0, _cb_initdefault, + }, {"shutdown-timeout", "n", N_("Wait seconds for all components to shut down."), - grecs_type_uint, &shutdown_timeout, 0, + grecs_type_uint, GRECS_DFLT, + &shutdown_timeout, 0, NULL, }, {"return-code", N_("tag: exit-code-list"), N_("Define what to do when the component finishes."), - grecs_type_section, &default_component, 0, + grecs_type_section, GRECS_DFLT, + &default_component, 0, return_code_section_parser, NULL, return_code_keywords}, {"acl", N_("name: string"), N_("Set global ACL."), - grecs_type_section, &pies_acl, 0, + grecs_type_section, GRECS_DFLT, + &pies_acl, 0, acl_section_parser, NULL, acl_keywords}, {"defacl", N_("name: string"), N_("Define an ACL."), - grecs_type_section, NULL, 0, + grecs_type_section, GRECS_DFLT, + NULL, 0, defacl_section_parser, NULL, acl_keywords}, {"include-inetd", N_("file-or-dir: string"), N_("Include inetd configuration file or directory"), - grecs_type_string, NULL, 0, + grecs_type_string, GRECS_DFLT, + NULL, 0, _cb_include_inetd }, {"include-meta1", N_("file: string"), N_("Include components from the specified MeTA1 configuration file."), - grecs_type_string, NULL, 0, + grecs_type_string, GRECS_DFLT, + NULL, 0, _cb_include_meta1, }, {"meta1-queue-dir", NULL, N_("Set the name of MeTA1 queue directory (default /var/spool/meta1)."), - grecs_type_string, &meta1_queue_dir, 0, + grecs_type_string, GRECS_DFLT, + &meta1_queue_dir, 0, NULL, }, {"mailer-program", NULL, N_("Full path to the mailer binary."), - grecs_type_string, &mailer_program, 0, + grecs_type_string, GRECS_DFLT, + &mailer_program, 0, NULL }, {"mailer-command-line", NULL, N_("Mailer command line (without recipient addresses)."), - grecs_type_string, &mailer_command_line, 0, + grecs_type_string, GRECS_DFLT, + &mailer_command_line, 0, NULL }, {NULL} @@ -1705,6 +1813,7 @@ enum pies_status pies_status_running }; +//FIXME: If telinit? enum pies_status pies_check_status (pid_t *ppid) { @@ -1771,7 +1880,7 @@ int request_restart_components (char **argv) { FILE *fp; - pid_t pid = pidfile_read (1); + pid_t pid = pidfile_read (1);//FIXME: useless in init mode, init has pid == 1 if (pid == -1) return 1; @@ -1998,6 +2107,40 @@ set_state_file_names (const char *base) qotdfile = mkfilename (statedir, base, ".qotd"); } +static char *try_console[] = { NULL, "/dev/console", "/dev/tty0" }; +char *console_device; + +static void +set_console_dev () +{ + int i; + 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; + } + } + } + /* provide default */ + console_device = "/dev/null"; +} + +static void +inittrans () +{ + if (progman_running_p ()) + /* Noting to do if there are processes left in the previous runlevel */ + return; + +} + int main (int argc, char **argv) { @@ -2016,12 +2159,43 @@ main (int argc, char **argv) mf_proctitle_init (argc, argv, environ); set_quoting_style (NULL, shell_quoting_style); + + init_process = getpid () == 1; /* Set default logging */ diag_setup (DIAG_TO_SYSLOG | (stderr_closed_p () ? 0 : DIAG_TO_STDERR)); config_init (); - parse_options (argc, argv, &index); + if (init_process) + { + for (index = 1; index < argc; index++) + { + if (!strcmp(argv[index], "single") || !strcmp(argv[index], "-s")) + dfl_level = 'S'; +#if 0 + //FIXME + else if (!strcmp(argv[index], "-a") || !strcmp(argv[index], "auto")) + putenv("AUTOBOOT=YES"); + else if (!strcmp(argv[index], "-b") || + !strcmp(argv[index],"emergency")) + emerg_shell = 1; + else if (!strcmp(argv[index], "-z")) + { + /* Ignore -z xxx */ + if (argv[index + 1]) + index++; + } +#endif + else if (strchr("0123456789sS", argv[index][0]) && !argv[index][1]) + { + dfl_level = argv[index][0]; + if (dfl_level == 's') + dfl_level = 'S'; + } + } + } + else + parse_options (argc, argv, &index); if (!instance) { @@ -2036,7 +2210,7 @@ main (int argc, char **argv) set_conf_file_names (instance); - if (!DEFAULT_PREPROCESSOR) + if (init_process || !DEFAULT_PREPROCESSOR) grecs_preprocessor = NULL; else { @@ -2130,27 +2304,33 @@ main (int argc, char **argv) umask (pies_umask); } - switch (pies_check_status (&pid)) + if (init_process) { - case pies_status_ctr: - break; - case pies_status_stale: - case pies_status_noresp: - if (!force_option) - { - logmsg (LOG_ERR, - _("another pies instance may be running (pid %lu), " - "use --force to override"), (unsigned long) pid); - exit (EX_USAGE); - } - break; - - case pies_status_running: - logmsg (LOG_ERR, _("another pies instance already running (pid %lu)"), - (unsigned long) pid); - exit (EX_USAGE); + foreground = 1; + set_console_dev (); } - + else + switch (pies_check_status (&pid)) + { + case pies_status_ctr: + break; + case pies_status_stale: + case pies_status_noresp: + if (!force_option) + { + logmsg (LOG_ERR, + _("another pies instance may be running (pid %lu), " + "use --force to override"), (unsigned long) pid); + exit (EX_USAGE); + } + break; + + case pies_status_running: + logmsg (LOG_ERR, _("another pies instance already running (pid %lu)"), + (unsigned long) pid); + exit (EX_USAGE); + } + logmsg (LOG_INFO, _("%s starting"), program_version); if (!foreground) @@ -2163,9 +2343,10 @@ main (int argc, char **argv) } diag_setup (DIAG_TO_SYSLOG); } - - create_pidfile (pidfile); + if (!init_process) + create_pidfile (pidfile); + if (argv[0][0] != '/') logmsg (LOG_NOTICE, _("not started as an absolute pathname; " @@ -2178,6 +2359,8 @@ main (int argc, char **argv) do { + if (init_process) + inittrans (); if (!children_cleanup) pies_pause (); switch (action) @@ -2208,7 +2391,7 @@ main (int argc, char **argv) } } } - while (action == ACTION_CONT); + while (init_process || action == ACTION_CONT); progman_stop (); remove_pidfile (pidfile); -- cgit v1.2.1