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