1 /* Getopt for GNU.
2 NOTE: getopt is now part of the C library, so if you don't know what
3 "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
4 before changing it!
5
6 Copyright (C) 1987, 88, 89, 90, 91, 92, 1993
7 Free Software Foundation, Inc.
8
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
12 later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
22
23
24 #include "common.h"
25
26
27 /* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a
28 long-named option. Because this is not POSIX.2 compliant, it is
29 being phased out. */
30 /* #define GETOPT_COMPAT */
31 #undef GETOPT_COMPAT
32
33 /* This version of `getopt' appears to the caller like standard Unix `getopt'
34 but it behaves differently for the user, since it allows the user
35 to intersperse the options with the other arguments.
36
37 As `getopt' works, it permutes the elements of ARGV so that,
38 when it is done, all the options precede everything else. Thus
39 all application programs are extended to handle flexible argument order.
40
41 Setting the environment variable POSIXLY_CORRECT disables permutation.
42 Then the behavior is completely standard.
43
44 GNU application programs can use a third alternative mode in which
45 they can distinguish the relative order of options and other arguments. */
46
47 #include "zbxgetopt.h"
48
49 #undef BAD_OPTION
50
51 /* For communication from `getopt' to the caller.
52 When `getopt' finds an option that takes an argument,
53 the argument value is returned here.
54 Also, when `ordering' is RETURN_IN_ORDER,
55 each non-option ARGV-element is returned here. */
56
57 char *zbx_optarg = NULL;
58
59 /* Index in ARGV of the next element to be scanned.
60 This is used for communication to and from the caller
61 and for communication between successive calls to `getopt'.
62
63 On entry to `getopt', zero means this is the first call; initialize.
64
65 When `getopt' returns EOF, this is the index of the first of the
66 non-option elements that the caller should itself scan.
67
68 Otherwise, `zbx_optind' communicates from one call to the next
69 how much of ARGV has been scanned so far. */
70
71 /* XXX 1003.2 says this must be 1 before any call. */
72 int zbx_optind = 0;
73
74 /* The next char to be scanned in the option-element
75 in which the last option character we returned was found.
76 This allows us to pick up the scan where we left off.
77
78 If this is zero, or a null string, it means resume the scan
79 by advancing to the next ARGV-element. */
80
81 static char *nextchar;
82
83 /* Callers store zero here to inhibit the error message
84 for unrecognized options. */
85
86 int zbx_opterr = 1;
87
88 /* Set to an option character which was unrecognized.
89 This must be initialized on some systems to avoid linking in the
90 system's own getopt implementation. */
91
92 #define BAD_OPTION '\0'
93 int zbx_optopt = BAD_OPTION;
94
95 /* Describe how to deal with options that follow non-option ARGV-elements.
96
97 If the caller did not specify anything,
98 the default is REQUIRE_ORDER if the environment variable
99 POSIXLY_CORRECT is defined, PERMUTE otherwise.
100
101 REQUIRE_ORDER means don't recognize them as options;
102 stop option processing when the first non-option is seen.
103 This is what Unix does.
104 This mode of operation is selected by either setting the environment
105 variable POSIXLY_CORRECT, or using `+' as the first character
106 of the list of option characters.
107
108 PERMUTE is the default. We permute the contents of ARGV as we scan,
109 so that eventually all the non-options are at the end. This allows options
110 to be given in any order, even with programs that were not written to
111 expect this.
112
113 RETURN_IN_ORDER is an option available to programs that were written
114 to expect options and other ARGV-elements in any order and that care about
115 the ordering of the two. We describe each non-option ARGV-element
116 as if it were the argument of an option with character code 1.
117 Using `-' as the first character of the list of option characters
118 selects this mode of operation.
119
120 The special argument `--' forces an end of option-scanning regardless
121 of the value of `ordering'. In the case of RETURN_IN_ORDER, only
122 `--' can cause `getopt' to return EOF with `zbx_optind' != ARGC. */
123
124 static enum
125 {
126 REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
127 } ordering;
128
129 /* Handle permutation of arguments. */
130
131 /* Describe the part of ARGV that contains non-options that have
132 been skipped. `first_nonopt' is the index in ARGV of the first of them;
133 `last_nonopt' is the index after the last of them. */
134
135 static int first_nonopt;
136 static int last_nonopt;
137
138 /* Exchange two adjacent subsequences of ARGV.
139 One subsequence is elements [first_nonopt,last_nonopt)
140 which contains all the non-options that have been skipped so far.
141 The other is elements [last_nonopt,zbx_optind), which contains all
142 the options processed since those non-options were skipped.
143
144 `first_nonopt' and `last_nonopt' are relocated so that they describe
145 the new indices of the non-options in ARGV after they are moved.
146
147 To perform the swap, we first reverse the order of all elements. So
148 all options now come before all non options, but they are in the
149 wrong order. So we put back the options and non options in original
150 order by reversing them again. For example:
151 original input: a b c -x -y
152 reverse all: -y -x c b a
153 reverse options: -x -y c b a
154 reverse non options: -x -y a b c
155 */
156
157
exchange(char ** argv)158 static void exchange (char **argv)
159 {
160 char *temp; char **first, **last;
161
162 /* Reverse all the elements [first_nonopt, zbx_optind) */
163 first = &argv[first_nonopt];
164 last = &argv[zbx_optind-1];
165 while (first < last) {
166 temp = *first; *first = *last; *last = temp; first++; last--;
167 }
168 /* Put back the options in order */
169 first = &argv[first_nonopt];
170 first_nonopt += (zbx_optind - last_nonopt);
171 last = &argv[first_nonopt - 1];
172 while (first < last) {
173 temp = *first; *first = *last; *last = temp; first++; last--;
174 }
175
176 /* Put back the non options in order */
177 first = &argv[first_nonopt];
178 last_nonopt = zbx_optind;
179 last = &argv[last_nonopt-1];
180 while (first < last) {
181 temp = *first; *first = *last; *last = temp; first++; last--;
182 }
183 }
184
185 /* Scan elements of ARGV (whose length is ARGC) for option characters
186 given in OPTSTRING.
187
188 If an element of ARGV starts with '-', and is not exactly "-" or "--",
189 then it is an option element. The characters of this element
190 (aside from the initial '-') are option characters. If `getopt'
191 is called repeatedly, it returns successively each of the option characters
192 from each of the option elements.
193
194 If `getopt' finds another option character, it returns that character,
195 updating `zbx_optind' and `nextchar' so that the next call to `getopt' can
196 resume the scan with the following option character or ARGV-element.
197
198 If there are no more option characters, `getopt' returns `EOF'.
199 Then `zbx_optind' is the index in ARGV of the first ARGV-element
200 that is not an option. (The ARGV-elements have been permuted
201 so that those that are not options now come last.)
202
203 OPTSTRING is a string containing the legitimate option characters.
204 If an option character is seen that is not listed in OPTSTRING,
205 return BAD_OPTION after printing an error message. If you set `zbx_opterr' to
206 zero, the error message is suppressed but we still return BAD_OPTION.
207
208 If a char in OPTSTRING is followed by a colon, that means it wants an arg,
209 so the following text in the same ARGV-element, or the text of the following
210 ARGV-element, is returned in `zbx_optarg'. Two colons mean an option that
211 wants an optional arg; if there is text in the current ARGV-element,
212 it is returned in `zbx_optarg', otherwise `zbx_optarg' is set to zero.
213
214 If OPTSTRING starts with `-' or `+', it requests different methods of
215 handling the non-option ARGV-elements.
216 See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
217
218 Long-named options begin with `--' instead of `-'.
219 Their names may be abbreviated as long as the abbreviation is unique
220 or is an exact match for some defined option. If they have an
221 argument, it follows the option name in the same ARGV-element, separated
222 from the option name by a `=', or else the in next ARGV-element.
223 When `getopt' finds a long-named option, it returns 0 if that option's
224 `flag' field is non-zero, the value of the option's `val' field
225 if the `flag' field is zero.
226
227 LONGOPTS is a vector of `struct zbx_option' terminated by an
228 element containing a name which is zero.
229
230 LONGIND returns the index in LONGOPT of the long-named option found.
231 It is only valid when a long-named option has been found by the most
232 recent call.
233
234 If LONG_ONLY is non-zero, '-' as well as '--' can introduce
235 long-named options. */
236
zbx_getopt_internal(int argc,char ** argv,const char * optstring,const struct zbx_option * longopts,int * longind,int long_only)237 static int zbx_getopt_internal (int argc, char **argv, const char *optstring,
238 const struct zbx_option *longopts, int *longind,
239 int long_only)
240 {
241 static char empty_string[1];
242 int option_index;
243
244 if (longind != NULL)
245 *longind = -1;
246
247 zbx_optarg = 0;
248
249 /* Initialize the internal data when the first call is made.
250 Start processing options with ARGV-element 1 (since ARGV-element 0
251 is the program name); the sequence of previously skipped
252 non-option ARGV-elements is empty. */
253
254 if (zbx_optind == 0)
255 {
256 first_nonopt = last_nonopt = zbx_optind = 1;
257
258 nextchar = NULL;
259
260 /* Determine how to handle the ordering of options and nonoptions. */
261
262 if (optstring[0] == '-')
263 {
264 ordering = RETURN_IN_ORDER;
265 ++optstring;
266 }
267 else if (optstring[0] == '+')
268 {
269 ordering = REQUIRE_ORDER;
270 ++optstring;
271 }
272 #if OFF
273 else if (getenv ("POSIXLY_CORRECT") != NULL)
274 ordering = REQUIRE_ORDER;
275 #endif
276 else
277 ordering = PERMUTE;
278 }
279
280 if (nextchar == NULL || *nextchar == '\0')
281 {
282 if (ordering == PERMUTE)
283 {
284 /* If we have just processed some options following some non-options,
285 exchange them so that the options come first. */
286
287 if (first_nonopt != last_nonopt && last_nonopt != zbx_optind)
288 exchange (argv);
289 else if (last_nonopt != zbx_optind)
290 first_nonopt = zbx_optind;
291
292 /* Now skip any additional non-options
293 and extend the range of non-options previously skipped. */
294
295 while (zbx_optind < argc
296 && (argv[zbx_optind][0] != '-' || argv[zbx_optind][1] == '\0')
297 #ifdef GETOPT_COMPAT
298 && (longopts == NULL
299 || argv[zbx_optind][0] != '+' || argv[zbx_optind][1] == '\0')
300 #endif /* GETOPT_COMPAT */
301 )
302 zbx_optind++;
303 last_nonopt = zbx_optind;
304 }
305
306 /* Special ARGV-element `--' means premature end of options.
307 Skip it like a null option,
308 then exchange with previous non-options as if it were an option,
309 then skip everything else like a non-option. */
310
311 if (zbx_optind != argc && !strcmp (argv[zbx_optind], "--"))
312 {
313 zbx_optind++;
314
315 if (first_nonopt != last_nonopt && last_nonopt != zbx_optind)
316 exchange (argv);
317 else if (first_nonopt == last_nonopt)
318 first_nonopt = zbx_optind;
319 last_nonopt = argc;
320
321 zbx_optind = argc;
322 }
323
324 /* If we have done all the ARGV-elements, stop the scan
325 and back over any non-options that we skipped and permuted. */
326
327 if (zbx_optind == argc)
328 {
329 /* Set the next-arg-index to point at the non-options
330 that we previously skipped, so the caller will digest them. */
331 if (first_nonopt != last_nonopt)
332 zbx_optind = first_nonopt;
333 return EOF;
334 }
335
336 /* If we have come to a non-option and did not permute it,
337 either stop the scan or describe it to the caller and pass it by. */
338
339 if ((argv[zbx_optind][0] != '-' || argv[zbx_optind][1] == '\0')
340 #ifdef GETOPT_COMPAT
341 && (longopts == NULL
342 || argv[zbx_optind][0] != '+' || argv[zbx_optind][1] == '\0')
343 #endif /* GETOPT_COMPAT */
344 )
345 {
346 if (ordering == REQUIRE_ORDER)
347 return EOF;
348 zbx_optarg = argv[zbx_optind++];
349 return 1;
350 }
351
352 /* We have found another option-ARGV-element.
353 Start decoding its characters. */
354
355 nextchar = (argv[zbx_optind] + 1
356 + (longopts != NULL && argv[zbx_optind][1] == '-'));
357 }
358
359 if (longopts != NULL
360 && ((argv[zbx_optind][0] == '-'
361 && (argv[zbx_optind][1] == '-' || long_only))
362 #ifdef GETOPT_COMPAT
363 || argv[zbx_optind][0] == '+'
364 #endif /* GETOPT_COMPAT */
365 ))
366 {
367 const struct zbx_option *p;
368 char *s = nextchar;
369 int exact = 0;
370 int ambig = 0;
371 const struct zbx_option *pfound = NULL;
372 int indfound = 0;
373 int needexact = 0;
374
375 #if ON
376 /* allow `--option#value' because you cannot assign a '='
377 to an environment variable under DOS command.com */
378 while (*s && *s != '=' && * s != '#')
379 s++;
380 #else
381 while (*s && *s != '=')
382 s++;
383 #endif
384
385 /* Test all options for either exact match or abbreviated matches. */
386 for (p = longopts, option_index = 0; p->name;
387 p++, option_index++)
388 if (!strncmp (p->name, nextchar, (unsigned) (s - nextchar)))
389 {
390 if (p->has_arg & 0x10)
391 needexact = 1;
392 if ((unsigned) (s - nextchar) == strlen (p->name))
393 {
394 /* Exact match found. */
395 pfound = p;
396 indfound = option_index;
397 exact = 1;
398 break;
399 }
400 #if OFF /* ZBX: disable long option partial matching */
401 else if (pfound == NULL)
402 {
403 /* First nonexact match found. */
404 pfound = p;
405 indfound = option_index;
406 }
407 else
408 /* Second nonexact match found. */
409 ambig = 1;
410 #endif
411 }
412
413 /* don't allow nonexact longoptions */
414 if (needexact && !exact)
415 {
416 if (zbx_opterr)
417 zbx_error("unrecognized option `%s'", argv[zbx_optind]);
418
419 nextchar += strlen (nextchar);
420 zbx_optind++;
421 return BAD_OPTION;
422 }
423 #if OFF /* disable since ambig is always 0*/
424 if (ambig && !exact)
425 {
426 if (zbx_opterr)
427 zbx_error("option `%s' is ambiguous", argv[zbx_optind]);
428
429 nextchar += strlen (nextchar);
430 zbx_optind++;
431 return BAD_OPTION;
432 }
433 #endif
434
435 if (pfound != NULL)
436 {
437 int have_arg = (s[0] != '\0');
438 if (have_arg && (pfound->has_arg & 0xf))
439 have_arg = (s[1] != '\0');
440 option_index = indfound;
441 zbx_optind++;
442 if (have_arg)
443 {
444 /* Don't test has_arg with >, because some C compilers don't
445 allow it to be used on enums. */
446 if (pfound->has_arg & 0xf)
447 zbx_optarg = s + 1;
448 else
449 {
450 if (zbx_opterr)
451 {
452 if (argv[zbx_optind - 1][1] == '-')
453 /* --option */
454 zbx_error("option `--%s' doesn't allow an argument",pfound->name);
455 else
456 /* +option or -option */
457 zbx_error("option `%c%s' doesn't allow an argument", argv[zbx_optind - 1][0], pfound->name);
458 }
459 nextchar += strlen (nextchar);
460 return BAD_OPTION;
461 }
462 }
463 else if ((pfound->has_arg & 0xf) == 1)
464 {
465 #if OFF
466 if (zbx_optind < argc)
467 #else
468 if (zbx_optind < argc && (pfound->has_arg & 0x20) == 0)
469 #endif
470 zbx_optarg = argv[zbx_optind++];
471 else
472 {
473 if (zbx_opterr)
474 zbx_error("option `--%s%s' requires an argument",
475 pfound->name, (pfound->has_arg & 0x20) ? "=" : "");
476 nextchar += strlen (nextchar);
477 return optstring[0] == ':' ? ':' : BAD_OPTION;
478 }
479 }
480 nextchar += strlen (nextchar);
481 if (longind != NULL)
482 *longind = option_index;
483 if (pfound->flag)
484 {
485 *(pfound->flag) = pfound->val;
486 return 0;
487 }
488 return pfound->val;
489 }
490 /* Can't find it as a long option. If this is not getopt_long_only,
491 or the option starts with '--' or is not a valid short
492 option, then it's an error.
493 Otherwise interpret it as a short option. */
494 if (!long_only || argv[zbx_optind][1] == '-'
495 #ifdef GETOPT_COMPAT
496 || argv[zbx_optind][0] == '+'
497 #endif /* GETOPT_COMPAT */
498 || strchr (optstring, *nextchar) == NULL)
499 {
500 if (zbx_opterr)
501 {
502 if (argv[zbx_optind][1] == '-')
503 /* --option */
504 zbx_error("unrecognized option `--%s'", nextchar);
505 else
506 /* +option or -option */
507 zbx_error("unrecognized option `%c%s'", argv[zbx_optind][0], nextchar);
508 }
509 nextchar = empty_string;
510 zbx_optind++;
511 return BAD_OPTION;
512 }
513 (void) &ambig; /* UNUSED */
514 }
515
516 /* Look at and handle the next option-character. */
517
518 {
519 char c = *nextchar++;
520 const char *temp = strchr (optstring, c);
521
522 /* Increment `zbx_optind' when we start to process its last character. */
523 if (*nextchar == '\0')
524 ++zbx_optind;
525
526 if (temp == NULL || c == ':')
527 {
528 if (zbx_opterr)
529 {
530 #if OFF
531 if (c < 040 || c >= 0177)
532 zbx_error("unrecognized option, character code 0%o", c);
533 else
534 zbx_error("unrecognized option `-%c'", c);
535 #else
536 /* 1003.2 specifies the format of this message. */
537 zbx_error("invalid option -- %c", c);
538 #endif
539 }
540 zbx_optopt = c;
541 return BAD_OPTION;
542 }
543 if (temp[1] == ':')
544 {
545 if (temp[2] == ':')
546 {
547 /* This is an option that accepts an argument optionally. */
548 if (*nextchar != '\0')
549 {
550 zbx_optarg = nextchar;
551 zbx_optind++;
552 }
553 else
554 zbx_optarg = 0;
555 nextchar = NULL;
556 }
557 else
558 {
559 /* This is an option that requires an argument. */
560 if (*nextchar != '\0')
561 {
562 zbx_optarg = nextchar;
563 /* If we end this ARGV-element by taking the rest as an arg,
564 we must advance to the next element now. */
565 zbx_optind++;
566 }
567 else if (zbx_optind == argc)
568 {
569 if (zbx_opterr)
570 {
571 #if OFF
572 zbx_error("option `-%c' requires an argument", c);
573 #else
574 /* 1003.2 specifies the format of this message. */
575 zbx_error("option requires an argument -- %c", c);
576 #endif
577 }
578 zbx_optopt = c;
579 if (optstring[0] == ':')
580 c = ':';
581 else
582 c = BAD_OPTION;
583 }
584 else
585 /* We already incremented `zbx_optind' once;
586 increment it again when taking next ARGV-elt as argument. */
587 zbx_optarg = argv[zbx_optind++];
588 nextchar = NULL;
589 }
590 }
591 return c;
592 }
593 }
594
zbx_getopt(int argc,char ** argv,const char * optstring)595 int zbx_getopt(int argc, char **argv, const char *optstring)
596 {
597 return zbx_getopt_internal (argc, argv, optstring,
598 (const struct zbx_option *) 0,
599 (int *) 0,
600 0);
601 }
602
zbx_getopt_long(int argc,char ** argv,const char * options,const struct zbx_option * long_options,int * opt_index)603 int zbx_getopt_long(int argc, char **argv, const char *options,
604 const struct zbx_option *long_options, int *opt_index)
605 {
606 return zbx_getopt_internal (argc, argv, options, long_options, opt_index, 0);
607 }
608
609
610 #ifdef TEST2
611
612 /* Compile with -DTEST to make an executable for use in testing
613 the above definition of `getopt'. */
614
615 int
main(argc,argv)616 main (argc, argv)
617 int argc;
618 char **argv;
619 {
620 int c;
621 int digit_optind = 0;
622
623 while (1)
624 {
625 int this_option_optind = zbx_optind ? zbx_optind : 1;
626
627 c = getopt (argc, argv, "abc:d:0123456789");
628 if (c == EOF)
629 break;
630
631 switch (c)
632 {
633 case '0':
634 case '1':
635 case '2':
636 case '3':
637 case '4':
638 case '5':
639 case '6':
640 case '7':
641 case '8':
642 case '9':
643 if (digit_optind != 0 && digit_optind != this_option_optind)
644 printf ("digits occur in two different argv-elements.\n");
645 digit_optind = this_option_optind;
646 printf ("option %c\n", c);
647 break;
648
649 case 'a':
650 printf ("option a\n");
651 break;
652
653 case 'b':
654 printf ("option b\n");
655 break;
656
657 case 'c':
658 printf ("option c with value `%s'\n", zbx_optarg);
659 break;
660
661 case BAD_OPTION:
662 break;
663
664 default:
665 printf ("?? getopt returned character code 0%o ??\n", c);
666 }
667 }
668
669 if (zbx_optind < argc)
670 {
671 printf ("non-option ARGV-elements: ");
672 while (zbx_optind < argc)
673 printf ("%s ", argv[zbx_optind++]);
674 printf ("\n");
675 }
676
677 exit (0);
678 }
679
680 #endif /* TEST */
681