fix for starting problems of SUID binaries
[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 #if defined(WIN32) && ! defined(__CYGWIN32__)
56 /* It's not Unix, really.  See?  Capital letters.  */
57 #include <windows.h>
58 #define getpid() GetCurrentProcessId ()
59 #endif
60
61 #ifndef _
62 /* This is for other GNU distributions with internationalized messages.
63    When compiling libc, the _ macro is predefined.  */
64 #ifdef HAVE_LIBINTL_H
65 #include <libintl.h>
66 #define _(msgid) gettext (msgid)
67 #else
68 #define _(msgid) (msgid)
69 #endif
70 #endif
71
72 /* Describe the long-named options requested by the application.
73    The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
74    of `struct GNoption' terminated by an element containing a name which is
75    zero.
76
77    The field `has_arg' is:
78    no_argument          (or 0) if the option does not take an argument,
79    required_argument  (or 1) if the option requires an argument,
80    optional_argument   (or 2) if the option takes an optional argument.
81
82    If the field `flag' is not NULL, it points to a variable that is set
83    to the value given in the field `val' when the option is found, but
84    left unchanged if the option is not found.
85
86    To have a long-named option do something other than set an `int' to
87    a compiled-in constant, such as set a value from `GNoptarg', set the
88    option's `flag' field to zero and its `val' field to a nonzero
89    value (the equivalent single-letter option character, if there is
90    one).  For long options that have a zero `flag' field, `getopt'
91    returns the contents of the `val' field.  */
92
93 struct GNoption
94 {
95   const char *name;
96   /* has_arg can't be an enum because some compilers complain about
97    * type mismatches in all the code that assumes it is an int.  */
98   int has_arg;
99   int *flag;
100   int val;
101 };
102
103
104 /* This version of `getopt' appears to the caller like standard Unix `getopt'
105    but it behaves differently for the user, since it allows the user
106    to intersperse the options with the other arguments.
107
108    As `getopt' works, it permutes the elements of ARGV so that,
109    when it is done, all the options precede everything else.  Thus
110    all application programs are extended to handle flexible argument order.
111
112    Setting the environment variable POSIXLY_CORRECT disables permutation.
113    Then the behavior is completely standard.
114
115    GNU application programs can use a third alternative mode in which
116    they can distinguish the relative order of options and other arguments.  */
117
118 /* For communication from `getopt' to the caller.
119    When `getopt' finds an option that takes an argument,
120    the argument value is returned here.
121    Also, when `ordering' is RETURN_IN_ORDER,
122    each non-option ARGV-element is returned here.  */
123
124 static char *GNoptarg = NULL;
125
126 /* Index in ARGV of the next element to be scanned.
127    This is used for communication to and from the caller
128    and for communication between successive calls to `getopt'.
129
130    On entry to `getopt', zero means this is the first call; initialize.
131
132    When `getopt' returns -1, this is the index of the first of the
133    non-option elements that the caller should itself scan.
134
135    Otherwise, `GNoptind' communicates from one call to the next
136    how much of ARGV has been scanned so far.  */
137
138 /* 1003.2 says this must be 1 before any call.  */
139 static int GNoptind = 1;
140
141 /* The next char to be scanned in the option-element
142    in which the last option character we returned was found.
143    This allows us to pick up the scan where we left off.
144
145    If this is zero, or a null string, it means resume the scan
146    by advancing to the next ARGV-element.  */
147
148 static char *nextchar;
149
150
151 /* Describe how to deal with options that follow non-option ARGV-elements.
152
153    If the caller did not specify anything,
154    the default is REQUIRE_ORDER if the environment variable
155    POSIXLY_CORRECT is defined, PERMUTE otherwise.
156
157    REQUIRE_ORDER means don't recognize them as options;
158    stop option processing when the first non-option is seen.
159    This is what Unix does.
160    This mode of operation is selected by either setting the environment
161    variable POSIXLY_CORRECT, or using `+' as the first character
162    of the list of option characters.
163
164    PERMUTE is the default.  We GNUNET_CRYPTO_random_permute the contents of ARGV as we scan,
165    so that eventually all the non-options are at the end.  This allows options
166    to be given in any order, even with programs that were not written to
167    expect this.
168
169    RETURN_IN_ORDER is an option available to programs that were written
170    to expect GNoptions and other ARGV-elements in any order and that care about
171    the ordering of the two.  We describe each non-option ARGV-element
172    as if it were the argument of an option with character code 1.
173    Using `-' as the first character of the list of option characters
174    selects this mode of operation.
175
176    The special argument `--' forces an end of option-scanning regardless
177    of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
178    `--' can cause `getopt' to return -1 with `GNoptind' != ARGC.  */
179
180 static enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering;
181
182 /* Value of POSIXLY_CORRECT environment variable.  */
183 static char *posixly_correct;
184
185 #ifdef __GNU_LIBRARY__
186 /* We want to avoid inclusion of string.h with non-GNU libraries
187    because there are many ways it can cause trouble.
188    On some systems, it contains special magic macros that don't work
189    in GCC.  */
190 #include <string.h>
191 #define my_index strchr
192 #else
193
194 /* Avoid depending on library functions or files
195    whose names are inconsistent.  */
196
197 char *
198 getenv ();
199
200 static char *
201 my_index (const char *str, int chr)
202 {
203   while (*str)
204   {
205     if (*str == chr)
206       return (char *) str;
207     str++;
208   }
209   return 0;
210 }
211
212 /* If using GCC, we can safely declare strlen this way.
213    If not using GCC, it is ok not to declare it.  */
214 #ifdef __GNUC__
215 /* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
216    That was relevant to code that was here before.  */
217 #if ! defined(__STDC__) || ! __STDC__
218 /* gcc with -traditional declares the built-in strlen to return int,
219    and has done so at least since version 2.4.5. -- rms.  */
220 extern int
221 strlen (const char *);
222 #endif /* not __STDC__ */
223 #endif /* __GNUC__ */
224
225 #endif /* not __GNU_LIBRARY__ */
226
227 /* Handle permutation of arguments.  */
228
229 /* Describe the part of ARGV that contains non-options that have
230    been skipped.  `first_nonopt' is the index in ARGV of the first of them;
231    `last_nonopt' is the index after the last of them.  */
232
233 static int first_nonopt;
234 static int last_nonopt;
235
236 #define SWAP_FLAGS(ch1, ch2)
237
238 /* Exchange two adjacent subsequences of ARGV.
239    One subsequence is elements [first_nonopt,last_nonopt)
240    which contains all the non-options that have been skipped so far.
241    The other is elements [last_nonopt,GNoptind), which contains all
242    the options processed since those non-options were skipped.
243
244    `first_nonopt' and `last_nonopt' are relocated so that they describe
245    the new indices of the non-options in ARGV after they are moved.  */
246
247 #if defined(__STDC__) && __STDC__
248 static void
249 exchange (char **);
250 #endif
251
252 static void
253 exchange (char **argv)
254 {
255   int bottom = first_nonopt;
256   int middle = last_nonopt;
257   int top = GNoptind;
258   char *tem;
259
260   /* Exchange the shorter segment with the far end of the longer segment.
261    * That puts the shorter segment into the right place.
262    * It leaves the longer segment in the right place overall,
263    * but it consists of two parts that need to be swapped next.  */
264
265   while (top > middle && middle > bottom)
266   {
267     if (top - middle > middle - bottom)
268     {
269       /* Bottom segment is the short one.  */
270       int len = middle - bottom;
271       register int i;
272
273       /* Swap it with the top part of the top segment.  */
274       for (i = 0; i < len; i++)
275       {
276         tem = argv[bottom + i];
277         argv[bottom + i] = argv[top - (middle - bottom) + i];
278         argv[top - (middle - bottom) + i] = tem;
279         SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
280       }
281       /* Exclude the moved bottom segment from further swapping.  */
282       top -= len;
283     }
284     else
285     {
286       /* Top segment is the short one.  */
287       int len = top - middle;
288       register int i;
289
290       /* Swap it with the bottom part of the bottom segment.  */
291       for (i = 0; i < len; i++)
292       {
293         tem = argv[bottom + i];
294         argv[bottom + i] = argv[middle + i];
295         argv[middle + i] = tem;
296         SWAP_FLAGS (bottom + i, middle + i);
297       }
298       /* Exclude the moved top segment from further swapping.  */
299       bottom += len;
300     }
301   }
302
303   /* Update records for the slots the non-options now occupy.  */
304
305   first_nonopt += (GNoptind - last_nonopt);
306   last_nonopt = GNoptind;
307 }
308
309 /* Initialize the internal data when the first call is made.  */
310
311 #if defined(__STDC__) && __STDC__
312 static const char *
313 _getopt_initialize (int, char *const *, const char *);
314 #endif
315 static const char *
316 _getopt_initialize (int argc, char *const *argv, const char *optstring)
317 {
318   /* Start processing options with ARGV-element 1 (since ARGV-element 0
319    * is the program name); the sequence of previously skipped
320    * non-option ARGV-elements is empty.  */
321
322   first_nonopt = last_nonopt = GNoptind;
323
324   nextchar = NULL;
325
326   posixly_correct = getenv ("POSIXLY_CORRECT");
327
328   /* Determine how to handle the ordering of options and nonoptions.  */
329
330   if (optstring[0] == '-')
331   {
332     ordering = RETURN_IN_ORDER;
333     ++optstring;
334   }
335   else if (optstring[0] == '+')
336   {
337     ordering = REQUIRE_ORDER;
338     ++optstring;
339   }
340   else if (posixly_correct != NULL)
341     ordering = REQUIRE_ORDER;
342   else
343     ordering = PERMUTE;
344
345   return optstring;
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.  */
521
522   if (longopts != NULL &&
523       (argv[GNoptind][1] == '-' ||
524        (long_only &&
525         (argv[GNoptind][2] || ! my_index (optstring, argv[GNoptind][1])))))
526   {
527     char *nameend;
528     const struct GNoption *p;
529     const struct GNoption *pfound = NULL;
530     int exact = 0;
531     int ambig = 0;
532     int indfound = -1;
533     int option_index;
534
535     for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
536       /* Do nothing.  */;
537
538     /* Test all long options for either exact match
539      * or abbreviated matches.  */
540     for (p = longopts, option_index = 0; p->name; p++, option_index++)
541       if (! strncmp (p->name, nextchar, nameend - nextchar))
542       {
543         if ((unsigned int) (nameend - nextchar) ==
544             (unsigned int) strlen (p->name))
545         {
546           /* Exact match found.  */
547           pfound = p;
548           indfound = option_index;
549           exact = 1;
550           break;
551         }
552         else if (pfound == NULL)
553         {
554           /* First nonexact match found.  */
555           pfound = p;
556           indfound = option_index;
557         }
558         else
559           /* Second or later nonexact match found.  */
560           ambig = 1;
561       }
562
563     if (ambig && ! exact)
564     {
565       if (GNopterr)
566         FPRINTF (stderr,
567                  _ ("%s: option `%s' is ambiguous\n"),
568                  argv[0],
569                  argv[GNoptind]);
570       nextchar += strlen (nextchar);
571       GNoptind++;
572       return '?';
573     }
574
575     if (pfound != NULL)
576     {
577       option_index = indfound;
578       GNoptind++;
579       if (*nameend)
580       {
581         /* Don't test has_arg with >, because some C compilers don't
582          * allow it to be used on enums.  */
583         if (pfound->has_arg)
584           GNoptarg = nameend + 1;
585         else
586         {
587           if (GNopterr)
588           {
589             if (argv[GNoptind - 1][1] == '-')
590               /* --option */
591               FPRINTF (stderr,
592                        _ ("%s: option `--%s' does not allow an argument\n"),
593                        argv[0],
594                        pfound->name);
595             else
596               /* +option or -option */
597               FPRINTF (stderr,
598                        _ ("%s: option `%c%s' does not allow an argument\n"),
599                        argv[0],
600                        argv[GNoptind - 1][0],
601                        pfound->name);
602           }
603           nextchar += strlen (nextchar);
604           return '?';
605         }
606       }
607       else if (pfound->has_arg == 1)
608       {
609         if (GNoptind < argc)
610         {
611           GNoptarg = argv[GNoptind++];
612         }
613         else
614         {
615           if (GNopterr)
616           {
617             FPRINTF (stderr,
618                      _ ("%s: option `%s' requires an argument\n"),
619                      argv[0],
620                      argv[GNoptind - 1]);
621           }
622           nextchar += strlen (nextchar);
623           return (optstring[0] == ':') ? ':' : '?';
624         }
625       }
626       nextchar += strlen (nextchar);
627       if (longind != NULL)
628         *longind = option_index;
629       if (pfound->flag)
630       {
631         *(pfound->flag) = pfound->val;
632         return 0;
633       }
634       return pfound->val;
635     }
636
637     /* Can't find it as a long option.  If this is not getopt_long_only,
638      * or the option starts with '--' or is not a valid short
639      * option, then it's an error.
640      * Otherwise interpret it as a short option.  */
641     if (! long_only || argv[GNoptind][1] == '-' ||
642         my_index (optstring, *nextchar) == NULL)
643     {
644       if (GNopterr)
645       {
646         if (argv[GNoptind][1] == '-')
647           /* --option */
648           FPRINTF (stderr,
649                    _ ("%s: unrecognized option `--%s'\n"),
650                    argv[0],
651                    nextchar);
652         else
653           /* +option or -option */
654           FPRINTF (stderr,
655                    _ ("%s: unrecognized option `%c%s'\n"),
656                    argv[0],
657                    argv[GNoptind][0],
658                    nextchar);
659       }
660       nextchar = (char *) "";
661       GNoptind++;
662       return '?';
663     }
664   }
665
666   /* Look at and handle the next short option-character.  */
667
668   {
669     char c = *nextchar++;
670     char *temp = my_index (optstring, c);
671
672     /* Increment `GNoptind' when we start to process its last character.  */
673     if (*nextchar == '\0')
674       ++GNoptind;
675
676     if (temp == NULL || c == ':')
677     {
678       if (GNopterr)
679       {
680         if (posixly_correct)
681           /* 1003.2 specifies the format of this message.  */
682           FPRINTF (stderr, _ ("%s: illegal option -- %c\n"), argv[0], c);
683         else
684           FPRINTF (stderr, _ ("%s: invalid option -- %c\n"), argv[0], c);
685       }
686       return '?';
687     }
688     /* Convenience. Treat POSIX -W foo same as long option --foo */
689     if (temp[0] == 'W' && temp[1] == ';')
690     {
691       char *nameend;
692       const struct GNoption *p;
693       const struct GNoption *pfound = NULL;
694       int exact = 0;
695       int ambig = 0;
696       int indfound = 0;
697       int option_index;
698
699       /* This is an option that requires an argument.  */
700       if (*nextchar != '\0')
701       {
702         GNoptarg = nextchar;
703         /* If we end this ARGV-element by taking the rest as an arg,
704          * we must advance to the next element now.  */
705         GNoptind++;
706       }
707       else if (GNoptind == argc)
708       {
709         if (GNopterr)
710         {
711           /* 1003.2 specifies the format of this message.  */
712           FPRINTF (stderr,
713                    _ ("%s: option requires an argument -- %c\n"),
714                    argv[0],
715                    c);
716         }
717         if (optstring[0] == ':')
718           c = ':';
719         else
720           c = '?';
721         return c;
722       }
723       else
724         /* We already incremented `GNoptind' once;
725          * increment it again when taking next ARGV-elt as argument.  */
726         GNoptarg = argv[GNoptind++];
727
728       /* GNoptarg is now the argument, see if it's in the
729        * table of longopts.  */
730
731       for (nextchar = nameend = GNoptarg; *nameend && *nameend != '=';
732            nameend++)
733         /* Do nothing.  */;
734
735       /* Test all long options for either exact match
736        * or abbreviated matches.  */
737       if (longopts != NULL)
738         for (p = longopts, option_index = 0; p->name; p++, option_index++)
739           if (! strncmp (p->name, nextchar, nameend - nextchar))
740           {
741             if ((unsigned int) (nameend - nextchar) == strlen (p->name))
742             {
743               /* Exact match found.  */
744               pfound = p;
745               indfound = option_index;
746               exact = 1;
747               break;
748             }
749             else if (pfound == NULL)
750             {
751               /* First nonexact match found.  */
752               pfound = p;
753               indfound = option_index;
754             }
755             else
756               /* Second or later nonexact match found.  */
757               ambig = 1;
758           }
759       if (ambig && ! exact)
760       {
761         if (GNopterr)
762           FPRINTF (stderr,
763                    _ ("%s: option `-W %s' is ambiguous\n"),
764                    argv[0],
765                    argv[GNoptind]);
766         nextchar += strlen (nextchar);
767         GNoptind++;
768         return '?';
769       }
770       if (pfound != NULL)
771       {
772         option_index = indfound;
773         if (*nameend)
774         {
775           /* Don't test has_arg with >, because some C compilers don't
776            * allow it to be used on enums.  */
777           if (pfound->has_arg)
778             GNoptarg = nameend + 1;
779           else
780           {
781             if (GNopterr)
782               FPRINTF (stderr,
783                        _ ("%s: option `-W %s' does not allow an argument\n"),
784                        argv[0],
785                        pfound->name);
786
787             nextchar += strlen (nextchar);
788             return '?';
789           }
790         }
791         else if (pfound->has_arg == 1)
792         {
793           if (GNoptind < argc)
794             GNoptarg = argv[GNoptind++];
795           else
796           {
797             if (GNopterr)
798               FPRINTF (stderr,
799                        _ ("%s: option `%s' requires an argument\n"),
800                        argv[0],
801                        argv[GNoptind - 1]);
802             nextchar += strlen (nextchar);
803             return optstring[0] == ':' ? ':' : '?';
804           }
805         }
806         nextchar += strlen (nextchar);
807         if (longind != NULL)
808           *longind = option_index;
809         if (pfound->flag)
810         {
811           *(pfound->flag) = pfound->val;
812           return 0;
813         }
814         return pfound->val;
815       }
816       nextchar = NULL;
817       return 'W'; /* Let the application handle it.   */
818     }
819     if (temp[1] == ':')
820     {
821       if (temp[2] == ':')
822       {
823         /* This is an option that accepts an argument optionally.  */
824         if (*nextchar != '\0')
825         {
826           GNoptarg = nextchar;
827           GNoptind++;
828         }
829         else
830           GNoptarg = NULL;
831         nextchar = NULL;
832       }
833       else
834       {
835         /* This is an option that requires an argument.  */
836         if (*nextchar != '\0')
837         {
838           GNoptarg = nextchar;
839           /* If we end this ARGV-element by taking the rest as an arg,
840            * we must advance to the next element now.  */
841           GNoptind++;
842         }
843         else if (GNoptind == argc)
844         {
845           if (GNopterr)
846           {
847             /* 1003.2 specifies the format of this message.  */
848             FPRINTF (stderr,
849                      _ ("%s: option requires an argument -- %c\n"),
850                      argv[0],
851                      c);
852           }
853           if (optstring[0] == ':')
854             c = ':';
855           else
856             c = '?';
857         }
858         else
859           /* We already incremented `GNoptind' once;
860            * increment it again when taking next ARGV-elt as argument.  */
861           GNoptarg = argv[GNoptind++];
862         nextchar = NULL;
863       }
864     }
865     return c;
866   }
867 }
868
869
870 static int
871 GNgetopt_long (int argc,
872                char *const *argv,
873                const char *options,
874                const struct GNoption *long_options,
875                int *opt_index)
876 {
877   return GN_getopt_internal (argc, argv, options, long_options, opt_index, 0);
878 }
879
880 /* ******************** now the GNUnet specific modifications... ********************* */
881
882 /**
883  * Parse the command line.
884  *
885  * @param binaryOptions Name of application with option summary
886  * @param allOptions defined options and handlers
887  * @param argc number of arguments
888  * @param argv actual arguments
889  * @return index into argv with first non-option
890  *   argument, or #GNUNET_SYSERR on error
891  */
892 int
893 GNUNET_GETOPT_run (const char *binaryOptions,
894                    const struct GNUNET_GETOPT_CommandLineOption *allOptions,
895                    unsigned int argc,
896                    char *const *argv)
897 {
898   struct GNoption *long_options;
899   struct GNUNET_GETOPT_CommandLineProcessorContext clpc;
900   int count;
901   char *shorts;
902   int spos;
903   int cont;
904   uint8_t *seen;
905   unsigned int optmatch = 0;
906   const char *have_exclusive = NULL;
907
908   GNUNET_assert (argc > 0);
909   GNoptind = 0;
910   clpc.binaryName = argv[0];
911   clpc.binaryOptions = binaryOptions;
912   clpc.allOptions = allOptions;
913   clpc.argv = argv;
914   clpc.argc = argc;
915   for (count = 0; NULL != allOptions[count].name; count++)
916     ;
917
918   /* transform our option representation into the format
919      used by the GNU getopt copylib */
920   long_options = GNUNET_new_array (count + 1, struct GNoption);
921   seen = GNUNET_new_array (count, uint8_t);
922   shorts = GNUNET_malloc (count * 2 + 1);
923   spos = 0;
924   for (unsigned i = 0; i < count; i++)
925   {
926     long_options[i].name = allOptions[i].name;
927     long_options[i].has_arg = allOptions[i].require_argument;
928     long_options[i].flag = NULL;
929     long_options[i].val = allOptions[i].shortName;
930     shorts[spos++] = allOptions[i].shortName;
931     if (allOptions[i].require_argument != 0)
932       shorts[spos++] = ':';
933   }
934   long_options[count].name = NULL;
935   long_options[count].has_arg = 0;
936   long_options[count].flag = NULL;
937   long_options[count].val = '\0';
938   shorts[spos] = '\0';
939   cont = GNUNET_OK;
940
941   /* main getopt loop */
942   while (1)
943   {
944     int option_index = 0;
945     unsigned int i;
946     int c;
947
948     c = GNgetopt_long (argc, argv, shorts, long_options, &option_index);
949     if (c == GNUNET_SYSERR)
950       break; /* No more flags to process */
951
952     /* Check which of our program's options was given by the user */
953     for (i = 0; i < count; i++)
954     {
955       clpc.currentArgument = GNoptind - 1;
956       if ((char) c == allOptions[i].shortName)
957       {
958         optmatch++;
959         if (allOptions[i].option_exclusive)
960           have_exclusive = allOptions[i].name;
961         if (GNUNET_OK == cont)
962         {
963           /* parse the option using the option-specific processor */
964           cont = allOptions[i].processor (&clpc,
965                                           allOptions[i].scls,
966                                           allOptions[i].name,
967                                           GNoptarg);
968         }
969         seen[i] = 1;
970         break;
971       }
972     }
973     if (i == count)
974     {
975       FPRINTF (stderr, _ ("Use %s to get a list of options.\n"), "--help");
976       cont = GNUNET_SYSERR;
977     }
978   }
979   GNUNET_free (shorts);
980   GNUNET_free (long_options);
981
982   /* check that if any option that was marked as exclusive
983      is the only option that was provided */
984   if ((NULL != have_exclusive) && (optmatch > 1))
985   {
986     FPRINTF (stderr,
987              _ ("Option `%s' can't be used with other options.\n"),
988              have_exclusive);
989     cont = GNUNET_SYSERR;
990   }
991   if (GNUNET_YES == cont)
992   {
993     /* check that all mandatory options are present */
994     for (count = 0; NULL != allOptions[count].name; count++)
995     {
996       if ((0 == seen[count]) && (allOptions[count].option_mandatory))
997       {
998         FPRINTF (stderr,
999                  _ ("Missing mandatory option `%s'.\n"),
1000                  allOptions[count].name);
1001         cont = GNUNET_SYSERR;
1002       }
1003     }
1004   }
1005   GNUNET_free (seen);
1006
1007   /* call cleaners, if available */
1008   for (unsigned int i = 0; NULL != allOptions[i].name; i++)
1009     if (NULL != allOptions[i].cleaner)
1010       allOptions[i].cleaner (allOptions[i].scls);
1011
1012   if (GNUNET_OK != cont)
1013     return cont;
1014   return GNoptind;
1015 }
1016
1017 /* end of getopt.c */