BSD 4 release
[unix-history] / usr / src / cmd / csh / sh.c
index 17168f8..dea30dd 100644 (file)
@@ -1,36 +1,41 @@
-/* Copyright (c) 1979 Regents of the University of California */
-#include "sh.h"
+static char *sccsid = "@(#)sh.c 4.1 10/9/80";
 
 
+#include "sh.h"
+#include <sys/ioctl.h>
 /*
  * C Shell
  *
 /*
  * C Shell
  *
- * Bill Joy, UC Berkeley
- * October, 1978
+ * Bill Joy, UC Berkeley, California, USA
+ * October 1978, May 1980
+ *
+ * Jim Kulp, IIASA, Laxenburg, Austria
+ * April 1980
  */
 
  */
 
-char   *pathlist[] =   { SRCHPATH, 0 };
+char   *pathlist[] =   { ".", "/usr/ucb", "/bin", "/usr/bin", 0 };
+char   HIST = '!';
+char   HISTSUB = '^';
+bool   nofile;
+bool   reenter;
+bool   nverbose;
+bool   nexececho;
+bool   quitit;
+bool   fast;
+bool   prompt = 1;
 
 main(c, av)
        int c;
        char **av;
 {
        register char **v, *cp;
 
 main(c, av)
        int c;
        char **av;
 {
        register char **v, *cp;
-       int nofile = 0;
-       int reenter = 0;
-       bool nverbose = 0, nexececho = 0, quitit = 0, fast = 0, prompt = 1;
-       char *hp;
+       register int f;
 
        settimes();                     /* Immed. estab. timing base */
 
        settimes();                     /* Immed. estab. timing base */
-       hp = getenv("HOME");
        v = av;
        if (eq(v[0], "a.out"))          /* A.out's are quittable */
                quitit = 1;
        uid = getuid();
        v = av;
        if (eq(v[0], "a.out"))          /* A.out's are quittable */
                quitit = 1;
        uid = getuid();
-#ifdef V6
-       loginsh = eq(*v, "-");          /* To do .login/.logout */
-#else
        loginsh = **v == '-';
        loginsh = **v == '-';
-#endif
        if (loginsh)
                time(&chktim);
 
        if (loginsh)
                time(&chktim);
 
@@ -49,43 +54,47 @@ main(c, av)
         */
 
        set("status", "0");
         */
 
        set("status", "0");
-       if (hp == 0)
+       dinit(cp = getenv("HOME"));     /* dinit thinks that HOME == cwd in a
+                                        * login shell */
+       if (cp == NOSTR)
                fast++;                 /* No home -> can't read scripts */
        else
                fast++;                 /* No home -> can't read scripts */
        else
-               set("home", hp);
-       if (uid == 0)
-               pathlist[0] = "/etc";
-       set1("path", saveblk(pathlist), &shvhed);
+               set("home", savestr(cp));
+       /*
+        * Grab other useful things from the environment.
+        * Should we grab everything??
+        */
+       if ((cp = getenv("USER")) != NOSTR)
+               set("user", savestr(cp));
+       if ((cp = getenv("TERM")) != NOSTR)
+               set("term", savestr(cp));
        /*
         * Re-initialize path if set in environment
        /*
         * Re-initialize path if set in environment
-        *
-       cp = getenv("PATH");
-       if (cp != 0) {
-               register int i = 0;
+        */
+       if ((cp = getenv("PATH")) == NOSTR)
+               set1("path", saveblk(pathlist), &shvhed);
+       else {
+               register unsigned i = 0;
                register char *dp;
                register char **pv;
 
                for (dp = cp; *dp; dp++)
                        if (*dp == ':')
                                i++;
                register char *dp;
                register char **pv;
 
                for (dp = cp; *dp; dp++)
                        if (*dp == ':')
                                i++;
-               pv = calloc(i+1, sizeof (char **));
-               dp = cp;
-               i = 0;
-               while (*dp) {
+               pv = (char **)calloc(i+2, sizeof (char **));
+               for (dp = cp, i = 0; ;)
                        if (*dp == ':') {
                                *dp = 0;
                        if (*dp == ':') {
                                *dp = 0;
-                               pv[i++] = savestr(cp);
-                               *dp = ':';
-                       } else if (*dp == 0) {
-                               pv[i++] = savestr(cp);
+                               pv[i++] = savestr(*cp ? cp : ".");
+                               *dp++ = ':';
+                               cp = dp;
+                       } else if (*dp++ == 0) {
+                               pv[i++] = savestr(*cp ? cp : ".");
                                break;
                        }
                                break;
                        }
-                       dp++;
-               }
                pv[i] = 0;
                set1("path", pv, &shvhed);
        }
                pv[i] = 0;
                set1("path", pv, &shvhed);
        }
-*/
        set("shell", SHELLPATH);
 
        doldol = putn(getpid());                /* For $$ */
        set("shell", SHELLPATH);
 
        doldol = putn(getpid());                /* For $$ */
@@ -99,7 +108,7 @@ main(c, av)
         * We catch it only if we are the login shell.
         */
        parintr = signal(SIGINT, SIG_IGN);      /* parents interruptibility */
         * We catch it only if we are the login shell.
         */
        parintr = signal(SIGINT, SIG_IGN);      /* parents interruptibility */
-       signal(SIGINT, parintr);                        /* ... restore */
+       sigset(SIGINT, parintr);                        /* ... restore */
        parterm = signal(SIGTERM, SIG_IGN);     /* parents terminability */
        signal(SIGTERM, parterm);                       /* ... restore */
 
        parterm = signal(SIGTERM, SIG_IGN);     /* parents terminability */
        signal(SIGTERM, parterm);                       /* ... restore */
 
@@ -119,7 +128,7 @@ main(c, av)
 
                case 0:                 /* -    Interruptible, no prompt */
                        prompt = 0;
 
                case 0:                 /* -    Interruptible, no prompt */
                        prompt = 0;
-                       **av = '-';
+                       setintr++;
                        nofile++;
                        break;
 
                        nofile++;
                        break;
 
@@ -142,7 +151,6 @@ main(c, av)
 
                case 'i':               /* -i   Interactive, even if !intty */
                        intact++;
 
                case 'i':               /* -i   Interactive, even if !intty */
                        intact++;
-                       **av = '-';
                        nofile++;
                        break;
 
                        nofile++;
                        break;
 
@@ -156,14 +164,10 @@ main(c, av)
 
                case 's':               /* -s   Read from std input */
                        nofile++;
 
                case 's':               /* -s   Read from std input */
                        nofile++;
-                       if (isatty(SHIN))
-                               **v = '-';
                        break;
 
                case 't':               /* -t   Read one line from input */
                        onelflg = 2;
                        break;
 
                case 't':               /* -t   Read one line from input */
                        onelflg = 2;
-                       if (isatty(SHIN))
-                               **v = '-';
                        prompt = 0;
                        nofile++;
                        break;
                        prompt = 0;
                        nofile++;
                        break;
@@ -207,39 +211,27 @@ main(c, av)
                prompt = 0;
                c--, v++;
        }
                prompt = 0;
                c--, v++;
        }
