VirtualBox

source: kBuild/trunk/src/kash/options.c@ 1200

Last change on this file since 1200 was 1199, checked in by bird, 17 years ago

moving globals into shinstance...

  • Property svn:eol-style set to native
File size: 11.9 KB
Line 
1/* $NetBSD: options.c,v 1.38 2005/03/20 21:38:17 dsl Exp $ */
2
3/*-
4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Kenneth Almquist.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#ifdef HAVE_SYS_CDEFS_H
36#include <sys/cdefs.h>
37#endif
38#ifndef lint
39#if 0
40static char sccsid[] = "@(#)options.c 8.2 (Berkeley) 5/4/95";
41#else
42__RCSID("$NetBSD: options.c,v 1.38 2005/03/20 21:38:17 dsl Exp $");
43#endif
44#endif /* not lint */
45
46#include <signal.h>
47#include <unistd.h>
48#include <stdlib.h>
49
50#include "shell.h"
51#define DEFINE_OPTIONS
52#include "options.h"
53#undef DEFINE_OPTIONS
54#include "nodes.h" /* for other header files */
55#include "eval.h"
56#include "jobs.h"
57#include "input.h"
58#include "output.h"
59#include "trap.h"
60#include "var.h"
61#include "memalloc.h"
62#include "error.h"
63#include "mystring.h"
64#ifndef SMALL
65#include "myhistedit.h"
66#endif
67#include "show.h"
68#include "shinstance.h"
69
70//char *arg0; /* value of $0 */
71//struct shparam shellparam; /* current positional parameters */
72//char **argptr; /* argument list for builtin commands */
73//char *optionarg; /* set by nextopt (like getopt) */
74//char *optptr; /* used by nextopt */
75
76//char *minusc; /* argument to -c option */
77
78
79STATIC void options(shinstance *, int);
80STATIC void minus_o(shinstance *, char *, int);
81STATIC void setoption(shinstance *, int, int);
82STATIC int getopts(shinstance *, char *, char *, char **, char ***, char **);
83
84
85/*
86 * Process the shell command line arguments.
87 */
88
89void
90procargs(shinstance *psh, int argc, char **argv)
91{
92 int i;
93
94 psh->argptr = argv;
95 if (argc > 0)
96 psh->argptr++;
97 for (i = 0; i < NOPTS; i++)
98 psh->optlist[i].val = 2;
99 options(psh, 1);
100 if (*psh->argptr == NULL && psh->minusc == NULL)
101 sflag(psh) = 1;
102 if (iflag(psh) == 2 && sflag(psh) == 1 && shfile_isatty(&psh->fdtab, 0) && shfile_isatty(&psh->fdtab, 1))
103 iflag(psh) = 1;
104 if (mflag(psh) == 2)
105 mflag(psh) = iflag(psh);
106 for (i = 0; i < NOPTS; i++)
107 if (psh->optlist[i].val == 2)
108 psh->optlist[i].val = 0;
109#if DEBUG == 2
110 debug(psh) = 1;
111#endif
112 psh->arg0 = argv[0];
113 if (sflag(psh) == 0 && psh->minusc == NULL) {
114 psh->commandname = argv[0];
115 psh->arg0 = *psh->argptr++;
116 setinputfile(psh, psh->arg0, 0);
117 psh->commandname = psh->arg0;
118 }
119 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
120 if (psh->minusc != NULL) {
121 if (psh->argptr == NULL || *psh->argptr == NULL)
122 error(psh, "Bad -c option");
123 psh->minusc = *psh->argptr++;
124 if (*psh->argptr != 0)
125 psh->arg0 = *psh->argptr++;
126 }
127
128 psh->shellparam.p = psh->argptr;
129 psh->shellparam.reset = 1;
130 /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
131 while (*psh->argptr) {
132 psh->shellparam.nparam++;
133 psh->argptr++;
134 }
135 optschanged(psh);
136}
137
138
139void
140optschanged(shinstance *psh)
141{
142 setinteractive(psh, iflag(psh));
143#ifndef SMALL
144 histedit(psh);
145#endif
146 setjobctl(psh, mflag(psh));
147}
148
149/*
150 * Process shell options. The global variable argptr contains a pointer
151 * to the argument list; we advance it past the options.
152 */
153
154STATIC void
155options(shinstance *psh, int cmdline)
156{
157 static char empty[] = "";
158 char *p;
159 int val;
160 int c;
161
162 if (cmdline)
163 psh->minusc = NULL;
164 while ((p = *psh->argptr) != NULL) {
165 psh->argptr++;
166 if ((c = *p++) == '-') {
167 val = 1;
168 if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
169 if (!cmdline) {
170 /* "-" means turn off -x and -v */
171 if (p[0] == '\0')
172 xflag(psh) = vflag(psh) = 0;
173 /* "--" means reset params */
174 else if (*psh->argptr == NULL)
175 setparam(psh, psh->argptr);
176 }
177 break; /* "-" or "--" terminates options */
178 }
179 } else if (c == '+') {
180 val = 0;
181 } else {
182 psh->argptr--;
183 break;
184 }
185 while ((c = *p++) != '\0') {
186 if (c == 'c' && cmdline) {
187 /* command is after shell args*/
188 psh->minusc = empty;
189 } else if (c == 'o') {
190 minus_o(psh, *psh->argptr, val);
191 if (*psh->argptr)
192 psh->argptr++;
193 } else {
194 setoption(psh, c, val);
195 }
196 }
197 }
198}
199
200static void
201set_opt_val(shinstance *psh, int i, int val)
202{
203 int j;
204 int flag;
205
206 if (val && (flag = psh->optlist[i].opt_set)) {
207 /* some options (eg vi/emacs) are mutually exclusive */
208 for (j = 0; j < NOPTS; j++)
209 if (psh->optlist[j].opt_set == flag)
210 psh->optlist[j].val = 0;
211 }
212 psh->optlist[i].val = val;
213#ifdef DEBUG
214 if (&psh->optlist[i].val == &debug(psh))
215 opentrace(psh);
216#endif
217}
218
219STATIC void
220minus_o(shinstance *psh, char *name, int val)
221{
222 int i;
223
224 if (name == NULL) {
225 out1str(psh, "Current option settings\n");
226 for (i = 0; i < NOPTS; i++)
227 out1fmt(psh, "%-16s%s\n", psh->optlist[i].name,
228 psh->optlist[i].val ? "on" : "off");
229 } else {
230 for (i = 0; i < NOPTS; i++)
231 if (equal(name, psh->optlist[i].name)) {
232 set_opt_val(psh, i, val);
233 return;
234 }
235 error(psh, "Illegal option -o %s", name);
236 }
237}
238
239
240STATIC void
241setoption(shinstance *psh, int flag, int val)
242{
243 int i;
244
245 for (i = 0; i < NOPTS; i++)
246 if (psh->optlist[i].letter == flag) {
247 set_opt_val(psh, i, val );
248 return;
249 }
250 error(psh, "Illegal option -%c", flag);
251 /* NOTREACHED */
252}
253
254
255
256#ifdef mkinit
257INCLUDE "options.h"
258
259SHELLPROC {
260 int i;
261
262 for (i = 0; psh->optlist[i].name; i++)
263 psh->optlist[i].val = 0;
264 optschanged(psh);
265
266}
267#endif
268
269
270/*
271 * Set the shell parameters.
272 */
273
274void
275setparam(shinstance *psh, char **argv)
276{
277 char **newparam;
278 char **ap;
279 int nparam;
280
281 for (nparam = 0 ; argv[nparam] ; nparam++)
282 continue;
283 ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
284 while (*argv) {
285 *ap++ = savestr(*argv++);
286 }
287 *ap = NULL;
288 freeparam(&psh->shellparam);
289 psh->shellparam.malloc = 1;
290 psh->shellparam.nparam = nparam;
291 psh->shellparam.p = newparam;
292 psh->shellparam.optnext = NULL;
293}
294
295
296/*
297 * Free the list of positional parameters.
298 */
299
300void
301freeparam(volatile struct shparam *param)
302{
303 char **ap;
304
305 if (param->malloc) {
306 for (ap = param->p ; *ap ; ap++)
307 ckfree(*ap);
308 ckfree(param->p);
309 }
310}
311
312
313
314/*
315 * The shift builtin command.
316 */
317
318int
319shiftcmd(shinstance *psh, int argc, char **argv)
320{
321 int n;
322 char **ap1, **ap2;
323
324 n = 1;
325 if (argc > 1)
326 n = number(psh, argv[1]);
327 if (n > psh->shellparam.nparam)
328 error(psh, "can't shift that many");
329 INTOFF;
330 psh->shellparam.nparam -= n;
331 for (ap1 = psh->shellparam.p ; --n >= 0 ; ap1++) {
332 if (psh->shellparam.malloc)
333 ckfree(*ap1);
334 }
335 ap2 = psh->shellparam.p;
336 while ((*ap2++ = *ap1++) != NULL);
337 psh->shellparam.optnext = NULL;
338 INTON;
339 return 0;
340}
341
342
343
344/*
345 * The set command builtin.
346 */
347
348int
349setcmd(shinstance *psh, int argc, char **argv)
350{
351 if (argc == 1)
352 return showvars(psh, 0, 0, 1);
353 INTOFF;
354 options(psh, 0);
355 optschanged(psh);
356 if (*psh->argptr != NULL) {
357 setparam(psh, psh->argptr);
358 }
359 INTON;
360 return 0;
361}
362
363
364void
365getoptsreset(shinstance *psh, const char *value)
366{
367 if (number(psh, value) == 1) {
368 psh->shellparam.optnext = NULL;
369 psh->shellparam.reset = 1;
370 }
371}
372
373/*
374 * The getopts builtin. Shellparam.optnext points to the next argument
375 * to be processed. Shellparam.optptr points to the next character to
376 * be processed in the current argument. If shellparam.optnext is NULL,
377 * then it's the first time getopts has been called.
378 */
379
380int
381getoptscmd(shinstance *psh, int argc, char **argv)
382{
383 char **optbase;
384
385 if (argc < 3)
386 error(psh, "usage: getopts optstring var [arg]");
387 else if (argc == 3)
388 optbase = psh->shellparam.p;
389 else
390 optbase = &argv[3];
391
392 if (psh->shellparam.reset == 1) {
393 psh->shellparam.optnext = optbase;
394 psh->shellparam.optptr = NULL;
395 psh->shellparam.reset = 0;
396 }
397
398 return getopts(psh, argv[1], argv[2], optbase, &psh->shellparam.optnext,
399 &psh->shellparam.optptr);
400}
401
402STATIC int
403getopts(shinstance *psh, char *optstr, char *optvar, char **optfirst, char ***optnext, char **optpptr)
404{
405 char *p, *q;
406 char c = '?';
407 int done = 0;
408 int ind = 0;
409 int err = 0;
410 char s[12];
411
412 if ((p = *optpptr) == NULL || *p == '\0') {
413 /* Current word is done, advance */
414 if (*optnext == NULL)
415 return 1;
416 p = **optnext;
417 if (p == NULL || *p != '-' || *++p == '\0') {
418atend:
419 ind = (int)(*optnext - optfirst + 1);
420 *optnext = NULL;
421 p = NULL;
422 done = 1;
423 goto out;
424 }
425 (*optnext)++;
426 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
427 goto atend;
428 }
429
430 c = *p++;
431 for (q = optstr; *q != c; ) {
432 if (*q == '\0') {
433 if (optstr[0] == ':') {
434 s[0] = c;
435 s[1] = '\0';
436 err |= setvarsafe(psh, "OPTARG", s, 0);
437 } else {
438 outfmt(&psh->errout, "Illegal option -%c\n", c);
439 (void) unsetvar(psh, "OPTARG", 0);
440 }
441 c = '?';
442 goto bad;
443 }
444 if (*++q == ':')
445 q++;
446 }
447
448 if (*++q == ':') {
449 if (*p == '\0' && (p = **optnext) == NULL) {
450 if (optstr[0] == ':') {
451 s[0] = c;
452 s[1] = '\0';
453 err |= setvarsafe(psh, "OPTARG", s, 0);
454 c = ':';
455 } else {
456 outfmt(&psh->errout, "No arg for -%c option\n", c);
457 (void) unsetvar(psh, "OPTARG", 0);
458 c = '?';
459 }
460 goto bad;
461 }
462
463 if (p == **optnext)
464 (*optnext)++;
465 err |= setvarsafe(psh, "OPTARG", p, 0);
466 p = NULL;
467 } else
468 err |= setvarsafe(psh, "OPTARG", "", 0);
469 ind = (int)(*optnext - optfirst + 1);
470 goto out;
471
472bad:
473 ind = 1;
474 *optnext = NULL;
475 p = NULL;
476out:
477 *optpptr = p;
478 fmtstr(s, sizeof(s), "%d", ind);
479 err |= setvarsafe(psh, "OPTIND", s, VNOFUNC);
480 s[0] = c;
481 s[1] = '\0';
482 err |= setvarsafe(psh, optvar, s, 0);
483 if (err) {
484 *optnext = NULL;
485 *optpptr = NULL;
486 output_flushall(psh);
487 exraise(psh, EXERROR);
488 }
489 return done;
490}
491
492/*
493 * XXX - should get rid of. have all builtins use getopt(3). the
494 * library getopt must have the BSD extension static variable "optreset"
495 * otherwise it can't be used within the shell safely.
496 *
497 * Standard option processing (a la getopt) for builtin routines. The
498 * only argument that is passed to nextopt is the option string; the
499 * other arguments are unnecessary. It return the character, or '\0' on
500 * end of input.
501 */
502
503int
504nextopt(shinstance *psh, const char *optstring)
505{
506 char *p;
507 const char *q;
508 char c;
509
510 if ((p = psh->optptr) == NULL || *p == '\0') {
511 p = *psh->argptr;
512 if (p == NULL || *p != '-' || *++p == '\0')
513 return '\0';
514 psh->argptr++;
515 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
516 return '\0';
517 }
518 c = *p++;
519 for (q = optstring ; *q != c ; ) {
520 if (*q == '\0')
521 error(psh, "Illegal option -%c", c);
522 if (*++q == ':')
523 q++;
524 }
525 if (*++q == ':') {
526 if (*p == '\0' && (p = *psh->argptr++) == NULL)
527 error(psh, "No arg for -%c option", c);
528 psh->optionarg = p;
529 p = NULL;
530 }
531 psh->optptr = p;
532 return c;
533}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette