aboutsummaryrefslogtreecommitdiff
path: root/util-linux/getopt.c
diff options
context:
space:
mode:
Diffstat (limited to 'util-linux/getopt.c')
-rw-r--r--util-linux/getopt.c456
1 files changed, 228 insertions, 228 deletions
diff --git a/util-linux/getopt.c b/util-linux/getopt.c
index fc3b9f97e..16dcbbca0 100644
--- a/util-linux/getopt.c
+++ b/util-linux/getopt.c
@@ -71,7 +71,7 @@ static int alternative; /* 0 is getopt_long, 1 is getopt_long_only */
71/* Function prototypes */ 71/* Function prototypes */
72static const char *normalize(const char *arg); 72static const char *normalize(const char *arg);
73static int generate_output(char * argv[],int argc,const char *optstr, 73static int generate_output(char * argv[],int argc,const char *optstr,
74 const struct option *longopts); 74 const struct option *longopts);
75static void add_long_options(char *options); 75static void add_long_options(char *options);
76static void add_longopt(const char *name,int has_arg); 76static void add_longopt(const char *name,int has_arg);
77static void set_shell(const char *new_shell); 77static void set_shell(const char *new_shell);
@@ -88,57 +88,57 @@ static void set_shell(const char *new_shell);
88 */ 88 */
89const char *normalize(const char *arg) 89const char *normalize(const char *arg)
90{ 90{
91 static char *BUFFER=NULL; 91 static char *BUFFER=NULL;
92 const char *argptr=arg; 92 const char *argptr=arg;
93 char *bufptr; 93 char *bufptr;
94 94
95 free(BUFFER); 95 free(BUFFER);
96 96
97 if (!quote) { /* Just copy arg */ 97 if (!quote) { /* Just copy arg */
98 BUFFER=bb_xstrdup(arg); 98 BUFFER=bb_xstrdup(arg);
99 return BUFFER; 99 return BUFFER;
100 } 100 }
101 101
102 /* Each character in arg may take up to four characters in the result: 102 /* Each character in arg may take up to four characters in the result:
103 For a quote we need a closing quote, a backslash, a quote and an 103 For a quote we need a closing quote, a backslash, a quote and an
104 opening quote! We need also the global opening and closing quote, 104 opening quote! We need also the global opening and closing quote,
105 and one extra character for '\0'. */ 105 and one extra character for '\0'. */
106 BUFFER=xmalloc(strlen(arg)*4+3); 106 BUFFER=xmalloc(strlen(arg)*4+3);
107 107
108 bufptr=BUFFER; 108 bufptr=BUFFER;
109 *bufptr++='\''; 109 *bufptr++='\'';
110 110
111 while (*argptr) { 111 while (*argptr) {
112 if (*argptr == '\'') { 112 if (*argptr == '\'') {
113 /* Quote: replace it with: '\'' */ 113 /* Quote: replace it with: '\'' */
114 *bufptr++='\''; 114 *bufptr++='\'';
115 *bufptr++='\\'; 115 *bufptr++='\\';
116 *bufptr++='\''; 116 *bufptr++='\'';
117 *bufptr++='\''; 117 *bufptr++='\'';
118 } else if (shell==TCSH && *argptr=='!') { 118 } else if (shell==TCSH && *argptr=='!') {
119 /* Exclamation mark: replace it with: \! */ 119 /* Exclamation mark: replace it with: \! */
120 *bufptr++='\''; 120 *bufptr++='\'';
121 *bufptr++='\\'; 121 *bufptr++='\\';
122 *bufptr++='!'; 122 *bufptr++='!';
123 *bufptr++='\''; 123 *bufptr++='\'';
124 } else if (shell==TCSH && *argptr=='\n') { 124 } else if (shell==TCSH && *argptr=='\n') {
125 /* Newline: replace it with: \n */ 125 /* Newline: replace it with: \n */
126 *bufptr++='\\'; 126 *bufptr++='\\';
127 *bufptr++='n'; 127 *bufptr++='n';
128 } else if (shell==TCSH && isspace(*argptr)) { 128 } else if (shell==TCSH && isspace(*argptr)) {
129 /* Non-newline whitespace: replace it with \<ws> */ 129 /* Non-newline whitespace: replace it with \<ws> */
130 *bufptr++='\''; 130 *bufptr++='\'';
131 *bufptr++='\\'; 131 *bufptr++='\\';
132 *bufptr++=*argptr; 132 *bufptr++=*argptr;
133 *bufptr++='\''; 133 *bufptr++='\'';
134 } else 134 } else
135 /* Just copy */ 135 /* Just copy */
136 *bufptr++=*argptr; 136 *bufptr++=*argptr;
137 argptr++; 137 argptr++;
138 } 138 }
139 *bufptr++='\''; 139 *bufptr++='\'';
140 *bufptr++='\0'; 140 *bufptr++='\0';
141 return BUFFER; 141 return BUFFER;
142} 142}
143 143
144/* 144/*
@@ -149,47 +149,47 @@ const char *normalize(const char *arg)
149 * Other settings are found in global variables. 149 * Other settings are found in global variables.
150 */ 150 */
151int generate_output(char * argv[],int argc,const char *optstr, 151int generate_output(char * argv[],int argc,const char *optstr,
152 const struct option *longopts) 152 const struct option *longopts)
153{ 153{
154 int exit_code = 0; /* We assume everything will be OK */ 154 int exit_code = 0; /* We assume everything will be OK */
155 int opt; 155 int opt;
156 int longindex; 156 int longindex;
157 const char *charptr; 157 const char *charptr;
158 158
159 if (quiet_errors) /* No error reporting from getopt(3) */ 159 if (quiet_errors) /* No error reporting from getopt(3) */
160 opterr=0; 160 opterr=0;
161 optind=0; /* Reset getopt(3) */ 161 optind=0; /* Reset getopt(3) */
162 162
163 while ((opt = (alternative? 163 while ((opt = (alternative?
164 getopt_long_only(argc,argv,optstr,longopts,&longindex): 164 getopt_long_only(argc,argv,optstr,longopts,&longindex):
165 getopt_long(argc,argv,optstr,longopts,&longindex))) 165 getopt_long(argc,argv,optstr,longopts,&longindex)))
166 != EOF) 166 != EOF)
167 if (opt == '?' || opt == ':' ) 167 if (opt == '?' || opt == ':' )
168 exit_code = 1; 168 exit_code = 1;
169 else if (!quiet_output) { 169 else if (!quiet_output) {
170 if (opt == LONG_OPT) { 170 if (opt == LONG_OPT) {
171 printf(" --%s",longopts[longindex].name); 171 printf(" --%s",longopts[longindex].name);
172 if (longopts[longindex].has_arg) 172 if (longopts[longindex].has_arg)
173 printf(" %s", 173 printf(" %s",
174 normalize(optarg?optarg:"")); 174 normalize(optarg?optarg:""));
175 } else if (opt == NON_OPT) 175 } else if (opt == NON_OPT)
176 printf(" %s",normalize(optarg)); 176 printf(" %s",normalize(optarg));
177 else { 177 else {
178 printf(" -%c",opt); 178 printf(" -%c",opt);
179 charptr = strchr(optstr,opt); 179 charptr = strchr(optstr,opt);
180 if (charptr != NULL && *++charptr == ':') 180 if (charptr != NULL && *++charptr == ':')
181 printf(" %s", 181 printf(" %s",
182 normalize(optarg?optarg:"")); 182 normalize(optarg?optarg:""));
183 } 183 }
184 } 184 }
185 185
186 if (! quiet_output) { 186 if (! quiet_output) {
187 printf(" --"); 187 printf(" --");
188 while (optind < argc) 188 while (optind < argc)
189 printf(" %s",normalize(argv[optind++])); 189 printf(" %s",normalize(argv[optind++]));
190 printf("\n"); 190 printf("\n");
191 } 191 }
192 return exit_code; 192 return exit_code;
193} 193}
194 194
195static struct option *long_options; 195static struct option *long_options;
@@ -201,32 +201,32 @@ static const int LONG_OPTIONS_INCR = 10;
201/* Register a long option. The contents of name is copied. */ 201/* Register a long option. The contents of name is copied. */
202void add_longopt(const char *name,int has_arg) 202void add_longopt(const char *name,int has_arg)
203{ 203{
204 if (!name) { /* init */ 204 if (!name) { /* init */
205 free(long_options); 205 free(long_options);
206 long_options=NULL; 206 long_options=NULL;
207 long_options_length=0; 207 long_options_length=0;
208 long_options_nr=0; 208 long_options_nr=0;
209 } 209 }
210 210
211 if (long_options_nr == long_options_length) { 211 if (long_options_nr == long_options_length) {
212 long_options_length += LONG_OPTIONS_INCR; 212 long_options_length += LONG_OPTIONS_INCR;
213 long_options=xrealloc(long_options, 213 long_options=xrealloc(long_options,
214 sizeof(struct option) * 214 sizeof(struct option) *
215 long_options_length); 215 long_options_length);
216 } 216 }
217 217
218 long_options[long_options_nr].name=NULL; 218 long_options[long_options_nr].name=NULL;
219 long_options[long_options_nr].has_arg=0; 219 long_options[long_options_nr].has_arg=0;
220 long_options[long_options_nr].flag=NULL; 220 long_options[long_options_nr].flag=NULL;
221 long_options[long_options_nr].val=0; 221 long_options[long_options_nr].val=0;
222 222
223 if (long_options_nr) { /* Not for init! */ 223 if (long_options_nr) { /* Not for init! */
224 long_options[long_options_nr-1].has_arg=has_arg; 224 long_options[long_options_nr-1].has_arg=has_arg;
225 long_options[long_options_nr-1].flag=NULL; 225 long_options[long_options_nr-1].flag=NULL;
226 long_options[long_options_nr-1].val=LONG_OPT; 226 long_options[long_options_nr-1].val=LONG_OPT;
227 long_options[long_options_nr-1].name=bb_xstrdup(name); 227 long_options[long_options_nr-1].name=bb_xstrdup(name);
228 } 228 }
229 long_options_nr++; 229 long_options_nr++;
230} 230}
231 231
232 232
@@ -237,43 +237,43 @@ void add_longopt(const char *name,int has_arg)
237 */ 237 */
238void add_long_options(char *options) 238void add_long_options(char *options)
239{ 239{
240 int arg_opt, tlen; 240 int arg_opt, tlen;
241 char *tokptr=strtok(options,", \t\n"); 241 char *tokptr=strtok(options,", \t\n");
242 while (tokptr) { 242 while (tokptr) {
243 arg_opt=no_argument; 243 arg_opt=no_argument;
244 tlen=strlen(tokptr); 244 tlen=strlen(tokptr);
245 if (tlen > 0) { 245 if (tlen > 0) {
246 if (tokptr[tlen-1] == ':') { 246 if (tokptr[tlen-1] == ':') {
247 if (tlen > 1 && tokptr[tlen-2] == ':') { 247 if (tlen > 1 && tokptr[tlen-2] == ':') {
248 tokptr[tlen-2]='\0'; 248 tokptr[tlen-2]='\0';
249 tlen -= 2; 249 tlen -= 2;
250 arg_opt=optional_argument; 250 arg_opt=optional_argument;
251 } else { 251 } else {
252 tokptr[tlen-1]='\0'; 252 tokptr[tlen-1]='\0';
253 tlen -= 1; 253 tlen -= 1;
254 arg_opt=required_argument; 254 arg_opt=required_argument;
255 } 255 }
256 if (tlen == 0) 256 if (tlen == 0)
257 bb_error_msg("empty long option after -l or --long argument"); 257 bb_error_msg("empty long option after -l or --long argument");
258 } 258 }
259 add_longopt(tokptr,arg_opt); 259 add_longopt(tokptr,arg_opt);
260 } 260 }
261 tokptr=strtok(NULL,", \t\n"); 261 tokptr=strtok(NULL,", \t\n");
262 } 262 }
263} 263}
264 264
265void set_shell(const char *new_shell) 265void set_shell(const char *new_shell)
266{ 266{
267 if (!strcmp(new_shell,"bash")) 267 if (!strcmp(new_shell,"bash"))
268 shell=BASH; 268 shell=BASH;
269 else if (!strcmp(new_shell,"tcsh")) 269 else if (!strcmp(new_shell,"tcsh"))
270 shell=TCSH; 270 shell=TCSH;
271 else if (!strcmp(new_shell,"sh")) 271 else if (!strcmp(new_shell,"sh"))
272 shell=BASH; 272 shell=BASH;
273 else if (!strcmp(new_shell,"csh")) 273 else if (!strcmp(new_shell,"csh"))
274 shell=TCSH; 274 shell=TCSH;
275 else 275 else
276 bb_error_msg("unknown shell after -s or --shell argument"); 276 bb_error_msg("unknown shell after -s or --shell argument");
277} 277}
278 278
279 279
@@ -287,16 +287,16 @@ void set_shell(const char *new_shell)
287 287
288static const struct option longopts[]= 288static const struct option longopts[]=
289{ 289{
290 {"options",required_argument,NULL,'o'}, 290 {"options",required_argument,NULL,'o'},
291 {"longoptions",required_argument,NULL,'l'}, 291 {"longoptions",required_argument,NULL,'l'},
292 {"quiet",no_argument,NULL,'q'}, 292 {"quiet",no_argument,NULL,'q'},
293 {"quiet-output",no_argument,NULL,'Q'}, 293 {"quiet-output",no_argument,NULL,'Q'},
294 {"shell",required_argument,NULL,'s'}, 294 {"shell",required_argument,NULL,'s'},
295 {"test",no_argument,NULL,'T'}, 295 {"test",no_argument,NULL,'T'},
296 {"unquoted",no_argument,NULL,'u'}, 296 {"unquoted",no_argument,NULL,'u'},
297 {"alternative",no_argument,NULL,'a'}, 297 {"alternative",no_argument,NULL,'a'},
298 {"name",required_argument,NULL,'n'}, 298 {"name",required_argument,NULL,'n'},
299 {NULL,0,NULL,0} 299 {NULL,0,NULL,0}
300}; 300};
301 301
302/* Stop scanning as soon as a non-option argument is found! */ 302/* Stop scanning as soon as a non-option argument is found! */
@@ -305,77 +305,77 @@ static const char shortopts[]="+ao:l:n:qQs:Tu";
305 305
306int getopt_main(int argc, char *argv[]) 306int getopt_main(int argc, char *argv[])
307{ 307{
308 const char *optstr = NULL; 308 const char *optstr = NULL;
309 char *name = NULL; 309 char *name = NULL;
310 int opt; 310 int opt;
311 int compatible=0; 311 int compatible=0;
312 312
313 init_longopt(); 313 init_longopt();
314 314
315 if (getenv("GETOPT_COMPATIBLE")) 315 if (getenv("GETOPT_COMPATIBLE"))
316 compatible=1; 316 compatible=1;
317 317
318 if (argc == 1) { 318 if (argc == 1) {
319 if (compatible) { 319 if (compatible) {
320 /* For some reason, the original getopt gave no error 320 /* For some reason, the original getopt gave no error
321 when there were no arguments. */ 321 when there were no arguments. */
322 printf(" --\n"); 322 printf(" --\n");
323 return 0; 323 return 0;
324 } else 324 } else
325 bb_error_msg_and_die("missing optstring argument"); 325 bb_error_msg_and_die("missing optstring argument");
326 } 326 }
327 327
328 if (argv[1][0] != '-' || compatible) { 328 if (argv[1][0] != '-' || compatible) {
329 char *s; 329 char *s;
330 330
331 quote=0; 331 quote=0;
332 s=xmalloc(strlen(argv[1])+1); 332 s=xmalloc(strlen(argv[1])+1);
333 strcpy(s,argv[1]+strspn(argv[1],"-+")); 333 strcpy(s,argv[1]+strspn(argv[1],"-+"));
334 argv[1]=argv[0]; 334 argv[1]=argv[0];
335 return (generate_output(argv+1,argc-1,s,long_options)); 335 return (generate_output(argv+1,argc-1,s,long_options));
336 } 336 }
337 337
338 while ((opt=getopt_long(argc,argv,shortopts,longopts,NULL)) != EOF) 338 while ((opt=getopt_long(argc,argv,shortopts,longopts,NULL)) != EOF)
339 switch (opt) { 339 switch (opt) {
340 case 'a': 340 case 'a':
341 alternative=1; 341 alternative=1;
342 break; 342 break;
343 case 'o': 343 case 'o':
344 optstr = optarg; 344 optstr = optarg;
345 break; 345 break;
346 case 'l': 346 case 'l':
347 add_long_options(optarg); 347 add_long_options(optarg);
348 break; 348 break;
349 case 'n': 349 case 'n':
350 name = optarg; 350 name = optarg;
351 break; 351 break;
352 case 'q': 352 case 'q':
353 quiet_errors=1; 353 quiet_errors=1;
354 break; 354 break;
355 case 'Q': 355 case 'Q':
356 quiet_output=1; 356 quiet_output=1;
357 break; 357 break;
358 case 's': 358 case 's':
359 set_shell(optarg); 359 set_shell(optarg);
360 break; 360 break;
361 case 'T': 361 case 'T':
362 return 4; 362 return 4;
363 case 'u': 363 case 'u':
364 quote=0; 364 quote=0;
365 break; 365 break;
366 default: 366 default:
367 bb_show_usage(); 367 bb_show_usage();
368 } 368 }
369 369
370 if (!optstr) { 370 if (!optstr) {
371 if (optind >= argc) 371 if (optind >= argc)
372 bb_error_msg_and_die("missing optstring argument"); 372 bb_error_msg_and_die("missing optstring argument");
373 else optstr=argv[optind++]; 373 else optstr=argv[optind++];
374 } 374 }
375 if (name) 375 if (name)
376 argv[optind-1]=name; 376 argv[optind-1]=name;
377 else 377 else
378 argv[optind-1]=argv[0]; 378 argv[optind-1]=argv[0];
379 return (generate_output(argv+optind-1,argc-optind+1,optstr,long_options)); 379 return (generate_output(argv+optind-1,argc-optind+1,optstr,long_options));
380} 380}
381 381