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