-/* Copyright (c) 1979 Regents of the University of California */
+static char *sccsid = "@(#)sh.func.c 4.1 10/9/80";
+
#include "sh.h"
+#include <sys/ioctl.h>
/*
* 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;
-
- 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);
return (0);
}
-func(t)
+func(t, bp)
register struct command *t;
-{
register struct biltins *bp;
+{
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;
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)
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)), "-")) {
- signal(SIGINT, SIG_IGN);
+ sigset(SIGINT, SIG_IGN);
gointr = "-";
} else {
gointr = savestr(vv);
- signal(SIGINT, pintr);
+ sigset(SIGINT, pintr);
}
}
;
}
-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()
{
{
islogin();
+ signal(SIGTERM, parterm);
execl("/bin/login", "login", v[1], 0);
+ untty();
exit(1);
}
char **v;
{
+ signal(SIGTERM, parterm);
execl("/bin/newgrp", "newgrp", v[1], 0);
execl("/usr/bin/newgrp", "newgrp", v[1], 0);
+ untty();
+ exit(1);
}
islogin()
{
+ if (chkstop == 0 && setintr)
+ panystop(0);
if (loginsh)
return;
error("Not login shell");
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");
/*
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()
* 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);
char **v;
{
+ if (chkstop == 0)
+ panystop(0);
/*
* Don't DEMAND parentheses here either.
*/
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++;
/*
preread()
{
- register int (*oldint)();
whyles->w_end = -1;
if (setintr)
- oldint = signal(SIGINT, pintr);
+ sigrelse(SIGINT);
search(ZBREAK, 0);
if (setintr)
- signal(SIGINT, oldint);
+ sighold(SIGINT);
whyles->w_end = btell();
}
struct command *kp;
{
register int i;
- register int (*saveintr)();
i = getn(v[1]);
if (setintr)
- saveintr = signal(SIGINT, SIG_IGN);
+ sighold(SIGINT);
lshift(v, 2);
while (i > 0) {
if (setintr)
- signal(SIGINT, pintr);
+ sigrelse(SIGINT);
reexecute(kp);
--i;
}
donefds();
if (setintr)
- signal(SIGINT, saveintr);
+ sigrelse(SIGINT);
}
doswbrk()
level = -1;
break;
}
- getword(0);
+ getword(NOSTR);
} while (level >= 0);
}
blkfree(wp->w_fe0);
if (wp->w_fename)
xfree(wp->w_fename);
- xfree(wp);
+ xfree((char *)wp);
whyles = nwp;
}
}
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;
bferr("No match");
} else
scan(v, trim);
+ if (sep == ' ' && !strcmp(*v, "-n"))
+ nonl++, v++;
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);
- }
if (*v)
putchar(sep | QUOTE);
}
- if (sep)
+ if (sep && nonl == 0)
putchar('\n');
+ else
+ flush();
if (setintr)
- signal(SIGINT, saveintr);
+ sighold(SIGINT);
if (gargv)
blkfree(gargv), gargv = 0;
}
-#ifndef V6
char **environ;
dosetenv(v)
char *lp = globone(v[2]);
setenv(v[1], lp);
+ if (eq(v[1], "PATH")) {
+ importpath(lp);
+ dohash();
+ }
xfree(lp);
}
+dounsetenv(v)
+ register char **v;
+{
+
+ v++;
+ do
+ unsetenv(*v++);
+ while (*v);
+}
+
setenv(name, value)
char *name, *value;
{
}
blk[0] = strspl(name, "="); blk[1] = 0;
environ = blkspl(environ, blk);
- xfree(oep);
+ xfree((char *)oep);
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;
{
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);
+}