xref: /onnv-gate/usr/src/cmd/tip/value.c (revision 549:9e644232f978)
10Sstevel@tonic-gate /*
2*549Smuffin  * Copyright 2000 Sun Microsystems, Inc.  All rights reserved.
3*549Smuffin  * Use is subject to license terms.
40Sstevel@tonic-gate  */
50Sstevel@tonic-gate 
60Sstevel@tonic-gate /*
70Sstevel@tonic-gate  * Copyright (c) 1983 Regents of the University of California.
80Sstevel@tonic-gate  * All rights reserved. The Berkeley software License Agreement
90Sstevel@tonic-gate  * specifies the terms and conditions for redistribution.
100Sstevel@tonic-gate  */
11*549Smuffin 
120Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
130Sstevel@tonic-gate 
140Sstevel@tonic-gate #include "tip.h"
150Sstevel@tonic-gate 
160Sstevel@tonic-gate #define	MIDDLE	35
170Sstevel@tonic-gate 
18*549Smuffin static value_t *vlookup(char *);
190Sstevel@tonic-gate static int col = 0;
200Sstevel@tonic-gate 
21*549Smuffin extern char	*interp(char *);
22*549Smuffin 
23*549Smuffin static void	vtoken(char *);
24*549Smuffin static void	vprint(value_t *);
25*549Smuffin static int	vaccess(unsigned, unsigned);
26*549Smuffin 
270Sstevel@tonic-gate /*
280Sstevel@tonic-gate  * Variable manipulation
290Sstevel@tonic-gate  */
30*549Smuffin void
vinit(void)31*549Smuffin vinit(void)
320Sstevel@tonic-gate {
33*549Smuffin 	value_t *p;
34*549Smuffin 	char *cp;
350Sstevel@tonic-gate 	FILE *f;
360Sstevel@tonic-gate 	char file[1024];
370Sstevel@tonic-gate 
380Sstevel@tonic-gate 	for (p = vtable; p->v_name != NULL; p++) {
390Sstevel@tonic-gate 		if (p->v_type&ENVIRON)
400Sstevel@tonic-gate 			if (cp = getenv(p->v_name))
410Sstevel@tonic-gate 				p->v_value = cp;
420Sstevel@tonic-gate 		if (p->v_type&IREMOTE)
430Sstevel@tonic-gate 			number(p->v_value) = *address(p->v_value);
440Sstevel@tonic-gate 	}
450Sstevel@tonic-gate 	/*
460Sstevel@tonic-gate 	 * Read the .tiprc file in the HOME directory
470Sstevel@tonic-gate 	 *  for sets
480Sstevel@tonic-gate 	 */
490Sstevel@tonic-gate 	if ((cp = value(HOME)) == NULL)
500Sstevel@tonic-gate 		cp = "";
51*549Smuffin 	(void) strlcpy(file, cp, sizeof (file));
52*549Smuffin 	(void) strlcat(file, "/.tiprc", sizeof (file));
530Sstevel@tonic-gate 	if ((f = fopen(file, "r")) != NULL) {
54*549Smuffin 		char *tp;
550Sstevel@tonic-gate 
560Sstevel@tonic-gate 		while (fgets(file, sizeof (file)-1, f) != NULL) {
570Sstevel@tonic-gate 			if (file[0] == '#')
580Sstevel@tonic-gate 				continue;
590Sstevel@tonic-gate 			if (vflag)
60*549Smuffin 				(void) printf("set %s", file);
610Sstevel@tonic-gate 			if (tp = strrchr(file, '\n'))
620Sstevel@tonic-gate 				*tp = '\0';
630Sstevel@tonic-gate 			vlex(file);
640Sstevel@tonic-gate 		}
65*549Smuffin 		(void) fclose(f);
660Sstevel@tonic-gate 	}
670Sstevel@tonic-gate 	/*
680Sstevel@tonic-gate 	 * To allow definition of exception prior to fork
690Sstevel@tonic-gate 	 */
700Sstevel@tonic-gate 	vtable[EXCEPTIONS].v_access &= ~(WRITE<<PUBLIC);
710Sstevel@tonic-gate }
720Sstevel@tonic-gate 
730Sstevel@tonic-gate /*VARARGS1*/
74*549Smuffin void
vassign(value_t * p,char * v)75*549Smuffin vassign(value_t *p, char *v)
760Sstevel@tonic-gate {
770Sstevel@tonic-gate 
780Sstevel@tonic-gate 	if (!vaccess(p->v_access, WRITE)) {
79*549Smuffin 		(void) printf("access denied\r\n");
800Sstevel@tonic-gate 		return;
810Sstevel@tonic-gate 	}
820Sstevel@tonic-gate 	switch (p->v_type&TMASK) {
830Sstevel@tonic-gate 
840Sstevel@tonic-gate 	case STRING:
850Sstevel@tonic-gate 		if (p->v_value != (char *)NULL) {
860Sstevel@tonic-gate 			if (equal(p->v_value, v))
870Sstevel@tonic-gate 				return;
880Sstevel@tonic-gate 			if (!(p->v_type&(ENVIRON|INIT)))
890Sstevel@tonic-gate 				free(p->v_value);
900Sstevel@tonic-gate 		}
910Sstevel@tonic-gate 		if ((p->v_value = malloc(strlen(v)+1)) == NOSTR) {
92*549Smuffin 			(void) printf("out of core\r\n");
930Sstevel@tonic-gate 			return;
940Sstevel@tonic-gate 		}
950Sstevel@tonic-gate 		p->v_type &= ~(ENVIRON|INIT);
96*549Smuffin 		(void) strcpy(p->v_value, v);
970Sstevel@tonic-gate 		break;
980Sstevel@tonic-gate 
990Sstevel@tonic-gate 	case NUMBER:
1000Sstevel@tonic-gate 		if (number(p->v_value) == number(v))
1010Sstevel@tonic-gate 			return;
1020Sstevel@tonic-gate 		number(p->v_value) = number(v);
1030Sstevel@tonic-gate 		break;
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate 	case BOOL:
1060Sstevel@tonic-gate 		if (boolean(p->v_value) == (*v != '!'))
1070Sstevel@tonic-gate 			return;
1080Sstevel@tonic-gate 		boolean(p->v_value) = (*v != '!');
1090Sstevel@tonic-gate 		break;
1100Sstevel@tonic-gate 
1110Sstevel@tonic-gate 	case CHAR:
1120Sstevel@tonic-gate 		if (character(p->v_value) == *v)
1130Sstevel@tonic-gate 			return;
1140Sstevel@tonic-gate 		character(p->v_value) = *v;
1150Sstevel@tonic-gate 	}
1160Sstevel@tonic-gate 	p->v_access |= CHANGED;
1170Sstevel@tonic-gate }
1180Sstevel@tonic-gate 
119*549Smuffin void
vlex(char * s)120*549Smuffin vlex(char *s)
1210Sstevel@tonic-gate {
122*549Smuffin 	value_t *p;
1230Sstevel@tonic-gate 
1240Sstevel@tonic-gate 	if (equal(s, "all")) {
1250Sstevel@tonic-gate 		for (p = vtable; p->v_name; p++)
1260Sstevel@tonic-gate 			if (vaccess(p->v_access, READ))
1270Sstevel@tonic-gate 				vprint(p);
1280Sstevel@tonic-gate 	} else {
129*549Smuffin 		char *cp;
1300Sstevel@tonic-gate 
1310Sstevel@tonic-gate 		do {
1320Sstevel@tonic-gate 			if (cp = vinterp(s, ' '))
1330Sstevel@tonic-gate 				cp++;
1340Sstevel@tonic-gate 			vtoken(s);
1350Sstevel@tonic-gate 			s = cp;
1360Sstevel@tonic-gate 		} while (s);
1370Sstevel@tonic-gate 	}
1380Sstevel@tonic-gate 	if (col > 0) {
139*549Smuffin 		(void) printf("\r\n");
1400Sstevel@tonic-gate 		col = 0;
1410Sstevel@tonic-gate 	}
1420Sstevel@tonic-gate }
1430Sstevel@tonic-gate 
144*549Smuffin static void
vtoken(char * s)145*549Smuffin vtoken(char *s)
1460Sstevel@tonic-gate {
147*549Smuffin 	value_t *p;
148*549Smuffin 	char *cp, *cp2;
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate 	if (cp = strchr(s, '=')) {
1510Sstevel@tonic-gate 		*cp = '\0';
1520Sstevel@tonic-gate 		if (p = vlookup(s)) {
1530Sstevel@tonic-gate 			cp++;
1540Sstevel@tonic-gate 			if (p->v_type&NUMBER)
155*549Smuffin 				vassign(p, (char *)atoi(cp));
1560Sstevel@tonic-gate 			else {
1570Sstevel@tonic-gate 				if (strcmp(s, "record") == 0)
1580Sstevel@tonic-gate 					if ((cp2 = expand(cp)) != NOSTR)
1590Sstevel@tonic-gate 						cp = cp2;
1600Sstevel@tonic-gate 				vassign(p, cp);
1610Sstevel@tonic-gate 			}
1620Sstevel@tonic-gate 			return;
1630Sstevel@tonic-gate 		}
1640Sstevel@tonic-gate 	} else if (cp = strchr(s, '?')) {
1650Sstevel@tonic-gate 		*cp = '\0';
166*549Smuffin 		if ((p = vlookup(s)) != NULL && vaccess(p->v_access, READ)) {
1670Sstevel@tonic-gate 			vprint(p);
1680Sstevel@tonic-gate 			return;
1690Sstevel@tonic-gate 		}
1700Sstevel@tonic-gate 	} else {
1710Sstevel@tonic-gate 		if (*s != '!')
1720Sstevel@tonic-gate 			p = vlookup(s);
1730Sstevel@tonic-gate 		else
1740Sstevel@tonic-gate 			p = vlookup(s+1);
1750Sstevel@tonic-gate 		if (p != NOVAL) {
1760Sstevel@tonic-gate 			if (p->v_type&BOOL)
1770Sstevel@tonic-gate 				vassign(p, s);
1780Sstevel@tonic-gate 			else
179*549Smuffin 				(void) printf("%s: no value specified\r\n", s);
1800Sstevel@tonic-gate 			return;
1810Sstevel@tonic-gate 		}
1820Sstevel@tonic-gate 	}
183*549Smuffin 	(void) printf("%s: unknown variable\r\n", s);
1840Sstevel@tonic-gate }
1850Sstevel@tonic-gate 
186*549Smuffin static void
vprint(value_t * p)187*549Smuffin vprint(value_t *p)
1880Sstevel@tonic-gate {
189*549Smuffin 	char *cp;
1900Sstevel@tonic-gate 
1910Sstevel@tonic-gate 	if (col > 0 && col < MIDDLE)
1920Sstevel@tonic-gate 		while (col++ < MIDDLE)
193*549Smuffin 			(void) putchar(' ');
1940Sstevel@tonic-gate 	col += strlen(p->v_name);
1950Sstevel@tonic-gate 	switch (p->v_type&TMASK) {
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate 	case BOOL:
1980Sstevel@tonic-gate 		if (boolean(p->v_value) == FALSE) {
1990Sstevel@tonic-gate 			col++;
200*549Smuffin 			(void) putchar('!');
2010Sstevel@tonic-gate 		}
202*549Smuffin 		(void) printf("%s", p->v_name);
2030Sstevel@tonic-gate 		break;
2040Sstevel@tonic-gate 
2050Sstevel@tonic-gate 	case STRING:
206*549Smuffin 		(void) printf("%s=", p->v_name);
2070Sstevel@tonic-gate 		col++;
2080Sstevel@tonic-gate 		if (p->v_value) {
209*549Smuffin 			cp = interp(p->v_value);
2100Sstevel@tonic-gate 			col += strlen(cp);
211*549Smuffin 			(void) printf("%s", cp);
2120Sstevel@tonic-gate 		}
2130Sstevel@tonic-gate 		break;
2140Sstevel@tonic-gate 
2150Sstevel@tonic-gate 	case NUMBER:
2160Sstevel@tonic-gate 		col += 6;
217*549Smuffin 		(void) printf("%s=%-5d", p->v_name, number(p->v_value));
2180Sstevel@tonic-gate 		break;
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate 	case CHAR:
221*549Smuffin 		(void) printf("%s=", p->v_name);
2220Sstevel@tonic-gate 		col++;
2230Sstevel@tonic-gate 		if (p->v_value) {
2240Sstevel@tonic-gate 			cp = ctrl(character(p->v_value));
2250Sstevel@tonic-gate 			col += strlen(cp);
226*549Smuffin 			(void) printf("%s", cp);
2270Sstevel@tonic-gate 		}
2280Sstevel@tonic-gate 		break;
2290Sstevel@tonic-gate 	}
2300Sstevel@tonic-gate 	if (col >= MIDDLE) {
2310Sstevel@tonic-gate 		col = 0;
232*549Smuffin 		(void) printf("\r\n");
2330Sstevel@tonic-gate 		return;
2340Sstevel@tonic-gate 	}
2350Sstevel@tonic-gate }
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate 
2380Sstevel@tonic-gate static int
vaccess(unsigned mode,unsigned rw)239*549Smuffin vaccess(unsigned mode, unsigned rw)
2400Sstevel@tonic-gate {
2410Sstevel@tonic-gate 	if (mode & (rw<<PUBLIC))
2420Sstevel@tonic-gate 		return (1);
2430Sstevel@tonic-gate 	if (mode & (rw<<PRIVATE))
2440Sstevel@tonic-gate 		return (1);
2450Sstevel@tonic-gate 	return ((mode & (rw<<ROOT)) && uid == 0);
2460Sstevel@tonic-gate }
2470Sstevel@tonic-gate 
2480Sstevel@tonic-gate static value_t *
vlookup(char * s)249*549Smuffin vlookup(char *s)
2500Sstevel@tonic-gate {
251*549Smuffin 	value_t *p;
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate 	for (p = vtable; p->v_name; p++)
2540Sstevel@tonic-gate 		if (equal(p->v_name, s) || (p->v_abrev && equal(p->v_abrev, s)))
2550Sstevel@tonic-gate 			return (p);
2560Sstevel@tonic-gate 	return (NULL);
2570Sstevel@tonic-gate }
2580Sstevel@tonic-gate 
2590Sstevel@tonic-gate char *
vinterp(char * s,char stop)260*549Smuffin vinterp(char *s, char stop)
2610Sstevel@tonic-gate {
262*549Smuffin 	char *p = s, c;
2630Sstevel@tonic-gate 	int num;
2640Sstevel@tonic-gate 
265*549Smuffin 	while ((c = *s++) != 0 && c != stop)
2660Sstevel@tonic-gate 		switch (c) {
2670Sstevel@tonic-gate 
2680Sstevel@tonic-gate 		case '^':
2690Sstevel@tonic-gate 			if (*s)
2700Sstevel@tonic-gate 				*p++ = *s++ - 0100;
2710Sstevel@tonic-gate 			else
2720Sstevel@tonic-gate 				*p++ = c;
2730Sstevel@tonic-gate 			break;
2740Sstevel@tonic-gate 
2750Sstevel@tonic-gate 		case '\\':
2760Sstevel@tonic-gate 			num = 0;
2770Sstevel@tonic-gate 			c = *s++;
2780Sstevel@tonic-gate 			if (c >= '0' && c <= '7')
2790Sstevel@tonic-gate 				num = (num<<3)+(c-'0');
2800Sstevel@tonic-gate 			else {
281*549Smuffin 				char *q = "n\nr\rt\tb\bf\f";
2820Sstevel@tonic-gate 
2830Sstevel@tonic-gate 				for (; *q; q++)
2840Sstevel@tonic-gate 					if (c == *q++) {
2850Sstevel@tonic-gate 						*p++ = *q;
2860Sstevel@tonic-gate 						goto cont;
2870Sstevel@tonic-gate 					}
2880Sstevel@tonic-gate 				*p++ = c;
2890Sstevel@tonic-gate 			cont:
2900Sstevel@tonic-gate 				break;
2910Sstevel@tonic-gate 			}
2920Sstevel@tonic-gate 			if ((c = *s++) >= '0' && c <= '7') {
2930Sstevel@tonic-gate 				num = (num<<3)+(c-'0');
2940Sstevel@tonic-gate 				if ((c = *s++) >= '0' && c <= '7')
2950Sstevel@tonic-gate 					num = (num<<3)+(c-'0');
2960Sstevel@tonic-gate 				else
2970Sstevel@tonic-gate 					s--;
2980Sstevel@tonic-gate 			} else
2990Sstevel@tonic-gate 				s--;
3000Sstevel@tonic-gate 			*p++ = num;
3010Sstevel@tonic-gate 			break;
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate 		default:
3040Sstevel@tonic-gate 			*p++ = c;
3050Sstevel@tonic-gate 		}
3060Sstevel@tonic-gate 	*p = '\0';
3070Sstevel@tonic-gate 	return (c == stop ? s-1 : NULL);
3080Sstevel@tonic-gate }
3090Sstevel@tonic-gate 
3100Sstevel@tonic-gate /*
3110Sstevel@tonic-gate  * assign variable s with value v (for NUMBER or STRING or CHAR types)
3120Sstevel@tonic-gate  */
313*549Smuffin int
vstring(char * s,char * v)314*549Smuffin vstring(char *s, char *v)
3150Sstevel@tonic-gate {
316*549Smuffin 	value_t *p;
3170Sstevel@tonic-gate 	char *v2;
3180Sstevel@tonic-gate 
3190Sstevel@tonic-gate 	p = vlookup(s);
3200Sstevel@tonic-gate 	if (p == 0)
3210Sstevel@tonic-gate 		return (1);
3220Sstevel@tonic-gate 	if (p->v_type&NUMBER)
323*549Smuffin 		vassign(p, (char *)atoi(v));
3240Sstevel@tonic-gate 	else {
3250Sstevel@tonic-gate 		if (strcmp(s, "record") == 0)
3260Sstevel@tonic-gate 			if ((v2 = expand(v)) != NOSTR)
3270Sstevel@tonic-gate 				v = v2;
3280Sstevel@tonic-gate 		vassign(p, v);
3290Sstevel@tonic-gate 	}
3300Sstevel@tonic-gate 	return (0);
3310Sstevel@tonic-gate }
332