getopt32: move support for "always treat first arg as option" to users (tar/ar)
[oweals/busybox.git] / libbb / getopt32.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * universal getopt32 implementation for busybox
4  *
5  * Copyright (C) 2003-2005  Vladimir Oleynik  <dzo@simtreas.ru>
6  *
7  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8  */
9 #if ENABLE_LONG_OPTS || ENABLE_FEATURE_GETOPT_LONG
10 # include <getopt.h>
11 #endif
12 #include "libbb.h"
13
14 //kbuild:lib-y += getopt32.o
15
16 /*      Documentation
17
18 uint32_t
19 getopt32(char **argv, const char *applet_opts, ...)
20
21         The command line options are passed as the applet_opts string.
22
23         If one of the given options is found, a flag value is added to
24         the return value.
25
26         The flag value is determined by the position of the char in
27         applet_opts string.  For example:
28
29         flags = getopt32(argv, "rnug");
30
31         "r" will set 1    (bit 0)
32         "n" will set 2    (bit 1)
33         "u" will set 4    (bit 2)
34         "g" will set 8    (bit 3)
35
36         and so on.  You can also look at the return value as a bit
37         field and each option sets one bit.
38
39         On exit, global variable optind is set so that if you
40         will do argc -= optind; argv += optind; then
41         argc will be equal to number of remaining non-option
42         arguments, first one would be in argv[0], next in argv[1] and so on
43         (options and their parameters will be moved into argv[]
44         positions prior to argv[optind]).
45
46  "o:"   If one of the options requires an argument, then add a ":"
47         after the char in applet_opts and provide a pointer to store
48         the argument.  For example:
49
50         char *pointer_to_arg_for_a;
51         char *pointer_to_arg_for_b;
52         char *pointer_to_arg_for_c;
53         char *pointer_to_arg_for_d;
54
55         flags = getopt32(argv, "a:b:c:d:",
56                         &pointer_to_arg_for_a, &pointer_to_arg_for_b,
57                         &pointer_to_arg_for_c, &pointer_to_arg_for_d);
58
59         The type of the pointer may be controlled by "o::" or "o+" in
60         the external string opt_complementary (see below for more info).
61
62  "o::"  If option can have an *optional* argument, then add a "::"
63         after its char in applet_opts and provide a pointer to store
64         the argument.  Note that optional arguments _must_
65         immediately follow the option: -oparam, not -o param.
66
67  "o:+"  This means that the parameter for this option is a nonnegative integer.
68         It will be processed with xatoi_positive() - allowed range
69         is 0..INT_MAX.
70
71         int param;  // "unsigned param;" will also work
72         getopt32(argv, "p:+", &param);
73
74  "o:*"  This means that the option can occur multiple times. Each occurrence
75         will be saved as a llist_t element instead of char*.
76
77         For example:
78         The grep applet can have one or more "-e pattern" arguments.
79         In this case you should use getopt32() as follows:
80
81         llist_t *patterns = NULL;
82
83         (this pointer must be initializated to NULL if the list is empty
84         as required by llist_add_to_end(llist_t **old_head, char *new_item).)
85
86         getopt32(argv, "e:*", &patterns);
87
88         $ grep -e user -e root /etc/passwd
89         root:x:0:0:root:/root:/bin/bash
90         user:x:500:500::/home/user:/bin/bash
91
92  "+"    If the first character in the applet_opts string is a plus,
93         then option processing will stop as soon as a non-option is
94         encountered in the argv array.  Useful for applets like env
95         which should not process arguments to subprograms:
96         env -i ls -d /
97         Here we want env to process just the '-i', not the '-d'.
98
99  "!"    Report bad option, missing required options,
100         inconsistent options with all-ones return value (instead of abort).
101
102 const char *applet_long_options
103
104         This struct allows you to define long options:
105
106         static const char applet_longopts[] ALIGN1 =
107                 //"name\0"  has_arg     val
108                 "verbose\0" No_argument "v"
109                 ;
110         applet_long_options = applet_longopts;
111
112         The last member of struct option (val) typically is set to
113         matching short option from applet_opts. If there is no matching
114         char in applet_opts, then:
115         - return bit has next position after short options
116         - if has_arg is not "No_argument", use ptr for arg also
117         - opt_complementary affects it too
118
119         Note: a good applet will make long options configurable via the
120         config process and not a required feature.  The current standard
121         is to name the config option CONFIG_FEATURE_<applet>_LONG_OPTIONS.
122
123 const char *opt_complementary
124
125  ":"    The colon (":") is used to separate groups of two or more chars
126         and/or groups of chars and special characters (stating some
127         conditions to be checked).
128
129  "abc"  If groups of two or more chars are specified, the first char
130         is the main option and the other chars are secondary options.
131         Their flags will be turned on if the main option is found even
132         if they are not specified on the command line.  For example:
133
134         opt_complementary = "abc";
135         flags = getopt32(argv, "abcd")
136
137         If getopt() finds "-a" on the command line, then
138         getopt32's return value will be as if "-a -b -c" were
139         found.
140
141  "ww"   Adjacent double options have a counter associated which indicates
142         the number of occurrences of the option.
143         For example the ps applet needs:
144         if w is given once, GNU ps sets the width to 132,
145         if w is given more than once, it is "unlimited"
146
147         int w_counter = 0; // must be initialized!
148         opt_complementary = "ww";
149         getopt32(argv, "w", &w_counter);
150         if (w_counter)
151                 width = (w_counter == 1) ? 132 : INT_MAX;
152         else
153                 get_terminal_width(...&width...);
154
155         w_counter is a pointer to an integer. It has to be passed to
156         getopt32() after all other option argument sinks.
157
158         For example: accept multiple -v to indicate the level of verbosity
159         and for each -b optarg, add optarg to my_b. Finally, if b is given,
160         turn off c and vice versa:
161
162         llist_t *my_b = NULL;
163         int verbose_level = 0;
164         opt_complementary = "vv:b-c:c-b";
165         f = getopt32(argv, "vb:*c", &my_b, &verbose_level);
166         if (f & 2)       // -c after -b unsets -b flag
167                 while (my_b) dosomething_with(llist_pop(&my_b));
168         if (my_b)        // but llist is stored if -b is specified
169                 free_llist(my_b);
170         if (verbose_level) printf("verbose level is %d\n", verbose_level);
171
172 Special characters:
173
174  "-N"   A dash as the first char in a opt_complementary group followed
175         by a single digit (0-9) means that at least N non-option
176         arguments must be present on the command line
177
178  "=N"   An equal sign as the first char in a opt_complementary group followed
179         by a single digit (0-9) means that exactly N non-option
180         arguments must be present on the command line
181
182  "?N"   A "?" as the first char in a opt_complementary group followed
183         by a single digit (0-9) means that at most N arguments must be present
184         on the command line.
185
186  "V-"   An option with dash before colon or end-of-line results in
187         bb_show_usage() being called if this option is encountered.
188         This is typically used to implement "print verbose usage message
189         and exit" option.
190
191  "a-b"  A dash between two options causes the second of the two
192         to be unset (and ignored) if it is given on the command line.
193
194         [FIXME: what if they are the same? like "x-x"? Is it ever useful?]
195
196         For example:
197         The du applet has the options "-s" and "-d depth".  If
198         getopt32 finds -s, then -d is unset or if it finds -d
199         then -s is unset.  (Note:  busybox implements the GNU
200         "--max-depth" option as "-d".)  To obtain this behavior, you
201         set opt_complementary = "s-d:d-s".  Only one flag value is
202         added to getopt32's return value depending on the
203         position of the options on the command line.  If one of the
204         two options requires an argument pointer (":" in applet_opts
205         as in "d:") optarg is set accordingly.
206
207         char *smax_print_depth;
208
209         opt_complementary = "s-d:d-s:x-x";
210         opt = getopt32(argv, "sd:x", &smax_print_depth);
211
212         if (opt & 2)
213                 max_print_depth = atoi(smax_print_depth);
214         if (opt & 4)
215                 printf("Detected odd -x usage\n");
216
217  "a--b" A double dash between two options, or between an option and a group
218         of options, means that they are mutually exclusive.  Unlike
219         the "-" case above, an error will be forced if the options
220         are used together.
221
222         For example:
223         The cut applet must have only one type of list specified, so
224         -b, -c and -f are mutually exclusive and should raise an error
225         if specified together.  In this case you must set
226         opt_complementary = "b--cf:c--bf:f--bc".  If two of the
227         mutually exclusive options are found, getopt32 will call
228         bb_show_usage() and die.
229
230  "x--x" Variation of the above, it means that -x option should occur
231         at most once.
232
233  "o+"   A plus after a char in opt_complementary means that the parameter
234         for this option is a nonnegative integer. It will be processed
235         with xatoi_positive() - allowed range is 0..INT_MAX.
236
237         int param;  // "unsigned param;" will also work
238         opt_complementary = "p+";
239         getopt32(argv, "p:", &param);
240
241  "o::"  A double colon after a char in opt_complementary means that the
242         option can occur multiple times. Each occurrence will be saved as
243         a llist_t element instead of char*.
244
245         For example:
246         The grep applet can have one or more "-e pattern" arguments.
247         In this case you should use getopt32() as follows:
248
249         llist_t *patterns = NULL;
250
251         (this pointer must be initializated to NULL if the list is empty
252         as required by llist_add_to_end(llist_t **old_head, char *new_item).)
253
254         opt_complementary = "e::";
255         getopt32(argv, "e:", &patterns);
256
257         $ grep -e user -e root /etc/passwd
258         root:x:0:0:root:/root:/bin/bash
259         user:x:500:500::/home/user:/bin/bash
260
261         "o+" and "o::" can be handled by "o:+" and "o:*" specifiers
262         in option string (and it is preferred), but this does not work
263         for "long options only" cases, such as tar --exclude=PATTERN,
264         wget --header=HDR cases.
265
266  "a?b"  A "?" between an option and a group of options means that
267         at least one of them is required to occur if the first option
268         occurs in preceding command line arguments.
269
270         For example from "id" applet:
271
272         // Don't allow -n -r -rn -ug -rug -nug -rnug
273         opt_complementary = "r?ug:n?ug:u--g:g--u";
274         flags = getopt32(argv, "rnug");
275
276         This example allowed only:
277         $ id; id -u; id -g; id -ru; id -nu; id -rg; id -ng; id -rnu; id -rng
278
279  "X"    A opt_complementary group with just a single letter means
280         that this option is required. If more than one such group exists,
281         at least one option is required to occur (not all of them).
282         For example from "start-stop-daemon" applet:
283
284         // Don't allow -KS -SK, but -S or -K is required
285         opt_complementary = "K:S:K--S:S--K";
286         flags = getopt32(argv, "KS...);
287
288
289         Don't forget to use ':'. For example, "?322-22-23X-x-a"
290         is interpreted as "?3:22:-2:2-2:2-3Xa:2--x" -
291         max 3 args; count uses of '-2'; min 2 args; if there is
292         a '-2' option then unset '-3', '-X' and '-a'; if there is
293         a '-2' and after it a '-x' then error out.
294         But it's far too obfuscated. Use ':' to separate groups.
295 */
296
297 /* Code here assumes that 'unsigned' is at least 32 bits wide */
298
299 const char *const bb_argv_dash[] = { "-", NULL };
300
301 const char *opt_complementary;
302
303 enum {
304         PARAM_STRING,
305         PARAM_LIST,
306         PARAM_INT,
307 };
308
309 typedef struct {
310         unsigned char opt_char;
311         smallint param_type;
312         unsigned switch_on;
313         unsigned switch_off;
314         unsigned incongruously;
315         unsigned requires;
316         void **optarg;  /* char**, llist_t** or int *. */
317         int *counter;
318 } t_complementary;
319
320 /* You can set applet_long_options for parse called long options */
321 #if ENABLE_LONG_OPTS || ENABLE_FEATURE_GETOPT_LONG
322 static const struct option bb_null_long_options[1] = {
323         { 0, 0, 0, 0 }
324 };
325 const char *applet_long_options;
326 #endif
327
328 uint32_t option_mask32;
329
330 /* Please keep getopt32 free from xmalloc */
331
332 uint32_t FAST_FUNC
333 getopt32(char **argv, const char *applet_opts, ...)
334 {
335         int argc;
336         unsigned flags = 0;
337         unsigned requires = 0;
338         t_complementary complementary[33]; /* last stays zero-filled */
339         char first_char;
340         int c;
341         const unsigned char *s;
342         t_complementary *on_off;
343         va_list p;
344 #if ENABLE_LONG_OPTS || ENABLE_FEATURE_GETOPT_LONG
345         const struct option *l_o;
346         struct option *long_options = (struct option *) &bb_null_long_options;
347 #endif
348         unsigned trigger;
349         int min_arg = 0;
350         int max_arg = -1;
351
352 #define SHOW_USAGE_IF_ERROR     1
353
354         int spec_flgs = 0;
355
356         /* skip 0: some applets cheat: they do not actually HAVE argv[0] */
357         argc = 1 + string_array_len(argv + 1);
358
359         va_start(p, applet_opts);
360
361         on_off = complementary;
362         memset(on_off, 0, sizeof(complementary));
363
364         applet_opts = strcpy(alloca(strlen(applet_opts) + 1), applet_opts);
365
366         /* skip bbox extension */
367         first_char = applet_opts[0];
368         if (first_char == '!')
369                 applet_opts++;
370
371         /* skip GNU extension */
372         s = (const unsigned char *)applet_opts;
373         if (*s == '+' || *s == '-')
374                 s++;
375         c = 0;
376         while (*s) {
377                 if (c >= 32)
378                         break;
379                 on_off->opt_char = *s;
380                 on_off->switch_on = (1U << c);
381                 if (*++s == ':') {
382                         on_off->optarg = va_arg(p, void **);
383                         if (s[1] == '+' || s[1] == '*') {
384                                 /* 'o:+' or 'o:*' */
385                                 on_off->param_type = (s[1] == '+') ?
386                                         PARAM_INT : PARAM_LIST;
387                                 overlapping_strcpy((char*)s + 1, (char*)s + 2);
388                         }
389                         /* skip possible 'o::' (or 'o:+:' !) */
390                         while (*++s == ':')
391                                 continue;
392                 }
393                 on_off++;
394                 c++;
395         }
396
397 #if ENABLE_LONG_OPTS || ENABLE_FEATURE_GETOPT_LONG
398         if (applet_long_options) {
399                 const char *optstr;
400                 unsigned i, count;
401
402                 count = 1;
403                 optstr = applet_long_options;
404                 while (optstr[0]) {
405                         optstr += strlen(optstr) + 3; /* skip NUL, has_arg, val */
406                         count++;
407                 }
408                 /* count == no. of longopts + 1 */
409                 long_options = alloca(count * sizeof(*long_options));
410                 memset(long_options, 0, count * sizeof(*long_options));
411                 i = 0;
412                 optstr = applet_long_options;
413                 while (--count) {
414                         long_options[i].name = optstr;
415                         optstr += strlen(optstr) + 1;
416                         long_options[i].has_arg = (unsigned char)(*optstr++);
417                         /* long_options[i].flag = NULL; */
418                         long_options[i].val = (unsigned char)(*optstr++);
419                         i++;
420                 }
421                 for (l_o = long_options; l_o->name; l_o++) {
422                         if (l_o->flag)
423                                 continue;
424                         for (on_off = complementary; on_off->opt_char; on_off++)
425                                 if (on_off->opt_char == l_o->val)
426                                         goto next_long;
427                         if (c >= 32)
428                                 break;
429                         on_off->opt_char = l_o->val;
430                         on_off->switch_on = (1U << c);
431                         if (l_o->has_arg != no_argument)
432                                 on_off->optarg = va_arg(p, void **);
433                         c++;
434  next_long: ;
435                 }
436                 /* Make it unnecessary to clear applet_long_options
437                  * by hand after each call to getopt32
438                  */
439                 applet_long_options = NULL;
440         }
441 #endif /* ENABLE_LONG_OPTS || ENABLE_FEATURE_GETOPT_LONG */
442
443         for (s = (const unsigned char *)opt_complementary; s && *s; s++) {
444                 t_complementary *pair;
445                 unsigned *pair_switch;
446
447                 if (*s == ':')
448                         continue;
449                 c = s[1];
450                 if (*s == '?') {
451                         if (c < '0' || c > '9') {
452                                 spec_flgs |= SHOW_USAGE_IF_ERROR;
453                         } else {
454                                 max_arg = c - '0';
455                                 s++;
456                         }
457                         continue;
458                 }
459                 if (*s == '-') {
460                         if (c >= '0' && c <= '9') {
461                                 min_arg = c - '0';
462                                 s++;
463                         }
464                         continue;
465                 }
466                 if (*s == '=') {
467                         min_arg = max_arg = c - '0';
468                         s++;
469                         continue;
470                 }
471                 for (on_off = complementary; on_off->opt_char; on_off++)
472                         if (on_off->opt_char == *s)
473                                 goto found_opt;
474                 /* Without this, diagnostic of such bugs is not easy */
475                 bb_error_msg_and_die("NO OPT %c!", *s);
476  found_opt:
477                 if (c == ':' && s[2] == ':') {
478                         on_off->param_type = PARAM_LIST;
479                         continue;
480                 }
481                 if (c == '+' && (s[2] == ':' || s[2] == '\0')) {
482                         on_off->param_type = PARAM_INT;
483                         s++;
484                         continue;
485                 }
486                 if (c == ':' || c == '\0') {
487                         requires |= on_off->switch_on;
488                         continue;
489                 }
490                 if (c == '-' && (s[2] == ':' || s[2] == '\0')) {
491                         flags |= on_off->switch_on;
492                         on_off->incongruously |= on_off->switch_on;
493                         s++;
494                         continue;
495                 }
496                 if (c == *s) {
497                         on_off->counter = va_arg(p, int *);
498                         s++;
499                 }
500                 pair = on_off;
501                 pair_switch = &pair->switch_on;
502                 for (s++; *s && *s != ':'; s++) {
503                         if (*s == '?') {
504                                 pair_switch = &pair->requires;
505                         } else if (*s == '-') {
506                                 if (pair_switch == &pair->switch_off)
507                                         pair_switch = &pair->incongruously;
508                                 else
509                                         pair_switch = &pair->switch_off;
510                         } else {
511                                 for (on_off = complementary; on_off->opt_char; on_off++)
512                                         if (on_off->opt_char == *s) {
513                                                 *pair_switch |= on_off->switch_on;
514                                                 break;
515                                         }
516                         }
517                 }
518                 s--;
519         }
520         opt_complementary = NULL;
521         va_end(p);
522
523         /* In case getopt32 was already called:
524          * reset the libc getopt() function, which keeps internal state.
525          * run_nofork_applet() does this, but we might end up here
526          * also via gunzip_main() -> gzip_main(). Play safe.
527          */
528         GETOPT_RESET();
529
530         /* Note: just "getopt() <= 0" will not work well for
531          * "fake" short options, like this one:
532          * wget $'-\203' "Test: test" http://kernel.org/
533          * (supposed to act as --header, but doesn't) */
534 #if ENABLE_LONG_OPTS || ENABLE_FEATURE_GETOPT_LONG
535         while ((c = getopt_long(argc, argv, applet_opts,
536                         long_options, NULL)) != -1) {
537 #else
538         while ((c = getopt(argc, argv, applet_opts)) != -1) {
539 #endif
540                 /* getopt prints "option requires an argument -- X"
541                  * and returns '?' if an option has no arg, but one is reqd */
542                 c &= 0xff; /* fight libc's sign extension */
543                 for (on_off = complementary; on_off->opt_char != c; on_off++) {
544                         /* c can be NUL if long opt has non-NULL ->flag,
545                          * but we construct long opts so that flag
546                          * is always NULL (see above) */
547                         if (on_off->opt_char == '\0' /* && c != '\0' */) {
548                                 /* c is probably '?' - "bad option" */
549                                 goto error;
550                         }
551                 }
552                 if (flags & on_off->incongruously)
553                         goto error;
554                 trigger = on_off->switch_on & on_off->switch_off;
555                 flags &= ~(on_off->switch_off ^ trigger);
556                 flags |= on_off->switch_on ^ trigger;
557                 flags ^= trigger;
558                 if (on_off->counter)
559                         (*(on_off->counter))++;
560                 if (optarg) {
561                         if (on_off->param_type == PARAM_LIST) {
562                                 llist_add_to_end((llist_t **)(on_off->optarg), optarg);
563                         } else if (on_off->param_type == PARAM_INT) {
564 //TODO: xatoi_positive indirectly pulls in printf machinery
565                                 *(unsigned*)(on_off->optarg) = xatoi_positive(optarg);
566                         } else if (on_off->optarg) {
567                                 *(char **)(on_off->optarg) = optarg;
568                         }
569                 }
570         }
571
572         /* check depending requires for given options */
573         for (on_off = complementary; on_off->opt_char; on_off++) {
574                 if (on_off->requires
575                  && (flags & on_off->switch_on)
576                  && (flags & on_off->requires) == 0
577                 ) {
578                         goto error;
579                 }
580         }
581         if (requires && (flags & requires) == 0)
582                 goto error;
583         argc -= optind;
584         if (argc < min_arg || (max_arg >= 0 && argc > max_arg))
585                 goto error;
586
587         option_mask32 = flags;
588         return flags;
589
590  error:
591         if (first_char != '!')
592                 bb_show_usage();
593         return (int32_t)-1;
594 }