value.c revision 50477
1/*
2 * Copyright (c) 1983, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by the University of
16 *	California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35#if 0
36static char sccsid[] = "@(#)value.c	8.1 (Berkeley) 6/6/93";
37#endif
38static const char rcsid[] =
39  "$FreeBSD: head/usr.bin/tip/tip/value.c 50477 1999-08-28 01:08:13Z peter $";
40#endif /* not lint */
41
42#include "tip.h"
43
44#define MIDDLE	35
45
46static value_t *vlookup();
47int vstring __P((char *, char *));
48void vlex __P((char *));
49void vassign __P((value_t *, char *));
50
51static int col = 0;
52
53/*
54 * Variable manipulation
55 */
56void
57vinit()
58{
59	register value_t *p;
60	register char *cp;
61	FILE *f;
62	char file[256];
63
64	for (p = vtable; p->v_name != NULL; p++) {
65		if (p->v_type&ENVIRON)
66			if ((cp = getenv(p->v_name)))
67				p->v_value = cp;
68		if (p->v_type&IREMOTE)
69			if (p->v_type&STRING)
70				p->v_value = *(char **) address(p->v_value);
71			else
72				number(p->v_value) = *address(p->v_value);
73	}
74	/*
75	 * Read the .tiprc file in the HOME directory
76	 *  for sets
77	 */
78	strcpy(file, value(HOME));
79	strcat(file, "/.tiprc");
80	if ((f = fopen(file, "r")) != NULL) {
81		register char *tp;
82
83		while (fgets(file, sizeof(file)-1, f) != NULL) {
84			if (vflag)
85				printf("set %s", file);
86			if ((tp = rindex(file, '\n')))
87				*tp = '\0';
88			vlex(file);
89		}
90		fclose(f);
91	}
92	/*
93	 * To allow definition of exception prior to fork
94	 */
95	vtable[EXCEPTIONS].v_access &= ~(WRITE<<PUBLIC);
96}
97
98static int vaccess();
99
100/*VARARGS1*/
101void
102vassign(p, v)
103	register value_t *p;
104	char *v;
105{
106
107	if (!vaccess(p->v_access, WRITE)) {
108		printf("access denied\r\n");
109		return;
110	}
111	switch (p->v_type&TMASK) {
112
113	case STRING:
114		if (p->v_value && equal(p->v_value, v))
115			return;
116		if (!(p->v_type&(ENVIRON|INIT)))
117			free(p->v_value);
118		if ((p->v_value = malloc(size(v)+1)) == NOSTR) {
119			printf("out of core\r\n");
120			return;
121		}
122		p->v_type &= ~(ENVIRON|INIT);
123		strcpy(p->v_value, v);
124		break;
125
126	case NUMBER:
127		if (number(p->v_value) == number(v))
128			return;
129		number(p->v_value) = number(v);
130		break;
131
132	case BOOL:
133		if (boolean(p->v_value) == (*v != '!'))
134			return;
135		boolean(p->v_value) = (*v != '!');
136		break;
137
138	case CHAR:
139		if (character(p->v_value) == *v)
140			return;
141		character(p->v_value) = *v;
142	}
143	p->v_access |= CHANGED;
144}
145
146static void vprint();
147
148void
149vlex(s)
150	register char *s;
151{
152	register value_t *p;
153	static void vtoken();
154
155	if (equal(s, "all")) {
156		for (p = vtable; p->v_name; p++)
157			if (vaccess(p->v_access, READ))
158				vprint(p);
159	} else {
160		register char *cp;
161
162		do {
163			if ((cp = vinterp(s, ' ')))
164				cp++;
165			vtoken(s);
166			s = cp;
167		} while (s);
168	}
169	if (col > 0) {
170		printf("\r\n");
171		col = 0;
172	}
173}
174
175static void
176vtoken(s)
177	register char *s;
178{
179	register value_t *p;
180	register char *cp;
181	char *expand();
182
183	if ((cp = index(s, '='))) {
184		*cp = '\0';
185		if ((p = vlookup(s))) {
186			cp++;
187			if (p->v_type&NUMBER)
188				vassign(p, atoi(cp));
189			else {
190				if (strcmp(s, "record") == 0)
191					cp = expand(cp);
192				vassign(p, cp);
193			}
194			return;
195		}
196	} else if ((cp = index(s, '?'))) {
197		*cp = '\0';
198		if ((p = vlookup(s)) && vaccess(p->v_access, READ)) {
199			vprint(p);
200			return;
201		}
202	} else {
203		if (*s != '!')
204			p = vlookup(s);
205		else
206			p = vlookup(s+1);
207		if (p != NOVAL) {
208			vassign(p, s);
209			return;
210		}
211	}
212	printf("%s: unknown variable\r\n", s);
213}
214
215static void
216vprint(p)
217	register value_t *p;
218{
219	register char *cp;
220	extern char *interp(), *ctrl();
221
222	if (col > 0 && col < MIDDLE)
223		while (col++ < MIDDLE)
224			putchar(' ');
225	col += size(p->v_name);
226	switch (p->v_type&TMASK) {
227
228	case BOOL:
229		if (boolean(p->v_value) == FALSE) {
230			col++;
231			putchar('!');
232		}
233		printf("%s", p->v_name);
234		break;
235
236	case STRING:
237		printf("%s=", p->v_name);
238		col++;
239		if (p->v_value) {
240			cp = interp(p->v_value, NULL);
241			col += size(cp);
242			printf("%s", cp);
243		}
244		break;
245
246	case NUMBER:
247		col += 6;
248		printf("%s=%-5d", p->v_name, number(p->v_value));
249		break;
250
251	case CHAR:
252		printf("%s=", p->v_name);
253		col++;
254		if (p->v_value) {
255			cp = ctrl(character(p->v_value));
256			col += size(cp);
257			printf("%s", cp);
258		}
259		break;
260	}
261	if (col >= MIDDLE) {
262		col = 0;
263		printf("\r\n");
264		return;
265	}
266}
267
268
269static int
270vaccess(mode, rw)
271	register unsigned mode, rw;
272{
273	if (mode & (rw<<PUBLIC))
274		return (1);
275	if (mode & (rw<<PRIVATE))
276		return (1);
277	return ((mode & (rw<<ROOT)) && getuid() == 0);
278}
279
280static value_t *
281vlookup(s)
282	register char *s;
283{
284	register value_t *p;
285
286	for (p = vtable; p->v_name; p++)
287		if (equal(p->v_name, s) || (p->v_abrev && equal(p->v_abrev, s)))
288			return (p);
289	return (NULL);
290}
291
292char *
293vinterp(s, stop)
294	register char *s;
295	char stop;
296{
297	register char *p = s, c;
298	int num;
299
300	while ((c = *s++) && c != stop)
301		switch (c) {
302
303		case '^':
304			if (*s)
305				*p++ = *s++ - 0100;
306			else
307				*p++ = c;
308			break;
309
310		case '\\':
311			num = 0;
312			c = *s++;
313			if (c >= '0' && c <= '7')
314				num = (num<<3)+(c-'0');
315			else {
316				register char *q = "n\nr\rt\tb\bf\f";
317
318				for (; *q; q++)
319					if (c == *q++) {
320						*p++ = *q;
321						goto cont;
322					}
323				*p++ = c;
324			cont:
325				break;
326			}
327			if ((c = *s++) >= '0' && c <= '7') {
328				num = (num<<3)+(c-'0');
329				if ((c = *s++) >= '0' && c <= '7')
330					num = (num<<3)+(c-'0');
331				else
332					s--;
333			} else
334				s--;
335			*p++ = num;
336			break;
337
338		default:
339			*p++ = c;
340		}
341	*p = '\0';
342	return (c == stop ? s-1 : NULL);
343}
344
345/*
346 * assign variable s with value v (for NUMBER or STRING or CHAR types)
347 */
348
349int
350vstring(s,v)
351	register char *s;
352	register char *v;
353{
354	register value_t *p;
355	char *expand();
356
357	p = vlookup(s);
358	if (p == 0)
359		return (1);
360	if (p->v_type&NUMBER)
361		vassign(p, atoi(v));
362	else {
363		if (strcmp(s, "record") == 0)
364			v = expand(v);
365		vassign(p, v);
366	}
367	return (0);
368}
369