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 23 /* 24 * Copyright 1990 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 29 /* All Rights Reserved */ 30 31 #pragma ident "%Z%%M% %I% %E% SMI" 32 /* 33 * UNIX shell 34 */ 35 36 #include "hash.h" 37 #include "defs.h" 38 #include <sys/types.h> 39 #include <sys/stat.h> 40 #include <errno.h> 41 42 #define EXECUTE 01 43 44 static unsigned char cost; 45 static int dotpath; 46 static int multrel; 47 static struct entry relcmd; 48 49 static int argpath(); 50 static void pr_path(unsigned char *, int); 51 52 short 53 pathlook(com, flg, arg) 54 unsigned char *com; 55 int flg; 56 struct argnod *arg; 57 { 58 unsigned char *name = com; 59 ENTRY *h; 60 61 ENTRY hentry; 62 int count = 0; 63 int i; 64 int pathset = 0; 65 int oldpath = 0; 66 struct namnod *n; 67 68 69 70 hentry.data = 0; 71 72 if (any('/', name)) 73 return(COMMAND); 74 75 h = hfind(name); 76 77 78 if (h) 79 { 80 if (h->data & (BUILTIN | FUNCTION)) 81 { 82 if (flg) 83 h->hits++; 84 return(h->data); 85 } 86 87 if (arg && (pathset = argpath(arg))) 88 return(PATH_COMMAND); 89 90 if ((h->data & DOT_COMMAND) == DOT_COMMAND) 91 { 92 if (multrel == 0 && hashdata(h->data) > dotpath) 93 oldpath = hashdata(h->data); 94 else 95 oldpath = dotpath; 96 97 h->data = 0; 98 goto pathsrch; 99 } 100 101 if (h->data & (COMMAND | REL_COMMAND)) 102 { 103 if (flg) 104 h->hits++; 105 return(h->data); 106 } 107 108 h->data = 0; 109 h->cost = 0; 110 } 111 112 if (i = syslook(name, commands, no_commands)) 113 { 114 hentry.data = (BUILTIN | i); 115 count = 1; 116 } 117 else 118 { 119 if (arg && (pathset = argpath(arg))) 120 return(PATH_COMMAND); 121 pathsrch: 122 count = findpath(name, oldpath); 123 } 124 125 if (count > 0) 126 { 127 if (h == 0) 128 { 129 hentry.cost = 0; 130 hentry.key = make(name); 131 h = henter(hentry); 132 } 133 134 if (h->data == 0) 135 { 136 if (count < dotpath) 137 h->data = COMMAND | count; 138 else 139 { 140 h->data = REL_COMMAND | count; 141 h->next = relcmd.next; 142 relcmd.next = h; 143 } 144 } 145 146 147 h->hits = flg; 148 h->cost += cost; 149 return(h->data); 150 } 151 else 152 { 153 return(-count); 154 } 155 } 156 157 158 static void 159 zapentry(h) 160 ENTRY *h; 161 { 162 h->data &= HASHZAP; 163 } 164 165 void 166 zaphash() 167 { 168 hscan(zapentry); 169 relcmd.next = 0; 170 } 171 172 void 173 zapcd() 174 { 175 ENTRY *ptr = relcmd.next; 176 177 while (ptr) 178 { 179 ptr->data |= CDMARK; 180 ptr = ptr->next; 181 } 182 relcmd.next = 0; 183 } 184 185 186 static void 187 hashout(h) 188 ENTRY *h; 189 { 190 sigchk(); 191 192 if (hashtype(h->data) == NOTFOUND) 193 return; 194 195 if (h->data & (BUILTIN | FUNCTION)) 196 return; 197 198 prn_buff(h->hits); 199 200 if (h->data & REL_COMMAND) 201 prc_buff('*'); 202 203 204 prc_buff(TAB); 205 prn_buff(h->cost); 206 prc_buff(TAB); 207 208 pr_path(h->key, hashdata(h->data)); 209 prc_buff(NL); 210 } 211 212 void 213 hashpr() 214 { 215 prs_buff("hits cost command\n"); 216 hscan(hashout); 217 } 218 219 void 220 set_dotpath(void) 221 { 222 unsigned char *path; 223 int cnt = 1; 224 225 dotpath = 10000; 226 path = getpath(""); 227 228 while (path && *path) 229 { 230 if (*path == '/') 231 cnt++; 232 else 233 { 234 if (dotpath == 10000) 235 dotpath = cnt; 236 else 237 { 238 multrel = 1; 239 return; 240 } 241 } 242 243 path = nextpath(path); 244 } 245 246 multrel = 0; 247 } 248 249 void 250 hash_func(unsigned char *name) 251 { 252 ENTRY *h; 253 ENTRY hentry; 254 255 h = hfind(name); 256 257 if (h) 258 h->data = FUNCTION; 259 else 260 { 261 hentry.data = FUNCTION; 262 hentry.key = make(name); 263 hentry.cost = 0; 264 hentry.hits = 0; 265 henter(hentry); 266 } 267 } 268 269 void 270 func_unhash(unsigned char *name) 271 { 272 ENTRY *h; 273 int i; 274 275 h = hfind(name); 276 277 if (h && (h->data & FUNCTION)) { 278 if(i = syslook(name, commands, no_commands)) 279 h->data = (BUILTIN|i); 280 else 281 h->data = NOTFOUND; 282 } 283 } 284 285 286 short 287 hash_cmd(name) 288 unsigned char *name; 289 { 290 ENTRY *h; 291 292 if (any('/', name)) 293 return(COMMAND); 294 295 h = hfind(name); 296 297 if (h) 298 { 299 if (h->data & (BUILTIN | FUNCTION)) 300 return(h->data); 301 else if ((h->data & REL_COMMAND) == REL_COMMAND) 302 { /* unlink h from relative command list */ 303 ENTRY *ptr = &relcmd; 304 while(ptr-> next != h) 305 ptr = ptr->next; 306 ptr->next = h->next; 307 } 308 zapentry(h); 309 } 310 311 return(pathlook(name, 0, 0)); 312 } 313 314 315 /* 316 * Return 0 if found, 1 if not. 317 */ 318 int 319 what_is_path(unsigned char *name) 320 { 321 ENTRY *h; 322 int cnt; 323 short hashval; 324 325 h = hfind(name); 326 327 prs_buff(name); 328 if (h) 329 { 330 hashval = hashdata(h->data); 331 332 switch (hashtype(h->data)) 333 { 334 case BUILTIN: 335 prs_buff(" is a shell builtin\n"); 336 return (0); 337 338 case FUNCTION: 339 { 340 struct namnod *n = lookup(name); 341 342 prs_buff(" is a function\n"); 343 prs_buff(name); 344 prs_buff("(){\n"); 345 prf(n->namenv); 346 prs_buff("\n}\n"); 347 return (0); 348 } 349 350 case REL_COMMAND: 351 { 352 short hash; 353 354 if ((h->data & DOT_COMMAND) == DOT_COMMAND) 355 { 356 hash = pathlook(name, 0, 0); 357 if (hashtype(hash) == NOTFOUND) 358 { 359 prs_buff(" not found\n"); 360 return (1); 361 } 362 else 363 hashval = hashdata(hash); 364 } 365 } 366 367 case COMMAND: 368 prs_buff(" is hashed ("); 369 pr_path(name, hashval); 370 prs_buff(")\n"); 371 return (0); 372 } 373 } 374 375 if (syslook(name, commands, no_commands)) 376 { 377 prs_buff(" is a shell builtin\n"); 378 return (0); 379 } 380 381 if ((cnt = findpath(name, 0)) > 0) 382 { 383 prs_buff(" is "); 384 pr_path(name, cnt); 385 prc_buff(NL); 386 return (0); 387 } 388 else 389 { 390 prs_buff(" not found\n"); 391 return (1); 392 } 393 } 394 395 int 396 findpath(unsigned char *name, int oldpath) 397 { 398 unsigned char *path; 399 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 int 454 chk_access(unsigned char *name, mode_t mode, int regflag) 455 { 456 static int flag; 457 static uid_t euid; 458 struct stat statb; 459 mode_t ftype; 460 461 if(flag == 0) { 462 euid = geteuid(); 463 flag = 1; 464 } 465 ftype = statb.st_mode & S_IFMT; 466 if (stat((char *)name, &statb) == 0) { 467 ftype = statb.st_mode & S_IFMT; 468 if(mode == S_IEXEC && regflag && ftype != S_IFREG) 469 return(2); 470 if(access((char *)name, 010|(mode>>6)) == 0) { 471 if(euid == 0) { 472 if (ftype != S_IFREG || mode != S_IEXEC) 473 return(0); 474 /* root can execute file as long as it has execute 475 permission for someone */ 476 if (statb.st_mode & (S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6))) 477 return(0); 478 return(3); 479 } 480 return(0); 481 } 482 } 483 return(errno == EACCES ? 3 : 1); 484 } 485 486 static void 487 pr_path(unsigned char *name, int count) 488 { 489 unsigned char *path; 490 491 path = getpath(name); 492 493 while (--count && path) 494 path = nextpath(path, name); 495 496 catpath(path, name); 497 prs_buff(curstak()); 498 } 499 500 501 static int 502 argpath(struct argnod *arg) 503 { 504 unsigned char *s; 505 unsigned char *start; 506 507 while (arg) 508 { 509 s = arg->argval; 510 start = s; 511 512 if (letter(*s)) 513 { 514 while (alphanum(*s)) 515 s++; 516 517 if (*s == '=') 518 { 519 *s = 0; 520 521 if (eq(start, pathname)) 522 { 523 *s = '='; 524 return(1); 525 } 526 else 527 *s = '='; 528 } 529 } 530 arg = arg->argnxt; 531 } 532 533 return(0); 534 } 535