value.c revision 28365
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	"$Id$";
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			number(p->v_value) = *address(p->v_value);
70	}
71	/*
72	 * Read the .tiprc file in the HOME directory
73	 *  for sets
74	 */
75	strcpy(file, value(HOME));
76	strcat(file, "/.tiprc");
77	if ((f = fopen(file, "r")) != NULL) {
78		register char *tp;
79
80		while (fgets(file, sizeof(file)-1, f) != NULL) {
81			if (vflag)
82				printf("set %s", file);
83			if ((tp = rindex(file, '\n')))
84				*tp = '\0';
85			vlex(file);
86		}
87		fclose(f);
88	}
89	/*
90	 * To allow definition of exception prior to fork
91	 */
92	vtable[EXCEPTIONS].v_access &= ~(WRITE<<PUBLIC);
93}
94
95static int vaccess();
96
97/*VARARGS1*/
98void
99vassign(p, v)
100	register value_t *p;
101	char *v;
102{
103
104	if (!vaccess(p->v_access, WRITE)) {
105		printf("access denied\r\n");
106		return;
107	}
108	switch (p->v_type&TMASK) {
109
110	case STRING:
111		if (p->v_value && equal(p->v_value, v))
112			return;
113		if (!(p->v_type&(ENVIRON|INIT)))
114			free(p->v_value);
115		if ((p->v_value = malloc(size(v)+1)) == NOSTR) {
116			printf("out of core\r\n");
117			return;
118		}
119		p->v_type &= ~(ENVIRON|INIT);
120		strcpy(p->v_value, v);
121		break;
122
123	case NUMBER:
124		if (number(p->v_value) == number(v))
125			return;
126		number(p->v_value) = number(v);
127		break;
128
129	case BOOL:
130		if (boolean(p->v_value) == (*v != '!'))
131			return;
132		boolean(p->v_value) = (*v != '!');
133		break;
134
135	case CHAR:
136		if (character(p->v_value) == *v)
137			return;
138		character(p->v_value) = *v;
139	}
140	p->v_access |= CHANGED;
141}
142
143static void vprint();
144
145void
146vlex(s)
147	register char *s;
148{
149	register value_t *p;
150	static void vtoken();
151
152	if (equal(s, "all")) {
153		for (p = vtable; p->v_name; p++)
154			if (vaccess(p->v_access, READ))
155				vprint(p);
156	} else {
157		register char *cp;
158
159		do {
160			if ((cp = vinterp(s, ' ')))
161				cp++;
162			vtoken(s);
163			s = cp;
164		} while (s);
165	}
166	if (col > 0) {
167		printf("\r\n");
168		col = 0;
169	}
170}
171
172static void
173vtoken(s)
174	register char *s;
175{
176	register value_t *p;
177	register char *cp;
178	char *expand();
179
180	if ((cp = index(s, '='))) {
181		*cp = '\0';
182		if ((p = vlookup(s))) {
183			cp++;
184			if (p->v_type&NUMBER)
185				vassign(p, atoi(cp));
186			else {
187				if (strcmp(s, "record") == 0)
188					cp = expand(cp);
189				vassign(p, cp);
190			}
191			return;
192		}
193	} else if ((cp = index(s, '?'))) {
194		*cp = '\0';
195		if ((p = vlookup(s)) && vaccess(p->v_access, READ)) {
196			vprint(p);
197			return;
198		}
199	} else {
200		if (*s != '!')
201			p = vlookup(s);
202		else
203			p = vlookup(s+1);
204		if (p != NOVAL) {
205			vassign(p, s);
206			return;
207		}
208	}
209	printf("%s: unknown variable\r\n", s);
210}
211
212static void
213vprint(p)
214	register value_t *p;
215{
216	register char *cp;
217	extern char *interp(), *ctrl();
218
219	if (col > 0 && col < MIDDLE)
220		while (col++ < MIDDLE)
221			putchar(' ');
222	col += size(p->v_name);
223	switch (p->v_type&TMASK) {
224
225	case BOOL:
226		if (boolean(p->v_value) == FALSE) {
227			col++;
228			putchar('!');
229		}
230		printf("%s", p->v_name);
231		break;
232
233	case STRING:
234		printf("%s=", p->v_name);
235		col++;
236		if (p->v_value) {
237			cp = interp(p->v_value, NULL);
238			col += size(cp);
239			printf("%s", cp);
240		}
241		break;
242
243	case NUMBER:
244		col += 6;
245		printf("%s=%-5d", p->v_name, number(p->v_value));
246		break;
247
248	case CHAR:
249		printf("%s=", p->v_name);
250		col++;
251		if (p->v_value) {
252			cp = ctrl(character(p->v_value));
253			col += size(cp);
254			printf("%s", cp);
255		}
256		break;
257	}
258	if (col >= MIDDLE) {
259		col = 0;
260		printf("\r\n");
261		return;
262	}
263}
264
265
266static int
267vaccess(mode, rw)
268	register unsigned mode, rw;
269{
270	if (mode & (rw<<PUBLIC))
271		return (1);
272	if (mode & (rw<<PRIVATE))
273		return (1);
274	return ((mode & (rw<<ROOT)) && getuid() == 0);
275}
276
277static value_t *
278vlookup(s)
279	register char *s;
280{
281	register value_t *p;
282
283	for (p = vtable; p->v_name; p++)
284		if (equal(p->v_name, s) || (p->v_abrev && equal(p->v_abrev, s)))
285			return (p);
286	return (NULL);
287}
288
289char *
290vinterp(s, stop)
291	register char *s;
292	char stop;
293{
294	register char *p = s, c;
295	int num;
296
297	while ((c = *s++) && c != stop)
298		switch (c) {
299
300		case '^':
301			if (*s)
302				*p++ = *s++ - 0100;
303			else
304				*p++ = c;
305			break;
306
307		case '\\':
308			num = 0;
309			c = *s++;
310			if (c >= '0' && c <= '7')
311				num = (num<<3)+(c-'0');
312			else {
313				register char *q = "n\nr\rt\tb\bf\f";
314
315				for (; *q; q++)
316					if (c == *q++) {
317						*p++ = *q;
318						goto cont;
319					}
320				*p++ = c;
321			cont:
322				break;
323			}
324			if ((c = *s++) >= '0' && c <= '7') {
325				num = (num<<3)+(c-'0');
326				if ((c = *s++) >= '0' && c <= '7')
327					num = (num<<3)+(c-'0');
328				else
329					s--;
330			} else
331				s--;
332			*p++ = num;
333			break;
334
335		default:
336			*p++ = c;
337		}
338	*p = '\0';
339	return (c == stop ? s-1 : NULL);
340}
341
342/*
343 * assign variable s with value v (for NUMBER or STRING or CHAR types)
344 */
345
346int
347vstring(s,v)
348	register char *s;
349	register char *v;
350{
351	register value_t *p;
352	char *expand();
353
354	p = vlookup(s);
355	if (p == 0)
356		return (1);
357	if (p->v_type&NUMBER)
358		vassign(p, atoi(v));
359	else {
360		if (strcmp(s, "record") == 0)
361			v = expand(v);
362		vassign(p, v);
363	}
364	return (0);
365}
366