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