sh.func.c revision 100616
1100616Smp/* $Header: /src/pub/tcsh/sh.func.c,v 3.103 2002/07/09 12:56:55 christos Exp $ */ 259243Sobrien/* 359243Sobrien * sh.func.c: csh builtin functions 459243Sobrien */ 559243Sobrien/*- 659243Sobrien * Copyright (c) 1980, 1991 The Regents of the University of California. 759243Sobrien * All rights reserved. 859243Sobrien * 959243Sobrien * Redistribution and use in source and binary forms, with or without 1059243Sobrien * modification, are permitted provided that the following conditions 1159243Sobrien * are met: 1259243Sobrien * 1. Redistributions of source code must retain the above copyright 1359243Sobrien * notice, this list of conditions and the following disclaimer. 1459243Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1559243Sobrien * notice, this list of conditions and the following disclaimer in the 1659243Sobrien * documentation and/or other materials provided with the distribution. 17100616Smp * 3. Neither the name of the University nor the names of its contributors 1859243Sobrien * may be used to endorse or promote products derived from this software 1959243Sobrien * without specific prior written permission. 2059243Sobrien * 2159243Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2259243Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2359243Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2459243Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2559243Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2659243Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2759243Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2859243Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2959243Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3059243Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3159243Sobrien * SUCH DAMAGE. 3259243Sobrien */ 3359243Sobrien#include "sh.h" 3459243Sobrien 35100616SmpRCSID("$Id: sh.func.c,v 3.103 2002/07/09 12:56:55 christos Exp $") 3659243Sobrien 3759243Sobrien#include "ed.h" 3859243Sobrien#include "tw.h" 3959243Sobrien#include "tc.h" 4069408Sache#ifdef WINNT_NATIVE 4159243Sobrien#include "nt.const.h" 4269408Sache#endif /* WINNT_NATIVE */ 4359243Sobrien 4459243Sobrien/* 4559243Sobrien * C shell 4659243Sobrien */ 4759243Sobrienextern int just_signaled; 4859243Sobrienextern char **environ; 4959243Sobrien 5059243Sobrienextern bool MapsAreInited; 5159243Sobrienextern bool NLSMapsAreInited; 5259243Sobrienextern bool NoNLSRebind; 5359243Sobrienextern bool GotTermCaps; 5459243Sobrien 5559243Sobrienstatic int zlast = -1; 5659243Sobrien 5759243Sobrienstatic void islogin __P((void)); 5859243Sobrienstatic void preread __P((void)); 5959243Sobrienstatic void doagain __P((void)); 6059243Sobrienstatic char *isrchx __P((int)); 6159243Sobrienstatic void search __P((int, int, Char *)); 6259243Sobrienstatic int getword __P((Char *)); 6359243Sobrienstatic void toend __P((void)); 6459243Sobrienstatic void xecho __P((int, Char **)); 6559243Sobrienstatic bool islocale_var __P((Char *)); 6659243Sobrien 6759243Sobrienstruct biltins * 6859243Sobrienisbfunc(t) 6959243Sobrien struct command *t; 7059243Sobrien{ 7159243Sobrien register Char *cp = t->t_dcom[0]; 7259243Sobrien register struct biltins *bp, *bp1, *bp2; 7359243Sobrien static struct biltins label = {"", dozip, 0, 0}; 7459243Sobrien static struct biltins foregnd = {"%job", dofg1, 0, 0}; 7559243Sobrien static struct biltins backgnd = {"%job &", dobg1, 0, 0}; 7659243Sobrien 7759243Sobrien /* 7859243Sobrien * We never match a builtin that has quoted the first 7959243Sobrien * character; this has been the traditional way to escape 8059243Sobrien * builtin commands. 8159243Sobrien */ 8259243Sobrien if (*cp & QUOTE) 8359243Sobrien return NULL; 8459243Sobrien 8559243Sobrien if (*cp != ':' && lastchr(cp) == ':') { 8659243Sobrien label.bname = short2str(cp); 8759243Sobrien return (&label); 8859243Sobrien } 8959243Sobrien if (*cp == '%') { 9059243Sobrien if (t->t_dflg & F_AMPERSAND) { 9159243Sobrien t->t_dflg &= ~F_AMPERSAND; 9259243Sobrien backgnd.bname = short2str(cp); 9359243Sobrien return (&backgnd); 9459243Sobrien } 9559243Sobrien foregnd.bname = short2str(cp); 9659243Sobrien return (&foregnd); 9759243Sobrien } 9859243Sobrien#ifdef WARP 9959243Sobrien /* 10059243Sobrien * This is a perhaps kludgy way to determine if the warp builtin is to be 10159243Sobrien * acknowledged or not. If checkwarp() fails, then we are to assume that 10259243Sobrien * the warp command is invalid, and carry on as we would handle any other 10359243Sobrien * non-builtin command. -- JDK 2/4/88 10459243Sobrien */ 10559243Sobrien if (eq(STRwarp, cp) && !checkwarp()) { 10659243Sobrien return (0); /* this builtin disabled */ 10759243Sobrien } 10859243Sobrien#endif /* WARP */ 10959243Sobrien /* 11059243Sobrien * Binary search Bp1 is the beginning of the current search range. Bp2 is 11159243Sobrien * one past the end. 11259243Sobrien */ 11359243Sobrien for (bp1 = bfunc, bp2 = bfunc + nbfunc; bp1 < bp2;) { 11459243Sobrien int i; 11559243Sobrien 11659243Sobrien bp = bp1 + ((bp2 - bp1) >> 1); 11759243Sobrien if ((i = ((char) *cp) - *bp->bname) == 0 && 11859243Sobrien (i = StrQcmp(cp, str2short(bp->bname))) == 0) 11959243Sobrien return bp; 12059243Sobrien if (i < 0) 12159243Sobrien bp2 = bp; 12259243Sobrien else 12359243Sobrien bp1 = bp + 1; 12459243Sobrien } 12569408Sache#ifdef WINNT_NATIVE 12659243Sobrien return nt_check_additional_builtins(cp); 12769408Sache#endif /*WINNT_NATIVE*/ 12859243Sobrien return (0); 12959243Sobrien} 13059243Sobrien 13159243Sobrienvoid 13259243Sobrienfunc(t, bp) 13359243Sobrien register struct command *t; 13459243Sobrien register struct biltins *bp; 13559243Sobrien{ 13659243Sobrien int i; 13759243Sobrien 13859243Sobrien xechoit(t->t_dcom); 13959243Sobrien setname(bp->bname); 14059243Sobrien i = blklen(t->t_dcom) - 1; 14159243Sobrien if (i < bp->minargs) 14259243Sobrien stderror(ERR_NAME | ERR_TOOFEW); 14359243Sobrien if (i > bp->maxargs) 14459243Sobrien stderror(ERR_NAME | ERR_TOOMANY); 14559243Sobrien (*bp->bfunct) (t->t_dcom, t); 14659243Sobrien} 14759243Sobrien 14859243Sobrien/*ARGSUSED*/ 14959243Sobrienvoid 15059243Sobriendoonintr(v, c) 15159243Sobrien Char **v; 15259243Sobrien struct command *c; 15359243Sobrien{ 15459243Sobrien register Char *cp; 15559243Sobrien register Char *vv = v[1]; 15659243Sobrien 15759243Sobrien USE(c); 15859243Sobrien if (parintr == SIG_IGN) 15959243Sobrien return; 16059243Sobrien if (setintr && intty) 16159243Sobrien stderror(ERR_NAME | ERR_TERMINAL); 16259243Sobrien cp = gointr; 16359243Sobrien gointr = 0; 16459243Sobrien xfree((ptr_t) cp); 16559243Sobrien if (vv == 0) { 16659243Sobrien#ifdef BSDSIGS 16759243Sobrien if (setintr) { 16859243Sobrien (void) sigblock(sigmask(SIGINT)); 16959243Sobrien (void) signal(SIGINT, pintr); 17059243Sobrien } 17159243Sobrien else 17259243Sobrien (void) signal(SIGINT, SIG_DFL); 17359243Sobrien#else /* !BSDSIGS */ 17459243Sobrien if (setintr) { 17559243Sobrien (void) sighold(SIGINT); 17659243Sobrien (void) sigset(SIGINT, pintr); 17759243Sobrien } 17859243Sobrien else 17959243Sobrien (void) sigset(SIGINT, SIG_DFL); 18059243Sobrien#endif /* BSDSIGS */ 18159243Sobrien gointr = 0; 18259243Sobrien } 18359243Sobrien else if (eq((vv = strip(vv)), STRminus)) { 18459243Sobrien#ifdef BSDSIGS 18559243Sobrien (void) signal(SIGINT, SIG_IGN); 18659243Sobrien#else /* !BSDSIGS */ 18759243Sobrien (void) sigset(SIGINT, SIG_IGN); 18859243Sobrien#endif /* BSDSIGS */ 18959243Sobrien gointr = Strsave(STRminus); 19059243Sobrien } 19159243Sobrien else { 19259243Sobrien gointr = Strsave(vv); 19359243Sobrien#ifdef BSDSIGS 19459243Sobrien (void) signal(SIGINT, pintr); 19559243Sobrien#else /* !BSDSIGS */ 19659243Sobrien (void) sigset(SIGINT, pintr); 19759243Sobrien#endif /* BSDSIGS */ 19859243Sobrien } 19959243Sobrien} 20059243Sobrien 20159243Sobrien/*ARGSUSED*/ 20259243Sobrienvoid 20359243Sobriendonohup(v, c) 20459243Sobrien Char **v; 20559243Sobrien struct command *c; 20659243Sobrien{ 20759243Sobrien USE(c); 20859243Sobrien USE(v); 20959243Sobrien if (intty) 21059243Sobrien stderror(ERR_NAME | ERR_TERMINAL); 21159243Sobrien if (setintr == 0) { 21259243Sobrien (void) signal(SIGHUP, SIG_IGN); 21359243Sobrien#ifdef CC 21459243Sobrien submit(getpid()); 21559243Sobrien#endif /* CC */ 21659243Sobrien } 21759243Sobrien} 21859243Sobrien 21959243Sobrien/*ARGSUSED*/ 22059243Sobrienvoid 22159243Sobriendohup(v, c) 22259243Sobrien Char **v; 22359243Sobrien struct command *c; 22459243Sobrien{ 22559243Sobrien USE(c); 22659243Sobrien USE(v); 22759243Sobrien if (intty) 22859243Sobrien stderror(ERR_NAME | ERR_TERMINAL); 22959243Sobrien if (setintr == 0) 23059243Sobrien (void) signal(SIGHUP, SIG_DFL); 23159243Sobrien} 23259243Sobrien 23359243Sobrien 23459243Sobrien/*ARGSUSED*/ 23559243Sobrienvoid 23659243Sobriendozip(v, c) 23759243Sobrien Char **v; 23859243Sobrien struct command *c; 23959243Sobrien{ 24059243Sobrien USE(c); 24159243Sobrien USE(v); 24259243Sobrien} 24359243Sobrien 24459243Sobrien/*ARGSUSED*/ 24559243Sobrienvoid 24659243Sobriendofiletest(v, c) 24759243Sobrien Char **v; 24859243Sobrien struct command *c; 24959243Sobrien{ 25059243Sobrien Char **fileptr, *ftest, *res; 25159243Sobrien 25259243Sobrien if (*(ftest = *++v) != '-') 25359243Sobrien stderror(ERR_NAME | ERR_FILEINQ); 25459243Sobrien ++v; 25559243Sobrien 25659243Sobrien gflag = 0; 25759243Sobrien tglob(v); 25859243Sobrien if (gflag) { 25959243Sobrien v = globall(v); 26059243Sobrien if (v == 0) 26159243Sobrien stderror(ERR_NAME | ERR_NOMATCH); 26259243Sobrien } 26359243Sobrien else 26459243Sobrien v = gargv = saveblk(v); 26559243Sobrien trim(v); 26659243Sobrien 26759243Sobrien while (*(fileptr = v++) != '\0') { 26859243Sobrien xprintf("%S", res = filetest(ftest, &fileptr, 0)); 26959243Sobrien xfree((ptr_t) res); 27059243Sobrien if (*v) 27159243Sobrien xprintf(" "); 27259243Sobrien } 27359243Sobrien xprintf("\n"); 27459243Sobrien 27559243Sobrien if (gargv) { 27659243Sobrien blkfree(gargv); 27759243Sobrien gargv = 0; 27859243Sobrien } 27959243Sobrien} 28059243Sobrien 28159243Sobrienvoid 28259243Sobrienprvars() 28359243Sobrien{ 28459243Sobrien plist(&shvhed, VAR_ALL); 28559243Sobrien} 28659243Sobrien 28759243Sobrien/*ARGSUSED*/ 28859243Sobrienvoid 28959243Sobriendoalias(v, c) 29059243Sobrien register Char **v; 29159243Sobrien struct command *c; 29259243Sobrien{ 29359243Sobrien register struct varent *vp; 29459243Sobrien register Char *p; 29559243Sobrien 29659243Sobrien USE(c); 29759243Sobrien v++; 29859243Sobrien p = *v++; 29959243Sobrien if (p == 0) 30059243Sobrien plist(&aliases, VAR_ALL); 30159243Sobrien else if (*v == 0) { 30259243Sobrien vp = adrof1(strip(p), &aliases); 303100616Smp if (vp && vp->vec) 30459243Sobrien blkpr(vp->vec), xputchar('\n'); 30559243Sobrien } 30659243Sobrien else { 30759243Sobrien if (eq(p, STRalias) || eq(p, STRunalias)) { 30859243Sobrien setname(short2str(p)); 30959243Sobrien stderror(ERR_NAME | ERR_DANGER); 31059243Sobrien } 31159243Sobrien set1(strip(p), saveblk(v), &aliases, VAR_READWRITE); 31259243Sobrien tw_cmd_free(); 31359243Sobrien } 31459243Sobrien} 31559243Sobrien 31659243Sobrien/*ARGSUSED*/ 31759243Sobrienvoid 31859243Sobrienunalias(v, c) 31959243Sobrien Char **v; 32059243Sobrien struct command *c; 32159243Sobrien{ 32259243Sobrien USE(c); 32359243Sobrien unset1(v, &aliases); 32459243Sobrien tw_cmd_free(); 32559243Sobrien} 32659243Sobrien 32759243Sobrien/*ARGSUSED*/ 32859243Sobrienvoid 32959243Sobriendologout(v, c) 33059243Sobrien Char **v; 33159243Sobrien struct command *c; 33259243Sobrien{ 33359243Sobrien USE(c); 33459243Sobrien USE(v); 33559243Sobrien islogin(); 33659243Sobrien goodbye(NULL, NULL); 33759243Sobrien} 33859243Sobrien 33959243Sobrien/*ARGSUSED*/ 34059243Sobrienvoid 34159243Sobriendologin(v, c) 34259243Sobrien Char **v; 34359243Sobrien struct command *c; 34459243Sobrien{ 34559243Sobrien USE(c); 34669408Sache#ifdef WINNT_NATIVE 34759243Sobrien USE(v); 34869408Sache#else /* !WINNT_NATIVE */ 34959243Sobrien islogin(); 35059243Sobrien rechist(NULL, adrof(STRsavehist) != NULL); 35159243Sobrien (void) signal(SIGTERM, parterm); 35259243Sobrien (void) execl(_PATH_BIN_LOGIN, "login", short2str(v[1]), NULL); 35359243Sobrien (void) execl(_PATH_USRBIN_LOGIN, "login", short2str(v[1]), NULL); 35459243Sobrien untty(); 35559243Sobrien xexit(1); 35669408Sache#endif /* !WINNT_NATIVE */ 35759243Sobrien} 35859243Sobrien 35959243Sobrien 36059243Sobrien#ifdef NEWGRP 36159243Sobrien/*ARGSUSED*/ 36259243Sobrienvoid 36359243Sobriendonewgrp(v, c) 36459243Sobrien Char **v; 36559243Sobrien struct command *c; 36659243Sobrien{ 36759243Sobrien char **p; 36859243Sobrien if (chkstop == 0 && setintr) 36959243Sobrien panystop(0); 37059243Sobrien (void) signal(SIGTERM, parterm); 37159243Sobrien p = short2blk(v); 37259243Sobrien /* 37359243Sobrien * From Beto Appleton (beto@aixwiz.austin.ibm.com) 37459243Sobrien * Newgrp can take 2 arguments... 37559243Sobrien */ 37659243Sobrien (void) execv(_PATH_BIN_NEWGRP, p); 37759243Sobrien (void) execv(_PATH_USRBIN_NEWGRP, p); 37859243Sobrien blkfree((Char **) p); 37959243Sobrien untty(); 38059243Sobrien xexit(1); 38159243Sobrien} 38259243Sobrien#endif /* NEWGRP */ 38359243Sobrien 38459243Sobrienstatic void 38559243Sobrienislogin() 38659243Sobrien{ 38759243Sobrien if (chkstop == 0 && setintr) 38859243Sobrien panystop(0); 38959243Sobrien if (loginsh) 39059243Sobrien return; 39159243Sobrien stderror(ERR_NOTLOGIN); 39259243Sobrien} 39359243Sobrien 39459243Sobrienvoid 39559243Sobriendoif(v, kp) 39659243Sobrien Char **v; 39759243Sobrien struct command *kp; 39859243Sobrien{ 39959243Sobrien register int i; 40059243Sobrien register Char **vv; 40159243Sobrien 40259243Sobrien v++; 40359243Sobrien i = expr(&v); 40459243Sobrien vv = v; 40559243Sobrien if (*vv == NULL) 40659243Sobrien stderror(ERR_NAME | ERR_EMPTYIF); 40759243Sobrien if (eq(*vv, STRthen)) { 40859243Sobrien if (*++vv) 40959243Sobrien stderror(ERR_NAME | ERR_IMPRTHEN); 41059243Sobrien setname(short2str(STRthen)); 41159243Sobrien /* 41259243Sobrien * If expression was zero, then scan to else , otherwise just fall into 41359243Sobrien * following code. 41459243Sobrien */ 41559243Sobrien if (!i) 41659243Sobrien search(TC_IF, 0, NULL); 41759243Sobrien return; 41859243Sobrien } 41959243Sobrien /* 42059243Sobrien * Simple command attached to this if. Left shift the node in this tree, 42159243Sobrien * munging it so we can reexecute it. 42259243Sobrien */ 42359243Sobrien if (i) { 42459243Sobrien lshift(kp->t_dcom, vv - kp->t_dcom); 42559243Sobrien reexecute(kp); 42659243Sobrien donefds(); 42759243Sobrien } 42859243Sobrien} 42959243Sobrien 43059243Sobrien/* 43159243Sobrien * Reexecute a command, being careful not 43259243Sobrien * to redo i/o redirection, which is already set up. 43359243Sobrien */ 43459243Sobrienvoid 43559243Sobrienreexecute(kp) 43659243Sobrien register struct command *kp; 43759243Sobrien{ 43859243Sobrien kp->t_dflg &= F_SAVE; 43959243Sobrien kp->t_dflg |= F_REPEAT; 44059243Sobrien /* 44159243Sobrien * If tty is still ours to arbitrate, arbitrate it; otherwise dont even set 44259243Sobrien * pgrp's as the jobs would then have no way to get the tty (we can't give 44359243Sobrien * it to them, and our parent wouldn't know their pgrp, etc. 44459243Sobrien */ 445100616Smp execute(kp, (tpgrp > 0 ? tpgrp : -1), NULL, NULL, TRUE); 44659243Sobrien} 44759243Sobrien 44859243Sobrien/*ARGSUSED*/ 44959243Sobrienvoid 45059243Sobriendoelse (v, c) 45159243Sobrien Char **v; 45259243Sobrien struct command *c; 45359243Sobrien{ 45459243Sobrien USE(c); 45559243Sobrien USE(v); 45659243Sobrien search(TC_ELSE, 0, NULL); 45759243Sobrien} 45859243Sobrien 45959243Sobrien/*ARGSUSED*/ 46059243Sobrienvoid 46159243Sobriendogoto(v, c) 46259243Sobrien Char **v; 46359243Sobrien struct command *c; 46459243Sobrien{ 46559243Sobrien Char *lp; 46659243Sobrien 46759243Sobrien USE(c); 46859243Sobrien gotolab(lp = globone(v[1], G_ERROR)); 46959243Sobrien xfree((ptr_t) lp); 47059243Sobrien} 47159243Sobrien 47259243Sobrienvoid 47359243Sobriengotolab(lab) 47459243Sobrien Char *lab; 47559243Sobrien{ 47659243Sobrien register struct whyle *wp; 47759243Sobrien /* 47859243Sobrien * While we still can, locate any unknown ends of existing loops. This 47959243Sobrien * obscure code is the WORST result of the fact that we don't really parse. 48059243Sobrien */ 48159243Sobrien zlast = TC_GOTO; 48259243Sobrien for (wp = whyles; wp; wp = wp->w_next) 48369408Sache if (wp->w_end.type == TCSH_F_SEEK && wp->w_end.f_seek == 0) { 48459243Sobrien search(TC_BREAK, 0, NULL); 48559243Sobrien btell(&wp->w_end); 48659243Sobrien } 48759243Sobrien else { 48859243Sobrien bseek(&wp->w_end); 48959243Sobrien } 49059243Sobrien search(TC_GOTO, 0, lab); 49159243Sobrien /* 49259243Sobrien * Eliminate loops which were exited. 49359243Sobrien */ 49459243Sobrien wfree(); 49559243Sobrien} 49659243Sobrien 49759243Sobrien/*ARGSUSED*/ 49859243Sobrienvoid 49959243Sobriendoswitch(v, c) 50059243Sobrien register Char **v; 50159243Sobrien struct command *c; 50259243Sobrien{ 50359243Sobrien register Char *cp, *lp; 50459243Sobrien 50559243Sobrien USE(c); 50659243Sobrien v++; 50759243Sobrien if (!*v || *(*v++) != '(') 50859243Sobrien stderror(ERR_SYNTAX); 50959243Sobrien cp = **v == ')' ? STRNULL : *v++; 51059243Sobrien if (*(*v++) != ')') 51159243Sobrien v--; 51259243Sobrien if (*v) 51359243Sobrien stderror(ERR_SYNTAX); 51459243Sobrien search(TC_SWITCH, 0, lp = globone(cp, G_ERROR)); 51559243Sobrien xfree((ptr_t) lp); 51659243Sobrien} 51759243Sobrien 51859243Sobrien/*ARGSUSED*/ 51959243Sobrienvoid 52059243Sobriendobreak(v, c) 52159243Sobrien Char **v; 52259243Sobrien struct command *c; 52359243Sobrien{ 52459243Sobrien USE(v); 52559243Sobrien USE(c); 52659243Sobrien if (whyles) 52759243Sobrien toend(); 52859243Sobrien else 52959243Sobrien stderror(ERR_NAME | ERR_NOTWHILE); 53059243Sobrien} 53159243Sobrien 53259243Sobrien/*ARGSUSED*/ 53359243Sobrienvoid 53459243Sobriendoexit(v, c) 53559243Sobrien Char **v; 53659243Sobrien struct command *c; 53759243Sobrien{ 53859243Sobrien USE(c); 53959243Sobrien 54059243Sobrien if (chkstop == 0 && (intty || intact) && evalvec == 0) 54159243Sobrien panystop(0); 54259243Sobrien /* 54359243Sobrien * Don't DEMAND parentheses here either. 54459243Sobrien */ 54559243Sobrien v++; 54659243Sobrien if (*v) { 54759243Sobrien set(STRstatus, putn(expr(&v)), VAR_READWRITE); 54859243Sobrien if (*v) 54959243Sobrien stderror(ERR_NAME | ERR_EXPRESSION); 55059243Sobrien } 55159243Sobrien btoeof(); 55259243Sobrien#if 0 55359243Sobrien if (intty) 55459243Sobrien#endif 55559243Sobrien /* Always close, why only on ttys? */ 55659243Sobrien (void) close(SHIN); 55759243Sobrien} 55859243Sobrien 55959243Sobrien/*ARGSUSED*/ 56059243Sobrienvoid 56159243Sobriendoforeach(v, c) 56259243Sobrien register Char **v; 56359243Sobrien struct command *c; 56459243Sobrien{ 56559243Sobrien register Char *cp, *sp; 56659243Sobrien register struct whyle *nwp; 56759243Sobrien 56859243Sobrien USE(c); 56959243Sobrien v++; 57059243Sobrien sp = cp = strip(*v); 57159243Sobrien if (!letter(*sp)) 57259243Sobrien stderror(ERR_NAME | ERR_VARBEGIN); 57359243Sobrien while (*cp && alnum(*cp)) 57459243Sobrien cp++; 57559243Sobrien if (*cp) 57659243Sobrien stderror(ERR_NAME | ERR_VARALNUM); 57759243Sobrien if ((cp - sp) > MAXVARLEN) 57859243Sobrien stderror(ERR_NAME | ERR_VARTOOLONG); 57959243Sobrien cp = *v++; 58059243Sobrien if (v[0][0] != '(' || v[blklen(v) - 1][0] != ')') 58159243Sobrien stderror(ERR_NAME | ERR_NOPAREN); 58259243Sobrien v++; 58359243Sobrien gflag = 0, tglob(v); 58459243Sobrien if (gflag) { 58559243Sobrien v = globall(v); 58659243Sobrien if (v == 0) 58759243Sobrien stderror(ERR_NAME | ERR_NOMATCH); 58859243Sobrien } 58959243Sobrien else { 59059243Sobrien v = gargv = saveblk(v); 59159243Sobrien trim(v); 59259243Sobrien } 59359243Sobrien nwp = (struct whyle *) xcalloc(1, sizeof *nwp); 59459243Sobrien nwp->w_fe = nwp->w_fe0 = v; 59559243Sobrien gargv = 0; 59659243Sobrien btell(&nwp->w_start); 59759243Sobrien nwp->w_fename = Strsave(cp); 59859243Sobrien nwp->w_next = whyles; 59969408Sache nwp->w_end.type = TCSH_F_SEEK; 60059243Sobrien whyles = nwp; 60159243Sobrien /* 60259243Sobrien * Pre-read the loop so as to be more comprehensible to a terminal user. 60359243Sobrien */ 60459243Sobrien zlast = TC_FOREACH; 60559243Sobrien if (intty) 60659243Sobrien preread(); 60759243Sobrien doagain(); 60859243Sobrien} 60959243Sobrien 61059243Sobrien/*ARGSUSED*/ 61159243Sobrienvoid 61259243Sobriendowhile(v, c) 61359243Sobrien Char **v; 61459243Sobrien struct command *c; 61559243Sobrien{ 61659243Sobrien register int status; 61759243Sobrien register bool again = whyles != 0 && 61859243Sobrien SEEKEQ(&whyles->w_start, &lineloc) && 61959243Sobrien whyles->w_fename == 0; 62059243Sobrien 62159243Sobrien USE(c); 62259243Sobrien v++; 62359243Sobrien /* 62459243Sobrien * Implement prereading here also, taking care not to evaluate the 62559243Sobrien * expression before the loop has been read up from a terminal. 62659243Sobrien */ 62759243Sobrien if (intty && !again) 62859243Sobrien status = !exp0(&v, 1); 62959243Sobrien else 63059243Sobrien status = !expr(&v); 63159243Sobrien if (*v) 63259243Sobrien stderror(ERR_NAME | ERR_EXPRESSION); 63359243Sobrien if (!again) { 63459243Sobrien register struct whyle *nwp = 63559243Sobrien (struct whyle *) xcalloc(1, sizeof(*nwp)); 63659243Sobrien 63759243Sobrien nwp->w_start = lineloc; 63869408Sache nwp->w_end.type = TCSH_F_SEEK; 63959243Sobrien nwp->w_end.f_seek = 0; 64059243Sobrien nwp->w_next = whyles; 64159243Sobrien whyles = nwp; 64259243Sobrien zlast = TC_WHILE; 64359243Sobrien if (intty) { 64459243Sobrien /* 64559243Sobrien * The tty preread 64659243Sobrien */ 64759243Sobrien preread(); 64859243Sobrien doagain(); 64959243Sobrien return; 65059243Sobrien } 65159243Sobrien } 65259243Sobrien if (status) 65359243Sobrien /* We ain't gonna loop no more, no more! */ 65459243Sobrien toend(); 65559243Sobrien} 65659243Sobrien 65759243Sobrienstatic void 65859243Sobrienpreread() 65959243Sobrien{ 66069408Sache whyles->w_end.type = TCSH_I_SEEK; 66159243Sobrien if (setintr) 66259243Sobrien#ifdef BSDSIGS 66359243Sobrien (void) sigsetmask(sigblock((sigmask_t) 0) & ~sigmask(SIGINT)); 66459243Sobrien#else /* !BSDSIGS */ 66559243Sobrien (void) sigrelse (SIGINT); 66659243Sobrien#endif /* BSDSIGS */ 66759243Sobrien search(TC_BREAK, 0, NULL); /* read the expression in */ 66859243Sobrien if (setintr) 66959243Sobrien#ifdef BSDSIGS 67059243Sobrien (void) sigblock(sigmask(SIGINT)); 67159243Sobrien#else /* !BSDSIGS */ 67259243Sobrien (void) sighold(SIGINT); 67359243Sobrien#endif /* BSDSIGS */ 67459243Sobrien btell(&whyles->w_end); 67559243Sobrien} 67659243Sobrien 67759243Sobrien/*ARGSUSED*/ 67859243Sobrienvoid 67959243Sobriendoend(v, c) 68059243Sobrien Char **v; 68159243Sobrien struct command *c; 68259243Sobrien{ 68359243Sobrien USE(v); 68459243Sobrien USE(c); 68559243Sobrien if (!whyles) 68659243Sobrien stderror(ERR_NAME | ERR_NOTWHILE); 68759243Sobrien btell(&whyles->w_end); 68859243Sobrien doagain(); 68959243Sobrien} 69059243Sobrien 69159243Sobrien/*ARGSUSED*/ 69259243Sobrienvoid 69359243Sobriendocontin(v, c) 69459243Sobrien Char **v; 69559243Sobrien struct command *c; 69659243Sobrien{ 69759243Sobrien USE(v); 69859243Sobrien USE(c); 69959243Sobrien if (!whyles) 70059243Sobrien stderror(ERR_NAME | ERR_NOTWHILE); 70159243Sobrien doagain(); 70259243Sobrien} 70359243Sobrien 70459243Sobrienstatic void 70559243Sobriendoagain() 70659243Sobrien{ 70759243Sobrien /* Repeating a while is simple */ 70859243Sobrien if (whyles->w_fename == 0) { 70959243Sobrien bseek(&whyles->w_start); 71059243Sobrien return; 71159243Sobrien } 71259243Sobrien /* 71359243Sobrien * The foreach variable list actually has a spurious word ")" at the end of 71459243Sobrien * the w_fe list. Thus we are at the of the list if one word beyond this 71559243Sobrien * is 0. 71659243Sobrien */ 71759243Sobrien if (!whyles->w_fe[1]) { 71859243Sobrien dobreak(NULL, NULL); 71959243Sobrien return; 72059243Sobrien } 72159243Sobrien set(whyles->w_fename, quote(Strsave(*whyles->w_fe++)), VAR_READWRITE); 72259243Sobrien bseek(&whyles->w_start); 72359243Sobrien} 72459243Sobrien 72559243Sobrienvoid 72659243Sobriendorepeat(v, kp) 72759243Sobrien Char **v; 72859243Sobrien struct command *kp; 72959243Sobrien{ 730100616Smp int i = 1; 73159243Sobrien 73259243Sobrien#ifdef BSDSIGS 73359243Sobrien register sigmask_t omask = 0; 73459243Sobrien#endif /* BSDSIGS */ 73559243Sobrien 736100616Smp do { 737100616Smp i *= getn(v[1]); 738100616Smp lshift(v, 2); 739100616Smp } while (v[0] != NULL && Strcmp(v[0], STRrepeat) == 0); 740100616Smp 74159243Sobrien if (setintr) 74259243Sobrien#ifdef BSDSIGS 74359243Sobrien omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT); 74459243Sobrien#else /* !BSDSIGS */ 74559243Sobrien (void) sighold(SIGINT); 74659243Sobrien#endif /* BSDSIGS */ 74759243Sobrien while (i > 0) { 74859243Sobrien if (setintr) 74959243Sobrien#ifdef BSDSIGS 75059243Sobrien (void) sigsetmask(omask); 75159243Sobrien#else /* !BSDSIGS */ 75259243Sobrien (void) sigrelse (SIGINT); 75359243Sobrien#endif /* BSDSIGS */ 75459243Sobrien reexecute(kp); 75559243Sobrien --i; 75659243Sobrien } 75759243Sobrien donefds(); 75859243Sobrien if (setintr) 75959243Sobrien#ifdef BSDSIGS 76059243Sobrien (void) sigsetmask(omask); 76159243Sobrien#else /* !BSDSIGS */ 76259243Sobrien (void) sigrelse (SIGINT); 76359243Sobrien#endif /* BSDSIGS */ 76459243Sobrien} 76559243Sobrien 76659243Sobrien/*ARGSUSED*/ 76759243Sobrienvoid 76859243Sobriendoswbrk(v, c) 76959243Sobrien Char **v; 77059243Sobrien struct command *c; 77159243Sobrien{ 77259243Sobrien USE(v); 77359243Sobrien USE(c); 77459243Sobrien search(TC_BRKSW, 0, NULL); 77559243Sobrien} 77659243Sobrien 77759243Sobrienint 77859243Sobriensrchx(cp) 77959243Sobrien Char *cp; 78059243Sobrien{ 78159243Sobrien struct srch *sp, *sp1, *sp2; 78259243Sobrien int i; 78359243Sobrien 78459243Sobrien /* 78559243Sobrien * Ignore keywords inside heredocs 78659243Sobrien */ 78759243Sobrien if (inheredoc) 78859243Sobrien return -1; 78959243Sobrien 79059243Sobrien /* 79159243Sobrien * Binary search Sp1 is the beginning of the current search range. Sp2 is 79259243Sobrien * one past the end. 79359243Sobrien */ 79459243Sobrien for (sp1 = srchn, sp2 = srchn + nsrchn; sp1 < sp2;) { 79559243Sobrien sp = sp1 + ((sp2 - sp1) >> 1); 79659243Sobrien if ((i = *cp - *sp->s_name) == 0 && 79759243Sobrien (i = Strcmp(cp, str2short(sp->s_name))) == 0) 79859243Sobrien return sp->s_value; 79959243Sobrien if (i < 0) 80059243Sobrien sp2 = sp; 80159243Sobrien else 80259243Sobrien sp1 = sp + 1; 80359243Sobrien } 80459243Sobrien return (-1); 80559243Sobrien} 80659243Sobrien 80759243Sobrienstatic char * 80859243Sobrienisrchx(n) 80959243Sobrien register int n; 81059243Sobrien{ 81159243Sobrien register struct srch *sp, *sp2; 81259243Sobrien 81359243Sobrien for (sp = srchn, sp2 = srchn + nsrchn; sp < sp2; sp++) 81459243Sobrien if (sp->s_value == n) 81559243Sobrien return (sp->s_name); 81659243Sobrien return (""); 81759243Sobrien} 81859243Sobrien 81959243Sobrien 82059243Sobrienstatic Char Stype; 82159243Sobrienstatic Char *Sgoal; 82259243Sobrien 82359243Sobrienstatic void 82459243Sobriensearch(type, level, goal) 82559243Sobrien int type; 82659243Sobrien register int level; 82759243Sobrien Char *goal; 82859243Sobrien{ 82959243Sobrien Char wordbuf[BUFSIZE]; 83059243Sobrien register Char *aword = wordbuf; 83159243Sobrien register Char *cp; 83259243Sobrien 83359243Sobrien Stype = (Char) type; 83459243Sobrien Sgoal = goal; 83559243Sobrien if (type == TC_GOTO) { 83659243Sobrien struct Ain a; 83769408Sache a.type = TCSH_F_SEEK; 83859243Sobrien a.f_seek = 0; 83959243Sobrien bseek(&a); 84059243Sobrien } 84159243Sobrien do { 84269408Sache if (intty && fseekp == feobp && aret == TCSH_F_SEEK) 84359243Sobrien printprompt(1, isrchx(type == TC_BREAK ? zlast : type)); 84459243Sobrien /* xprintf("? "), flush(); */ 84559243Sobrien aword[0] = 0; 84659243Sobrien (void) getword(aword); 84759243Sobrien switch (srchx(aword)) { 84859243Sobrien 84959243Sobrien case TC_ELSE: 85059243Sobrien if (level == 0 && type == TC_IF) 85159243Sobrien return; 85259243Sobrien break; 85359243Sobrien 85459243Sobrien case TC_IF: 85559243Sobrien while (getword(aword)) 85659243Sobrien continue; 85759243Sobrien if ((type == TC_IF || type == TC_ELSE) && 85859243Sobrien eq(aword, STRthen)) 85959243Sobrien level++; 86059243Sobrien break; 86159243Sobrien 86259243Sobrien case TC_ENDIF: 86359243Sobrien if (type == TC_IF || type == TC_ELSE) 86459243Sobrien level--; 86559243Sobrien break; 86659243Sobrien 86759243Sobrien case TC_FOREACH: 86859243Sobrien case TC_WHILE: 86959243Sobrien if (type == TC_BREAK) 87059243Sobrien level++; 87159243Sobrien break; 87259243Sobrien 87359243Sobrien case TC_END: 87459243Sobrien if (type == TC_BREAK) 87559243Sobrien level--; 87659243Sobrien break; 87759243Sobrien 87859243Sobrien case TC_SWITCH: 87959243Sobrien if (type == TC_SWITCH || type == TC_BRKSW) 88059243Sobrien level++; 88159243Sobrien break; 88259243Sobrien 88359243Sobrien case TC_ENDSW: 88459243Sobrien if (type == TC_SWITCH || type == TC_BRKSW) 88559243Sobrien level--; 88659243Sobrien break; 88759243Sobrien 88859243Sobrien case TC_LABEL: 88959243Sobrien if (type == TC_GOTO && getword(aword) && eq(aword, goal)) 89059243Sobrien level = -1; 89159243Sobrien break; 89259243Sobrien 89359243Sobrien default: 89459243Sobrien if (type != TC_GOTO && (type != TC_SWITCH || level != 0)) 89559243Sobrien break; 89659243Sobrien if (lastchr(aword) != ':') 89759243Sobrien break; 89859243Sobrien aword[Strlen(aword) - 1] = 0; 89959243Sobrien if ((type == TC_GOTO && eq(aword, goal)) || 90059243Sobrien (type == TC_SWITCH && eq(aword, STRdefault))) 90159243Sobrien level = -1; 90259243Sobrien break; 90359243Sobrien 90459243Sobrien case TC_CASE: 90559243Sobrien if (type != TC_SWITCH || level != 0) 90659243Sobrien break; 90759243Sobrien (void) getword(aword); 90859243Sobrien if (lastchr(aword) == ':') 90959243Sobrien aword[Strlen(aword) - 1] = 0; 91059243Sobrien cp = strip(Dfix1(aword)); 91159243Sobrien if (Gmatch(goal, cp)) 91259243Sobrien level = -1; 91359243Sobrien xfree((ptr_t) cp); 91459243Sobrien break; 91559243Sobrien 91659243Sobrien case TC_DEFAULT: 91759243Sobrien if (type == TC_SWITCH && level == 0) 91859243Sobrien level = -1; 91959243Sobrien break; 92059243Sobrien } 92159243Sobrien (void) getword(NULL); 92259243Sobrien } while (level >= 0); 92359243Sobrien} 92459243Sobrien 92559243Sobrienstatic int 92659243Sobriengetword(wp) 92759243Sobrien register Char *wp; 92859243Sobrien{ 92959243Sobrien int found = 0, first; 93059243Sobrien int c, d; 93159243Sobrien 93259243Sobrien c = readc(1); 93359243Sobrien d = 0; 93459243Sobrien do { 93559243Sobrien while (c == ' ' || c == '\t') 93659243Sobrien c = readc(1); 93759243Sobrien if (c == '#') 93859243Sobrien do 93959243Sobrien c = readc(1); 94059243Sobrien while (c >= 0 && c != '\n'); 94159243Sobrien if (c < 0) 94259243Sobrien goto past; 94359243Sobrien if (c == '\n') { 94459243Sobrien if (wp) 94559243Sobrien break; 94659243Sobrien return (0); 94759243Sobrien } 94859243Sobrien unreadc(c); 94959243Sobrien found = 1; 95059243Sobrien first = 1; 95159243Sobrien do { 95259243Sobrien c = readc(1); 95359243Sobrien if (c == '\\' && (c = readc(1)) == '\n') 95459243Sobrien c = ' '; 95559243Sobrien if (c == '\'' || c == '"') { 95659243Sobrien if (d == 0) 95759243Sobrien d = c; 95859243Sobrien else if (d == c) 95959243Sobrien d = 0; 96059243Sobrien } 96159243Sobrien if (c < 0) 96259243Sobrien goto past; 96359243Sobrien if (wp) { 96459243Sobrien *wp++ = (Char) c; 96559243Sobrien *wp = '\0'; 96659243Sobrien } 96759243Sobrien if (!first && !d && c == '(') { 96859243Sobrien if (wp) { 96959243Sobrien unreadc(c); 97059243Sobrien *--wp = '\0'; 97159243Sobrien return found; 97259243Sobrien } 97359243Sobrien else 97459243Sobrien break; 97559243Sobrien } 97659243Sobrien first = 0; 97759243Sobrien } while ((d || (c != ' ' && c != '\t')) && c != '\n'); 97859243Sobrien } while (wp == 0); 97959243Sobrien 98059243Sobrien unreadc(c); 98159243Sobrien if (found) 98259243Sobrien *--wp = '\0'; 98359243Sobrien 98459243Sobrien return (found); 98559243Sobrien 98659243Sobrienpast: 98759243Sobrien switch (Stype) { 98859243Sobrien 98959243Sobrien case TC_IF: 99059243Sobrien stderror(ERR_NAME | ERR_NOTFOUND, "then/endif"); 99159243Sobrien break; 99259243Sobrien 99359243Sobrien case TC_ELSE: 99459243Sobrien stderror(ERR_NAME | ERR_NOTFOUND, "endif"); 99559243Sobrien break; 99659243Sobrien 99759243Sobrien case TC_BRKSW: 99859243Sobrien case TC_SWITCH: 99959243Sobrien stderror(ERR_NAME | ERR_NOTFOUND, "endsw"); 100059243Sobrien break; 100159243Sobrien 100259243Sobrien case TC_BREAK: 100359243Sobrien stderror(ERR_NAME | ERR_NOTFOUND, "end"); 100459243Sobrien break; 100559243Sobrien 100659243Sobrien case TC_GOTO: 100759243Sobrien setname(short2str(Sgoal)); 100859243Sobrien stderror(ERR_NAME | ERR_NOTFOUND, "label"); 100959243Sobrien break; 101059243Sobrien 101159243Sobrien default: 101259243Sobrien break; 101359243Sobrien } 101459243Sobrien /* NOTREACHED */ 101559243Sobrien return (0); 101659243Sobrien} 101759243Sobrien 101859243Sobrienstatic void 101959243Sobrientoend() 102059243Sobrien{ 102169408Sache if (whyles->w_end.type == TCSH_F_SEEK && whyles->w_end.f_seek == 0) { 102259243Sobrien search(TC_BREAK, 0, NULL); 102359243Sobrien btell(&whyles->w_end); 102459243Sobrien whyles->w_end.f_seek--; 102559243Sobrien } 102659243Sobrien else { 102759243Sobrien bseek(&whyles->w_end); 102859243Sobrien } 102959243Sobrien wfree(); 103059243Sobrien} 103159243Sobrien 103259243Sobrienvoid 103359243Sobrienwfree() 103459243Sobrien{ 103559243Sobrien struct Ain o; 103659243Sobrien struct whyle *nwp; 103759243Sobrien#ifdef lint 103859243Sobrien nwp = NULL; /* sun lint is dumb! */ 103959243Sobrien#endif 104059243Sobrien 104159243Sobrien#ifdef FDEBUG 104259243Sobrien static char foo[] = "IAFE"; 104359243Sobrien#endif /* FDEBUG */ 104459243Sobrien 104559243Sobrien btell(&o); 104659243Sobrien 104759243Sobrien#ifdef FDEBUG 104859243Sobrien xprintf("o->type %c o->a_seek %d o->f_seek %d\n", 104959243Sobrien foo[o.type + 1], o.a_seek, o.f_seek); 105059243Sobrien#endif /* FDEBUG */ 105159243Sobrien 105259243Sobrien for (; whyles; whyles = nwp) { 105359243Sobrien register struct whyle *wp = whyles; 105459243Sobrien nwp = wp->w_next; 105559243Sobrien 105659243Sobrien#ifdef FDEBUG 105759243Sobrien xprintf("start->type %c start->a_seek %d start->f_seek %d\n", 105859243Sobrien foo[wp->w_start.type+1], 105959243Sobrien wp->w_start.a_seek, wp->w_start.f_seek); 106059243Sobrien xprintf("end->type %c end->a_seek %d end->f_seek %d\n", 106159243Sobrien foo[wp->w_end.type + 1], wp->w_end.a_seek, wp->w_end.f_seek); 106259243Sobrien#endif /* FDEBUG */ 106359243Sobrien 106459243Sobrien /* 106559243Sobrien * XXX: We free loops that have different seek types. 106659243Sobrien */ 106769408Sache if (wp->w_end.type != TCSH_I_SEEK && wp->w_start.type == wp->w_end.type && 106859243Sobrien wp->w_start.type == o.type) { 106969408Sache if (wp->w_end.type == TCSH_F_SEEK) { 107059243Sobrien if (o.f_seek >= wp->w_start.f_seek && 107159243Sobrien (wp->w_end.f_seek == 0 || o.f_seek < wp->w_end.f_seek)) 107259243Sobrien break; 107359243Sobrien } 107459243Sobrien else { 107559243Sobrien if (o.a_seek >= wp->w_start.a_seek && 107659243Sobrien (wp->w_end.a_seek == 0 || o.a_seek < wp->w_end.a_seek)) 107759243Sobrien break; 107859243Sobrien } 107959243Sobrien } 108059243Sobrien 108159243Sobrien if (wp->w_fe0) 108259243Sobrien blkfree(wp->w_fe0); 108359243Sobrien if (wp->w_fename) 108459243Sobrien xfree((ptr_t) wp->w_fename); 108559243Sobrien xfree((ptr_t) wp); 108659243Sobrien } 108759243Sobrien} 108859243Sobrien 108959243Sobrien/*ARGSUSED*/ 109059243Sobrienvoid 109159243Sobriendoecho(v, c) 109259243Sobrien Char **v; 109359243Sobrien struct command *c; 109459243Sobrien{ 109559243Sobrien USE(c); 109659243Sobrien xecho(' ', v); 109759243Sobrien} 109859243Sobrien 109959243Sobrien/*ARGSUSED*/ 110059243Sobrienvoid 110159243Sobriendoglob(v, c) 110259243Sobrien Char **v; 110359243Sobrien struct command *c; 110459243Sobrien{ 110559243Sobrien USE(c); 110659243Sobrien xecho(0, v); 110759243Sobrien flush(); 110859243Sobrien} 110959243Sobrien 111059243Sobrienstatic void 111159243Sobrienxecho(sep, v) 111259243Sobrien int sep; 111359243Sobrien register Char **v; 111459243Sobrien{ 111559243Sobrien register Char *cp; 111659243Sobrien int nonl = 0; 111759243Sobrien#ifdef ECHO_STYLE 111859243Sobrien int echo_style = ECHO_STYLE; 111959243Sobrien#else /* !ECHO_STYLE */ 112059243Sobrien# if SYSVREL > 0 112159243Sobrien int echo_style = SYSV_ECHO; 112259243Sobrien# else /* SYSVREL == 0 */ 112359243Sobrien int echo_style = BSD_ECHO; 112459243Sobrien# endif /* SYSVREL */ 112559243Sobrien#endif /* ECHO_STYLE */ 112659243Sobrien struct varent *vp; 112759243Sobrien 112859243Sobrien if ((vp = adrof(STRecho_style)) != NULL && vp->vec != NULL && 112959243Sobrien vp->vec[0] != NULL) { 113059243Sobrien if (Strcmp(vp->vec[0], STRbsd) == 0) 113159243Sobrien echo_style = BSD_ECHO; 113259243Sobrien else if (Strcmp(vp->vec[0], STRsysv) == 0) 113359243Sobrien echo_style = SYSV_ECHO; 113459243Sobrien else if (Strcmp(vp->vec[0], STRboth) == 0) 113559243Sobrien echo_style = BOTH_ECHO; 113659243Sobrien else if (Strcmp(vp->vec[0], STRnone) == 0) 113759243Sobrien echo_style = NONE_ECHO; 113859243Sobrien } 113959243Sobrien 114059243Sobrien if (setintr) 114159243Sobrien#ifdef BSDSIGS 114259243Sobrien (void) sigsetmask(sigblock((sigmask_t) 0) & ~sigmask(SIGINT)); 114359243Sobrien#else /* !BSDSIGS */ 114459243Sobrien (void) sigrelse (SIGINT); 114559243Sobrien#endif /* BSDSIGS */ 114659243Sobrien v++; 114759243Sobrien if (*v == 0) 114883098Smp goto done; 114959243Sobrien gflag = 0, tglob(v); 115059243Sobrien if (gflag) { 115159243Sobrien v = globall(v); 115259243Sobrien if (v == 0) 115359243Sobrien stderror(ERR_NAME | ERR_NOMATCH); 115459243Sobrien } 115559243Sobrien else { 115659243Sobrien v = gargv = saveblk(v); 115759243Sobrien trim(v); 115859243Sobrien } 115959243Sobrien 116059243Sobrien if ((echo_style & BSD_ECHO) != 0 && sep == ' ' && *v && eq(*v, STRmn)) 116159243Sobrien nonl++, v++; 116259243Sobrien 116359243Sobrien while ((cp = *v++) != 0) { 116459243Sobrien register int c; 116559243Sobrien 116659243Sobrien while ((c = *cp++) != 0) { 116759243Sobrien if ((echo_style & SYSV_ECHO) != 0 && c == '\\') { 116859243Sobrien switch (c = *cp++) { 116959243Sobrien case 'a': 117059243Sobrien c = '\a'; 117159243Sobrien break; 117259243Sobrien case 'b': 117359243Sobrien c = '\b'; 117459243Sobrien break; 117559243Sobrien case 'c': 117659243Sobrien nonl = 1; 117759243Sobrien goto done; 117859243Sobrien case 'e': 117959243Sobrien#if 0 /* Windows does not understand \e */ 118059243Sobrien c = '\e'; 118159243Sobrien#else 118259243Sobrien c = '\033'; 118359243Sobrien#endif 118459243Sobrien break; 118559243Sobrien case 'f': 118659243Sobrien c = '\f'; 118759243Sobrien break; 118859243Sobrien case 'n': 118959243Sobrien c = '\n'; 119059243Sobrien break; 119159243Sobrien case 'r': 119259243Sobrien c = '\r'; 119359243Sobrien break; 119459243Sobrien case 't': 119559243Sobrien c = '\t'; 119659243Sobrien break; 119759243Sobrien case 'v': 119859243Sobrien c = '\v'; 119959243Sobrien break; 120059243Sobrien case '\\': 120159243Sobrien c = '\\'; 120259243Sobrien break; 120359243Sobrien case '0': 120459243Sobrien c = 0; 120559243Sobrien if (*cp >= '0' && *cp < '8') 120659243Sobrien c = c * 8 + *cp++ - '0'; 120759243Sobrien if (*cp >= '0' && *cp < '8') 120859243Sobrien c = c * 8 + *cp++ - '0'; 120959243Sobrien if (*cp >= '0' && *cp < '8') 121059243Sobrien c = c * 8 + *cp++ - '0'; 121159243Sobrien break; 121259243Sobrien case '\0': 121359243Sobrien c = '\\'; 121459243Sobrien cp--; 121559243Sobrien break; 121659243Sobrien default: 121759243Sobrien xputchar('\\' | QUOTE); 121859243Sobrien break; 121959243Sobrien } 122059243Sobrien } 122159243Sobrien xputchar(c | QUOTE); 122259243Sobrien 122359243Sobrien } 122459243Sobrien if (*v) 122559243Sobrien xputchar(sep | QUOTE); 122659243Sobrien } 122759243Sobriendone: 122859243Sobrien if (sep && nonl == 0) 122959243Sobrien xputchar('\n'); 123059243Sobrien else 123159243Sobrien flush(); 123259243Sobrien if (setintr) 123359243Sobrien#ifdef BSDSIGS 123459243Sobrien (void) sigblock(sigmask(SIGINT)); 123559243Sobrien#else /* !BSDSIGS */ 123659243Sobrien (void) sighold(SIGINT); 123759243Sobrien#endif /* BSDSIGS */ 123859243Sobrien if (gargv) 123959243Sobrien blkfree(gargv), gargv = 0; 124059243Sobrien} 124159243Sobrien 124259243Sobrien/* check whether an environment variable should invoke 'set_locale()' */ 124359243Sobrienstatic bool 124459243Sobrienislocale_var(var) 124559243Sobrien Char *var; 124659243Sobrien{ 124759243Sobrien static Char *locale_vars[] = { 124859243Sobrien STRLANG, STRLC_CTYPE, STRLC_NUMERIC, STRLC_TIME, 124959243Sobrien STRLC_COLLATE, STRLC_MESSAGES, STRLC_MONETARY, 0 125059243Sobrien }; 125159243Sobrien register Char **v; 125259243Sobrien 125359243Sobrien for (v = locale_vars; *v; ++v) 125459243Sobrien if (eq(var, *v)) 125559243Sobrien return 1; 125659243Sobrien return 0; 125759243Sobrien} 125859243Sobrien 125959243Sobrien/*ARGSUSED*/ 126059243Sobrienvoid 126159243Sobriendoprintenv(v, c) 126259243Sobrien register Char **v; 126359243Sobrien struct command *c; 126459243Sobrien{ 126559243Sobrien Char *e; 126659243Sobrien extern bool output_raw; 126759243Sobrien extern bool xlate_cr; 126859243Sobrien 126959243Sobrien USE(c); 127059243Sobrien if (setintr) 127159243Sobrien#ifdef BSDSIGS 127259243Sobrien (void) sigsetmask(sigblock((sigmask_t) 0) & ~sigmask(SIGINT)); 127359243Sobrien#else /* !BSDSIGS */ 127459243Sobrien (void) sigrelse (SIGINT); 127559243Sobrien#endif /* BSDSIGS */ 127659243Sobrien 127759243Sobrien v++; 127859243Sobrien if (*v == 0) { 127959243Sobrien register Char **ep; 128059243Sobrien 128159243Sobrien xlate_cr = 1; 128259243Sobrien for (ep = STR_environ; *ep; ep++) 128359243Sobrien xprintf("%S\n", *ep); 128459243Sobrien xlate_cr = 0; 128559243Sobrien } 128659243Sobrien else if ((e = tgetenv(*v)) != NULL) { 128759243Sobrien output_raw = 1; 128859243Sobrien xprintf("%S\n", e); 128959243Sobrien output_raw = 0; 129059243Sobrien } 129159243Sobrien else 129259243Sobrien set(STRstatus, Strsave(STR1), VAR_READWRITE); 129359243Sobrien} 129459243Sobrien 129559243Sobrien/* from "Karl Berry." <karl%mote.umb.edu@relay.cs.net> -- for NeXT things 129659243Sobrien (and anything else with a modern compiler) */ 129759243Sobrien 129859243Sobrien/*ARGSUSED*/ 129959243Sobrienvoid 130059243Sobriendosetenv(v, c) 130159243Sobrien register Char **v; 130259243Sobrien struct command *c; 130359243Sobrien{ 130459243Sobrien Char *vp, *lp; 130559243Sobrien 130659243Sobrien USE(c); 130759243Sobrien if (*++v == 0) { 130859243Sobrien doprintenv(--v, 0); 130959243Sobrien return; 131059243Sobrien } 131159243Sobrien 131259243Sobrien vp = *v++; 131359243Sobrien 1314100616Smp lp = vp; 1315100616Smp if (!letter(*lp)) 1316100616Smp stderror(ERR_NAME | ERR_VARBEGIN); 1317100616Smp 1318100616Smp for (; alnum(*lp); lp++) 1319100616Smp continue; 1320100616Smp 1321100616Smp if (*lp != '\0') 1322100616Smp stderror(ERR_NAME | ERR_SYNTAX); 1323100616Smp 132459243Sobrien if ((lp = *v++) == 0) 132559243Sobrien lp = STRNULL; 132659243Sobrien 132759243Sobrien tsetenv(vp, lp = globone(lp, G_APPEND)); 132859243Sobrien if (eq(vp, STRKPATH)) { 132959243Sobrien importpath(lp); 133059243Sobrien dohash(NULL, NULL); 133159243Sobrien xfree((ptr_t) lp); 133259243Sobrien return; 133359243Sobrien } 133459243Sobrien 133559243Sobrien#ifdef apollo 133659243Sobrien if (eq(vp, STRSYSTYPE)) { 133759243Sobrien dohash(NULL, NULL); 133859243Sobrien xfree((ptr_t) lp); 133959243Sobrien return; 134059243Sobrien } 134159243Sobrien#endif /* apollo */ 134259243Sobrien 134359243Sobrien /* dspkanji/dspmbyte autosetting */ 134459243Sobrien /* PATCH IDEA FROM Issei.Suzuki VERY THANKS */ 134559243Sobrien#if defined(DSPMBYTE) 134659243Sobrien if(eq(vp, STRLANG) && !adrof(CHECK_MBYTEVAR)) { 134759243Sobrien autoset_dspmbyte(lp); 134859243Sobrien } 134959243Sobrien#endif 135059243Sobrien 135159243Sobrien if (islocale_var(vp)) { 135259243Sobrien#ifdef NLS 135359243Sobrien int k; 135459243Sobrien 135559243Sobrien# ifdef SETLOCALEBUG 135659243Sobrien dont_free = 1; 135759243Sobrien# endif /* SETLOCALEBUG */ 135859243Sobrien (void) setlocale(LC_ALL, ""); 135959243Sobrien# ifdef LC_COLLATE 136059243Sobrien (void) setlocale(LC_COLLATE, ""); 136159243Sobrien# endif 136259243Sobrien# ifdef NLS_CATALOGS 136359243Sobrien# ifdef LC_MESSAGES 136459243Sobrien (void) setlocale(LC_MESSAGES, ""); 136559243Sobrien# endif /* LC_MESSAGES */ 136659243Sobrien (void) catclose(catd); 136759243Sobrien nlsinit(); 136859243Sobrien# endif /* NLS_CATALOGS */ 136959243Sobrien# ifdef LC_CTYPE 137059243Sobrien (void) setlocale(LC_CTYPE, ""); /* for iscntrl */ 137159243Sobrien# endif /* LC_CTYPE */ 137259243Sobrien# ifdef SETLOCALEBUG 137359243Sobrien dont_free = 0; 137459243Sobrien# endif /* SETLOCALEBUG */ 137559243Sobrien# ifdef STRCOLLBUG 137659243Sobrien fix_strcoll_bug(); 137759243Sobrien# endif /* STRCOLLBUG */ 137859243Sobrien tw_cmd_free(); /* since the collation sequence has changed */ 137959243Sobrien for (k = 0200; k <= 0377 && !Isprint(k); k++) 138059243Sobrien continue; 138159243Sobrien AsciiOnly = k > 0377; 138259243Sobrien#else /* !NLS */ 138359243Sobrien AsciiOnly = 0; 138459243Sobrien#endif /* NLS */ 138559243Sobrien NLSMapsAreInited = 0; 138659243Sobrien ed_Init(); 138759243Sobrien if (MapsAreInited && !NLSMapsAreInited) 138859243Sobrien ed_InitNLSMaps(); 138959243Sobrien xfree((ptr_t) lp); 139059243Sobrien return; 139159243Sobrien } 139259243Sobrien 1393100616Smp#ifdef NLS_CATALOGS 1394100616Smp if (eq(vp, STRNLSPATH)) { 1395100616Smp (void) catclose(catd); 1396100616Smp nlsinit(); 1397100616Smp } 1398100616Smp#endif 1399100616Smp 140059243Sobrien if (eq(vp, STRNOREBIND)) { 140159243Sobrien NoNLSRebind = 1; 140259243Sobrien MapsAreInited = 0; 140359243Sobrien NLSMapsAreInited = 0; 140459243Sobrien ed_InitMaps(); 140559243Sobrien xfree((ptr_t) lp); 140659243Sobrien return; 140759243Sobrien } 140869408Sache#ifdef WINNT_NATIVE 140959243Sobrien if (eq(vp, STRtcshlang)) { 141059243Sobrien nlsinit(); 141159243Sobrien xfree((ptr_t) lp); 141259243Sobrien return; 141359243Sobrien } 141469408Sache#endif /* WINNT_NATIVE */ 141559243Sobrien if (eq(vp, STRKTERM)) { 141659243Sobrien char *t; 141759243Sobrien set(STRterm, quote(lp), VAR_READWRITE); /* lp memory used here */ 141859243Sobrien t = short2str(lp); 141959243Sobrien if (noediting && strcmp(t, "unknown") != 0 && strcmp(t,"dumb") != 0) { 142059243Sobrien editing = 1; 142159243Sobrien noediting = 0; 142259243Sobrien set(STRedit, Strsave(STRNULL), VAR_READWRITE); 142359243Sobrien } 142459243Sobrien GotTermCaps = 0; 142559243Sobrien ed_Init(); 142659243Sobrien return; 142759243Sobrien } 142859243Sobrien 142959243Sobrien if (eq(vp, STRKHOME)) { 143059243Sobrien /* 143159243Sobrien * convert to canonical pathname (possibly resolving symlinks) 143259243Sobrien */ 143359243Sobrien lp = dcanon(lp, lp); 143459243Sobrien set(STRhome, quote(lp), VAR_READWRITE); /* cp memory used here */ 143559243Sobrien 143659243Sobrien /* fix directory stack for new tilde home */ 143759243Sobrien dtilde(); 143859243Sobrien return; 143959243Sobrien } 144059243Sobrien 144159243Sobrien if (eq(vp, STRKSHLVL)) { 144259243Sobrien /* lp memory used here */ 144359243Sobrien set(STRshlvl, quote(lp), VAR_READWRITE); 144459243Sobrien return; 144559243Sobrien } 144659243Sobrien 144759243Sobrien if (eq(vp, STRKUSER)) { 144859243Sobrien set(STRuser, quote(lp), VAR_READWRITE); /* lp memory used here */ 144959243Sobrien return; 145059243Sobrien } 145159243Sobrien 145259243Sobrien if (eq(vp, STRKGROUP)) { 145359243Sobrien set(STRgroup, quote(lp), VAR_READWRITE); /* lp memory used here */ 145459243Sobrien return; 145559243Sobrien } 145659243Sobrien 145759243Sobrien#ifdef COLOR_LS_F 145859243Sobrien if (eq(vp, STRLS_COLORS)) { 145959243Sobrien parseLS_COLORS(lp); 146059243Sobrien return; 146159243Sobrien } 146259243Sobrien#endif /* COLOR_LS_F */ 146359243Sobrien 146459243Sobrien#ifdef SIG_WINDOW 146559243Sobrien /* 146659243Sobrien * Load/Update $LINES $COLUMNS 146759243Sobrien */ 146859243Sobrien if ((eq(lp, STRNULL) && (eq(vp, STRLINES) || eq(vp, STRCOLUMNS))) || 146959243Sobrien eq(vp, STRTERMCAP)) { 147059243Sobrien xfree((ptr_t) lp); 147159243Sobrien check_window_size(1); 147259243Sobrien return; 147359243Sobrien } 147459243Sobrien 147559243Sobrien /* 147659243Sobrien * Change the size to the one directed by $LINES and $COLUMNS 147759243Sobrien */ 147859243Sobrien if (eq(vp, STRLINES) || eq(vp, STRCOLUMNS)) { 147959243Sobrien#if 0 148059243Sobrien GotTermCaps = 0; 148159243Sobrien#endif 148259243Sobrien xfree((ptr_t) lp); 148359243Sobrien ed_Init(); 148459243Sobrien return; 148559243Sobrien } 148659243Sobrien#endif /* SIG_WINDOW */ 148759243Sobrien xfree((ptr_t) lp); 148859243Sobrien} 148959243Sobrien 149059243Sobrien/*ARGSUSED*/ 149159243Sobrienvoid 149259243Sobriendounsetenv(v, c) 149359243Sobrien register Char **v; 149459243Sobrien struct command *c; 149559243Sobrien{ 149659243Sobrien Char **ep, *p, *n; 149759243Sobrien int i, maxi; 149859243Sobrien static Char *name = NULL; 149959243Sobrien 150059243Sobrien USE(c); 150159243Sobrien if (name) 150259243Sobrien xfree((ptr_t) name); 150359243Sobrien /* 150459243Sobrien * Find the longest environment variable 150559243Sobrien */ 150659243Sobrien for (maxi = 0, ep = STR_environ; *ep; ep++) { 150759243Sobrien for (i = 0, p = *ep; *p && *p != '='; p++, i++) 150859243Sobrien continue; 150959243Sobrien if (i > maxi) 151059243Sobrien maxi = i; 151159243Sobrien } 151259243Sobrien 151359243Sobrien name = (Char *) xmalloc((size_t) ((maxi + 1) * sizeof(Char))); 151459243Sobrien 151559243Sobrien while (++v && *v) 151659243Sobrien for (maxi = 1; maxi;) 151759243Sobrien for (maxi = 0, ep = STR_environ; *ep; ep++) { 151859243Sobrien for (n = name, p = *ep; *p && *p != '='; *n++ = *p++) 151959243Sobrien continue; 152059243Sobrien *n = '\0'; 152159243Sobrien if (!Gmatch(name, *v)) 152259243Sobrien continue; 152359243Sobrien maxi = 1; 152459243Sobrien 152559243Sobrien /* Unset the name. This wasn't being done until 152659243Sobrien * later but most of the stuff following won't 152759243Sobrien * work (particularly the setlocale() and getenv() 152859243Sobrien * stuff) as intended until the name is actually 152959243Sobrien * removed. (sg) 153059243Sobrien */ 153159243Sobrien Unsetenv(name); 153259243Sobrien 153359243Sobrien if (eq(name, STRNOREBIND)) { 153459243Sobrien NoNLSRebind = 0; 153559243Sobrien MapsAreInited = 0; 153659243Sobrien NLSMapsAreInited = 0; 153759243Sobrien ed_InitMaps(); 153859243Sobrien } 153959243Sobrien#ifdef apollo 154059243Sobrien else if (eq(name, STRSYSTYPE)) 154159243Sobrien dohash(NULL, NULL); 154259243Sobrien#endif /* apollo */ 154359243Sobrien else if (islocale_var(name)) { 154459243Sobrien#ifdef NLS 154559243Sobrien int k; 154659243Sobrien 154759243Sobrien# ifdef SETLOCALEBUG 154859243Sobrien dont_free = 1; 154959243Sobrien# endif /* SETLOCALEBUG */ 155059243Sobrien (void) setlocale(LC_ALL, ""); 155159243Sobrien# ifdef LC_COLLATE 155259243Sobrien (void) setlocale(LC_COLLATE, ""); 155359243Sobrien# endif 155459243Sobrien# ifdef NLS_CATALOGS 155559243Sobrien# ifdef LC_MESSAGES 155659243Sobrien (void) setlocale(LC_MESSAGES, ""); 155759243Sobrien# endif /* LC_MESSAGES */ 155859243Sobrien (void) catclose(catd); 155959243Sobrien nlsinit(); 156059243Sobrien# endif /* NLS_CATALOGS */ 156159243Sobrien# ifdef LC_CTYPE 156259243Sobrien (void) setlocale(LC_CTYPE, ""); /* for iscntrl */ 156359243Sobrien# endif /* LC_CTYPE */ 156459243Sobrien# ifdef SETLOCALEBUG 156559243Sobrien dont_free = 0; 156659243Sobrien# endif /* SETLOCALEBUG */ 156759243Sobrien# ifdef STRCOLLBUG 156859243Sobrien fix_strcoll_bug(); 156959243Sobrien# endif /* STRCOLLBUG */ 157059243Sobrien tw_cmd_free();/* since the collation sequence has changed */ 157159243Sobrien for (k = 0200; k <= 0377 && !Isprint(k); k++) 157259243Sobrien continue; 157359243Sobrien AsciiOnly = k > 0377; 157459243Sobrien#else /* !NLS */ 157559243Sobrien AsciiOnly = getenv("LANG") == NULL && 157659243Sobrien getenv("LC_CTYPE") == NULL; 157759243Sobrien#endif /* NLS */ 157859243Sobrien NLSMapsAreInited = 0; 157959243Sobrien ed_Init(); 158059243Sobrien if (MapsAreInited && !NLSMapsAreInited) 158159243Sobrien ed_InitNLSMaps(); 158259243Sobrien 158359243Sobrien } 158469408Sache#ifdef WINNT_NATIVE 158559243Sobrien else if (eq(name,(STRtcshlang))) { 158659243Sobrien nls_dll_unload(); 158759243Sobrien nlsinit(); 158859243Sobrien } 158969408Sache#endif /* WINNT_NATIVE */ 159059243Sobrien#ifdef COLOR_LS_F 159159243Sobrien else if (eq(name, STRLS_COLORS)) 159259243Sobrien parseLS_COLORS(n); 159359243Sobrien#endif /* COLOR_LS_F */ 1594100616Smp#ifdef NLS_CATALOGS 1595100616Smp else if (eq(name, STRNLSPATH)) { 1596100616Smp (void) catclose(catd); 1597100616Smp nlsinit(); 1598100616Smp } 1599100616Smp#endif 160059243Sobrien /* 160159243Sobrien * start again cause the environment changes 160259243Sobrien */ 160359243Sobrien break; 160459243Sobrien } 160559243Sobrien xfree((ptr_t) name); name = NULL; 160659243Sobrien} 160759243Sobrien 160859243Sobrienvoid 160959243Sobrientsetenv(name, val) 161059243Sobrien Char *name, *val; 161159243Sobrien{ 161259243Sobrien#ifdef SETENV_IN_LIB 161359243Sobrien/* 161459243Sobrien * XXX: This does not work right, since tcsh cannot track changes to 161559243Sobrien * the environment this way. (the builtin setenv without arguments does 161659243Sobrien * not print the right stuff neither does unsetenv). This was for Mach, 161759243Sobrien * it is not needed anymore. 161859243Sobrien */ 161959243Sobrien#undef setenv 162059243Sobrien char nameBuf[BUFSIZE]; 162159243Sobrien char *cname = short2str(name); 162259243Sobrien 162359243Sobrien if (cname == NULL) 162459243Sobrien return; 162559243Sobrien (void) strcpy(nameBuf, cname); 162659243Sobrien setenv(nameBuf, short2str(val), 1); 162759243Sobrien#else /* !SETENV_IN_LIB */ 162859243Sobrien register Char **ep = STR_environ; 162959243Sobrien register Char *cp, *dp; 163059243Sobrien Char *blk[2]; 163159243Sobrien Char **oep = ep; 163259243Sobrien 163369408Sache#ifdef WINNT_NATIVE 163459243Sobrien nt_set_env(name,val); 163569408Sache#endif /* WINNT_NATIVE */ 163659243Sobrien for (; *ep; ep++) { 163769408Sache#ifdef WINNT_NATIVE 163859243Sobrien for (cp = name, dp = *ep; *cp && Tolower(*cp & TRIM) == Tolower(*dp); 163959243Sobrien cp++, dp++) 164059243Sobrien#else 164159243Sobrien for (cp = name, dp = *ep; *cp && (*cp & TRIM) == *dp; cp++, dp++) 164269408Sache#endif /* WINNT_NATIVE */ 164359243Sobrien continue; 164459243Sobrien if (*cp != 0 || *dp != '=') 164559243Sobrien continue; 164659243Sobrien cp = Strspl(STRequal, val); 164759243Sobrien xfree((ptr_t) * ep); 164859243Sobrien *ep = strip(Strspl(name, cp)); 164959243Sobrien xfree((ptr_t) cp); 165059243Sobrien blkfree((Char **) environ); 165159243Sobrien environ = short2blk(STR_environ); 165259243Sobrien return; 165359243Sobrien } 165459243Sobrien cp = Strspl(name, STRequal); 165559243Sobrien blk[0] = strip(Strspl(cp, val)); 165659243Sobrien xfree((ptr_t) cp); 165759243Sobrien blk[1] = 0; 165859243Sobrien STR_environ = blkspl(STR_environ, blk); 165959243Sobrien blkfree((Char **) environ); 166059243Sobrien environ = short2blk(STR_environ); 166159243Sobrien xfree((ptr_t) oep); 166259243Sobrien#endif /* SETENV_IN_LIB */ 166359243Sobrien} 166459243Sobrien 166559243Sobrienvoid 166659243SobrienUnsetenv(name) 166759243Sobrien Char *name; 166859243Sobrien{ 166959243Sobrien register Char **ep = STR_environ; 167059243Sobrien register Char *cp, *dp; 167159243Sobrien Char **oep = ep; 167259243Sobrien 167369408Sache#ifdef WINNT_NATIVE 167459243Sobrien nt_set_env(name,NULL); 167569408Sache#endif /*WINNT_NATIVE */ 167659243Sobrien for (; *ep; ep++) { 167759243Sobrien for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++) 167859243Sobrien continue; 167959243Sobrien if (*cp != 0 || *dp != '=') 168059243Sobrien continue; 168159243Sobrien cp = *ep; 168259243Sobrien *ep = 0; 168359243Sobrien STR_environ = blkspl(STR_environ, ep + 1); 168459243Sobrien blkfree((Char **) environ); 168559243Sobrien environ = short2blk(STR_environ); 168659243Sobrien *ep = cp; 168759243Sobrien xfree((ptr_t) cp); 168859243Sobrien xfree((ptr_t) oep); 168959243Sobrien return; 169059243Sobrien } 169159243Sobrien} 169259243Sobrien 169359243Sobrien/*ARGSUSED*/ 169459243Sobrienvoid 169559243Sobriendoumask(v, c) 169659243Sobrien register Char **v; 169759243Sobrien struct command *c; 169859243Sobrien{ 169959243Sobrien register Char *cp = v[1]; 170059243Sobrien register int i; 170159243Sobrien 170259243Sobrien USE(c); 170359243Sobrien if (cp == 0) { 170459415Sobrien i = (int)umask(0); 170559243Sobrien (void) umask(i); 170659243Sobrien xprintf("%o\n", i); 170759243Sobrien return; 170859243Sobrien } 170959243Sobrien i = 0; 171059243Sobrien while (Isdigit(*cp) && *cp != '8' && *cp != '9') 171159243Sobrien i = i * 8 + *cp++ - '0'; 171259243Sobrien if (*cp || i < 0 || i > 0777) 171359243Sobrien stderror(ERR_NAME | ERR_MASK); 171459243Sobrien (void) umask(i); 171559243Sobrien} 171659243Sobrien 171759243Sobrien#ifndef HAVENOLIMIT 171859243Sobrien# ifndef BSDLIMIT 171959243Sobrien typedef long RLIM_TYPE; 172059243Sobrien# ifndef RLIM_INFINITY 172159243Sobrien# if !defined(_MINIX) && !defined(__clipper__) && !defined(_CRAY) 172259243Sobrien extern RLIM_TYPE ulimit(); 172359243Sobrien# endif /* ! _MINIX && !__clipper__ */ 172459243Sobrien# define RLIM_INFINITY 0x003fffff 172559243Sobrien# define RLIMIT_FSIZE 1 172659243Sobrien# endif /* RLIM_INFINITY */ 172759243Sobrien# ifdef aiws 172859243Sobrien# define toset(a) (((a) == 3) ? 1004 : (a) + 1) 172959243Sobrien# define RLIMIT_DATA 3 173059243Sobrien# define RLIMIT_STACK 1005 173159243Sobrien# else /* aiws */ 173259243Sobrien# define toset(a) ((a) + 1) 173359243Sobrien# endif /* aiws */ 173459243Sobrien# else /* BSDLIMIT */ 1735100616Smp# if (defined(BSD4_4) || defined(__linux__)) && !defined(__386BSD__) 1736100616Smp typedef rlim_t RLIM_TYPE; 173759243Sobrien# else 173859243Sobrien# if defined(SOLARIS2) || (defined(sgi) && SYSVREL > 3) 173959243Sobrien typedef rlim_t RLIM_TYPE; 174059243Sobrien# else 174159243Sobrien# if defined(_SX) 174259243Sobrien typedef long long RLIM_TYPE; 1743100616Smp# else /* !_SX */ 174459243Sobrien typedef unsigned long RLIM_TYPE; 174559243Sobrien# endif /* _SX */ 174659243Sobrien# endif /* SOLARIS2 || (sgi && SYSVREL > 3) */ 174759243Sobrien# endif /* BSD4_4 && !__386BSD__ */ 174859243Sobrien# endif /* BSDLIMIT */ 174959243Sobrien 175059243Sobrien# if (HPUXVERSION > 700) && defined(BSDLIMIT) 175159243Sobrien/* Yes hpux8.0 has limits but <sys/resource.h> does not make them public */ 175259243Sobrien/* Yes, we could have defined _KERNEL, and -I/etc/conf/h, but is that better? */ 175359243Sobrien# ifndef RLIMIT_CPU 175459243Sobrien# define RLIMIT_CPU 0 175559243Sobrien# define RLIMIT_FSIZE 1 175659243Sobrien# define RLIMIT_DATA 2 175759243Sobrien# define RLIMIT_STACK 3 175859243Sobrien# define RLIMIT_CORE 4 175959243Sobrien# define RLIMIT_RSS 5 176059243Sobrien# define RLIMIT_NOFILE 6 176159243Sobrien# endif /* RLIMIT_CPU */ 176259243Sobrien# ifndef RLIM_INFINITY 176359243Sobrien# define RLIM_INFINITY 0x7fffffff 176459243Sobrien# endif /* RLIM_INFINITY */ 176559243Sobrien /* 176659243Sobrien * old versions of HP/UX counted limits in 512 bytes 176759243Sobrien */ 176859243Sobrien# ifndef SIGRTMIN 176959243Sobrien# define FILESIZE512 177059243Sobrien# endif /* SIGRTMIN */ 177159243Sobrien# endif /* (HPUXVERSION > 700) && BSDLIMIT */ 177259243Sobrien 177359243Sobrien# if SYSVREL > 3 && defined(BSDLIMIT) && !defined(_SX) 177459243Sobrien/* In order to use rusage, we included "/usr/ucbinclude/sys/resource.h" in */ 177559243Sobrien/* sh.h. However, some SVR4 limits are defined in <sys/resource.h>. Rather */ 177659243Sobrien/* than include both and get warnings, we define the extra SVR4 limits here. */ 177783098Smp/* XXX: I don't understand if RLIMIT_AS is defined, why don't we define */ 177883098Smp/* RLIMIT_VMEM based on it? */ 177959243Sobrien# ifndef RLIMIT_VMEM 178059243Sobrien# define RLIMIT_VMEM 6 178159243Sobrien# endif 178259243Sobrien# ifndef RLIMIT_AS 178359243Sobrien# define RLIMIT_AS RLIMIT_VMEM 178459243Sobrien# endif 178559243Sobrien# endif /* SYSVREL > 3 && BSDLIMIT */ 178659243Sobrien 178783098Smp# if defined(__linux__) && defined(RLIMIT_AS) && !defined(RLIMIT_VMEM) 178883098Smp# define RLIMIT_VMEM RLIMIT_AS 178983098Smp# endif 179083098Smp 179159243Sobrienstruct limits limits[] = 179259243Sobrien{ 179359243Sobrien# ifdef RLIMIT_CPU 179459243Sobrien { RLIMIT_CPU, "cputime", 1, "seconds" }, 179559243Sobrien# endif /* RLIMIT_CPU */ 179659243Sobrien 179759243Sobrien# ifdef RLIMIT_FSIZE 179859243Sobrien# ifndef aiws 179959243Sobrien { RLIMIT_FSIZE, "filesize", 1024, "kbytes" }, 180059243Sobrien# else 180159243Sobrien { RLIMIT_FSIZE, "filesize", 512, "blocks" }, 180259243Sobrien# endif /* aiws */ 180359243Sobrien# endif /* RLIMIT_FSIZE */ 180459243Sobrien 180559243Sobrien# ifdef RLIMIT_DATA 180659243Sobrien { RLIMIT_DATA, "datasize", 1024, "kbytes" }, 180759243Sobrien# endif /* RLIMIT_DATA */ 180859243Sobrien 180959243Sobrien# ifdef RLIMIT_STACK 181059243Sobrien# ifndef aiws 181159243Sobrien { RLIMIT_STACK, "stacksize", 1024, "kbytes" }, 181259243Sobrien# else 181359243Sobrien { RLIMIT_STACK, "stacksize", 1024 * 1024, "kbytes"}, 181459243Sobrien# endif /* aiws */ 181559243Sobrien# endif /* RLIMIT_STACK */ 181659243Sobrien 181759243Sobrien# ifdef RLIMIT_CORE 181859243Sobrien { RLIMIT_CORE, "coredumpsize", 1024, "kbytes" }, 181959243Sobrien# endif /* RLIMIT_CORE */ 182059243Sobrien 182159243Sobrien# ifdef RLIMIT_RSS 182259243Sobrien { RLIMIT_RSS, "memoryuse", 1024, "kbytes" }, 182359243Sobrien# endif /* RLIMIT_RSS */ 182459243Sobrien 182559243Sobrien# ifdef RLIMIT_UMEM 182659243Sobrien { RLIMIT_UMEM, "memoryuse", 1024, "kbytes" }, 182759243Sobrien# endif /* RLIMIT_UMEM */ 182859243Sobrien 182959243Sobrien# ifdef RLIMIT_VMEM 183059243Sobrien { RLIMIT_VMEM, "vmemoryuse", 1024, "kbytes" }, 183159243Sobrien# endif /* RLIMIT_VMEM */ 183259243Sobrien 183359243Sobrien# ifdef RLIMIT_NOFILE 183459243Sobrien { RLIMIT_NOFILE, "descriptors", 1, "" }, 183559243Sobrien# endif /* RLIMIT_NOFILE */ 183659243Sobrien 183759243Sobrien# ifdef RLIMIT_CONCUR 183859243Sobrien { RLIMIT_CONCUR, "concurrency", 1, "thread(s)" }, 183959243Sobrien# endif /* RLIMIT_CONCUR */ 184059243Sobrien 184159243Sobrien# ifdef RLIMIT_MEMLOCK 184259243Sobrien { RLIMIT_MEMLOCK, "memorylocked", 1024, "kbytes" }, 184359243Sobrien# endif /* RLIMIT_MEMLOCK */ 184459243Sobrien 184559243Sobrien# ifdef RLIMIT_NPROC 184659243Sobrien { RLIMIT_NPROC, "maxproc", 1, "" }, 184759243Sobrien# endif /* RLIMIT_NPROC */ 184859243Sobrien 1849100616Smp# if defined(RLIMIT_OFILE) && !defined(RLIMIT_NOFILE) 185059243Sobrien { RLIMIT_OFILE, "openfiles", 1, "" }, 1851100616Smp# endif /* RLIMIT_OFILE && !defined(RLIMIT_NOFILE) */ 185259243Sobrien 1853100616Smp# ifdef RLIMIT_SBSIZE 1854100616Smp { RLIMIT_SBSIZE, "sbsize", 1, "" }, 1855100616Smp# endif /* RLIMIT_SBSIZE */ 1856100616Smp 185759243Sobrien { -1, NULL, 0, NULL } 185859243Sobrien}; 185959243Sobrien 186059243Sobrienstatic struct limits *findlim __P((Char *)); 186159243Sobrienstatic RLIM_TYPE getval __P((struct limits *, Char **)); 186259243Sobrienstatic void limtail __P((Char *, char*)); 186359243Sobrienstatic void plim __P((struct limits *, int)); 186459243Sobrienstatic int setlim __P((struct limits *, int, RLIM_TYPE)); 186559243Sobrien 186659243Sobrien#ifdef convex 186759243Sobrienstatic RLIM_TYPE 186859243Sobrienrestrict_limit(value) 186959243Sobrien double value; 187059243Sobrien{ 187159243Sobrien /* 187259243Sobrien * is f too large to cope with? return the maximum or minimum int 187359243Sobrien */ 187459243Sobrien if (value > (double) INT_MAX) 187559243Sobrien return (RLIM_TYPE) INT_MAX; 187659243Sobrien else if (value < (double) INT_MIN) 187759243Sobrien return (RLIM_TYPE) INT_MIN; 187859243Sobrien else 187959243Sobrien return (RLIM_TYPE) value; 188059243Sobrien} 188159243Sobrien#else /* !convex */ 188259243Sobrien# define restrict_limit(x) ((RLIM_TYPE) (x)) 188359243Sobrien#endif /* convex */ 188459243Sobrien 188559243Sobrien 188659243Sobrienstatic struct limits * 188759243Sobrienfindlim(cp) 188859243Sobrien Char *cp; 188959243Sobrien{ 189059243Sobrien register struct limits *lp, *res; 189159243Sobrien 189259243Sobrien res = (struct limits *) NULL; 189359243Sobrien for (lp = limits; lp->limconst >= 0; lp++) 189459243Sobrien if (prefix(cp, str2short(lp->limname))) { 189559243Sobrien if (res) 189659243Sobrien stderror(ERR_NAME | ERR_AMBIG); 189759243Sobrien res = lp; 189859243Sobrien } 189959243Sobrien if (res) 190059243Sobrien return (res); 190159243Sobrien stderror(ERR_NAME | ERR_LIMIT); 190259243Sobrien /* NOTREACHED */ 190359243Sobrien return (0); 190459243Sobrien} 190559243Sobrien 190659243Sobrien/*ARGSUSED*/ 190759243Sobrienvoid 190859243Sobriendolimit(v, c) 190959243Sobrien register Char **v; 191059243Sobrien struct command *c; 191159243Sobrien{ 191259243Sobrien register struct limits *lp; 191359243Sobrien register RLIM_TYPE limit; 191459243Sobrien int hard = 0; 191559243Sobrien 191659243Sobrien USE(c); 191759243Sobrien v++; 191859243Sobrien if (*v && eq(*v, STRmh)) { 191959243Sobrien hard = 1; 192059243Sobrien v++; 192159243Sobrien } 192259243Sobrien if (*v == 0) { 192359243Sobrien for (lp = limits; lp->limconst >= 0; lp++) 192459243Sobrien plim(lp, hard); 192559243Sobrien return; 192659243Sobrien } 192759243Sobrien lp = findlim(v[0]); 192859243Sobrien if (v[1] == 0) { 192959243Sobrien plim(lp, hard); 193059243Sobrien return; 193159243Sobrien } 193259243Sobrien limit = getval(lp, v + 1); 193359243Sobrien if (setlim(lp, hard, limit) < 0) 193459243Sobrien stderror(ERR_SILENT); 193559243Sobrien} 193659243Sobrien 193759243Sobrienstatic RLIM_TYPE 193859243Sobriengetval(lp, v) 193959243Sobrien register struct limits *lp; 194059243Sobrien Char **v; 194159243Sobrien{ 194259243Sobrien register float f; 194359243Sobrien#ifndef atof /* This can be a macro on linux */ 194459243Sobrien extern double atof __P((const char *)); 194559243Sobrien#endif /* atof */ 194659243Sobrien Char *cp = *v++; 194759243Sobrien 194859243Sobrien f = atof(short2str(cp)); 194959243Sobrien 195059243Sobrien# ifdef convex 195159243Sobrien /* 195259243Sobrien * is f too large to cope with. limit f to minint, maxint - X-6768 by 195359243Sobrien * strike 195459243Sobrien */ 195559243Sobrien if ((f < (double) INT_MIN) || (f > (double) INT_MAX)) { 195659243Sobrien stderror(ERR_NAME | ERR_TOOLARGE); 195759243Sobrien } 195859243Sobrien# endif /* convex */ 195959243Sobrien 196059243Sobrien while (Isdigit(*cp) || *cp == '.' || *cp == 'e' || *cp == 'E') 196159243Sobrien cp++; 196259243Sobrien if (*cp == 0) { 196359243Sobrien if (*v == 0) 196469408Sache return restrict_limit((f * lp->limdiv) + 0.5); 196559243Sobrien cp = *v; 196659243Sobrien } 196759243Sobrien switch (*cp) { 196859243Sobrien# ifdef RLIMIT_CPU 196959243Sobrien case ':': 197059243Sobrien if (lp->limconst != RLIMIT_CPU) 197159243Sobrien goto badscal; 197259243Sobrien return f == 0.0 ? (RLIM_TYPE) 0 : restrict_limit((f * 60.0 + atof(short2str(cp + 1)))); 197359243Sobrien case 'h': 197459243Sobrien if (lp->limconst != RLIMIT_CPU) 197559243Sobrien goto badscal; 197659243Sobrien limtail(cp, "hours"); 197759243Sobrien f *= 3600.0; 197859243Sobrien break; 197959243Sobrien case 'm': 198059243Sobrien if (lp->limconst == RLIMIT_CPU) { 198159243Sobrien limtail(cp, "minutes"); 198259243Sobrien f *= 60.0; 198359243Sobrien break; 198459243Sobrien } 198559243Sobrien *cp = 'm'; 198659243Sobrien limtail(cp, "megabytes"); 198759243Sobrien f *= 1024.0 * 1024.0; 198859243Sobrien break; 198959243Sobrien case 's': 199059243Sobrien if (lp->limconst != RLIMIT_CPU) 199159243Sobrien goto badscal; 199259243Sobrien limtail(cp, "seconds"); 199359243Sobrien break; 199459243Sobrien# endif /* RLIMIT_CPU */ 199559243Sobrien case 'M': 199659243Sobrien# ifdef RLIMIT_CPU 199759243Sobrien if (lp->limconst == RLIMIT_CPU) 199859243Sobrien goto badscal; 199959243Sobrien# endif /* RLIMIT_CPU */ 200059243Sobrien *cp = 'm'; 200159243Sobrien limtail(cp, "megabytes"); 200259243Sobrien f *= 1024.0 * 1024.0; 200359243Sobrien break; 200459243Sobrien case 'k': 200559243Sobrien# ifdef RLIMIT_CPU 200659243Sobrien if (lp->limconst == RLIMIT_CPU) 200759243Sobrien goto badscal; 200859243Sobrien# endif /* RLIMIT_CPU */ 200959243Sobrien limtail(cp, "kbytes"); 201059243Sobrien f *= 1024.0; 201159243Sobrien break; 201259243Sobrien case 'b': 201359243Sobrien# ifdef RLIMIT_CPU 201459243Sobrien if (lp->limconst == RLIMIT_CPU) 201559243Sobrien goto badscal; 201659243Sobrien# endif /* RLIMIT_CPU */ 201759243Sobrien limtail(cp, "blocks"); 201859243Sobrien f *= 512.0; 201959243Sobrien break; 202059243Sobrien case 'u': 202159243Sobrien limtail(cp, "unlimited"); 202259243Sobrien return ((RLIM_TYPE) RLIM_INFINITY); 202359243Sobrien default: 202459243Sobrien# ifdef RLIMIT_CPU 202559243Sobrienbadscal: 202659243Sobrien# endif /* RLIMIT_CPU */ 202759243Sobrien stderror(ERR_NAME | ERR_SCALEF); 202859243Sobrien } 202959243Sobrien# ifdef convex 203059243Sobrien return f == 0.0 ? (RLIM_TYPE) 0 : restrict_limit((f + 0.5)); 203159243Sobrien# else 203259243Sobrien f += 0.5; 203359243Sobrien if (f > (float) RLIM_INFINITY) 203459243Sobrien return ((RLIM_TYPE) RLIM_INFINITY); 203559243Sobrien else 203659243Sobrien return ((RLIM_TYPE) f); 203759243Sobrien# endif /* convex */ 203859243Sobrien} 203959243Sobrien 204059243Sobrienstatic void 204159243Sobrienlimtail(cp, str) 204259243Sobrien Char *cp; 204359243Sobrien char *str; 204459243Sobrien{ 204561515Sobrien char *sp; 204661515Sobrien 204761515Sobrien sp = str; 204859243Sobrien while (*cp && *cp == *str) 204959243Sobrien cp++, str++; 205059243Sobrien if (*cp) 205161515Sobrien stderror(ERR_BADSCALE, sp); 205259243Sobrien} 205359243Sobrien 205459243Sobrien 205559243Sobrien/*ARGSUSED*/ 205659243Sobrienstatic void 205759243Sobrienplim(lp, hard) 205859243Sobrien register struct limits *lp; 205959243Sobrien int hard; 206059243Sobrien{ 206159243Sobrien# ifdef BSDLIMIT 206259243Sobrien struct rlimit rlim; 206359243Sobrien# endif /* BSDLIMIT */ 206459243Sobrien RLIM_TYPE limit; 206559243Sobrien int div = lp->limdiv; 206659243Sobrien 206759243Sobrien xprintf("%s \t", lp->limname); 206859243Sobrien 206959243Sobrien# ifndef BSDLIMIT 207059243Sobrien limit = ulimit(lp->limconst, 0); 207159243Sobrien# ifdef aiws 207259243Sobrien if (lp->limconst == RLIMIT_DATA) 207359243Sobrien limit -= 0x20000000; 207459243Sobrien# endif /* aiws */ 207559243Sobrien# else /* BSDLIMIT */ 207659243Sobrien (void) getrlimit(lp->limconst, &rlim); 207759243Sobrien limit = hard ? rlim.rlim_max : rlim.rlim_cur; 207859243Sobrien# endif /* BSDLIMIT */ 207959243Sobrien 208059243Sobrien# if !defined(BSDLIMIT) || defined(FILESIZE512) 208159243Sobrien /* 208259243Sobrien * Christos: filesize comes in 512 blocks. we divide by 2 to get 1024 208359243Sobrien * blocks. Note we cannot pre-multiply cause we might overflow (A/UX) 208459243Sobrien */ 208559243Sobrien if (lp->limconst == RLIMIT_FSIZE) { 208659243Sobrien if (limit >= (RLIM_INFINITY / 512)) 208759243Sobrien limit = RLIM_INFINITY; 208859243Sobrien else 208959243Sobrien div = (div == 1024 ? 2 : 1); 209059243Sobrien } 209159243Sobrien# endif /* !BSDLIMIT || FILESIZE512 */ 209259243Sobrien 209359243Sobrien if (limit == RLIM_INFINITY) 209459243Sobrien xprintf("unlimited"); 209559243Sobrien else 209659243Sobrien# ifdef RLIMIT_CPU 209759243Sobrien if (lp->limconst == RLIMIT_CPU) 209859243Sobrien psecs((long) limit); 209959243Sobrien else 210059243Sobrien# endif /* RLIMIT_CPU */ 210159243Sobrien xprintf("%ld %s", (long) (limit / div), lp->limscale); 210259243Sobrien xputchar('\n'); 210359243Sobrien} 210459243Sobrien 210559243Sobrien/*ARGSUSED*/ 210659243Sobrienvoid 210759243Sobriendounlimit(v, c) 210859243Sobrien register Char **v; 210959243Sobrien struct command *c; 211059243Sobrien{ 211159243Sobrien register struct limits *lp; 211259243Sobrien int lerr = 0; 211359243Sobrien int hard = 0; 211459243Sobrien int force = 0; 211559243Sobrien 211659243Sobrien USE(c); 211759243Sobrien while (*++v && **v == '-') { 211859243Sobrien Char *vp = *v; 211959243Sobrien while (*++vp) 212059243Sobrien switch (*vp) { 212159243Sobrien case 'f': 212259243Sobrien force = 1; 212359243Sobrien break; 212459243Sobrien case 'h': 212559243Sobrien hard = 1; 212659243Sobrien break; 212759243Sobrien default: 212859243Sobrien stderror(ERR_ULIMUS); 212959243Sobrien break; 213059243Sobrien } 213159243Sobrien } 213259243Sobrien 213359243Sobrien if (*v == 0) { 213459243Sobrien for (lp = limits; lp->limconst >= 0; lp++) 213559243Sobrien if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0) 213659243Sobrien lerr++; 213759243Sobrien if (!force && lerr) 213859243Sobrien stderror(ERR_SILENT); 213959243Sobrien return; 214059243Sobrien } 214159243Sobrien while (*v) { 214259243Sobrien lp = findlim(*v++); 214359243Sobrien if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0 && !force) 214459243Sobrien stderror(ERR_SILENT); 214559243Sobrien } 214659243Sobrien} 214759243Sobrien 214859243Sobrienstatic int 214959243Sobriensetlim(lp, hard, limit) 215059243Sobrien register struct limits *lp; 215159243Sobrien int hard; 215259243Sobrien RLIM_TYPE limit; 215359243Sobrien{ 215459243Sobrien# ifdef BSDLIMIT 215559243Sobrien struct rlimit rlim; 215659243Sobrien 215759243Sobrien (void) getrlimit(lp->limconst, &rlim); 215859243Sobrien 215959243Sobrien# ifdef FILESIZE512 216059243Sobrien /* Even though hpux has setrlimit(), it expects fsize in 512 byte blocks */ 216159243Sobrien if (limit != RLIM_INFINITY && lp->limconst == RLIMIT_FSIZE) 216259243Sobrien limit /= 512; 216359243Sobrien# endif /* FILESIZE512 */ 216459243Sobrien if (hard) 216559243Sobrien rlim.rlim_max = limit; 216659243Sobrien else if (limit == RLIM_INFINITY && euid != 0) 216759243Sobrien rlim.rlim_cur = rlim.rlim_max; 216859243Sobrien else 216959243Sobrien rlim.rlim_cur = limit; 217059243Sobrien 2171100616Smp if (rlim.rlim_cur > rlim.rlim_max) 2172100616Smp rlim.rlim_max = rlim.rlim_cur; 2173100616Smp 217459243Sobrien if (setrlimit(lp->limconst, &rlim) < 0) { 217559243Sobrien# else /* BSDLIMIT */ 217659243Sobrien if (limit != RLIM_INFINITY && lp->limconst == RLIMIT_FSIZE) 217759243Sobrien limit /= 512; 217859243Sobrien# ifdef aiws 217959243Sobrien if (lp->limconst == RLIMIT_DATA) 218059243Sobrien limit += 0x20000000; 218159243Sobrien# endif /* aiws */ 218259243Sobrien if (ulimit(toset(lp->limconst), limit) < 0) { 218359243Sobrien# endif /* BSDLIMIT */ 2184100616Smp xprintf(CGETS(15, 1, "%s: %s: Can't %s%s limit (%s)\n"), bname, 2185100616Smp lp->limname, limit == RLIM_INFINITY ? CGETS(15, 2, "remove") : 2186100616Smp CGETS(15, 3, "set"), hard ? CGETS(14, 4, " hard") : "", 2187100616Smp strerror(errno)); 218859243Sobrien return (-1); 218959243Sobrien } 219059243Sobrien return (0); 219159243Sobrien} 219259243Sobrien 219359243Sobrien#endif /* !HAVENOLIMIT */ 219459243Sobrien 219559243Sobrien/*ARGSUSED*/ 219659243Sobrienvoid 219759243Sobriendosuspend(v, c) 219859243Sobrien Char **v; 219959243Sobrien struct command *c; 220059243Sobrien{ 220159243Sobrien#ifdef BSDJOBS 220259243Sobrien int ctpgrp; 220359243Sobrien 220459243Sobrien signalfun_t old; 220559243Sobrien#endif /* BSDJOBS */ 220659243Sobrien 220759243Sobrien USE(c); 220859243Sobrien USE(v); 220959243Sobrien 221059243Sobrien if (loginsh) 221159243Sobrien stderror(ERR_SUSPLOG); 221259243Sobrien untty(); 221359243Sobrien 221459243Sobrien#ifdef BSDJOBS 221559243Sobrien old = signal(SIGTSTP, SIG_DFL); 221659243Sobrien (void) kill(0, SIGTSTP); 221759243Sobrien /* the shell stops here */ 221859243Sobrien (void) signal(SIGTSTP, old); 221959243Sobrien#else /* !BSDJOBS */ 222059243Sobrien stderror(ERR_JOBCONTROL); 222159243Sobrien#endif /* BSDJOBS */ 222259243Sobrien 222359243Sobrien#ifdef BSDJOBS 222459243Sobrien if (tpgrp != -1) { 222559243Sobrienretry: 222659243Sobrien ctpgrp = tcgetpgrp(FSHTTY); 222759243Sobrien if (ctpgrp != opgrp) { 222859243Sobrien old = signal(SIGTTIN, SIG_DFL); 222959243Sobrien (void) kill(0, SIGTTIN); 223059243Sobrien (void) signal(SIGTTIN, old); 223159243Sobrien goto retry; 223259243Sobrien } 223359243Sobrien (void) setpgid(0, shpgrp); 223459243Sobrien (void) tcsetpgrp(FSHTTY, shpgrp); 223559243Sobrien } 223659243Sobrien#endif /* BSDJOBS */ 223759243Sobrien (void) setdisc(FSHTTY); 223859243Sobrien} 223959243Sobrien 224059243Sobrien/* This is the dreaded EVAL built-in. 224159243Sobrien * If you don't fiddle with file descriptors, and reset didfds, 224259243Sobrien * this command will either ignore redirection inside or outside 224359243Sobrien * its arguments, e.g. eval "date >x" vs. eval "date" >x 224459243Sobrien * The stuff here seems to work, but I did it by trial and error rather 224559243Sobrien * than really knowing what was going on. If tpgrp is zero, we are 224659243Sobrien * probably a background eval, e.g. "eval date &", and we want to 224759243Sobrien * make sure that any processes we start stay in our pgrp. 224859243Sobrien * This is also the case for "time eval date" -- stay in same pgrp. 224959243Sobrien * Otherwise, under stty tostop, processes will stop in the wrong 225059243Sobrien * pgrp, with no way for the shell to get them going again. -IAN! 225159243Sobrien */ 225259243Sobrien 225359243Sobrienstatic Char **gv = NULL, **gav = NULL; 225459243Sobrien 225559243Sobrien/*ARGSUSED*/ 225659243Sobrienvoid 225759243Sobriendoeval(v, c) 225859243Sobrien Char **v; 225959243Sobrien struct command *c; 226059243Sobrien{ 226159243Sobrien Char **oevalvec; 226259243Sobrien Char *oevalp; 226359243Sobrien int odidfds; 226459243Sobrien#ifndef CLOSE_ON_EXEC 226559243Sobrien int odidcch; 226659243Sobrien#endif /* CLOSE_ON_EXEC */ 226759243Sobrien jmp_buf_t osetexit; 226859243Sobrien int my_reenter; 226959243Sobrien Char **savegv; 227059243Sobrien int saveIN, saveOUT, saveDIAG; 227159243Sobrien int oSHIN, oSHOUT, oSHDIAG; 227259243Sobrien 227359243Sobrien USE(c); 227459243Sobrien oevalvec = evalvec; 227559243Sobrien oevalp = evalp; 227659243Sobrien odidfds = didfds; 227759243Sobrien#ifndef CLOSE_ON_EXEC 227859243Sobrien odidcch = didcch; 227959243Sobrien#endif /* CLOSE_ON_EXEC */ 228059243Sobrien oSHIN = SHIN; 228159243Sobrien oSHOUT = SHOUT; 228259243Sobrien oSHDIAG = SHDIAG; 228359243Sobrien 228459243Sobrien savegv = gv; 228559243Sobrien gav = v; 228659243Sobrien 228759243Sobrien gav++; 228859243Sobrien if (*gav == 0) 228959243Sobrien return; 229059243Sobrien gflag = 0, tglob(gav); 229159243Sobrien if (gflag) { 229259243Sobrien gv = gav = globall(gav); 229359243Sobrien gargv = 0; 229459243Sobrien if (gav == 0) 229559243Sobrien stderror(ERR_NOMATCH); 229659243Sobrien gav = copyblk(gav); 229759243Sobrien } 229859243Sobrien else { 229959243Sobrien gv = NULL; 230059243Sobrien gav = copyblk(gav); 230159243Sobrien trim(gav); 230259243Sobrien } 230359243Sobrien 230459243Sobrien saveIN = dcopy(SHIN, -1); 230559243Sobrien saveOUT = dcopy(SHOUT, -1); 230659243Sobrien saveDIAG = dcopy(SHDIAG, -1); 230759243Sobrien 230859243Sobrien getexit(osetexit); 230959243Sobrien 231059243Sobrien /* PWP: setjmp/longjmp bugfix for optimizing compilers */ 231159243Sobrien#ifdef cray 231259243Sobrien my_reenter = 1; /* assume non-zero return val */ 231359243Sobrien if (setexit() == 0) { 231459243Sobrien my_reenter = 0; /* Oh well, we were wrong */ 231559243Sobrien#else /* !cray */ 231659243Sobrien if ((my_reenter = setexit()) == 0) { 231759243Sobrien#endif /* cray */ 231859243Sobrien evalvec = gav; 231959243Sobrien evalp = 0; 232059243Sobrien SHIN = dcopy(0, -1); 232159243Sobrien SHOUT = dcopy(1, -1); 232259243Sobrien SHDIAG = dcopy(2, -1); 232359243Sobrien#ifndef CLOSE_ON_EXEC 232459243Sobrien didcch = 0; 232559243Sobrien#endif /* CLOSE_ON_EXEC */ 232659243Sobrien didfds = 0; 232759243Sobrien process(0); 232859243Sobrien } 232959243Sobrien 233059243Sobrien evalvec = oevalvec; 233159243Sobrien evalp = oevalp; 233259243Sobrien doneinp = 0; 233359243Sobrien#ifndef CLOSE_ON_EXEC 233459243Sobrien didcch = odidcch; 233559243Sobrien#endif /* CLOSE_ON_EXEC */ 233659243Sobrien didfds = odidfds; 233759243Sobrien (void) close(SHIN); 233859243Sobrien (void) close(SHOUT); 233959243Sobrien (void) close(SHDIAG); 234059243Sobrien SHIN = dmove(saveIN, oSHIN); 234159243Sobrien SHOUT = dmove(saveOUT, oSHOUT); 234259243Sobrien SHDIAG = dmove(saveDIAG, oSHDIAG); 234359243Sobrien 234459243Sobrien if (gv) 234559243Sobrien blkfree(gv); 234659243Sobrien 234759243Sobrien gv = savegv; 234859243Sobrien resexit(osetexit); 234959243Sobrien if (my_reenter) 235059243Sobrien stderror(ERR_SILENT); 235159243Sobrien} 235259243Sobrien 235359243Sobrien/*************************************************************************/ 235459243Sobrien/* print list of builtin commands */ 235559243Sobrien 235659243Sobrien/*ARGSUSED*/ 235759243Sobrienvoid 235859243Sobriendobuiltins(v, c) 235959243SobrienChar **v; 236059243Sobrienstruct command *c; 236159243Sobrien{ 236259243Sobrien /* would use print_by_column() in tw.parse.c but that assumes 236359243Sobrien * we have an array of Char * to pass.. (sg) 236459243Sobrien */ 236559243Sobrien extern int Tty_raw_mode; 236659243Sobrien extern int TermH; /* from the editor routines */ 236759243Sobrien extern int lbuffed; /* from sh.print.c */ 236859243Sobrien 236959243Sobrien register struct biltins *b; 237059243Sobrien register int row, col, columns, rows; 237159243Sobrien unsigned int w, maxwidth; 237259243Sobrien 237359243Sobrien USE(c); 237459243Sobrien USE(v); 237559243Sobrien lbuffed = 0; /* turn off line buffering */ 237659243Sobrien 237759243Sobrien /* find widest string */ 237859243Sobrien for (maxwidth = 0, b = bfunc; b < &bfunc[nbfunc]; ++b) 237959243Sobrien maxwidth = max(maxwidth, strlen(b->bname)); 238059243Sobrien ++maxwidth; /* for space */ 238159243Sobrien 238259243Sobrien columns = (TermH + 1) / maxwidth; /* PWP: terminal size change */ 238359243Sobrien if (!columns) 238459243Sobrien columns = 1; 238559243Sobrien rows = (nbfunc + (columns - 1)) / columns; 238659243Sobrien 238759243Sobrien for (b = bfunc, row = 0; row < rows; row++) { 238859243Sobrien for (col = 0; col < columns; col++) { 238959243Sobrien if (b < &bfunc[nbfunc]) { 239059243Sobrien w = strlen(b->bname); 239159243Sobrien xprintf("%s", b->bname); 239259243Sobrien if (col < (columns - 1)) /* Not last column? */ 239359243Sobrien for (; w < maxwidth; w++) 239459243Sobrien xputchar(' '); 239559243Sobrien ++b; 239659243Sobrien } 239759243Sobrien } 239859243Sobrien if (row < (rows - 1)) { 239959243Sobrien if (Tty_raw_mode) 240059243Sobrien xputchar('\r'); 240159243Sobrien xputchar('\n'); 240259243Sobrien } 240359243Sobrien } 240469408Sache#ifdef WINNT_NATIVE 240559243Sobrien nt_print_builtins(maxwidth); 240659243Sobrien#else 240759243Sobrien if (Tty_raw_mode) 240859243Sobrien xputchar('\r'); 240959243Sobrien xputchar('\n'); 241069408Sache#endif /* WINNT_NATIVE */ 241159243Sobrien 241259243Sobrien lbuffed = 1; /* turn back on line buffering */ 241359243Sobrien flush(); 241459243Sobrien} 241559243Sobrien 241659243Sobrienvoid 241759243Sobriennlsinit() 241859243Sobrien{ 241959243Sobrien#ifdef NLS_CATALOGS 242069408Sache char catalog[ 256 ] = { 't', 'c', 's', 'h', '\0' }; 242169408Sache 242269408Sache if (adrof(STRcatalog) != NULL) 242369408Sache xsnprintf((char *)catalog, sizeof(catalog), "tcsh.%s", 242469408Sache short2str(varval(STRcatalog))); 242569408Sache catd = catopen(catalog, MCLoadBySet); 242669408Sache#endif /* NLS_CATALOGS */ 242769408Sache#ifdef WINNT_NATIVE 242859243Sobrien nls_dll_init(); 242969408Sache#endif /* WINNT_NATIVE */ 243059243Sobrien errinit(); /* init the errorlist in correct locale */ 243159243Sobrien mesginit(); /* init the messages for signals */ 243259243Sobrien dateinit(); /* init the messages for dates */ 243359243Sobrien editinit(); /* init the editor messages */ 243459243Sobrien terminit(); /* init the termcap messages */ 243559243Sobrien} 2436