1 /* getopt.c - getopt for Bash.  Used by the getopt builtin. */
2 
3 /* Copyright (C) 1993-2009 Free Software Foundation, Inc.
4 
5    This file is part of GNU Bash, the Bourne Again SHell.
6 
7    Bash is free software: you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation, either version 3 of the License, or
10    (at your option) any later version.
11 
12    Bash is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with Bash.  If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 #include <config.h>
22 
23 #if defined (HAVE_UNISTD_H)
24 #  ifdef _MINIX
25 #    include <sys/types.h>
26 #  endif
27 #  include <unistd.h>
28 #endif
29 
30 #include <stdio.h>
31 #include "memalloc.h"
32 #include "../bashintl.h"
33 #include "../shell.h"
34 #include "getopt.h"
35 
36 /* For communication from `sh_getopt' to the caller.
37    When `sh_getopt' finds an option that takes an argument,
38    the argument value is returned here. */
39 char *sh_optarg = 0;
40 
41 /* Index in ARGV of the next element to be scanned.
42    This is used for communication to and from the caller
43    and for communication between successive calls to `sh_getopt'.
44 
45    On entry to `sh_getopt', zero means this is the first call; initialize.
46 
47    When `sh_getopt' returns EOF, this is the index of the first of the
48    non-option elements that the caller should itself scan.
49 
50    Otherwise, `sh_optind' communicates from one call to the next
51    how much of ARGV has been scanned so far.  */
52 
53 /* XXX 1003.2 says this must be 1 before any call.  */
54 int sh_optind = 0;
55 
56 /* Index of the current argument. */
57 static int sh_curopt;
58 
59 /* The next char to be scanned in the option-element
60    in which the last option character we returned was found.
61    This allows us to pick up the scan where we left off.
62 
63    If this is zero, or a null string, it means resume the scan
64    by advancing to the next ARGV-element.  */
65 
66 static char *nextchar;
67 static int sh_charindex;
68 
69 /* Callers store zero here to inhibit the error message
70    for unrecognized options.  */
71 
72 int sh_opterr = 1;
73 
74 /* Set to an option character which was unrecognized.
75    This must be initialized on some systems to avoid linking in the
76    system's own getopt implementation.  */
77 
78 int sh_optopt = '?';
79 
80 /* Set to 1 when we see an invalid option; public so getopts can reset it. */
81 int sh_badopt = 0;
82 
83 /* Scan elements of ARGV (whose length is ARGC) for option characters
84    given in OPTSTRING.
85 
86    If an element of ARGV starts with '-', and is not exactly "-" or "--",
87    then it is an option element.  The characters of this element
88    (aside from the initial '-') are option characters.  If `sh_getopt'
89    is called repeatedly, it returns successively each of the option characters
90    from each of the option elements.
91 
92    If `sh_getopt' finds another option character, it returns that character,
93    updating `sh_optind' and `nextchar' so that the next call to `sh_getopt' can
94    resume the scan with the following option character or ARGV-element.
95 
96    If there are no more option characters, `sh_getopt' returns `EOF'.
97    Then `sh_optind' is the index in ARGV of the first ARGV-element
98    that is not an option.
99 
100    OPTSTRING is a string containing the legitimate option characters.
101    If an option character is seen that is not listed in OPTSTRING,
102    return '?' after printing an error message.  If you set `sh_opterr' to
103    zero, the error message is suppressed but we still return '?'.
104 
105    If a char in OPTSTRING is followed by a colon, that means it wants an arg,
106    so the following text in the same ARGV-element, or the text of the following
107    ARGV-element, is returned in `sh_optarg'. */
108 
109 /* 1003.2 specifies the format of this message.  */
110 #define BADOPT(x)  fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], x)
111 #define NEEDARG(x) fprintf (stderr, _("%s: option requires an argument -- %c\n"), argv[0], x)
112 
113 int
sh_getopt(argc,argv,optstring)114 sh_getopt (argc, argv, optstring)
115      int argc;
116      char *const *argv;
117      const char *optstring;
118 {
119   char c, *temp;
120 
121   sh_optarg = 0;
122 
123   if (sh_optind >= argc || sh_optind < 0)	/* XXX was sh_optind > argc */
124     {
125       sh_optind = argc;
126       return (EOF);
127     }
128 
129   /* Initialize the internal data when the first call is made.
130      Start processing options with ARGV-element 1 (since ARGV-element 0
131      is the program name); the sequence of previously skipped
132      non-option ARGV-elements is empty.  */
133 
134   if (sh_optind == 0)
135     {
136       sh_optind = 1;
137       nextchar = (char *)NULL;
138     }
139 
140   if (nextchar == 0 || *nextchar == '\0')
141     {
142       /* If we have done all the ARGV-elements, stop the scan. */
143       if (sh_optind >= argc)
144 	return EOF;
145 
146       temp = argv[sh_optind];
147 
148       /* Special ARGV-element `--' means premature end of options.
149 	 Skip it like a null option, and return EOF. */
150       if (temp[0] == '-' && temp[1] == '-' && temp[2] == '\0')
151 	{
152 	  sh_optind++;
153 	  return EOF;
154 	}
155 
156       /* If we have come to a non-option, either stop the scan or describe
157 	 it to the caller and pass it by.  This makes the pseudo-option
158 	 `-' mean the end of options, but does not skip over it. */
159       if (temp[0] != '-' || temp[1] == '\0')
160 	return EOF;
161 
162       /* We have found another option-ARGV-element.
163 	 Start decoding its characters.  */
164       nextchar = argv[sh_curopt = sh_optind] + 1;
165       sh_charindex = 1;
166     }
167 
168   /* Look at and handle the next option-character.  */
169 
170   c = *nextchar++; sh_charindex++;
171   temp = strchr (optstring, c);
172 
173   sh_optopt = c;
174 
175   /* Increment `sh_optind' when we start to process its last character.  */
176   if (nextchar == 0 || *nextchar == '\0')
177     {
178       sh_optind++;
179       nextchar = (char *)NULL;
180     }
181 
182   if (sh_badopt = (temp == NULL || c == ':'))
183     {
184       if (sh_opterr)
185 	BADOPT (c);
186 
187       return '?';
188     }
189 
190   if (temp[1] == ':')
191     {
192       if (nextchar && *nextchar)
193 	{
194 	  /* This is an option that requires an argument.  */
195 	  sh_optarg = nextchar;
196 	  /* If we end this ARGV-element by taking the rest as an arg,
197 	     we must advance to the next element now.  */
198 	  sh_optind++;
199 	}
200       else if (sh_optind == argc)
201 	{
202 	  if (sh_opterr)
203 	    NEEDARG (c);
204 
205 	  sh_optopt = c;
206 	  sh_optarg = "";	/* Needed by getopts. */
207 	  c = (optstring[0] == ':') ? ':' : '?';
208 	}
209       else
210 	/* We already incremented `sh_optind' once;
211 	   increment it again when taking next ARGV-elt as argument.  */
212 	sh_optarg = argv[sh_optind++];
213       nextchar = (char *)NULL;
214     }
215   return c;
216 }
217 
218 void
sh_getopt_restore_state(argv)219 sh_getopt_restore_state (argv)
220      char **argv;
221 {
222   if (nextchar)
223     nextchar = argv[sh_curopt] + sh_charindex;
224 }
225 
226 sh_getopt_state_t *
sh_getopt_alloc_istate()227 sh_getopt_alloc_istate ()
228 {
229   sh_getopt_state_t *ret;
230 
231   ret = (sh_getopt_state_t *)xmalloc (sizeof (sh_getopt_state_t));
232   return ret;
233 }
234 
235 void
sh_getopt_dispose_istate(gs)236 sh_getopt_dispose_istate (gs)
237      sh_getopt_state_t *gs;
238 {
239   free (gs);
240 }
241 
242 sh_getopt_state_t *
sh_getopt_save_istate()243 sh_getopt_save_istate ()
244 {
245   sh_getopt_state_t *ret;
246 
247   ret = sh_getopt_alloc_istate ();
248 
249   ret->gs_optarg = sh_optarg;
250   ret->gs_optind = sh_optind;
251   ret->gs_curopt = sh_curopt;
252   ret->gs_nextchar = nextchar;		/* XXX */
253   ret->gs_charindex = sh_charindex;
254   ret->gs_flags = 0;			/* XXX for later use */
255 
256   return ret;
257 }
258 
259 void
sh_getopt_restore_istate(state)260 sh_getopt_restore_istate (state)
261      sh_getopt_state_t *state;
262 {
263   sh_optarg = state->gs_optarg;
264   sh_optind = state->gs_optind;
265   sh_curopt = state->gs_curopt;
266   nextchar = state->gs_nextchar;	/* XXX - probably not usable */
267   sh_charindex = state->gs_charindex;
268 
269   sh_getopt_dispose_istate (state);
270 }
271 
272 #if 0
273 void
274 sh_getopt_debug_restore_state (argv)
275      char **argv;
276 {
277   if (nextchar && nextchar != argv[sh_curopt] + sh_charindex)
278     {
279       itrace("sh_getopt_debug_restore_state: resetting nextchar");
280       nextchar = argv[sh_curopt] + sh_charindex;
281     }
282 }
283 #endif
284 
285 #ifdef TEST
286 
287 /* Compile with -DTEST to make an executable for use in testing
288    the above definition of `sh_getopt'.  */
289 
290 int
main(argc,argv)291 main (argc, argv)
292      int argc;
293      char **argv;
294 {
295   int c;
296   int digit_sh_optind = 0;
297 
298   while (1)
299     {
300       int this_option_sh_optind = sh_optind ? sh_optind : 1;
301 
302       c = sh_getopt (argc, argv, "abc:d:0123456789");
303       if (c == EOF)
304 	break;
305 
306       switch (c)
307 	{
308 	case '0':
309 	case '1':
310 	case '2':
311 	case '3':
312 	case '4':
313 	case '5':
314 	case '6':
315 	case '7':
316 	case '8':
317 	case '9':
318 	  if (digit_sh_optind != 0 && digit_sh_optind != this_option_sh_optind)
319 	    printf ("digits occur in two different argv-elements.\n");
320 	  digit_sh_optind = this_option_sh_optind;
321 	  printf ("option %c\n", c);
322 	  break;
323 
324 	case 'a':
325 	  printf ("option a\n");
326 	  break;
327 
328 	case 'b':
329 	  printf ("option b\n");
330 	  break;
331 
332 	case 'c':
333 	  printf ("option c with value `%s'\n", sh_optarg);
334 	  break;
335 
336 	case '?':
337 	  break;
338 
339 	default:
340 	  printf ("?? sh_getopt returned character code 0%o ??\n", c);
341 	}
342     }
343 
344   if (sh_optind < argc)
345     {
346       printf ("non-option ARGV-elements: ");
347       while (sh_optind < argc)
348 	printf ("%s ", argv[sh_optind++]);
349       printf ("\n");
350     }
351 
352   exit (0);
353 }
354 
355 #endif /* TEST */
356