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