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