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 <locale.h> 18*7c478bd9Sstevel@tonic-gate #include "sh.h" 19*7c478bd9Sstevel@tonic-gate /* #include <sys/ioctl.h> */ 20*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 21*7c478bd9Sstevel@tonic-gate #include <sys/filio.h> 22*7c478bd9Sstevel@tonic-gate #include "sh.tconst.h" 23*7c478bd9Sstevel@tonic-gate #include <pwd.h> 24*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 25*7c478bd9Sstevel@tonic-gate #include "sh_policy.h" /* for pfcsh */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* 28*7c478bd9Sstevel@tonic-gate * We use these csh(1) private versions of the select macros, (see select(3C)) 29*7c478bd9Sstevel@tonic-gate * so as not to be limited by the size of struct fd_set (ie 1024). 30*7c478bd9Sstevel@tonic-gate */ 31*7c478bd9Sstevel@tonic-gate #define CSH_FD_SET(n, p) ((*((p) + ((n)/NFDBITS))) |= (1 << ((n) % NFDBITS))) 32*7c478bd9Sstevel@tonic-gate #define CSH_FD_CLR(n, p) ((*((p) + ((n)/NFDBITS))) &= ~(1 << ((n) % NFDBITS))) 33*7c478bd9Sstevel@tonic-gate #define CSH_FD_ISSET(n, p) ((*((p) + ((n)/NFDBITS))) & (1 << ((n) % NFDBITS))) 34*7c478bd9Sstevel@tonic-gate #define CSH_FD_ZERO(p, n) memset((void *)(p), 0, (n)) 35*7c478bd9Sstevel@tonic-gate 36*7c478bd9Sstevel@tonic-gate tchar *pathlist[] = { S_usrbin/*"/usr/bin"*/, S_DOT /*"."*/, 0 }; 37*7c478bd9Sstevel@tonic-gate tchar *dumphist[] = { S_history /*"history"*/, S_h /*"-h"*/, 0, 0 }; 38*7c478bd9Sstevel@tonic-gate tchar *loadhist[] = { S_source /*"source"*/, S_h /*"-h"*/, S_NDOThistory /*"~/.history"*/, 0 }; 39*7c478bd9Sstevel@tonic-gate tchar HIST = '!'; 40*7c478bd9Sstevel@tonic-gate tchar HISTSUB = '^'; 41*7c478bd9Sstevel@tonic-gate int nofile; 42*7c478bd9Sstevel@tonic-gate bool reenter; 43*7c478bd9Sstevel@tonic-gate bool nverbose; 44*7c478bd9Sstevel@tonic-gate bool nexececho; 45*7c478bd9Sstevel@tonic-gate bool quitit; 46*7c478bd9Sstevel@tonic-gate bool fast; 47*7c478bd9Sstevel@tonic-gate bool batch; 48*7c478bd9Sstevel@tonic-gate bool prompt = 1; 49*7c478bd9Sstevel@tonic-gate bool enterhist = 0; 50*7c478bd9Sstevel@tonic-gate 51*7c478bd9Sstevel@tonic-gate extern gid_t getegid(), getgid(); 52*7c478bd9Sstevel@tonic-gate extern uid_t geteuid(), getuid(); 53*7c478bd9Sstevel@tonic-gate extern tchar **strblktotsblk(/* char **, int */); 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate int siglwp(); 56*7c478bd9Sstevel@tonic-gate int sigwaiting(); 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate main(c, av) 59*7c478bd9Sstevel@tonic-gate int c; 60*7c478bd9Sstevel@tonic-gate char **av; 61*7c478bd9Sstevel@tonic-gate { 62*7c478bd9Sstevel@tonic-gate register tchar **v, *cp, *p, *q, *r; 63*7c478bd9Sstevel@tonic-gate register int f; 64*7c478bd9Sstevel@tonic-gate struct sigvec osv; 65*7c478bd9Sstevel@tonic-gate struct sigaction sa; 66*7c478bd9Sstevel@tonic-gate tchar s_prompt[MAXHOSTNAMELEN+3]; 67*7c478bd9Sstevel@tonic-gate 68*7c478bd9Sstevel@tonic-gate pfcshflag = 0; 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate /* 71*7c478bd9Sstevel@tonic-gate * set up the error exit, if there is an error before 72*7c478bd9Sstevel@tonic-gate * this is done, it will core dump, and we don't 73*7c478bd9Sstevel@tonic-gate * tolerate core dumps 74*7c478bd9Sstevel@tonic-gate */ 75*7c478bd9Sstevel@tonic-gate haderr = 0; 76*7c478bd9Sstevel@tonic-gate setexit(); 77*7c478bd9Sstevel@tonic-gate if ( haderr ) { 78*7c478bd9Sstevel@tonic-gate /* 79*7c478bd9Sstevel@tonic-gate * if were here, there was an error in the csh 80*7c478bd9Sstevel@tonic-gate * startup so just punt 81*7c478bd9Sstevel@tonic-gate */ 82*7c478bd9Sstevel@tonic-gate printf("csh startup error, csh exiting...\n"); 83*7c478bd9Sstevel@tonic-gate flush(); 84*7c478bd9Sstevel@tonic-gate exitstat(); 85*7c478bd9Sstevel@tonic-gate } 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 89*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 90*7c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 91*7c478bd9Sstevel@tonic-gate #endif 92*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 93*7c478bd9Sstevel@tonic-gate 94*7c478bd9Sstevel@tonic-gate /* 95*7c478bd9Sstevel@tonic-gate * This is a profile shell if the simple name of argv[0] is 96*7c478bd9Sstevel@tonic-gate * pfcsh or -pfcsh 97*7c478bd9Sstevel@tonic-gate */ 98*7c478bd9Sstevel@tonic-gate p = strtots(NOSTR, "pfcsh"); 99*7c478bd9Sstevel@tonic-gate r = strtots(NOSTR, "-pfcsh"); 100*7c478bd9Sstevel@tonic-gate if ((p != NOSTR) && (r != NOSTR) && 101*7c478bd9Sstevel@tonic-gate ((q = strtots(NOSTR, *av)) != NOSTR)) { 102*7c478bd9Sstevel@tonic-gate if (c > 0 && (eq(p, simple(q)) || eq(r, simple(q)))) { 103*7c478bd9Sstevel@tonic-gate pfcshflag = 1; 104*7c478bd9Sstevel@tonic-gate } 105*7c478bd9Sstevel@tonic-gate XFREE(q); 106*7c478bd9Sstevel@tonic-gate } 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate if (p != NOSTR) 109*7c478bd9Sstevel@tonic-gate XFREE(p); 110*7c478bd9Sstevel@tonic-gate if (r != NOSTR) 111*7c478bd9Sstevel@tonic-gate XFREE(r); 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate if (pfcshflag == 1) { 114*7c478bd9Sstevel@tonic-gate secpolicy_init(); 115*7c478bd9Sstevel@tonic-gate } 116*7c478bd9Sstevel@tonic-gate 117*7c478bd9Sstevel@tonic-gate /* Copy arguments */ 118*7c478bd9Sstevel@tonic-gate v = strblktotsblk(av, c); 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate /* 121*7c478bd9Sstevel@tonic-gate * Initialize paraml list 122*7c478bd9Sstevel@tonic-gate */ 123*7c478bd9Sstevel@tonic-gate paraml.next = paraml.prev = ¶ml; 124*7c478bd9Sstevel@tonic-gate 125*7c478bd9Sstevel@tonic-gate settimes(); /* Immed. estab. timing base */ 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate if (eq(v[0], S_aout/*"a.out"*/)) /* A.out's are quittable */ 128*7c478bd9Sstevel@tonic-gate quitit = 1; 129*7c478bd9Sstevel@tonic-gate uid = getuid(); 130*7c478bd9Sstevel@tonic-gate loginsh = **v == '-'; 131*7c478bd9Sstevel@tonic-gate if (loginsh) 132*7c478bd9Sstevel@tonic-gate (void) time(&chktim); 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate /* 135*7c478bd9Sstevel@tonic-gate * Move the descriptors to safe places. 136*7c478bd9Sstevel@tonic-gate * The variable didfds is 0 while we have only FSH* to work with. 137*7c478bd9Sstevel@tonic-gate * When didfds is true, we have 0,1,2 and prefer to use these. 138*7c478bd9Sstevel@tonic-gate * 139*7c478bd9Sstevel@tonic-gate * Also, setup data for csh internal file descriptor book keeping. 140*7c478bd9Sstevel@tonic-gate */ 141*7c478bd9Sstevel@tonic-gate initdesc(c, av); 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate /* 144*7c478bd9Sstevel@tonic-gate * Initialize the shell variables. 145*7c478bd9Sstevel@tonic-gate * ARGV and PROMPT are initialized later. 146*7c478bd9Sstevel@tonic-gate * STATUS is also munged in several places. 147*7c478bd9Sstevel@tonic-gate * CHILD is munged when forking/waiting 148*7c478bd9Sstevel@tonic-gate */ 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate /* don't do globbing here, just set exact copies */ 151*7c478bd9Sstevel@tonic-gate setNS(S_noglob); 152*7c478bd9Sstevel@tonic-gate 153*7c478bd9Sstevel@tonic-gate set(S_status /* "status" */, S_0 /* "0" */); 154*7c478bd9Sstevel@tonic-gate dinit(cp = getenvs_("HOME")); /* dinit thinks that HOME==cwd in a */ 155*7c478bd9Sstevel@tonic-gate /* login shell */ 156*7c478bd9Sstevel@tonic-gate if (cp == NOSTR) 157*7c478bd9Sstevel@tonic-gate fast++; /* No home -> can't read scripts */ 158*7c478bd9Sstevel@tonic-gate else { 159*7c478bd9Sstevel@tonic-gate if (strlen_(cp) >= BUFSIZ - 10) { 160*7c478bd9Sstevel@tonic-gate cp = NOSTR; 161*7c478bd9Sstevel@tonic-gate fast++; 162*7c478bd9Sstevel@tonic-gate printf("%s\n", gettext("Pathname too long")); 163*7c478bd9Sstevel@tonic-gate set(S_home /* "home" */, savestr(cp)); 164*7c478bd9Sstevel@tonic-gate local_setenv(S_HOME, savestr(cp)); 165*7c478bd9Sstevel@tonic-gate } 166*7c478bd9Sstevel@tonic-gate set(S_home /* "home" */, savestr(cp)); 167*7c478bd9Sstevel@tonic-gate } 168*7c478bd9Sstevel@tonic-gate /* 169*7c478bd9Sstevel@tonic-gate * Grab other useful things from the environment. 170*7c478bd9Sstevel@tonic-gate * Should we grab everything?? 171*7c478bd9Sstevel@tonic-gate */ 172*7c478bd9Sstevel@tonic-gate if ((cp = getenvs_("USER")) != NOSTR) 173*7c478bd9Sstevel@tonic-gate set(S_user/*"user"*/, savestr(cp)); 174*7c478bd9Sstevel@tonic-gate else { 175*7c478bd9Sstevel@tonic-gate /* 176*7c478bd9Sstevel@tonic-gate * If USER is not defined, set it here. 177*7c478bd9Sstevel@tonic-gate */ 178*7c478bd9Sstevel@tonic-gate struct passwd *pw; 179*7c478bd9Sstevel@tonic-gate pw = getpwuid(getuid()); 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate if (pw != NULL) { 182*7c478bd9Sstevel@tonic-gate set(S_user, strtots((tchar *)0, pw->pw_name )); 183*7c478bd9Sstevel@tonic-gate local_setenv(S_USER, strtots((tchar *)0, pw->pw_name)); 184*7c478bd9Sstevel@tonic-gate } 185*7c478bd9Sstevel@tonic-gate else if (loginsh) { /* Give up setting USER variable. */ 186*7c478bd9Sstevel@tonic-gate printf("Warning: USER environment variable could not be set.\n"); 187*7c478bd9Sstevel@tonic-gate } 188*7c478bd9Sstevel@tonic-gate } 189*7c478bd9Sstevel@tonic-gate if ((cp = getenvs_("TERM")) != NOSTR) 190*7c478bd9Sstevel@tonic-gate set(S_term/*"term"*/, savestr(cp)); 191*7c478bd9Sstevel@tonic-gate /* 192*7c478bd9Sstevel@tonic-gate * Re-initialize path if set in environment 193*7c478bd9Sstevel@tonic-gate */ 194*7c478bd9Sstevel@tonic-gate if ((cp = getenvs_("PATH")) == NOSTR) 195*7c478bd9Sstevel@tonic-gate set1(S_path/*"path"*/, saveblk(pathlist), &shvhed); 196*7c478bd9Sstevel@tonic-gate else 197*7c478bd9Sstevel@tonic-gate importpath(cp); 198*7c478bd9Sstevel@tonic-gate set(S_shell/*"shell"*/, S_SHELLPATH); 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate doldol = putn(getpid()); /* For $$ */ 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate /* restore globbing until the user says otherwise */ 203*7c478bd9Sstevel@tonic-gate unsetv(S_noglob); 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate /* 206*7c478bd9Sstevel@tonic-gate * Record the interrupt states from the parent process. 207*7c478bd9Sstevel@tonic-gate * If the parent is non-interruptible our hand must be forced 208*7c478bd9Sstevel@tonic-gate * or we (and our children) won't be either. 209*7c478bd9Sstevel@tonic-gate * Our children inherit termination from our parent. 210*7c478bd9Sstevel@tonic-gate * We catch it only if we are the login shell. 211*7c478bd9Sstevel@tonic-gate */ 212*7c478bd9Sstevel@tonic-gate /* parents interruptibility */ 213*7c478bd9Sstevel@tonic-gate (void) sigvec(SIGINT, (struct sigvec *)0, &osv); 214*7c478bd9Sstevel@tonic-gate parintr = osv.sv_handler; 215*7c478bd9Sstevel@tonic-gate /* parents terminability */ 216*7c478bd9Sstevel@tonic-gate (void) sigvec(SIGTERM, (struct sigvec *)0, &osv); 217*7c478bd9Sstevel@tonic-gate parterm = osv.sv_handler; 218*7c478bd9Sstevel@tonic-gate 219*7c478bd9Sstevel@tonic-gate _signal(SIGLWP, siglwp); 220*7c478bd9Sstevel@tonic-gate _signal(SIGWAITING, sigwaiting); 221*7c478bd9Sstevel@tonic-gate if (loginsh) { 222*7c478bd9Sstevel@tonic-gate (void) signal(SIGHUP, phup); /* exit processing on HUP */ 223*7c478bd9Sstevel@tonic-gate (void) signal(SIGXCPU, phup); /* ...and on XCPU */ 224*7c478bd9Sstevel@tonic-gate (void) signal(SIGXFSZ, phup); /* ...and on XFSZ */ 225*7c478bd9Sstevel@tonic-gate } 226*7c478bd9Sstevel@tonic-gate 227*7c478bd9Sstevel@tonic-gate /* 228*7c478bd9Sstevel@tonic-gate * Process the arguments. 229*7c478bd9Sstevel@tonic-gate * 230*7c478bd9Sstevel@tonic-gate * Note that processing of -v/-x is actually delayed till after 231*7c478bd9Sstevel@tonic-gate * script processing. 232*7c478bd9Sstevel@tonic-gate */ 233*7c478bd9Sstevel@tonic-gate c--, v++; 234*7c478bd9Sstevel@tonic-gate while (c > 0 && (cp = v[0])[0] == '-' && *++cp != '\0' && !batch) { 235*7c478bd9Sstevel@tonic-gate do switch (*cp++) { 236*7c478bd9Sstevel@tonic-gate 237*7c478bd9Sstevel@tonic-gate case 'b': /* -b Next arg is input file */ 238*7c478bd9Sstevel@tonic-gate batch++; 239*7c478bd9Sstevel@tonic-gate break; 240*7c478bd9Sstevel@tonic-gate 241*7c478bd9Sstevel@tonic-gate case 'c': /* -c Command input from arg */ 242*7c478bd9Sstevel@tonic-gate if (c == 1) 243*7c478bd9Sstevel@tonic-gate exit(0); 244*7c478bd9Sstevel@tonic-gate c--, v++; 245*7c478bd9Sstevel@tonic-gate arginp = v[0]; 246*7c478bd9Sstevel@tonic-gate prompt = 0; 247*7c478bd9Sstevel@tonic-gate nofile++; 248*7c478bd9Sstevel@tonic-gate cflg++; 249*7c478bd9Sstevel@tonic-gate break; 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate case 'e': /* -e Exit on any error */ 252*7c478bd9Sstevel@tonic-gate exiterr++; 253*7c478bd9Sstevel@tonic-gate break; 254*7c478bd9Sstevel@tonic-gate 255*7c478bd9Sstevel@tonic-gate case 'f': /* -f Fast start */ 256*7c478bd9Sstevel@tonic-gate fast++; 257*7c478bd9Sstevel@tonic-gate break; 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate case 'i': /* -i Interactive, even if !intty */ 260*7c478bd9Sstevel@tonic-gate intact++; 261*7c478bd9Sstevel@tonic-gate nofile++; 262*7c478bd9Sstevel@tonic-gate break; 263*7c478bd9Sstevel@tonic-gate 264*7c478bd9Sstevel@tonic-gate case 'n': /* -n Don't execute */ 265*7c478bd9Sstevel@tonic-gate noexec++; 266*7c478bd9Sstevel@tonic-gate break; 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate case 'q': /* -q (Undoc'd) ... die on quit */ 269*7c478bd9Sstevel@tonic-gate quitit = 1; 270*7c478bd9Sstevel@tonic-gate break; 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate case 's': /* -s Read from std input */ 273*7c478bd9Sstevel@tonic-gate nofile++; 274*7c478bd9Sstevel@tonic-gate break; 275*7c478bd9Sstevel@tonic-gate 276*7c478bd9Sstevel@tonic-gate case 't': /* -t Read one line from input */ 277*7c478bd9Sstevel@tonic-gate onelflg = 2; 278*7c478bd9Sstevel@tonic-gate prompt = 0; 279*7c478bd9Sstevel@tonic-gate nofile++; 280*7c478bd9Sstevel@tonic-gate break; 281*7c478bd9Sstevel@tonic-gate #ifdef TRACE 282*7c478bd9Sstevel@tonic-gate case 'T': /* -T trace switch on */ 283*7c478bd9Sstevel@tonic-gate trace_init(); 284*7c478bd9Sstevel@tonic-gate break; 285*7c478bd9Sstevel@tonic-gate #endif 286*7c478bd9Sstevel@tonic-gate 287*7c478bd9Sstevel@tonic-gate case 'v': /* -v Echo hist expanded input */ 288*7c478bd9Sstevel@tonic-gate nverbose = 1; /* ... later */ 289*7c478bd9Sstevel@tonic-gate break; 290*7c478bd9Sstevel@tonic-gate 291*7c478bd9Sstevel@tonic-gate case 'x': /* -x Echo just before execution */ 292*7c478bd9Sstevel@tonic-gate nexececho = 1; /* ... later */ 293*7c478bd9Sstevel@tonic-gate break; 294*7c478bd9Sstevel@tonic-gate 295*7c478bd9Sstevel@tonic-gate case 'V': /* -V Echo hist expanded input */ 296*7c478bd9Sstevel@tonic-gate setNS(S_verbose/*"verbose"*/); /* NOW! */ 297*7c478bd9Sstevel@tonic-gate break; 298*7c478bd9Sstevel@tonic-gate 299*7c478bd9Sstevel@tonic-gate case 'X': /* -X Echo just before execution */ 300*7c478bd9Sstevel@tonic-gate setNS(S_echo/*"echo"*/); /* NOW! */ 301*7c478bd9Sstevel@tonic-gate break; 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate } while (*cp); 304*7c478bd9Sstevel@tonic-gate v++, c--; 305*7c478bd9Sstevel@tonic-gate } 306*7c478bd9Sstevel@tonic-gate 307*7c478bd9Sstevel@tonic-gate if (quitit) /* With all due haste, for debugging */ 308*7c478bd9Sstevel@tonic-gate (void) signal(SIGQUIT, SIG_DFL); 309*7c478bd9Sstevel@tonic-gate 310*7c478bd9Sstevel@tonic-gate /* 311*7c478bd9Sstevel@tonic-gate * Unless prevented by -c, -i, -s, or -t, if there 312*7c478bd9Sstevel@tonic-gate * are remaining arguments the first of them is the name 313*7c478bd9Sstevel@tonic-gate * of a shell file from which to read commands. 314*7c478bd9Sstevel@tonic-gate */ 315*7c478bd9Sstevel@tonic-gate if (!batch && (uid != geteuid() || getgid() != getegid())) { 316*7c478bd9Sstevel@tonic-gate errno = EACCES; 317*7c478bd9Sstevel@tonic-gate child++; /* So this ... */ 318*7c478bd9Sstevel@tonic-gate Perror(S_csh/*"csh"*/); /* ... doesn't return */ 319*7c478bd9Sstevel@tonic-gate } 320*7c478bd9Sstevel@tonic-gate 321*7c478bd9Sstevel@tonic-gate if (nofile == 0 && c > 0) { 322*7c478bd9Sstevel@tonic-gate nofile = open_(v[0], 0); 323*7c478bd9Sstevel@tonic-gate if (nofile < 0) { 324*7c478bd9Sstevel@tonic-gate child++; /* So this ... */ 325*7c478bd9Sstevel@tonic-gate Perror(v[0]); /* ... doesn't return */ 326*7c478bd9Sstevel@tonic-gate } 327*7c478bd9Sstevel@tonic-gate file = v[0]; 328*7c478bd9Sstevel@tonic-gate SHIN = dmove(nofile, FSHIN); /* Replace FSHIN */ 329*7c478bd9Sstevel@tonic-gate (void) fcntl(SHIN, F_SETFD, 1); 330*7c478bd9Sstevel@tonic-gate prompt = 0; 331*7c478bd9Sstevel@tonic-gate c--, v++; 332*7c478bd9Sstevel@tonic-gate } 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate /* 335*7c478bd9Sstevel@tonic-gate * Consider input a tty if it really is or we are interactive. 336*7c478bd9Sstevel@tonic-gate */ 337*7c478bd9Sstevel@tonic-gate intty = intact || isatty(SHIN); 338*7c478bd9Sstevel@tonic-gate 339*7c478bd9Sstevel@tonic-gate /* 340*7c478bd9Sstevel@tonic-gate * Decide whether we should play with signals or not. 341*7c478bd9Sstevel@tonic-gate * If we are explicitly told (via -i, or -) or we are a login 342*7c478bd9Sstevel@tonic-gate * shell (arg0 starts with -) or the input and output are both 343*7c478bd9Sstevel@tonic-gate * the ttys("csh", or "csh</dev/ttyx>/dev/ttyx") 344*7c478bd9Sstevel@tonic-gate * Note that in only the login shell is it likely that parent 345*7c478bd9Sstevel@tonic-gate * may have set signals to be ignored 346*7c478bd9Sstevel@tonic-gate */ 347*7c478bd9Sstevel@tonic-gate if (loginsh || intact || intty && isatty(SHOUT)) 348*7c478bd9Sstevel@tonic-gate setintr = 1; 349*7c478bd9Sstevel@tonic-gate #ifdef TELL 350*7c478bd9Sstevel@tonic-gate settell(); 351*7c478bd9Sstevel@tonic-gate #endif 352*7c478bd9Sstevel@tonic-gate /* 353*7c478bd9Sstevel@tonic-gate * Save the remaining arguments in argv. 354*7c478bd9Sstevel@tonic-gate */ 355*7c478bd9Sstevel@tonic-gate setq(S_argv/*"argv"*/, v, &shvhed); 356*7c478bd9Sstevel@tonic-gate 357*7c478bd9Sstevel@tonic-gate /* 358*7c478bd9Sstevel@tonic-gate * Set up the prompt. 359*7c478bd9Sstevel@tonic-gate */ 360*7c478bd9Sstevel@tonic-gate if (prompt) { 361*7c478bd9Sstevel@tonic-gate gethostname_(s_prompt, MAXHOSTNAMELEN); 362*7c478bd9Sstevel@tonic-gate strcat_(s_prompt, uid == 0 ? S_SHARPSP/*"# "*/ : S_PERSENTSP/*"% "*/); 363*7c478bd9Sstevel@tonic-gate set(S_prompt/*"prompt"*/, s_prompt); 364*7c478bd9Sstevel@tonic-gate } 365*7c478bd9Sstevel@tonic-gate 366*7c478bd9Sstevel@tonic-gate /* 367*7c478bd9Sstevel@tonic-gate * If we are an interactive shell, then start fiddling 368*7c478bd9Sstevel@tonic-gate * with the signals; this is a tricky game. 369*7c478bd9Sstevel@tonic-gate */ 370*7c478bd9Sstevel@tonic-gate shpgrp = getpgid(0); 371*7c478bd9Sstevel@tonic-gate opgrp = tpgrp = -1; 372*7c478bd9Sstevel@tonic-gate if (setintr) { 373*7c478bd9Sstevel@tonic-gate **av = '-'; 374*7c478bd9Sstevel@tonic-gate if (!quitit) /* Wary! */ 375*7c478bd9Sstevel@tonic-gate (void) signal(SIGQUIT, SIG_IGN); 376*7c478bd9Sstevel@tonic-gate (void) signal(SIGINT, pintr); 377*7c478bd9Sstevel@tonic-gate (void) sigblock(sigmask(SIGINT)); 378*7c478bd9Sstevel@tonic-gate (void) signal(SIGTERM, SIG_IGN); 379*7c478bd9Sstevel@tonic-gate if (quitit == 0 && arginp == 0) { 380*7c478bd9Sstevel@tonic-gate (void) signal(SIGTSTP, SIG_IGN); 381*7c478bd9Sstevel@tonic-gate (void) signal(SIGTTIN, SIG_IGN); 382*7c478bd9Sstevel@tonic-gate (void) signal(SIGTTOU, SIG_IGN); 383*7c478bd9Sstevel@tonic-gate /* 384*7c478bd9Sstevel@tonic-gate * Wait till in foreground, in case someone 385*7c478bd9Sstevel@tonic-gate * stupidly runs 386*7c478bd9Sstevel@tonic-gate * csh & 387*7c478bd9Sstevel@tonic-gate * dont want to try to grab away the tty. 388*7c478bd9Sstevel@tonic-gate */ 389*7c478bd9Sstevel@tonic-gate if (isatty(FSHDIAG)) 390*7c478bd9Sstevel@tonic-gate f = FSHDIAG; 391*7c478bd9Sstevel@tonic-gate else if (isatty(FSHOUT)) 392*7c478bd9Sstevel@tonic-gate f = FSHOUT; 393*7c478bd9Sstevel@tonic-gate else if (isatty(OLDSTD)) 394*7c478bd9Sstevel@tonic-gate f = OLDSTD; 395*7c478bd9Sstevel@tonic-gate else 396*7c478bd9Sstevel@tonic-gate f = -1; 397*7c478bd9Sstevel@tonic-gate retry: 398*7c478bd9Sstevel@tonic-gate if (ioctl(f, TIOCGPGRP, (char *)&tpgrp) == 0 && 399*7c478bd9Sstevel@tonic-gate tpgrp != -1) { 400*7c478bd9Sstevel@tonic-gate if (tpgrp != shpgrp) { 401*7c478bd9Sstevel@tonic-gate void (*old)() = (void (*)())signal(SIGTTIN, SIG_DFL); 402*7c478bd9Sstevel@tonic-gate (void) kill(0, SIGTTIN); 403*7c478bd9Sstevel@tonic-gate (void) signal(SIGTTIN, old); 404*7c478bd9Sstevel@tonic-gate goto retry; 405*7c478bd9Sstevel@tonic-gate } 406*7c478bd9Sstevel@tonic-gate opgrp = shpgrp; 407*7c478bd9Sstevel@tonic-gate shpgrp = getpid(); 408*7c478bd9Sstevel@tonic-gate tpgrp = shpgrp; 409*7c478bd9Sstevel@tonic-gate (void) setpgid(0, shpgrp); 410*7c478bd9Sstevel@tonic-gate (void) ioctl(f, TIOCSPGRP, (char *)&shpgrp); 411*7c478bd9Sstevel@tonic-gate (void) fcntl(dcopy(f, FSHTTY), F_SETFD, 1); 412*7c478bd9Sstevel@tonic-gate } else { 413*7c478bd9Sstevel@tonic-gate notty: 414*7c478bd9Sstevel@tonic-gate printf("Warning: no access to tty; thus no job control in this shell...\n"); 415*7c478bd9Sstevel@tonic-gate tpgrp = -1; 416*7c478bd9Sstevel@tonic-gate } 417*7c478bd9Sstevel@tonic-gate } 418*7c478bd9Sstevel@tonic-gate } 419*7c478bd9Sstevel@tonic-gate if (setintr == 0 && parintr == SIG_DFL) 420*7c478bd9Sstevel@tonic-gate setintr++; 421*7c478bd9Sstevel@tonic-gate 422*7c478bd9Sstevel@tonic-gate /* 423*7c478bd9Sstevel@tonic-gate * Set SIGCHLD handler, making sure that reads restart after it runs. 424*7c478bd9Sstevel@tonic-gate */ 425*7c478bd9Sstevel@tonic-gate sigemptyset(&sa.sa_mask); 426*7c478bd9Sstevel@tonic-gate sa.sa_handler = pchild; 427*7c478bd9Sstevel@tonic-gate sa.sa_flags = SA_RESTART; 428*7c478bd9Sstevel@tonic-gate (void) sigaction(SIGCHLD, &sa, (struct sigaction *) NULL); 429*7c478bd9Sstevel@tonic-gate 430*7c478bd9Sstevel@tonic-gate /* 431*7c478bd9Sstevel@tonic-gate * Set an exit here in case of an interrupt or error reading 432*7c478bd9Sstevel@tonic-gate * the shell start-up scripts. 433*7c478bd9Sstevel@tonic-gate */ 434*7c478bd9Sstevel@tonic-gate setexit(); 435*7c478bd9Sstevel@tonic-gate haderr = 0; /* In case second time through */ 436*7c478bd9Sstevel@tonic-gate if (!fast && reenter == 0) { 437*7c478bd9Sstevel@tonic-gate reenter++; 438*7c478bd9Sstevel@tonic-gate 439*7c478bd9Sstevel@tonic-gate /* 440*7c478bd9Sstevel@tonic-gate * If this is a login csh, and /etc/.login exists, 441*7c478bd9Sstevel@tonic-gate * source /etc/.login first. 442*7c478bd9Sstevel@tonic-gate */ 443*7c478bd9Sstevel@tonic-gate if (loginsh) { 444*7c478bd9Sstevel@tonic-gate tchar tmp_etc[4+1]; /*strlen("/etc")+1 */ 445*7c478bd9Sstevel@tonic-gate tchar tmp_login[7+1]; /*strlen("/.login")+1*/ 446*7c478bd9Sstevel@tonic-gate 447*7c478bd9Sstevel@tonic-gate strtots(tmp_etc, "/etc"); 448*7c478bd9Sstevel@tonic-gate strtots(tmp_login, "/.login"); 449*7c478bd9Sstevel@tonic-gate srccat_inlogin(tmp_etc, tmp_login); 450*7c478bd9Sstevel@tonic-gate } 451*7c478bd9Sstevel@tonic-gate 452*7c478bd9Sstevel@tonic-gate /* Will have value("home") here because set fast if don't */ 453*7c478bd9Sstevel@tonic-gate srccat(value(S_home/*"home"*/), S_SLADOTcshrc/*"/.cshrc"*/); 454*7c478bd9Sstevel@tonic-gate 455*7c478bd9Sstevel@tonic-gate /*Hash path*/ 456*7c478bd9Sstevel@tonic-gate if (!fast && !arginp && !onelflg && !havhash) 457*7c478bd9Sstevel@tonic-gate dohash(xhash); 458*7c478bd9Sstevel@tonic-gate 459*7c478bd9Sstevel@tonic-gate 460*7c478bd9Sstevel@tonic-gate /* 461*7c478bd9Sstevel@tonic-gate * Reconstruct the history list now, so that it's 462*7c478bd9Sstevel@tonic-gate * available from within .login. 463*7c478bd9Sstevel@tonic-gate */ 464*7c478bd9Sstevel@tonic-gate dosource(loadhist); 465*7c478bd9Sstevel@tonic-gate if (loginsh) { 466*7c478bd9Sstevel@tonic-gate srccat_inlogin(value(S_home/*"home"*/), S_SLADOTlogin/*"/.login"*/); 467*7c478bd9Sstevel@tonic-gate } 468*7c478bd9Sstevel@tonic-gate 469*7c478bd9Sstevel@tonic-gate /* 470*7c478bd9Sstevel@tonic-gate * To get cdpath hashing $cdpath must have a 471*7c478bd9Sstevel@tonic-gate * value, not $CDPATH. So if after reading 472*7c478bd9Sstevel@tonic-gate * the startup files ( .cshrc ), and 473*7c478bd9Sstevel@tonic-gate * user has specified a value for cdpath, then 474*7c478bd9Sstevel@tonic-gate * cache $cdpath paths. xhash2 is global array 475*7c478bd9Sstevel@tonic-gate * for $cdpath caching. 476*7c478bd9Sstevel@tonic-gate */ 477*7c478bd9Sstevel@tonic-gate if (!fast && !arginp && !onelflg && !havhash2 ) 478*7c478bd9Sstevel@tonic-gate dohash(xhash2); 479*7c478bd9Sstevel@tonic-gate } 480*7c478bd9Sstevel@tonic-gate 481*7c478bd9Sstevel@tonic-gate /* 482*7c478bd9Sstevel@tonic-gate * Now are ready for the -v and -x flags 483*7c478bd9Sstevel@tonic-gate */ 484*7c478bd9Sstevel@tonic-gate if (nverbose) 485*7c478bd9Sstevel@tonic-gate setNS(S_verbose/*"verbose"*/); 486*7c478bd9Sstevel@tonic-gate if (nexececho) 487*7c478bd9Sstevel@tonic-gate setNS(S_echo/*"echo"*/); 488*7c478bd9Sstevel@tonic-gate 489*7c478bd9Sstevel@tonic-gate /* 490*7c478bd9Sstevel@tonic-gate * All the rest of the world is inside this call. 491*7c478bd9Sstevel@tonic-gate * The argument to process indicates whether it should 492*7c478bd9Sstevel@tonic-gate * catch "error unwinds". Thus if we are a interactive shell 493*7c478bd9Sstevel@tonic-gate * our call here will never return by being blown past on an error. 494*7c478bd9Sstevel@tonic-gate */ 495*7c478bd9Sstevel@tonic-gate process(setintr); 496*7c478bd9Sstevel@tonic-gate 497*7c478bd9Sstevel@tonic-gate /* 498*7c478bd9Sstevel@tonic-gate * Mop-up. 499*7c478bd9Sstevel@tonic-gate */ 500*7c478bd9Sstevel@tonic-gate if (loginsh) { 501*7c478bd9Sstevel@tonic-gate printf("logout\n"); 502*7c478bd9Sstevel@tonic-gate (void) close(SHIN); /* No need for unsetfd(). */ 503*7c478bd9Sstevel@tonic-gate child++; 504*7c478bd9Sstevel@tonic-gate goodbye(); 505*7c478bd9Sstevel@tonic-gate } 506*7c478bd9Sstevel@tonic-gate rechist(); 507*7c478bd9Sstevel@tonic-gate exitstat(); 508*7c478bd9Sstevel@tonic-gate } 509*7c478bd9Sstevel@tonic-gate 510*7c478bd9Sstevel@tonic-gate untty() 511*7c478bd9Sstevel@tonic-gate { 512*7c478bd9Sstevel@tonic-gate 513*7c478bd9Sstevel@tonic-gate if (tpgrp > 0) { 514*7c478bd9Sstevel@tonic-gate (void) setpgid(0, opgrp); 515*7c478bd9Sstevel@tonic-gate (void) ioctl(FSHTTY, TIOCSPGRP, (char *)&opgrp); 516*7c478bd9Sstevel@tonic-gate } 517*7c478bd9Sstevel@tonic-gate } 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate importpath(cp) 520*7c478bd9Sstevel@tonic-gate tchar *cp; 521*7c478bd9Sstevel@tonic-gate { 522*7c478bd9Sstevel@tonic-gate register int i = 0; 523*7c478bd9Sstevel@tonic-gate register tchar *dp; 524*7c478bd9Sstevel@tonic-gate register tchar **pv; 525*7c478bd9Sstevel@tonic-gate int c; 526*7c478bd9Sstevel@tonic-gate static tchar dot[2] = {'.', 0}; 527*7c478bd9Sstevel@tonic-gate 528*7c478bd9Sstevel@tonic-gate for (dp = cp; *dp; dp++) 529*7c478bd9Sstevel@tonic-gate if (*dp == ':') 530*7c478bd9Sstevel@tonic-gate i++; 531*7c478bd9Sstevel@tonic-gate /* 532*7c478bd9Sstevel@tonic-gate * i+2 where i is the number of colons in the path. 533*7c478bd9Sstevel@tonic-gate * There are i+1 directories in the path plus we need 534*7c478bd9Sstevel@tonic-gate * room for a zero terminator. 535*7c478bd9Sstevel@tonic-gate */ 536*7c478bd9Sstevel@tonic-gate pv = (tchar **) calloc((unsigned) (i + 2), sizeof (tchar **)); 537*7c478bd9Sstevel@tonic-gate dp = cp; 538*7c478bd9Sstevel@tonic-gate i = 0; 539*7c478bd9Sstevel@tonic-gate if (*dp) 540*7c478bd9Sstevel@tonic-gate for (;;) { 541*7c478bd9Sstevel@tonic-gate if ((c = *dp) == ':' || c == 0) { 542*7c478bd9Sstevel@tonic-gate *dp = 0; 543*7c478bd9Sstevel@tonic-gate pv[i++] = savestr(*cp ? cp : dot); 544*7c478bd9Sstevel@tonic-gate if (c) { 545*7c478bd9Sstevel@tonic-gate cp = dp + 1; 546*7c478bd9Sstevel@tonic-gate *dp = ':'; 547*7c478bd9Sstevel@tonic-gate } else 548*7c478bd9Sstevel@tonic-gate break; 549*7c478bd9Sstevel@tonic-gate } 550*7c478bd9Sstevel@tonic-gate dp++; 551*7c478bd9Sstevel@tonic-gate } 552*7c478bd9Sstevel@tonic-gate pv[i] = 0; 553*7c478bd9Sstevel@tonic-gate set1(S_path /*"path"*/, pv, &shvhed); 554*7c478bd9Sstevel@tonic-gate } 555*7c478bd9Sstevel@tonic-gate 556*7c478bd9Sstevel@tonic-gate /* 557*7c478bd9Sstevel@tonic-gate * Source to the file which is the catenation of the argument names. 558*7c478bd9Sstevel@tonic-gate */ 559*7c478bd9Sstevel@tonic-gate srccat(cp, dp) 560*7c478bd9Sstevel@tonic-gate tchar *cp, *dp; 561*7c478bd9Sstevel@tonic-gate { 562*7c478bd9Sstevel@tonic-gate register tchar *ep = strspl(cp, dp); 563*7c478bd9Sstevel@tonic-gate register int unit = dmove(open_(ep, 0), -1); 564*7c478bd9Sstevel@tonic-gate 565*7c478bd9Sstevel@tonic-gate (void) fcntl(unit, F_SETFD, 1); 566*7c478bd9Sstevel@tonic-gate xfree(ep); 567*7c478bd9Sstevel@tonic-gate #ifdef INGRES 568*7c478bd9Sstevel@tonic-gate srcunit(unit, 0, 0); 569*7c478bd9Sstevel@tonic-gate #else 570*7c478bd9Sstevel@tonic-gate srcunit(unit, 1, 0); 571*7c478bd9Sstevel@tonic-gate #endif 572*7c478bd9Sstevel@tonic-gate } 573*7c478bd9Sstevel@tonic-gate 574*7c478bd9Sstevel@tonic-gate /* 575*7c478bd9Sstevel@tonic-gate * Source to the file which is the catenation of the argument names. 576*7c478bd9Sstevel@tonic-gate * This one does not check the ownership. 577*7c478bd9Sstevel@tonic-gate */ 578*7c478bd9Sstevel@tonic-gate srccat_inlogin(cp, dp) 579*7c478bd9Sstevel@tonic-gate tchar *cp, *dp; 580*7c478bd9Sstevel@tonic-gate { 581*7c478bd9Sstevel@tonic-gate register tchar *ep = strspl(cp, dp); 582*7c478bd9Sstevel@tonic-gate register int unit = dmove(open_(ep, 0), -1); 583*7c478bd9Sstevel@tonic-gate 584*7c478bd9Sstevel@tonic-gate (void) fcntl(unit, F_SETFD, 1); 585*7c478bd9Sstevel@tonic-gate xfree(ep); 586*7c478bd9Sstevel@tonic-gate srcunit(unit, 0, 0); 587*7c478bd9Sstevel@tonic-gate } 588*7c478bd9Sstevel@tonic-gate 589*7c478bd9Sstevel@tonic-gate /* 590*7c478bd9Sstevel@tonic-gate * Source to a unit. If onlyown it must be our file or our group or 591*7c478bd9Sstevel@tonic-gate * we don't chance it. This occurs on ".cshrc"s and the like. 592*7c478bd9Sstevel@tonic-gate */ 593*7c478bd9Sstevel@tonic-gate srcunit(unit, onlyown, hflg) 594*7c478bd9Sstevel@tonic-gate register int unit; 595*7c478bd9Sstevel@tonic-gate bool onlyown; 596*7c478bd9Sstevel@tonic-gate bool hflg; 597*7c478bd9Sstevel@tonic-gate { 598*7c478bd9Sstevel@tonic-gate /* We have to push down a lot of state here */ 599*7c478bd9Sstevel@tonic-gate /* All this could go into a structure */ 600*7c478bd9Sstevel@tonic-gate int oSHIN = -1, oldintty = intty; 601*7c478bd9Sstevel@tonic-gate struct whyle *oldwhyl = whyles; 602*7c478bd9Sstevel@tonic-gate tchar *ogointr = gointr, *oarginp = arginp; 603*7c478bd9Sstevel@tonic-gate tchar *oevalp = evalp, **oevalvec = evalvec; 604*7c478bd9Sstevel@tonic-gate int oonelflg = onelflg; 605*7c478bd9Sstevel@tonic-gate bool oenterhist = enterhist; 606*7c478bd9Sstevel@tonic-gate tchar OHIST = HIST; 607*7c478bd9Sstevel@tonic-gate #ifdef TELL 608*7c478bd9Sstevel@tonic-gate bool otell = cantell; 609*7c478bd9Sstevel@tonic-gate #endif 610*7c478bd9Sstevel@tonic-gate struct Bin saveB; 611*7c478bd9Sstevel@tonic-gate 612*7c478bd9Sstevel@tonic-gate /* The (few) real local variables */ 613*7c478bd9Sstevel@tonic-gate jmp_buf oldexit; 614*7c478bd9Sstevel@tonic-gate int reenter, omask; 615*7c478bd9Sstevel@tonic-gate 616*7c478bd9Sstevel@tonic-gate if (unit < 0) 617*7c478bd9Sstevel@tonic-gate return; 618*7c478bd9Sstevel@tonic-gate if (didfds) 619*7c478bd9Sstevel@tonic-gate donefds(); 620*7c478bd9Sstevel@tonic-gate if (onlyown) { 621*7c478bd9Sstevel@tonic-gate struct stat stb; 622*7c478bd9Sstevel@tonic-gate 623*7c478bd9Sstevel@tonic-gate if (fstat(unit, &stb) < 0 || 624*7c478bd9Sstevel@tonic-gate (stb.st_uid != uid && stb.st_gid != getgid())) { 625*7c478bd9Sstevel@tonic-gate (void) close(unit); 626*7c478bd9Sstevel@tonic-gate unsetfd(unit); 627*7c478bd9Sstevel@tonic-gate return; 628*7c478bd9Sstevel@tonic-gate } 629*7c478bd9Sstevel@tonic-gate } 630*7c478bd9Sstevel@tonic-gate 631*7c478bd9Sstevel@tonic-gate /* 632*7c478bd9Sstevel@tonic-gate * There is a critical section here while we are pushing down the 633*7c478bd9Sstevel@tonic-gate * input stream since we have stuff in different structures. 634*7c478bd9Sstevel@tonic-gate * If we weren't careful an interrupt could corrupt SHIN's Bin 635*7c478bd9Sstevel@tonic-gate * structure and kill the shell. 636*7c478bd9Sstevel@tonic-gate * 637*7c478bd9Sstevel@tonic-gate * We could avoid the critical region by grouping all the stuff 638*7c478bd9Sstevel@tonic-gate * in a single structure and pointing at it to move it all at 639*7c478bd9Sstevel@tonic-gate * once. This is less efficient globally on many variable references 640*7c478bd9Sstevel@tonic-gate * however. 641*7c478bd9Sstevel@tonic-gate */ 642*7c478bd9Sstevel@tonic-gate getexit(oldexit); 643*7c478bd9Sstevel@tonic-gate reenter = 0; 644*7c478bd9Sstevel@tonic-gate if (setintr) 645*7c478bd9Sstevel@tonic-gate omask = sigblock(sigmask(SIGINT)); 646*7c478bd9Sstevel@tonic-gate setexit(); 647*7c478bd9Sstevel@tonic-gate reenter++; 648*7c478bd9Sstevel@tonic-gate if (reenter == 1) { 649*7c478bd9Sstevel@tonic-gate /* Setup the new values of the state stuff saved above */ 650*7c478bd9Sstevel@tonic-gate copy( (char *)&saveB, (char *)&B, sizeof saveB); 651*7c478bd9Sstevel@tonic-gate fbuf = (tchar **) 0; 652*7c478bd9Sstevel@tonic-gate fseekp = feobp = fblocks = 0; 653*7c478bd9Sstevel@tonic-gate oSHIN = SHIN, SHIN = unit, arginp = 0, onelflg = 0; 654*7c478bd9Sstevel@tonic-gate intty = isatty(SHIN), whyles = 0, gointr = 0; 655*7c478bd9Sstevel@tonic-gate evalvec = 0; evalp = 0; 656*7c478bd9Sstevel@tonic-gate enterhist = hflg; 657*7c478bd9Sstevel@tonic-gate if (enterhist) 658*7c478bd9Sstevel@tonic-gate HIST = '\0'; 659*7c478bd9Sstevel@tonic-gate /* 660*7c478bd9Sstevel@tonic-gate * Now if we are allowing commands to be interrupted, 661*7c478bd9Sstevel@tonic-gate * we let ourselves be interrupted. 662*7c478bd9Sstevel@tonic-gate */ 663*7c478bd9Sstevel@tonic-gate if (setintr) 664*7c478bd9Sstevel@tonic-gate (void) sigsetmask(omask); 665*7c478bd9Sstevel@tonic-gate #ifdef TELL 666*7c478bd9Sstevel@tonic-gate settell(); 667*7c478bd9Sstevel@tonic-gate #endif 668*7c478bd9Sstevel@tonic-gate process(0); /* 0 -> blow away on errors */ 669*7c478bd9Sstevel@tonic-gate } 670*7c478bd9Sstevel@tonic-gate if (setintr) 671*7c478bd9Sstevel@tonic-gate (void) sigsetmask(omask); 672*7c478bd9Sstevel@tonic-gate if (oSHIN >= 0) { 673*7c478bd9Sstevel@tonic-gate register int i; 674*7c478bd9Sstevel@tonic-gate 675*7c478bd9Sstevel@tonic-gate /* We made it to the new state... free up its storage */ 676*7c478bd9Sstevel@tonic-gate /* This code could get run twice but xfree doesn't care */ 677*7c478bd9Sstevel@tonic-gate for (i = 0; i < fblocks; i++) 678*7c478bd9Sstevel@tonic-gate xfree(fbuf[i]); 679*7c478bd9Sstevel@tonic-gate xfree( (char *)fbuf); 680*7c478bd9Sstevel@tonic-gate 681*7c478bd9Sstevel@tonic-gate /* Reset input arena */ 682*7c478bd9Sstevel@tonic-gate copy( (char *)&B, (char *)&saveB, sizeof B); 683*7c478bd9Sstevel@tonic-gate 684*7c478bd9Sstevel@tonic-gate (void) close(SHIN), SHIN = oSHIN; 685*7c478bd9Sstevel@tonic-gate unsetfd(SHIN); 686*7c478bd9Sstevel@tonic-gate arginp = oarginp, onelflg = oonelflg; 687*7c478bd9Sstevel@tonic-gate evalp = oevalp, evalvec = oevalvec; 688*7c478bd9Sstevel@tonic-gate intty = oldintty, whyles = oldwhyl, gointr = ogointr; 689*7c478bd9Sstevel@tonic-gate if (enterhist) 690*7c478bd9Sstevel@tonic-gate HIST = OHIST; 691*7c478bd9Sstevel@tonic-gate enterhist = oenterhist; 692*7c478bd9Sstevel@tonic-gate #ifdef TELL 693*7c478bd9Sstevel@tonic-gate cantell = otell; 694*7c478bd9Sstevel@tonic-gate #endif 695*7c478bd9Sstevel@tonic-gate } 696*7c478bd9Sstevel@tonic-gate 697*7c478bd9Sstevel@tonic-gate resexit(oldexit); 698*7c478bd9Sstevel@tonic-gate /* 699*7c478bd9Sstevel@tonic-gate * If process reset() (effectively an unwind) then 700*7c478bd9Sstevel@tonic-gate * we must also unwind. 701*7c478bd9Sstevel@tonic-gate */ 702*7c478bd9Sstevel@tonic-gate if (reenter >= 2) 703*7c478bd9Sstevel@tonic-gate error(NULL); 704*7c478bd9Sstevel@tonic-gate } 705*7c478bd9Sstevel@tonic-gate 706*7c478bd9Sstevel@tonic-gate rechist() 707*7c478bd9Sstevel@tonic-gate { 708*7c478bd9Sstevel@tonic-gate tchar buf[BUFSIZ]; 709*7c478bd9Sstevel@tonic-gate int fp, ftmp, oldidfds; 710*7c478bd9Sstevel@tonic-gate 711*7c478bd9Sstevel@tonic-gate if (!fast) { 712*7c478bd9Sstevel@tonic-gate if (value(S_savehist/*"savehist"*/)[0] == '\0') 713*7c478bd9Sstevel@tonic-gate return; 714*7c478bd9Sstevel@tonic-gate (void) strcpy_(buf, value(S_home/*"home"*/)); 715*7c478bd9Sstevel@tonic-gate (void) strcat_(buf, S_SLADOThistory/*"/.history"*/); 716*7c478bd9Sstevel@tonic-gate fp = creat_(buf, 0666); 717*7c478bd9Sstevel@tonic-gate if (fp == -1) 718*7c478bd9Sstevel@tonic-gate return; 719*7c478bd9Sstevel@tonic-gate oldidfds = didfds; 720*7c478bd9Sstevel@tonic-gate didfds = 0; 721*7c478bd9Sstevel@tonic-gate ftmp = SHOUT; 722*7c478bd9Sstevel@tonic-gate SHOUT = fp; 723*7c478bd9Sstevel@tonic-gate (void) strcpy_(buf, value(S_savehist/*"savehist"*/)); 724*7c478bd9Sstevel@tonic-gate dumphist[2] = buf; 725*7c478bd9Sstevel@tonic-gate dohist(dumphist); 726*7c478bd9Sstevel@tonic-gate (void) close(fp); 727*7c478bd9Sstevel@tonic-gate unsetfd(fp); 728*7c478bd9Sstevel@tonic-gate SHOUT = ftmp; 729*7c478bd9Sstevel@tonic-gate didfds = oldidfds; 730*7c478bd9Sstevel@tonic-gate } 731*7c478bd9Sstevel@tonic-gate } 732*7c478bd9Sstevel@tonic-gate 733*7c478bd9Sstevel@tonic-gate goodbye() 734*7c478bd9Sstevel@tonic-gate { 735*7c478bd9Sstevel@tonic-gate if (loginsh) { 736*7c478bd9Sstevel@tonic-gate (void) signal(SIGQUIT, SIG_IGN); 737*7c478bd9Sstevel@tonic-gate (void) signal(SIGINT, SIG_IGN); 738*7c478bd9Sstevel@tonic-gate (void) signal(SIGTERM, SIG_IGN); 739*7c478bd9Sstevel@tonic-gate setintr = 0; /* No interrupts after "logout" */ 740*7c478bd9Sstevel@tonic-gate if (adrof(S_home/*"home"*/)) 741*7c478bd9Sstevel@tonic-gate srccat(value(S_home/*"home"*/), S_SLADOTlogout/*"/.logout"*/); 742*7c478bd9Sstevel@tonic-gate } 743*7c478bd9Sstevel@tonic-gate rechist(); 744*7c478bd9Sstevel@tonic-gate exitstat(); 745*7c478bd9Sstevel@tonic-gate } 746*7c478bd9Sstevel@tonic-gate 747*7c478bd9Sstevel@tonic-gate exitstat() 748*7c478bd9Sstevel@tonic-gate { 749*7c478bd9Sstevel@tonic-gate 750*7c478bd9Sstevel@tonic-gate #ifdef PROF 751*7c478bd9Sstevel@tonic-gate monitor(0); 752*7c478bd9Sstevel@tonic-gate #endif 753*7c478bd9Sstevel@tonic-gate /* 754*7c478bd9Sstevel@tonic-gate * Note that if STATUS is corrupted (i.e. getn bombs) 755*7c478bd9Sstevel@tonic-gate * then error will exit directly because we poke child here. 756*7c478bd9Sstevel@tonic-gate * Otherwise we might continue unwarrantedly (sic). 757*7c478bd9Sstevel@tonic-gate */ 758*7c478bd9Sstevel@tonic-gate child++; 759*7c478bd9Sstevel@tonic-gate untty(); 760*7c478bd9Sstevel@tonic-gate exit(getn(value(S_status/*"status"*/))); 761*7c478bd9Sstevel@tonic-gate } 762*7c478bd9Sstevel@tonic-gate 763*7c478bd9Sstevel@tonic-gate /* 764*7c478bd9Sstevel@tonic-gate * in the event of a HUP we want to save the history 765*7c478bd9Sstevel@tonic-gate */ 766*7c478bd9Sstevel@tonic-gate void 767*7c478bd9Sstevel@tonic-gate phup() 768*7c478bd9Sstevel@tonic-gate { 769*7c478bd9Sstevel@tonic-gate rechist(); 770*7c478bd9Sstevel@tonic-gate exit(1); 771*7c478bd9Sstevel@tonic-gate } 772*7c478bd9Sstevel@tonic-gate 773*7c478bd9Sstevel@tonic-gate tchar *jobargv[2] = { S_jobs/*"jobs"*/, 0 }; 774*7c478bd9Sstevel@tonic-gate /* 775*7c478bd9Sstevel@tonic-gate * Catch an interrupt, e.g. during lexical input. 776*7c478bd9Sstevel@tonic-gate * If we are an interactive shell, we reset the interrupt catch 777*7c478bd9Sstevel@tonic-gate * immediately. In any case we drain the shell output, 778*7c478bd9Sstevel@tonic-gate * and finally go through the normal error mechanism, which 779*7c478bd9Sstevel@tonic-gate * gets a chance to make the shell go away. 780*7c478bd9Sstevel@tonic-gate */ 781*7c478bd9Sstevel@tonic-gate void 782*7c478bd9Sstevel@tonic-gate pintr() 783*7c478bd9Sstevel@tonic-gate { 784*7c478bd9Sstevel@tonic-gate pintr1(1); 785*7c478bd9Sstevel@tonic-gate } 786*7c478bd9Sstevel@tonic-gate 787*7c478bd9Sstevel@tonic-gate pintr1(wantnl) 788*7c478bd9Sstevel@tonic-gate bool wantnl; 789*7c478bd9Sstevel@tonic-gate { 790*7c478bd9Sstevel@tonic-gate register tchar **v; 791*7c478bd9Sstevel@tonic-gate int omask; 792*7c478bd9Sstevel@tonic-gate 793*7c478bd9Sstevel@tonic-gate omask = sigblock(0); 794*7c478bd9Sstevel@tonic-gate if (setintr) { 795*7c478bd9Sstevel@tonic-gate (void) sigsetmask(omask & ~sigmask(SIGINT)); 796*7c478bd9Sstevel@tonic-gate if (pjobs) { 797*7c478bd9Sstevel@tonic-gate pjobs = 0; 798*7c478bd9Sstevel@tonic-gate printf("\n"); 799*7c478bd9Sstevel@tonic-gate dojobs(jobargv); 800*7c478bd9Sstevel@tonic-gate bferr("Interrupted"); 801*7c478bd9Sstevel@tonic-gate } 802*7c478bd9Sstevel@tonic-gate } 803*7c478bd9Sstevel@tonic-gate (void) sigsetmask(omask & ~sigmask(SIGCHLD)); 804*7c478bd9Sstevel@tonic-gate draino(); 805*7c478bd9Sstevel@tonic-gate 806*7c478bd9Sstevel@tonic-gate /* 807*7c478bd9Sstevel@tonic-gate * If we have an active "onintr" then we search for the label. 808*7c478bd9Sstevel@tonic-gate * Note that if one does "onintr -" then we shan't be interruptible 809*7c478bd9Sstevel@tonic-gate * so we needn't worry about that here. 810*7c478bd9Sstevel@tonic-gate */ 811*7c478bd9Sstevel@tonic-gate if (gointr) { 812*7c478bd9Sstevel@tonic-gate search(ZGOTO, 0, gointr); 813*7c478bd9Sstevel@tonic-gate timflg = 0; 814*7c478bd9Sstevel@tonic-gate if (v = pargv) 815*7c478bd9Sstevel@tonic-gate pargv = 0, blkfree(v); 816*7c478bd9Sstevel@tonic-gate if (v = gargv) 817*7c478bd9Sstevel@tonic-gate gargv = 0, blkfree(v); 818*7c478bd9Sstevel@tonic-gate reset(); 819*7c478bd9Sstevel@tonic-gate } else if (intty && wantnl) 820*7c478bd9Sstevel@tonic-gate printf("\n"); /* Some like this, others don't */ 821*7c478bd9Sstevel@tonic-gate error(NULL); 822*7c478bd9Sstevel@tonic-gate } 823*7c478bd9Sstevel@tonic-gate 824*7c478bd9Sstevel@tonic-gate /* 825*7c478bd9Sstevel@tonic-gate * Process is the main driving routine for the shell. 826*7c478bd9Sstevel@tonic-gate * It runs all command processing, except for those within { ... } 827*7c478bd9Sstevel@tonic-gate * in expressions (which is run by a routine evalav in sh.exp.c which 828*7c478bd9Sstevel@tonic-gate * is a stripped down process), and `...` evaluation which is run 829*7c478bd9Sstevel@tonic-gate * also by a subset of this code in sh.glob.c in the routine backeval. 830*7c478bd9Sstevel@tonic-gate * 831*7c478bd9Sstevel@tonic-gate * The code here is a little strange because part of it is interruptible 832*7c478bd9Sstevel@tonic-gate * and hence freeing of structures appears to occur when none is necessary 833*7c478bd9Sstevel@tonic-gate * if this is ignored. 834*7c478bd9Sstevel@tonic-gate * 835*7c478bd9Sstevel@tonic-gate * Note that if catch is not set then we will unwind on any error. 836*7c478bd9Sstevel@tonic-gate * If an end-of-file occurs, we return. 837*7c478bd9Sstevel@tonic-gate */ 838*7c478bd9Sstevel@tonic-gate process(catch) 839*7c478bd9Sstevel@tonic-gate bool catch; 840*7c478bd9Sstevel@tonic-gate { 841*7c478bd9Sstevel@tonic-gate jmp_buf osetexit; 842*7c478bd9Sstevel@tonic-gate register struct command *t; 843*7c478bd9Sstevel@tonic-gate 844*7c478bd9Sstevel@tonic-gate getexit(osetexit); 845*7c478bd9Sstevel@tonic-gate for (;;) { 846*7c478bd9Sstevel@tonic-gate pendjob(); 847*7c478bd9Sstevel@tonic-gate paraml.next = paraml.prev = ¶ml; 848*7c478bd9Sstevel@tonic-gate paraml.word = S_ /*""*/; 849*7c478bd9Sstevel@tonic-gate t = 0; 850*7c478bd9Sstevel@tonic-gate setexit(); 851*7c478bd9Sstevel@tonic-gate justpr = enterhist; /* execute if not entering history */ 852*7c478bd9Sstevel@tonic-gate 853*7c478bd9Sstevel@tonic-gate /* 854*7c478bd9Sstevel@tonic-gate * Interruptible during interactive reads 855*7c478bd9Sstevel@tonic-gate */ 856*7c478bd9Sstevel@tonic-gate if (setintr) 857*7c478bd9Sstevel@tonic-gate (void) sigsetmask(sigblock(0) & ~sigmask(SIGINT)); 858*7c478bd9Sstevel@tonic-gate 859*7c478bd9Sstevel@tonic-gate /* 860*7c478bd9Sstevel@tonic-gate * For the sake of reset() 861*7c478bd9Sstevel@tonic-gate */ 862*7c478bd9Sstevel@tonic-gate freelex(¶ml), freesyn(t), t = 0; 863*7c478bd9Sstevel@tonic-gate 864*7c478bd9Sstevel@tonic-gate if (haderr) { 865*7c478bd9Sstevel@tonic-gate if (!catch) { 866*7c478bd9Sstevel@tonic-gate /* unwind */ 867*7c478bd9Sstevel@tonic-gate doneinp = 0; 868*7c478bd9Sstevel@tonic-gate resexit(osetexit); 869*7c478bd9Sstevel@tonic-gate reset(); 870*7c478bd9Sstevel@tonic-gate } 871*7c478bd9Sstevel@tonic-gate haderr = 0; 872*7c478bd9Sstevel@tonic-gate /* 873*7c478bd9Sstevel@tonic-gate * Every error is eventually caught here or 874*7c478bd9Sstevel@tonic-gate * the shell dies. It is at this 875*7c478bd9Sstevel@tonic-gate * point that we clean up any left-over open 876*7c478bd9Sstevel@tonic-gate * files, by closing all but a fixed number 877*7c478bd9Sstevel@tonic-gate * of pre-defined files. Thus routines don't 878*7c478bd9Sstevel@tonic-gate * have to worry about leaving files open due 879*7c478bd9Sstevel@tonic-gate * to deeper errors... they will get closed here. 880*7c478bd9Sstevel@tonic-gate */ 881*7c478bd9Sstevel@tonic-gate closem(); 882*7c478bd9Sstevel@tonic-gate continue; 883*7c478bd9Sstevel@tonic-gate } 884*7c478bd9Sstevel@tonic-gate if (doneinp) { 885*7c478bd9Sstevel@tonic-gate doneinp = 0; 886*7c478bd9Sstevel@tonic-gate break; 887*7c478bd9Sstevel@tonic-gate } 888*7c478bd9Sstevel@tonic-gate if (chkstop) 889*7c478bd9Sstevel@tonic-gate chkstop--; 890*7c478bd9Sstevel@tonic-gate if (neednote) 891*7c478bd9Sstevel@tonic-gate pnote(); 892*7c478bd9Sstevel@tonic-gate if (intty && prompt && evalvec == 0) { 893*7c478bd9Sstevel@tonic-gate mailchk(); 894*7c478bd9Sstevel@tonic-gate /* 895*7c478bd9Sstevel@tonic-gate * If we are at the end of the input buffer 896*7c478bd9Sstevel@tonic-gate * then we are going to read fresh stuff. 897*7c478bd9Sstevel@tonic-gate * Otherwise, we are rereading input and don't 898*7c478bd9Sstevel@tonic-gate * need or want to prompt. 899*7c478bd9Sstevel@tonic-gate */ 900*7c478bd9Sstevel@tonic-gate if (fseekp == feobp) 901*7c478bd9Sstevel@tonic-gate printprompt(); 902*7c478bd9Sstevel@tonic-gate } 903*7c478bd9Sstevel@tonic-gate err = 0; 904*7c478bd9Sstevel@tonic-gate 905*7c478bd9Sstevel@tonic-gate /* 906*7c478bd9Sstevel@tonic-gate * Echo not only on VERBOSE, but also with history expansion. 907*7c478bd9Sstevel@tonic-gate */ 908*7c478bd9Sstevel@tonic-gate if (lex(¶ml) && intty || 909*7c478bd9Sstevel@tonic-gate adrof(S_verbose /*"verbose"*/)) { 910*7c478bd9Sstevel@tonic-gate haderr = 1; 911*7c478bd9Sstevel@tonic-gate prlex(¶ml); 912*7c478bd9Sstevel@tonic-gate haderr = 0; 913*7c478bd9Sstevel@tonic-gate } 914*7c478bd9Sstevel@tonic-gate 915*7c478bd9Sstevel@tonic-gate /* 916*7c478bd9Sstevel@tonic-gate * The parser may lose space if interrupted. 917*7c478bd9Sstevel@tonic-gate */ 918*7c478bd9Sstevel@tonic-gate if (setintr) 919*7c478bd9Sstevel@tonic-gate (void) sigblock(sigmask(SIGINT)); 920*7c478bd9Sstevel@tonic-gate 921*7c478bd9Sstevel@tonic-gate /* 922*7c478bd9Sstevel@tonic-gate * Save input text on the history list if 923*7c478bd9Sstevel@tonic-gate * reading in old history, or it 924*7c478bd9Sstevel@tonic-gate * is from the terminal at the top level and not 925*7c478bd9Sstevel@tonic-gate * in a loop. 926*7c478bd9Sstevel@tonic-gate */ 927*7c478bd9Sstevel@tonic-gate if (enterhist || catch && intty && !whyles) 928*7c478bd9Sstevel@tonic-gate savehist(¶ml); 929*7c478bd9Sstevel@tonic-gate 930*7c478bd9Sstevel@tonic-gate /* 931*7c478bd9Sstevel@tonic-gate * Print lexical error messages, except when sourcing 932*7c478bd9Sstevel@tonic-gate * history lists. 933*7c478bd9Sstevel@tonic-gate */ 934*7c478bd9Sstevel@tonic-gate if (!enterhist && err) 935*7c478bd9Sstevel@tonic-gate error("%s", gettext(err)); 936*7c478bd9Sstevel@tonic-gate 937*7c478bd9Sstevel@tonic-gate /* 938*7c478bd9Sstevel@tonic-gate * If had a history command :p modifier then 939*7c478bd9Sstevel@tonic-gate * this is as far as we should go 940*7c478bd9Sstevel@tonic-gate */ 941*7c478bd9Sstevel@tonic-gate if (justpr) 942*7c478bd9Sstevel@tonic-gate reset(); 943*7c478bd9Sstevel@tonic-gate 944*7c478bd9Sstevel@tonic-gate alias(¶ml); 945*7c478bd9Sstevel@tonic-gate 946*7c478bd9Sstevel@tonic-gate /* 947*7c478bd9Sstevel@tonic-gate * Parse the words of the input into a parse tree. 948*7c478bd9Sstevel@tonic-gate */ 949*7c478bd9Sstevel@tonic-gate t = syntax(paraml.next, ¶ml, 0); 950*7c478bd9Sstevel@tonic-gate if (err) 951*7c478bd9Sstevel@tonic-gate error("%s", gettext(err)); 952*7c478bd9Sstevel@tonic-gate 953*7c478bd9Sstevel@tonic-gate /* 954*7c478bd9Sstevel@tonic-gate * Execute the parse tree 955*7c478bd9Sstevel@tonic-gate */ 956*7c478bd9Sstevel@tonic-gate { 957*7c478bd9Sstevel@tonic-gate /* 958*7c478bd9Sstevel@tonic-gate * POSIX requires SIGCHLD to be held 959*7c478bd9Sstevel@tonic-gate * until all processes have joined the 960*7c478bd9Sstevel@tonic-gate * process group in order to avoid race 961*7c478bd9Sstevel@tonic-gate * condition. 962*7c478bd9Sstevel@tonic-gate */ 963*7c478bd9Sstevel@tonic-gate int omask; 964*7c478bd9Sstevel@tonic-gate 965*7c478bd9Sstevel@tonic-gate omask = sigblock(sigmask(SIGCHLD)); 966*7c478bd9Sstevel@tonic-gate execute(t, tpgrp); 967*7c478bd9Sstevel@tonic-gate (void)sigsetmask(omask &~ sigmask(SIGCHLD)); 968*7c478bd9Sstevel@tonic-gate } 969*7c478bd9Sstevel@tonic-gate 970*7c478bd9Sstevel@tonic-gate if (err) 971*7c478bd9Sstevel@tonic-gate error("%s", gettext(err)); 972*7c478bd9Sstevel@tonic-gate /* 973*7c478bd9Sstevel@tonic-gate * Made it! 974*7c478bd9Sstevel@tonic-gate */ 975*7c478bd9Sstevel@tonic-gate freelex(¶ml), freesyn(t); 976*7c478bd9Sstevel@tonic-gate } 977*7c478bd9Sstevel@tonic-gate resexit(osetexit); 978*7c478bd9Sstevel@tonic-gate } 979*7c478bd9Sstevel@tonic-gate 980*7c478bd9Sstevel@tonic-gate dosource(t) 981*7c478bd9Sstevel@tonic-gate register tchar **t; 982*7c478bd9Sstevel@tonic-gate { 983*7c478bd9Sstevel@tonic-gate register tchar *f; 984*7c478bd9Sstevel@tonic-gate register int u; 985*7c478bd9Sstevel@tonic-gate bool hflg = 0; 986*7c478bd9Sstevel@tonic-gate tchar buf[BUFSIZ]; 987*7c478bd9Sstevel@tonic-gate 988*7c478bd9Sstevel@tonic-gate t++; 989*7c478bd9Sstevel@tonic-gate if (*t && eq(*t, S_h /*"-h"*/)) { 990*7c478bd9Sstevel@tonic-gate if (*++t == NOSTR) 991*7c478bd9Sstevel@tonic-gate bferr("Too few arguments."); 992*7c478bd9Sstevel@tonic-gate hflg++; 993*7c478bd9Sstevel@tonic-gate } 994*7c478bd9Sstevel@tonic-gate (void) strcpy_(buf, *t); 995*7c478bd9Sstevel@tonic-gate f = globone(buf); 996*7c478bd9Sstevel@tonic-gate u = dmove(open_(f, 0), -1); 997*7c478bd9Sstevel@tonic-gate xfree(f); 998*7c478bd9Sstevel@tonic-gate freelex(¶ml); 999*7c478bd9Sstevel@tonic-gate if (u < 0 && !hflg) 1000*7c478bd9Sstevel@tonic-gate Perror(f); 1001*7c478bd9Sstevel@tonic-gate (void) fcntl(u, F_SETFD, 1); 1002*7c478bd9Sstevel@tonic-gate srcunit(u, 0, hflg); 1003*7c478bd9Sstevel@tonic-gate } 1004*7c478bd9Sstevel@tonic-gate 1005*7c478bd9Sstevel@tonic-gate /* 1006*7c478bd9Sstevel@tonic-gate * Check for mail. 1007*7c478bd9Sstevel@tonic-gate * If we are a login shell, then we don't want to tell 1008*7c478bd9Sstevel@tonic-gate * about any mail file unless its been modified 1009*7c478bd9Sstevel@tonic-gate * after the time we started. 1010*7c478bd9Sstevel@tonic-gate * This prevents us from telling the user things he already 1011*7c478bd9Sstevel@tonic-gate * knows, since the login program insists on saying 1012*7c478bd9Sstevel@tonic-gate * "You have mail." 1013*7c478bd9Sstevel@tonic-gate */ 1014*7c478bd9Sstevel@tonic-gate mailchk() 1015*7c478bd9Sstevel@tonic-gate { 1016*7c478bd9Sstevel@tonic-gate register struct varent *v; 1017*7c478bd9Sstevel@tonic-gate register tchar **vp; 1018*7c478bd9Sstevel@tonic-gate time_t t; 1019*7c478bd9Sstevel@tonic-gate int intvl, cnt; 1020*7c478bd9Sstevel@tonic-gate struct stat stb; 1021*7c478bd9Sstevel@tonic-gate bool new; 1022*7c478bd9Sstevel@tonic-gate 1023*7c478bd9Sstevel@tonic-gate v = adrof(S_mail /*"mail"*/); 1024*7c478bd9Sstevel@tonic-gate if (v == 0) 1025*7c478bd9Sstevel@tonic-gate return; 1026*7c478bd9Sstevel@tonic-gate (void) time(&t); 1027*7c478bd9Sstevel@tonic-gate vp = v->vec; 1028*7c478bd9Sstevel@tonic-gate cnt = blklen(vp); 1029*7c478bd9Sstevel@tonic-gate intvl = (cnt && number(*vp)) ? (--cnt, getn(*vp++)) : MAILINTVL; 1030*7c478bd9Sstevel@tonic-gate if (intvl < 1) 1031*7c478bd9Sstevel@tonic-gate intvl = 1; 1032*7c478bd9Sstevel@tonic-gate if (chktim + intvl > t) 1033*7c478bd9Sstevel@tonic-gate return; 1034*7c478bd9Sstevel@tonic-gate for (; *vp; vp++) { 1035*7c478bd9Sstevel@tonic-gate if (stat_(*vp, &stb) < 0) 1036*7c478bd9Sstevel@tonic-gate continue; 1037*7c478bd9Sstevel@tonic-gate new = stb.st_mtime > time0.tv_sec; 1038*7c478bd9Sstevel@tonic-gate if (stb.st_size == 0 || stb.st_atime >= stb.st_mtime || 1039*7c478bd9Sstevel@tonic-gate (stb.st_atime <= chktim && stb.st_mtime <= chktim) || 1040*7c478bd9Sstevel@tonic-gate loginsh && !new) 1041*7c478bd9Sstevel@tonic-gate continue; 1042*7c478bd9Sstevel@tonic-gate if (cnt == 1) 1043*7c478bd9Sstevel@tonic-gate printf("You have %smail.\n", new ? "new " : ""); 1044*7c478bd9Sstevel@tonic-gate else 1045*7c478bd9Sstevel@tonic-gate printf("%s in %t.\n", new ? "New mail" : "Mail", *vp); 1046*7c478bd9Sstevel@tonic-gate } 1047*7c478bd9Sstevel@tonic-gate chktim = t; 1048*7c478bd9Sstevel@tonic-gate } 1049*7c478bd9Sstevel@tonic-gate 1050*7c478bd9Sstevel@tonic-gate /* 1051*7c478bd9Sstevel@tonic-gate * Extract a home directory from the password file 1052*7c478bd9Sstevel@tonic-gate * The argument points to a buffer where the name of the 1053*7c478bd9Sstevel@tonic-gate * user whose home directory is sought is currently. 1054*7c478bd9Sstevel@tonic-gate * We write the home directory of the user back there. 1055*7c478bd9Sstevel@tonic-gate */ 1056*7c478bd9Sstevel@tonic-gate gethdir(home) 1057*7c478bd9Sstevel@tonic-gate tchar *home; 1058*7c478bd9Sstevel@tonic-gate { 1059*7c478bd9Sstevel@tonic-gate /* getpwname will not be modified, so we need temp. buffer */ 1060*7c478bd9Sstevel@tonic-gate char home_str[BUFSIZ]; 1061*7c478bd9Sstevel@tonic-gate tchar home_ts[BUFSIZ]; 1062*7c478bd9Sstevel@tonic-gate register struct passwd *pp /*= getpwnam(home)*/; 1063*7c478bd9Sstevel@tonic-gate 1064*7c478bd9Sstevel@tonic-gate pp = getpwnam(tstostr(home_str, home)); 1065*7c478bd9Sstevel@tonic-gate if (pp == 0) 1066*7c478bd9Sstevel@tonic-gate return (1); 1067*7c478bd9Sstevel@tonic-gate (void) strcpy_(home, strtots(home_ts, pp->pw_dir)); 1068*7c478bd9Sstevel@tonic-gate return (0); 1069*7c478bd9Sstevel@tonic-gate } 1070*7c478bd9Sstevel@tonic-gate 1071*7c478bd9Sstevel@tonic-gate 1072*7c478bd9Sstevel@tonic-gate /* 1073*7c478bd9Sstevel@tonic-gate #ifdef PROF 1074*7c478bd9Sstevel@tonic-gate done(i) 1075*7c478bd9Sstevel@tonic-gate #else 1076*7c478bd9Sstevel@tonic-gate exit(i) 1077*7c478bd9Sstevel@tonic-gate #endif 1078*7c478bd9Sstevel@tonic-gate int i; 1079*7c478bd9Sstevel@tonic-gate { 1080*7c478bd9Sstevel@tonic-gate 1081*7c478bd9Sstevel@tonic-gate untty(); 1082*7c478bd9Sstevel@tonic-gate _exit(i); 1083*7c478bd9Sstevel@tonic-gate } 1084*7c478bd9Sstevel@tonic-gate */ 1085*7c478bd9Sstevel@tonic-gate 1086*7c478bd9Sstevel@tonic-gate printprompt() 1087*7c478bd9Sstevel@tonic-gate { 1088*7c478bd9Sstevel@tonic-gate register tchar *cp; 1089*7c478bd9Sstevel@tonic-gate 1090*7c478bd9Sstevel@tonic-gate if (!whyles) { 1091*7c478bd9Sstevel@tonic-gate /* 1092*7c478bd9Sstevel@tonic-gate * Print the prompt string 1093*7c478bd9Sstevel@tonic-gate */ 1094*7c478bd9Sstevel@tonic-gate for (cp = value(S_prompt /*"prompt"*/); *cp; cp++) 1095*7c478bd9Sstevel@tonic-gate if (*cp == HIST) 1096*7c478bd9Sstevel@tonic-gate printf("%d", eventno + 1); 1097*7c478bd9Sstevel@tonic-gate else { 1098*7c478bd9Sstevel@tonic-gate if (*cp == '\\' && cp[1] == HIST) 1099*7c478bd9Sstevel@tonic-gate cp++; 1100*7c478bd9Sstevel@tonic-gate Putchar(*cp | QUOTE); 1101*7c478bd9Sstevel@tonic-gate } 1102*7c478bd9Sstevel@tonic-gate } else 1103*7c478bd9Sstevel@tonic-gate /* 1104*7c478bd9Sstevel@tonic-gate * Prompt for forward reading loop 1105*7c478bd9Sstevel@tonic-gate * body content. 1106*7c478bd9Sstevel@tonic-gate */ 1107*7c478bd9Sstevel@tonic-gate printf("? "); 1108*7c478bd9Sstevel@tonic-gate flush(); 1109*7c478bd9Sstevel@tonic-gate } 1110*7c478bd9Sstevel@tonic-gate 1111*7c478bd9Sstevel@tonic-gate /* 1112*7c478bd9Sstevel@tonic-gate * Save char * block. 1113*7c478bd9Sstevel@tonic-gate */ 1114*7c478bd9Sstevel@tonic-gate tchar ** 1115*7c478bd9Sstevel@tonic-gate strblktotsblk(v, num) 1116*7c478bd9Sstevel@tonic-gate register char **v; 1117*7c478bd9Sstevel@tonic-gate int num; 1118*7c478bd9Sstevel@tonic-gate { 1119*7c478bd9Sstevel@tonic-gate register tchar **newv = 1120*7c478bd9Sstevel@tonic-gate (tchar **) calloc((unsigned) (num+ 1), sizeof (tchar **)); 1121*7c478bd9Sstevel@tonic-gate tchar **onewv = newv; 1122*7c478bd9Sstevel@tonic-gate 1123*7c478bd9Sstevel@tonic-gate while (*v && num--) 1124*7c478bd9Sstevel@tonic-gate *newv++ = strtots(NOSTR,*v++); 1125*7c478bd9Sstevel@tonic-gate *newv = 0; 1126*7c478bd9Sstevel@tonic-gate return (onewv); 1127*7c478bd9Sstevel@tonic-gate } 1128*7c478bd9Sstevel@tonic-gate 1129*7c478bd9Sstevel@tonic-gate 1130*7c478bd9Sstevel@tonic-gate sigwaiting() 1131*7c478bd9Sstevel@tonic-gate { 1132*7c478bd9Sstevel@tonic-gate _signal(SIGWAITING, sigwaiting); 1133*7c478bd9Sstevel@tonic-gate } 1134*7c478bd9Sstevel@tonic-gate 1135*7c478bd9Sstevel@tonic-gate siglwp() 1136*7c478bd9Sstevel@tonic-gate { 1137*7c478bd9Sstevel@tonic-gate _signal(SIGLWP, siglwp); 1138*7c478bd9Sstevel@tonic-gate } 1139*7c478bd9Sstevel@tonic-gate 1140*7c478bd9Sstevel@tonic-gate 1141*7c478bd9Sstevel@tonic-gate /* 1142*7c478bd9Sstevel@tonic-gate * Following functions and data are used for csh to do its 1143*7c478bd9Sstevel@tonic-gate * file descriptors book keeping. 1144*7c478bd9Sstevel@tonic-gate */ 1145*7c478bd9Sstevel@tonic-gate 1146*7c478bd9Sstevel@tonic-gate static int *fdinuse = NULL; /* The list of files opened by csh */ 1147*7c478bd9Sstevel@tonic-gate static int nbytesused = 0; /* no of bytes allocated to fdinuse */ 1148*7c478bd9Sstevel@tonic-gate static int max_fd = 0; /* The maximum descriptor in fdinuse */ 1149*7c478bd9Sstevel@tonic-gate static int my_pid; /* The process id set in initdesc() */ 1150*7c478bd9Sstevel@tonic-gate static int NoFile = NOFILE; /* The number of files I can use. */ 1151*7c478bd9Sstevel@tonic-gate 1152*7c478bd9Sstevel@tonic-gate /* 1153*7c478bd9Sstevel@tonic-gate * Get the number of files this csh can use. 1154*7c478bd9Sstevel@tonic-gate * 1155*7c478bd9Sstevel@tonic-gate * Move the initial descriptors to their eventual 1156*7c478bd9Sstevel@tonic-gate * resting places, closing all other units. 1157*7c478bd9Sstevel@tonic-gate * 1158*7c478bd9Sstevel@tonic-gate * Also, reserve 0/1/2, so NIS+ routines do not get 1159*7c478bd9Sstevel@tonic-gate * hold of them. And initialize fdinuse list and set 1160*7c478bd9Sstevel@tonic-gate * the current process id. 1161*7c478bd9Sstevel@tonic-gate * 1162*7c478bd9Sstevel@tonic-gate * If this csh was invoked from setuid'ed script file, 1163*7c478bd9Sstevel@tonic-gate * do not close the third argument passed. The file 1164*7c478bd9Sstevel@tonic-gate * must be one of /dev/fd/0,1,2,,, 1165*7c478bd9Sstevel@tonic-gate * (execv() always passes three arguments when it execs a script 1166*7c478bd9Sstevel@tonic-gate * file in a form of #! /bin/csh -b.) 1167*7c478bd9Sstevel@tonic-gate * 1168*7c478bd9Sstevel@tonic-gate * If is_reinit is set in initdesc_x(), then we only close the file 1169*7c478bd9Sstevel@tonic-gate * descriptors that we actually opened (as recorded in fdinuse). 1170*7c478bd9Sstevel@tonic-gate */ 1171*7c478bd9Sstevel@tonic-gate initdesc(argc, argv) 1172*7c478bd9Sstevel@tonic-gate int argc; 1173*7c478bd9Sstevel@tonic-gate char *argv[]; 1174*7c478bd9Sstevel@tonic-gate { 1175*7c478bd9Sstevel@tonic-gate initdesc_x(argc, argv, 0); 1176*7c478bd9Sstevel@tonic-gate } 1177*7c478bd9Sstevel@tonic-gate 1178*7c478bd9Sstevel@tonic-gate reinitdesc(argc, argv) 1179*7c478bd9Sstevel@tonic-gate int argc; 1180*7c478bd9Sstevel@tonic-gate char *argv[]; 1181*7c478bd9Sstevel@tonic-gate { 1182*7c478bd9Sstevel@tonic-gate initdesc_x(argc, argv, 1); 1183*7c478bd9Sstevel@tonic-gate } 1184*7c478bd9Sstevel@tonic-gate 1185*7c478bd9Sstevel@tonic-gate /* 1186*7c478bd9Sstevel@tonic-gate * Callback functions for closing all file descriptors. 1187*7c478bd9Sstevel@tonic-gate */ 1188*7c478bd9Sstevel@tonic-gate static int 1189*7c478bd9Sstevel@tonic-gate close_except(void *cd, int fd) 1190*7c478bd9Sstevel@tonic-gate { 1191*7c478bd9Sstevel@tonic-gate int script_fd = *(int *)cd; 1192*7c478bd9Sstevel@tonic-gate 1193*7c478bd9Sstevel@tonic-gate if (fd >= 3 && fd < NoFile && fd != script_fd) 1194*7c478bd9Sstevel@tonic-gate (void) close(fd); 1195*7c478bd9Sstevel@tonic-gate return (0); 1196*7c478bd9Sstevel@tonic-gate } 1197*7c478bd9Sstevel@tonic-gate 1198*7c478bd9Sstevel@tonic-gate static int 1199*7c478bd9Sstevel@tonic-gate close_inuse(void *cd, int fd) 1200*7c478bd9Sstevel@tonic-gate { 1201*7c478bd9Sstevel@tonic-gate int script_fd = *(int *)cd; 1202*7c478bd9Sstevel@tonic-gate 1203*7c478bd9Sstevel@tonic-gate if (fd >= 3 && fd < NoFile && fd != script_fd && 1204*7c478bd9Sstevel@tonic-gate CSH_FD_ISSET(fd, fdinuse)) { 1205*7c478bd9Sstevel@tonic-gate (void) close(fd); 1206*7c478bd9Sstevel@tonic-gate unsetfd(fd); 1207*7c478bd9Sstevel@tonic-gate } 1208*7c478bd9Sstevel@tonic-gate return (0); 1209*7c478bd9Sstevel@tonic-gate } 1210*7c478bd9Sstevel@tonic-gate 1211*7c478bd9Sstevel@tonic-gate initdesc_x(argc, argv, is_reinit) 1212*7c478bd9Sstevel@tonic-gate int argc; 1213*7c478bd9Sstevel@tonic-gate char *argv[]; 1214*7c478bd9Sstevel@tonic-gate int is_reinit; 1215*7c478bd9Sstevel@tonic-gate { 1216*7c478bd9Sstevel@tonic-gate 1217*7c478bd9Sstevel@tonic-gate int script_fd = -1; 1218*7c478bd9Sstevel@tonic-gate struct stat buf; 1219*7c478bd9Sstevel@tonic-gate struct rlimit rlp; 1220*7c478bd9Sstevel@tonic-gate 1221*7c478bd9Sstevel@tonic-gate /* 1222*7c478bd9Sstevel@tonic-gate * Get pid of this shell 1223*7c478bd9Sstevel@tonic-gate */ 1224*7c478bd9Sstevel@tonic-gate my_pid = getpid(); 1225*7c478bd9Sstevel@tonic-gate 1226*7c478bd9Sstevel@tonic-gate /* 1227*7c478bd9Sstevel@tonic-gate * Get the hard limit numbers of descriptors 1228*7c478bd9Sstevel@tonic-gate * this csh can use. 1229*7c478bd9Sstevel@tonic-gate */ 1230*7c478bd9Sstevel@tonic-gate if (getrlimit(RLIMIT_NOFILE, &rlp) == 0) 1231*7c478bd9Sstevel@tonic-gate NoFile = rlp.rlim_cur; 1232*7c478bd9Sstevel@tonic-gate 1233*7c478bd9Sstevel@tonic-gate /* 1234*7c478bd9Sstevel@tonic-gate * If this csh was invoked for executing setuid script file, 1235*7c478bd9Sstevel@tonic-gate * the third argument passed is the special file name 1236*7c478bd9Sstevel@tonic-gate * which should not be closed. This special file name is 1237*7c478bd9Sstevel@tonic-gate * in the form /dev/fd/X. 1238*7c478bd9Sstevel@tonic-gate */ 1239*7c478bd9Sstevel@tonic-gate if (argc >= 3) 1240*7c478bd9Sstevel@tonic-gate if (sscanf(argv[2], "/dev/fd/%d", &script_fd) != 1) 1241*7c478bd9Sstevel@tonic-gate script_fd = -1; 1242*7c478bd9Sstevel@tonic-gate else 1243*7c478bd9Sstevel@tonic-gate fcntl(script_fd, F_SETFD, 1); /* Make sure to close 1244*7c478bd9Sstevel@tonic-gate * this file on exec. 1245*7c478bd9Sstevel@tonic-gate */ 1246*7c478bd9Sstevel@tonic-gate 1247*7c478bd9Sstevel@tonic-gate if (fdinuse == NULL) { 1248*7c478bd9Sstevel@tonic-gate nbytesused = sizeof(int) * howmany(NoFile, sizeof(int) * NBBY); 1249*7c478bd9Sstevel@tonic-gate fdinuse = (int *) xalloc(nbytesused); 1250*7c478bd9Sstevel@tonic-gate } 1251*7c478bd9Sstevel@tonic-gate 1252*7c478bd9Sstevel@tonic-gate /* 1253*7c478bd9Sstevel@tonic-gate * Close all files except 0/1/2 to get a clean 1254*7c478bd9Sstevel@tonic-gate * file descritor space. 1255*7c478bd9Sstevel@tonic-gate */ 1256*7c478bd9Sstevel@tonic-gate if (!is_reinit) 1257*7c478bd9Sstevel@tonic-gate (void) fdwalk(close_except, &script_fd); 1258*7c478bd9Sstevel@tonic-gate else 1259*7c478bd9Sstevel@tonic-gate (void) fdwalk(close_inuse, &script_fd); 1260*7c478bd9Sstevel@tonic-gate 1261*7c478bd9Sstevel@tonic-gate didfds = 0; /* 0, 1, 2 aren't set up */ 1262*7c478bd9Sstevel@tonic-gate 1263*7c478bd9Sstevel@tonic-gate if (fstat(0, &buf) < 0) 1264*7c478bd9Sstevel@tonic-gate open("/dev/null", 0); 1265*7c478bd9Sstevel@tonic-gate 1266*7c478bd9Sstevel@tonic-gate (void) fcntl(SHIN = dcopy(0, FSHIN), F_SETFD, 1); 1267*7c478bd9Sstevel@tonic-gate (void) fcntl(SHOUT = dcopy(1, FSHOUT), F_SETFD, 1); 1268*7c478bd9Sstevel@tonic-gate (void) fcntl(SHDIAG = dcopy(2, FSHDIAG), F_SETFD, 1); 1269*7c478bd9Sstevel@tonic-gate (void) fcntl(OLDSTD = dcopy(SHIN, FOLDSTD), F_SETFD, 1); 1270*7c478bd9Sstevel@tonic-gate 1271*7c478bd9Sstevel@tonic-gate /* 1272*7c478bd9Sstevel@tonic-gate * Open 0/1/2 to avoid Nis+ functions to pick them up. 1273*7c478bd9Sstevel@tonic-gate * Now, 0/1/2 are saved, close them and open them. 1274*7c478bd9Sstevel@tonic-gate */ 1275*7c478bd9Sstevel@tonic-gate close(0); close(1); close(2); 1276*7c478bd9Sstevel@tonic-gate open("/dev/null", 0); 1277*7c478bd9Sstevel@tonic-gate dup(0); 1278*7c478bd9Sstevel@tonic-gate dup(0); 1279*7c478bd9Sstevel@tonic-gate 1280*7c478bd9Sstevel@tonic-gate /* 1281*7c478bd9Sstevel@tonic-gate * Clear fd_set mask 1282*7c478bd9Sstevel@tonic-gate */ 1283*7c478bd9Sstevel@tonic-gate if ( ! is_reinit) 1284*7c478bd9Sstevel@tonic-gate CSH_FD_ZERO(fdinuse, nbytesused); 1285*7c478bd9Sstevel@tonic-gate } 1286*7c478bd9Sstevel@tonic-gate 1287*7c478bd9Sstevel@tonic-gate /* 1288*7c478bd9Sstevel@tonic-gate * This routine is called after an error to close up 1289*7c478bd9Sstevel@tonic-gate * any units which may have been left open accidentally. 1290*7c478bd9Sstevel@tonic-gate * 1291*7c478bd9Sstevel@tonic-gate * You only need to remove files in fdinuse list. 1292*7c478bd9Sstevel@tonic-gate * After you have removed the files, you can clear the 1293*7c478bd9Sstevel@tonic-gate * list and max_fd. 1294*7c478bd9Sstevel@tonic-gate */ 1295*7c478bd9Sstevel@tonic-gate closem() 1296*7c478bd9Sstevel@tonic-gate { 1297*7c478bd9Sstevel@tonic-gate register int f; 1298*7c478bd9Sstevel@tonic-gate 1299*7c478bd9Sstevel@tonic-gate for (f = 3; f <= max_fd; f++) { 1300*7c478bd9Sstevel@tonic-gate if (CSH_FD_ISSET(f, fdinuse) && 1301*7c478bd9Sstevel@tonic-gate f != SHIN && f != SHOUT && f != SHDIAG && 1302*7c478bd9Sstevel@tonic-gate f != OLDSTD && f != FSHTTY) 1303*7c478bd9Sstevel@tonic-gate close(f); 1304*7c478bd9Sstevel@tonic-gate } 1305*7c478bd9Sstevel@tonic-gate CSH_FD_ZERO(fdinuse, nbytesused); 1306*7c478bd9Sstevel@tonic-gate max_fd = 0; 1307*7c478bd9Sstevel@tonic-gate } 1308*7c478bd9Sstevel@tonic-gate 1309*7c478bd9Sstevel@tonic-gate /* 1310*7c478bd9Sstevel@tonic-gate * Reset my_pid when a new process is created. Only call this 1311*7c478bd9Sstevel@tonic-gate * if you want the process to affect fdinuse (e.g., fork, but 1312*7c478bd9Sstevel@tonic-gate * not vfork). 1313*7c478bd9Sstevel@tonic-gate */ 1314*7c478bd9Sstevel@tonic-gate new_process() 1315*7c478bd9Sstevel@tonic-gate { 1316*7c478bd9Sstevel@tonic-gate my_pid = getpid(); 1317*7c478bd9Sstevel@tonic-gate } 1318*7c478bd9Sstevel@tonic-gate 1319*7c478bd9Sstevel@tonic-gate 1320*7c478bd9Sstevel@tonic-gate /* 1321*7c478bd9Sstevel@tonic-gate * Whenever Csh open/create/dup/pipe a file or files, 1322*7c478bd9Sstevel@tonic-gate * Csh keeps track of its open files. The open files 1323*7c478bd9Sstevel@tonic-gate * are kept in "fdinuse, Fd In Use" list. 1324*7c478bd9Sstevel@tonic-gate * 1325*7c478bd9Sstevel@tonic-gate * When a file descriptor is newly allocated, setfd() is 1326*7c478bd9Sstevel@tonic-gate * used to mark the fact in "fdinuse" list. 1327*7c478bd9Sstevel@tonic-gate * For example, 1328*7c478bd9Sstevel@tonic-gate * fd = open("newfile", 0); 1329*7c478bd9Sstevel@tonic-gate * setfd(fd); 1330*7c478bd9Sstevel@tonic-gate * 1331*7c478bd9Sstevel@tonic-gate * When a file is freed by close() function, unsetfd() is 1332*7c478bd9Sstevel@tonic-gate * used to remove the fd from "fdinuse" list. 1333*7c478bd9Sstevel@tonic-gate * For example, 1334*7c478bd9Sstevel@tonic-gate * close(fd); 1335*7c478bd9Sstevel@tonic-gate * unsetfd(fd); 1336*7c478bd9Sstevel@tonic-gate */ 1337*7c478bd9Sstevel@tonic-gate setfd(fd) 1338*7c478bd9Sstevel@tonic-gate int fd; 1339*7c478bd9Sstevel@tonic-gate { 1340*7c478bd9Sstevel@tonic-gate /* 1341*7c478bd9Sstevel@tonic-gate * Because you want to avoid 1342*7c478bd9Sstevel@tonic-gate * conflict due to vfork(). 1343*7c478bd9Sstevel@tonic-gate */ 1344*7c478bd9Sstevel@tonic-gate if (my_pid != getpid()) 1345*7c478bd9Sstevel@tonic-gate return; 1346*7c478bd9Sstevel@tonic-gate 1347*7c478bd9Sstevel@tonic-gate if (fd >= NoFile || fd < 0) 1348*7c478bd9Sstevel@tonic-gate return; 1349*7c478bd9Sstevel@tonic-gate 1350*7c478bd9Sstevel@tonic-gate if (fd > max_fd) 1351*7c478bd9Sstevel@tonic-gate max_fd = fd; 1352*7c478bd9Sstevel@tonic-gate CSH_FD_SET(fd, fdinuse); 1353*7c478bd9Sstevel@tonic-gate } 1354*7c478bd9Sstevel@tonic-gate 1355*7c478bd9Sstevel@tonic-gate unsetfd(fd) 1356*7c478bd9Sstevel@tonic-gate int fd; 1357*7c478bd9Sstevel@tonic-gate { 1358*7c478bd9Sstevel@tonic-gate register int i; 1359*7c478bd9Sstevel@tonic-gate 1360*7c478bd9Sstevel@tonic-gate /* 1361*7c478bd9Sstevel@tonic-gate * Because you want to avoid 1362*7c478bd9Sstevel@tonic-gate * conflict due to vfork(). 1363*7c478bd9Sstevel@tonic-gate */ 1364*7c478bd9Sstevel@tonic-gate if (my_pid != getpid()) 1365*7c478bd9Sstevel@tonic-gate return; 1366*7c478bd9Sstevel@tonic-gate 1367*7c478bd9Sstevel@tonic-gate if (fd >= NoFile || fd < 0) 1368*7c478bd9Sstevel@tonic-gate return; 1369*7c478bd9Sstevel@tonic-gate 1370*7c478bd9Sstevel@tonic-gate CSH_FD_CLR(fd, fdinuse); 1371*7c478bd9Sstevel@tonic-gate if (fd == max_fd) { 1372*7c478bd9Sstevel@tonic-gate for (i = max_fd-1; i >= 3; i--) 1373*7c478bd9Sstevel@tonic-gate if (CSH_FD_ISSET(i, fdinuse)) { 1374*7c478bd9Sstevel@tonic-gate max_fd = i; 1375*7c478bd9Sstevel@tonic-gate return; 1376*7c478bd9Sstevel@tonic-gate } 1377*7c478bd9Sstevel@tonic-gate max_fd = 0; 1378*7c478bd9Sstevel@tonic-gate } 1379*7c478bd9Sstevel@tonic-gate } 1380*7c478bd9Sstevel@tonic-gate 1381*7c478bd9Sstevel@tonic-gate /* 1382*7c478bd9Sstevel@tonic-gate * A generic call back routine to output error messages from the 1383*7c478bd9Sstevel@tonic-gate * policy backing functions called by pfcsh. 1384*7c478bd9Sstevel@tonic-gate */ 1385*7c478bd9Sstevel@tonic-gate void 1386*7c478bd9Sstevel@tonic-gate secpolicy_print(int level, const char *msg) 1387*7c478bd9Sstevel@tonic-gate { 1388*7c478bd9Sstevel@tonic-gate switch (level) { 1389*7c478bd9Sstevel@tonic-gate case SECPOLICY_WARN: 1390*7c478bd9Sstevel@tonic-gate default: 1391*7c478bd9Sstevel@tonic-gate haderr = 1; 1392*7c478bd9Sstevel@tonic-gate printf("%s: ", msg); /* printf() does gettext() */ 1393*7c478bd9Sstevel@tonic-gate break; 1394*7c478bd9Sstevel@tonic-gate case SECPOLICY_ERROR: 1395*7c478bd9Sstevel@tonic-gate bferr(msg); /* bferr() does gettext() */ 1396*7c478bd9Sstevel@tonic-gate break; 1397*7c478bd9Sstevel@tonic-gate } 1398*7c478bd9Sstevel@tonic-gate } 1399