xref: /titanic_51/usr/src/cmd/tip/value.c (revision 8eea8e29cc4374d1ee24c25a07f45af132db3499)
1 /*
2  * Copyright (c) 2000 by Sun Microsystems, Inc.
3  * All rights reserved.
4  */
5 
6 /* from UCB 4.5 6/25/83 */
7 /*
8  * Copyright (c) 1983 Regents of the University of California.
9  * All rights reserved. The Berkeley software License Agreement
10  * specifies the terms and conditions for redistribution.
11  */
12 #pragma ident	"%Z%%M%	%I%	%E% SMI"
13 
14 #include "tip.h"
15 
16 #define	MIDDLE	35
17 
18 static value_t *vlookup();
19 static int col = 0;
20 
21 /*
22  * Variable manipulation
23  */
24 vinit()
25 {
26 	register value_t *p;
27 	register char *cp;
28 	FILE *f;
29 	char file[1024];
30 
31 	for (p = vtable; p->v_name != NULL; p++) {
32 		if (p->v_type&ENVIRON)
33 			if (cp = getenv(p->v_name))
34 				p->v_value = cp;
35 		if (p->v_type&IREMOTE)
36 			number(p->v_value) = *address(p->v_value);
37 	}
38 	/*
39 	 * Read the .tiprc file in the HOME directory
40 	 *  for sets
41 	 */
42 	if ((cp = value(HOME)) == NULL)
43 		cp = "";
44 	strlcpy(file, cp, sizeof (file));
45 	strlcat(file, "/.tiprc", sizeof (file));
46 	if ((f = fopen(file, "r")) != NULL) {
47 		register char *tp;
48 
49 		while (fgets(file, sizeof (file)-1, f) != NULL) {
50 			if (file[0] == '#')
51 				continue;
52 			if (vflag)
53 				printf("set %s", file);
54 			if (tp = strrchr(file, '\n'))
55 				*tp = '\0';
56 			vlex(file);
57 		}
58 		fclose(f);
59 	}
60 	/*
61 	 * To allow definition of exception prior to fork
62 	 */
63 	vtable[EXCEPTIONS].v_access &= ~(WRITE<<PUBLIC);
64 }
65 
66 /*VARARGS1*/
67 vassign(p, v)
68 	register value_t *p;
69 	char *v;
70 {
71 
72 	if (!vaccess(p->v_access, WRITE)) {
73 		printf("access denied\r\n");
74 		return;
75 	}
76 	switch (p->v_type&TMASK) {
77 
78 	case STRING:
79 		if (p->v_value != (char *)NULL) {
80 			if (equal(p->v_value, v))
81 				return;
82 			if (!(p->v_type&(ENVIRON|INIT)))
83 				free(p->v_value);
84 		}
85 		if ((p->v_value = malloc(strlen(v)+1)) == NOSTR) {
86 			printf("out of core\r\n");
87 			return;
88 		}
89 		p->v_type &= ~(ENVIRON|INIT);
90 		strcpy(p->v_value, v);
91 		break;
92 
93 	case NUMBER:
94 		if (number(p->v_value) == number(v))
95 			return;
96 		number(p->v_value) = number(v);
97 		break;
98 
99 	case BOOL:
100 		if (boolean(p->v_value) == (*v != '!'))
101 			return;
102 		boolean(p->v_value) = (*v != '!');
103 		break;
104 
105 	case CHAR:
106 		if (character(p->v_value) == *v)
107 			return;
108 		character(p->v_value) = *v;
109 	}
110 	p->v_access |= CHANGED;
111 }
112 
113 vlex(s)
114 	register char *s;
115 {
116 	register value_t *p;
117 
118 	if (equal(s, "all")) {
119 		for (p = vtable; p->v_name; p++)
120 			if (vaccess(p->v_access, READ))
121 				vprint(p);
122 	} else {
123 		register char *cp;
124 
125 		do {
126 			if (cp = vinterp(s, ' '))
127 				cp++;
128 			vtoken(s);
129 			s = cp;
130 		} while (s);
131 	}
132 	if (col > 0) {
133 		printf("\r\n");
134 		col = 0;
135 	}
136 }
137 
138 static int
139 vtoken(s)
140 	register char *s;
141 {
142 	register value_t *p;
143 	register char *cp, *cp2;
144 	char *expand();
145 
146 	if (cp = strchr(s, '=')) {
147 		*cp = '\0';
148 		if (p = vlookup(s)) {
149 			cp++;
150 			if (p->v_type&NUMBER)
151 				vassign(p, atoi(cp));
152 			else {
153 				if (strcmp(s, "record") == 0)
154 					if ((cp2 = expand(cp)) != NOSTR)
155 						cp = cp2;
156 				vassign(p, cp);
157 			}
158 			return;
159 		}
160 	} else if (cp = strchr(s, '?')) {
161 		*cp = '\0';
162 		if ((p = vlookup(s)) && vaccess(p->v_access, READ)) {
163 			vprint(p);
164 			return;
165 		}
166 	} else {
167 		if (*s != '!')
168 			p = vlookup(s);
169 		else
170 			p = vlookup(s+1);
171 		if (p != NOVAL) {
172 			if (p->v_type&BOOL)
173 				vassign(p, s);
174 			else
175 				printf("%s: no value specified\r\n", s);
176 			return;
177 		}
178 	}
179 	printf("%s: unknown variable\r\n", s);
180 }
181 
182 static int
183 vprint(p)
184 	register value_t *p;
185 {
186 	register char *cp;
187 	extern char *interp(), *ctrl();
188 
189 	if (col > 0 && col < MIDDLE)
190 		while (col++ < MIDDLE)
191 			putchar(' ');
192 	col += strlen(p->v_name);
193 	switch (p->v_type&TMASK) {
194 
195 	case BOOL:
196 		if (boolean(p->v_value) == FALSE) {
197 			col++;
198 			putchar('!');
199 		}
200 		printf("%s", p->v_name);
201 		break;
202 
203 	case STRING:
204 		printf("%s=", p->v_name);
205 		col++;
206 		if (p->v_value) {
207 			cp = interp(p->v_value, NULL);
208 			col += strlen(cp);
209 			printf("%s", cp);
210 		}
211 		break;
212 
213 	case NUMBER:
214 		col += 6;
215 		printf("%s=%-5d", p->v_name, number(p->v_value));
216 		break;
217 
218 	case CHAR:
219 		printf("%s=", p->v_name);
220 		col++;
221 		if (p->v_value) {
222 			cp = ctrl(character(p->v_value));
223 			col += strlen(cp);
224 			printf("%s", cp);
225 		}
226 		break;
227 	}
228 	if (col >= MIDDLE) {
229 		col = 0;
230 		printf("\r\n");
231 		return;
232 	}
233 }
234 
235 
236 static int
237 vaccess(mode, rw)
238 	register unsigned mode, rw;
239 {
240 	if (mode & (rw<<PUBLIC))
241 		return (1);
242 	if (mode & (rw<<PRIVATE))
243 		return (1);
244 	return ((mode & (rw<<ROOT)) && uid == 0);
245 }
246 
247 static value_t *
248 vlookup(s)
249 	register char *s;
250 {
251 	register value_t *p;
252 
253 	for (p = vtable; p->v_name; p++)
254 		if (equal(p->v_name, s) || (p->v_abrev && equal(p->v_abrev, s)))
255 			return (p);
256 	return (NULL);
257 }
258 
259 char *
260 vinterp(s, stop)
261 	register char *s;
262 	char stop;
263 {
264 	register char *p = s, c;
265 	int num;
266 
267 	while ((c = *s++) && c != stop)
268 		switch (c) {
269 
270 		case '^':
271 			if (*s)
272 				*p++ = *s++ - 0100;
273 			else
274 				*p++ = c;
275 			break;
276 
277 		case '\\':
278 			num = 0;
279 			c = *s++;
280 			if (c >= '0' && c <= '7')
281 				num = (num<<3)+(c-'0');
282 			else {
283 				register char *q = "n\nr\rt\tb\bf\f";
284 
285 				for (; *q; q++)
286 					if (c == *q++) {
287 						*p++ = *q;
288 						goto cont;
289 					}
290 				*p++ = c;
291 			cont:
292 				break;
293 			}
294 			if ((c = *s++) >= '0' && c <= '7') {
295 				num = (num<<3)+(c-'0');
296 				if ((c = *s++) >= '0' && c <= '7')
297 					num = (num<<3)+(c-'0');
298 				else
299 					s--;
300 			} else
301 				s--;
302 			*p++ = num;
303 			break;
304 
305 		default:
306 			*p++ = c;
307 		}
308 	*p = '\0';
309 	return (c == stop ? s-1 : NULL);
310 }
311 
312 /*
313  * assign variable s with value v (for NUMBER or STRING or CHAR types)
314  */
315 
316 vstring(s, v)
317 	register char *s;
318 	register char *v;
319 {
320 	register value_t *p;
321 	char *v2;
322 	char *expand();
323 
324 	p = vlookup(s);
325 	if (p == 0)
326 		return (1);
327 	if (p->v_type&NUMBER)
328 		vassign(p, atoi(v));
329 	else {
330 		if (strcmp(s, "record") == 0)
331 			if ((v2 = expand(v)) != NOSTR)
332 				v = v2;
333 		vassign(p, v);
334 	}
335 	return (0);
336 }
337