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