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