aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libbb.h20
-rw-r--r--libbb/parse_config.c106
-rw-r--r--miscutils/crond.c83
-rw-r--r--networking/nameif.c20
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)
985char *bb_askpass(int timeout, const char * prompt) FAST_FUNC; 985char *bb_askpass(int timeout, const char * prompt) FAST_FUNC;
986int bb_ask_confirmation(void) FAST_FUNC; 986int bb_ask_confirmation(void) FAST_FUNC;
987 987
988extern int bb_parse_mode(const char* s, mode_t* theMode) FAST_FUNC; 988int 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
995typedef struct parser_t {
996 char *data;
997 char *line;
998 int lineno;
999} parser_t;
1000extern char* config_open(parser_t *parser, const char *filename) FAST_FUNC;
1001#else
1002typedef struct parser_t { 993typedef 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;
1007extern FILE* config_open(parser_t *parser, const char *filename) FAST_FUNC; 998FILE* 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 */
1010extern char* config_read(parser_t *parser, char **tokens, int ntokens, int mintokens, const char *delims, char comment) FAST_FUNC; 1000int config_read(parser_t *parser, char **tokens, int ntokens, int mintokens, const char *delims, char comment) FAST_FUNC;
1011extern void config_close(parser_t *parser) FAST_FUNC; 1001void 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
36char* 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
56void FAST_FUNC config_close(parser_t *parser)
57{
58 // for now just free config data
59 free(parser->data);
60}
61
62char* 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
129FILE* FAST_FUNC config_open(parser_t *parser, const char *filename) 34FILE* 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
143void FAST_FUNC config_close(parser_t *parser) 48void 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
148char* FAST_FUNC config_read(parser_t *parser, char **tokens, int ntokens, int mintokens, const char *delims, char comment) 55int 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
307static char *ParseField(char *user, char *ary, int modvalue, int off, 307static 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
420static void FixDayDow(CronLine *line) 418static void FixDayDow(CronLine *line)
@@ -445,11 +443,10 @@ static void FixDayDow(CronLine *line)
445 443
446static void SynchronizeFile(const char *fileName) 444static 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
540static void CheckUpdates(void) 525static 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);