]>
Commit | Line | Data |
---|---|---|
726f6388 JA |
1 | This file is getopts.def, from which is created getopts.c. |
2 | It implements the builtin "getopts" in Bash. | |
3 | ||
a0c0a00f | 4 | Copyright (C) 1987-2015 Free Software Foundation, Inc. |
726f6388 JA |
5 | |
6 | This file is part of GNU Bash, the Bourne Again SHell. | |
7 | ||
3185942a JA |
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. | |
726f6388 | 12 | |
3185942a JA |
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. | |
726f6388 | 17 | |
3185942a JA |
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/>. | |
726f6388 JA |
20 | |
21 | $PRODUCES getopts.c | |
22 | ||
23 | $BUILTIN getopts | |
726f6388 JA |
24 | $FUNCTION getopts_builtin |
25 | $SHORT_DOC getopts optstring name [arg] | |
3185942a JA |
26 | Parse option arguments. |
27 | ||
28 | Getopts is used by shell procedures to parse positional parameters | |
29 | as options. | |
726f6388 JA |
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 | |
7117c2d2 | 44 | this mode, no error messages are printed. If an invalid option is |
726f6388 JA |
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 | |
7117c2d2 | 48 | silent mode, and an invalid option is seen, getopts places '?' into |
b80f6443 | 49 | NAME and unsets OPTARG. If a required argument is not found, a '?' |
726f6388 JA |
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. | |
3185942a JA |
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. | |
726f6388 JA |
63 | $END |
64 | ||
ccc6cda3 JA |
65 | #include <config.h> |
66 | ||
726f6388 JA |
67 | #include <stdio.h> |
68 | ||
ccc6cda3 | 69 | #if defined (HAVE_UNISTD_H) |
cce855bc JA |
70 | # ifdef _MINIX |
71 | # include <sys/types.h> | |
72 | # endif | |
ccc6cda3 JA |
73 | # include <unistd.h> |
74 | #endif | |
726f6388 | 75 | |
ccc6cda3 | 76 | #include "../bashansi.h" |
a0c0a00f | 77 | #include "../bashintl.h" |
726f6388 | 78 | |
ccc6cda3 JA |
79 | #include "../shell.h" |
80 | #include "common.h" | |
81 | #include "bashgetopt.h" | |
726f6388 JA |
82 | #include "getopt.h" |
83 | ||
ccc6cda3 | 84 | #define G_EOF -1 |
7117c2d2 | 85 | #define G_INVALID_OPT -2 |
ccc6cda3 | 86 | #define G_ARG_MISSING -3 |
726f6388 JA |
87 | |
88 | extern char *this_command_name; | |
726f6388 | 89 | |
a0c0a00f | 90 | static int getopts_unbind_variable __P((char *)); |
7117c2d2 JA |
91 | static int getopts_bind_variable __P((char *, char *)); |
92 | static int dogetopts __P((int, char **)); | |
93 | ||
726f6388 JA |
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 | getopts_reset (newind) | |
98 | int newind; | |
99 | { | |
100 | sh_optind = newind; | |
ccc6cda3 JA |
101 | sh_badopt = 0; |
102 | } | |
103 | ||
a0c0a00f CR |
104 | static int |
105 | getopts_unbind_variable (name) | |
106 | char *name; | |
107 | { | |
108 | #if 0 | |
109 | return (unbind_variable (name)); | |
110 | #else | |
111 | return (unbind_variable_noref (name)); | |
112 | #endif | |
113 | } | |
114 | ||
ccc6cda3 JA |
115 | static int |
116 | getopts_bind_variable (name, value) | |
117 | char *name, *value; | |
118 | { | |
119 | SHELL_VAR *v; | |
120 | ||
121 | if (legal_identifier (name)) | |
122 | { | |
95732b49 | 123 | v = bind_variable (name, value, 0); |
495aee44 CR |
124 | if (v && (readonly_p (v) || noassign_p (v))) |
125 | return (EX_MISCERROR); | |
126 | return (v ? EXECUTION_SUCCESS : EXECUTION_FAILURE); | |
ccc6cda3 JA |
127 | } |
128 | else | |
129 | { | |
7117c2d2 | 130 | sh_invalidid (name); |
ccc6cda3 JA |
131 | return (EXECUTION_FAILURE); |
132 | } | |
726f6388 JA |
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 | |
7117c2d2 | 139 | and invalid option characters. The handling is as follows. |
726f6388 | 140 | |
7117c2d2 | 141 | INVALID OPTIONS: |
726f6388 JA |
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 | dogetopts (argc, argv) | |
164 | int argc; | |
165 | char **argv; | |
166 | { | |
ccc6cda3 | 167 | int ret, special_error, old_opterr, i, n; |
726f6388 JA |
168 | char strval[2], numval[16]; |
169 | char *optstr; /* list of options */ | |
170 | char *name; /* variable to get flag val */ | |
171 | char *t; | |
172 | ||
173 | if (argc < 3) | |
174 | { | |
ccc6cda3 | 175 | builtin_usage (); |
726f6388 JA |
176 | return (EX_USAGE); |
177 | } | |
178 | ||
179 | /* argv[0] is "getopts". */ | |
180 | ||
181 | optstr = argv[1]; | |
182 | name = argv[2]; | |
183 | argc -= 2; | |
184 | argv += 2; | |
185 | ||
186 | special_error = optstr[0] == ':'; | |
187 | ||
188 | if (special_error) | |
189 | { | |
190 | old_opterr = sh_opterr; | |
191 | optstr++; | |
192 | sh_opterr = 0; /* suppress diagnostic messages */ | |
193 | } | |
194 | ||
195 | if (argc > 1) | |
196 | { | |
197 | sh_getopt_restore_state (argv); | |
198 | t = argv[0]; | |
199 | argv[0] = dollar_vars[0]; | |
200 | ret = sh_getopt (argc, argv, optstr); | |
201 | argv[0] = t; | |
202 | } | |
203 | else if (rest_of_args == (WORD_LIST *)NULL) | |
204 | { | |
ccc6cda3 JA |
205 | for (i = 0; i < 10 && dollar_vars[i]; i++) |
206 | ; | |
b72432fd JA |
207 | |
208 | sh_getopt_restore_state (dollar_vars); | |
726f6388 JA |
209 | ret = sh_getopt (i, dollar_vars, optstr); |
210 | } | |
211 | else | |
212 | { | |
726f6388 JA |
213 | register WORD_LIST *words; |
214 | char **v; | |
215 | ||
ccc6cda3 JA |
216 | for (i = 0; i < 10 && dollar_vars[i]; i++) |
217 | ; | |
218 | for (words = rest_of_args; words; words = words->next, i++) | |
219 | ; | |
7117c2d2 | 220 | v = strvec_create (i + 1); |
726f6388 | 221 | for (i = 0; i < 10 && dollar_vars[i]; i++) |
28ef6c31 | 222 | v[i] = dollar_vars[i]; |
726f6388 | 223 | for (words = rest_of_args; words; words = words->next, i++) |
28ef6c31 | 224 | v[i] = words->word->word; |
726f6388 | 225 | v[i] = (char *)NULL; |
b72432fd | 226 | sh_getopt_restore_state (v); |
726f6388 JA |
227 | ret = sh_getopt (i, v, optstr); |
228 | free (v); | |
229 | } | |
230 | ||
231 | if (special_error) | |
232 | sh_opterr = old_opterr; | |
233 | ||
7117c2d2 JA |
234 | /* Set the OPTIND variable in any case, to handle "--" skipping. It's |
235 | highly unlikely that 14 digits will be too few. */ | |
726f6388 JA |
236 | if (sh_optind < 10) |
237 | { | |
238 | numval[14] = sh_optind + '0'; | |
239 | numval[15] = '\0'; | |
240 | i = 14; | |
241 | } | |
242 | else | |
243 | { | |
244 | numval[i = 15] = '\0'; | |
245 | n = sh_optind; | |
246 | do | |
247 | { | |
248 | numval[--i] = (n % 10) + '0'; | |
249 | } | |
250 | while (n /= 10); | |
251 | } | |
95732b49 | 252 | bind_variable ("OPTIND", numval + i, 0); |
726f6388 JA |
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 | |
7117c2d2 | 256 | is in OPTOPT. If an invalid option was encountered, OPTARG is |
726f6388 | 257 | NULL. If a required option argument was missing, OPTARG points |
ccc6cda3 | 258 | to a NULL string (that is, sh_optarg[0] == 0). */ |
726f6388 JA |
259 | if (ret == '?') |
260 | { | |
261 | if (sh_optarg == NULL) | |
7117c2d2 | 262 | ret = G_INVALID_OPT; |
726f6388 JA |
263 | else if (sh_optarg[0] == '\0') |
264 | ret = G_ARG_MISSING; | |
265 | } | |
266 | ||
267 | if (ret == G_EOF) | |
268 | { | |
a0c0a00f | 269 | getopts_unbind_variable ("OPTARG"); |
ccc6cda3 | 270 | getopts_bind_variable (name, "?"); |
726f6388 JA |
271 | return (EXECUTION_FAILURE); |
272 | } | |
273 | ||
7117c2d2 | 274 | if (ret == G_INVALID_OPT) |
726f6388 | 275 | { |
7117c2d2 | 276 | /* Invalid option encountered. */ |
ccc6cda3 | 277 | ret = getopts_bind_variable (name, "?"); |
726f6388 JA |
278 | |
279 | if (special_error) | |
280 | { | |
ccc6cda3 | 281 | strval[0] = (char)sh_optopt; |
726f6388 | 282 | strval[1] = '\0'; |
95732b49 | 283 | bind_variable ("OPTARG", strval, 0); |
726f6388 JA |
284 | } |
285 | else | |
a0c0a00f | 286 | getopts_unbind_variable ("OPTARG"); |
ccc6cda3 JA |
287 | |
288 | return (ret); | |
726f6388 JA |
289 | } |
290 | ||
291 | if (ret == G_ARG_MISSING) | |
292 | { | |
293 | /* Required argument missing. */ | |
294 | if (special_error) | |
295 | { | |
ccc6cda3 | 296 | ret = getopts_bind_variable (name, ":"); |
726f6388 | 297 | |
ccc6cda3 | 298 | strval[0] = (char)sh_optopt; |
726f6388 | 299 | strval[1] = '\0'; |
95732b49 | 300 | bind_variable ("OPTARG", strval, 0); |
726f6388 JA |
301 | } |
302 | else | |
303 | { | |
ccc6cda3 | 304 | ret = getopts_bind_variable (name, "?"); |
a0c0a00f | 305 | getopts_unbind_variable ("OPTARG"); |
726f6388 | 306 | } |
ccc6cda3 | 307 | return (ret); |
726f6388 JA |
308 | } |
309 | ||
95732b49 | 310 | bind_variable ("OPTARG", sh_optarg, 0); |
726f6388 JA |
311 | |
312 | strval[0] = (char) ret; | |
313 | strval[1] = '\0'; | |
ccc6cda3 | 314 | return (getopts_bind_variable (name, strval)); |
726f6388 JA |
315 | } |
316 | ||
317 | /* The getopts builtin. Build an argv, and call dogetopts with it. */ | |
318 | int | |
319 | getopts_builtin (list) | |
320 | WORD_LIST *list; | |
321 | { | |
726f6388 JA |
322 | char **av; |
323 | int ac, ret; | |
726f6388 JA |
324 | |
325 | if (list == 0) | |
d166f048 JA |
326 | { |
327 | builtin_usage (); | |
328 | return EX_USAGE; | |
329 | } | |
726f6388 | 330 | |
ccc6cda3 | 331 | reset_internal_getopt (); |
a0c0a00f | 332 | if ((ret = internal_getopt (list, "")) != -1) |
ccc6cda3 | 333 | { |
a0c0a00f CR |
334 | if (ret == GETOPT_HELP) |
335 | builtin_help (); | |
336 | else | |
337 | builtin_usage (); | |
f73dda09 | 338 | return (EX_USAGE); |
ccc6cda3 JA |
339 | } |
340 | list = loptend; | |
726f6388 | 341 | |
ccc6cda3 | 342 | av = make_builtin_argv (list, &ac); |
726f6388 JA |
343 | ret = dogetopts (ac, av); |
344 | free ((char *)av); | |
ccc6cda3 | 345 | |
726f6388 JA |
346 | return (ret); |
347 | } |