home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / bin / sh / options.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-15  |  8.5 KB  |  389 lines

  1. /*-
  2.  * Copyright (c) 1991 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Kenneth Almquist.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  */
  36.  
  37. #ifndef lint
  38. static char sccsid[] = "@(#)options.c    5.2 (Berkeley) 3/13/91";
  39. #endif /* not lint */
  40.  
  41. #include "shell.h"
  42. #define DEFINE_OPTIONS
  43. #include "options.h"
  44. #undef DEFINE_OPTIONS
  45. #include "nodes.h"    /* for other header files */
  46. #include "eval.h"
  47. #include "jobs.h"
  48. #include "input.h"
  49. #include "output.h"
  50. #include "trap.h"
  51. #include "var.h"
  52. #include "memalloc.h"
  53. #include "error.h"
  54. #include "mystring.h"
  55.  
  56. char *arg0;            /* value of $0 */
  57. struct shparam shellparam;    /* current positional parameters */
  58. char **argptr;            /* argument list for builtin commands */
  59. char *optarg;            /* set by nextopt (like getopt) */
  60. char *optptr;            /* used by nextopt */
  61.  
  62. char *minusc;            /* argument to -c option */
  63.  
  64.  
  65. #ifdef __STDC__
  66. STATIC void options(int);
  67. STATIC void setoption(int, int);
  68. #else
  69. STATIC void options();
  70. STATIC void setoption();
  71. #endif
  72.  
  73.  
  74.  
  75. /*
  76.  * Process the shell command line arguments.
  77.  */
  78.  
  79. void
  80. procargs(argc, argv)
  81.     char **argv;
  82.     {
  83.     char *p;
  84.  
  85.     argptr = argv;
  86.     if (argc > 0)
  87.         argptr++;
  88.     for (p = optval ; p < optval + sizeof optval - 1 ; p++)
  89.         *p = 2;
  90.     options(1);
  91.     if (*argptr == NULL && minusc == NULL)
  92.         sflag = 1;
  93.     if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
  94.         iflag = 1;
  95.     if (jflag == 2)
  96.         jflag = iflag;
  97.     for (p = optval ; p < optval + sizeof optval - 1 ; p++)
  98.         if (*p == 2)
  99.             *p = 0;
  100.     arg0 = argv[0];
  101.     if (sflag == 0 && minusc == NULL) {
  102.         commandname = arg0 = *argptr++;
  103.         setinputfile(commandname, 0);
  104.     }
  105.     shellparam.p = argptr;
  106.     /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
  107.     while (*argptr) {
  108.         shellparam.nparam++;
  109.         argptr++;
  110.     }
  111.     setinteractive(iflag);
  112.     setjobctl(jflag);
  113. }
  114.  
  115.  
  116.  
  117. /*
  118.  * Process shell options.  The global variable argptr contains a pointer
  119.  * to the argument list; we advance it past the options.
  120.  */
  121.  
  122. STATIC void
  123. options(cmdline) {
  124.     register char *p;
  125.     int val;
  126.     int c;
  127.  
  128.     if (cmdline)
  129.         minusc = NULL;
  130.     while ((p = *argptr) != NULL) {
  131.         argptr++;
  132.         if ((c = *p++) == '-') {
  133.             val = 1;
  134.                         if (p[0] == '\0' || p[0] == '-' && p[1] == '\0') {
  135.                                 if (!cmdline) {
  136.                                         /* "-" means turn off -x and -v */
  137.                                         if (p[0] == '\0')
  138.                                                 xflag = vflag = 0;
  139.                                         /* "--" means reset params */
  140.                                         else if (*argptr == NULL)
  141.                                                 setparam(argptr);
  142.                                 }
  143.                 break;      /* "-" or  "--" terminates options */
  144.             }
  145.         } else if (c == '+') {
  146.             val = 0;
  147.         } else {
  148.             argptr--;
  149.             break;
  150.         }
  151.         while ((c = *p++) != '\0') {
  152.             if (c == 'c' && cmdline) {
  153.                 char *q;
  154. #ifdef NOHACK    /* removing this code allows sh -ce 'foo' for compat */
  155.                 if (*p == '\0')
  156. #endif
  157.                     q = *argptr++;
  158.                 if (q == NULL || minusc != NULL)
  159.                     error("Bad -c option");
  160.                 minusc = q;
  161. #ifdef NOHACK
  162.                 break;
  163. #endif
  164.             } else {
  165.                 setoption(c, val);
  166.             }
  167.         }
  168.         if (! cmdline)
  169.             break;
  170.     }
  171. }
  172.  
  173.  
  174. STATIC void
  175. setoption(flag, val)
  176.     char flag;
  177.     int val;
  178.     {
  179.     register char *p;
  180.  
  181.     if ((p = strchr(optchar, flag)) == NULL)
  182.         error("Illegal option -%c", flag);
  183.     optval[p - optchar] = val;
  184. }
  185.  
  186.  
  187.  
  188. #ifdef mkinit
  189. INCLUDE "options.h"
  190.  
  191. SHELLPROC {
  192.     char *p;
  193.  
  194.     for (p = optval ; p < optval + sizeof optval ; p++)
  195.         *p = 0;
  196. }
  197. #endif
  198.  
  199.  
  200. /*
  201.  * Set the shell parameters.
  202.  */
  203.  
  204. void
  205. setparam(argv)
  206.     char **argv;
  207.     {
  208.     char **newparam;
  209.     char **ap;
  210.     int nparam;
  211.  
  212.     for (nparam = 0 ; argv[nparam] ; nparam++);
  213.     ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
  214.     while (*argv) {
  215.         *ap++ = savestr(*argv++);
  216.     }
  217.     *ap = NULL;
  218.     freeparam(&shellparam);
  219.     shellparam.malloc = 1;
  220.     shellparam.nparam = nparam;
  221.     shellparam.p = newparam;
  222.     shellparam.optnext = NULL;
  223. }
  224.  
  225.  
  226. /*
  227.  * Free the list of positional parameters.
  228.  */
  229.  
  230. void
  231. freeparam(param)
  232.     struct shparam *param;
  233.     {
  234.     char **ap;
  235.  
  236.     if (param->malloc) {
  237.         for (ap = param->p ; *ap ; ap++)
  238.             ckfree(*ap);
  239.         ckfree(param->p);
  240.     }
  241. }
  242.  
  243.  
  244.  
  245. /*
  246.  * The shift builtin command.
  247.  */
  248.  
  249. shiftcmd(argc, argv)  char **argv; {
  250.     int n;
  251.     char **ap1, **ap2;
  252.  
  253.     n = 1;
  254.     if (argc > 1)
  255.         n = number(argv[1]);
  256.     if (n > shellparam.nparam)
  257.         n = shellparam.nparam;
  258.     INTOFF;
  259.     shellparam.nparam -= n;
  260.     for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
  261.         if (shellparam.malloc)
  262.             ckfree(*ap1);
  263.     }
  264.     ap2 = shellparam.p;
  265.     while ((*ap2++ = *ap1++) != NULL);
  266.     shellparam.optnext = NULL;
  267.     INTON;
  268.     return 0;
  269. }
  270.  
  271.  
  272.  
  273. /*
  274.  * The set command builtin.
  275.  */
  276.  
  277. setcmd(argc, argv)  char **argv; {
  278.     if (argc == 1)
  279.         return showvarscmd(argc, argv);
  280.     INTOFF;
  281.     options(0);
  282.     setinteractive(iflag);
  283.     setjobctl(jflag);
  284.     if (*argptr != NULL) {
  285.         setparam(argptr);
  286.     }
  287.     INTON;
  288.     return 0;
  289. }
  290.  
  291.  
  292. /*
  293.  * The getopts builtin.  Shellparam.optnext points to the next argument
  294.  * to be processed.  Shellparam.optptr points to the next character to
  295.  * be processed in the current argument.  If shellparam.optnext is NULL,
  296.  * then it's the first time getopts has been called.
  297.  */
  298.  
  299. getoptscmd(argc, argv)  char **argv; {
  300.     register char *p, *q;
  301.     char c;
  302.     char s[10];
  303.  
  304.     if (argc != 3)
  305.         error("Usage: getopts optstring var");
  306.     if (shellparam.optnext == NULL) {
  307.         shellparam.optnext = shellparam.p;
  308.         shellparam.optptr = NULL;
  309.     }
  310.     if ((p = shellparam.optptr) == NULL || *p == '\0') {
  311.         p = *shellparam.optnext;
  312.         if (p == NULL || *p != '-' || *++p == '\0') {
  313. atend:
  314.             fmtstr(s, 10, "%d", shellparam.optnext - shellparam.p + 1);
  315.             setvar("OPTIND", s, 0);
  316.             shellparam.optnext = NULL;
  317.             return 1;
  318.         }
  319.         shellparam.optnext++;
  320.         if (p[0] == '-' && p[1] == '\0')    /* check for "--" */
  321.             goto atend;
  322.     }
  323.     c = *p++;
  324.     for (q = argv[1] ; *q != c ; ) {
  325.         if (*q == '\0') {
  326.             out1fmt("Illegal option -%c\n", c);
  327.             c = '?';
  328.             goto out;
  329.         }
  330.         if (*++q == ':')
  331.             q++;
  332.     }
  333.     if (*++q == ':') {
  334.         if (*p == '\0' && (p = *shellparam.optnext) == NULL) {
  335.             out1fmt("No arg for -%c option\n", c);
  336.             c = '?';
  337.             goto out;
  338.         }
  339.         shellparam.optnext++;
  340.         setvar("OPTARG", p, 0);
  341.         p = NULL;
  342.     }
  343. out:
  344.     shellparam.optptr = p;
  345.     s[0] = c;
  346.     s[1] = '\0';
  347.     setvar(argv[2], s, 0);
  348.     return 0;
  349. }
  350.  
  351. /*
  352.  * Standard option processing (a la getopt) for builtin routines.  The
  353.  * only argument that is passed to nextopt is the option string; the
  354.  * other arguments are unnecessary.  It return the character, or '\0' on
  355.  * end of input.
  356.  */
  357.  
  358. int
  359. nextopt(optstring)
  360.     char *optstring;
  361.     {
  362.     register char *p, *q;
  363.     char c;
  364.  
  365.     if ((p = optptr) == NULL || *p == '\0') {
  366.         p = *argptr;
  367.         if (p == NULL || *p != '-' || *++p == '\0')
  368.             return '\0';
  369.         argptr++;
  370.         if (p[0] == '-' && p[1] == '\0')    /* check for "--" */
  371.             return '\0';
  372.     }
  373.     c = *p++;
  374.     for (q = optstring ; *q != c ; ) {
  375.         if (*q == '\0')
  376.             error("Illegal option -%c", c);
  377.         if (*++q == ':')
  378.             q++;
  379.     }
  380.     if (*++q == ':') {
  381.         if (*p == '\0' && (p = *argptr++) == NULL)
  382.             error("No arg for -%c option", c);
  383.         optarg = p;
  384.         p = NULL;
  385.     }
  386.     optptr = p;
  387.     return c;
  388. }
  389.