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