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 "sh.h" 18*7c478bd9Sstevel@tonic-gate #include <dirent.h> 19*7c478bd9Sstevel@tonic-gate #include <string.h> 20*7c478bd9Sstevel@tonic-gate #include "sh.tconst.h" 21*7c478bd9Sstevel@tonic-gate #include "sh_policy.h" 22*7c478bd9Sstevel@tonic-gate 23*7c478bd9Sstevel@tonic-gate 24*7c478bd9Sstevel@tonic-gate /* 25*7c478bd9Sstevel@tonic-gate * C shell 26*7c478bd9Sstevel@tonic-gate */ 27*7c478bd9Sstevel@tonic-gate 28*7c478bd9Sstevel@tonic-gate /* 29*7c478bd9Sstevel@tonic-gate * System level search and execute of a command. 30*7c478bd9Sstevel@tonic-gate * We look in each directory for the specified command name. 31*7c478bd9Sstevel@tonic-gate * If the name contains a '/' then we execute only the full path name. 32*7c478bd9Sstevel@tonic-gate * If there is no search path then we execute only full path names. 33*7c478bd9Sstevel@tonic-gate */ 34*7c478bd9Sstevel@tonic-gate 35*7c478bd9Sstevel@tonic-gate /* 36*7c478bd9Sstevel@tonic-gate * As we search for the command we note the first non-trivial error 37*7c478bd9Sstevel@tonic-gate * message for presentation to the user. This allows us often 38*7c478bd9Sstevel@tonic-gate * to show that a file has the wrong mode/no access when the file 39*7c478bd9Sstevel@tonic-gate * is not in the last component of the search path, so we must 40*7c478bd9Sstevel@tonic-gate * go on after first detecting the error. 41*7c478bd9Sstevel@tonic-gate */ 42*7c478bd9Sstevel@tonic-gate char *exerr; /* Execution error message */ 43*7c478bd9Sstevel@tonic-gate 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate extern DIR *opendir_(); 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gate doexec(t) 49*7c478bd9Sstevel@tonic-gate register struct command *t; 50*7c478bd9Sstevel@tonic-gate { 51*7c478bd9Sstevel@tonic-gate tchar *sav; 52*7c478bd9Sstevel@tonic-gate register tchar *dp, **pv, **av; 53*7c478bd9Sstevel@tonic-gate register struct varent *v; 54*7c478bd9Sstevel@tonic-gate bool slash; 55*7c478bd9Sstevel@tonic-gate int hashval, hashval1, i; 56*7c478bd9Sstevel@tonic-gate tchar *blk[2]; 57*7c478bd9Sstevel@tonic-gate #ifdef TRACE 58*7c478bd9Sstevel@tonic-gate tprintf("TRACE- doexec()\n"); 59*7c478bd9Sstevel@tonic-gate #endif 60*7c478bd9Sstevel@tonic-gate 61*7c478bd9Sstevel@tonic-gate /* 62*7c478bd9Sstevel@tonic-gate * Glob the command name. If this does anything, then we 63*7c478bd9Sstevel@tonic-gate * will execute the command only relative to ".". One special 64*7c478bd9Sstevel@tonic-gate * case: if there is no PATH, then we execute only commands 65*7c478bd9Sstevel@tonic-gate * which start with '/'. 66*7c478bd9Sstevel@tonic-gate */ 67*7c478bd9Sstevel@tonic-gate dp = globone(t->t_dcom[0]); 68*7c478bd9Sstevel@tonic-gate sav = t->t_dcom[0]; 69*7c478bd9Sstevel@tonic-gate exerr = 0; t->t_dcom[0] = dp; 70*7c478bd9Sstevel@tonic-gate setname(dp); 71*7c478bd9Sstevel@tonic-gate xfree(sav); 72*7c478bd9Sstevel@tonic-gate v = adrof(S_path /*"path"*/); 73*7c478bd9Sstevel@tonic-gate if (v == 0 && dp[0] != '/') { 74*7c478bd9Sstevel@tonic-gate pexerr(); 75*7c478bd9Sstevel@tonic-gate } 76*7c478bd9Sstevel@tonic-gate slash = gflag; 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate /* 79*7c478bd9Sstevel@tonic-gate * Glob the argument list, if necessary. 80*7c478bd9Sstevel@tonic-gate * Otherwise trim off the quote bits. 81*7c478bd9Sstevel@tonic-gate */ 82*7c478bd9Sstevel@tonic-gate gflag = 0; av = &t->t_dcom[1]; 83*7c478bd9Sstevel@tonic-gate tglob(av); 84*7c478bd9Sstevel@tonic-gate if (gflag) { 85*7c478bd9Sstevel@tonic-gate av = glob(av); 86*7c478bd9Sstevel@tonic-gate if (av == 0) 87*7c478bd9Sstevel@tonic-gate error("No match"); 88*7c478bd9Sstevel@tonic-gate } 89*7c478bd9Sstevel@tonic-gate blk[0] = t->t_dcom[0]; 90*7c478bd9Sstevel@tonic-gate blk[1] = 0; 91*7c478bd9Sstevel@tonic-gate av = blkspl(blk, av); 92*7c478bd9Sstevel@tonic-gate #ifdef VFORK 93*7c478bd9Sstevel@tonic-gate Vav = av; 94*7c478bd9Sstevel@tonic-gate #endif 95*7c478bd9Sstevel@tonic-gate trim(av); 96*7c478bd9Sstevel@tonic-gate slash |= any('/', av[0]); 97*7c478bd9Sstevel@tonic-gate 98*7c478bd9Sstevel@tonic-gate xechoit(av); /* Echo command if -x */ 99*7c478bd9Sstevel@tonic-gate /* 100*7c478bd9Sstevel@tonic-gate * Since all internal file descriptors are set to close on exec, 101*7c478bd9Sstevel@tonic-gate * we don't need to close them explicitly here. Just reorient 102*7c478bd9Sstevel@tonic-gate * ourselves for error messages. 103*7c478bd9Sstevel@tonic-gate */ 104*7c478bd9Sstevel@tonic-gate SHIN = 0; SHOUT = 1; SHDIAG = 2; OLDSTD = 0; 105*7c478bd9Sstevel@tonic-gate 106*7c478bd9Sstevel@tonic-gate /* 107*7c478bd9Sstevel@tonic-gate * We must do this AFTER any possible forking (like `foo` 108*7c478bd9Sstevel@tonic-gate * in glob) so that this shell can still do subprocesses. 109*7c478bd9Sstevel@tonic-gate */ 110*7c478bd9Sstevel@tonic-gate (void) sigsetmask(0); 111*7c478bd9Sstevel@tonic-gate 112*7c478bd9Sstevel@tonic-gate /* 113*7c478bd9Sstevel@tonic-gate * If no path, no words in path, or a / in the filename 114*7c478bd9Sstevel@tonic-gate * then restrict the command search. 115*7c478bd9Sstevel@tonic-gate */ 116*7c478bd9Sstevel@tonic-gate if (v == 0 || v->vec[0] == 0 || slash) 117*7c478bd9Sstevel@tonic-gate pv = justabs; 118*7c478bd9Sstevel@tonic-gate else 119*7c478bd9Sstevel@tonic-gate pv = v->vec; 120*7c478bd9Sstevel@tonic-gate sav = strspl(S_SLASH /* "/" */, *av); /* / command name for postpending */ 121*7c478bd9Sstevel@tonic-gate #ifdef VFORK 122*7c478bd9Sstevel@tonic-gate Vsav = sav; 123*7c478bd9Sstevel@tonic-gate #endif 124*7c478bd9Sstevel@tonic-gate if (havhash) 125*7c478bd9Sstevel@tonic-gate hashval = hashname(*av); 126*7c478bd9Sstevel@tonic-gate i = 0; 127*7c478bd9Sstevel@tonic-gate #ifdef VFORK 128*7c478bd9Sstevel@tonic-gate hits++; 129*7c478bd9Sstevel@tonic-gate #endif 130*7c478bd9Sstevel@tonic-gate do { 131*7c478bd9Sstevel@tonic-gate if (!slash && pv[0][0] == '/' && havhash) { 132*7c478bd9Sstevel@tonic-gate hashval1 = hash(hashval, i); 133*7c478bd9Sstevel@tonic-gate if (!bit(xhash, hashval1)) 134*7c478bd9Sstevel@tonic-gate goto cont; 135*7c478bd9Sstevel@tonic-gate } 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate if (pv[0][0] == 0 || eq(pv[0], S_DOT/*"."*/)) { /* don't make ./xxx */ 138*7c478bd9Sstevel@tonic-gate texec(t, *av, av); 139*7c478bd9Sstevel@tonic-gate } else { 140*7c478bd9Sstevel@tonic-gate dp = strspl(*pv, sav); 141*7c478bd9Sstevel@tonic-gate #ifdef VFORK 142*7c478bd9Sstevel@tonic-gate Vdp = dp; 143*7c478bd9Sstevel@tonic-gate #endif 144*7c478bd9Sstevel@tonic-gate texec(t, dp, av); 145*7c478bd9Sstevel@tonic-gate #ifdef VFORK 146*7c478bd9Sstevel@tonic-gate Vdp = 0; 147*7c478bd9Sstevel@tonic-gate #endif 148*7c478bd9Sstevel@tonic-gate xfree(dp); 149*7c478bd9Sstevel@tonic-gate } 150*7c478bd9Sstevel@tonic-gate #ifdef VFORK 151*7c478bd9Sstevel@tonic-gate misses++; 152*7c478bd9Sstevel@tonic-gate #endif 153*7c478bd9Sstevel@tonic-gate cont: 154*7c478bd9Sstevel@tonic-gate pv++; 155*7c478bd9Sstevel@tonic-gate i++; 156*7c478bd9Sstevel@tonic-gate } while (*pv); 157*7c478bd9Sstevel@tonic-gate #ifdef VFORK 158*7c478bd9Sstevel@tonic-gate hits--; 159*7c478bd9Sstevel@tonic-gate #endif 160*7c478bd9Sstevel@tonic-gate #ifdef VFORK 161*7c478bd9Sstevel@tonic-gate Vsav = 0; 162*7c478bd9Sstevel@tonic-gate Vav = 0; 163*7c478bd9Sstevel@tonic-gate #endif 164*7c478bd9Sstevel@tonic-gate xfree(sav); 165*7c478bd9Sstevel@tonic-gate xfree( (char *)av); 166*7c478bd9Sstevel@tonic-gate pexerr(); 167*7c478bd9Sstevel@tonic-gate } 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate pexerr() 170*7c478bd9Sstevel@tonic-gate { 171*7c478bd9Sstevel@tonic-gate 172*7c478bd9Sstevel@tonic-gate #ifdef TRACE 173*7c478bd9Sstevel@tonic-gate tprintf("TRACE- pexerr()\n"); 174*7c478bd9Sstevel@tonic-gate #endif 175*7c478bd9Sstevel@tonic-gate /* Couldn't find the damn thing */ 176*7c478bd9Sstevel@tonic-gate if (exerr) 177*7c478bd9Sstevel@tonic-gate bferr(exerr); 178*7c478bd9Sstevel@tonic-gate bferr("Command not found"); 179*7c478bd9Sstevel@tonic-gate } 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate /* 182*7c478bd9Sstevel@tonic-gate * Execute command f, arg list t. 183*7c478bd9Sstevel@tonic-gate * Record error message if not found. 184*7c478bd9Sstevel@tonic-gate * Also do shell scripts here. 185*7c478bd9Sstevel@tonic-gate */ 186*7c478bd9Sstevel@tonic-gate texec(cmd, f, t) 187*7c478bd9Sstevel@tonic-gate register struct command *cmd; 188*7c478bd9Sstevel@tonic-gate tchar *f; 189*7c478bd9Sstevel@tonic-gate register tchar **t; 190*7c478bd9Sstevel@tonic-gate { 191*7c478bd9Sstevel@tonic-gate register int pfstatus = 0; 192*7c478bd9Sstevel@tonic-gate register struct varent *v; 193*7c478bd9Sstevel@tonic-gate register tchar **vp; 194*7c478bd9Sstevel@tonic-gate tchar *lastsh[2]; 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate #ifdef TRACE 197*7c478bd9Sstevel@tonic-gate tprintf("TRACE- texec()\n"); 198*7c478bd9Sstevel@tonic-gate #endif 199*7c478bd9Sstevel@tonic-gate /* convert cfname and cargs from tchar to char */ 200*7c478bd9Sstevel@tonic-gate tconvert(cmd, f, t); 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate if (pfcshflag == 1) { 203*7c478bd9Sstevel@tonic-gate pfstatus = secpolicy_pfexec((const char *)(cmd->cfname), 204*7c478bd9Sstevel@tonic-gate cmd->cargs, (const char **)NULL); 205*7c478bd9Sstevel@tonic-gate if (pfstatus != NOATTRS) { 206*7c478bd9Sstevel@tonic-gate errno = pfstatus; 207*7c478bd9Sstevel@tonic-gate } 208*7c478bd9Sstevel@tonic-gate } 209*7c478bd9Sstevel@tonic-gate if ((pfcshflag == 0) || (pfstatus == NOATTRS)) { 210*7c478bd9Sstevel@tonic-gate execv(cmd->cfname, cmd->cargs); 211*7c478bd9Sstevel@tonic-gate } 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate /* 214*7c478bd9Sstevel@tonic-gate * exec returned, free up allocations from above 215*7c478bd9Sstevel@tonic-gate * tconvert(), zero cfname and cargs to prevent 216*7c478bd9Sstevel@tonic-gate * duplicate free() in freesyn() 217*7c478bd9Sstevel@tonic-gate */ 218*7c478bd9Sstevel@tonic-gate xfree(cmd->cfname); 219*7c478bd9Sstevel@tonic-gate chr_blkfree(cmd->cargs); 220*7c478bd9Sstevel@tonic-gate cmd->cfname = (char *) 0; 221*7c478bd9Sstevel@tonic-gate cmd->cargs = (char **) 0; 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate switch (errno) { 224*7c478bd9Sstevel@tonic-gate case ENOEXEC: 225*7c478bd9Sstevel@tonic-gate /* check that this is not a binary file */ 226*7c478bd9Sstevel@tonic-gate { 227*7c478bd9Sstevel@tonic-gate register int ff = open_(f, 0); 228*7c478bd9Sstevel@tonic-gate tchar ch; 229*7c478bd9Sstevel@tonic-gate 230*7c478bd9Sstevel@tonic-gate if (ff != -1 && read_(ff, &ch, 1) == 1 && !isprint(ch) 231*7c478bd9Sstevel@tonic-gate && !isspace(ch)) { 232*7c478bd9Sstevel@tonic-gate printf("Cannot execute binary file.\n"); 233*7c478bd9Sstevel@tonic-gate Perror(f); 234*7c478bd9Sstevel@tonic-gate (void) close(ff); 235*7c478bd9Sstevel@tonic-gate unsetfd(ff); 236*7c478bd9Sstevel@tonic-gate return; 237*7c478bd9Sstevel@tonic-gate } 238*7c478bd9Sstevel@tonic-gate (void) close(ff); 239*7c478bd9Sstevel@tonic-gate unsetfd(ff); 240*7c478bd9Sstevel@tonic-gate } 241*7c478bd9Sstevel@tonic-gate /* 242*7c478bd9Sstevel@tonic-gate * If there is an alias for shell, then 243*7c478bd9Sstevel@tonic-gate * put the words of the alias in front of the 244*7c478bd9Sstevel@tonic-gate * argument list replacing the command name. 245*7c478bd9Sstevel@tonic-gate * Note no interpretation of the words at this point. 246*7c478bd9Sstevel@tonic-gate */ 247*7c478bd9Sstevel@tonic-gate v = adrof1(S_shell /*"shell"*/, &aliases); 248*7c478bd9Sstevel@tonic-gate if (v == 0) { 249*7c478bd9Sstevel@tonic-gate #ifdef OTHERSH 250*7c478bd9Sstevel@tonic-gate register int ff = open_(f, 0); 251*7c478bd9Sstevel@tonic-gate tchar ch; 252*7c478bd9Sstevel@tonic-gate #endif 253*7c478bd9Sstevel@tonic-gate 254*7c478bd9Sstevel@tonic-gate vp = lastsh; 255*7c478bd9Sstevel@tonic-gate vp[0] = adrof(S_shell /*"shell"*/) ? value(S_shell /*"shell"*/) : S_SHELLPATH/*SHELLPATH*/; 256*7c478bd9Sstevel@tonic-gate vp[1] = (tchar *) NULL; 257*7c478bd9Sstevel@tonic-gate #ifdef OTHERSH 258*7c478bd9Sstevel@tonic-gate if (ff != -1 && read_(ff, &ch, 1) == 1 && ch != '#') 259*7c478bd9Sstevel@tonic-gate vp[0] = S_OTHERSH/*OTHERSH*/; 260*7c478bd9Sstevel@tonic-gate (void) close(ff); 261*7c478bd9Sstevel@tonic-gate unsetfd(ff); 262*7c478bd9Sstevel@tonic-gate #endif 263*7c478bd9Sstevel@tonic-gate } else 264*7c478bd9Sstevel@tonic-gate vp = v->vec; 265*7c478bd9Sstevel@tonic-gate t[0] = f; 266*7c478bd9Sstevel@tonic-gate t = blkspl(vp, t); /* Splice up the new arglst */ 267*7c478bd9Sstevel@tonic-gate f = *t; 268*7c478bd9Sstevel@tonic-gate 269*7c478bd9Sstevel@tonic-gate tconvert(cmd, f, t); /* convert tchar to char */ 270*7c478bd9Sstevel@tonic-gate 271*7c478bd9Sstevel@tonic-gate /* 272*7c478bd9Sstevel@tonic-gate * now done with tchar arg list t, 273*7c478bd9Sstevel@tonic-gate * free the space calloc'd by above blkspl() 274*7c478bd9Sstevel@tonic-gate */ 275*7c478bd9Sstevel@tonic-gate xfree((char *) t); 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate execv(cmd->cfname, cmd->cargs); /* exec the command */ 278*7c478bd9Sstevel@tonic-gate 279*7c478bd9Sstevel@tonic-gate /* exec returned, same free'ing as above */ 280*7c478bd9Sstevel@tonic-gate xfree(cmd->cfname); 281*7c478bd9Sstevel@tonic-gate chr_blkfree(cmd->cargs); 282*7c478bd9Sstevel@tonic-gate cmd->cfname = (char *) 0; 283*7c478bd9Sstevel@tonic-gate cmd->cargs = (char **) 0; 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate /* The sky is falling, the sky is falling! */ 286*7c478bd9Sstevel@tonic-gate 287*7c478bd9Sstevel@tonic-gate case ENOMEM: 288*7c478bd9Sstevel@tonic-gate Perror(f); 289*7c478bd9Sstevel@tonic-gate 290*7c478bd9Sstevel@tonic-gate case ENOENT: 291*7c478bd9Sstevel@tonic-gate break; 292*7c478bd9Sstevel@tonic-gate 293*7c478bd9Sstevel@tonic-gate default: 294*7c478bd9Sstevel@tonic-gate if (exerr == 0) { 295*7c478bd9Sstevel@tonic-gate exerr = strerror(errno); 296*7c478bd9Sstevel@tonic-gate setname(f); 297*7c478bd9Sstevel@tonic-gate } 298*7c478bd9Sstevel@tonic-gate } 299*7c478bd9Sstevel@tonic-gate } 300*7c478bd9Sstevel@tonic-gate 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate static 303*7c478bd9Sstevel@tonic-gate tconvert(cmd, fname, list) 304*7c478bd9Sstevel@tonic-gate register struct command *cmd; 305*7c478bd9Sstevel@tonic-gate register tchar *fname, **list; 306*7c478bd9Sstevel@tonic-gate { 307*7c478bd9Sstevel@tonic-gate register char **rc; 308*7c478bd9Sstevel@tonic-gate register int len; 309*7c478bd9Sstevel@tonic-gate 310*7c478bd9Sstevel@tonic-gate cmd->cfname = tstostr(NULL, fname); 311*7c478bd9Sstevel@tonic-gate 312*7c478bd9Sstevel@tonic-gate len = blklen(list); 313*7c478bd9Sstevel@tonic-gate rc = cmd->cargs = (char **) 314*7c478bd9Sstevel@tonic-gate calloc((u_int) (len + 1), sizeof(char **)); 315*7c478bd9Sstevel@tonic-gate while (len--) 316*7c478bd9Sstevel@tonic-gate *rc++ = tstostr(NULL, *list++); 317*7c478bd9Sstevel@tonic-gate *rc = NULL; 318*7c478bd9Sstevel@tonic-gate } 319*7c478bd9Sstevel@tonic-gate 320*7c478bd9Sstevel@tonic-gate 321*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 322*7c478bd9Sstevel@tonic-gate execash(t, kp) 323*7c478bd9Sstevel@tonic-gate tchar **t; 324*7c478bd9Sstevel@tonic-gate register struct command *kp; 325*7c478bd9Sstevel@tonic-gate { 326*7c478bd9Sstevel@tonic-gate #ifdef TRACE 327*7c478bd9Sstevel@tonic-gate tprintf("TRACE- execash()\n"); 328*7c478bd9Sstevel@tonic-gate #endif 329*7c478bd9Sstevel@tonic-gate 330*7c478bd9Sstevel@tonic-gate rechist(); 331*7c478bd9Sstevel@tonic-gate (void) signal(SIGINT, parintr); 332*7c478bd9Sstevel@tonic-gate (void) signal(SIGQUIT, parintr); 333*7c478bd9Sstevel@tonic-gate (void) signal(SIGTERM, parterm); /* if doexec loses, screw */ 334*7c478bd9Sstevel@tonic-gate lshift(kp->t_dcom, 1); 335*7c478bd9Sstevel@tonic-gate exiterr++; 336*7c478bd9Sstevel@tonic-gate doexec(kp); 337*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 338*7c478bd9Sstevel@tonic-gate } 339*7c478bd9Sstevel@tonic-gate 340*7c478bd9Sstevel@tonic-gate xechoit(t) 341*7c478bd9Sstevel@tonic-gate tchar **t; 342*7c478bd9Sstevel@tonic-gate { 343*7c478bd9Sstevel@tonic-gate #ifdef TRACE 344*7c478bd9Sstevel@tonic-gate tprintf("TRACE- xechoit()\n"); 345*7c478bd9Sstevel@tonic-gate #endif 346*7c478bd9Sstevel@tonic-gate 347*7c478bd9Sstevel@tonic-gate if (adrof(S_echo /*"echo"*/)) { 348*7c478bd9Sstevel@tonic-gate flush(); 349*7c478bd9Sstevel@tonic-gate haderr = 1; 350*7c478bd9Sstevel@tonic-gate blkpr(t), Putchar('\n'); 351*7c478bd9Sstevel@tonic-gate haderr = 0; 352*7c478bd9Sstevel@tonic-gate } 353*7c478bd9Sstevel@tonic-gate } 354*7c478bd9Sstevel@tonic-gate 355*7c478bd9Sstevel@tonic-gate /* 356*7c478bd9Sstevel@tonic-gate * This routine called when user enters "rehash". 357*7c478bd9Sstevel@tonic-gate * Both the path and cdpath caching arrays will 358*7c478bd9Sstevel@tonic-gate * be rehashed, via calling dohash. If either 359*7c478bd9Sstevel@tonic-gate * variable is not set with a value, then dohash 360*7c478bd9Sstevel@tonic-gate * just exits. 361*7c478bd9Sstevel@tonic-gate */ 362*7c478bd9Sstevel@tonic-gate 363*7c478bd9Sstevel@tonic-gate dorehash() 364*7c478bd9Sstevel@tonic-gate { 365*7c478bd9Sstevel@tonic-gate dohash(xhash); 366*7c478bd9Sstevel@tonic-gate dohash(xhash2); 367*7c478bd9Sstevel@tonic-gate } 368*7c478bd9Sstevel@tonic-gate 369*7c478bd9Sstevel@tonic-gate /* 370*7c478bd9Sstevel@tonic-gate * Fill up caching arrays for path and cdpath 371*7c478bd9Sstevel@tonic-gate */ 372*7c478bd9Sstevel@tonic-gate dohash(cachearray) 373*7c478bd9Sstevel@tonic-gate char cachearray[]; 374*7c478bd9Sstevel@tonic-gate { 375*7c478bd9Sstevel@tonic-gate struct stat stb; 376*7c478bd9Sstevel@tonic-gate DIR *dirp; 377*7c478bd9Sstevel@tonic-gate register struct dirent *dp; 378*7c478bd9Sstevel@tonic-gate register int cnt; 379*7c478bd9Sstevel@tonic-gate int i = 0; 380*7c478bd9Sstevel@tonic-gate struct varent *v; 381*7c478bd9Sstevel@tonic-gate tchar **pv; 382*7c478bd9Sstevel@tonic-gate int hashval; 383*7c478bd9Sstevel@tonic-gate tchar curdir_[MAXNAMLEN+1]; 384*7c478bd9Sstevel@tonic-gate 385*7c478bd9Sstevel@tonic-gate #ifdef TRACE 386*7c478bd9Sstevel@tonic-gate tprintf("TRACE- dohash()\n"); 387*7c478bd9Sstevel@tonic-gate #endif 388*7c478bd9Sstevel@tonic-gate /* Caching $path */ 389*7c478bd9Sstevel@tonic-gate if ( cachearray == xhash ) { 390*7c478bd9Sstevel@tonic-gate havhash = 1; 391*7c478bd9Sstevel@tonic-gate v = adrof(S_path /*"path"*/); 392*7c478bd9Sstevel@tonic-gate }else { /* Caching $cdpath */ 393*7c478bd9Sstevel@tonic-gate havhash2 = 1; 394*7c478bd9Sstevel@tonic-gate v = adrof(S_cdpath /*"cdpath"*/); 395*7c478bd9Sstevel@tonic-gate } 396*7c478bd9Sstevel@tonic-gate 397*7c478bd9Sstevel@tonic-gate for (cnt = 0; cnt < ( HSHSIZ / 8 ); cnt++) 398*7c478bd9Sstevel@tonic-gate cachearray[cnt] = 0; 399*7c478bd9Sstevel@tonic-gate if (v == 0) 400*7c478bd9Sstevel@tonic-gate { 401*7c478bd9Sstevel@tonic-gate return; 402*7c478bd9Sstevel@tonic-gate } 403*7c478bd9Sstevel@tonic-gate for (pv = v->vec; *pv; pv++, i++) { 404*7c478bd9Sstevel@tonic-gate if (pv[0][0] != '/') 405*7c478bd9Sstevel@tonic-gate continue; 406*7c478bd9Sstevel@tonic-gate dirp = opendir_(*pv); 407*7c478bd9Sstevel@tonic-gate if (dirp == NULL) 408*7c478bd9Sstevel@tonic-gate continue; 409*7c478bd9Sstevel@tonic-gate if (fstat(dirp->dd_fd, &stb) < 0 || !isdir(stb)) { 410*7c478bd9Sstevel@tonic-gate unsetfd(dirp->dd_fd); 411*7c478bd9Sstevel@tonic-gate closedir_(dirp); 412*7c478bd9Sstevel@tonic-gate continue; 413*7c478bd9Sstevel@tonic-gate } 414*7c478bd9Sstevel@tonic-gate while ((dp = readdir(dirp)) != NULL) { 415*7c478bd9Sstevel@tonic-gate if (dp->d_ino == 0) 416*7c478bd9Sstevel@tonic-gate continue; 417*7c478bd9Sstevel@tonic-gate if (dp->d_name[0] == '.' && 418*7c478bd9Sstevel@tonic-gate (dp->d_name[1] == '\0' || 419*7c478bd9Sstevel@tonic-gate dp->d_name[1] == '.' && dp->d_name[2] == '\0')) 420*7c478bd9Sstevel@tonic-gate continue; 421*7c478bd9Sstevel@tonic-gate hashval = hash(hashname(strtots(curdir_,dp->d_name)), i); 422*7c478bd9Sstevel@tonic-gate bis(cachearray, hashval); 423*7c478bd9Sstevel@tonic-gate } 424*7c478bd9Sstevel@tonic-gate unsetfd(dirp->dd_fd); 425*7c478bd9Sstevel@tonic-gate closedir_(dirp); 426*7c478bd9Sstevel@tonic-gate } 427*7c478bd9Sstevel@tonic-gate } 428*7c478bd9Sstevel@tonic-gate 429*7c478bd9Sstevel@tonic-gate dounhash() 430*7c478bd9Sstevel@tonic-gate { 431*7c478bd9Sstevel@tonic-gate 432*7c478bd9Sstevel@tonic-gate #ifdef TRACE 433*7c478bd9Sstevel@tonic-gate tprintf("TRACE- dounhash()\n"); 434*7c478bd9Sstevel@tonic-gate #endif 435*7c478bd9Sstevel@tonic-gate havhash = 0; 436*7c478bd9Sstevel@tonic-gate havhash2 = 0; 437*7c478bd9Sstevel@tonic-gate } 438*7c478bd9Sstevel@tonic-gate 439*7c478bd9Sstevel@tonic-gate #ifdef VFORK 440*7c478bd9Sstevel@tonic-gate hashstat() 441*7c478bd9Sstevel@tonic-gate { 442*7c478bd9Sstevel@tonic-gate #ifdef TRACE 443*7c478bd9Sstevel@tonic-gate tprintf("TRACE- hashstat_()\n"); 444*7c478bd9Sstevel@tonic-gate #endif 445*7c478bd9Sstevel@tonic-gate 446*7c478bd9Sstevel@tonic-gate if (hits+misses) 447*7c478bd9Sstevel@tonic-gate printf("%d hits, %d misses, %d%%\n", 448*7c478bd9Sstevel@tonic-gate hits, misses, 100 * hits / (hits + misses)); 449*7c478bd9Sstevel@tonic-gate } 450*7c478bd9Sstevel@tonic-gate #endif 451*7c478bd9Sstevel@tonic-gate 452*7c478bd9Sstevel@tonic-gate /* 453*7c478bd9Sstevel@tonic-gate * Hash a command name. 454*7c478bd9Sstevel@tonic-gate */ 455*7c478bd9Sstevel@tonic-gate hashname(cp) 456*7c478bd9Sstevel@tonic-gate register tchar *cp; 457*7c478bd9Sstevel@tonic-gate { 458*7c478bd9Sstevel@tonic-gate register long h = 0; 459*7c478bd9Sstevel@tonic-gate 460*7c478bd9Sstevel@tonic-gate #ifdef TRACE 461*7c478bd9Sstevel@tonic-gate tprintf("TRACE- hashname()\n"); 462*7c478bd9Sstevel@tonic-gate #endif 463*7c478bd9Sstevel@tonic-gate while (*cp) 464*7c478bd9Sstevel@tonic-gate h = hash(h, *cp++); 465*7c478bd9Sstevel@tonic-gate return ((int) h); 466*7c478bd9Sstevel@tonic-gate } 467