-
        /*
         * Consider input a tty if it really is or we are interactive.
         */
        intty = intact || isatty(SHIN);
        /*
         * Consider input a tty if it really is or we are interactive.
         */
        intty = intact || isatty(SHIN);
+       /*
+        * Decide whether we should play with signals or not.
+        * If we are explicitly told (via -i, or -) or we are a login
+        * shell (arg0 starts with -) or the input and output are both
+        * the ttys("csh", or "csh</dev/ttyx>/dev/ttyx")
+        * Note that in only the login shell is it likely that parent
+        * may have set signals to be ignored
+        */
+       if (loginsh || intact || intty && isatty(SHOUT))
+               setintr = 1;
 #ifdef TELL
        settell();
 #endif
        /*
 #ifdef TELL
        settell();
 #endif
        /*
-        * Commands are interruptible if we are interactive
-        * or the process which created us was.
-        */
-       if (intact || parintr == SIG_DFL)
-               **av = '-';
-
-       /*
-        * Save the remaining arguments in ARGV.
-        * Normally the system-supplied argument list is ok as
-        * a zero terminated value block.
-        * On some version 6 systems, it is -1 terminated and setting it
-        * to zero messes up "ps" so we change it to zero, copy
-        * the block of pointers, and put it back the way it was.
+        * Save the remaining arguments in argv.
         */
         */
