Line data Source code
1 : This file is getopts.def, from which is created getopts.c.
2 : It implements the builtin "getopts" in Bash.
3 :
4 : Copyright (C) 1987-2015 Free Software Foundation, Inc.
5 :
6 : This file is part of GNU Bash, the Bourne Again SHell.
7 :
8 : Bash is free software: you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation, either version 3 of the License, or
11 : (at your option) any later version.
12 :
13 : Bash is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with Bash. If not, see <http://www.gnu.org/licenses/>.
20 :
21 : $PRODUCES getopts.c
22 :
23 : $BUILTIN getopts
24 : $FUNCTION getopts_builtin
25 : $SHORT_DOC getopts optstring name [arg]
26 : Parse option arguments.
27 :
28 : Getopts is used by shell procedures to parse positional parameters
29 : as options.
30 :
31 : OPTSTRING contains the option letters to be recognized; if a letter
32 : is followed by a colon, the option is expected to have an argument,
33 : which should be separated from it by white space.
34 :
35 : Each time it is invoked, getopts will place the next option in the
36 : shell variable $name, initializing name if it does not exist, and
37 : the index of the next argument to be processed into the shell
38 : variable OPTIND. OPTIND is initialized to 1 each time the shell or
39 : a shell script is invoked. When an option requires an argument,
40 : getopts places that argument into the shell variable OPTARG.
41 :
42 : getopts reports errors in one of two ways. If the first character
43 : of OPTSTRING is a colon, getopts uses silent error reporting. In
44 : this mode, no error messages are printed. If an invalid option is
45 : seen, getopts places the option character found into OPTARG. If a
46 : required argument is not found, getopts places a ':' into NAME and
47 : sets OPTARG to the option character found. If getopts is not in
48 : silent mode, and an invalid option is seen, getopts places '?' into
49 : NAME and unsets OPTARG. If a required argument is not found, a '?'
50 : is placed in NAME, OPTARG is unset, and a diagnostic message is
51 : printed.
52 :
53 : If the shell variable OPTERR has the value 0, getopts disables the
54 : printing of error messages, even if the first character of
55 : OPTSTRING is not a colon. OPTERR has the value 1 by default.
56 :
57 : Getopts normally parses the positional parameters ($0 - $9), but if
58 : more arguments are given, they are parsed instead.
59 :
60 : Exit Status:
61 : Returns success if an option is found; fails if the end of options is
62 : encountered or an error occurs.
63 : $END
64 :
65 : #include <config.h>
66 :
67 : #include <stdio.h>
68 :
69 : #if defined (HAVE_UNISTD_H)
70 : # ifdef _MINIX
71 : # include <sys/types.h>
72 : # endif
73 : # include <unistd.h>
74 : #endif
75 :
76 : #include "../bashansi.h"
77 : #include "../bashintl.h"
78 :
79 : #include "../shell.h"
80 : #include "common.h"
81 : #include "bashgetopt.h"
82 : #include "getopt.h"
83 :
84 : #define G_EOF -1
85 : #define G_INVALID_OPT -2
86 : #define G_ARG_MISSING -3
87 :
88 : extern char *this_command_name;
89 :
90 : static int getopts_unbind_variable __P((char *));
91 : static int getopts_bind_variable __P((char *, char *));
92 : static int dogetopts __P((int, char **));
93 :
94 : /* getopts_reset is magic code for when OPTIND is reset. N is the
95 : value that has just been assigned to OPTIND. */
96 : void
97 9542939 : getopts_reset (newind)
98 : int newind;
99 : {
100 9542939 : sh_optind = newind;
101 9542939 : sh_badopt = 0;
102 9542939 : }
103 :
104 : static int
105 : getopts_unbind_variable (name)
106 : char *name;
107 : {
108 : #if 0
109 : return (unbind_variable (name));
110 : #else
111 0 : return (unbind_variable_noref (name));
112 : #endif
113 : }
114 :
115 : static int
116 0 : getopts_bind_variable (name, value)
117 : char *name, *value;
118 : {
119 0 : SHELL_VAR *v;
120 :
121 0 : if (legal_identifier (name))
122 : {
123 0 : v = bind_variable (name, value, 0);
124 0 : if (v && (readonly_p (v) || noassign_p (v)))
125 : return (EX_MISCERROR);
126 0 : return (v ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
127 : }
128 : else
129 : {
130 0 : sh_invalidid (name);
131 0 : return (EXECUTION_FAILURE);
132 : }
133 : }
134 :
135 : /* Error handling is now performed as specified by Posix.2, draft 11
136 : (identical to that of ksh-88). The special handling is enabled if
137 : the first character of the option string is a colon; this handling
138 : disables diagnostic messages concerning missing option arguments
139 : and invalid option characters. The handling is as follows.
140 :
141 : INVALID OPTIONS:
142 : name -> "?"
143 : if (special_error) then
144 : OPTARG = option character found
145 : no error output
146 : else
147 : OPTARG unset
148 : diagnostic message
149 : fi
150 :
151 : MISSING OPTION ARGUMENT;
152 : if (special_error) then
153 : name -> ":"
154 : OPTARG = option character found
155 : else
156 : name -> "?"
157 : OPTARG unset
158 : diagnostic message
159 : fi
160 : */
161 :
162 : static int
163 0 : dogetopts (argc, argv)
164 : int argc;
165 : char **argv;
166 : {
167 0 : int ret, special_error, old_opterr, i, n;
168 0 : char strval[2], numval[16];
169 0 : char *optstr; /* list of options */
170 0 : char *name; /* variable to get flag val */
171 0 : char *t;
172 :
173 0 : if (argc < 3)
174 : {
175 0 : builtin_usage ();
176 0 : return (EX_USAGE);
177 : }
178 :
179 : /* argv[0] is "getopts". */
180 :
181 0 : optstr = argv[1];
182 0 : name = argv[2];
183 0 : argc -= 2;
184 0 : argv += 2;
185 :
186 0 : special_error = optstr[0] == ':';
187 :
188 0 : if (special_error)
189 : {
190 0 : old_opterr = sh_opterr;
191 0 : optstr++;
192 0 : sh_opterr = 0; /* suppress diagnostic messages */
193 : }
194 :
195 0 : if (argc > 1)
196 : {
197 0 : sh_getopt_restore_state (argv);
198 0 : t = argv[0];
199 0 : argv[0] = dollar_vars[0];
200 0 : ret = sh_getopt (argc, argv, optstr);
201 0 : argv[0] = t;
202 : }
203 0 : else if (rest_of_args == (WORD_LIST *)NULL)
204 : {
205 0 : for (i = 0; i < 10 && dollar_vars[i]; i++)
206 0 : ;
207 :
208 0 : sh_getopt_restore_state (dollar_vars);
209 0 : ret = sh_getopt (i, dollar_vars, optstr);
210 : }
211 : else
212 : {
213 : register WORD_LIST *words;
214 : char **v;
215 :
216 0 : for (i = 0; i < 10 && dollar_vars[i]; i++)
217 0 : ;
218 0 : for (words = rest_of_args; words; words = words->next, i++)
219 0 : ;
220 0 : v = strvec_create (i + 1);
221 0 : for (i = 0; i < 10 && dollar_vars[i]; i++)
222 0 : v[i] = dollar_vars[i];
223 0 : for (words = rest_of_args; words; words = words->next, i++)
224 0 : v[i] = words->word->word;
225 0 : v[i] = (char *)NULL;
226 0 : sh_getopt_restore_state (v);
227 0 : ret = sh_getopt (i, v, optstr);
228 0 : free (v);
229 : }
230 :
231 0 : if (special_error)
232 0 : sh_opterr = old_opterr;
233 :
234 : /* Set the OPTIND variable in any case, to handle "--" skipping. It's
235 : highly unlikely that 14 digits will be too few. */
236 0 : if (sh_optind < 10)
237 : {
238 0 : numval[14] = sh_optind + '0';
239 0 : numval[15] = '\0';
240 0 : i = 14;
241 : }
242 : else
243 : {
244 0 : numval[i = 15] = '\0';
245 0 : n = sh_optind;
246 0 : do
247 : {
248 0 : numval[--i] = (n % 10) + '0';
249 : }
250 0 : while (n /= 10);
251 : }
252 0 : bind_variable ("OPTIND", numval + i, 0);
253 :
254 : /* If an error occurred, decide which one it is and set the return
255 : code appropriately. In all cases, the option character in error
256 : is in OPTOPT. If an invalid option was encountered, OPTARG is
257 : NULL. If a required option argument was missing, OPTARG points
258 : to a NULL string (that is, sh_optarg[0] == 0). */
259 0 : if (ret == '?')
260 : {
261 0 : if (sh_optarg == NULL)
262 : ret = G_INVALID_OPT;
263 0 : else if (sh_optarg[0] == '\0')
264 : ret = G_ARG_MISSING;
265 : }
266 :
267 0 : if (ret == G_EOF)
268 : {
269 0 : getopts_unbind_variable ("OPTARG");
270 0 : getopts_bind_variable (name, "?");
271 0 : return (EXECUTION_FAILURE);
272 : }
273 :
274 0 : if (ret == G_INVALID_OPT)
275 : {
276 : /* Invalid option encountered. */
277 0 : ret = getopts_bind_variable (name, "?");
278 :
279 0 : if (special_error)
280 : {
281 0 : strval[0] = (char)sh_optopt;
282 0 : strval[1] = '\0';
283 0 : bind_variable ("OPTARG", strval, 0);
284 : }
285 : else
286 0 : getopts_unbind_variable ("OPTARG");
287 :
288 0 : return (ret);
289 : }
290 :
291 0 : if (ret == G_ARG_MISSING)
292 : {
293 : /* Required argument missing. */
294 0 : if (special_error)
295 : {
296 0 : ret = getopts_bind_variable (name, ":");
297 :
298 0 : strval[0] = (char)sh_optopt;
299 0 : strval[1] = '\0';
300 0 : bind_variable ("OPTARG", strval, 0);
301 : }
302 : else
303 : {
304 0 : ret = getopts_bind_variable (name, "?");
305 0 : getopts_unbind_variable ("OPTARG");
306 : }
307 0 : return (ret);
308 : }
309 :
310 0 : bind_variable ("OPTARG", sh_optarg, 0);
311 :
312 0 : strval[0] = (char) ret;
313 0 : strval[1] = '\0';
314 0 : return (getopts_bind_variable (name, strval));
315 : }
316 :
317 : /* The getopts builtin. Build an argv, and call dogetopts with it. */
318 : int
319 0 : getopts_builtin (list)
320 : WORD_LIST *list;
321 : {
322 0 : char **av;
323 0 : int ac, ret;
324 :
325 0 : if (list == 0)
326 : {
327 0 : builtin_usage ();
328 0 : return EX_USAGE;
329 : }
330 :
331 0 : reset_internal_getopt ();
332 0 : if ((ret = internal_getopt (list, "")) != -1)
333 : {
334 0 : if (ret == GETOPT_HELP)
335 0 : builtin_help ();
336 : else
337 0 : builtin_usage ();
338 0 : return (EX_USAGE);
339 : }
340 0 : list = loptend;
341 :
342 0 : av = make_builtin_argv (list, &ac);
343 0 : ret = dogetopts (ac, av);
344 0 : free ((char *)av);
345 :
346 0 : return (ret);
347 : }
|