home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / bin / sh / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-15  |  6.8 KB  |  326 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. char copyright[] =
  39. "@(#) Copyright (c) 1991 The Regents of the University of California.\n\
  40.  All rights reserved.\n";
  41. #endif /* not lint */
  42.  
  43. #ifndef lint
  44. static char sccsid[] = "@(#)main.c    5.2 (Berkeley) 3/13/91";
  45. #endif /* not lint */
  46.  
  47. #include <signal.h>
  48. #include <fcntl.h>
  49. #include "shell.h"
  50. #include "main.h"
  51. #include "mail.h"
  52. #include "options.h"
  53. #include "output.h"
  54. #include "parser.h"
  55. #include "nodes.h"
  56. #include "eval.h"
  57. #include "jobs.h"
  58. #include "input.h"
  59. #include "trap.h"
  60. #if ATTY
  61. #include "var.h"
  62. #endif
  63. #include "memalloc.h"
  64. #include "error.h"
  65. #include "init.h"
  66. #include "mystring.h"
  67.  
  68. #define PROFILE 0
  69.  
  70. int rootpid;
  71. int rootshell;
  72. STATIC union node *curcmd;
  73. STATIC union node *prevcmd;
  74. extern int errno;
  75. #if PROFILE
  76. short profile_buf[16384];
  77. extern int etext();
  78. #endif
  79.  
  80. #ifdef __STDC__
  81. STATIC void read_profile(char *);
  82. char *getenv(char *);
  83. #else
  84. STATIC void read_profile();
  85. char *getenv();
  86. #endif
  87.  
  88.  
  89. /*
  90.  * Main routine.  We initialize things, parse the arguments, execute
  91.  * profiles if we're a login shell, and then call cmdloop to execute
  92.  * commands.  The setjmp call sets up the location to jump to when an
  93.  * exception occurs.  When an exception occurs the variable "state"
  94.  * is used to figure out how far we had gotten.
  95.  */
  96.  
  97. main(argc, argv)  char **argv; {
  98.     struct jmploc jmploc;
  99.     struct stackmark smark;
  100.     volatile int state;
  101.     char *shinit;
  102.  
  103. #if PROFILE
  104.     monitor(4, etext, profile_buf, sizeof profile_buf, 50);
  105. #endif
  106.     state = 0;
  107.     if (setjmp(jmploc.loc)) {
  108.         /*
  109.          * When a shell procedure is executed, we raise the
  110.          * exception EXSHELLPROC to clean up before executing
  111.          * the shell procedure.
  112.          */
  113.         if (exception == EXSHELLPROC) {
  114.             rootpid = getpid();
  115.             rootshell = 1;
  116.             minusc = NULL;
  117.             state = 3;
  118.         } else if (state == 0 || iflag == 0 || ! rootshell)
  119.             exitshell(2);
  120.         reset();
  121. #if ATTY
  122.         if (exception == EXINT
  123.          && (! attyset() || equal(termval(), "emacs"))) {
  124. #else
  125.         if (exception == EXINT) {
  126. #endif
  127.             out2c('\n');
  128.             flushout(&errout);
  129.         }
  130.         popstackmark(&smark);
  131.         FORCEINTON;                /* enable interrupts */
  132.         if (state == 1)
  133.             goto state1;
  134.         else if (state == 2)
  135.             goto state2;
  136.         else
  137.             goto state3;
  138.     }
  139.     handler = &jmploc;
  140. #ifdef DEBUG
  141.     opentrace();
  142.     trputs("Shell args:  ");  trargs(argv);
  143. #endif
  144.     rootpid = getpid();
  145.     rootshell = 1;
  146.     init();
  147.     setstackmark(&smark);
  148.     procargs(argc, argv);
  149.     if (argv[0] && argv[0][0] == '-') {
  150.         state = 1;
  151.         read_profile("/etc/profile");
  152. state1:
  153.         state = 2;
  154.         read_profile(".profile");
  155.     } else if ((sflag || minusc) && (shinit = getenv("SHINIT")) != NULL) {
  156.         state = 2;
  157.         evalstring(shinit);
  158.     }
  159. state2:
  160.     state = 3;
  161.     if (minusc) {
  162.         evalstring(minusc);
  163.     }
  164.     if (sflag || minusc == NULL) {
  165. state3:
  166.         cmdloop(1);
  167.     }
  168. #if PROFILE
  169.     monitor(0);
  170. #endif
  171.     exitshell(exitstatus);
  172. }
  173.  
  174.  
  175. /*
  176.  * Read and execute commands.  "Top" is nonzero for the top level command
  177.  * loop; it turns on prompting if the shell is interactive.
  178.  */
  179.  
  180. void
  181. cmdloop(top) {
  182.     union node *n;
  183.     struct stackmark smark;
  184.     int inter;
  185.     int numeof;
  186.  
  187.     TRACE(("cmdloop(%d) called\n", top));
  188.     setstackmark(&smark);
  189.     numeof = 0;
  190.     for (;;) {
  191.         if (pendingsigs)
  192.             dotrap();
  193.         inter = 0;
  194.         if (iflag && top) {
  195.             inter++;
  196.             showjobs(1);
  197.             chkmail(0);
  198.             flushout(&output);
  199.         }
  200.         n = parsecmd(inter);
  201. #ifdef DEBUG
  202.         /* showtree(n); */
  203. #endif
  204.         if (n == NEOF) {
  205.             if (Iflag == 0 || numeof >= 50)
  206.                 break;
  207.             out2str("\nUse \"exit\" to leave shell.\n");
  208.             numeof++;
  209.         } else if (n != NULL && nflag == 0) {
  210.             if (inter) {
  211.                 INTOFF;
  212.                 if (prevcmd)
  213.                     freefunc(prevcmd);
  214.                 prevcmd = curcmd;
  215.                 curcmd = copyfunc(n);
  216.                 INTON;
  217.             }
  218.             evaltree(n, 0);
  219. #ifdef notdef
  220.             if (exitstatus)                      /*DEBUG*/
  221.                 outfmt(&errout, "Exit status 0x%X\n", exitstatus);
  222. #endif
  223.         }
  224.         popstackmark(&smark);
  225.     }
  226.     popstackmark(&smark);        /* unnecessary */
  227. }
  228.  
  229.  
  230.  
  231. /*
  232.  * Read /etc/profile or .profile.  Return on error.
  233.  */
  234.  
  235. STATIC void
  236. read_profile(name)
  237.     char *name;
  238.     {
  239.     int fd;
  240.  
  241.     INTOFF;
  242.     if ((fd = open(name, O_RDONLY)) >= 0)
  243.         setinputfd(fd, 1);
  244.     INTON;
  245.     if (fd < 0)
  246.         return;
  247.     cmdloop(0);
  248.     popfile();
  249. }
  250.  
  251.  
  252.  
  253. /*
  254.  * Read a file containing shell functions.
  255.  */
  256.  
  257. void
  258. readcmdfile(name)
  259.     char *name;
  260.     {
  261.     int fd;
  262.  
  263.     INTOFF;
  264.     if ((fd = open(name, O_RDONLY)) >= 0)
  265.         setinputfd(fd, 1);
  266.     else
  267.         error("Can't open %s", name);
  268.     INTON;
  269.     cmdloop(0);
  270.     popfile();
  271. }
  272.  
  273.  
  274.  
  275. /*
  276.  * Take commands from a file.  To be compatable we should do a path
  277.  * search for the file, but a path search doesn't make any sense.
  278.  */
  279.  
  280. dotcmd(argc, argv)  char **argv; {
  281.     exitstatus = 0;
  282.     if (argc >= 2) {        /* That's what SVR2 does */
  283.         setinputfile(argv[1], 1);
  284.         commandname = argv[1];
  285.         cmdloop(0);
  286.         popfile();
  287.     }
  288.     return exitstatus;
  289. }
  290.  
  291.  
  292. exitcmd(argc, argv)  char **argv; {
  293.     if (argc > 1)
  294.         exitstatus = number(argv[1]);
  295.     exitshell(exitstatus);
  296. }
  297.  
  298.  
  299. lccmd(argc, argv)  char **argv; {
  300.     if (argc > 1) {
  301.         defun(argv[1], prevcmd);
  302.         return 0;
  303.     } else {
  304.         INTOFF;
  305.         freefunc(curcmd);
  306.         curcmd = prevcmd;
  307.         prevcmd = NULL;
  308.         INTON;
  309.         evaltree(curcmd, 0);
  310.         return exitstatus;
  311.     }
  312. }
  313.  
  314.  
  315.  
  316. #ifdef notdef
  317. /*
  318.  * Should never be called.
  319.  */
  320.  
  321. void
  322. exit(exitstatus) {
  323.     _exit(exitstatus);
  324. }
  325. #endif
  326.