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