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
vinit(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
vassign(value_t * p,char * v)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
vlex(char * s)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
vtoken(char * s)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
vprint(value_t * p)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
vaccess(unsigned mode,unsigned rw)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 *
vlookup(char * s)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 *
vinterp(char * s,char stop)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
vstring(char * s,char * v)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