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