options.c

Go to the documentation of this file.
00001 /*-
00002  * Copyright (c) 1991 The Regents of the University of California.
00003  * All rights reserved.
00004  *
00005  * This code is derived from software contributed to Berkeley by
00006  * Kenneth Almquist.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions
00010  * are met:
00011  * 1. Redistributions of source code must retain the above copyright
00012  *    notice, this list of conditions and the following disclaimer.
00013  * 2. Redistributions in binary form must reproduce the above copyright
00014  *    notice, this list of conditions and the following disclaimer in the
00015  *    documentation and/or other materials provided with the distribution.
00016  * 3. All advertising materials mentioning features or use of this software
00017  *    must display the following acknowledgement:
00018  *      This product includes software developed by the University of
00019  *      California, Berkeley and its contributors.
00020  * 4. Neither the name of the University nor the names of its contributors
00021  *    may be used to endorse or promote products derived from this software
00022  *    without specific prior written permission.
00023  *
00024  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00025  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00026  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00027  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00028  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00029  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00030  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00031  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00032  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00033  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00034  * SUCH DAMAGE.
00035  */
00036 
00037 #ifndef lint
00038 static char sccsid[] = "@(#)options.c   5.2 (Berkeley) 3/13/91";
00039 #endif /* not lint */
00040 
00041 #include "shell.h"
00042 #define DEFINE_OPTIONS
00043 #include "options.h"
00044 #undef DEFINE_OPTIONS
00045 #include "nodes.h"      /* for other header files */
00046 #include "eval.h"
00047 #include "jobs.h"
00048 #include "input.h"
00049 #include "output.h"
00050 #include "trap.h"
00051 #include "var.h"
00052 #include "memalloc.h"
00053 #include "error.h"
00054 #include "mystring.h"
00055 
00056 char *arg0;                     /* value of $0 */
00057 struct shparam shellparam;      /* current positional parameters */
00058 char **argptr;                  /* argument list for builtin commands */
00059 char *optarg;                   /* set by nextopt (like getopt) */
00060 char *optptr;                   /* used by nextopt */
00061 int editable;                   /* isatty(0) && isatty(1) */
00062 
00063 char *minusc;                   /* argument to -c option */
00064 
00065 
00066 #ifdef __STDC__
00067 STATIC void options(int);
00068 STATIC void setoption(int, int);
00069 #else
00070 STATIC void options();
00071 STATIC void setoption();
00072 #endif
00073 
00074 
00075 
00076 /*
00077  * Process the shell command line arguments.
00078  */
00079 
00080 void
00081 procargs(argc, argv)
00082         char **argv;
00083         {
00084         char *p;
00085 
00086         argptr = argv;
00087         if (argc > 0)
00088                 argptr++;
00089         for (p = optval ; p < optval + sizeof optval - 1 ; p++)
00090                 *p = 2;
00091         options(1);
00092         if (*argptr == NULL && minusc == NULL)
00093                 sflag = 1;
00094         editable = (isatty(0) && isatty(1));
00095         if (iflag == 2 && sflag == 1 && editable)
00096                 iflag = 1;
00097         if (jflag == 2)
00098                 jflag = iflag;
00099         for (p = optval ; p < optval + sizeof optval - 1 ; p++)
00100                 if (*p == 2)
00101                         *p = 0;
00102         arg0 = argv[0];
00103         if (sflag == 0) {
00104                 arg0 = *argptr++;
00105                 if (minusc == NULL) {
00106                         commandname = arg0;
00107                         setinputfile(commandname, 0);
00108                 }
00109         }
00110         shellparam.p = argptr;
00111         /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
00112         while (*argptr) {
00113                 shellparam.nparam++;
00114                 argptr++;
00115         }
00116         setinteractive(iflag);
00117         setjobctl(jflag);
00118 }
00119 
00120 
00121 
00122 /*
00123  * Process shell options.  The global variable argptr contains a pointer
00124  * to the argument list; we advance it past the options.
00125  */
00126 
00127 STATIC void
00128 options(cmdline) {
00129         register char *p;
00130         int val;
00131         int c;
00132 
00133         if (cmdline)
00134                 minusc = NULL;
00135         while ((p = *argptr) != NULL) {
00136                 argptr++;
00137                 if ((c = *p++) == '-') {
00138                         val = 1;
00139                         if (p[0] == '\0' || p[0] == '-' && p[1] == '\0') {
00140                                 if (!cmdline) {
00141                                         /* "-" means turn off -x and -v */
00142                                         if (p[0] == '\0')
00143                                                 xflag = vflag = 0;
00144                                         /* "--" means reset params */
00145                                         else if (*argptr == NULL)
00146                                                 setparam(argptr);
00147                                 }
00148                                 break;    /* "-" or  "--" terminates options */
00149                         }
00150                 } else if (c == '+') {
00151                         val = 0;
00152                 } else {
00153                         argptr--;
00154                         break;
00155                 }
00156                 while ((c = *p++) != '\0') {
00157                         if (c == 'c' && cmdline) {
00158                                 char *q;
00159 #ifdef NOHACK   /* removing this code allows sh -ce 'foo' for compat */
00160                                 if (*p == '\0')
00161 #endif
00162                                         q = *argptr++;
00163                                 if (q == NULL || minusc != NULL)
00164                                         error("Bad -c option");
00165                                 minusc = q;
00166 #ifdef NOHACK
00167                                 break;
00168 #endif
00169                         } else {
00170                                 setoption(c, val);
00171                         }
00172                 }
00173                 if (! cmdline)
00174                         break;
00175         }
00176 }
00177 
00178 
00179 STATIC void
00180 setoption(flag, val)
00181         char flag;
00182         int val;
00183         {
00184         register char *p;
00185 
00186         if ((p = strchr(optchar, flag)) == NULL)
00187                 error("Illegal option -%c", flag);
00188         optval[p - optchar] = val;
00189 }
00190 
00191 
00192 
00193 #ifdef mkinit
00194 INCLUDE "options.h"
00195 
00196 SHELLPROC {
00197         char *p;
00198 
00199         for (p = optval ; p < optval + sizeof optval ; p++)
00200                 *p = 0;
00201 }
00202 #endif
00203 
00204 
00205 /*
00206  * Set the shell parameters.
00207  */
00208 
00209 void
00210 setparam(argv)
00211         char **argv;
00212         {
00213         char **newparam;
00214         char **ap;
00215         int nparam;
00216 
00217         for (nparam = 0 ; argv[nparam] ; nparam++);
00218         ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
00219         while (*argv) {
00220                 *ap++ = savestr(*argv++);
00221         }
00222         *ap = NULL;
00223         freeparam(&shellparam);
00224         shellparam.malloc = 1;
00225         shellparam.nparam = nparam;
00226         shellparam.p = newparam;
00227         shellparam.optnext = NULL;
00228 }
00229 
00230 
00231 /*
00232  * Free the list of positional parameters.
00233  */
00234 
00235 void
00236 freeparam(param)
00237         struct shparam *param;
00238         {
00239         char **ap;
00240 
00241         if (param->malloc) {
00242                 for (ap = param->p ; *ap ; ap++)
00243                         ckfree(*ap);
00244                 ckfree(param->p);
00245         }
00246 }
00247 
00248 
00249 
00250 /*
00251  * The shift builtin command.
00252  */
00253 
00254 shiftcmd(argc, argv)  char **argv; {
00255         int n;
00256         char **ap1, **ap2;
00257 
00258         n = 1;
00259         if (argc > 1)
00260                 n = number(argv[1]);
00261         if (n > shellparam.nparam)
00262                 n = shellparam.nparam;
00263         INTOFF;
00264         shellparam.nparam -= n;
00265         for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
00266                 if (shellparam.malloc)
00267                         ckfree(*ap1);
00268         }
00269         ap2 = shellparam.p;
00270         while ((*ap2++ = *ap1++) != NULL);
00271         shellparam.optnext = NULL;
00272         INTON;
00273         return 0;
00274 }
00275 
00276 
00277 
00278 /*
00279  * The set command builtin.
00280  */
00281 
00282 setcmd(argc, argv)  char **argv; {
00283         if (argc == 1)
00284                 return showvarscmd(argc, argv);
00285         INTOFF;
00286         options(0);
00287         setinteractive(iflag);
00288         setjobctl(jflag);
00289         if (*argptr != NULL) {
00290                 setparam(argptr);
00291         }
00292         INTON;
00293         return 0;
00294 }
00295 
00296 
00297 /*
00298  * The getopts builtin.  Shellparam.optnext points to the next argument
00299  * to be processed.  Shellparam.optptr points to the next character to
00300  * be processed in the current argument.  If shellparam.optnext is NULL,
00301  * then it's the first time getopts has been called.
00302  */
00303 
00304 getoptscmd(argc, argv)  char **argv; {
00305         register char *p, *q;
00306         char c;
00307         char s[10];
00308 
00309         if (argc != 3)
00310                 error("Usage: getopts optstring var");
00311         if (shellparam.optnext == NULL) {
00312                 shellparam.optnext = shellparam.p;
00313                 shellparam.optptr = NULL;
00314         }
00315         if ((p = shellparam.optptr) == NULL || *p == '\0') {
00316                 p = *shellparam.optnext;
00317                 if (p == NULL || *p != '-' || *++p == '\0') {
00318 atend:
00319                         fmtstr(s, 10, "%d", shellparam.optnext - shellparam.p + 1);
00320                         setvar("OPTIND", s, 0);
00321                         shellparam.optnext = NULL;
00322                         return 1;
00323                 }
00324                 shellparam.optnext++;
00325                 if (p[0] == '-' && p[1] == '\0')        /* check for "--" */
00326                         goto atend;
00327         }
00328         c = *p++;
00329         for (q = argv[1] ; *q != c ; ) {
00330                 if (*q == '\0') {
00331                         out1fmt("Illegal option -%c\n", c);
00332                         c = '?';
00333                         goto out;
00334                 }
00335                 if (*++q == ':')
00336                         q++;
00337         }
00338         if (*++q == ':') {
00339                 if (*p == '\0') {
00340                         if ((p = *shellparam.optnext) == NULL) {
00341                                 out1fmt("No arg for -%c option\n", c);
00342                                 c = '?';
00343                                 goto out;
00344                         }
00345                         shellparam.optnext++;
00346                 }
00347                 setvar("OPTARG", p, 0);
00348                 p = "";
00349         }
00350 out:
00351         shellparam.optptr = p;
00352         s[0] = c;
00353         s[1] = '\0';
00354         setvar(argv[2], s, 0);
00355         fmtstr(s, 10, "%d", shellparam.optnext - shellparam.p + 1);
00356         setvar("OPTIND", s, 0);
00357         return 0;
00358 }
00359 
00360 /*
00361  * Standard option processing (a la getopt) for builtin routines.  The
00362  * only argument that is passed to nextopt is the option string; the
00363  * other arguments are unnecessary.  It return the character, or '\0' on
00364  * end of input.
00365  */
00366 
00367 int
00368 nextopt(optstring)
00369         char *optstring;
00370         {
00371         register char *p, *q;
00372         char c;
00373 
00374         if ((p = optptr) == NULL || *p == '\0') {
00375                 p = *argptr;
00376                 if (p == NULL || *p != '-' || *++p == '\0')
00377                         return '\0';
00378                 argptr++;
00379                 if (p[0] == '-' && p[1] == '\0')        /* check for "--" */
00380                         return '\0';
00381         }
00382         c = *p++;
00383         for (q = optstring ; *q != c ; ) {
00384                 if (*q == '\0')
00385                         error("Illegal option -%c", c);
00386                 if (*++q == ':')
00387                         q++;
00388         }
00389         if (*++q == ':') {
00390                 if (*p == '\0' && (p = *argptr++) == NULL)
00391                         error("No arg for -%c option", c);
00392                 optarg = p;
00393                 p = NULL;
00394         }
00395         optptr = p;
00396         return c;
00397 }

Generated on Fri Apr 14 22:56:41 2006 for minix by  doxygen 1.4.6