xref: /netbsd/usr.bin/tip/value.c (revision bf9ec67e)
1 /*	$NetBSD: value.c,v 1.9 1998/07/12 09:59:30 mrg Exp $	*/
2 
3 /*
4  * Copyright (c) 1983, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *	This product includes software developed by the University of
18  *	California, Berkeley and its contributors.
19  * 4. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 #include <sys/cdefs.h>
37 #ifndef lint
38 #if 0
39 static char sccsid[] = "@(#)value.c	8.1 (Berkeley) 6/6/93";
40 #endif
41 __RCSID("$NetBSD: value.c,v 1.9 1998/07/12 09:59:30 mrg Exp $");
42 #endif /* not lint */
43 
44 #include "tip.h"
45 
46 #define MIDDLE	35
47 
48 static int col = 0;
49 
50 static	int	vaccess __P((unsigned, unsigned));
51 static	void	vassign __P((value_t *, char *));
52 static	value_t *vlookup __P((char *));
53 static	void	vprint __P((value_t *));
54 static	void	vtoken __P((char *));
55 
56 /*
57  * Variable manipulation
58  */
59 void
60 vinit()
61 {
62 	value_t *p;
63 	char *cp;
64 	FILE *f;
65 	char file[MAXPATHLEN];
66 
67 	for (p = vtable; p->v_name != NULL; p++) {
68 		if (p->v_type&ENVIRON)
69 			if ((cp = getenv(p->v_name)) != NULL)
70 				p->v_value = cp;
71 		if (p->v_type&IREMOTE)
72 			setnumber(p->v_value, *address(p->v_value));
73 	}
74 	/*
75 	 * Read the .tiprc file in the HOME directory
76 	 *  for sets
77 	 */
78 	snprintf(file, sizeof(file), "%s/.tiprc", value(HOME));
79 	if ((f = fopen(file, "r")) != NULL) {
80 		char *tp;
81 
82 		while (fgets(file, sizeof(file)-1, f) != NULL) {
83 			if (vflag)
84 				printf("set %s", file);
85 			if ((tp = strrchr(file, '\n')) != NULL)
86 				*tp = '\0';
87 			vlex(file);
88 		}
89 		fclose(f);
90 	}
91 	/*
92 	 * To allow definition of exception prior to fork
93 	 */
94 	vtable[EXCEPTIONS].v_access &= ~(WRITE<<PUBLIC);
95 }
96 
97 void
98 vassign(p, v)
99 	value_t *p;
100 	char *v;
101 {
102 
103 	if (!vaccess(p->v_access, WRITE)) {
104 		printf("access denied\r\n");
105 		return;
106 	}
107 	switch (p->v_type&TMASK) {
108 
109 	case STRING:
110 		if (p->v_value && equal(p->v_value, v))
111 			return;
112 		if (!(p->v_type&(ENVIRON|INIT)))
113 			free(p->v_value);
114 		if ((p->v_value = strdup(v)) == NULL) {
115 			printf("out of core\r\n");
116 			return;
117 		}
118 		p->v_type &= ~(ENVIRON|INIT);
119 		break;
120 
121 	case NUMBER:
122 		if (number(p->v_value) == number(v))
123 			return;
124 		setnumber(p->v_value, number(v));
125 		break;
126 
127 	case BOOL:
128 		if (boolean(p->v_value) == (*v != '!'))
129 			return;
130 		setboolean(p->v_value, (*v != '!'));
131 		break;
132 
133 	case CHAR:
134 		if (character(p->v_value) == *v)
135 			return;
136 		setcharacter(p->v_value, *v);
137 	}
138 	p->v_access |= CHANGED;
139 }
140 
141 void
142 vlex(s)
143 	char *s;
144 {
145 	value_t *p;
146 
147 	if (equal(s, "all")) {
148 		for (p = vtable; p->v_name; p++)
149 			if (vaccess(p->v_access, READ))
150 				vprint(p);
151 	} else {
152 		char *cp;
153 
154 		do {
155 			if ((cp = vinterp(s, ' ')) != NULL)
156 				cp++;
157 			vtoken(s);
158 			s = cp;
159 		} while (s);
160 	}
161 	if (col > 0) {
162 		printf("\r\n");
163 		col = 0;
164 	}
165 }
166 
167 static void
168 vtoken(s)
169 	char *s;
170 {
171 	value_t *p;
172 	char *cp;
173 
174 	if ((cp = strchr(s, '=')) != NULL) {
175 		*cp = '\0';
176 		if ((p = vlookup(s)) != NULL) {
177 			cp++;
178 			if (p->v_type&NUMBER)
179 				vassign(p, (char *)(long)atoi(cp));
180 			else {
181 				if (strcmp(s, "record") == 0)
182 					cp = expand(cp);
183 				vassign(p, cp);
184 			}
185 			return;
186 		}
187 	} else if ((cp = strchr(s, '?')) != NULL) {
188 		*cp = '\0';
189 		if ((p = vlookup(s)) && vaccess(p->v_access, READ)) {
190 			vprint(p);
191 			return;
192 		}
193 	} else {
194 		if (*s != '!')
195 			p = vlookup(s);
196 		else
197 			p = vlookup(s+1);
198 		if (p != NULL) {
199 			vassign(p, s);
200 			return;
201 		}
202 	}
203 	printf("%s: unknown variable\r\n", s);
204 }
205 
206 static void
207 vprint(p)
208 	value_t *p;
209 {
210 	char *cp;
211 
212 	if (col > 0 && col < MIDDLE)
213 		while (col++ < MIDDLE)
214 			putchar(' ');
215 	col += strlen(p->v_name);
216 	switch (p->v_type&TMASK) {
217 
218 	case BOOL:
219 		if (boolean(p->v_value) == FALSE) {
220 			col++;
221 			putchar('!');
222 		}
223 		printf("%s", p->v_name);
224 		break;
225 
226 	case STRING:
227 		printf("%s=", p->v_name);
228 		col++;
229 		if (p->v_value) {
230 			cp = interp(p->v_value);
231 			col += strlen(cp);
232 			printf("%s", cp);
233 		}
234 		break;
235 
236 	case NUMBER:
237 		col += 6;
238 		printf("%s=%-5d", p->v_name, (int)number(p->v_value));
239 		break;
240 
241 	case CHAR:
242 		printf("%s=", p->v_name);
243 		col++;
244 		if (p->v_value) {
245 			cp = ctrl(character(p->v_value));
246 			col += strlen(cp);
247 			printf("%s", cp);
248 		}
249 		break;
250 	}
251 	if (col >= MIDDLE) {
252 		col = 0;
253 		printf("\r\n");
254 		return;
255 	}
256 }
257 
258 
259 static int
260 vaccess(mode, rw)
261 	unsigned mode, rw;
262 {
263 
264 	if (mode & (rw<<PUBLIC))
265 		return (1);
266 	if (mode & (rw<<PRIVATE))
267 		return (1);
268 	return ((mode & (rw<<ROOT)) && getuid() == 0);
269 }
270 
271 static value_t *
272 vlookup(s)
273 	char *s;
274 {
275 	value_t *p;
276 
277 	for (p = vtable; p->v_name; p++)
278 		if (equal(p->v_name, s) || (p->v_abrev && equal(p->v_abrev, s)))
279 			return (p);
280 	return (NULL);
281 }
282 
283 char *
284 vinterp(s, stop)
285 	char *s;
286 	char stop;
287 {
288 	char *p = s, c;
289 	int num;
290 
291 	while ((c = *s++) && c != stop)
292 		switch (c) {
293 
294 		case '^':
295 			if (*s)
296 				*p++ = *s++ - 0100;
297 			else
298 				*p++ = c;
299 			break;
300 
301 		case '\\':
302 			num = 0;
303 			c = *s++;
304 			if (c >= '0' && c <= '7')
305 				num = (num<<3)+(c-'0');
306 			else {
307 				char *q = "n\nr\rt\tb\bf\f";
308 
309 				for (; *q; q++)
310 					if (c == *q++) {
311 						*p++ = *q;
312 						goto cont;
313 					}
314 				*p++ = c;
315 			cont:
316 				break;
317 			}
318 			if ((c = *s++) >= '0' && c <= '7') {
319 				num = (num<<3)+(c-'0');
320 				if ((c = *s++) >= '0' && c <= '7')
321 					num = (num<<3)+(c-'0');
322 				else
323 					s--;
324 			} else
325 				s--;
326 			*p++ = num;
327 			break;
328 
329 		default:
330 			*p++ = c;
331 		}
332 	*p = '\0';
333 	return (c == stop ? s-1 : NULL);
334 }
335 
336 /*
337  * assign variable s with value v (for NUMBER or STRING or CHAR types)
338  */
339 
340 int
341 vstring(s,v)
342 	char *s;
343 	char *v;
344 {
345 	value_t *p;
346 
347 	p = vlookup(s);
348 	if (p == 0)
349 		return (1);
350 	if (p->v_type&NUMBER)
351 		vassign(p, (char *)(long)atoi(v));
352 	else {
353 		if (strcmp(s, "record") == 0)
354 			v = expand(v);
355 		vassign(p, v);
356 	}
357 	return (0);
358 }
359