value.c revision 129004
1/*	$OpenBSD: value.c,v 1.7 2001/10/24 18:38:58 millert Exp $	*/
2/*	$NetBSD: value.c,v 1.6 1997/02/11 09:24:09 mrg Exp $	*/
3
4/*
5 * Copyright (c) 1983, 1993
6 *	The Regents of the University of California.  All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 *    must display the following acknowledgement:
18 *	This product includes software developed by the University of
19 *	California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 *    may be used to endorse or promote products derived from this software
22 *    without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#include <sys/cdefs.h>
38__FBSDID("$FreeBSD: head/usr.bin/tip/tip/value.c 129004 2004-05-06 13:25:09Z stefanf $");
39
40#ifndef lint
41#if 0
42static char sccsid[] = "@(#)value.c	8.1 (Berkeley) 6/6/93";
43static char rcsid[] = "$OpenBSD: value.c,v 1.7 2001/10/24 18:38:58 millert Exp $";
44#endif
45#endif /* not lint */
46
47#include "tip.h"
48
49#define MIDDLE	35
50
51static value_t *vlookup();
52static int col = 0;
53
54/*
55 * Variable manipulation
56 */
57void
58vinit()
59{
60	value_t *p;
61	char *cp;
62	FILE *f;
63	char file[FILENAME_MAX];
64
65	for (p = vtable; p->v_name != NULL; p++) {
66		if (p->v_type&ENVIRON)
67			if ((cp = getenv(p->v_name)))
68				p->v_value = cp;
69		if (p->v_type&IREMOTE)
70			setnumber(p->v_value, *address(p->v_value));
71	}
72	/*
73	 * Read the .tiprc file in the HOME directory
74	 *  for sets
75	 */
76	if (strlen(value(HOME)) + sizeof("/.tiprc") > sizeof(file)) {
77		(void)fprintf(stderr, "Home directory path too long: %s\n",
78			value(HOME));
79	} else {
80		snprintf(file, sizeof file, "%s/.tiprc", value(HOME));
81		if ((f = fopen(file, "r")) != NULL) {
82			char *tp;
83
84			while (fgets(file, sizeof(file)-1, f) != NULL) {
85				if (vflag)
86					printf("set %s", file);
87				if ((tp = strrchr(file, '\n')))
88					*tp = '\0';
89				vlex(file);
90			}
91			fclose(f);
92		}
93	}
94	/*
95	 * To allow definition of exception prior to fork
96	 */
97	vtable[EXCEPTIONS].v_access &= ~(WRITE<<PUBLIC);
98}
99
100static int vaccess();
101
102/*VARARGS1*/
103void
104vassign(p, v)
105	value_t *p;
106	char *v;
107{
108
109	if (!vaccess(p->v_access, WRITE)) {
110		printf("access denied\r\n");
111		return;
112	}
113	switch (p->v_type&TMASK) {
114
115	case STRING:
116		if (p->v_value && equal(p->v_value, v))
117			return;
118		if (!(p->v_type&(ENVIRON|INIT)))
119			free(p->v_value);
120		if ((p->v_value = strdup(v)) == NOSTR) {
121			printf("out of core\r\n");
122			return;
123		}
124		p->v_type &= ~(ENVIRON|INIT);
125		break;
126
127	case NUMBER:
128		if (number(p->v_value) == number(v))
129			return;
130		setnumber(p->v_value, number(v));
131		break;
132
133	case BOOL:
134		if (boolean(p->v_value) == (*v != '!'))
135			return;
136		setboolean(p->v_value, (*v != '!'));
137		break;
138
139	case CHAR:
140		if (character(p->v_value) == *v)
141			return;
142		setcharacter(p->v_value, *v);
143	}
144	p->v_access |= CHANGED;
145}
146
147static void vprint();
148static void vtoken();
149
150void
151vlex(s)
152	char *s;
153{
154	value_t *p;
155
156	if (equal(s, "all")) {
157		for (p = vtable; p->v_name; p++)
158			if (vaccess(p->v_access, READ))
159				vprint(p);
160	} else {
161		char *cp;
162
163		do {
164			if ((cp = vinterp(s, ' ')))
165				cp++;
166			vtoken(s);
167			s = cp;
168		} while (s);
169	}
170	if (col > 0) {
171		printf("\r\n");
172		col = 0;
173	}
174}
175
176static void
177vtoken(s)
178	char *s;
179{
180	value_t *p;
181	char *cp;
182	char *expand();
183
184	if ((cp = strchr(s, '='))) {
185		*cp = '\0';
186		if ((p = vlookup(s))) {
187			cp++;
188			if (p->v_type&NUMBER)
189				vassign(p, atoi(cp));
190			else {
191				if (strcmp(s, "record") == 0)
192					cp = expand(cp);
193				vassign(p, cp);
194			}
195			return;
196		}
197	} else if ((cp = strchr(s, '?'))) {
198		*cp = '\0';
199		if ((p = vlookup(s)) && vaccess(p->v_access, READ)) {
200			vprint(p);
201			return;
202		}
203	} else {
204		if (*s != '!')
205			p = vlookup(s);
206		else
207			p = vlookup(s+1);
208		if (p != NOVAL) {
209			vassign(p, s);
210			return;
211		}
212	}
213	printf("%s: unknown variable\r\n", s);
214}
215
216static void
217vprint(p)
218	value_t *p;
219{
220	char *cp;
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);
241			col += size(cp);
242			printf("%s", cp);
243		}
244		break;
245
246	case NUMBER:
247		col += 6;
248		printf("%s=%-5ld", 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	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	char *s;
283{
284	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	char *s;
295	char stop;
296{
297	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				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 */
348int
349vstring(s,v)
350	char *s;
351	char *v;
352{
353	value_t *p;
354	char *expand();
355
356	p = vlookup(s);
357	if (p == 0)
358		return (1);
359	if (p->v_type&NUMBER)
360		vassign(p, atoi(v));
361	else {
362		if (strcmp(s, "record") == 0)
363			v = expand(v);
364		vassign(p, v);
365	}
366	return (0);
367}
368