1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 3*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 4*7c478bd9Sstevel@tonic-gate */ 5*7c478bd9Sstevel@tonic-gate 6*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 7*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 8*7c478bd9Sstevel@tonic-gate 9*7c478bd9Sstevel@tonic-gate /* 10*7c478bd9Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California. 11*7c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley Software License Agreement 12*7c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 13*7c478bd9Sstevel@tonic-gate */ 14*7c478bd9Sstevel@tonic-gate 15*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 16*7c478bd9Sstevel@tonic-gate 17*7c478bd9Sstevel@tonic-gate #include <stdlib.h> /* MB_xxx, mbxxx(), wcxxx() etc. */ 18*7c478bd9Sstevel@tonic-gate #include <limits.h> 19*7c478bd9Sstevel@tonic-gate #include <sys/time.h> 20*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 21*7c478bd9Sstevel@tonic-gate #include <sys/siginfo.h> 22*7c478bd9Sstevel@tonic-gate #include <sys/ucontext.h> 23*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 24*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 25*7c478bd9Sstevel@tonic-gate #include <sys/termios.h> 26*7c478bd9Sstevel@tonic-gate #include <sys/ttold.h> 27*7c478bd9Sstevel@tonic-gate #include <errno.h> 28*7c478bd9Sstevel@tonic-gate #include <signal.h> /* std sysV signal.h */ 29*7c478bd9Sstevel@tonic-gate #include <setjmp.h> 30*7c478bd9Sstevel@tonic-gate #include <sys/resource.h> 31*7c478bd9Sstevel@tonic-gate #include "signal.h" /* mainly BSD related signal.h */ 32*7c478bd9Sstevel@tonic-gate #include "sh.local.h" 33*7c478bd9Sstevel@tonic-gate #include "sh.char.h" 34*7c478bd9Sstevel@tonic-gate 35*7c478bd9Sstevel@tonic-gate /* 36*7c478bd9Sstevel@tonic-gate * MAXHOSTNAMELEN is defined in param.h under SunOS 37*7c478bd9Sstevel@tonic-gate */ 38*7c478bd9Sstevel@tonic-gate #define MAXHOSTNAMELEN 64 39*7c478bd9Sstevel@tonic-gate 40*7c478bd9Sstevel@tonic-gate #ifdef MBCHAR 41*7c478bd9Sstevel@tonic-gate # if !defined(MB_LEN_MAX) || !defined(MB_CUR_MAX) 42*7c478bd9Sstevel@tonic-gate Error: I need both ANSI macros! 43*7c478bd9Sstevel@tonic-gate # endif 44*7c478bd9Sstevel@tonic-gate #else 45*7c478bd9Sstevel@tonic-gate # if !defined(MB_LEN_MAX) 46*7c478bd9Sstevel@tonic-gate # define MB_LEN_MAX 1 47*7c478bd9Sstevel@tonic-gate # endif 48*7c478bd9Sstevel@tonic-gate # if !defined(MB_CUR_MAX) 49*7c478bd9Sstevel@tonic-gate # define MB_CUR_MAX 1 50*7c478bd9Sstevel@tonic-gate # endif 51*7c478bd9Sstevel@tonic-gate #endif 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate #ifndef MBCHAR /* Let's replace the ANSI functions with our own macro 54*7c478bd9Sstevel@tonic-gate * for efficiency! 55*7c478bd9Sstevel@tonic-gate */ 56*7c478bd9Sstevel@tonic-gate #define mbtowc(pwc, pmb, n_is_ignored) ((*(pwc)=*(pmb)), 1) 57*7c478bd9Sstevel@tonic-gate #define wctomb(pmb, wc) ((*(pmb)=((char)wc)), 1) 58*7c478bd9Sstevel@tonic-gate #endif/*!MBCHAR*/ 59*7c478bd9Sstevel@tonic-gate 60*7c478bd9Sstevel@tonic-gate /* 61*7c478bd9Sstevel@tonic-gate * C shell 62*7c478bd9Sstevel@tonic-gate * 63*7c478bd9Sstevel@tonic-gate * Bill Joy, UC Berkeley 64*7c478bd9Sstevel@tonic-gate * October, 1978; May 1980 65*7c478bd9Sstevel@tonic-gate * 66*7c478bd9Sstevel@tonic-gate * Jim Kulp, IIASA, Laxenburg Austria 67*7c478bd9Sstevel@tonic-gate * April, 1980 68*7c478bd9Sstevel@tonic-gate */ 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate /*If we are setting the $cwd variable becuz we did a 71*7c478bd9Sstevel@tonic-gate cd, chdir, pushd, popd command, then set didchdir to 72*7c478bd9Sstevel@tonic-gate 1. This prevents globbing down when setting $cwd. 73*7c478bd9Sstevel@tonic-gate However, if the user set $cwd, we want the globbing 74*7c478bd9Sstevel@tonic-gate done; so, didchdir would be equal to 0 in that case. 75*7c478bd9Sstevel@tonic-gate */ 76*7c478bd9Sstevel@tonic-gate int didchdir; 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate #define isdir(d) ((d.st_mode & S_IFMT) == S_IFDIR) 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate typedef char bool; 81*7c478bd9Sstevel@tonic-gate 82*7c478bd9Sstevel@tonic-gate /* tchar (Tagged CHARacter) is a place holder to keep a QUOTE bit and 83*7c478bd9Sstevel@tonic-gate * a character. 84*7c478bd9Sstevel@tonic-gate * For European language handling, lower 8 bits of tchar is used 85*7c478bd9Sstevel@tonic-gate * to store a character. For other languages, especially Asian, 16 bits 86*7c478bd9Sstevel@tonic-gate * are used to store a character. 87*7c478bd9Sstevel@tonic-gate * Following typedef's assume short int is a 16-bit entity and long int is 88*7c478bd9Sstevel@tonic-gate * a 32-bit entity. 89*7c478bd9Sstevel@tonic-gate * The QUOTE bit tells whether the character is subject to further 90*7c478bd9Sstevel@tonic-gate * interpretation such as history substitution, file mathing, command 91*7c478bd9Sstevel@tonic-gate * subsitution. TRIM is a mask to strip off the QUOTE bit. 92*7c478bd9Sstevel@tonic-gate */ 93*7c478bd9Sstevel@tonic-gate #ifdef MBCHAR /* For multibyte character handling. */ 94*7c478bd9Sstevel@tonic-gate typedef long int tchar; 95*7c478bd9Sstevel@tonic-gate #define QUOTE 0x80000000 96*7c478bd9Sstevel@tonic-gate #define TRIM 0x7fffffff 97*7c478bd9Sstevel@tonic-gate #else/*!MBCHAR*/ /* European language requires only 8 bits. */ 98*7c478bd9Sstevel@tonic-gate typedef unsigned short int tchar; 99*7c478bd9Sstevel@tonic-gate #define QUOTE 0x8000 100*7c478bd9Sstevel@tonic-gate #define TRIM 0x00ff 101*7c478bd9Sstevel@tonic-gate #endif/*!MBCHAR*/ 102*7c478bd9Sstevel@tonic-gate #define eq(a, b) (strcmp_(a, b) == 0) 103*7c478bd9Sstevel@tonic-gate 104*7c478bd9Sstevel@tonic-gate extern int Putchar(tchar); 105*7c478bd9Sstevel@tonic-gate 106*7c478bd9Sstevel@tonic-gate /* 107*7c478bd9Sstevel@tonic-gate * Global flags 108*7c478bd9Sstevel@tonic-gate */ 109*7c478bd9Sstevel@tonic-gate bool chkstop; /* Warned of stopped jobs... allow exit */ 110*7c478bd9Sstevel@tonic-gate bool didfds; /* Have setup i/o fd's for child */ 111*7c478bd9Sstevel@tonic-gate bool doneinp; /* EOF indicator after reset from readc */ 112*7c478bd9Sstevel@tonic-gate bool exiterr; /* Exit if error or non-zero exit status */ 113*7c478bd9Sstevel@tonic-gate bool child; /* Child shell ... errors cause exit */ 114*7c478bd9Sstevel@tonic-gate bool haderr; /* Reset was because of an error */ 115*7c478bd9Sstevel@tonic-gate bool intty; /* Input is a tty */ 116*7c478bd9Sstevel@tonic-gate bool cflg; /* invoked with -c option */ 117*7c478bd9Sstevel@tonic-gate bool intact; /* We are interactive... therefore prompt */ 118*7c478bd9Sstevel@tonic-gate bool justpr; /* Just print because of :p hist mod */ 119*7c478bd9Sstevel@tonic-gate bool loginsh; /* We are a loginsh -> .login/.logout */ 120*7c478bd9Sstevel@tonic-gate bool neednote; /* Need to pnotify() */ 121*7c478bd9Sstevel@tonic-gate bool noexec; /* Don't execute, just syntax check */ 122*7c478bd9Sstevel@tonic-gate bool pjobs; /* want to print jobs if interrupted */ 123*7c478bd9Sstevel@tonic-gate bool pfcshflag; /* set to 0 for pfcsh */ 124*7c478bd9Sstevel@tonic-gate bool setintr; /* Set interrupts on/off -> Wait intr... */ 125*7c478bd9Sstevel@tonic-gate bool timflg; /* Time the next waited for command */ 126*7c478bd9Sstevel@tonic-gate bool havhash; /* path hashing is available */ 127*7c478bd9Sstevel@tonic-gate bool havhash2; /* cdpath hashing is available */ 128*7c478bd9Sstevel@tonic-gate #ifdef FILEC 129*7c478bd9Sstevel@tonic-gate bool filec; /* doing filename expansion */ 130*7c478bd9Sstevel@tonic-gate #endif 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate /* 133*7c478bd9Sstevel@tonic-gate * Global i/o info 134*7c478bd9Sstevel@tonic-gate */ 135*7c478bd9Sstevel@tonic-gate tchar *arginp; /* Argument input for sh -c and internal `xx` */ 136*7c478bd9Sstevel@tonic-gate int onelflg; /* 2 -> need line for -t, 1 -> exit on read */ 137*7c478bd9Sstevel@tonic-gate tchar *file; /* Name of shell file for $0 */ 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate char *err; /* Error message from scanner/parser */ 140*7c478bd9Sstevel@tonic-gate struct timeval time0; /* Time at which the shell started */ 141*7c478bd9Sstevel@tonic-gate struct rusage ru0; 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate /* 144*7c478bd9Sstevel@tonic-gate * Miscellany 145*7c478bd9Sstevel@tonic-gate */ 146*7c478bd9Sstevel@tonic-gate tchar *doldol; /* Character pid for $$ */ 147*7c478bd9Sstevel@tonic-gate int uid; /* Invokers uid */ 148*7c478bd9Sstevel@tonic-gate time_t chktim; /* Time mail last checked */ 149*7c478bd9Sstevel@tonic-gate int shpgrp; /* Pgrp of shell */ 150*7c478bd9Sstevel@tonic-gate int tpgrp; /* Terminal process group */ 151*7c478bd9Sstevel@tonic-gate /* If tpgrp is -1, leave tty alone! */ 152*7c478bd9Sstevel@tonic-gate int opgrp; /* Initial pgrp and tty pgrp */ 153*7c478bd9Sstevel@tonic-gate int oldisc; /* Initial line discipline or -1 */ 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate /* 156*7c478bd9Sstevel@tonic-gate * These are declared here because they want to be 157*7c478bd9Sstevel@tonic-gate * initialized in sh.init.c (to allow them to be made readonly) 158*7c478bd9Sstevel@tonic-gate */ 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate extern struct biltins { 161*7c478bd9Sstevel@tonic-gate tchar *bname; 162*7c478bd9Sstevel@tonic-gate int (*bfunct)(); 163*7c478bd9Sstevel@tonic-gate short minargs, maxargs; 164*7c478bd9Sstevel@tonic-gate } bfunc[]; 165*7c478bd9Sstevel@tonic-gate extern int nbfunc; 166*7c478bd9Sstevel@tonic-gate 167*7c478bd9Sstevel@tonic-gate extern struct srch { 168*7c478bd9Sstevel@tonic-gate tchar *s_name; 169*7c478bd9Sstevel@tonic-gate short s_value; 170*7c478bd9Sstevel@tonic-gate } srchn[]; 171*7c478bd9Sstevel@tonic-gate extern int nsrchn; 172*7c478bd9Sstevel@tonic-gate 173*7c478bd9Sstevel@tonic-gate /* 174*7c478bd9Sstevel@tonic-gate * To be able to redirect i/o for builtins easily, the shell moves the i/o 175*7c478bd9Sstevel@tonic-gate * descriptors it uses away from 0,1,2. 176*7c478bd9Sstevel@tonic-gate * Ideally these should be in units which are closed across exec's 177*7c478bd9Sstevel@tonic-gate * (this saves work) but for version 6, this is not usually possible. 178*7c478bd9Sstevel@tonic-gate * The desired initial values for these descriptors are defined in 179*7c478bd9Sstevel@tonic-gate * sh.local.h. 180*7c478bd9Sstevel@tonic-gate */ 181*7c478bd9Sstevel@tonic-gate short SHIN; /* Current shell input (script) */ 182*7c478bd9Sstevel@tonic-gate short SHOUT; /* Shell output */ 183*7c478bd9Sstevel@tonic-gate short SHDIAG; /* Diagnostic output... shell errs go here */ 184*7c478bd9Sstevel@tonic-gate short OLDSTD; /* Old standard input (def for cmds) */ 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate /* 187*7c478bd9Sstevel@tonic-gate * Error control 188*7c478bd9Sstevel@tonic-gate * 189*7c478bd9Sstevel@tonic-gate * Errors in scanning and parsing set up an error message to be printed 190*7c478bd9Sstevel@tonic-gate * at the end and complete. Other errors always cause a reset. 191*7c478bd9Sstevel@tonic-gate * Because of source commands and .cshrc we need nested error catches. 192*7c478bd9Sstevel@tonic-gate */ 193*7c478bd9Sstevel@tonic-gate 194*7c478bd9Sstevel@tonic-gate jmp_buf reslab; 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate #define setexit() ((void) setjmp(reslab)) 197*7c478bd9Sstevel@tonic-gate #define reset() longjmp(reslab, 0) 198*7c478bd9Sstevel@tonic-gate /* Should use structure assignment here */ 199*7c478bd9Sstevel@tonic-gate #define getexit(a) copy((void *)(a), (void *)reslab, sizeof reslab) 200*7c478bd9Sstevel@tonic-gate #define resexit(a) copy((void *)reslab, ((void *)(a)), sizeof reslab) 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate tchar *gointr; /* Label for an onintr transfer */ 203*7c478bd9Sstevel@tonic-gate void (*parintr)(); /* Parents interrupt catch */ 204*7c478bd9Sstevel@tonic-gate void (*parterm)(); /* Parents terminate catch */ 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate 207*7c478bd9Sstevel@tonic-gate /* 208*7c478bd9Sstevel@tonic-gate * Each level of input has a buffered input structure. 209*7c478bd9Sstevel@tonic-gate * There are one or more blocks of buffered input for each level, 210*7c478bd9Sstevel@tonic-gate * exactly one if the input is seekable and tell is available. 211*7c478bd9Sstevel@tonic-gate * In other cases, the shell buffers enough blocks to keep all loops 212*7c478bd9Sstevel@tonic-gate * in the buffer. 213*7c478bd9Sstevel@tonic-gate */ 214*7c478bd9Sstevel@tonic-gate struct Bin { 215*7c478bd9Sstevel@tonic-gate off_t Bfseekp; /* Seek pointer */ 216*7c478bd9Sstevel@tonic-gate off_t Bfbobp; /* Seekp of beginning of buffers */ 217*7c478bd9Sstevel@tonic-gate off_t Bfeobp; /* Seekp of end of buffers */ 218*7c478bd9Sstevel@tonic-gate short Bfblocks; /* Number of buffer blocks */ 219*7c478bd9Sstevel@tonic-gate tchar **Bfbuf; /* The array of buffer blocks */ 220*7c478bd9Sstevel@tonic-gate } B; 221*7c478bd9Sstevel@tonic-gate 222*7c478bd9Sstevel@tonic-gate #define fseekp B.Bfseekp 223*7c478bd9Sstevel@tonic-gate #define fbobp B.Bfbobp 224*7c478bd9Sstevel@tonic-gate #define feobp B.Bfeobp 225*7c478bd9Sstevel@tonic-gate #define fblocks B.Bfblocks 226*7c478bd9Sstevel@tonic-gate #define fbuf B.Bfbuf 227*7c478bd9Sstevel@tonic-gate 228*7c478bd9Sstevel@tonic-gate #define btell() fseekp 229*7c478bd9Sstevel@tonic-gate 230*7c478bd9Sstevel@tonic-gate #ifndef btell 231*7c478bd9Sstevel@tonic-gate off_t btell(); 232*7c478bd9Sstevel@tonic-gate #endif 233*7c478bd9Sstevel@tonic-gate 234*7c478bd9Sstevel@tonic-gate /* 235*7c478bd9Sstevel@tonic-gate * The shell finds commands in loops by reseeking the input 236*7c478bd9Sstevel@tonic-gate * For whiles, in particular, it reseeks to the beginning of the 237*7c478bd9Sstevel@tonic-gate * line the while was on; hence the while placement restrictions. 238*7c478bd9Sstevel@tonic-gate */ 239*7c478bd9Sstevel@tonic-gate off_t lineloc; 240*7c478bd9Sstevel@tonic-gate 241*7c478bd9Sstevel@tonic-gate #ifdef TELL 242*7c478bd9Sstevel@tonic-gate bool cantell; /* Is current source tellable ? */ 243*7c478bd9Sstevel@tonic-gate #endif 244*7c478bd9Sstevel@tonic-gate 245*7c478bd9Sstevel@tonic-gate /* 246*7c478bd9Sstevel@tonic-gate * Input lines are parsed into doubly linked circular 247*7c478bd9Sstevel@tonic-gate * lists of words of the following form. 248*7c478bd9Sstevel@tonic-gate */ 249*7c478bd9Sstevel@tonic-gate struct wordent { 250*7c478bd9Sstevel@tonic-gate tchar *word; 251*7c478bd9Sstevel@tonic-gate struct wordent *prev; 252*7c478bd9Sstevel@tonic-gate struct wordent *next; 253*7c478bd9Sstevel@tonic-gate }; 254*7c478bd9Sstevel@tonic-gate 255*7c478bd9Sstevel@tonic-gate /* 256*7c478bd9Sstevel@tonic-gate * During word building, both in the initial lexical phase and 257*7c478bd9Sstevel@tonic-gate * when expanding $ variable substitutions, expansion by `!' and `$' 258*7c478bd9Sstevel@tonic-gate * must be inhibited when reading ahead in routines which are themselves 259*7c478bd9Sstevel@tonic-gate * processing `!' and `$' expansion or after characters such as `\' or in 260*7c478bd9Sstevel@tonic-gate * quotations. The following flags are passed to the getC routines 261*7c478bd9Sstevel@tonic-gate * telling them which of these substitutions are appropriate for the 262*7c478bd9Sstevel@tonic-gate * next character to be returned. 263*7c478bd9Sstevel@tonic-gate */ 264*7c478bd9Sstevel@tonic-gate #define DODOL 1 265*7c478bd9Sstevel@tonic-gate #define DOEXCL 2 266*7c478bd9Sstevel@tonic-gate #define DOALL DODOL|DOEXCL 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate /* 269*7c478bd9Sstevel@tonic-gate * Labuf implements a general buffer for lookahead during lexical operations. 270*7c478bd9Sstevel@tonic-gate * Text which is to be placed in the input stream can be stuck here. 271*7c478bd9Sstevel@tonic-gate * We stick parsed ahead $ constructs during initial input, 272*7c478bd9Sstevel@tonic-gate * process id's from `$$', and modified variable values (from qualifiers 273*7c478bd9Sstevel@tonic-gate * during expansion in sh.dol.c) here. 274*7c478bd9Sstevel@tonic-gate */ 275*7c478bd9Sstevel@tonic-gate tchar *labuf; 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate tchar *lap; 278*7c478bd9Sstevel@tonic-gate 279*7c478bd9Sstevel@tonic-gate /* 280*7c478bd9Sstevel@tonic-gate * Parser structure 281*7c478bd9Sstevel@tonic-gate * 282*7c478bd9Sstevel@tonic-gate * Each command is parsed to a tree of command structures and 283*7c478bd9Sstevel@tonic-gate * flags are set bottom up during this process, to be propagated down 284*7c478bd9Sstevel@tonic-gate * as needed during the semantics/exeuction pass (sh.sem.c). 285*7c478bd9Sstevel@tonic-gate */ 286*7c478bd9Sstevel@tonic-gate struct command { 287*7c478bd9Sstevel@tonic-gate short t_dtyp; /* Type of node */ 288*7c478bd9Sstevel@tonic-gate short t_dflg; /* Flags, e.g. FAND|... */ 289*7c478bd9Sstevel@tonic-gate union { 290*7c478bd9Sstevel@tonic-gate tchar *T_dlef; /* Input redirect word */ 291*7c478bd9Sstevel@tonic-gate struct command *T_dcar; /* Left part of list/pipe */ 292*7c478bd9Sstevel@tonic-gate } L; 293*7c478bd9Sstevel@tonic-gate union { 294*7c478bd9Sstevel@tonic-gate tchar *T_drit; /* Output redirect word */ 295*7c478bd9Sstevel@tonic-gate struct command *T_dcdr; /* Right part of list/pipe */ 296*7c478bd9Sstevel@tonic-gate } R; 297*7c478bd9Sstevel@tonic-gate #define t_dlef L.T_dlef 298*7c478bd9Sstevel@tonic-gate #define t_dcar L.T_dcar 299*7c478bd9Sstevel@tonic-gate #define t_drit R.T_drit 300*7c478bd9Sstevel@tonic-gate #define t_dcdr R.T_dcdr 301*7c478bd9Sstevel@tonic-gate tchar **t_dcom; /* Command/argument vector */ 302*7c478bd9Sstevel@tonic-gate char *cfname; /* char pathname for execv */ 303*7c478bd9Sstevel@tonic-gate char **cargs; /* char arg vec for execv */ 304*7c478bd9Sstevel@tonic-gate struct command *t_dspr; /* Pointer to ()'d subtree */ 305*7c478bd9Sstevel@tonic-gate short t_nice; 306*7c478bd9Sstevel@tonic-gate }; 307*7c478bd9Sstevel@tonic-gate 308*7c478bd9Sstevel@tonic-gate #define TCOM 1 /* t_dcom <t_dlef >t_drit */ 309*7c478bd9Sstevel@tonic-gate #define TPAR 2 /* ( t_dspr ) <t_dlef >t_drit */ 310*7c478bd9Sstevel@tonic-gate #define TFIL 3 /* t_dlef | t_drit */ 311*7c478bd9Sstevel@tonic-gate #define TLST 4 /* t_dlef ; t_drit */ 312*7c478bd9Sstevel@tonic-gate #define TOR 5 /* t_dlef || t_drit */ 313*7c478bd9Sstevel@tonic-gate #define TAND 6 /* t_dlef && t_drit */ 314*7c478bd9Sstevel@tonic-gate 315*7c478bd9Sstevel@tonic-gate #define FSAVE (FNICE|FTIME|FNOHUP) /* save these when re-doing */ 316*7c478bd9Sstevel@tonic-gate 317*7c478bd9Sstevel@tonic-gate #define FAND (1<<0) /* executes in background */ 318*7c478bd9Sstevel@tonic-gate #define FCAT (1<<1) /* output is redirected >> */ 319*7c478bd9Sstevel@tonic-gate #define FPIN (1<<2) /* input is a pipe */ 320*7c478bd9Sstevel@tonic-gate #define FPOU (1<<3) /* output is a pipe */ 321*7c478bd9Sstevel@tonic-gate #define FPAR (1<<4) /* don't fork, last ()ized cmd */ 322*7c478bd9Sstevel@tonic-gate #define FINT (1<<5) /* should be immune from intr's */ 323*7c478bd9Sstevel@tonic-gate /* spare */ 324*7c478bd9Sstevel@tonic-gate #define FDIAG (1<<7) /* redirect unit 2 with unit 1 */ 325*7c478bd9Sstevel@tonic-gate #define FANY (1<<8) /* output was ! */ 326*7c478bd9Sstevel@tonic-gate #define FHERE (1<<9) /* input redirection is << */ 327*7c478bd9Sstevel@tonic-gate #define FREDO (1<<10) /* reexec aft if, repeat,... */ 328*7c478bd9Sstevel@tonic-gate #define FNICE (1<<11) /* t_nice is meaningful */ 329*7c478bd9Sstevel@tonic-gate #define FNOHUP (1<<12) /* nohup this command */ 330*7c478bd9Sstevel@tonic-gate #define FTIME (1<<13) /* time this command */ 331*7c478bd9Sstevel@tonic-gate 332*7c478bd9Sstevel@tonic-gate /* 333*7c478bd9Sstevel@tonic-gate * The keywords for the parser 334*7c478bd9Sstevel@tonic-gate */ 335*7c478bd9Sstevel@tonic-gate #define ZBREAK 0 336*7c478bd9Sstevel@tonic-gate #define ZBRKSW 1 337*7c478bd9Sstevel@tonic-gate #define ZCASE 2 338*7c478bd9Sstevel@tonic-gate #define ZDEFAULT 3 339*7c478bd9Sstevel@tonic-gate #define ZELSE 4 340*7c478bd9Sstevel@tonic-gate #define ZEND 5 341*7c478bd9Sstevel@tonic-gate #define ZENDIF 6 342*7c478bd9Sstevel@tonic-gate #define ZENDSW 7 343*7c478bd9Sstevel@tonic-gate #define ZEXIT 8 344*7c478bd9Sstevel@tonic-gate #define ZFOREACH 9 345*7c478bd9Sstevel@tonic-gate #define ZGOTO 10 346*7c478bd9Sstevel@tonic-gate #define ZIF 11 347*7c478bd9Sstevel@tonic-gate #define ZLABEL 12 348*7c478bd9Sstevel@tonic-gate #define ZLET 13 349*7c478bd9Sstevel@tonic-gate #define ZSET 14 350*7c478bd9Sstevel@tonic-gate #define ZSWITCH 15 351*7c478bd9Sstevel@tonic-gate #define ZTEST 16 352*7c478bd9Sstevel@tonic-gate #define ZTHEN 17 353*7c478bd9Sstevel@tonic-gate #define ZWHILE 18 354*7c478bd9Sstevel@tonic-gate 355*7c478bd9Sstevel@tonic-gate /* 356*7c478bd9Sstevel@tonic-gate * Structure defining the existing while/foreach loops at this 357*7c478bd9Sstevel@tonic-gate * source level. Loops are implemented by seeking back in the 358*7c478bd9Sstevel@tonic-gate * input. For foreach (fe), the word list is attached here. 359*7c478bd9Sstevel@tonic-gate */ 360*7c478bd9Sstevel@tonic-gate struct whyle { 361*7c478bd9Sstevel@tonic-gate off_t w_start; /* Point to restart loop */ 362*7c478bd9Sstevel@tonic-gate off_t w_end; /* End of loop (0 if unknown) */ 363*7c478bd9Sstevel@tonic-gate tchar **w_fe, **w_fe0; /* Current/initial wordlist for fe */ 364*7c478bd9Sstevel@tonic-gate tchar *w_fename; /* Name for fe */ 365*7c478bd9Sstevel@tonic-gate struct whyle *w_next; /* Next (more outer) loop */ 366*7c478bd9Sstevel@tonic-gate } *whyles; 367*7c478bd9Sstevel@tonic-gate 368*7c478bd9Sstevel@tonic-gate /* 369*7c478bd9Sstevel@tonic-gate * Variable structure 370*7c478bd9Sstevel@tonic-gate * 371*7c478bd9Sstevel@tonic-gate * Aliases and variables are stored in AVL balanced binary trees. 372*7c478bd9Sstevel@tonic-gate */ 373*7c478bd9Sstevel@tonic-gate struct varent { 374*7c478bd9Sstevel@tonic-gate tchar **vec; /* Array of words which is the value */ 375*7c478bd9Sstevel@tonic-gate tchar *v_name; /* Name of variable/alias */ 376*7c478bd9Sstevel@tonic-gate struct varent *v_link[3]; /* The links, see below */ 377*7c478bd9Sstevel@tonic-gate int v_bal; /* Balance factor */ 378*7c478bd9Sstevel@tonic-gate } shvhed, aliases; 379*7c478bd9Sstevel@tonic-gate #define v_left v_link[0] 380*7c478bd9Sstevel@tonic-gate #define v_right v_link[1] 381*7c478bd9Sstevel@tonic-gate #define v_parent v_link[2] 382*7c478bd9Sstevel@tonic-gate 383*7c478bd9Sstevel@tonic-gate struct varent *adrof1(); 384*7c478bd9Sstevel@tonic-gate #define adrof(v) adrof1(v, &shvhed) 385*7c478bd9Sstevel@tonic-gate #define value(v) value1(v, &shvhed) 386*7c478bd9Sstevel@tonic-gate 387*7c478bd9Sstevel@tonic-gate /* 388*7c478bd9Sstevel@tonic-gate * MAX_VAR_LEN - maximum variable name defined by csh man page to be 20 389*7c478bd9Sstevel@tonic-gate */ 390*7c478bd9Sstevel@tonic-gate #define MAX_VAR_LEN 20 391*7c478bd9Sstevel@tonic-gate 392*7c478bd9Sstevel@tonic-gate /* 393*7c478bd9Sstevel@tonic-gate * MAX_VREF_LEN - maximum variable reference $name[...] 394*7c478bd9Sstevel@tonic-gate * it can be as big as a csh word, which is 1024 395*7c478bd9Sstevel@tonic-gate */ 396*7c478bd9Sstevel@tonic-gate #define MAX_VREF_LEN 1024 397*7c478bd9Sstevel@tonic-gate 398*7c478bd9Sstevel@tonic-gate 399*7c478bd9Sstevel@tonic-gate /* 400*7c478bd9Sstevel@tonic-gate * The following are for interfacing redo substitution in 401*7c478bd9Sstevel@tonic-gate * aliases to the lexical routines. 402*7c478bd9Sstevel@tonic-gate */ 403*7c478bd9Sstevel@tonic-gate struct wordent *alhistp; /* Argument list (first) */ 404*7c478bd9Sstevel@tonic-gate struct wordent *alhistt; /* Node after last in arg list */ 405*7c478bd9Sstevel@tonic-gate tchar **alvec; /* The (remnants of) alias vector */ 406*7c478bd9Sstevel@tonic-gate 407*7c478bd9Sstevel@tonic-gate /* 408*7c478bd9Sstevel@tonic-gate * Filename/command name expansion variables 409*7c478bd9Sstevel@tonic-gate */ 410*7c478bd9Sstevel@tonic-gate short gflag; /* After tglob -> is globbing needed? */ 411*7c478bd9Sstevel@tonic-gate 412*7c478bd9Sstevel@tonic-gate /* 413*7c478bd9Sstevel@tonic-gate * A reasonable limit on number of arguments would seem to be 414*7c478bd9Sstevel@tonic-gate * the maximum number of characters in an arg list / 6. 415*7c478bd9Sstevel@tonic-gate * 416*7c478bd9Sstevel@tonic-gate * XXX: With the new VM system, NCARGS has become enormous, making 417*7c478bd9Sstevel@tonic-gate * it impractical to allocate arrays with NCARGS / 6 entries on 418*7c478bd9Sstevel@tonic-gate * the stack. The proper fix is to revamp code elsewhere (in 419*7c478bd9Sstevel@tonic-gate * sh.dol.c and sh.glob.c) to use a different technique for handling 420*7c478bd9Sstevel@tonic-gate * command line arguments. In the meantime, we simply fall back 421*7c478bd9Sstevel@tonic-gate * on using the old value of NCARGS. 422*7c478bd9Sstevel@tonic-gate */ 423*7c478bd9Sstevel@tonic-gate #ifdef notyet 424*7c478bd9Sstevel@tonic-gate #define GAVSIZ (NCARGS / 6) 425*7c478bd9Sstevel@tonic-gate #else notyet 426*7c478bd9Sstevel@tonic-gate #define GAVSIZ (10240 / 6) 427*7c478bd9Sstevel@tonic-gate #endif notyet 428*7c478bd9Sstevel@tonic-gate 429*7c478bd9Sstevel@tonic-gate /* 430*7c478bd9Sstevel@tonic-gate * Variables for filename expansion 431*7c478bd9Sstevel@tonic-gate */ 432*7c478bd9Sstevel@tonic-gate tchar **gargv; /* Pointer to the (stack) arglist */ 433*7c478bd9Sstevel@tonic-gate long gargc; /* Number args in gargv */ 434*7c478bd9Sstevel@tonic-gate long gnleft; 435*7c478bd9Sstevel@tonic-gate 436*7c478bd9Sstevel@tonic-gate /* 437*7c478bd9Sstevel@tonic-gate * Variables for command expansion. 438*7c478bd9Sstevel@tonic-gate */ 439*7c478bd9Sstevel@tonic-gate tchar **pargv; /* Pointer to the argv list space */ 440*7c478bd9Sstevel@tonic-gate tchar *pargs; /* Pointer to start current word */ 441*7c478bd9Sstevel@tonic-gate long pargc; /* Count of arguments in pargv */ 442*7c478bd9Sstevel@tonic-gate long pnleft; /* Number of chars left in pargs */ 443*7c478bd9Sstevel@tonic-gate tchar *pargcp; /* Current index into pargs */ 444*7c478bd9Sstevel@tonic-gate 445*7c478bd9Sstevel@tonic-gate /* 446*7c478bd9Sstevel@tonic-gate * History list 447*7c478bd9Sstevel@tonic-gate * 448*7c478bd9Sstevel@tonic-gate * Each history list entry contains an embedded wordlist 449*7c478bd9Sstevel@tonic-gate * from the scanner, a number for the event, and a reference count 450*7c478bd9Sstevel@tonic-gate * to aid in discarding old entries. 451*7c478bd9Sstevel@tonic-gate * 452*7c478bd9Sstevel@tonic-gate * Essentially "invisible" entries are put on the history list 453*7c478bd9Sstevel@tonic-gate * when history substitution includes modifiers, and thrown away 454*7c478bd9Sstevel@tonic-gate * at the next discarding since their event numbers are very negative. 455*7c478bd9Sstevel@tonic-gate */ 456*7c478bd9Sstevel@tonic-gate struct Hist { 457*7c478bd9Sstevel@tonic-gate struct wordent Hlex; 458*7c478bd9Sstevel@tonic-gate int Hnum; 459*7c478bd9Sstevel@tonic-gate int Href; 460*7c478bd9Sstevel@tonic-gate struct Hist *Hnext; 461*7c478bd9Sstevel@tonic-gate } Histlist; 462*7c478bd9Sstevel@tonic-gate 463*7c478bd9Sstevel@tonic-gate struct wordent paraml; /* Current lexical word list */ 464*7c478bd9Sstevel@tonic-gate int eventno; /* Next events number */ 465*7c478bd9Sstevel@tonic-gate int lastev; /* Last event reference (default) */ 466*7c478bd9Sstevel@tonic-gate 467*7c478bd9Sstevel@tonic-gate tchar HIST; /* history invocation character */ 468*7c478bd9Sstevel@tonic-gate tchar HISTSUB; /* auto-substitute character */ 469*7c478bd9Sstevel@tonic-gate 470*7c478bd9Sstevel@tonic-gate /* 471*7c478bd9Sstevel@tonic-gate * In lines for frequently called functions 472*7c478bd9Sstevel@tonic-gate * 473*7c478bd9Sstevel@tonic-gate * WARNING: changes here also need to occur in the xfree() function in 474*7c478bd9Sstevel@tonic-gate * sh.misc.c. 475*7c478bd9Sstevel@tonic-gate */ 476*7c478bd9Sstevel@tonic-gate #if defined(sparc) 477*7c478bd9Sstevel@tonic-gate #define XFREE(cp) { \ 478*7c478bd9Sstevel@tonic-gate extern char end[]; \ 479*7c478bd9Sstevel@tonic-gate char stack; \ 480*7c478bd9Sstevel@tonic-gate /*??*/ if (((char *)(cp)) >= end && ((char *)(cp)) < &stack) \ 481*7c478bd9Sstevel@tonic-gate /*??*/ free((void *)(cp)); \ 482*7c478bd9Sstevel@tonic-gate } 483*7c478bd9Sstevel@tonic-gate #elif defined(i386) 484*7c478bd9Sstevel@tonic-gate #define XFREE(cp) { \ 485*7c478bd9Sstevel@tonic-gate extern char end[]; \ 486*7c478bd9Sstevel@tonic-gate if (((char *)(cp)) >= end) \ 487*7c478bd9Sstevel@tonic-gate free((void *)(cp)); \ 488*7c478bd9Sstevel@tonic-gate } 489*7c478bd9Sstevel@tonic-gate #else 490*7c478bd9Sstevel@tonic-gate #error XFREE macro is machine dependant and no machine type is recognized 491*7c478bd9Sstevel@tonic-gate #endif 492*7c478bd9Sstevel@tonic-gate void *alloctmp; 493*7c478bd9Sstevel@tonic-gate #define xalloc(i) ((alloctmp = (void *)malloc(i)) ? alloctmp : (void *)nomem(i))/*??*/ 494*7c478bd9Sstevel@tonic-gate #define xrealloc(buf, i) ((alloctmp = (void *)realloc(buf, i)) ? alloctmp : \ 495*7c478bd9Sstevel@tonic-gate (void *)nomem(i)) 496*7c478bd9Sstevel@tonic-gate 497*7c478bd9Sstevel@tonic-gate tchar *Dfix1(); 498*7c478bd9Sstevel@tonic-gate tchar **blkcat(); 499*7c478bd9Sstevel@tonic-gate tchar **blkcpy(); 500*7c478bd9Sstevel@tonic-gate tchar **blkend(); 501*7c478bd9Sstevel@tonic-gate tchar **blkspl(); 502*7c478bd9Sstevel@tonic-gate char **blkspl_(); 503*7c478bd9Sstevel@tonic-gate void *malloc(); 504*7c478bd9Sstevel@tonic-gate tchar *cname(); 505*7c478bd9Sstevel@tonic-gate tchar **copyblk(); 506*7c478bd9Sstevel@tonic-gate tchar **dobackp(); 507*7c478bd9Sstevel@tonic-gate tchar *domod(); 508*7c478bd9Sstevel@tonic-gate struct wordent *dosub(); 509*7c478bd9Sstevel@tonic-gate tchar *exp3(); 510*7c478bd9Sstevel@tonic-gate tchar *exp3a(); 511*7c478bd9Sstevel@tonic-gate tchar *exp4(); 512*7c478bd9Sstevel@tonic-gate tchar *exp5(); 513*7c478bd9Sstevel@tonic-gate tchar *exp6(); 514*7c478bd9Sstevel@tonic-gate struct Hist *enthist(); 515*7c478bd9Sstevel@tonic-gate struct Hist *findev(); 516*7c478bd9Sstevel@tonic-gate struct wordent *freenod(); 517*7c478bd9Sstevel@tonic-gate char *getenv(); 518*7c478bd9Sstevel@tonic-gate tchar *getenv_(/* tchar * */); 519*7c478bd9Sstevel@tonic-gate tchar *getenvs_(/* char * */); 520*7c478bd9Sstevel@tonic-gate tchar *getinx(); 521*7c478bd9Sstevel@tonic-gate struct varent *getvx(); 522*7c478bd9Sstevel@tonic-gate struct passwd *getpwnam(); 523*7c478bd9Sstevel@tonic-gate struct wordent *gethent(); 524*7c478bd9Sstevel@tonic-gate struct wordent *getsub(); 525*7c478bd9Sstevel@tonic-gate char *getwd(); 526*7c478bd9Sstevel@tonic-gate tchar *getwd_(); 527*7c478bd9Sstevel@tonic-gate tchar **glob(); 528*7c478bd9Sstevel@tonic-gate tchar *globone(); 529*7c478bd9Sstevel@tonic-gate char *index(); 530*7c478bd9Sstevel@tonic-gate tchar *index_(); 531*7c478bd9Sstevel@tonic-gate struct biltins *isbfunc(); 532*7c478bd9Sstevel@tonic-gate off_t lseek(); 533*7c478bd9Sstevel@tonic-gate tchar *operate(); 534*7c478bd9Sstevel@tonic-gate void phup(); 535*7c478bd9Sstevel@tonic-gate void pintr(); 536*7c478bd9Sstevel@tonic-gate void pchild(); 537*7c478bd9Sstevel@tonic-gate tchar *putn(); 538*7c478bd9Sstevel@tonic-gate char *rindex(); 539*7c478bd9Sstevel@tonic-gate tchar *rindex_(); 540*7c478bd9Sstevel@tonic-gate tchar **saveblk(); 541*7c478bd9Sstevel@tonic-gate tchar *savestr(); 542*7c478bd9Sstevel@tonic-gate char *strcat(); 543*7c478bd9Sstevel@tonic-gate tchar *strcat_(); 544*7c478bd9Sstevel@tonic-gate int strlen_(tchar *); 545*7c478bd9Sstevel@tonic-gate char *strcpy(); 546*7c478bd9Sstevel@tonic-gate tchar *strcpy_(); 547*7c478bd9Sstevel@tonic-gate tchar *strend(); 548*7c478bd9Sstevel@tonic-gate tchar *strip(); 549*7c478bd9Sstevel@tonic-gate tchar *strspl(); 550*7c478bd9Sstevel@tonic-gate tchar *subword(); 551*7c478bd9Sstevel@tonic-gate struct command *syntax(); 552*7c478bd9Sstevel@tonic-gate struct command *syn0(); 553*7c478bd9Sstevel@tonic-gate struct command *syn1(); 554*7c478bd9Sstevel@tonic-gate struct command *syn1a(); 555*7c478bd9Sstevel@tonic-gate struct command *syn1b(); 556*7c478bd9Sstevel@tonic-gate struct command *syn2(); 557*7c478bd9Sstevel@tonic-gate struct command *syn3(); 558*7c478bd9Sstevel@tonic-gate tchar *value1(); 559*7c478bd9Sstevel@tonic-gate tchar *xhome(); 560*7c478bd9Sstevel@tonic-gate tchar *xname(); 561*7c478bd9Sstevel@tonic-gate tchar *xset(); 562*7c478bd9Sstevel@tonic-gate 563*7c478bd9Sstevel@tonic-gate #define NOSTR ((tchar *) 0) 564*7c478bd9Sstevel@tonic-gate 565*7c478bd9Sstevel@tonic-gate /* 566*7c478bd9Sstevel@tonic-gate * setname is a macro to copy the path in bname. (see sh.err.c) 567*7c478bd9Sstevel@tonic-gate * Here we are dynamically reallocating the bname to the new length 568*7c478bd9Sstevel@tonic-gate * to store the new path 569*7c478bd9Sstevel@tonic-gate */ 570*7c478bd9Sstevel@tonic-gate tchar *bname; 571*7c478bd9Sstevel@tonic-gate #define setname(a) { \ 572*7c478bd9Sstevel@tonic-gate bname = xrealloc(bname, (strlen_(a)+1) * sizeof (tchar)); \ 573*7c478bd9Sstevel@tonic-gate strcpy_(bname, a); \ 574*7c478bd9Sstevel@tonic-gate bname[strlen_(a)] = '\0'; \ 575*7c478bd9Sstevel@tonic-gate } 576*7c478bd9Sstevel@tonic-gate 577*7c478bd9Sstevel@tonic-gate #ifdef VFORK 578*7c478bd9Sstevel@tonic-gate tchar *Vsav; 579*7c478bd9Sstevel@tonic-gate tchar **Vav; 580*7c478bd9Sstevel@tonic-gate tchar *Vdp; 581*7c478bd9Sstevel@tonic-gate #endif 582*7c478bd9Sstevel@tonic-gate 583*7c478bd9Sstevel@tonic-gate tchar **evalvec; 584*7c478bd9Sstevel@tonic-gate tchar *evalp; 585*7c478bd9Sstevel@tonic-gate 586*7c478bd9Sstevel@tonic-gate /* Conversion functions between char and tchar strings. */ 587*7c478bd9Sstevel@tonic-gate tchar *strtots(/* tchar * , char * */); 588*7c478bd9Sstevel@tonic-gate char *tstostr(/* char * , tchar * */); 589*7c478bd9Sstevel@tonic-gate 590*7c478bd9Sstevel@tonic-gate #ifndef NULL 591*7c478bd9Sstevel@tonic-gate #define NULL 0 592*7c478bd9Sstevel@tonic-gate #endif 593*7c478bd9Sstevel@tonic-gate 594*7c478bd9Sstevel@tonic-gate 595*7c478bd9Sstevel@tonic-gate /* 596*7c478bd9Sstevel@tonic-gate * Xhash is an array of HSHSIZ bits (HSHSIZ / 8 chars), which are used 597*7c478bd9Sstevel@tonic-gate * to hash execs. If it is allocated (havhash true), then to tell 598*7c478bd9Sstevel@tonic-gate * whether ``name'' is (possibly) present in the i'th component 599*7c478bd9Sstevel@tonic-gate * of the variable path, you look at the bit in xhash indexed by 600*7c478bd9Sstevel@tonic-gate * hash(hashname("name"), i). This is setup automatically 601*7c478bd9Sstevel@tonic-gate * after .login is executed, and recomputed whenever ``path'' is 602*7c478bd9Sstevel@tonic-gate * changed. 603*7c478bd9Sstevel@tonic-gate * The two part hash function is designed to let texec() call the 604*7c478bd9Sstevel@tonic-gate * more expensive hashname() only once and the simple hash() several 605*7c478bd9Sstevel@tonic-gate * times (once for each path component checked). 606*7c478bd9Sstevel@tonic-gate * Byte size is assumed to be 8. 607*7c478bd9Sstevel@tonic-gate */ 608*7c478bd9Sstevel@tonic-gate #define HSHSIZ (32*1024) /* 4k bytes */ 609*7c478bd9Sstevel@tonic-gate #define HSHMASK (HSHSIZ - 1) 610*7c478bd9Sstevel@tonic-gate #define HSHMUL 243 611*7c478bd9Sstevel@tonic-gate 612*7c478bd9Sstevel@tonic-gate /* 613*7c478bd9Sstevel@tonic-gate * The following two arrays are used for caching. xhash 614*7c478bd9Sstevel@tonic-gate * is for caching path variable and xhash2 is for cdpath 615*7c478bd9Sstevel@tonic-gate * variable. 616*7c478bd9Sstevel@tonic-gate */ 617*7c478bd9Sstevel@tonic-gate 618*7c478bd9Sstevel@tonic-gate char xhash[HSHSIZ / 8]; 619*7c478bd9Sstevel@tonic-gate char xhash2[HSHSIZ / 8]; 620*7c478bd9Sstevel@tonic-gate #define hash(a, b) ((a) * HSHMUL + (b) & HSHMASK) 621*7c478bd9Sstevel@tonic-gate #define bit(h, b) ((h)[(b) >> 3] & 1 << ((b) & 7)) /* bit test */ 622*7c478bd9Sstevel@tonic-gate #define bis(h, b) ((h)[(b) >> 3] |= 1 << ((b) & 7)) /* bit set */ 623*7c478bd9Sstevel@tonic-gate #ifdef VFORK 624*7c478bd9Sstevel@tonic-gate int hits, misses; 625*7c478bd9Sstevel@tonic-gate #endif 626*7c478bd9Sstevel@tonic-gate 627*7c478bd9Sstevel@tonic-gate 628