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