1 /* $NetBSD: options.c,v 1.38 2005/03/20 21:38:17 dsl Exp $ */
4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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
37 static char sccsid
[] = "@(#)options.c 8.2 (Berkeley) 5/4/95";
39 __RCSID("$NetBSD: options.c,v 1.38 2005/03/20 21:38:17 dsl Exp $");
46 #define DEFINE_OPTIONS
49 #include "nodes.h" /* for other header files */
60 # include "myhistedit.h"
63 #include "shinstance.h"
65 //char *arg0; /* value of $0 */
66 //struct shparam shellparam; /* current positional parameters */
67 //char **argptr; /* argument list for builtin commands */
68 //char *optionarg; /* set by nextopt (like getopt) */
69 //char *optptr; /* used by nextopt */
71 //char *minusc; /* argument to -c option */
74 STATIC
void options(shinstance
*, int);
75 STATIC
void minus_o(shinstance
*, char *, int);
76 STATIC
void setoption(shinstance
*, int, int);
77 STATIC
int getopts(shinstance
*, char *, char *, char **, char ***, char **);
81 * Process the shell command line arguments.
85 procargs(shinstance
*psh
, int argc
, char **argv
)
92 for (i
= 0; i
< NOPTS
; i
++)
93 psh
->optlist
[i
].val
= 2;
95 if (*psh
->argptr
== NULL
&& psh
->minusc
== NULL
)
97 if (iflag(psh
) == 2 && sflag(psh
) == 1 && shfile_isatty(&psh
->fdtab
, 0) && shfile_isatty(&psh
->fdtab
, 1))
100 mflag(psh
) = iflag(psh
);
101 for (i
= 0; i
< NOPTS
; i
++)
102 if (psh
->optlist
[i
].val
== 2)
103 psh
->optlist
[i
].val
= 0;
108 if (sflag(psh
) == 0 && psh
->minusc
== NULL
) {
109 psh
->commandname
= argv
[0];
110 psh
->arg0
= *psh
->argptr
++;
111 setinputfile(psh
, psh
->arg0
, 0);
112 psh
->commandname
= psh
->arg0
;
114 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
115 if (psh
->minusc
!= NULL
) {
116 if (psh
->argptr
== NULL
|| *psh
->argptr
== NULL
)
117 error(psh
, "Bad -c option");
118 psh
->minusc
= *psh
->argptr
++;
119 if (*psh
->argptr
!= 0)
120 psh
->arg0
= *psh
->argptr
++;
123 psh
->shellparam
.p
= psh
->argptr
;
124 psh
->shellparam
.reset
= 1;
125 /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
126 while (*psh
->argptr
) {
127 psh
->shellparam
.nparam
++;
135 optschanged(shinstance
*psh
)
137 setinteractive(psh
, iflag(psh
));
141 setjobctl(psh
, mflag(psh
));
145 * Process shell options. The global variable argptr contains a pointer
146 * to the argument list; we advance it past the options.
150 options(shinstance
*psh
, int cmdline
)
152 static char empty
[] = "";
159 while ((p
= *psh
->argptr
) != NULL
) {
161 if ((c
= *p
++) == '-') {
163 if (p
[0] == '\0' || (p
[0] == '-' && p
[1] == '\0')) {
165 /* "-" means turn off -x and -v */
167 xflag(psh
) = vflag(psh
) = 0;
168 /* "--" means reset params */
169 else if (*psh
->argptr
== NULL
)
170 setparam(psh
, psh
->argptr
);
172 break; /* "-" or "--" terminates options */
174 } else if (c
== '+') {
180 while ((c
= *p
++) != '\0') {
181 if (c
== 'c' && cmdline
) {
182 /* command is after shell args*/
184 } else if (c
== 'o') {
185 minus_o(psh
, *psh
->argptr
, val
);
189 setoption(psh
, c
, val
);
196 set_opt_val(shinstance
*psh
, int i
, int val
)
201 if (val
&& (flag
= psh
->optlist
[i
].opt_set
)) {
202 /* some options (eg vi/emacs) are mutually exclusive */
203 for (j
= 0; j
< NOPTS
; j
++)
204 if (psh
->optlist
[j
].opt_set
== flag
)
205 psh
->optlist
[j
].val
= 0;
207 psh
->optlist
[i
].val
= val
;
209 if (&psh
->optlist
[i
].val
== &debug(psh
))
215 minus_o(shinstance
*psh
, char *name
, int val
)
220 out1str(psh
, "Current option settings\n");
221 for (i
= 0; i
< NOPTS
; i
++)
222 out1fmt(psh
, "%-16s%s\n", psh
->optlist
[i
].name
,
223 psh
->optlist
[i
].val
? "on" : "off");
225 for (i
= 0; i
< NOPTS
; i
++)
226 if (equal(name
, psh
->optlist
[i
].name
)) {
227 set_opt_val(psh
, i
, val
);
230 error(psh
, "Illegal option -o %s", name
);
236 setoption(shinstance
*psh
, int flag
, int val
)
240 for (i
= 0; i
< NOPTS
; i
++)
241 if (psh
->optlist
[i
].letter
== flag
) {
242 set_opt_val(psh
, i
, val
);
245 error(psh
, "Illegal option -%c", flag
);
255 memcpy(&psh
->optlist
[0], &ro_optlist
[0], sizeof(psh
->optlist
));
261 for (i
= 0; psh
->optlist
[i
].name
; i
++)
262 psh
->optlist
[i
].val
= 0;
270 * Set the shell parameters.
274 setparam(shinstance
*psh
, char **argv
)
280 for (nparam
= 0 ; argv
[nparam
] ; nparam
++)
282 ap
= newparam
= ckmalloc((nparam
+ 1) * sizeof *ap
);
284 *ap
++ = savestr(*argv
++);
287 freeparam(&psh
->shellparam
);
288 psh
->shellparam
.malloc
= 1;
289 psh
->shellparam
.nparam
= nparam
;
290 psh
->shellparam
.p
= newparam
;
291 psh
->shellparam
.optnext
= NULL
;
296 * Free the list of positional parameters.
300 freeparam(volatile struct shparam
*param
)
305 for (ap
= param
->p
; *ap
; ap
++)
314 * The shift builtin command.
318 shiftcmd(shinstance
*psh
, int argc
, char **argv
)
325 n
= number(psh
, argv
[1]);
326 if (n
> psh
->shellparam
.nparam
)
327 error(psh
, "can't shift that many");
329 psh
->shellparam
.nparam
-= n
;
330 for (ap1
= psh
->shellparam
.p
; --n
>= 0 ; ap1
++) {
331 if (psh
->shellparam
.malloc
)
334 ap2
= psh
->shellparam
.p
;
335 while ((*ap2
++ = *ap1
++) != NULL
);
336 psh
->shellparam
.optnext
= NULL
;
344 * The set command builtin.
348 setcmd(shinstance
*psh
, int argc
, char **argv
)
351 return showvars(psh
, 0, 0, 1);
355 if (*psh
->argptr
!= NULL
) {
356 setparam(psh
, psh
->argptr
);
364 getoptsreset(shinstance
*psh
, const char *value
)
366 if (number(psh
, value
) == 1) {
367 psh
->shellparam
.optnext
= NULL
;
368 psh
->shellparam
.reset
= 1;
373 * The getopts builtin. Shellparam.optnext points to the next argument
374 * to be processed. Shellparam.optptr points to the next character to
375 * be processed in the current argument. If shellparam.optnext is NULL,
376 * then it's the first time getopts has been called.
380 getoptscmd(shinstance
*psh
, int argc
, char **argv
)
385 error(psh
, "usage: getopts optstring var [arg]");
387 optbase
= psh
->shellparam
.p
;
391 if (psh
->shellparam
.reset
== 1) {
392 psh
->shellparam
.optnext
= optbase
;
393 psh
->shellparam
.optptr
= NULL
;
394 psh
->shellparam
.reset
= 0;
397 return getopts(psh
, argv
[1], argv
[2], optbase
, &psh
->shellparam
.optnext
,
398 &psh
->shellparam
.optptr
);
402 getopts(shinstance
*psh
, char *optstr
, char *optvar
, char **optfirst
, char ***optnext
, char **optpptr
)
411 if ((p
= *optpptr
) == NULL
|| *p
== '\0') {
412 /* Current word is done, advance */
413 if (*optnext
== NULL
)
416 if (p
== NULL
|| *p
!= '-' || *++p
== '\0') {
418 ind
= (int)(*optnext
- optfirst
+ 1);
425 if (p
[0] == '-' && p
[1] == '\0') /* check for "--" */
430 for (q
= optstr
; *q
!= c
; ) {
432 if (optstr
[0] == ':') {
435 err
|= setvarsafe(psh
, "OPTARG", s
, 0);
437 outfmt(&psh
->errout
, "Illegal option -%c\n", c
);
438 (void) unsetvar(psh
, "OPTARG", 0);
448 if (*p
== '\0' && (p
= **optnext
) == NULL
) {
449 if (optstr
[0] == ':') {
452 err
|= setvarsafe(psh
, "OPTARG", s
, 0);
455 outfmt(&psh
->errout
, "No arg for -%c option\n", c
);
456 (void) unsetvar(psh
, "OPTARG", 0);
464 err
|= setvarsafe(psh
, "OPTARG", p
, 0);
467 err
|= setvarsafe(psh
, "OPTARG", "", 0);
468 ind
= (int)(*optnext
- optfirst
+ 1);
477 fmtstr(s
, sizeof(s
), "%d", ind
);
478 err
|= setvarsafe(psh
, "OPTIND", s
, VNOFUNC
);
481 err
|= setvarsafe(psh
, optvar
, s
, 0);
485 output_flushall(psh
);
486 exraise(psh
, EXERROR
);
492 * XXX - should get rid of. have all builtins use getopt(3). the
493 * library getopt must have the BSD extension static variable "optreset"
494 * otherwise it can't be used within the shell safely.
496 * Standard option processing (a la getopt) for builtin routines. The
497 * only argument that is passed to nextopt is the option string; the
498 * other arguments are unnecessary. It return the character, or '\0' on
503 nextopt(shinstance
*psh
, const char *optstring
)
509 if ((p
= psh
->optptr
) == NULL
|| *p
== '\0') {
511 if (p
== NULL
|| *p
!= '-' || *++p
== '\0')
514 if (p
[0] == '-' && p
[1] == '\0') /* check for "--" */
518 for (q
= optstring
; *q
!= c
; ) {
520 error(psh
, "Illegal option -%c", c
);
525 if (*p
== '\0' && (p
= *psh
->argptr
++) == NULL
)
526 error(psh
, "No arg for -%c option", c
);