diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2009-11-26 21:49:15 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2009-11-26 21:49:15 +0200 |
commit | 9de9182e3517c677e2309b0dd58ab4e3af1b3176 (patch) | |
tree | a8d2f33ee720591be9212b9cc6a33a5b018f60bd /src/pies.c | |
parent | c0802ebe4ebd7e7bb173c6efa2c6e59dd5440cc3 (diff) | |
download | pies-9de9182e3517c677e2309b0dd58ab4e3af1b3176.tar.gz pies-9de9182e3517c677e2309b0dd58ab4e3af1b3176.tar.bz2 |
Implement internal inetd services in the pies config.
* src/pies.h (CF_INTERNAL): New flag.
(ISCF_TCPMUX): New macro.
(struct component): Reorder fields.
New field: tcpmux.
(progman_lookup_service): Remove proto.
(progman_lookup_tcpmux): New proto.
(struct inetd_builtin.foo): Change signature. All uses updated.
* src/progman.c (progman_lookup_service): Remove.
(progman_lookup_tcpmux): New function.
(progman_create_sockets): Skip tcpmux subservices.
(progman_start): Skip disabled inetd components.
* src/inetd-bi.c (tcpmux): Use progman_lookup_tcpmux.
* src/inetd.c (tcpmux_service, mktag): New functions.
(inetd_conf_file): Minor changes.
* src/pies.c (_cb_bitmask, _cb_precious)
(_cb_disabled, _cb_wait): Remove.
(str_to_cf, _cb_flags): New functions.
(component_keywords): Remove keywords:
disable, precious, wait.
Add keywords: flags, service, tcpmux-master.
(component_verify): Improve.
* src/url.c (pies_url_destroy): Fix coredump on NULL argument.
Diffstat (limited to 'src/pies.c')
-rw-r--r-- | src/pies.c | 294 |
1 files changed, 198 insertions, 96 deletions
@@ -148,8 +148,8 @@ stderr_closed_p () (!(val) || ((val)->type == GRECS_TYPE_STRING && !(val)->v.string)) int -assert_grecs_value_type (grecs_locus_t * locus, - const grecs_value_t * value, int type) +assert_grecs_value_type (grecs_locus_t *locus, + const grecs_value_t *value, int type) { if (GRECS_VALUE_IS_EMPTY (value)) { @@ -168,7 +168,7 @@ assert_grecs_value_type (grecs_locus_t * locus, } int -assert_scalar_stmt (grecs_locus_t * locus, enum grecs_callback_command cmd) +assert_scalar_stmt (grecs_locus_t *locus, enum grecs_callback_command cmd) { if (cmd != grecs_callback_set_value) { @@ -181,8 +181,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[] = { @@ -317,8 +317,8 @@ static struct tokendef sig_tokendef[] = { static struct action * create_action (struct component *comp, - grecs_locus_t * locus, - grecs_value_t * val, int argc, + grecs_locus_t *locus, + grecs_value_t *val, int argc, const char *(*getarg) (grecs_value_t *, int, grecs_locus_t *)) { int i; @@ -399,7 +399,7 @@ create_action (struct component *comp, } const char * -_get_string_arg (grecs_value_t * val, int num, grecs_locus_t * locus) +_get_string_arg (grecs_value_t *val, int num, grecs_locus_t *locus) { if (num != 0) return NULL; @@ -407,7 +407,7 @@ _get_string_arg (grecs_value_t * val, int num, grecs_locus_t * locus) } const char * -_get_array_arg (grecs_value_t * val, int num, grecs_locus_t * locus) +_get_array_arg (grecs_value_t *val, int num, grecs_locus_t *locus) { if (num < val->v.arg.c) { @@ -419,7 +419,7 @@ _get_array_arg (grecs_value_t * val, int num, grecs_locus_t * locus) } const char * -_get_list_arg (grecs_value_t * val, int num, grecs_locus_t * locus) +_get_list_arg (grecs_value_t *val, int num, grecs_locus_t *locus) { grecs_value_t *elt = (grecs_value_t *) gl_list_get_at (val->v.list, num); if (!elt) @@ -433,9 +433,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, + grecs_locus_t *locus, void *varptr, - grecs_value_t * value, void *cb_data) + grecs_value_t *value, void *cb_data) { struct component *comp = varptr; size_t count; @@ -508,8 +508,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; @@ -539,8 +539,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; @@ -561,8 +561,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; @@ -646,8 +646,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; @@ -671,8 +671,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[] = { @@ -754,8 +754,8 @@ _cb_redir (enum grecs_callback_command cmd, 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; @@ -817,8 +817,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; @@ -834,8 +834,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; @@ -848,49 +848,86 @@ _cb_limits (enum grecs_callback_command cmd, return 0; } -static int -_cb_bitmask (enum grecs_callback_command cmd, - grecs_locus_t *locus, - int *fptr, grecs_value_t *value, int mask) +int +str_to_cf (const char *string, int *flags) { - int arg; + size_t len = strlen (string); + int neg = 0; + int mask; - if (assert_scalar_stmt (locus, cmd) - || assert_grecs_value_type (locus, value, GRECS_TYPE_STRING) - || grecs_string_convert (&arg, grecs_type_bool, value->v.string, - locus)) + if (len > 2 && memcmp (string, "no", 2) == 0) + { + neg++; + string += 2; + } + + if (strcmp (string, "disable") == 0) + mask = CF_DISABLED; + else if (strcmp (string, "precious") == 0) + mask = CF_PRECIOUS; + else if (strcmp (string, "wait") == 0) + mask = CF_WAIT; + else if (strcmp (string, "tcpmux") == 0) + mask = CF_TCPMUX; + else if (strcmp (string, "tcpmuxplus") == 0) + mask = CF_TCPMUXPLUS; + else if (strcmp (string, "internal") == 0) + mask = CF_INTERNAL; + else return 1; - if (arg) - *fptr |= mask; + + if (neg) + *flags &= ~mask; else - *fptr &= ~mask; + *flags |= mask; return 0; } static int -_cb_precious (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, grecs_value_t *value, void *cb_data) +_cb_flags (enum grecs_callback_command cmd, + grecs_locus_t *locus, + void *varptr, grecs_value_t *value, void *cb_data) { - return _cb_bitmask (cmd, locus, varptr, value, CF_PRECIOUS); -} + int *flags = varptr; + + switch (value->type) + { + case GRECS_TYPE_STRING: + if (str_to_cf (value->v.string, flags)) + { + grecs_error (locus, 0, _("%s: unrecognised flag"), value->v.string); + return 1; + } + break; -static int -_cb_disabled (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, grecs_value_t *value, void *cb_data) -{ - return _cb_bitmask (cmd, locus, varptr, value, CF_DISABLED); -} + case GRECS_TYPE_LIST: + { + const void *p; + gl_list_iterator_t itr = gl_list_iterator (value->v.list); + + while (gl_list_iterator_next (&itr, &p, NULL)) + { + const grecs_value_t *vp = p; + if (assert_grecs_value_type (locus, vp, GRECS_TYPE_STRING)) + return 1; + if (str_to_cf (vp->v.string, flags)) + { + grecs_error (locus, 0, _("%s: unrecognised flag"), + vp->v.string); + return 1; + } + } + } + break; -static int -_cb_wait (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, grecs_value_t *value, void *cb_data) -{ - return _cb_bitmask (cmd, locus, varptr, value, CF_WAIT); + case GRECS_TYPE_ARRAY: + grecs_error (locus, 0, _("too many arguments")); + return 1; + } + return 0; } + struct grecs_keyword component_keywords[] = { {"mode", /* TRANSLATORS: The words between '{' and '}' are keywords, do not @@ -926,6 +963,11 @@ struct grecs_keyword component_keywords[] = { 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), + _cb_flags }, {"pass-fd-timeout", NULL, N_("Time to wait for pass-fd socket to become available."), @@ -933,26 +975,6 @@ struct grecs_keyword component_keywords[] = { offsetof (struct component, pass_fd_timeout), NULL, }, - {"disable", - NULL, - N_("Disable this entry."), - grecs_type_bool, NULL, offsetof (struct component, flags), - _cb_disabled, - }, - {"precious", - NULL, - N_("Mark this entry as precious."), - grecs_type_bool, NULL, - offsetof (struct component, flags), - _cb_precious, - }, - {"wait", - NULL, - N_("Wait for the server program to return."), - grecs_type_bool, NULL, - offsetof (struct component, flags), - _cb_wait, - }, {"max-instances", NULL, N_("Maximum number of running instances."), @@ -973,6 +995,7 @@ struct grecs_keyword component_keywords[] = { _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, @@ -1067,6 +1090,16 @@ struct grecs_keyword component_keywords[] = { N_("Define what to do when the component finishes."), grecs_type_section, NULL, 0, return_code_section_parser, NULL, return_code_keywords}, + {"service", + N_("name"), + N_("Service name for inetd component."), + grecs_type_string, NULL, offsetof (struct component, service), + NULL }, + {"tcpmux-master", + N_("tag"), + N_("Tag of master TCPMUX component."), + grecs_type_string, NULL, offsetof (struct component, tcpmux), + NULL }, {NULL} }; @@ -1101,32 +1134,71 @@ component_verify (struct component *comp, grecs_locus_t *locus) { int header = 0; int i; -#define COMPERR(fmt, arg) \ +#define COMPERR(func, fmt, arg) \ do \ { \ if (!header) \ { \ - grecs_error (locus, 0, _("in component %s:"), comp->tag); \ + grecs_warning (locus, 0, _("in component %s:"), comp->tag); \ header = 1; \ } \ - grecs_error (locus, 0, fmt, arg); \ + func (locus, 0, fmt, arg); \ } \ while (0) - if (!comp->argv) - COMPERR ("%s", _("missing command line")); + if (comp->flags & CF_INTERNAL) + { + comp->mode = pies_comp_inetd; + if (!comp->service) + /* TRANSLATORS: do not translate quoted words, they are keywords. */ + COMPERR (grecs_error, + "%s", _("`internal' used without `service'")); + else + { + comp->builtin = inetd_builtin_lookup (comp->service, + comp->socket_type); + if (!comp->builtin) + COMPERR (grecs_error, + "%s", _("unknown internal service")); + if (comp->argv) + /* TRANSLATORS: do not translate quoted words, they are + keywords. */ + COMPERR (grecs_error, + "%s", _("`internal' used with `command'")); + } + } + else if (!comp->argv) + COMPERR (grecs_error, + "%s", _("missing command line")); + + if (ISCF_TCPMUX (comp->flags)) + { + comp->mode = pies_comp_inetd; + if ((comp->flags & (CF_TCPMUX | CF_TCPMUXPLUS)) + == (CF_TCPMUX | CF_TCPMUXPLUS)) + COMPERR (grecs_error, + "%s", _("both `tcpmux' and `tcpmuxplus' used")); + else if (!comp->service) + /* TRANSLATORS: do not translate quoted words, they are keywords. */ + COMPERR (grecs_error, + "%s", _("`internal' used without `service'")); + } + if (comp->pass_fd_socket && comp->mode != pies_comp_pass_fd) - COMPERR ("%s", _("pass-fd-socket ignored: wrong mode")); + COMPERR (grecs_error, + "%s", _("pass-fd-socket ignored: wrong mode")); switch (comp->mode) { case pies_comp_exec: if (comp->socket_url) - COMPERR ("%s", _("socket ignored: wrong mode")); + COMPERR (grecs_error, + "%s", _("socket ignored: wrong mode")); break; case pies_comp_pass_fd: if (!comp->pass_fd_socket) - COMPERR ("%s", _("must supply pass-fd-socket in this mode")); + COMPERR (grecs_error, + "%s", _("must supply pass-fd-socket in this mode")); else if (comp->pass_fd_socket[0] != '/') { if (comp->dir) @@ -1136,16 +1208,43 @@ component_verify (struct component *comp, grecs_locus_t *locus) comp->pass_fd_socket = p; } else - COMPERR ("%s", _("pass-fd-socket must be an absolute " + COMPERR (grecs_error, + "%s", _("pass-fd-socket must be an absolute " "file name or chdir must be specified")); } /* Fall through */ case pies_comp_accept: - case pies_comp_inetd: if (!comp->socket_url) { - COMPERR ("%s", _("socket must be specified in this mode")); + COMPERR (grecs_error, + "%s", _("socket must be specified in this mode")); + /* FIXME: Memory leak */ + return 1; + } + break; + + case pies_comp_inetd: + if (ISCF_TCPMUX (comp->flags)) + { + pies_url_destroy (&comp->socket_url); + if (!comp->tcpmux) + { + COMPERR (grecs_warning, + "%s", + _("TCPMUX master not specified, assuming \"tcpmux\"")); + comp->tcpmux = xstrdup ("tcpmux"); + } + } + else if (comp->tcpmux) + { + comp->flags |= CF_TCPMUX; + pies_url_destroy (&comp->socket_url); + } + else if (!comp->socket_url) + { + COMPERR (grecs_error, + "%s", _("socket must be specified in this mode")); /* FIXME: Memory leak */ return 1; } @@ -1156,21 +1255,23 @@ component_verify (struct component *comp, grecs_locus_t *locus) if ((comp->flags & CF_WAIT) && comp->socket_type == SOCK_STREAM) { if (comp->max_instances) - COMPERR ("%s", _("max-instances ignored")); + COMPERR (grecs_error, "%s", _("max-instances ignored")); else comp->max_instances = 1; } } else if (comp->flags & CF_WAIT) { - COMPERR ("%s", _("wait is useless in this mode")); + /* TRANSLATORS: `wait' is a keywords, do not translate. */ + 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) { - COMPERR ("%s", _("stdout translation invalid in this mode")); + COMPERR (grecs_error, + "%s", _("stdout translation invalid in this mode")); comp->redir[RETR_OUT].type = redir_null; } @@ -1186,7 +1287,8 @@ component_verify (struct component *comp, grecs_locus_t *locus) comp->redir[i].v.file = p; } else - COMPERR (_("%s: must be an absolute " + COMPERR (grecs_error, + _("%s: must be an absolute " "file name or chdir must be specified"), comp->redir[i].v.file); } @@ -1225,8 +1327,8 @@ component_finish (struct component *comp, grecs_locus_t *locus) static int component_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; void **section_data = cb_data; @@ -1758,7 +1860,7 @@ enum pies_status }; enum pies_status -pies_check_status (pid_t * ppid) +pies_check_status (pid_t *ppid) { pid_t pid = pidfile_read (0); int i; |