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