-/*
-       if (c == 0)
-               set("argv", 0);
-       else
- */
-       if ((int) v[c] == -1) {
-               /* ick */
-               v[c] = 0, setq("argv", copyblk(v), &shvhed), v[c] = (char *) -1;
-       } else
-               setq("argv", v, &shvhed);
+       setq("argv", v, &shvhed);
 
        /*
         * Set up the prompt.
 
        /*
         * Set up the prompt.
@@ -251,13 +243,66 @@ main(c, av)
         * If we are an interactive shell, then start fiddling
         * with the signals; this is a tricky game.
         */
         * If we are an interactive shell, then start fiddling
         * with the signals; this is a tricky game.
         */
-       if (**av == '-') {
-               setintr++;
+       shpgrp = getpgrp(0);
+       opgrp = tpgrp = -1;
+       oldisc = -1;
+       if (setintr) {
+               **av = '-';
                if (!quitit)            /* Wary! */
                        signal(SIGQUIT, SIG_IGN);
                if (!quitit)            /* Wary! */
                        signal(SIGQUIT, SIG_IGN);
-               signal(SIGINT, SIG_IGN);
+               sigset(SIGINT, pintr);
+               sighold(SIGINT);
                signal(SIGTERM, SIG_IGN);
                signal(SIGTERM, SIG_IGN);
+               if (quitit == 0 && arginp == 0) {
+                       signal(SIGTSTP, SIG_IGN);
+                       signal(SIGTTIN, SIG_IGN);
+                       signal(SIGTTOU, SIG_IGN);
+                       /*
+                        * Wait till in foreground, in case someone
+                        * stupidly runs
+                        *      csh &
+                        * dont want to try to grab away the tty.
+                        */
+                       if (isatty(FSHDIAG))
+                               f = FSHDIAG;
+                       else if (isatty(FSHOUT))
+                               f = FSHOUT;
+                       else if (isatty(OLDSTD))
+                               f = OLDSTD;
+                       else
+                               f = -1;
+retry:
+                       if (ioctl(f, TIOCGPGRP, &tpgrp) == 0 && tpgrp != -1) {
+                               int ldisc;
+                               if (tpgrp != shpgrp) {
+                                       int old = sigsys(SIGTTIN, SIG_DFL);
+                                       kill(0, SIGTTIN);
+                                       sigsys(SIGTTIN, old);
+                                       goto retry;
+                               }
+                               if (ioctl(f, TIOCGETD, &oldisc) != 0) 
+                                       goto notty;
+                               if (oldisc != NTTYDISC) {
+                       printf("Switching to new tty driver...\n");
+                                       ldisc = NTTYDISC;
+                                       ioctl(f, TIOCSETD, &ldisc);
+                               } else
+                                       oldisc = -1;
+                               opgrp = shpgrp;
+                               shpgrp = getpid();
+                               tpgrp = shpgrp;
+                               ioctl(f, TIOCSPGRP, &shpgrp);
+                               setpgrp(0, shpgrp);
+                               dcopy(f, FSHTTY);
+                               ioctl(FSHTTY, FIOCLEX, 0);
+                       } else {
+notty:
+  printf("Warning: no access to tty; thus no job control in this shell...\n");
+                               tpgrp = -1;
+                       }
+               }
        }
        }
