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