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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 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 static void pr_path(unsigned char *, int); 49 50 short 51 pathlook(com, flg, arg) 52 unsigned char *com; 53 int flg; 54 struct argnod *arg; 55 { 56 unsigned char *name = com; 57 ENTRY *h; 58 59 ENTRY hentry; 60 int count = 0; 61 int i; 62 int pathset = 0; 63 int oldpath = 0; 64 struct namnod *n; 65 66 67 68 hentry.data = 0; 69 70 if (any('/', name)) 71 return(COMMAND); 72 73 h = hfind(name); 74 75 76 if (h) 77 { 78 if (h->data & (BUILTIN | FUNCTION)) 79 { 80 if (flg) 81 h->hits++; 82 return(h->data); 83 } 84 85 if (arg && (pathset = argpath(arg))) 86 return(PATH_COMMAND); 87 88 if ((h->data & DOT_COMMAND) == DOT_COMMAND) 89 { 90 if (multrel == 0 && hashdata(h->data) > dotpath) 91 oldpath = hashdata(h->data); 92 else 93 oldpath = dotpath; 94 95 h->data = 0; 96 goto pathsrch; 97 } 98 99 if (h->data & (COMMAND | REL_COMMAND)) 100 { 101 if (flg) 102 h->hits++; 103 return(h->data); 104 } 105 106 h->data = 0; 107 h->cost = 0; 108 } 109 110 if (i = syslook(name, commands, no_commands)) 111 { 112 hentry.data = (BUILTIN | i); 113 count = 1; 114 } 115 else 116 { 117 if (arg && (pathset = argpath(arg))) 118 return(PATH_COMMAND); 119 pathsrch: 120 count = findpath(name, oldpath); 121 } 122 123 if (count > 0) 124 { 125 if (h == 0) 126 { 127 hentry.cost = 0; 128 hentry.key = make(name); 129 h = henter(hentry); 130 } 131 132 if (h->data == 0) 133 { 134 if (count < dotpath) 135 h->data = COMMAND | count; 136 else 137 { 138 h->data = REL_COMMAND | count; 139 h->next = relcmd.next; 140 relcmd.next = h; 141 } 142 } 143 144 145 h->hits = flg; 146 h->cost += cost; 147 return(h->data); 148 } 149 else 150 { 151 return(-count); 152 } 153 } 154 155 156 static void 157 zapentry(h) 158 ENTRY *h; 159 { 160 h->data &= HASHZAP; 161 } 162 163 void 164 zaphash() 165 { 166 hscan(zapentry); 167 relcmd.next = 0; 168 } 169 170 void 171 zapcd() 172 { 173 ENTRY *ptr = relcmd.next; 174 175 while (ptr) 176 { 177 ptr->data |= CDMARK; 178 ptr = ptr->next; 179 } 180 relcmd.next = 0; 181 } 182 183 184 static void 185 hashout(h) 186 ENTRY *h; 187 { 188 sigchk(); 189 190 if (hashtype(h->data) == NOTFOUND) 191 return; 192 193 if (h->data & (BUILTIN | FUNCTION)) 194 return; 195 196 prn_buff(h->hits); 197 198 if (h->data & REL_COMMAND) 199 prc_buff('*'); 200 201 202 prc_buff(TAB); 203 prn_buff(h->cost); 204 prc_buff(TAB); 205 206 pr_path(h->key, hashdata(h->data)); 207 prc_buff(NL); 208 } 209 210 void 211 hashpr() 212 { 213 prs_buff(_gettext("hits cost command\n")); 214 hscan(hashout); 215 } 216 217 void 218 set_dotpath(void) 219 { 220 unsigned char *path; 221 int cnt = 1; 222 223 dotpath = 10000; 224 path = getpath(""); 225 226 while (path && *path) 227 { 228 if (*path == '/') 229 cnt++; 230 else 231 { 232 if (dotpath == 10000) 233 dotpath = cnt; 234 else 235 { 236 multrel = 1; 237 return; 238 } 239 } 240 241 path = nextpath(path); 242 } 243 244 multrel = 0; 245 } 246 247 void 248 hash_func(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 void 268 func_unhash(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 int 317 what_is_path(unsigned char *name) 318 { 319 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(_gettext(" is a shell builtin\n")); 334 return (0); 335 336 case FUNCTION: 337 { 338 struct namnod *n = lookup(name); 339 struct fndnod *f = fndptr(n->namenv); 340 341 prs_buff(_gettext(" is a function\n")); 342 prs_buff(name); 343 prs_buff("(){\n"); 344 if (f != NULL) 345 prf(f->fndval); 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(_gettext(" not" 360 " found\n")); 361 return (1); 362 } 363 else 364 hashval = hashdata(hash); 365 } 366 } 367 368 case COMMAND: 369 prs_buff(_gettext(" is hashed (")); 370 pr_path(name, hashval); 371 prs_buff(")\n"); 372 return (0); 373 } 374 } 375 376 if (syslook(name, commands, no_commands)) 377 { 378 prs_buff(_gettext(" is a shell builtin\n")); 379 return (0); 380 } 381 382 if ((cnt = findpath(name, 0)) > 0) 383 { 384 prs_buff(_gettext(" is ")); 385 pr_path(name, cnt); 386 prc_buff(NL); 387 return (0); 388 } 389 else 390 { 391 prs_buff(_gettext(" not found\n")); 392 return (1); 393 } 394 } 395 396 int 397 findpath(unsigned char *name, int oldpath) 398 { 399 unsigned char *path; 400 int count = 1; 401 402 unsigned char *p; 403 int ok = 1; 404 int e_code = 1; 405 406 cost = 0; 407 path = getpath(name); 408 409 if (oldpath) 410 { 411 count = dotpath; 412 while (--count) 413 path = nextpath(path); 414 415 if (oldpath > dotpath) 416 { 417 catpath(path, name); 418 p = curstak(); 419 cost = 1; 420 421 if ((ok = chk_access(p, S_IEXEC, 1)) == 0) 422 return(dotpath); 423 else 424 return(oldpath); 425 } 426 else 427 count = dotpath; 428 } 429 430 while (path) 431 { 432 path = catpath(path, name); 433 cost++; 434 p = curstak(); 435 436 if ((ok = chk_access(p, S_IEXEC, 1)) == 0) 437 break; 438 else 439 e_code = max(e_code, ok); 440 441 count++; 442 } 443 444 return(ok ? -e_code : count); 445 } 446 447 /* 448 * Determine if file given by name is accessible with permissions 449 * given by mode. 450 * Regflag argument non-zero means not to consider 451 * a non-regular file as executable. 452 */ 453 454 int 455 chk_access(unsigned char *name, mode_t mode, int regflag) 456 { 457 static int flag; 458 static uid_t euid; 459 struct stat statb; 460 mode_t ftype; 461 462 if(flag == 0) { 463 euid = geteuid(); 464 flag = 1; 465 } 466 ftype = statb.st_mode & S_IFMT; 467 if (stat((char *)name, &statb) == 0) { 468 ftype = statb.st_mode & S_IFMT; 469 if(mode == S_IEXEC && regflag && ftype != S_IFREG) 470 return(2); 471 if(access((char *)name, 010|(mode>>6)) == 0) { 472 if(euid == 0) { 473 if (ftype != S_IFREG || mode != S_IEXEC) 474 return(0); 475 /* root can execute file as long as it has execute 476 permission for someone */ 477 if (statb.st_mode & (S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6))) 478 return(0); 479 return(3); 480 } 481 return(0); 482 } 483 } 484 return(errno == EACCES ? 3 : 1); 485 } 486 487 static void 488 pr_path(unsigned char *name, int count) 489 { 490 unsigned char *path; 491 492 path = getpath(name); 493 494 while (--count && path) 495 path = nextpath(path, name); 496 497 catpath(path, name); 498 prs_buff(curstak()); 499 } 500 501 502 static int 503 argpath(struct argnod *arg) 504 { 505 unsigned char *s; 506 unsigned char *start; 507 508 while (arg) 509 { 510 s = arg->argval; 511 start = s; 512 513 if (letter(*s)) 514 { 515 while (alphanum(*s)) 516 s++; 517 518 if (*s == '=') 519 { 520 *s = 0; 521 522 if (eq(start, pathname)) 523 { 524 *s = '='; 525 return(1); 526 } 527 else 528 *s = '='; 529 } 530 } 531 arg = arg->argnxt; 532 } 533 534 return(0); 535 } 536