+       sigset(SIGCHLD, pchild);                /* while signals not ready */
 
        /*
         * Set an exit here in case of an interrupt or error reading
 
        /*
         * Set an exit here in case of an interrupt or error reading
@@ -271,12 +316,10 @@ main(c, av)
                srccat(value("home"), "/.cshrc");
                if (!fast && !arginp && !onelflg)
                        dohash();
                srccat(value("home"), "/.cshrc");
                if (!fast && !arginp && !onelflg)
                        dohash();
-               if (loginsh)
-#ifdef NOHELP
-                       srccat("", ".login");
-#else
+               if (loginsh) {
+                       int ldisc;
                        srccat(value("home"), "/.login");
                        srccat(value("home"), "/.login");
-#endif
+               }
        }
 
        /*
        }
 
        /*
@@ -307,6 +350,56 @@ main(c, av)
        exitstat();
 }
 
        exitstat();
 }
 
+untty()
+{
+
+       if (tpgrp > 0) {
+               setpgrp(0, opgrp);
+               ioctl(FSHTTY, TIOCSPGRP, &opgrp);
+               if (oldisc != -1 && oldisc != NTTYDISC) {
+                       printf("\nReverting to old tty driver...\n");
+                       ioctl(FSHTTY, TIOCSETD, &oldisc);
+               }
+       }
+}
+
+importpath(cp)
+char *cp;
+{
+       register int i = 0;
+       register char *dp;
+       register char **pv;
+       int c;
+       static char dot[2] = {'.', 0};
+
+       for (dp = cp; *dp; dp++)
+               if (*dp == ':')
+                       i++;
+       /*
+        * i+2 where i is the number of colons in the path.
+        * There are i+1 directories in the path plus we need
+        * room for a zero terminator.
+        */
+       pv = (char **) calloc(i+2, sizeof (char **));
+       dp = cp;
+       i = 0;
+       if (*dp)
+       for (;;) {
+               if ((c = *dp) == ':' || c == 0) {
+                       *dp = 0;
+                       pv[i++] = savestr(*cp ? cp : dot);
+                       if (c) {
+                               cp = dp + 1;
+                               *dp = ':';
+                       } else
+                               break;
+               }
+               dp++;
+       }
+       pv[i] = 0;
+       set1("path", pv, &shvhed);
+}
+
 /*
  * Source to the file which is the catenation of the argument names.
  */
 /*
  * Source to the file which is the catenation of the argument names.
  */
@@ -318,11 +411,15 @@ srccat(cp, dp)
 
        /* ioctl(unit, FIOCLEX, NULL); */
        xfree(ep);
 
        /* ioctl(unit, FIOCLEX, NULL); */
        xfree(ep);
+#ifdef INGRES
        srcunit(unit, 0);
        srcunit(unit, 0);
+#else
+       srcunit(unit, 1);
+#endif
 }
 
 /*
 }
 
 /*
- * Source to a unit.  If onlyown it must be our file or
+ * Source to a unit.  If onlyown it must be our file or our group or
  * we don't chance it. This occurs on ".cshrc"s and the like.
  */
 srcunit(unit, onlyown)
  * we don't chance it. This occurs on ".cshrc"s and the like.
  */
 srcunit(unit, onlyown)
@@ -334,6 +431,7 @@ srcunit(unit, onlyown)
        int oSHIN = -1, oldintty = intty;
        struct whyle *oldwhyl = whyles;
        char *ogointr = gointr, *oarginp = arginp;
        int oSHIN = -1, oldintty = intty;
        struct whyle *oldwhyl = whyles;
        char *ogointr = gointr, *oarginp = arginp;
+       char *oevalp = evalp, **oevalvec = evalvec;
        int oonelflg = onelflg;
 #ifdef TELL
        bool otell = cantell;
        int oonelflg = onelflg;
 #ifdef TELL
        bool otell = cantell;
@@ -343,24 +441,15 @@ srcunit(unit, onlyown)
        /* The (few) real local variables */
        jmp_buf oldexit;
        int reenter;
        /* The (few) real local variables */
        jmp_buf oldexit;
        int reenter;
-       register int (*oldint)();
 
        if (unit < 0)
                return;
 
        if (unit < 0)
                return;
