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