aboutsummaryrefslogtreecommitdiff
path: root/libbb
diff options
context:
space:
mode:
Diffstat (limited to 'libbb')
-rw-r--r--libbb/getopt32.c82
-rw-r--r--libbb/parse_config.c4
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 @@
17uint32_t 17uint32_t
18getopt32(char **argv, const char *applet_opts, ...) 18getopt32(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:+", &param);
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:", &param); 263 getopt32(argv, "p:", &param);
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