+       if (didfds)
+               donefds();
        if (onlyown) {
                struct stat stb;
 
        if (onlyown) {
                struct stat stb;
 
-#ifdef CC
-               if (fstat(unit, &stb) < 0 || (stb.st_uid != uid && stb.st_uid != (uid &~ 0377))) {
-#endif
-#ifdef CORY
-               if (fstat(unit, &stb) < 0 || (stb.st_uid != uid && stb.st_uid != (uid &~ 0377))) {
-#endif
-#ifndef CC
-#ifndef CORY
-               if (fstat(unit, &stb) < 0 || stb.st_uid != uid) {
-#endif
-#endif
+               if (fstat(unit, &stb) < 0 || (stb.st_uid != uid && stb.st_gid != getgid())) {
                        close(unit);
                        return;
                }
                        close(unit);
                        return;
                }
@@ -379,27 +468,31 @@ srcunit(unit, onlyown)
         */
        getexit(oldexit);
        reenter = 0;
         */
        getexit(oldexit);
        reenter = 0;
-       oldint = signal(SIGINT, SIG_IGN);
+       if (setintr)
+               sighold(SIGINT);
        setexit();
        reenter++;
        if (reenter == 1) {
                /* Setup the new values of the state stuff saved above */
        setexit();
        reenter++;
        if (reenter == 1) {
                /* Setup the new values of the state stuff saved above */
-               copy(&saveB, &B, sizeof saveB);
+               copy((char *)&saveB, (char *)&B, sizeof saveB);
                fbuf = (char **) 0;
                fseekp = feobp = fblocks = 0;
                oSHIN = SHIN, SHIN = unit, arginp = 0, onelflg = 0;
                intty = isatty(SHIN), whyles = 0, gointr = 0;
                fbuf = (char **) 0;
                fseekp = feobp = fblocks = 0;
                oSHIN = SHIN, SHIN = unit, arginp = 0, onelflg = 0;
                intty = isatty(SHIN), whyles = 0, gointr = 0;
+               evalvec = 0; evalp = 0;
                /*
                 * Now if we are allowing commands to be interrupted,
                 * we let ourselves be interrupted.
                 */
                /*
                 * Now if we are allowing commands to be interrupted,
                 * we let ourselves be interrupted.
                 */
-               signal(SIGINT, setintr ? pintr : oldint);
+               if (setintr)
+                       sigrelse(SIGINT);
 #ifdef TELL
                settell();
 #endif
                process(0);             /* 0 -> blow away on errors */
        }
 #ifdef TELL
                settell();
 #endif
                process(0);             /* 0 -> blow away on errors */
        }
-       signal(SIGINT, oldint);
+       if (setintr)
+               sigrelse(SIGINT);
        if (oSHIN >= 0) {
                register int i;
 
        if (oSHIN >= 0) {
                register int i;
 
@@ -407,13 +500,14 @@ srcunit(unit, onlyown)
                /* This code could get run twice but xfree doesn't care */
                for (i = 0; i < fblocks; i++)
                        xfree(fbuf[i]);
                /* This code could get run twice but xfree doesn't care */
                for (i = 0; i < fblocks; i++)
                        xfree(fbuf[i]);
-               xfree(fbuf);
+               xfree((char *)fbuf);
 
                /* Reset input arena */
 
                /* Reset input arena */
-               copy(&B, &saveB, sizeof B);
+               copy((char *)&B, (char *)&saveB, sizeof B);
 
                close(SHIN), SHIN = oSHIN;
                arginp = oarginp, onelflg = oonelflg;
 
                close(SHIN), SHIN = oSHIN;
                arginp = oarginp, onelflg = oonelflg;
+               evalp = oevalp, evalvec = oevalvec;
                intty = oldintty, whyles = oldwhyl, gointr = ogointr;
 #ifdef TELL
                cantell = otell;
                intty = oldintty, whyles = oldwhyl, gointr = ogointr;
 #ifdef TELL
                cantell = otell;
@@ -426,7 +520,7 @@ srcunit(unit, onlyown)
         * we must also unwind.
         */
        if (reenter >= 2)
         * we must also unwind.
         */
        if (reenter >= 2)
-               error(0);
+               error(NOSTR);
 }
 
 goodbye()
 }
 
 goodbye()
@@ -434,7 +528,7 @@ goodbye()
 
        if (loginsh) {
                signal(SIGQUIT, SIG_IGN);
 
        if (loginsh) {
                signal(SIGQUIT, SIG_IGN);
-               signal(SIGINT, SIG_IGN);
+               sigset(SIGINT, SIG_IGN);
                signal(SIGTERM, SIG_IGN);
                setintr = 0;            /* No interrupts after "logout" */
                if (adrof("home"))
                signal(SIGTERM, SIG_IGN);
                setintr = 0;            /* No interrupts after "logout" */
                if (adrof("home"))
@@ -455,6 +549,7 @@ exitstat()
        exit(getn(value("status")));
 }
 
        exit(getn(value("status")));
 }
 
+char   *jobargv[2] = { "jobs", 0 };
 /*
  * Catch an interrupt, e.g. during lexical input.
  * If we are an interactive shell, we reset the interrupt catch
 /*
  * Catch an interrupt, e.g. during lexical input.
  * If we are an interactive shell, we reset the interrupt catch
@@ -466,8 +561,18 @@ pintr()
 {
        register char **v;
 
 {
        register char **v;
 
+       if (setintr) {
+               sigrelse(SIGINT);
+               if (pjobs) {
+                       pjobs = 0;
+                       printf("\n");
+                       dojobs(jobargv);
+                       bferr("Interrupted");
+               }
+       }
        if (setintr)
        if (setintr)
-               signal(SIGINT, SIG_IGN);
+               sighold(SIGINT);
+       sigrelse(SIGCHLD);
        draino();
 
        /*
        draino();
 
        /*
@@ -485,7 +590,7 @@ pintr()
                reset();
        } else if (intty)
                printf("\n");           /* Some like this, others don't */
                reset();
        } else if (intty)
                printf("\n");           /* Some like this, others don't */
-       error(0);
+       error(NOSTR);
 }
 
 /*
 }
 
 /*
@@ -500,18 +605,18 @@ pintr()
  * if this is ignored.
  *
  * Note that if catch is not set then we will unwind on any error.
  * if this is ignored.
  *
  * Note that if catch is not set then we will unwind on any error.
- * In an end-of-file occurs, we return.
+ * If an end-of-file occurs, we return.
  */
 process(catch)
        bool catch;
 {
        register char *cp;
        jmp_buf osetexit;
  */
 process(catch)
        bool catch;
 {
        register char *cp;
        jmp_buf osetexit;
-       struct wordent paraml;
        struct command *t;
 
        getexit(osetexit);
        for (;;) {
        struct command *t;
 
        getexit(osetexit);
        for (;;) {
+               pendjob();
                paraml.next = paraml.prev = &paraml;
                paraml.word = "";
                t = 0;
                paraml.next = paraml.prev = &paraml;
                paraml.word = "";
                t = 0;
@@ -522,7 +627,7 @@ process(catch)
                 * Interruptible during interactive reads
                 */
                if (setintr)
                 * Interruptible during interactive reads
                 */
                if (setintr)
-                       signal(SIGINT, pintr);
+                       sigrelse(SIGINT);
 
                /*
                 * For the sake of reset()
 
                /*
                 * For the sake of reset()
@@ -553,7 +658,11 @@ process(catch)
                        doneinp = 0;
                        break;
                }
                        doneinp = 0;
                        break;
                }
-               if (intty) {
+               if (chkstop)
+                       chkstop--;
+               if (neednote)
+                       pnote();
+               if (intty && evalvec == 0) {
                        mailchk();
                        /*
                         * If we are at the end of the input buffer
                        mailchk();
                        /*
                         * If we are at the end of the input buffer
@@ -564,10 +673,10 @@ process(catch)
                        if (fseekp == feobp)
                                if (!whyles)
                                        for (cp = value("prompt"); *cp; cp++)
                        if (fseekp == feobp)
                                if (!whyles)
                                        for (cp = value("prompt"); *cp; cp++)
-                                               if (*cp == '!')
+                                               if (*cp == HIST)
                                                        printf("%d", eventno + 1);
                                                else {
                                                        printf("%d", eventno + 1);
                                                else {
-                                                       if (*cp == '\\' && cp[1] == '!')
+                                                       if (*cp == '\\' && cp[1] == HIST)
                                                                cp++;
                                                        putchar(*cp | QUOTE);
                                                }
                                                                cp++;
                                                        putchar(*cp | QUOTE);
                                                }
@@ -595,7 +704,7 @@ process(catch)
                 * The parser may lose space if interrupted.
                 */
                if (setintr)
                 * The parser may lose space if interrupted.
                 */
                if (setintr)
-                       signal(SIGINT, SIG_IGN);
+                       sighold(SIGINT);
 
                /*
                 * Save input text on the history list if it
 
                /*
                 * Save input text on the history list if it
@@ -623,14 +732,14 @@ process(catch)
                /*
                 * Parse the words of the input into a parse tree.
                 */
                /*
                 * Parse the words of the input into a parse tree.
                 */
-               t = syntax(paraml.next, &paraml);
+               t = syntax(paraml.next, &paraml, 0);
                if (err)
                        error(err);
 
                /*
                 * Execute the parse tree
                 */
                if (err)
                        error(err);
 
                /*
                 * Execute the parse tree
                 */
-               execute(t);
+               execute(t, tpgrp);
 
                /*
                 * Made it!
 
                /*
                 * Made it!
@@ -652,7 +761,6 @@ dosource(t)
        xfree(f);
        if (u < 0)
                Perror(f);
        xfree(f);
        if (u < 0)
                Perror(f);
-       didfds = 0;
        srcunit(u, 0);
 }
 
        srcunit(u, 0);
 }
 
@@ -662,7 +770,7 @@ dosource(t)
  * about any mail file unless its been modified
  * after the time we started.
  * This prevents us from telling the user things he already
  * about any mail file unless its been modified
  * after the time we started.
  * This prevents us from telling the user things he already
- * knows, since the login program insist on saying
+ * knows, since the login program insists on saying
  * "You have mail."
  */
 mailchk()
  * "You have mail."
  */
 mailchk()
@@ -671,6 +779,8 @@ mailchk()
        register char **vp;
        time_t t;
        int intvl, cnt;
        register char **vp;
        time_t t;
        int intvl, cnt;
+       struct stat stb;
+       bool new;
 
        v = adrof("mail");
        if (v == 0)
 
        v = adrof("mail");
        if (v == 0)
@@ -684,23 +794,12 @@ mailchk()
        if (chktim + intvl > t)
                return;
        for (; *vp; vp++) {
        if (chktim + intvl > t)
                return;
        for (; *vp; vp++) {
-               bool new;
-               struct stat stb;
-
                if (stat(*vp, &stb) < 0)
                        continue;
                if (stat(*vp, &stb) < 0)
                        continue;
-               /*
-                * We assume that a file has been read if the access time is
-                * greater than the mod time.
-                */
-#ifndef CORY
-               if (stb.st_size == 0)
-                       continue;
-#endif
-               if (stb.st_atime > stb.st_mtime || stb.st_atime < chktim)
-                       continue;
                new = stb.st_mtime > time0;
                new = stb.st_mtime > time0;
-               if (loginsh && !new)
+               if (stb.st_size == 0 || stb.st_atime > stb.st_mtime ||
+                   (stb.st_atime < chktim && stb.st_mtime < chktim) ||
+                   loginsh && !new)
                        continue;
                if (cnt == 1)
                        printf("You have %smail.\n", new ? "new " : "");
                        continue;
                if (cnt == 1)
                        printf("You have %smail.\n", new ? "new " : "");
@@ -744,11 +843,14 @@ initdesc()
        closem();
 }
 
        closem();
 }
 
-#ifndef V6
 exit(i)
        int i;
 {
 
 exit(i)
        int i;
 {
 
+       untty();
+#ifdef PROF
+       IEH3exit(i);
+#else
        _exit(i);
        _exit(i);
-}
 #endif
 #endif
+}