diff options
Diffstat (limited to 'libbb')
-rw-r--r-- | libbb/getopt32.c | 74 | ||||
-rw-r--r-- | libbb/parse_config.c | 5 | ||||
-rw-r--r-- | libbb/vfork_daemon_rexec.c | 3 |
3 files changed, 42 insertions, 40 deletions
diff --git a/libbb/getopt32.c b/libbb/getopt32.c index b2b4de8cb..f778c6e89 100644 --- a/libbb/getopt32.c +++ b/libbb/getopt32.c | |||
@@ -96,9 +96,11 @@ getopt32(char **argv, const char *applet_opts, ...) | |||
96 | env -i ls -d / | 96 | env -i ls -d / |
97 | Here we want env to process just the '-i', not the '-d'. | 97 | Here we want env to process just the '-i', not the '-d'. |
98 | 98 | ||
99 | "!" Report bad option, missing required options, | 99 | "!" Report bad options, missing required options, |
100 | inconsistent options with all-ones return value (instead of abort). | 100 | inconsistent options with all-ones return value (instead of abort). |
101 | 101 | ||
102 | "^" options string is "^optchars""\0""opt_complementary". | ||
103 | |||
102 | uint32_t | 104 | uint32_t |
103 | getopt32long(char **argv, const char *applet_opts, const char *logopts...) | 105 | getopt32long(char **argv, const char *applet_opts, const char *logopts...) |
104 | 106 | ||
@@ -121,7 +123,7 @@ getopt32long(char **argv, const char *applet_opts, const char *logopts...) | |||
121 | config process and not a required feature. The current standard | 123 | config process and not a required feature. The current standard |
122 | is to name the config option CONFIG_FEATURE_<applet>_LONG_OPTIONS. | 124 | is to name the config option CONFIG_FEATURE_<applet>_LONG_OPTIONS. |
123 | 125 | ||
124 | const char *opt_complementary | 126 | opt_complementary - option modifiers. |
125 | 127 | ||
126 | ":" The colon (":") is used to separate groups of two or more chars | 128 | ":" The colon (":") is used to separate groups of two or more chars |
127 | and/or groups of chars and special characters (stating some | 129 | and/or groups of chars and special characters (stating some |
@@ -132,8 +134,7 @@ const char *opt_complementary | |||
132 | Their flags will be turned on if the main option is found even | 134 | Their flags will be turned on if the main option is found even |
133 | if they are not specified on the command line. For example: | 135 | if they are not specified on the command line. For example: |
134 | 136 | ||
135 | opt_complementary = "abc"; | 137 | flags = getopt32(argv, "^abcd""\0""abc") |
136 | flags = getopt32(argv, "abcd") | ||
137 | 138 | ||
138 | If getopt() finds "-a" on the command line, then | 139 | If getopt() finds "-a" on the command line, then |
139 | getopt32's return value will be as if "-a -b -c" were | 140 | getopt32's return value will be as if "-a -b -c" were |
@@ -146,8 +147,7 @@ const char *opt_complementary | |||
146 | if w is given more than once, it is "unlimited" | 147 | if w is given more than once, it is "unlimited" |
147 | 148 | ||
148 | int w_counter = 0; // must be initialized! | 149 | int w_counter = 0; // must be initialized! |
149 | opt_complementary = "ww"; | 150 | getopt32(argv, "^w""\0""ww", &w_counter); |
150 | getopt32(argv, "w", &w_counter); | ||
151 | if (w_counter) | 151 | if (w_counter) |
152 | width = (w_counter == 1) ? 132 : INT_MAX; | 152 | width = (w_counter == 1) ? 132 : INT_MAX; |
153 | else | 153 | else |
@@ -162,8 +162,9 @@ const char *opt_complementary | |||
162 | 162 | ||
163 | llist_t *my_b = NULL; | 163 | llist_t *my_b = NULL; |
164 | int verbose_level = 0; | 164 | int verbose_level = 0; |
165 | opt_complementary = "vv:b-c:c-b"; | 165 | f = getopt32(argv, "^vb:*c" |
166 | f = getopt32(argv, "vb:*c", &my_b, &verbose_level); | 166 | "\0""vv:b-c:c-b" |
167 | , &my_b, &verbose_level); | ||
167 | if (f & 2) // -c after -b unsets -b flag | 168 | if (f & 2) // -c after -b unsets -b flag |
168 | while (my_b) dosomething_with(llist_pop(&my_b)); | 169 | while (my_b) dosomething_with(llist_pop(&my_b)); |
169 | if (my_b) // but llist is stored if -b is specified | 170 | if (my_b) // but llist is stored if -b is specified |
@@ -199,7 +200,7 @@ Special characters: | |||
199 | getopt32 finds -s, then -d is unset or if it finds -d | 200 | getopt32 finds -s, then -d is unset or if it finds -d |
200 | then -s is unset. (Note: busybox implements the GNU | 201 | then -s is unset. (Note: busybox implements the GNU |
201 | "--max-depth" option as "-d".) To obtain this behavior, you | 202 | "--max-depth" option as "-d".) To obtain this behavior, you |
202 | set opt_complementary = "s-d:d-s". Only one flag value is | 203 | set opt_complementary to "s-d:d-s". Only one flag value is |
203 | added to getopt32's return value depending on the | 204 | added to getopt32's return value depending on the |
204 | position of the options on the command line. If one of the | 205 | position of the options on the command line. If one of the |
205 | two options requires an argument pointer (":" in applet_opts | 206 | two options requires an argument pointer (":" in applet_opts |
@@ -207,8 +208,7 @@ Special characters: | |||
207 | 208 | ||
208 | char *smax_print_depth; | 209 | char *smax_print_depth; |
209 | 210 | ||
210 | opt_complementary = "s-d:d-s:x-x"; | 211 | opt = getopt32(argv, "^sd:x""\0""s-d:d-s:x-x", &smax_print_depth); |
211 | opt = getopt32(argv, "sd:x", &smax_print_depth); | ||
212 | 212 | ||
213 | if (opt & 2) | 213 | if (opt & 2) |
214 | max_print_depth = atoi(smax_print_depth); | 214 | max_print_depth = atoi(smax_print_depth); |
@@ -224,7 +224,7 @@ Special characters: | |||
224 | The cut applet must have only one type of list specified, so | 224 | The cut applet must have only one type of list specified, so |
225 | -b, -c and -f are mutually exclusive and should raise an error | 225 | -b, -c and -f are mutually exclusive and should raise an error |
226 | if specified together. In this case you must set | 226 | if specified together. In this case you must set |
227 | opt_complementary = "b--cf:c--bf:f--bc". If two of the | 227 | opt_complementary to "b--cf:c--bf:f--bc". If two of the |
228 | mutually exclusive options are found, getopt32 will call | 228 | mutually exclusive options are found, getopt32 will call |
229 | bb_show_usage() and die. | 229 | bb_show_usage() and die. |
230 | 230 | ||
@@ -236,8 +236,7 @@ Special characters: | |||
236 | with xatoi_positive() - allowed range is 0..INT_MAX. | 236 | with xatoi_positive() - allowed range is 0..INT_MAX. |
237 | 237 | ||
238 | int param; // "unsigned param;" will also work | 238 | int param; // "unsigned param;" will also work |
239 | opt_complementary = "p+"; | 239 | getopt32(argv, "^p:""\0""p+", ¶m); |
240 | getopt32(argv, "p:", ¶m); | ||
241 | 240 | ||
242 | "o::" A double colon after a char in opt_complementary means that the | 241 | "o::" A double colon after a char in opt_complementary means that the |
243 | option can occur multiple times. Each occurrence will be saved as | 242 | option can occur multiple times. Each occurrence will be saved as |
@@ -252,8 +251,7 @@ Special characters: | |||
252 | (this pointer must be initializated to NULL if the list is empty | 251 | (this pointer must be initializated to NULL if the list is empty |
253 | as required by llist_add_to_end(llist_t **old_head, char *new_item).) | 252 | as required by llist_add_to_end(llist_t **old_head, char *new_item).) |
254 | 253 | ||
255 | opt_complementary = "e::"; | 254 | getopt32(argv, "^e:""\0""e::", &patterns); |
256 | getopt32(argv, "e:", &patterns); | ||
257 | 255 | ||
258 | $ grep -e user -e root /etc/passwd | 256 | $ grep -e user -e root /etc/passwd |
259 | root:x:0:0:root:/root:/bin/bash | 257 | root:x:0:0:root:/root:/bin/bash |
@@ -271,8 +269,7 @@ Special characters: | |||
271 | For example from "id" applet: | 269 | For example from "id" applet: |
272 | 270 | ||
273 | // Don't allow -n -r -rn -ug -rug -nug -rnug | 271 | // Don't allow -n -r -rn -ug -rug -nug -rnug |
274 | opt_complementary = "r?ug:n?ug:u--g:g--u"; | 272 | flags = getopt32(argv, "^rnug""\0""r?ug:n?ug:u--g:g--u"); |
275 | flags = getopt32(argv, "rnug"); | ||
276 | 273 | ||
277 | This example allowed only: | 274 | This example allowed only: |
278 | $ id; id -u; id -g; id -ru; id -nu; id -rg; id -ng; id -rnu; id -rng | 275 | $ id; id -u; id -g; id -ru; id -nu; id -rg; id -ng; id -rnu; id -rng |
@@ -283,8 +280,7 @@ Special characters: | |||
283 | For example from "start-stop-daemon" applet: | 280 | For example from "start-stop-daemon" applet: |
284 | 281 | ||
285 | // Don't allow -KS -SK, but -S or -K is required | 282 | // Don't allow -KS -SK, but -S or -K is required |
286 | opt_complementary = "K:S:K--S:S--K"; | 283 | flags = getopt32(argv, "^KS...""\0""K:S:K--S:S--K"); |
287 | flags = getopt32(argv, "KS...); | ||
288 | 284 | ||
289 | 285 | ||
290 | Don't forget to use ':'. For example, "?322-22-23X-x-a" | 286 | Don't forget to use ':'. For example, "?322-22-23X-x-a" |
@@ -299,8 +295,6 @@ Special characters: | |||
299 | 295 | ||
300 | const char *const bb_argv_dash[] = { "-", NULL }; | 296 | const char *const bb_argv_dash[] = { "-", NULL }; |
301 | 297 | ||
302 | const char *opt_complementary; | ||
303 | |||
304 | enum { | 298 | enum { |
305 | PARAM_STRING, | 299 | PARAM_STRING, |
306 | PARAM_LIST, | 300 | PARAM_LIST, |
@@ -337,10 +331,12 @@ vgetopt32(char **argv, const char *applet_opts, const char *applet_long_options, | |||
337 | int argc; | 331 | int argc; |
338 | unsigned flags = 0; | 332 | unsigned flags = 0; |
339 | unsigned requires = 0; | 333 | unsigned requires = 0; |
334 | unsigned len; | ||
340 | t_complementary complementary[33]; /* last stays zero-filled */ | 335 | t_complementary complementary[33]; /* last stays zero-filled */ |
341 | char first_char; | 336 | char dont_die_flag; |
342 | int c; | 337 | int c; |
343 | const unsigned char *s; | 338 | const unsigned char *s; |
339 | const char *opt_complementary; | ||
344 | t_complementary *on_off; | 340 | t_complementary *on_off; |
345 | #if ENABLE_LONG_OPTS | 341 | #if ENABLE_LONG_OPTS |
346 | const struct option *l_o; | 342 | const struct option *l_o; |
@@ -349,23 +345,29 @@ vgetopt32(char **argv, const char *applet_opts, const char *applet_long_options, | |||
349 | unsigned trigger; | 345 | unsigned trigger; |
350 | int min_arg = 0; | 346 | int min_arg = 0; |
351 | int max_arg = -1; | 347 | int max_arg = -1; |
352 | |||
353 | #define SHOW_USAGE_IF_ERROR 1 | ||
354 | |||
355 | int spec_flgs = 0; | 348 | int spec_flgs = 0; |
356 | 349 | ||
357 | /* skip 0: some applets cheat: they do not actually HAVE argv[0] */ | 350 | #define SHOW_USAGE_IF_ERROR 1 |
358 | argc = 1 + string_array_len(argv + 1); | ||
359 | 351 | ||
360 | on_off = complementary; | 352 | on_off = complementary; |
361 | memset(on_off, 0, sizeof(complementary)); | 353 | memset(on_off, 0, sizeof(complementary)); |
362 | 354 | ||
363 | applet_opts = strcpy(alloca(strlen(applet_opts) + 1), applet_opts); | 355 | len = strlen(applet_opts); |
364 | 356 | ||
365 | /* skip bbox extension */ | 357 | /* skip bbox extension */ |
366 | first_char = applet_opts[0]; | 358 | opt_complementary = NULL; |
367 | if (first_char == '!') | 359 | if (applet_opts[0] == '^') { |
368 | applet_opts++; | 360 | applet_opts++; |
361 | /* point it past terminating NUL */ | ||
362 | opt_complementary = applet_opts + len; | ||
363 | } | ||
364 | |||
365 | /* skip another bbox extension */ | ||
366 | dont_die_flag = applet_opts[0]; | ||
367 | if (dont_die_flag == '!') | ||
368 | applet_opts++; | ||
369 | |||
370 | applet_opts = strcpy(alloca(len + 1), applet_opts); | ||
369 | 371 | ||
370 | /* skip GNU extension */ | 372 | /* skip GNU extension */ |
371 | s = (const unsigned char *)applet_opts; | 373 | s = (const unsigned char *)applet_opts; |
@@ -435,7 +437,8 @@ vgetopt32(char **argv, const char *applet_opts, const char *applet_long_options, | |||
435 | } | 437 | } |
436 | #endif /* ENABLE_LONG_OPTS */ | 438 | #endif /* ENABLE_LONG_OPTS */ |
437 | 439 | ||
438 | for (s = (const unsigned char *)opt_complementary; s && *s; s++) { | 440 | s = (const unsigned char *)opt_complementary; |
441 | if (s) for (; *s; s++) { | ||
439 | t_complementary *pair; | 442 | t_complementary *pair; |
440 | unsigned *pair_switch; | 443 | unsigned *pair_switch; |
441 | 444 | ||
@@ -513,8 +516,6 @@ vgetopt32(char **argv, const char *applet_opts, const char *applet_long_options, | |||
513 | s--; | 516 | s--; |
514 | } | 517 | } |
515 | 518 | ||
516 | /* Make it unnecessary to clear it by hand after each getopt32 call */ | ||
517 | opt_complementary = NULL; | ||
518 | /* In case getopt32 was already called: | 519 | /* In case getopt32 was already called: |
519 | * reset the libc getopt() function, which keeps internal state. | 520 | * reset the libc getopt() function, which keeps internal state. |
520 | * run_nofork_applet() does this, but we might end up here | 521 | * run_nofork_applet() does this, but we might end up here |
@@ -522,6 +523,9 @@ vgetopt32(char **argv, const char *applet_opts, const char *applet_long_options, | |||
522 | */ | 523 | */ |
523 | GETOPT_RESET(); | 524 | GETOPT_RESET(); |
524 | 525 | ||
526 | /* skip 0: some applets cheat: they do not actually HAVE argv[0] */ | ||
527 | argc = 1 + string_array_len(argv + 1); | ||
528 | |||
525 | /* Note: just "getopt() <= 0" will not work well for | 529 | /* Note: just "getopt() <= 0" will not work well for |
526 | * "fake" short options, like this one: | 530 | * "fake" short options, like this one: |
527 | * wget $'-\203' "Test: test" http://kernel.org/ | 531 | * wget $'-\203' "Test: test" http://kernel.org/ |
@@ -583,7 +587,7 @@ vgetopt32(char **argv, const char *applet_opts, const char *applet_long_options, | |||
583 | return flags; | 587 | return flags; |
584 | 588 | ||
585 | error: | 589 | error: |
586 | if (first_char != '!') | 590 | if (dont_die_flag != '!') |
587 | bb_show_usage(); | 591 | bb_show_usage(); |
588 | return (int32_t)-1; | 592 | return (int32_t)-1; |
589 | } | 593 | } |
diff --git a/libbb/parse_config.c b/libbb/parse_config.c index eaf69d97f..8701b010c 100644 --- a/libbb/parse_config.c +++ b/libbb/parse_config.c | |||
@@ -42,8 +42,9 @@ int parse_main(int argc UNUSED_PARAM, char **argv) | |||
42 | int mintokens = 0, ntokens = 128; | 42 | int mintokens = 0, ntokens = 128; |
43 | unsigned noout; | 43 | unsigned noout; |
44 | 44 | ||
45 | opt_complementary = "-1"; | 45 | noout = 1 & getopt32(argv, "^" "xn:+m:+d:f:+" "\0" "-1", |
46 | noout = 1 & getopt32(argv, "xn:+m:+d:f:+", &ntokens, &mintokens, &delims, &flags); | 46 | &ntokens, &mintokens, &delims, &flags |
47 | ); | ||
47 | //argc -= optind; | 48 | //argc -= optind; |
48 | argv += optind; | 49 | argv += optind; |
49 | 50 | ||
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index 15c92a7cd..6125983ce 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c | |||
@@ -98,7 +98,6 @@ int FAST_FUNC run_nofork_applet(int applet_no, char **argv) | |||
98 | * (getopt32() does it itself, but getopt() doesn't (and can't)) | 98 | * (getopt32() does it itself, but getopt() doesn't (and can't)) |
99 | */ | 99 | */ |
100 | GETOPT_RESET(); | 100 | GETOPT_RESET(); |
101 | /* opt_complementary = NULL; - cleared by each getopt32() call anyway */ | ||
102 | 101 | ||
103 | argc = string_array_len(argv); | 102 | argc = string_array_len(argv); |
104 | 103 | ||
@@ -123,7 +122,6 @@ int FAST_FUNC run_nofork_applet(int applet_no, char **argv) | |||
123 | restore_nofork_data(&old); | 122 | restore_nofork_data(&old); |
124 | /* Other globals can be simply reset to defaults */ | 123 | /* Other globals can be simply reset to defaults */ |
125 | GETOPT_RESET(); | 124 | GETOPT_RESET(); |
126 | /* opt_complementary = NULL; - cleared by each getopt32() call anyway */ | ||
127 | 125 | ||
128 | return rc & 0xff; /* don't confuse people with "exitcodes" >255 */ | 126 | return rc & 0xff; /* don't confuse people with "exitcodes" >255 */ |
129 | } | 127 | } |
@@ -138,7 +136,6 @@ void FAST_FUNC run_noexec_applet_and_exit(int a, const char *name, char **argv) | |||
138 | xfunc_error_retval = EXIT_FAILURE; | 136 | xfunc_error_retval = EXIT_FAILURE; |
139 | die_func = NULL; | 137 | die_func = NULL; |
140 | GETOPT_RESET(); | 138 | GETOPT_RESET(); |
141 | /* opt_complementary = NULL; - cleared by each getopt32() call anyway */ | ||
142 | 139 | ||
143 | //TODO: think pidof, pgrep, pkill! | 140 | //TODO: think pidof, pgrep, pkill! |
144 | //set_task_comm() makes our pidof find NOEXECs (e.g. "yes >/dev/null"), | 141 | //set_task_comm() makes our pidof find NOEXECs (e.g. "yes >/dev/null"), |