diff options
author | obrien <obrien@FreeBSD.org> | 2000-04-18 07:31:36 +0000 |
---|---|---|
committer | obrien <obrien@FreeBSD.org> | 2000-04-18 07:31:36 +0000 |
commit | 6d573144b323d585e9999b045a7cdfb0f3f8d491 (patch) | |
tree | 6f3237f7547194d4258d65f1e1ecc234ebd3692f /bin/csh/func.c | |
parent | a0eba154d3e138792cbfc004135e7ab7310e0e6a (diff) | |
download | FreeBSD-src-6d573144b323d585e9999b045a7cdfb0f3f8d491.zip FreeBSD-src-6d573144b323d585e9999b045a7cdfb0f3f8d491.tar.gz |
Upgrade csh.
Diffstat (limited to 'bin/csh/func.c')
-rw-r--r-- | bin/csh/func.c | 1520 |
1 files changed, 0 insertions, 1520 deletions
diff --git a/bin/csh/func.c b/bin/csh/func.c deleted file mode 100644 index 2a1b802..0000000 --- a/bin/csh/func.c +++ /dev/null @@ -1,1520 +0,0 @@ -/*- - * Copyright (c) 1980, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)func.c 8.1 (Berkeley) 5/31/93"; -#else -static const char rcsid[] = - "$FreeBSD$"; -#endif -#endif /* not lint */ - -#include <sys/types.h> -#include <sys/stat.h> -#include <signal.h> -#include <locale.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#if __STDC__ -# include <stdarg.h> -#else -# include <varargs.h> -#endif - -#include "csh.h" -#include "extern.h" -#include "pathnames.h" - -extern char **environ; - -static int zlast = -1; -static void islogin __P((void)); -static void reexecute __P((struct command *)); -static void preread __P((void)); -static void doagain __P((void)); -static void search __P((int, int, Char *)); -static int getword __P((Char *)); -static int keyword __P((Char *)); -static void toend __P((void)); -static void xecho __P((int, Char **)); -static void Unsetenv __P((Char *)); - -struct biltins * -isbfunc(t) - struct command *t; -{ - Char *cp = t->t_dcom[0]; - struct biltins *bp, *bp1, *bp2; - static struct biltins label = {"", dozip, 0, 0}; - static struct biltins foregnd = {"%job", dofg1, 0, 0}; - static struct biltins backgnd = {"%job &", dobg1, 0, 0}; - - if (lastchr(cp) == ':') { - label.bname = short2str(cp); - return (&label); - } - if (*cp == '%') { - if (t->t_dflg & F_AMPERSAND) { - t->t_dflg &= ~F_AMPERSAND; - backgnd.bname = short2str(cp); - return (&backgnd); - } - foregnd.bname = short2str(cp); - return (&foregnd); - } - /* - * Binary search Bp1 is the beginning of the current search range. Bp2 is - * one past the end. - */ - for (bp1 = bfunc, bp2 = bfunc + nbfunc; bp1 < bp2;) { - int i; - - bp = bp1 + ((bp2 - bp1) >> 1); - if ((i = *cp - *bp->bname) == 0 && - (i = Strcmp(cp, str2short(bp->bname))) == 0) - return bp; - if (i < 0) - bp2 = bp; - else - bp1 = bp + 1; - } - return (0); -} - -void -func(t, bp) - struct command *t; - struct biltins *bp; -{ - int i; - - xechoit(t->t_dcom); - setname(bp->bname); - i = blklen(t->t_dcom) - 1; - if (i < bp->minargs) - stderror(ERR_NAME | ERR_TOOFEW); - if (i > bp->maxargs) - stderror(ERR_NAME | ERR_TOOMANY); - (*bp->bfunct) (t->t_dcom, t); -} - -void -/*ARGSUSED*/ -doonintr(v, t) - Char **v; - struct command *t; -{ - Char *cp; - Char *vv = v[1]; - - if (parintr == SIG_IGN) - return; - if (setintr && intty) - stderror(ERR_NAME | ERR_TERMINAL); - cp = gointr; - gointr = 0; - xfree((ptr_t) cp); - if (vv == 0) { - if (setintr) - (void) sigblock(sigmask(SIGINT)); - else - (void) signal(SIGINT, SIG_DFL); - gointr = 0; - } - else if (eq((vv = strip(vv)), STRminus)) { - (void) signal(SIGINT, SIG_IGN); - gointr = Strsave(STRminus); - } - else { - gointr = Strsave(vv); - (void) signal(SIGINT, pintr); - } -} - -void -/*ARGSUSED*/ -donohup(v, t) - Char **v; - struct command *t; -{ - if (intty) - stderror(ERR_NAME | ERR_TERMINAL); - if (setintr == 0) { - (void) signal(SIGHUP, SIG_IGN); - } -} - -void -/*ARGSUSED*/ -dozip(v, t) - Char **v; - struct command *t; -{ - ; -} - -void -prvars() -{ - plist(&shvhed); -} - -void -/*ARGSUSED*/ -doalias(v, t) - Char **v; - struct command *t; -{ - struct varent *vp; - Char *p; - - v++; - p = *v++; - if (p == 0) - plist(&aliases); - else if (*v == 0) { - vp = adrof1(strip(p), &aliases); - if (vp) { - blkpr(cshout, vp->vec); - fputc('\n', cshout); - } - } - else { - if (eq(p, STRalias) || eq(p, STRunalias)) { - setname(vis_str(p)); - stderror(ERR_NAME | ERR_DANGER); - } - set1(strip(p), saveblk(v), &aliases); - } -} - -void -/*ARGSUSED*/ -unalias(v, t) - Char **v; - struct command *t; -{ - unset1(v, &aliases); -} - -void -/*ARGSUSED*/ -dologout(v, t) - Char **v; - struct command *t; -{ - islogin(); - goodbye(); -} - -void -/*ARGSUSED*/ -dologin(v, t) - Char **v; - struct command *t; -{ - islogin(); - rechist(); - (void) signal(SIGTERM, parterm); - (void) execl(_PATH_LOGIN, "login", short2str(v[1]), NULL); - untty(); - xexit(1); -} - -static void -islogin() -{ - if (chkstop == 0 && setintr) - panystop(0); - if (loginsh) - return; - stderror(ERR_NOTLOGIN); -} - -void -doif(v, kp) - Char **v; - struct command *kp; -{ - int i; - Char **vv; - - v++; - i = expr(&v); - vv = v; - if (*vv == NULL) - stderror(ERR_NAME | ERR_EMPTYIF); - if (eq(*vv, STRthen)) { - if (*++vv) - stderror(ERR_NAME | ERR_IMPRTHEN); - setname(vis_str(STRthen)); - /* - * If expression was zero, then scan to else, otherwise just fall into - * following code. - */ - if (!i) - search(T_IF, 0, NULL); - return; - } - /* - * Simple command attached to this if. Left shift the node in this tree, - * munging it so we can reexecute it. - */ - if (i) { - lshift(kp->t_dcom, vv - kp->t_dcom); - reexecute(kp); - donefds(); - } -} - -/* - * Reexecute a command, being careful not - * to redo i/o redirection, which is already set up. - */ -static void -reexecute(kp) - struct command *kp; -{ - kp->t_dflg &= F_SAVE; - kp->t_dflg |= F_REPEAT; - /* - * 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), NULL, NULL); -} - -void -/*ARGSUSED*/ -doelse(v, t) - Char **v; - struct command *t; -{ - search(T_ELSE, 0, NULL); -} - -void -/*ARGSUSED*/ -dogoto(v, t) - Char **v; - struct command *t; -{ - Char *lp; - - gotolab(lp = globone(v[1], G_ERROR)); - xfree((ptr_t) lp); -} - -void -gotolab(lab) - Char *lab; -{ - struct whyle *wp; - /* - * While we still can, locate any unknown ends of existing loops. This - * obscure code is the WORST result of the fact that we don't really parse. - */ - zlast = T_GOTO; - for (wp = whyles; wp; wp = wp->w_next) - if (wp->w_end.type == F_SEEK && wp->w_end.f_seek == 0) { - search(T_BREAK, 0, NULL); - btell(&wp->w_end); - } - else - bseek(&wp->w_end); - search(T_GOTO, 0, lab); - /* - * Eliminate loops which were exited. - */ - wfree(); -} - -void -/*ARGSUSED*/ -doswitch(v, t) - Char **v; - struct command *t; -{ - Char *cp, *lp; - - v++; - if (!*v || *(*v++) != '(') - stderror(ERR_SYNTAX); - cp = **v == ')' ? STRNULL : *v++; - if (*(*v++) != ')') - v--; - if (*v) - stderror(ERR_SYNTAX); - search(T_SWITCH, 0, lp = globone(cp, G_ERROR)); - xfree((ptr_t) lp); -} - -void -/*ARGSUSED*/ -dobreak(v, t) - Char **v; - struct command *t; -{ - if (whyles) - toend(); - else - stderror(ERR_NAME | ERR_NOTWHILE); -} - -void -/*ARGSUSED*/ -doexit(v, t) - Char **v; - struct command *t; -{ - if (chkstop == 0 && (intty || intact) && evalvec == 0) - panystop(0); - /* - * Don't DEMAND parentheses here either. - */ - v++; - if (*v) { - set(STRstatus, putn(expr(&v))); - if (*v) - stderror(ERR_NAME | ERR_EXPRESSION); - } - btoeof(); - if (intty) - (void) close(SHIN); -} - -void -/*ARGSUSED*/ -doforeach(v, t) - Char **v; - struct command *t; -{ - Char *cp, *sp; - struct whyle *nwp; - - v++; - sp = cp = strip(*v); - if (!letter(*sp)) - stderror(ERR_NAME | ERR_VARBEGIN); - while (*cp && alnum(*cp)) - cp++; - if (*cp) - stderror(ERR_NAME | ERR_VARALNUM); - if ((cp - sp) > MAXVARLEN) - stderror(ERR_NAME | ERR_VARTOOLONG); - cp = *v++; - if (v[0][0] != '(' || v[blklen(v) - 1][0] != ')') - stderror(ERR_NAME | ERR_NOPAREN); - v++; - gflag = 0, tglob(v); - v = globall(v); - if (v == 0) - stderror(ERR_NAME | ERR_NOMATCH); - nwp = (struct whyle *) xcalloc(1, sizeof *nwp); - nwp->w_fe = nwp->w_fe0 = v; - gargv = 0; - btell(&nwp->w_start); - nwp->w_fename = Strsave(cp); - nwp->w_next = whyles; - nwp->w_end.type = F_SEEK; - whyles = nwp; - /* - * Pre-read the loop so as to be more comprehensible to a terminal user. - */ - zlast = T_FOREACH; - if (intty) - preread(); - doagain(); -} - -void -/*ARGSUSED*/ -dowhile(v, t) - Char **v; - struct command *t; -{ - int status; - bool again = whyles != 0 && SEEKEQ(&whyles->w_start, &lineloc) && - whyles->w_fename == 0; - - v++; - /* - * Implement prereading here also, taking care not to evaluate the - * expression before the loop has been read up from a terminal. - */ - if (intty && !again) - status = !exp0(&v, 1); - else - status = !expr(&v); - if (*v) - stderror(ERR_NAME | ERR_EXPRESSION); - if (!again) { - struct whyle *nwp = - (struct whyle *) xcalloc(1, sizeof(*nwp)); - - nwp->w_start = lineloc; - nwp->w_end.type = F_SEEK; - nwp->w_end.f_seek = 0; - nwp->w_next = whyles; - whyles = nwp; - zlast = T_WHILE; - if (intty) { - /* - * The tty preread - */ - preread(); - doagain(); - return; - } - } - if (status) - /* We ain't gonna loop no more, no more! */ - toend(); -} - -static void -preread() -{ - whyles->w_end.type = I_SEEK; - if (setintr) - (void) sigsetmask(sigblock(0) & ~sigmask(SIGINT)); - - search(T_BREAK, 0, NULL); /* read the expression in */ - if (setintr) - (void) sigblock(sigmask(SIGINT)); - btell(&whyles->w_end); -} - -void -/*ARGSUSED*/ -doend(v, t) - Char **v; - struct command *t; -{ - if (!whyles) - stderror(ERR_NAME | ERR_NOTWHILE); - btell(&whyles->w_end); - doagain(); -} - -void -/*ARGSUSED*/ -docontin(v, t) - Char **v; - struct command *t; -{ - if (!whyles) - stderror(ERR_NAME | ERR_NOTWHILE); - doagain(); -} - -static void -doagain() -{ - /* Repeating a while is simple */ - if (whyles->w_fename == 0) { - bseek(&whyles->w_start); - return; - } - /* - * The foreach variable list actually has a spurious word ")" at the end of - * the w_fe list. Thus we are at the of the list if one word beyond this - * is 0. - */ - if (!whyles->w_fe[1]) { - dobreak(NULL, NULL); - return; - } - set(whyles->w_fename, Strsave(*whyles->w_fe++)); - bseek(&whyles->w_start); -} - -void -dorepeat(v, kp) - Char **v; - struct command *kp; -{ - int i; - int omask = 0; - - i = getn(v[1]); - if (setintr) - omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT); - lshift(v, 2); - while (i > 0) { - if (setintr) - (void) sigsetmask(omask); - reexecute(kp); - --i; - } - donefds(); - if (setintr) - (void) sigsetmask(omask); -} - -void -/*ARGSUSED*/ -doswbrk(v, t) - Char **v; - struct command *t; -{ - search(T_BRKSW, 0, NULL); -} - -int -srchx(cp) - Char *cp; -{ - struct srch *sp, *sp1, *sp2; - int i; - - /* - * Binary search Sp1 is the beginning of the current search range. Sp2 is - * one past the end. - */ - for (sp1 = srchn, sp2 = srchn + nsrchn; sp1 < sp2;) { - sp = sp1 + ((sp2 - sp1) >> 1); - if ((i = *cp - *sp->s_name) == 0 && - (i = Strcmp(cp, str2short(sp->s_name))) == 0) - return sp->s_value; - if (i < 0) - sp2 = sp; - else - sp1 = sp + 1; - } - return (-1); -} - -static Char Stype; -static Char *Sgoal; - -/*VARARGS2*/ -static void -search(type, level, goal) - int type; - int level; - Char *goal; -{ - Char wordbuf[BUFSIZ]; - Char *aword = wordbuf; - Char *cp; - - Stype = type; - Sgoal = goal; - if (type == T_GOTO) { - struct Ain a; - a.type = F_SEEK; - a.f_seek = 0; - bseek(&a); - } - do { - if (intty && fseekp == feobp && aret == F_SEEK) - (void) fprintf(cshout, "? "), (void) fflush(cshout); - aword[0] = 0; - (void) getword(aword); - switch (srchx(aword)) { - - case T_ELSE: - if (level == 0 && type == T_IF) - return; - break; - - case T_IF: - while (getword(aword)) - continue; - if ((type == T_IF || type == T_ELSE) && - eq(aword, STRthen)) - level++; - break; - - case T_ENDIF: - if (type == T_IF || type == T_ELSE) - level--; - break; - - case T_FOREACH: - case T_WHILE: - if (type == T_BREAK) - level++; - break; - - case T_END: - if (type == T_BREAK) - level--; - break; - - case T_SWITCH: - if (type == T_SWITCH || type == T_BRKSW) - level++; - break; - - case T_ENDSW: - if (type == T_SWITCH || type == T_BRKSW) - level--; - break; - - case T_LABEL: - if (type == T_GOTO && getword(aword) && eq(aword, goal)) - level = -1; - break; - - default: - if (type != T_GOTO && (type != T_SWITCH || level != 0)) - break; - if (lastchr(aword) != ':') - break; - aword[Strlen(aword) - 1] = 0; - if ((type == T_GOTO && eq(aword, goal)) || - (type == T_SWITCH && eq(aword, STRdefault))) - level = -1; - break; - - case T_CASE: - if (type != T_SWITCH || level != 0) - break; - (void) getword(aword); - if (lastchr(aword) == ':') - aword[Strlen(aword) - 1] = 0; - cp = strip(Dfix1(aword)); - if (Gmatch(goal, cp)) - level = -1; - xfree((ptr_t) cp); - break; - - case T_DEFAULT: - if (type == T_SWITCH && level == 0) - level = -1; - break; - } - (void) getword(NULL); - } while (level >= 0); -} - -static int -getword(wp) - Char *wp; -{ - int found = 0; - int c, d; - int kwd = 0; - Char *owp = wp; - - c = readc(1); - d = 0; - do { - while (c == ' ' || c == '\t') - c = readc(1); - if (c == '#') - do - c = readc(1); - while (c >= 0 && c != '\n'); - if (c < 0) - goto past; - if (c == '\n') { - if (wp) - break; - return (0); - } - unreadc(c); - found = 1; - do { - c = readc(1); - if (c == '\\' && (c = readc(1)) == '\n') - c = ' '; - if (c == '\'' || c == '"') { - if (d == 0) - d = c; - else if (d == c) - d = 0; - } - if (c < 0) - goto past; - if (wp) { - *wp++ = c; - *wp = 0; /* end the string b4 test */ - } - } while ((d || (!(kwd = keyword(owp)) && c != ' ' - && c != '\t')) && c != '\n'); - } while (wp == 0); - - /* - * if we have read a keyword ( "if", "switch" or "while" ) then we do not - * need to unreadc the look-ahead char - */ - if (!kwd) { - unreadc(c); - if (found) - *--wp = 0; - } - - return (found); - -past: - switch (Stype) { - - case T_IF: - stderror(ERR_NAME | ERR_NOTFOUND, "then/endif"); - - case T_ELSE: - stderror(ERR_NAME | ERR_NOTFOUND, "endif"); - - case T_BRKSW: - case T_SWITCH: - stderror(ERR_NAME | ERR_NOTFOUND, "endsw"); - - case T_BREAK: - stderror(ERR_NAME | ERR_NOTFOUND, "end"); - - case T_GOTO: - setname(vis_str(Sgoal)); - stderror(ERR_NAME | ERR_NOTFOUND, "label"); - } - /* NOTREACHED */ - return (0); -} - -/* - * keyword(wp) determines if wp is one of the built-n functions if, - * switch or while. It seems that when an if statement looks like - * "if(" then getword above sucks in the '(' and so the search routine - * never finds what it is scanning for. Rather than rewrite doword, I hack - * in a test to see if the string forms a keyword. Then doword stops - * and returns the word "if" -strike - */ - -static int -keyword(wp) - Char *wp; -{ - static Char STRif[] = {'i', 'f', '\0'}; - static Char STRwhile[] = {'w', 'h', 'i', 'l', 'e', '\0'}; - static Char STRswitch[] = {'s', 'w', 'i', 't', 'c', 'h', '\0'}; - - if (!wp) - return (0); - - if ((Strcmp(wp, STRif) == 0) || (Strcmp(wp, STRwhile) == 0) - || (Strcmp(wp, STRswitch) == 0)) - return (1); - - return (0); -} - -static void -toend() -{ - if (whyles->w_end.type == F_SEEK && whyles->w_end.f_seek == 0) { - search(T_BREAK, 0, NULL); - btell(&whyles->w_end); - whyles->w_end.f_seek--; - } - else - bseek(&whyles->w_end); - wfree(); -} - -void -wfree() -{ - struct Ain o; - struct whyle *nwp; - - btell(&o); - - for (; whyles; whyles = nwp) { - struct whyle *wp = whyles; - nwp = wp->w_next; - - /* - * We free loops that have different seek types. - */ - if (wp->w_end.type != I_SEEK && wp->w_start.type == wp->w_end.type && - wp->w_start.type == o.type) { - if (wp->w_end.type == F_SEEK) { - if (o.f_seek >= wp->w_start.f_seek && - (wp->w_end.f_seek == 0 || o.f_seek < wp->w_end.f_seek)) - break; - } - else { - if (o.a_seek >= wp->w_start.a_seek && - (wp->w_end.a_seek == 0 || o.a_seek < wp->w_end.a_seek)) - break; - } - } - - if (wp->w_fe0) - blkfree(wp->w_fe0); - if (wp->w_fename) - xfree((ptr_t) wp->w_fename); - xfree((ptr_t) wp); - } -} - -void -/*ARGSUSED*/ -doecho(v, t) - Char **v; - struct command *t; -{ - xecho(' ', v); -} - -void -/*ARGSUSED*/ -doglob(v, t) - Char **v; - struct command *t; -{ - xecho(0, v); - (void) fflush(cshout); -} - -static void -xecho(sep, v) - int sep; - Char **v; -{ - Char *cp; - int nonl = 0; - - if (setintr) - (void) sigsetmask(sigblock(0) & ~sigmask(SIGINT)); - v++; - if (*v == 0) - return; - gflag = 0, tglob(v); - if (gflag) { - v = globall(v); - if (v == 0) - stderror(ERR_NAME | ERR_NOMATCH); - } - else { - v = gargv = saveblk(v); - trim(v); - } - if (sep == ' ' && *v && eq(*v, STRmn)) - nonl++, v++; - while ((cp = *v++) != NULL) { - int c; - - while ((c = *cp++) != '\0') - (void) vis_fputc(c | QUOTE, cshout); - - if (*v) - (void) vis_fputc(sep | QUOTE, cshout); - } - if (sep && nonl == 0) - (void) fputc('\n', cshout); - else - (void) fflush(cshout); - if (setintr) - (void) sigblock(sigmask(SIGINT)); - if (gargv) - blkfree(gargv), gargv = 0; -} - -void -/*ARGSUSED*/ -dosetenv(v, t) - Char **v; - struct command *t; -{ - Char *vp, *lp; - - v++; - if ((vp = *v++) == 0) { - Char **ep; - - if (setintr) - (void) sigsetmask(sigblock(0) & ~sigmask(SIGINT)); - for (ep = STR_environ; *ep; ep++) - (void) fprintf(cshout, "%s\n", vis_str(*ep)); - return; - } - if ((lp = *v++) == 0) - lp = STRNULL; - Setenv(vp, lp = globone(lp, G_APPEND)); - if (eq(vp, STRPATH)) { - importpath(lp); - dohash(NULL, NULL); - } - else if (eq(vp, STRLANG) || eq(vp, STRLC_CTYPE) || - eq(vp, STRLC_ALL) || eq(vp, STRLC_COLLATE)) { -#ifdef NLS - int k; - - (void) setlocale(LC_ALL, ""); - for (k = 0200; k <= 0377 && !Isprint(k); k++) - continue; - AsciiOnly = k > 0377; -#else - AsciiOnly = 0; -#endif /* NLS */ - } - xfree((ptr_t) lp); -} - -void -/*ARGSUSED*/ -dounsetenv(v, t) - Char **v; - struct command *t; -{ - Char **ep, *p, *n; - int i, maxi; - static Char *name = NULL; - - if (name) - xfree((ptr_t) name); - /* - * Find the longest environment variable - */ - for (maxi = 0, ep = STR_environ; *ep; ep++) { - for (i = 0, p = *ep; *p && *p != '='; p++, i++) - continue; - if (i > maxi) - maxi = i; - } - - name = (Char *) xmalloc((size_t) (maxi + 1) * sizeof(Char)); - - while (++v && *v) - for (maxi = 1; maxi;) - for (maxi = 0, ep = STR_environ; *ep; ep++) { - for (n = name, p = *ep; *p && *p != '='; *n++ = *p++) - continue; - *n = '\0'; - if (!Gmatch(name, *v)) - continue; - maxi = 1; - /* - * Delete name, and start again cause the environment changes - */ - Unsetenv(name); - if (eq(name, STRLANG) || eq(name, STRLC_CTYPE) || - eq(name, STRLC_ALL) || eq(name, STRLC_COLLATE)) { -#ifdef NLS - int k; - - (void) setlocale(LC_ALL, ""); - for (k = 0200; k <= 0377 && !Isprint(k); k++) - continue; - AsciiOnly = k > 0377; -#else - AsciiOnly = getenv("LANG") == NULL && - getenv("LC_ALL") == NULL && - getenv("LC_CTYPE") == NULL; -#endif /* NLS */ - } - break; - } - xfree((ptr_t) name); - name = NULL; -} - -void -Setenv(name, val) - Char *name, *val; -{ - Char **ep = STR_environ; - Char *cp, *dp; - Char *blk[2]; - Char **oep = ep; - - - for (; *ep; ep++) { - for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++) - continue; - if (*cp != 0 || *dp != '=') - continue; - cp = Strspl(STRequal, val); - xfree((ptr_t) * ep); - *ep = strip(Strspl(name, cp)); - xfree((ptr_t) cp); - blkfree((Char **) environ); - environ = short2blk(STR_environ); - return; - } - cp = Strspl(name, STRequal); - blk[0] = strip(Strspl(cp, val)); - xfree((ptr_t) cp); - blk[1] = 0; - STR_environ = blkspl(STR_environ, blk); - blkfree((Char **) environ); - environ = short2blk(STR_environ); - xfree((ptr_t) oep); -} - -static void -Unsetenv(name) - Char *name; -{ - Char **ep = STR_environ; - 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; - STR_environ = blkspl(STR_environ, ep + 1); - environ = short2blk(STR_environ); - *ep = cp; - xfree((ptr_t) cp); - xfree((ptr_t) oep); - return; - } -} - -void -/*ARGSUSED*/ -doumask(v, t) - Char **v; - struct command *t; -{ - Char *cp = v[1]; - int i; - - if (cp == 0) { - i = umask(0); - (void) umask(i); - (void) fprintf(cshout, "%o\n", i); - return; - } - i = 0; - while (Isdigit(*cp) && *cp != '8' && *cp != '9') - i = i * 8 + *cp++ - '0'; - if (*cp || i < 0 || i > 0777) - stderror(ERR_NAME | ERR_MASK); - (void) umask(i); -} - -typedef quad_t RLIM_TYPE; - -static struct limits { - int limconst; - char *limname; - int limdiv; - char *limscale; -} limits[] = { - { RLIMIT_CPU, "cputime", 1, "seconds" }, - { RLIMIT_FSIZE, "filesize", 1024, "kbytes" }, - { RLIMIT_DATA, "datasize", 1024, "kbytes" }, - { RLIMIT_STACK, "stacksize", 1024, "kbytes" }, - { RLIMIT_CORE, "coredumpsize", 1024, "kbytes" }, - { RLIMIT_RSS, "memoryuse", 1024, "kbytes" }, - { RLIMIT_MEMLOCK, "memorylocked", 1024, "kbytes" }, - { RLIMIT_NPROC, "maxproc", 1, "" }, - { RLIMIT_NOFILE, "openfiles", 1, "" }, - { RLIMIT_SBSIZE, "sbsize ", 1, "bytes" }, - { -1, NULL, 0, NULL } -}; - -static struct limits *findlim(); -static RLIM_TYPE getval(); -static void limtail(); -static void plim(); -static int setlim(); - -static struct limits * -findlim(cp) - Char *cp; -{ - struct limits *lp, *res; - - res = (struct limits *) NULL; - for (lp = limits; lp->limconst >= 0; lp++) - if (prefix(cp, str2short(lp->limname))) { - if (res) - stderror(ERR_NAME | ERR_AMBIG); - res = lp; - } - if (res) - return (res); - stderror(ERR_NAME | ERR_LIMIT); - /* NOTREACHED */ - return (0); -} - -void -/*ARGSUSED*/ -dolimit(v, t) - Char **v; - struct command *t; -{ - struct limits *lp; - RLIM_TYPE limit; - char hard = 0; - - v++; - if (*v && eq(*v, STRmh)) { - hard = 1; - v++; - } - if (*v == 0) { - for (lp = limits; lp->limconst >= 0; lp++) - plim(lp, hard); - return; - } - lp = findlim(v[0]); - if (v[1] == 0) { - plim(lp, hard); - return; - } - limit = getval(lp, v + 1); - if (setlim(lp, hard, limit) < 0) - stderror(ERR_SILENT); -} - -static RLIM_TYPE -getval(lp, v) - struct limits *lp; - Char **v; -{ - float f; - Char *cp = *v++; - - f = atof(short2str(cp)); - - while (Isdigit(*cp) || *cp == '.' || *cp == 'e' || *cp == 'E') - cp++; - if (*cp == 0) { - if (*v == 0) - return ((RLIM_TYPE) ((f + 0.5) * lp->limdiv)); - cp = *v; - } - switch (*cp) { - case ':': - if (lp->limconst != RLIMIT_CPU) - goto badscal; - return ((RLIM_TYPE) (f * 60.0 + atof(short2str(cp + 1)))); - case 'h': - if (lp->limconst != RLIMIT_CPU) - goto badscal; - limtail(cp, "hours"); - f *= 3600.0; - break; - case 'm': - if (lp->limconst == RLIMIT_CPU) { - limtail(cp, "minutes"); - f *= 60.0; - break; - } - *cp = 'm'; - limtail(cp, "megabytes"); - f *= 1024.0 * 1024.0; - break; - case 's': - if (lp->limconst != RLIMIT_CPU) - goto badscal; - limtail(cp, "seconds"); - break; - case 'M': - if (lp->limconst == RLIMIT_CPU) - goto badscal; - *cp = 'm'; - limtail(cp, "megabytes"); - f *= 1024.0 * 1024.0; - break; - case 'k': - if (lp->limconst == RLIMIT_CPU) - goto badscal; - limtail(cp, "kbytes"); - f *= 1024.0; - break; - case 'u': - limtail(cp, "unlimited"); - return (RLIM_INFINITY); - default: -badscal: - stderror(ERR_NAME | ERR_SCALEF); - } - f += 0.5; - if (f > (float) RLIM_INFINITY) - return RLIM_INFINITY; - else - return ((RLIM_TYPE) f); -} - -static void -limtail(cp, str) - Char *cp; - char *str; -{ - while (*cp && *cp == *str) - cp++, str++; - if (*cp) - stderror(ERR_BADSCALE, str); -} - - -/*ARGSUSED*/ -static void -plim(lp, hard) - struct limits *lp; - Char hard; -{ - struct rlimit rlim; - RLIM_TYPE limit; - - (void) fprintf(cshout, "%s \t", lp->limname); - - (void) getrlimit(lp->limconst, &rlim); - limit = hard ? rlim.rlim_max : rlim.rlim_cur; - - if (limit == RLIM_INFINITY) - (void) fprintf(cshout, "unlimited"); - else if (lp->limconst == RLIMIT_CPU) - psecs((long) limit); - else - (void) fprintf(cshout, "%ld %s", (long) (limit / lp->limdiv), - lp->limscale); - (void) fputc('\n', cshout); -} - -void -/*ARGSUSED*/ -dounlimit(v, t) - Char **v; - struct command *t; -{ - struct limits *lp; - int lerr = 0; - Char hard = 0; - - v++; - if (*v && eq(*v, STRmh)) { - hard = 1; - v++; - } - if (*v == 0) { - for (lp = limits; lp->limconst >= 0; lp++) - if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0) - lerr++; - if (lerr) - stderror(ERR_SILENT); - return; - } - while (*v) { - lp = findlim(*v++); - if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0) - stderror(ERR_SILENT); - } -} - -static int -setlim(lp, hard, limit) - struct limits *lp; - Char hard; - RLIM_TYPE limit; -{ - struct rlimit rlim; - - (void) getrlimit(lp->limconst, &rlim); - - if (hard) - rlim.rlim_max = limit; - else if (limit == RLIM_INFINITY && geteuid() != 0) - rlim.rlim_cur = rlim.rlim_max; - else - rlim.rlim_cur = limit; - - if (setrlimit(lp->limconst, &rlim) < 0) { - (void) fprintf(csherr, "%s: %s: Can't %s%s limit\n", bname, lp->limname, - limit == RLIM_INFINITY ? "remove" : "set", - hard ? " hard" : ""); - return (-1); - } - return (0); -} - -void -/*ARGSUSED*/ -dosuspend(v, t) - Char **v; - struct command *t; -{ - int ctpgrp; - - void (*old) __P((int)); - - if (loginsh) - stderror(ERR_SUSPLOG); - untty(); - - old = signal(SIGTSTP, SIG_DFL); - (void) kill(0, SIGTSTP); - /* the shell stops here */ - (void) signal(SIGTSTP, old); - - if (tpgrp != -1) { - ctpgrp = tcgetpgrp(FSHTTY); - while (ctpgrp != opgrp) { - old = signal(SIGTTIN, SIG_DFL); - (void) kill(0, SIGTTIN); - (void) signal(SIGTTIN, old); - } - (void) setpgid(0, shpgrp); - (void) tcsetpgrp(FSHTTY, shpgrp); - } -} - -/* This is the dreaded EVAL built-in. - * If you don't fiddle with file descriptors, and reset didfds, - * this command will either ignore redirection inside or outside - * its arguments, e.g. eval "date >x" vs. eval "date" >x - * The stuff here seems to work, but I did it by trial and error rather - * than really knowing what was going on. If tpgrp is zero, we are - * probably a background eval, e.g. "eval date &", and we want to - * make sure that any processes we start stay in our pgrp. - * This is also the case for "time eval date" -- stay in same pgrp. - * Otherwise, under stty tostop, processes will stop in the wrong - * pgrp, with no way for the shell to get them going again. -IAN! - */ -static Char **gv = NULL; -void -/*ARGSUSED*/ -doeval(v, t) - Char **v; - struct command *t; -{ - Char **oevalvec; - Char *oevalp; - int odidfds; - jmp_buf osetexit; - int my_reenter; - Char **savegv = gv; - int saveIN; - int saveOUT; - int saveERR; - int oSHIN; - int oSHOUT; - int oSHERR; - - UNREGISTER(v); - - oevalvec = evalvec; - oevalp = evalp; - odidfds = didfds; - oSHIN = SHIN; - oSHOUT = SHOUT; - oSHERR = SHERR; - - v++; - if (*v == 0) - return; - gflag = 0, tglob(v); - if (gflag) { - gv = v = globall(v); - gargv = 0; - if (v == 0) - stderror(ERR_NOMATCH); - v = copyblk(v); - } - else { - gv = NULL; - v = copyblk(v); - trim(v); - } - - saveIN = dcopy(SHIN, -1); - saveOUT = dcopy(SHOUT, -1); - saveERR = dcopy(SHERR, -1); - - getexit(osetexit); - - if ((my_reenter = setexit()) == 0) { - evalvec = v; - evalp = 0; - SHIN = dcopy(0, -1); - SHOUT = dcopy(1, -1); - SHERR = dcopy(2, -1); - didfds = 0; - process(0); - } - - evalvec = oevalvec; - evalp = oevalp; - doneinp = 0; - didfds = odidfds; - (void) close(SHIN); - (void) close(SHOUT); - (void) close(SHERR); - SHIN = dmove(saveIN, oSHIN); - SHOUT = dmove(saveOUT, oSHOUT); - SHERR = dmove(saveERR, oSHERR); - if (gv) - blkfree(gv), gv = NULL; - resexit(osetexit); - gv = savegv; - if (my_reenter) - stderror(ERR_SILENT); -} - -void -/*ARGSUSED*/ -doprintf(v, t) - Char **v; - struct command *t; -{ - Char **newv; - char **c; - extern int progprintf __P((int, char **)); - int ret; - - gflag = 0; - tglob(v); - if (gflag) { - newv = globall(v); - if (newv == 0) { - stderror(ERR_NAME | ERR_NOMATCH); - return; - } - v = newv; - gargv=0; - } - - ret = progprintf(blklen(v), c = short2blk(v)); - (void) fflush(cshout); - (void) fflush(csherr); - - blkfree((Char **) c); - if (ret) - stderror(ERR_SILENT); -} |