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