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