1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 3*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 4*7c478bd9Sstevel@tonic-gate */ 5*7c478bd9Sstevel@tonic-gate 6*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 7*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 8*7c478bd9Sstevel@tonic-gate 9*7c478bd9Sstevel@tonic-gate /* 10*7c478bd9Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California. 11*7c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley Software License Agreement 12*7c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 13*7c478bd9Sstevel@tonic-gate */ 14*7c478bd9Sstevel@tonic-gate 15*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 16*7c478bd9Sstevel@tonic-gate 17*7c478bd9Sstevel@tonic-gate #include "sh.h" 18*7c478bd9Sstevel@tonic-gate #include <locale.h> /* For LC_ALL */ 19*7c478bd9Sstevel@tonic-gate #include "sh.tconst.h" 20*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 21*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 22*7c478bd9Sstevel@tonic-gate 23*7c478bd9Sstevel@tonic-gate /* 24*7c478bd9Sstevel@tonic-gate * N.B.: Some of the limits change from SunOS 4.x to SunOS 5.0. In 25*7c478bd9Sstevel@tonic-gate * particular, RLIMIT_RSS is gone and RLIMIT_VMEM is new. Beware of consusing 26*7c478bd9Sstevel@tonic-gate * the keywords that the command prints for these two. The old one was 27*7c478bd9Sstevel@tonic-gate * "memoryuse" and the new one is "memorysize". Note also that a given limit 28*7c478bd9Sstevel@tonic-gate * doesn't necessarily appear in the same position in the two releases. 29*7c478bd9Sstevel@tonic-gate */ 30*7c478bd9Sstevel@tonic-gate struct limits { 31*7c478bd9Sstevel@tonic-gate int limconst; 32*7c478bd9Sstevel@tonic-gate tchar *limname; 33*7c478bd9Sstevel@tonic-gate int limdiv; 34*7c478bd9Sstevel@tonic-gate tchar *limscale; 35*7c478bd9Sstevel@tonic-gate } limits[] = { 36*7c478bd9Sstevel@tonic-gate RLIMIT_CPU, S_cputime, /* "cputime" */ 37*7c478bd9Sstevel@tonic-gate 1, S_seconds, /* "seconds" */ 38*7c478bd9Sstevel@tonic-gate RLIMIT_FSIZE, S_filesize, /* "filesize" */ 39*7c478bd9Sstevel@tonic-gate 1024, S_kbytes, /* "kbytes" */ 40*7c478bd9Sstevel@tonic-gate RLIMIT_DATA, S_datasize, /* "datasize" */ 41*7c478bd9Sstevel@tonic-gate 1024, S_kbytes, /* "kbytes" */ 42*7c478bd9Sstevel@tonic-gate RLIMIT_STACK, S_stacksize, /* "stacksize" */ 43*7c478bd9Sstevel@tonic-gate 1024, S_kbytes, /* "kbytes" */ 44*7c478bd9Sstevel@tonic-gate RLIMIT_CORE, S_coredumpsize, /* "coredumpsize" */ 45*7c478bd9Sstevel@tonic-gate 1024, S_kbytes, /* "kbytes" */ 46*7c478bd9Sstevel@tonic-gate RLIMIT_NOFILE, S_descriptors, /* "descriptors" */ 47*7c478bd9Sstevel@tonic-gate 1, S_, /* "" */ 48*7c478bd9Sstevel@tonic-gate RLIMIT_VMEM, S_memorysize, /* "memorysize" */ 49*7c478bd9Sstevel@tonic-gate 1024, S_kbytes, /* "kbytes" */ 50*7c478bd9Sstevel@tonic-gate -1, 0, 51*7c478bd9Sstevel@tonic-gate }; 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate static int getval(struct limits *lp, tchar **v, rlim_t *); 54*7c478bd9Sstevel@tonic-gate void islogin(); 55*7c478bd9Sstevel@tonic-gate int dolabel(); 56*7c478bd9Sstevel@tonic-gate void reexecute(struct command *kp); 57*7c478bd9Sstevel@tonic-gate void preread_(); 58*7c478bd9Sstevel@tonic-gate void doagain(); 59*7c478bd9Sstevel@tonic-gate void toend(); 60*7c478bd9Sstevel@tonic-gate void wfree(); 61*7c478bd9Sstevel@tonic-gate void echo(tchar sep, tchar **v); 62*7c478bd9Sstevel@tonic-gate void local_setenv(tchar *name, tchar *val); 63*7c478bd9Sstevel@tonic-gate void local_unsetenv(tchar *name); 64*7c478bd9Sstevel@tonic-gate void limtail(tchar *cp, tchar *str0); 65*7c478bd9Sstevel@tonic-gate void plim(struct limits *lp, tchar hard); 66*7c478bd9Sstevel@tonic-gate void search(); 67*7c478bd9Sstevel@tonic-gate 68*7c478bd9Sstevel@tonic-gate #define BUFSZ 1028 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate /* 71*7c478bd9Sstevel@tonic-gate * C shell 72*7c478bd9Sstevel@tonic-gate */ 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate struct 75*7c478bd9Sstevel@tonic-gate biltins * 76*7c478bd9Sstevel@tonic-gate isbfunc(struct command *t) 77*7c478bd9Sstevel@tonic-gate { 78*7c478bd9Sstevel@tonic-gate tchar *cp = t->t_dcom[0]; 79*7c478bd9Sstevel@tonic-gate struct biltins *bp, *bp1, *bp2; 80*7c478bd9Sstevel@tonic-gate int dofg1(), dobg1(); 81*7c478bd9Sstevel@tonic-gate 82*7c478bd9Sstevel@tonic-gate static struct biltins label = { S_, dolabel, 0, 0 }; 83*7c478bd9Sstevel@tonic-gate static struct biltins foregnd = { S_Pjob, dofg1, 0, 0 }; 84*7c478bd9Sstevel@tonic-gate static struct biltins backgnd = { S_PjobAND, dobg1, 0, 0 }; 85*7c478bd9Sstevel@tonic-gate #ifdef TRACE 86*7c478bd9Sstevel@tonic-gate tprintf("TRACE- isbfunc()\n"); 87*7c478bd9Sstevel@tonic-gate #endif 88*7c478bd9Sstevel@tonic-gate if (lastchr(cp) == ':') { 89*7c478bd9Sstevel@tonic-gate label.bname = cp; 90*7c478bd9Sstevel@tonic-gate return (&label); 91*7c478bd9Sstevel@tonic-gate } 92*7c478bd9Sstevel@tonic-gate if (*cp == '%') { 93*7c478bd9Sstevel@tonic-gate if (t->t_dflg & FAND) { 94*7c478bd9Sstevel@tonic-gate t->t_dflg &= ~FAND; 95*7c478bd9Sstevel@tonic-gate backgnd.bname = cp; 96*7c478bd9Sstevel@tonic-gate return (&backgnd); 97*7c478bd9Sstevel@tonic-gate } 98*7c478bd9Sstevel@tonic-gate foregnd.bname = cp; 99*7c478bd9Sstevel@tonic-gate return (&foregnd); 100*7c478bd9Sstevel@tonic-gate } 101*7c478bd9Sstevel@tonic-gate /* 102*7c478bd9Sstevel@tonic-gate * Binary search 103*7c478bd9Sstevel@tonic-gate * Bp1 is the beginning of the current search range. 104*7c478bd9Sstevel@tonic-gate * Bp2 is one past the end. 105*7c478bd9Sstevel@tonic-gate */ 106*7c478bd9Sstevel@tonic-gate for (bp1 = bfunc, bp2 = bfunc + nbfunc; bp1 < bp2; ) { 107*7c478bd9Sstevel@tonic-gate int i; 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate bp = bp1 + (bp2 - bp1 >> 1); 110*7c478bd9Sstevel@tonic-gate if ((i = *cp - *bp->bname) == 0 && 111*7c478bd9Sstevel@tonic-gate (i = strcmp_(cp, bp->bname)) == 0) { 112*7c478bd9Sstevel@tonic-gate return (bp); 113*7c478bd9Sstevel@tonic-gate } 114*7c478bd9Sstevel@tonic-gate if (i < 0) { 115*7c478bd9Sstevel@tonic-gate bp2 = bp; 116*7c478bd9Sstevel@tonic-gate } else { 117*7c478bd9Sstevel@tonic-gate bp1 = bp + 1; 118*7c478bd9Sstevel@tonic-gate } 119*7c478bd9Sstevel@tonic-gate } 120*7c478bd9Sstevel@tonic-gate return (0); 121*7c478bd9Sstevel@tonic-gate } 122*7c478bd9Sstevel@tonic-gate 123*7c478bd9Sstevel@tonic-gate void 124*7c478bd9Sstevel@tonic-gate func(struct command *t, struct biltins *bp) 125*7c478bd9Sstevel@tonic-gate { 126*7c478bd9Sstevel@tonic-gate int i; 127*7c478bd9Sstevel@tonic-gate 128*7c478bd9Sstevel@tonic-gate #ifdef TRACE 129*7c478bd9Sstevel@tonic-gate tprintf("TRACE- func()\n"); 130*7c478bd9Sstevel@tonic-gate #endif 131*7c478bd9Sstevel@tonic-gate xechoit(t->t_dcom); 132*7c478bd9Sstevel@tonic-gate setname(bp->bname); 133*7c478bd9Sstevel@tonic-gate i = blklen(t->t_dcom) - 1; 134*7c478bd9Sstevel@tonic-gate if (i < bp->minargs) { 135*7c478bd9Sstevel@tonic-gate bferr("Too few arguments"); 136*7c478bd9Sstevel@tonic-gate } 137*7c478bd9Sstevel@tonic-gate if (i > bp->maxargs) { 138*7c478bd9Sstevel@tonic-gate bferr("Too many arguments"); 139*7c478bd9Sstevel@tonic-gate } 140*7c478bd9Sstevel@tonic-gate (*bp->bfunct)(t->t_dcom, t); 141*7c478bd9Sstevel@tonic-gate } 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate int 144*7c478bd9Sstevel@tonic-gate dolabel() 145*7c478bd9Sstevel@tonic-gate { 146*7c478bd9Sstevel@tonic-gate #ifdef TRACE 147*7c478bd9Sstevel@tonic-gate tprintf("TRACE- dolabel()\n"); 148*7c478bd9Sstevel@tonic-gate #endif 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate } 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate void 153*7c478bd9Sstevel@tonic-gate doonintr(tchar **v) 154*7c478bd9Sstevel@tonic-gate { 155*7c478bd9Sstevel@tonic-gate tchar *cp; 156*7c478bd9Sstevel@tonic-gate tchar *vv = v[1]; 157*7c478bd9Sstevel@tonic-gate 158*7c478bd9Sstevel@tonic-gate #ifdef TRACE 159*7c478bd9Sstevel@tonic-gate tprintf("TRACE- doonintr()\n"); 160*7c478bd9Sstevel@tonic-gate #endif 161*7c478bd9Sstevel@tonic-gate if (parintr == SIG_IGN) { 162*7c478bd9Sstevel@tonic-gate return; 163*7c478bd9Sstevel@tonic-gate } 164*7c478bd9Sstevel@tonic-gate if (setintr && intty) { 165*7c478bd9Sstevel@tonic-gate bferr("Can't from terminal"); 166*7c478bd9Sstevel@tonic-gate } 167*7c478bd9Sstevel@tonic-gate cp = gointr, gointr = 0, xfree(cp); 168*7c478bd9Sstevel@tonic-gate if (vv == 0) { 169*7c478bd9Sstevel@tonic-gate if (setintr) { 170*7c478bd9Sstevel@tonic-gate (void) sigblock(sigmask(SIGINT)); 171*7c478bd9Sstevel@tonic-gate } else { 172*7c478bd9Sstevel@tonic-gate (void) signal(SIGINT, SIG_DFL); 173*7c478bd9Sstevel@tonic-gate } 174*7c478bd9Sstevel@tonic-gate gointr = 0; 175*7c478bd9Sstevel@tonic-gate } else if (eq((vv = strip(vv)), S_MINUS)) { 176*7c478bd9Sstevel@tonic-gate (void) signal(SIGINT, SIG_IGN); 177*7c478bd9Sstevel@tonic-gate gointr = S_MINUS; 178*7c478bd9Sstevel@tonic-gate } else { 179*7c478bd9Sstevel@tonic-gate gointr = savestr(vv); 180*7c478bd9Sstevel@tonic-gate (void) signal(SIGINT, pintr); 181*7c478bd9Sstevel@tonic-gate } 182*7c478bd9Sstevel@tonic-gate } 183*7c478bd9Sstevel@tonic-gate 184*7c478bd9Sstevel@tonic-gate void 185*7c478bd9Sstevel@tonic-gate donohup() 186*7c478bd9Sstevel@tonic-gate { 187*7c478bd9Sstevel@tonic-gate 188*7c478bd9Sstevel@tonic-gate #ifdef TRACE 189*7c478bd9Sstevel@tonic-gate tprintf("TRACE- donohup()\n"); 190*7c478bd9Sstevel@tonic-gate #endif 191*7c478bd9Sstevel@tonic-gate if (intty) { 192*7c478bd9Sstevel@tonic-gate bferr("Can't from terminal"); 193*7c478bd9Sstevel@tonic-gate } 194*7c478bd9Sstevel@tonic-gate if (setintr == 0) { 195*7c478bd9Sstevel@tonic-gate (void) signal(SIGHUP, SIG_IGN); 196*7c478bd9Sstevel@tonic-gate #ifdef CC 197*7c478bd9Sstevel@tonic-gate submit(getpid()); 198*7c478bd9Sstevel@tonic-gate #endif 199*7c478bd9Sstevel@tonic-gate } 200*7c478bd9Sstevel@tonic-gate } 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate void 203*7c478bd9Sstevel@tonic-gate dozip() 204*7c478bd9Sstevel@tonic-gate { 205*7c478bd9Sstevel@tonic-gate ; 206*7c478bd9Sstevel@tonic-gate } 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate void 209*7c478bd9Sstevel@tonic-gate prvars() 210*7c478bd9Sstevel@tonic-gate { 211*7c478bd9Sstevel@tonic-gate #ifdef TRACE 212*7c478bd9Sstevel@tonic-gate tprintf("TRACE- prvars()\n"); 213*7c478bd9Sstevel@tonic-gate #endif 214*7c478bd9Sstevel@tonic-gate 215*7c478bd9Sstevel@tonic-gate plist(&shvhed); 216*7c478bd9Sstevel@tonic-gate } 217*7c478bd9Sstevel@tonic-gate 218*7c478bd9Sstevel@tonic-gate void 219*7c478bd9Sstevel@tonic-gate doalias(tchar **v) 220*7c478bd9Sstevel@tonic-gate { 221*7c478bd9Sstevel@tonic-gate struct varent *vp; 222*7c478bd9Sstevel@tonic-gate tchar *p; 223*7c478bd9Sstevel@tonic-gate 224*7c478bd9Sstevel@tonic-gate #ifdef TRACE 225*7c478bd9Sstevel@tonic-gate tprintf("TRACE- doalias()\n"); 226*7c478bd9Sstevel@tonic-gate #endif 227*7c478bd9Sstevel@tonic-gate v++; 228*7c478bd9Sstevel@tonic-gate p = *v++; 229*7c478bd9Sstevel@tonic-gate if (p == 0) { 230*7c478bd9Sstevel@tonic-gate plist(&aliases); 231*7c478bd9Sstevel@tonic-gate } else if (*v == 0) { 232*7c478bd9Sstevel@tonic-gate vp = adrof1(strip(p), &aliases); 233*7c478bd9Sstevel@tonic-gate if (vp) { 234*7c478bd9Sstevel@tonic-gate blkpr(vp->vec), printf("\n"); 235*7c478bd9Sstevel@tonic-gate } 236*7c478bd9Sstevel@tonic-gate } else { 237*7c478bd9Sstevel@tonic-gate if (eq(p, S_alias) || 238*7c478bd9Sstevel@tonic-gate eq(p, S_unalias)) { 239*7c478bd9Sstevel@tonic-gate setname(p); 240*7c478bd9Sstevel@tonic-gate bferr("Too dangerous to alias that"); 241*7c478bd9Sstevel@tonic-gate } 242*7c478bd9Sstevel@tonic-gate set1(strip(p), saveblk(v), &aliases); 243*7c478bd9Sstevel@tonic-gate } 244*7c478bd9Sstevel@tonic-gate } 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate void 247*7c478bd9Sstevel@tonic-gate unalias(tchar **v) 248*7c478bd9Sstevel@tonic-gate { 249*7c478bd9Sstevel@tonic-gate 250*7c478bd9Sstevel@tonic-gate #ifdef TRACE 251*7c478bd9Sstevel@tonic-gate tprintf("TRACE- unalias()\n"); 252*7c478bd9Sstevel@tonic-gate #endif 253*7c478bd9Sstevel@tonic-gate unset1(v, &aliases); 254*7c478bd9Sstevel@tonic-gate } 255*7c478bd9Sstevel@tonic-gate 256*7c478bd9Sstevel@tonic-gate void 257*7c478bd9Sstevel@tonic-gate dologout() 258*7c478bd9Sstevel@tonic-gate { 259*7c478bd9Sstevel@tonic-gate 260*7c478bd9Sstevel@tonic-gate #ifdef TRACE 261*7c478bd9Sstevel@tonic-gate tprintf("TRACE- dologout()\n"); 262*7c478bd9Sstevel@tonic-gate #endif 263*7c478bd9Sstevel@tonic-gate islogin(); 264*7c478bd9Sstevel@tonic-gate goodbye(); 265*7c478bd9Sstevel@tonic-gate } 266*7c478bd9Sstevel@tonic-gate 267*7c478bd9Sstevel@tonic-gate void 268*7c478bd9Sstevel@tonic-gate dologin(tchar **v) 269*7c478bd9Sstevel@tonic-gate { 270*7c478bd9Sstevel@tonic-gate 271*7c478bd9Sstevel@tonic-gate char *v_; /* work */ 272*7c478bd9Sstevel@tonic-gate #ifdef TRACE 273*7c478bd9Sstevel@tonic-gate tprintf("TRACE- dologin()\n"); 274*7c478bd9Sstevel@tonic-gate #endif 275*7c478bd9Sstevel@tonic-gate islogin(); 276*7c478bd9Sstevel@tonic-gate rechist(); 277*7c478bd9Sstevel@tonic-gate (void) signal(SIGTERM, parterm); 278*7c478bd9Sstevel@tonic-gate if (v[1] != NULL) { 279*7c478bd9Sstevel@tonic-gate v_ = tstostr(NULL, v[1]); /* No need to free */ 280*7c478bd9Sstevel@tonic-gate } else { 281*7c478bd9Sstevel@tonic-gate v_ = 0; 282*7c478bd9Sstevel@tonic-gate } 283*7c478bd9Sstevel@tonic-gate execl("/bin/login", "login", v_, 0); 284*7c478bd9Sstevel@tonic-gate untty(); 285*7c478bd9Sstevel@tonic-gate exit(1); 286*7c478bd9Sstevel@tonic-gate } 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate #ifdef NEWGRP 289*7c478bd9Sstevel@tonic-gate void 290*7c478bd9Sstevel@tonic-gate donewgrp(tchar **v) 291*7c478bd9Sstevel@tonic-gate { 292*7c478bd9Sstevel@tonic-gate 293*7c478bd9Sstevel@tonic-gate char *v_; /* work */ 294*7c478bd9Sstevel@tonic-gate #ifdef TRACE 295*7c478bd9Sstevel@tonic-gate tprintf("TRACE- donewgrp()\n"); 296*7c478bd9Sstevel@tonic-gate #endif 297*7c478bd9Sstevel@tonic-gate if (chkstop == 0 && setintr) { 298*7c478bd9Sstevel@tonic-gate panystop(0); 299*7c478bd9Sstevel@tonic-gate } 300*7c478bd9Sstevel@tonic-gate (void) signal(SIGTERM, parterm); 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate if (v[1] != NULL) { 303*7c478bd9Sstevel@tonic-gate v_ = tstostr(NOSTR, v[1]); /* No need to free */ 304*7c478bd9Sstevel@tonic-gate } else { 305*7c478bd9Sstevel@tonic-gate v_ = 0; 306*7c478bd9Sstevel@tonic-gate } 307*7c478bd9Sstevel@tonic-gate execl("/bin/newgrp", "newgrp", v_, 0); 308*7c478bd9Sstevel@tonic-gate execl("/usr/bin/newgrp", "newgrp", v_, 0); 309*7c478bd9Sstevel@tonic-gate untty(); 310*7c478bd9Sstevel@tonic-gate exit(1); 311*7c478bd9Sstevel@tonic-gate } 312*7c478bd9Sstevel@tonic-gate #endif 313*7c478bd9Sstevel@tonic-gate 314*7c478bd9Sstevel@tonic-gate void 315*7c478bd9Sstevel@tonic-gate islogin() 316*7c478bd9Sstevel@tonic-gate { 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate #ifdef TRACE 319*7c478bd9Sstevel@tonic-gate tprintf("TRACE- islogin()\n"); 320*7c478bd9Sstevel@tonic-gate #endif 321*7c478bd9Sstevel@tonic-gate if (chkstop == 0 && setintr) { 322*7c478bd9Sstevel@tonic-gate panystop(0); 323*7c478bd9Sstevel@tonic-gate } 324*7c478bd9Sstevel@tonic-gate if (loginsh) { 325*7c478bd9Sstevel@tonic-gate return; 326*7c478bd9Sstevel@tonic-gate } 327*7c478bd9Sstevel@tonic-gate error("Not login shell"); 328*7c478bd9Sstevel@tonic-gate } 329*7c478bd9Sstevel@tonic-gate 330*7c478bd9Sstevel@tonic-gate void 331*7c478bd9Sstevel@tonic-gate doif(tchar **v, struct command *kp) 332*7c478bd9Sstevel@tonic-gate { 333*7c478bd9Sstevel@tonic-gate int i; 334*7c478bd9Sstevel@tonic-gate tchar **vv; 335*7c478bd9Sstevel@tonic-gate 336*7c478bd9Sstevel@tonic-gate #ifdef TRACE 337*7c478bd9Sstevel@tonic-gate tprintf("TRACE- doif()\n"); 338*7c478bd9Sstevel@tonic-gate #endif 339*7c478bd9Sstevel@tonic-gate v++; 340*7c478bd9Sstevel@tonic-gate i = exp(&v); 341*7c478bd9Sstevel@tonic-gate vv = v; 342*7c478bd9Sstevel@tonic-gate if (*vv == NOSTR) { 343*7c478bd9Sstevel@tonic-gate bferr("Empty if"); 344*7c478bd9Sstevel@tonic-gate } 345*7c478bd9Sstevel@tonic-gate if (eq(*vv, S_then)) { 346*7c478bd9Sstevel@tonic-gate if (*++vv) { 347*7c478bd9Sstevel@tonic-gate bferr("Improper then"); 348*7c478bd9Sstevel@tonic-gate } 349*7c478bd9Sstevel@tonic-gate setname(S_then); 350*7c478bd9Sstevel@tonic-gate /* 351*7c478bd9Sstevel@tonic-gate * If expression was zero, then scan to else, 352*7c478bd9Sstevel@tonic-gate * otherwise just fall into following code. 353*7c478bd9Sstevel@tonic-gate */ 354*7c478bd9Sstevel@tonic-gate if (!i) { 355*7c478bd9Sstevel@tonic-gate search(ZIF, 0); 356*7c478bd9Sstevel@tonic-gate } 357*7c478bd9Sstevel@tonic-gate return; 358*7c478bd9Sstevel@tonic-gate } 359*7c478bd9Sstevel@tonic-gate /* 360*7c478bd9Sstevel@tonic-gate * Simple command attached to this if. 361*7c478bd9Sstevel@tonic-gate * Left shift the node in this tree, munging it 362*7c478bd9Sstevel@tonic-gate * so we can reexecute it. 363*7c478bd9Sstevel@tonic-gate */ 364*7c478bd9Sstevel@tonic-gate if (i) { 365*7c478bd9Sstevel@tonic-gate lshift(kp->t_dcom, vv - kp->t_dcom); 366*7c478bd9Sstevel@tonic-gate reexecute(kp); 367*7c478bd9Sstevel@tonic-gate donefds(); 368*7c478bd9Sstevel@tonic-gate } 369*7c478bd9Sstevel@tonic-gate } 370*7c478bd9Sstevel@tonic-gate 371*7c478bd9Sstevel@tonic-gate /* 372*7c478bd9Sstevel@tonic-gate * Reexecute a command, being careful not 373*7c478bd9Sstevel@tonic-gate * to redo i/o redirection, which is already set up. 374*7c478bd9Sstevel@tonic-gate */ 375*7c478bd9Sstevel@tonic-gate void 376*7c478bd9Sstevel@tonic-gate reexecute(struct command *kp) 377*7c478bd9Sstevel@tonic-gate { 378*7c478bd9Sstevel@tonic-gate 379*7c478bd9Sstevel@tonic-gate #ifdef TRACE 380*7c478bd9Sstevel@tonic-gate tprintf("TRACE- reexecute()\n"); 381*7c478bd9Sstevel@tonic-gate #endif 382*7c478bd9Sstevel@tonic-gate kp->t_dflg &= FSAVE; 383*7c478bd9Sstevel@tonic-gate kp->t_dflg |= FREDO; 384*7c478bd9Sstevel@tonic-gate /* 385*7c478bd9Sstevel@tonic-gate * If tty is still ours to arbitrate, arbitrate it; 386*7c478bd9Sstevel@tonic-gate * otherwise dont even set pgrp's as the jobs would 387*7c478bd9Sstevel@tonic-gate * then have no way to get the tty (we can't give it 388*7c478bd9Sstevel@tonic-gate * to them, and our parent wouldn't know their pgrp, etc. 389*7c478bd9Sstevel@tonic-gate */ 390*7c478bd9Sstevel@tonic-gate execute(kp, tpgrp > 0 ? tpgrp : -1); 391*7c478bd9Sstevel@tonic-gate } 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate void 394*7c478bd9Sstevel@tonic-gate doelse() 395*7c478bd9Sstevel@tonic-gate { 396*7c478bd9Sstevel@tonic-gate 397*7c478bd9Sstevel@tonic-gate #ifdef TRACE 398*7c478bd9Sstevel@tonic-gate tprintf("TRACE- doelse()\n"); 399*7c478bd9Sstevel@tonic-gate #endif 400*7c478bd9Sstevel@tonic-gate search(ZELSE, 0); 401*7c478bd9Sstevel@tonic-gate } 402*7c478bd9Sstevel@tonic-gate 403*7c478bd9Sstevel@tonic-gate void 404*7c478bd9Sstevel@tonic-gate dogoto(tchar **v) 405*7c478bd9Sstevel@tonic-gate { 406*7c478bd9Sstevel@tonic-gate struct whyle *wp; 407*7c478bd9Sstevel@tonic-gate tchar *lp; 408*7c478bd9Sstevel@tonic-gate #ifdef TRACE 409*7c478bd9Sstevel@tonic-gate tprintf("TRACE- dogoto()\n"); 410*7c478bd9Sstevel@tonic-gate #endif 411*7c478bd9Sstevel@tonic-gate 412*7c478bd9Sstevel@tonic-gate /* 413*7c478bd9Sstevel@tonic-gate * While we still can, locate any unknown ends of existing loops. 414*7c478bd9Sstevel@tonic-gate * This obscure code is the WORST result of the fact that we 415*7c478bd9Sstevel@tonic-gate * don't really parse. 416*7c478bd9Sstevel@tonic-gate */ 417*7c478bd9Sstevel@tonic-gate for (wp = whyles; wp; wp = wp->w_next) { 418*7c478bd9Sstevel@tonic-gate if (wp->w_end == 0) { 419*7c478bd9Sstevel@tonic-gate search(ZBREAK, 0); 420*7c478bd9Sstevel@tonic-gate wp->w_end = btell(); 421*7c478bd9Sstevel@tonic-gate } else { 422*7c478bd9Sstevel@tonic-gate bseek(wp->w_end); 423*7c478bd9Sstevel@tonic-gate } 424*7c478bd9Sstevel@tonic-gate } 425*7c478bd9Sstevel@tonic-gate search(ZGOTO, 0, lp = globone(v[1])); 426*7c478bd9Sstevel@tonic-gate xfree(lp); 427*7c478bd9Sstevel@tonic-gate /* 428*7c478bd9Sstevel@tonic-gate * Eliminate loops which were exited. 429*7c478bd9Sstevel@tonic-gate */ 430*7c478bd9Sstevel@tonic-gate wfree(); 431*7c478bd9Sstevel@tonic-gate } 432*7c478bd9Sstevel@tonic-gate 433*7c478bd9Sstevel@tonic-gate void 434*7c478bd9Sstevel@tonic-gate doswitch(tchar **v) 435*7c478bd9Sstevel@tonic-gate { 436*7c478bd9Sstevel@tonic-gate tchar *cp, *lp; 437*7c478bd9Sstevel@tonic-gate 438*7c478bd9Sstevel@tonic-gate #ifdef TRACE 439*7c478bd9Sstevel@tonic-gate tprintf("TRACE- doswitch()\n"); 440*7c478bd9Sstevel@tonic-gate #endif 441*7c478bd9Sstevel@tonic-gate v++; 442*7c478bd9Sstevel@tonic-gate if (!*v || *(*v++) != '(') { 443*7c478bd9Sstevel@tonic-gate goto syntax; 444*7c478bd9Sstevel@tonic-gate } 445*7c478bd9Sstevel@tonic-gate cp = **v == ')' ? S_ : *v++; 446*7c478bd9Sstevel@tonic-gate if (*(*v++) != ')') { 447*7c478bd9Sstevel@tonic-gate v--; 448*7c478bd9Sstevel@tonic-gate } 449*7c478bd9Sstevel@tonic-gate if (*v) { 450*7c478bd9Sstevel@tonic-gate syntax: 451*7c478bd9Sstevel@tonic-gate error("Syntax error"); 452*7c478bd9Sstevel@tonic-gate } 453*7c478bd9Sstevel@tonic-gate search(ZSWITCH, 0, lp = globone(cp)); 454*7c478bd9Sstevel@tonic-gate xfree(lp); 455*7c478bd9Sstevel@tonic-gate } 456*7c478bd9Sstevel@tonic-gate 457*7c478bd9Sstevel@tonic-gate void 458*7c478bd9Sstevel@tonic-gate dobreak() 459*7c478bd9Sstevel@tonic-gate { 460*7c478bd9Sstevel@tonic-gate 461*7c478bd9Sstevel@tonic-gate #ifdef TRACE 462*7c478bd9Sstevel@tonic-gate tprintf("TRACE- dobreak()\n"); 463*7c478bd9Sstevel@tonic-gate #endif 464*7c478bd9Sstevel@tonic-gate if (whyles) { 465*7c478bd9Sstevel@tonic-gate toend(); 466*7c478bd9Sstevel@tonic-gate } else { 467*7c478bd9Sstevel@tonic-gate bferr("Not in while/foreach"); 468*7c478bd9Sstevel@tonic-gate } 469*7c478bd9Sstevel@tonic-gate } 470*7c478bd9Sstevel@tonic-gate 471*7c478bd9Sstevel@tonic-gate void 472*7c478bd9Sstevel@tonic-gate doexit(tchar **v) 473*7c478bd9Sstevel@tonic-gate { 474*7c478bd9Sstevel@tonic-gate 475*7c478bd9Sstevel@tonic-gate #ifdef TRACE 476*7c478bd9Sstevel@tonic-gate tprintf("TRACE- doexit()\n"); 477*7c478bd9Sstevel@tonic-gate #endif 478*7c478bd9Sstevel@tonic-gate if (chkstop == 0) { 479*7c478bd9Sstevel@tonic-gate panystop(0); 480*7c478bd9Sstevel@tonic-gate } 481*7c478bd9Sstevel@tonic-gate /* 482*7c478bd9Sstevel@tonic-gate * Don't DEMAND parentheses here either. 483*7c478bd9Sstevel@tonic-gate */ 484*7c478bd9Sstevel@tonic-gate v++; 485*7c478bd9Sstevel@tonic-gate if (*v) { 486*7c478bd9Sstevel@tonic-gate set(S_status, putn(exp(&v))); 487*7c478bd9Sstevel@tonic-gate if (*v) { 488*7c478bd9Sstevel@tonic-gate bferr("Expression syntax"); 489*7c478bd9Sstevel@tonic-gate } 490*7c478bd9Sstevel@tonic-gate } 491*7c478bd9Sstevel@tonic-gate btoeof(); 492*7c478bd9Sstevel@tonic-gate if (intty) { 493*7c478bd9Sstevel@tonic-gate (void) close(SHIN); 494*7c478bd9Sstevel@tonic-gate unsetfd(SHIN); 495*7c478bd9Sstevel@tonic-gate } 496*7c478bd9Sstevel@tonic-gate } 497*7c478bd9Sstevel@tonic-gate 498*7c478bd9Sstevel@tonic-gate void 499*7c478bd9Sstevel@tonic-gate doforeach(tchar **v) 500*7c478bd9Sstevel@tonic-gate { 501*7c478bd9Sstevel@tonic-gate tchar *cp; 502*7c478bd9Sstevel@tonic-gate struct whyle *nwp; 503*7c478bd9Sstevel@tonic-gate 504*7c478bd9Sstevel@tonic-gate #ifdef TRACE 505*7c478bd9Sstevel@tonic-gate tprintf("TRACE- doforeach()\n"); 506*7c478bd9Sstevel@tonic-gate #endif 507*7c478bd9Sstevel@tonic-gate v++; 508*7c478bd9Sstevel@tonic-gate cp = strip(*v); 509*7c478bd9Sstevel@tonic-gate while (*cp && alnum(*cp)) { 510*7c478bd9Sstevel@tonic-gate cp++; 511*7c478bd9Sstevel@tonic-gate } 512*7c478bd9Sstevel@tonic-gate if (*cp || strlen_(*v) >= 20 || !letter(**v)) { 513*7c478bd9Sstevel@tonic-gate bferr("Invalid variable"); 514*7c478bd9Sstevel@tonic-gate } 515*7c478bd9Sstevel@tonic-gate cp = *v++; 516*7c478bd9Sstevel@tonic-gate if (v[0][0] != '(' || v[blklen(v) - 1][0] != ')') { 517*7c478bd9Sstevel@tonic-gate bferr("Words not ()'ed"); 518*7c478bd9Sstevel@tonic-gate } 519*7c478bd9Sstevel@tonic-gate v++; 520*7c478bd9Sstevel@tonic-gate gflag = 0, tglob(v); 521*7c478bd9Sstevel@tonic-gate v = glob(v); 522*7c478bd9Sstevel@tonic-gate if (v == 0) { 523*7c478bd9Sstevel@tonic-gate bferr("No match"); 524*7c478bd9Sstevel@tonic-gate } 525*7c478bd9Sstevel@tonic-gate nwp = (struct whyle *)calloc(1, sizeof (*nwp)); 526*7c478bd9Sstevel@tonic-gate nwp->w_fe = nwp->w_fe0 = v; gargv = 0; 527*7c478bd9Sstevel@tonic-gate nwp->w_start = btell(); 528*7c478bd9Sstevel@tonic-gate nwp->w_fename = savestr(cp); 529*7c478bd9Sstevel@tonic-gate nwp->w_next = whyles; 530*7c478bd9Sstevel@tonic-gate whyles = nwp; 531*7c478bd9Sstevel@tonic-gate /* 532*7c478bd9Sstevel@tonic-gate * Pre-read the loop so as to be more 533*7c478bd9Sstevel@tonic-gate * comprehensible to a terminal user. 534*7c478bd9Sstevel@tonic-gate */ 535*7c478bd9Sstevel@tonic-gate if (intty) { 536*7c478bd9Sstevel@tonic-gate preread_(); 537*7c478bd9Sstevel@tonic-gate } 538*7c478bd9Sstevel@tonic-gate doagain(); 539*7c478bd9Sstevel@tonic-gate } 540*7c478bd9Sstevel@tonic-gate 541*7c478bd9Sstevel@tonic-gate void 542*7c478bd9Sstevel@tonic-gate dowhile(tchar **v) 543*7c478bd9Sstevel@tonic-gate { 544*7c478bd9Sstevel@tonic-gate int status; 545*7c478bd9Sstevel@tonic-gate bool again = whyles != 0 && whyles->w_start == lineloc && 546*7c478bd9Sstevel@tonic-gate whyles->w_fename == 0; 547*7c478bd9Sstevel@tonic-gate 548*7c478bd9Sstevel@tonic-gate #ifdef TRACE 549*7c478bd9Sstevel@tonic-gate tprintf("TRACE- dowhile()\n"); 550*7c478bd9Sstevel@tonic-gate #endif 551*7c478bd9Sstevel@tonic-gate v++; 552*7c478bd9Sstevel@tonic-gate /* 553*7c478bd9Sstevel@tonic-gate * Implement prereading here also, taking care not to 554*7c478bd9Sstevel@tonic-gate * evaluate the expression before the loop has been read up 555*7c478bd9Sstevel@tonic-gate * from a terminal. 556*7c478bd9Sstevel@tonic-gate */ 557*7c478bd9Sstevel@tonic-gate if (intty && !again) { 558*7c478bd9Sstevel@tonic-gate status = !exp0(&v, 1); 559*7c478bd9Sstevel@tonic-gate } else { 560*7c478bd9Sstevel@tonic-gate status = !exp(&v); 561*7c478bd9Sstevel@tonic-gate } 562*7c478bd9Sstevel@tonic-gate if (*v) { 563*7c478bd9Sstevel@tonic-gate bferr("Expression syntax"); 564*7c478bd9Sstevel@tonic-gate } 565*7c478bd9Sstevel@tonic-gate if (!again) { 566*7c478bd9Sstevel@tonic-gate struct whyle *nwp = (struct whyle *)calloc(1, sizeof (*nwp)); 567*7c478bd9Sstevel@tonic-gate 568*7c478bd9Sstevel@tonic-gate nwp->w_start = lineloc; 569*7c478bd9Sstevel@tonic-gate nwp->w_end = 0; 570*7c478bd9Sstevel@tonic-gate nwp->w_next = whyles; 571*7c478bd9Sstevel@tonic-gate whyles = nwp; 572*7c478bd9Sstevel@tonic-gate if (intty) { 573*7c478bd9Sstevel@tonic-gate /* 574*7c478bd9Sstevel@tonic-gate * The tty preread 575*7c478bd9Sstevel@tonic-gate */ 576*7c478bd9Sstevel@tonic-gate preread_(); 577*7c478bd9Sstevel@tonic-gate doagain(); 578*7c478bd9Sstevel@tonic-gate return; 579*7c478bd9Sstevel@tonic-gate } 580*7c478bd9Sstevel@tonic-gate } 581*7c478bd9Sstevel@tonic-gate if (status) { 582*7c478bd9Sstevel@tonic-gate /* We ain't gonna loop no more, no more! */ 583*7c478bd9Sstevel@tonic-gate toend(); 584*7c478bd9Sstevel@tonic-gate } 585*7c478bd9Sstevel@tonic-gate } 586*7c478bd9Sstevel@tonic-gate 587*7c478bd9Sstevel@tonic-gate void 588*7c478bd9Sstevel@tonic-gate preread_() 589*7c478bd9Sstevel@tonic-gate { 590*7c478bd9Sstevel@tonic-gate #ifdef TRACE 591*7c478bd9Sstevel@tonic-gate tprintf("TRACE- preread()\n"); 592*7c478bd9Sstevel@tonic-gate #endif 593*7c478bd9Sstevel@tonic-gate 594*7c478bd9Sstevel@tonic-gate whyles->w_end = -1; 595*7c478bd9Sstevel@tonic-gate if (setintr) { 596*7c478bd9Sstevel@tonic-gate (void) sigsetmask(sigblock(0) & ~sigmask(SIGINT)); 597*7c478bd9Sstevel@tonic-gate } 598*7c478bd9Sstevel@tonic-gate search(ZBREAK, 0); 599*7c478bd9Sstevel@tonic-gate if (setintr) { 600*7c478bd9Sstevel@tonic-gate (void) sigblock(sigmask(SIGINT)); 601*7c478bd9Sstevel@tonic-gate } 602*7c478bd9Sstevel@tonic-gate whyles->w_end = btell(); 603*7c478bd9Sstevel@tonic-gate } 604*7c478bd9Sstevel@tonic-gate 605*7c478bd9Sstevel@tonic-gate void 606*7c478bd9Sstevel@tonic-gate doend() 607*7c478bd9Sstevel@tonic-gate { 608*7c478bd9Sstevel@tonic-gate 609*7c478bd9Sstevel@tonic-gate #ifdef TRACE 610*7c478bd9Sstevel@tonic-gate tprintf("TRACE- doend()\n"); 611*7c478bd9Sstevel@tonic-gate #endif 612*7c478bd9Sstevel@tonic-gate if (!whyles) { 613*7c478bd9Sstevel@tonic-gate bferr("Not in while/foreach"); 614*7c478bd9Sstevel@tonic-gate } 615*7c478bd9Sstevel@tonic-gate whyles->w_end = btell(); 616*7c478bd9Sstevel@tonic-gate doagain(); 617*7c478bd9Sstevel@tonic-gate } 618*7c478bd9Sstevel@tonic-gate 619*7c478bd9Sstevel@tonic-gate void 620*7c478bd9Sstevel@tonic-gate docontin() 621*7c478bd9Sstevel@tonic-gate { 622*7c478bd9Sstevel@tonic-gate #ifdef TRACE 623*7c478bd9Sstevel@tonic-gate tprintf("TRACE- docontin()\n"); 624*7c478bd9Sstevel@tonic-gate #endif 625*7c478bd9Sstevel@tonic-gate 626*7c478bd9Sstevel@tonic-gate if (!whyles) { 627*7c478bd9Sstevel@tonic-gate bferr("Not in while/foreach"); 628*7c478bd9Sstevel@tonic-gate } 629*7c478bd9Sstevel@tonic-gate doagain(); 630*7c478bd9Sstevel@tonic-gate } 631*7c478bd9Sstevel@tonic-gate 632*7c478bd9Sstevel@tonic-gate void 633*7c478bd9Sstevel@tonic-gate doagain() 634*7c478bd9Sstevel@tonic-gate { 635*7c478bd9Sstevel@tonic-gate 636*7c478bd9Sstevel@tonic-gate #ifdef TRACE 637*7c478bd9Sstevel@tonic-gate tprintf("TRACE- doagain()\n"); 638*7c478bd9Sstevel@tonic-gate #endif 639*7c478bd9Sstevel@tonic-gate /* Repeating a while is simple */ 640*7c478bd9Sstevel@tonic-gate if (whyles->w_fename == 0) { 641*7c478bd9Sstevel@tonic-gate bseek(whyles->w_start); 642*7c478bd9Sstevel@tonic-gate return; 643*7c478bd9Sstevel@tonic-gate } 644*7c478bd9Sstevel@tonic-gate /* 645*7c478bd9Sstevel@tonic-gate * The foreach variable list actually has a spurious word 646*7c478bd9Sstevel@tonic-gate * ")" at the end of the w_fe list. Thus we are at the 647*7c478bd9Sstevel@tonic-gate * of the list if one word beyond this is 0. 648*7c478bd9Sstevel@tonic-gate */ 649*7c478bd9Sstevel@tonic-gate if (!whyles->w_fe[1]) { 650*7c478bd9Sstevel@tonic-gate dobreak(); 651*7c478bd9Sstevel@tonic-gate return; 652*7c478bd9Sstevel@tonic-gate } 653*7c478bd9Sstevel@tonic-gate set(whyles->w_fename, savestr(*whyles->w_fe++)); 654*7c478bd9Sstevel@tonic-gate bseek(whyles->w_start); 655*7c478bd9Sstevel@tonic-gate } 656*7c478bd9Sstevel@tonic-gate 657*7c478bd9Sstevel@tonic-gate void 658*7c478bd9Sstevel@tonic-gate dorepeat(tchar **v, struct command *kp) 659*7c478bd9Sstevel@tonic-gate { 660*7c478bd9Sstevel@tonic-gate int i, omask; 661*7c478bd9Sstevel@tonic-gate 662*7c478bd9Sstevel@tonic-gate #ifdef TRACE 663*7c478bd9Sstevel@tonic-gate tprintf("TRACE- dorepeat()\n"); 664*7c478bd9Sstevel@tonic-gate #endif 665*7c478bd9Sstevel@tonic-gate i = getn(v[1]); 666*7c478bd9Sstevel@tonic-gate if (setintr) { 667*7c478bd9Sstevel@tonic-gate omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT); 668*7c478bd9Sstevel@tonic-gate } 669*7c478bd9Sstevel@tonic-gate lshift(v, 2); 670*7c478bd9Sstevel@tonic-gate while (i > 0) { 671*7c478bd9Sstevel@tonic-gate if (setintr) { 672*7c478bd9Sstevel@tonic-gate (void) sigsetmask(omask); 673*7c478bd9Sstevel@tonic-gate } 674*7c478bd9Sstevel@tonic-gate reexecute(kp); 675*7c478bd9Sstevel@tonic-gate --i; 676*7c478bd9Sstevel@tonic-gate } 677*7c478bd9Sstevel@tonic-gate donefds(); 678*7c478bd9Sstevel@tonic-gate if (setintr) { 679*7c478bd9Sstevel@tonic-gate (void) sigsetmask(omask); 680*7c478bd9Sstevel@tonic-gate } 681*7c478bd9Sstevel@tonic-gate } 682*7c478bd9Sstevel@tonic-gate 683*7c478bd9Sstevel@tonic-gate void 684*7c478bd9Sstevel@tonic-gate doswbrk() 685*7c478bd9Sstevel@tonic-gate { 686*7c478bd9Sstevel@tonic-gate 687*7c478bd9Sstevel@tonic-gate #ifdef TRACE 688*7c478bd9Sstevel@tonic-gate tprintf("TRACE- doswbrk()\n"); 689*7c478bd9Sstevel@tonic-gate #endif 690*7c478bd9Sstevel@tonic-gate search(ZBRKSW, 0); 691*7c478bd9Sstevel@tonic-gate } 692*7c478bd9Sstevel@tonic-gate 693*7c478bd9Sstevel@tonic-gate int 694*7c478bd9Sstevel@tonic-gate srchx(tchar *cp) 695*7c478bd9Sstevel@tonic-gate { 696*7c478bd9Sstevel@tonic-gate struct srch *sp, *sp1, *sp2; 697*7c478bd9Sstevel@tonic-gate int i; 698*7c478bd9Sstevel@tonic-gate 699*7c478bd9Sstevel@tonic-gate #ifdef TRACE 700*7c478bd9Sstevel@tonic-gate tprintf("TRACE- srchx()\n"); 701*7c478bd9Sstevel@tonic-gate #endif 702*7c478bd9Sstevel@tonic-gate /* 703*7c478bd9Sstevel@tonic-gate * Binary search 704*7c478bd9Sstevel@tonic-gate * Sp1 is the beginning of the current search range. 705*7c478bd9Sstevel@tonic-gate * Sp2 is one past the end. 706*7c478bd9Sstevel@tonic-gate */ 707*7c478bd9Sstevel@tonic-gate for (sp1 = srchn, sp2 = srchn + nsrchn; sp1 < sp2; ) { 708*7c478bd9Sstevel@tonic-gate sp = sp1 + (sp2 - sp1 >> 1); 709*7c478bd9Sstevel@tonic-gate if ((i = *cp - *sp->s_name) == 0 && 710*7c478bd9Sstevel@tonic-gate (i = strcmp_(cp, sp->s_name)) == 0) { 711*7c478bd9Sstevel@tonic-gate return (sp->s_value); 712*7c478bd9Sstevel@tonic-gate } 713*7c478bd9Sstevel@tonic-gate if (i < 0) { 714*7c478bd9Sstevel@tonic-gate sp2 = sp; 715*7c478bd9Sstevel@tonic-gate } else { 716*7c478bd9Sstevel@tonic-gate sp1 = sp + 1; 717*7c478bd9Sstevel@tonic-gate } 718*7c478bd9Sstevel@tonic-gate } 719*7c478bd9Sstevel@tonic-gate return (-1); 720*7c478bd9Sstevel@tonic-gate } 721*7c478bd9Sstevel@tonic-gate 722*7c478bd9Sstevel@tonic-gate tchar Stype; 723*7c478bd9Sstevel@tonic-gate tchar *Sgoal; 724*7c478bd9Sstevel@tonic-gate 725*7c478bd9Sstevel@tonic-gate /*VARARGS2*/ 726*7c478bd9Sstevel@tonic-gate void 727*7c478bd9Sstevel@tonic-gate search(type, level, goal) 728*7c478bd9Sstevel@tonic-gate int type; int level; tchar *goal; 729*7c478bd9Sstevel@tonic-gate { 730*7c478bd9Sstevel@tonic-gate tchar wordbuf[BUFSIZ]; 731*7c478bd9Sstevel@tonic-gate tchar *aword = wordbuf; 732*7c478bd9Sstevel@tonic-gate tchar *cp; 733*7c478bd9Sstevel@tonic-gate 734*7c478bd9Sstevel@tonic-gate #ifdef TRACE 735*7c478bd9Sstevel@tonic-gate tprintf("TRACE- search()\n"); 736*7c478bd9Sstevel@tonic-gate #endif 737*7c478bd9Sstevel@tonic-gate Stype = type; Sgoal = goal; 738*7c478bd9Sstevel@tonic-gate if (type == ZGOTO) { 739*7c478bd9Sstevel@tonic-gate bseek((off_t)0); 740*7c478bd9Sstevel@tonic-gate } 741*7c478bd9Sstevel@tonic-gate do { 742*7c478bd9Sstevel@tonic-gate if (intty && fseekp == feobp) { 743*7c478bd9Sstevel@tonic-gate printf("? "), flush(); 744*7c478bd9Sstevel@tonic-gate } 745*7c478bd9Sstevel@tonic-gate aword[0] = 0; 746*7c478bd9Sstevel@tonic-gate (void) getword(aword); 747*7c478bd9Sstevel@tonic-gate 748*7c478bd9Sstevel@tonic-gate switch (srchx(aword)) { 749*7c478bd9Sstevel@tonic-gate 750*7c478bd9Sstevel@tonic-gate case ZELSE: 751*7c478bd9Sstevel@tonic-gate if (level == 0 && type == ZIF) { 752*7c478bd9Sstevel@tonic-gate return; 753*7c478bd9Sstevel@tonic-gate } 754*7c478bd9Sstevel@tonic-gate break; 755*7c478bd9Sstevel@tonic-gate 756*7c478bd9Sstevel@tonic-gate case ZIF: 757*7c478bd9Sstevel@tonic-gate while (getword(aword)) { 758*7c478bd9Sstevel@tonic-gate continue; 759*7c478bd9Sstevel@tonic-gate } 760*7c478bd9Sstevel@tonic-gate if ((type == ZIF || type == ZELSE) && 761*7c478bd9Sstevel@tonic-gate eq(aword, S_then)) { 762*7c478bd9Sstevel@tonic-gate level++; 763*7c478bd9Sstevel@tonic-gate } 764*7c478bd9Sstevel@tonic-gate break; 765*7c478bd9Sstevel@tonic-gate 766*7c478bd9Sstevel@tonic-gate case ZENDIF: 767*7c478bd9Sstevel@tonic-gate if (type == ZIF || type == ZELSE) { 768*7c478bd9Sstevel@tonic-gate level--; 769*7c478bd9Sstevel@tonic-gate } 770*7c478bd9Sstevel@tonic-gate break; 771*7c478bd9Sstevel@tonic-gate 772*7c478bd9Sstevel@tonic-gate case ZFOREACH: 773*7c478bd9Sstevel@tonic-gate case ZWHILE: 774*7c478bd9Sstevel@tonic-gate if (type == ZBREAK) { 775*7c478bd9Sstevel@tonic-gate level++; 776*7c478bd9Sstevel@tonic-gate } 777*7c478bd9Sstevel@tonic-gate break; 778*7c478bd9Sstevel@tonic-gate 779*7c478bd9Sstevel@tonic-gate case ZEND: 780*7c478bd9Sstevel@tonic-gate if (type == ZBREAK) { 781*7c478bd9Sstevel@tonic-gate level--; 782*7c478bd9Sstevel@tonic-gate } 783*7c478bd9Sstevel@tonic-gate break; 784*7c478bd9Sstevel@tonic-gate 785*7c478bd9Sstevel@tonic-gate case ZSWITCH: 786*7c478bd9Sstevel@tonic-gate if (type == ZSWITCH || type == ZBRKSW) { 787*7c478bd9Sstevel@tonic-gate level++; 788*7c478bd9Sstevel@tonic-gate } 789*7c478bd9Sstevel@tonic-gate break; 790*7c478bd9Sstevel@tonic-gate 791*7c478bd9Sstevel@tonic-gate case ZENDSW: 792*7c478bd9Sstevel@tonic-gate if (type == ZSWITCH || type == ZBRKSW) { 793*7c478bd9Sstevel@tonic-gate level--; 794*7c478bd9Sstevel@tonic-gate } 795*7c478bd9Sstevel@tonic-gate break; 796*7c478bd9Sstevel@tonic-gate 797*7c478bd9Sstevel@tonic-gate case ZLABEL: 798*7c478bd9Sstevel@tonic-gate if (type == ZGOTO && getword(aword) && 799*7c478bd9Sstevel@tonic-gate eq(aword, goal)) { 800*7c478bd9Sstevel@tonic-gate level = -1; 801*7c478bd9Sstevel@tonic-gate } 802*7c478bd9Sstevel@tonic-gate break; 803*7c478bd9Sstevel@tonic-gate 804*7c478bd9Sstevel@tonic-gate default: 805*7c478bd9Sstevel@tonic-gate if (type != ZGOTO && (type != ZSWITCH || level != 0)) { 806*7c478bd9Sstevel@tonic-gate break; 807*7c478bd9Sstevel@tonic-gate } 808*7c478bd9Sstevel@tonic-gate if (lastchr(aword) != ':') { 809*7c478bd9Sstevel@tonic-gate break; 810*7c478bd9Sstevel@tonic-gate } 811*7c478bd9Sstevel@tonic-gate aword[strlen_(aword) - 1] = 0; 812*7c478bd9Sstevel@tonic-gate if (type == ZGOTO && eq(aword, goal) || 813*7c478bd9Sstevel@tonic-gate type == ZSWITCH && eq(aword, S_default)) { 814*7c478bd9Sstevel@tonic-gate level = -1; 815*7c478bd9Sstevel@tonic-gate } 816*7c478bd9Sstevel@tonic-gate break; 817*7c478bd9Sstevel@tonic-gate 818*7c478bd9Sstevel@tonic-gate case ZCASE: 819*7c478bd9Sstevel@tonic-gate if (type != ZSWITCH || level != 0) { 820*7c478bd9Sstevel@tonic-gate break; 821*7c478bd9Sstevel@tonic-gate } 822*7c478bd9Sstevel@tonic-gate (void) getword(aword); 823*7c478bd9Sstevel@tonic-gate if (lastchr(aword) == ':') { 824*7c478bd9Sstevel@tonic-gate aword[strlen_(aword) - 1] = 0; 825*7c478bd9Sstevel@tonic-gate } 826*7c478bd9Sstevel@tonic-gate cp = strip(Dfix1(aword)); 827*7c478bd9Sstevel@tonic-gate if (Gmatch(goal, cp)) { 828*7c478bd9Sstevel@tonic-gate level = -1; 829*7c478bd9Sstevel@tonic-gate } 830*7c478bd9Sstevel@tonic-gate xfree(cp); 831*7c478bd9Sstevel@tonic-gate break; 832*7c478bd9Sstevel@tonic-gate 833*7c478bd9Sstevel@tonic-gate case ZDEFAULT: 834*7c478bd9Sstevel@tonic-gate if (type == ZSWITCH && level == 0) { 835*7c478bd9Sstevel@tonic-gate level = -1; 836*7c478bd9Sstevel@tonic-gate } 837*7c478bd9Sstevel@tonic-gate break; 838*7c478bd9Sstevel@tonic-gate } 839*7c478bd9Sstevel@tonic-gate (void) getword(NOSTR); 840*7c478bd9Sstevel@tonic-gate } while (level >= 0); 841*7c478bd9Sstevel@tonic-gate } 842*7c478bd9Sstevel@tonic-gate 843*7c478bd9Sstevel@tonic-gate int 844*7c478bd9Sstevel@tonic-gate getword(tchar *wp) 845*7c478bd9Sstevel@tonic-gate { 846*7c478bd9Sstevel@tonic-gate int found = 0; 847*7c478bd9Sstevel@tonic-gate int c, d; 848*7c478bd9Sstevel@tonic-gate #ifdef TRACE 849*7c478bd9Sstevel@tonic-gate tprintf("TRACE- getword()\n"); 850*7c478bd9Sstevel@tonic-gate #endif 851*7c478bd9Sstevel@tonic-gate 852*7c478bd9Sstevel@tonic-gate c = readc(1); 853*7c478bd9Sstevel@tonic-gate d = 0; 854*7c478bd9Sstevel@tonic-gate do { 855*7c478bd9Sstevel@tonic-gate while (issp(c)) { 856*7c478bd9Sstevel@tonic-gate c = readc(1); 857*7c478bd9Sstevel@tonic-gate } 858*7c478bd9Sstevel@tonic-gate if (c == '#') { 859*7c478bd9Sstevel@tonic-gate do { 860*7c478bd9Sstevel@tonic-gate c = readc(1); 861*7c478bd9Sstevel@tonic-gate } while (c >= 0 && c != '\n'); 862*7c478bd9Sstevel@tonic-gate } 863*7c478bd9Sstevel@tonic-gate if (c < 0) { 864*7c478bd9Sstevel@tonic-gate goto past; 865*7c478bd9Sstevel@tonic-gate } 866*7c478bd9Sstevel@tonic-gate if (c == '\n') { 867*7c478bd9Sstevel@tonic-gate if (wp) { 868*7c478bd9Sstevel@tonic-gate break; 869*7c478bd9Sstevel@tonic-gate } 870*7c478bd9Sstevel@tonic-gate return (0); 871*7c478bd9Sstevel@tonic-gate } 872*7c478bd9Sstevel@tonic-gate 873*7c478bd9Sstevel@tonic-gate /* ( and ) form separate words */ 874*7c478bd9Sstevel@tonic-gate if (c == '(' || c == ')') { 875*7c478bd9Sstevel@tonic-gate return (1); 876*7c478bd9Sstevel@tonic-gate } 877*7c478bd9Sstevel@tonic-gate 878*7c478bd9Sstevel@tonic-gate unreadc(c); 879*7c478bd9Sstevel@tonic-gate found = 1; 880*7c478bd9Sstevel@tonic-gate do { 881*7c478bd9Sstevel@tonic-gate c = readc(1); 882*7c478bd9Sstevel@tonic-gate if (c == '\\' && (c = readc(1)) == '\n') { 883*7c478bd9Sstevel@tonic-gate c = ' '; 884*7c478bd9Sstevel@tonic-gate } 885*7c478bd9Sstevel@tonic-gate if (c == '\'' || c == '"') { 886*7c478bd9Sstevel@tonic-gate if (d == 0) { 887*7c478bd9Sstevel@tonic-gate d = c; 888*7c478bd9Sstevel@tonic-gate } else if (d == c) { 889*7c478bd9Sstevel@tonic-gate d = 0; 890*7c478bd9Sstevel@tonic-gate } 891*7c478bd9Sstevel@tonic-gate } 892*7c478bd9Sstevel@tonic-gate if (c < 0) { 893*7c478bd9Sstevel@tonic-gate goto past; 894*7c478bd9Sstevel@tonic-gate } 895*7c478bd9Sstevel@tonic-gate if (wp) { 896*7c478bd9Sstevel@tonic-gate *wp++ = c; 897*7c478bd9Sstevel@tonic-gate } 898*7c478bd9Sstevel@tonic-gate } while ((d || !issp(c) && c != '(' && c != ')') && c != '\n'); 899*7c478bd9Sstevel@tonic-gate } while (wp == 0); 900*7c478bd9Sstevel@tonic-gate unreadc(c); 901*7c478bd9Sstevel@tonic-gate if (found) { 902*7c478bd9Sstevel@tonic-gate *--wp = 0; 903*7c478bd9Sstevel@tonic-gate } 904*7c478bd9Sstevel@tonic-gate return (found); 905*7c478bd9Sstevel@tonic-gate 906*7c478bd9Sstevel@tonic-gate past: 907*7c478bd9Sstevel@tonic-gate switch (Stype) { 908*7c478bd9Sstevel@tonic-gate 909*7c478bd9Sstevel@tonic-gate case ZIF: 910*7c478bd9Sstevel@tonic-gate bferr("then/endif not found"); 911*7c478bd9Sstevel@tonic-gate 912*7c478bd9Sstevel@tonic-gate case ZELSE: 913*7c478bd9Sstevel@tonic-gate bferr("endif not found"); 914*7c478bd9Sstevel@tonic-gate 915*7c478bd9Sstevel@tonic-gate case ZBRKSW: 916*7c478bd9Sstevel@tonic-gate case ZSWITCH: 917*7c478bd9Sstevel@tonic-gate bferr("endsw not found"); 918*7c478bd9Sstevel@tonic-gate 919*7c478bd9Sstevel@tonic-gate case ZBREAK: 920*7c478bd9Sstevel@tonic-gate bferr("end not found"); 921*7c478bd9Sstevel@tonic-gate 922*7c478bd9Sstevel@tonic-gate case ZGOTO: 923*7c478bd9Sstevel@tonic-gate setname(Sgoal); 924*7c478bd9Sstevel@tonic-gate bferr("label not found"); 925*7c478bd9Sstevel@tonic-gate } 926*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 927*7c478bd9Sstevel@tonic-gate } 928*7c478bd9Sstevel@tonic-gate 929*7c478bd9Sstevel@tonic-gate void 930*7c478bd9Sstevel@tonic-gate toend() 931*7c478bd9Sstevel@tonic-gate { 932*7c478bd9Sstevel@tonic-gate 933*7c478bd9Sstevel@tonic-gate #ifdef TRACE 934*7c478bd9Sstevel@tonic-gate tprintf("TRACE- toend()\n"); 935*7c478bd9Sstevel@tonic-gate #endif 936*7c478bd9Sstevel@tonic-gate if (whyles->w_end == 0) { 937*7c478bd9Sstevel@tonic-gate search(ZBREAK, 0); 938*7c478bd9Sstevel@tonic-gate whyles->w_end = btell() - 1; 939*7c478bd9Sstevel@tonic-gate } else { 940*7c478bd9Sstevel@tonic-gate bseek(whyles->w_end); 941*7c478bd9Sstevel@tonic-gate } 942*7c478bd9Sstevel@tonic-gate wfree(); 943*7c478bd9Sstevel@tonic-gate } 944*7c478bd9Sstevel@tonic-gate 945*7c478bd9Sstevel@tonic-gate void 946*7c478bd9Sstevel@tonic-gate wfree() 947*7c478bd9Sstevel@tonic-gate { 948*7c478bd9Sstevel@tonic-gate long o = btell(); 949*7c478bd9Sstevel@tonic-gate 950*7c478bd9Sstevel@tonic-gate #ifdef TRACE 951*7c478bd9Sstevel@tonic-gate tprintf("TRACE- wfree()\n"); 952*7c478bd9Sstevel@tonic-gate #endif 953*7c478bd9Sstevel@tonic-gate while (whyles) { 954*7c478bd9Sstevel@tonic-gate struct whyle *wp = whyles; 955*7c478bd9Sstevel@tonic-gate struct whyle *nwp = wp->w_next; 956*7c478bd9Sstevel@tonic-gate 957*7c478bd9Sstevel@tonic-gate if (o >= wp->w_start && (wp->w_end == 0 || o < wp->w_end)) { 958*7c478bd9Sstevel@tonic-gate break; 959*7c478bd9Sstevel@tonic-gate } 960*7c478bd9Sstevel@tonic-gate if (wp->w_fe0) { 961*7c478bd9Sstevel@tonic-gate blkfree(wp->w_fe0); 962*7c478bd9Sstevel@tonic-gate } 963*7c478bd9Sstevel@tonic-gate if (wp->w_fename) { 964*7c478bd9Sstevel@tonic-gate xfree(wp->w_fename); 965*7c478bd9Sstevel@tonic-gate } 966*7c478bd9Sstevel@tonic-gate xfree((char *)wp); 967*7c478bd9Sstevel@tonic-gate whyles = nwp; 968*7c478bd9Sstevel@tonic-gate } 969*7c478bd9Sstevel@tonic-gate } 970*7c478bd9Sstevel@tonic-gate 971*7c478bd9Sstevel@tonic-gate void 972*7c478bd9Sstevel@tonic-gate doecho(tchar **v) 973*7c478bd9Sstevel@tonic-gate { 974*7c478bd9Sstevel@tonic-gate 975*7c478bd9Sstevel@tonic-gate #ifdef TRACE 976*7c478bd9Sstevel@tonic-gate tprintf("TRACE- doecho()\n"); 977*7c478bd9Sstevel@tonic-gate #endif 978*7c478bd9Sstevel@tonic-gate echo(' ', v); 979*7c478bd9Sstevel@tonic-gate } 980*7c478bd9Sstevel@tonic-gate 981*7c478bd9Sstevel@tonic-gate void 982*7c478bd9Sstevel@tonic-gate doglob(tchar **v) 983*7c478bd9Sstevel@tonic-gate { 984*7c478bd9Sstevel@tonic-gate 985*7c478bd9Sstevel@tonic-gate #ifdef TRACE 986*7c478bd9Sstevel@tonic-gate tprintf("TRACE- doglob()\n"); 987*7c478bd9Sstevel@tonic-gate #endif 988*7c478bd9Sstevel@tonic-gate echo(0, v); 989*7c478bd9Sstevel@tonic-gate flush(); 990*7c478bd9Sstevel@tonic-gate } 991*7c478bd9Sstevel@tonic-gate 992*7c478bd9Sstevel@tonic-gate void 993*7c478bd9Sstevel@tonic-gate echo(tchar sep, tchar **v) 994*7c478bd9Sstevel@tonic-gate { 995*7c478bd9Sstevel@tonic-gate tchar *cp; 996*7c478bd9Sstevel@tonic-gate int nonl = 0; 997*7c478bd9Sstevel@tonic-gate 998*7c478bd9Sstevel@tonic-gate #ifdef TRACE 999*7c478bd9Sstevel@tonic-gate tprintf("TRACE- echo()\n"); 1000*7c478bd9Sstevel@tonic-gate #endif 1001*7c478bd9Sstevel@tonic-gate if (setintr) { 1002*7c478bd9Sstevel@tonic-gate (void) sigsetmask(sigblock(0) & ~sigmask(SIGINT)); 1003*7c478bd9Sstevel@tonic-gate } 1004*7c478bd9Sstevel@tonic-gate v++; 1005*7c478bd9Sstevel@tonic-gate if (*v == 0) { 1006*7c478bd9Sstevel@tonic-gate /* 1007*7c478bd9Sstevel@tonic-gate * echo command needs to have newline when there are no 1008*7c478bd9Sstevel@tonic-gate * flags or arguments. glob should have no newline. If 1009*7c478bd9Sstevel@tonic-gate * the separator is a blank, we are doing an echo. If the 1010*7c478bd9Sstevel@tonic-gate * separator is zero, we are globbing. 1011*7c478bd9Sstevel@tonic-gate */ 1012*7c478bd9Sstevel@tonic-gate if (sep == (tchar)' ') 1013*7c478bd9Sstevel@tonic-gate Putchar('\n'); 1014*7c478bd9Sstevel@tonic-gate return; 1015*7c478bd9Sstevel@tonic-gate } 1016*7c478bd9Sstevel@tonic-gate gflag = 0, tglob(v); 1017*7c478bd9Sstevel@tonic-gate if (gflag) { 1018*7c478bd9Sstevel@tonic-gate v = glob(v); 1019*7c478bd9Sstevel@tonic-gate if (v == 0) { 1020*7c478bd9Sstevel@tonic-gate bferr("No match"); 1021*7c478bd9Sstevel@tonic-gate } 1022*7c478bd9Sstevel@tonic-gate } 1023*7c478bd9Sstevel@tonic-gate /* check for -n arg, NOTE: it might be quoted */ 1024*7c478bd9Sstevel@tonic-gate if (sep == ' ' && *v && strlen_(*v) == 2 && 1025*7c478bd9Sstevel@tonic-gate ((**v&TRIM) == '-' && (*(*v + 1) & TRIM) == 'n' && 1026*7c478bd9Sstevel@tonic-gate (*(*v+2)&TRIM) == 0)) { 1027*7c478bd9Sstevel@tonic-gate nonl++, v++; 1028*7c478bd9Sstevel@tonic-gate } 1029*7c478bd9Sstevel@tonic-gate while (cp = *v++) { 1030*7c478bd9Sstevel@tonic-gate int c; 1031*7c478bd9Sstevel@tonic-gate 1032*7c478bd9Sstevel@tonic-gate while (c = *cp++) { 1033*7c478bd9Sstevel@tonic-gate Putchar(c | QUOTE); 1034*7c478bd9Sstevel@tonic-gate } 1035*7c478bd9Sstevel@tonic-gate if (*v) { 1036*7c478bd9Sstevel@tonic-gate Putchar(sep | QUOTE); 1037*7c478bd9Sstevel@tonic-gate } 1038*7c478bd9Sstevel@tonic-gate } 1039*7c478bd9Sstevel@tonic-gate if (sep && nonl == 0) { 1040*7c478bd9Sstevel@tonic-gate Putchar('\n'); 1041*7c478bd9Sstevel@tonic-gate } else { 1042*7c478bd9Sstevel@tonic-gate flush(); 1043*7c478bd9Sstevel@tonic-gate } 1044*7c478bd9Sstevel@tonic-gate if (setintr) { 1045*7c478bd9Sstevel@tonic-gate (void) sigblock(sigmask(SIGINT)); 1046*7c478bd9Sstevel@tonic-gate } 1047*7c478bd9Sstevel@tonic-gate if (gargv) { 1048*7c478bd9Sstevel@tonic-gate blkfree(gargv), gargv = 0; 1049*7c478bd9Sstevel@tonic-gate } 1050*7c478bd9Sstevel@tonic-gate } 1051*7c478bd9Sstevel@tonic-gate 1052*7c478bd9Sstevel@tonic-gate extern char **environ; 1053*7c478bd9Sstevel@tonic-gate 1054*7c478bd9Sstevel@tonic-gate /* 1055*7c478bd9Sstevel@tonic-gate * Check if the environment variable vp affects this csh's behavior 1056*7c478bd9Sstevel@tonic-gate * and therefore we should call setlocale() or not. 1057*7c478bd9Sstevel@tonic-gate * This function has two side effects when it returns 1: 1058*7c478bd9Sstevel@tonic-gate * variable islocalevar_catnum is set to the LC_xxx value. 1059*7c478bd9Sstevel@tonic-gate * variable islocalevar_catname is set to the string "LC_xxx" 1060*7c478bd9Sstevel@tonic-gate */ 1061*7c478bd9Sstevel@tonic-gate static int islocalevar_catnum; 1062*7c478bd9Sstevel@tonic-gate static char *islocalevar_catname; 1063*7c478bd9Sstevel@tonic-gate 1064*7c478bd9Sstevel@tonic-gate static 1065*7c478bd9Sstevel@tonic-gate bool 1066*7c478bd9Sstevel@tonic-gate islocalevar(tchar *vp) 1067*7c478bd9Sstevel@tonic-gate { 1068*7c478bd9Sstevel@tonic-gate static struct lcinfo { 1069*7c478bd9Sstevel@tonic-gate tchar * evname; /* The name of the env. var. */ 1070*7c478bd9Sstevel@tonic-gate } categories_we_care[] = { 1071*7c478bd9Sstevel@tonic-gate S_LANG, S_LC_ALL, S_LC_CTYPE, S_LC_MESSAGES, 1072*7c478bd9Sstevel@tonic-gate NOSTR /* assumption: LC_xxx >= 0 */ 1073*7c478bd9Sstevel@tonic-gate }; 1074*7c478bd9Sstevel@tonic-gate struct lcinfo *p = categories_we_care; 1075*7c478bd9Sstevel@tonic-gate 1076*7c478bd9Sstevel@tonic-gate do { 1077*7c478bd9Sstevel@tonic-gate if (strcmp_(vp, p->evname) == 0) { 1078*7c478bd9Sstevel@tonic-gate return (1); 1079*7c478bd9Sstevel@tonic-gate } 1080*7c478bd9Sstevel@tonic-gate } while (((++p)->evname) != NOSTR); 1081*7c478bd9Sstevel@tonic-gate return (0); 1082*7c478bd9Sstevel@tonic-gate } 1083*7c478bd9Sstevel@tonic-gate 1084*7c478bd9Sstevel@tonic-gate void 1085*7c478bd9Sstevel@tonic-gate dosetenv(tchar **v) 1086*7c478bd9Sstevel@tonic-gate { 1087*7c478bd9Sstevel@tonic-gate tchar *vp, *lp; 1088*7c478bd9Sstevel@tonic-gate 1089*7c478bd9Sstevel@tonic-gate #ifdef TRACE 1090*7c478bd9Sstevel@tonic-gate tprintf("TRACE- dosetenv()\n"); 1091*7c478bd9Sstevel@tonic-gate #endif 1092*7c478bd9Sstevel@tonic-gate v++; 1093*7c478bd9Sstevel@tonic-gate if ((vp = *v++) == 0) { 1094*7c478bd9Sstevel@tonic-gate char **ep; 1095*7c478bd9Sstevel@tonic-gate 1096*7c478bd9Sstevel@tonic-gate if (setintr) { 1097*7c478bd9Sstevel@tonic-gate (void) sigsetmask(sigblock(0) & ~ sigmask(SIGINT)); 1098*7c478bd9Sstevel@tonic-gate } 1099*7c478bd9Sstevel@tonic-gate for (ep = environ; *ep; ep++) { 1100*7c478bd9Sstevel@tonic-gate printf("%s\n", *ep); 1101*7c478bd9Sstevel@tonic-gate } 1102*7c478bd9Sstevel@tonic-gate return; 1103*7c478bd9Sstevel@tonic-gate } 1104*7c478bd9Sstevel@tonic-gate 1105*7c478bd9Sstevel@tonic-gate if ((lp = *v++) == 0) { 1106*7c478bd9Sstevel@tonic-gate lp = S_; /* "" */ 1107*7c478bd9Sstevel@tonic-gate } 1108*7c478bd9Sstevel@tonic-gate local_setenv(vp, lp = globone(lp)); 1109*7c478bd9Sstevel@tonic-gate if (eq(vp, S_PATH)) { 1110*7c478bd9Sstevel@tonic-gate importpath(lp); 1111*7c478bd9Sstevel@tonic-gate dohash(xhash); 1112*7c478bd9Sstevel@tonic-gate } else if (islocalevar(vp)) { 1113*7c478bd9Sstevel@tonic-gate if (!setlocale(LC_ALL, "")) { 1114*7c478bd9Sstevel@tonic-gate error("Locale could not be set properly"); 1115*7c478bd9Sstevel@tonic-gate } 1116*7c478bd9Sstevel@tonic-gate } 1117*7c478bd9Sstevel@tonic-gate 1118*7c478bd9Sstevel@tonic-gate xfree(lp); 1119*7c478bd9Sstevel@tonic-gate } 1120*7c478bd9Sstevel@tonic-gate 1121*7c478bd9Sstevel@tonic-gate void 1122*7c478bd9Sstevel@tonic-gate dounsetenv(tchar **v) 1123*7c478bd9Sstevel@tonic-gate { 1124*7c478bd9Sstevel@tonic-gate #ifdef TRACE 1125*7c478bd9Sstevel@tonic-gate tprintf("TRACE- dounsetenv()\n"); 1126*7c478bd9Sstevel@tonic-gate #endif 1127*7c478bd9Sstevel@tonic-gate v++; 1128*7c478bd9Sstevel@tonic-gate do { 1129*7c478bd9Sstevel@tonic-gate local_unsetenv(*v); 1130*7c478bd9Sstevel@tonic-gate if (islocalevar(*v++)) { 1131*7c478bd9Sstevel@tonic-gate setlocale(LC_ALL, ""); /* Hope no error! */ 1132*7c478bd9Sstevel@tonic-gate } 1133*7c478bd9Sstevel@tonic-gate } while (*v); 1134*7c478bd9Sstevel@tonic-gate } 1135*7c478bd9Sstevel@tonic-gate 1136*7c478bd9Sstevel@tonic-gate void 1137*7c478bd9Sstevel@tonic-gate local_setenv(tchar *name, tchar *val) 1138*7c478bd9Sstevel@tonic-gate { 1139*7c478bd9Sstevel@tonic-gate char **ep = environ; 1140*7c478bd9Sstevel@tonic-gate tchar *cp; 1141*7c478bd9Sstevel@tonic-gate char *dp; 1142*7c478bd9Sstevel@tonic-gate tchar *ep_; /* temporary */ 1143*7c478bd9Sstevel@tonic-gate char *blk[2], **oep = ep; 1144*7c478bd9Sstevel@tonic-gate 1145*7c478bd9Sstevel@tonic-gate #ifdef TRACE 1146*7c478bd9Sstevel@tonic-gate /* tprintf("TRACE- local_setenv(%t, %t)\n", name, val); */ 1147*7c478bd9Sstevel@tonic-gate /* printf("IN local_setenv args = (%t)\n", val); */ 1148*7c478bd9Sstevel@tonic-gate #endif 1149*7c478bd9Sstevel@tonic-gate for (; *ep; ep++) { 1150*7c478bd9Sstevel@tonic-gate #ifdef MBCHAR 1151*7c478bd9Sstevel@tonic-gate for (cp = name, dp = *ep; *cp && *dp; cp++) { 1152*7c478bd9Sstevel@tonic-gate /* 1153*7c478bd9Sstevel@tonic-gate * This loop compares two chars in different 1154*7c478bd9Sstevel@tonic-gate * representations, EUC (as char *) and wchar_t 1155*7c478bd9Sstevel@tonic-gate * (in tchar), and ends when they are different. 1156*7c478bd9Sstevel@tonic-gate */ 1157*7c478bd9Sstevel@tonic-gate wchar_t dwc; 1158*7c478bd9Sstevel@tonic-gate int n; 1159*7c478bd9Sstevel@tonic-gate 1160*7c478bd9Sstevel@tonic-gate n = mbtowc(&dwc, dp, MB_CUR_MAX); 1161*7c478bd9Sstevel@tonic-gate if (n <= 0) { 1162*7c478bd9Sstevel@tonic-gate break; /* Illegal multibyte. */ 1163*7c478bd9Sstevel@tonic-gate } 1164*7c478bd9Sstevel@tonic-gate dp += n; /* Advance to next multibyte char. */ 1165*7c478bd9Sstevel@tonic-gate if (dwc == (wchar_t)(*cp & TRIM)) { 1166*7c478bd9Sstevel@tonic-gate continue; 1167*7c478bd9Sstevel@tonic-gate } else { 1168*7c478bd9Sstevel@tonic-gate break; 1169*7c478bd9Sstevel@tonic-gate } 1170*7c478bd9Sstevel@tonic-gate } 1171*7c478bd9Sstevel@tonic-gate #else /* !MBCHAR */ 1172*7c478bd9Sstevel@tonic-gate for (cp = name, dp = *ep; *cp && (char)*cp == *dp; cp++, dp++) { 1173*7c478bd9Sstevel@tonic-gate continue; 1174*7c478bd9Sstevel@tonic-gate } 1175*7c478bd9Sstevel@tonic-gate #endif /* !MBCHAR */ 1176*7c478bd9Sstevel@tonic-gate if (*cp != 0 || *dp != '=') { 1177*7c478bd9Sstevel@tonic-gate continue; 1178*7c478bd9Sstevel@tonic-gate } 1179*7c478bd9Sstevel@tonic-gate cp = strspl(S_EQ, val); 1180*7c478bd9Sstevel@tonic-gate xfree(*ep); 1181*7c478bd9Sstevel@tonic-gate ep_ = strspl(name, cp); /* ep_ is xalloc'ed */ 1182*7c478bd9Sstevel@tonic-gate xfree(cp); 1183*7c478bd9Sstevel@tonic-gate /* 1184*7c478bd9Sstevel@tonic-gate * Trimming is not needed here. 1185*7c478bd9Sstevel@tonic-gate * trim(); 1186*7c478bd9Sstevel@tonic-gate */ 1187*7c478bd9Sstevel@tonic-gate *ep = tstostr(NULL, ep_); 1188*7c478bd9Sstevel@tonic-gate xfree(ep_); /* because temp. use */ 1189*7c478bd9Sstevel@tonic-gate return; 1190*7c478bd9Sstevel@tonic-gate } 1191*7c478bd9Sstevel@tonic-gate ep_ = strspl(name, S_EQ); /* ep_ is xalloc'ed */ 1192*7c478bd9Sstevel@tonic-gate blk[0] = tstostr(NULL, ep_); 1193*7c478bd9Sstevel@tonic-gate blk[1] = 0; 1194*7c478bd9Sstevel@tonic-gate xfree(ep_); 1195*7c478bd9Sstevel@tonic-gate environ = (char **)blkspl_((unsigned char **)environ, blk); 1196*7c478bd9Sstevel@tonic-gate xfree((void *)oep); 1197*7c478bd9Sstevel@tonic-gate local_setenv(name, val); 1198*7c478bd9Sstevel@tonic-gate } 1199*7c478bd9Sstevel@tonic-gate 1200*7c478bd9Sstevel@tonic-gate void 1201*7c478bd9Sstevel@tonic-gate local_unsetenv(tchar *name) 1202*7c478bd9Sstevel@tonic-gate { 1203*7c478bd9Sstevel@tonic-gate char **ep = environ; 1204*7c478bd9Sstevel@tonic-gate tchar *cp; 1205*7c478bd9Sstevel@tonic-gate char *dp; 1206*7c478bd9Sstevel@tonic-gate char **oep = ep; 1207*7c478bd9Sstevel@tonic-gate char *cp_; /* tmp use */ 1208*7c478bd9Sstevel@tonic-gate static cnt = 0; /* delete counter */ 1209*7c478bd9Sstevel@tonic-gate 1210*7c478bd9Sstevel@tonic-gate #ifdef TRACE 1211*7c478bd9Sstevel@tonic-gate tprintf("TRACE- local_unsetenv()\n"); 1212*7c478bd9Sstevel@tonic-gate #endif 1213*7c478bd9Sstevel@tonic-gate for (; *ep; ep++) { 1214*7c478bd9Sstevel@tonic-gate #ifdef MBCHAR 1215*7c478bd9Sstevel@tonic-gate for (cp = name, dp = *ep; *cp && *dp; cp++) { 1216*7c478bd9Sstevel@tonic-gate /* 1217*7c478bd9Sstevel@tonic-gate * This loop compares two chars in different 1218*7c478bd9Sstevel@tonic-gate * representations, EUC (as char *) and wchar_t 1219*7c478bd9Sstevel@tonic-gate * (in tchar), and ends when they are different. 1220*7c478bd9Sstevel@tonic-gate */ 1221*7c478bd9Sstevel@tonic-gate wchar_t dwc; 1222*7c478bd9Sstevel@tonic-gate int n; 1223*7c478bd9Sstevel@tonic-gate 1224*7c478bd9Sstevel@tonic-gate n = mbtowc(&dwc, dp, MB_CUR_MAX); 1225*7c478bd9Sstevel@tonic-gate if (n <= 0) { 1226*7c478bd9Sstevel@tonic-gate break; /* Illegal multibyte. */ 1227*7c478bd9Sstevel@tonic-gate } 1228*7c478bd9Sstevel@tonic-gate dp += n; /* Advance to next multibyte char. */ 1229*7c478bd9Sstevel@tonic-gate if (dwc == (wchar_t)(*cp & TRIM)) { 1230*7c478bd9Sstevel@tonic-gate continue; 1231*7c478bd9Sstevel@tonic-gate } else { 1232*7c478bd9Sstevel@tonic-gate break; 1233*7c478bd9Sstevel@tonic-gate } 1234*7c478bd9Sstevel@tonic-gate } 1235*7c478bd9Sstevel@tonic-gate #else /* !MBCHAR */ 1236*7c478bd9Sstevel@tonic-gate for (cp = name, dp = *ep; *cp && (char)*cp == *dp; cp++, dp++) { 1237*7c478bd9Sstevel@tonic-gate continue; 1238*7c478bd9Sstevel@tonic-gate } 1239*7c478bd9Sstevel@tonic-gate #endif /* !MBCHAR */ 1240*7c478bd9Sstevel@tonic-gate if (*cp != 0 || *dp != '=') { 1241*7c478bd9Sstevel@tonic-gate continue; 1242*7c478bd9Sstevel@tonic-gate } 1243*7c478bd9Sstevel@tonic-gate cp_ = *ep; 1244*7c478bd9Sstevel@tonic-gate *ep = 0; 1245*7c478bd9Sstevel@tonic-gate environ = (char **)blkspl_((unsigned char **)environ, ep+1); 1246*7c478bd9Sstevel@tonic-gate *ep = cp_; 1247*7c478bd9Sstevel@tonic-gate xfree(cp_); 1248*7c478bd9Sstevel@tonic-gate xfree((void *)oep); 1249*7c478bd9Sstevel@tonic-gate return; 1250*7c478bd9Sstevel@tonic-gate } 1251*7c478bd9Sstevel@tonic-gate } 1252*7c478bd9Sstevel@tonic-gate 1253*7c478bd9Sstevel@tonic-gate void 1254*7c478bd9Sstevel@tonic-gate doumask(tchar **v) 1255*7c478bd9Sstevel@tonic-gate { 1256*7c478bd9Sstevel@tonic-gate tchar *cp = v[1]; 1257*7c478bd9Sstevel@tonic-gate int i; 1258*7c478bd9Sstevel@tonic-gate 1259*7c478bd9Sstevel@tonic-gate #ifdef TRACE 1260*7c478bd9Sstevel@tonic-gate tprintf("TRACE- dounmask()\n"); 1261*7c478bd9Sstevel@tonic-gate #endif 1262*7c478bd9Sstevel@tonic-gate if (cp == 0) { 1263*7c478bd9Sstevel@tonic-gate i = umask(0); 1264*7c478bd9Sstevel@tonic-gate (void) umask(i); 1265*7c478bd9Sstevel@tonic-gate printf("%o\n", i); 1266*7c478bd9Sstevel@tonic-gate return; 1267*7c478bd9Sstevel@tonic-gate } 1268*7c478bd9Sstevel@tonic-gate i = 0; 1269*7c478bd9Sstevel@tonic-gate while (digit(*cp) && *cp != '8' && *cp != '9') { 1270*7c478bd9Sstevel@tonic-gate i = i * 8 + *cp++ - '0'; 1271*7c478bd9Sstevel@tonic-gate } 1272*7c478bd9Sstevel@tonic-gate if (*cp || i < 0 || i > 0777) { 1273*7c478bd9Sstevel@tonic-gate bferr("Improper mask"); 1274*7c478bd9Sstevel@tonic-gate } 1275*7c478bd9Sstevel@tonic-gate (void) umask(i); 1276*7c478bd9Sstevel@tonic-gate } 1277*7c478bd9Sstevel@tonic-gate 1278*7c478bd9Sstevel@tonic-gate 1279*7c478bd9Sstevel@tonic-gate struct limits * 1280*7c478bd9Sstevel@tonic-gate findlim(tchar *cp) 1281*7c478bd9Sstevel@tonic-gate { 1282*7c478bd9Sstevel@tonic-gate struct limits *lp, *res; 1283*7c478bd9Sstevel@tonic-gate 1284*7c478bd9Sstevel@tonic-gate #ifdef TRACE 1285*7c478bd9Sstevel@tonic-gate tprintf("TRACE- findlim()\n"); 1286*7c478bd9Sstevel@tonic-gate #endif 1287*7c478bd9Sstevel@tonic-gate res = 0; 1288*7c478bd9Sstevel@tonic-gate for (lp = limits; lp->limconst >= 0; lp++) { 1289*7c478bd9Sstevel@tonic-gate if (prefix(cp, lp->limname)) { 1290*7c478bd9Sstevel@tonic-gate if (res) { 1291*7c478bd9Sstevel@tonic-gate bferr("Ambiguous"); 1292*7c478bd9Sstevel@tonic-gate } 1293*7c478bd9Sstevel@tonic-gate res = lp; 1294*7c478bd9Sstevel@tonic-gate } 1295*7c478bd9Sstevel@tonic-gate } 1296*7c478bd9Sstevel@tonic-gate if (res) { 1297*7c478bd9Sstevel@tonic-gate return (res); 1298*7c478bd9Sstevel@tonic-gate } 1299*7c478bd9Sstevel@tonic-gate bferr("No such limit"); 1300*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 1301*7c478bd9Sstevel@tonic-gate } 1302*7c478bd9Sstevel@tonic-gate 1303*7c478bd9Sstevel@tonic-gate void 1304*7c478bd9Sstevel@tonic-gate dolimit(tchar **v) 1305*7c478bd9Sstevel@tonic-gate { 1306*7c478bd9Sstevel@tonic-gate struct limits *lp; 1307*7c478bd9Sstevel@tonic-gate rlim_t limit; 1308*7c478bd9Sstevel@tonic-gate tchar hard = 0; 1309*7c478bd9Sstevel@tonic-gate 1310*7c478bd9Sstevel@tonic-gate #ifdef TRACE 1311*7c478bd9Sstevel@tonic-gate tprintf("TRACE- dolimit()\n"); 1312*7c478bd9Sstevel@tonic-gate #endif 1313*7c478bd9Sstevel@tonic-gate v++; 1314*7c478bd9Sstevel@tonic-gate if (*v && eq(*v, S_h)) { 1315*7c478bd9Sstevel@tonic-gate hard = 1; 1316*7c478bd9Sstevel@tonic-gate v++; 1317*7c478bd9Sstevel@tonic-gate } 1318*7c478bd9Sstevel@tonic-gate if (*v == 0) { 1319*7c478bd9Sstevel@tonic-gate for (lp = limits; lp->limconst >= 0; lp++) { 1320*7c478bd9Sstevel@tonic-gate plim(lp, hard); 1321*7c478bd9Sstevel@tonic-gate } 1322*7c478bd9Sstevel@tonic-gate return; 1323*7c478bd9Sstevel@tonic-gate } 1324*7c478bd9Sstevel@tonic-gate lp = findlim(v[0]); 1325*7c478bd9Sstevel@tonic-gate if (v[1] == 0) { 1326*7c478bd9Sstevel@tonic-gate plim(lp, hard); 1327*7c478bd9Sstevel@tonic-gate return; 1328*7c478bd9Sstevel@tonic-gate } 1329*7c478bd9Sstevel@tonic-gate switch (getval(lp, v+1, &limit)) { 1330*7c478bd9Sstevel@tonic-gate case 0: 1331*7c478bd9Sstevel@tonic-gate error("Value specified for limit is too large"); 1332*7c478bd9Sstevel@tonic-gate return; 1333*7c478bd9Sstevel@tonic-gate case (-1): 1334*7c478bd9Sstevel@tonic-gate error("Numeric conversion failed"); 1335*7c478bd9Sstevel@tonic-gate return; 1336*7c478bd9Sstevel@tonic-gate default: 1337*7c478bd9Sstevel@tonic-gate if (setlim(lp, hard, limit) < 0) { 1338*7c478bd9Sstevel@tonic-gate error(NOSTR); 1339*7c478bd9Sstevel@tonic-gate } 1340*7c478bd9Sstevel@tonic-gate } 1341*7c478bd9Sstevel@tonic-gate } 1342*7c478bd9Sstevel@tonic-gate 1343*7c478bd9Sstevel@tonic-gate static int 1344*7c478bd9Sstevel@tonic-gate getval(struct limits *lp, tchar **v, rlim_t *retval) 1345*7c478bd9Sstevel@tonic-gate { 1346*7c478bd9Sstevel@tonic-gate rlim_t value, tmp, tmp2; 1347*7c478bd9Sstevel@tonic-gate tchar *cp = *v++; 1348*7c478bd9Sstevel@tonic-gate char chbuf[BUFSIZ * MB_LEN_MAX]; 1349*7c478bd9Sstevel@tonic-gate 1350*7c478bd9Sstevel@tonic-gate #ifdef TRACE 1351*7c478bd9Sstevel@tonic-gate tprintf("TRACE- getval()\n"); 1352*7c478bd9Sstevel@tonic-gate #endif 1353*7c478bd9Sstevel@tonic-gate 1354*7c478bd9Sstevel@tonic-gate tstostr(chbuf, cp); 1355*7c478bd9Sstevel@tonic-gate errno = 0; 1356*7c478bd9Sstevel@tonic-gate value = strtoull(chbuf, NULL, 0); 1357*7c478bd9Sstevel@tonic-gate /* 1358*7c478bd9Sstevel@tonic-gate * we must accept zero, but the conversion can fail and give us 1359*7c478bd9Sstevel@tonic-gate * zero as well...try to deal with it as gracefully as possible 1360*7c478bd9Sstevel@tonic-gate * by checking for EINVAL 1361*7c478bd9Sstevel@tonic-gate */ 1362*7c478bd9Sstevel@tonic-gate if (value == 0 && errno == EINVAL) 1363*7c478bd9Sstevel@tonic-gate return (-1); 1364*7c478bd9Sstevel@tonic-gate 1365*7c478bd9Sstevel@tonic-gate while (digit(*cp) || *cp == '.' || *cp == 'e' || *cp == 'E') { 1366*7c478bd9Sstevel@tonic-gate cp++; 1367*7c478bd9Sstevel@tonic-gate } 1368*7c478bd9Sstevel@tonic-gate if (*cp == 0) { 1369*7c478bd9Sstevel@tonic-gate if (*v == 0) { 1370*7c478bd9Sstevel@tonic-gate tmp = value * (rlim_t)lp->limdiv; 1371*7c478bd9Sstevel@tonic-gate /* Check for overflow */ 1372*7c478bd9Sstevel@tonic-gate if (tmp >= value) { 1373*7c478bd9Sstevel@tonic-gate *retval = tmp; 1374*7c478bd9Sstevel@tonic-gate return (1); 1375*7c478bd9Sstevel@tonic-gate } else { 1376*7c478bd9Sstevel@tonic-gate return (0); 1377*7c478bd9Sstevel@tonic-gate } 1378*7c478bd9Sstevel@tonic-gate } 1379*7c478bd9Sstevel@tonic-gate cp = *v; 1380*7c478bd9Sstevel@tonic-gate } 1381*7c478bd9Sstevel@tonic-gate switch (*cp) { 1382*7c478bd9Sstevel@tonic-gate 1383*7c478bd9Sstevel@tonic-gate case ':': 1384*7c478bd9Sstevel@tonic-gate if (lp->limconst != RLIMIT_CPU) { 1385*7c478bd9Sstevel@tonic-gate goto badscal; 1386*7c478bd9Sstevel@tonic-gate } 1387*7c478bd9Sstevel@tonic-gate tstostr(chbuf, cp + 1); 1388*7c478bd9Sstevel@tonic-gate tmp = strtoull(chbuf, NULL, 0); 1389*7c478bd9Sstevel@tonic-gate tmp2 = value * 60 + tmp; 1390*7c478bd9Sstevel@tonic-gate if (tmp2 >= value) { 1391*7c478bd9Sstevel@tonic-gate *retval = tmp2; 1392*7c478bd9Sstevel@tonic-gate return (1); 1393*7c478bd9Sstevel@tonic-gate } else { 1394*7c478bd9Sstevel@tonic-gate return (0); 1395*7c478bd9Sstevel@tonic-gate } 1396*7c478bd9Sstevel@tonic-gate 1397*7c478bd9Sstevel@tonic-gate case 'h': 1398*7c478bd9Sstevel@tonic-gate if (lp->limconst != RLIMIT_CPU) { 1399*7c478bd9Sstevel@tonic-gate goto badscal; 1400*7c478bd9Sstevel@tonic-gate } 1401*7c478bd9Sstevel@tonic-gate limtail(cp, S_hours); 1402*7c478bd9Sstevel@tonic-gate tmp = value * 3600; 1403*7c478bd9Sstevel@tonic-gate if (tmp < value) { 1404*7c478bd9Sstevel@tonic-gate return (0); 1405*7c478bd9Sstevel@tonic-gate } 1406*7c478bd9Sstevel@tonic-gate value = tmp; 1407*7c478bd9Sstevel@tonic-gate break; 1408*7c478bd9Sstevel@tonic-gate 1409*7c478bd9Sstevel@tonic-gate case 'm': 1410*7c478bd9Sstevel@tonic-gate if (lp->limconst == RLIMIT_CPU) { 1411*7c478bd9Sstevel@tonic-gate limtail(cp, S_minutes); 1412*7c478bd9Sstevel@tonic-gate tmp = value * 60; 1413*7c478bd9Sstevel@tonic-gate if (tmp < value) { 1414*7c478bd9Sstevel@tonic-gate return (0); 1415*7c478bd9Sstevel@tonic-gate } 1416*7c478bd9Sstevel@tonic-gate value = tmp; 1417*7c478bd9Sstevel@tonic-gate break; 1418*7c478bd9Sstevel@tonic-gate } 1419*7c478bd9Sstevel@tonic-gate case 'M': 1420*7c478bd9Sstevel@tonic-gate if (lp->limconst == RLIMIT_CPU) { 1421*7c478bd9Sstevel@tonic-gate goto badscal; 1422*7c478bd9Sstevel@tonic-gate } 1423*7c478bd9Sstevel@tonic-gate *cp = 'm'; 1424*7c478bd9Sstevel@tonic-gate limtail(cp, S_megabytes); 1425*7c478bd9Sstevel@tonic-gate tmp = value * 1024 * 1024; 1426*7c478bd9Sstevel@tonic-gate if (tmp < value) { 1427*7c478bd9Sstevel@tonic-gate return (0); 1428*7c478bd9Sstevel@tonic-gate } 1429*7c478bd9Sstevel@tonic-gate value = tmp; 1430*7c478bd9Sstevel@tonic-gate break; 1431*7c478bd9Sstevel@tonic-gate 1432*7c478bd9Sstevel@tonic-gate case 's': 1433*7c478bd9Sstevel@tonic-gate if (lp->limconst != RLIMIT_CPU) { 1434*7c478bd9Sstevel@tonic-gate goto badscal; 1435*7c478bd9Sstevel@tonic-gate } 1436*7c478bd9Sstevel@tonic-gate limtail(cp, S_seconds); 1437*7c478bd9Sstevel@tonic-gate break; 1438*7c478bd9Sstevel@tonic-gate 1439*7c478bd9Sstevel@tonic-gate case 'k': 1440*7c478bd9Sstevel@tonic-gate if (lp->limconst == RLIMIT_CPU) { 1441*7c478bd9Sstevel@tonic-gate goto badscal; 1442*7c478bd9Sstevel@tonic-gate } 1443*7c478bd9Sstevel@tonic-gate limtail(cp, S_kbytes); 1444*7c478bd9Sstevel@tonic-gate tmp = value * 1024; 1445*7c478bd9Sstevel@tonic-gate if (tmp < value) { 1446*7c478bd9Sstevel@tonic-gate return (0); 1447*7c478bd9Sstevel@tonic-gate } 1448*7c478bd9Sstevel@tonic-gate value = tmp; 1449*7c478bd9Sstevel@tonic-gate break; 1450*7c478bd9Sstevel@tonic-gate 1451*7c478bd9Sstevel@tonic-gate case 'u': 1452*7c478bd9Sstevel@tonic-gate limtail(cp, S_unlimited); 1453*7c478bd9Sstevel@tonic-gate *retval = RLIM_INFINITY; 1454*7c478bd9Sstevel@tonic-gate return (1); 1455*7c478bd9Sstevel@tonic-gate 1456*7c478bd9Sstevel@tonic-gate default: 1457*7c478bd9Sstevel@tonic-gate badscal: 1458*7c478bd9Sstevel@tonic-gate bferr("Improper or unknown scale factor"); 1459*7c478bd9Sstevel@tonic-gate } 1460*7c478bd9Sstevel@tonic-gate *retval = value; 1461*7c478bd9Sstevel@tonic-gate return (1); 1462*7c478bd9Sstevel@tonic-gate } 1463*7c478bd9Sstevel@tonic-gate 1464*7c478bd9Sstevel@tonic-gate void 1465*7c478bd9Sstevel@tonic-gate limtail(tchar *cp, tchar *str0) 1466*7c478bd9Sstevel@tonic-gate { 1467*7c478bd9Sstevel@tonic-gate tchar *str = str0; 1468*7c478bd9Sstevel@tonic-gate #ifdef TRACE 1469*7c478bd9Sstevel@tonic-gate tprintf("TRACE- limtail()\n"); 1470*7c478bd9Sstevel@tonic-gate #endif 1471*7c478bd9Sstevel@tonic-gate 1472*7c478bd9Sstevel@tonic-gate while (*cp && *cp == *str) { 1473*7c478bd9Sstevel@tonic-gate cp++, str++; 1474*7c478bd9Sstevel@tonic-gate } 1475*7c478bd9Sstevel@tonic-gate if (*cp) { 1476*7c478bd9Sstevel@tonic-gate error("Bad scaling; did you mean ``%t''?", str0); 1477*7c478bd9Sstevel@tonic-gate } 1478*7c478bd9Sstevel@tonic-gate } 1479*7c478bd9Sstevel@tonic-gate 1480*7c478bd9Sstevel@tonic-gate void 1481*7c478bd9Sstevel@tonic-gate plim(struct limits *lp, tchar hard) 1482*7c478bd9Sstevel@tonic-gate { 1483*7c478bd9Sstevel@tonic-gate struct rlimit rlim; 1484*7c478bd9Sstevel@tonic-gate char buf[BUFSZ]; 1485*7c478bd9Sstevel@tonic-gate char *pbuf; 1486*7c478bd9Sstevel@tonic-gate rlim_t limit; 1487*7c478bd9Sstevel@tonic-gate 1488*7c478bd9Sstevel@tonic-gate #ifdef TRACE 1489*7c478bd9Sstevel@tonic-gate tprintf("TRACE- plim()\n"); 1490*7c478bd9Sstevel@tonic-gate #endif 1491*7c478bd9Sstevel@tonic-gate printf("%t \t", lp->limname); 1492*7c478bd9Sstevel@tonic-gate (void) getrlimit(lp->limconst, &rlim); 1493*7c478bd9Sstevel@tonic-gate limit = hard ? rlim.rlim_max : rlim.rlim_cur; 1494*7c478bd9Sstevel@tonic-gate if (limit == RLIM_INFINITY) { 1495*7c478bd9Sstevel@tonic-gate printf("unlimited"); 1496*7c478bd9Sstevel@tonic-gate } else if (lp->limconst == RLIMIT_CPU) { 1497*7c478bd9Sstevel@tonic-gate psecs_ull(limit); 1498*7c478bd9Sstevel@tonic-gate } else { 1499*7c478bd9Sstevel@tonic-gate buf[BUFSZ - 1] = '\0'; 1500*7c478bd9Sstevel@tonic-gate pbuf = ulltostr((limit / lp->limdiv), &buf[BUFSZ - 1]); 1501*7c478bd9Sstevel@tonic-gate printf("%s %t", pbuf, lp->limscale); 1502*7c478bd9Sstevel@tonic-gate } 1503*7c478bd9Sstevel@tonic-gate printf("\n"); 1504*7c478bd9Sstevel@tonic-gate } 1505*7c478bd9Sstevel@tonic-gate 1506*7c478bd9Sstevel@tonic-gate void 1507*7c478bd9Sstevel@tonic-gate dounlimit(tchar **v) 1508*7c478bd9Sstevel@tonic-gate { 1509*7c478bd9Sstevel@tonic-gate struct limits *lp; 1510*7c478bd9Sstevel@tonic-gate int err = 0; 1511*7c478bd9Sstevel@tonic-gate tchar hard = 0; 1512*7c478bd9Sstevel@tonic-gate #ifdef TRACE 1513*7c478bd9Sstevel@tonic-gate tprintf("TRACE- dounlimit()\n"); 1514*7c478bd9Sstevel@tonic-gate #endif 1515*7c478bd9Sstevel@tonic-gate 1516*7c478bd9Sstevel@tonic-gate v++; 1517*7c478bd9Sstevel@tonic-gate if (*v && eq(*v, S_h)) { 1518*7c478bd9Sstevel@tonic-gate hard = 1; 1519*7c478bd9Sstevel@tonic-gate v++; 1520*7c478bd9Sstevel@tonic-gate } 1521*7c478bd9Sstevel@tonic-gate if (*v == 0) { 1522*7c478bd9Sstevel@tonic-gate for (lp = limits; lp->limconst >= 0; lp++) { 1523*7c478bd9Sstevel@tonic-gate if (setlim(lp, hard, RLIM_INFINITY) < 0) { 1524*7c478bd9Sstevel@tonic-gate err++; 1525*7c478bd9Sstevel@tonic-gate } 1526*7c478bd9Sstevel@tonic-gate } 1527*7c478bd9Sstevel@tonic-gate if (err) { 1528*7c478bd9Sstevel@tonic-gate error(NULL); 1529*7c478bd9Sstevel@tonic-gate } 1530*7c478bd9Sstevel@tonic-gate return; 1531*7c478bd9Sstevel@tonic-gate } 1532*7c478bd9Sstevel@tonic-gate while (*v) { 1533*7c478bd9Sstevel@tonic-gate lp = findlim(*v++); 1534*7c478bd9Sstevel@tonic-gate if (setlim(lp, hard, RLIM_INFINITY) < 0) { 1535*7c478bd9Sstevel@tonic-gate error(NULL); 1536*7c478bd9Sstevel@tonic-gate } 1537*7c478bd9Sstevel@tonic-gate } 1538*7c478bd9Sstevel@tonic-gate } 1539*7c478bd9Sstevel@tonic-gate 1540*7c478bd9Sstevel@tonic-gate int 1541*7c478bd9Sstevel@tonic-gate setlim(struct limits *lp, tchar hard, rlim_t limit) 1542*7c478bd9Sstevel@tonic-gate { 1543*7c478bd9Sstevel@tonic-gate struct rlimit rlim; 1544*7c478bd9Sstevel@tonic-gate 1545*7c478bd9Sstevel@tonic-gate #ifdef TRACE 1546*7c478bd9Sstevel@tonic-gate tprintf("TRACE- setlim()\n"); 1547*7c478bd9Sstevel@tonic-gate #endif 1548*7c478bd9Sstevel@tonic-gate (void) getrlimit(lp->limconst, &rlim); 1549*7c478bd9Sstevel@tonic-gate if (hard) { 1550*7c478bd9Sstevel@tonic-gate rlim.rlim_max = limit; 1551*7c478bd9Sstevel@tonic-gate } else if (limit == RLIM_INFINITY && geteuid() != 0) { 1552*7c478bd9Sstevel@tonic-gate rlim.rlim_cur = rlim.rlim_max; 1553*7c478bd9Sstevel@tonic-gate } else { 1554*7c478bd9Sstevel@tonic-gate rlim.rlim_cur = limit; 1555*7c478bd9Sstevel@tonic-gate } 1556*7c478bd9Sstevel@tonic-gate if (setrlimit(lp->limconst, &rlim) < 0) { 1557*7c478bd9Sstevel@tonic-gate printf("%t: %t: Can't %s%s limit\n", bname, lp->limname, 1558*7c478bd9Sstevel@tonic-gate limit == RLIM_INFINITY ? "remove" : "set", 1559*7c478bd9Sstevel@tonic-gate hard ? " hard" : ""); 1560*7c478bd9Sstevel@tonic-gate return (-1); 1561*7c478bd9Sstevel@tonic-gate } 1562*7c478bd9Sstevel@tonic-gate return (0); 1563*7c478bd9Sstevel@tonic-gate } 1564*7c478bd9Sstevel@tonic-gate 1565*7c478bd9Sstevel@tonic-gate void 1566*7c478bd9Sstevel@tonic-gate dosuspend() 1567*7c478bd9Sstevel@tonic-gate { 1568*7c478bd9Sstevel@tonic-gate int ctpgrp; 1569*7c478bd9Sstevel@tonic-gate void (*old)(); 1570*7c478bd9Sstevel@tonic-gate 1571*7c478bd9Sstevel@tonic-gate #ifdef TRACE 1572*7c478bd9Sstevel@tonic-gate tprintf("TRACE- dosuspend()\n"); 1573*7c478bd9Sstevel@tonic-gate #endif 1574*7c478bd9Sstevel@tonic-gate if (loginsh) { 1575*7c478bd9Sstevel@tonic-gate error("Can't suspend a login shell (yet)"); 1576*7c478bd9Sstevel@tonic-gate } 1577*7c478bd9Sstevel@tonic-gate if (getpid() == getsid(0)) { 1578*7c478bd9Sstevel@tonic-gate error("Can't suspend this shell"); 1579*7c478bd9Sstevel@tonic-gate } 1580*7c478bd9Sstevel@tonic-gate untty(); 1581*7c478bd9Sstevel@tonic-gate old = (void (*)())signal(SIGTSTP, SIG_DFL); 1582*7c478bd9Sstevel@tonic-gate (void) kill(0, SIGTSTP); 1583*7c478bd9Sstevel@tonic-gate /* the shell stops here */ 1584*7c478bd9Sstevel@tonic-gate (void) signal(SIGTSTP, old); 1585*7c478bd9Sstevel@tonic-gate if (tpgrp != -1) { 1586*7c478bd9Sstevel@tonic-gate retry: 1587*7c478bd9Sstevel@tonic-gate (void) ioctl(FSHTTY, TIOCGPGRP, (char *)&ctpgrp); 1588*7c478bd9Sstevel@tonic-gate if (ctpgrp != opgrp) { 1589*7c478bd9Sstevel@tonic-gate old = (void (*)())signal(SIGTTIN, SIG_DFL); 1590*7c478bd9Sstevel@tonic-gate (void) kill(0, SIGTTIN); 1591*7c478bd9Sstevel@tonic-gate (void) signal(SIGTTIN, old); 1592*7c478bd9Sstevel@tonic-gate goto retry; 1593*7c478bd9Sstevel@tonic-gate } 1594*7c478bd9Sstevel@tonic-gate (void) setpgid(0, shpgrp); 1595*7c478bd9Sstevel@tonic-gate (void) ioctl(FSHTTY, TIOCSPGRP, (char *)&shpgrp); 1596*7c478bd9Sstevel@tonic-gate } 1597*7c478bd9Sstevel@tonic-gate } 1598*7c478bd9Sstevel@tonic-gate 1599*7c478bd9Sstevel@tonic-gate void 1600*7c478bd9Sstevel@tonic-gate doeval(tchar **v) 1601*7c478bd9Sstevel@tonic-gate { 1602*7c478bd9Sstevel@tonic-gate tchar **oevalvec = evalvec; 1603*7c478bd9Sstevel@tonic-gate tchar *oevalp = evalp; 1604*7c478bd9Sstevel@tonic-gate jmp_buf osetexit; 1605*7c478bd9Sstevel@tonic-gate int reenter; 1606*7c478bd9Sstevel@tonic-gate tchar **gv = 0; 1607*7c478bd9Sstevel@tonic-gate 1608*7c478bd9Sstevel@tonic-gate #ifdef TRACE 1609*7c478bd9Sstevel@tonic-gate tprintf("TRACE- doeval()\n"); 1610*7c478bd9Sstevel@tonic-gate #endif 1611*7c478bd9Sstevel@tonic-gate v++; 1612*7c478bd9Sstevel@tonic-gate if (*v == 0) { 1613*7c478bd9Sstevel@tonic-gate return; 1614*7c478bd9Sstevel@tonic-gate } 1615*7c478bd9Sstevel@tonic-gate gflag = 0, tglob(v); 1616*7c478bd9Sstevel@tonic-gate if (gflag) { 1617*7c478bd9Sstevel@tonic-gate gv = v = glob(v); 1618*7c478bd9Sstevel@tonic-gate gargv = 0; 1619*7c478bd9Sstevel@tonic-gate if (v == 0) { 1620*7c478bd9Sstevel@tonic-gate error("No match"); 1621*7c478bd9Sstevel@tonic-gate } 1622*7c478bd9Sstevel@tonic-gate v = copyblk(v); 1623*7c478bd9Sstevel@tonic-gate } else { 1624*7c478bd9Sstevel@tonic-gate trim(v); 1625*7c478bd9Sstevel@tonic-gate } 1626*7c478bd9Sstevel@tonic-gate getexit(osetexit); 1627*7c478bd9Sstevel@tonic-gate reenter = 0; 1628*7c478bd9Sstevel@tonic-gate setexit(); 1629*7c478bd9Sstevel@tonic-gate reenter++; 1630*7c478bd9Sstevel@tonic-gate if (reenter == 1) { 1631*7c478bd9Sstevel@tonic-gate evalvec = v; 1632*7c478bd9Sstevel@tonic-gate evalp = 0; 1633*7c478bd9Sstevel@tonic-gate process(0); 1634*7c478bd9Sstevel@tonic-gate } 1635*7c478bd9Sstevel@tonic-gate evalvec = oevalvec; 1636*7c478bd9Sstevel@tonic-gate evalp = oevalp; 1637*7c478bd9Sstevel@tonic-gate doneinp = 0; 1638*7c478bd9Sstevel@tonic-gate if (gv) { 1639*7c478bd9Sstevel@tonic-gate blkfree(gv); 1640*7c478bd9Sstevel@tonic-gate } 1641*7c478bd9Sstevel@tonic-gate resexit(osetexit); 1642*7c478bd9Sstevel@tonic-gate if (reenter >= 2) { 1643*7c478bd9Sstevel@tonic-gate error(NULL); 1644*7c478bd9Sstevel@tonic-gate } 1645*7c478bd9Sstevel@tonic-gate } 1646