aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-07-26 23:08:31 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-07-26 23:08:31 +0000
commit084266ed520805bbc4ec3f9b4d14e644ecd75880 (patch)
treefe2c8531dc039c81c12a39f39fcfdf6c1b8ec996
parent8895c2073e9341d8e0348365e75ba6aa4b9b8d05 (diff)
downloadbusybox-w32-084266ed520805bbc4ec3f9b4d14e644ecd75880.tar.gz
busybox-w32-084266ed520805bbc4ec3f9b4d14e644ecd75880.tar.bz2
busybox-w32-084266ed520805bbc4ec3f9b4d14e644ecd75880.zip
fix several problems with config parser:
a bug where it underflows the string a bug where it never frees parser_t struct make read_config() return 0 if parser is NULL, make config_close() accept and ignore NULL parser - eliminates many if() blocks reverse the sense of parser bit flags - negative flags are harder to grok. hexdump: revert the change to use config parser, it is BIGGER and also requires additional quirks in parser *: explicitly use PARSER_NORMAL instead of 0 function old new delta login_main 1575 1596 +21 config_close 18 29 +11 bbunpack 383 391 +8 qgravechar 106 109 +3 rtnl_tab_initialize 121 117 -4 expand 1697 1693 -4 man_main 717 712 -5 nameif_main 674 668 -6 hexdump_main 597 591 -6 read_config 217 209 -8 dnsd_main 1478 1470 -8 sysctl_main 203 189 -14 config_open2 44 25 -19 make_device 1177 1141 -36 config_read 597 549 -48 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 4/11 up/down: 43/-158) Total: -115 bytes
-rw-r--r--include/libbb.h21
-rw-r--r--init/init.c4
-rw-r--r--libbb/parse_config.c102
-rw-r--r--loginutils/login.c21
-rw-r--r--miscutils/crond.c12
-rw-r--r--miscutils/fbsplash.c4
-rw-r--r--miscutils/man.c1
-rw-r--r--modutils/modprobe-small.c2
-rw-r--r--networking/dnsd.c60
-rw-r--r--networking/hostname.c2
-rw-r--r--networking/libiproute/rt_names.c4
-rw-r--r--networking/nameif.c10
-rw-r--r--networking/udhcp/files.c5
-rw-r--r--procps/sysctl.c5
-rw-r--r--selinux/sestatus.c5
-rwxr-xr-xtestsuite/parse.tests28
-rw-r--r--util-linux/hexdump.c16
-rw-r--r--util-linux/mdev.c6
18 files changed, 163 insertions, 145 deletions
diff --git a/include/libbb.h b/include/libbb.h
index 47fcdf08b..48cbd90c0 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -998,15 +998,20 @@ int bb_parse_mode(const char* s, mode_t* theMode) FAST_FUNC;
998 * Config file parser 998 * Config file parser
999 */ 999 */
1000enum { 1000enum {
1001 PARSE_VANILLA = 0x00000000, // trim line, collapse delimiters, warn and continue if less than mintokens 1001 PARSE_COLLAPSE = 0x00010000, // treat consecutive delimiters as one
1002 PARSE_DONT_REDUCE = 0x00010000, // do not treat consecutive delimiters as one 1002 PARSE_TRIM = 0x00020000, // trim leading and trailing delimiters
1003 PARSE_DONT_TRIM = 0x00020000, // do not trim line of leading and trailing delimiters 1003// TODO: COLLAPSE and TRIM seem to always go in pair
1004 PARSE_LAST_IS_GREEDY = 0x00040000, // last token takes whole remainder of the line 1004 PARSE_GREEDY = 0x00040000, // last token takes entire remainder of the line
1005// PARSE_DONT_NULL = 0x00080000, // do not set tokens[] to NULL 1005 PARSE_MIN_DIE = 0x00100000, // die if < min tokens found
1006 PARSE_MIN_DIE = 0x00100000, // die if less tokens found
1007 // keep a copy of current line 1006 // keep a copy of current line
1008 PARSE_KEEP_COPY = 0x00200000 * ENABLE_DEBUG_CROND_OPTION, 1007 PARSE_KEEP_COPY = 0x00200000 * ENABLE_DEBUG_CROND_OPTION,
1009 PARSE_ESCAPE = 0x00400000, // process escape sequences in tokens 1008// PARSE_ESCAPE = 0x00400000, // process escape sequences in tokens
1009 // NORMAL is:
1010 // * remove leading and trailing delimiters and collapse
1011 // multiple delimiters into one
1012 // * warn and continue if less than mintokens delimiters found
1013 // * grab everything into last token
1014 PARSE_NORMAL = PARSE_COLLAPSE | PARSE_TRIM | PARSE_GREEDY,
1010}; 1015};
1011typedef struct parser_t { 1016typedef struct parser_t {
1012 FILE *fp; 1017 FILE *fp;
diff --git a/init/init.c b/init/init.c
index 884603af3..e02773cc0 100644
--- a/init/init.c
+++ b/init/init.c
@@ -701,13 +701,13 @@ static void parse_inittab(void)
701 new_init_action(ASKFIRST, bb_default_login_shell, VC_4); 701 new_init_action(ASKFIRST, bb_default_login_shell, VC_4);
702 /* sysinit */ 702 /* sysinit */
703 new_init_action(SYSINIT, INIT_SCRIPT, ""); 703 new_init_action(SYSINIT, INIT_SCRIPT, "");
704
705 return; 704 return;
706 } 705 }
707 /* optional_tty:ignored_runlevel:action:command 706 /* optional_tty:ignored_runlevel:action:command
708 * Delims are not to be collapsed and need exactly 4 tokens 707 * Delims are not to be collapsed and need exactly 4 tokens
709 */ 708 */
710 while (config_read(parser, token, 4, 0, "#:", PARSE_DONT_TRIM|PARSE_DONT_REDUCE|PARSE_LAST_IS_GREEDY)) { 709 while (config_read(parser, token, 4, 0, "#:",
710 PARSE_NORMAL & ~(PARSE_TRIM | PARSE_COLLAPSE))) {
711 int action; 711 int action;
712 char *tty = token[0]; 712 char *tty = token[0];
713 713
diff --git a/libbb/parse_config.c b/libbb/parse_config.c
index 83dc997f6..ace6f3ad3 100644
--- a/libbb/parse_config.c
+++ b/libbb/parse_config.c
@@ -14,8 +14,9 @@ int parse_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
14int parse_main(int argc UNUSED_PARAM, char **argv) 14int parse_main(int argc UNUSED_PARAM, char **argv)
15{ 15{
16 const char *delims = "# \t"; 16 const char *delims = "# \t";
17 unsigned flags = 0; 17 unsigned flags = PARSE_NORMAL;
18 int mintokens = 0, ntokens = 128; 18 int mintokens = 0, ntokens = 128;
19
19 opt_complementary = "-1:n+:m+:f+"; 20 opt_complementary = "-1:n+:m+:f+";
20 getopt32(argv, "n:m:d:f:", &ntokens, &mintokens, &delims, &flags); 21 getopt32(argv, "n:m:d:f:", &ntokens, &mintokens, &delims, &flags);
21 //argc -= optind; 22 //argc -= optind;
@@ -61,13 +62,15 @@ Typical usage:
61 62
62parser_t* FAST_FUNC config_open2(const char *filename, FILE* FAST_FUNC (*fopen_func)(const char *path)) 63parser_t* FAST_FUNC config_open2(const char *filename, FILE* FAST_FUNC (*fopen_func)(const char *path))
63{ 64{
64 parser_t *parser = xzalloc(sizeof(parser_t)); 65 FILE* fp;
65 /* empty file configures nothing */ 66 parser_t *parser;
66 parser->fp = fopen_func(filename); 67
67 if (parser->fp) 68 fp = fopen_func(filename);
68 return parser; 69 if (!fp)
69 free(parser); 70 return NULL;
70 return NULL; 71 parser = xzalloc(sizeof(*parser));
72 parser->fp = fp;
73 return parser;
71} 74}
72 75
73parser_t* FAST_FUNC config_open(const char *filename) 76parser_t* FAST_FUNC config_open(const char *filename)
@@ -87,41 +90,53 @@ static void config_free_data(parser_t *const parser)
87 90
88void FAST_FUNC config_close(parser_t *parser) 91void FAST_FUNC config_close(parser_t *parser)
89{ 92{
90 config_free_data(parser); 93 if (parser) {
91 fclose(parser->fp); 94 config_free_data(parser);
95 fclose(parser->fp);
96 free(parser);
97 }
92} 98}
93 99
94/* 100/*
951. Read a line from config file. If nothing to read then bail out returning 0. 1010. If parser is NULL return 0.
96 Handle continuation character. Advance lineno for each physical line. Cut comments. 1021. Read a line from config file. If nothing to read then return 0.
972. if PARSE_DONT_TRIM is not set (default) skip leading and cut trailing delimiters, if any. 103 Handle continuation character. Advance lineno for each physical line.
104 Discard everything past comment characher.
1052. if PARSE_TRIM is set (default), remove leading and trailing delimiters.
983. If resulting line is empty goto 1. 1063. If resulting line is empty goto 1.
994. Look for first delimiter. If PARSE_DONT_REDUCE or PARSE_DONT_TRIM is set then pin empty token. 1074. Look for first delimiter. If !PARSE_COLLAPSE or !PARSE_TRIM is set then
1005. Else (default) if number of seen tokens is equal to max number of tokens (token is the last one) 108 remember the token as empty.
101 and PARSE_LAST_IS_GREEDY is set then pin the remainder of the line as the last token. 1095. Else (default) if number of seen tokens is equal to max number of tokens
102 Else (token is not last or PARSE_LAST_IS_GREEDY is not set) just replace first delimiter with '\0' 110 (token is the last one) and PARSE_GREEDY is set then the remainder
103 thus delimiting token and pin it. 111 of the line is the last token.
1046. Advance line pointer past the end of token. If number of seen tokens is less than required number 112 Else (token is not last or PARSE_GREEDY is not set) just replace
105 of tokens then goto 4. 113 first delimiter with '\0' thus delimiting the token.
1067. Control the number of seen tokens is not less the min number of tokens. Die if condition is not met. 1146. Advance line pointer past the end of token. If number of seen tokens
115 is less than required number of tokens then goto 4.
1167. Check the number of seen tokens is not less the min number of tokens.
117 Complain or die otherwise depending on PARSE_MIN_DIE.
1078. Return the number of seen tokens. 1188. Return the number of seen tokens.
108 119
109mintokens > 0 make config_read() exit with error message if less than mintokens 120mintokens > 0 make config_read() print error message if less than mintokens
110(but more than 0) are found. Empty lines are always skipped (not warned about). 121(but more than 0) are found. Empty lines are always skipped (not warned about).
111*/ 122*/
112#undef config_read 123#undef config_read
113int FAST_FUNC config_read(parser_t *parser, char **tokens, unsigned flags, const char *delims) 124int FAST_FUNC config_read(parser_t *parser, char **tokens, unsigned flags, const char *delims)
114{ 125{
115 char *line, *q; 126 char *line, *q;
116 char comment = *delims++; 127 char comment;
117 int ii; 128 int ii;
118 int ntokens = flags & 0xFF; 129 int ntokens;
119 int mintokens = (flags & 0xFF00) >> 8; 130 int mintokens;
131
132 comment = *delims++;
133 ntokens = flags & 0xFF;
134 mintokens = (flags & 0xFF00) >> 8;
120 135
121 again: 136 again:
122 // N.B. this could only be used in read-in-one-go version, or when tokens use xstrdup(). TODO 137 memset(tokens, 0, sizeof(tokens[0]) * ntokens);
123 //if (!parser->lineno || !(flags & PARSE_DONT_NULL)) 138 if (!parser)
124 memset(tokens, 0, sizeof(tokens[0]) * ntokens); 139 return 0;
125 config_free_data(parser); 140 config_free_data(parser);
126 141
127 while (1) { 142 while (1) {
@@ -142,20 +157,20 @@ int FAST_FUNC config_read(parser_t *parser, char **tokens, unsigned flags, const
142 line[--ii] = '\0'; 157 line[--ii] = '\0';
143//TODO: add xmalloc_fgetline-like iface but with appending to existing str 158//TODO: add xmalloc_fgetline-like iface but with appending to existing str
144 q = xmalloc_fgetline(parser->fp); 159 q = xmalloc_fgetline(parser->fp);
145 if (q) { 160 if (!q)
146 parser->lineno++; 161 break;
147 line = xasprintf("%s%s", line, q); 162 parser->lineno++;
148 free(q); 163 line = xasprintf("%s%s", line, q);
149 } 164 free(q);
150 } 165 }
151 // comments mean EOLs 166 // discard comments
152 if (comment) { 167 if (comment) {
153 q = strchrnul(line, comment); 168 q = strchrnul(line, comment);
154 *q = '\0'; 169 *q = '\0';
155 ii = q - line; 170 ii = q - line;
156 } 171 }
157 // skip leading and trailing delimiters 172 // skip leading and trailing delimiters
158 if (!(flags & PARSE_DONT_TRIM)) { 173 if (flags & PARSE_TRIM) {
159 // skip leading 174 // skip leading
160 int n = strspn(line, delims); 175 int n = strspn(line, delims);
161 if (n) { 176 if (n) {
@@ -177,7 +192,6 @@ int FAST_FUNC config_read(parser_t *parser, char **tokens, unsigned flags, const
177 // skip empty line 192 // skip empty line
178 free(line); 193 free(line);
179 } 194 }
180
181 // non-empty line found, parse and return the number of tokens 195 // non-empty line found, parse and return the number of tokens
182 196
183 // store line 197 // store line
@@ -190,14 +204,15 @@ int FAST_FUNC config_read(parser_t *parser, char **tokens, unsigned flags, const
190 ntokens--; // now it's max allowed token no 204 ntokens--; // now it's max allowed token no
191 // N.B. non-empty remainder is also a token, 205 // N.B. non-empty remainder is also a token,
192 // so if ntokens <= 1, we just return the whole line 206 // so if ntokens <= 1, we just return the whole line
193 // N.B. if PARSE_LAST_IS_GREEDY is set the remainder of the line is stuck to the last token 207 // N.B. if PARSE_GREEDY is set the remainder of the line is stuck to the last token
194 for (ii = 0; *line && ii <= ntokens; ) { 208 ii = 0;
209 while (*line && ii <= ntokens) {
195 //bb_info_msg("L[%s]", line); 210 //bb_info_msg("L[%s]", line);
196 // get next token 211 // get next token
197 // at the last token and need greedy token -> 212 // at last token and need greedy token ->
198 if ((flags & PARSE_LAST_IS_GREEDY) && (ii == ntokens)) { 213 if ((flags & PARSE_GREEDY) && (ii == ntokens)) {
199 // skip possible delimiters 214 // skip possible delimiters
200 if (!(flags & PARSE_DONT_REDUCE)) 215 if (flags & PARSE_COLLAPSE)
201 line += strspn(line, delims); 216 line += strspn(line, delims);
202 // don't cut the line 217 // don't cut the line
203 q = line + strlen(line); 218 q = line + strlen(line);
@@ -208,10 +223,11 @@ int FAST_FUNC config_read(parser_t *parser, char **tokens, unsigned flags, const
208 *q++ = '\0'; 223 *q++ = '\0';
209 } 224 }
210 // pin token 225 // pin token
211 if ((flags & (PARSE_DONT_REDUCE|PARSE_DONT_TRIM)) || *line) { 226 if (!(flags & (PARSE_COLLAPSE | PARSE_TRIM)) || *line) {
212 //bb_info_msg("N[%d] T[%s]", ii, line); 227 //bb_info_msg("N[%d] T[%s]", ii, line);
213 tokens[ii++] = line; 228 tokens[ii++] = line;
214 // process escapes in token 229 // process escapes in token
230#if 0 // unused so far
215 if (flags & PARSE_ESCAPE) { 231 if (flags & PARSE_ESCAPE) {
216 char *s = line; 232 char *s = line;
217 while (*s) { 233 while (*s) {
@@ -224,6 +240,7 @@ int FAST_FUNC config_read(parser_t *parser, char **tokens, unsigned flags, const
224 } 240 }
225 *line = '\0'; 241 *line = '\0';
226 } 242 }
243#endif
227 } 244 }
228 line = q; 245 line = q;
229 //bb_info_msg("A[%s]", line); 246 //bb_info_msg("A[%s]", line);
@@ -234,6 +251,7 @@ int FAST_FUNC config_read(parser_t *parser, char **tokens, unsigned flags, const
234 parser->lineno, ii, mintokens); 251 parser->lineno, ii, mintokens);
235 if (flags & PARSE_MIN_DIE) 252 if (flags & PARSE_MIN_DIE)
236 xfunc_die(); 253 xfunc_die();
254 ntokens++;
237 goto again; 255 goto again;
238 } 256 }
239 257
diff --git a/loginutils/login.c b/loginutils/login.c
index 5a75ed218..8732b99f1 100644
--- a/loginutils/login.c
+++ b/loginutils/login.c
@@ -139,20 +139,17 @@ static ALWAYS_INLINE void die_if_nologin(void) {}
139#if ENABLE_FEATURE_SECURETTY && !ENABLE_PAM 139#if ENABLE_FEATURE_SECURETTY && !ENABLE_PAM
140static int check_securetty(void) 140static int check_securetty(void)
141{ 141{
142 char *buf; 142 char *buf = (char*)"/etc/securetty"; /* any non-NULL is ok */
143 int ret = 1;
144 parser_t *parser = config_open2("/etc/securetty", fopen_for_read); 143 parser_t *parser = config_open2("/etc/securetty", fopen_for_read);
145 /* N.B. A missing securetty file is not an error. */ 144 while (config_read(parser, &buf, 1, 1, "# \t", PARSE_NORMAL)) {
146 if (parser) { 145 if (strcmp(buf, short_tty) == 0)
147 while (config_read(parser, &buf, 1, 1, "# \t", 0)) { 146 break;
148 if (strcmp(buf, short_tty) == 0) 147 buf = NULL;
149 break;
150 }
151 config_close(parser);
152 // buf != NULL here iff config file was empty (OK) or buf equals short_tty (OK)
153 ret = buf != NULL;
154 } 148 }
155 return ret; 149 config_close(parser);
150 /* buf != NULL here if config file was not found, empty
151 * or line was found which equals short_tty */
152 return buf != NULL;
156} 153}
157#else 154#else
158static ALWAYS_INLINE int check_securetty(void) { return 1; } 155static ALWAYS_INLINE int check_securetty(void) { return 1; }
diff --git a/miscutils/crond.c b/miscutils/crond.c
index b3a06a376..2f0bf6ea8 100644
--- a/miscutils/crond.c
+++ b/miscutils/crond.c
@@ -469,11 +469,15 @@ static void SynchronizeFile(const char *fileName)
469 file->cf_User = xstrdup(fileName); 469 file->cf_User = xstrdup(fileName);
470 pline = &file->cf_LineBase; 470 pline = &file->cf_LineBase;
471 471
472 while (--maxLines 472 while (1) {
473 && (n = config_read(parser, tokens, 6, 1, "# \t", PARSE_LAST_IS_GREEDY|PARSE_KEEP_COPY))
474 ) {
475 CronLine *line; 473 CronLine *line;
476 474
475 if (!--maxLines)
476 break;
477 n = config_read(parser, tokens, 6, 1, "# \t", PARSE_NORMAL | PARSE_KEEP_COPY);
478 if (!n)
479 break;
480
477 if (DebugOpt) 481 if (DebugOpt)
478 crondlog(LVL5 "user:%s entry:%s", fileName, parser->data); 482 crondlog(LVL5 "user:%s entry:%s", fileName, parser->data);
479 483
@@ -488,7 +492,7 @@ static void SynchronizeFile(const char *fileName)
488 /* check if a minimum of tokens is specified */ 492 /* check if a minimum of tokens is specified */
489 if (n < 6) 493 if (n < 6)
490 continue; 494 continue;
491 *pline = line = xzalloc(sizeof(CronLine)); 495 *pline = line = xzalloc(sizeof(*line));
492 /* parse date ranges */ 496 /* parse date ranges */
493 ParseField(file->cf_User, line->cl_Mins, 60, 0, NULL, tokens[0]); 497 ParseField(file->cf_User, line->cl_Mins, 60, 0, NULL, tokens[0]);
494 ParseField(file->cf_User, line->cl_Hrs, 24, 0, NULL, tokens[1]); 498 ParseField(file->cf_User, line->cl_Hrs, 24, 0, NULL, tokens[1]);
diff --git a/miscutils/fbsplash.c b/miscutils/fbsplash.c
index 6357f78ea..f8289c3d1 100644
--- a/miscutils/fbsplash.c
+++ b/miscutils/fbsplash.c
@@ -288,10 +288,10 @@ static void init(const char *cfg_filename)
288 "DEBUG\0" 288 "DEBUG\0"
289#endif 289#endif
290 ; 290 ;
291
292 char *token[2]; 291 char *token[2];
293 parser_t *parser = config_open2(cfg_filename, xfopen_stdin); 292 parser_t *parser = config_open2(cfg_filename, xfopen_stdin);
294 while (config_read(parser, token, 2, 2, "#=", PARSE_MIN_DIE)) { 293 while (config_read(parser, token, 2, 2, "#=",
294 (PARSE_NORMAL | PARSE_MIN_DIE) & ~(PARSE_TRIM | PARSE_COLLAPSE))) {
295 unsigned val = xatoi_u(token[1]); 295 unsigned val = xatoi_u(token[1]);
296 int i = index_in_strings(param_names, token[0]); 296 int i = index_in_strings(param_names, token[0]);
297 if (i < 0) 297 if (i < 0)
diff --git a/miscutils/man.c b/miscutils/man.c
index 7ef5941a1..adb85b81c 100644
--- a/miscutils/man.c
+++ b/miscutils/man.c
@@ -82,6 +82,7 @@ int man_main(int argc UNUSED_PARAM, char **argv)
82 char *cur_path, *cur_sect; 82 char *cur_path, *cur_sect;
83 int count_mp, cur_mp; 83 int count_mp, cur_mp;
84 int opt, not_found; 84 int opt, not_found;
85 char *token[2];
85 86
86 opt_complementary = "-1"; /* at least one argument */ 87 opt_complementary = "-1"; /* at least one argument */
87 opt = getopt32(argv, "+aw"); 88 opt = getopt32(argv, "+aw");
diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c
index 1654cc52d..63be9aadb 100644
--- a/modutils/modprobe-small.c
+++ b/modutils/modprobe-small.c
@@ -491,7 +491,7 @@ static int already_loaded(const char *name)
491 int ret = 0; 491 int ret = 0;
492 char *s; 492 char *s;
493 parser_t *parser = config_open2("/proc/modules", xfopen_for_read); 493 parser_t *parser = config_open2("/proc/modules", xfopen_for_read);
494 while (config_read(parser, &s, 1, 1, "# \t", 0)) { 494 while (config_read(parser, &s, 1, 1, "# \t", PARSE_NORMAL & ~PARSE_GREEDY)) {
495 if (strcmp(s, name) == 0) { 495 if (strcmp(s, name) == 0) {
496 ret = 1; 496 ret = 1;
497 break; 497 break;
diff --git a/networking/dnsd.c b/networking/dnsd.c
index efb5cfba7..e8dcb404b 100644
--- a/networking/dnsd.c
+++ b/networking/dnsd.c
@@ -106,43 +106,41 @@ static void undot(uint8_t * rip)
106 */ 106 */
107static void dnsentryinit(void) 107static void dnsentryinit(void)
108{ 108{
109 char *token[2];
109 parser_t *parser; 110 parser_t *parser;
110 struct dns_entry *m, *prev; 111 struct dns_entry *m, *prev;
111 112
112 prev = dnsentry = NULL; 113 prev = dnsentry = NULL;
113 parser = config_open(fileconf); 114 parser = config_open(fileconf);
114 if (parser) { 115 while (config_read(parser, token, 2, 2, "# \t", PARSE_NORMAL)) {
115 char *token[2]; 116 unsigned a, b, c, d;
116 while (config_read(parser, token, 2, 2, "# \t", 0)) { 117 /*
117 unsigned int a,b,c,d; 118 * Assumes all host names are lower case only
118 /* 119 * Hostnames with more than one label are not handled correctly.
119 * Assumes all host names are lower case only 120 * Presently the dot is copied into name without
120 * Hostnames with more than one label are not handled correctly. 121 * converting to a length/string substring for that label.
121 * Presently the dot is copied into name without 122 */
122 * converting to a length/string substring for that label. 123// if (!token[1] || sscanf(token[1], ".%u.%u.%u.%u"+1, &a, &b, &c, &d) != 4)
123 */ 124 if (sscanf(token[1], ".%u.%u.%u.%u"+1, &a, &b, &c, &d) != 4)
124// if (!token[1] || sscanf(token[1], ".%u.%u.%u.%u"+1, &a, &b, &c, &d) != 4) 125 continue;
125 if (sscanf(token[1], ".%u.%u.%u.%u"+1, &a, &b, &c, &d) != 4) 126
126 continue; 127 m = xzalloc(sizeof(*m));
127 128 /*m->next = NULL;*/
128 m = xzalloc(sizeof(*m)); 129 sprintf(m->ip, ".%u.%u.%u.%u"+1, a, b, c, d);
129 /*m->next = NULL;*/ 130 sprintf(m->rip, ".%u.%u.%u.%u", d, c, b, a);
130 sprintf(m->ip, ".%u.%u.%u.%u"+1, a, b, c, d); 131 undot((uint8_t*)m->rip);
131 sprintf(m->rip, ".%u.%u.%u.%u", d, c, b, a); 132 convname(m->name, (uint8_t*)token[0]);
132 undot((uint8_t*)m->rip); 133
133 convname(m->name, (uint8_t*)token[0]); 134 if (OPT_verbose)
134 135 fprintf(stderr, "\tname:%s, ip:%s\n", &(m->name[1]), m->ip);
135 if (OPT_verbose) 136
136 fprintf(stderr, "\tname:%s, ip:%s\n", &(m->name[1]), m->ip); 137 if (prev == NULL)
137 138 dnsentry = m;
138 if (prev == NULL) 139 else
139 dnsentry = m; 140 prev->next = m;
140 else 141 prev = m;
141 prev->next = m;
142 prev = m;
143 }
144 config_close(parser);
145 } 142 }
143 config_close(parser);
146} 144}
147 145
148/* 146/*
diff --git a/networking/hostname.c b/networking/hostname.c
index dd2a20689..48e70db91 100644
--- a/networking/hostname.c
+++ b/networking/hostname.c
@@ -20,7 +20,7 @@ static void do_sethostname(char *s, int isfile)
20 return; 20 return;
21 if (isfile) { 21 if (isfile) {
22 parser_t *parser = config_open2(s, xfopen_for_read); 22 parser_t *parser = config_open2(s, xfopen_for_read);
23 while (config_read(parser, &s, 1, 1, "# \t", 0)) { 23 while (config_read(parser, &s, 1, 1, "# \t", PARSE_NORMAL & ~PARSE_GREEDY)) {
24 do_sethostname(s, 0); 24 do_sethostname(s, 0);
25 } 25 }
26 if (ENABLE_FEATURE_CLEAN_UP) 26 if (ENABLE_FEATURE_CLEAN_UP)
diff --git a/networking/libiproute/rt_names.c b/networking/libiproute/rt_names.c
index 1a2d52e86..e4d10613b 100644
--- a/networking/libiproute/rt_names.c
+++ b/networking/libiproute/rt_names.c
@@ -20,9 +20,7 @@ static void rtnl_tab_initialize(const char *file, const char **tab, int size)
20{ 20{
21 char *token[2]; 21 char *token[2];
22 parser_t *parser = config_open2(file, fopen_for_read); 22 parser_t *parser = config_open2(file, fopen_for_read);
23 if (!parser) 23 while (config_read(parser, token, 2, 2, "# \t", PARSE_NORMAL)) {
24 return;
25 while (config_read(parser, token, 2, 2, "# \t", 0)) {
26 int id = bb_strtou(token[0], NULL, 0); 24 int id = bb_strtou(token[0], NULL, 0);
27 if (id < 0 || id > size) { 25 if (id < 0 || id > size) {
28 bb_error_msg("database %s is corrupted at line %d", 26 bb_error_msg("database %s is corrupted at line %d",
diff --git a/networking/nameif.c b/networking/nameif.c
index 5a3bd606f..12c08f13b 100644
--- a/networking/nameif.c
+++ b/networking/nameif.c
@@ -160,13 +160,11 @@ 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 char *tokens[2];
163 struct parser_t *parser = config_open(fname); 164 struct parser_t *parser = config_open(fname);
164 if (parser) { 165 while (config_read(parser, tokens, 2, 2, "# \t", PARSE_NORMAL))
165 char *tokens[2]; 166 prepend_new_eth_table(&clist, tokens[0], tokens[1]);
166 while (config_read(parser, tokens, 2, 2, "# \t", 0)) 167 config_close(parser);
167 prepend_new_eth_table(&clist, tokens[0], tokens[1]);
168 config_close(parser);
169 }
170 } 168 }
171 169
172 ctl_sk = xsocket(PF_INET, SOCK_DGRAM, 0); 170 ctl_sk = xsocket(PF_INET, SOCK_DGRAM, 0);
diff --git a/networking/udhcp/files.c b/networking/udhcp/files.c
index 264a98899..ff5847d25 100644
--- a/networking/udhcp/files.c
+++ b/networking/udhcp/files.c
@@ -318,10 +318,7 @@ void read_config(const char *file)
318 keywords[i].handler(keywords[i].def, keywords[i].var); 318 keywords[i].handler(keywords[i].def, keywords[i].var);
319 319
320 parser = config_open(file); 320 parser = config_open(file);
321 if (!parser) 321 while (config_read(parser, token, 2, 2, "# \t", PARSE_NORMAL)) {
322 return;
323
324 while (config_read(parser, token, 2, 2, "# \t", PARSE_LAST_IS_GREEDY)) {
325 for (k = keywords, i = 0; i < ARRAY_SIZE(keywords); k++, i++) { 322 for (k = keywords, i = 0; i < ARRAY_SIZE(keywords); k++, i++) {
326 if (!strcasecmp(token[0], k->keyword)) { 323 if (!strcasecmp(token[0], k->keyword)) {
327 if (!k->handler(token[1], k->var)) { 324 if (!k->handler(token[1], k->var)) {
diff --git a/procps/sysctl.c b/procps/sysctl.c
index 3fe6f6f3e..79f0074c9 100644
--- a/procps/sysctl.c
+++ b/procps/sysctl.c
@@ -95,10 +95,7 @@ static int sysctl_preload_file_and_exit(const char *filename)
95 parser_t *parser; 95 parser_t *parser;
96 96
97 parser = config_open(filename); 97 parser = config_open(filename);
98 if (!parser) 98 while (config_read(parser, token, 2, 2, "# \t=", PARSE_NORMAL)) { // TODO: ';' is comment char too
99 return 1;
100
101 while (config_read(parser, token, 2, 2, "# \t=", PARSE_LAST_IS_GREEDY)) { // TODO: ';' is comment char too
102// if (!token[1]) { 99// if (!token[1]) {
103// bb_error_msg(WARN_BAD_LINE, filename, parser->lineno); 100// bb_error_msg(WARN_BAD_LINE, filename, parser->lineno);
104// } else { 101// } else {
diff --git a/selinux/sestatus.c b/selinux/sestatus.c
index 1351600c8..eca557e4c 100644
--- a/selinux/sestatus.c
+++ b/selinux/sestatus.c
@@ -54,10 +54,7 @@ static void read_config(char **pc, int npc, char **fc, int nfc)
54 pc[0] = fc[0] = NULL; 54 pc[0] = fc[0] = NULL;
55 55
56 parser = config_open("/etc/sestatus.conf"); 56 parser = config_open("/etc/sestatus.conf");
57 if (!parser) 57 while (config_read(parser, &buf, 1, 1, "# \t", PARSE_NORMAL)) {
58 return;
59
60 while (config_read(parser, &buf, 1, 1, "# \t", PARSE_LAST_IS_GREEDY)) {
61 if (strcmp(buf, "[process]") == 0) { 58 if (strcmp(buf, "[process]") == 0) {
62 section = 1; 59 section = 1;
63 } else if (strcmp(buf, "[files]") == 0) { 60 } else if (strcmp(buf, "[files]") == 0) {
diff --git a/testsuite/parse.tests b/testsuite/parse.tests
index 06be8d2b9..f1ee7b830 100755
--- a/testsuite/parse.tests
+++ b/testsuite/parse.tests
@@ -5,20 +5,24 @@
5 5
6. testing.sh 6. testing.sh
7 7
8NO_REDUCE=65536 8COLLAPSE=$(( 0x00010000))
9NO_TRIM=131072 9TRIM=$(( 0x00020000))
10GREEDY=262144 10GREEDY=$(( 0x00040000))
11MIN_DIE=$(( 0x00100000))
12KEEP_COPY=$((0x00200000))
13ESCAPE=$(( 0x00400000))
14NORMAL=$(( COLLAPSE | TRIM | GREEDY))
11 15
12# testing "description" "command" "result" "infile" "stdin" 16# testing "description" "command" "result" "infile" "stdin"
13 17
14testing "mdev.conf" \ 18testing "parse mdev.conf" \
15 "parse -n 4 -m 3 -f $GREEDY -" \ 19 "parse -n 4 -m 3 -f $((NORMAL)) -" \
16 "[sda][0:0][644][@echo @echo TEST]\n" \ 20 "[sda][0:0][644][@echo @echo TEST]\n" \
17 "-" \ 21 "-" \
18 " sda 0:0 644 @echo @echo TEST # echo trap\n" 22 " sda 0:0 644 @echo @echo TEST # echo trap\n"
19 23
20testing "notrim" \ 24testing "parse notrim" \
21 "parse -n 4 -m 3 -f $(($GREEDY+$NO_TRIM)) -" \ 25 "parse -n 4 -m 3 -f $((NORMAL - TRIM - COLLAPSE)) -" \
22 "[][sda][0:0][644 @echo @echo TEST ]\n" \ 26 "[][sda][0:0][644 @echo @echo TEST ]\n" \
23 "-" \ 27 "-" \
24 " sda 0:0 644 @echo @echo TEST \n" 28 " sda 0:0 644 @echo @echo TEST \n"
@@ -49,12 +53,12 @@ cat >$FILE.res <<EOF
49[/dev/cdrom][/cdrom][iso9660][ro,user,noauto,nohide][0][0] 53[/dev/cdrom][/cdrom][iso9660][ro,user,noauto,nohide][0][0]
50[/dev/hdb5][/redhat][ext2][rw,root,noauto,nohide][0][0] 54[/dev/hdb5][/redhat][ext2][rw,root,noauto,nohide][0][0]
51[/dev/hdb6][/win2home][ntfs][rw,root,noauto,nohide][0][0] 55[/dev/hdb6][/win2home][ntfs][rw,root,noauto,nohide][0][0]
52[/dev/hdb7][/win2skul][ntfs][rw,root,noauto,nohide][none][0] 56[/dev/hdb7][/win2skul][ntfs][rw,root,noauto,nohide][none][0 0]
53[none][/dev/pts][devpts][gid=5,mode=620][0][0] 57[none][/dev/pts][devpts][gid=5,mode=620][0][0]
54[none][/proc][proc][defaults][0][0] 58[none][/proc][proc][defaults][0][0]
55EOF 59EOF
56 60
57testing "polluted fstab" \ 61testing "parse polluted fstab" \
58 "parse -n 6 -m 6 $FILE" \ 62 "parse -n 6 -m 6 $FILE" \
59 "`cat $FILE.res`\n" \ 63 "`cat $FILE.res`\n" \
60 "" \ 64 "" \
@@ -74,8 +78,8 @@ cat >$FILE.res <<EOF
74[][][shutdown][/sbin/swapoff -a] 78[][][shutdown][/sbin/swapoff -a]
75EOF 79EOF
76 80
77testing "inittab from examples" \ 81testing "parse inittab from examples" \
78 "parse -n 4 -m 4 -f $(($GREEDY+$NO_TRIM)) -d'#:' $FILE" \ 82 "parse -n 4 -m 4 -f $((NORMAL - TRIM - COLLAPSE)) -d'#:' $FILE" \
79 "`cat $FILE.res`\n" \ 83 "`cat $FILE.res`\n" \
80 "" \ 84 "" \
81 "" 85 ""
@@ -94,7 +98,7 @@ cat >$FILE.res <<EOF
94[option][lease][864000] 98[option][lease][864000]
95EOF 99EOF
96 100
97testing "udhcpd.conf from examples" \ 101testing "parse udhcpd.conf from examples" \
98 "parse -n 127 $FILE" \ 102 "parse -n 127 $FILE" \
99 "`cat $FILE.res`\n" \ 103 "`cat $FILE.res`\n" \
100 "" \ 104 "" \
diff --git a/util-linux/hexdump.c b/util-linux/hexdump.c
index 8ac12f082..48edd70a9 100644
--- a/util-linux/hexdump.c
+++ b/util-linux/hexdump.c
@@ -16,11 +16,19 @@
16 16
17static void bb_dump_addfile(dumper_t *dumper, char *name) 17static void bb_dump_addfile(dumper_t *dumper, char *name)
18{ 18{
19 parser_t *parser = config_open2(name, xfopen_for_read); 19 char *p;
20 while (config_read(parser, &name, 1, 1, "# \t", 0)) { 20 FILE *fp;
21 bb_dump_add(dumper, name); 21 char *buf;
22
23 fp = xfopen_for_read(name);
24 while ((buf = xmalloc_fgetline(fp)) != NULL) {
25 p = skip_whitespace(buf);
26 if (*p && (*p != '#')) {
27 bb_dump_add(dumper, p);
28 }
29 free(buf);
22 } 30 }
23 config_close(parser); 31 fclose(fp);
24} 32}
25 33
26static const char *const add_strings[] = { 34static const char *const add_strings[] = {
diff --git a/util-linux/mdev.c b/util-linux/mdev.c
index f6440b190..d0d010382 100644
--- a/util-linux/mdev.c
+++ b/util-linux/mdev.c
@@ -107,10 +107,7 @@ static void make_device(char *path, int delete)
107 parser = config_open2("/etc/mdev.conf", fopen_for_read); 107 parser = config_open2("/etc/mdev.conf", fopen_for_read);
108 108
109 /* If we have config file, look up user settings */ 109 /* If we have config file, look up user settings */
110 if (!parser) 110 while (config_read(parser, tokens, 4, 3, "# \t", PARSE_NORMAL)) {
111 goto end_parse;
112
113 while (config_read(parser, tokens, 4, 3, "# \t", PARSE_LAST_IS_GREEDY)) {
114 regmatch_t off[1 + 9*ENABLE_FEATURE_MDEV_RENAME_REGEXP]; 111 regmatch_t off[1 + 9*ENABLE_FEATURE_MDEV_RENAME_REGEXP];
115 char *val; 112 char *val;
116 113
@@ -244,7 +241,6 @@ static void make_device(char *path, int delete)
244 } /* end of "while line is read from /etc/mdev.conf" */ 241 } /* end of "while line is read from /etc/mdev.conf" */
245 242
246 config_close(parser); 243 config_close(parser);
247 end_parse:
248#endif /* ENABLE_FEATURE_MDEV_CONF */ 244#endif /* ENABLE_FEATURE_MDEV_CONF */
249 245
250 if (!delete && sscanf(dev_maj_min, "%u:%u", &major, &minor) == 2) { 246 if (!delete && sscanf(dev_maj_min, "%u:%u", &major, &minor) == 2) {