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