diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-07-26 23:08:31 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-07-26 23:08:31 +0000 |
commit | 084266ed520805bbc4ec3f9b4d14e644ecd75880 (patch) | |
tree | fe2c8531dc039c81c12a39f39fcfdf6c1b8ec996 | |
parent | 8895c2073e9341d8e0348365e75ba6aa4b9b8d05 (diff) | |
download | busybox-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.h | 21 | ||||
-rw-r--r-- | init/init.c | 4 | ||||
-rw-r--r-- | libbb/parse_config.c | 102 | ||||
-rw-r--r-- | loginutils/login.c | 21 | ||||
-rw-r--r-- | miscutils/crond.c | 12 | ||||
-rw-r--r-- | miscutils/fbsplash.c | 4 | ||||
-rw-r--r-- | miscutils/man.c | 1 | ||||
-rw-r--r-- | modutils/modprobe-small.c | 2 | ||||
-rw-r--r-- | networking/dnsd.c | 60 | ||||
-rw-r--r-- | networking/hostname.c | 2 | ||||
-rw-r--r-- | networking/libiproute/rt_names.c | 4 | ||||
-rw-r--r-- | networking/nameif.c | 10 | ||||
-rw-r--r-- | networking/udhcp/files.c | 5 | ||||
-rw-r--r-- | procps/sysctl.c | 5 | ||||
-rw-r--r-- | selinux/sestatus.c | 5 | ||||
-rwxr-xr-x | testsuite/parse.tests | 28 | ||||
-rw-r--r-- | util-linux/hexdump.c | 16 | ||||
-rw-r--r-- | util-linux/mdev.c | 6 |
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 | */ |
1000 | enum { | 1000 | enum { |
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 | }; |
1011 | typedef struct parser_t { | 1016 | typedef 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; | |||
14 | int parse_main(int argc UNUSED_PARAM, char **argv) | 14 | int 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 | ||
62 | parser_t* FAST_FUNC config_open2(const char *filename, FILE* FAST_FUNC (*fopen_func)(const char *path)) | 63 | parser_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 | ||
73 | parser_t* FAST_FUNC config_open(const char *filename) | 76 | parser_t* FAST_FUNC config_open(const char *filename) |
@@ -87,41 +90,53 @@ static void config_free_data(parser_t *const parser) | |||
87 | 90 | ||
88 | void FAST_FUNC config_close(parser_t *parser) | 91 | void 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 | /* |
95 | 1. Read a line from config file. If nothing to read then bail out returning 0. | 101 | 0. If parser is NULL return 0. |
96 | Handle continuation character. Advance lineno for each physical line. Cut comments. | 102 | 1. Read a line from config file. If nothing to read then return 0. |
97 | 2. 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. | ||
105 | 2. if PARSE_TRIM is set (default), remove leading and trailing delimiters. | ||
98 | 3. If resulting line is empty goto 1. | 106 | 3. If resulting line is empty goto 1. |
99 | 4. Look for first delimiter. If PARSE_DONT_REDUCE or PARSE_DONT_TRIM is set then pin empty token. | 107 | 4. Look for first delimiter. If !PARSE_COLLAPSE or !PARSE_TRIM is set then |
100 | 5. 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. | 109 | 5. 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. |
104 | 6. 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. |
106 | 7. Control the number of seen tokens is not less the min number of tokens. Die if condition is not met. | 114 | 6. Advance line pointer past the end of token. If number of seen tokens |
115 | is less than required number of tokens then goto 4. | ||
116 | 7. Check the number of seen tokens is not less the min number of tokens. | ||
117 | Complain or die otherwise depending on PARSE_MIN_DIE. | ||
107 | 8. Return the number of seen tokens. | 118 | 8. Return the number of seen tokens. |
108 | 119 | ||
109 | mintokens > 0 make config_read() exit with error message if less than mintokens | 120 | mintokens > 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 |
113 | int FAST_FUNC config_read(parser_t *parser, char **tokens, unsigned flags, const char *delims) | 124 | int 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 |
140 | static int check_securetty(void) | 140 | static 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 |
158 | static ALWAYS_INLINE int check_securetty(void) { return 1; } | 155 | static 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 | */ |
107 | static void dnsentryinit(void) | 107 | static 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 | ||
8 | NO_REDUCE=65536 | 8 | COLLAPSE=$(( 0x00010000)) |
9 | NO_TRIM=131072 | 9 | TRIM=$(( 0x00020000)) |
10 | GREEDY=262144 | 10 | GREEDY=$(( 0x00040000)) |
11 | MIN_DIE=$(( 0x00100000)) | ||
12 | KEEP_COPY=$((0x00200000)) | ||
13 | ESCAPE=$(( 0x00400000)) | ||
14 | NORMAL=$(( COLLAPSE | TRIM | GREEDY)) | ||
11 | 15 | ||
12 | # testing "description" "command" "result" "infile" "stdin" | 16 | # testing "description" "command" "result" "infile" "stdin" |
13 | 17 | ||
14 | testing "mdev.conf" \ | 18 | testing "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 | ||
20 | testing "notrim" \ | 24 | testing "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] |
55 | EOF | 59 | EOF |
56 | 60 | ||
57 | testing "polluted fstab" \ | 61 | testing "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] |
75 | EOF | 79 | EOF |
76 | 80 | ||
77 | testing "inittab from examples" \ | 81 | testing "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] |
95 | EOF | 99 | EOF |
96 | 100 | ||
97 | testing "udhcpd.conf from examples" \ | 101 | testing "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 | ||
17 | static void bb_dump_addfile(dumper_t *dumper, char *name) | 17 | static 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 | ||
26 | static const char *const add_strings[] = { | 34 | static 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) { |