home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / AP / ASH / ASH-LINU.2 / ASH-LINU / ash-linux-0.2 / options.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-24  |  8.6 KB  |  390 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[] = "from: @(#)options.c    5.2 (Berkeley) 3/13/91";*/
  39. static char rcsid[] = "options.c,v 1.4 1993/08/01 18:58:04 mycroft Exp";
  40. #endif /* not lint */
  41.  
  42. #include "shell.h"
  43. #define DEFINE_OPTIONS
  44. #include "options.h"
  45. #undef DEFINE_OPTIONS
  46. #include "nodes.h"    /* for other header files */
  47. #include "eval.h"
  48. #include "jobs.h"
  49. #include "input.h"
  50. #include "output.h"
  51. #include "trap.h"
  52. #include "var.h"
  53. #include "memalloc.h"
  54. #include "error.h"
  55. #include "mystring.h"
  56.  
  57. char *arg0;            /* value of $0 */
  58. struct shparam shellparam;    /* current positional parameters */
  59. char **argptr;            /* argument list for builtin commands */
  60. char *optarg;            /* set by nextopt (like getopt) */
  61. char *optptr;            /* used by nextopt */
  62.  
  63. char *minusc;            /* argument to -c option */
  64.  
  65.  
  66. #ifdef __STDC__
  67. STATIC void options(int);
  68. STATIC void setoption(int, int);
  69. #else
  70. STATIC void options();
  71. STATIC void setoption();
  72. #endif
  73.  
  74.  
  75.  
  76. /*
  77.  * Process the shell command line arguments.
  78.  */
  79.  
  80. void
  81. procargs(argc, argv)
  82.     char **argv;
  83.     {
  84.     char *p;
  85.  
  86.     argptr = argv;
  87.     if (argc > 0)
  88.         argptr++;
  89.     for (p = optval ; p < optval + sizeof optval - 1 ; p++)
  90.         *p = 2;
  91.     options(1);
  92.     if (*argptr == NULL && minusc == NULL)
  93.         sflag = 1;
  94.     if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
  95.         iflag = 1;
  96.     if (jflag == 2)
  97.         jflag = iflag;
  98.     for (p = optval ; p < optval + sizeof optval - 1 ; p++)
  99.         if (*p == 2)
  100.             *p = 0;
  101.     arg0 = argv[0];
  102.     if (sflag == 0 && minusc == NULL) {
  103.         commandname = arg0 = *argptr++;
  104.         setinputfile(commandname, 0);
  105.     }
  106.     shellparam.p = argptr;
  107.     /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
  108.     while (*argptr) {
  109.         shellparam.nparam++;
  110.         argptr++;
  111.     }
  112.     setinteractive(iflag);
  113.     setjobctl(jflag);
  114. }
  115.  
  116.  
  117.  
  118. /*
  119.  * Process shell options.  The global variable argptr contains a pointer
  120.  * to the argument list; we advance it past the options.
  121.  */
  122.  
  123. STATIC void
  124. options(cmdline) {
  125.     register char *p;
  126.     int val;
  127.     int c;
  128.  
  129.     if (cmdline)
  130.         minusc = NULL;
  131.     while ((p = *argptr) != NULL) {
  132.         argptr++;
  133.         if ((c = *p++) == '-') {
  134.             val = 1;
  135.                         if (p[0] == '\0' || p[0] == '-' && p[1] == '\0') {
  136.                                 if (!cmdline) {
  137.                                         /* "-" means turn off -x and -v */
  138.                                         if (p[0] == '\0')
  139.                                                 xflag = vflag = 0;
  140.                                         /* "--" means reset params */
  141.                                         else if (*argptr == NULL)
  142.                                                 setparam(argptr);
  143.                                 }
  144.                 break;      /* "-" or  "--" terminates options */
  145.             }
  146.         } else if (c == '+') {
  147.             val = 0;
  148.         } else {
  149.             argptr--;
  150.             break;
  151.         }
  152.         while ((c = *p++) != '\0') {
  153.             if (c == 'c' && cmdline) {
  154.                 char *q;
  155. #ifdef NOHACK    /* removing this code allows sh -ce 'foo' for compat */
  156.                 if (*p == '\0')
  157. #endif
  158.                     q = *argptr++;
  159.                 if (q == NULL || minusc != NULL)
  160.                     error("Bad -c option");
  161.                 minusc = q;
  162. #ifdef NOHACK
  163.                 break;
  164. #endif
  165.             } else {
  166.                 setoption(c, val);
  167.             }
  168.         }
  169.         if (! cmdline)
  170.             break;
  171.     }
  172. }
  173.  
  174.  
  175. STATIC void
  176. setoption(flag, val)
  177.     char flag;
  178.     int val;
  179.     {
  180.     register char *p;
  181.  
  182.     if ((p = strchr(optchar, flag)) == NULL)
  183.         error("Illegal option -%c", flag);
  184.     optval[p - optchar] = val;
  185. }
  186.  
  187.  
  188.  
  189. #ifdef mkinit
  190. INCLUDE "options.h"
  191.  
  192. SHELLPROC {
  193.     char *p;
  194.  
  195.     for (p = optval ; p < optval + sizeof optval ; p++)
  196.         *p = 0;
  197. }
  198. #endif
  199.  
  200.  
  201. /*
  202.  * Set the shell parameters.
  203.  */
  204.  
  205. void
  206. setparam(argv)
  207.     char **argv;
  208.     {
  209.     char **newparam;
  210.     char **ap;
  211.     int nparam;
  212.  
  213.     for (nparam = 0 ; argv[nparam] ; nparam++);
  214.     ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
  215.     while (*argv) {
  216.         *ap++ = savestr(*argv++);
  217.     }
  218.     *ap = NULL;
  219.     freeparam(&shellparam);
  220.     shellparam.malloc = 1;
  221.     shellparam.nparam = nparam;
  222.     shellparam.p = newparam;
  223.     shellparam.optnext = NULL;
  224. }
  225.  
  226.  
  227. /*
  228.  * Free the list of positional parameters.
  229.  */
  230.  
  231. void
  232. freeparam(param)
  233.     struct shparam *param;
  234.     {
  235.     char **ap;
  236.  
  237.     if (param->malloc) {
  238.         for (ap = param->p ; *ap ; ap++)
  239.             ckfree(*ap);
  240.         ckfree(param->p);
  241.     }
  242. }
  243.  
  244.  
  245.  
  246. /*
  247.  * The shift builtin command.
  248.  */
  249.  
  250. shiftcmd(argc, argv)  char **argv; {
  251.     int n;
  252.     char **ap1, **ap2;
  253.  
  254.     n = 1;
  255.     if (argc > 1)
  256.         n = number(argv[1]);
  257.     if (n > shellparam.nparam)
  258.         n = shellparam.nparam;
  259.     INTOFF;
  260.     shellparam.nparam -= n;
  261.     for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
  262.         if (shellparam.malloc)
  263.             ckfree(*ap1);
  264.     }
  265.     ap2 = shellparam.p;
  266.     while ((*ap2++ = *ap1++) != NULL);
  267.     shellparam.optnext = NULL;
  268.     INTON;
  269.     return 0;
  270. }
  271.  
  272.  
  273.  
  274. /*
  275.  * The set command builtin.
  276.  */
  277.  
  278. setcmd(argc, argv)  char **argv; {
  279.     if (argc == 1)
  280.         return showvarscmd(argc, argv);
  281.     INTOFF;
  282.     options(0);
  283.     setinteractive(iflag);
  284.     setjobctl(jflag);
  285.     if (*argptr != NULL) {
  286.         setparam(argptr);
  287.     }
  288.     INTON;
  289.     return 0;
  290. }
  291.  
  292.  
  293. /*
  294.  * The getopts builtin.  Shellparam.optnext points to the next argument
  295.  * to be processed.  Shellparam.optptr points to the next character to
  296.  * be processed in the current argument.  If shellparam.optnext is NULL,
  297.  * then it's the first time getopts has been called.
  298.  */
  299.  
  300. getoptscmd(argc, argv)  char **argv; {
  301.     register char *p, *q;
  302.     char c;
  303.     char s[10];
  304.  
  305.     if (argc != 3)
  306.         error("Usage: getopts optstring var");
  307.     if (shellparam.optnext == NULL) {
  308.         shellparam.optnext = shellparam.p;
  309.         shellparam.optptr = NULL;
  310.     }
  311.     if ((p = shellparam.optptr) == NULL || *p == '\0') {
  312.         p = *shellparam.optnext;
  313.         if (p == NULL || *p != '-' || *++p == '\0') {
  314. atend:
  315.             fmtstr(s, 10, "%d", shellparam.optnext - shellparam.p + 1);
  316.             setvar("OPTIND", s, 0);
  317.             shellparam.optnext = NULL;
  318.             return 1;
  319.         }
  320.         shellparam.optnext++;
  321.         if (p[0] == '-' && p[1] == '\0')    /* check for "--" */
  322.             goto atend;
  323.     }
  324.     c = *p++;
  325.     for (q = argv[1] ; *q != c ; ) {
  326.         if (*q == '\0') {
  327.             out1fmt("Illegal option -%c\n", c);
  328.             c = '?';
  329.             goto out;
  330.         }
  331.         if (*++q == ':')
  332.             q++;
  333.     }
  334.     if (*++q == ':') {
  335.         if (*p == '\0' && (p = *shellparam.optnext) == NULL) {
  336.             out1fmt("No arg for -%c option\n", c);
  337.             c = '?';
  338.             goto out;
  339.         }
  340.         shellparam.optnext++;
  341.         setvar("OPTARG", p, 0);
  342.         p = NULL;
  343.     }
  344. out:
  345.     shellparam.optptr = p;
  346.     s[0] = c;
  347.     s[1] = '\0';
  348.     setvar(argv[2], s, 0);
  349.     return 0;
  350. }
  351.  
  352. /*
  353.  * Standard option processing (a la getopt) for builtin routines.  The
  354.  * only argument that is passed to nextopt is the option string; the
  355.  * other arguments are unnecessary.  It return the character, or '\0' on
  356.  * end of input.
  357.  */
  358.  
  359. int
  360. nextopt(optstring)
  361.     char *optstring;
  362.     {
  363.     register char *p, *q;
  364.     char c;
  365.  
  366.     if ((p = optptr) == NULL || *p == '\0') {
  367.         p = *argptr;
  368.         if (p == NULL || *p != '-' || *++p == '\0')
  369.             return '\0';
  370.         argptr++;
  371.         if (p[0] == '-' && p[1] == '\0')    /* check for "--" */
  372.             return '\0';
  373.     }
  374.     c = *p++;
  375.     for (q = optstring ; *q != c ; ) {
  376.         if (*q == '\0')
  377.             error("Illegal option -%c", c);
  378.         if (*++q == ':')
  379.             q++;
  380.     }
  381.     if (*++q == ':') {
  382.         if (*p == '\0' && (p = *argptr++) == NULL)
  383.             error("No arg for -%c option", c);
  384.         optarg = p;
  385.         p = NULL;
  386.     }
  387.     optptr = p;
  388.     return c;
  389. }
  390.