xref: /titanic_52/usr/src/cmd/csh/sh.exp.c (revision fd5e9823d4460a5415f67ed45c1ba18531689ecc)
17c478bd9Sstevel@tonic-gate /*
2*fd5e9823Sblu  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
77c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
87c478bd9Sstevel@tonic-gate 
97c478bd9Sstevel@tonic-gate /*
107c478bd9Sstevel@tonic-gate  * Copyright (c) 1980 Regents of the University of California.
117c478bd9Sstevel@tonic-gate  * All rights reserved.  The Berkeley Software License Agreement
127c478bd9Sstevel@tonic-gate  * specifies the terms and conditions for redistribution.
137c478bd9Sstevel@tonic-gate  */
147c478bd9Sstevel@tonic-gate 
157c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
167c478bd9Sstevel@tonic-gate 
177c478bd9Sstevel@tonic-gate #include "sh.h"
187c478bd9Sstevel@tonic-gate #include "sh.tconst.h"
197c478bd9Sstevel@tonic-gate 
207c478bd9Sstevel@tonic-gate /*
217c478bd9Sstevel@tonic-gate  * C shell
227c478bd9Sstevel@tonic-gate  */
237c478bd9Sstevel@tonic-gate 
247c478bd9Sstevel@tonic-gate #define	IGNORE	1	/* in ignore, it means to ignore value, just parse */
257c478bd9Sstevel@tonic-gate #define	NOGLOB	2	/* in ignore, it means not to globone */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #define	ADDOP	1
287c478bd9Sstevel@tonic-gate #define	MULOP	2
297c478bd9Sstevel@tonic-gate #define	EQOP	4
307c478bd9Sstevel@tonic-gate #define	RELOP	8
317c478bd9Sstevel@tonic-gate #define	RESTOP	16
327c478bd9Sstevel@tonic-gate #define	ANYOP	31
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate #define	EQEQ	1
357c478bd9Sstevel@tonic-gate #define	GTR	2
367c478bd9Sstevel@tonic-gate #define	LSS	4
377c478bd9Sstevel@tonic-gate #define	NOTEQ	6
387c478bd9Sstevel@tonic-gate #define	EQMATCH 7
397c478bd9Sstevel@tonic-gate #define	NOTEQMATCH 8
407c478bd9Sstevel@tonic-gate 
416c02b4a4Smuffin int	exp0(tchar ***, bool);
426c02b4a4Smuffin int	exp1(tchar ***, bool);
436c02b4a4Smuffin int	exp2(tchar ***, bool);
446c02b4a4Smuffin int	exp2a(tchar ***, bool);
456c02b4a4Smuffin int	exp2b(tchar ***, bool);
466c02b4a4Smuffin int	exp2c(tchar ***, bool);
476c02b4a4Smuffin tchar	*exp3(tchar ***, bool);
486c02b4a4Smuffin tchar	*exp3a(tchar ***, bool);
496c02b4a4Smuffin tchar	*exp4(tchar ***, bool);
506c02b4a4Smuffin tchar	*exp5(tchar ***, bool);
516c02b4a4Smuffin tchar	*exp6(tchar ***, bool);
526c02b4a4Smuffin void	evalav(tchar **);
536c02b4a4Smuffin 
547c478bd9Sstevel@tonic-gate /*
557c478bd9Sstevel@tonic-gate  * Determine if file given by name is accessible with permissions
567c478bd9Sstevel@tonic-gate  * given by mode.
577c478bd9Sstevel@tonic-gate  *
587c478bd9Sstevel@tonic-gate  * Borrowed from the Bourne sh, and modified a bit
597c478bd9Sstevel@tonic-gate  *
607c478bd9Sstevel@tonic-gate  * If the requested access  is  permitted,  a  value  of  0  is
617c478bd9Sstevel@tonic-gate  * returned.  Otherwise, a value of -1 is returned and errno is
627c478bd9Sstevel@tonic-gate  * set to indicate the error
637c478bd9Sstevel@tonic-gate  */
647c478bd9Sstevel@tonic-gate 
656c02b4a4Smuffin int
666c02b4a4Smuffin chk_access(tchar *path, mode_t mode)
677c478bd9Sstevel@tonic-gate {
687c478bd9Sstevel@tonic-gate 	static int flag;
697c478bd9Sstevel@tonic-gate 	static uid_t euid;
707c478bd9Sstevel@tonic-gate 	struct stat statb;
717c478bd9Sstevel@tonic-gate 	mode_t ftype;
727c478bd9Sstevel@tonic-gate 	unsigned char name[MAXPATHLEN*MB_LEN_MAX]; /* General use buffer. */
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate 	/* convert tchar * to char * */
757c478bd9Sstevel@tonic-gate 	tstostr(name, path);
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate 	if (flag == 0) {
787c478bd9Sstevel@tonic-gate 		euid = geteuid();
797c478bd9Sstevel@tonic-gate 		flag = 1;
807c478bd9Sstevel@tonic-gate 	}
817c478bd9Sstevel@tonic-gate 	if (stat((char *)name, &statb) == 0) {
827c478bd9Sstevel@tonic-gate 		ftype = statb.st_mode & S_IFMT;
837c478bd9Sstevel@tonic-gate 		if (access((char *)name, 010|(mode>>6)) == 0) {
847c478bd9Sstevel@tonic-gate 			if (euid == 0) {
857c478bd9Sstevel@tonic-gate 				if (ftype != S_IFREG || mode != S_IEXEC)
867c478bd9Sstevel@tonic-gate 					return (0);
877c478bd9Sstevel@tonic-gate 				/* root can execute file as long as it has execute
887c478bd9Sstevel@tonic-gate 				permission for someone */
897c478bd9Sstevel@tonic-gate 				if (statb.st_mode & (S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6)))
907c478bd9Sstevel@tonic-gate 					return (0);
917c478bd9Sstevel@tonic-gate 				return (-1);
927c478bd9Sstevel@tonic-gate 			}
937c478bd9Sstevel@tonic-gate 			return (0);
947c478bd9Sstevel@tonic-gate 		}
957c478bd9Sstevel@tonic-gate 	}
967c478bd9Sstevel@tonic-gate 	return (-1);
977c478bd9Sstevel@tonic-gate }
987c478bd9Sstevel@tonic-gate 
996c02b4a4Smuffin int
1006c02b4a4Smuffin exp(tchar ***vp)
1017c478bd9Sstevel@tonic-gate {
1027c478bd9Sstevel@tonic-gate #ifdef TRACE
1037c478bd9Sstevel@tonic-gate 	tprintf("TRACE- exp()\n");
1047c478bd9Sstevel@tonic-gate #endif
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate 	return (exp0(vp, 0));
1077c478bd9Sstevel@tonic-gate }
1087c478bd9Sstevel@tonic-gate 
1096c02b4a4Smuffin int
1106c02b4a4Smuffin exp0(tchar ***vp, bool ignore)
1117c478bd9Sstevel@tonic-gate {
1126c02b4a4Smuffin 	int p1 = exp1(vp, ignore);
1137c478bd9Sstevel@tonic-gate #ifdef TRACE
1147c478bd9Sstevel@tonic-gate 	tprintf("TRACE- exp0()\n");
1157c478bd9Sstevel@tonic-gate #endif
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate #ifdef EDEBUG
1187c478bd9Sstevel@tonic-gate 	etraci("exp0 p1", p1, vp);
1197c478bd9Sstevel@tonic-gate #endif
1207c478bd9Sstevel@tonic-gate 	if (**vp && eq(**vp, S_BARBAR /* "||" */)) {
1216c02b4a4Smuffin 		int p2;
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate 		(*vp)++;
1247c478bd9Sstevel@tonic-gate 		p2 = exp0(vp, (ignore&IGNORE) || p1);
1257c478bd9Sstevel@tonic-gate #ifdef EDEBUG
1267c478bd9Sstevel@tonic-gate 		etraci("exp0 p2", p2, vp);
1277c478bd9Sstevel@tonic-gate #endif
1287c478bd9Sstevel@tonic-gate 		return (p1 || p2);
1297c478bd9Sstevel@tonic-gate 	}
1307c478bd9Sstevel@tonic-gate 	return (p1);
1317c478bd9Sstevel@tonic-gate }
1327c478bd9Sstevel@tonic-gate 
1336c02b4a4Smuffin int
1346c02b4a4Smuffin exp1(tchar ***vp, bool ignore)
1357c478bd9Sstevel@tonic-gate {
1366c02b4a4Smuffin 	int p1 = exp2(vp, ignore);
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate #ifdef TRACE
1397c478bd9Sstevel@tonic-gate 	tprintf("TRACE- exp1()\n");
1407c478bd9Sstevel@tonic-gate #endif
1417c478bd9Sstevel@tonic-gate #ifdef EDEBUG
1427c478bd9Sstevel@tonic-gate 	etraci("exp1 p1", p1, vp);
1437c478bd9Sstevel@tonic-gate #endif
1447c478bd9Sstevel@tonic-gate 	if (**vp && eq(**vp, S_ANDAND /* "&&" */)) {
1456c02b4a4Smuffin 		int p2;
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate 		(*vp)++;
1487c478bd9Sstevel@tonic-gate 		p2 = exp1(vp, (ignore&IGNORE) || !p1);
1497c478bd9Sstevel@tonic-gate #ifdef EDEBUG
1507c478bd9Sstevel@tonic-gate 		etraci("exp1 p2", p2, vp);
1517c478bd9Sstevel@tonic-gate #endif
1527c478bd9Sstevel@tonic-gate 		return (p1 && p2);
1537c478bd9Sstevel@tonic-gate 	}
1547c478bd9Sstevel@tonic-gate 	return (p1);
1557c478bd9Sstevel@tonic-gate }
1567c478bd9Sstevel@tonic-gate 
1576c02b4a4Smuffin int
1586c02b4a4Smuffin exp2(tchar ***vp, bool ignore)
1597c478bd9Sstevel@tonic-gate {
1606c02b4a4Smuffin 	int p1 = exp2a(vp, ignore);
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate #ifdef TRACE
1637c478bd9Sstevel@tonic-gate 	tprintf("TRACE- exp2()\n");
1647c478bd9Sstevel@tonic-gate #endif
1657c478bd9Sstevel@tonic-gate #ifdef EDEBUG
1667c478bd9Sstevel@tonic-gate 	etraci("exp3 p1", p1, vp);
1677c478bd9Sstevel@tonic-gate #endif
1687c478bd9Sstevel@tonic-gate 	if (**vp && eq(**vp, S_BAR /* "|" */)) {
1696c02b4a4Smuffin 		int p2;
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate 		(*vp)++;
1727c478bd9Sstevel@tonic-gate 		p2 = exp2(vp, ignore);
1737c478bd9Sstevel@tonic-gate #ifdef EDEBUG
1747c478bd9Sstevel@tonic-gate 		etraci("exp3 p2", p2, vp);
1757c478bd9Sstevel@tonic-gate #endif
1767c478bd9Sstevel@tonic-gate 		return (p1 | p2);
1777c478bd9Sstevel@tonic-gate 	}
1787c478bd9Sstevel@tonic-gate 	return (p1);
1797c478bd9Sstevel@tonic-gate }
1807c478bd9Sstevel@tonic-gate 
1816c02b4a4Smuffin int
1826c02b4a4Smuffin exp2a(tchar ***vp, bool ignore)
1837c478bd9Sstevel@tonic-gate {
1846c02b4a4Smuffin 	int p1 = exp2b(vp, ignore);
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate #ifdef TRACE
1877c478bd9Sstevel@tonic-gate 	tprintf("TRACE- exp2a()\n");
1887c478bd9Sstevel@tonic-gate #endif
1897c478bd9Sstevel@tonic-gate #ifdef EDEBUG
1907c478bd9Sstevel@tonic-gate 	etraci("exp2a p1", p1, vp);
1917c478bd9Sstevel@tonic-gate #endif
1927c478bd9Sstevel@tonic-gate 	if (**vp && eq(**vp, S_HAT /* "^" */)) {
1936c02b4a4Smuffin 		int p2;
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate 		(*vp)++;
1967c478bd9Sstevel@tonic-gate 		p2 = exp2a(vp, ignore);
1977c478bd9Sstevel@tonic-gate #ifdef EDEBUG
1987c478bd9Sstevel@tonic-gate 		etraci("exp2a p2", p2, vp);
1997c478bd9Sstevel@tonic-gate #endif
2007c478bd9Sstevel@tonic-gate 		return (p1 ^ p2);
2017c478bd9Sstevel@tonic-gate 	}
2027c478bd9Sstevel@tonic-gate 	return (p1);
2037c478bd9Sstevel@tonic-gate }
2047c478bd9Sstevel@tonic-gate 
2056c02b4a4Smuffin int
2066c02b4a4Smuffin exp2b(tchar ***vp, bool ignore)
2077c478bd9Sstevel@tonic-gate {
2086c02b4a4Smuffin 	int p1 = exp2c(vp, ignore);
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate #ifdef TRACE
2117c478bd9Sstevel@tonic-gate 	tprintf("TRACE- exp2b()\n");
2127c478bd9Sstevel@tonic-gate #endif
2137c478bd9Sstevel@tonic-gate #ifdef EDEBUG
2147c478bd9Sstevel@tonic-gate 	etraci("exp2b p1", p1, vp);
2157c478bd9Sstevel@tonic-gate #endif
2167c478bd9Sstevel@tonic-gate 	if (**vp && eq(**vp, S_AND /* "&" */)) {
2176c02b4a4Smuffin 		int p2;
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate 		(*vp)++;
2207c478bd9Sstevel@tonic-gate 		p2 = exp2b(vp, ignore);
2217c478bd9Sstevel@tonic-gate #ifdef EDEBUG
2227c478bd9Sstevel@tonic-gate 		etraci("exp2b p2", p2, vp);
2237c478bd9Sstevel@tonic-gate #endif
2247c478bd9Sstevel@tonic-gate 		return (p1 & p2);
2257c478bd9Sstevel@tonic-gate 	}
2267c478bd9Sstevel@tonic-gate 	return (p1);
2277c478bd9Sstevel@tonic-gate }
2287c478bd9Sstevel@tonic-gate 
2296c02b4a4Smuffin int
2306c02b4a4Smuffin exp2c(tchar ***vp, bool ignore)
2317c478bd9Sstevel@tonic-gate {
2326c02b4a4Smuffin 	tchar *p1 = exp3(vp, ignore);
2336c02b4a4Smuffin 	tchar *p2;
2346c02b4a4Smuffin 	int i;
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate #ifdef TRACE
2377c478bd9Sstevel@tonic-gate 	tprintf("TRACE- exp2c()\n");
2387c478bd9Sstevel@tonic-gate #endif
2397c478bd9Sstevel@tonic-gate #ifdef EDEBUG
2407c478bd9Sstevel@tonic-gate 	etracc("exp2c p1", p1, vp);
2417c478bd9Sstevel@tonic-gate #endif
2427c478bd9Sstevel@tonic-gate 	if (i = isa(**vp, EQOP)) {
2437c478bd9Sstevel@tonic-gate 		(*vp)++;
2447c478bd9Sstevel@tonic-gate 		if (i == EQMATCH || i == NOTEQMATCH)
2457c478bd9Sstevel@tonic-gate 			ignore |= NOGLOB;
2467c478bd9Sstevel@tonic-gate 		p2 = exp3(vp, ignore);
2477c478bd9Sstevel@tonic-gate #ifdef EDEBUG
2487c478bd9Sstevel@tonic-gate 		etracc("exp2c p2", p2, vp);
2497c478bd9Sstevel@tonic-gate #endif
2507c478bd9Sstevel@tonic-gate 		if (!(ignore&IGNORE)) switch (i) {
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 		case EQEQ:
2537c478bd9Sstevel@tonic-gate 			i = eq(p1, p2);
2547c478bd9Sstevel@tonic-gate 			break;
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate 		case NOTEQ:
2577c478bd9Sstevel@tonic-gate 			i = !eq(p1, p2);
2587c478bd9Sstevel@tonic-gate 			break;
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate 		case EQMATCH:
2617c478bd9Sstevel@tonic-gate 			i = Gmatch(p1, p2);
2627c478bd9Sstevel@tonic-gate 			break;
2637c478bd9Sstevel@tonic-gate 
2647c478bd9Sstevel@tonic-gate 		case NOTEQMATCH:
2657c478bd9Sstevel@tonic-gate 			i = !Gmatch(p1, p2);
2667c478bd9Sstevel@tonic-gate 			break;
2677c478bd9Sstevel@tonic-gate 		}
2687c478bd9Sstevel@tonic-gate 		xfree(p1), xfree(p2);
2697c478bd9Sstevel@tonic-gate 		return (i);
2707c478bd9Sstevel@tonic-gate 	}
2717c478bd9Sstevel@tonic-gate 	i = egetn(p1);
2727c478bd9Sstevel@tonic-gate 	xfree(p1);
2737c478bd9Sstevel@tonic-gate 	return (i);
2747c478bd9Sstevel@tonic-gate }
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate tchar *
2776c02b4a4Smuffin exp3(tchar ***vp, bool ignore)
2787c478bd9Sstevel@tonic-gate {
2796c02b4a4Smuffin 	tchar *p1, *p2;
2806c02b4a4Smuffin 	int i;
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate #ifdef TRACE
2837c478bd9Sstevel@tonic-gate 	tprintf("TRACE- exp3()\n");
2847c478bd9Sstevel@tonic-gate #endif
2857c478bd9Sstevel@tonic-gate 	p1 = exp3a(vp, ignore);
2867c478bd9Sstevel@tonic-gate #ifdef EDEBUG
2877c478bd9Sstevel@tonic-gate 	etracc("exp3 p1", p1, vp);
2887c478bd9Sstevel@tonic-gate #endif
2897c478bd9Sstevel@tonic-gate 	if (i = isa(**vp, RELOP)) {
2907c478bd9Sstevel@tonic-gate 		(*vp)++;
2917c478bd9Sstevel@tonic-gate 		if (**vp && eq(**vp, S_EQ /* "=" */))
2927c478bd9Sstevel@tonic-gate 			i |= 1, (*vp)++;
2937c478bd9Sstevel@tonic-gate 		p2 = exp3(vp, ignore);
2947c478bd9Sstevel@tonic-gate #ifdef EDEBUG
2957c478bd9Sstevel@tonic-gate 		etracc("exp3 p2", p2, vp);
2967c478bd9Sstevel@tonic-gate #endif
2977c478bd9Sstevel@tonic-gate 		if (!(ignore&IGNORE)) switch (i) {
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 		case GTR:
3007c478bd9Sstevel@tonic-gate 			i = egetn(p1) > egetn(p2);
3017c478bd9Sstevel@tonic-gate 			break;
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 		case GTR|1:
3047c478bd9Sstevel@tonic-gate 			i = egetn(p1) >= egetn(p2);
3057c478bd9Sstevel@tonic-gate 			break;
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate 		case LSS:
3087c478bd9Sstevel@tonic-gate 			i = egetn(p1) < egetn(p2);
3097c478bd9Sstevel@tonic-gate 			break;
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate 		case LSS|1:
3127c478bd9Sstevel@tonic-gate 			i = egetn(p1) <= egetn(p2);
3137c478bd9Sstevel@tonic-gate 			break;
3147c478bd9Sstevel@tonic-gate 		}
3157c478bd9Sstevel@tonic-gate 		xfree(p1), xfree(p2);
3167c478bd9Sstevel@tonic-gate 		return (putn(i));
3177c478bd9Sstevel@tonic-gate 	}
3187c478bd9Sstevel@tonic-gate 	return (p1);
3197c478bd9Sstevel@tonic-gate }
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate tchar *
3226c02b4a4Smuffin exp3a(tchar ***vp, bool ignore)
3237c478bd9Sstevel@tonic-gate {
3246c02b4a4Smuffin 	tchar *p1, *p2, *op;
3256c02b4a4Smuffin 	int i;
3267c478bd9Sstevel@tonic-gate 
3277c478bd9Sstevel@tonic-gate #ifdef TRACE
3287c478bd9Sstevel@tonic-gate 	tprintf("TRACE- exp3a()\n");
3297c478bd9Sstevel@tonic-gate #endif
3307c478bd9Sstevel@tonic-gate 	p1 = exp4(vp, ignore);
3317c478bd9Sstevel@tonic-gate #ifdef EDEBUG
3327c478bd9Sstevel@tonic-gate 	etracc("exp3a p1", p1, vp);
3337c478bd9Sstevel@tonic-gate #endif
3347c478bd9Sstevel@tonic-gate 	op = **vp;
3357c478bd9Sstevel@tonic-gate 	/* if (op && any(op[0], "<>") && op[0] == op[1]) { */
3367c478bd9Sstevel@tonic-gate 	if (op && (op[0] == '<' || op[0] == '>') && op[0] == op[1]) {
3377c478bd9Sstevel@tonic-gate 		(*vp)++;
3387c478bd9Sstevel@tonic-gate 		p2 = exp3a(vp, ignore);
3397c478bd9Sstevel@tonic-gate #ifdef EDEBUG
3407c478bd9Sstevel@tonic-gate 		etracc("exp3a p2", p2, vp);
3417c478bd9Sstevel@tonic-gate #endif
3427c478bd9Sstevel@tonic-gate 		if (op[0] == '<')
3437c478bd9Sstevel@tonic-gate 			i = egetn(p1) << egetn(p2);
3447c478bd9Sstevel@tonic-gate 		else
3457c478bd9Sstevel@tonic-gate 			i = egetn(p1) >> egetn(p2);
3467c478bd9Sstevel@tonic-gate 		xfree(p1), xfree(p2);
3477c478bd9Sstevel@tonic-gate 		return (putn(i));
3487c478bd9Sstevel@tonic-gate 	}
3497c478bd9Sstevel@tonic-gate 	return (p1);
3507c478bd9Sstevel@tonic-gate }
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate tchar *
3536c02b4a4Smuffin exp4(tchar ***vp, bool ignore)
3547c478bd9Sstevel@tonic-gate {
3556c02b4a4Smuffin 	tchar *p1, *p2;
3566c02b4a4Smuffin 	int i = 0;
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate #ifdef TRACE
3597c478bd9Sstevel@tonic-gate 	tprintf("TRACE- exp4()\n");
3607c478bd9Sstevel@tonic-gate #endif
3617c478bd9Sstevel@tonic-gate 	p1 = exp5(vp, ignore);
3627c478bd9Sstevel@tonic-gate #ifdef EDEBUG
3637c478bd9Sstevel@tonic-gate 	etracc("exp4 p1", p1, vp);
3647c478bd9Sstevel@tonic-gate #endif
3657c478bd9Sstevel@tonic-gate 	if (isa(**vp, ADDOP)) {
3666c02b4a4Smuffin 		tchar *op = *(*vp)++;
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate 		p2 = exp4(vp, ignore);
3697c478bd9Sstevel@tonic-gate #ifdef EDEBUG
3707c478bd9Sstevel@tonic-gate 		etracc("exp4 p2", p2, vp);
3717c478bd9Sstevel@tonic-gate #endif
3727c478bd9Sstevel@tonic-gate 		if (!(ignore&IGNORE)) switch (op[0]) {
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate 		case '+':
3757c478bd9Sstevel@tonic-gate 			i = egetn(p1) + egetn(p2);
3767c478bd9Sstevel@tonic-gate 			break;
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate 		case '-':
3797c478bd9Sstevel@tonic-gate 			i = egetn(p1) - egetn(p2);
3807c478bd9Sstevel@tonic-gate 			break;
3817c478bd9Sstevel@tonic-gate 		}
3827c478bd9Sstevel@tonic-gate 		xfree(p1), xfree(p2);
3837c478bd9Sstevel@tonic-gate 		return (putn(i));
3847c478bd9Sstevel@tonic-gate 	}
3857c478bd9Sstevel@tonic-gate 	return (p1);
3867c478bd9Sstevel@tonic-gate }
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate tchar *
3896c02b4a4Smuffin exp5(tchar ***vp, bool ignore)
3907c478bd9Sstevel@tonic-gate {
3916c02b4a4Smuffin 	tchar *p1, *p2;
3926c02b4a4Smuffin 	int i = 0;
3937c478bd9Sstevel@tonic-gate 
3947c478bd9Sstevel@tonic-gate #ifdef TRACE
3957c478bd9Sstevel@tonic-gate 	tprintf("TRACE- exp5()\n");
3967c478bd9Sstevel@tonic-gate #endif
3977c478bd9Sstevel@tonic-gate 	p1 = exp6(vp, ignore);
3987c478bd9Sstevel@tonic-gate #ifdef EDEBUG
3997c478bd9Sstevel@tonic-gate 	etracc("exp5 p1", p1, vp);
4007c478bd9Sstevel@tonic-gate #endif
4017c478bd9Sstevel@tonic-gate 	if (isa(**vp, MULOP)) {
4026c02b4a4Smuffin 		tchar *op = *(*vp)++;
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate 		p2 = exp5(vp, ignore);
4057c478bd9Sstevel@tonic-gate #ifdef EDEBUG
4067c478bd9Sstevel@tonic-gate 		etracc("exp5 p2", p2, vp);
4077c478bd9Sstevel@tonic-gate #endif
4087c478bd9Sstevel@tonic-gate 		if (!(ignore&IGNORE)) switch (op[0]) {
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate 		case '*':
4117c478bd9Sstevel@tonic-gate 			i = egetn(p1) * egetn(p2);
4127c478bd9Sstevel@tonic-gate 			break;
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate 		case '/':
4157c478bd9Sstevel@tonic-gate 			i = egetn(p2);
4167c478bd9Sstevel@tonic-gate 			if (i == 0)
4177c478bd9Sstevel@tonic-gate 				error("Divide by 0");
4187c478bd9Sstevel@tonic-gate 			i = egetn(p1) / i;
4197c478bd9Sstevel@tonic-gate 			break;
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate 		case '%':
4227c478bd9Sstevel@tonic-gate 			i = egetn(p2);
4237c478bd9Sstevel@tonic-gate 			if (i == 0)
4247c478bd9Sstevel@tonic-gate 				error("Mod by 0");
4257c478bd9Sstevel@tonic-gate 			i = egetn(p1) % i;
4267c478bd9Sstevel@tonic-gate 			break;
4277c478bd9Sstevel@tonic-gate 		}
4287c478bd9Sstevel@tonic-gate 		xfree(p1), xfree(p2);
4297c478bd9Sstevel@tonic-gate 		return (putn(i));
4307c478bd9Sstevel@tonic-gate 	}
4317c478bd9Sstevel@tonic-gate 	return (p1);
4327c478bd9Sstevel@tonic-gate }
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate tchar *
4356c02b4a4Smuffin exp6(tchar ***vp, bool ignore)
4367c478bd9Sstevel@tonic-gate {
4377c478bd9Sstevel@tonic-gate 	int ccode, i;
4386c02b4a4Smuffin 	tchar *cp, *dp, *ep;
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate #ifdef TRACE
4417c478bd9Sstevel@tonic-gate 	tprintf("TRACE- exp6()\n");
4427c478bd9Sstevel@tonic-gate #endif
4437c478bd9Sstevel@tonic-gate 	if (**vp == 0)
4447c478bd9Sstevel@tonic-gate 		bferr("Expression syntax");
4457c478bd9Sstevel@tonic-gate 	if (eq(**vp, S_EXAS /* "!" */)) {
4467c478bd9Sstevel@tonic-gate 		(*vp)++;
4477c478bd9Sstevel@tonic-gate 		cp = exp6(vp, ignore);
4487c478bd9Sstevel@tonic-gate #ifdef EDEBUG
4497c478bd9Sstevel@tonic-gate 		etracc("exp6 ! cp", cp, vp);
4507c478bd9Sstevel@tonic-gate #endif
4517c478bd9Sstevel@tonic-gate 		i = egetn(cp);
4527c478bd9Sstevel@tonic-gate 		xfree(cp);
4537c478bd9Sstevel@tonic-gate 		return (putn(!i));
4547c478bd9Sstevel@tonic-gate 	}
4557c478bd9Sstevel@tonic-gate 	if (eq(**vp, S_TIL /* "~" */)) {
4567c478bd9Sstevel@tonic-gate 		(*vp)++;
4577c478bd9Sstevel@tonic-gate 		cp = exp6(vp, ignore);
4587c478bd9Sstevel@tonic-gate #ifdef EDEBUG
4597c478bd9Sstevel@tonic-gate 		etracc("exp6 ~ cp", cp, vp);
4607c478bd9Sstevel@tonic-gate #endif
4617c478bd9Sstevel@tonic-gate 		i = egetn(cp);
4627c478bd9Sstevel@tonic-gate 		xfree(cp);
4637c478bd9Sstevel@tonic-gate 		return (putn(~i));
4647c478bd9Sstevel@tonic-gate 	}
4657c478bd9Sstevel@tonic-gate 	if (eq(**vp, S_LPAR /* "(" */)) {
4667c478bd9Sstevel@tonic-gate 		(*vp)++;
4677c478bd9Sstevel@tonic-gate 		ccode = exp0(vp, ignore);
4687c478bd9Sstevel@tonic-gate #ifdef EDEBUG
4697c478bd9Sstevel@tonic-gate 		etraci("exp6 () ccode", ccode, vp);
4707c478bd9Sstevel@tonic-gate #endif
4717c478bd9Sstevel@tonic-gate 		if (*vp == 0 || **vp == 0 || ***vp != ')')
4727c478bd9Sstevel@tonic-gate 			bferr("Expression syntax");
4737c478bd9Sstevel@tonic-gate 		(*vp)++;
4747c478bd9Sstevel@tonic-gate 		return (putn(ccode));
4757c478bd9Sstevel@tonic-gate 	}
4767c478bd9Sstevel@tonic-gate 	if (eq(**vp, S_LBRA /* "{" */)) {
4776c02b4a4Smuffin 		tchar **v;
4787c478bd9Sstevel@tonic-gate 		struct command faket;
4797c478bd9Sstevel@tonic-gate 		tchar *fakecom[2];
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 		faket.t_dtyp = TCOM;
4827c478bd9Sstevel@tonic-gate 		faket.t_dflg = 0;
4837c478bd9Sstevel@tonic-gate 		faket.t_dcar = faket.t_dcdr = faket.t_dspr = (struct command *)0;
4847c478bd9Sstevel@tonic-gate 		faket.t_dcom = fakecom;
4857c478bd9Sstevel@tonic-gate 		fakecom[0] = S_BRAPPPBRA /* "{ ... }" */;
4867c478bd9Sstevel@tonic-gate 		fakecom[1] = NOSTR;
4877c478bd9Sstevel@tonic-gate 		(*vp)++;
4887c478bd9Sstevel@tonic-gate 		v = *vp;
4897c478bd9Sstevel@tonic-gate 		for (;;) {
4907c478bd9Sstevel@tonic-gate 			if (!**vp)
4917c478bd9Sstevel@tonic-gate 				bferr("Missing }");
4927c478bd9Sstevel@tonic-gate 			if (eq(*(*vp)++, S_RBRA /* "}" */))
4937c478bd9Sstevel@tonic-gate 				break;
4947c478bd9Sstevel@tonic-gate 		}
4957c478bd9Sstevel@tonic-gate 		if (ignore&IGNORE)
4967c478bd9Sstevel@tonic-gate 			return (S_ /* "" */);
4977c478bd9Sstevel@tonic-gate 		psavejob();
4987c478bd9Sstevel@tonic-gate 		if (pfork(&faket, -1) == 0) {
4997c478bd9Sstevel@tonic-gate 			*--(*vp) = 0;
5007c478bd9Sstevel@tonic-gate 			evalav(v);
5017c478bd9Sstevel@tonic-gate 			exitstat();
5027c478bd9Sstevel@tonic-gate 		}
5037c478bd9Sstevel@tonic-gate 		pwait();
5047c478bd9Sstevel@tonic-gate 		prestjob();
5057c478bd9Sstevel@tonic-gate #ifdef EDEBUG
5067c478bd9Sstevel@tonic-gate 		etraci("exp6 {} status", egetn(value("status")), vp);
5077c478bd9Sstevel@tonic-gate #endif
5087c478bd9Sstevel@tonic-gate 		return (putn(egetn(value(S_status /* "status" */)) == 0));
5097c478bd9Sstevel@tonic-gate 	}
5107c478bd9Sstevel@tonic-gate 	if (isa(**vp, ANYOP))
5117c478bd9Sstevel@tonic-gate 		return (S_ /* "" */);
5127c478bd9Sstevel@tonic-gate 	cp = *(*vp)++;
5137c478bd9Sstevel@tonic-gate 	if (*cp == '-' && any(cp[1], S_erwxfdzo /* "erwxfdzo" */)) {
5147c478bd9Sstevel@tonic-gate 		struct stat stb;
5157c478bd9Sstevel@tonic-gate 
5167c478bd9Sstevel@tonic-gate 		if (cp[2] != '\0')
5177c478bd9Sstevel@tonic-gate 			bferr("Malformed file inquiry");
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate 		/*
5207c478bd9Sstevel@tonic-gate 		 * Detect missing file names by checking for operator
5217c478bd9Sstevel@tonic-gate 		 * in the file name position.  However, if an operator
5227c478bd9Sstevel@tonic-gate 		 * name appears there, we must make sure that there's
5237c478bd9Sstevel@tonic-gate 		 * no file by that name (e.g., "/") before announcing
5247c478bd9Sstevel@tonic-gate 		 * an error.  Even this check isn't quite right, since
5257c478bd9Sstevel@tonic-gate 		 * it doesn't take globbing into account.
5267c478bd9Sstevel@tonic-gate 		 */
527*fd5e9823Sblu 		if ((**vp == NULL) || isa(**vp, ANYOP) && stat_(**vp, &stb))
5287c478bd9Sstevel@tonic-gate 			bferr("Missing file name");
5297c478bd9Sstevel@tonic-gate 		dp = *(*vp)++;
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate 		if (ignore&IGNORE)
5327c478bd9Sstevel@tonic-gate 			return (S_ /* "" */);
5337c478bd9Sstevel@tonic-gate 		ep = globone(dp);
5347c478bd9Sstevel@tonic-gate 		switch (cp[1]) {
5357c478bd9Sstevel@tonic-gate 
5367c478bd9Sstevel@tonic-gate 		case 'r':
5377c478bd9Sstevel@tonic-gate 			i = !chk_access(ep, S_IREAD);
5387c478bd9Sstevel@tonic-gate 			break;
5397c478bd9Sstevel@tonic-gate 
5407c478bd9Sstevel@tonic-gate 		case 'w':
5417c478bd9Sstevel@tonic-gate 			i = !chk_access(ep, S_IWRITE);
5427c478bd9Sstevel@tonic-gate 			break;
5437c478bd9Sstevel@tonic-gate 
5447c478bd9Sstevel@tonic-gate 		case 'x':
5457c478bd9Sstevel@tonic-gate 			i = !chk_access(ep, S_IEXEC);
5467c478bd9Sstevel@tonic-gate 			break;
5477c478bd9Sstevel@tonic-gate 
5487c478bd9Sstevel@tonic-gate 		default:
5497c478bd9Sstevel@tonic-gate 			if (stat_(ep, &stb)) {
5507c478bd9Sstevel@tonic-gate 				xfree(ep);
5517c478bd9Sstevel@tonic-gate 				return (S_0 /* "0" */);
5527c478bd9Sstevel@tonic-gate 			}
5537c478bd9Sstevel@tonic-gate 			switch (cp[1]) {
5547c478bd9Sstevel@tonic-gate 
5557c478bd9Sstevel@tonic-gate 			case 'f':
5567c478bd9Sstevel@tonic-gate 				i = (stb.st_mode & S_IFMT) == S_IFREG;
5577c478bd9Sstevel@tonic-gate 				break;
5587c478bd9Sstevel@tonic-gate 
5597c478bd9Sstevel@tonic-gate 			case 'd':
5607c478bd9Sstevel@tonic-gate 				i = (stb.st_mode & S_IFMT) == S_IFDIR;
5617c478bd9Sstevel@tonic-gate 				break;
5627c478bd9Sstevel@tonic-gate 
5637c478bd9Sstevel@tonic-gate 			case 'z':
5647c478bd9Sstevel@tonic-gate 				i = stb.st_size == 0;
5657c478bd9Sstevel@tonic-gate 				break;
5667c478bd9Sstevel@tonic-gate 
5677c478bd9Sstevel@tonic-gate 			case 'e':
5687c478bd9Sstevel@tonic-gate 				i = 1;
5697c478bd9Sstevel@tonic-gate 				break;
5707c478bd9Sstevel@tonic-gate 
5717c478bd9Sstevel@tonic-gate 			case 'o':
5727c478bd9Sstevel@tonic-gate 				i = stb.st_uid == uid;
5737c478bd9Sstevel@tonic-gate 				break;
5747c478bd9Sstevel@tonic-gate 			}
5757c478bd9Sstevel@tonic-gate 		}
5767c478bd9Sstevel@tonic-gate #ifdef EDEBUG
5777c478bd9Sstevel@tonic-gate 		etraci("exp6 -? i", i, vp);
5787c478bd9Sstevel@tonic-gate #endif
5797c478bd9Sstevel@tonic-gate 		xfree(ep);
5807c478bd9Sstevel@tonic-gate 		return (putn(i));
5817c478bd9Sstevel@tonic-gate 	}
5827c478bd9Sstevel@tonic-gate #ifdef EDEBUG
5837c478bd9Sstevel@tonic-gate 	etracc("exp6 default", cp, vp);
5847c478bd9Sstevel@tonic-gate #endif
5857c478bd9Sstevel@tonic-gate 	return (ignore&NOGLOB ? savestr(cp) : globone(cp));
5867c478bd9Sstevel@tonic-gate }
5877c478bd9Sstevel@tonic-gate 
5886c02b4a4Smuffin void
5896c02b4a4Smuffin evalav(tchar **v)
5907c478bd9Sstevel@tonic-gate {
5917c478bd9Sstevel@tonic-gate 	struct wordent paraml;
5926c02b4a4Smuffin 	struct wordent *hp = &paraml;
5937c478bd9Sstevel@tonic-gate 	struct command *t;
5946c02b4a4Smuffin 	struct wordent *wdp = hp;
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate #ifdef TRACE
5977c478bd9Sstevel@tonic-gate 	tprintf("TRACE- evalav()\n");
5987c478bd9Sstevel@tonic-gate #endif
5997c478bd9Sstevel@tonic-gate 	set(S_status /* "status" */, S_0 /* "0" */);
6007c478bd9Sstevel@tonic-gate 	hp->prev = hp->next = hp;
6017c478bd9Sstevel@tonic-gate 	hp->word = S_ /* "" */;
6027c478bd9Sstevel@tonic-gate 	while (*v) {
60365b0c20eSnakanon 		struct wordent *new = (struct wordent *)xcalloc(1, sizeof *wdp);
6047c478bd9Sstevel@tonic-gate 
6057c478bd9Sstevel@tonic-gate 		new->prev = wdp;
6067c478bd9Sstevel@tonic-gate 		new->next = hp;
6077c478bd9Sstevel@tonic-gate 		wdp->next = new;
6087c478bd9Sstevel@tonic-gate 		wdp = new;
6097c478bd9Sstevel@tonic-gate 		wdp->word = savestr(*v++);
6107c478bd9Sstevel@tonic-gate 	}
6117c478bd9Sstevel@tonic-gate 	hp->prev = wdp;
6127c478bd9Sstevel@tonic-gate 	alias(&paraml);
6137c478bd9Sstevel@tonic-gate 	t = syntax(paraml.next, &paraml, 0);
6147c478bd9Sstevel@tonic-gate 	if (err)
6157c478bd9Sstevel@tonic-gate 		error("%s", gettext(err));
6167c478bd9Sstevel@tonic-gate 	execute(t, -1);
6177c478bd9Sstevel@tonic-gate 	freelex(&paraml), freesyn(t);
6187c478bd9Sstevel@tonic-gate }
6197c478bd9Sstevel@tonic-gate 
6206c02b4a4Smuffin int
6216c02b4a4Smuffin isa(tchar *cp, int what)
6227c478bd9Sstevel@tonic-gate {
6237c478bd9Sstevel@tonic-gate 
6247c478bd9Sstevel@tonic-gate #ifdef TRACE
6257c478bd9Sstevel@tonic-gate 	tprintf("TRACE- isa()\n");
6267c478bd9Sstevel@tonic-gate #endif
6277c478bd9Sstevel@tonic-gate 	if (cp == 0)
6287c478bd9Sstevel@tonic-gate 		return ((what & RESTOP) != 0);
6297c478bd9Sstevel@tonic-gate 	if (cp[1] == 0) {
6307c478bd9Sstevel@tonic-gate 		if (what & ADDOP && (*cp == '+' || *cp == '-'))
6317c478bd9Sstevel@tonic-gate 			return (1);
6327c478bd9Sstevel@tonic-gate 		if (what & MULOP && (*cp == '*' || *cp == '/' || *cp == '%'))
6337c478bd9Sstevel@tonic-gate 			return (1);
6347c478bd9Sstevel@tonic-gate 		if (what & RESTOP && (*cp == '(' || *cp == ')' || *cp == '!' ||
6357c478bd9Sstevel@tonic-gate 					*cp == '~' || *cp == '^' || *cp == '"'))
6367c478bd9Sstevel@tonic-gate 			return (1);
6377c478bd9Sstevel@tonic-gate 	} else if (cp[2] == 0) {
6387c478bd9Sstevel@tonic-gate 		if (what & RESTOP) {
6397c478bd9Sstevel@tonic-gate 			if (cp[0] == '|' && cp[1] == '&')
6407c478bd9Sstevel@tonic-gate 				return (1);
6417c478bd9Sstevel@tonic-gate 			if (cp[0] == '<' && cp[1] == '<')
6427c478bd9Sstevel@tonic-gate 				return (1);
6437c478bd9Sstevel@tonic-gate 			if (cp[0] == '>' && cp[1] == '>')
6447c478bd9Sstevel@tonic-gate 				return (1);
6457c478bd9Sstevel@tonic-gate 		}
6467c478bd9Sstevel@tonic-gate 		if (what & EQOP) {
6477c478bd9Sstevel@tonic-gate 			if (cp[0] == '=') {
6487c478bd9Sstevel@tonic-gate 				if (cp[1] == '=')
6497c478bd9Sstevel@tonic-gate 					return (EQEQ);
6507c478bd9Sstevel@tonic-gate 				if (cp[1] == '~')
6517c478bd9Sstevel@tonic-gate 					return (EQMATCH);
6527c478bd9Sstevel@tonic-gate 			} else if (cp[0] == '!') {
6537c478bd9Sstevel@tonic-gate 				if (cp[1] == '=')
6547c478bd9Sstevel@tonic-gate 					return (NOTEQ);
6557c478bd9Sstevel@tonic-gate 				if (cp[1] == '~')
6567c478bd9Sstevel@tonic-gate 					return (NOTEQMATCH);
6577c478bd9Sstevel@tonic-gate 			}
6587c478bd9Sstevel@tonic-gate 		}
6597c478bd9Sstevel@tonic-gate 	}
6607c478bd9Sstevel@tonic-gate 	if (what & RELOP) {
6617c478bd9Sstevel@tonic-gate 		if (*cp == '<')
6627c478bd9Sstevel@tonic-gate 			return (LSS);
6637c478bd9Sstevel@tonic-gate 		if (*cp == '>')
6647c478bd9Sstevel@tonic-gate 			return (GTR);
6657c478bd9Sstevel@tonic-gate 	}
6667c478bd9Sstevel@tonic-gate 	return (0);
6677c478bd9Sstevel@tonic-gate }
6687c478bd9Sstevel@tonic-gate 
6696c02b4a4Smuffin int
6706c02b4a4Smuffin egetn(tchar *cp)
6717c478bd9Sstevel@tonic-gate {
6727c478bd9Sstevel@tonic-gate 
6737c478bd9Sstevel@tonic-gate #ifdef TRACE
6747c478bd9Sstevel@tonic-gate 	tprintf("TRACE- egetn()\n");
6757c478bd9Sstevel@tonic-gate #endif
6767c478bd9Sstevel@tonic-gate 	if (*cp && *cp != '-' && !digit(*cp))
6777c478bd9Sstevel@tonic-gate 		bferr("Expression syntax");
6787c478bd9Sstevel@tonic-gate 	return (getn(cp));
6797c478bd9Sstevel@tonic-gate }
6807c478bd9Sstevel@tonic-gate 
6817c478bd9Sstevel@tonic-gate /* Phew! */
6827c478bd9Sstevel@tonic-gate 
6837c478bd9Sstevel@tonic-gate #ifdef EDEBUG
6846c02b4a4Smuffin void
6856c02b4a4Smuffin etraci(tchar *str, int i, tchar ***vp)
6867c478bd9Sstevel@tonic-gate {
6877c478bd9Sstevel@tonic-gate 
6887c478bd9Sstevel@tonic-gate 	printf("%s=%d\t", str, i);
6897c478bd9Sstevel@tonic-gate 	blkpr(*vp);
6907c478bd9Sstevel@tonic-gate 	printf("\n");
6917c478bd9Sstevel@tonic-gate }
6927c478bd9Sstevel@tonic-gate 
6936c02b4a4Smuffin void
6946c02b4a4Smuffin etracc(tchar *str, tchar *cp, tchar ***vp)
6957c478bd9Sstevel@tonic-gate {
6967c478bd9Sstevel@tonic-gate 
6977c478bd9Sstevel@tonic-gate 	printf("%s=%s\t", str, cp);
6987c478bd9Sstevel@tonic-gate 	blkpr(*vp);
6997c478bd9Sstevel@tonic-gate 	printf("\n");
7007c478bd9Sstevel@tonic-gate }
7017c478bd9Sstevel@tonic-gate #endif
702