15325 bhyve upstream sync 2023 January
[illumos-gate.git] / usr / src / cmd / sh / hashserv.c
blob5c49f3ff735bf5fbaf21df798d239ee3d43b8622
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
31 * UNIX shell
34 #include "hash.h"
35 #include "defs.h"
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <errno.h>
40 #define EXECUTE 01
42 static unsigned char cost;
43 static int dotpath;
44 static int multrel;
45 static struct entry relcmd;
47 static int argpath();
48 static void pr_path(unsigned char *, int);
50 short
51 pathlook(com, flg, arg)
52 unsigned char *com;
53 int flg;
54 struct argnod *arg;
56 unsigned char *name = com;
57 ENTRY *h;
59 ENTRY hentry;
60 int count = 0;
61 int i;
62 int pathset = 0;
63 int oldpath = 0;
64 struct namnod *n;
68 hentry.data = 0;
70 if (any('/', name))
71 return(COMMAND);
73 h = hfind(name);
76 if (h)
78 if (h->data & (BUILTIN | FUNCTION))
80 if (flg)
81 h->hits++;
82 return(h->data);
85 if (arg && (pathset = argpath(arg)))
86 return(PATH_COMMAND);
88 if ((h->data & DOT_COMMAND) == DOT_COMMAND)
90 if (multrel == 0 && hashdata(h->data) > dotpath)
91 oldpath = hashdata(h->data);
92 else
93 oldpath = dotpath;
95 h->data = 0;
96 goto pathsrch;
99 if (h->data & (COMMAND | REL_COMMAND))
101 if (flg)
102 h->hits++;
103 return(h->data);
106 h->data = 0;
107 h->cost = 0;
110 if (i = syslook(name, commands, no_commands))
112 hentry.data = (BUILTIN | i);
113 count = 1;
115 else
117 if (arg && (pathset = argpath(arg)))
118 return(PATH_COMMAND);
119 pathsrch:
120 count = findpath(name, oldpath);
123 if (count > 0)
125 if (h == 0)
127 hentry.cost = 0;
128 hentry.key = make(name);
129 h = henter(hentry);
132 if (h->data == 0)
134 if (count < dotpath)
135 h->data = COMMAND | count;
136 else
138 h->data = REL_COMMAND | count;
139 h->next = relcmd.next;
140 relcmd.next = h;
145 h->hits = flg;
146 h->cost += cost;
147 return(h->data);
149 else
151 return(-count);
156 static void
157 zapentry(h)
158 ENTRY *h;
160 h->data &= HASHZAP;
163 void
164 zaphash()
166 hscan(zapentry);
167 relcmd.next = 0;
170 void
171 zapcd()
173 ENTRY *ptr = relcmd.next;
175 while (ptr)
177 ptr->data |= CDMARK;
178 ptr = ptr->next;
180 relcmd.next = 0;
184 static void
185 hashout(h)
186 ENTRY *h;
188 sigchk();
190 if (hashtype(h->data) == NOTFOUND)
191 return;
193 if (h->data & (BUILTIN | FUNCTION))
194 return;
196 prn_buff(h->hits);
198 if (h->data & REL_COMMAND)
199 prc_buff('*');
202 prc_buff(TAB);
203 prn_buff(h->cost);
204 prc_buff(TAB);
206 pr_path(h->key, hashdata(h->data));
207 prc_buff(NL);
210 void
211 hashpr()
213 prs_buff(_gettext("hits cost command\n"));
214 hscan(hashout);
217 void
218 set_dotpath(void)
220 unsigned char *path;
221 int cnt = 1;
223 dotpath = 10000;
224 path = getpath("");
226 while (path && *path)
228 if (*path == '/')
229 cnt++;
230 else
232 if (dotpath == 10000)
233 dotpath = cnt;
234 else
236 multrel = 1;
237 return;
241 path = nextpath(path);
244 multrel = 0;
247 void
248 hash_func(unsigned char *name)
250 ENTRY *h;
251 ENTRY hentry;
253 h = hfind(name);
255 if (h)
256 h->data = FUNCTION;
257 else
259 hentry.data = FUNCTION;
260 hentry.key = make(name);
261 hentry.cost = 0;
262 hentry.hits = 0;
263 henter(hentry);
267 void
268 func_unhash(unsigned char *name)
270 ENTRY *h;
271 int i;
273 h = hfind(name);
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;
284 short
285 hash_cmd(name)
286 unsigned char *name;
288 ENTRY *h;
290 if (any('/', name))
291 return(COMMAND);
293 h = hfind(name);
295 if (h)
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;
306 zapentry(h);
309 return(pathlook(name, 0, 0));
314 * Return 0 if found, 1 if not.
317 what_is_path(unsigned char *name)
319 ENTRY *h;
320 int cnt;
321 short hashval;
323 h = hfind(name);
325 prs_buff(name);
326 if (h)
328 hashval = hashdata(h->data);
330 switch (hashtype(h->data))
332 case BUILTIN:
333 prs_buff(_gettext(" is a shell builtin\n"));
334 return (0);
336 case FUNCTION:
338 struct namnod *n = lookup(name);
339 struct fndnod *f = fndptr(n->namenv);
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);
350 case REL_COMMAND:
352 short hash;
354 if ((h->data & DOT_COMMAND) == DOT_COMMAND)
356 hash = pathlook(name, 0, 0);
357 if (hashtype(hash) == NOTFOUND)
359 prs_buff(_gettext(" not"
360 " found\n"));
361 return (1);
363 else
364 hashval = hashdata(hash);
368 case COMMAND:
369 prs_buff(_gettext(" is hashed ("));
370 pr_path(name, hashval);
371 prs_buff(")\n");
372 return (0);
376 if (syslook(name, commands, no_commands))
378 prs_buff(_gettext(" is a shell builtin\n"));
379 return (0);
382 if ((cnt = findpath(name, 0)) > 0)
384 prs_buff(_gettext(" is "));
385 pr_path(name, cnt);
386 prc_buff(NL);
387 return (0);
389 else
391 prs_buff(_gettext(" not found\n"));
392 return (1);
397 findpath(unsigned char *name, int oldpath)
399 unsigned char *path;
400 int count = 1;
402 unsigned char *p;
403 int ok = 1;
404 int e_code = 1;
406 cost = 0;
407 path = getpath(name);
409 if (oldpath)
411 count = dotpath;
412 while (--count)
413 path = nextpath(path);
415 if (oldpath > dotpath)
417 catpath(path, name);
418 p = curstak();
419 cost = 1;
421 if ((ok = chk_access(p, S_IEXEC, 1)) == 0)
422 return(dotpath);
423 else
424 return(oldpath);
426 else
427 count = dotpath;
430 while (path)
432 path = catpath(path, name);
433 cost++;
434 p = curstak();
436 if ((ok = chk_access(p, S_IEXEC, 1)) == 0)
437 break;
438 else
439 e_code = max(e_code, ok);
441 count++;
444 return(ok ? -e_code : count);
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.
455 chk_access(unsigned char *name, mode_t mode, int regflag)
457 static int flag;
458 static uid_t euid;
459 struct stat statb;
460 mode_t ftype;
462 if(flag == 0) {
463 euid = geteuid();
464 flag = 1;
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);
481 return(0);
484 return(errno == EACCES ? 3 : 1);
487 static void
488 pr_path(unsigned char *name, int count)
490 unsigned char *path;
492 path = getpath(name);
494 while (--count && path)
495 path = nextpath(path, name);
497 catpath(path, name);
498 prs_buff(curstak());
502 static int
503 argpath(struct argnod *arg)
505 unsigned char *s;
506 unsigned char *start;
508 while (arg)
510 s = arg->argval;
511 start = s;
513 if (letter(*s))
515 while (alphanum(*s))
516 s++;
518 if (*s == '=')
520 *s = 0;
522 if (eq(start, pathname))
524 *s = '=';
525 return(1);
527 else
528 *s = '=';
531 arg = arg->argnxt;
534 return(0);