17c478bd9Sstevel@tonic-gate /* 26c02b4a4Smuffin * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 37c478bd9Sstevel@tonic-gate * Use is subject to license terms. 47c478bd9Sstevel@tonic-gate */ 57c478bd9Sstevel@tonic-gate 67c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 77c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 87c478bd9Sstevel@tonic-gate 97c478bd9Sstevel@tonic-gate /* 107c478bd9Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California. 117c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley Software License Agreement 127c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 137c478bd9Sstevel@tonic-gate */ 147c478bd9Sstevel@tonic-gate 157c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 167c478bd9Sstevel@tonic-gate 177c478bd9Sstevel@tonic-gate #include <locale.h> 187c478bd9Sstevel@tonic-gate #include "sh.h" 197c478bd9Sstevel@tonic-gate /* #include <sys/ioctl.h> */ 207c478bd9Sstevel@tonic-gate #include <fcntl.h> 217c478bd9Sstevel@tonic-gate #include <sys/filio.h> 227c478bd9Sstevel@tonic-gate #include "sh.tconst.h" 237c478bd9Sstevel@tonic-gate #include <pwd.h> 247c478bd9Sstevel@tonic-gate #include <stdlib.h> 257c478bd9Sstevel@tonic-gate #include "sh_policy.h" /* for pfcsh */ 2684368791Smuffin #ifdef TRACE 2784368791Smuffin #include <stdio.h> 2884368791Smuffin #endif 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate /* 317c478bd9Sstevel@tonic-gate * We use these csh(1) private versions of the select macros, (see select(3C)) 327c478bd9Sstevel@tonic-gate * so as not to be limited by the size of struct fd_set (ie 1024). 337c478bd9Sstevel@tonic-gate */ 347c478bd9Sstevel@tonic-gate #define CSH_FD_SET(n, p) ((*((p) + ((n)/NFDBITS))) |= (1 << ((n) % NFDBITS))) 357c478bd9Sstevel@tonic-gate #define CSH_FD_CLR(n, p) ((*((p) + ((n)/NFDBITS))) &= ~(1 << ((n) % NFDBITS))) 367c478bd9Sstevel@tonic-gate #define CSH_FD_ISSET(n, p) ((*((p) + ((n)/NFDBITS))) & (1 << ((n) % NFDBITS))) 377c478bd9Sstevel@tonic-gate #define CSH_FD_ZERO(p, n) memset((void *)(p), 0, (n)) 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate tchar *pathlist[] = { S_usrbin /* "/usr/bin" */, S_DOT /* "." */, 0 }; 407c478bd9Sstevel@tonic-gate tchar *dumphist[] = { S_history /* "history" */, S_h /* "-h" */, 0, 0 }; 417c478bd9Sstevel@tonic-gate tchar *loadhist[] = { S_source /* "source" */, S_h /* "-h" */, S_NDOThistory /* "~/.history" */, 0 }; 427c478bd9Sstevel@tonic-gate tchar HIST = '!'; 437c478bd9Sstevel@tonic-gate tchar HISTSUB = '^'; 447c478bd9Sstevel@tonic-gate int nofile; 457c478bd9Sstevel@tonic-gate bool reenter; 467c478bd9Sstevel@tonic-gate bool nverbose; 477c478bd9Sstevel@tonic-gate bool nexececho; 487c478bd9Sstevel@tonic-gate bool quitit; 497c478bd9Sstevel@tonic-gate bool fast; 507c478bd9Sstevel@tonic-gate bool batch; 517c478bd9Sstevel@tonic-gate bool prompt = 1; 527c478bd9Sstevel@tonic-gate bool enterhist = 0; 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate extern gid_t getegid(), getgid(); 557c478bd9Sstevel@tonic-gate extern uid_t geteuid(), getuid(); 567c478bd9Sstevel@tonic-gate extern tchar **strblktotsblk(/* char **, int */); 577c478bd9Sstevel@tonic-gate 586c02b4a4Smuffin void importpath(tchar *); 596c02b4a4Smuffin void srccat(tchar *, tchar *); 606c02b4a4Smuffin void srccat_inlogin(tchar *, tchar *); 616c02b4a4Smuffin void srcunit(int, bool, bool); 626c02b4a4Smuffin void rechist(void); 636c02b4a4Smuffin void goodbye(void); 646c02b4a4Smuffin void pintr1(bool); 656c02b4a4Smuffin void process(bool); 666c02b4a4Smuffin void dosource(tchar **); 676c02b4a4Smuffin void mailchk(void); 686c02b4a4Smuffin void printprompt(void); 696c02b4a4Smuffin void sigwaiting(void); 706c02b4a4Smuffin void siglwp(void); 716c02b4a4Smuffin void initdesc(int, char *[]); 726c02b4a4Smuffin void initdesc_x(int, char *[], int); 736c02b4a4Smuffin void closem(void); 746c02b4a4Smuffin void unsetfd(int); 756c02b4a4Smuffin void secpolicy_print(int, const char *); 766c02b4a4Smuffin void phup(void); 777c478bd9Sstevel@tonic-gate 7884368791Smuffin #ifdef TRACE 7984368791Smuffin FILE *trace; 8084368791Smuffin /* 8184368791Smuffin * Trace routines 8284368791Smuffin */ 8384368791Smuffin #define TRACEFILE "/tmp/trace.XXXXXX" 8484368791Smuffin 8584368791Smuffin /* 8684368791Smuffin * Initialize trace file. 8784368791Smuffin * Called from main. 8884368791Smuffin */ 8984368791Smuffin void 9084368791Smuffin trace_init(void) 9184368791Smuffin { 9284368791Smuffin char name[128]; 9384368791Smuffin char *p; 9484368791Smuffin 9584368791Smuffin strcpy(name, TRACEFILE); 9684368791Smuffin p = mktemp(name); 9784368791Smuffin trace = fopen(p, "w"); 9884368791Smuffin } 9984368791Smuffin 10084368791Smuffin /* 10184368791Smuffin * write message to trace file 10284368791Smuffin */ 10384368791Smuffin /*VARARGS1*/ 10484368791Smuffin void 10584368791Smuffin tprintf(fmt, a, b, c, d, e, f, g, h, i, j) 10684368791Smuffin char *fmt; 10784368791Smuffin { 10884368791Smuffin if (trace) { 10984368791Smuffin fprintf(trace, fmt, a, b, c, d, e, f, g, h, i, j); 11084368791Smuffin fflush(trace); 11184368791Smuffin } 11284368791Smuffin } 11384368791Smuffin #endif 1146c02b4a4Smuffin 1156c02b4a4Smuffin int 1166c02b4a4Smuffin main(int c, char **av) 1177c478bd9Sstevel@tonic-gate { 1186c02b4a4Smuffin tchar **v, *cp, *p, *q, *r; 1196c02b4a4Smuffin int f; 1207c478bd9Sstevel@tonic-gate struct sigvec osv; 1217c478bd9Sstevel@tonic-gate struct sigaction sa; 1227c478bd9Sstevel@tonic-gate tchar s_prompt[MAXHOSTNAMELEN+3]; 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate pfcshflag = 0; 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate /* 1277c478bd9Sstevel@tonic-gate * set up the error exit, if there is an error before 1287c478bd9Sstevel@tonic-gate * this is done, it will core dump, and we don't 1297c478bd9Sstevel@tonic-gate * tolerate core dumps 1307c478bd9Sstevel@tonic-gate */ 1317c478bd9Sstevel@tonic-gate haderr = 0; 1327c478bd9Sstevel@tonic-gate setexit(); 1337c478bd9Sstevel@tonic-gate if (haderr) { 1347c478bd9Sstevel@tonic-gate /* 1357c478bd9Sstevel@tonic-gate * if were here, there was an error in the csh 1367c478bd9Sstevel@tonic-gate * startup so just punt 1377c478bd9Sstevel@tonic-gate */ 1387c478bd9Sstevel@tonic-gate printf("csh startup error, csh exiting...\n"); 1397c478bd9Sstevel@tonic-gate flush(); 1407c478bd9Sstevel@tonic-gate exitstat(); 1417c478bd9Sstevel@tonic-gate } 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 1457c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 1467c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 1477c478bd9Sstevel@tonic-gate #endif 1487c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 1497c478bd9Sstevel@tonic-gate 1507c478bd9Sstevel@tonic-gate /* 1517c478bd9Sstevel@tonic-gate * This is a profile shell if the simple name of argv[0] is 1527c478bd9Sstevel@tonic-gate * pfcsh or -pfcsh 1537c478bd9Sstevel@tonic-gate */ 1547c478bd9Sstevel@tonic-gate p = strtots(NOSTR, "pfcsh"); 1557c478bd9Sstevel@tonic-gate r = strtots(NOSTR, "-pfcsh"); 1567c478bd9Sstevel@tonic-gate if ((p != NOSTR) && (r != NOSTR) && 1577c478bd9Sstevel@tonic-gate ((q = strtots(NOSTR, *av)) != NOSTR)) { 1587c478bd9Sstevel@tonic-gate if (c > 0 && (eq(p, simple(q)) || eq(r, simple(q)))) { 1597c478bd9Sstevel@tonic-gate pfcshflag = 1; 1607c478bd9Sstevel@tonic-gate } 16165b0c20eSnakanon xfree(q); 1627c478bd9Sstevel@tonic-gate } 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate if (p != NOSTR) 16565b0c20eSnakanon xfree(p); 1667c478bd9Sstevel@tonic-gate if (r != NOSTR) 16765b0c20eSnakanon xfree(r); 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate if (pfcshflag == 1) { 1707c478bd9Sstevel@tonic-gate secpolicy_init(); 1717c478bd9Sstevel@tonic-gate } 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate /* Copy arguments */ 1747c478bd9Sstevel@tonic-gate v = strblktotsblk(av, c); 1757c478bd9Sstevel@tonic-gate 1767c478bd9Sstevel@tonic-gate /* 1777c478bd9Sstevel@tonic-gate * Initialize paraml list 1787c478bd9Sstevel@tonic-gate */ 1797c478bd9Sstevel@tonic-gate paraml.next = paraml.prev = ¶ml; 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate settimes(); /* Immed. estab. timing base */ 1827c478bd9Sstevel@tonic-gate 1837c478bd9Sstevel@tonic-gate if (eq(v[0], S_aout /* "a.out" */)) /* A.out's are quittable */ 1847c478bd9Sstevel@tonic-gate quitit = 1; 1857c478bd9Sstevel@tonic-gate uid = getuid(); 1867c478bd9Sstevel@tonic-gate loginsh = **v == '-'; 1877c478bd9Sstevel@tonic-gate if (loginsh) 1887c478bd9Sstevel@tonic-gate (void) time(&chktim); 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate /* 1917c478bd9Sstevel@tonic-gate * Move the descriptors to safe places. 1927c478bd9Sstevel@tonic-gate * The variable didfds is 0 while we have only FSH* to work with. 1937c478bd9Sstevel@tonic-gate * When didfds is true, we have 0,1,2 and prefer to use these. 1947c478bd9Sstevel@tonic-gate * 1957c478bd9Sstevel@tonic-gate * Also, setup data for csh internal file descriptor book keeping. 1967c478bd9Sstevel@tonic-gate */ 1977c478bd9Sstevel@tonic-gate initdesc(c, av); 1987c478bd9Sstevel@tonic-gate 1997c478bd9Sstevel@tonic-gate /* 2007c478bd9Sstevel@tonic-gate * Initialize the shell variables. 2017c478bd9Sstevel@tonic-gate * ARGV and PROMPT are initialized later. 2027c478bd9Sstevel@tonic-gate * STATUS is also munged in several places. 2037c478bd9Sstevel@tonic-gate * CHILD is munged when forking/waiting 2047c478bd9Sstevel@tonic-gate */ 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate /* don't do globbing here, just set exact copies */ 2077c478bd9Sstevel@tonic-gate setNS(S_noglob); 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate set(S_status /* "status" */, S_0 /* "0" */); 2107c478bd9Sstevel@tonic-gate dinit(cp = getenvs_("HOME")); /* dinit thinks that HOME==cwd in a */ 2117c478bd9Sstevel@tonic-gate /* login shell */ 2127c478bd9Sstevel@tonic-gate if (cp == NOSTR) 2137c478bd9Sstevel@tonic-gate fast++; /* No home -> can't read scripts */ 2147c478bd9Sstevel@tonic-gate else { 2157c478bd9Sstevel@tonic-gate if (strlen_(cp) >= BUFSIZ - 10) { 2167c478bd9Sstevel@tonic-gate cp = NOSTR; 2177c478bd9Sstevel@tonic-gate fast++; 2187c478bd9Sstevel@tonic-gate printf("%s\n", gettext("Pathname too long")); 2197c478bd9Sstevel@tonic-gate set(S_home /* "home" */, savestr(cp)); 2207c478bd9Sstevel@tonic-gate local_setenv(S_HOME, savestr(cp)); 2217c478bd9Sstevel@tonic-gate } 2227c478bd9Sstevel@tonic-gate set(S_home /* "home" */, savestr(cp)); 2237c478bd9Sstevel@tonic-gate } 2247c478bd9Sstevel@tonic-gate /* 2257c478bd9Sstevel@tonic-gate * Grab other useful things from the environment. 2267c478bd9Sstevel@tonic-gate * Should we grab everything?? 2277c478bd9Sstevel@tonic-gate */ 2287c478bd9Sstevel@tonic-gate if ((cp = getenvs_("USER")) != NOSTR) 2297c478bd9Sstevel@tonic-gate set(S_user /* "user" */, savestr(cp)); 2307c478bd9Sstevel@tonic-gate else { 2317c478bd9Sstevel@tonic-gate /* 2327c478bd9Sstevel@tonic-gate * If USER is not defined, set it here. 2337c478bd9Sstevel@tonic-gate */ 2347c478bd9Sstevel@tonic-gate struct passwd *pw; 2357c478bd9Sstevel@tonic-gate pw = getpwuid(getuid()); 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate if (pw != NULL) { 2387c478bd9Sstevel@tonic-gate set(S_user, strtots((tchar *)0, pw->pw_name)); 2397c478bd9Sstevel@tonic-gate local_setenv(S_USER, strtots((tchar *)0, pw->pw_name)); 2407c478bd9Sstevel@tonic-gate } 2417c478bd9Sstevel@tonic-gate else if (loginsh) { /* Give up setting USER variable. */ 2427c478bd9Sstevel@tonic-gate printf("Warning: USER environment variable could not be set.\n"); 2437c478bd9Sstevel@tonic-gate } 2447c478bd9Sstevel@tonic-gate } 2457c478bd9Sstevel@tonic-gate if ((cp = getenvs_("TERM")) != NOSTR) 2467c478bd9Sstevel@tonic-gate set(S_term /* "term" */, savestr(cp)); 2477c478bd9Sstevel@tonic-gate /* 2487c478bd9Sstevel@tonic-gate * Re-initialize path if set in environment 2497c478bd9Sstevel@tonic-gate */ 2507c478bd9Sstevel@tonic-gate if ((cp = getenvs_("PATH")) == NOSTR) 2517c478bd9Sstevel@tonic-gate set1(S_path /* "path" */, saveblk(pathlist), &shvhed); 2527c478bd9Sstevel@tonic-gate else 2537c478bd9Sstevel@tonic-gate importpath(cp); 2547c478bd9Sstevel@tonic-gate set(S_shell /* "shell" */, S_SHELLPATH); 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate doldol = putn(getpid()); /* For $$ */ 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate /* restore globbing until the user says otherwise */ 2597c478bd9Sstevel@tonic-gate unsetv(S_noglob); 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate /* 2627c478bd9Sstevel@tonic-gate * Record the interrupt states from the parent process. 2637c478bd9Sstevel@tonic-gate * If the parent is non-interruptible our hand must be forced 2647c478bd9Sstevel@tonic-gate * or we (and our children) won't be either. 2657c478bd9Sstevel@tonic-gate * Our children inherit termination from our parent. 2667c478bd9Sstevel@tonic-gate * We catch it only if we are the login shell. 2677c478bd9Sstevel@tonic-gate */ 2687c478bd9Sstevel@tonic-gate /* parents interruptibility */ 2697c478bd9Sstevel@tonic-gate (void) sigvec(SIGINT, (struct sigvec *)0, &osv); 2707c478bd9Sstevel@tonic-gate parintr = osv.sv_handler; 2717c478bd9Sstevel@tonic-gate /* parents terminability */ 2727c478bd9Sstevel@tonic-gate (void) sigvec(SIGTERM, (struct sigvec *)0, &osv); 2737c478bd9Sstevel@tonic-gate parterm = osv.sv_handler; 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate _signal(SIGLWP, siglwp); 2767c478bd9Sstevel@tonic-gate _signal(SIGWAITING, sigwaiting); 2777c478bd9Sstevel@tonic-gate if (loginsh) { 2787c478bd9Sstevel@tonic-gate (void) signal(SIGHUP, phup); /* exit processing on HUP */ 2797c478bd9Sstevel@tonic-gate (void) signal(SIGXCPU, phup); /* ...and on XCPU */ 2807c478bd9Sstevel@tonic-gate (void) signal(SIGXFSZ, phup); /* ...and on XFSZ */ 2817c478bd9Sstevel@tonic-gate } 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate /* 2847c478bd9Sstevel@tonic-gate * Process the arguments. 2857c478bd9Sstevel@tonic-gate * 2867c478bd9Sstevel@tonic-gate * Note that processing of -v/-x is actually delayed till after 2877c478bd9Sstevel@tonic-gate * script processing. 2887c478bd9Sstevel@tonic-gate */ 2897c478bd9Sstevel@tonic-gate c--, v++; 2907c478bd9Sstevel@tonic-gate while (c > 0 && (cp = v[0])[0] == '-' && *++cp != '\0' && !batch) { 2917c478bd9Sstevel@tonic-gate do switch (*cp++) { 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate case 'b': /* -b Next arg is input file */ 2947c478bd9Sstevel@tonic-gate batch++; 2957c478bd9Sstevel@tonic-gate break; 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate case 'c': /* -c Command input from arg */ 2987c478bd9Sstevel@tonic-gate if (c == 1) 2997c478bd9Sstevel@tonic-gate exit(0); 3007c478bd9Sstevel@tonic-gate c--, v++; 3017c478bd9Sstevel@tonic-gate arginp = v[0]; 3027c478bd9Sstevel@tonic-gate prompt = 0; 3037c478bd9Sstevel@tonic-gate nofile++; 3047c478bd9Sstevel@tonic-gate cflg++; 3057c478bd9Sstevel@tonic-gate break; 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate case 'e': /* -e Exit on any error */ 3087c478bd9Sstevel@tonic-gate exiterr++; 3097c478bd9Sstevel@tonic-gate break; 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate case 'f': /* -f Fast start */ 3127c478bd9Sstevel@tonic-gate fast++; 3137c478bd9Sstevel@tonic-gate break; 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate case 'i': /* -i Interactive, even if !intty */ 3167c478bd9Sstevel@tonic-gate intact++; 3177c478bd9Sstevel@tonic-gate nofile++; 3187c478bd9Sstevel@tonic-gate break; 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate case 'n': /* -n Don't execute */ 3217c478bd9Sstevel@tonic-gate noexec++; 3227c478bd9Sstevel@tonic-gate break; 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate case 'q': /* -q (Undoc'd) ... die on quit */ 3257c478bd9Sstevel@tonic-gate quitit = 1; 3267c478bd9Sstevel@tonic-gate break; 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate case 's': /* -s Read from std input */ 3297c478bd9Sstevel@tonic-gate nofile++; 3307c478bd9Sstevel@tonic-gate break; 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate case 't': /* -t Read one line from input */ 3337c478bd9Sstevel@tonic-gate onelflg = 2; 3347c478bd9Sstevel@tonic-gate prompt = 0; 3357c478bd9Sstevel@tonic-gate nofile++; 3367c478bd9Sstevel@tonic-gate break; 3377c478bd9Sstevel@tonic-gate #ifdef TRACE 3387c478bd9Sstevel@tonic-gate case 'T': /* -T trace switch on */ 3397c478bd9Sstevel@tonic-gate trace_init(); 3407c478bd9Sstevel@tonic-gate break; 3417c478bd9Sstevel@tonic-gate #endif 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate case 'v': /* -v Echo hist expanded input */ 3447c478bd9Sstevel@tonic-gate nverbose = 1; /* ... later */ 3457c478bd9Sstevel@tonic-gate break; 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate case 'x': /* -x Echo just before execution */ 3487c478bd9Sstevel@tonic-gate nexececho = 1; /* ... later */ 3497c478bd9Sstevel@tonic-gate break; 3507c478bd9Sstevel@tonic-gate 3517c478bd9Sstevel@tonic-gate case 'V': /* -V Echo hist expanded input */ 3527c478bd9Sstevel@tonic-gate setNS(S_verbose /* "verbose" */); /* NOW! */ 3537c478bd9Sstevel@tonic-gate break; 3547c478bd9Sstevel@tonic-gate 3557c478bd9Sstevel@tonic-gate case 'X': /* -X Echo just before execution */ 3567c478bd9Sstevel@tonic-gate setNS(S_echo /* "echo" */); /* NOW! */ 3577c478bd9Sstevel@tonic-gate break; 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate } while (*cp); 3607c478bd9Sstevel@tonic-gate v++, c--; 3617c478bd9Sstevel@tonic-gate } 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate if (quitit) /* With all due haste, for debugging */ 3647c478bd9Sstevel@tonic-gate (void) signal(SIGQUIT, SIG_DFL); 3657c478bd9Sstevel@tonic-gate 3667c478bd9Sstevel@tonic-gate /* 3677c478bd9Sstevel@tonic-gate * Unless prevented by -c, -i, -s, or -t, if there 3687c478bd9Sstevel@tonic-gate * are remaining arguments the first of them is the name 3697c478bd9Sstevel@tonic-gate * of a shell file from which to read commands. 3707c478bd9Sstevel@tonic-gate */ 3717c478bd9Sstevel@tonic-gate if (!batch && (uid != geteuid() || getgid() != getegid())) { 3727c478bd9Sstevel@tonic-gate errno = EACCES; 3737c478bd9Sstevel@tonic-gate child++; /* So this ... */ 3747c478bd9Sstevel@tonic-gate Perror(S_csh /* "csh" */); /* ... doesn't return */ 3757c478bd9Sstevel@tonic-gate } 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate if (nofile == 0 && c > 0) { 3787c478bd9Sstevel@tonic-gate nofile = open_(v[0], 0); 3797c478bd9Sstevel@tonic-gate if (nofile < 0) { 3807c478bd9Sstevel@tonic-gate child++; /* So this ... */ 3817c478bd9Sstevel@tonic-gate Perror(v[0]); /* ... doesn't return */ 3827c478bd9Sstevel@tonic-gate } 3837c478bd9Sstevel@tonic-gate file = v[0]; 3847c478bd9Sstevel@tonic-gate SHIN = dmove(nofile, FSHIN); /* Replace FSHIN */ 3857c478bd9Sstevel@tonic-gate (void) fcntl(SHIN, F_SETFD, 1); 3867c478bd9Sstevel@tonic-gate prompt = 0; 3877c478bd9Sstevel@tonic-gate c--, v++; 3887c478bd9Sstevel@tonic-gate } 3897c478bd9Sstevel@tonic-gate 3907c478bd9Sstevel@tonic-gate /* 3917c478bd9Sstevel@tonic-gate * Consider input a tty if it really is or we are interactive. 3927c478bd9Sstevel@tonic-gate */ 3937c478bd9Sstevel@tonic-gate intty = intact || isatty(SHIN); 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate /* 3967c478bd9Sstevel@tonic-gate * Decide whether we should play with signals or not. 3977c478bd9Sstevel@tonic-gate * If we are explicitly told (via -i, or -) or we are a login 3987c478bd9Sstevel@tonic-gate * shell (arg0 starts with -) or the input and output are both 3997c478bd9Sstevel@tonic-gate * the ttys("csh", or "csh</dev/ttyx>/dev/ttyx") 4007c478bd9Sstevel@tonic-gate * Note that in only the login shell is it likely that parent 4017c478bd9Sstevel@tonic-gate * may have set signals to be ignored 4027c478bd9Sstevel@tonic-gate */ 4037c478bd9Sstevel@tonic-gate if (loginsh || intact || intty && isatty(SHOUT)) 4047c478bd9Sstevel@tonic-gate setintr = 1; 4057c478bd9Sstevel@tonic-gate #ifdef TELL 4067c478bd9Sstevel@tonic-gate settell(); 4077c478bd9Sstevel@tonic-gate #endif 4087c478bd9Sstevel@tonic-gate /* 4097c478bd9Sstevel@tonic-gate * Save the remaining arguments in argv. 4107c478bd9Sstevel@tonic-gate */ 411*3b09452cSnakanon setq(S_argv /* "argv" */, copyblk(v), &shvhed); 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate /* 4147c478bd9Sstevel@tonic-gate * Set up the prompt. 4157c478bd9Sstevel@tonic-gate */ 4167c478bd9Sstevel@tonic-gate if (prompt) { 4177c478bd9Sstevel@tonic-gate gethostname_(s_prompt, MAXHOSTNAMELEN); 4187c478bd9Sstevel@tonic-gate strcat_(s_prompt, uid == 0 ? S_SHARPSP /* "# " */ : S_PERSENTSP /* "% " */); 4197c478bd9Sstevel@tonic-gate set(S_prompt /* "prompt" */, s_prompt); 4207c478bd9Sstevel@tonic-gate } 4217c478bd9Sstevel@tonic-gate 4227c478bd9Sstevel@tonic-gate /* 4237c478bd9Sstevel@tonic-gate * If we are an interactive shell, then start fiddling 4247c478bd9Sstevel@tonic-gate * with the signals; this is a tricky game. 4257c478bd9Sstevel@tonic-gate */ 4267c478bd9Sstevel@tonic-gate shpgrp = getpgid(0); 4277c478bd9Sstevel@tonic-gate opgrp = tpgrp = -1; 4287c478bd9Sstevel@tonic-gate if (setintr) { 4297c478bd9Sstevel@tonic-gate **av = '-'; 4307c478bd9Sstevel@tonic-gate if (!quitit) /* Wary! */ 4317c478bd9Sstevel@tonic-gate (void) signal(SIGQUIT, SIG_IGN); 4327c478bd9Sstevel@tonic-gate (void) signal(SIGINT, pintr); 4337c478bd9Sstevel@tonic-gate (void) sigblock(sigmask(SIGINT)); 4347c478bd9Sstevel@tonic-gate (void) signal(SIGTERM, SIG_IGN); 4357c478bd9Sstevel@tonic-gate if (quitit == 0 && arginp == 0) { 4367c478bd9Sstevel@tonic-gate (void) signal(SIGTSTP, SIG_IGN); 4377c478bd9Sstevel@tonic-gate (void) signal(SIGTTIN, SIG_IGN); 4387c478bd9Sstevel@tonic-gate (void) signal(SIGTTOU, SIG_IGN); 4397c478bd9Sstevel@tonic-gate /* 4407c478bd9Sstevel@tonic-gate * Wait till in foreground, in case someone 4417c478bd9Sstevel@tonic-gate * stupidly runs 4427c478bd9Sstevel@tonic-gate * csh & 4437c478bd9Sstevel@tonic-gate * dont want to try to grab away the tty. 4447c478bd9Sstevel@tonic-gate */ 4457c478bd9Sstevel@tonic-gate if (isatty(FSHDIAG)) 4467c478bd9Sstevel@tonic-gate f = FSHDIAG; 4477c478bd9Sstevel@tonic-gate else if (isatty(FSHOUT)) 4487c478bd9Sstevel@tonic-gate f = FSHOUT; 4497c478bd9Sstevel@tonic-gate else if (isatty(OLDSTD)) 4507c478bd9Sstevel@tonic-gate f = OLDSTD; 4517c478bd9Sstevel@tonic-gate else 4527c478bd9Sstevel@tonic-gate f = -1; 4537c478bd9Sstevel@tonic-gate retry: 4547c478bd9Sstevel@tonic-gate if (ioctl(f, TIOCGPGRP, (char *)&tpgrp) == 0 && 4557c478bd9Sstevel@tonic-gate tpgrp != -1) { 4567c478bd9Sstevel@tonic-gate if (tpgrp != shpgrp) { 4577c478bd9Sstevel@tonic-gate void (*old)() = (void (*)())signal(SIGTTIN, SIG_DFL); 4587c478bd9Sstevel@tonic-gate (void) kill(0, SIGTTIN); 4597c478bd9Sstevel@tonic-gate (void) signal(SIGTTIN, old); 4607c478bd9Sstevel@tonic-gate goto retry; 4617c478bd9Sstevel@tonic-gate } 4627c478bd9Sstevel@tonic-gate opgrp = shpgrp; 4637c478bd9Sstevel@tonic-gate shpgrp = getpid(); 4647c478bd9Sstevel@tonic-gate tpgrp = shpgrp; 4657c478bd9Sstevel@tonic-gate (void) setpgid(0, shpgrp); 4667c478bd9Sstevel@tonic-gate (void) ioctl(f, TIOCSPGRP, (char *)&shpgrp); 4677c478bd9Sstevel@tonic-gate (void) fcntl(dcopy(f, FSHTTY), F_SETFD, 1); 4687c478bd9Sstevel@tonic-gate } else { 4697c478bd9Sstevel@tonic-gate notty: 4707c478bd9Sstevel@tonic-gate printf("Warning: no access to tty; thus no job control in this shell...\n"); 4717c478bd9Sstevel@tonic-gate tpgrp = -1; 4727c478bd9Sstevel@tonic-gate } 4737c478bd9Sstevel@tonic-gate } 4747c478bd9Sstevel@tonic-gate } 4757c478bd9Sstevel@tonic-gate if (setintr == 0 && parintr == SIG_DFL) 4767c478bd9Sstevel@tonic-gate setintr++; 4777c478bd9Sstevel@tonic-gate 4787c478bd9Sstevel@tonic-gate /* 4797c478bd9Sstevel@tonic-gate * Set SIGCHLD handler, making sure that reads restart after it runs. 4807c478bd9Sstevel@tonic-gate */ 4817c478bd9Sstevel@tonic-gate sigemptyset(&sa.sa_mask); 4827c478bd9Sstevel@tonic-gate sa.sa_handler = pchild; 4837c478bd9Sstevel@tonic-gate sa.sa_flags = SA_RESTART; 4847c478bd9Sstevel@tonic-gate (void) sigaction(SIGCHLD, &sa, (struct sigaction *)NULL); 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate /* 4877c478bd9Sstevel@tonic-gate * Set an exit here in case of an interrupt or error reading 4887c478bd9Sstevel@tonic-gate * the shell start-up scripts. 4897c478bd9Sstevel@tonic-gate */ 4907c478bd9Sstevel@tonic-gate setexit(); 4917c478bd9Sstevel@tonic-gate haderr = 0; /* In case second time through */ 4927c478bd9Sstevel@tonic-gate if (!fast && reenter == 0) { 4937c478bd9Sstevel@tonic-gate reenter++; 4947c478bd9Sstevel@tonic-gate 4957c478bd9Sstevel@tonic-gate /* 4967c478bd9Sstevel@tonic-gate * If this is a login csh, and /etc/.login exists, 4977c478bd9Sstevel@tonic-gate * source /etc/.login first. 4987c478bd9Sstevel@tonic-gate */ 4997c478bd9Sstevel@tonic-gate if (loginsh) { 5007c478bd9Sstevel@tonic-gate tchar tmp_etc[4+1]; /* strlen("/etc")+1 */ 5017c478bd9Sstevel@tonic-gate tchar tmp_login[7+1]; /* strlen("/.login")+1 */ 5027c478bd9Sstevel@tonic-gate 5037c478bd9Sstevel@tonic-gate strtots(tmp_etc, "/etc"); 5047c478bd9Sstevel@tonic-gate strtots(tmp_login, "/.login"); 5057c478bd9Sstevel@tonic-gate srccat_inlogin(tmp_etc, tmp_login); 5067c478bd9Sstevel@tonic-gate } 5077c478bd9Sstevel@tonic-gate 5087c478bd9Sstevel@tonic-gate /* Will have value("home") here because set fast if don't */ 5097c478bd9Sstevel@tonic-gate srccat(value(S_home /* "home" */), S_SLADOTcshrc /* "/.cshrc" */); 5107c478bd9Sstevel@tonic-gate 5117c478bd9Sstevel@tonic-gate /* Hash path */ 5127c478bd9Sstevel@tonic-gate if (!fast && !arginp && !onelflg && !havhash) 5137c478bd9Sstevel@tonic-gate dohash(xhash); 5147c478bd9Sstevel@tonic-gate 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate /* 5177c478bd9Sstevel@tonic-gate * Reconstruct the history list now, so that it's 5187c478bd9Sstevel@tonic-gate * available from within .login. 5197c478bd9Sstevel@tonic-gate */ 5207c478bd9Sstevel@tonic-gate dosource(loadhist); 5217c478bd9Sstevel@tonic-gate if (loginsh) { 5227c478bd9Sstevel@tonic-gate srccat_inlogin(value(S_home /* "home" */), S_SLADOTlogin /* "/.login" */); 5237c478bd9Sstevel@tonic-gate } 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate /* 5267c478bd9Sstevel@tonic-gate * To get cdpath hashing $cdpath must have a 5277c478bd9Sstevel@tonic-gate * value, not $CDPATH. So if after reading 5287c478bd9Sstevel@tonic-gate * the startup files ( .cshrc ), and 5297c478bd9Sstevel@tonic-gate * user has specified a value for cdpath, then 5307c478bd9Sstevel@tonic-gate * cache $cdpath paths. xhash2 is global array 5317c478bd9Sstevel@tonic-gate * for $cdpath caching. 5327c478bd9Sstevel@tonic-gate */ 5337c478bd9Sstevel@tonic-gate if (!fast && !arginp && !onelflg && !havhash2) 5347c478bd9Sstevel@tonic-gate dohash(xhash2); 5357c478bd9Sstevel@tonic-gate } 5367c478bd9Sstevel@tonic-gate 5377c478bd9Sstevel@tonic-gate /* 5387c478bd9Sstevel@tonic-gate * Now are ready for the -v and -x flags 5397c478bd9Sstevel@tonic-gate */ 5407c478bd9Sstevel@tonic-gate if (nverbose) 5417c478bd9Sstevel@tonic-gate setNS(S_verbose /* "verbose" */); 5427c478bd9Sstevel@tonic-gate if (nexececho) 5437c478bd9Sstevel@tonic-gate setNS(S_echo /* "echo" */); 5447c478bd9Sstevel@tonic-gate 5457c478bd9Sstevel@tonic-gate /* 5467c478bd9Sstevel@tonic-gate * All the rest of the world is inside this call. 5477c478bd9Sstevel@tonic-gate * The argument to process indicates whether it should 5487c478bd9Sstevel@tonic-gate * catch "error unwinds". Thus if we are a interactive shell 5497c478bd9Sstevel@tonic-gate * our call here will never return by being blown past on an error. 5507c478bd9Sstevel@tonic-gate */ 5517c478bd9Sstevel@tonic-gate process(setintr); 5527c478bd9Sstevel@tonic-gate 5537c478bd9Sstevel@tonic-gate /* 5547c478bd9Sstevel@tonic-gate * Mop-up. 5557c478bd9Sstevel@tonic-gate */ 5567c478bd9Sstevel@tonic-gate if (loginsh) { 5577c478bd9Sstevel@tonic-gate printf("logout\n"); 5587c478bd9Sstevel@tonic-gate (void) close(SHIN); /* No need for unsetfd(). */ 5597c478bd9Sstevel@tonic-gate child++; 5607c478bd9Sstevel@tonic-gate goodbye(); 5617c478bd9Sstevel@tonic-gate } 5627c478bd9Sstevel@tonic-gate rechist(); 5637c478bd9Sstevel@tonic-gate exitstat(); 5647c478bd9Sstevel@tonic-gate } 5657c478bd9Sstevel@tonic-gate 5666c02b4a4Smuffin void 5676c02b4a4Smuffin untty(void) 5687c478bd9Sstevel@tonic-gate { 5697c478bd9Sstevel@tonic-gate 5707c478bd9Sstevel@tonic-gate if (tpgrp > 0) { 5717c478bd9Sstevel@tonic-gate (void) setpgid(0, opgrp); 5727c478bd9Sstevel@tonic-gate (void) ioctl(FSHTTY, TIOCSPGRP, (char *)&opgrp); 5737c478bd9Sstevel@tonic-gate } 5747c478bd9Sstevel@tonic-gate } 5757c478bd9Sstevel@tonic-gate 5766c02b4a4Smuffin void 5776c02b4a4Smuffin importpath(tchar *cp) 5787c478bd9Sstevel@tonic-gate { 5796c02b4a4Smuffin int i = 0; 5806c02b4a4Smuffin tchar *dp; 5816c02b4a4Smuffin tchar **pv; 5827c478bd9Sstevel@tonic-gate int c; 5837c478bd9Sstevel@tonic-gate static tchar dot[2] = {'.', 0}; 5847c478bd9Sstevel@tonic-gate 5857c478bd9Sstevel@tonic-gate for (dp = cp; *dp; dp++) 5867c478bd9Sstevel@tonic-gate if (*dp == ':') 5877c478bd9Sstevel@tonic-gate i++; 5887c478bd9Sstevel@tonic-gate /* 5897c478bd9Sstevel@tonic-gate * i+2 where i is the number of colons in the path. 5907c478bd9Sstevel@tonic-gate * There are i+1 directories in the path plus we need 5917c478bd9Sstevel@tonic-gate * room for a zero terminator. 5927c478bd9Sstevel@tonic-gate */ 59365b0c20eSnakanon pv = (tchar **)xcalloc((unsigned)(i + 2), sizeof (tchar **)); 5947c478bd9Sstevel@tonic-gate dp = cp; 5957c478bd9Sstevel@tonic-gate i = 0; 5967c478bd9Sstevel@tonic-gate if (*dp) 5977c478bd9Sstevel@tonic-gate for (;;) { 5987c478bd9Sstevel@tonic-gate if ((c = *dp) == ':' || c == 0) { 5997c478bd9Sstevel@tonic-gate *dp = 0; 6007c478bd9Sstevel@tonic-gate pv[i++] = savestr(*cp ? cp : dot); 6017c478bd9Sstevel@tonic-gate if (c) { 6027c478bd9Sstevel@tonic-gate cp = dp + 1; 6037c478bd9Sstevel@tonic-gate *dp = ':'; 6047c478bd9Sstevel@tonic-gate } else 6057c478bd9Sstevel@tonic-gate break; 6067c478bd9Sstevel@tonic-gate } 6077c478bd9Sstevel@tonic-gate dp++; 6087c478bd9Sstevel@tonic-gate } 6097c478bd9Sstevel@tonic-gate pv[i] = 0; 6107c478bd9Sstevel@tonic-gate set1(S_path /* "path" */, pv, &shvhed); 6117c478bd9Sstevel@tonic-gate } 6127c478bd9Sstevel@tonic-gate 6137c478bd9Sstevel@tonic-gate /* 6147c478bd9Sstevel@tonic-gate * Source to the file which is the catenation of the argument names. 6157c478bd9Sstevel@tonic-gate */ 6166c02b4a4Smuffin void 6176c02b4a4Smuffin srccat(tchar *cp, tchar *dp) 6187c478bd9Sstevel@tonic-gate { 6196c02b4a4Smuffin tchar *ep = strspl(cp, dp); 6206c02b4a4Smuffin int unit = dmove(open_(ep, 0), -1); 6217c478bd9Sstevel@tonic-gate 6227c478bd9Sstevel@tonic-gate (void) fcntl(unit, F_SETFD, 1); 6237c478bd9Sstevel@tonic-gate xfree(ep); 6247c478bd9Sstevel@tonic-gate #ifdef INGRES 6257c478bd9Sstevel@tonic-gate srcunit(unit, 0, 0); 6267c478bd9Sstevel@tonic-gate #else 6277c478bd9Sstevel@tonic-gate srcunit(unit, 1, 0); 6287c478bd9Sstevel@tonic-gate #endif 6297c478bd9Sstevel@tonic-gate } 6307c478bd9Sstevel@tonic-gate 6317c478bd9Sstevel@tonic-gate /* 6327c478bd9Sstevel@tonic-gate * Source to the file which is the catenation of the argument names. 6337c478bd9Sstevel@tonic-gate * This one does not check the ownership. 6347c478bd9Sstevel@tonic-gate */ 6356c02b4a4Smuffin void 6366c02b4a4Smuffin srccat_inlogin(tchar *cp, tchar *dp) 6377c478bd9Sstevel@tonic-gate { 6386c02b4a4Smuffin tchar *ep = strspl(cp, dp); 6396c02b4a4Smuffin int unit = dmove(open_(ep, 0), -1); 6407c478bd9Sstevel@tonic-gate 6417c478bd9Sstevel@tonic-gate (void) fcntl(unit, F_SETFD, 1); 6427c478bd9Sstevel@tonic-gate xfree(ep); 6437c478bd9Sstevel@tonic-gate srcunit(unit, 0, 0); 6447c478bd9Sstevel@tonic-gate } 6457c478bd9Sstevel@tonic-gate 6467c478bd9Sstevel@tonic-gate /* 6477c478bd9Sstevel@tonic-gate * Source to a unit. If onlyown it must be our file or our group or 6487c478bd9Sstevel@tonic-gate * we don't chance it. This occurs on ".cshrc"s and the like. 6497c478bd9Sstevel@tonic-gate */ 6506c02b4a4Smuffin void 6516c02b4a4Smuffin srcunit(int unit, bool onlyown, bool hflg) 6527c478bd9Sstevel@tonic-gate { 6537c478bd9Sstevel@tonic-gate /* We have to push down a lot of state here */ 6547c478bd9Sstevel@tonic-gate /* All this could go into a structure */ 6557c478bd9Sstevel@tonic-gate int oSHIN = -1, oldintty = intty; 6567c478bd9Sstevel@tonic-gate struct whyle *oldwhyl = whyles; 6577c478bd9Sstevel@tonic-gate tchar *ogointr = gointr, *oarginp = arginp; 6587c478bd9Sstevel@tonic-gate tchar *oevalp = evalp, **oevalvec = evalvec; 6597c478bd9Sstevel@tonic-gate int oonelflg = onelflg; 6607c478bd9Sstevel@tonic-gate bool oenterhist = enterhist; 6617c478bd9Sstevel@tonic-gate tchar OHIST = HIST; 6627c478bd9Sstevel@tonic-gate #ifdef TELL 6637c478bd9Sstevel@tonic-gate bool otell = cantell; 6647c478bd9Sstevel@tonic-gate #endif 6657c478bd9Sstevel@tonic-gate struct Bin saveB; 6667c478bd9Sstevel@tonic-gate 6677c478bd9Sstevel@tonic-gate /* The (few) real local variables */ 6687c478bd9Sstevel@tonic-gate jmp_buf oldexit; 6697c478bd9Sstevel@tonic-gate int reenter, omask; 6707c478bd9Sstevel@tonic-gate 6717c478bd9Sstevel@tonic-gate if (unit < 0) 6727c478bd9Sstevel@tonic-gate return; 6737c478bd9Sstevel@tonic-gate if (didfds) 6747c478bd9Sstevel@tonic-gate donefds(); 6757c478bd9Sstevel@tonic-gate if (onlyown) { 6767c478bd9Sstevel@tonic-gate struct stat stb; 6777c478bd9Sstevel@tonic-gate 6787c478bd9Sstevel@tonic-gate if (fstat(unit, &stb) < 0 || 6797c478bd9Sstevel@tonic-gate (stb.st_uid != uid && stb.st_gid != getgid())) { 6807c478bd9Sstevel@tonic-gate (void) close(unit); 6817c478bd9Sstevel@tonic-gate unsetfd(unit); 6827c478bd9Sstevel@tonic-gate return; 6837c478bd9Sstevel@tonic-gate } 6847c478bd9Sstevel@tonic-gate } 6857c478bd9Sstevel@tonic-gate 6867c478bd9Sstevel@tonic-gate /* 6877c478bd9Sstevel@tonic-gate * There is a critical section here while we are pushing down the 6887c478bd9Sstevel@tonic-gate * input stream since we have stuff in different structures. 6897c478bd9Sstevel@tonic-gate * If we weren't careful an interrupt could corrupt SHIN's Bin 6907c478bd9Sstevel@tonic-gate * structure and kill the shell. 6917c478bd9Sstevel@tonic-gate * 6927c478bd9Sstevel@tonic-gate * We could avoid the critical region by grouping all the stuff 6937c478bd9Sstevel@tonic-gate * in a single structure and pointing at it to move it all at 6947c478bd9Sstevel@tonic-gate * once. This is less efficient globally on many variable references 6957c478bd9Sstevel@tonic-gate * however. 6967c478bd9Sstevel@tonic-gate */ 6977c478bd9Sstevel@tonic-gate getexit(oldexit); 6987c478bd9Sstevel@tonic-gate reenter = 0; 6997c478bd9Sstevel@tonic-gate if (setintr) 7007c478bd9Sstevel@tonic-gate omask = sigblock(sigmask(SIGINT)); 7017c478bd9Sstevel@tonic-gate setexit(); 7027c478bd9Sstevel@tonic-gate reenter++; 7037c478bd9Sstevel@tonic-gate if (reenter == 1) { 7047c478bd9Sstevel@tonic-gate /* Setup the new values of the state stuff saved above */ 7057c478bd9Sstevel@tonic-gate copy((char *)&saveB, (char *)&B, sizeof saveB); 7067c478bd9Sstevel@tonic-gate fbuf = (tchar **) 0; 7077c478bd9Sstevel@tonic-gate fseekp = feobp = fblocks = 0; 7087c478bd9Sstevel@tonic-gate oSHIN = SHIN, SHIN = unit, arginp = 0, onelflg = 0; 7097c478bd9Sstevel@tonic-gate intty = isatty(SHIN), whyles = 0, gointr = 0; 7107c478bd9Sstevel@tonic-gate evalvec = 0; evalp = 0; 7117c478bd9Sstevel@tonic-gate enterhist = hflg; 7127c478bd9Sstevel@tonic-gate if (enterhist) 7137c478bd9Sstevel@tonic-gate HIST = '\0'; 7147c478bd9Sstevel@tonic-gate /* 7157c478bd9Sstevel@tonic-gate * Now if we are allowing commands to be interrupted, 7167c478bd9Sstevel@tonic-gate * we let ourselves be interrupted. 7177c478bd9Sstevel@tonic-gate */ 7187c478bd9Sstevel@tonic-gate if (setintr) 7197c478bd9Sstevel@tonic-gate (void) sigsetmask(omask); 7207c478bd9Sstevel@tonic-gate #ifdef TELL 7217c478bd9Sstevel@tonic-gate settell(); 7227c478bd9Sstevel@tonic-gate #endif 7237c478bd9Sstevel@tonic-gate process(0); /* 0 -> blow away on errors */ 7247c478bd9Sstevel@tonic-gate } 7257c478bd9Sstevel@tonic-gate if (setintr) 7267c478bd9Sstevel@tonic-gate (void) sigsetmask(omask); 7277c478bd9Sstevel@tonic-gate if (oSHIN >= 0) { 7286c02b4a4Smuffin int i; 7297c478bd9Sstevel@tonic-gate 7307c478bd9Sstevel@tonic-gate /* We made it to the new state... free up its storage */ 7317c478bd9Sstevel@tonic-gate /* This code could get run twice but xfree doesn't care */ 7327c478bd9Sstevel@tonic-gate for (i = 0; i < fblocks; i++) 7337c478bd9Sstevel@tonic-gate xfree(fbuf[i]); 7347c478bd9Sstevel@tonic-gate xfree((char *)fbuf); 7357c478bd9Sstevel@tonic-gate 7367c478bd9Sstevel@tonic-gate /* Reset input arena */ 7377c478bd9Sstevel@tonic-gate copy((char *)&B, (char *)&saveB, sizeof B); 7387c478bd9Sstevel@tonic-gate 7397c478bd9Sstevel@tonic-gate (void) close(SHIN), SHIN = oSHIN; 7407c478bd9Sstevel@tonic-gate unsetfd(SHIN); 7417c478bd9Sstevel@tonic-gate arginp = oarginp, onelflg = oonelflg; 7427c478bd9Sstevel@tonic-gate evalp = oevalp, evalvec = oevalvec; 7437c478bd9Sstevel@tonic-gate intty = oldintty, whyles = oldwhyl, gointr = ogointr; 7447c478bd9Sstevel@tonic-gate if (enterhist) 7457c478bd9Sstevel@tonic-gate HIST = OHIST; 7467c478bd9Sstevel@tonic-gate enterhist = oenterhist; 7477c478bd9Sstevel@tonic-gate #ifdef TELL 7487c478bd9Sstevel@tonic-gate cantell = otell; 7497c478bd9Sstevel@tonic-gate #endif 7507c478bd9Sstevel@tonic-gate } 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate resexit(oldexit); 7537c478bd9Sstevel@tonic-gate /* 7547c478bd9Sstevel@tonic-gate * If process reset() (effectively an unwind) then 7557c478bd9Sstevel@tonic-gate * we must also unwind. 7567c478bd9Sstevel@tonic-gate */ 7577c478bd9Sstevel@tonic-gate if (reenter >= 2) 7587c478bd9Sstevel@tonic-gate error(NULL); 7597c478bd9Sstevel@tonic-gate } 7607c478bd9Sstevel@tonic-gate 7616c02b4a4Smuffin void 7626c02b4a4Smuffin rechist(void) 7637c478bd9Sstevel@tonic-gate { 7647c478bd9Sstevel@tonic-gate tchar buf[BUFSIZ]; 7657c478bd9Sstevel@tonic-gate int fp, ftmp, oldidfds; 7667c478bd9Sstevel@tonic-gate 7677c478bd9Sstevel@tonic-gate if (!fast) { 7687c478bd9Sstevel@tonic-gate if (value(S_savehist /* "savehist" */)[0] == '\0') 7697c478bd9Sstevel@tonic-gate return; 7707c478bd9Sstevel@tonic-gate (void) strcpy_(buf, value(S_home /* "home" */)); 7717c478bd9Sstevel@tonic-gate (void) strcat_(buf, S_SLADOThistory /* "/.history" */); 7727c478bd9Sstevel@tonic-gate fp = creat_(buf, 0666); 7737c478bd9Sstevel@tonic-gate if (fp == -1) 7747c478bd9Sstevel@tonic-gate return; 7757c478bd9Sstevel@tonic-gate oldidfds = didfds; 7767c478bd9Sstevel@tonic-gate didfds = 0; 7777c478bd9Sstevel@tonic-gate ftmp = SHOUT; 7787c478bd9Sstevel@tonic-gate SHOUT = fp; 7797c478bd9Sstevel@tonic-gate (void) strcpy_(buf, value(S_savehist /* "savehist" */)); 7807c478bd9Sstevel@tonic-gate dumphist[2] = buf; 7817c478bd9Sstevel@tonic-gate dohist(dumphist); 7827c478bd9Sstevel@tonic-gate (void) close(fp); 7837c478bd9Sstevel@tonic-gate unsetfd(fp); 7847c478bd9Sstevel@tonic-gate SHOUT = ftmp; 7857c478bd9Sstevel@tonic-gate didfds = oldidfds; 7867c478bd9Sstevel@tonic-gate } 7877c478bd9Sstevel@tonic-gate } 7887c478bd9Sstevel@tonic-gate 7896c02b4a4Smuffin void 7906c02b4a4Smuffin goodbye(void) 7917c478bd9Sstevel@tonic-gate { 7927c478bd9Sstevel@tonic-gate if (loginsh) { 7937c478bd9Sstevel@tonic-gate (void) signal(SIGQUIT, SIG_IGN); 7947c478bd9Sstevel@tonic-gate (void) signal(SIGINT, SIG_IGN); 7957c478bd9Sstevel@tonic-gate (void) signal(SIGTERM, SIG_IGN); 7967c478bd9Sstevel@tonic-gate setintr = 0; /* No interrupts after "logout" */ 7977c478bd9Sstevel@tonic-gate if (adrof(S_home /* "home" */)) 7987c478bd9Sstevel@tonic-gate srccat(value(S_home /* "home" */), S_SLADOTlogout /* "/.logout" */); 7997c478bd9Sstevel@tonic-gate } 8007c478bd9Sstevel@tonic-gate rechist(); 8017c478bd9Sstevel@tonic-gate exitstat(); 8027c478bd9Sstevel@tonic-gate } 8037c478bd9Sstevel@tonic-gate 8046c02b4a4Smuffin void 8056c02b4a4Smuffin exitstat(void) 8067c478bd9Sstevel@tonic-gate { 8077c478bd9Sstevel@tonic-gate 8087c478bd9Sstevel@tonic-gate #ifdef PROF 8097c478bd9Sstevel@tonic-gate monitor(0); 8107c478bd9Sstevel@tonic-gate #endif 8117c478bd9Sstevel@tonic-gate /* 8127c478bd9Sstevel@tonic-gate * Note that if STATUS is corrupted (i.e. getn bombs) 8137c478bd9Sstevel@tonic-gate * then error will exit directly because we poke child here. 8147c478bd9Sstevel@tonic-gate * Otherwise we might continue unwarrantedly (sic). 8157c478bd9Sstevel@tonic-gate */ 8167c478bd9Sstevel@tonic-gate child++; 8177c478bd9Sstevel@tonic-gate untty(); 8187c478bd9Sstevel@tonic-gate exit(getn(value(S_status /* "status" */))); 8197c478bd9Sstevel@tonic-gate } 8207c478bd9Sstevel@tonic-gate 8217c478bd9Sstevel@tonic-gate /* 8227c478bd9Sstevel@tonic-gate * in the event of a HUP we want to save the history 8237c478bd9Sstevel@tonic-gate */ 8247c478bd9Sstevel@tonic-gate void 8256c02b4a4Smuffin phup(void) 8267c478bd9Sstevel@tonic-gate { 8277c478bd9Sstevel@tonic-gate rechist(); 8287c478bd9Sstevel@tonic-gate exit(1); 8297c478bd9Sstevel@tonic-gate } 8307c478bd9Sstevel@tonic-gate 8317c478bd9Sstevel@tonic-gate tchar *jobargv[2] = { S_jobs /* "jobs" */, 0 }; 8327c478bd9Sstevel@tonic-gate /* 8337c478bd9Sstevel@tonic-gate * Catch an interrupt, e.g. during lexical input. 8347c478bd9Sstevel@tonic-gate * If we are an interactive shell, we reset the interrupt catch 8357c478bd9Sstevel@tonic-gate * immediately. In any case we drain the shell output, 8367c478bd9Sstevel@tonic-gate * and finally go through the normal error mechanism, which 8377c478bd9Sstevel@tonic-gate * gets a chance to make the shell go away. 8387c478bd9Sstevel@tonic-gate */ 8397c478bd9Sstevel@tonic-gate void 8406c02b4a4Smuffin pintr(void) 8417c478bd9Sstevel@tonic-gate { 8427c478bd9Sstevel@tonic-gate pintr1(1); 8437c478bd9Sstevel@tonic-gate } 8447c478bd9Sstevel@tonic-gate 8456c02b4a4Smuffin void 8466c02b4a4Smuffin pintr1(bool wantnl) 8477c478bd9Sstevel@tonic-gate { 8486c02b4a4Smuffin tchar **v; 8497c478bd9Sstevel@tonic-gate int omask; 8507c478bd9Sstevel@tonic-gate 8517c478bd9Sstevel@tonic-gate omask = sigblock(0); 8527c478bd9Sstevel@tonic-gate if (setintr) { 8537c478bd9Sstevel@tonic-gate (void) sigsetmask(omask & ~sigmask(SIGINT)); 8547c478bd9Sstevel@tonic-gate if (pjobs) { 8557c478bd9Sstevel@tonic-gate pjobs = 0; 8567c478bd9Sstevel@tonic-gate printf("\n"); 8577c478bd9Sstevel@tonic-gate dojobs(jobargv); 8587c478bd9Sstevel@tonic-gate bferr("Interrupted"); 8597c478bd9Sstevel@tonic-gate } 8607c478bd9Sstevel@tonic-gate } 8617c478bd9Sstevel@tonic-gate (void) sigsetmask(omask & ~sigmask(SIGCHLD)); 8627c478bd9Sstevel@tonic-gate draino(); 8637c478bd9Sstevel@tonic-gate 8647c478bd9Sstevel@tonic-gate /* 8657c478bd9Sstevel@tonic-gate * If we have an active "onintr" then we search for the label. 8667c478bd9Sstevel@tonic-gate * Note that if one does "onintr -" then we shan't be interruptible 8677c478bd9Sstevel@tonic-gate * so we needn't worry about that here. 8687c478bd9Sstevel@tonic-gate */ 8697c478bd9Sstevel@tonic-gate if (gointr) { 8707c478bd9Sstevel@tonic-gate search(ZGOTO, 0, gointr); 8717c478bd9Sstevel@tonic-gate timflg = 0; 8727c478bd9Sstevel@tonic-gate if (v = pargv) 8737c478bd9Sstevel@tonic-gate pargv = 0, blkfree(v); 8747c478bd9Sstevel@tonic-gate if (v = gargv) 8757c478bd9Sstevel@tonic-gate gargv = 0, blkfree(v); 8767c478bd9Sstevel@tonic-gate reset(); 8777c478bd9Sstevel@tonic-gate } else if (intty && wantnl) 8787c478bd9Sstevel@tonic-gate printf("\n"); /* Some like this, others don't */ 8797c478bd9Sstevel@tonic-gate error(NULL); 8807c478bd9Sstevel@tonic-gate } 8817c478bd9Sstevel@tonic-gate 8827c478bd9Sstevel@tonic-gate /* 8837c478bd9Sstevel@tonic-gate * Process is the main driving routine for the shell. 8847c478bd9Sstevel@tonic-gate * It runs all command processing, except for those within { ... } 8857c478bd9Sstevel@tonic-gate * in expressions (which is run by a routine evalav in sh.exp.c which 8867c478bd9Sstevel@tonic-gate * is a stripped down process), and `...` evaluation which is run 8877c478bd9Sstevel@tonic-gate * also by a subset of this code in sh.glob.c in the routine backeval. 8887c478bd9Sstevel@tonic-gate * 8897c478bd9Sstevel@tonic-gate * The code here is a little strange because part of it is interruptible 8907c478bd9Sstevel@tonic-gate * and hence freeing of structures appears to occur when none is necessary 8917c478bd9Sstevel@tonic-gate * if this is ignored. 8927c478bd9Sstevel@tonic-gate * 8937c478bd9Sstevel@tonic-gate * Note that if catch is not set then we will unwind on any error. 8947c478bd9Sstevel@tonic-gate * If an end-of-file occurs, we return. 8957c478bd9Sstevel@tonic-gate */ 8966c02b4a4Smuffin void 8976c02b4a4Smuffin process(bool catch) 8987c478bd9Sstevel@tonic-gate { 8997c478bd9Sstevel@tonic-gate jmp_buf osetexit; 9006c02b4a4Smuffin struct command *t; 9017c478bd9Sstevel@tonic-gate 9027c478bd9Sstevel@tonic-gate getexit(osetexit); 9037c478bd9Sstevel@tonic-gate for (;;) { 9047c478bd9Sstevel@tonic-gate pendjob(); 90565b0c20eSnakanon freelex(¶ml); 9067c478bd9Sstevel@tonic-gate paraml.next = paraml.prev = ¶ml; 9077c478bd9Sstevel@tonic-gate paraml.word = S_ /* "" */; 9087c478bd9Sstevel@tonic-gate t = 0; 9097c478bd9Sstevel@tonic-gate setexit(); 9107c478bd9Sstevel@tonic-gate justpr = enterhist; /* execute if not entering history */ 9117c478bd9Sstevel@tonic-gate 9127c478bd9Sstevel@tonic-gate /* 9137c478bd9Sstevel@tonic-gate * Interruptible during interactive reads 9147c478bd9Sstevel@tonic-gate */ 9157c478bd9Sstevel@tonic-gate if (setintr) 9167c478bd9Sstevel@tonic-gate (void) sigsetmask(sigblock(0) & ~sigmask(SIGINT)); 9177c478bd9Sstevel@tonic-gate 9187c478bd9Sstevel@tonic-gate /* 9197c478bd9Sstevel@tonic-gate * For the sake of reset() 9207c478bd9Sstevel@tonic-gate */ 9217c478bd9Sstevel@tonic-gate freelex(¶ml), freesyn(t), t = 0; 9227c478bd9Sstevel@tonic-gate 9237c478bd9Sstevel@tonic-gate if (haderr) { 9247c478bd9Sstevel@tonic-gate if (!catch) { 9257c478bd9Sstevel@tonic-gate /* unwind */ 9267c478bd9Sstevel@tonic-gate doneinp = 0; 9277c478bd9Sstevel@tonic-gate resexit(osetexit); 9287c478bd9Sstevel@tonic-gate reset(); 9297c478bd9Sstevel@tonic-gate } 9307c478bd9Sstevel@tonic-gate haderr = 0; 9317c478bd9Sstevel@tonic-gate /* 9327c478bd9Sstevel@tonic-gate * Every error is eventually caught here or 9337c478bd9Sstevel@tonic-gate * the shell dies. It is at this 9347c478bd9Sstevel@tonic-gate * point that we clean up any left-over open 9357c478bd9Sstevel@tonic-gate * files, by closing all but a fixed number 9367c478bd9Sstevel@tonic-gate * of pre-defined files. Thus routines don't 9377c478bd9Sstevel@tonic-gate * have to worry about leaving files open due 9387c478bd9Sstevel@tonic-gate * to deeper errors... they will get closed here. 9397c478bd9Sstevel@tonic-gate */ 9407c478bd9Sstevel@tonic-gate closem(); 9417c478bd9Sstevel@tonic-gate continue; 9427c478bd9Sstevel@tonic-gate } 9437c478bd9Sstevel@tonic-gate if (doneinp) { 9447c478bd9Sstevel@tonic-gate doneinp = 0; 9457c478bd9Sstevel@tonic-gate break; 9467c478bd9Sstevel@tonic-gate } 9477c478bd9Sstevel@tonic-gate if (chkstop) 9487c478bd9Sstevel@tonic-gate chkstop--; 9497c478bd9Sstevel@tonic-gate if (neednote) 9507c478bd9Sstevel@tonic-gate pnote(); 9517c478bd9Sstevel@tonic-gate if (intty && prompt && evalvec == 0) { 9527c478bd9Sstevel@tonic-gate mailchk(); 9537c478bd9Sstevel@tonic-gate /* 9547c478bd9Sstevel@tonic-gate * If we are at the end of the input buffer 9557c478bd9Sstevel@tonic-gate * then we are going to read fresh stuff. 9567c478bd9Sstevel@tonic-gate * Otherwise, we are rereading input and don't 9577c478bd9Sstevel@tonic-gate * need or want to prompt. 9587c478bd9Sstevel@tonic-gate */ 9597c478bd9Sstevel@tonic-gate if (fseekp == feobp) 9607c478bd9Sstevel@tonic-gate printprompt(); 9617c478bd9Sstevel@tonic-gate } 9627c478bd9Sstevel@tonic-gate err = 0; 9637c478bd9Sstevel@tonic-gate 9647c478bd9Sstevel@tonic-gate /* 9657c478bd9Sstevel@tonic-gate * Echo not only on VERBOSE, but also with history expansion. 9667c478bd9Sstevel@tonic-gate */ 9677c478bd9Sstevel@tonic-gate if (lex(¶ml) && intty || 9687c478bd9Sstevel@tonic-gate adrof(S_verbose /* "verbose" */)) { 9697c478bd9Sstevel@tonic-gate haderr = 1; 9707c478bd9Sstevel@tonic-gate prlex(¶ml); 9717c478bd9Sstevel@tonic-gate haderr = 0; 9727c478bd9Sstevel@tonic-gate } 9737c478bd9Sstevel@tonic-gate 9747c478bd9Sstevel@tonic-gate /* 9757c478bd9Sstevel@tonic-gate * The parser may lose space if interrupted. 9767c478bd9Sstevel@tonic-gate */ 9777c478bd9Sstevel@tonic-gate if (setintr) 9787c478bd9Sstevel@tonic-gate (void) sigblock(sigmask(SIGINT)); 9797c478bd9Sstevel@tonic-gate 9807c478bd9Sstevel@tonic-gate /* 9817c478bd9Sstevel@tonic-gate * Save input text on the history list if 9827c478bd9Sstevel@tonic-gate * reading in old history, or it 9837c478bd9Sstevel@tonic-gate * is from the terminal at the top level and not 9847c478bd9Sstevel@tonic-gate * in a loop. 9857c478bd9Sstevel@tonic-gate */ 9867c478bd9Sstevel@tonic-gate if (enterhist || catch && intty && !whyles) 9877c478bd9Sstevel@tonic-gate savehist(¶ml); 9887c478bd9Sstevel@tonic-gate 9897c478bd9Sstevel@tonic-gate /* 9907c478bd9Sstevel@tonic-gate * Print lexical error messages, except when sourcing 9917c478bd9Sstevel@tonic-gate * history lists. 9927c478bd9Sstevel@tonic-gate */ 9937c478bd9Sstevel@tonic-gate if (!enterhist && err) 9947c478bd9Sstevel@tonic-gate error("%s", gettext(err)); 9957c478bd9Sstevel@tonic-gate 9967c478bd9Sstevel@tonic-gate /* 9977c478bd9Sstevel@tonic-gate * If had a history command :p modifier then 9987c478bd9Sstevel@tonic-gate * this is as far as we should go 9997c478bd9Sstevel@tonic-gate */ 10007c478bd9Sstevel@tonic-gate if (justpr) 10017c478bd9Sstevel@tonic-gate reset(); 10027c478bd9Sstevel@tonic-gate 10037c478bd9Sstevel@tonic-gate alias(¶ml); 10047c478bd9Sstevel@tonic-gate 10057c478bd9Sstevel@tonic-gate /* 10067c478bd9Sstevel@tonic-gate * Parse the words of the input into a parse tree. 10077c478bd9Sstevel@tonic-gate */ 10087c478bd9Sstevel@tonic-gate t = syntax(paraml.next, ¶ml, 0); 10097c478bd9Sstevel@tonic-gate if (err) 10107c478bd9Sstevel@tonic-gate error("%s", gettext(err)); 10117c478bd9Sstevel@tonic-gate 10127c478bd9Sstevel@tonic-gate /* 10137c478bd9Sstevel@tonic-gate * Execute the parse tree 10147c478bd9Sstevel@tonic-gate */ 10157c478bd9Sstevel@tonic-gate { 10167c478bd9Sstevel@tonic-gate /* 10177c478bd9Sstevel@tonic-gate * POSIX requires SIGCHLD to be held 10187c478bd9Sstevel@tonic-gate * until all processes have joined the 10197c478bd9Sstevel@tonic-gate * process group in order to avoid race 10207c478bd9Sstevel@tonic-gate * condition. 10217c478bd9Sstevel@tonic-gate */ 10227c478bd9Sstevel@tonic-gate int omask; 10237c478bd9Sstevel@tonic-gate 10247c478bd9Sstevel@tonic-gate omask = sigblock(sigmask(SIGCHLD)); 10257c478bd9Sstevel@tonic-gate execute(t, tpgrp); 10267c478bd9Sstevel@tonic-gate (void) sigsetmask(omask &~ sigmask(SIGCHLD)); 10277c478bd9Sstevel@tonic-gate } 10287c478bd9Sstevel@tonic-gate 10297c478bd9Sstevel@tonic-gate if (err) 10307c478bd9Sstevel@tonic-gate error("%s", gettext(err)); 10317c478bd9Sstevel@tonic-gate /* 10327c478bd9Sstevel@tonic-gate * Made it! 10337c478bd9Sstevel@tonic-gate */ 10347c478bd9Sstevel@tonic-gate freelex(¶ml), freesyn(t); 10357c478bd9Sstevel@tonic-gate } 10367c478bd9Sstevel@tonic-gate resexit(osetexit); 10377c478bd9Sstevel@tonic-gate } 10387c478bd9Sstevel@tonic-gate 10396c02b4a4Smuffin void 10406c02b4a4Smuffin dosource(tchar **t) 10417c478bd9Sstevel@tonic-gate { 10426c02b4a4Smuffin tchar *f; 10436c02b4a4Smuffin int u; 10447c478bd9Sstevel@tonic-gate bool hflg = 0; 10457c478bd9Sstevel@tonic-gate tchar buf[BUFSIZ]; 10467c478bd9Sstevel@tonic-gate 10477c478bd9Sstevel@tonic-gate t++; 10487c478bd9Sstevel@tonic-gate if (*t && eq(*t, S_h /* "-h" */)) { 10497c478bd9Sstevel@tonic-gate if (*++t == NOSTR) 10507c478bd9Sstevel@tonic-gate bferr("Too few arguments."); 10517c478bd9Sstevel@tonic-gate hflg++; 10527c478bd9Sstevel@tonic-gate } 10537c478bd9Sstevel@tonic-gate (void) strcpy_(buf, *t); 10547c478bd9Sstevel@tonic-gate f = globone(buf); 10557c478bd9Sstevel@tonic-gate u = dmove(open_(f, 0), -1); 10567c478bd9Sstevel@tonic-gate xfree(f); 10577c478bd9Sstevel@tonic-gate freelex(¶ml); 10587c478bd9Sstevel@tonic-gate if (u < 0 && !hflg) 10597c478bd9Sstevel@tonic-gate Perror(f); 10607c478bd9Sstevel@tonic-gate (void) fcntl(u, F_SETFD, 1); 10617c478bd9Sstevel@tonic-gate srcunit(u, 0, hflg); 10627c478bd9Sstevel@tonic-gate } 10637c478bd9Sstevel@tonic-gate 10647c478bd9Sstevel@tonic-gate /* 10657c478bd9Sstevel@tonic-gate * Check for mail. 10667c478bd9Sstevel@tonic-gate * If we are a login shell, then we don't want to tell 10677c478bd9Sstevel@tonic-gate * about any mail file unless its been modified 10687c478bd9Sstevel@tonic-gate * after the time we started. 10697c478bd9Sstevel@tonic-gate * This prevents us from telling the user things he already 10707c478bd9Sstevel@tonic-gate * knows, since the login program insists on saying 10717c478bd9Sstevel@tonic-gate * "You have mail." 10727c478bd9Sstevel@tonic-gate */ 10736c02b4a4Smuffin void 10746c02b4a4Smuffin mailchk(void) 10757c478bd9Sstevel@tonic-gate { 10766c02b4a4Smuffin struct varent *v; 10776c02b4a4Smuffin tchar **vp; 10787c478bd9Sstevel@tonic-gate time_t t; 10797c478bd9Sstevel@tonic-gate int intvl, cnt; 10807c478bd9Sstevel@tonic-gate struct stat stb; 10817c478bd9Sstevel@tonic-gate bool new; 10827c478bd9Sstevel@tonic-gate 10837c478bd9Sstevel@tonic-gate v = adrof(S_mail /* "mail" */); 10847c478bd9Sstevel@tonic-gate if (v == 0) 10857c478bd9Sstevel@tonic-gate return; 10867c478bd9Sstevel@tonic-gate (void) time(&t); 10877c478bd9Sstevel@tonic-gate vp = v->vec; 10887c478bd9Sstevel@tonic-gate cnt = blklen(vp); 10897c478bd9Sstevel@tonic-gate intvl = (cnt && number(*vp)) ? (--cnt, getn(*vp++)) : MAILINTVL; 10907c478bd9Sstevel@tonic-gate if (intvl < 1) 10917c478bd9Sstevel@tonic-gate intvl = 1; 10927c478bd9Sstevel@tonic-gate if (chktim + intvl > t) 10937c478bd9Sstevel@tonic-gate return; 10947c478bd9Sstevel@tonic-gate for (; *vp; vp++) { 10957c478bd9Sstevel@tonic-gate if (stat_(*vp, &stb) < 0) 10967c478bd9Sstevel@tonic-gate continue; 10977c478bd9Sstevel@tonic-gate new = stb.st_mtime > time0.tv_sec; 10987c478bd9Sstevel@tonic-gate if (stb.st_size == 0 || stb.st_atime >= stb.st_mtime || 10997c478bd9Sstevel@tonic-gate (stb.st_atime <= chktim && stb.st_mtime <= chktim) || 11007c478bd9Sstevel@tonic-gate loginsh && !new) 11017c478bd9Sstevel@tonic-gate continue; 11027c478bd9Sstevel@tonic-gate if (cnt == 1) 11037c478bd9Sstevel@tonic-gate printf("You have %smail.\n", new ? "new " : ""); 11047c478bd9Sstevel@tonic-gate else 11057c478bd9Sstevel@tonic-gate printf("%s in %t.\n", new ? "New mail" : "Mail", *vp); 11067c478bd9Sstevel@tonic-gate } 11077c478bd9Sstevel@tonic-gate chktim = t; 11087c478bd9Sstevel@tonic-gate } 11097c478bd9Sstevel@tonic-gate 11107c478bd9Sstevel@tonic-gate /* 11117c478bd9Sstevel@tonic-gate * Extract a home directory from the password file 11127c478bd9Sstevel@tonic-gate * The argument points to a buffer where the name of the 11137c478bd9Sstevel@tonic-gate * user whose home directory is sought is currently. 11147c478bd9Sstevel@tonic-gate * We write the home directory of the user back there. 11157c478bd9Sstevel@tonic-gate */ 11166c02b4a4Smuffin int 11176c02b4a4Smuffin gethdir(tchar *home) 11187c478bd9Sstevel@tonic-gate { 11197c478bd9Sstevel@tonic-gate /* getpwname will not be modified, so we need temp. buffer */ 11207c478bd9Sstevel@tonic-gate char home_str[BUFSIZ]; 11217c478bd9Sstevel@tonic-gate tchar home_ts[BUFSIZ]; 11226c02b4a4Smuffin struct passwd *pp /* = getpwnam(home) */; 11237c478bd9Sstevel@tonic-gate 11247c478bd9Sstevel@tonic-gate pp = getpwnam(tstostr(home_str, home)); 11257c478bd9Sstevel@tonic-gate if (pp == 0) 11267c478bd9Sstevel@tonic-gate return (1); 11277c478bd9Sstevel@tonic-gate (void) strcpy_(home, strtots(home_ts, pp->pw_dir)); 11287c478bd9Sstevel@tonic-gate return (0); 11297c478bd9Sstevel@tonic-gate } 11307c478bd9Sstevel@tonic-gate 11317c478bd9Sstevel@tonic-gate 113265b0c20eSnakanon #if 0 11336c02b4a4Smuffin void 11347c478bd9Sstevel@tonic-gate #ifdef PROF 11356c02b4a4Smuffin done(int i) 11367c478bd9Sstevel@tonic-gate #else 11376c02b4a4Smuffin exit(int i) 11387c478bd9Sstevel@tonic-gate #endif 11397c478bd9Sstevel@tonic-gate { 11407c478bd9Sstevel@tonic-gate 11417c478bd9Sstevel@tonic-gate untty(); 11427c478bd9Sstevel@tonic-gate _exit(i); 11437c478bd9Sstevel@tonic-gate } 114465b0c20eSnakanon #endif 11457c478bd9Sstevel@tonic-gate 11466c02b4a4Smuffin void 11476c02b4a4Smuffin printprompt(void) 11487c478bd9Sstevel@tonic-gate { 11496c02b4a4Smuffin tchar *cp; 11507c478bd9Sstevel@tonic-gate 11517c478bd9Sstevel@tonic-gate if (!whyles) { 11527c478bd9Sstevel@tonic-gate /* 11537c478bd9Sstevel@tonic-gate * Print the prompt string 11547c478bd9Sstevel@tonic-gate */ 11557c478bd9Sstevel@tonic-gate for (cp = value(S_prompt /* "prompt" */); *cp; cp++) 11567c478bd9Sstevel@tonic-gate if (*cp == HIST) 11577c478bd9Sstevel@tonic-gate printf("%d", eventno + 1); 11587c478bd9Sstevel@tonic-gate else { 11597c478bd9Sstevel@tonic-gate if (*cp == '\\' && cp[1] == HIST) 11607c478bd9Sstevel@tonic-gate cp++; 11617c478bd9Sstevel@tonic-gate Putchar(*cp | QUOTE); 11627c478bd9Sstevel@tonic-gate } 11637c478bd9Sstevel@tonic-gate } else 11647c478bd9Sstevel@tonic-gate /* 11657c478bd9Sstevel@tonic-gate * Prompt for forward reading loop 11667c478bd9Sstevel@tonic-gate * body content. 11677c478bd9Sstevel@tonic-gate */ 11687c478bd9Sstevel@tonic-gate printf("? "); 11697c478bd9Sstevel@tonic-gate flush(); 11707c478bd9Sstevel@tonic-gate } 11717c478bd9Sstevel@tonic-gate 11727c478bd9Sstevel@tonic-gate /* 11737c478bd9Sstevel@tonic-gate * Save char * block. 11747c478bd9Sstevel@tonic-gate */ 11757c478bd9Sstevel@tonic-gate tchar ** 11766c02b4a4Smuffin strblktotsblk(char **v, int num) 11777c478bd9Sstevel@tonic-gate { 11786c02b4a4Smuffin tchar **newv = 117965b0c20eSnakanon (tchar **)xcalloc((unsigned)(num+ 1), sizeof (tchar **)); 11807c478bd9Sstevel@tonic-gate tchar **onewv = newv; 11817c478bd9Sstevel@tonic-gate 11827c478bd9Sstevel@tonic-gate while (*v && num--) 11837c478bd9Sstevel@tonic-gate *newv++ = strtots(NOSTR, *v++); 11847c478bd9Sstevel@tonic-gate *newv = 0; 11857c478bd9Sstevel@tonic-gate return (onewv); 11867c478bd9Sstevel@tonic-gate } 11877c478bd9Sstevel@tonic-gate 11886c02b4a4Smuffin void 11896c02b4a4Smuffin sigwaiting(void) 11907c478bd9Sstevel@tonic-gate { 11917c478bd9Sstevel@tonic-gate _signal(SIGWAITING, sigwaiting); 11927c478bd9Sstevel@tonic-gate } 11937c478bd9Sstevel@tonic-gate 11946c02b4a4Smuffin void 11956c02b4a4Smuffin siglwp(void) 11967c478bd9Sstevel@tonic-gate { 11977c478bd9Sstevel@tonic-gate _signal(SIGLWP, siglwp); 11987c478bd9Sstevel@tonic-gate } 11997c478bd9Sstevel@tonic-gate 12007c478bd9Sstevel@tonic-gate 12017c478bd9Sstevel@tonic-gate /* 12027c478bd9Sstevel@tonic-gate * Following functions and data are used for csh to do its 12037c478bd9Sstevel@tonic-gate * file descriptors book keeping. 12047c478bd9Sstevel@tonic-gate */ 12057c478bd9Sstevel@tonic-gate 12067c478bd9Sstevel@tonic-gate static int *fdinuse = NULL; /* The list of files opened by csh */ 12077c478bd9Sstevel@tonic-gate static int nbytesused = 0; /* no of bytes allocated to fdinuse */ 12087c478bd9Sstevel@tonic-gate static int max_fd = 0; /* The maximum descriptor in fdinuse */ 12097c478bd9Sstevel@tonic-gate static int my_pid; /* The process id set in initdesc() */ 12107c478bd9Sstevel@tonic-gate static int NoFile = NOFILE; /* The number of files I can use. */ 12117c478bd9Sstevel@tonic-gate 12127c478bd9Sstevel@tonic-gate /* 12137c478bd9Sstevel@tonic-gate * Get the number of files this csh can use. 12147c478bd9Sstevel@tonic-gate * 12157c478bd9Sstevel@tonic-gate * Move the initial descriptors to their eventual 12167c478bd9Sstevel@tonic-gate * resting places, closing all other units. 12177c478bd9Sstevel@tonic-gate * 12187c478bd9Sstevel@tonic-gate * Also, reserve 0/1/2, so NIS+ routines do not get 12197c478bd9Sstevel@tonic-gate * hold of them. And initialize fdinuse list and set 12207c478bd9Sstevel@tonic-gate * the current process id. 12217c478bd9Sstevel@tonic-gate * 12227c478bd9Sstevel@tonic-gate * If this csh was invoked from setuid'ed script file, 12237c478bd9Sstevel@tonic-gate * do not close the third argument passed. The file 12247c478bd9Sstevel@tonic-gate * must be one of /dev/fd/0,1,2,,, 12257c478bd9Sstevel@tonic-gate * (execv() always passes three arguments when it execs a script 12267c478bd9Sstevel@tonic-gate * file in a form of #! /bin/csh -b.) 12277c478bd9Sstevel@tonic-gate * 12287c478bd9Sstevel@tonic-gate * If is_reinit is set in initdesc_x(), then we only close the file 12297c478bd9Sstevel@tonic-gate * descriptors that we actually opened (as recorded in fdinuse). 12307c478bd9Sstevel@tonic-gate */ 12316c02b4a4Smuffin void 12326c02b4a4Smuffin initdesc(int argc, char *argv[]) 12337c478bd9Sstevel@tonic-gate { 12347c478bd9Sstevel@tonic-gate initdesc_x(argc, argv, 0); 12357c478bd9Sstevel@tonic-gate } 12367c478bd9Sstevel@tonic-gate 12376c02b4a4Smuffin void 12386c02b4a4Smuffin reinitdesc(int argc, char *argv[]) 12397c478bd9Sstevel@tonic-gate { 12407c478bd9Sstevel@tonic-gate initdesc_x(argc, argv, 1); 12417c478bd9Sstevel@tonic-gate } 12427c478bd9Sstevel@tonic-gate 12437c478bd9Sstevel@tonic-gate /* 12447c478bd9Sstevel@tonic-gate * Callback functions for closing all file descriptors. 12457c478bd9Sstevel@tonic-gate */ 12467c478bd9Sstevel@tonic-gate static int 12477c478bd9Sstevel@tonic-gate close_except(void *cd, int fd) 12487c478bd9Sstevel@tonic-gate { 12497c478bd9Sstevel@tonic-gate int script_fd = *(int *)cd; 12507c478bd9Sstevel@tonic-gate 12517c478bd9Sstevel@tonic-gate if (fd >= 3 && fd < NoFile && fd != script_fd) 12527c478bd9Sstevel@tonic-gate (void) close(fd); 12537c478bd9Sstevel@tonic-gate return (0); 12547c478bd9Sstevel@tonic-gate } 12557c478bd9Sstevel@tonic-gate 12567c478bd9Sstevel@tonic-gate static int 12577c478bd9Sstevel@tonic-gate close_inuse(void *cd, int fd) 12587c478bd9Sstevel@tonic-gate { 12597c478bd9Sstevel@tonic-gate int script_fd = *(int *)cd; 12607c478bd9Sstevel@tonic-gate 12617c478bd9Sstevel@tonic-gate if (fd >= 3 && fd < NoFile && fd != script_fd && 12627c478bd9Sstevel@tonic-gate CSH_FD_ISSET(fd, fdinuse)) { 12637c478bd9Sstevel@tonic-gate (void) close(fd); 12647c478bd9Sstevel@tonic-gate unsetfd(fd); 12657c478bd9Sstevel@tonic-gate } 12667c478bd9Sstevel@tonic-gate return (0); 12677c478bd9Sstevel@tonic-gate } 12687c478bd9Sstevel@tonic-gate 12696c02b4a4Smuffin void 12706c02b4a4Smuffin initdesc_x(int argc, char *argv[], int is_reinit) 12717c478bd9Sstevel@tonic-gate { 12727c478bd9Sstevel@tonic-gate 12737c478bd9Sstevel@tonic-gate int script_fd = -1; 12747c478bd9Sstevel@tonic-gate struct stat buf; 12757c478bd9Sstevel@tonic-gate struct rlimit rlp; 12767c478bd9Sstevel@tonic-gate 12777c478bd9Sstevel@tonic-gate /* 12787c478bd9Sstevel@tonic-gate * Get pid of this shell 12797c478bd9Sstevel@tonic-gate */ 12807c478bd9Sstevel@tonic-gate my_pid = getpid(); 12817c478bd9Sstevel@tonic-gate 12827c478bd9Sstevel@tonic-gate /* 12837c478bd9Sstevel@tonic-gate * Get the hard limit numbers of descriptors 12847c478bd9Sstevel@tonic-gate * this csh can use. 12857c478bd9Sstevel@tonic-gate */ 12867c478bd9Sstevel@tonic-gate if (getrlimit(RLIMIT_NOFILE, &rlp) == 0) 12877c478bd9Sstevel@tonic-gate NoFile = rlp.rlim_cur; 12887c478bd9Sstevel@tonic-gate 12897c478bd9Sstevel@tonic-gate /* 12907c478bd9Sstevel@tonic-gate * If this csh was invoked for executing setuid script file, 12917c478bd9Sstevel@tonic-gate * the third argument passed is the special file name 12927c478bd9Sstevel@tonic-gate * which should not be closed. This special file name is 12937c478bd9Sstevel@tonic-gate * in the form /dev/fd/X. 12947c478bd9Sstevel@tonic-gate */ 12957c478bd9Sstevel@tonic-gate if (argc >= 3) 12967c478bd9Sstevel@tonic-gate if (sscanf(argv[2], "/dev/fd/%d", &script_fd) != 1) 12977c478bd9Sstevel@tonic-gate script_fd = -1; 12987c478bd9Sstevel@tonic-gate else 12997c478bd9Sstevel@tonic-gate fcntl(script_fd, F_SETFD, 1); /* Make sure to close 13007c478bd9Sstevel@tonic-gate * this file on exec. 13017c478bd9Sstevel@tonic-gate */ 13027c478bd9Sstevel@tonic-gate 13037c478bd9Sstevel@tonic-gate if (fdinuse == NULL) { 13047c478bd9Sstevel@tonic-gate nbytesused = sizeof (int) * howmany(NoFile, sizeof (int) * NBBY); 13057c478bd9Sstevel@tonic-gate fdinuse = (int *)xalloc(nbytesused); 13067c478bd9Sstevel@tonic-gate } 13077c478bd9Sstevel@tonic-gate 13087c478bd9Sstevel@tonic-gate /* 13097c478bd9Sstevel@tonic-gate * Close all files except 0/1/2 to get a clean 13107c478bd9Sstevel@tonic-gate * file descritor space. 13117c478bd9Sstevel@tonic-gate */ 13127c478bd9Sstevel@tonic-gate if (!is_reinit) 13137c478bd9Sstevel@tonic-gate (void) fdwalk(close_except, &script_fd); 13147c478bd9Sstevel@tonic-gate else 13157c478bd9Sstevel@tonic-gate (void) fdwalk(close_inuse, &script_fd); 13167c478bd9Sstevel@tonic-gate 13177c478bd9Sstevel@tonic-gate didfds = 0; /* 0, 1, 2 aren't set up */ 13187c478bd9Sstevel@tonic-gate 13197c478bd9Sstevel@tonic-gate if (fstat(0, &buf) < 0) 13207c478bd9Sstevel@tonic-gate open("/dev/null", 0); 13217c478bd9Sstevel@tonic-gate 13227c478bd9Sstevel@tonic-gate (void) fcntl(SHIN = dcopy(0, FSHIN), F_SETFD, 1); 13237c478bd9Sstevel@tonic-gate (void) fcntl(SHOUT = dcopy(1, FSHOUT), F_SETFD, 1); 13247c478bd9Sstevel@tonic-gate (void) fcntl(SHDIAG = dcopy(2, FSHDIAG), F_SETFD, 1); 13257c478bd9Sstevel@tonic-gate (void) fcntl(OLDSTD = dcopy(SHIN, FOLDSTD), F_SETFD, 1); 13267c478bd9Sstevel@tonic-gate 13277c478bd9Sstevel@tonic-gate /* 13287c478bd9Sstevel@tonic-gate * Open 0/1/2 to avoid Nis+ functions to pick them up. 13297c478bd9Sstevel@tonic-gate * Now, 0/1/2 are saved, close them and open them. 13307c478bd9Sstevel@tonic-gate */ 13317c478bd9Sstevel@tonic-gate close(0); close(1); close(2); 13327c478bd9Sstevel@tonic-gate open("/dev/null", 0); 13337c478bd9Sstevel@tonic-gate dup(0); 13347c478bd9Sstevel@tonic-gate dup(0); 13357c478bd9Sstevel@tonic-gate 13367c478bd9Sstevel@tonic-gate /* 13377c478bd9Sstevel@tonic-gate * Clear fd_set mask 13387c478bd9Sstevel@tonic-gate */ 13397c478bd9Sstevel@tonic-gate if (!is_reinit) 13407c478bd9Sstevel@tonic-gate CSH_FD_ZERO(fdinuse, nbytesused); 13417c478bd9Sstevel@tonic-gate } 13427c478bd9Sstevel@tonic-gate 13437c478bd9Sstevel@tonic-gate /* 13447c478bd9Sstevel@tonic-gate * This routine is called after an error to close up 13457c478bd9Sstevel@tonic-gate * any units which may have been left open accidentally. 13467c478bd9Sstevel@tonic-gate * 13477c478bd9Sstevel@tonic-gate * You only need to remove files in fdinuse list. 13487c478bd9Sstevel@tonic-gate * After you have removed the files, you can clear the 13497c478bd9Sstevel@tonic-gate * list and max_fd. 13507c478bd9Sstevel@tonic-gate */ 13516c02b4a4Smuffin void 13526c02b4a4Smuffin closem(void) 13537c478bd9Sstevel@tonic-gate { 13546c02b4a4Smuffin int f; 13557c478bd9Sstevel@tonic-gate 13567c478bd9Sstevel@tonic-gate for (f = 3; f <= max_fd; f++) { 13577c478bd9Sstevel@tonic-gate if (CSH_FD_ISSET(f, fdinuse) && 13587c478bd9Sstevel@tonic-gate f != SHIN && f != SHOUT && f != SHDIAG && 13597c478bd9Sstevel@tonic-gate f != OLDSTD && f != FSHTTY) 13607c478bd9Sstevel@tonic-gate close(f); 13617c478bd9Sstevel@tonic-gate } 13627c478bd9Sstevel@tonic-gate CSH_FD_ZERO(fdinuse, nbytesused); 13637c478bd9Sstevel@tonic-gate max_fd = 0; 13647c478bd9Sstevel@tonic-gate } 13657c478bd9Sstevel@tonic-gate 13667c478bd9Sstevel@tonic-gate /* 13677c478bd9Sstevel@tonic-gate * Reset my_pid when a new process is created. Only call this 13687c478bd9Sstevel@tonic-gate * if you want the process to affect fdinuse (e.g., fork, but 13697c478bd9Sstevel@tonic-gate * not vfork). 13707c478bd9Sstevel@tonic-gate */ 13716c02b4a4Smuffin void 13726c02b4a4Smuffin new_process(void) 13737c478bd9Sstevel@tonic-gate { 13747c478bd9Sstevel@tonic-gate my_pid = getpid(); 13757c478bd9Sstevel@tonic-gate } 13767c478bd9Sstevel@tonic-gate 13777c478bd9Sstevel@tonic-gate 13787c478bd9Sstevel@tonic-gate /* 13797c478bd9Sstevel@tonic-gate * Whenever Csh open/create/dup/pipe a file or files, 13807c478bd9Sstevel@tonic-gate * Csh keeps track of its open files. The open files 13817c478bd9Sstevel@tonic-gate * are kept in "fdinuse, Fd In Use" list. 13827c478bd9Sstevel@tonic-gate * 13837c478bd9Sstevel@tonic-gate * When a file descriptor is newly allocated, setfd() is 13847c478bd9Sstevel@tonic-gate * used to mark the fact in "fdinuse" list. 13857c478bd9Sstevel@tonic-gate * For example, 13867c478bd9Sstevel@tonic-gate * fd = open("newfile", 0); 13877c478bd9Sstevel@tonic-gate * setfd(fd); 13887c478bd9Sstevel@tonic-gate * 13897c478bd9Sstevel@tonic-gate * When a file is freed by close() function, unsetfd() is 13907c478bd9Sstevel@tonic-gate * used to remove the fd from "fdinuse" list. 13917c478bd9Sstevel@tonic-gate * For example, 13927c478bd9Sstevel@tonic-gate * close(fd); 13937c478bd9Sstevel@tonic-gate * unsetfd(fd); 13947c478bd9Sstevel@tonic-gate */ 13956c02b4a4Smuffin void 13966c02b4a4Smuffin setfd(int fd) 13977c478bd9Sstevel@tonic-gate { 13987c478bd9Sstevel@tonic-gate /* 13997c478bd9Sstevel@tonic-gate * Because you want to avoid 14007c478bd9Sstevel@tonic-gate * conflict due to vfork(). 14017c478bd9Sstevel@tonic-gate */ 14027c478bd9Sstevel@tonic-gate if (my_pid != getpid()) 14037c478bd9Sstevel@tonic-gate return; 14047c478bd9Sstevel@tonic-gate 14057c478bd9Sstevel@tonic-gate if (fd >= NoFile || fd < 0) 14067c478bd9Sstevel@tonic-gate return; 14077c478bd9Sstevel@tonic-gate 14087c478bd9Sstevel@tonic-gate if (fd > max_fd) 14097c478bd9Sstevel@tonic-gate max_fd = fd; 14107c478bd9Sstevel@tonic-gate CSH_FD_SET(fd, fdinuse); 14117c478bd9Sstevel@tonic-gate } 14127c478bd9Sstevel@tonic-gate 14136c02b4a4Smuffin void 14146c02b4a4Smuffin unsetfd(int fd) 14157c478bd9Sstevel@tonic-gate { 14166c02b4a4Smuffin int i; 14177c478bd9Sstevel@tonic-gate 14187c478bd9Sstevel@tonic-gate /* 14197c478bd9Sstevel@tonic-gate * Because you want to avoid 14207c478bd9Sstevel@tonic-gate * conflict due to vfork(). 14217c478bd9Sstevel@tonic-gate */ 14227c478bd9Sstevel@tonic-gate if (my_pid != getpid()) 14237c478bd9Sstevel@tonic-gate return; 14247c478bd9Sstevel@tonic-gate 14257c478bd9Sstevel@tonic-gate if (fd >= NoFile || fd < 0) 14267c478bd9Sstevel@tonic-gate return; 14277c478bd9Sstevel@tonic-gate 14287c478bd9Sstevel@tonic-gate CSH_FD_CLR(fd, fdinuse); 14297c478bd9Sstevel@tonic-gate if (fd == max_fd) { 14307c478bd9Sstevel@tonic-gate for (i = max_fd-1; i >= 3; i--) 14317c478bd9Sstevel@tonic-gate if (CSH_FD_ISSET(i, fdinuse)) { 14327c478bd9Sstevel@tonic-gate max_fd = i; 14337c478bd9Sstevel@tonic-gate return; 14347c478bd9Sstevel@tonic-gate } 14357c478bd9Sstevel@tonic-gate max_fd = 0; 14367c478bd9Sstevel@tonic-gate } 14377c478bd9Sstevel@tonic-gate } 14387c478bd9Sstevel@tonic-gate 14397c478bd9Sstevel@tonic-gate /* 14407c478bd9Sstevel@tonic-gate * A generic call back routine to output error messages from the 14417c478bd9Sstevel@tonic-gate * policy backing functions called by pfcsh. 14427c478bd9Sstevel@tonic-gate */ 14437c478bd9Sstevel@tonic-gate void 14447c478bd9Sstevel@tonic-gate secpolicy_print(int level, const char *msg) 14457c478bd9Sstevel@tonic-gate { 14467c478bd9Sstevel@tonic-gate switch (level) { 14477c478bd9Sstevel@tonic-gate case SECPOLICY_WARN: 14487c478bd9Sstevel@tonic-gate default: 14497c478bd9Sstevel@tonic-gate haderr = 1; 14507c478bd9Sstevel@tonic-gate printf("%s: ", msg); /* printf() does gettext() */ 14517c478bd9Sstevel@tonic-gate break; 14527c478bd9Sstevel@tonic-gate case SECPOLICY_ERROR: 14536c02b4a4Smuffin bferr((char *)msg); /* bferr() does gettext() */ 14547c478bd9Sstevel@tonic-gate break; 14557c478bd9Sstevel@tonic-gate } 14567c478bd9Sstevel@tonic-gate } 1457