diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-07-19 09:27:19 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-07-19 09:27:19 +0000 |
commit | 2e157ddf9ecd9d58864425f0e87409ddc218df94 (patch) | |
tree | 18f415d4847897a12d790b545f94c32ae68c199c | |
parent | bd28f6bf7f53ede8df39112d40cb52f2a3d00177 (diff) | |
download | busybox-w32-2e157ddf9ecd9d58864425f0e87409ddc218df94.tar.gz busybox-w32-2e157ddf9ecd9d58864425f0e87409ddc218df94.tar.bz2 busybox-w32-2e157ddf9ecd9d58864425f0e87409ddc218df94.zip |
libbb: updated config_parse() from Vladimir
function old new delta
config_read 385 460 +75
runsvdir_main 1701 1716 +15
readit 331 338 +7
passwd_main 1049 1053 +4
parse_command 1504 1507 +3
decode_format_string 822 824 +2
bb__parsespent 117 119 +2
udhcp_get_option 221 222 +1
changepath 196 194 -2
parse_inittab 400 396 -4
nameif_main 683 679 -4
make_device 1176 1172 -4
config_open 48 40 -8
expand_main 698 689 -9
readcmd 1012 1002 -10
config_free_data 37 21 -16
SynchronizeFile 683 643 -40
sleep_main 474 362 -112
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 8/10 up/down: 109/-209) Total: -100 bytes
-rw-r--r-- | Config.in | 7 | ||||
-rw-r--r-- | include/applets.h | 1 | ||||
-rw-r--r-- | include/libbb.h | 14 | ||||
-rw-r--r-- | include/usage.h | 5 | ||||
-rw-r--r-- | init/init.c | 4 | ||||
-rw-r--r-- | libbb/parse_config.c | 148 | ||||
-rw-r--r-- | miscutils/crond.c | 13 | ||||
-rw-r--r-- | networking/nameif.c | 2 | ||||
-rwxr-xr-x | testsuite/parse.tests | 64 | ||||
-rw-r--r-- | util-linux/mdev.c | 2 |
10 files changed, 206 insertions, 54 deletions
@@ -479,6 +479,13 @@ config INCLUDE_SUSv2 | |||
479 | will be supported in head, tail, and fold. (Note: should | 479 | will be supported in head, tail, and fold. (Note: should |
480 | affect renice too.) | 480 | affect renice too.) |
481 | 481 | ||
482 | config PARSE | ||
483 | bool "Uniform config file parser debugging applet: parse" | ||
484 | |||
485 | config FEATURE_PARSE_COPY | ||
486 | bool "Keep a copy of current line" | ||
487 | depends on PARSE | ||
488 | |||
482 | endmenu | 489 | endmenu |
483 | 490 | ||
484 | menu 'Installation Options' | 491 | menu 'Installation Options' |
diff --git a/include/applets.h b/include/applets.h index aff9070bb..5dd485ab4 100644 --- a/include/applets.h +++ b/include/applets.h | |||
@@ -268,6 +268,7 @@ USE_NOHUP(APPLET(nohup, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) | |||
268 | USE_NSLOOKUP(APPLET(nslookup, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) | 268 | USE_NSLOOKUP(APPLET(nslookup, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) |
269 | USE_OD(APPLET(od, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) | 269 | USE_OD(APPLET(od, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) |
270 | USE_OPENVT(APPLET(openvt, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) | 270 | USE_OPENVT(APPLET(openvt, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) |
271 | USE_PARSE(APPLET(parse, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) | ||
271 | USE_PASSWD(APPLET(passwd, _BB_DIR_USR_BIN, _BB_SUID_ALWAYS)) | 272 | USE_PASSWD(APPLET(passwd, _BB_DIR_USR_BIN, _BB_SUID_ALWAYS)) |
272 | USE_PATCH(APPLET(patch, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) | 273 | USE_PATCH(APPLET(patch, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) |
273 | USE_PGREP(APPLET(pgrep, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) | 274 | USE_PGREP(APPLET(pgrep, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) |
diff --git a/include/libbb.h b/include/libbb.h index 14af1368c..af6c1385d 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -988,16 +988,22 @@ int bb_ask_confirmation(void) FAST_FUNC; | |||
988 | 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 | * Config file parser |
992 | */ | 992 | */ |
993 | #define PARSE_DONT_REDUCE 0x00010000 // do not treat consecutive delimiters as one | ||
994 | #define PARSE_DONT_TRIM 0x00020000 // do not trim line of leading and trailing delimiters | ||
995 | #define PARSE_LAST_IS_GREEDY 0x00040000 // last token takes whole remainder of the line | ||
996 | //#define PARSE_DONT_NULL 0x00080000 // do not set tokens[] to NULL | ||
993 | typedef struct parser_t { | 997 | typedef struct parser_t { |
994 | FILE *fp; | 998 | FILE *fp; |
995 | char *line, *data; | 999 | char *line; |
1000 | USE_FEATURE_PARSE_COPY(char *data;) | ||
996 | int lineno; | 1001 | int lineno; |
997 | } parser_t; | 1002 | } parser_t; |
998 | parser_t* config_open(const char *filename) FAST_FUNC; | 1003 | parser_t* config_open(const char *filename) FAST_FUNC; |
999 | /* TODO: add define magic to collapse ntokens/mintokens/comment into one int param */ | 1004 | int config_read(parser_t *parser, char **tokens, unsigned flags, const char *delims) FAST_FUNC; |
1000 | int config_read(parser_t *parser, char **tokens, int ntokens, int mintokens, const char *delims, char comment) FAST_FUNC; | 1005 | #define config_read(parser, tokens, max, min, str, flags) \ |
1006 | config_read(parser, tokens, ((flags) | (((min) & 0xFF) << 8) | ((max) & 0xFF)), str) | ||
1001 | void config_close(parser_t *parser) FAST_FUNC; | 1007 | void config_close(parser_t *parser) FAST_FUNC; |
1002 | 1008 | ||
1003 | /* Concatenate path and filename to new allocated buffer. | 1009 | /* Concatenate path and filename to new allocated buffer. |
diff --git a/include/usage.h b/include/usage.h index f9a993a21..61c5c8ee3 100644 --- a/include/usage.h +++ b/include/usage.h | |||
@@ -2903,6 +2903,11 @@ | |||
2903 | #define openvt_example_usage \ | 2903 | #define openvt_example_usage \ |
2904 | "openvt 2 /bin/ash\n" | 2904 | "openvt 2 /bin/ash\n" |
2905 | 2905 | ||
2906 | #define parse_trivial_usage \ | ||
2907 | "[-n maxtokens] [-m mintokens] [-d delims] [-f flags] file ..." | ||
2908 | #define parse_full_usage "\n\n" \ | ||
2909 | "[-n maxtokens] [-m mintokens] [-d delims] [-f flags] file ..." | ||
2910 | |||
2906 | #define passwd_trivial_usage \ | 2911 | #define passwd_trivial_usage \ |
2907 | "[OPTION] [name]" | 2912 | "[OPTION] [name]" |
2908 | #define passwd_full_usage "\n\n" \ | 2913 | #define passwd_full_usage "\n\n" \ |
diff --git a/init/init.c b/init/init.c index 9637589ce..0e4a8f1e5 100644 --- a/init/init.c +++ b/init/init.c | |||
@@ -808,7 +808,7 @@ static void parse_inittab(void) | |||
808 | /* optional_tty:ignored_runlevel:action:command | 808 | /* optional_tty:ignored_runlevel:action:command |
809 | * Delims are not to be collapsed and need exactly 4 tokens | 809 | * Delims are not to be collapsed and need exactly 4 tokens |
810 | */ | 810 | */ |
811 | while (config_read(parser, token, -4, 0, ":", '#') >= 0) { | 811 | while (config_read(parser, token, 4, 0, "#:", PARSE_DONT_TRIM|PARSE_DONT_REDUCE|PARSE_LAST_IS_GREEDY)) { |
812 | int action; | 812 | int action; |
813 | char *tty = token[0]; | 813 | char *tty = token[0]; |
814 | 814 | ||
@@ -828,7 +828,7 @@ static void parse_inittab(void) | |||
828 | free(tty); | 828 | free(tty); |
829 | continue; | 829 | continue; |
830 | bad_entry: | 830 | bad_entry: |
831 | message(L_LOG | L_CONSOLE, "Bad inittab entry: %s", parser->line); | 831 | message(L_LOG | L_CONSOLE, "Bad inittab entry at line %d", parser->lineno); |
832 | } | 832 | } |
833 | config_close(parser); | 833 | config_close(parser); |
834 | #endif | 834 | #endif |
diff --git a/libbb/parse_config.c b/libbb/parse_config.c index 5f6dbbde1..3945501ad 100644 --- a/libbb/parse_config.c +++ b/libbb/parse_config.c | |||
@@ -9,23 +9,51 @@ | |||
9 | 9 | ||
10 | #include "libbb.h" | 10 | #include "libbb.h" |
11 | 11 | ||
12 | #if ENABLE_PARSE | ||
13 | int parse_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | ||
14 | int parse_main(int argc UNUSED_PARAM, char **argv) | ||
15 | { | ||
16 | const char *delims = "# \t"; | ||
17 | unsigned flags = 0; | ||
18 | int mintokens = 0, ntokens = 128; | ||
19 | opt_complementary = "-1:n+:m+:f+"; | ||
20 | getopt32(argv, "n:m:d:f:", &ntokens, &mintokens, &delims, &flags); | ||
21 | //argc -= optind; | ||
22 | argv += optind; | ||
23 | while (*argv) { | ||
24 | parser_t *p = config_open(*argv); | ||
25 | if (p) { | ||
26 | int n; | ||
27 | char **t = xmalloc(sizeof(char *) * ntokens); | ||
28 | while ((n = config_read(p, t, ntokens, mintokens, delims, flags)) > 0) { | ||
29 | for (int i = 0; i < n; ++i) | ||
30 | printf("[%s]", t[i]); | ||
31 | puts(""); | ||
32 | } | ||
33 | config_close(p); | ||
34 | } | ||
35 | argv++; | ||
36 | } | ||
37 | return EXIT_SUCCESS; | ||
38 | } | ||
39 | #endif | ||
40 | |||
12 | /* | 41 | /* |
13 | 42 | ||
14 | Typical usage: | 43 | Typical usage: |
15 | 44 | ||
16 | ----- CUT ----- | 45 | ----- CUT ----- |
17 | char *t[3]; // tokens placeholder | 46 | char *t[3]; // tokens placeholder |
18 | parser_t p; // parser structure | 47 | parser_t *p = config_open(filename); |
19 | // open file | 48 | if (p) { |
20 | if (config_open(filename, &p)) { | ||
21 | // parse line-by-line | 49 | // parse line-by-line |
22 | while (*config_read(&p, t, 3, 0, delimiters, comment_char) >= 0) { // 0..3 tokens | 50 | while (config_read(p, t, 3, 0, delimiters, flags)) { // 1..3 tokens |
23 | // use tokens | 51 | // use tokens |
24 | bb_error_msg("TOKENS: [%s][%s][%s]", t[0], t[1], t[2]); | 52 | bb_error_msg("TOKENS: [%s][%s][%s]", t[0], t[1], t[2]); |
25 | } | 53 | } |
26 | ... | 54 | ... |
27 | // free parser | 55 | // free parser |
28 | config_close(&p); | 56 | config_close(p); |
29 | } | 57 | } |
30 | ----- CUT ----- | 58 | ----- CUT ----- |
31 | 59 | ||
@@ -35,44 +63,69 @@ parser_t* FAST_FUNC config_open(const char *filename) | |||
35 | { | 63 | { |
36 | parser_t *parser = xzalloc(sizeof(parser_t)); | 64 | parser_t *parser = xzalloc(sizeof(parser_t)); |
37 | /* empty file configures nothing */ | 65 | /* empty file configures nothing */ |
38 | parser->fp = fopen_or_warn(filename, "r"); | 66 | parser->fp = fopen_or_warn_stdin(filename); |
39 | if (parser->fp) | 67 | if (parser->fp) |
40 | return parser; | 68 | return parser; |
41 | config_close (parser); | ||
42 | if (ENABLE_FEATURE_CLEAN_UP) | 69 | if (ENABLE_FEATURE_CLEAN_UP) |
43 | free(parser); | 70 | free(parser); |
44 | return NULL; | 71 | return NULL; |
45 | } | 72 | } |
46 | 73 | ||
47 | static void config_free_data(parser_t *const parser) | 74 | static void config_free_data(parser_t *const parser) |
48 | { | 75 | { |
49 | free(parser->line); | 76 | free(parser->line); |
50 | free(parser->data); | 77 | parser->line = NULL; |
51 | parser->line = parser->data = NULL; | 78 | USE_FEATURE_PARSE_COPY( |
79 | free(parser->data); | ||
80 | parser->data = NULL; | ||
81 | ) | ||
52 | } | 82 | } |
83 | |||
53 | void FAST_FUNC config_close(parser_t *parser) | 84 | void FAST_FUNC config_close(parser_t *parser) |
54 | { | 85 | { |
55 | config_free_data(parser); | 86 | config_free_data(parser); |
56 | fclose(parser->fp); | 87 | fclose(parser->fp); |
57 | } | 88 | } |
58 | 89 | ||
59 | int FAST_FUNC config_read(parser_t *parser, char **tokens, int ntokens, int mintokens, const char *delims, char comment) | 90 | /* |
91 | 1. Read a line from config file. If nothing to read then bail out returning 0. | ||
92 | Handle continuation character. Advance lineno for each physical line. Cut comments. | ||
93 | 2. if PARSE_DONT_TRIM is not set (default) skip leading and cut trailing delimiters, if any. | ||
94 | 3. If resulting line is empty goto 1. | ||
95 | 4. Look for first delimiter. If PARSE_DONT_REDUCE or PARSE_DONT_TRIM is set then pin empty token. | ||
96 | 5. Else (default) if number of seen tokens is equal to max number of tokens (token is the last one) | ||
97 | and PARSE_LAST_IS_GREEDY is set then pin the remainder of the line as the last token. | ||
98 | Else (token is not last or PARSE_LAST_IS_GREEDY is not set) just replace first delimiter with '\0' | ||
99 | thus delimiting token and pin it. | ||
100 | 6. Advance line pointer past the end of token. If number of seen tokens is less than required number | ||
101 | of tokens then goto 4. | ||
102 | 7. Control the number of seen tokens is not less the min number of tokens. Die if condition is not met. | ||
103 | 8. Return the number of seen tokens. | ||
104 | |||
105 | mintokens > 0 make config_read() exit with error message if less than mintokens | ||
106 | (but more than 0) are found. Empty lines are always skipped (not warned about). | ||
107 | */ | ||
108 | #undef config_read | ||
109 | int FAST_FUNC config_read(parser_t *parser, char **tokens, unsigned flags, const char *delims) | ||
60 | { | 110 | { |
61 | char *line, *q; | 111 | char *line, *q; |
62 | int ii, seen; | 112 | char comment = *delims++; |
63 | /* do not treat consecutive delimiters as one delimiter */ | 113 | int ii; |
64 | bool noreduce = (ntokens < 0); | 114 | int ntokens = flags & 0xFF; |
65 | if (noreduce) | 115 | int mintokens = (flags & 0xFF00) >> 8; |
66 | ntokens = -ntokens; | 116 | |
67 | 117 | /* | |
68 | memset(tokens, 0, sizeof(tokens[0]) * ntokens); | 118 | // N.B. this could only be used in read-in-one-go version, or when tokens use xstrdup(). TODO |
119 | if (!parser->lineno || !(flags & PARSE_DONT_NULL)) | ||
120 | */ | ||
121 | memset(tokens, 0, sizeof(tokens[0]) * ntokens); | ||
69 | config_free_data(parser); | 122 | config_free_data(parser); |
70 | 123 | ||
71 | while (1) { | 124 | while (1) { |
72 | //TODO: speed up xmalloc_fgetline by internally using fgets, not fgetc | 125 | //TODO: speed up xmalloc_fgetline by internally using fgets, not fgetc |
73 | line = xmalloc_fgetline(parser->fp); | 126 | line = xmalloc_fgetline(parser->fp); |
74 | if (!line) | 127 | if (!line) |
75 | return -1; | 128 | return 0; |
76 | 129 | ||
77 | parser->lineno++; | 130 | parser->lineno++; |
78 | // handle continuations. Tito's code stolen :) | 131 | // handle continuations. Tito's code stolen :) |
@@ -98,12 +151,22 @@ int FAST_FUNC config_read(parser_t *parser, char **tokens, int ntokens, int mint | |||
98 | *q = '\0'; | 151 | *q = '\0'; |
99 | ii = q - line; | 152 | ii = q - line; |
100 | } | 153 | } |
101 | // skip leading delimiters | 154 | // skip leading and trailing delimiters |
102 | seen = strspn(line, delims); | 155 | if (!(flags & PARSE_DONT_TRIM)) { |
103 | if (seen) { | 156 | // skip leading |
104 | ii -= seen; | 157 | int n = strspn(line, delims); |
105 | strcpy(line, line + seen); | 158 | if (n) { |
159 | ii -= n; | ||
160 | strcpy(line, line + n); | ||
161 | } | ||
162 | // cut trailing | ||
163 | if (ii) { | ||
164 | while (strchr(delims, line[--ii])) | ||
165 | continue; | ||
166 | line[++ii] = '\0'; | ||
167 | } | ||
106 | } | 168 | } |
169 | // if something still remains -> return it | ||
107 | if (ii) | 170 | if (ii) |
108 | break; | 171 | break; |
109 | 172 | ||
@@ -112,36 +175,39 @@ int FAST_FUNC config_read(parser_t *parser, char **tokens, int ntokens, int mint | |||
112 | free(line); | 175 | free(line); |
113 | } | 176 | } |
114 | 177 | ||
115 | // non-empty line found, parse and return | 178 | // non-empty line found, parse and return the number of tokens |
116 | 179 | ||
117 | // store line | 180 | // store line |
118 | parser->line = line = xrealloc(line, ii + 1); | 181 | parser->line = line = xrealloc(line, ii + 1); |
119 | parser->data = xstrdup(line); | 182 | USE_FEATURE_PARSE_COPY( |
183 | parser->data = xstrdup(line); | ||
184 | ) | ||
120 | 185 | ||
121 | /* now split line to tokens */ | 186 | /* now split line to tokens */ |
122 | ii = noreduce ? seen : 0; | ||
123 | ntokens--; // now it's max allowed token no | 187 | ntokens--; // now it's max allowed token no |
124 | while (1) { | 188 | // N.B, non-empty remainder is also a token, |
189 | // so if ntokens <= 1, we just return the whole line | ||
190 | // N.B. if PARSE_LAST_IS_GREEDY is set the remainder of the line is stuck to the last token | ||
191 | for (ii = 0; *line && ii <= ntokens; ) { | ||
192 | //bb_info_msg("L[%s]", line); | ||
125 | // get next token | 193 | // get next token |
126 | if (ii == ntokens) | 194 | // at the last token and need greedy token -> |
127 | break; | 195 | if ((flags & PARSE_LAST_IS_GREEDY) && (ii == ntokens)) { |
128 | q = line + strcspn(line, delims); | 196 | // ... don't cut the line |
129 | if (!*q) | 197 | q = line + strlen(line); |
130 | break; | 198 | } else { |
199 | // vanilla token. cut the line at the first delim | ||
200 | q = line + strcspn(line, delims); | ||
201 | *q++ = '\0'; | ||
202 | } | ||
131 | // pin token | 203 | // pin token |
132 | *q++ = '\0'; | 204 | if ((flags & (PARSE_DONT_REDUCE|PARSE_DONT_TRIM)) || *line) { |
133 | if (noreduce || *line) { | 205 | //bb_info_msg("N[%d] T[%s]", ii, line); |
134 | tokens[ii++] = line; | 206 | tokens[ii++] = line; |
135 | //bb_info_msg("L[%d] T[%s]\n", ii, line); | ||
136 | } | 207 | } |
137 | line = q; | 208 | line = q; |
138 | } | 209 | } |
139 | 210 | ||
140 | // non-empty remainder is also a token, | ||
141 | // so if ntokens <= 1, we just return the whole line | ||
142 | if (noreduce || *line) | ||
143 | tokens[ii++] = line; | ||
144 | |||
145 | if (ii < mintokens) | 211 | if (ii < mintokens) |
146 | bb_error_msg_and_die("bad line %u: %d tokens found, %d needed", | 212 | bb_error_msg_and_die("bad line %u: %d tokens found, %d needed", |
147 | parser->lineno, ii, mintokens); | 213 | parser->lineno, ii, mintokens); |
diff --git a/miscutils/crond.c b/miscutils/crond.c index d8423cf4f..154243c78 100644 --- a/miscutils/crond.c +++ b/miscutils/crond.c | |||
@@ -469,12 +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 && (n=config_read(parser, tokens, 6, 0, " \t", '#')) >= 0) { | 472 | while (--maxLines |
473 | && (n = config_read(parser, tokens, 6, 1, "# \t", PARSE_LAST_IS_GREEDY)) | ||
474 | ) { | ||
473 | CronLine *line; | 475 | CronLine *line; |
474 | 476 | ||
475 | if (DebugOpt) { | 477 | USE_FEATURE_PARSE_COPY( |
476 | crondlog(LVL5 "user:%s entry:%s", fileName, parser->data); | 478 | if (DebugOpt) |
477 | } | 479 | crondlog(LVL5 "user:%s entry:%s", fileName, parser->data); |
480 | ) | ||
478 | 481 | ||
479 | /* check if line is setting MAILTO= */ | 482 | /* check if line is setting MAILTO= */ |
480 | if (0 == strncmp(tokens[0], "MAILTO=", 7)) { | 483 | if (0 == strncmp(tokens[0], "MAILTO=", 7)) { |
@@ -485,7 +488,7 @@ static void SynchronizeFile(const char *fileName) | |||
485 | continue; | 488 | continue; |
486 | } | 489 | } |
487 | /* check if a minimum of tokens is specified */ | 490 | /* check if a minimum of tokens is specified */ |
488 | if (n < 5) | 491 | if (n < 6) |
489 | continue; | 492 | continue; |
490 | *pline = line = xzalloc(sizeof(CronLine)); | 493 | *pline = line = xzalloc(sizeof(CronLine)); |
491 | /* parse date ranges */ | 494 | /* parse date ranges */ |
diff --git a/networking/nameif.c b/networking/nameif.c index 291780a28..76a8cb7df 100644 --- a/networking/nameif.c +++ b/networking/nameif.c | |||
@@ -163,7 +163,7 @@ int nameif_main(int argc, char **argv) | |||
163 | struct parser_t *parser = config_open(fname); | 163 | struct parser_t *parser = config_open(fname); |
164 | if (parser) { | 164 | if (parser) { |
165 | char *tokens[2]; | 165 | char *tokens[2]; |
166 | while (config_read(parser, tokens, 2, 2, " \t", '#') >= 0) | 166 | while (config_read(parser, tokens, 2, 2, "# \t", 0)) |
167 | prepend_new_eth_table(&clist, tokens[0], tokens[1]); | 167 | prepend_new_eth_table(&clist, tokens[0], tokens[1]); |
168 | config_close(parser); | 168 | config_close(parser); |
169 | } | 169 | } |
diff --git a/testsuite/parse.tests b/testsuite/parse.tests new file mode 100755 index 000000000..1b43f9c9f --- /dev/null +++ b/testsuite/parse.tests | |||
@@ -0,0 +1,64 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | # Copyright 2008 by Denys Vlasenko <vda.linux@googlemail.com> | ||
4 | # Licensed under GPL v2, see file LICENSE for details. | ||
5 | |||
6 | . testing.sh | ||
7 | |||
8 | NO_REDUCE=65536 | ||
9 | NO_TRIM=131072 | ||
10 | GREEDY=262144 | ||
11 | |||
12 | # testing "description" "command" "result" "infile" "stdin" | ||
13 | |||
14 | testing "mdev.conf" \ | ||
15 | "parse -n 4 -m 3 -f $GREEDY -" \ | ||
16 | "[sda][0:0][644][@echo @echo TEST]\n" \ | ||
17 | "-" \ | ||
18 | " sda 0:0 644 @echo @echo TEST # echo trap\n" | ||
19 | |||
20 | testing "notrim" \ | ||
21 | "parse -n 4 -m 3 -f $(($GREEDY+$NO_TRIM)) -" \ | ||
22 | "[][sda][0:0][644 @echo @echo TEST ]\n" \ | ||
23 | "-" \ | ||
24 | " sda 0:0 644 @echo @echo TEST \n" | ||
25 | |||
26 | FILE=__parse.fstab | ||
27 | cat >$FILE <<EOF | ||
28 | # | ||
29 | # Device Point System Options | ||
30 | #_______________________________________________________________ | ||
31 | /dev/hdb3 / ext2 defaults 1 0 | ||
32 | /dev/hdb1 /dosc hpfs ro 1 0 | ||
33 | /dev/fd0 /dosa vfat rw,user,noauto,nohide 0 0 | ||
34 | /dev/fd1 /dosb vfat rw,user,noauto,nohide 0 0 | ||
35 | # | ||
36 | /dev/cdrom /cdrom iso9660 ro,user,noauto,nohide 0 0 | ||
37 | /dev/hdb5 /redhat ext2 rw,root,noauto,nohide 0 0 #sssd | ||
38 | /dev/hdb6 /win2home ntfs rw,root,noauto,nohide 0 0# ssdsd | ||
39 | /dev/hdb7 /win2skul ntfs rw,root,noauto,nohide none 0 0 | ||
40 | none /dev/pts devpts gid=5,mode=620 0 0 | ||
41 | none /proc proc defaults 0 0 | ||
42 | EOF | ||
43 | |||
44 | cat >$FILE.res <<EOF | ||
45 | [/dev/hdb3][/][ext2][defaults][1][0] | ||
46 | [/dev/hdb1][/dosc][hpfs][ro][1][0] | ||
47 | [/dev/fd0][/dosa][vfat][rw,user,noauto,nohide][0][0] | ||
48 | [/dev/fd1][/dosb][vfat][rw,user,noauto,nohide][0][0] | ||
49 | [/dev/cdrom][/cdrom][iso9660][ro,user,noauto,nohide][0][0] | ||
50 | [/dev/hdb5][/redhat][ext2][rw,root,noauto,nohide][0][0] | ||
51 | [/dev/hdb6][/win2home][ntfs][rw,root,noauto,nohide][0][0] | ||
52 | [/dev/hdb7][/win2skul][ntfs][rw,root,noauto,nohide][none][0] | ||
53 | [none][/dev/pts][devpts][gid=5,mode=620][0][0] | ||
54 | [none][/proc][proc][defaults][0][0] | ||
55 | EOF | ||
56 | |||
57 | testing "polluted fstab" \ | ||
58 | "parse -n 6 -m 6 $FILE" \ | ||
59 | "`cat $FILE.res`\n" \ | ||
60 | "" \ | ||
61 | "" | ||
62 | rm -f $FILE $FILE.res | ||
63 | |||
64 | exit $FAILCOUNT | ||
diff --git a/util-linux/mdev.c b/util-linux/mdev.c index f83dd6adf..7ad55c8af 100644 --- a/util-linux/mdev.c +++ b/util-linux/mdev.c | |||
@@ -101,7 +101,7 @@ static void make_device(char *path, int delete) | |||
101 | if (!parser) | 101 | if (!parser) |
102 | goto end_parse; | 102 | goto end_parse; |
103 | 103 | ||
104 | while (config_read(parser, tokens, 4, 3, " \t", '#') >= 0) { | 104 | while (config_read(parser, tokens, 4, 3, "# \t", PARSE_LAST_IS_GREEDY)) { |
105 | regmatch_t off[1+9*ENABLE_FEATURE_MDEV_RENAME_REGEXP]; | 105 | regmatch_t off[1+9*ENABLE_FEATURE_MDEV_RENAME_REGEXP]; |
106 | char *val; | 106 | char *val; |
107 | 107 | ||