1*47135Sbostic /*- 2*47135Sbostic * Copyright (c) 1991 The Regents of the University of California. 3*47135Sbostic * All rights reserved. 4*47135Sbostic * 5*47135Sbostic * This code is derived from software contributed to Berkeley by 6*47135Sbostic * Kenneth Almquist. 7*47135Sbostic * 8*47135Sbostic * %sccs.include.redist.c% 9*47135Sbostic */ 10*47135Sbostic 11*47135Sbostic #ifndef lint 12*47135Sbostic static char sccsid[] = "@(#)options.c 5.1 (Berkeley) 03/07/91"; 13*47135Sbostic #endif /* not lint */ 14*47135Sbostic 15*47135Sbostic #include "shell.h" 16*47135Sbostic #define DEFINE_OPTIONS 17*47135Sbostic #include "options.h" 18*47135Sbostic #undef DEFINE_OPTIONS 19*47135Sbostic #include "nodes.h" /* for other header files */ 20*47135Sbostic #include "eval.h" 21*47135Sbostic #include "jobs.h" 22*47135Sbostic #include "input.h" 23*47135Sbostic #include "output.h" 24*47135Sbostic #include "trap.h" 25*47135Sbostic #include "var.h" 26*47135Sbostic #include "memalloc.h" 27*47135Sbostic #include "error.h" 28*47135Sbostic #include "mystring.h" 29*47135Sbostic 30*47135Sbostic char *arg0; /* value of $0 */ 31*47135Sbostic struct shparam shellparam; /* current positional parameters */ 32*47135Sbostic char **argptr; /* argument list for builtin commands */ 33*47135Sbostic char *optarg; /* set by nextopt (like getopt) */ 34*47135Sbostic char *optptr; /* used by nextopt */ 35*47135Sbostic 36*47135Sbostic char *minusc; /* argument to -c option */ 37*47135Sbostic 38*47135Sbostic 39*47135Sbostic #ifdef __STDC__ 40*47135Sbostic STATIC void options(int); 41*47135Sbostic STATIC void setoption(int, int); 42*47135Sbostic #else 43*47135Sbostic STATIC void options(); 44*47135Sbostic STATIC void setoption(); 45*47135Sbostic #endif 46*47135Sbostic 47*47135Sbostic 48*47135Sbostic 49*47135Sbostic /* 50*47135Sbostic * Process the shell command line arguments. 51*47135Sbostic */ 52*47135Sbostic 53*47135Sbostic void 54*47135Sbostic procargs(argc, argv) 55*47135Sbostic char **argv; 56*47135Sbostic { 57*47135Sbostic char *p; 58*47135Sbostic 59*47135Sbostic argptr = argv; 60*47135Sbostic if (argc > 0) 61*47135Sbostic argptr++; 62*47135Sbostic for (p = optval ; p < optval + sizeof optval - 1 ; p++) 63*47135Sbostic *p = 2; 64*47135Sbostic options(1); 65*47135Sbostic if (*argptr == NULL && minusc == NULL) 66*47135Sbostic sflag = 1; 67*47135Sbostic if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1)) 68*47135Sbostic iflag = 1; 69*47135Sbostic if (jflag == 2) 70*47135Sbostic jflag = iflag; 71*47135Sbostic for (p = optval ; p < optval + sizeof optval - 1 ; p++) 72*47135Sbostic if (*p == 2) 73*47135Sbostic *p = 0; 74*47135Sbostic arg0 = argv[0]; 75*47135Sbostic if (sflag == 0 && minusc == NULL) { 76*47135Sbostic commandname = arg0 = *argptr++; 77*47135Sbostic setinputfile(commandname, 0); 78*47135Sbostic } 79*47135Sbostic shellparam.p = argptr; 80*47135Sbostic /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */ 81*47135Sbostic while (*argptr) { 82*47135Sbostic shellparam.nparam++; 83*47135Sbostic argptr++; 84*47135Sbostic } 85*47135Sbostic setinteractive(iflag); 86*47135Sbostic setjobctl(jflag); 87*47135Sbostic } 88*47135Sbostic 89*47135Sbostic 90*47135Sbostic 91*47135Sbostic /* 92*47135Sbostic * Process shell options. The global variable argptr contains a pointer 93*47135Sbostic * to the argument list; we advance it past the options. 94*47135Sbostic */ 95*47135Sbostic 96*47135Sbostic STATIC void 97*47135Sbostic options(cmdline) { 98*47135Sbostic register char *p; 99*47135Sbostic int val; 100*47135Sbostic int c; 101*47135Sbostic 102*47135Sbostic minusc = NULL; 103*47135Sbostic while ((p = *argptr) != NULL) { 104*47135Sbostic argptr++; 105*47135Sbostic if ((c = *p++) == '-') { 106*47135Sbostic val = 1; 107*47135Sbostic if (p[0] == '\0' || p[0] == '-' && p[1] == '\0') 108*47135Sbostic break; /* "-" or "--" terminates options */ 109*47135Sbostic } else if (c == '+') { 110*47135Sbostic val = 0; 111*47135Sbostic } else { 112*47135Sbostic argptr--; 113*47135Sbostic break; 114*47135Sbostic } 115*47135Sbostic while ((c = *p++) != '\0') { 116*47135Sbostic if (c == 'c' && cmdline) { 117*47135Sbostic char *q; 118*47135Sbostic #ifdef NOHACK 119*47135Sbostic if (*p == '\0') 120*47135Sbostic #endif 121*47135Sbostic q = *argptr++; 122*47135Sbostic if (q == NULL || minusc != NULL) 123*47135Sbostic error("Bad -c option"); 124*47135Sbostic minusc = q; 125*47135Sbostic #ifdef NOHACK 126*47135Sbostic break; 127*47135Sbostic #endif 128*47135Sbostic } else { 129*47135Sbostic setoption(c, val); 130*47135Sbostic } 131*47135Sbostic } 132*47135Sbostic if (! cmdline) 133*47135Sbostic break; 134*47135Sbostic } 135*47135Sbostic } 136*47135Sbostic 137*47135Sbostic 138*47135Sbostic STATIC void 139*47135Sbostic setoption(flag, val) 140*47135Sbostic char flag; 141*47135Sbostic int val; 142*47135Sbostic { 143*47135Sbostic register char *p; 144*47135Sbostic 145*47135Sbostic if ((p = strchr(optchar, flag)) == NULL) 146*47135Sbostic error("Illegal option -%c", flag); 147*47135Sbostic optval[p - optchar] = val; 148*47135Sbostic } 149*47135Sbostic 150*47135Sbostic 151*47135Sbostic 152*47135Sbostic #ifdef mkinit 153*47135Sbostic INCLUDE "options.h" 154*47135Sbostic 155*47135Sbostic SHELLPROC { 156*47135Sbostic char *p; 157*47135Sbostic 158*47135Sbostic for (p = optval ; p < optval + sizeof optval ; p++) 159*47135Sbostic *p = 0; 160*47135Sbostic } 161*47135Sbostic #endif 162*47135Sbostic 163*47135Sbostic 164*47135Sbostic /* 165*47135Sbostic * Set the shell parameters. 166*47135Sbostic */ 167*47135Sbostic 168*47135Sbostic void 169*47135Sbostic setparam(argv) 170*47135Sbostic char **argv; 171*47135Sbostic { 172*47135Sbostic char **newparam; 173*47135Sbostic char **ap; 174*47135Sbostic int nparam; 175*47135Sbostic 176*47135Sbostic for (nparam = 0 ; argv[nparam] ; nparam++); 177*47135Sbostic ap = newparam = ckmalloc((nparam + 1) * sizeof *ap); 178*47135Sbostic while (*argv) { 179*47135Sbostic *ap++ = savestr(*argv++); 180*47135Sbostic } 181*47135Sbostic *ap = NULL; 182*47135Sbostic freeparam(&shellparam); 183*47135Sbostic shellparam.malloc = 1; 184*47135Sbostic shellparam.nparam = nparam; 185*47135Sbostic shellparam.p = newparam; 186*47135Sbostic shellparam.optnext = NULL; 187*47135Sbostic } 188*47135Sbostic 189*47135Sbostic 190*47135Sbostic /* 191*47135Sbostic * Free the list of positional parameters. 192*47135Sbostic */ 193*47135Sbostic 194*47135Sbostic void 195*47135Sbostic freeparam(param) 196*47135Sbostic struct shparam *param; 197*47135Sbostic { 198*47135Sbostic char **ap; 199*47135Sbostic 200*47135Sbostic if (param->malloc) { 201*47135Sbostic for (ap = param->p ; *ap ; ap++) 202*47135Sbostic ckfree(*ap); 203*47135Sbostic ckfree(param->p); 204*47135Sbostic } 205*47135Sbostic } 206*47135Sbostic 207*47135Sbostic 208*47135Sbostic 209*47135Sbostic /* 210*47135Sbostic * The shift builtin command. 211*47135Sbostic */ 212*47135Sbostic 213*47135Sbostic shiftcmd(argc, argv) char **argv; { 214*47135Sbostic int n; 215*47135Sbostic char **ap1, **ap2; 216*47135Sbostic 217*47135Sbostic n = 1; 218*47135Sbostic if (argc > 1) 219*47135Sbostic n = number(argv[1]); 220*47135Sbostic if (n > shellparam.nparam) 221*47135Sbostic n = shellparam.nparam; 222*47135Sbostic INTOFF; 223*47135Sbostic shellparam.nparam -= n; 224*47135Sbostic for (ap1 = shellparam.p ; --n >= 0 ; ap1++) { 225*47135Sbostic if (shellparam.malloc) 226*47135Sbostic ckfree(*ap1); 227*47135Sbostic } 228*47135Sbostic ap2 = shellparam.p; 229*47135Sbostic while ((*ap2++ = *ap1++) != NULL); 230*47135Sbostic shellparam.optnext = NULL; 231*47135Sbostic INTON; 232*47135Sbostic return 0; 233*47135Sbostic } 234*47135Sbostic 235*47135Sbostic 236*47135Sbostic 237*47135Sbostic /* 238*47135Sbostic * The set command builtin. 239*47135Sbostic */ 240*47135Sbostic 241*47135Sbostic setcmd(argc, argv) char **argv; { 242*47135Sbostic if (argc == 1) 243*47135Sbostic return showvarscmd(argc, argv); 244*47135Sbostic INTOFF; 245*47135Sbostic options(0); 246*47135Sbostic setinteractive(iflag); 247*47135Sbostic setjobctl(jflag); 248*47135Sbostic if (*argptr != NULL) { 249*47135Sbostic setparam(argptr); 250*47135Sbostic } 251*47135Sbostic INTON; 252*47135Sbostic return 0; 253*47135Sbostic } 254*47135Sbostic 255*47135Sbostic 256*47135Sbostic /* 257*47135Sbostic * The getopts builtin. Shellparam.optnext points to the next argument 258*47135Sbostic * to be processed. Shellparam.optptr points to the next character to 259*47135Sbostic * be processed in the current argument. If shellparam.optnext is NULL, 260*47135Sbostic * then it's the first time getopts has been called. 261*47135Sbostic */ 262*47135Sbostic 263*47135Sbostic getoptscmd(argc, argv) char **argv; { 264*47135Sbostic register char *p, *q; 265*47135Sbostic char c; 266*47135Sbostic char s[10]; 267*47135Sbostic 268*47135Sbostic if (argc != 3) 269*47135Sbostic error("Usage: getopts optstring var"); 270*47135Sbostic if (shellparam.optnext == NULL) { 271*47135Sbostic shellparam.optnext = shellparam.p; 272*47135Sbostic shellparam.optptr = NULL; 273*47135Sbostic } 274*47135Sbostic if ((p = shellparam.optptr) == NULL || *p == '\0') { 275*47135Sbostic p = *shellparam.optnext; 276*47135Sbostic if (p == NULL || *p != '-' || *++p == '\0') { 277*47135Sbostic atend: 278*47135Sbostic fmtstr(s, 10, "%d", shellparam.optnext - shellparam.p + 1); 279*47135Sbostic setvar("OPTIND", s, 0); 280*47135Sbostic shellparam.optnext = NULL; 281*47135Sbostic return 1; 282*47135Sbostic } 283*47135Sbostic shellparam.optnext++; 284*47135Sbostic if (p[0] == '-' && p[1] == '\0') /* check for "--" */ 285*47135Sbostic goto atend; 286*47135Sbostic } 287*47135Sbostic c = *p++; 288*47135Sbostic for (q = argv[1] ; *q != c ; ) { 289*47135Sbostic if (*q == '\0') { 290*47135Sbostic out1fmt("Illegal option -%c\n", c); 291*47135Sbostic c = '?'; 292*47135Sbostic goto out; 293*47135Sbostic } 294*47135Sbostic if (*++q == ':') 295*47135Sbostic q++; 296*47135Sbostic } 297*47135Sbostic if (*++q == ':') { 298*47135Sbostic if (*p == '\0' && (p = *shellparam.optnext) == NULL) { 299*47135Sbostic out1fmt("No arg for -%c option\n", c); 300*47135Sbostic c = '?'; 301*47135Sbostic goto out; 302*47135Sbostic } 303*47135Sbostic shellparam.optnext++; 304*47135Sbostic setvar("OPTARG", p, 0); 305*47135Sbostic p = NULL; 306*47135Sbostic } 307*47135Sbostic out: 308*47135Sbostic shellparam.optptr = p; 309*47135Sbostic s[0] = c; 310*47135Sbostic s[1] = '\0'; 311*47135Sbostic setvar(argv[2], s, 0); 312*47135Sbostic return 0; 313*47135Sbostic } 314*47135Sbostic 315*47135Sbostic 316*47135Sbostic /* 317*47135Sbostic * Standard option processing (a la getopt) for builtin routines. The 318*47135Sbostic * only argument that is passed to nextopt is the option string; the 319*47135Sbostic * other arguments are unnecessary. It return the character, or -1 on 320*47135Sbostic * end of input. This routine assumes that all characters in optstring 321*47135Sbostic * are positive. 322*47135Sbostic */ 323*47135Sbostic 324*47135Sbostic int 325*47135Sbostic nextopt(optstring) 326*47135Sbostic char *optstring; 327*47135Sbostic { 328*47135Sbostic register char *p, *q; 329*47135Sbostic char c; 330*47135Sbostic 331*47135Sbostic if ((p = optptr) == NULL || *p == '\0') { 332*47135Sbostic p = *argptr; 333*47135Sbostic if (p == NULL || *p != '-' || *++p == '\0') 334*47135Sbostic return -1; 335*47135Sbostic argptr++; 336*47135Sbostic if (p[0] == '-' && p[1] == '\0') /* check for "--" */ 337*47135Sbostic return -1; 338*47135Sbostic } 339*47135Sbostic c = *p++; 340*47135Sbostic for (q = optstring ; *q != c ; ) { 341*47135Sbostic if (*q == '\0') 342*47135Sbostic error("Illegal option -%c", c); 343*47135Sbostic if (*++q == ':') 344*47135Sbostic q++; 345*47135Sbostic } 346*47135Sbostic if (*++q == ':') { 347*47135Sbostic if (*p == '\0' && (p = *argptr++) == NULL) 348*47135Sbostic error("No arg for -%c option", c); 349*47135Sbostic optarg = p; 350*47135Sbostic p = NULL; 351*47135Sbostic } 352*47135Sbostic optptr = p; 353*47135Sbostic return c; 354*47135Sbostic } 355