sh.func.c revision 59415
159415Sobrien/* $Header: /src/pub/tcsh/sh.func.c,v 3.86 2000/01/14 22:57:27 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 3959415SobrienRCSID("$Id: sh.func.c,v 3.86 2000/01/14 22:57:27 christos Exp $") 4059243Sobrien 4159243Sobrien#include "ed.h" 4259243Sobrien#include "tw.h" 4359243Sobrien#include "tc.h" 4459243Sobrien#ifdef WINNT 4559243Sobrien#include "nt.const.h" 4659243Sobrien#endif /* WINNT */ 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 } 12959243Sobrien#ifdef WINNT 13059243Sobrien return nt_check_additional_builtins(cp); 13159243Sobrien#endif /*WINNT*/ 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); 35059243Sobrien#ifdef WINNT 35159243Sobrien USE(v); 35259243Sobrien#else /* !WINNT */ 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); 36059243Sobrien#endif /* !WINNT */ 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) 48759243Sobrien if (wp->w_end.type == 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; 60359243Sobrien nwp->w_end.type = 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; 64259243Sobrien nwp->w_end.type = 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{ 66459243Sobrien whyles->w_end.type = 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; 83959243Sobrien a.type = F_SEEK; 84059243Sobrien a.f_seek = 0; 84159243Sobrien bseek(&a); 84259243Sobrien } 84359243Sobrien do { 84459243Sobrien if (intty && fseekp == feobp && aret == 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{ 102359243Sobrien if (whyles->w_end.type == 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 */ 106959243Sobrien if (wp->w_end.type != I_SEEK && wp->w_start.type == wp->w_end.type && 107059243Sobrien wp->w_start.type == o.type) { 107159243Sobrien if (wp->w_end.type == 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) 115059243Sobrien return; 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 } 139359243Sobrien#ifdef WINNT 139459243Sobrien if (eq(vp, STRtcshlang)) { 139559243Sobrien nlsinit(); 139659243Sobrien xfree((ptr_t) lp); 139759243Sobrien return; 139859243Sobrien } 139959243Sobrien if (eq(vp, STRtcshonlystartexes)) { 140059243Sobrien __nt_only_start_exes = 1; 140159243Sobrien xfree((ptr_t) lp); 140259243Sobrien return; 140359243Sobrien } 140459243Sobrien#endif /* WINNT */ 140559243Sobrien if (eq(vp, STRKTERM)) { 140659243Sobrien char *t; 140759243Sobrien set(STRterm, quote(lp), VAR_READWRITE); /* lp memory used here */ 140859243Sobrien t = short2str(lp); 140959243Sobrien if (noediting && strcmp(t, "unknown") != 0 && strcmp(t,"dumb") != 0) { 141059243Sobrien editing = 1; 141159243Sobrien noediting = 0; 141259243Sobrien set(STRedit, Strsave(STRNULL), VAR_READWRITE); 141359243Sobrien } 141459243Sobrien GotTermCaps = 0; 141559243Sobrien ed_Init(); 141659243Sobrien return; 141759243Sobrien } 141859243Sobrien 141959243Sobrien if (eq(vp, STRKHOME)) { 142059243Sobrien /* 142159243Sobrien * convert to canonical pathname (possibly resolving symlinks) 142259243Sobrien */ 142359243Sobrien lp = dcanon(lp, lp); 142459243Sobrien set(STRhome, quote(lp), VAR_READWRITE); /* cp memory used here */ 142559243Sobrien 142659243Sobrien /* fix directory stack for new tilde home */ 142759243Sobrien dtilde(); 142859243Sobrien return; 142959243Sobrien } 143059243Sobrien 143159243Sobrien if (eq(vp, STRKSHLVL)) { 143259243Sobrien /* lp memory used here */ 143359243Sobrien set(STRshlvl, quote(lp), VAR_READWRITE); 143459243Sobrien return; 143559243Sobrien } 143659243Sobrien 143759243Sobrien if (eq(vp, STRKUSER)) { 143859243Sobrien set(STRuser, quote(lp), VAR_READWRITE); /* lp memory used here */ 143959243Sobrien return; 144059243Sobrien } 144159243Sobrien 144259243Sobrien if (eq(vp, STRKGROUP)) { 144359243Sobrien set(STRgroup, quote(lp), VAR_READWRITE); /* lp memory used here */ 144459243Sobrien return; 144559243Sobrien } 144659243Sobrien 144759243Sobrien#ifdef COLOR_LS_F 144859243Sobrien if (eq(vp, STRLS_COLORS)) { 144959243Sobrien parseLS_COLORS(lp); 145059243Sobrien return; 145159243Sobrien } 145259243Sobrien#endif /* COLOR_LS_F */ 145359243Sobrien 145459243Sobrien#ifdef SIG_WINDOW 145559243Sobrien /* 145659243Sobrien * Load/Update $LINES $COLUMNS 145759243Sobrien */ 145859243Sobrien if ((eq(lp, STRNULL) && (eq(vp, STRLINES) || eq(vp, STRCOLUMNS))) || 145959243Sobrien eq(vp, STRTERMCAP)) { 146059243Sobrien xfree((ptr_t) lp); 146159243Sobrien check_window_size(1); 146259243Sobrien return; 146359243Sobrien } 146459243Sobrien 146559243Sobrien /* 146659243Sobrien * Change the size to the one directed by $LINES and $COLUMNS 146759243Sobrien */ 146859243Sobrien if (eq(vp, STRLINES) || eq(vp, STRCOLUMNS)) { 146959243Sobrien#if 0 147059243Sobrien GotTermCaps = 0; 147159243Sobrien#endif 147259243Sobrien xfree((ptr_t) lp); 147359243Sobrien ed_Init(); 147459243Sobrien return; 147559243Sobrien } 147659243Sobrien#endif /* SIG_WINDOW */ 147759243Sobrien xfree((ptr_t) lp); 147859243Sobrien} 147959243Sobrien 148059243Sobrien/*ARGSUSED*/ 148159243Sobrienvoid 148259243Sobriendounsetenv(v, c) 148359243Sobrien register Char **v; 148459243Sobrien struct command *c; 148559243Sobrien{ 148659243Sobrien Char **ep, *p, *n; 148759243Sobrien int i, maxi; 148859243Sobrien static Char *name = NULL; 148959243Sobrien 149059243Sobrien USE(c); 149159243Sobrien if (name) 149259243Sobrien xfree((ptr_t) name); 149359243Sobrien /* 149459243Sobrien * Find the longest environment variable 149559243Sobrien */ 149659243Sobrien for (maxi = 0, ep = STR_environ; *ep; ep++) { 149759243Sobrien for (i = 0, p = *ep; *p && *p != '='; p++, i++) 149859243Sobrien continue; 149959243Sobrien if (i > maxi) 150059243Sobrien maxi = i; 150159243Sobrien } 150259243Sobrien 150359243Sobrien name = (Char *) xmalloc((size_t) ((maxi + 1) * sizeof(Char))); 150459243Sobrien 150559243Sobrien while (++v && *v) 150659243Sobrien for (maxi = 1; maxi;) 150759243Sobrien for (maxi = 0, ep = STR_environ; *ep; ep++) { 150859243Sobrien for (n = name, p = *ep; *p && *p != '='; *n++ = *p++) 150959243Sobrien continue; 151059243Sobrien *n = '\0'; 151159243Sobrien if (!Gmatch(name, *v)) 151259243Sobrien continue; 151359243Sobrien maxi = 1; 151459243Sobrien 151559243Sobrien /* Unset the name. This wasn't being done until 151659243Sobrien * later but most of the stuff following won't 151759243Sobrien * work (particularly the setlocale() and getenv() 151859243Sobrien * stuff) as intended until the name is actually 151959243Sobrien * removed. (sg) 152059243Sobrien */ 152159243Sobrien Unsetenv(name); 152259243Sobrien 152359243Sobrien if (eq(name, STRNOREBIND)) { 152459243Sobrien NoNLSRebind = 0; 152559243Sobrien MapsAreInited = 0; 152659243Sobrien NLSMapsAreInited = 0; 152759243Sobrien ed_InitMaps(); 152859243Sobrien } 152959243Sobrien#ifdef apollo 153059243Sobrien else if (eq(name, STRSYSTYPE)) 153159243Sobrien dohash(NULL, NULL); 153259243Sobrien#endif /* apollo */ 153359243Sobrien else if (islocale_var(name)) { 153459243Sobrien#ifdef NLS 153559243Sobrien int k; 153659243Sobrien 153759243Sobrien# ifdef SETLOCALEBUG 153859243Sobrien dont_free = 1; 153959243Sobrien# endif /* SETLOCALEBUG */ 154059243Sobrien (void) setlocale(LC_ALL, ""); 154159243Sobrien# ifdef LC_COLLATE 154259243Sobrien (void) setlocale(LC_COLLATE, ""); 154359243Sobrien# endif 154459243Sobrien# ifdef NLS_CATALOGS 154559243Sobrien# ifdef LC_MESSAGES 154659243Sobrien (void) setlocale(LC_MESSAGES, ""); 154759243Sobrien# endif /* LC_MESSAGES */ 154859243Sobrien (void) catclose(catd); 154959243Sobrien nlsinit(); 155059243Sobrien# endif /* NLS_CATALOGS */ 155159243Sobrien# ifdef LC_CTYPE 155259243Sobrien (void) setlocale(LC_CTYPE, ""); /* for iscntrl */ 155359243Sobrien# endif /* LC_CTYPE */ 155459243Sobrien# ifdef SETLOCALEBUG 155559243Sobrien dont_free = 0; 155659243Sobrien# endif /* SETLOCALEBUG */ 155759243Sobrien# ifdef STRCOLLBUG 155859243Sobrien fix_strcoll_bug(); 155959243Sobrien# endif /* STRCOLLBUG */ 156059243Sobrien tw_cmd_free();/* since the collation sequence has changed */ 156159243Sobrien for (k = 0200; k <= 0377 && !Isprint(k); k++) 156259243Sobrien continue; 156359243Sobrien AsciiOnly = k > 0377; 156459243Sobrien#else /* !NLS */ 156559243Sobrien AsciiOnly = getenv("LANG") == NULL && 156659243Sobrien getenv("LC_CTYPE") == NULL; 156759243Sobrien#endif /* NLS */ 156859243Sobrien NLSMapsAreInited = 0; 156959243Sobrien ed_Init(); 157059243Sobrien if (MapsAreInited && !NLSMapsAreInited) 157159243Sobrien ed_InitNLSMaps(); 157259243Sobrien 157359243Sobrien } 157459243Sobrien#ifdef WINNT 157559243Sobrien else if (eq(name,(STRtcshlang))) { 157659243Sobrien nls_dll_unload(); 157759243Sobrien nlsinit(); 157859243Sobrien } 157959243Sobrien else if (eq(name,(STRtcshonlystartexes))) { 158059243Sobrien __nt_only_start_exes = 0; 158159243Sobrien } 158259243Sobrien#endif /* WINNT */ 158359243Sobrien#ifdef COLOR_LS_F 158459243Sobrien else if (eq(name, STRLS_COLORS)) 158559243Sobrien parseLS_COLORS(n); 158659243Sobrien#endif /* COLOR_LS_F */ 158759243Sobrien /* 158859243Sobrien * start again cause the environment changes 158959243Sobrien */ 159059243Sobrien break; 159159243Sobrien } 159259243Sobrien xfree((ptr_t) name); name = NULL; 159359243Sobrien} 159459243Sobrien 159559243Sobrienvoid 159659243Sobrientsetenv(name, val) 159759243Sobrien Char *name, *val; 159859243Sobrien{ 159959243Sobrien#ifdef SETENV_IN_LIB 160059243Sobrien/* 160159243Sobrien * XXX: This does not work right, since tcsh cannot track changes to 160259243Sobrien * the environment this way. (the builtin setenv without arguments does 160359243Sobrien * not print the right stuff neither does unsetenv). This was for Mach, 160459243Sobrien * it is not needed anymore. 160559243Sobrien */ 160659243Sobrien#undef setenv 160759243Sobrien char nameBuf[BUFSIZE]; 160859243Sobrien char *cname = short2str(name); 160959243Sobrien 161059243Sobrien if (cname == NULL) 161159243Sobrien return; 161259243Sobrien (void) strcpy(nameBuf, cname); 161359243Sobrien setenv(nameBuf, short2str(val), 1); 161459243Sobrien#else /* !SETENV_IN_LIB */ 161559243Sobrien register Char **ep = STR_environ; 161659243Sobrien register Char *cp, *dp; 161759243Sobrien Char *blk[2]; 161859243Sobrien Char **oep = ep; 161959243Sobrien 162059243Sobrien#ifdef WINNT 162159243Sobrien nt_set_env(name,val); 162259243Sobrien#endif /* WINNT */ 162359243Sobrien for (; *ep; ep++) { 162459243Sobrien#ifdef WINNT 162559243Sobrien for (cp = name, dp = *ep; *cp && Tolower(*cp & TRIM) == Tolower(*dp); 162659243Sobrien cp++, dp++) 162759243Sobrien#else 162859243Sobrien for (cp = name, dp = *ep; *cp && (*cp & TRIM) == *dp; cp++, dp++) 162959243Sobrien#endif /* WINNT */ 163059243Sobrien continue; 163159243Sobrien if (*cp != 0 || *dp != '=') 163259243Sobrien continue; 163359243Sobrien cp = Strspl(STRequal, val); 163459243Sobrien xfree((ptr_t) * ep); 163559243Sobrien *ep = strip(Strspl(name, cp)); 163659243Sobrien xfree((ptr_t) cp); 163759243Sobrien blkfree((Char **) environ); 163859243Sobrien environ = short2blk(STR_environ); 163959243Sobrien return; 164059243Sobrien } 164159243Sobrien cp = Strspl(name, STRequal); 164259243Sobrien blk[0] = strip(Strspl(cp, val)); 164359243Sobrien xfree((ptr_t) cp); 164459243Sobrien blk[1] = 0; 164559243Sobrien STR_environ = blkspl(STR_environ, blk); 164659243Sobrien blkfree((Char **) environ); 164759243Sobrien environ = short2blk(STR_environ); 164859243Sobrien xfree((ptr_t) oep); 164959243Sobrien#endif /* SETENV_IN_LIB */ 165059243Sobrien} 165159243Sobrien 165259243Sobrienvoid 165359243SobrienUnsetenv(name) 165459243Sobrien Char *name; 165559243Sobrien{ 165659243Sobrien register Char **ep = STR_environ; 165759243Sobrien register Char *cp, *dp; 165859243Sobrien Char **oep = ep; 165959243Sobrien 166059243Sobrien#ifdef WINNT 166159243Sobrien nt_set_env(name,NULL); 166259243Sobrien#endif /*WINNT */ 166359243Sobrien for (; *ep; ep++) { 166459243Sobrien for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++) 166559243Sobrien continue; 166659243Sobrien if (*cp != 0 || *dp != '=') 166759243Sobrien continue; 166859243Sobrien cp = *ep; 166959243Sobrien *ep = 0; 167059243Sobrien STR_environ = blkspl(STR_environ, ep + 1); 167159243Sobrien blkfree((Char **) environ); 167259243Sobrien environ = short2blk(STR_environ); 167359243Sobrien *ep = cp; 167459243Sobrien xfree((ptr_t) cp); 167559243Sobrien xfree((ptr_t) oep); 167659243Sobrien return; 167759243Sobrien } 167859243Sobrien} 167959243Sobrien 168059243Sobrien/*ARGSUSED*/ 168159243Sobrienvoid 168259243Sobriendoumask(v, c) 168359243Sobrien register Char **v; 168459243Sobrien struct command *c; 168559243Sobrien{ 168659243Sobrien register Char *cp = v[1]; 168759243Sobrien register int i; 168859243Sobrien 168959243Sobrien USE(c); 169059243Sobrien if (cp == 0) { 169159415Sobrien i = (int)umask(0); 169259243Sobrien (void) umask(i); 169359243Sobrien xprintf("%o\n", i); 169459243Sobrien return; 169559243Sobrien } 169659243Sobrien i = 0; 169759243Sobrien while (Isdigit(*cp) && *cp != '8' && *cp != '9') 169859243Sobrien i = i * 8 + *cp++ - '0'; 169959243Sobrien if (*cp || i < 0 || i > 0777) 170059243Sobrien stderror(ERR_NAME | ERR_MASK); 170159243Sobrien (void) umask(i); 170259243Sobrien} 170359243Sobrien 170459243Sobrien#ifndef HAVENOLIMIT 170559243Sobrien# ifndef BSDLIMIT 170659243Sobrien typedef long RLIM_TYPE; 170759243Sobrien# ifndef RLIM_INFINITY 170859243Sobrien# if !defined(_MINIX) && !defined(__clipper__) && !defined(_CRAY) 170959243Sobrien extern RLIM_TYPE ulimit(); 171059243Sobrien# endif /* ! _MINIX && !__clipper__ */ 171159243Sobrien# define RLIM_INFINITY 0x003fffff 171259243Sobrien# define RLIMIT_FSIZE 1 171359243Sobrien# endif /* RLIM_INFINITY */ 171459243Sobrien# ifdef aiws 171559243Sobrien# define toset(a) (((a) == 3) ? 1004 : (a) + 1) 171659243Sobrien# define RLIMIT_DATA 3 171759243Sobrien# define RLIMIT_STACK 1005 171859243Sobrien# else /* aiws */ 171959243Sobrien# define toset(a) ((a) + 1) 172059243Sobrien# endif /* aiws */ 172159243Sobrien# else /* BSDLIMIT */ 172259243Sobrien# if defined(BSD4_4) && !defined(__386BSD__) 172359243Sobrien typedef quad_t RLIM_TYPE; 172459243Sobrien# else 172559243Sobrien# if defined(SOLARIS2) || (defined(sgi) && SYSVREL > 3) 172659243Sobrien typedef rlim_t RLIM_TYPE; 172759243Sobrien# else 172859243Sobrien# if defined(_SX) 172959243Sobrien typedef long long RLIM_TYPE; 173059243Sobrien# else /* _SX */ 173159243Sobrien typedef unsigned long RLIM_TYPE; 173259243Sobrien# endif /* _SX */ 173359243Sobrien# endif /* SOLARIS2 || (sgi && SYSVREL > 3) */ 173459243Sobrien# endif /* BSD4_4 && !__386BSD__ */ 173559243Sobrien# endif /* BSDLIMIT */ 173659243Sobrien 173759243Sobrien# if (HPUXVERSION > 700) && defined(BSDLIMIT) 173859243Sobrien/* Yes hpux8.0 has limits but <sys/resource.h> does not make them public */ 173959243Sobrien/* Yes, we could have defined _KERNEL, and -I/etc/conf/h, but is that better? */ 174059243Sobrien# ifndef RLIMIT_CPU 174159243Sobrien# define RLIMIT_CPU 0 174259243Sobrien# define RLIMIT_FSIZE 1 174359243Sobrien# define RLIMIT_DATA 2 174459243Sobrien# define RLIMIT_STACK 3 174559243Sobrien# define RLIMIT_CORE 4 174659243Sobrien# define RLIMIT_RSS 5 174759243Sobrien# define RLIMIT_NOFILE 6 174859243Sobrien# endif /* RLIMIT_CPU */ 174959243Sobrien# ifndef RLIM_INFINITY 175059243Sobrien# define RLIM_INFINITY 0x7fffffff 175159243Sobrien# endif /* RLIM_INFINITY */ 175259243Sobrien /* 175359243Sobrien * old versions of HP/UX counted limits in 512 bytes 175459243Sobrien */ 175559243Sobrien# ifndef SIGRTMIN 175659243Sobrien# define FILESIZE512 175759243Sobrien# endif /* SIGRTMIN */ 175859243Sobrien# endif /* (HPUXVERSION > 700) && BSDLIMIT */ 175959243Sobrien 176059243Sobrien# if SYSVREL > 3 && defined(BSDLIMIT) && !defined(_SX) 176159243Sobrien/* In order to use rusage, we included "/usr/ucbinclude/sys/resource.h" in */ 176259243Sobrien/* sh.h. However, some SVR4 limits are defined in <sys/resource.h>. Rather */ 176359243Sobrien/* than include both and get warnings, we define the extra SVR4 limits here. */ 176459243Sobrien# ifndef RLIMIT_VMEM 176559243Sobrien# define RLIMIT_VMEM 6 176659243Sobrien# endif 176759243Sobrien# ifndef RLIMIT_AS 176859243Sobrien# define RLIMIT_AS RLIMIT_VMEM 176959243Sobrien# endif 177059243Sobrien# endif /* SYSVREL > 3 && BSDLIMIT */ 177159243Sobrien 177259243Sobrienstruct limits limits[] = 177359243Sobrien{ 177459243Sobrien# ifdef RLIMIT_CPU 177559243Sobrien { RLIMIT_CPU, "cputime", 1, "seconds" }, 177659243Sobrien# endif /* RLIMIT_CPU */ 177759243Sobrien 177859243Sobrien# ifdef RLIMIT_FSIZE 177959243Sobrien# ifndef aiws 178059243Sobrien { RLIMIT_FSIZE, "filesize", 1024, "kbytes" }, 178159243Sobrien# else 178259243Sobrien { RLIMIT_FSIZE, "filesize", 512, "blocks" }, 178359243Sobrien# endif /* aiws */ 178459243Sobrien# endif /* RLIMIT_FSIZE */ 178559243Sobrien 178659243Sobrien# ifdef RLIMIT_DATA 178759243Sobrien { RLIMIT_DATA, "datasize", 1024, "kbytes" }, 178859243Sobrien# endif /* RLIMIT_DATA */ 178959243Sobrien 179059243Sobrien# ifdef RLIMIT_STACK 179159243Sobrien# ifndef aiws 179259243Sobrien { RLIMIT_STACK, "stacksize", 1024, "kbytes" }, 179359243Sobrien# else 179459243Sobrien { RLIMIT_STACK, "stacksize", 1024 * 1024, "kbytes"}, 179559243Sobrien# endif /* aiws */ 179659243Sobrien# endif /* RLIMIT_STACK */ 179759243Sobrien 179859243Sobrien# ifdef RLIMIT_CORE 179959243Sobrien { RLIMIT_CORE, "coredumpsize", 1024, "kbytes" }, 180059243Sobrien# endif /* RLIMIT_CORE */ 180159243Sobrien 180259243Sobrien# ifdef RLIMIT_RSS 180359243Sobrien { RLIMIT_RSS, "memoryuse", 1024, "kbytes" }, 180459243Sobrien# endif /* RLIMIT_RSS */ 180559243Sobrien 180659243Sobrien# ifdef RLIMIT_UMEM 180759243Sobrien { RLIMIT_UMEM, "memoryuse", 1024, "kbytes" }, 180859243Sobrien# endif /* RLIMIT_UMEM */ 180959243Sobrien 181059243Sobrien# ifdef RLIMIT_VMEM 181159243Sobrien { RLIMIT_VMEM, "vmemoryuse", 1024, "kbytes" }, 181259243Sobrien# endif /* RLIMIT_VMEM */ 181359243Sobrien 181459243Sobrien# ifdef RLIMIT_NOFILE 181559243Sobrien { RLIMIT_NOFILE, "descriptors", 1, "" }, 181659243Sobrien# endif /* RLIMIT_NOFILE */ 181759243Sobrien 181859243Sobrien# ifdef RLIMIT_CONCUR 181959243Sobrien { RLIMIT_CONCUR, "concurrency", 1, "thread(s)" }, 182059243Sobrien# endif /* RLIMIT_CONCUR */ 182159243Sobrien 182259243Sobrien# ifdef RLIMIT_MEMLOCK 182359243Sobrien { RLIMIT_MEMLOCK, "memorylocked", 1024, "kbytes" }, 182459243Sobrien# endif /* RLIMIT_MEMLOCK */ 182559243Sobrien 182659243Sobrien# ifdef RLIMIT_NPROC 182759243Sobrien { RLIMIT_NPROC, "maxproc", 1, "" }, 182859243Sobrien# endif /* RLIMIT_NPROC */ 182959243Sobrien 183059243Sobrien# ifdef RLIMIT_OFILE 183159243Sobrien { RLIMIT_OFILE, "openfiles", 1, "" }, 183259243Sobrien# endif /* RLIMIT_OFILE */ 183359243Sobrien 183459243Sobrien { -1, NULL, 0, NULL } 183559243Sobrien}; 183659243Sobrien 183759243Sobrienstatic struct limits *findlim __P((Char *)); 183859243Sobrienstatic RLIM_TYPE getval __P((struct limits *, Char **)); 183959243Sobrienstatic void limtail __P((Char *, char*)); 184059243Sobrienstatic void plim __P((struct limits *, int)); 184159243Sobrienstatic int setlim __P((struct limits *, int, RLIM_TYPE)); 184259243Sobrien 184359243Sobrien#ifdef convex 184459243Sobrienstatic RLIM_TYPE 184559243Sobrienrestrict_limit(value) 184659243Sobrien double value; 184759243Sobrien{ 184859243Sobrien /* 184959243Sobrien * is f too large to cope with? return the maximum or minimum int 185059243Sobrien */ 185159243Sobrien if (value > (double) INT_MAX) 185259243Sobrien return (RLIM_TYPE) INT_MAX; 185359243Sobrien else if (value < (double) INT_MIN) 185459243Sobrien return (RLIM_TYPE) INT_MIN; 185559243Sobrien else 185659243Sobrien return (RLIM_TYPE) value; 185759243Sobrien} 185859243Sobrien#else /* !convex */ 185959243Sobrien# define restrict_limit(x) ((RLIM_TYPE) (x)) 186059243Sobrien#endif /* convex */ 186159243Sobrien 186259243Sobrien 186359243Sobrienstatic struct limits * 186459243Sobrienfindlim(cp) 186559243Sobrien Char *cp; 186659243Sobrien{ 186759243Sobrien register struct limits *lp, *res; 186859243Sobrien 186959243Sobrien res = (struct limits *) NULL; 187059243Sobrien for (lp = limits; lp->limconst >= 0; lp++) 187159243Sobrien if (prefix(cp, str2short(lp->limname))) { 187259243Sobrien if (res) 187359243Sobrien stderror(ERR_NAME | ERR_AMBIG); 187459243Sobrien res = lp; 187559243Sobrien } 187659243Sobrien if (res) 187759243Sobrien return (res); 187859243Sobrien stderror(ERR_NAME | ERR_LIMIT); 187959243Sobrien /* NOTREACHED */ 188059243Sobrien return (0); 188159243Sobrien} 188259243Sobrien 188359243Sobrien/*ARGSUSED*/ 188459243Sobrienvoid 188559243Sobriendolimit(v, c) 188659243Sobrien register Char **v; 188759243Sobrien struct command *c; 188859243Sobrien{ 188959243Sobrien register struct limits *lp; 189059243Sobrien register RLIM_TYPE limit; 189159243Sobrien int hard = 0; 189259243Sobrien 189359243Sobrien USE(c); 189459243Sobrien v++; 189559243Sobrien if (*v && eq(*v, STRmh)) { 189659243Sobrien hard = 1; 189759243Sobrien v++; 189859243Sobrien } 189959243Sobrien if (*v == 0) { 190059243Sobrien for (lp = limits; lp->limconst >= 0; lp++) 190159243Sobrien plim(lp, hard); 190259243Sobrien return; 190359243Sobrien } 190459243Sobrien lp = findlim(v[0]); 190559243Sobrien if (v[1] == 0) { 190659243Sobrien plim(lp, hard); 190759243Sobrien return; 190859243Sobrien } 190959243Sobrien limit = getval(lp, v + 1); 191059243Sobrien if (setlim(lp, hard, limit) < 0) 191159243Sobrien stderror(ERR_SILENT); 191259243Sobrien} 191359243Sobrien 191459243Sobrienstatic RLIM_TYPE 191559243Sobriengetval(lp, v) 191659243Sobrien register struct limits *lp; 191759243Sobrien Char **v; 191859243Sobrien{ 191959243Sobrien register float f; 192059243Sobrien#ifndef atof /* This can be a macro on linux */ 192159243Sobrien extern double atof __P((const char *)); 192259243Sobrien#endif /* atof */ 192359243Sobrien Char *cp = *v++; 192459243Sobrien 192559243Sobrien f = atof(short2str(cp)); 192659243Sobrien 192759243Sobrien# ifdef convex 192859243Sobrien /* 192959243Sobrien * is f too large to cope with. limit f to minint, maxint - X-6768 by 193059243Sobrien * strike 193159243Sobrien */ 193259243Sobrien if ((f < (double) INT_MIN) || (f > (double) INT_MAX)) { 193359243Sobrien stderror(ERR_NAME | ERR_TOOLARGE); 193459243Sobrien } 193559243Sobrien# endif /* convex */ 193659243Sobrien 193759243Sobrien while (Isdigit(*cp) || *cp == '.' || *cp == 'e' || *cp == 'E') 193859243Sobrien cp++; 193959243Sobrien if (*cp == 0) { 194059243Sobrien if (*v == 0) 194159243Sobrien return f == 0.0 ? (RLIM_TYPE) 0 : restrict_limit((f + 0.5) * lp->limdiv); 194259243Sobrien cp = *v; 194359243Sobrien } 194459243Sobrien switch (*cp) { 194559243Sobrien# ifdef RLIMIT_CPU 194659243Sobrien case ':': 194759243Sobrien if (lp->limconst != RLIMIT_CPU) 194859243Sobrien goto badscal; 194959243Sobrien return f == 0.0 ? (RLIM_TYPE) 0 : restrict_limit((f * 60.0 + atof(short2str(cp + 1)))); 195059243Sobrien case 'h': 195159243Sobrien if (lp->limconst != RLIMIT_CPU) 195259243Sobrien goto badscal; 195359243Sobrien limtail(cp, "hours"); 195459243Sobrien f *= 3600.0; 195559243Sobrien break; 195659243Sobrien case 'm': 195759243Sobrien if (lp->limconst == RLIMIT_CPU) { 195859243Sobrien limtail(cp, "minutes"); 195959243Sobrien f *= 60.0; 196059243Sobrien break; 196159243Sobrien } 196259243Sobrien *cp = 'm'; 196359243Sobrien limtail(cp, "megabytes"); 196459243Sobrien f *= 1024.0 * 1024.0; 196559243Sobrien break; 196659243Sobrien case 's': 196759243Sobrien if (lp->limconst != RLIMIT_CPU) 196859243Sobrien goto badscal; 196959243Sobrien limtail(cp, "seconds"); 197059243Sobrien break; 197159243Sobrien# endif /* RLIMIT_CPU */ 197259243Sobrien case 'M': 197359243Sobrien# ifdef RLIMIT_CPU 197459243Sobrien if (lp->limconst == RLIMIT_CPU) 197559243Sobrien goto badscal; 197659243Sobrien# endif /* RLIMIT_CPU */ 197759243Sobrien *cp = 'm'; 197859243Sobrien limtail(cp, "megabytes"); 197959243Sobrien f *= 1024.0 * 1024.0; 198059243Sobrien break; 198159243Sobrien case 'k': 198259243Sobrien# ifdef RLIMIT_CPU 198359243Sobrien if (lp->limconst == RLIMIT_CPU) 198459243Sobrien goto badscal; 198559243Sobrien# endif /* RLIMIT_CPU */ 198659243Sobrien limtail(cp, "kbytes"); 198759243Sobrien f *= 1024.0; 198859243Sobrien break; 198959243Sobrien case 'b': 199059243Sobrien# ifdef RLIMIT_CPU 199159243Sobrien if (lp->limconst == RLIMIT_CPU) 199259243Sobrien goto badscal; 199359243Sobrien# endif /* RLIMIT_CPU */ 199459243Sobrien limtail(cp, "blocks"); 199559243Sobrien f *= 512.0; 199659243Sobrien break; 199759243Sobrien case 'u': 199859243Sobrien limtail(cp, "unlimited"); 199959243Sobrien return ((RLIM_TYPE) RLIM_INFINITY); 200059243Sobrien default: 200159243Sobrien# ifdef RLIMIT_CPU 200259243Sobrienbadscal: 200359243Sobrien# endif /* RLIMIT_CPU */ 200459243Sobrien stderror(ERR_NAME | ERR_SCALEF); 200559243Sobrien } 200659243Sobrien# ifdef convex 200759243Sobrien return f == 0.0 ? (RLIM_TYPE) 0 : restrict_limit((f + 0.5)); 200859243Sobrien# else 200959243Sobrien f += 0.5; 201059243Sobrien if (f > (float) RLIM_INFINITY) 201159243Sobrien return ((RLIM_TYPE) RLIM_INFINITY); 201259243Sobrien else 201359243Sobrien return ((RLIM_TYPE) f); 201459243Sobrien# endif /* convex */ 201559243Sobrien} 201659243Sobrien 201759243Sobrienstatic void 201859243Sobrienlimtail(cp, str) 201959243Sobrien Char *cp; 202059243Sobrien char *str; 202159243Sobrien{ 202259243Sobrien while (*cp && *cp == *str) 202359243Sobrien cp++, str++; 202459243Sobrien if (*cp) 202559243Sobrien stderror(ERR_BADSCALE, str); 202659243Sobrien} 202759243Sobrien 202859243Sobrien 202959243Sobrien/*ARGSUSED*/ 203059243Sobrienstatic void 203159243Sobrienplim(lp, hard) 203259243Sobrien register struct limits *lp; 203359243Sobrien int hard; 203459243Sobrien{ 203559243Sobrien# ifdef BSDLIMIT 203659243Sobrien struct rlimit rlim; 203759243Sobrien# endif /* BSDLIMIT */ 203859243Sobrien RLIM_TYPE limit; 203959243Sobrien int div = lp->limdiv; 204059243Sobrien 204159243Sobrien xprintf("%s \t", lp->limname); 204259243Sobrien 204359243Sobrien# ifndef BSDLIMIT 204459243Sobrien limit = ulimit(lp->limconst, 0); 204559243Sobrien# ifdef aiws 204659243Sobrien if (lp->limconst == RLIMIT_DATA) 204759243Sobrien limit -= 0x20000000; 204859243Sobrien# endif /* aiws */ 204959243Sobrien# else /* BSDLIMIT */ 205059243Sobrien (void) getrlimit(lp->limconst, &rlim); 205159243Sobrien limit = hard ? rlim.rlim_max : rlim.rlim_cur; 205259243Sobrien# endif /* BSDLIMIT */ 205359243Sobrien 205459243Sobrien# if !defined(BSDLIMIT) || defined(FILESIZE512) 205559243Sobrien /* 205659243Sobrien * Christos: filesize comes in 512 blocks. we divide by 2 to get 1024 205759243Sobrien * blocks. Note we cannot pre-multiply cause we might overflow (A/UX) 205859243Sobrien */ 205959243Sobrien if (lp->limconst == RLIMIT_FSIZE) { 206059243Sobrien if (limit >= (RLIM_INFINITY / 512)) 206159243Sobrien limit = RLIM_INFINITY; 206259243Sobrien else 206359243Sobrien div = (div == 1024 ? 2 : 1); 206459243Sobrien } 206559243Sobrien# endif /* !BSDLIMIT || FILESIZE512 */ 206659243Sobrien 206759243Sobrien if (limit == RLIM_INFINITY) 206859243Sobrien xprintf("unlimited"); 206959243Sobrien else 207059243Sobrien# ifdef RLIMIT_CPU 207159243Sobrien if (lp->limconst == RLIMIT_CPU) 207259243Sobrien psecs((long) limit); 207359243Sobrien else 207459243Sobrien# endif /* RLIMIT_CPU */ 207559243Sobrien xprintf("%ld %s", (long) (limit / div), lp->limscale); 207659243Sobrien xputchar('\n'); 207759243Sobrien} 207859243Sobrien 207959243Sobrien/*ARGSUSED*/ 208059243Sobrienvoid 208159243Sobriendounlimit(v, c) 208259243Sobrien register Char **v; 208359243Sobrien struct command *c; 208459243Sobrien{ 208559243Sobrien register struct limits *lp; 208659243Sobrien int lerr = 0; 208759243Sobrien int hard = 0; 208859243Sobrien int force = 0; 208959243Sobrien 209059243Sobrien USE(c); 209159243Sobrien while (*++v && **v == '-') { 209259243Sobrien Char *vp = *v; 209359243Sobrien while (*++vp) 209459243Sobrien switch (*vp) { 209559243Sobrien case 'f': 209659243Sobrien force = 1; 209759243Sobrien break; 209859243Sobrien case 'h': 209959243Sobrien hard = 1; 210059243Sobrien break; 210159243Sobrien default: 210259243Sobrien stderror(ERR_ULIMUS); 210359243Sobrien break; 210459243Sobrien } 210559243Sobrien } 210659243Sobrien 210759243Sobrien if (*v == 0) { 210859243Sobrien for (lp = limits; lp->limconst >= 0; lp++) 210959243Sobrien if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0) 211059243Sobrien lerr++; 211159243Sobrien if (!force && lerr) 211259243Sobrien stderror(ERR_SILENT); 211359243Sobrien return; 211459243Sobrien } 211559243Sobrien while (*v) { 211659243Sobrien lp = findlim(*v++); 211759243Sobrien if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0 && !force) 211859243Sobrien stderror(ERR_SILENT); 211959243Sobrien } 212059243Sobrien} 212159243Sobrien 212259243Sobrienstatic int 212359243Sobriensetlim(lp, hard, limit) 212459243Sobrien register struct limits *lp; 212559243Sobrien int hard; 212659243Sobrien RLIM_TYPE limit; 212759243Sobrien{ 212859243Sobrien# ifdef BSDLIMIT 212959243Sobrien struct rlimit rlim; 213059243Sobrien 213159243Sobrien (void) getrlimit(lp->limconst, &rlim); 213259243Sobrien 213359243Sobrien# ifdef FILESIZE512 213459243Sobrien /* Even though hpux has setrlimit(), it expects fsize in 512 byte blocks */ 213559243Sobrien if (limit != RLIM_INFINITY && lp->limconst == RLIMIT_FSIZE) 213659243Sobrien limit /= 512; 213759243Sobrien# endif /* FILESIZE512 */ 213859243Sobrien if (hard) 213959243Sobrien rlim.rlim_max = limit; 214059243Sobrien else if (limit == RLIM_INFINITY && euid != 0) 214159243Sobrien rlim.rlim_cur = rlim.rlim_max; 214259243Sobrien else 214359243Sobrien rlim.rlim_cur = limit; 214459243Sobrien 214559243Sobrien if (setrlimit(lp->limconst, &rlim) < 0) { 214659243Sobrien# else /* BSDLIMIT */ 214759243Sobrien if (limit != RLIM_INFINITY && lp->limconst == RLIMIT_FSIZE) 214859243Sobrien limit /= 512; 214959243Sobrien# ifdef aiws 215059243Sobrien if (lp->limconst == RLIMIT_DATA) 215159243Sobrien limit += 0x20000000; 215259243Sobrien# endif /* aiws */ 215359243Sobrien if (ulimit(toset(lp->limconst), limit) < 0) { 215459243Sobrien# endif /* BSDLIMIT */ 215559243Sobrien xprintf(CGETS(15, 1, "%s: %s: Can't %s%s limit\n"), bname, lp->limname, 215659243Sobrien limit == RLIM_INFINITY ? CGETS(15, 2, "remove") : 215759243Sobrien CGETS(15, 3, "set"), 215859243Sobrien hard ? CGETS(14, 4, " hard") : ""); 215959243Sobrien return (-1); 216059243Sobrien } 216159243Sobrien return (0); 216259243Sobrien} 216359243Sobrien 216459243Sobrien#endif /* !HAVENOLIMIT */ 216559243Sobrien 216659243Sobrien/*ARGSUSED*/ 216759243Sobrienvoid 216859243Sobriendosuspend(v, c) 216959243Sobrien Char **v; 217059243Sobrien struct command *c; 217159243Sobrien{ 217259243Sobrien#ifdef BSDJOBS 217359243Sobrien int ctpgrp; 217459243Sobrien 217559243Sobrien signalfun_t old; 217659243Sobrien#endif /* BSDJOBS */ 217759243Sobrien 217859243Sobrien USE(c); 217959243Sobrien USE(v); 218059243Sobrien 218159243Sobrien if (loginsh) 218259243Sobrien stderror(ERR_SUSPLOG); 218359243Sobrien untty(); 218459243Sobrien 218559243Sobrien#ifdef BSDJOBS 218659243Sobrien old = signal(SIGTSTP, SIG_DFL); 218759243Sobrien (void) kill(0, SIGTSTP); 218859243Sobrien /* the shell stops here */ 218959243Sobrien (void) signal(SIGTSTP, old); 219059243Sobrien#else /* !BSDJOBS */ 219159243Sobrien stderror(ERR_JOBCONTROL); 219259243Sobrien#endif /* BSDJOBS */ 219359243Sobrien 219459243Sobrien#ifdef BSDJOBS 219559243Sobrien if (tpgrp != -1) { 219659243Sobrienretry: 219759243Sobrien ctpgrp = tcgetpgrp(FSHTTY); 219859243Sobrien if (ctpgrp != opgrp) { 219959243Sobrien old = signal(SIGTTIN, SIG_DFL); 220059243Sobrien (void) kill(0, SIGTTIN); 220159243Sobrien (void) signal(SIGTTIN, old); 220259243Sobrien goto retry; 220359243Sobrien } 220459243Sobrien (void) setpgid(0, shpgrp); 220559243Sobrien (void) tcsetpgrp(FSHTTY, shpgrp); 220659243Sobrien } 220759243Sobrien#endif /* BSDJOBS */ 220859243Sobrien (void) setdisc(FSHTTY); 220959243Sobrien} 221059243Sobrien 221159243Sobrien/* This is the dreaded EVAL built-in. 221259243Sobrien * If you don't fiddle with file descriptors, and reset didfds, 221359243Sobrien * this command will either ignore redirection inside or outside 221459243Sobrien * its arguments, e.g. eval "date >x" vs. eval "date" >x 221559243Sobrien * The stuff here seems to work, but I did it by trial and error rather 221659243Sobrien * than really knowing what was going on. If tpgrp is zero, we are 221759243Sobrien * probably a background eval, e.g. "eval date &", and we want to 221859243Sobrien * make sure that any processes we start stay in our pgrp. 221959243Sobrien * This is also the case for "time eval date" -- stay in same pgrp. 222059243Sobrien * Otherwise, under stty tostop, processes will stop in the wrong 222159243Sobrien * pgrp, with no way for the shell to get them going again. -IAN! 222259243Sobrien */ 222359243Sobrien 222459243Sobrienstatic Char **gv = NULL, **gav = NULL; 222559243Sobrien 222659243Sobrien/*ARGSUSED*/ 222759243Sobrienvoid 222859243Sobriendoeval(v, c) 222959243Sobrien Char **v; 223059243Sobrien struct command *c; 223159243Sobrien{ 223259243Sobrien Char **oevalvec; 223359243Sobrien Char *oevalp; 223459243Sobrien int odidfds; 223559243Sobrien#ifndef CLOSE_ON_EXEC 223659243Sobrien int odidcch; 223759243Sobrien#endif /* CLOSE_ON_EXEC */ 223859243Sobrien jmp_buf_t osetexit; 223959243Sobrien int my_reenter; 224059243Sobrien Char **savegv; 224159243Sobrien int saveIN, saveOUT, saveDIAG; 224259243Sobrien int oSHIN, oSHOUT, oSHDIAG; 224359243Sobrien 224459243Sobrien USE(c); 224559243Sobrien oevalvec = evalvec; 224659243Sobrien oevalp = evalp; 224759243Sobrien odidfds = didfds; 224859243Sobrien#ifndef CLOSE_ON_EXEC 224959243Sobrien odidcch = didcch; 225059243Sobrien#endif /* CLOSE_ON_EXEC */ 225159243Sobrien oSHIN = SHIN; 225259243Sobrien oSHOUT = SHOUT; 225359243Sobrien oSHDIAG = SHDIAG; 225459243Sobrien 225559243Sobrien savegv = gv; 225659243Sobrien gav = v; 225759243Sobrien 225859243Sobrien gav++; 225959243Sobrien if (*gav == 0) 226059243Sobrien return; 226159243Sobrien gflag = 0, tglob(gav); 226259243Sobrien if (gflag) { 226359243Sobrien gv = gav = globall(gav); 226459243Sobrien gargv = 0; 226559243Sobrien if (gav == 0) 226659243Sobrien stderror(ERR_NOMATCH); 226759243Sobrien gav = copyblk(gav); 226859243Sobrien } 226959243Sobrien else { 227059243Sobrien gv = NULL; 227159243Sobrien gav = copyblk(gav); 227259243Sobrien trim(gav); 227359243Sobrien } 227459243Sobrien 227559243Sobrien saveIN = dcopy(SHIN, -1); 227659243Sobrien saveOUT = dcopy(SHOUT, -1); 227759243Sobrien saveDIAG = dcopy(SHDIAG, -1); 227859243Sobrien 227959243Sobrien getexit(osetexit); 228059243Sobrien 228159243Sobrien /* PWP: setjmp/longjmp bugfix for optimizing compilers */ 228259243Sobrien#ifdef cray 228359243Sobrien my_reenter = 1; /* assume non-zero return val */ 228459243Sobrien if (setexit() == 0) { 228559243Sobrien my_reenter = 0; /* Oh well, we were wrong */ 228659243Sobrien#else /* !cray */ 228759243Sobrien if ((my_reenter = setexit()) == 0) { 228859243Sobrien#endif /* cray */ 228959243Sobrien evalvec = gav; 229059243Sobrien evalp = 0; 229159243Sobrien SHIN = dcopy(0, -1); 229259243Sobrien SHOUT = dcopy(1, -1); 229359243Sobrien SHDIAG = dcopy(2, -1); 229459243Sobrien#ifndef CLOSE_ON_EXEC 229559243Sobrien didcch = 0; 229659243Sobrien#endif /* CLOSE_ON_EXEC */ 229759243Sobrien didfds = 0; 229859243Sobrien process(0); 229959243Sobrien } 230059243Sobrien 230159243Sobrien evalvec = oevalvec; 230259243Sobrien evalp = oevalp; 230359243Sobrien doneinp = 0; 230459243Sobrien#ifndef CLOSE_ON_EXEC 230559243Sobrien didcch = odidcch; 230659243Sobrien#endif /* CLOSE_ON_EXEC */ 230759243Sobrien didfds = odidfds; 230859243Sobrien (void) close(SHIN); 230959243Sobrien (void) close(SHOUT); 231059243Sobrien (void) close(SHDIAG); 231159243Sobrien SHIN = dmove(saveIN, oSHIN); 231259243Sobrien SHOUT = dmove(saveOUT, oSHOUT); 231359243Sobrien SHDIAG = dmove(saveDIAG, oSHDIAG); 231459243Sobrien 231559243Sobrien if (gv) 231659243Sobrien blkfree(gv); 231759243Sobrien 231859243Sobrien gv = savegv; 231959243Sobrien resexit(osetexit); 232059243Sobrien if (my_reenter) 232159243Sobrien stderror(ERR_SILENT); 232259243Sobrien} 232359243Sobrien 232459243Sobrien/*************************************************************************/ 232559243Sobrien/* print list of builtin commands */ 232659243Sobrien 232759243Sobrien/*ARGSUSED*/ 232859243Sobrienvoid 232959243Sobriendobuiltins(v, c) 233059243SobrienChar **v; 233159243Sobrienstruct command *c; 233259243Sobrien{ 233359243Sobrien /* would use print_by_column() in tw.parse.c but that assumes 233459243Sobrien * we have an array of Char * to pass.. (sg) 233559243Sobrien */ 233659243Sobrien extern int Tty_raw_mode; 233759243Sobrien extern int TermH; /* from the editor routines */ 233859243Sobrien extern int lbuffed; /* from sh.print.c */ 233959243Sobrien 234059243Sobrien register struct biltins *b; 234159243Sobrien register int row, col, columns, rows; 234259243Sobrien unsigned int w, maxwidth; 234359243Sobrien 234459243Sobrien USE(c); 234559243Sobrien USE(v); 234659243Sobrien lbuffed = 0; /* turn off line buffering */ 234759243Sobrien 234859243Sobrien /* find widest string */ 234959243Sobrien for (maxwidth = 0, b = bfunc; b < &bfunc[nbfunc]; ++b) 235059243Sobrien maxwidth = max(maxwidth, strlen(b->bname)); 235159243Sobrien ++maxwidth; /* for space */ 235259243Sobrien 235359243Sobrien columns = (TermH + 1) / maxwidth; /* PWP: terminal size change */ 235459243Sobrien if (!columns) 235559243Sobrien columns = 1; 235659243Sobrien rows = (nbfunc + (columns - 1)) / columns; 235759243Sobrien 235859243Sobrien for (b = bfunc, row = 0; row < rows; row++) { 235959243Sobrien for (col = 0; col < columns; col++) { 236059243Sobrien if (b < &bfunc[nbfunc]) { 236159243Sobrien w = strlen(b->bname); 236259243Sobrien xprintf("%s", b->bname); 236359243Sobrien if (col < (columns - 1)) /* Not last column? */ 236459243Sobrien for (; w < maxwidth; w++) 236559243Sobrien xputchar(' '); 236659243Sobrien ++b; 236759243Sobrien } 236859243Sobrien } 236959243Sobrien if (row < (rows - 1)) { 237059243Sobrien if (Tty_raw_mode) 237159243Sobrien xputchar('\r'); 237259243Sobrien xputchar('\n'); 237359243Sobrien } 237459243Sobrien } 237559243Sobrien#ifdef WINNT 237659243Sobrien nt_print_builtins(maxwidth); 237759243Sobrien#else 237859243Sobrien if (Tty_raw_mode) 237959243Sobrien xputchar('\r'); 238059243Sobrien xputchar('\n'); 238159243Sobrien#endif /* WINNT */ 238259243Sobrien 238359243Sobrien lbuffed = 1; /* turn back on line buffering */ 238459243Sobrien flush(); 238559243Sobrien} 238659243Sobrien 238759243Sobrienvoid 238859243Sobriennlsinit() 238959243Sobrien{ 239059243Sobrien#ifdef NLS_CATALOGS 239159243Sobrien catd = catopen("tcsh", MCLoadBySet); 239259243Sobrien#endif 239359243Sobrien#ifdef WINNT 239459243Sobrien nls_dll_init(); 239559243Sobrien#endif /* WINNT */ 239659243Sobrien errinit(); /* init the errorlist in correct locale */ 239759243Sobrien mesginit(); /* init the messages for signals */ 239859243Sobrien dateinit(); /* init the messages for dates */ 239959243Sobrien editinit(); /* init the editor messages */ 240059243Sobrien terminit(); /* init the termcap messages */ 240159243Sobrien} 2402