BSD 4 release
[unix-history] / usr / src / cmd / csh / sh.func.c
index 59062c5..b353ddd 100644 (file)
@@ -1,19 +1,37 @@
-/* Copyright (c) 1979 Regents of the University of California */
+static char *sccsid = "@(#)sh.func.c 4.1 10/9/80";
+
 #include "sh.h"
 #include "sh.h"
+#include <sys/ioctl.h>
 
 /*
  * C shell
  */
 
 struct biltins *
 
 /*
  * C shell
  */
 
 struct biltins *
-isbfunc(cp)
-       register char *cp;
+isbfunc(t)
+       register struct command *t;
 {
 {
+       register char *cp = t->t_dcom[0];
        register char *dp;
        register struct biltins *bp;
        register char *dp;
        register struct biltins *bp;
-
-       if (lastchr(cp) == ':')
-               return ((struct biltins *) 1);
+       int dolabel(), dofg1(), dobg1();
+       static struct biltins label = { "", dolabel, 0, 0 };
+       static struct biltins foregnd = { "%job", dofg1, 0, 0 };
+       static struct biltins backgnd = { "%job &", dobg1, 0, 0 };
+
+       if (lastchr(cp) == ':') {
+               label.bname = cp;
+               return (&label);
+       }
+       if (*cp == '%') {
+               if (t->t_dflg & FAND) {
+                       t->t_dflg &= ~FAND;
+                       backgnd.bname = cp;
+                       return (&backgnd);
+               } 
+               foregnd.bname = cp;
+               return (&foregnd);
+       }
        for (bp = bfunc; dp = bp->bname; bp++) {
                if (dp[0] == cp[0] && eq(dp, cp))
                        return (bp);
        for (bp = bfunc; dp = bp->bname; bp++) {
                if (dp[0] == cp[0] && eq(dp, cp))
                        return (bp);
@@ -23,28 +41,12 @@ isbfunc(cp)
        return (0);
 }
 
        return (0);
 }
 
-func(t)
+func(t, bp)
        register struct command *t;
        register struct command *t;
-{
        register struct biltins *bp;
        register struct biltins *bp;
+{
        int i;
 
        int i;
 
-       bp = bfunc;
-       if (lastchr(t->t_dcom[0]) == ':') {
-               xechoit(t->t_dcom);
-               if (!eq(t->t_dcom[0], ":") && t->t_dcom[1])
-                       error("No args on labels");
-               return (1);
-       }
-       bp = isbfunc(t->t_dcom[0]);
-       if (bp == 0)
-               return (0);
-       /* timed builtins must go in background if output is pipe, or &'ed */
-       if (eq(bp->bname, "time"))
-               if ((t->t_dflg & FAND) || (t->t_dflg & FPOU))
-                       return (0);
-       if (eq(bp->bname, "nohup") && t->t_dcom[1])
-               return (0);
        xechoit(t->t_dcom);
        setname(bp->bname);
        i = blklen(t->t_dcom) - 1;
        xechoit(t->t_dcom);
        setname(bp->bname);
        i = blklen(t->t_dcom) - 1;
@@ -52,9 +54,12 @@ func(t)
                bferr("Too few arguments");
        if (i > bp->maxargs)
                bferr("Too many arguments");
                bferr("Too few arguments");
        if (i > bp->maxargs)
                bferr("Too many arguments");
-       i = (*bp->bfunct)(t->t_dcom, t);
-       /* time and nice may not do their deeds, all others guarantee too */
-       return (eq(bp->bname, "time") || eq(bp->bname, "nice") ? i : 1);
+       (*bp->bfunct)(t->t_dcom, t);
+}
+
+dolabel()
+{
+
 }
 
 doonintr(v)
 }
 
 doonintr(v)
@@ -69,14 +74,17 @@ doonintr(v)
                bferr("Can't from terminal");
        cp = gointr, gointr = 0, xfree(cp);
        if (vv == 0) {
                bferr("Can't from terminal");
        cp = gointr, gointr = 0, xfree(cp);
        if (vv == 0) {
-               signal(SIGINT, setintr ? SIG_IGN : SIG_DFL);
+               if (setintr)
+                       sighold(SIGINT);
+               else
+                       sigset(SIGINT, SIG_DFL);
                gointr = 0;
        } else if (eq((vv = strip(vv)), "-")) {
                gointr = 0;
        } else if (eq((vv = strip(vv)), "-")) {
-               signal(SIGINT, SIG_IGN);
+               sigset(SIGINT, SIG_IGN);
                gointr = "-";
        } else {
                gointr = savestr(vv);
                gointr = "-";
        } else {
                gointr = savestr(vv);
-               signal(SIGINT, pintr);
+               sigset(SIGINT, pintr);
        }
 }
 
        }
 }
 
