inetd: use config parser. by Vladimir
No binary (build failed)
—
(log yok)
| @@ -300,9 +300,8 @@ struct globals { | |
| unsigned max_concurrency; | |
| smallint alarm_armed; | |
| uid_t real_uid; /* user ID who ran us */ | |
| - | unsigned config_lineno; |
| const char *config_filename; | |
| - | FILE *fconfig; |
| + | parser_t *parser; |
| char *default_local_hostname; | |
| #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN | |
| char *end_ring; | |
| @@ -327,9 +326,8 @@ struct BUG_G_too_big { | |
| #define max_concurrency (G.max_concurrency) | |
| #define alarm_armed (G.alarm_armed ) | |
| #define real_uid (G.real_uid ) | |
| - | #define config_lineno (G.config_lineno ) |
| #define config_filename (G.config_filename) | |
| - | #define fconfig (G.fconfig ) |
| + | #define parser (G.parser ) |
| #define default_local_hostname (G.default_local_hostname) | |
| #define first_ps_byte (G.first_ps_byte ) | |
| #define last_ps_byte (G.last_ps_byte ) | |
| @@ -543,61 +541,20 @@ static int reopen_config_file(void) | |
| { | |
| free(default_local_hostname); | |
| default_local_hostname = xstrdup("*"); | |
| - | if (fconfig != NULL) |
| - | fclose(fconfig); |
| - | config_lineno = 0; |
| - | fconfig = fopen_or_warn(config_filename, "r"); |
| - | return (fconfig != NULL); |
| + | if (parser != NULL) |
| + | config_close(parser); |
| + | parser = config_open(config_filename); |
| + | return (parser != NULL); |
| } | |
| static void close_config_file(void) | |
| { | |
| - | if (fconfig) { |
| - | fclose(fconfig); |
| - | fconfig = NULL; |
| + | if (parser) { |
| + | config_close(parser); |
| + | parser = NULL; |
| } | |
| } | |
| - | static char *next_line(void) |
| - | { |
| - | if (fgets(line, LINE_SIZE, fconfig) == NULL) |
| - | return NULL; |
| - | config_lineno++; |
| - | *strchrnul(line, '\n') = '\0'; |
| - | return line; |
| - | } |
| - | |
| - | static char *next_word(char **cpp) |
| - | { |
| - | char *start; |
| - | char *cp = *cpp; |
| - | |
| - | if (cp == NULL) |
| - | return NULL; |
| - | again: |
| - | while (*cp == ' ' || *cp == '\t') |
| - | cp++; |
| - | if (*cp == '\0') { |
| - | int c = getc(fconfig); |
| - | ungetc(c, fconfig); |
| - | if (c == ' ' || c == '\t') { |
| - | cp = next_line(); |
| - | if (cp) |
| - | goto again; |
| - | } |
| - | *cpp = NULL; |
| - | return NULL; |
| - | } |
| - | start = cp; |
| - | while (*cp && *cp != ' ' && *cp != '\t') |
| - | cp++; |
| - | if (*cp != '\0') |
| - | *cp++ = '\0'; |
| - | |
| - | *cpp = cp; |
| - | return start; |
| - | } |
| - | |
| static void free_servtab_strings(servtab_t *cp) | |
| { | |
| int i; | |
| @@ -643,55 +600,49 @@ static servtab_t *dup_servtab(servtab_t *sep) | |
| } | |
| /* gcc generates much more code if this is inlined */ | |
| - | static NOINLINE servtab_t *parse_one_line(void) |
| + | static servtab_t *parse_one_line(void) |
| { | |
| int argc; | |
| - | char *p, *cp, *arg; |
| + | char *token[6+MAXARGV]; |
| + | char *p, *arg; |
| char *hostdelim; | |
| servtab_t *sep; | |
| servtab_t *nsep; | |
| new: | |
| sep = new_servtab(); | |
| more: | |
| - | while ((cp = next_line()) && *cp == '#') |
| - | continue; /* skip comment lines */ |
| - | if (cp == NULL) { |
| + | argc = config_read(parser, token, 6+MAXARGV, 1, "# \t", PARSE_NORMAL); |
| + | if (!argc) { |
| free(sep); | |
| return NULL; | |
| } | |
| - | arg = next_word(&cp); |
| - | if (arg == NULL) /* a blank line. */ |
| - | goto more; |
| - | |
| /* [host:]service socktype proto wait user[:group] prog [args] */ | |
| /* Check for "host:...." line */ | |
| + | arg = token[0]; |
| hostdelim = strrchr(arg, ':'); | |
| if (hostdelim) { | |
| *hostdelim = '\0'; | |
| sep->se_local_hostname = xstrdup(arg); | |
| arg = hostdelim + 1; | |
| - | if (*arg == '\0') { |
| - | arg = next_word(&cp); |
| - | if (arg == NULL) { |
| - | /* Line has just "host:", change the |
| - | * default host for the following lines. */ |
| - | free(default_local_hostname); |
| - | default_local_hostname = sep->se_local_hostname; |
| - | goto more; |
| - | } |
| + | if (*arg == '\0' && argc == 1) { |
| + | /* Line has just "host:", change the |
| + | * default host for the following lines. */ |
| + | free(default_local_hostname); |
| + | default_local_hostname = sep->se_local_hostname; |
| + | goto more; |
| } | |
| } else | |
| sep->se_local_hostname = xstrdup(default_local_hostname); | |
| /* service socktype proto wait user[:group] prog [args] */ | |
| sep->se_service = xstrdup(arg); | |
| + | |
| /* socktype proto wait user[:group] prog [args] */ | |
| - | arg = next_word(&cp); |
| - | if (arg == NULL) { |
| + | if (argc < 6) { |
| parse_err: | |
| bb_error_msg("parse error on line %u, line is ignored", | |
| - | config_lineno); |
| + | parser->lineno); |
| free_servtab_strings(sep); | |
| /* Just "goto more" can make sep to carry over e.g. | |
| * "rpc"-ness (by having se_rpcver_lo != 0). | |
| @@ -699,6 +650,7 @@ static NOINLINE servtab_t *parse_one_line(void) | |
| free(sep); | |
| goto new; | |
| } | |
| + | |
| { | |
| static int8_t SOCK_xxx[] ALIGN1 = { | |
| -1, | |
| @@ -708,13 +660,11 @@ static NOINLINE servtab_t *parse_one_line(void) | |
| sep->se_socktype = SOCK_xxx[1 + index_in_strings( | |
| "stream""\0" "dgram""\0" "rdm""\0" | |
| "seqpacket""\0" "raw""\0" | |
| - | , arg)]; |
| + | , token[1])]; |
| } | |
| /* {unix,[rpc/]{tcp,udp}[6]} wait user[:group] prog [args] */ | |
| - | sep->se_proto = arg = xstrdup(next_word(&cp)); |
| - | if (arg == NULL) |
| - | goto parse_err; |
| + | sep->se_proto = arg = xstrdup(token[2]); |
| if (strcmp(arg, "unix") == 0) { | |
| sep->se_family = AF_UNIX; | |
| } else { | |
| @@ -773,9 +723,7 @@ static NOINLINE servtab_t *parse_one_line(void) | |
| } | |
| /* [no]wait[.max] user[:group] prog [args] */ | |
| - | arg = next_word(&cp); |
| - | if (arg == NULL) |
| - | goto parse_err; |
| + | arg = token[3]; |
| sep->se_max = max_concurrency; | |
| p = strchr(arg, '.'); | |
| if (p) { | |
| @@ -791,9 +739,7 @@ static NOINLINE servtab_t *parse_one_line(void) | |
| goto parse_err; | |
| /* user[:group] prog [args] */ | |
| - | sep->se_user = xstrdup(next_word(&cp)); |
| - | if (sep->se_user == NULL) |
| - | goto parse_err; |
| + | sep->se_user = xstrdup(token[4]); |
| arg = strchr(sep->se_user, '.'); | |
| if (arg == NULL) | |
| arg = strchr(sep->se_user, ':'); | |
| @@ -803,9 +749,7 @@ static NOINLINE servtab_t *parse_one_line(void) | |
| } | |
| /* prog [args] */ | |
| - | sep->se_program = xstrdup(next_word(&cp)); |
| - | if (sep->se_program == NULL) |
| - | goto parse_err; |
| + | sep->se_program = xstrdup(token[5]); |
| #ifdef INETD_BUILTINS_ENABLED | |
| if (strcmp(sep->se_program, "internal") == 0 | |
| && strlen(sep->se_service) <= 7 | |
| @@ -826,7 +770,7 @@ static NOINLINE servtab_t *parse_one_line(void) | |
| } | |
| #endif | |
| argc = 0; | |
| - | while ((arg = next_word(&cp)) != NULL && argc < MAXARGV) |
| + | while ((arg = token[6+argc]) != NULL && argc < MAXARGV) |
| sep->se_argv[argc++] = xstrdup(arg); | |
| /* catch mixups. "<service> stream udp ..." == wtf */ | |
| @@ -839,6 +783,11 @@ static NOINLINE servtab_t *parse_one_line(void) | |
| goto parse_err; | |
| } | |
| + | // bb_info_msg( |
| + | // "ENTRY[%s][%s][%s][%d][%d][%d][%d][%d][%s][%s][%s]", |
| + | // sep->se_local_hostname, sep->se_service, sep->se_proto, sep->se_wait, sep->se_proto_no, |
| + | // sep->se_max, sep->se_count, sep->se_time, sep->se_user, sep->se_group, sep->se_program); |
| + | |
| /* check if the hostname specifier is a comma separated list | |
| * of hostnames. we'll make new entries for each address. */ | |
| while ((hostdelim = strrchr(sep->se_local_hostname, ',')) != NULL) { | |