1 | /* |
1 | /* |
2 | * getopt.c - Enhanced implementation of BSD getopt(1) |
2 | * getopt.c - Enhanced implementation of BSD getopt(1) |
3 | * Copyright (c) 1997-2005 Frodo Looijaard <frodo@frodo.looijaard.name> |
3 | * Copyright (c) 1997-2014 Frodo Looijaard <frodo@frodo.looijaard.name> |
4 | * |
4 | * |
5 | * This program is free software; you can redistribute it and/or modify |
5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by |
6 | * it under the terms of the GNU General Public License as published by |
7 | * the Free Software Foundation; either version 2 of the License, or |
7 | * the Free Software Foundation; either version 2 of the License, or |
8 | * (at your option) any later version. |
8 | * (at your option) any later version. |
… | |
… | |
37 | * <misiek@pld.org.pl>) |
37 | * <misiek@pld.org.pl>) |
38 | * Version 1.1.4: Mon Nov 7 2005 |
38 | * Version 1.1.4: Mon Nov 7 2005 |
39 | * Fixed a few type's in the manpage |
39 | * Fixed a few type's in the manpage |
40 | * Version 1.1.5: Sun Aug 12 2012 |
40 | * Version 1.1.5: Sun Aug 12 2012 |
41 | * Sync with util-linux-2.21, fixed build problems, many new translations |
41 | * Sync with util-linux-2.21, fixed build problems, many new translations |
|
|
42 | * Version 1.1.6: Mon Nov 24 2014 |
|
|
43 | * Sync with util-linux git 20141120, detect ambiguous long options, fix |
|
|
44 | * backslash problem in tcsh |
42 | */ |
45 | */ |
43 | |
46 | |
44 | /* Exit codes: |
47 | /* Exit codes: |
45 | * 0) No errors, successful operation. |
48 | * 0) No errors, successful operation. |
46 | * 1) getopt(3) returned an error. |
49 | * 1) getopt(3) returned an error. |
… | |
… | |
71 | |
74 | |
72 | /* NON_OPT is the code that is returned when a non-option is found in '+' |
75 | /* NON_OPT is the code that is returned when a non-option is found in '+' |
73 | * mode */ |
76 | * mode */ |
74 | #define NON_OPT 1 |
77 | #define NON_OPT 1 |
75 | /* LONG_OPT is the code that is returned when a long option is found. */ |
78 | /* LONG_OPT is the code that is returned when a long option is found. */ |
76 | #define LONG_OPT 2 |
79 | #define LONG_OPT 0 |
77 | |
80 | |
78 | /* The shells recognized. */ |
81 | /* The shells recognized. */ |
79 | typedef enum { BASH, TCSH } shell_t; |
82 | typedef enum { BASH, TCSH } shell_t; |
80 | |
83 | |
81 | |
84 | |
… | |
… | |
139 | /* Quote: replace it with: '\'' */ |
142 | /* Quote: replace it with: '\'' */ |
140 | *bufptr++ = '\''; |
143 | *bufptr++ = '\''; |
141 | *bufptr++ = '\\'; |
144 | *bufptr++ = '\\'; |
142 | *bufptr++ = '\''; |
145 | *bufptr++ = '\''; |
143 | *bufptr++ = '\''; |
146 | *bufptr++ = '\''; |
|
|
147 | } else if (shell == TCSH && *argptr == '\\') { |
|
|
148 | /* Backslash: replace it with: '\\' */ |
|
|
149 | *bufptr++ = '\\'; |
|
|
150 | *bufptr++ = '\\'; |
144 | } else if (shell == TCSH && *argptr == '!') { |
151 | } else if (shell == TCSH && *argptr == '!') { |
145 | /* Exclamation mark: replace it with: \! */ |
152 | /* Exclamation mark: replace it with: \! */ |
146 | *bufptr++ = '\''; |
153 | *bufptr++ = '\''; |
147 | *bufptr++ = '\\'; |
154 | *bufptr++ = '\\'; |
148 | *bufptr++ = '!'; |
155 | *bufptr++ = '!'; |
… | |
… | |
238 | |
245 | |
239 | /* Register a long option. The contents of name is copied. */ |
246 | /* Register a long option. The contents of name is copied. */ |
240 | static void add_longopt(const char *name, int has_arg) |
247 | static void add_longopt(const char *name, int has_arg) |
241 | { |
248 | { |
242 | char *tmp; |
249 | char *tmp; |
|
|
250 | static int flag; |
|
|
251 | |
243 | if (!name) { |
252 | if (!name) { |
244 | /* init */ |
253 | /* init */ |
245 | free(long_options); |
254 | free(long_options); |
246 | long_options = NULL; |
255 | long_options = NULL; |
247 | long_options_length = 0; |
256 | long_options_length = 0; |
… | |
… | |
261 | long_options[long_options_nr].val = 0; |
270 | long_options[long_options_nr].val = 0; |
262 | |
271 | |
263 | if (long_options_nr && name) { |
272 | if (long_options_nr && name) { |
264 | /* Not for init! */ |
273 | /* Not for init! */ |
265 | long_options[long_options_nr - 1].has_arg = has_arg; |
274 | long_options[long_options_nr - 1].has_arg = has_arg; |
266 | long_options[long_options_nr - 1].flag = NULL; |
275 | long_options[long_options_nr - 1].flag = &flag; |
267 | long_options[long_options_nr - 1].val = LONG_OPT; |
276 | long_options[long_options_nr - 1].val = long_options_nr; |
268 | tmp = xmalloc(strlen(name) + 1); |
277 | tmp = xmalloc(strlen(name) + 1); |
269 | strcpy(tmp, name); |
278 | strcpy(tmp, name); |
270 | long_options[long_options_nr - 1].name = tmp; |
279 | long_options[long_options_nr - 1].name = tmp; |
271 | } |
280 | } |
272 | long_options_nr++; |
281 | long_options_nr++; |