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