xref: /csrg-svn/bin/sh/options.c (revision 47299)
147135Sbostic /*-
247135Sbostic  * Copyright (c) 1991 The Regents of the University of California.
347135Sbostic  * All rights reserved.
447135Sbostic  *
547135Sbostic  * This code is derived from software contributed to Berkeley by
647135Sbostic  * Kenneth Almquist.
747135Sbostic  *
847135Sbostic  * %sccs.include.redist.c%
947135Sbostic  */
1047135Sbostic 
1147135Sbostic #ifndef lint
12*47299Smarc static char sccsid[] = "@(#)options.c	5.2 (Berkeley) 03/13/91";
1347135Sbostic #endif /* not lint */
1447135Sbostic 
1547135Sbostic #include "shell.h"
1647135Sbostic #define DEFINE_OPTIONS
1747135Sbostic #include "options.h"
1847135Sbostic #undef DEFINE_OPTIONS
1947135Sbostic #include "nodes.h"	/* for other header files */
2047135Sbostic #include "eval.h"
2147135Sbostic #include "jobs.h"
2247135Sbostic #include "input.h"
2347135Sbostic #include "output.h"
2447135Sbostic #include "trap.h"
2547135Sbostic #include "var.h"
2647135Sbostic #include "memalloc.h"
2747135Sbostic #include "error.h"
2847135Sbostic #include "mystring.h"
2947135Sbostic 
3047135Sbostic char *arg0;			/* value of $0 */
3147135Sbostic struct shparam shellparam;	/* current positional parameters */
3247135Sbostic char **argptr;			/* argument list for builtin commands */
3347135Sbostic char *optarg;			/* set by nextopt (like getopt) */
3447135Sbostic char *optptr;			/* used by nextopt */
3547135Sbostic 
3647135Sbostic char *minusc;			/* argument to -c option */
3747135Sbostic 
3847135Sbostic 
3947135Sbostic #ifdef __STDC__
4047135Sbostic STATIC void options(int);
4147135Sbostic STATIC void setoption(int, int);
4247135Sbostic #else
4347135Sbostic STATIC void options();
4447135Sbostic STATIC void setoption();
4547135Sbostic #endif
4647135Sbostic 
4747135Sbostic 
4847135Sbostic 
4947135Sbostic /*
5047135Sbostic  * Process the shell command line arguments.
5147135Sbostic  */
5247135Sbostic 
5347135Sbostic void
5447135Sbostic procargs(argc, argv)
5547135Sbostic 	char **argv;
5647135Sbostic 	{
5747135Sbostic 	char *p;
5847135Sbostic 
5947135Sbostic 	argptr = argv;
6047135Sbostic 	if (argc > 0)
6147135Sbostic 		argptr++;
6247135Sbostic 	for (p = optval ; p < optval + sizeof optval - 1 ; p++)
6347135Sbostic 		*p = 2;
6447135Sbostic 	options(1);
6547135Sbostic 	if (*argptr == NULL && minusc == NULL)
6647135Sbostic 		sflag = 1;
6747135Sbostic 	if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
6847135Sbostic 		iflag = 1;
6947135Sbostic 	if (jflag == 2)
7047135Sbostic 		jflag = iflag;
7147135Sbostic 	for (p = optval ; p < optval + sizeof optval - 1 ; p++)
7247135Sbostic 		if (*p == 2)
7347135Sbostic 			*p = 0;
7447135Sbostic 	arg0 = argv[0];
7547135Sbostic 	if (sflag == 0 && minusc == NULL) {
7647135Sbostic 		commandname = arg0 = *argptr++;
7747135Sbostic 		setinputfile(commandname, 0);
7847135Sbostic 	}
7947135Sbostic 	shellparam.p = argptr;
8047135Sbostic 	/* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
8147135Sbostic 	while (*argptr) {
8247135Sbostic 		shellparam.nparam++;
8347135Sbostic 		argptr++;
8447135Sbostic 	}
8547135Sbostic 	setinteractive(iflag);
8647135Sbostic 	setjobctl(jflag);
8747135Sbostic }
8847135Sbostic 
8947135Sbostic 
9047135Sbostic 
9147135Sbostic /*
9247135Sbostic  * Process shell options.  The global variable argptr contains a pointer
9347135Sbostic  * to the argument list; we advance it past the options.
9447135Sbostic  */
9547135Sbostic 
9647135Sbostic STATIC void
9747135Sbostic options(cmdline) {
9847135Sbostic 	register char *p;
9947135Sbostic 	int val;
10047135Sbostic 	int c;
10147135Sbostic 
102*47299Smarc 	if (cmdline)
103*47299Smarc 		minusc = NULL;
10447135Sbostic 	while ((p = *argptr) != NULL) {
10547135Sbostic 		argptr++;
10647135Sbostic 		if ((c = *p++) == '-') {
10747135Sbostic 			val = 1;
108*47299Smarc                         if (p[0] == '\0' || p[0] == '-' && p[1] == '\0') {
109*47299Smarc                                 if (!cmdline) {
110*47299Smarc                                         /* "-" means turn off -x and -v */
111*47299Smarc                                         if (p[0] == '\0')
112*47299Smarc                                                 xflag = vflag = 0;
113*47299Smarc                                         /* "--" means reset params */
114*47299Smarc                                         else if (*argptr == NULL)
115*47299Smarc                                                 setparam(argptr);
116*47299Smarc                                 }
11747135Sbostic 				break;	  /* "-" or  "--" terminates options */
118*47299Smarc 			}
11947135Sbostic 		} else if (c == '+') {
12047135Sbostic 			val = 0;
12147135Sbostic 		} else {
12247135Sbostic 			argptr--;
12347135Sbostic 			break;
12447135Sbostic 		}
12547135Sbostic 		while ((c = *p++) != '\0') {
12647135Sbostic 			if (c == 'c' && cmdline) {
12747135Sbostic 				char *q;
128*47299Smarc #ifdef NOHACK	/* removing this code allows sh -ce 'foo' for compat */
12947135Sbostic 				if (*p == '\0')
13047135Sbostic #endif
13147135Sbostic 					q = *argptr++;
13247135Sbostic 				if (q == NULL || minusc != NULL)
13347135Sbostic 					error("Bad -c option");
13447135Sbostic 				minusc = q;
13547135Sbostic #ifdef NOHACK
13647135Sbostic 				break;
13747135Sbostic #endif
13847135Sbostic 			} else {
13947135Sbostic 				setoption(c, val);
14047135Sbostic 			}
14147135Sbostic 		}
14247135Sbostic 		if (! cmdline)
14347135Sbostic 			break;
14447135Sbostic 	}
14547135Sbostic }
14647135Sbostic 
14747135Sbostic 
14847135Sbostic STATIC void
14947135Sbostic setoption(flag, val)
15047135Sbostic 	char flag;
15147135Sbostic 	int val;
15247135Sbostic 	{
15347135Sbostic 	register char *p;
15447135Sbostic 
15547135Sbostic 	if ((p = strchr(optchar, flag)) == NULL)
15647135Sbostic 		error("Illegal option -%c", flag);
15747135Sbostic 	optval[p - optchar] = val;
15847135Sbostic }
15947135Sbostic 
16047135Sbostic 
16147135Sbostic 
16247135Sbostic #ifdef mkinit
16347135Sbostic INCLUDE "options.h"
16447135Sbostic 
16547135Sbostic SHELLPROC {
16647135Sbostic 	char *p;
16747135Sbostic 
16847135Sbostic 	for (p = optval ; p < optval + sizeof optval ; p++)
16947135Sbostic 		*p = 0;
17047135Sbostic }
17147135Sbostic #endif
17247135Sbostic 
17347135Sbostic 
17447135Sbostic /*
17547135Sbostic  * Set the shell parameters.
17647135Sbostic  */
17747135Sbostic 
17847135Sbostic void
17947135Sbostic setparam(argv)
18047135Sbostic 	char **argv;
18147135Sbostic 	{
18247135Sbostic 	char **newparam;
18347135Sbostic 	char **ap;
18447135Sbostic 	int nparam;
18547135Sbostic 
18647135Sbostic 	for (nparam = 0 ; argv[nparam] ; nparam++);
18747135Sbostic 	ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
18847135Sbostic 	while (*argv) {
18947135Sbostic 		*ap++ = savestr(*argv++);
19047135Sbostic 	}
19147135Sbostic 	*ap = NULL;
19247135Sbostic 	freeparam(&shellparam);
19347135Sbostic 	shellparam.malloc = 1;
19447135Sbostic 	shellparam.nparam = nparam;
19547135Sbostic 	shellparam.p = newparam;
19647135Sbostic 	shellparam.optnext = NULL;
19747135Sbostic }
19847135Sbostic 
19947135Sbostic 
20047135Sbostic /*
20147135Sbostic  * Free the list of positional parameters.
20247135Sbostic  */
20347135Sbostic 
20447135Sbostic void
20547135Sbostic freeparam(param)
20647135Sbostic 	struct shparam *param;
20747135Sbostic 	{
20847135Sbostic 	char **ap;
20947135Sbostic 
21047135Sbostic 	if (param->malloc) {
21147135Sbostic 		for (ap = param->p ; *ap ; ap++)
21247135Sbostic 			ckfree(*ap);
21347135Sbostic 		ckfree(param->p);
21447135Sbostic 	}
21547135Sbostic }
21647135Sbostic 
21747135Sbostic 
21847135Sbostic 
21947135Sbostic /*
22047135Sbostic  * The shift builtin command.
22147135Sbostic  */
22247135Sbostic 
22347135Sbostic shiftcmd(argc, argv)  char **argv; {
22447135Sbostic 	int n;
22547135Sbostic 	char **ap1, **ap2;
22647135Sbostic 
22747135Sbostic 	n = 1;
22847135Sbostic 	if (argc > 1)
22947135Sbostic 		n = number(argv[1]);
23047135Sbostic 	if (n > shellparam.nparam)
23147135Sbostic 		n = shellparam.nparam;
23247135Sbostic 	INTOFF;
23347135Sbostic 	shellparam.nparam -= n;
23447135Sbostic 	for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
23547135Sbostic 		if (shellparam.malloc)
23647135Sbostic 			ckfree(*ap1);
23747135Sbostic 	}
23847135Sbostic 	ap2 = shellparam.p;
23947135Sbostic 	while ((*ap2++ = *ap1++) != NULL);
24047135Sbostic 	shellparam.optnext = NULL;
24147135Sbostic 	INTON;
24247135Sbostic 	return 0;
24347135Sbostic }
24447135Sbostic 
24547135Sbostic 
24647135Sbostic 
24747135Sbostic /*
24847135Sbostic  * The set command builtin.
24947135Sbostic  */
25047135Sbostic 
25147135Sbostic setcmd(argc, argv)  char **argv; {
25247135Sbostic 	if (argc == 1)
25347135Sbostic 		return showvarscmd(argc, argv);
25447135Sbostic 	INTOFF;
25547135Sbostic 	options(0);
25647135Sbostic 	setinteractive(iflag);
25747135Sbostic 	setjobctl(jflag);
25847135Sbostic 	if (*argptr != NULL) {
25947135Sbostic 		setparam(argptr);
26047135Sbostic 	}
26147135Sbostic 	INTON;
26247135Sbostic 	return 0;
26347135Sbostic }
26447135Sbostic 
26547135Sbostic 
26647135Sbostic /*
26747135Sbostic  * The getopts builtin.  Shellparam.optnext points to the next argument
26847135Sbostic  * to be processed.  Shellparam.optptr points to the next character to
26947135Sbostic  * be processed in the current argument.  If shellparam.optnext is NULL,
27047135Sbostic  * then it's the first time getopts has been called.
27147135Sbostic  */
27247135Sbostic 
27347135Sbostic getoptscmd(argc, argv)  char **argv; {
27447135Sbostic 	register char *p, *q;
27547135Sbostic 	char c;
27647135Sbostic 	char s[10];
27747135Sbostic 
27847135Sbostic 	if (argc != 3)
27947135Sbostic 		error("Usage: getopts optstring var");
28047135Sbostic 	if (shellparam.optnext == NULL) {
28147135Sbostic 		shellparam.optnext = shellparam.p;
28247135Sbostic 		shellparam.optptr = NULL;
28347135Sbostic 	}
28447135Sbostic 	if ((p = shellparam.optptr) == NULL || *p == '\0') {
28547135Sbostic 		p = *shellparam.optnext;
28647135Sbostic 		if (p == NULL || *p != '-' || *++p == '\0') {
28747135Sbostic atend:
28847135Sbostic 			fmtstr(s, 10, "%d", shellparam.optnext - shellparam.p + 1);
28947135Sbostic 			setvar("OPTIND", s, 0);
29047135Sbostic 			shellparam.optnext = NULL;
29147135Sbostic 			return 1;
29247135Sbostic 		}
29347135Sbostic 		shellparam.optnext++;
29447135Sbostic 		if (p[0] == '-' && p[1] == '\0')	/* check for "--" */
29547135Sbostic 			goto atend;
29647135Sbostic 	}
29747135Sbostic 	c = *p++;
29847135Sbostic 	for (q = argv[1] ; *q != c ; ) {
29947135Sbostic 		if (*q == '\0') {
30047135Sbostic 			out1fmt("Illegal option -%c\n", c);
30147135Sbostic 			c = '?';
30247135Sbostic 			goto out;
30347135Sbostic 		}
30447135Sbostic 		if (*++q == ':')
30547135Sbostic 			q++;
30647135Sbostic 	}
30747135Sbostic 	if (*++q == ':') {
30847135Sbostic 		if (*p == '\0' && (p = *shellparam.optnext) == NULL) {
30947135Sbostic 			out1fmt("No arg for -%c option\n", c);
31047135Sbostic 			c = '?';
31147135Sbostic 			goto out;
31247135Sbostic 		}
31347135Sbostic 		shellparam.optnext++;
31447135Sbostic 		setvar("OPTARG", p, 0);
31547135Sbostic 		p = NULL;
31647135Sbostic 	}
31747135Sbostic out:
31847135Sbostic 	shellparam.optptr = p;
31947135Sbostic 	s[0] = c;
32047135Sbostic 	s[1] = '\0';
32147135Sbostic 	setvar(argv[2], s, 0);
32247135Sbostic 	return 0;
32347135Sbostic }
32447135Sbostic 
32547135Sbostic /*
32647135Sbostic  * Standard option processing (a la getopt) for builtin routines.  The
32747135Sbostic  * only argument that is passed to nextopt is the option string; the
328*47299Smarc  * other arguments are unnecessary.  It return the character, or '\0' on
329*47299Smarc  * end of input.
33047135Sbostic  */
33147135Sbostic 
33247135Sbostic int
33347135Sbostic nextopt(optstring)
33447135Sbostic 	char *optstring;
33547135Sbostic 	{
33647135Sbostic 	register char *p, *q;
33747135Sbostic 	char c;
33847135Sbostic 
33947135Sbostic 	if ((p = optptr) == NULL || *p == '\0') {
34047135Sbostic 		p = *argptr;
34147135Sbostic 		if (p == NULL || *p != '-' || *++p == '\0')
342*47299Smarc 			return '\0';
34347135Sbostic 		argptr++;
34447135Sbostic 		if (p[0] == '-' && p[1] == '\0')	/* check for "--" */
345*47299Smarc 			return '\0';
34647135Sbostic 	}
34747135Sbostic 	c = *p++;
34847135Sbostic 	for (q = optstring ; *q != c ; ) {
34947135Sbostic 		if (*q == '\0')
35047135Sbostic 			error("Illegal option -%c", c);
35147135Sbostic 		if (*++q == ':')
35247135Sbostic 			q++;
35347135Sbostic 	}
35447135Sbostic 	if (*++q == ':') {
35547135Sbostic 		if (*p == '\0' && (p = *argptr++) == NULL)
35647135Sbostic 			error("No arg for -%c option", c);
35747135Sbostic 		optarg = p;
35847135Sbostic 		p = NULL;
35947135Sbostic 	}
36047135Sbostic 	optptr = p;
36147135Sbostic 	return c;
36247135Sbostic }
363