1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23 /* All Rights Reserved */ 24 25 26 /* Portions Copyright(c) 1988, Sun Microsystems, Inc. */ 27 /* All Rights Reserved. */ 28 29 #ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.10.5.1 */ 30 /* 31 * UNIX shell 32 */ 33 34 #include "hash.h" 35 #include "defs.h" 36 #include <sys/types.h> 37 #include <sys/stat.h> 38 #include <errno.h> 39 40 #define EXECUTE 01 41 42 static unsigned char cost; 43 static int dotpath; 44 static int multrel; 45 static struct entry relcmd; 46 47 static int argpath(); 48 49 short 50 pathlook(com, flg, arg) 51 unsigned char *com; 52 int flg; 53 register struct argnod *arg; 54 { 55 register unsigned char *name = com; 56 register ENTRY *h; 57 58 ENTRY hentry; 59 int count = 0; 60 int i; 61 int pathset = 0; 62 int oldpath = 0; 63 struct namnod *n; 64 65 66 67 hentry.data = 0; 68 69 if (any('/', name)) 70 return(COMMAND); 71 72 h = hfind(name); 73 74 75 if (h) 76 { 77 if (h->data & (BUILTIN | FUNCTION)) 78 { 79 if (flg) 80 h->hits++; 81 return(h->data); 82 } 83 84 if (arg && (pathset = argpath(arg))) 85 return(PATH_COMMAND); 86 87 if ((h->data & DOT_COMMAND) == DOT_COMMAND) 88 { 89 if (multrel == 0 && hashdata(h->data) > dotpath) 90 oldpath = hashdata(h->data); 91 else 92 oldpath = dotpath; 93 94 h->data = 0; 95 goto pathsrch; 96 } 97 98 if (h->data & (COMMAND | REL_COMMAND)) 99 { 100 if (flg) 101 h->hits++; 102 return(h->data); 103 } 104 105 h->data = 0; 106 h->cost = 0; 107 } 108 109 if (i = syslook(name, commands, no_commands)) 110 { 111 hentry.data = (BUILTIN | i); 112 count = 1; 113 } 114 else 115 { 116 if (arg && (pathset = argpath(arg))) 117 return(PATH_COMMAND); 118 pathsrch: 119 count = findpath(name, oldpath); 120 } 121 122 if (count > 0) 123 { 124 if (h == 0) 125 { 126 hentry.cost = 0; 127 hentry.key = make(name); 128 h = henter(hentry); 129 } 130 131 if (h->data == 0) 132 { 133 if (count < dotpath) 134 h->data = COMMAND | count; 135 else 136 { 137 h->data = REL_COMMAND | count; 138 h->next = relcmd.next; 139 relcmd.next = h; 140 } 141 } 142 143 144 h->hits = flg; 145 h->cost += cost; 146 return(h->data); 147 } 148 else 149 { 150 return(-count); 151 } 152 } 153 154 155 static void 156 zapentry(h) 157 ENTRY *h; 158 { 159 h->data &= HASHZAP; 160 } 161 162 void 163 zaphash() 164 { 165 hscan(zapentry); 166 relcmd.next = 0; 167 } 168 169 void 170 zapcd() 171 { 172 ENTRY *ptr = relcmd.next; 173 174 while (ptr) 175 { 176 ptr->data |= CDMARK; 177 ptr = ptr->next; 178 } 179 relcmd.next = 0; 180 } 181 182 183 static void 184 hashout(h) 185 ENTRY *h; 186 { 187 sigchk(); 188 189 if (hashtype(h->data) == NOTFOUND) 190 return; 191 192 if (h->data & (BUILTIN | FUNCTION)) 193 return; 194 195 prn_buff(h->hits); 196 197 if (h->data & REL_COMMAND) 198 prc_buff('*'); 199 200 201 prc_buff(TAB); 202 prn_buff(h->cost); 203 prc_buff(TAB); 204 205 pr_path(h->key, hashdata(h->data)); 206 prc_buff(NL); 207 } 208 209 void 210 hashpr() 211 { 212 prs_buff("hits cost command\n"); 213 hscan(hashout); 214 } 215 216 217 set_dotpath() 218 { 219 register unsigned char *path; 220 register int cnt = 1; 221 222 dotpath = 10000; 223 path = getpath(""); 224 225 while (path && *path) 226 { 227 if (*path == '/') 228 cnt++; 229 else 230 { 231 if (dotpath == 10000) 232 dotpath = cnt; 233 else 234 { 235 multrel = 1; 236 return; 237 } 238 } 239 240 path = nextpath(path); 241 } 242 243 multrel = 0; 244 } 245 246 247 hash_func(name) 248 unsigned char *name; 249 { 250 ENTRY *h; 251 ENTRY hentry; 252 253 h = hfind(name); 254 255 if (h) 256 h->data = FUNCTION; 257 else 258 { 259 hentry.data = FUNCTION; 260 hentry.key = make(name); 261 hentry.cost = 0; 262 hentry.hits = 0; 263 henter(hentry); 264 } 265 } 266 267 func_unhash(name) 268 unsigned char *name; 269 { 270 ENTRY *h; 271 int i; 272 273 h = hfind(name); 274 275 if (h && (h->data & FUNCTION)) { 276 if(i = syslook(name, commands, no_commands)) 277 h->data = (BUILTIN|i); 278 else 279 h->data = NOTFOUND; 280 } 281 } 282 283 284 short 285 hash_cmd(name) 286 unsigned char *name; 287 { 288 ENTRY *h; 289 290 if (any('/', name)) 291 return(COMMAND); 292 293 h = hfind(name); 294 295 if (h) 296 { 297 if (h->data & (BUILTIN | FUNCTION)) 298 return(h->data); 299 else if ((h->data & REL_COMMAND) == REL_COMMAND) 300 { /* unlink h from relative command list */ 301 ENTRY *ptr = &relcmd; 302 while(ptr-> next != h) 303 ptr = ptr->next; 304 ptr->next = h->next; 305 } 306 zapentry(h); 307 } 308 309 return(pathlook(name, 0, 0)); 310 } 311 312 313 /* 314 * Return 0 if found, 1 if not. 315 */ 316 what_is_path(name) 317 register unsigned char *name; 318 { 319 register ENTRY *h; 320 int cnt; 321 short hashval; 322 323 h = hfind(name); 324 325 prs_buff(name); 326 if (h) 327 { 328 hashval = hashdata(h->data); 329 330 switch (hashtype(h->data)) 331 { 332 case BUILTIN: 333 prs_buff(" is a shell builtin\n"); 334 return (0); 335 336 case FUNCTION: 337 { 338 struct namnod *n = lookup(name); 339 340 prs_buff(" is a function\n"); 341 prs_buff(name); 342 prs_buff("(){\n"); 343 prf(n->namenv); 344 prs_buff("\n}\n"); 345 return (0); 346 } 347 348 case REL_COMMAND: 349 { 350 short hash; 351 352 if ((h->data & DOT_COMMAND) == DOT_COMMAND) 353 { 354 hash = pathlook(name, 0, 0); 355 if (hashtype(hash) == NOTFOUND) 356 { 357 prs_buff(" not found\n"); 358 return (1); 359 } 360 else 361 hashval = hashdata(hash); 362 } 363 } 364 365 case COMMAND: 366 prs_buff(" is hashed ("); 367 pr_path(name, hashval); 368 prs_buff(")\n"); 369 return (0); 370 } 371 } 372 373 if (syslook(name, commands, no_commands)) 374 { 375 prs_buff(" is a shell builtin\n"); 376 return (0); 377 } 378 379 if ((cnt = findpath(name, 0)) > 0) 380 { 381 prs_buff(" is "); 382 pr_path(name, cnt); 383 prc_buff(NL); 384 return (0); 385 } 386 else 387 { 388 prs_buff(" not found\n"); 389 return (1); 390 } 391 } 392 393 394 findpath(name, oldpath) 395 register unsigned char *name; 396 int oldpath; 397 { 398 register unsigned char *path; 399 register int count = 1; 400 401 unsigned char *p; 402 int ok = 1; 403 int e_code = 1; 404 405 cost = 0; 406 path = getpath(name); 407 408 if (oldpath) 409 { 410 count = dotpath; 411 while (--count) 412 path = nextpath(path); 413 414 if (oldpath > dotpath) 415 { 416 catpath(path, name); 417 p = curstak(); 418 cost = 1; 419 420 if ((ok = chk_access(p, S_IEXEC, 1)) == 0) 421 return(dotpath); 422 else 423 return(oldpath); 424 } 425 else 426 count = dotpath; 427 } 428 429 while (path) 430 { 431 path = catpath(path, name); 432 cost++; 433 p = curstak(); 434 435 if ((ok = chk_access(p, S_IEXEC, 1)) == 0) 436 break; 437 else 438 e_code = max(e_code, ok); 439 440 count++; 441 } 442 443 return(ok ? -e_code : count); 444 } 445 446 /* 447 * Determine if file given by name is accessible with permissions 448 * given by mode. 449 * Regflag argument non-zero means not to consider 450 * a non-regular file as executable. 451 */ 452 453 chk_access(name, mode, regflag) 454 register unsigned char *name; 455 mode_t mode; 456 int regflag; 457 { 458 static int flag; 459 static uid_t euid; 460 struct stat statb; 461 mode_t ftype; 462 463 if(flag == 0) { 464 euid = geteuid(); 465 flag = 1; 466 } 467 ftype = statb.st_mode & S_IFMT; 468 if (stat((char *)name, &statb) == 0) { 469 ftype = statb.st_mode & S_IFMT; 470 if(mode == S_IEXEC && regflag && ftype != S_IFREG) 471 return(2); 472 if(access((char *)name, 010|(mode>>6)) == 0) { 473 if(euid == 0) { 474 if (ftype != S_IFREG || mode != S_IEXEC) 475 return(0); 476 /* root can execute file as long as it has execute 477 permission for someone */ 478 if (statb.st_mode & (S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6))) 479 return(0); 480 return(3); 481 } 482 return(0); 483 } 484 } 485 return(errno == EACCES ? 3 : 1); 486 } 487 488 489 pr_path(name, count) 490 register unsigned char *name; 491 int count; 492 { 493 register unsigned char *path; 494 495 path = getpath(name); 496 497 while (--count && path) 498 path = nextpath(path, name); 499 500 catpath(path, name); 501 prs_buff(curstak()); 502 } 503 504 505 static 506 argpath(arg) 507 register struct argnod *arg; 508 { 509 register unsigned char *s; 510 register unsigned char *start; 511 512 while (arg) 513 { 514 s = arg->argval; 515 start = s; 516 517 if (letter(*s)) 518 { 519 while (alphanum(*s)) 520 s++; 521 522 if (*s == '=') 523 { 524 *s = 0; 525 526 if (eq(start, pathname)) 527 { 528 *s = '='; 529 return(1); 530 } 531 else 532 *s = '='; 533 } 534 } 535 arg = arg->argnxt; 536 } 537 538 return(0); 539 } 540