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