summaryrefslogtreecommitdiffstats
path: root/contrib/tcsh/sh.func.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/tcsh/sh.func.c')
-rw-r--r--contrib/tcsh/sh.func.c2457
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 */
-}
OpenPOWER on IntegriCloud