diff options
Diffstat (limited to 'contrib/tcsh/sh.func.c')
-rw-r--r-- | contrib/tcsh/sh.func.c | 2457 |
1 files changed, 0 insertions, 2457 deletions
diff --git a/contrib/tcsh/sh.func.c b/contrib/tcsh/sh.func.c deleted file mode 100644 index 92e2447..0000000 --- a/contrib/tcsh/sh.func.c +++ /dev/null @@ -1,2457 +0,0 @@ -/* $Header: /p/tcsh/cvsroot/tcsh/sh.func.c,v 3.143 2006/08/24 20:56:31 christos Exp $ */ -/* - * sh.func.c: csh builtin functions - */ -/*- - * Copyright (c) 1980, 1991 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. 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. - */ -#include "sh.h" - -RCSID("$tcsh: sh.func.c,v 3.143 2006/08/24 20:56:31 christos Exp $") - -#include "ed.h" -#include "tw.h" -#include "tc.h" -#ifdef WINNT_NATIVE -#include "nt.const.h" -#endif /* WINNT_NATIVE */ - -#if defined (NLS_CATALOGS) && defined(HAVE_ICONV) && defined(HAVE_NL_LANGINFO) -#include <langinfo.h> -static iconv_t catgets_iconv; /* Or (iconv_t)-1 */ -#endif - -/* - * C shell - */ - -extern int MapsAreInited; -extern int NLSMapsAreInited; -extern int GotTermCaps; - -static int zlast = -1; - -static void islogin (void); -static void preread (void); -static void doagain (void); -static const char *isrchx (int); -static void search (int, int, Char *); -static int getword (struct Strbuf *); -static void toend (void); -static void xecho (int, Char **); -static int islocale_var (Char *); -static void wpfree (struct whyle *); - -const struct biltins * -isbfunc(struct command *t) -{ - Char *cp = t->t_dcom[0]; - const 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}; - - /* - * We never match a builtin that has quoted the first - * character; this has been the traditional way to escape - * builtin commands. - */ - if (*cp & QUOTE) - return NULL; - - if (*cp != ':' && 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); - } -#ifdef WARP - /* - * This is a perhaps kludgy way to determine if the warp builtin is to be - * acknowledged or not. If checkwarp() fails, then we are to assume that - * the warp command is invalid, and carry on as we would handle any other - * non-builtin command. -- JDK 2/4/88 - */ - if (eq(STRwarp, cp) && !checkwarp()) { - return (0); /* this builtin disabled */ - } -#endif /* WARP */ - /* - * 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 = ((char) *cp) - *bp->bname) == 0 && - (i = StrQcmp(cp, str2short(bp->bname))) == 0) - return bp; - if (i < 0) - bp2 = bp; - else - bp1 = bp + 1; - } -#ifdef WINNT_NATIVE - return nt_check_additional_builtins(cp); -#endif /*WINNT_NATIVE*/ - return (0); -} - -void -func(struct command *t, const 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); -} - -/*ARGSUSED*/ -void -doonintr(Char **v, struct command *c) -{ - Char *cp; - Char *vv = v[1]; - - USE(c); - if (parintr.sa_handler == SIG_IGN) - return; - if (setintr && intty) - stderror(ERR_NAME | ERR_TERMINAL); - cp = gointr; - gointr = 0; - xfree(cp); - if (vv == 0) { - if (setintr) - sigset_interrupting(SIGINT, queue_pintr); - 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); - sigset_interrupting(SIGINT, queue_pintr); - } -} - -/*ARGSUSED*/ -void -donohup(Char **v, struct command *c) -{ - USE(c); - USE(v); - if (intty) - stderror(ERR_NAME | ERR_TERMINAL); - if (setintr == 0) { - (void) signal(SIGHUP, SIG_IGN); - phup_disabled = 1; -#ifdef CC - submit(getpid()); -#endif /* CC */ - } -} - -/*ARGSUSED*/ -void -dohup(Char **v, struct command *c) -{ - USE(c); - USE(v); - if (intty) - stderror(ERR_NAME | ERR_TERMINAL); - if (setintr == 0) - (void) signal(SIGHUP, SIG_DFL); -} - - -/*ARGSUSED*/ -void -dozip(Char **v, struct command *c) -{ - USE(c); - USE(v); -} - -/*ARGSUSED*/ -void -dofiletest(Char **v, struct command *c) -{ - Char **globbed, **fileptr, *ftest, *res; - - USE(c); - if (*(ftest = *++v) != '-') - stderror(ERR_NAME | ERR_FILEINQ); - ++v; - - v = glob_all_or_error(v); - globbed = v; - cleanup_push(globbed, blk_cleanup); - - while (*(fileptr = v++) != '\0') { - res = filetest(ftest, &fileptr, 0); - cleanup_push(res, xfree); - xprintf("%S", res); - cleanup_until(res); - if (*v) - xprintf(" "); - } - xprintf("\n"); - - cleanup_until(globbed); -} - -void -prvars(void) -{ - plist(&shvhed, VAR_ALL); -} - -/*ARGSUSED*/ -void -doalias(Char **v, struct command *c) -{ - struct varent *vp; - Char *p; - - USE(c); - v++; - p = *v++; - if (p == 0) - plist(&aliases, VAR_ALL); - else if (*v == 0) { - vp = adrof1(strip(p), &aliases); - if (vp && vp->vec) - blkpr(vp->vec), xputchar('\n'); - } - else { - if (eq(p, STRalias) || eq(p, STRunalias)) { - setname(short2str(p)); - stderror(ERR_NAME | ERR_DANGER); - } - set1(strip(p), saveblk(v), &aliases, VAR_READWRITE); - tw_cmd_free(); - } -} - -/*ARGSUSED*/ -void -unalias(Char **v, struct command *c) -{ - USE(c); - unset1(v, &aliases); - tw_cmd_free(); -} - -/*ARGSUSED*/ -void -dologout(Char **v, struct command *c) -{ - USE(c); - USE(v); - islogin(); - goodbye(NULL, NULL); -} - -/*ARGSUSED*/ -void -dologin(Char **v, struct command *c) -{ -#ifdef WINNT_NATIVE - USE(c); - USE(v); -#else /* !WINNT_NATIVE */ - char **p = short2blk(v); - - USE(c); - cleanup_push((Char **)p, blk_cleanup); - islogin(); - rechist(NULL, adrof(STRsavehist) != NULL); - sigaction(SIGTERM, &parterm, NULL); - (void) execv(_PATH_BIN_LOGIN, p); - (void) execv(_PATH_USRBIN_LOGIN, p); - cleanup_until((Char **)p); - untty(); - xexit(1); -#endif /* !WINNT_NATIVE */ -} - - -#ifdef NEWGRP -/*ARGSUSED*/ -void -donewgrp(Char **v, struct command *c) -{ - char **p; - if (chkstop == 0 && setintr) - panystop(0); - sigaction(SIGTERM, &parterm, NULL); - p = short2blk(v); - /* - * From Beto Appleton (beto@aixwiz.austin.ibm.com) - * Newgrp can take 2 arguments... - */ - (void) execv(_PATH_BIN_NEWGRP, p); - (void) execv(_PATH_USRBIN_NEWGRP, p); - blkfree((Char **) p); - untty(); - xexit(1); -} -#endif /* NEWGRP */ - -static void -islogin(void) -{ - if (chkstop == 0 && setintr) - panystop(0); - if (loginsh) - return; - stderror(ERR_NOTLOGIN); -} - -void -doif(Char **v, struct command *kp) -{ - int i; - Char **vv; - - v++; - i = noexec ? 1 : expr(&v); - vv = v; - if (*vv == NULL) - stderror(ERR_NAME | ERR_EMPTYIF); - if (eq(*vv, STRthen)) { - if (*++vv) - stderror(ERR_NAME | ERR_IMPRTHEN); - setname(short2str(STRthen)); - /* - * If expression was zero, then scan to else , otherwise just fall into - * following code. - */ - if (!i) - search(TC_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. - */ -void -reexecute(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, TRUE); -} - -/*ARGSUSED*/ -void -doelse (Char **v, struct command *c) -{ - USE(c); - USE(v); - if (!noexec) - search(TC_ELSE, 0, NULL); -} - -/*ARGSUSED*/ -void -dogoto(Char **v, struct command *c) -{ - Char *lp; - - USE(c); - lp = globone(v[1], G_ERROR); - cleanup_push(lp, xfree); - if (!noexec) - gotolab(lp); - cleanup_until(lp); -} - -void -gotolab(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 = TC_GOTO; - for (wp = whyles; wp; wp = wp->w_next) - if (wp->w_end.type == TCSH_F_SEEK && wp->w_end.f_seek == 0) { - search(TC_BREAK, 0, NULL); - btell(&wp->w_end); - } - else { - bseek(&wp->w_end); - } - search(TC_GOTO, 0, lab); - /* - * Eliminate loops which were exited. - */ - wfree(); -} - -/*ARGSUSED*/ -void -doswitch(Char **v, struct command *c) -{ - Char *cp, *lp; - - USE(c); - v++; - if (!*v || *(*v++) != '(') - stderror(ERR_SYNTAX); - cp = **v == ')' ? STRNULL : *v++; - if (*(*v++) != ')') - v--; - if (*v) - stderror(ERR_SYNTAX); - lp = globone(cp, G_ERROR); - cleanup_push(lp, xfree); - if (!noexec) - search(TC_SWITCH, 0, lp); - cleanup_until(lp); -} - -/*ARGSUSED*/ -void -dobreak(Char **v, struct command *c) -{ - USE(v); - USE(c); - if (whyles == NULL) - stderror(ERR_NAME | ERR_NOTWHILE); - if (!noexec) - toend(); -} - -/*ARGSUSED*/ -void -doexit(Char **v, struct command *c) -{ - USE(c); - - if (chkstop == 0 && (intty || intact) && evalvec == 0) - panystop(0); - /* - * Don't DEMAND parentheses here either. - */ - v++; - if (*v) { - setv(STRstatus, putn(expr(&v)), VAR_READWRITE); - if (*v) - stderror(ERR_NAME | ERR_EXPRESSION); - } - btoeof(); -#if 0 - if (intty) -#endif - /* Always close, why only on ttys? */ - xclose(SHIN); -} - -/*ARGSUSED*/ -void -doforeach(Char **v, struct command *c) -{ - Char *cp, *sp; - struct whyle *nwp; - int gflag; - - USE(c); - 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); - cp = *v++; - if (v[0][0] != '(' || v[blklen(v) - 1][0] != ')') - stderror(ERR_NAME | ERR_NOPAREN); - v++; - gflag = tglob(v); - if (gflag) { - v = globall(v, gflag); - if (v == 0 && !noexec) - stderror(ERR_NAME | ERR_NOMATCH); - } - else { - v = saveblk(v); - trim(v); - } - nwp = xcalloc(1, sizeof *nwp); - nwp->w_fe = nwp->w_fe0 = v; - btell(&nwp->w_start); - nwp->w_fename = Strsave(cp); - nwp->w_next = whyles; - nwp->w_end.type = TCSH_F_SEEK; - whyles = nwp; - /* - * Pre-read the loop so as to be more comprehensible to a terminal user. - */ - zlast = TC_FOREACH; - if (intty) - preread(); - if (!noexec) - doagain(); -} - -/*ARGSUSED*/ -void -dowhile(Char **v, struct command *c) -{ - int status; - int again = whyles != 0 && - SEEKEQ(&whyles->w_start, &lineloc) && - whyles->w_fename == 0; - - USE(c); - v++; - /* - * Implement prereading here also, taking care not to evaluate the - * expression before the loop has been read up from a terminal. - */ - if (noexec) - status = 0; - else if (intty && !again) - status = !exp0(&v, 1); - else - status = !expr(&v); - if (*v && !noexec) - stderror(ERR_NAME | ERR_EXPRESSION); - if (!again) { - struct whyle *nwp = xcalloc(1, sizeof(*nwp)); - - nwp->w_start = lineloc; - nwp->w_end.type = TCSH_F_SEEK; - nwp->w_end.f_seek = 0; - nwp->w_next = whyles; - whyles = nwp; - zlast = TC_WHILE; - if (intty) { - /* - * The tty preread - */ - preread(); - doagain(); - return; - } - } - if (status) - /* We ain't gonna loop no more, no more! */ - toend(); -} - -static void -preread(void) -{ - int old_pintr_disabled; - - whyles->w_end.type = TCSH_I_SEEK; - if (setintr) - pintr_push_enable(&old_pintr_disabled); - search(TC_BREAK, 0, NULL); /* read the expression in */ - if (setintr) - cleanup_until(&old_pintr_disabled); - btell(&whyles->w_end); -} - -/*ARGSUSED*/ -void -doend(Char **v, struct command *c) -{ - USE(v); - USE(c); - if (!whyles) - stderror(ERR_NAME | ERR_NOTWHILE); - btell(&whyles->w_end); - if (!noexec) - doagain(); -} - -/*ARGSUSED*/ -void -docontin(Char **v, struct command *c) -{ - USE(v); - USE(c); - if (!whyles) - stderror(ERR_NAME | ERR_NOTWHILE); - if (!noexec) - doagain(); -} - -static void -doagain(void) -{ - /* 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; - } - setv(whyles->w_fename, quote(Strsave(*whyles->w_fe++)), VAR_READWRITE); - bseek(&whyles->w_start); -} - -void -dorepeat(Char **v, struct command *kp) -{ - int i = 1; - - do { - i *= getn(v[1]); - lshift(v, 2); - } while (v[0] != NULL && Strcmp(v[0], STRrepeat) == 0); - if (noexec) - i = 1; - - if (setintr) { - pintr_disabled++; - cleanup_push(&pintr_disabled, disabled_cleanup); - } - while (i > 0) { - if (setintr && pintr_disabled == 1) { - cleanup_until(&pintr_disabled); - pintr_disabled++; - cleanup_push(&pintr_disabled, disabled_cleanup); - } - reexecute(kp); - --i; - } - cleanup_until(&pintr_disabled); - donefds(); -} - -/*ARGSUSED*/ -void -doswbrk(Char **v, struct command *c) -{ - USE(v); - USE(c); - if (!noexec) - search(TC_BRKSW, 0, NULL); -} - -int -srchx(Char *cp) -{ - struct srch *sp, *sp1, *sp2; - int i; - - /* - * Ignore keywords inside heredocs - */ - if (inheredoc) - return -1; - - /* - * 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 const char * -isrchx(int n) -{ - struct srch *sp, *sp2; - - for (sp = srchn, sp2 = srchn + nsrchn; sp < sp2; sp++) - if (sp->s_value == n) - return (sp->s_name); - return (""); -} - - -static int Stype; -static Char *Sgoal; - -static void -search(int type, int level, Char *goal) -{ - struct Strbuf word = Strbuf_INIT; - Char *cp; - struct whyle *wp; - int wlevel = 0; - - Stype = type; - Sgoal = goal; - if (type == TC_GOTO) { - struct Ain a; - a.type = TCSH_F_SEEK; - a.f_seek = 0; - bseek(&a); - } - cleanup_push(&word, Strbuf_cleanup); - do { - if (intty && fseekp == feobp && aret == TCSH_F_SEEK) - printprompt(1, isrchx(type == TC_BREAK ? zlast : type)); - /* xprintf("? "), flush(); */ - (void) getword(&word); - Strbuf_terminate(&word); - switch (srchx(word.s)) { - - case TC_ELSE: - if (level == 0 && type == TC_IF) - goto end; - break; - - case TC_IF: - while (getword(&word)) - continue; - if ((type == TC_IF || type == TC_ELSE) && - eq(word.s, STRthen)) - level++; - break; - - case TC_ENDIF: - if (type == TC_IF || type == TC_ELSE) - level--; - break; - - case TC_FOREACH: - case TC_WHILE: - wlevel++; - if (type == TC_BREAK) - level++; - break; - - case TC_END: - if (type == TC_BRKSW) { - if (wlevel == 0) { - wp = whyles; - if (wp) { - whyles = wp->w_next; - wpfree(wp); - } - } - } - if (type == TC_BREAK) - level--; - wlevel--; - break; - - case TC_SWITCH: - if (type == TC_SWITCH || type == TC_BRKSW) - level++; - break; - - case TC_ENDSW: - if (type == TC_SWITCH || type == TC_BRKSW) - level--; - break; - - case TC_LABEL: - if (type == TC_GOTO && getword(&word) && eq(word.s, goal)) - level = -1; - break; - - default: - if (type != TC_GOTO && (type != TC_SWITCH || level != 0)) - break; - if (word.len == 0 || word.s[word.len - 1] != ':') - break; - word.s[--word.len] = 0; - if ((type == TC_GOTO && eq(word.s, goal)) || - (type == TC_SWITCH && eq(word.s, STRdefault))) - level = -1; - break; - - case TC_CASE: - if (type != TC_SWITCH || level != 0) - break; - (void) getword(&word); - if (word.len != 0 && word.s[word.len - 1] == ':') - word.s[--word.len] = 0; - cp = strip(Dfix1(word.s)); - cleanup_push(cp, xfree); - if (Gmatch(goal, cp)) - level = -1; - cleanup_until(cp); - break; - - case TC_DEFAULT: - if (type == TC_SWITCH && level == 0) - level = -1; - break; - } - (void) getword(NULL); - } while (level >= 0); - end: - cleanup_until(&word); -} - -static int -getword(struct Strbuf *wp) -{ - int found = 0, first; - eChar c, d; - - if (wp) - wp->len = 0; - c = readc(1); - d = 0; - do { - while (c == ' ' || c == '\t') - c = readc(1); - if (c == '#') - do - c = readc(1); - while (c != CHAR_ERR && c != '\n'); - if (c == CHAR_ERR) - goto past; - if (c == '\n') { - if (wp) - break; - return (0); - } - unreadc(c); - found = 1; - first = 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 == CHAR_ERR) - goto past; - if (wp) - Strbuf_append1(wp, (Char) c); - if (!first && !d && c == '(') { - if (wp) - goto past_word_end; - else - break; - } - first = 0; - } while ((d || (c != ' ' && c != '\t')) && c != '\n'); - } while (wp == 0); - - past_word_end: - unreadc(c); - if (found) { - wp->len--; - Strbuf_terminate(wp); - } - - return (found); - -past: - switch (Stype) { - - case TC_IF: - stderror(ERR_NAME | ERR_NOTFOUND, "then/endif"); - break; - - case TC_ELSE: - stderror(ERR_NAME | ERR_NOTFOUND, "endif"); - break; - - case TC_BRKSW: - case TC_SWITCH: - stderror(ERR_NAME | ERR_NOTFOUND, "endsw"); - break; - - case TC_BREAK: - stderror(ERR_NAME | ERR_NOTFOUND, "end"); - break; - - case TC_GOTO: - setname(short2str(Sgoal)); - stderror(ERR_NAME | ERR_NOTFOUND, "label"); - break; - - default: - break; - } - /* NOTREACHED */ - return (0); -} - -static void -toend(void) -{ - if (whyles->w_end.type == TCSH_F_SEEK && whyles->w_end.f_seek == 0) { - search(TC_BREAK, 0, NULL); - btell(&whyles->w_end); - whyles->w_end.f_seek--; - } - else { - bseek(&whyles->w_end); - } - wfree(); -} - -static void -wpfree(struct whyle *wp) -{ - if (wp->w_fe0) - blkfree(wp->w_fe0); - xfree(wp->w_fename); - xfree(wp); -} - -void -wfree(void) -{ - struct Ain o; - struct whyle *nwp; -#ifdef lint - nwp = NULL; /* sun lint is dumb! */ -#endif - -#ifdef FDEBUG - static const char foo[] = "IAFE"; -#endif /* FDEBUG */ - - btell(&o); - -#ifdef FDEBUG - xprintf("o->type %c o->a_seek %d o->f_seek %d\n", - foo[o.type + 1], o.a_seek, o.f_seek); -#endif /* FDEBUG */ - - for (; whyles; whyles = nwp) { - struct whyle *wp = whyles; - nwp = wp->w_next; - -#ifdef FDEBUG - xprintf("start->type %c start->a_seek %d start->f_seek %d\n", - foo[wp->w_start.type+1], - wp->w_start.a_seek, wp->w_start.f_seek); - xprintf("end->type %c end->a_seek %d end->f_seek %d\n", - foo[wp->w_end.type + 1], wp->w_end.a_seek, wp->w_end.f_seek); -#endif /* FDEBUG */ - - /* - * XXX: We free loops that have different seek types. - */ - if (wp->w_end.type != TCSH_I_SEEK && wp->w_start.type == wp->w_end.type && - wp->w_start.type == o.type) { - if (wp->w_end.type == TCSH_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; - } - } - - wpfree(wp); - } -} - -/*ARGSUSED*/ -void -doecho(Char **v, struct command *c) -{ - USE(c); - xecho(' ', v); -} - -/*ARGSUSED*/ -void -doglob(Char **v, struct command *c) -{ - USE(c); - xecho(0, v); - flush(); -} - -static void -xecho(int sep, Char **v) -{ - Char *cp, **globbed = NULL; - int nonl = 0; - int echo_style = ECHO_STYLE; - struct varent *vp; - - if ((vp = adrof(STRecho_style)) != NULL && vp->vec != NULL && - vp->vec[0] != NULL) { - if (Strcmp(vp->vec[0], STRbsd) == 0) - echo_style = BSD_ECHO; - else if (Strcmp(vp->vec[0], STRsysv) == 0) - echo_style = SYSV_ECHO; - else if (Strcmp(vp->vec[0], STRboth) == 0) - echo_style = BOTH_ECHO; - else if (Strcmp(vp->vec[0], STRnone) == 0) - echo_style = NONE_ECHO; - } - - v++; - if (*v == 0) - goto done; - if (setintr) { - int old_pintr_disabled; - pintr_push_enable(&old_pintr_disabled); - v = glob_all_or_error(v); - cleanup_until(&old_pintr_disabled); - } else { - v = glob_all_or_error(v); - } - globbed = v; - if (globbed != NULL) - cleanup_push(globbed, blk_cleanup); - - if ((echo_style & BSD_ECHO) != 0 && sep == ' ' && *v && eq(*v, STRmn)) - nonl++, v++; - - while ((cp = *v++) != 0) { - Char c; - - if (setintr) { - int old_pintr_disabled; - - pintr_push_enable(&old_pintr_disabled); - cleanup_until(&old_pintr_disabled); - } - while ((c = *cp++) != 0) { - if ((echo_style & SYSV_ECHO) != 0 && c == '\\') { - switch (c = *cp++) { - case 'a': - c = '\a'; - break; - case 'b': - c = '\b'; - break; - case 'c': - nonl = 1; - goto done; - case 'e': -#if 0 /* Windows does not understand \e */ - c = '\e'; -#else - c = CTL_ESC('\033'); -#endif - break; - case 'f': - c = '\f'; - break; - case 'n': - c = '\n'; - break; - case 'r': - c = '\r'; - break; - case 't': - c = '\t'; - break; - case 'v': - c = '\v'; - break; - case '\\': - c = '\\'; - break; - case '0': - c = 0; - if (*cp >= '0' && *cp < '8') - c = c * 8 + *cp++ - '0'; - if (*cp >= '0' && *cp < '8') - c = c * 8 + *cp++ - '0'; - if (*cp >= '0' && *cp < '8') - c = c * 8 + *cp++ - '0'; - break; - case '\0': - c = '\\'; - cp--; - break; - default: - xputchar('\\' | QUOTE); - break; - } - } - xputwchar(c | QUOTE); - - } - if (*v) - xputchar(sep | QUOTE); - } -done: - if (sep && nonl == 0) - xputchar('\n'); - else - flush(); - if (globbed != NULL) - cleanup_until(globbed); -} - -/* check whether an environment variable should invoke 'set_locale()' */ -static int -islocale_var(Char *var) -{ - static Char *locale_vars[] = { - STRLANG, STRLC_ALL, STRLC_CTYPE, STRLC_NUMERIC, - STRLC_TIME, STRLC_COLLATE, STRLC_MESSAGES, STRLC_MONETARY, 0 - }; - Char **v; - - for (v = locale_vars; *v; ++v) - if (eq(var, *v)) - return 1; - return 0; -} - -static void -xlate_cr_cleanup(void *dummy) -{ - USE(dummy); - xlate_cr = 0; -} - -/*ARGSUSED*/ -void -doprintenv(Char **v, struct command *c) -{ - Char *e; - - USE(c); - v++; - if (*v == 0) { - Char **ep; - - xlate_cr = 1; - cleanup_push(&xlate_cr, xlate_cr_cleanup); - for (ep = STR_environ; *ep; ep++) { - if (setintr) { - int old_pintr_disabled; - - pintr_push_enable(&old_pintr_disabled); - cleanup_until(&old_pintr_disabled); - } - xprintf("%S\n", *ep); - } - cleanup_until(&xlate_cr); - } - else if ((e = tgetenv(*v)) != NULL) { - int old_output_raw; - - old_output_raw = output_raw; - output_raw = 1; - cleanup_push(&old_output_raw, output_raw_restore); - xprintf("%S\n", e); - cleanup_until(&old_output_raw); - } - else - setcopy(STRstatus, STR1, VAR_READWRITE); -} - -/* from "Karl Berry." <karl%mote.umb.edu@relay.cs.net> -- for NeXT things - (and anything else with a modern compiler) */ - -/*ARGSUSED*/ -void -dosetenv(Char **v, struct command *c) -{ - Char *vp, *lp; - - USE(c); - if (*++v == 0) { - doprintenv(--v, 0); - return; - } - - vp = *v++; - - lp = vp; - - for (; *lp != '\0' ; lp++) { - if (*lp == '=') - stderror(ERR_NAME | ERR_SYNTAX); - } - if ((lp = *v++) == 0) - lp = STRNULL; - - lp = globone(lp, G_APPEND); - cleanup_push(lp, xfree); - tsetenv(vp, lp); - if (eq(vp, STRKPATH)) { - importpath(lp); - dohash(NULL, NULL); - cleanup_until(lp); - return; - } - -#ifdef apollo - if (eq(vp, STRSYSTYPE)) { - dohash(NULL, NULL); - cleanup_until(lp); - return; - } -#endif /* apollo */ - - /* dspkanji/dspmbyte autosetting */ - /* PATCH IDEA FROM Issei.Suzuki VERY THANKS */ -#if defined(DSPMBYTE) - if(eq(vp, STRLANG) && !adrof(CHECK_MBYTEVAR)) { - autoset_dspmbyte(lp); - } -#endif - - if (islocale_var(vp)) { -#ifdef NLS - int k; - -# ifdef SETLOCALEBUG - dont_free = 1; -# endif /* SETLOCALEBUG */ - (void) setlocale(LC_ALL, ""); -# ifdef LC_COLLATE - (void) setlocale(LC_COLLATE, ""); -# endif -# ifdef LC_CTYPE - (void) setlocale(LC_CTYPE, ""); /* for iscntrl */ -# endif /* LC_CTYPE */ -# ifdef NLS_CATALOGS -# ifdef LC_MESSAGES - (void) setlocale(LC_MESSAGES, ""); -# endif /* LC_MESSAGES */ - nlsclose(); - nlsinit(); -# endif /* NLS_CATALOGS */ -# ifdef SETLOCALEBUG - dont_free = 0; -# endif /* SETLOCALEBUG */ -# ifdef STRCOLLBUG - fix_strcoll_bug(); -# endif /* STRCOLLBUG */ - tw_cmd_free(); /* since the collation sequence has changed */ - for (k = 0200; k <= 0377 && !Isprint(CTL_ESC(k)); k++) - continue; - AsciiOnly = MB_CUR_MAX == 1 && k > 0377; -#else /* !NLS */ - AsciiOnly = 0; -#endif /* NLS */ - NLSMapsAreInited = 0; - ed_Init(); - if (MapsAreInited && !NLSMapsAreInited) - ed_InitNLSMaps(); - cleanup_until(lp); - return; - } - -#ifdef NLS_CATALOGS - if (eq(vp, STRNLSPATH)) { - nlsclose(); - nlsinit(); - } -#endif - - if (eq(vp, STRNOREBIND)) { - NoNLSRebind = 1; - MapsAreInited = 0; - NLSMapsAreInited = 0; - ed_InitMaps(); - cleanup_until(lp); - return; - } -#ifdef WINNT_NATIVE - if (eq(vp, STRtcshlang)) { - nlsinit(); - cleanup_until(lp); - return; - } -#endif /* WINNT_NATIVE */ - if (eq(vp, STRKTERM)) { - char *t; - - setv(STRterm, quote(lp), VAR_READWRITE); /* lp memory used here */ - cleanup_ignore(lp); - cleanup_until(lp); - t = short2str(lp); - if (noediting && strcmp(t, "unknown") != 0 && strcmp(t,"dumb") != 0) { - editing = 1; - noediting = 0; - setNS(STRedit); - } - GotTermCaps = 0; - ed_Init(); - return; - } - - if (eq(vp, STRKHOME)) { - Char *canon; - /* - * convert to canonical pathname (possibly resolving symlinks) - */ - canon = dcanon(lp, lp); - cleanup_ignore(lp); - cleanup_until(lp); - cleanup_push(canon, xfree); - setv(STRhome, quote(canon), VAR_READWRITE); /* lp memory used here */ - cleanup_ignore(canon); - cleanup_until(canon); - - /* fix directory stack for new tilde home */ - dtilde(); - return; - } - - if (eq(vp, STRKSHLVL)) { - setv(STRshlvl, quote(lp), VAR_READWRITE); /* lp memory used here */ - cleanup_ignore(lp); - cleanup_until(lp); - return; - } - - if (eq(vp, STRKUSER)) { - setv(STRuser, quote(lp), VAR_READWRITE); /* lp memory used here */ - cleanup_ignore(lp); - cleanup_until(lp); - return; - } - - if (eq(vp, STRKGROUP)) { - setv(STRgroup, quote(lp), VAR_READWRITE); /* lp memory used here */ - cleanup_ignore(lp); - cleanup_until(lp); - return; - } - -#ifdef COLOR_LS_F - if (eq(vp, STRLS_COLORS)) { - parseLS_COLORS(lp); - cleanup_until(lp); - return; - } -#endif /* COLOR_LS_F */ - -#ifdef SIG_WINDOW - /* - * Load/Update $LINES $COLUMNS - */ - if ((eq(lp, STRNULL) && (eq(vp, STRLINES) || eq(vp, STRCOLUMNS))) || - eq(vp, STRTERMCAP)) { - cleanup_until(lp); - check_window_size(1); - return; - } - - /* - * Change the size to the one directed by $LINES and $COLUMNS - */ - if (eq(vp, STRLINES) || eq(vp, STRCOLUMNS)) { -#if 0 - GotTermCaps = 0; -#endif - cleanup_until(lp); - ed_Init(); - return; - } -#endif /* SIG_WINDOW */ - cleanup_until(lp); -} - -/*ARGSUSED*/ -void -dounsetenv(Char **v, struct command *c) -{ - Char **ep, *p, *n, *name; - int i, maxi; - - USE(c); - /* - * 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 = xmalloc((maxi + 1) * sizeof(Char)); - cleanup_push(name, xfree); - - 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; - - /* Unset the name. This wasn't being done until - * later but most of the stuff following won't - * work (particularly the setlocale() and getenv() - * stuff) as intended until the name is actually - * removed. (sg) - */ - Unsetenv(name); - - if (eq(name, STRNOREBIND)) { - NoNLSRebind = 0; - MapsAreInited = 0; - NLSMapsAreInited = 0; - ed_InitMaps(); - } -#ifdef apollo - else if (eq(name, STRSYSTYPE)) - dohash(NULL, NULL); -#endif /* apollo */ - else if (islocale_var(name)) { -#ifdef NLS - int k; - -# ifdef SETLOCALEBUG - dont_free = 1; -# endif /* SETLOCALEBUG */ - (void) setlocale(LC_ALL, ""); -# ifdef LC_COLLATE - (void) setlocale(LC_COLLATE, ""); -# endif -# ifdef LC_CTYPE - (void) setlocale(LC_CTYPE, ""); /* for iscntrl */ -# endif /* LC_CTYPE */ -# ifdef NLS_CATALOGS -# ifdef LC_MESSAGES - (void) setlocale(LC_MESSAGES, ""); -# endif /* LC_MESSAGES */ - nlsclose(); - nlsinit(); -# endif /* NLS_CATALOGS */ -# ifdef SETLOCALEBUG - dont_free = 0; -# endif /* SETLOCALEBUG */ -# ifdef STRCOLLBUG - fix_strcoll_bug(); -# endif /* STRCOLLBUG */ - tw_cmd_free();/* since the collation sequence has changed */ - for (k = 0200; k <= 0377 && !Isprint(CTL_ESC(k)); k++) - continue; - AsciiOnly = MB_CUR_MAX == 1 && k > 0377; -#else /* !NLS */ - AsciiOnly = getenv("LANG") == NULL && - getenv("LC_CTYPE") == NULL; -#endif /* NLS */ - NLSMapsAreInited = 0; - ed_Init(); - if (MapsAreInited && !NLSMapsAreInited) - ed_InitNLSMaps(); - - } -#ifdef WINNT_NATIVE - else if (eq(name,(STRtcshlang))) { - nls_dll_unload(); - nlsinit(); - } -#endif /* WINNT_NATIVE */ -#ifdef COLOR_LS_F - else if (eq(name, STRLS_COLORS)) - parseLS_COLORS(n); -#endif /* COLOR_LS_F */ -#ifdef NLS_CATALOGS - else if (eq(name, STRNLSPATH)) { - nlsclose(); - nlsinit(); - } -#endif - /* - * start again cause the environment changes - */ - break; - } - cleanup_until(name); -} - -void -tsetenv(const Char *name, const Char *val) -{ -#ifdef SETENV_IN_LIB -/* - * XXX: This does not work right, since tcsh cannot track changes to - * the environment this way. (the builtin setenv without arguments does - * not print the right stuff neither does unsetenv). This was for Mach, - * it is not needed anymore. - */ -#undef setenv - char *cname; - - if (name == NULL) - return; - cname = strsave(short2str(name)); - setenv(cname, short2str(val), 1); - xfree(cname); -#else /* !SETENV_IN_LIB */ - Char **ep = STR_environ; - const Char *ccp; - Char *cp, *dp; - Char *blk[2]; - Char **oep = ep; - -#ifdef WINNT_NATIVE - nt_set_env(name,val); -#endif /* WINNT_NATIVE */ - for (; *ep; ep++) { -#ifdef WINNT_NATIVE - for (ccp = name, dp = *ep; *ccp && Tolower(*ccp & TRIM) == Tolower(*dp); - ccp++, dp++) -#else - for (ccp = name, dp = *ep; *ccp && (*ccp & TRIM) == *dp; ccp++, dp++) -#endif /* WINNT_NATIVE */ - continue; - if (*ccp != 0 || *dp != '=') - continue; - cp = Strspl(STRequal, val); - xfree(*ep); - *ep = strip(Strspl(name, cp)); - xfree(cp); - blkfree((Char **) environ); - environ = short2blk(STR_environ); - return; - } - cp = Strspl(name, STRequal); - blk[0] = strip(Strspl(cp, val)); - xfree(cp); - blk[1] = 0; - STR_environ = blkspl(STR_environ, blk); - blkfree((Char **) environ); - environ = short2blk(STR_environ); - xfree(oep); -#endif /* SETENV_IN_LIB */ -} - -void -Unsetenv(Char *name) -{ - Char **ep = STR_environ; - Char *cp, *dp; - Char **oep = ep; - -#ifdef WINNT_NATIVE - nt_set_env(name,NULL); -#endif /*WINNT_NATIVE */ - 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); - blkfree((Char **) environ); - environ = short2blk(STR_environ); - *ep = cp; - xfree(cp); - xfree(oep); - return; - } -} - -/*ARGSUSED*/ -void -doumask(Char **v, struct command *c) -{ - Char *cp = v[1]; - int i; - - USE(c); - if (cp == 0) { - i = (int)umask(0); - (void) umask(i); - xprintf("%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); -} - -#ifndef HAVENOLIMIT -# ifndef BSDLIMIT - typedef long RLIM_TYPE; -# ifdef _OSD_POSIX /* BS2000 */ -# include <ulimit.h> -# endif -# ifndef RLIM_INFINITY -# if !defined(_MINIX) && !defined(__clipper__) && !defined(_CRAY) - extern RLIM_TYPE ulimit(); -# endif /* ! _MINIX && !__clipper__ */ -# define RLIM_INFINITY 0x003fffff -# define RLIMIT_FSIZE 1 -# endif /* RLIM_INFINITY */ -# ifdef aiws -# define toset(a) (((a) == 3) ? 1004 : (a) + 1) -# define RLIMIT_DATA 3 -# define RLIMIT_STACK 1005 -# else /* aiws */ -# define toset(a) ((a) + 1) -# endif /* aiws */ -# else /* BSDLIMIT */ -# if (defined(BSD4_4) || defined(__linux__) || defined(__GNU__) || defined(__GLIBC__) || (HPUXVERSION >= 1100)) && !defined(__386BSD__) - typedef rlim_t RLIM_TYPE; -# else -# if defined(SOLARIS2) || (defined(sgi) && SYSVREL > 3) - typedef rlim_t RLIM_TYPE; -# else -# if defined(_SX) - typedef long long RLIM_TYPE; -# else /* !_SX */ - typedef unsigned long RLIM_TYPE; -# endif /* _SX */ -# endif /* SOLARIS2 || (sgi && SYSVREL > 3) */ -# endif /* BSD4_4 && !__386BSD__ */ -# endif /* BSDLIMIT */ - -# if (HPUXVERSION > 700) && (HPUXVERSION < 1100) && defined(BSDLIMIT) -/* Yes hpux8.0 has limits but <sys/resource.h> does not make them public */ -/* Yes, we could have defined _KERNEL, and -I/etc/conf/h, but is that better? */ -# ifndef RLIMIT_CPU -# define RLIMIT_CPU 0 -# define RLIMIT_FSIZE 1 -# define RLIMIT_DATA 2 -# define RLIMIT_STACK 3 -# define RLIMIT_CORE 4 -# define RLIMIT_RSS 5 -# define RLIMIT_NOFILE 6 -# endif /* RLIMIT_CPU */ -# ifndef RLIM_INFINITY -# define RLIM_INFINITY 0x7fffffff -# endif /* RLIM_INFINITY */ - /* - * old versions of HP/UX counted limits in 512 bytes - */ -# ifndef SIGRTMIN -# define FILESIZE512 -# endif /* SIGRTMIN */ -# endif /* (HPUXVERSION > 700) && (HPUXVERSION < 1100) && BSDLIMIT */ - -# if SYSVREL > 3 && defined(BSDLIMIT) && !defined(_SX) -/* In order to use rusage, we included "/usr/ucbinclude/sys/resource.h" in */ -/* sh.h. However, some SVR4 limits are defined in <sys/resource.h>. Rather */ -/* than include both and get warnings, we define the extra SVR4 limits here. */ -/* XXX: I don't understand if RLIMIT_AS is defined, why don't we define */ -/* RLIMIT_VMEM based on it? */ -# ifndef RLIMIT_VMEM -# define RLIMIT_VMEM 6 -# endif -# ifndef RLIMIT_AS -# define RLIMIT_AS RLIMIT_VMEM -# endif -# endif /* SYSVREL > 3 && BSDLIMIT */ - -# if (defined(__linux__) || defined(__GNU__) || defined(__GLIBC__)) && defined(RLIMIT_AS) && !defined(RLIMIT_VMEM) -# define RLIMIT_VMEM RLIMIT_AS -# endif - -struct limits limits[] = -{ -# ifdef RLIMIT_CPU - { RLIMIT_CPU, "cputime", 1, "seconds" }, -# endif /* RLIMIT_CPU */ - -# ifdef RLIMIT_FSIZE -# ifndef aiws - { RLIMIT_FSIZE, "filesize", 1024, "kbytes" }, -# else - { RLIMIT_FSIZE, "filesize", 512, "blocks" }, -# endif /* aiws */ -# endif /* RLIMIT_FSIZE */ - -# ifdef RLIMIT_DATA - { RLIMIT_DATA, "datasize", 1024, "kbytes" }, -# endif /* RLIMIT_DATA */ - -# ifdef RLIMIT_STACK -# ifndef aiws - { RLIMIT_STACK, "stacksize", 1024, "kbytes" }, -# else - { RLIMIT_STACK, "stacksize", 1024 * 1024, "kbytes"}, -# endif /* aiws */ -# endif /* RLIMIT_STACK */ - -# ifdef RLIMIT_CORE - { RLIMIT_CORE, "coredumpsize", 1024, "kbytes" }, -# endif /* RLIMIT_CORE */ - -# ifdef RLIMIT_RSS - { RLIMIT_RSS, "memoryuse", 1024, "kbytes" }, -# endif /* RLIMIT_RSS */ - -# ifdef RLIMIT_UMEM - { RLIMIT_UMEM, "memoryuse", 1024, "kbytes" }, -# endif /* RLIMIT_UMEM */ - -# ifdef RLIMIT_VMEM - { RLIMIT_VMEM, "vmemoryuse", 1024, "kbytes" }, -# endif /* RLIMIT_VMEM */ - -# if defined(RLIMIT_HEAP) /* found on BS2000/OSD systems */ - { RLIMIT_HEAP, "heapsize", 1024, "kbytes" }, -# endif /* RLIMIT_HEAP */ - -# ifdef RLIMIT_NOFILE - { RLIMIT_NOFILE, "descriptors", 1, "" }, -# endif /* RLIMIT_NOFILE */ - -# ifdef RLIMIT_CONCUR - { RLIMIT_CONCUR, "concurrency", 1, "thread(s)" }, -# endif /* RLIMIT_CONCUR */ - -# ifdef RLIMIT_MEMLOCK - { RLIMIT_MEMLOCK, "memorylocked", 1024, "kbytes" }, -# endif /* RLIMIT_MEMLOCK */ - -# ifdef RLIMIT_NPROC - { RLIMIT_NPROC, "maxproc", 1, "" }, -# endif /* RLIMIT_NPROC */ - -# if defined(RLIMIT_OFILE) && !defined(RLIMIT_NOFILE) - { RLIMIT_OFILE, "openfiles", 1, "" }, -# endif /* RLIMIT_OFILE && !defined(RLIMIT_NOFILE) */ - -# ifdef RLIMIT_SBSIZE - { RLIMIT_SBSIZE, "sbsize", 1, "" }, -# endif /* RLIMIT_SBSIZE */ - - { -1, NULL, 0, NULL } -}; - -static struct limits *findlim (Char *); -static RLIM_TYPE getval (struct limits *, Char **); -static void limtail (Char *, const char *); -static void plim (struct limits *, int); -static int setlim (struct limits *, int, RLIM_TYPE); - -#ifdef convex -static RLIM_TYPE -restrict_limit(double value) -{ - /* - * is f too large to cope with? return the maximum or minimum int - */ - if (value > (double) INT_MAX) - return (RLIM_TYPE) INT_MAX; - else if (value < (double) INT_MIN) - return (RLIM_TYPE) INT_MIN; - else - return (RLIM_TYPE) value; -} -#else /* !convex */ -# define restrict_limit(x) ((RLIM_TYPE) (x)) -#endif /* convex */ - - -static struct limits * -findlim(Char *cp) -{ - struct limits *lp, *res; - - res = 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); -} - -/*ARGSUSED*/ -void -dolimit(Char **v, struct command *c) -{ - struct limits *lp; - RLIM_TYPE limit; - int hard = 0; - - USE(c); - 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(struct limits *lp, Char **v) -{ - float f; - Char *cp = *v++; - - f = atof(short2str(cp)); - -# ifdef convex - /* - * is f too large to cope with. limit f to minint, maxint - X-6768 by - * strike - */ - if ((f < (double) INT_MIN) || (f > (double) INT_MAX)) { - stderror(ERR_NAME | ERR_TOOLARGE); - } -# endif /* convex */ - - while (Isdigit(*cp) || *cp == '.' || *cp == 'e' || *cp == 'E') - cp++; - if (*cp == 0) { - if (*v == 0) - return restrict_limit((f * lp->limdiv) + 0.5); - cp = *v; - } - switch (*cp) { -# ifdef RLIMIT_CPU - case ':': - if (lp->limconst != RLIMIT_CPU) - goto badscal; - return f == 0.0 ? (RLIM_TYPE) 0 : restrict_limit((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; -# endif /* RLIMIT_CPU */ - case 'M': -# ifdef RLIMIT_CPU - if (lp->limconst == RLIMIT_CPU) - goto badscal; -# endif /* RLIMIT_CPU */ - *cp = 'm'; - limtail(cp, "megabytes"); - f *= 1024.0 * 1024.0; - break; - case 'k': -# ifdef RLIMIT_CPU - if (lp->limconst == RLIMIT_CPU) - goto badscal; -# endif /* RLIMIT_CPU */ - limtail(cp, "kbytes"); - f *= 1024.0; - break; - case 'b': -# ifdef RLIMIT_CPU - if (lp->limconst == RLIMIT_CPU) - goto badscal; -# endif /* RLIMIT_CPU */ - limtail(cp, "blocks"); - f *= 512.0; - break; - case 'u': - limtail(cp, "unlimited"); - return ((RLIM_TYPE) RLIM_INFINITY); - default: -# ifdef RLIMIT_CPU -badscal: -# endif /* RLIMIT_CPU */ - stderror(ERR_NAME | ERR_SCALEF); - } -# ifdef convex - return f == 0.0 ? (RLIM_TYPE) 0 : restrict_limit((f + 0.5)); -# else - f += 0.5; - if (f > (float) RLIM_INFINITY) - return ((RLIM_TYPE) RLIM_INFINITY); - else - return ((RLIM_TYPE) f); -# endif /* convex */ -} - -static void -limtail(Char *cp, const char *str) -{ - const char *sp; - - sp = str; - while (*cp && *cp == (Char)*str) - cp++, str++; - if (*cp) - stderror(ERR_BADSCALE, sp); -} - - -/*ARGSUSED*/ -static void -plim(struct limits *lp, int hard) -{ -# ifdef BSDLIMIT - struct rlimit rlim; -# endif /* BSDLIMIT */ - RLIM_TYPE limit; - int xdiv = lp->limdiv; - - xprintf("%-13.13s", lp->limname); - -# ifndef BSDLIMIT - limit = ulimit(lp->limconst, 0); -# ifdef aiws - if (lp->limconst == RLIMIT_DATA) - limit -= 0x20000000; -# endif /* aiws */ -# else /* BSDLIMIT */ - (void) getrlimit(lp->limconst, &rlim); - limit = hard ? rlim.rlim_max : rlim.rlim_cur; -# endif /* BSDLIMIT */ - -# if !defined(BSDLIMIT) || defined(FILESIZE512) - /* - * Christos: filesize comes in 512 blocks. we divide by 2 to get 1024 - * blocks. Note we cannot pre-multiply cause we might overflow (A/UX) - */ - if (lp->limconst == RLIMIT_FSIZE) { - if (limit >= (RLIM_INFINITY / 512)) - limit = RLIM_INFINITY; - else - xdiv = (xdiv == 1024 ? 2 : 1); - } -# endif /* !BSDLIMIT || FILESIZE512 */ - - if (limit == RLIM_INFINITY) - xprintf("unlimited"); - else -# if defined(RLIMIT_CPU) && defined(_OSD_POSIX) - if (lp->limconst == RLIMIT_CPU && - (unsigned long)limit >= 0x7ffffffdUL) - xprintf("unlimited"); - else -# endif -# ifdef RLIMIT_CPU - if (lp->limconst == RLIMIT_CPU) - psecs(limit); - else -# endif /* RLIMIT_CPU */ - xprintf("%ld %s", (long) (limit / xdiv), lp->limscale); - xputchar('\n'); -} - -/*ARGSUSED*/ -void -dounlimit(Char **v, struct command *c) -{ - struct limits *lp; - int lerr = 0; - int hard = 0; - int force = 0; - - USE(c); - while (*++v && **v == '-') { - Char *vp = *v; - while (*++vp) - switch (*vp) { - case 'f': - force = 1; - break; - case 'h': - hard = 1; - break; - default: - stderror(ERR_ULIMUS); - break; - } - } - - if (*v == 0) { - for (lp = limits; lp->limconst >= 0; lp++) - if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0) - lerr++; - if (!force && lerr) - stderror(ERR_SILENT); - return; - } - while (*v) { - lp = findlim(*v++); - if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0 && !force) - stderror(ERR_SILENT); - } -} - -static int -setlim(struct limits *lp, int hard, RLIM_TYPE limit) -{ -# ifdef BSDLIMIT - struct rlimit rlim; - - (void) getrlimit(lp->limconst, &rlim); - -# ifdef FILESIZE512 - /* Even though hpux has setrlimit(), it expects fsize in 512 byte blocks */ - if (limit != RLIM_INFINITY && lp->limconst == RLIMIT_FSIZE) - limit /= 512; -# endif /* FILESIZE512 */ - if (hard) - rlim.rlim_max = limit; - else if (limit == RLIM_INFINITY && euid != 0) - rlim.rlim_cur = rlim.rlim_max; - else - rlim.rlim_cur = limit; - - if (rlim.rlim_cur > rlim.rlim_max) - rlim.rlim_max = rlim.rlim_cur; - - if (setrlimit(lp->limconst, &rlim) < 0) { -# else /* BSDLIMIT */ - if (limit != RLIM_INFINITY && lp->limconst == RLIMIT_FSIZE) - limit /= 512; -# ifdef aiws - if (lp->limconst == RLIMIT_DATA) - limit += 0x20000000; -# endif /* aiws */ - if (ulimit(toset(lp->limconst), limit) < 0) { -# endif /* BSDLIMIT */ - int err; - char *op, *type; - - err = errno; - op = strsave(limit == RLIM_INFINITY ? CGETS(15, 2, "remove") : - CGETS(15, 3, "set")); - cleanup_push(op, xfree); - type = strsave(hard ? CGETS(15, 4, " hard") : ""); - cleanup_push(type, xfree); - xprintf(CGETS(15, 1, "%s: %s: Can't %s%s limit (%s)\n"), bname, - lp->limname, op, type, strerror(err)); - cleanup_until(op); - return (-1); - } - return (0); -} - -#endif /* !HAVENOLIMIT */ - -/*ARGSUSED*/ -void -dosuspend(Char **v, struct command *c) -{ -#ifdef BSDJOBS - int ctpgrp; - struct sigaction old; -#endif /* BSDJOBS */ - - USE(c); - USE(v); - - if (loginsh) - stderror(ERR_SUSPLOG); - untty(); - -#ifdef BSDJOBS - sigaction(SIGTSTP, NULL, &old); - signal(SIGTSTP, SIG_DFL); - (void) kill(0, SIGTSTP); - /* the shell stops here */ - sigaction(SIGTSTP, &old, NULL); -#else /* !BSDJOBS */ - stderror(ERR_JOBCONTROL); -#endif /* BSDJOBS */ - -#ifdef BSDJOBS - if (tpgrp != -1) { -retry: - ctpgrp = tcgetpgrp(FSHTTY); - if (ctpgrp == -1) - stderror(ERR_SYSTEM, "tcgetpgrp", strerror(errno)); - if (ctpgrp != opgrp) { - sigaction(SIGTTIN, NULL, &old); - signal(SIGTTIN, SIG_DFL); - (void) kill(0, SIGTTIN); - sigaction(SIGTTIN, &old, NULL); - goto retry; - } - (void) setpgid(0, shpgrp); - (void) tcsetpgrp(FSHTTY, shpgrp); - } -#endif /* BSDJOBS */ - (void) setdisc(FSHTTY); -} - -/* 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! - */ - -struct doeval_state -{ - Char **evalvec, *evalp; - int didfds; -#ifndef CLOSE_ON_EXEC - int didcch; -#endif - int saveIN, saveOUT, saveDIAG; - int SHIN, SHOUT, SHDIAG; -}; - -static void -doeval_cleanup(void *xstate) -{ - struct doeval_state *state; - - state = xstate; - evalvec = state->evalvec; - evalp = state->evalp; - doneinp = 0; -#ifndef CLOSE_ON_EXEC - didcch = state->didcch; -#endif /* CLOSE_ON_EXEC */ - didfds = state->didfds; - xclose(SHIN); - xclose(SHOUT); - xclose(SHDIAG); - close_on_exec(SHIN = dmove(state->saveIN, state->SHIN), 1); - close_on_exec(SHOUT = dmove(state->saveOUT, state->SHOUT), 1); - close_on_exec(SHDIAG = dmove(state->saveDIAG, state->SHDIAG), 1); -} - -/*ARGSUSED*/ -void -doeval(Char **v, struct command *c) -{ - struct doeval_state state; - int gflag; - Char **gv; - - USE(c); - v++; - if (*v == 0) - return; - gflag = tglob(v); - if (gflag) { - gv = v = globall(v, gflag); - if (v == 0) - stderror(ERR_NOMATCH); - cleanup_push(gv, blk_cleanup); - v = copyblk(v); - } - else { - gv = NULL; - v = copyblk(v); - trim(v); - } - - state.evalvec = evalvec; - state.evalp = evalp; - state.didfds = didfds; -#ifndef CLOSE_ON_EXEC - state.didcch = didcch; -#endif /* CLOSE_ON_EXEC */ - state.SHIN = SHIN; - state.SHOUT = SHOUT; - state.SHDIAG = SHDIAG; - - (void)close_on_exec(state.saveIN = dcopy(SHIN, -1), 1); - (void)close_on_exec(state.saveOUT = dcopy(SHOUT, -1), 1); - (void)close_on_exec(state.saveDIAG = dcopy(SHDIAG, -1), 1); - - cleanup_push(&state, doeval_cleanup); - - evalvec = v; - evalp = 0; - (void)close_on_exec(SHIN = dcopy(0, -1), 1); - (void)close_on_exec(SHOUT = dcopy(1, -1), 1); - (void)close_on_exec(SHDIAG = dcopy(2, -1), 1); -#ifndef CLOSE_ON_EXEC - didcch = 0; -#endif /* CLOSE_ON_EXEC */ - didfds = 0; - process(0); - - cleanup_until(&state); - - if (gv) - cleanup_until(gv); -} - -/*************************************************************************/ -/* print list of builtin commands */ - -static void -lbuffed_cleanup (void *dummy) -{ - USE(dummy); - lbuffed = 1; -} - -/*ARGSUSED*/ -void -dobuiltins(Char **v, struct command *c) -{ - /* would use print_by_column() in tw.parse.c but that assumes - * we have an array of Char * to pass.. (sg) - */ - const struct biltins *b; - int row, col, columns, rows; - unsigned int w, maxwidth; - - USE(c); - USE(v); - lbuffed = 0; /* turn off line buffering */ - cleanup_push(&lbuffed, lbuffed_cleanup); - - /* find widest string */ - for (maxwidth = 0, b = bfunc; b < &bfunc[nbfunc]; ++b) - maxwidth = max(maxwidth, strlen(b->bname)); - ++maxwidth; /* for space */ - - columns = (TermH + 1) / maxwidth; /* PWP: terminal size change */ - if (!columns) - columns = 1; - rows = (nbfunc + (columns - 1)) / columns; - - for (b = bfunc, row = 0; row < rows; row++) { - for (col = 0; col < columns; col++) { - if (b < &bfunc[nbfunc]) { - w = strlen(b->bname); - xprintf("%s", b->bname); - if (col < (columns - 1)) /* Not last column? */ - for (; w < maxwidth; w++) - xputchar(' '); - ++b; - } - } - if (row < (rows - 1)) { - if (Tty_raw_mode) - xputchar('\r'); - xputchar('\n'); - } - } -#ifdef WINNT_NATIVE - nt_print_builtins(maxwidth); -#else - if (Tty_raw_mode) - xputchar('\r'); - xputchar('\n'); -#endif /* WINNT_NATIVE */ - - cleanup_until(&lbuffed); /* turn back on line buffering */ - flush(); -} - -#ifdef NLS_CATALOGS -char * -xcatgets(nl_catd ctd, int set_id, int msg_id, const char *s) -{ - char *res; - - errno = 0; - while ((res = catgets(ctd, set_id, msg_id, s)) == s && errno == EINTR) { - handle_pending_signals(); - errno = 0; - } - return res; -} - - -# if defined(HAVE_ICONV) && defined(HAVE_NL_LANGINFO) -char * -iconv_catgets(nl_catd ctd, int set_id, int msg_id, const char *s) -{ - static char *buf = NULL; - static size_t buf_size = 0; - - char *orig, *dest, *p; - ICONV_CONST char *src; - size_t src_size, dest_size; - - orig = xcatgets(ctd, set_id, msg_id, s); - if (catgets_iconv == (iconv_t)-1 || orig == s) - return orig; - src = orig; - src_size = strlen(src) + 1; - if (buf == NULL && (buf = xmalloc(buf_size = src_size + 32)) == NULL) - return orig; - dest = buf; - while (src_size != 0) { - dest_size = buf + buf_size - dest; - if (iconv(catgets_iconv, &src, &src_size, &dest, &dest_size) - == (size_t)-1) { - switch (errno) { - case E2BIG: - if ((p = xrealloc(buf, buf_size * 2)) == NULL) - return orig; - buf_size *= 2; - dest = p + (dest - buf); - buf = p; - break; - - case EILSEQ: case EINVAL: default: - return orig; - } - } - } - return buf; -} -# endif /* HAVE_ICONV && HAVE_NL_LANGINFO */ -#endif /* NLS_CATALOGS */ - -void -nlsinit(void) -{ -#ifdef NLS_CATALOGS - static const char default_catalog[] = "tcsh"; - - char *catalog = (char *)(intptr_t)default_catalog; - - if (adrof(STRcatalog) != NULL) - catalog = xasprintf("tcsh.%s", short2str(varval(STRcatalog))); - catd = catopen(catalog, MCLoadBySet); - if (catalog != default_catalog) - xfree(catalog); -#if defined(HAVE_ICONV) && defined(HAVE_NL_LANGINFO) - /* xcatgets (), not CGETS, the charset name should be in ASCII anyway. */ - catgets_iconv = iconv_open (nl_langinfo (CODESET), - xcatgets(catd, 255, 1, "ASCII")); -#endif /* HAVE_ICONV && HAVE_NL_LANGINFO */ -#endif /* NLS_CATALOGS */ -#ifdef WINNT_NATIVE - nls_dll_init(); -#endif /* WINNT_NATIVE */ - errinit(); /* init the errorlist in correct locale */ - mesginit(); /* init the messages for signals */ - dateinit(); /* init the messages for dates */ - editinit(); /* init the editor messages */ - terminit(); /* init the termcap messages */ -} - -void -nlsclose(void) -{ -#ifdef NLS_CATALOGS -#if defined(HAVE_ICONV) && defined(HAVE_NL_LANGINFO) - if (catgets_iconv != (iconv_t)-1) { - iconv_close(catgets_iconv); - catgets_iconv = (iconv_t)-1; - } -#endif /* HAVE_ICONV && HAVE_NL_LANGINFO */ - if (catd != (nl_catd)-1) { - /* - * catclose can call other functions which can call longjmp - * making us re-enter this code. Prevent infinite recursion - * by resetting catd. Problem reported and solved by: - * Gerhard Niklasch - */ - nl_catd oldcatd = catd; - catd = (nl_catd)-1; - while (catclose(oldcatd) == -1 && errno == EINTR) - handle_pending_signals(); - } -#endif /* NLS_CATALOGS */ -} |