diff options
Diffstat (limited to 'libbb')
-rw-r--r-- | libbb/getopt32.c | 82 | ||||
-rw-r--r-- | libbb/parse_config.c | 4 |
2 files changed, 61 insertions, 25 deletions
diff --git a/libbb/getopt32.c b/libbb/getopt32.c index d0e83d88e..15b6efc09 100644 --- a/libbb/getopt32.c +++ b/libbb/getopt32.c | |||
@@ -17,23 +17,20 @@ | |||
17 | uint32_t | 17 | uint32_t |
18 | getopt32(char **argv, const char *applet_opts, ...) | 18 | getopt32(char **argv, const char *applet_opts, ...) |
19 | 19 | ||
20 | The command line options must be declared in const char | 20 | The command line options are passed as the applet_opts string. |
21 | *applet_opts as a string of chars, for example: | ||
22 | |||
23 | flags = getopt32(argv, "rnug"); | ||
24 | 21 | ||
25 | If one of the given options is found, a flag value is added to | 22 | If one of the given options is found, a flag value is added to |
26 | the return value (an unsigned long). | 23 | the return value. |
27 | 24 | ||
28 | The flag value is determined by the position of the char in | 25 | The flag value is determined by the position of the char in |
29 | applet_opts string. For example, in the above case: | 26 | applet_opts string. For example: |
30 | 27 | ||
31 | flags = getopt32(argv, "rnug"); | 28 | flags = getopt32(argv, "rnug"); |
32 | 29 | ||
33 | "r" will add 1 (bit 0) | 30 | "r" will set 1 (bit 0) |
34 | "n" will add 2 (bit 1) | 31 | "n" will set 2 (bit 1) |
35 | "u" will add 4 (bit 2) | 32 | "u" will set 4 (bit 2) |
36 | "g" will add 8 (bit 3) | 33 | "g" will set 8 (bit 3) |
37 | 34 | ||
38 | and so on. You can also look at the return value as a bit | 35 | and so on. You can also look at the return value as a bit |
39 | field and each option sets one bit. | 36 | field and each option sets one bit. |
@@ -45,7 +42,7 @@ getopt32(char **argv, const char *applet_opts, ...) | |||
45 | (options and their parameters will be moved into argv[] | 42 | (options and their parameters will be moved into argv[] |
46 | positions prior to argv[optind]). | 43 | positions prior to argv[optind]). |
47 | 44 | ||
48 | ":" If one of the options requires an argument, then add a ":" | 45 | "o:" If one of the options requires an argument, then add a ":" |
49 | after the char in applet_opts and provide a pointer to store | 46 | after the char in applet_opts and provide a pointer to store |
50 | the argument. For example: | 47 | the argument. For example: |
51 | 48 | ||
@@ -58,15 +55,39 @@ getopt32(char **argv, const char *applet_opts, ...) | |||
58 | &pointer_to_arg_for_a, &pointer_to_arg_for_b, | 55 | &pointer_to_arg_for_a, &pointer_to_arg_for_b, |
59 | &pointer_to_arg_for_c, &pointer_to_arg_for_d); | 56 | &pointer_to_arg_for_c, &pointer_to_arg_for_d); |
60 | 57 | ||
61 | The type of the pointer (char* or llist_t*) may be controlled | 58 | The type of the pointer may be controlled by "o::" or "o+" in |
62 | by the "::" special separator that is set in the external string | 59 | the external string opt_complementary (see below for more info). |
63 | opt_complementary (see below for more info). | ||
64 | 60 | ||
65 | "::" If option can have an *optional* argument, then add a "::" | 61 | "o::" If option can have an *optional* argument, then add a "::" |
66 | after its char in applet_opts and provide a pointer to store | 62 | after its char in applet_opts and provide a pointer to store |
67 | the argument. Note that optional arguments _must_ | 63 | the argument. Note that optional arguments _must_ |
68 | immediately follow the option: -oparam, not -o param. | 64 | immediately follow the option: -oparam, not -o param. |
69 | 65 | ||
66 | "o:+" This means that the parameter for this option is a nonnegative integer. | ||
67 | It will be processed with xatoi_positive() - allowed range | ||
68 | is 0..INT_MAX. | ||
69 | |||
70 | int param; // "unsigned param;" will also work | ||
71 | getopt32(argv, "p:+", ¶m); | ||
72 | |||
73 | "o:*" This means that the option can occur multiple times. Each occurrence | ||
74 | will be saved as a llist_t element instead of char*. | ||
75 | |||
76 | For example: | ||
77 | The grep applet can have one or more "-e pattern" arguments. | ||
78 | In this case you should use getopt32() as follows: | ||
79 | |||
80 | llist_t *patterns = NULL; | ||
81 | |||
82 | (this pointer must be initializated to NULL if the list is empty | ||
83 | as required by llist_add_to_end(llist_t **old_head, char *new_item).) | ||
84 | |||
85 | getopt32(argv, "e:*", &patterns); | ||
86 | |||
87 | $ grep -e user -e root /etc/passwd | ||
88 | root:x:0:0:root:/root:/bin/bash | ||
89 | user:x:500:500::/home/user:/bin/bash | ||
90 | |||
70 | "+" If the first character in the applet_opts string is a plus, | 91 | "+" If the first character in the applet_opts string is a plus, |
71 | then option processing will stop as soon as a non-option is | 92 | then option processing will stop as soon as a non-option is |
72 | encountered in the argv array. Useful for applets like env | 93 | encountered in the argv array. Useful for applets like env |
@@ -82,7 +103,7 @@ const char *applet_long_options | |||
82 | This struct allows you to define long options: | 103 | This struct allows you to define long options: |
83 | 104 | ||
84 | static const char applet_longopts[] ALIGN1 = | 105 | static const char applet_longopts[] ALIGN1 = |
85 | //"name\0" has_arg val | 106 | //"name\0" has_arg val |
86 | "verbose\0" No_argument "v" | 107 | "verbose\0" No_argument "v" |
87 | ; | 108 | ; |
88 | applet_long_options = applet_longopts; | 109 | applet_long_options = applet_longopts; |
@@ -90,7 +111,7 @@ const char *applet_long_options | |||
90 | The last member of struct option (val) typically is set to | 111 | The last member of struct option (val) typically is set to |
91 | matching short option from applet_opts. If there is no matching | 112 | matching short option from applet_opts. If there is no matching |
92 | char in applet_opts, then: | 113 | char in applet_opts, then: |
93 | - return bit have next position after short options | 114 | - return bit has next position after short options |
94 | - if has_arg is not "No_argument", use ptr for arg also | 115 | - if has_arg is not "No_argument", use ptr for arg also |
95 | - opt_complementary affects it too | 116 | - opt_complementary affects it too |
96 | 117 | ||
@@ -139,8 +160,8 @@ const char *opt_complementary | |||
139 | 160 | ||
140 | llist_t *my_b = NULL; | 161 | llist_t *my_b = NULL; |
141 | int verbose_level = 0; | 162 | int verbose_level = 0; |
142 | opt_complementary = "vv:b::b-c:c-b"; | 163 | opt_complementary = "vv:b-c:c-b"; |
143 | f = getopt32(argv, "vb:c", &my_b, &verbose_level); | 164 | f = getopt32(argv, "vb:*c", &my_b, &verbose_level); |
144 | if (f & 2) // -c after -b unsets -b flag | 165 | if (f & 2) // -c after -b unsets -b flag |
145 | while (my_b) dosomething_with(llist_pop(&my_b)); | 166 | while (my_b) dosomething_with(llist_pop(&my_b)); |
146 | if (my_b) // but llist is stored if -b is specified | 167 | if (my_b) // but llist is stored if -b is specified |
@@ -233,7 +254,7 @@ Special characters: | |||
233 | "x--x" Variation of the above, it means that -x option should occur | 254 | "x--x" Variation of the above, it means that -x option should occur |
234 | at most once. | 255 | at most once. |
235 | 256 | ||
236 | "a+" A plus after a char in opt_complementary means that the parameter | 257 | "o+" A plus after a char in opt_complementary means that the parameter |
237 | for this option is a nonnegative integer. It will be processed | 258 | for this option is a nonnegative integer. It will be processed |
238 | with xatoi_positive() - allowed range is 0..INT_MAX. | 259 | with xatoi_positive() - allowed range is 0..INT_MAX. |
239 | 260 | ||
@@ -241,7 +262,7 @@ Special characters: | |||
241 | opt_complementary = "p+"; | 262 | opt_complementary = "p+"; |
242 | getopt32(argv, "p:", ¶m); | 263 | getopt32(argv, "p:", ¶m); |
243 | 264 | ||
244 | "a::" A double colon after a char in opt_complementary means that the | 265 | "o::" A double colon after a char in opt_complementary means that the |
245 | option can occur multiple times. Each occurrence will be saved as | 266 | option can occur multiple times. Each occurrence will be saved as |
246 | a llist_t element instead of char*. | 267 | a llist_t element instead of char*. |
247 | 268 | ||
@@ -255,12 +276,17 @@ Special characters: | |||
255 | as required by llist_add_to_end(llist_t **old_head, char *new_item).) | 276 | as required by llist_add_to_end(llist_t **old_head, char *new_item).) |
256 | 277 | ||
257 | opt_complementary = "e::"; | 278 | opt_complementary = "e::"; |
258 | |||
259 | getopt32(argv, "e:", &patterns); | 279 | getopt32(argv, "e:", &patterns); |
280 | |||
260 | $ grep -e user -e root /etc/passwd | 281 | $ grep -e user -e root /etc/passwd |
261 | root:x:0:0:root:/root:/bin/bash | 282 | root:x:0:0:root:/root:/bin/bash |
262 | user:x:500:500::/home/user:/bin/bash | 283 | user:x:500:500::/home/user:/bin/bash |
263 | 284 | ||
285 | "o+" and "o::" can be handled by "o:+" and "o:*" specifiers | ||
286 | in option string (and it is preferred), but this does not work | ||
287 | for "long options only" cases, such as tar --exclude=PATTERN, | ||
288 | wget --header=HDR cases. | ||
289 | |||
264 | "a?b" A "?" between an option and a group of options means that | 290 | "a?b" A "?" between an option and a group of options means that |
265 | at least one of them is required to occur if the first option | 291 | at least one of them is required to occur if the first option |
266 | occurs in preceding command line arguments. | 292 | occurs in preceding command line arguments. |
@@ -359,10 +385,11 @@ getopt32(char **argv, const char *applet_opts, ...) | |||
359 | 385 | ||
360 | va_start(p, applet_opts); | 386 | va_start(p, applet_opts); |
361 | 387 | ||
362 | c = 0; | ||
363 | on_off = complementary; | 388 | on_off = complementary; |
364 | memset(on_off, 0, sizeof(complementary)); | 389 | memset(on_off, 0, sizeof(complementary)); |
365 | 390 | ||
391 | applet_opts = strcpy(alloca(strlen(applet_opts) + 1), applet_opts); | ||
392 | |||
366 | /* skip bbox extension */ | 393 | /* skip bbox extension */ |
367 | first_char = applet_opts[0]; | 394 | first_char = applet_opts[0]; |
368 | if (first_char == '!') | 395 | if (first_char == '!') |
@@ -372,6 +399,7 @@ getopt32(char **argv, const char *applet_opts, ...) | |||
372 | s = (const unsigned char *)applet_opts; | 399 | s = (const unsigned char *)applet_opts; |
373 | if (*s == '+' || *s == '-') | 400 | if (*s == '+' || *s == '-') |
374 | s++; | 401 | s++; |
402 | c = 0; | ||
375 | while (*s) { | 403 | while (*s) { |
376 | if (c >= 32) | 404 | if (c >= 32) |
377 | break; | 405 | break; |
@@ -379,6 +407,13 @@ getopt32(char **argv, const char *applet_opts, ...) | |||
379 | on_off->switch_on = (1 << c); | 407 | on_off->switch_on = (1 << c); |
380 | if (*++s == ':') { | 408 | if (*++s == ':') { |
381 | on_off->optarg = va_arg(p, void **); | 409 | on_off->optarg = va_arg(p, void **); |
410 | if (s[1] == '+' || s[1] == '*') { | ||
411 | /* 'o:+' or 'o:*' */ | ||
412 | on_off->param_type = (s[1] == '+') ? | ||
413 | PARAM_INT : PARAM_LIST; | ||
414 | overlapping_strcpy((char*)s + 1, (char*)s + 2); | ||
415 | } | ||
416 | /* skip possible 'o::' (or 'o:+:' !) */ | ||
382 | while (*++s == ':') | 417 | while (*++s == ':') |
383 | continue; | 418 | continue; |
384 | } | 419 | } |
@@ -431,6 +466,7 @@ getopt32(char **argv, const char *applet_opts, ...) | |||
431 | applet_long_options = NULL; | 466 | applet_long_options = NULL; |
432 | } | 467 | } |
433 | #endif /* ENABLE_LONG_OPTS || ENABLE_FEATURE_GETOPT_LONG */ | 468 | #endif /* ENABLE_LONG_OPTS || ENABLE_FEATURE_GETOPT_LONG */ |
469 | |||
434 | for (s = (const unsigned char *)opt_complementary; s && *s; s++) { | 470 | for (s = (const unsigned char *)opt_complementary; s && *s; s++) { |
435 | t_complementary *pair; | 471 | t_complementary *pair; |
436 | unsigned *pair_switch; | 472 | unsigned *pair_switch; |
diff --git a/libbb/parse_config.c b/libbb/parse_config.c index 1590d9a4c..408439766 100644 --- a/libbb/parse_config.c +++ b/libbb/parse_config.c | |||
@@ -42,8 +42,8 @@ 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:n+:m+:f+"; | 45 | opt_complementary = "-1"; |
46 | noout = 1 & getopt32(argv, "xn:m:d:f:", &ntokens, &mintokens, &delims, &flags); | 46 | noout = 1 & getopt32(argv, "xn:+m:+d:f:+", &ntokens, &mintokens, &delims, &flags); |
47 | //argc -= optind; | 47 | //argc -= optind; |
48 | argv += optind; | 48 | argv += optind; |
49 | 49 | ||