diff options
-rw-r--r-- | include/libbb.h | 20 | ||||
-rw-r--r-- | libbb/parse_config.c | 106 | ||||
-rw-r--r-- | miscutils/crond.c | 83 | ||||
-rw-r--r-- | networking/nameif.c | 20 |
4 files changed, 52 insertions, 177 deletions
diff --git a/include/libbb.h b/include/libbb.h index 3a7c2eee9..c124b1a5e 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -985,30 +985,20 @@ extern int set_loop(char **devname, const char *file, unsigned long long offset) | |||
985 | char *bb_askpass(int timeout, const char * prompt) FAST_FUNC; | 985 | char *bb_askpass(int timeout, const char * prompt) FAST_FUNC; |
986 | int bb_ask_confirmation(void) FAST_FUNC; | 986 | int bb_ask_confirmation(void) FAST_FUNC; |
987 | 987 | ||
988 | extern int bb_parse_mode(const char* s, mode_t* theMode) FAST_FUNC; | 988 | int bb_parse_mode(const char* s, mode_t* theMode) FAST_FUNC; |
989 | 989 | ||
990 | /* | 990 | /* |
991 | * Uniform config file parser helpers | 991 | * Uniform config file parser helpers |
992 | */ | 992 | */ |
993 | #define PARSER_STDIO_BASED 1 | ||
994 | #if !PARSER_STDIO_BASED | ||
995 | typedef struct parser_t { | ||
996 | char *data; | ||
997 | char *line; | ||
998 | int lineno; | ||
999 | } parser_t; | ||
1000 | extern char* config_open(parser_t *parser, const char *filename) FAST_FUNC; | ||
1001 | #else | ||
1002 | typedef struct parser_t { | 993 | typedef struct parser_t { |
1003 | FILE *fp; | 994 | FILE *fp; |
1004 | char *line; | 995 | char *line, *data; |
1005 | int lineno; | 996 | int lineno; |
1006 | } parser_t; | 997 | } parser_t; |
1007 | extern FILE* config_open(parser_t *parser, const char *filename) FAST_FUNC; | 998 | FILE* config_open(parser_t *parser, const char *filename) FAST_FUNC; |
1008 | #endif | ||
1009 | /* TODO: add define magic to collapse ntokens/mintokens/comment into one int param */ | 999 | /* TODO: add define magic to collapse ntokens/mintokens/comment into one int param */ |
1010 | extern char* config_read(parser_t *parser, char **tokens, int ntokens, int mintokens, const char *delims, char comment) FAST_FUNC; | 1000 | int config_read(parser_t *parser, char **tokens, int ntokens, int mintokens, const char *delims, char comment) FAST_FUNC; |
1011 | extern void config_close(parser_t *parser) FAST_FUNC; | 1001 | void config_close(parser_t *parser) FAST_FUNC; |
1012 | 1002 | ||
1013 | /* Concatenate path and filename to new allocated buffer. | 1003 | /* Concatenate path and filename to new allocated buffer. |
1014 | * Add "/" only as needed (no duplicate "//" are produced). | 1004 | * Add "/" only as needed (no duplicate "//" are produced). |
diff --git a/libbb/parse_config.c b/libbb/parse_config.c index 6612db367..e63204b09 100644 --- a/libbb/parse_config.c +++ b/libbb/parse_config.c | |||
@@ -31,101 +31,6 @@ Typical usage: | |||
31 | 31 | ||
32 | */ | 32 | */ |
33 | 33 | ||
34 | #if !PARSER_STDIO_BASED | ||
35 | |||
36 | char* FAST_FUNC config_open(parser_t *parser, const char *filename) | ||
37 | { | ||
38 | // empty file configures nothing! | ||
39 | char *data = xmalloc_open_read_close(filename, NULL); | ||
40 | if (!data) | ||
41 | return data; | ||
42 | |||
43 | // convert 0x5c 0x0a (backslashes at the very end of line) to 0x20 0x20 (spaces) | ||
44 | for (char *s = data; (s = strchr(s, '\\')) != NULL; ++s) | ||
45 | if ('\n' == s[1]) { | ||
46 | s[0] = s[1] = ' '; | ||
47 | } | ||
48 | |||
49 | // init parser | ||
50 | parser->line = parser->data = data; | ||
51 | parser->lineno = 0; | ||
52 | |||
53 | return data; | ||
54 | } | ||
55 | |||
56 | void FAST_FUNC config_close(parser_t *parser) | ||
57 | { | ||
58 | // for now just free config data | ||
59 | free(parser->data); | ||
60 | } | ||
61 | |||
62 | char* FAST_FUNC config_read(parser_t *parser, char **tokens, int ntokens, int mintokens, const char *delims, char comment) | ||
63 | { | ||
64 | char *ret, *line; | ||
65 | int noreduce = (ntokens<0); // do not treat subsequent delimiters as one delimiter | ||
66 | if (ntokens < 0) | ||
67 | ntokens = -ntokens; | ||
68 | ret = line = parser->line; | ||
69 | // nullify tokens | ||
70 | memset(tokens, 0, sizeof(void *) * ntokens); | ||
71 | // now split to lines | ||
72 | while (*line) { | ||
73 | int token_num = 0; | ||
74 | // limit the line | ||
75 | char *ptr = strchrnul(line, '\n'); | ||
76 | *ptr++ = '\0'; | ||
77 | // line number | ||
78 | parser->lineno++; | ||
79 | // comments mean EOLs | ||
80 | if (comment) | ||
81 | *strchrnul(line, comment) = '\0'; | ||
82 | // skip leading delimiters | ||
83 | while (*line && strchr(delims, *line)) | ||
84 | line++; | ||
85 | // skip empty lines | ||
86 | if (*line) { | ||
87 | char *s; | ||
88 | // now split line to tokens | ||
89 | s = line; | ||
90 | while (s) { | ||
91 | char *p; | ||
92 | // get next token | ||
93 | if (token_num+1 >= ntokens) | ||
94 | break; | ||
95 | p = s; | ||
96 | while (*p && !strchr(delims, *p)) | ||
97 | p++; | ||
98 | if (!*p) | ||
99 | break; | ||
100 | *p++ = '\0'; | ||
101 | // pin token | ||
102 | if (noreduce || *s) { | ||
103 | tokens[token_num++] = s; | ||
104 | //bb_error_msg("L[%d] T[%s]", token_num, s); | ||
105 | } | ||
106 | s = p; | ||
107 | } | ||
108 | // non-empty remainder is also a token. So if ntokens == 0, we just return the whole line | ||
109 | if (s && (noreduce || *s)) | ||
110 | tokens[token_num++] = s; | ||
111 | // sanity check: have we got all required tokens? | ||
112 | if (token_num < mintokens) | ||
113 | bb_error_msg_and_die("bad line %u, %d tokens found, %d needed", parser->lineno, token_num, mintokens); | ||
114 | // advance data for the next call | ||
115 | line = ptr; | ||
116 | break; | ||
117 | } | ||
118 | // line didn't contain any token -> try next line | ||
119 | ret = line = ptr; | ||
120 | } | ||
121 | parser->line = line; | ||
122 | |||
123 | // return current line. caller must check *ret to determine whether to continue | ||
124 | return ret; | ||
125 | } | ||
126 | |||
127 | #else // stdio-based | ||
128 | |||
129 | FILE* FAST_FUNC config_open(parser_t *parser, const char *filename) | 34 | FILE* FAST_FUNC config_open(parser_t *parser, const char *filename) |
130 | { | 35 | { |
131 | // empty file configures nothing! | 36 | // empty file configures nothing! |
@@ -142,10 +47,12 @@ FILE* FAST_FUNC config_open(parser_t *parser, const char *filename) | |||
142 | 47 | ||
143 | void FAST_FUNC config_close(parser_t *parser) | 48 | void FAST_FUNC config_close(parser_t *parser) |
144 | { | 49 | { |
50 | free(parser->line); | ||
51 | free(parser->data); | ||
145 | fclose(parser->fp); | 52 | fclose(parser->fp); |
146 | } | 53 | } |
147 | 54 | ||
148 | char* FAST_FUNC config_read(parser_t *parser, char **tokens, int ntokens, int mintokens, const char *delims, char comment) | 55 | int FAST_FUNC config_read(parser_t *parser, char **tokens, int ntokens, int mintokens, const char *delims, char comment) |
149 | { | 56 | { |
150 | char *line, *q; | 57 | char *line, *q; |
151 | int token_num, len; | 58 | int token_num, len; |
@@ -160,6 +67,8 @@ char* FAST_FUNC config_read(parser_t *parser, char **tokens, int ntokens, int mi | |||
160 | // free used line | 67 | // free used line |
161 | free(parser->line); | 68 | free(parser->line); |
162 | parser->line = NULL; | 69 | parser->line = NULL; |
70 | free(parser->data); | ||
71 | parser->data = NULL; | ||
163 | 72 | ||
164 | while (1) { | 73 | while (1) { |
165 | int n; | 74 | int n; |
@@ -211,6 +120,7 @@ char* FAST_FUNC config_read(parser_t *parser, char **tokens, int ntokens, int mi | |||
211 | 120 | ||
212 | // store line | 121 | // store line |
213 | parser->line = line = xrealloc(line, len + 1); | 122 | parser->line = line = xrealloc(line, len + 1); |
123 | parser->data = xstrdup(line); | ||
214 | 124 | ||
215 | // now split line to tokens | 125 | // now split line to tokens |
216 | //TODO: discard consecutive delimiters? | 126 | //TODO: discard consecutive delimiters? |
@@ -241,7 +151,5 @@ char* FAST_FUNC config_read(parser_t *parser, char **tokens, int ntokens, int mi | |||
241 | bb_error_msg_and_die("bad line %u: %d tokens found, %d needed", | 151 | bb_error_msg_and_die("bad line %u: %d tokens found, %d needed", |
242 | parser->lineno, token_num, mintokens); | 152 | parser->lineno, token_num, mintokens); |
243 | 153 | ||
244 | return parser->line; // maybe token_num instead? | 154 | return token_num; |
245 | } | 155 | } |
246 | |||
247 | #endif | ||
diff --git a/miscutils/crond.c b/miscutils/crond.c index e48abf9f8..af37bb15b 100644 --- a/miscutils/crond.c +++ b/miscutils/crond.c | |||
@@ -304,7 +304,7 @@ static const char MonAry[] ALIGN1 = | |||
304 | /* "Jan""Feb""Mar""Apr""May""Jun""Jul""Aug""Sep""Oct""Nov""Dec" */ | 304 | /* "Jan""Feb""Mar""Apr""May""Jun""Jul""Aug""Sep""Oct""Nov""Dec" */ |
305 | ; | 305 | ; |
306 | 306 | ||
307 | static char *ParseField(char *user, char *ary, int modvalue, int off, | 307 | static void ParseField(char *user, char *ary, int modvalue, int off, |
308 | const char *names, char *ptr) | 308 | const char *names, char *ptr) |
309 | /* 'names' is a pointer to a set of 3-char abbreviations */ | 309 | /* 'names' is a pointer to a set of 3-char abbreviations */ |
310 | { | 310 | { |
@@ -312,11 +312,11 @@ static char *ParseField(char *user, char *ary, int modvalue, int off, | |||
312 | int n1 = -1; | 312 | int n1 = -1; |
313 | int n2 = -1; | 313 | int n2 = -1; |
314 | 314 | ||
315 | if (base == NULL) { | 315 | // this can't happen due to config_read() |
316 | return NULL; | 316 | /*if (base == NULL) |
317 | } | 317 | return;*/ |
318 | 318 | ||
319 | while (!isspace(*ptr)) { | 319 | while (1) { |
320 | int skip = 0; | 320 | int skip = 0; |
321 | 321 | ||
322 | /* Handle numeric digit or symbol or '*' */ | 322 | /* Handle numeric digit or symbol or '*' */ |
@@ -352,8 +352,7 @@ static char *ParseField(char *user, char *ary, int modvalue, int off, | |||
352 | 352 | ||
353 | /* handle optional range '-' */ | 353 | /* handle optional range '-' */ |
354 | if (skip == 0) { | 354 | if (skip == 0) { |
355 | crondlog(WARN9 "user %s: parse error at %s", user, base); | 355 | goto err; |
356 | return NULL; | ||
357 | } | 356 | } |
358 | if (*ptr == '-' && n2 < 0) { | 357 | if (*ptr == '-' && n2 < 0) { |
359 | ++ptr; | 358 | ++ptr; |
@@ -388,8 +387,7 @@ static char *ParseField(char *user, char *ary, int modvalue, int off, | |||
388 | s0 = skip; | 387 | s0 = skip; |
389 | } | 388 | } |
390 | if (--failsafe == 0) { | 389 | if (--failsafe == 0) { |
391 | crondlog(WARN9 "user %s: parse error at %s", user, base); | 390 | goto err; |
392 | return NULL; | ||
393 | } | 391 | } |
394 | } while (n1 != n2); | 392 | } while (n1 != n2); |
395 | 393 | ||
@@ -402,9 +400,10 @@ static char *ParseField(char *user, char *ary, int modvalue, int off, | |||
402 | n2 = -1; | 400 | n2 = -1; |
403 | } | 401 | } |
404 | 402 | ||
405 | if (!isspace(*ptr)) { | 403 | if (*ptr) { |
404 | err: | ||
406 | crondlog(WARN9 "user %s: parse error at %s", user, base); | 405 | crondlog(WARN9 "user %s: parse error at %s", user, base); |
407 | return NULL; | 406 | return; |
408 | } | 407 | } |
409 | 408 | ||
410 | if (DebugOpt && (LogLevel <= 5)) { /* like LVL5 */ | 409 | if (DebugOpt && (LogLevel <= 5)) { /* like LVL5 */ |
@@ -414,7 +413,6 @@ static char *ParseField(char *user, char *ary, int modvalue, int off, | |||
414 | fprintf(stderr, "%d", (unsigned char)ary[i]); | 413 | fprintf(stderr, "%d", (unsigned char)ary[i]); |
415 | fputc('\n', stderr); | 414 | fputc('\n', stderr); |
416 | } | 415 | } |
417 | return skip_whitespace(ptr); | ||
418 | } | 416 | } |
419 | 417 | ||
420 | static void FixDayDow(CronLine *line) | 418 | static void FixDayDow(CronLine *line) |
@@ -445,11 +443,10 @@ static void FixDayDow(CronLine *line) | |||
445 | 443 | ||
446 | static void SynchronizeFile(const char *fileName) | 444 | static void SynchronizeFile(const char *fileName) |
447 | { | 445 | { |
448 | FILE *fi; | 446 | struct parser_t parser; |
449 | struct stat sbuf; | 447 | struct stat sbuf; |
450 | int maxEntries; | ||
451 | int maxLines; | 448 | int maxLines; |
452 | char buf[1024]; | 449 | char *tokens[6]; |
453 | #if ENABLE_FEATURE_CROND_CALL_SENDMAIL | 450 | #if ENABLE_FEATURE_CROND_CALL_SENDMAIL |
454 | char *mailTo = NULL; | 451 | char *mailTo = NULL; |
455 | #endif | 452 | #endif |
@@ -458,57 +455,44 @@ static void SynchronizeFile(const char *fileName) | |||
458 | return; | 455 | return; |
459 | 456 | ||
460 | DeleteFile(fileName); | 457 | DeleteFile(fileName); |
461 | fi = fopen(fileName, "r"); | 458 | if (!config_open(&parser, fileName)) |
462 | if (!fi) | ||
463 | return; | 459 | return; |
464 | 460 | ||
465 | maxEntries = MAXLINES; | 461 | maxLines = (strcmp(fileName, "root") == 0) ? 65535 : MAXLINES; |
466 | if (strcmp(fileName, "root") == 0) { | ||
467 | maxEntries = 65535; | ||
468 | } | ||
469 | maxLines = maxEntries * 10; | ||
470 | 462 | ||
471 | if (fstat(fileno(fi), &sbuf) == 0 && sbuf.st_uid == DaemonUid) { | 463 | if (fstat(fileno(parser.fp), &sbuf) == 0 && sbuf.st_uid == DaemonUid) { |
472 | CronFile *file = xzalloc(sizeof(CronFile)); | 464 | CronFile *file = xzalloc(sizeof(CronFile)); |
473 | CronLine **pline; | 465 | CronLine **pline; |
466 | int n; | ||
474 | 467 | ||
475 | file->cf_User = xstrdup(fileName); | 468 | file->cf_User = xstrdup(fileName); |
476 | pline = &file->cf_LineBase; | 469 | pline = &file->cf_LineBase; |
477 | 470 | ||
478 | while (fgets(buf, sizeof(buf), fi) != NULL && --maxLines) { | 471 | while (--maxLines && (n=config_read(&parser, tokens, 6, 0, " \t", '#')) > 0) { |
479 | CronLine *line; | 472 | CronLine *line; |
480 | char *ptr; | ||
481 | 473 | ||
482 | trim(buf); | ||
483 | if (buf[0] == '\0' || buf[0] == '#') { | ||
484 | continue; | ||
485 | } | ||
486 | if (--maxEntries == 0) { | ||
487 | break; | ||
488 | } | ||
489 | if (DebugOpt) { | 474 | if (DebugOpt) { |
490 | crondlog(LVL5 "user:%s entry:%s", fileName, buf); | 475 | crondlog(LVL5 "user:%s entry:%s", fileName, parser.data); |
491 | } | 476 | } |
477 | |||
492 | /* check if line is setting MAILTO= */ | 478 | /* check if line is setting MAILTO= */ |
493 | if (0 == strncmp("MAILTO=", buf, 7)) { | 479 | if (0 == strncmp(tokens[0], "MAILTO=", 7)) { |
494 | #if ENABLE_FEATURE_CROND_CALL_SENDMAIL | 480 | #if ENABLE_FEATURE_CROND_CALL_SENDMAIL |
495 | free(mailTo); | 481 | free(mailTo); |
496 | mailTo = (buf[7]) ? xstrdup(buf+7) : NULL; | 482 | mailTo = (tokens[0][7]) ? xstrdup(&tokens[0][7]) : NULL; |
497 | #endif /* otherwise just ignore such lines */ | 483 | #endif /* otherwise just ignore such lines */ |
498 | continue; | 484 | continue; |
499 | } | 485 | } |
486 | /* check if a minimum of tokens is specified */ | ||
487 | if (n < 5) | ||
488 | continue; | ||
500 | *pline = line = xzalloc(sizeof(CronLine)); | 489 | *pline = line = xzalloc(sizeof(CronLine)); |
501 | /* parse date ranges */ | 490 | /* parse date ranges */ |
502 | ptr = ParseField(file->cf_User, line->cl_Mins, 60, 0, NULL, buf); | 491 | ParseField(file->cf_User, line->cl_Mins, 60, 0, NULL, tokens[0]); |
503 | ptr = ParseField(file->cf_User, line->cl_Hrs, 24, 0, NULL, ptr); | 492 | ParseField(file->cf_User, line->cl_Hrs, 24, 0, NULL, tokens[1]); |
504 | ptr = ParseField(file->cf_User, line->cl_Days, 32, 0, NULL, ptr); | 493 | ParseField(file->cf_User, line->cl_Days, 32, 0, NULL, tokens[2]); |
505 | ptr = ParseField(file->cf_User, line->cl_Mons, 12, -1, MonAry, ptr); | 494 | ParseField(file->cf_User, line->cl_Mons, 12, -1, MonAry, tokens[3]); |
506 | ptr = ParseField(file->cf_User, line->cl_Dow, 7, 0, DowAry, ptr); | 495 | ParseField(file->cf_User, line->cl_Dow, 7, 0, DowAry, tokens[4]); |
507 | /* check failure */ | ||
508 | if (ptr == NULL) { | ||
509 | free(line); | ||
510 | continue; | ||
511 | } | ||
512 | /* | 496 | /* |
513 | * fix days and dow - if one is not "*" and the other | 497 | * fix days and dow - if one is not "*" and the other |
514 | * is "*", the other is set to 0, and vise-versa | 498 | * is "*", the other is set to 0, and vise-versa |
@@ -519,22 +503,23 @@ static void SynchronizeFile(const char *fileName) | |||
519 | line->cl_MailTo = xstrdup(mailTo); | 503 | line->cl_MailTo = xstrdup(mailTo); |
520 | #endif | 504 | #endif |
521 | /* copy command */ | 505 | /* copy command */ |
522 | line->cl_Shell = xstrdup(ptr); | 506 | line->cl_Shell = xstrdup(tokens[5]); |
523 | if (DebugOpt) { | 507 | if (DebugOpt) { |
524 | crondlog(LVL5 " command:%s", ptr); | 508 | crondlog(LVL5 " command:%s", tokens[5]); |
525 | } | 509 | } |
526 | pline = &line->cl_Next; | 510 | pline = &line->cl_Next; |
511 | //bb_error_msg("M[%s]F[%s][%s][%s][%s][%s][%s]", mailTo, tokens[0], tokens[1], tokens[2], tokens[3], tokens[4], tokens[5]); | ||
527 | } | 512 | } |
528 | *pline = NULL; | 513 | *pline = NULL; |
529 | 514 | ||
530 | file->cf_Next = FileBase; | 515 | file->cf_Next = FileBase; |
531 | FileBase = file; | 516 | FileBase = file; |
532 | 517 | ||
533 | if (maxLines == 0 || maxEntries == 0) { | 518 | if (maxLines == 0) { |
534 | crondlog(WARN9 "user %s: too many lines", fileName); | 519 | crondlog(WARN9 "user %s: too many lines", fileName); |
535 | } | 520 | } |
536 | } | 521 | } |
537 | fclose(fi); | 522 | config_close(&parser); |
538 | } | 523 | } |
539 | 524 | ||
540 | static void CheckUpdates(void) | 525 | static void CheckUpdates(void) |
diff --git a/networking/nameif.c b/networking/nameif.c index f3d333baf..506f4fa1c 100644 --- a/networking/nameif.c +++ b/networking/nameif.c | |||
@@ -160,21 +160,13 @@ int nameif_main(int argc, char **argv) | |||
160 | prepend_new_eth_table(&clist, ifname, *argv++); | 160 | prepend_new_eth_table(&clist, ifname, *argv++); |
161 | } | 161 | } |
162 | } else { | 162 | } else { |
163 | ifh = xfopen(fname, "r"); | 163 | struct parser_t parser; |
164 | while ((line = xmalloc_fgets(ifh)) != NULL) { | 164 | if (config_open(&parser, fname)) { |
165 | char *next; | 165 | char *tokens[2]; |
166 | 166 | while (config_read(&parser, tokens, 2, 2, " \t", '#')) | |
167 | line_ptr = skip_whitespace(line); | 167 | prepend_new_eth_table(&clist, tokens[0], tokens[1]); |
168 | if ((line_ptr[0] == '#') || (line_ptr[0] == '\n')) | 168 | config_close(&parser); |
169 | goto read_next_line; | ||
170 | next = skip_non_whitespace(line_ptr); | ||
171 | if (*next) | ||
172 | *next++ = '\0'; | ||
173 | prepend_new_eth_table(&clist, line_ptr, next); | ||
174 | read_next_line: | ||
175 | free(line); | ||
176 | } | 169 | } |
177 | fclose(ifh); | ||
178 | } | 170 | } |
179 | 171 | ||
180 | ctl_sk = xsocket(PF_INET, SOCK_DGRAM, 0); | 172 | ctl_sk = xsocket(PF_INET, SOCK_DGRAM, 0); |