use NULL value in load_path_suffix to NOT load any files
[oweals/gnunet.git] / src / util / getopt.c
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, 93, 94, 95, 96, 97
7      Free Software Foundation, Inc.
8
9    NOTE: The canonical source of this file is maintained with the GNU C Library.
10    Bugs can be reported to bug-glibc@prep.ai.mit.edu.
11
12    This program is free software; you can redistribute it and/or modify it
13    under the terms of the GNU General Public License as published by the
14    Free Software Foundation; either version 3, or (at your option) any
15    later version.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21
22    You should have received a copy of the GNU General Public License
23    along with this program; if not, write to the Free Software
24    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
25    USA.
26
27
28    This code was heavily modified for GNUnet.
29    Copyright (C) 2006, 2017 Christian Grothoff
30  */
31
32 /**
33  * @file util/getopt.c
34  * @brief GNU style option parsing
35  *
36  * TODO: get rid of statics (make reentrant) and
37  * replace main GNU getopt parser with one that
38  * actually fits our API.
39  */
40 #include "platform.h"
41 #include "gnunet_util_lib.h"
42
43 #ifdef VMS
44 #include <unixlib.h>
45 #if HAVE_STRING_H - 0
46 #include <string.h>
47 #endif
48 #endif
49
50 #define LOG(kind, ...) GNUNET_log_from (kind, "util-getopt", __VA_ARGS__)
51
52 #define LOG_STRERROR(kind, syscall) \
53   GNUNET_log_from_strerror (kind, "util-getopt", syscall)
54
55 #ifndef _
56 /* This is for other GNU distributions with internationalized messages.
57    When compiling libc, the _ macro is predefined.  */
58 #ifdef HAVE_LIBINTL_H
59 #include <libintl.h>
60 #define _(msgid) gettext (msgid)
61 #else
62 #define _(msgid) (msgid)
63 #endif
64 #endif
65
66 /* Describe the long-named options requested by the application.
67    The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
68    of `struct GNoption' terminated by an element containing a name which is
69    zero.
70
71    The field `has_arg' is:
72    no_argument          (or 0) if the option does not take an argument,
73    required_argument  (or 1) if the option requires an argument,
74    optional_argument   (or 2) if the option takes an optional argument.
75
76    If the field `flag' is not NULL, it points to a variable that is set
77    to the value given in the field `val' when the option is found, but
78    left unchanged if the option is not found.
79
80    To have a long-named option do something other than set an `int' to
81    a compiled-in constant, such as set a value from `GNoptarg', set the
82    option's `flag' field to zero and its `val' field to a nonzero
83    value (the equivalent single-letter option character, if there is
84    one).  For long options that have a zero `flag' field, `getopt'
85    returns the contents of the `val' field.  */
86
87 struct GNoption
88 {
89   const char *name;
90   /* has_arg can't be an enum because some compilers complain about
91    * type mismatches in all the code that assumes it is an int.  */
92   int has_arg;
93   int *flag;
94   int val;
95 };
96
97
98 /* This version of `getopt' appears to the caller like standard Unix `getopt'
99    but it behaves differently for the user, since it allows the user
100    to intersperse the options with the other arguments.
101
102    As `getopt' works, it permutes the elements of ARGV so that,
103    when it is done, all the options precede everything else.  Thus
104    all application programs are extended to handle flexible argument order.
105
106    Setting the environment variable POSIXLY_CORRECT disables permutation.
107    Then the behavior is completely standard.
108
109    GNU application programs can use a third alternative mode in which
110    they can distinguish the relative order of options and other arguments.  */
111
112 /* For communication from `getopt' to the caller.
113    When `getopt' finds an option that takes an argument,
114    the argument value is returned here.
115    Also, when `ordering' is RETURN_IN_ORDER,
116    each non-option ARGV-element is returned here.  */
117
118 static char *GNoptarg = NULL;
119
120 /* Index in ARGV of the next element to be scanned.
121    This is used for communication to and from the caller
122    and for communication between successive calls to `getopt'.
123
124    On entry to `getopt', zero means this is the first call; initialize.
125
126    When `getopt' returns -1, this is the index of the first of the
127    non-option elements that the caller should itself scan.
128
129    Otherwise, `GNoptind' communicates from one call to the next
130    how much of ARGV has been scanned so far.  */
131
132 /* 1003.2 says this must be 1 before any call.  */
133 static int GNoptind = 1;
134
135 /* The next char to be scanned in the option-element
136    in which the last option character we returned was found.
137    This allows us to pick up the scan where we left off.
138
139    If this is zero, or a null string, it means resume the scan
140    by advancing to the next ARGV-element.  */
141
142 static char *nextchar;
143
144
145 /* Describe how to deal with options that follow non-option ARGV-elements.
146
147    If the caller did not specify anything,
148    the default is REQUIRE_ORDER if the environment variable
149    POSIXLY_CORRECT is defined, PERMUTE otherwise.
150
151    REQUIRE_ORDER means don't recognize them as options;
152    stop option processing when the first non-option is seen.
153    This is what Unix does.
154    This mode of operation is selected by either setting the environment
155    variable POSIXLY_CORRECT, or using `+' as the first character
156    of the list of option characters.
157
158    PERMUTE is the default.  We GNUNET_CRYPTO_random_permute the contents of ARGV as we scan,
159    so that eventually all the non-options are at the end.  This allows options
160    to be given in any order, even with programs that were not written to
161    expect this.
162
163    RETURN_IN_ORDER is an option available to programs that were written
164    to expect GNoptions and other ARGV-elements in any order and that care about
165    the ordering of the two.  We describe each non-option ARGV-element
166    as if it were the argument of an option with character code 1.
167    Using `-' as the first character of the list of option characters
168    selects this mode of operation.
169
170    The special argument `--' forces an end of option-scanning regardless
171    of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
172    `--' can cause `getopt' to return -1 with `GNoptind' != ARGC.  */
173
174 static enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering;
175
176 /* Value of POSIXLY_CORRECT environment variable.  */
177 static char *posixly_correct;
178
179 #ifdef __GNU_LIBRARY__
180 /* We want to avoid inclusion of string.h with non-GNU libraries
181    because there are many ways it can cause trouble.
182    On some systems, it contains special magic macros that don't work
183    in GCC.  */
184 #include <string.h>
185 #define my_index strchr
186 #else
187
188 /* Avoid depending on library functions or files
189    whose names are inconsistent.  */
190
191 char *
192 getenv ();
193
194 static char *
195 my_index (const char *str, int chr)
196 {
197   while (*str)
198   {
199     if (*str == chr)
200       return (char *) str;
201     str++;
202   }
203   return 0;
204 }
205
206
207 /* If using GCC, we can safely declare strlen this way.
208    If not using GCC, it is ok not to declare it.  */
209 #ifdef __GNUC__
210 /* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
211    That was relevant to code that was here before.  */
212 #if ! defined(__STDC__) || ! __STDC__
213 /* gcc with -traditional declares the built-in strlen to return int,
214    and has done so at least since version 2.4.5. -- rms.  */
215 extern int
216 strlen (const char *);
217
218 #endif /* not __STDC__ */
219 #endif /* __GNUC__ */
220
221 #endif /* not __GNU_LIBRARY__ */
222
223 /* Handle permutation of arguments.  */
224
225 /* Describe the part of ARGV that contains non-options that have
226    been skipped.  `first_nonopt' is the index in ARGV of the first of them;
227    `last_nonopt' is the index after the last of them.  */
228
229 static int first_nonopt;
230 static int last_nonopt;
231
232 #define SWAP_FLAGS(ch1, ch2)
233
234 /* Exchange two adjacent subsequences of ARGV.
235    One subsequence is elements [first_nonopt,last_nonopt)
236    which contains all the non-options that have been skipped so far.
237    The other is elements [last_nonopt,GNoptind), which contains all
238    the options processed since those non-options were skipped.
239
240    `first_nonopt' and `last_nonopt' are relocated so that they describe
241    the new indices of the non-options in ARGV after they are moved.  */
242
243 #if defined(__STDC__) && __STDC__
244 static void
245 exchange (char **);
246
247 #endif
248
249 static void
250 exchange (char **argv)
251 {
252   int bottom = first_nonopt;
253   int middle = last_nonopt;
254   int top = GNoptind;
255   char *tem;
256
257   /* Exchange the shorter segment with the far end of the longer segment.
258    * That puts the shorter segment into the right place.
259    * It leaves the longer segment in the right place overall,
260    * but it consists of two parts that need to be swapped next.  */
261
262   while (top > middle && middle > bottom)
263   {
264     if (top - middle > middle - bottom)
265     {
266       /* Bottom segment is the short one.  */
267       int len = middle - bottom;
268       register int i;
269
270       /* Swap it with the top part of the top segment.  */
271       for (i = 0; i < len; i++)
272       {
273         tem = argv[bottom + i];
274         argv[bottom + i] = argv[top - (middle - bottom) + i];
275         argv[top - (middle - bottom) + i] = tem;
276         SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
277       }
278       /* Exclude the moved bottom segment from further swapping.  */
279       top -= len;
280     }
281     else
282     {
283       /* Top segment is the short one.  */
284       int len = top - middle;
285       register int i;
286
287       /* Swap it with the bottom part of the bottom segment.  */
288       for (i = 0; i < len; i++)
289       {
290         tem = argv[bottom + i];
291         argv[bottom + i] = argv[middle + i];
292         argv[middle + i] = tem;
293         SWAP_FLAGS (bottom + i, middle + i);
294       }
295       /* Exclude the moved top segment from further swapping.  */
296       bottom += len;
297     }
298   }
299
300   /* Update records for the slots the non-options now occupy.  */
301
302   first_nonopt += (GNoptind - last_nonopt);
303   last_nonopt = GNoptind;
304 }
305
306
307 /* Initialize the internal data when the first call is made.  */
308
309 #if defined(__STDC__) && __STDC__
310 static const char *
311 _getopt_initialize (int, char *const *, const char *);
312
313 #endif
314 static const char *
315 _getopt_initialize (int argc, char *const *argv, const char *optstring)
316 {
317   /* Start processing options with ARGV-element 1 (since ARGV-element 0
318    * is the program name); the sequence of previously skipped
319    * non-option ARGV-elements is empty.  */
320
321   first_nonopt = last_nonopt = GNoptind;
322
323   nextchar = NULL;
324
325   posixly_correct = getenv ("POSIXLY_CORRECT");
326
327   /* Determine how to handle the ordering of options and nonoptions.  */
328
329   if (optstring[0] == '-')
330   {
331     ordering = RETURN_IN_ORDER;
332     ++optstring;
333   }
334   else if (optstring[0] == '+')
335   {
336     ordering = REQUIRE_ORDER;
337     ++optstring;
338   }
339   else if (posixly_correct != NULL)
340     ordering = REQUIRE_ORDER;
341   else
342     ordering = PERMUTE;
343
344   return optstring;
345 }
346
347
348 /* Scan elements of ARGV (whose length is ARGC) for option characters
349    given in OPTSTRING.
350
351    If an element of ARGV starts with '-', and is not exactly "-" or "--",
352    then it is an option element.  The characters of this element
353    (aside from the initial '-') are option characters.  If `getopt'
354    is called repeatedly, it returns successively each of the option characters
355    from each of the option elements.
356
357    If `getopt' finds another option character, it returns that character,
358    updating `GNoptind' and `nextchar' so that the next call to `getopt' can
359    resume the scan with the following option character or ARGV-element.
360
361    If there are no more option characters, `getopt' returns -1.
362    Then `GNoptind' is the index in ARGV of the first ARGV-element
363    that is not an option.  (The ARGV-elements have been permuted
364    so that those that are not options now come last.)
365
366    OPTSTRING is a string containing the legitimate option characters.
367    If an option character is seen that is not listed in OPTSTRING,
368    return '?' after printing an error message.  If you set `GNopterr' to
369    zero, the error message is suppressed but we still return '?'.
370
371    If a char in OPTSTRING is followed by a colon, that means it wants an arg,
372    so the following text in the same ARGV-element, or the text of the following
373    ARGV-element, is returned in `GNoptarg'.  Two colons mean an option that
374    wants an optional arg; if there is text in the current ARGV-element,
375    it is returned in `GNoptarg', otherwise `GNoptarg' is set to zero.
376
377    If OPTSTRING starts with `-' or `+', it requests different methods of
378    handling the non-option ARGV-elements.
379    See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
380
381    Long-named options begin with `--' instead of `-'.
382    Their names may be abbreviated as long as the abbreviation is unique
383    or is an exact match for some defined option.  If they have an
384    argument, it follows the option name in the same ARGV-element, separated
385    from the option name by a `=', or else the in next ARGV-element.
386    When `getopt' finds a long-named option, it returns 0 if that option's
387    `flag' field is nonzero, the value of the option's `val' field
388    if the `flag' field is zero.
389
390    The elements of ARGV aren't really const, because we GNUNET_CRYPTO_random_permute them.
391    But we pretend they're const in the prototype to be compatible
392    with other systems.
393
394    LONGOPTS is a vector of `struct GNoption' terminated by an
395    element containing a name which is zero.
396
397    LONGIND returns the index in LONGOPT of the long-named option found.
398    It is only valid when a long-named option has been found by the most
399    recent call.
400
401    If LONG_ONLY is nonzero, '-' as well as '--' can introduce
402    long-named options.  */
403
404 static int
405 GN_getopt_internal (int argc,
406                     char *const *argv,
407                     const char *optstring,
408                     const struct GNoption *longopts,
409                     int *longind,
410                     int long_only)
411 {
412   static int __getopt_initialized = 0;
413   static int GNopterr = 1;
414
415   GNoptarg = NULL;
416
417   if ((GNoptind == 0) || ! __getopt_initialized)
418   {
419     if (GNoptind == 0)
420       GNoptind = 1;   /* Don't scan ARGV[0], the program name.  */
421     optstring = _getopt_initialize (argc, argv, optstring);
422     __getopt_initialized = 1;
423   }
424
425   /* Test whether ARGV[GNoptind] points to a non-option argument.
426    * Either it does not have option syntax, or there is an environment flag
427    * from the shell indicating it is not an option.  The later information
428    * is only used when the used in the GNU libc.  */
429 #define NONOPTION_P (argv[GNoptind][0] != '-' || argv[GNoptind][1] == '\0')
430
431   if ((nextchar == NULL) || (*nextchar == '\0'))
432   {
433     /* Advance to the next ARGV-element.  */
434
435     /* Give FIRST_NONOPT & LAST_NONOPT rational values if GNoptind has been
436     * moved back by the user (who may also have changed the arguments).  */
437     if (last_nonopt > GNoptind)
438       last_nonopt = GNoptind;
439     if (first_nonopt > GNoptind)
440       first_nonopt = GNoptind;
441
442     if (ordering == PERMUTE)
443     {
444       /* If we have just processed some options following some non-options,
445        * exchange them so that the options come first.  */
446
447       if ((first_nonopt != last_nonopt) && (last_nonopt != GNoptind) )
448         exchange ((char **) argv);
449       else if (last_nonopt != GNoptind)
450         first_nonopt = GNoptind;
451
452       /* Skip any additional non-options
453        * and extend the range of non-options previously skipped.  */
454
455       while (GNoptind < argc && NONOPTION_P)
456         GNoptind++;
457       last_nonopt = GNoptind;
458     }
459
460     /* The special ARGV-element `--' means premature end of options.
461      * Skip it like a null option,
462      * then exchange with previous non-options as if it were an option,
463      * then skip everything else like a non-option.  */
464     if ((GNoptind != argc) && ! strcmp (argv[GNoptind], "--"))
465     {
466       GNoptind++;
467
468       if ((first_nonopt != last_nonopt) && (last_nonopt != GNoptind) )
469         exchange ((char **) argv);
470       else if (first_nonopt == last_nonopt)
471         first_nonopt = GNoptind;
472       last_nonopt = argc;
473
474       GNoptind = argc;
475     }
476
477     /* If we have done all the ARGV-elements, stop the scan
478      * and back over any non-options that we skipped and permuted.  */
479
480     if (GNoptind == argc)
481     {
482       /* Set the next-arg-index to point at the non-options
483        * that we previously skipped, so the caller will digest them.  */
484       if (first_nonopt != last_nonopt)
485         GNoptind = first_nonopt;
486       return -1;
487     }
488
489     /* If we have come to a non-option and did not permute it,
490      * either stop the scan or describe it to the caller and pass it by.  */
491
492     if (NONOPTION_P)
493     {
494       if (ordering == REQUIRE_ORDER)
495         return -1;
496       GNoptarg = argv[GNoptind++];
497       return 1;
498     }
499
500     /* We have found another option-ARGV-element.
501      * Skip the initial punctuation.  */
502
503     nextchar =
504       (argv[GNoptind] + 1 + (longopts != NULL && argv[GNoptind][1] == '-'));
505   }
506
507   /* Decode the current option-ARGV-element.  */
508
509   /* Check whether the ARGV-element is a long option.
510    *
511    * If long_only and the ARGV-element has the form "-f", where f is
512    * a valid short option, don't consider it an abbreviated form of
513    * a long option that starts with f.  Otherwise there would be no
514    * way to give the -f short option.
515    *
516    * On the other hand, if there's a long option "fubar" and
517    * the ARGV-element is "-fu", do consider that an abbreviation of
518    * the long option, just like "--fu", and not "-f" with arg "u".
519    *
520    * This distinction seems to be the most useful approach.  */if ((longopts != NULL) &&
521       ((argv[GNoptind][1] == '-') ||
522        (long_only &&
523         (argv[GNoptind][2] || ! my_index (optstring, argv[GNoptind][1])))))
524   {
525     char *nameend;
526     const struct GNoption *p;
527     const struct GNoption *pfound = NULL;
528     int exact = 0;
529     int ambig = 0;
530     int indfound = -1;
531     int option_index;
532
533     for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
534       /* Do nothing.  */;
535
536     /* Test all long options for either exact match
537      * or abbreviated matches.  */
538     for (p = longopts, option_index = 0; p->name; p++, option_index++)
539       if (! strncmp (p->name, nextchar, nameend - nextchar))
540       {
541         if ((unsigned int) (nameend - nextchar) ==
542             (unsigned int) strlen (p->name))
543         {
544           /* Exact match found.  */
545           pfound = p;
546           indfound = option_index;
547           exact = 1;
548           break;
549         }
550         else if (pfound == NULL)
551         {
552           /* First nonexact match found.  */
553           pfound = p;
554           indfound = option_index;
555         }
556         else
557           /* Second or later nonexact match found.  */
558           ambig = 1;
559       }
560
561     if (ambig && ! exact)
562     {
563       if (GNopterr)
564         fprintf (stderr,
565                  _ ("%s: option `%s' is ambiguous\n"),
566                  argv[0],
567                  argv[GNoptind]);
568       nextchar += strlen (nextchar);
569       GNoptind++;
570       return '?';
571     }
572
573     if (pfound != NULL)
574     {
575       option_index = indfound;
576       GNoptind++;
577       if (*nameend)
578       {
579         /* Don't test has_arg with >, because some C compilers don't
580          * allow it to be used on enums.  */
581         if (pfound->has_arg)
582           GNoptarg = nameend + 1;
583         else
584         {
585           if (GNopterr)
586           {
587             if (argv[GNoptind - 1][1] == '-')
588               /* --option */
589               fprintf (stderr,
590                        _ ("%s: option `--%s' does not allow an argument\n"),
591                        argv[0],
592                        pfound->name);
593             else
594               /* +option or -option */
595               fprintf (stderr,
596                        _ ("%s: option `%c%s' does not allow an argument\n"),
597                        argv[0],
598                        argv[GNoptind - 1][0],
599                        pfound->name);
600           }
601           nextchar += strlen (nextchar);
602           return '?';
603         }
604       }
605       else if (pfound->has_arg == 1)
606       {
607         if (GNoptind < argc)
608         {
609           GNoptarg = argv[GNoptind++];
610         }
611         else
612         {
613           if (GNopterr)
614           {
615             fprintf (stderr,
616                      _ ("%s: option `%s' requires an argument\n"),
617                      argv[0],
618                      argv[GNoptind - 1]);
619           }
620           nextchar += strlen (nextchar);
621           return (optstring[0] == ':') ? ':' : '?';
622         }
623       }
624       nextchar += strlen (nextchar);
625       if (longind != NULL)
626         *longind = option_index;
627       if (pfound->flag)
628       {
629         *(pfound->flag) = pfound->val;
630         return 0;
631       }
632       return pfound->val;
633     }
634
635     /* Can't find it as a long option.  If this is not getopt_long_only,
636      * or the option starts with '--' or is not a valid short
637      * option, then it's an error.
638      * Otherwise interpret it as a short option.  */
639     if (! long_only || (argv[GNoptind][1] == '-') ||
640         (my_index (optstring, *nextchar) == NULL) )
641     {
642       if (GNopterr)
643       {
644         if (argv[GNoptind][1] == '-')
645           /* --option */
646           fprintf (stderr,
647                    _ ("%s: unrecognized option `--%s'\n"),
648                    argv[0],
649                    nextchar);
650         else
651           /* +option or -option */
652           fprintf (stderr,
653                    _ ("%s: unrecognized option `%c%s'\n"),
654                    argv[0],
655                    argv[GNoptind][0],
656                    nextchar);
657       }
658       nextchar = (char *) "";
659       GNoptind++;
660       return '?';
661     }
662   }
663
664   /* Look at and handle the next short option-character.  */
665
666   {
667     char c = *nextchar++;
668     char *temp = my_index (optstring, c);
669
670     /* Increment `GNoptind' when we start to process its last character.  */
671     if (*nextchar == '\0')
672       ++GNoptind;
673
674     if ((temp == NULL) || (c == ':'))
675     {
676       if (GNopterr)
677       {
678         if (posixly_correct)
679           /* 1003.2 specifies the format of this message.  */
680           fprintf (stderr, _ ("%s: illegal option -- %c\n"), argv[0], c);
681         else
682           fprintf (stderr, _ ("%s: invalid option -- %c\n"), argv[0], c);
683       }
684       return '?';
685     }
686     /* Convenience. Treat POSIX -W foo same as long option --foo */
687     if ((temp[0] == 'W') && (temp[1] == ';'))
688     {
689       char *nameend;
690       const struct GNoption *p;
691       const struct GNoption *pfound = NULL;
692       int exact = 0;
693       int ambig = 0;
694       int indfound = 0;
695       int option_index;
696
697       /* This is an option that requires an argument.  */
698       if (*nextchar != '\0')
699       {
700         GNoptarg = nextchar;
701         /* If we end this ARGV-element by taking the rest as an arg,
702          * we must advance to the next element now.  */
703         GNoptind++;
704       }
705       else if (GNoptind == argc)
706       {
707         if (GNopterr)
708         {
709           /* 1003.2 specifies the format of this message.  */
710           fprintf (stderr,
711                    _ ("%s: option requires an argument -- %c\n"),
712                    argv[0],
713                    c);
714         }
715         if (optstring[0] == ':')
716           c = ':';
717         else
718           c = '?';
719         return c;
720       }
721       else
722         /* We already incremented `GNoptind' once;
723          * increment it again when taking next ARGV-elt as argument.  */
724         GNoptarg = argv[GNoptind++];
725
726       /* GNoptarg is now the argument, see if it's in the
727        * table of longopts.  */
728
729       for (nextchar = nameend = GNoptarg; *nameend && *nameend != '=';
730            nameend++)
731         /* Do nothing.  */;
732
733       /* Test all long options for either exact match
734        * or abbreviated matches.  */
735       if (longopts != NULL)
736         for (p = longopts, option_index = 0; p->name; p++, option_index++)
737           if (! strncmp (p->name, nextchar, nameend - nextchar))
738           {
739             if ((unsigned int) (nameend - nextchar) == strlen (p->name))
740             {
741               /* Exact match found.  */
742               pfound = p;
743               indfound = option_index;
744               exact = 1;
745               break;
746             }
747             else if (pfound == NULL)
748             {
749               /* First nonexact match found.  */
750               pfound = p;
751               indfound = option_index;
752             }
753             else
754               /* Second or later nonexact match found.  */
755               ambig = 1;
756           }
757       if (ambig && ! exact)
758       {
759         if (GNopterr)
760           fprintf (stderr,
761                    _ ("%s: option `-W %s' is ambiguous\n"),
762                    argv[0],
763                    argv[GNoptind]);
764         nextchar += strlen (nextchar);
765         GNoptind++;
766         return '?';
767       }
768       if (pfound != NULL)
769       {
770         option_index = indfound;
771         if (*nameend)
772         {
773           /* Don't test has_arg with >, because some C compilers don't
774            * allow it to be used on enums.  */
775           if (pfound->has_arg)
776             GNoptarg = nameend + 1;
777           else
778           {
779             if (GNopterr)
780               fprintf (stderr,
781                        _ ("%s: option `-W %s' does not allow an argument\n"),
782                        argv[0],
783                        pfound->name);
784
785             nextchar += strlen (nextchar);
786             return '?';
787           }
788         }
789         else if (pfound->has_arg == 1)
790         {
791           if (GNoptind < argc)
792             GNoptarg = argv[GNoptind++];
793           else
794           {
795             if (GNopterr)
796               fprintf (stderr,
797                        _ ("%s: option `%s' requires an argument\n"),
798                        argv[0],
799                        argv[GNoptind - 1]);
800             nextchar += strlen (nextchar);
801             return optstring[0] == ':' ? ':' : '?';
802           }
803         }
804         nextchar += strlen (nextchar);
805         if (longind != NULL)
806           *longind = option_index;
807         if (pfound->flag)
808         {
809           *(pfound->flag) = pfound->val;
810           return 0;
811         }
812         return pfound->val;
813       }
814       nextchar = NULL;
815       return 'W';   /* Let the application handle it.   */
816     }
817     if (temp[1] == ':')
818     {
819       if (temp[2] == ':')
820       {
821         /* This is an option that accepts an argument optionally.  */
822         if (*nextchar != '\0')
823         {
824           GNoptarg = nextchar;
825           GNoptind++;
826         }
827         else
828           GNoptarg = NULL;
829         nextchar = NULL;
830       }
831       else
832       {
833         /* This is an option that requires an argument.  */
834         if (*nextchar != '\0')
835         {
836           GNoptarg = nextchar;
837           /* If we end this ARGV-element by taking the rest as an arg,
838            * we must advance to the next element now.  */
839           GNoptind++;
840         }
841         else if (GNoptind == argc)
842         {
843           if (GNopterr)
844           {
845             /* 1003.2 specifies the format of this message.  */
846             fprintf (stderr,
847                      _ ("%s: option requires an argument -- %c\n"),
848                      argv[0],
849                      c);
850           }
851           if (optstring[0] == ':')
852             c = ':';
853           else
854             c = '?';
855         }
856         else
857           /* We already incremented `GNoptind' once;
858            * increment it again when taking next ARGV-elt as argument.  */
859           GNoptarg = argv[GNoptind++];
860         nextchar = NULL;
861       }
862     }
863     return c;
864   }
865 }
866
867
868 static int
869 GNgetopt_long (int argc,
870                char *const *argv,
871                const char *options,
872                const struct GNoption *long_options,
873                int *opt_index)
874 {
875   return GN_getopt_internal (argc, argv, options, long_options, opt_index, 0);
876 }
877
878
879 /* ******************** now the GNUnet specific modifications... ********************* */
880
881 /**
882  * Parse the command line.
883  *
884  * @param binaryOptions Name of application with option summary
885  * @param allOptions defined options and handlers
886  * @param argc number of arguments
887  * @param argv actual arguments
888  * @return index into argv with first non-option
889  *   argument, or #GNUNET_SYSERR on error
890  */
891 int
892 GNUNET_GETOPT_run (const char *binaryOptions,
893                    const struct GNUNET_GETOPT_CommandLineOption *allOptions,
894                    unsigned int argc,
895                    char *const *argv)
896 {
897   struct GNoption *long_options;
898   struct GNUNET_GETOPT_CommandLineProcessorContext clpc;
899   int count;
900   char *shorts;
901   int spos;
902   int cont;
903   uint8_t *seen;
904   unsigned int optmatch = 0;
905   const char *have_exclusive = NULL;
906
907   GNUNET_assert (argc > 0);
908   GNoptind = 0;
909   clpc.binaryName = argv[0];
910   clpc.binaryOptions = binaryOptions;
911   clpc.allOptions = allOptions;
912   clpc.argv = argv;
913   clpc.argc = argc;
914   for (count = 0; NULL != allOptions[count].name; count++)
915     ;
916
917   /* transform our option representation into the format
918      used by the GNU getopt copylib */
919   long_options = GNUNET_new_array (count + 1, struct GNoption);
920   seen = GNUNET_new_array (count, uint8_t);
921   shorts = GNUNET_malloc (count * 2 + 1);
922   spos = 0;
923   for (unsigned i = 0; i < count; i++)
924   {
925     long_options[i].name = allOptions[i].name;
926     long_options[i].has_arg = allOptions[i].require_argument;
927     long_options[i].flag = NULL;
928     long_options[i].val = allOptions[i].shortName;
929     shorts[spos++] = allOptions[i].shortName;
930     if (allOptions[i].require_argument != 0)
931       shorts[spos++] = ':';
932   }
933   long_options[count].name = NULL;
934   long_options[count].has_arg = 0;
935   long_options[count].flag = NULL;
936   long_options[count].val = '\0';
937   shorts[spos] = '\0';
938   cont = GNUNET_OK;
939
940   /* main getopt loop */
941   while (1)
942   {
943     int option_index = 0;
944     unsigned int i;
945     int c;
946
947     c = GNgetopt_long (argc, argv, shorts, long_options, &option_index);
948     if (c == GNUNET_SYSERR)
949       break;   /* No more flags to process */
950
951     /* Check which of our program's options was given by the user */
952     for (i = 0; i < count; i++)
953     {
954       clpc.currentArgument = GNoptind - 1;
955       if ((char) c == allOptions[i].shortName)
956       {
957         optmatch++;
958         if (allOptions[i].option_exclusive)
959           have_exclusive = allOptions[i].name;
960         if (GNUNET_OK == cont)
961         {
962           /* parse the option using the option-specific processor */
963           cont = allOptions[i].processor (&clpc,
964                                           allOptions[i].scls,
965                                           allOptions[i].name,
966                                           GNoptarg);
967         }
968         seen[i] = 1;
969         break;
970       }
971     }
972     if (i == count)
973     {
974       fprintf (stderr, _ ("Use %s to get a list of options.\n"), "--help");
975       cont = GNUNET_SYSERR;
976     }
977   }
978   GNUNET_free (shorts);
979   GNUNET_free (long_options);
980
981   /* check that if any option that was marked as exclusive
982      is the only option that was provided */
983   if ((NULL != have_exclusive) && (optmatch > 1))
984   {
985     fprintf (stderr,
986              _ ("Option `%s' can't be used with other options.\n"),
987              have_exclusive);
988     cont = GNUNET_SYSERR;
989   }
990   if (GNUNET_YES == cont)
991   {
992     /* check that all mandatory options are present */
993     for (count = 0; NULL != allOptions[count].name; count++)
994     {
995       if ((0 == seen[count]) && (allOptions[count].option_mandatory))
996       {
997         fprintf (stderr,
998                  _ ("Missing mandatory option `%s'.\n"),
999                  allOptions[count].name);
1000         cont = GNUNET_SYSERR;
1001       }
1002     }
1003   }
1004   GNUNET_free (seen);
1005
1006   /* call cleaners, if available */
1007   for (unsigned int i = 0; NULL != allOptions[i].name; i++)
1008     if (NULL != allOptions[i].cleaner)
1009       allOptions[i].cleaner (allOptions[i].scls);
1010
1011   if (GNUNET_OK != cont)
1012     return cont;
1013   return GNoptind;
1014 }
1015
1016
1017 /* end of getopt.c */