xref: /titanic_52/usr/src/cmd/sh/hashserv.c (revision 1a7c1b724419d3cb5fa6eea75123c6b2060ba31b)
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