@@ -99,28 +107,6 @@ dozip()
        ;
 }
 
        ;
 }
 
-chngd(vp)
-       register char **vp;
-{
-       register int i;
-       register char *dp;
-
-       vp++;
-       dp = *vp;
-       if (dp)
-               dp = globone(dp);
-       else {
-               dp = value("home");
-               if (*dp == 0)
-                       bferr("No home");
-       }
-       i = chdir(dp);
-       if (*vp)
-               xfree(dp);
-       if (i < 0)
-               Perror(dp);
-}
-
 prvars()
 {
 
 prvars()
 {
 
@@ -169,7 +155,9 @@ dologin(v)
 {
 
        islogin();
 {
 
        islogin();
+       signal(SIGTERM, parterm);
        execl("/bin/login", "login", v[1], 0);
        execl("/bin/login", "login", v[1], 0);
+       untty();
        exit(1);
 }
 
        exit(1);
 }
 
@@ -177,13 +165,18 @@ donewgrp(v)
        char **v;
 {
 
        char **v;
 {
 
+       signal(SIGTERM, parterm);
        execl("/bin/newgrp", "newgrp", v[1], 0);
        execl("/usr/bin/newgrp", "newgrp", v[1], 0);
        execl("/bin/newgrp", "newgrp", v[1], 0);
        execl("/usr/bin/newgrp", "newgrp", v[1], 0);
+       untty();
+       exit(1);
 }
 
 islogin()
 {
 
 }
 
 islogin()
 {
 
+       if (chkstop == 0 && setintr)
+               panystop(0);
        if (loginsh)
                return;
        error("Not login shell");
        if (loginsh)
                return;
        error("Not login shell");
@@ -199,9 +192,10 @@ doif(v, kp)
        v++;
        i = exp(&v);
        vv = v;
        v++;
        i = exp(&v);
        vv = v;
-       if (*vv && eq(*vv, "then")) {
-               vv++;
-               if (*vv)
+       if (*vv == NOSTR)
+               bferr("Empty if");
+       if (eq(*vv, "then")) {
+               if (*++vv)
                        bferr("Improper then");
                setname("then");
                /*
                        bferr("Improper then");
                setname("then");
                /*
@@ -232,8 +226,15 @@ reexecute(kp)
        register struct command *kp;
 {
 
        register struct command *kp;
 {
 
-       kp->t_dflg = FREDO;
-       execute(kp);
+       kp->t_dflg &= FSAVE;
+       kp->t_dflg |= FREDO;
+       /*
+        * If tty is still ours to arbitrate, arbitrate it;
+        * otherwise dont even set pgrp's as the jobs would
+        * then have no way to get the tty (we can't give it
+        * to them, and our parent wouldn't know their pgrp, etc.
+        */
+       execute(kp, tpgrp > 0 ? tpgrp : -1);
 }
 
 doelse()
 }
 
 doelse()
@@ -254,9 +255,10 @@ dogoto(v)
         * don't really parse.
         */
        for (wp = whyles; wp; wp = wp->w_next)
         * don't really parse.
         */
        for (wp = whyles; wp; wp = wp->w_next)
-               if (wp->w_end == 0)
-                       wp->w_end = search(ZBREAK, 0);
-               else
+               if (wp->w_end == 0) {
+                       search(ZBREAK, 0);
+                       wp->w_end = btell();
+               } else
                        bseek(wp->w_end);
        search(ZGOTO, 0, lp = globone(v[1]));
        xfree(lp);
                        bseek(wp->w_end);
        search(ZGOTO, 0, lp = globone(v[1]));
        xfree(lp);
@@ -297,6 +299,8 @@ doexit(v)
        char **v;
 {
 
        char **v;
 {
 
+       if (chkstop == 0)
+               panystop(0);
        /*
         * Don't DEMAND parentheses here either.
         */
        /*
         * Don't DEMAND parentheses here either.
         */
@@ -350,7 +354,8 @@ dowhile(v)
        char **v;
 {
        register int status;
        char **v;
 {
        register int status;
-       register bool again = whyles != 0 && whyles->w_start == lineloc;
+       register bool again = whyles != 0 && whyles->w_start == lineloc &&
+           whyles->w_fename == 0;
 
        v++;
        /*
 
        v++;
        /*
@@ -387,14 +392,13 @@ dowhile(v)
 
 preread()
 {
 
 preread()
 {
-       register int (*oldint)();
 
        whyles->w_end = -1;
        if (setintr)
 
        whyles->w_end = -1;
        if (setintr)
-               oldint = signal(SIGINT, pintr);
+               sigrelse(SIGINT);
        search(ZBREAK, 0);
        if (setintr)
        search(ZBREAK, 0);
        if (setintr)
-               signal(SIGINT, oldint);
+               sighold(SIGINT);
        whyles->w_end = btell();
 }
 
        whyles->w_end = btell();
 }
 
@@ -441,21 +445,20 @@ dorepeat(v, kp)
        struct command *kp;
 {
        register int i;
        struct command *kp;
 {
        register int i;
-       register int (*saveintr)();
 
        i = getn(v[1]);
        if (setintr)
 
        i = getn(v[1]);
        if (setintr)
-               saveintr = signal(SIGINT, SIG_IGN);
+               sighold(SIGINT);
        lshift(v, 2);
        while (i > 0) {
                if (setintr)
        lshift(v, 2);
        while (i > 0) {
                if (setintr)
-                       signal(SIGINT, pintr);
+                       sigrelse(SIGINT);
                reexecute(kp);
                --i;
        }
        donefds();
        if (setintr)
                reexecute(kp);
                --i;
        }
        donefds();
        if (setintr)
-               signal(SIGINT, saveintr);
+               sigrelse(SIGINT);
 }
 
 doswbrk()
 }
 
 doswbrk()
@@ -567,7 +570,7 @@ search(type, level, goal)
                                level = -1;
                        break;
                }
                                level = -1;
                        break;
                }
-               getword(0);
+               getword(NOSTR);
        } while (level >= 0);
 }
 
        } while (level >= 0);
 }
 
@@ -659,7 +662,7 @@ wfree()
                        blkfree(wp->w_fe0);
                if (wp->w_fename)
                        xfree(wp->w_fename);
                        blkfree(wp->w_fe0);
                if (wp->w_fename)
                        xfree(wp->w_fename);
-               xfree(wp);
+               xfree((char *)wp);
                whyles = nwp;
        }
 }
                whyles = nwp;
        }
 }
@@ -684,10 +687,10 @@ echo(sep, v)
        register char **v;
 {
        register char *cp;
        register char **v;
 {
        register char *cp;
-       int (*saveintr)();
-       if (setintr)
-               saveintr = signal(SIGINT, pintr);
+       int nonl = 0;
 
 
+       if (setintr)
+               sigrelse(SIGINT);
        v++;
        if (*v == 0)
                return;
        v++;
        if (*v == 0)
                return;
@@ -698,34 +701,26 @@ echo(sep, v)
                        bferr("No match");
        } else
                scan(v, trim);
                        bferr("No match");
        } else
                scan(v, trim);
+       if (sep == ' ' && !strcmp(*v, "-n"))
+               nonl++, v++;
        while (cp = *v++) {
                register int c;
 
        while (cp = *v++) {
                register int c;
 
-               while (c = *cp++) {
-                       if (sep == ' ' && *cp && c == '\\') {
-                               c = *cp++;
-                               if (c == 'c') {
-                                       flush();
-                                       return;
-                               } else if (c == 'n')
-                                       c = '\n';
-                               else
-                                       putchar('\\');
-                       }
+               while (c = *cp++)
                        putchar(c | QUOTE);
                        putchar(c | QUOTE);
-               }
                if (*v)
                        putchar(sep | QUOTE);
        }
                if (*v)
                        putchar(sep | QUOTE);
        }
-       if (sep)
+       if (sep && nonl == 0)
                putchar('\n');
                putchar('\n');
+       else
+               flush();
        if (setintr)
        if (setintr)
-               signal(SIGINT, saveintr);
+               sighold(SIGINT);
        if (gargv)
                blkfree(gargv), gargv = 0;
 }
 
        if (gargv)
                blkfree(gargv), gargv = 0;
 }
 
-#ifndef        V6
 char   **environ;
 
 dosetenv(v)
 char   **environ;
 
 dosetenv(v)
@@ -734,9 +729,23 @@ dosetenv(v)
        char *lp = globone(v[2]);
 
        setenv(v[1], lp);
        char *lp = globone(v[2]);
 
        setenv(v[1], lp);
+       if (eq(v[1], "PATH")) {
+               importpath(lp);
+               dohash();
+       }
        xfree(lp);
 }
 
        xfree(lp);
 }
 
+dounsetenv(v)
+       register char **v;
+{
+
+       v++;
+       do
+               unsetenv(*v++);
+       while (*v);
+}
+
 setenv(name, value)
        char *name, *value;
 {
 setenv(name, value)
        char *name, *value;
 {
@@ -758,10 +767,32 @@ setenv(name, value)
        }
        blk[0] = strspl(name, "="); blk[1] = 0;
        environ = blkspl(environ, blk);
        }
        blk[0] = strspl(name, "="); blk[1] = 0;
        environ = blkspl(environ, blk);
-       xfree(oep);
+       xfree((char *)oep);
        setenv(name, value);
 }
 
        setenv(name, value);
 }
 
+unsetenv(name)
+       char *name;
+{
+       register char **ep = environ;
+       register char *cp, *dp;
+       char **oep = ep;
+
+       for (; *ep; ep++) {
+               for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++)
+                       continue;
+               if (*cp != 0 || *dp != '=')
+                       continue;
+               cp = *ep;
+               *ep = 0;
+               environ = blkspl(environ, ep+1);
+               *ep = cp;
+               xfree(cp);
+               xfree((char *)oep);
+               return;
+       }
+}
+
 doumask(v)
        register char **v;
 {
 doumask(v)
        register char **v;
 {
@@ -781,4 +812,255 @@ doumask(v)
                bferr("Improper mask");
        umask(i);
 }
                bferr("Improper mask");
        umask(i);
 }
-#endif
+
+#include <sys/limit.h>
+
+struct limits {
+       int     limconst;
+       char    *limname;
+       int     limdiv;
+       char    *limscale;
+} limits[] = {
+       LIM_NORAISE,    "noraise",      1,      "",
+       LIM_CPU,        "cputime",      1,      "seconds",
+       LIM_FSIZE,      "filesize",     1024,   "kbytes",
+       LIM_DATA,       "datasize",     1024,   "kbytes",
+       LIM_STACK,      "stacksize",    1024,   "kbytes",
+       LIM_CORE,       "coredumpsize", 1024,   "kbytes",
+       -1,             0,
+};
+
+struct limits *
+findlim(cp)
+       char *cp;
+{
+       register struct limits *lp, *res;
+
+       res = 0;
+       for (lp = limits; lp->limconst >= 0; lp++)
+               if (prefix(cp, lp->limname)) {
+                       if (res)
+                               bferr("Ambiguous");
+                       res = lp;
+               }
+       if (res)
+               return (res);
+       bferr("No such limit");
+}
+
+dolimit(v)
+       register char **v;
+{
+       register struct limits *lp;
+       register int limit;
+
+       v++;
+       if (*v == 0) {
+               for (lp = limits+1; lp->limconst >= 0; lp++)
+                       plim(lp);
+               if (vlimit(LIM_NORAISE, -1) && getuid())
+                       printf("Limits cannot be raised\n");
+               return;
+       }
+       lp = findlim(v[0]);
+       if (v[1] == 0) {
+               plim(lp);
+               return;
+       }
+       limit = getval(lp, v+1);
+       setlim(lp, limit);
+}
+
+getval(lp, v)
+       register struct limits *lp;
+       char **v;
+{
+       register float f;
+       double atof();
+       char *cp = *v++;
+
+       f = atof(cp);
+       while (digit(*cp) || *cp == '.' || *cp == 'e' || *cp == 'E')
+               cp++;
+       if (*cp == 0) {
+               if (*v == 0)
+                       return ((int)(f+0.5) * lp->limdiv);
+               cp = *v;
+       }
+       if (lp->limconst == LIM_NORAISE)
+               goto badscal;
+       switch (*cp) {
+
+       case ':':
+               if (lp->limconst != LIM_CPU)
+                       goto badscal;
+               return ((int)(f * 60.0 + atof(cp+1)));
+
+       case 'h':
+               if (lp->limconst != LIM_CPU)
+                       goto badscal;
+               limtail(cp, "hours");
+               f *= 3600.;
+               break;
+
+       case 'm':
+               if (lp->limconst == LIM_CPU) {
+                       limtail(cp, "minutes");
+                       f *= 60.;
+                       break;
+               }
+       case 'M':
+               if (lp->limconst == LIM_CPU)
+                       goto badscal;
+               *cp = 'm';
+               limtail(cp, "megabytes");
+               f *= 1024.*1024.;
+               break;
+
+       case 's':
+               if (lp->limconst != LIM_CPU)
+                       goto badscal;
+               limtail(cp, "seconds");
+               break;
+
+       case 'k':
+               if (lp->limconst == LIM_CPU)
+                       goto badscal;
+               limtail(cp, "kbytes");
+               f *= 1024;
+               break;
+
+       case 'u':
+               limtail(cp, "unlimited");
+               return (INFINITY);
+
+       default:
+badscal:
+               bferr("Improper or unknown scale factor");
+       }
+       return ((int)(f+0.5));
+}
+
+limtail(cp, str0)
+       char *cp, *str0;
+{
+       register char *str = str0;
+
+       while (*cp && *cp == *str)
+               cp++, str++;
+       if (*cp)
+               error("Bad scaling; did you mean ``%s''?", str0);
+}
+
+plim(lp)
+       register struct limits *lp;
+{
+       register int lim;
+
+       printf("%s \t", lp->limname);
+       lim = vlimit(lp->limconst, -1);
+       if (lim == INFINITY)
+               printf("unlimited");
+       else if (lp->limconst == LIM_CPU)
+               psecs((long)lim);
+       else
+               printf("%d %s", lim / lp->limdiv, lp->limscale);
+       printf("\n");
+}
+
+dounlimit(v)
+       register char **v;
+{
+       register struct limits *lp;
+
+       v++;
+       if (*v == 0) {
+               for (lp = limits+1; lp->limconst >= 0; lp++)
+                       setlim(lp, INFINITY);
+               return;
+       }
+       while (*v) {
+               lp = findlim(*v++);
+               setlim(lp, INFINITY);
+       }
+}
+
+setlim(lp, limit)
+       register struct limits *lp;
+{
+
+       if (vlimit(lp->limconst, limit) < 0)
+               Perror(bname);
+}
+
+dosuspend()
+{
+       int old, ldisc;
+       short ctpgrp;
+
+       if (loginsh)
+               error("Can't suspend a login shell (yet)");
+       untty();
+       old = sigsys(SIGTSTP, SIG_DFL);
+       kill(0, SIGTSTP);
+       /* the shell stops here */
+       sigsys(SIGTSTP, old);
+       if (tpgrp != -1) {
+retry:
+               ioctl(FSHTTY, TIOCGPGRP, &ctpgrp);
+               if (ctpgrp != opgrp) {
+                       old = sigsys(SIGTTIN, SIG_DFL);
+                       kill(0, SIGTTIN);
+                       sigsys(SIGTTIN, old);
+                       goto retry;
+               }
+               ioctl(FSHTTY, TIOCSPGRP, &shpgrp);
+               setpgrp(0, shpgrp);
+       }
+       ioctl(FSHTTY, TIOCGETD, &oldisc);
+       if (oldisc != NTTYDISC) {
+               printf("Switching to new tty driver...\n");
+               ldisc = NTTYDISC;
+               ioctl(FSHTTY, TIOCSETD, &ldisc);
+       }
+}
+
+doeval(v)
+       char **v;
+{
+       char **oevalvec = evalvec;
+       char *oevalp = evalp;
+       jmp_buf osetexit;
+       int reenter;
+       char **gv = 0;
+
+       v++;
+       if (*v == 0)
+               return;
+       gflag = 0; rscan(v, tglob);
+       if (gflag) {
+               gv = v = glob(v);
+               gargv = 0;
+               if (v == 0)
+                       error("No match");
+               v = copyblk(v);
+       } else
+               scan(v, trim);
+       getexit(osetexit);
+       reenter = 0;
+       setexit();
+       reenter++;
+       if (reenter == 1) {
+               evalvec = v;
+               evalp = 0;
+               process(0);
+       }
+       evalvec = oevalvec;
+       evalp = oevalp;
+       doneinp = 0;
+       if (gv)
+               blkfree(gv);
+       resexit(osetexit);
+       if (reenter >= 2)
+               error(NOSTR);
+}