sh.func.c revision 131962
1131962Smp/* $Header: /src/pub/tcsh/sh.func.c,v 3.111 2004/05/13 15:23:39 christos Exp $ */ 259243Sobrien/* 359243Sobrien * sh.func.c: csh builtin functions 459243Sobrien */ 559243Sobrien/*- 659243Sobrien * Copyright (c) 1980, 1991 The Regents of the University of California. 759243Sobrien * All rights reserved. 859243Sobrien * 959243Sobrien * Redistribution and use in source and binary forms, with or without 1059243Sobrien * modification, are permitted provided that the following conditions 1159243Sobrien * are met: 1259243Sobrien * 1. Redistributions of source code must retain the above copyright 1359243Sobrien * notice, this list of conditions and the following disclaimer. 1459243Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1559243Sobrien * notice, this list of conditions and the following disclaimer in the 1659243Sobrien * documentation and/or other materials provided with the distribution. 17100616Smp * 3. Neither the name of the University nor the names of its contributors 1859243Sobrien * may be used to endorse or promote products derived from this software 1959243Sobrien * without specific prior written permission. 2059243Sobrien * 2159243Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2259243Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2359243Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2459243Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2559243Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2659243Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2759243Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2859243Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2959243Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3059243Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3159243Sobrien * SUCH DAMAGE. 3259243Sobrien */ 3359243Sobrien#include "sh.h" 3459243Sobrien 35131962SmpRCSID("$Id: sh.func.c,v 3.111 2004/05/13 15:23:39 christos Exp $") 3659243Sobrien 3759243Sobrien#include "ed.h" 3859243Sobrien#include "tw.h" 3959243Sobrien#include "tc.h" 4069408Sache#ifdef WINNT_NATIVE 4159243Sobrien#include "nt.const.h" 4269408Sache#endif /* WINNT_NATIVE */ 4359243Sobrien 4459243Sobrien/* 4559243Sobrien * C shell 4659243Sobrien */ 4759243Sobrienextern int just_signaled; 4859243Sobrienextern char **environ; 4959243Sobrien 5059243Sobrienextern bool MapsAreInited; 5159243Sobrienextern bool NLSMapsAreInited; 5259243Sobrienextern bool NoNLSRebind; 5359243Sobrienextern bool GotTermCaps; 5459243Sobrien 5559243Sobrienstatic int zlast = -1; 5659243Sobrien 5759243Sobrienstatic void islogin __P((void)); 5859243Sobrienstatic void preread __P((void)); 5959243Sobrienstatic void doagain __P((void)); 6059243Sobrienstatic char *isrchx __P((int)); 6159243Sobrienstatic void search __P((int, int, Char *)); 6259243Sobrienstatic int getword __P((Char *)); 6359243Sobrienstatic void toend __P((void)); 6459243Sobrienstatic void xecho __P((int, Char **)); 6559243Sobrienstatic bool islocale_var __P((Char *)); 66131962Smpstatic void wpfree __P((struct whyle *)); 6759243Sobrien 6859243Sobrienstruct biltins * 6959243Sobrienisbfunc(t) 7059243Sobrien struct command *t; 7159243Sobrien{ 7259243Sobrien register Char *cp = t->t_dcom[0]; 7359243Sobrien register struct biltins *bp, *bp1, *bp2; 7459243Sobrien static struct biltins label = {"", dozip, 0, 0}; 7559243Sobrien static struct biltins foregnd = {"%job", dofg1, 0, 0}; 7659243Sobrien static struct biltins backgnd = {"%job &", dobg1, 0, 0}; 7759243Sobrien 7859243Sobrien /* 7959243Sobrien * We never match a builtin that has quoted the first 8059243Sobrien * character; this has been the traditional way to escape 8159243Sobrien * builtin commands. 8259243Sobrien */ 8359243Sobrien if (*cp & QUOTE) 8459243Sobrien return NULL; 8559243Sobrien 8659243Sobrien if (*cp != ':' && lastchr(cp) == ':') { 8759243Sobrien label.bname = short2str(cp); 8859243Sobrien return (&label); 8959243Sobrien } 9059243Sobrien if (*cp == '%') { 9159243Sobrien if (t->t_dflg & F_AMPERSAND) { 9259243Sobrien t->t_dflg &= ~F_AMPERSAND; 9359243Sobrien backgnd.bname = short2str(cp); 9459243Sobrien return (&backgnd); 9559243Sobrien } 9659243Sobrien foregnd.bname = short2str(cp); 9759243Sobrien return (&foregnd); 9859243Sobrien } 9959243Sobrien#ifdef WARP 10059243Sobrien /* 10159243Sobrien * This is a perhaps kludgy way to determine if the warp builtin is to be 10259243Sobrien * acknowledged or not. If checkwarp() fails, then we are to assume that 10359243Sobrien * the warp command is invalid, and carry on as we would handle any other 10459243Sobrien * non-builtin command. -- JDK 2/4/88 10559243Sobrien */ 10659243Sobrien if (eq(STRwarp, cp) && !checkwarp()) { 10759243Sobrien return (0); /* this builtin disabled */ 10859243Sobrien } 10959243Sobrien#endif /* WARP */ 11059243Sobrien /* 11159243Sobrien * Binary search Bp1 is the beginning of the current search range. Bp2 is 11259243Sobrien * one past the end. 11359243Sobrien */ 11459243Sobrien for (bp1 = bfunc, bp2 = bfunc + nbfunc; bp1 < bp2;) { 11559243Sobrien int i; 11659243Sobrien 11759243Sobrien bp = bp1 + ((bp2 - bp1) >> 1); 11859243Sobrien if ((i = ((char) *cp) - *bp->bname) == 0 && 11959243Sobrien (i = StrQcmp(cp, str2short(bp->bname))) == 0) 12059243Sobrien return bp; 12159243Sobrien if (i < 0) 12259243Sobrien bp2 = bp; 12359243Sobrien else 12459243Sobrien bp1 = bp + 1; 12559243Sobrien } 12669408Sache#ifdef WINNT_NATIVE 12759243Sobrien return nt_check_additional_builtins(cp); 12869408Sache#endif /*WINNT_NATIVE*/ 12959243Sobrien return (0); 13059243Sobrien} 13159243Sobrien 13259243Sobrienvoid 13359243Sobrienfunc(t, bp) 13459243Sobrien register struct command *t; 13559243Sobrien register struct biltins *bp; 13659243Sobrien{ 13759243Sobrien int i; 13859243Sobrien 13959243Sobrien xechoit(t->t_dcom); 14059243Sobrien setname(bp->bname); 14159243Sobrien i = blklen(t->t_dcom) - 1; 14259243Sobrien if (i < bp->minargs) 14359243Sobrien stderror(ERR_NAME | ERR_TOOFEW); 14459243Sobrien if (i > bp->maxargs) 14559243Sobrien stderror(ERR_NAME | ERR_TOOMANY); 14659243Sobrien (*bp->bfunct) (t->t_dcom, t); 14759243Sobrien} 14859243Sobrien 14959243Sobrien/*ARGSUSED*/ 15059243Sobrienvoid 15159243Sobriendoonintr(v, c) 15259243Sobrien Char **v; 15359243Sobrien struct command *c; 15459243Sobrien{ 15559243Sobrien register Char *cp; 15659243Sobrien register Char *vv = v[1]; 15759243Sobrien 15859243Sobrien USE(c); 15959243Sobrien if (parintr == SIG_IGN) 16059243Sobrien return; 16159243Sobrien if (setintr && intty) 16259243Sobrien stderror(ERR_NAME | ERR_TERMINAL); 16359243Sobrien cp = gointr; 16459243Sobrien gointr = 0; 16559243Sobrien xfree((ptr_t) cp); 16659243Sobrien if (vv == 0) { 16759243Sobrien#ifdef BSDSIGS 16859243Sobrien if (setintr) { 16959243Sobrien (void) sigblock(sigmask(SIGINT)); 17059243Sobrien (void) signal(SIGINT, pintr); 17159243Sobrien } 17259243Sobrien else 17359243Sobrien (void) signal(SIGINT, SIG_DFL); 17459243Sobrien#else /* !BSDSIGS */ 17559243Sobrien if (setintr) { 17659243Sobrien (void) sighold(SIGINT); 17759243Sobrien (void) sigset(SIGINT, pintr); 17859243Sobrien } 17959243Sobrien else 18059243Sobrien (void) sigset(SIGINT, SIG_DFL); 18159243Sobrien#endif /* BSDSIGS */ 18259243Sobrien gointr = 0; 18359243Sobrien } 18459243Sobrien else if (eq((vv = strip(vv)), STRminus)) { 18559243Sobrien#ifdef BSDSIGS 18659243Sobrien (void) signal(SIGINT, SIG_IGN); 18759243Sobrien#else /* !BSDSIGS */ 18859243Sobrien (void) sigset(SIGINT, SIG_IGN); 18959243Sobrien#endif /* BSDSIGS */ 19059243Sobrien gointr = Strsave(STRminus); 19159243Sobrien } 19259243Sobrien else { 19359243Sobrien gointr = Strsave(vv); 19459243Sobrien#ifdef BSDSIGS 19559243Sobrien (void) signal(SIGINT, pintr); 19659243Sobrien#else /* !BSDSIGS */ 19759243Sobrien (void) sigset(SIGINT, pintr); 19859243Sobrien#endif /* BSDSIGS */ 19959243Sobrien } 20059243Sobrien} 20159243Sobrien 20259243Sobrien/*ARGSUSED*/ 20359243Sobrienvoid 20459243Sobriendonohup(v, c) 20559243Sobrien Char **v; 20659243Sobrien struct command *c; 20759243Sobrien{ 20859243Sobrien USE(c); 20959243Sobrien USE(v); 21059243Sobrien if (intty) 21159243Sobrien stderror(ERR_NAME | ERR_TERMINAL); 21259243Sobrien if (setintr == 0) { 21359243Sobrien (void) signal(SIGHUP, SIG_IGN); 21459243Sobrien#ifdef CC 21559243Sobrien submit(getpid()); 21659243Sobrien#endif /* CC */ 21759243Sobrien } 21859243Sobrien} 21959243Sobrien 22059243Sobrien/*ARGSUSED*/ 22159243Sobrienvoid 22259243Sobriendohup(v, c) 22359243Sobrien Char **v; 22459243Sobrien struct command *c; 22559243Sobrien{ 22659243Sobrien USE(c); 22759243Sobrien USE(v); 22859243Sobrien if (intty) 22959243Sobrien stderror(ERR_NAME | ERR_TERMINAL); 23059243Sobrien if (setintr == 0) 23159243Sobrien (void) signal(SIGHUP, SIG_DFL); 23259243Sobrien} 23359243Sobrien 23459243Sobrien 23559243Sobrien/*ARGSUSED*/ 23659243Sobrienvoid 23759243Sobriendozip(v, c) 23859243Sobrien Char **v; 23959243Sobrien struct command *c; 24059243Sobrien{ 24159243Sobrien USE(c); 24259243Sobrien USE(v); 24359243Sobrien} 24459243Sobrien 24559243Sobrien/*ARGSUSED*/ 24659243Sobrienvoid 24759243Sobriendofiletest(v, c) 24859243Sobrien Char **v; 24959243Sobrien struct command *c; 25059243Sobrien{ 25159243Sobrien Char **fileptr, *ftest, *res; 25259243Sobrien 25359243Sobrien if (*(ftest = *++v) != '-') 25459243Sobrien stderror(ERR_NAME | ERR_FILEINQ); 25559243Sobrien ++v; 25659243Sobrien 25759243Sobrien gflag = 0; 25859243Sobrien tglob(v); 25959243Sobrien if (gflag) { 26059243Sobrien v = globall(v); 26159243Sobrien if (v == 0) 26259243Sobrien stderror(ERR_NAME | ERR_NOMATCH); 26359243Sobrien } 26459243Sobrien else 26559243Sobrien v = gargv = saveblk(v); 26659243Sobrien trim(v); 26759243Sobrien 26859243Sobrien while (*(fileptr = v++) != '\0') { 26959243Sobrien xprintf("%S", res = filetest(ftest, &fileptr, 0)); 27059243Sobrien xfree((ptr_t) res); 27159243Sobrien if (*v) 27259243Sobrien xprintf(" "); 27359243Sobrien } 27459243Sobrien xprintf("\n"); 27559243Sobrien 27659243Sobrien if (gargv) { 27759243Sobrien blkfree(gargv); 27859243Sobrien gargv = 0; 27959243Sobrien } 28059243Sobrien} 28159243Sobrien 28259243Sobrienvoid 28359243Sobrienprvars() 28459243Sobrien{ 28559243Sobrien plist(&shvhed, VAR_ALL); 28659243Sobrien} 28759243Sobrien 28859243Sobrien/*ARGSUSED*/ 28959243Sobrienvoid 29059243Sobriendoalias(v, c) 29159243Sobrien register Char **v; 29259243Sobrien struct command *c; 29359243Sobrien{ 29459243Sobrien register struct varent *vp; 29559243Sobrien register Char *p; 29659243Sobrien 29759243Sobrien USE(c); 29859243Sobrien v++; 29959243Sobrien p = *v++; 30059243Sobrien if (p == 0) 30159243Sobrien plist(&aliases, VAR_ALL); 30259243Sobrien else if (*v == 0) { 30359243Sobrien vp = adrof1(strip(p), &aliases); 304100616Smp if (vp && vp->vec) 30559243Sobrien blkpr(vp->vec), xputchar('\n'); 30659243Sobrien } 30759243Sobrien else { 30859243Sobrien if (eq(p, STRalias) || eq(p, STRunalias)) { 30959243Sobrien setname(short2str(p)); 31059243Sobrien stderror(ERR_NAME | ERR_DANGER); 31159243Sobrien } 31259243Sobrien set1(strip(p), saveblk(v), &aliases, VAR_READWRITE); 31359243Sobrien tw_cmd_free(); 31459243Sobrien } 31559243Sobrien} 31659243Sobrien 31759243Sobrien/*ARGSUSED*/ 31859243Sobrienvoid 31959243Sobrienunalias(v, c) 32059243Sobrien Char **v; 32159243Sobrien struct command *c; 32259243Sobrien{ 32359243Sobrien USE(c); 32459243Sobrien unset1(v, &aliases); 32559243Sobrien tw_cmd_free(); 32659243Sobrien} 32759243Sobrien 32859243Sobrien/*ARGSUSED*/ 32959243Sobrienvoid 33059243Sobriendologout(v, c) 33159243Sobrien Char **v; 33259243Sobrien struct command *c; 33359243Sobrien{ 33459243Sobrien USE(c); 33559243Sobrien USE(v); 33659243Sobrien islogin(); 33759243Sobrien goodbye(NULL, NULL); 33859243Sobrien} 33959243Sobrien 34059243Sobrien/*ARGSUSED*/ 34159243Sobrienvoid 34259243Sobriendologin(v, c) 34359243Sobrien Char **v; 34459243Sobrien struct command *c; 34559243Sobrien{ 346131962Smp#ifdef WINNT_NATIVE 34759243Sobrien USE(c); 34859243Sobrien USE(v); 34969408Sache#else /* !WINNT_NATIVE */ 350131962Smp char **p = short2blk(v); 351131962Smp USE(c); 35259243Sobrien islogin(); 35359243Sobrien rechist(NULL, adrof(STRsavehist) != NULL); 35459243Sobrien (void) signal(SIGTERM, parterm); 355131962Smp (void) execv(_PATH_BIN_LOGIN, p); 356131962Smp (void) execv(_PATH_USRBIN_LOGIN, p); 357131962Smp blkfree((Char **) p); 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 */ 449100616Smp execute(kp, (tpgrp > 0 ? tpgrp : -1), NULL, NULL, TRUE); 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{ 734100616Smp int i = 1; 73559243Sobrien 73659243Sobrien#ifdef BSDSIGS 73759243Sobrien register sigmask_t omask = 0; 73859243Sobrien#endif /* BSDSIGS */ 73959243Sobrien 740100616Smp do { 741100616Smp i *= getn(v[1]); 742100616Smp lshift(v, 2); 743100616Smp } while (v[0] != NULL && Strcmp(v[0], STRrepeat) == 0); 744100616Smp 74559243Sobrien if (setintr) 74659243Sobrien#ifdef BSDSIGS 74759243Sobrien omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT); 74859243Sobrien#else /* !BSDSIGS */ 74959243Sobrien (void) sighold(SIGINT); 75059243Sobrien#endif /* BSDSIGS */ 75159243Sobrien while (i > 0) { 75259243Sobrien if (setintr) 75359243Sobrien#ifdef BSDSIGS 75459243Sobrien (void) sigsetmask(omask); 75559243Sobrien#else /* !BSDSIGS */ 75659243Sobrien (void) sigrelse (SIGINT); 75759243Sobrien#endif /* BSDSIGS */ 75859243Sobrien reexecute(kp); 75959243Sobrien --i; 76059243Sobrien } 76159243Sobrien donefds(); 76259243Sobrien if (setintr) 76359243Sobrien#ifdef BSDSIGS 76459243Sobrien (void) sigsetmask(omask); 76559243Sobrien#else /* !BSDSIGS */ 76659243Sobrien (void) sigrelse (SIGINT); 76759243Sobrien#endif /* BSDSIGS */ 76859243Sobrien} 76959243Sobrien 77059243Sobrien/*ARGSUSED*/ 77159243Sobrienvoid 77259243Sobriendoswbrk(v, c) 77359243Sobrien Char **v; 77459243Sobrien struct command *c; 77559243Sobrien{ 77659243Sobrien USE(v); 77759243Sobrien USE(c); 77859243Sobrien search(TC_BRKSW, 0, NULL); 77959243Sobrien} 78059243Sobrien 78159243Sobrienint 78259243Sobriensrchx(cp) 78359243Sobrien Char *cp; 78459243Sobrien{ 78559243Sobrien struct srch *sp, *sp1, *sp2; 78659243Sobrien int i; 78759243Sobrien 78859243Sobrien /* 78959243Sobrien * Ignore keywords inside heredocs 79059243Sobrien */ 79159243Sobrien if (inheredoc) 79259243Sobrien return -1; 79359243Sobrien 79459243Sobrien /* 79559243Sobrien * Binary search Sp1 is the beginning of the current search range. Sp2 is 79659243Sobrien * one past the end. 79759243Sobrien */ 79859243Sobrien for (sp1 = srchn, sp2 = srchn + nsrchn; sp1 < sp2;) { 79959243Sobrien sp = sp1 + ((sp2 - sp1) >> 1); 80059243Sobrien if ((i = *cp - *sp->s_name) == 0 && 80159243Sobrien (i = Strcmp(cp, str2short(sp->s_name))) == 0) 80259243Sobrien return sp->s_value; 80359243Sobrien if (i < 0) 80459243Sobrien sp2 = sp; 80559243Sobrien else 80659243Sobrien sp1 = sp + 1; 80759243Sobrien } 80859243Sobrien return (-1); 80959243Sobrien} 81059243Sobrien 81159243Sobrienstatic char * 81259243Sobrienisrchx(n) 81359243Sobrien register int n; 81459243Sobrien{ 81559243Sobrien register struct srch *sp, *sp2; 81659243Sobrien 81759243Sobrien for (sp = srchn, sp2 = srchn + nsrchn; sp < sp2; sp++) 81859243Sobrien if (sp->s_value == n) 81959243Sobrien return (sp->s_name); 82059243Sobrien return (""); 82159243Sobrien} 82259243Sobrien 82359243Sobrien 82459243Sobrienstatic Char Stype; 82559243Sobrienstatic Char *Sgoal; 82659243Sobrien 82759243Sobrienstatic void 82859243Sobriensearch(type, level, goal) 82959243Sobrien int type; 83059243Sobrien register int level; 83159243Sobrien Char *goal; 83259243Sobrien{ 83359243Sobrien Char wordbuf[BUFSIZE]; 83459243Sobrien register Char *aword = wordbuf; 83559243Sobrien register Char *cp; 836131962Smp struct whyle *wp; 837131962Smp int wlevel = 0; 83859243Sobrien 83959243Sobrien Stype = (Char) type; 84059243Sobrien Sgoal = goal; 84159243Sobrien if (type == TC_GOTO) { 84259243Sobrien struct Ain a; 84369408Sache a.type = TCSH_F_SEEK; 84459243Sobrien a.f_seek = 0; 84559243Sobrien bseek(&a); 84659243Sobrien } 84759243Sobrien do { 84869408Sache if (intty && fseekp == feobp && aret == TCSH_F_SEEK) 84959243Sobrien printprompt(1, isrchx(type == TC_BREAK ? zlast : type)); 85059243Sobrien /* xprintf("? "), flush(); */ 85159243Sobrien aword[0] = 0; 85259243Sobrien (void) getword(aword); 85359243Sobrien switch (srchx(aword)) { 85459243Sobrien 85559243Sobrien case TC_ELSE: 85659243Sobrien if (level == 0 && type == TC_IF) 85759243Sobrien return; 85859243Sobrien break; 85959243Sobrien 86059243Sobrien case TC_IF: 86159243Sobrien while (getword(aword)) 86259243Sobrien continue; 86359243Sobrien if ((type == TC_IF || type == TC_ELSE) && 86459243Sobrien eq(aword, STRthen)) 86559243Sobrien level++; 86659243Sobrien break; 86759243Sobrien 86859243Sobrien case TC_ENDIF: 86959243Sobrien if (type == TC_IF || type == TC_ELSE) 87059243Sobrien level--; 87159243Sobrien break; 87259243Sobrien 87359243Sobrien case TC_FOREACH: 87459243Sobrien case TC_WHILE: 875131962Smp wlevel++; 87659243Sobrien if (type == TC_BREAK) 87759243Sobrien level++; 87859243Sobrien break; 87959243Sobrien 88059243Sobrien case TC_END: 881131962Smp if (type == TC_BRKSW) { 882131962Smp if (wlevel == 0) { 883131962Smp wp = whyles; 884131962Smp if (wp) { 885131962Smp whyles = wp->w_next; 886131962Smp wpfree(wp); 887131962Smp } 888131962Smp } 889131962Smp } 89059243Sobrien if (type == TC_BREAK) 89159243Sobrien level--; 892131962Smp wlevel--; 89359243Sobrien break; 89459243Sobrien 89559243Sobrien case TC_SWITCH: 89659243Sobrien if (type == TC_SWITCH || type == TC_BRKSW) 89759243Sobrien level++; 89859243Sobrien break; 89959243Sobrien 90059243Sobrien case TC_ENDSW: 90159243Sobrien if (type == TC_SWITCH || type == TC_BRKSW) 90259243Sobrien level--; 90359243Sobrien break; 90459243Sobrien 90559243Sobrien case TC_LABEL: 90659243Sobrien if (type == TC_GOTO && getword(aword) && eq(aword, goal)) 90759243Sobrien level = -1; 90859243Sobrien break; 90959243Sobrien 91059243Sobrien default: 91159243Sobrien if (type != TC_GOTO && (type != TC_SWITCH || level != 0)) 91259243Sobrien break; 91359243Sobrien if (lastchr(aword) != ':') 91459243Sobrien break; 91559243Sobrien aword[Strlen(aword) - 1] = 0; 91659243Sobrien if ((type == TC_GOTO && eq(aword, goal)) || 91759243Sobrien (type == TC_SWITCH && eq(aword, STRdefault))) 91859243Sobrien level = -1; 91959243Sobrien break; 92059243Sobrien 92159243Sobrien case TC_CASE: 92259243Sobrien if (type != TC_SWITCH || level != 0) 92359243Sobrien break; 92459243Sobrien (void) getword(aword); 92559243Sobrien if (lastchr(aword) == ':') 92659243Sobrien aword[Strlen(aword) - 1] = 0; 92759243Sobrien cp = strip(Dfix1(aword)); 92859243Sobrien if (Gmatch(goal, cp)) 92959243Sobrien level = -1; 93059243Sobrien xfree((ptr_t) cp); 93159243Sobrien break; 93259243Sobrien 93359243Sobrien case TC_DEFAULT: 93459243Sobrien if (type == TC_SWITCH && level == 0) 93559243Sobrien level = -1; 93659243Sobrien break; 93759243Sobrien } 93859243Sobrien (void) getword(NULL); 93959243Sobrien } while (level >= 0); 94059243Sobrien} 94159243Sobrien 94259243Sobrienstatic int 94359243Sobriengetword(wp) 94459243Sobrien register Char *wp; 94559243Sobrien{ 94659243Sobrien int found = 0, first; 94759243Sobrien int c, d; 94859243Sobrien 94959243Sobrien c = readc(1); 95059243Sobrien d = 0; 95159243Sobrien do { 95259243Sobrien while (c == ' ' || c == '\t') 95359243Sobrien c = readc(1); 95459243Sobrien if (c == '#') 95559243Sobrien do 95659243Sobrien c = readc(1); 95759243Sobrien while (c >= 0 && c != '\n'); 95859243Sobrien if (c < 0) 95959243Sobrien goto past; 96059243Sobrien if (c == '\n') { 96159243Sobrien if (wp) 96259243Sobrien break; 96359243Sobrien return (0); 96459243Sobrien } 96559243Sobrien unreadc(c); 96659243Sobrien found = 1; 96759243Sobrien first = 1; 96859243Sobrien do { 96959243Sobrien c = readc(1); 97059243Sobrien if (c == '\\' && (c = readc(1)) == '\n') 97159243Sobrien c = ' '; 97259243Sobrien if (c == '\'' || c == '"') { 97359243Sobrien if (d == 0) 97459243Sobrien d = c; 97559243Sobrien else if (d == c) 97659243Sobrien d = 0; 97759243Sobrien } 97859243Sobrien if (c < 0) 97959243Sobrien goto past; 98059243Sobrien if (wp) { 98159243Sobrien *wp++ = (Char) c; 98259243Sobrien *wp = '\0'; 98359243Sobrien } 98459243Sobrien if (!first && !d && c == '(') { 98559243Sobrien if (wp) { 98659243Sobrien unreadc(c); 98759243Sobrien *--wp = '\0'; 98859243Sobrien return found; 98959243Sobrien } 99059243Sobrien else 99159243Sobrien break; 99259243Sobrien } 99359243Sobrien first = 0; 99459243Sobrien } while ((d || (c != ' ' && c != '\t')) && c != '\n'); 99559243Sobrien } while (wp == 0); 99659243Sobrien 99759243Sobrien unreadc(c); 99859243Sobrien if (found) 99959243Sobrien *--wp = '\0'; 100059243Sobrien 100159243Sobrien return (found); 100259243Sobrien 100359243Sobrienpast: 100459243Sobrien switch (Stype) { 100559243Sobrien 100659243Sobrien case TC_IF: 100759243Sobrien stderror(ERR_NAME | ERR_NOTFOUND, "then/endif"); 100859243Sobrien break; 100959243Sobrien 101059243Sobrien case TC_ELSE: 101159243Sobrien stderror(ERR_NAME | ERR_NOTFOUND, "endif"); 101259243Sobrien break; 101359243Sobrien 101459243Sobrien case TC_BRKSW: 101559243Sobrien case TC_SWITCH: 101659243Sobrien stderror(ERR_NAME | ERR_NOTFOUND, "endsw"); 101759243Sobrien break; 101859243Sobrien 101959243Sobrien case TC_BREAK: 102059243Sobrien stderror(ERR_NAME | ERR_NOTFOUND, "end"); 102159243Sobrien break; 102259243Sobrien 102359243Sobrien case TC_GOTO: 102459243Sobrien setname(short2str(Sgoal)); 102559243Sobrien stderror(ERR_NAME | ERR_NOTFOUND, "label"); 102659243Sobrien break; 102759243Sobrien 102859243Sobrien default: 102959243Sobrien break; 103059243Sobrien } 103159243Sobrien /* NOTREACHED */ 103259243Sobrien return (0); 103359243Sobrien} 103459243Sobrien 103559243Sobrienstatic void 103659243Sobrientoend() 103759243Sobrien{ 103869408Sache if (whyles->w_end.type == TCSH_F_SEEK && whyles->w_end.f_seek == 0) { 103959243Sobrien search(TC_BREAK, 0, NULL); 104059243Sobrien btell(&whyles->w_end); 104159243Sobrien whyles->w_end.f_seek--; 104259243Sobrien } 104359243Sobrien else { 104459243Sobrien bseek(&whyles->w_end); 104559243Sobrien } 104659243Sobrien wfree(); 104759243Sobrien} 104859243Sobrien 1049131962Smpstatic void 1050131962Smpwpfree(wp) 1051131962Smp struct whyle *wp; 1052131962Smp{ 1053131962Smp if (wp->w_fe0) 1054131962Smp blkfree(wp->w_fe0); 1055131962Smp if (wp->w_fename) 1056131962Smp xfree((ptr_t) wp->w_fename); 1057131962Smp xfree((ptr_t) wp); 1058131962Smp} 1059131962Smp 106059243Sobrienvoid 106159243Sobrienwfree() 106259243Sobrien{ 106359243Sobrien struct Ain o; 106459243Sobrien struct whyle *nwp; 106559243Sobrien#ifdef lint 106659243Sobrien nwp = NULL; /* sun lint is dumb! */ 106759243Sobrien#endif 106859243Sobrien 106959243Sobrien#ifdef FDEBUG 107059243Sobrien static char foo[] = "IAFE"; 107159243Sobrien#endif /* FDEBUG */ 107259243Sobrien 107359243Sobrien btell(&o); 107459243Sobrien 107559243Sobrien#ifdef FDEBUG 107659243Sobrien xprintf("o->type %c o->a_seek %d o->f_seek %d\n", 107759243Sobrien foo[o.type + 1], o.a_seek, o.f_seek); 107859243Sobrien#endif /* FDEBUG */ 107959243Sobrien 108059243Sobrien for (; whyles; whyles = nwp) { 108159243Sobrien register struct whyle *wp = whyles; 108259243Sobrien nwp = wp->w_next; 108359243Sobrien 108459243Sobrien#ifdef FDEBUG 108559243Sobrien xprintf("start->type %c start->a_seek %d start->f_seek %d\n", 108659243Sobrien foo[wp->w_start.type+1], 108759243Sobrien wp->w_start.a_seek, wp->w_start.f_seek); 108859243Sobrien xprintf("end->type %c end->a_seek %d end->f_seek %d\n", 108959243Sobrien foo[wp->w_end.type + 1], wp->w_end.a_seek, wp->w_end.f_seek); 109059243Sobrien#endif /* FDEBUG */ 109159243Sobrien 109259243Sobrien /* 109359243Sobrien * XXX: We free loops that have different seek types. 109459243Sobrien */ 109569408Sache if (wp->w_end.type != TCSH_I_SEEK && wp->w_start.type == wp->w_end.type && 109659243Sobrien wp->w_start.type == o.type) { 109769408Sache if (wp->w_end.type == TCSH_F_SEEK) { 109859243Sobrien if (o.f_seek >= wp->w_start.f_seek && 109959243Sobrien (wp->w_end.f_seek == 0 || o.f_seek < wp->w_end.f_seek)) 110059243Sobrien break; 110159243Sobrien } 110259243Sobrien else { 110359243Sobrien if (o.a_seek >= wp->w_start.a_seek && 110459243Sobrien (wp->w_end.a_seek == 0 || o.a_seek < wp->w_end.a_seek)) 110559243Sobrien break; 110659243Sobrien } 110759243Sobrien } 110859243Sobrien 1109131962Smp wpfree(wp); 111059243Sobrien } 111159243Sobrien} 111259243Sobrien 111359243Sobrien/*ARGSUSED*/ 111459243Sobrienvoid 111559243Sobriendoecho(v, c) 111659243Sobrien Char **v; 111759243Sobrien struct command *c; 111859243Sobrien{ 111959243Sobrien USE(c); 112059243Sobrien xecho(' ', v); 112159243Sobrien} 112259243Sobrien 112359243Sobrien/*ARGSUSED*/ 112459243Sobrienvoid 112559243Sobriendoglob(v, c) 112659243Sobrien Char **v; 112759243Sobrien struct command *c; 112859243Sobrien{ 112959243Sobrien USE(c); 113059243Sobrien xecho(0, v); 113159243Sobrien flush(); 113259243Sobrien} 113359243Sobrien 113459243Sobrienstatic void 113559243Sobrienxecho(sep, v) 113659243Sobrien int sep; 113759243Sobrien register Char **v; 113859243Sobrien{ 113959243Sobrien register Char *cp; 114059243Sobrien int nonl = 0; 114159243Sobrien#ifdef ECHO_STYLE 114259243Sobrien int echo_style = ECHO_STYLE; 114359243Sobrien#else /* !ECHO_STYLE */ 114459243Sobrien# if SYSVREL > 0 114559243Sobrien int echo_style = SYSV_ECHO; 114659243Sobrien# else /* SYSVREL == 0 */ 114759243Sobrien int echo_style = BSD_ECHO; 114859243Sobrien# endif /* SYSVREL */ 114959243Sobrien#endif /* ECHO_STYLE */ 115059243Sobrien struct varent *vp; 115159243Sobrien 115259243Sobrien if ((vp = adrof(STRecho_style)) != NULL && vp->vec != NULL && 115359243Sobrien vp->vec[0] != NULL) { 115459243Sobrien if (Strcmp(vp->vec[0], STRbsd) == 0) 115559243Sobrien echo_style = BSD_ECHO; 115659243Sobrien else if (Strcmp(vp->vec[0], STRsysv) == 0) 115759243Sobrien echo_style = SYSV_ECHO; 115859243Sobrien else if (Strcmp(vp->vec[0], STRboth) == 0) 115959243Sobrien echo_style = BOTH_ECHO; 116059243Sobrien else if (Strcmp(vp->vec[0], STRnone) == 0) 116159243Sobrien echo_style = NONE_ECHO; 116259243Sobrien } 116359243Sobrien 116459243Sobrien if (setintr) 116559243Sobrien#ifdef BSDSIGS 116659243Sobrien (void) sigsetmask(sigblock((sigmask_t) 0) & ~sigmask(SIGINT)); 116759243Sobrien#else /* !BSDSIGS */ 116859243Sobrien (void) sigrelse (SIGINT); 116959243Sobrien#endif /* BSDSIGS */ 117059243Sobrien v++; 117159243Sobrien if (*v == 0) 117283098Smp goto done; 117359243Sobrien gflag = 0, tglob(v); 117459243Sobrien if (gflag) { 117559243Sobrien v = globall(v); 117659243Sobrien if (v == 0) 117759243Sobrien stderror(ERR_NAME | ERR_NOMATCH); 117859243Sobrien } 117959243Sobrien else { 118059243Sobrien v = gargv = saveblk(v); 118159243Sobrien trim(v); 118259243Sobrien } 118359243Sobrien 118459243Sobrien if ((echo_style & BSD_ECHO) != 0 && sep == ' ' && *v && eq(*v, STRmn)) 118559243Sobrien nonl++, v++; 118659243Sobrien 118759243Sobrien while ((cp = *v++) != 0) { 118859243Sobrien register int c; 118959243Sobrien 119059243Sobrien while ((c = *cp++) != 0) { 119159243Sobrien if ((echo_style & SYSV_ECHO) != 0 && c == '\\') { 119259243Sobrien switch (c = *cp++) { 119359243Sobrien case 'a': 119459243Sobrien c = '\a'; 119559243Sobrien break; 119659243Sobrien case 'b': 119759243Sobrien c = '\b'; 119859243Sobrien break; 119959243Sobrien case 'c': 120059243Sobrien nonl = 1; 120159243Sobrien goto done; 120259243Sobrien case 'e': 120359243Sobrien#if 0 /* Windows does not understand \e */ 120459243Sobrien c = '\e'; 120559243Sobrien#else 120659243Sobrien c = '\033'; 120759243Sobrien#endif 120859243Sobrien break; 120959243Sobrien case 'f': 121059243Sobrien c = '\f'; 121159243Sobrien break; 121259243Sobrien case 'n': 121359243Sobrien c = '\n'; 121459243Sobrien break; 121559243Sobrien case 'r': 121659243Sobrien c = '\r'; 121759243Sobrien break; 121859243Sobrien case 't': 121959243Sobrien c = '\t'; 122059243Sobrien break; 122159243Sobrien case 'v': 122259243Sobrien c = '\v'; 122359243Sobrien break; 122459243Sobrien case '\\': 122559243Sobrien c = '\\'; 122659243Sobrien break; 122759243Sobrien case '0': 122859243Sobrien c = 0; 122959243Sobrien if (*cp >= '0' && *cp < '8') 123059243Sobrien c = c * 8 + *cp++ - '0'; 123159243Sobrien if (*cp >= '0' && *cp < '8') 123259243Sobrien c = c * 8 + *cp++ - '0'; 123359243Sobrien if (*cp >= '0' && *cp < '8') 123459243Sobrien c = c * 8 + *cp++ - '0'; 123559243Sobrien break; 123659243Sobrien case '\0': 123759243Sobrien c = '\\'; 123859243Sobrien cp--; 123959243Sobrien break; 124059243Sobrien default: 124159243Sobrien xputchar('\\' | QUOTE); 124259243Sobrien break; 124359243Sobrien } 124459243Sobrien } 124559243Sobrien xputchar(c | QUOTE); 124659243Sobrien 124759243Sobrien } 124859243Sobrien if (*v) 124959243Sobrien xputchar(sep | QUOTE); 125059243Sobrien } 125159243Sobriendone: 125259243Sobrien if (sep && nonl == 0) 125359243Sobrien xputchar('\n'); 125459243Sobrien else 125559243Sobrien flush(); 125659243Sobrien if (setintr) 125759243Sobrien#ifdef BSDSIGS 125859243Sobrien (void) sigblock(sigmask(SIGINT)); 125959243Sobrien#else /* !BSDSIGS */ 126059243Sobrien (void) sighold(SIGINT); 126159243Sobrien#endif /* BSDSIGS */ 126259243Sobrien if (gargv) 126359243Sobrien blkfree(gargv), gargv = 0; 126459243Sobrien} 126559243Sobrien 126659243Sobrien/* check whether an environment variable should invoke 'set_locale()' */ 126759243Sobrienstatic bool 126859243Sobrienislocale_var(var) 126959243Sobrien Char *var; 127059243Sobrien{ 127159243Sobrien static Char *locale_vars[] = { 1272131962Smp STRLANG, STRLC_ALL, STRLC_CTYPE, STRLC_NUMERIC, 1273131962Smp STRLC_TIME, STRLC_COLLATE, STRLC_MESSAGES, STRLC_MONETARY, 0 127459243Sobrien }; 127559243Sobrien register Char **v; 127659243Sobrien 127759243Sobrien for (v = locale_vars; *v; ++v) 127859243Sobrien if (eq(var, *v)) 127959243Sobrien return 1; 128059243Sobrien return 0; 128159243Sobrien} 128259243Sobrien 128359243Sobrien/*ARGSUSED*/ 128459243Sobrienvoid 128559243Sobriendoprintenv(v, c) 128659243Sobrien register Char **v; 128759243Sobrien struct command *c; 128859243Sobrien{ 128959243Sobrien Char *e; 129059243Sobrien extern bool output_raw; 129159243Sobrien extern bool xlate_cr; 129259243Sobrien 129359243Sobrien USE(c); 129459243Sobrien if (setintr) 129559243Sobrien#ifdef BSDSIGS 129659243Sobrien (void) sigsetmask(sigblock((sigmask_t) 0) & ~sigmask(SIGINT)); 129759243Sobrien#else /* !BSDSIGS */ 129859243Sobrien (void) sigrelse (SIGINT); 129959243Sobrien#endif /* BSDSIGS */ 130059243Sobrien 130159243Sobrien v++; 130259243Sobrien if (*v == 0) { 130359243Sobrien register Char **ep; 130459243Sobrien 130559243Sobrien xlate_cr = 1; 130659243Sobrien for (ep = STR_environ; *ep; ep++) 130759243Sobrien xprintf("%S\n", *ep); 130859243Sobrien xlate_cr = 0; 130959243Sobrien } 131059243Sobrien else if ((e = tgetenv(*v)) != NULL) { 131159243Sobrien output_raw = 1; 131259243Sobrien xprintf("%S\n", e); 131359243Sobrien output_raw = 0; 131459243Sobrien } 131559243Sobrien else 131659243Sobrien set(STRstatus, Strsave(STR1), VAR_READWRITE); 131759243Sobrien} 131859243Sobrien 131959243Sobrien/* from "Karl Berry." <karl%mote.umb.edu@relay.cs.net> -- for NeXT things 132059243Sobrien (and anything else with a modern compiler) */ 132159243Sobrien 132259243Sobrien/*ARGSUSED*/ 132359243Sobrienvoid 132459243Sobriendosetenv(v, c) 132559243Sobrien register Char **v; 132659243Sobrien struct command *c; 132759243Sobrien{ 132859243Sobrien Char *vp, *lp; 132959243Sobrien 133059243Sobrien USE(c); 133159243Sobrien if (*++v == 0) { 133259243Sobrien doprintenv(--v, 0); 133359243Sobrien return; 133459243Sobrien } 133559243Sobrien 133659243Sobrien vp = *v++; 133759243Sobrien 1338100616Smp lp = vp; 1339100616Smp 1340131962Smp for (; *lp != '\0' ; lp++) { 1341131962Smp if (*lp == '=') 1342131962Smp stderror(ERR_NAME | ERR_SYNTAX); 1343131962Smp } 134459243Sobrien if ((lp = *v++) == 0) 134559243Sobrien lp = STRNULL; 134659243Sobrien 134759243Sobrien tsetenv(vp, lp = globone(lp, G_APPEND)); 134859243Sobrien if (eq(vp, STRKPATH)) { 134959243Sobrien importpath(lp); 135059243Sobrien dohash(NULL, NULL); 135159243Sobrien xfree((ptr_t) lp); 135259243Sobrien return; 135359243Sobrien } 135459243Sobrien 135559243Sobrien#ifdef apollo 135659243Sobrien if (eq(vp, STRSYSTYPE)) { 135759243Sobrien dohash(NULL, NULL); 135859243Sobrien xfree((ptr_t) lp); 135959243Sobrien return; 136059243Sobrien } 136159243Sobrien#endif /* apollo */ 136259243Sobrien 136359243Sobrien /* dspkanji/dspmbyte autosetting */ 136459243Sobrien /* PATCH IDEA FROM Issei.Suzuki VERY THANKS */ 136559243Sobrien#if defined(DSPMBYTE) 136659243Sobrien if(eq(vp, STRLANG) && !adrof(CHECK_MBYTEVAR)) { 136759243Sobrien autoset_dspmbyte(lp); 136859243Sobrien } 136959243Sobrien#endif 137059243Sobrien 137159243Sobrien if (islocale_var(vp)) { 137259243Sobrien#ifdef NLS 137359243Sobrien int k; 137459243Sobrien 137559243Sobrien# ifdef SETLOCALEBUG 137659243Sobrien dont_free = 1; 137759243Sobrien# endif /* SETLOCALEBUG */ 137859243Sobrien (void) setlocale(LC_ALL, ""); 137959243Sobrien# ifdef LC_COLLATE 138059243Sobrien (void) setlocale(LC_COLLATE, ""); 138159243Sobrien# endif 138259243Sobrien# ifdef NLS_CATALOGS 138359243Sobrien# ifdef LC_MESSAGES 138459243Sobrien (void) setlocale(LC_MESSAGES, ""); 138559243Sobrien# endif /* LC_MESSAGES */ 138659243Sobrien (void) catclose(catd); 138759243Sobrien nlsinit(); 138859243Sobrien# endif /* NLS_CATALOGS */ 138959243Sobrien# ifdef LC_CTYPE 139059243Sobrien (void) setlocale(LC_CTYPE, ""); /* for iscntrl */ 139159243Sobrien# endif /* LC_CTYPE */ 139259243Sobrien# ifdef SETLOCALEBUG 139359243Sobrien dont_free = 0; 139459243Sobrien# endif /* SETLOCALEBUG */ 139559243Sobrien# ifdef STRCOLLBUG 139659243Sobrien fix_strcoll_bug(); 139759243Sobrien# endif /* STRCOLLBUG */ 139859243Sobrien tw_cmd_free(); /* since the collation sequence has changed */ 139959243Sobrien for (k = 0200; k <= 0377 && !Isprint(k); k++) 140059243Sobrien continue; 140159243Sobrien AsciiOnly = k > 0377; 140259243Sobrien#else /* !NLS */ 140359243Sobrien AsciiOnly = 0; 140459243Sobrien#endif /* NLS */ 140559243Sobrien NLSMapsAreInited = 0; 140659243Sobrien ed_Init(); 140759243Sobrien if (MapsAreInited && !NLSMapsAreInited) 140859243Sobrien ed_InitNLSMaps(); 140959243Sobrien xfree((ptr_t) lp); 141059243Sobrien return; 141159243Sobrien } 141259243Sobrien 1413100616Smp#ifdef NLS_CATALOGS 1414100616Smp if (eq(vp, STRNLSPATH)) { 1415100616Smp (void) catclose(catd); 1416100616Smp nlsinit(); 1417100616Smp } 1418100616Smp#endif 1419100616Smp 142059243Sobrien if (eq(vp, STRNOREBIND)) { 142159243Sobrien NoNLSRebind = 1; 142259243Sobrien MapsAreInited = 0; 142359243Sobrien NLSMapsAreInited = 0; 142459243Sobrien ed_InitMaps(); 142559243Sobrien xfree((ptr_t) lp); 142659243Sobrien return; 142759243Sobrien } 142869408Sache#ifdef WINNT_NATIVE 142959243Sobrien if (eq(vp, STRtcshlang)) { 143059243Sobrien nlsinit(); 143159243Sobrien xfree((ptr_t) lp); 143259243Sobrien return; 143359243Sobrien } 143469408Sache#endif /* WINNT_NATIVE */ 143559243Sobrien if (eq(vp, STRKTERM)) { 143659243Sobrien char *t; 143759243Sobrien set(STRterm, quote(lp), VAR_READWRITE); /* lp memory used here */ 143859243Sobrien t = short2str(lp); 143959243Sobrien if (noediting && strcmp(t, "unknown") != 0 && strcmp(t,"dumb") != 0) { 144059243Sobrien editing = 1; 144159243Sobrien noediting = 0; 144259243Sobrien set(STRedit, Strsave(STRNULL), VAR_READWRITE); 144359243Sobrien } 144459243Sobrien GotTermCaps = 0; 144559243Sobrien ed_Init(); 144659243Sobrien return; 144759243Sobrien } 144859243Sobrien 144959243Sobrien if (eq(vp, STRKHOME)) { 145059243Sobrien /* 145159243Sobrien * convert to canonical pathname (possibly resolving symlinks) 145259243Sobrien */ 145359243Sobrien lp = dcanon(lp, lp); 145459243Sobrien set(STRhome, quote(lp), VAR_READWRITE); /* cp memory used here */ 145559243Sobrien 145659243Sobrien /* fix directory stack for new tilde home */ 145759243Sobrien dtilde(); 145859243Sobrien return; 145959243Sobrien } 146059243Sobrien 146159243Sobrien if (eq(vp, STRKSHLVL)) { 146259243Sobrien /* lp memory used here */ 146359243Sobrien set(STRshlvl, quote(lp), VAR_READWRITE); 146459243Sobrien return; 146559243Sobrien } 146659243Sobrien 146759243Sobrien if (eq(vp, STRKUSER)) { 146859243Sobrien set(STRuser, quote(lp), VAR_READWRITE); /* lp memory used here */ 146959243Sobrien return; 147059243Sobrien } 147159243Sobrien 147259243Sobrien if (eq(vp, STRKGROUP)) { 147359243Sobrien set(STRgroup, quote(lp), VAR_READWRITE); /* lp memory used here */ 147459243Sobrien return; 147559243Sobrien } 147659243Sobrien 147759243Sobrien#ifdef COLOR_LS_F 147859243Sobrien if (eq(vp, STRLS_COLORS)) { 147959243Sobrien parseLS_COLORS(lp); 148059243Sobrien return; 148159243Sobrien } 148259243Sobrien#endif /* COLOR_LS_F */ 148359243Sobrien 148459243Sobrien#ifdef SIG_WINDOW 148559243Sobrien /* 148659243Sobrien * Load/Update $LINES $COLUMNS 148759243Sobrien */ 148859243Sobrien if ((eq(lp, STRNULL) && (eq(vp, STRLINES) || eq(vp, STRCOLUMNS))) || 148959243Sobrien eq(vp, STRTERMCAP)) { 149059243Sobrien xfree((ptr_t) lp); 149159243Sobrien check_window_size(1); 149259243Sobrien return; 149359243Sobrien } 149459243Sobrien 149559243Sobrien /* 149659243Sobrien * Change the size to the one directed by $LINES and $COLUMNS 149759243Sobrien */ 149859243Sobrien if (eq(vp, STRLINES) || eq(vp, STRCOLUMNS)) { 149959243Sobrien#if 0 150059243Sobrien GotTermCaps = 0; 150159243Sobrien#endif 150259243Sobrien xfree((ptr_t) lp); 150359243Sobrien ed_Init(); 150459243Sobrien return; 150559243Sobrien } 150659243Sobrien#endif /* SIG_WINDOW */ 150759243Sobrien xfree((ptr_t) lp); 150859243Sobrien} 150959243Sobrien 151059243Sobrien/*ARGSUSED*/ 151159243Sobrienvoid 151259243Sobriendounsetenv(v, c) 151359243Sobrien register Char **v; 151459243Sobrien struct command *c; 151559243Sobrien{ 151659243Sobrien Char **ep, *p, *n; 151759243Sobrien int i, maxi; 151859243Sobrien static Char *name = NULL; 151959243Sobrien 152059243Sobrien USE(c); 152159243Sobrien if (name) 152259243Sobrien xfree((ptr_t) name); 152359243Sobrien /* 152459243Sobrien * Find the longest environment variable 152559243Sobrien */ 152659243Sobrien for (maxi = 0, ep = STR_environ; *ep; ep++) { 152759243Sobrien for (i = 0, p = *ep; *p && *p != '='; p++, i++) 152859243Sobrien continue; 152959243Sobrien if (i > maxi) 153059243Sobrien maxi = i; 153159243Sobrien } 153259243Sobrien 153359243Sobrien name = (Char *) xmalloc((size_t) ((maxi + 1) * sizeof(Char))); 153459243Sobrien 153559243Sobrien while (++v && *v) 153659243Sobrien for (maxi = 1; maxi;) 153759243Sobrien for (maxi = 0, ep = STR_environ; *ep; ep++) { 153859243Sobrien for (n = name, p = *ep; *p && *p != '='; *n++ = *p++) 153959243Sobrien continue; 154059243Sobrien *n = '\0'; 154159243Sobrien if (!Gmatch(name, *v)) 154259243Sobrien continue; 154359243Sobrien maxi = 1; 154459243Sobrien 154559243Sobrien /* Unset the name. This wasn't being done until 154659243Sobrien * later but most of the stuff following won't 154759243Sobrien * work (particularly the setlocale() and getenv() 154859243Sobrien * stuff) as intended until the name is actually 154959243Sobrien * removed. (sg) 155059243Sobrien */ 155159243Sobrien Unsetenv(name); 155259243Sobrien 155359243Sobrien if (eq(name, STRNOREBIND)) { 155459243Sobrien NoNLSRebind = 0; 155559243Sobrien MapsAreInited = 0; 155659243Sobrien NLSMapsAreInited = 0; 155759243Sobrien ed_InitMaps(); 155859243Sobrien } 155959243Sobrien#ifdef apollo 156059243Sobrien else if (eq(name, STRSYSTYPE)) 156159243Sobrien dohash(NULL, NULL); 156259243Sobrien#endif /* apollo */ 156359243Sobrien else if (islocale_var(name)) { 156459243Sobrien#ifdef NLS 156559243Sobrien int k; 156659243Sobrien 156759243Sobrien# ifdef SETLOCALEBUG 156859243Sobrien dont_free = 1; 156959243Sobrien# endif /* SETLOCALEBUG */ 157059243Sobrien (void) setlocale(LC_ALL, ""); 157159243Sobrien# ifdef LC_COLLATE 157259243Sobrien (void) setlocale(LC_COLLATE, ""); 157359243Sobrien# endif 157459243Sobrien# ifdef NLS_CATALOGS 157559243Sobrien# ifdef LC_MESSAGES 157659243Sobrien (void) setlocale(LC_MESSAGES, ""); 157759243Sobrien# endif /* LC_MESSAGES */ 157859243Sobrien (void) catclose(catd); 157959243Sobrien nlsinit(); 158059243Sobrien# endif /* NLS_CATALOGS */ 158159243Sobrien# ifdef LC_CTYPE 158259243Sobrien (void) setlocale(LC_CTYPE, ""); /* for iscntrl */ 158359243Sobrien# endif /* LC_CTYPE */ 158459243Sobrien# ifdef SETLOCALEBUG 158559243Sobrien dont_free = 0; 158659243Sobrien# endif /* SETLOCALEBUG */ 158759243Sobrien# ifdef STRCOLLBUG 158859243Sobrien fix_strcoll_bug(); 158959243Sobrien# endif /* STRCOLLBUG */ 159059243Sobrien tw_cmd_free();/* since the collation sequence has changed */ 159159243Sobrien for (k = 0200; k <= 0377 && !Isprint(k); k++) 159259243Sobrien continue; 159359243Sobrien AsciiOnly = k > 0377; 159459243Sobrien#else /* !NLS */ 159559243Sobrien AsciiOnly = getenv("LANG") == NULL && 159659243Sobrien getenv("LC_CTYPE") == NULL; 159759243Sobrien#endif /* NLS */ 159859243Sobrien NLSMapsAreInited = 0; 159959243Sobrien ed_Init(); 160059243Sobrien if (MapsAreInited && !NLSMapsAreInited) 160159243Sobrien ed_InitNLSMaps(); 160259243Sobrien 160359243Sobrien } 160469408Sache#ifdef WINNT_NATIVE 160559243Sobrien else if (eq(name,(STRtcshlang))) { 160659243Sobrien nls_dll_unload(); 160759243Sobrien nlsinit(); 160859243Sobrien } 160969408Sache#endif /* WINNT_NATIVE */ 161059243Sobrien#ifdef COLOR_LS_F 161159243Sobrien else if (eq(name, STRLS_COLORS)) 161259243Sobrien parseLS_COLORS(n); 161359243Sobrien#endif /* COLOR_LS_F */ 1614100616Smp#ifdef NLS_CATALOGS 1615100616Smp else if (eq(name, STRNLSPATH)) { 1616100616Smp (void) catclose(catd); 1617100616Smp nlsinit(); 1618100616Smp } 1619100616Smp#endif 162059243Sobrien /* 162159243Sobrien * start again cause the environment changes 162259243Sobrien */ 162359243Sobrien break; 162459243Sobrien } 162559243Sobrien xfree((ptr_t) name); name = NULL; 162659243Sobrien} 162759243Sobrien 162859243Sobrienvoid 162959243Sobrientsetenv(name, val) 163059243Sobrien Char *name, *val; 163159243Sobrien{ 163259243Sobrien#ifdef SETENV_IN_LIB 163359243Sobrien/* 163459243Sobrien * XXX: This does not work right, since tcsh cannot track changes to 163559243Sobrien * the environment this way. (the builtin setenv without arguments does 163659243Sobrien * not print the right stuff neither does unsetenv). This was for Mach, 163759243Sobrien * it is not needed anymore. 163859243Sobrien */ 163959243Sobrien#undef setenv 164059243Sobrien char nameBuf[BUFSIZE]; 164159243Sobrien char *cname = short2str(name); 164259243Sobrien 164359243Sobrien if (cname == NULL) 164459243Sobrien return; 164559243Sobrien (void) strcpy(nameBuf, cname); 164659243Sobrien setenv(nameBuf, short2str(val), 1); 164759243Sobrien#else /* !SETENV_IN_LIB */ 164859243Sobrien register Char **ep = STR_environ; 164959243Sobrien register Char *cp, *dp; 165059243Sobrien Char *blk[2]; 165159243Sobrien Char **oep = ep; 165259243Sobrien 165369408Sache#ifdef WINNT_NATIVE 165459243Sobrien nt_set_env(name,val); 165569408Sache#endif /* WINNT_NATIVE */ 165659243Sobrien for (; *ep; ep++) { 165769408Sache#ifdef WINNT_NATIVE 165859243Sobrien for (cp = name, dp = *ep; *cp && Tolower(*cp & TRIM) == Tolower(*dp); 165959243Sobrien cp++, dp++) 166059243Sobrien#else 166159243Sobrien for (cp = name, dp = *ep; *cp && (*cp & TRIM) == *dp; cp++, dp++) 166269408Sache#endif /* WINNT_NATIVE */ 166359243Sobrien continue; 166459243Sobrien if (*cp != 0 || *dp != '=') 166559243Sobrien continue; 166659243Sobrien cp = Strspl(STRequal, val); 166759243Sobrien xfree((ptr_t) * ep); 166859243Sobrien *ep = strip(Strspl(name, cp)); 166959243Sobrien xfree((ptr_t) cp); 167059243Sobrien blkfree((Char **) environ); 167159243Sobrien environ = short2blk(STR_environ); 167259243Sobrien return; 167359243Sobrien } 167459243Sobrien cp = Strspl(name, STRequal); 167559243Sobrien blk[0] = strip(Strspl(cp, val)); 167659243Sobrien xfree((ptr_t) cp); 167759243Sobrien blk[1] = 0; 167859243Sobrien STR_environ = blkspl(STR_environ, blk); 167959243Sobrien blkfree((Char **) environ); 168059243Sobrien environ = short2blk(STR_environ); 168159243Sobrien xfree((ptr_t) oep); 168259243Sobrien#endif /* SETENV_IN_LIB */ 168359243Sobrien} 168459243Sobrien 168559243Sobrienvoid 168659243SobrienUnsetenv(name) 168759243Sobrien Char *name; 168859243Sobrien{ 168959243Sobrien register Char **ep = STR_environ; 169059243Sobrien register Char *cp, *dp; 169159243Sobrien Char **oep = ep; 169259243Sobrien 169369408Sache#ifdef WINNT_NATIVE 169459243Sobrien nt_set_env(name,NULL); 169569408Sache#endif /*WINNT_NATIVE */ 169659243Sobrien for (; *ep; ep++) { 169759243Sobrien for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++) 169859243Sobrien continue; 169959243Sobrien if (*cp != 0 || *dp != '=') 170059243Sobrien continue; 170159243Sobrien cp = *ep; 170259243Sobrien *ep = 0; 170359243Sobrien STR_environ = blkspl(STR_environ, ep + 1); 170459243Sobrien blkfree((Char **) environ); 170559243Sobrien environ = short2blk(STR_environ); 170659243Sobrien *ep = cp; 170759243Sobrien xfree((ptr_t) cp); 170859243Sobrien xfree((ptr_t) oep); 170959243Sobrien return; 171059243Sobrien } 171159243Sobrien} 171259243Sobrien 171359243Sobrien/*ARGSUSED*/ 171459243Sobrienvoid 171559243Sobriendoumask(v, c) 171659243Sobrien register Char **v; 171759243Sobrien struct command *c; 171859243Sobrien{ 171959243Sobrien register Char *cp = v[1]; 172059243Sobrien register int i; 172159243Sobrien 172259243Sobrien USE(c); 172359243Sobrien if (cp == 0) { 172459415Sobrien i = (int)umask(0); 172559243Sobrien (void) umask(i); 172659243Sobrien xprintf("%o\n", i); 172759243Sobrien return; 172859243Sobrien } 172959243Sobrien i = 0; 173059243Sobrien while (Isdigit(*cp) && *cp != '8' && *cp != '9') 173159243Sobrien i = i * 8 + *cp++ - '0'; 173259243Sobrien if (*cp || i < 0 || i > 0777) 173359243Sobrien stderror(ERR_NAME | ERR_MASK); 173459243Sobrien (void) umask(i); 173559243Sobrien} 173659243Sobrien 173759243Sobrien#ifndef HAVENOLIMIT 173859243Sobrien# ifndef BSDLIMIT 173959243Sobrien typedef long RLIM_TYPE; 174059243Sobrien# ifndef RLIM_INFINITY 174159243Sobrien# if !defined(_MINIX) && !defined(__clipper__) && !defined(_CRAY) 174259243Sobrien extern RLIM_TYPE ulimit(); 174359243Sobrien# endif /* ! _MINIX && !__clipper__ */ 174459243Sobrien# define RLIM_INFINITY 0x003fffff 174559243Sobrien# define RLIMIT_FSIZE 1 174659243Sobrien# endif /* RLIM_INFINITY */ 174759243Sobrien# ifdef aiws 174859243Sobrien# define toset(a) (((a) == 3) ? 1004 : (a) + 1) 174959243Sobrien# define RLIMIT_DATA 3 175059243Sobrien# define RLIMIT_STACK 1005 175159243Sobrien# else /* aiws */ 175259243Sobrien# define toset(a) ((a) + 1) 175359243Sobrien# endif /* aiws */ 175459243Sobrien# else /* BSDLIMIT */ 1755131962Smp# if (defined(BSD4_4) || defined(__linux__) || (HPUXVERSION >= 1100)) && !defined(__386BSD__) 1756100616Smp typedef rlim_t RLIM_TYPE; 175759243Sobrien# else 175859243Sobrien# if defined(SOLARIS2) || (defined(sgi) && SYSVREL > 3) 175959243Sobrien typedef rlim_t RLIM_TYPE; 176059243Sobrien# else 176159243Sobrien# if defined(_SX) 176259243Sobrien typedef long long RLIM_TYPE; 1763100616Smp# else /* !_SX */ 176459243Sobrien typedef unsigned long RLIM_TYPE; 176559243Sobrien# endif /* _SX */ 176659243Sobrien# endif /* SOLARIS2 || (sgi && SYSVREL > 3) */ 176759243Sobrien# endif /* BSD4_4 && !__386BSD__ */ 176859243Sobrien# endif /* BSDLIMIT */ 176959243Sobrien 1770131962Smp# if (HPUXVERSION > 700) && (HPUXVERSION < 1100) && defined(BSDLIMIT) 177159243Sobrien/* Yes hpux8.0 has limits but <sys/resource.h> does not make them public */ 177259243Sobrien/* Yes, we could have defined _KERNEL, and -I/etc/conf/h, but is that better? */ 177359243Sobrien# ifndef RLIMIT_CPU 177459243Sobrien# define RLIMIT_CPU 0 177559243Sobrien# define RLIMIT_FSIZE 1 177659243Sobrien# define RLIMIT_DATA 2 177759243Sobrien# define RLIMIT_STACK 3 177859243Sobrien# define RLIMIT_CORE 4 177959243Sobrien# define RLIMIT_RSS 5 178059243Sobrien# define RLIMIT_NOFILE 6 178159243Sobrien# endif /* RLIMIT_CPU */ 178259243Sobrien# ifndef RLIM_INFINITY 178359243Sobrien# define RLIM_INFINITY 0x7fffffff 178459243Sobrien# endif /* RLIM_INFINITY */ 178559243Sobrien /* 178659243Sobrien * old versions of HP/UX counted limits in 512 bytes 178759243Sobrien */ 178859243Sobrien# ifndef SIGRTMIN 178959243Sobrien# define FILESIZE512 179059243Sobrien# endif /* SIGRTMIN */ 1791131962Smp# endif /* (HPUXVERSION > 700) && (HPUXVERSION < 1100) && BSDLIMIT */ 179259243Sobrien 179359243Sobrien# if SYSVREL > 3 && defined(BSDLIMIT) && !defined(_SX) 179459243Sobrien/* In order to use rusage, we included "/usr/ucbinclude/sys/resource.h" in */ 179559243Sobrien/* sh.h. However, some SVR4 limits are defined in <sys/resource.h>. Rather */ 179659243Sobrien/* than include both and get warnings, we define the extra SVR4 limits here. */ 179783098Smp/* XXX: I don't understand if RLIMIT_AS is defined, why don't we define */ 179883098Smp/* RLIMIT_VMEM based on it? */ 179959243Sobrien# ifndef RLIMIT_VMEM 180059243Sobrien# define RLIMIT_VMEM 6 180159243Sobrien# endif 180259243Sobrien# ifndef RLIMIT_AS 180359243Sobrien# define RLIMIT_AS RLIMIT_VMEM 180459243Sobrien# endif 180559243Sobrien# endif /* SYSVREL > 3 && BSDLIMIT */ 180659243Sobrien 180783098Smp# if defined(__linux__) && defined(RLIMIT_AS) && !defined(RLIMIT_VMEM) 180883098Smp# define RLIMIT_VMEM RLIMIT_AS 180983098Smp# endif 181083098Smp 181159243Sobrienstruct limits limits[] = 181259243Sobrien{ 181359243Sobrien# ifdef RLIMIT_CPU 181459243Sobrien { RLIMIT_CPU, "cputime", 1, "seconds" }, 181559243Sobrien# endif /* RLIMIT_CPU */ 181659243Sobrien 181759243Sobrien# ifdef RLIMIT_FSIZE 181859243Sobrien# ifndef aiws 181959243Sobrien { RLIMIT_FSIZE, "filesize", 1024, "kbytes" }, 182059243Sobrien# else 182159243Sobrien { RLIMIT_FSIZE, "filesize", 512, "blocks" }, 182259243Sobrien# endif /* aiws */ 182359243Sobrien# endif /* RLIMIT_FSIZE */ 182459243Sobrien 182559243Sobrien# ifdef RLIMIT_DATA 182659243Sobrien { RLIMIT_DATA, "datasize", 1024, "kbytes" }, 182759243Sobrien# endif /* RLIMIT_DATA */ 182859243Sobrien 182959243Sobrien# ifdef RLIMIT_STACK 183059243Sobrien# ifndef aiws 183159243Sobrien { RLIMIT_STACK, "stacksize", 1024, "kbytes" }, 183259243Sobrien# else 183359243Sobrien { RLIMIT_STACK, "stacksize", 1024 * 1024, "kbytes"}, 183459243Sobrien# endif /* aiws */ 183559243Sobrien# endif /* RLIMIT_STACK */ 183659243Sobrien 183759243Sobrien# ifdef RLIMIT_CORE 183859243Sobrien { RLIMIT_CORE, "coredumpsize", 1024, "kbytes" }, 183959243Sobrien# endif /* RLIMIT_CORE */ 184059243Sobrien 184159243Sobrien# ifdef RLIMIT_RSS 184259243Sobrien { RLIMIT_RSS, "memoryuse", 1024, "kbytes" }, 184359243Sobrien# endif /* RLIMIT_RSS */ 184459243Sobrien 184559243Sobrien# ifdef RLIMIT_UMEM 184659243Sobrien { RLIMIT_UMEM, "memoryuse", 1024, "kbytes" }, 184759243Sobrien# endif /* RLIMIT_UMEM */ 184859243Sobrien 184959243Sobrien# ifdef RLIMIT_VMEM 185059243Sobrien { RLIMIT_VMEM, "vmemoryuse", 1024, "kbytes" }, 185159243Sobrien# endif /* RLIMIT_VMEM */ 185259243Sobrien 185359243Sobrien# ifdef RLIMIT_NOFILE 185459243Sobrien { RLIMIT_NOFILE, "descriptors", 1, "" }, 185559243Sobrien# endif /* RLIMIT_NOFILE */ 185659243Sobrien 185759243Sobrien# ifdef RLIMIT_CONCUR 185859243Sobrien { RLIMIT_CONCUR, "concurrency", 1, "thread(s)" }, 185959243Sobrien# endif /* RLIMIT_CONCUR */ 186059243Sobrien 186159243Sobrien# ifdef RLIMIT_MEMLOCK 186259243Sobrien { RLIMIT_MEMLOCK, "memorylocked", 1024, "kbytes" }, 186359243Sobrien# endif /* RLIMIT_MEMLOCK */ 186459243Sobrien 186559243Sobrien# ifdef RLIMIT_NPROC 186659243Sobrien { RLIMIT_NPROC, "maxproc", 1, "" }, 186759243Sobrien# endif /* RLIMIT_NPROC */ 186859243Sobrien 1869100616Smp# if defined(RLIMIT_OFILE) && !defined(RLIMIT_NOFILE) 187059243Sobrien { RLIMIT_OFILE, "openfiles", 1, "" }, 1871100616Smp# endif /* RLIMIT_OFILE && !defined(RLIMIT_NOFILE) */ 187259243Sobrien 1873100616Smp# ifdef RLIMIT_SBSIZE 1874100616Smp { RLIMIT_SBSIZE, "sbsize", 1, "" }, 1875100616Smp# endif /* RLIMIT_SBSIZE */ 1876100616Smp 187759243Sobrien { -1, NULL, 0, NULL } 187859243Sobrien}; 187959243Sobrien 188059243Sobrienstatic struct limits *findlim __P((Char *)); 188159243Sobrienstatic RLIM_TYPE getval __P((struct limits *, Char **)); 188259243Sobrienstatic void limtail __P((Char *, char*)); 188359243Sobrienstatic void plim __P((struct limits *, int)); 188459243Sobrienstatic int setlim __P((struct limits *, int, RLIM_TYPE)); 188559243Sobrien 188659243Sobrien#ifdef convex 188759243Sobrienstatic RLIM_TYPE 188859243Sobrienrestrict_limit(value) 188959243Sobrien double value; 189059243Sobrien{ 189159243Sobrien /* 189259243Sobrien * is f too large to cope with? return the maximum or minimum int 189359243Sobrien */ 189459243Sobrien if (value > (double) INT_MAX) 189559243Sobrien return (RLIM_TYPE) INT_MAX; 189659243Sobrien else if (value < (double) INT_MIN) 189759243Sobrien return (RLIM_TYPE) INT_MIN; 189859243Sobrien else 189959243Sobrien return (RLIM_TYPE) value; 190059243Sobrien} 190159243Sobrien#else /* !convex */ 190259243Sobrien# define restrict_limit(x) ((RLIM_TYPE) (x)) 190359243Sobrien#endif /* convex */ 190459243Sobrien 190559243Sobrien 190659243Sobrienstatic struct limits * 190759243Sobrienfindlim(cp) 190859243Sobrien Char *cp; 190959243Sobrien{ 191059243Sobrien register struct limits *lp, *res; 191159243Sobrien 191259243Sobrien res = (struct limits *) NULL; 191359243Sobrien for (lp = limits; lp->limconst >= 0; lp++) 191459243Sobrien if (prefix(cp, str2short(lp->limname))) { 191559243Sobrien if (res) 191659243Sobrien stderror(ERR_NAME | ERR_AMBIG); 191759243Sobrien res = lp; 191859243Sobrien } 191959243Sobrien if (res) 192059243Sobrien return (res); 192159243Sobrien stderror(ERR_NAME | ERR_LIMIT); 192259243Sobrien /* NOTREACHED */ 192359243Sobrien return (0); 192459243Sobrien} 192559243Sobrien 192659243Sobrien/*ARGSUSED*/ 192759243Sobrienvoid 192859243Sobriendolimit(v, c) 192959243Sobrien register Char **v; 193059243Sobrien struct command *c; 193159243Sobrien{ 193259243Sobrien register struct limits *lp; 193359243Sobrien register RLIM_TYPE limit; 193459243Sobrien int hard = 0; 193559243Sobrien 193659243Sobrien USE(c); 193759243Sobrien v++; 193859243Sobrien if (*v && eq(*v, STRmh)) { 193959243Sobrien hard = 1; 194059243Sobrien v++; 194159243Sobrien } 194259243Sobrien if (*v == 0) { 194359243Sobrien for (lp = limits; lp->limconst >= 0; lp++) 194459243Sobrien plim(lp, hard); 194559243Sobrien return; 194659243Sobrien } 194759243Sobrien lp = findlim(v[0]); 194859243Sobrien if (v[1] == 0) { 194959243Sobrien plim(lp, hard); 195059243Sobrien return; 195159243Sobrien } 195259243Sobrien limit = getval(lp, v + 1); 195359243Sobrien if (setlim(lp, hard, limit) < 0) 195459243Sobrien stderror(ERR_SILENT); 195559243Sobrien} 195659243Sobrien 195759243Sobrienstatic RLIM_TYPE 195859243Sobriengetval(lp, v) 195959243Sobrien register struct limits *lp; 196059243Sobrien Char **v; 196159243Sobrien{ 196259243Sobrien register float f; 196359243Sobrien#ifndef atof /* This can be a macro on linux */ 196459243Sobrien extern double atof __P((const char *)); 196559243Sobrien#endif /* atof */ 196659243Sobrien Char *cp = *v++; 196759243Sobrien 196859243Sobrien f = atof(short2str(cp)); 196959243Sobrien 197059243Sobrien# ifdef convex 197159243Sobrien /* 197259243Sobrien * is f too large to cope with. limit f to minint, maxint - X-6768 by 197359243Sobrien * strike 197459243Sobrien */ 197559243Sobrien if ((f < (double) INT_MIN) || (f > (double) INT_MAX)) { 197659243Sobrien stderror(ERR_NAME | ERR_TOOLARGE); 197759243Sobrien } 197859243Sobrien# endif /* convex */ 197959243Sobrien 198059243Sobrien while (Isdigit(*cp) || *cp == '.' || *cp == 'e' || *cp == 'E') 198159243Sobrien cp++; 198259243Sobrien if (*cp == 0) { 198359243Sobrien if (*v == 0) 198469408Sache return restrict_limit((f * lp->limdiv) + 0.5); 198559243Sobrien cp = *v; 198659243Sobrien } 198759243Sobrien switch (*cp) { 198859243Sobrien# ifdef RLIMIT_CPU 198959243Sobrien case ':': 199059243Sobrien if (lp->limconst != RLIMIT_CPU) 199159243Sobrien goto badscal; 199259243Sobrien return f == 0.0 ? (RLIM_TYPE) 0 : restrict_limit((f * 60.0 + atof(short2str(cp + 1)))); 199359243Sobrien case 'h': 199459243Sobrien if (lp->limconst != RLIMIT_CPU) 199559243Sobrien goto badscal; 199659243Sobrien limtail(cp, "hours"); 199759243Sobrien f *= 3600.0; 199859243Sobrien break; 199959243Sobrien case 'm': 200059243Sobrien if (lp->limconst == RLIMIT_CPU) { 200159243Sobrien limtail(cp, "minutes"); 200259243Sobrien f *= 60.0; 200359243Sobrien break; 200459243Sobrien } 200559243Sobrien *cp = 'm'; 200659243Sobrien limtail(cp, "megabytes"); 200759243Sobrien f *= 1024.0 * 1024.0; 200859243Sobrien break; 200959243Sobrien case 's': 201059243Sobrien if (lp->limconst != RLIMIT_CPU) 201159243Sobrien goto badscal; 201259243Sobrien limtail(cp, "seconds"); 201359243Sobrien break; 201459243Sobrien# endif /* RLIMIT_CPU */ 201559243Sobrien case 'M': 201659243Sobrien# ifdef RLIMIT_CPU 201759243Sobrien if (lp->limconst == RLIMIT_CPU) 201859243Sobrien goto badscal; 201959243Sobrien# endif /* RLIMIT_CPU */ 202059243Sobrien *cp = 'm'; 202159243Sobrien limtail(cp, "megabytes"); 202259243Sobrien f *= 1024.0 * 1024.0; 202359243Sobrien break; 202459243Sobrien case 'k': 202559243Sobrien# ifdef RLIMIT_CPU 202659243Sobrien if (lp->limconst == RLIMIT_CPU) 202759243Sobrien goto badscal; 202859243Sobrien# endif /* RLIMIT_CPU */ 202959243Sobrien limtail(cp, "kbytes"); 203059243Sobrien f *= 1024.0; 203159243Sobrien break; 203259243Sobrien case 'b': 203359243Sobrien# ifdef RLIMIT_CPU 203459243Sobrien if (lp->limconst == RLIMIT_CPU) 203559243Sobrien goto badscal; 203659243Sobrien# endif /* RLIMIT_CPU */ 203759243Sobrien limtail(cp, "blocks"); 203859243Sobrien f *= 512.0; 203959243Sobrien break; 204059243Sobrien case 'u': 204159243Sobrien limtail(cp, "unlimited"); 204259243Sobrien return ((RLIM_TYPE) RLIM_INFINITY); 204359243Sobrien default: 204459243Sobrien# ifdef RLIMIT_CPU 204559243Sobrienbadscal: 204659243Sobrien# endif /* RLIMIT_CPU */ 204759243Sobrien stderror(ERR_NAME | ERR_SCALEF); 204859243Sobrien } 204959243Sobrien# ifdef convex 205059243Sobrien return f == 0.0 ? (RLIM_TYPE) 0 : restrict_limit((f + 0.5)); 205159243Sobrien# else 205259243Sobrien f += 0.5; 205359243Sobrien if (f > (float) RLIM_INFINITY) 205459243Sobrien return ((RLIM_TYPE) RLIM_INFINITY); 205559243Sobrien else 205659243Sobrien return ((RLIM_TYPE) f); 205759243Sobrien# endif /* convex */ 205859243Sobrien} 205959243Sobrien 206059243Sobrienstatic void 206159243Sobrienlimtail(cp, str) 206259243Sobrien Char *cp; 206359243Sobrien char *str; 206459243Sobrien{ 206561515Sobrien char *sp; 206661515Sobrien 206761515Sobrien sp = str; 206859243Sobrien while (*cp && *cp == *str) 206959243Sobrien cp++, str++; 207059243Sobrien if (*cp) 207161515Sobrien stderror(ERR_BADSCALE, sp); 207259243Sobrien} 207359243Sobrien 207459243Sobrien 207559243Sobrien/*ARGSUSED*/ 207659243Sobrienstatic void 207759243Sobrienplim(lp, hard) 207859243Sobrien register struct limits *lp; 207959243Sobrien int hard; 208059243Sobrien{ 208159243Sobrien# ifdef BSDLIMIT 208259243Sobrien struct rlimit rlim; 208359243Sobrien# endif /* BSDLIMIT */ 208459243Sobrien RLIM_TYPE limit; 208559243Sobrien int div = lp->limdiv; 208659243Sobrien 2087131962Smp xprintf("%-13.13s", lp->limname); 208859243Sobrien 208959243Sobrien# ifndef BSDLIMIT 209059243Sobrien limit = ulimit(lp->limconst, 0); 209159243Sobrien# ifdef aiws 209259243Sobrien if (lp->limconst == RLIMIT_DATA) 209359243Sobrien limit -= 0x20000000; 209459243Sobrien# endif /* aiws */ 209559243Sobrien# else /* BSDLIMIT */ 209659243Sobrien (void) getrlimit(lp->limconst, &rlim); 209759243Sobrien limit = hard ? rlim.rlim_max : rlim.rlim_cur; 209859243Sobrien# endif /* BSDLIMIT */ 209959243Sobrien 210059243Sobrien# if !defined(BSDLIMIT) || defined(FILESIZE512) 210159243Sobrien /* 210259243Sobrien * Christos: filesize comes in 512 blocks. we divide by 2 to get 1024 210359243Sobrien * blocks. Note we cannot pre-multiply cause we might overflow (A/UX) 210459243Sobrien */ 210559243Sobrien if (lp->limconst == RLIMIT_FSIZE) { 210659243Sobrien if (limit >= (RLIM_INFINITY / 512)) 210759243Sobrien limit = RLIM_INFINITY; 210859243Sobrien else 210959243Sobrien div = (div == 1024 ? 2 : 1); 211059243Sobrien } 211159243Sobrien# endif /* !BSDLIMIT || FILESIZE512 */ 211259243Sobrien 211359243Sobrien if (limit == RLIM_INFINITY) 211459243Sobrien xprintf("unlimited"); 211559243Sobrien else 211659243Sobrien# ifdef RLIMIT_CPU 211759243Sobrien if (lp->limconst == RLIMIT_CPU) 211859243Sobrien psecs((long) limit); 211959243Sobrien else 212059243Sobrien# endif /* RLIMIT_CPU */ 212159243Sobrien xprintf("%ld %s", (long) (limit / div), lp->limscale); 212259243Sobrien xputchar('\n'); 212359243Sobrien} 212459243Sobrien 212559243Sobrien/*ARGSUSED*/ 212659243Sobrienvoid 212759243Sobriendounlimit(v, c) 212859243Sobrien register Char **v; 212959243Sobrien struct command *c; 213059243Sobrien{ 213159243Sobrien register struct limits *lp; 213259243Sobrien int lerr = 0; 213359243Sobrien int hard = 0; 213459243Sobrien int force = 0; 213559243Sobrien 213659243Sobrien USE(c); 213759243Sobrien while (*++v && **v == '-') { 213859243Sobrien Char *vp = *v; 213959243Sobrien while (*++vp) 214059243Sobrien switch (*vp) { 214159243Sobrien case 'f': 214259243Sobrien force = 1; 214359243Sobrien break; 214459243Sobrien case 'h': 214559243Sobrien hard = 1; 214659243Sobrien break; 214759243Sobrien default: 214859243Sobrien stderror(ERR_ULIMUS); 214959243Sobrien break; 215059243Sobrien } 215159243Sobrien } 215259243Sobrien 215359243Sobrien if (*v == 0) { 215459243Sobrien for (lp = limits; lp->limconst >= 0; lp++) 215559243Sobrien if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0) 215659243Sobrien lerr++; 215759243Sobrien if (!force && lerr) 215859243Sobrien stderror(ERR_SILENT); 215959243Sobrien return; 216059243Sobrien } 216159243Sobrien while (*v) { 216259243Sobrien lp = findlim(*v++); 216359243Sobrien if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0 && !force) 216459243Sobrien stderror(ERR_SILENT); 216559243Sobrien } 216659243Sobrien} 216759243Sobrien 216859243Sobrienstatic int 216959243Sobriensetlim(lp, hard, limit) 217059243Sobrien register struct limits *lp; 217159243Sobrien int hard; 217259243Sobrien RLIM_TYPE limit; 217359243Sobrien{ 217459243Sobrien# ifdef BSDLIMIT 217559243Sobrien struct rlimit rlim; 217659243Sobrien 217759243Sobrien (void) getrlimit(lp->limconst, &rlim); 217859243Sobrien 217959243Sobrien# ifdef FILESIZE512 218059243Sobrien /* Even though hpux has setrlimit(), it expects fsize in 512 byte blocks */ 218159243Sobrien if (limit != RLIM_INFINITY && lp->limconst == RLIMIT_FSIZE) 218259243Sobrien limit /= 512; 218359243Sobrien# endif /* FILESIZE512 */ 218459243Sobrien if (hard) 218559243Sobrien rlim.rlim_max = limit; 218659243Sobrien else if (limit == RLIM_INFINITY && euid != 0) 218759243Sobrien rlim.rlim_cur = rlim.rlim_max; 218859243Sobrien else 218959243Sobrien rlim.rlim_cur = limit; 219059243Sobrien 2191100616Smp if (rlim.rlim_cur > rlim.rlim_max) 2192100616Smp rlim.rlim_max = rlim.rlim_cur; 2193100616Smp 219459243Sobrien if (setrlimit(lp->limconst, &rlim) < 0) { 219559243Sobrien# else /* BSDLIMIT */ 219659243Sobrien if (limit != RLIM_INFINITY && lp->limconst == RLIMIT_FSIZE) 219759243Sobrien limit /= 512; 219859243Sobrien# ifdef aiws 219959243Sobrien if (lp->limconst == RLIMIT_DATA) 220059243Sobrien limit += 0x20000000; 220159243Sobrien# endif /* aiws */ 220259243Sobrien if (ulimit(toset(lp->limconst), limit) < 0) { 220359243Sobrien# endif /* BSDLIMIT */ 2204100616Smp xprintf(CGETS(15, 1, "%s: %s: Can't %s%s limit (%s)\n"), bname, 2205100616Smp lp->limname, limit == RLIM_INFINITY ? CGETS(15, 2, "remove") : 2206100616Smp CGETS(15, 3, "set"), hard ? CGETS(14, 4, " hard") : "", 2207100616Smp strerror(errno)); 220859243Sobrien return (-1); 220959243Sobrien } 221059243Sobrien return (0); 221159243Sobrien} 221259243Sobrien 221359243Sobrien#endif /* !HAVENOLIMIT */ 221459243Sobrien 221559243Sobrien/*ARGSUSED*/ 221659243Sobrienvoid 221759243Sobriendosuspend(v, c) 221859243Sobrien Char **v; 221959243Sobrien struct command *c; 222059243Sobrien{ 222159243Sobrien#ifdef BSDJOBS 222259243Sobrien int ctpgrp; 222359243Sobrien 222459243Sobrien signalfun_t old; 222559243Sobrien#endif /* BSDJOBS */ 222659243Sobrien 222759243Sobrien USE(c); 222859243Sobrien USE(v); 222959243Sobrien 223059243Sobrien if (loginsh) 223159243Sobrien stderror(ERR_SUSPLOG); 223259243Sobrien untty(); 223359243Sobrien 223459243Sobrien#ifdef BSDJOBS 223559243Sobrien old = signal(SIGTSTP, SIG_DFL); 223659243Sobrien (void) kill(0, SIGTSTP); 223759243Sobrien /* the shell stops here */ 223859243Sobrien (void) signal(SIGTSTP, old); 223959243Sobrien#else /* !BSDJOBS */ 224059243Sobrien stderror(ERR_JOBCONTROL); 224159243Sobrien#endif /* BSDJOBS */ 224259243Sobrien 224359243Sobrien#ifdef BSDJOBS 224459243Sobrien if (tpgrp != -1) { 224559243Sobrienretry: 224659243Sobrien ctpgrp = tcgetpgrp(FSHTTY); 2247131962Smp if (ctpgrp == -1) 2248131962Smp stderror(ERR_SYSTEM, "tcgetpgrp", strerror(errno)); 224959243Sobrien if (ctpgrp != opgrp) { 225059243Sobrien old = signal(SIGTTIN, SIG_DFL); 225159243Sobrien (void) kill(0, SIGTTIN); 225259243Sobrien (void) signal(SIGTTIN, old); 225359243Sobrien goto retry; 225459243Sobrien } 225559243Sobrien (void) setpgid(0, shpgrp); 225659243Sobrien (void) tcsetpgrp(FSHTTY, shpgrp); 225759243Sobrien } 225859243Sobrien#endif /* BSDJOBS */ 225959243Sobrien (void) setdisc(FSHTTY); 226059243Sobrien} 226159243Sobrien 226259243Sobrien/* This is the dreaded EVAL built-in. 226359243Sobrien * If you don't fiddle with file descriptors, and reset didfds, 226459243Sobrien * this command will either ignore redirection inside or outside 226559243Sobrien * its arguments, e.g. eval "date >x" vs. eval "date" >x 226659243Sobrien * The stuff here seems to work, but I did it by trial and error rather 226759243Sobrien * than really knowing what was going on. If tpgrp is zero, we are 226859243Sobrien * probably a background eval, e.g. "eval date &", and we want to 226959243Sobrien * make sure that any processes we start stay in our pgrp. 227059243Sobrien * This is also the case for "time eval date" -- stay in same pgrp. 227159243Sobrien * Otherwise, under stty tostop, processes will stop in the wrong 227259243Sobrien * pgrp, with no way for the shell to get them going again. -IAN! 227359243Sobrien */ 227459243Sobrien 227559243Sobrienstatic Char **gv = NULL, **gav = NULL; 227659243Sobrien 227759243Sobrien/*ARGSUSED*/ 227859243Sobrienvoid 227959243Sobriendoeval(v, c) 228059243Sobrien Char **v; 228159243Sobrien struct command *c; 228259243Sobrien{ 228359243Sobrien Char **oevalvec; 228459243Sobrien Char *oevalp; 228559243Sobrien int odidfds; 228659243Sobrien#ifndef CLOSE_ON_EXEC 228759243Sobrien int odidcch; 228859243Sobrien#endif /* CLOSE_ON_EXEC */ 228959243Sobrien jmp_buf_t osetexit; 229059243Sobrien int my_reenter; 229159243Sobrien Char **savegv; 229259243Sobrien int saveIN, saveOUT, saveDIAG; 229359243Sobrien int oSHIN, oSHOUT, oSHDIAG; 229459243Sobrien 229559243Sobrien USE(c); 229659243Sobrien oevalvec = evalvec; 229759243Sobrien oevalp = evalp; 229859243Sobrien odidfds = didfds; 229959243Sobrien#ifndef CLOSE_ON_EXEC 230059243Sobrien odidcch = didcch; 230159243Sobrien#endif /* CLOSE_ON_EXEC */ 230259243Sobrien oSHIN = SHIN; 230359243Sobrien oSHOUT = SHOUT; 230459243Sobrien oSHDIAG = SHDIAG; 230559243Sobrien 230659243Sobrien savegv = gv; 230759243Sobrien gav = v; 230859243Sobrien 230959243Sobrien gav++; 231059243Sobrien if (*gav == 0) 231159243Sobrien return; 231259243Sobrien gflag = 0, tglob(gav); 231359243Sobrien if (gflag) { 231459243Sobrien gv = gav = globall(gav); 231559243Sobrien gargv = 0; 231659243Sobrien if (gav == 0) 231759243Sobrien stderror(ERR_NOMATCH); 231859243Sobrien gav = copyblk(gav); 231959243Sobrien } 232059243Sobrien else { 232159243Sobrien gv = NULL; 232259243Sobrien gav = copyblk(gav); 232359243Sobrien trim(gav); 232459243Sobrien } 232559243Sobrien 232659243Sobrien saveIN = dcopy(SHIN, -1); 232759243Sobrien saveOUT = dcopy(SHOUT, -1); 232859243Sobrien saveDIAG = dcopy(SHDIAG, -1); 232959243Sobrien 233059243Sobrien getexit(osetexit); 233159243Sobrien 233259243Sobrien /* PWP: setjmp/longjmp bugfix for optimizing compilers */ 233359243Sobrien#ifdef cray 233459243Sobrien my_reenter = 1; /* assume non-zero return val */ 233559243Sobrien if (setexit() == 0) { 233659243Sobrien my_reenter = 0; /* Oh well, we were wrong */ 233759243Sobrien#else /* !cray */ 233859243Sobrien if ((my_reenter = setexit()) == 0) { 233959243Sobrien#endif /* cray */ 234059243Sobrien evalvec = gav; 234159243Sobrien evalp = 0; 234259243Sobrien SHIN = dcopy(0, -1); 234359243Sobrien SHOUT = dcopy(1, -1); 234459243Sobrien SHDIAG = dcopy(2, -1); 234559243Sobrien#ifndef CLOSE_ON_EXEC 234659243Sobrien didcch = 0; 234759243Sobrien#endif /* CLOSE_ON_EXEC */ 234859243Sobrien didfds = 0; 234959243Sobrien process(0); 235059243Sobrien } 235159243Sobrien 235259243Sobrien evalvec = oevalvec; 235359243Sobrien evalp = oevalp; 235459243Sobrien doneinp = 0; 235559243Sobrien#ifndef CLOSE_ON_EXEC 235659243Sobrien didcch = odidcch; 235759243Sobrien#endif /* CLOSE_ON_EXEC */ 235859243Sobrien didfds = odidfds; 235959243Sobrien (void) close(SHIN); 236059243Sobrien (void) close(SHOUT); 236159243Sobrien (void) close(SHDIAG); 236259243Sobrien SHIN = dmove(saveIN, oSHIN); 236359243Sobrien SHOUT = dmove(saveOUT, oSHOUT); 236459243Sobrien SHDIAG = dmove(saveDIAG, oSHDIAG); 236559243Sobrien 236659243Sobrien if (gv) 236759243Sobrien blkfree(gv); 236859243Sobrien 236959243Sobrien gv = savegv; 237059243Sobrien resexit(osetexit); 237159243Sobrien if (my_reenter) 237259243Sobrien stderror(ERR_SILENT); 237359243Sobrien} 237459243Sobrien 237559243Sobrien/*************************************************************************/ 237659243Sobrien/* print list of builtin commands */ 237759243Sobrien 237859243Sobrien/*ARGSUSED*/ 237959243Sobrienvoid 238059243Sobriendobuiltins(v, c) 238159243SobrienChar **v; 238259243Sobrienstruct command *c; 238359243Sobrien{ 238459243Sobrien /* would use print_by_column() in tw.parse.c but that assumes 238559243Sobrien * we have an array of Char * to pass.. (sg) 238659243Sobrien */ 238759243Sobrien extern int Tty_raw_mode; 238859243Sobrien extern int TermH; /* from the editor routines */ 238959243Sobrien extern int lbuffed; /* from sh.print.c */ 239059243Sobrien 239159243Sobrien register struct biltins *b; 239259243Sobrien register int row, col, columns, rows; 239359243Sobrien unsigned int w, maxwidth; 239459243Sobrien 239559243Sobrien USE(c); 239659243Sobrien USE(v); 239759243Sobrien lbuffed = 0; /* turn off line buffering */ 239859243Sobrien 239959243Sobrien /* find widest string */ 240059243Sobrien for (maxwidth = 0, b = bfunc; b < &bfunc[nbfunc]; ++b) 240159243Sobrien maxwidth = max(maxwidth, strlen(b->bname)); 240259243Sobrien ++maxwidth; /* for space */ 240359243Sobrien 240459243Sobrien columns = (TermH + 1) / maxwidth; /* PWP: terminal size change */ 240559243Sobrien if (!columns) 240659243Sobrien columns = 1; 240759243Sobrien rows = (nbfunc + (columns - 1)) / columns; 240859243Sobrien 240959243Sobrien for (b = bfunc, row = 0; row < rows; row++) { 241059243Sobrien for (col = 0; col < columns; col++) { 241159243Sobrien if (b < &bfunc[nbfunc]) { 241259243Sobrien w = strlen(b->bname); 241359243Sobrien xprintf("%s", b->bname); 241459243Sobrien if (col < (columns - 1)) /* Not last column? */ 241559243Sobrien for (; w < maxwidth; w++) 241659243Sobrien xputchar(' '); 241759243Sobrien ++b; 241859243Sobrien } 241959243Sobrien } 242059243Sobrien if (row < (rows - 1)) { 242159243Sobrien if (Tty_raw_mode) 242259243Sobrien xputchar('\r'); 242359243Sobrien xputchar('\n'); 242459243Sobrien } 242559243Sobrien } 242669408Sache#ifdef WINNT_NATIVE 242759243Sobrien nt_print_builtins(maxwidth); 242859243Sobrien#else 242959243Sobrien if (Tty_raw_mode) 243059243Sobrien xputchar('\r'); 243159243Sobrien xputchar('\n'); 243269408Sache#endif /* WINNT_NATIVE */ 243359243Sobrien 243459243Sobrien lbuffed = 1; /* turn back on line buffering */ 243559243Sobrien flush(); 243659243Sobrien} 243759243Sobrien 243859243Sobrienvoid 243959243Sobriennlsinit() 244059243Sobrien{ 244159243Sobrien#ifdef NLS_CATALOGS 244269408Sache char catalog[ 256 ] = { 't', 'c', 's', 'h', '\0' }; 244369408Sache 244469408Sache if (adrof(STRcatalog) != NULL) 244569408Sache xsnprintf((char *)catalog, sizeof(catalog), "tcsh.%s", 244669408Sache short2str(varval(STRcatalog))); 244769408Sache catd = catopen(catalog, MCLoadBySet); 244869408Sache#endif /* NLS_CATALOGS */ 244969408Sache#ifdef WINNT_NATIVE 245059243Sobrien nls_dll_init(); 245169408Sache#endif /* WINNT_NATIVE */ 245259243Sobrien errinit(); /* init the errorlist in correct locale */ 245359243Sobrien mesginit(); /* init the messages for signals */ 245459243Sobrien dateinit(); /* init the messages for dates */ 245559243Sobrien editinit(); /* init the editor messages */ 245659243Sobrien terminit(); /* init the termcap messages */ 245759243Sobrien} 2458