~ubuntu-branches/ubuntu/trusty/bash/trusty-security

« back to all changes in this revision

Viewing changes to builtins/getopts.def

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2014-03-03 22:52:05 UTC
  • mfrom: (1.3.5) (2.2.6 experimental)
  • Revision ID: package-import@ubuntu.com-20140303225205-87ltrt5kspeq0g1b
Tags: 4.3-1ubuntu1
* Merge with Debian; remaining changes:
  - skel.bashrc:
    - Run lesspipe.
    - Enable ls aliases.
    - Set options in ll alias to -alF.
    - Define an alert alias.
    - Enabled colored grep aliases.
  - etc.bash.bashrc:
    - Add sudo hint.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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-2004 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
 
 
78
#include "../shell.h"
 
79
#include "common.h"
 
80
#include "bashgetopt.h"
 
81
#include "getopt.h"
 
82
 
 
83
#define G_EOF           -1
 
84
#define G_INVALID_OPT   -2
 
85
#define G_ARG_MISSING   -3
 
86
 
 
87
extern char *this_command_name;
 
88
 
 
89
static int getopts_bind_variable __P((char *, char *));
 
90
static int dogetopts __P((int, char **));
 
91
 
 
92
/* getopts_reset is magic code for when OPTIND is reset.  N is the
 
93
   value that has just been assigned to OPTIND. */
 
94
void
 
95
getopts_reset (newind)
 
96
     int newind;
 
97
{
 
98
  sh_optind = newind;
 
99
  sh_badopt = 0;
 
100
}
 
101
 
 
102
static int
 
103
getopts_bind_variable (name, value)
 
104
     char *name, *value;
 
105
{
 
106
  SHELL_VAR *v;
 
107
 
 
108
  if (legal_identifier (name))
 
109
    {
 
110
      v = bind_variable (name, value, 0);
 
111
      if (v && (readonly_p (v) || noassign_p (v)))
 
112
        return (EX_MISCERROR);
 
113
      return (v ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
 
114
    }
 
115
  else
 
116
    {
 
117
      sh_invalidid (name);
 
118
      return (EXECUTION_FAILURE);
 
119
    }
 
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
 
126
   and invalid option characters.  The handling is as follows.
 
127
 
 
128
   INVALID OPTIONS:
 
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
 
 
149
static int
 
150
dogetopts (argc, argv)
 
151
     int argc;
 
152
     char **argv;
 
153
{
 
154
  int ret, special_error, old_opterr, i, n;
 
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
    {
 
162
      builtin_usage ();
 
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
    {
 
192
      for (i = 0; i < 10 && dollar_vars[i]; i++)
 
193
        ;
 
194
 
 
195
      sh_getopt_restore_state (dollar_vars);
 
196
      ret = sh_getopt (i, dollar_vars, optstr);
 
197
    }
 
198
  else
 
199
    {
 
200
      register WORD_LIST *words;
 
201
      char **v;
 
202
 
 
203
      for (i = 0; i < 10 && dollar_vars[i]; i++)
 
204
        ;
 
205
      for (words = rest_of_args; words; words = words->next, i++)
 
206
        ;
 
207
      v = strvec_create (i + 1);
 
208
      for (i = 0; i < 10 && dollar_vars[i]; i++)
 
209
        v[i] = dollar_vars[i];
 
210
      for (words = rest_of_args; words; words = words->next, i++)
 
211
        v[i] = words->word->word;
 
212
      v[i] = (char *)NULL;
 
213
      sh_getopt_restore_state (v);
 
214
      ret = sh_getopt (i, v, optstr);
 
215
      free (v);
 
216
    }
 
217
 
 
218
  if (special_error)
 
219
    sh_opterr = old_opterr;
 
220
 
 
221
  /* Set the OPTIND variable in any case, to handle "--" skipping.  It's
 
222
     highly unlikely that 14 digits will be too few. */
 
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
    }
 
239
  bind_variable ("OPTIND", numval + i, 0);
 
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
 
243
     is in OPTOPT.  If an invalid option was encountered, OPTARG is
 
244
     NULL.  If a required option argument was missing, OPTARG points
 
245
     to a NULL string (that is, sh_optarg[0] == 0). */
 
246
  if (ret == '?')
 
247
    {
 
248
      if (sh_optarg == NULL)
 
249
        ret = G_INVALID_OPT;
 
250
      else if (sh_optarg[0] == '\0')
 
251
        ret = G_ARG_MISSING;
 
252
    }
 
253
            
 
254
  if (ret == G_EOF)
 
255
    {
 
256
      unbind_variable ("OPTARG");
 
257
      getopts_bind_variable (name, "?");
 
258
      return (EXECUTION_FAILURE);
 
259
    }
 
260
 
 
261
  if (ret == G_INVALID_OPT)
 
262
    {
 
263
      /* Invalid option encountered. */
 
264
      ret = getopts_bind_variable (name, "?");
 
265
 
 
266
      if (special_error)
 
267
        {
 
268
          strval[0] = (char)sh_optopt;
 
269
          strval[1] = '\0';
 
270
          bind_variable ("OPTARG", strval, 0);
 
271
        }
 
272
      else
 
273
        unbind_variable ("OPTARG");
 
274
 
 
275
      return (ret);
 
276
    }
 
277
 
 
278
  if (ret == G_ARG_MISSING)
 
279
    {
 
280
      /* Required argument missing. */
 
281
      if (special_error)
 
282
        {
 
283
          ret = getopts_bind_variable (name, ":");
 
284
 
 
285
          strval[0] = (char)sh_optopt;
 
286
          strval[1] = '\0';
 
287
          bind_variable ("OPTARG", strval, 0);
 
288
        }
 
289
      else
 
290
        {
 
291
          ret = getopts_bind_variable (name, "?");
 
292
          unbind_variable ("OPTARG");
 
293
        }
 
294
      return (ret);
 
295
    }                   
 
296
 
 
297
  bind_variable ("OPTARG", sh_optarg, 0);
 
298
 
 
299
  strval[0] = (char) ret;
 
300
  strval[1] = '\0';
 
301
  return (getopts_bind_variable (name, strval));
 
302
}
 
303
 
 
304
/* The getopts builtin.  Build an argv, and call dogetopts with it. */
 
305
int
 
306
getopts_builtin (list)
 
307
     WORD_LIST *list;
 
308
{
 
309
  char **av;
 
310
  int ac, ret;
 
311
 
 
312
  if (list == 0)
 
313
    {
 
314
      builtin_usage ();
 
315
      return EX_USAGE;
 
316
    }
 
317
 
 
318
  reset_internal_getopt ();
 
319
  if (internal_getopt (list, "") != -1)
 
320
    {
 
321
      builtin_usage ();
 
322
      return (EX_USAGE);
 
323
    }
 
324
  list = loptend;
 
325
 
 
326
  av = make_builtin_argv (list, &ac);
 
327
  ret = dogetopts (ac, av);
 
328
  free ((char *)av);
 
329
 
 
330
  return (ret);
 
331
}