Annotation of src/usr.bin/tip/value.c, Revision 1.32
1.32 ! chl 1: /* $OpenBSD: value.c,v 1.31 2010/07/02 07:55:00 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:
1.30 nicm 33: #include <paths.h>
34:
1.1 deraadt 35: #include "tip.h"
36:
1.26 nicm 37: /*
38: * Variable manipulation.
39: */
40:
1.30 nicm 41: value_t vtable[] = {
42: { "beautify", V_BOOL, "be", NULL, 0 },
43: { "baudrate", V_NUMBER, "ba", NULL, 0 },
44: { "connect", V_STRING|V_READONLY, "cm", NULL, 0 },
45: { "device", V_STRING|V_READONLY, "dv", NULL, 0 },
46: { "eofread", V_STRING, "eofr", NULL, 0 },
47: { "eofwrite", V_STRING, "eofw", NULL, 0 },
48: { "eol", V_STRING, NULL, NULL, 0 },
49: { "escape", V_CHAR, "es", NULL, 0 },
50: { "exceptions", V_STRING, "ex", NULL, 0 },
51: { "force", V_CHAR, "fo", NULL, 0 },
52: { "framesize", V_NUMBER, "fr", NULL, 0 },
53: { "host", V_STRING|V_READONLY, "ho", NULL, 0 },
54: { "log", V_STRING, NULL, NULL, 0 },
55: { "prompt", V_CHAR, "pr", NULL, 0 },
56: { "raise", V_BOOL, "ra", NULL, 0 },
57: { "raisechar", V_CHAR, "rc", NULL, 0 },
58: { "record", V_STRING, "rec", NULL, 0 },
59: { "remote", V_STRING|V_READONLY, NULL, NULL, 0 },
60: { "script", V_BOOL, "sc", NULL, 0 },
61: { "tabexpand", V_BOOL, "tab", NULL, 0 },
62: { "verbose", V_BOOL, "verb", NULL, 0 },
63: { "SHELL", V_STRING, NULL, NULL, 0 },
64: { "HOME", V_STRING, NULL, NULL, 0 },
65: { "echocheck", V_BOOL, "ec", NULL, 0 },
66: { "disconnect", V_STRING, "di", NULL, 0 },
67: { "tandem", V_BOOL, "ta", NULL, 0 },
68: { "linedelay", V_NUMBER, "ldelay", NULL, 0 },
69: { "chardelay", V_NUMBER, "cdelay", NULL, 0 },
70: { "etimeout", V_NUMBER, "et", NULL, 0 },
71: { "rawftp", V_BOOL, "raw", NULL, 0 },
72: { "halfduplex", V_BOOL, "hdx", NULL, 0 },
73: { "localecho", V_BOOL, "le", NULL, 0 },
74: { "parity", V_STRING, "par", NULL, 0 },
75: { "hardwareflow", V_BOOL, "hf", NULL, 0 },
76: { "linedisc", V_NUMBER, "ld", NULL, 0 },
77: { "direct", V_BOOL, "dc", NULL, 0 },
78: { NULL, 0, NULL, NULL, 0 },
79: };
80:
1.29 nicm 81: static int vlookup(char *);
82: static void vtoken(char *);
1.31 nicm 83: static size_t vprint(value_t *);
84: static void vprintall(void);
1.29 nicm 85: static char *vinterp(char *, int);
1.13 moritz 86:
1.26 nicm 87: /* Get a string value. */
88: char *
89: vgetstr(int value)
90: {
1.28 nicm 91: value_t *vp = &vtable[value];
92: int type;
93:
94: type = vp->v_flags & V_TYPEMASK;
95: if (type != V_STRING)
96: errx(1, "variable %s not a string", vp->v_name);
97: return (vp->v_string);
1.26 nicm 98: }
99:
100: /* Get a number value. */
101: int
102: vgetnum(int value)
103: {
1.28 nicm 104: value_t *vp = &vtable[value];
105: int type;
106:
107: type = vp->v_flags & V_TYPEMASK;
108: if (type != V_NUMBER && type != V_BOOL && type != V_CHAR)
109: errx(1, "variable %s not a number", vp->v_name);
110: return (vp->v_number);
1.26 nicm 111: }
112:
113: /* Set a string value. */
114: void
115: vsetstr(int value, char *string)
116: {
1.28 nicm 117: value_t *vp = &vtable[value];
118: int type;
119:
120: type = vp->v_flags & V_TYPEMASK;
121: if (type != V_STRING)
122: errx(1, "variable %s not a string", vp->v_name);
123:
124: if (value == RECORD && string != NULL)
125: string = expand(string);
126:
1.30 nicm 127: free(vp->v_string);
1.28 nicm 128: if (string != NULL) {
129: vp->v_string = strdup(string);
130: if (vp->v_string == NULL)
131: err(1, "strdup");
132: } else
133: vp->v_string = NULL;
1.26 nicm 134: }
135:
136: /* Set a number value. */
137: void
138: vsetnum(int value, int number)
139: {
1.28 nicm 140: value_t *vp = &vtable[value];
141: int type;
142:
143: type = vp->v_flags & V_TYPEMASK;
144: if (type != V_NUMBER && type != V_BOOL && type != V_CHAR)
145: errx(1, "variable %s not a number", vp->v_name);
146:
147: vp->v_number = number;
1.26 nicm 148: }
149:
1.31 nicm 150: /* Print a single variable and its value. */
151: static size_t
152: vprint(value_t *p)
153: {
154: char *cp;
155: size_t width;
156:
157: width = size(p->v_name);
158: switch (p->v_flags & V_TYPEMASK) {
159: case V_BOOL:
160: if (!p->v_number) {
161: width++;
162: putchar('!');
163: }
164: printf("%s", p->v_name);
165: break;
166: case V_STRING:
167: printf("%s=", p->v_name);
168: width++;
169: if (p->v_string) {
170: cp = interp(p->v_string);
171: width += size(cp);
172: printf("%s", cp);
173: }
174: break;
175: case V_NUMBER:
176: width += 6;
177: printf("%s=%-5d", p->v_name, p->v_number);
178: break;
179: case V_CHAR:
180: printf("%s=", p->v_name);
181: width++;
182: if (p->v_number) {
183: cp = ctrl(p->v_number);
184: width += size(cp);
185: printf("%s", cp);
186: }
187: break;
188: }
189: return (width);
190: }
191:
192: /* Print all variables. */
193: static void
194: vprintall(void)
195: {
196: value_t *vp;
197: size_t width;
198:
199: #define MIDDLE 35
200: width = 0;
201: for (vp = vtable; vp->v_name; vp++) {
202: if (vp->v_flags & V_READONLY)
203: continue;
204: if (width > 0 && width < MIDDLE) {
205: while (width++ < MIDDLE)
206: putchar(' ');
207: }
208: width += vprint(vp);
209: if (width > MIDDLE) {
210: printf("\r\n");
211: width = 0;
212: }
213: }
214: #undef MIDDLE
215: }
216:
1.29 nicm 217: /* Find index of variable by name or abbreviation. */
218: static int
219: vlookup(char *s)
220: {
221: value_t *vp;
222: u_int i;
223:
224: for (i = 0; vtable[i].v_name != NULL; i++) {
225: vp = &vtable[i];
226: if (strcmp(vp->v_name, s) == 0 ||
227: (vp->v_abbrev != NULL && strcmp(vp->v_abbrev, s) == 0))
228: return (i);
229: }
230: return (-1);
231: }
232:
1.5 deraadt 233: void
1.11 deraadt 234: vinit(void)
1.1 deraadt 235: {
1.30 nicm 236: struct passwd *pw;
237: value_t *vp;
238: char file[FILENAME_MAX], *cp;
239: int written;
240: FILE *fp;
1.1 deraadt 241:
1.23 nicm 242: /* Read environment variables. */
1.30 nicm 243: if ((cp = getenv("HOME")) != NULL)
1.25 nicm 244: vsetstr(HOME, cp);
1.30 nicm 245: else {
246: pw = getpwuid(getuid());
247: if (pw != NULL && pw->pw_dir != NULL)
248: vsetstr(HOME, pw->pw_dir);
249: else
250: vsetstr(HOME, "/");
251: }
252: if ((cp = getenv("SHELL")) != NULL)
1.25 nicm 253: vsetstr(SHELL, cp);
1.30 nicm 254: else
255: vsetstr(SHELL, _PATH_BSHELL);
256:
257: /* Clear the table and set the defaults. */
258: for (vp = vtable; vp->v_name != NULL; vp++) {
259: vp->v_string = NULL;
260: vp->v_number = 0;
261: }
262: vsetnum(BEAUTIFY, 1);
263: vsetnum(ESCAPE, '~');
264: vsetnum(FORCE, CTRL('p'));
265: vsetnum(PROMPT, '\n');
266: vsetnum(TAND, 1);
267: vsetnum(VERBOSE, 1);
268: vsetstr(LOG, _PATH_ACULOG);
1.23 nicm 269:
270: /* Read the .tiprc file in the HOME directory. */
1.25 nicm 271: written = snprintf(file, sizeof(file), "%s/.tiprc", vgetstr(HOME));
1.16 moritz 272: if (written < 0 || written >= sizeof(file)) {
1.4 millert 273: (void)fprintf(stderr, "Home directory path too long: %s\n",
1.25 nicm 274: vgetstr(HOME));
1.3 millert 275: } else {
1.11 deraadt 276: if ((fp = fopen(file, "r")) != NULL) {
1.7 millert 277: char *tp;
1.3 millert 278:
1.15 ray 279: while (fgets(file, sizeof(file), fp) != NULL) {
1.3 millert 280: if (vflag)
281: printf("set %s", file);
1.5 deraadt 282: if ((tp = strrchr(file, '\n')))
1.3 millert 283: *tp = '\0';
284: vlex(file);
285: }
1.11 deraadt 286: fclose(fp);
1.1 deraadt 287: }
288: }
289: }
290:
1.5 deraadt 291: void
1.11 deraadt 292: vlex(char *s)
1.1 deraadt 293: {
1.11 deraadt 294: char *cp;
1.1 deraadt 295:
1.31 nicm 296: if (strcmp(s, "all") == 0)
297: vprintall();
298: else {
1.1 deraadt 299: do {
1.5 deraadt 300: if ((cp = vinterp(s, ' ')))
1.1 deraadt 301: cp++;
302: vtoken(s);
303: s = cp;
304: } while (s);
305: }
306: }
307:
1.29 nicm 308: /* Set a variable from a token. */
1.1 deraadt 309: static void
1.11 deraadt 310: vtoken(char *s)
1.1 deraadt 311: {
1.29 nicm 312: value_t *vp;
313: int i, value;
314: char *cp;
315: const char *cause;
1.1 deraadt 316:
1.5 deraadt 317: if ((cp = strchr(s, '='))) {
1.1 deraadt 318: *cp = '\0';
1.29 nicm 319: if ((i = vlookup(s)) != -1) {
320: vp = &vtable[i];
321: if (vp->v_flags & V_READONLY) {
322: printf("access denied\r\n");
323: return;
324: }
1.1 deraadt 325: cp++;
1.29 nicm 326: switch (vp->v_flags & V_TYPEMASK) {
327: case V_STRING:
328: vsetstr(i, cp);
329: break;
330: case V_BOOL:
331: vsetnum(i, 1);
332: break;
333: case V_NUMBER:
334: value = strtonum(cp, 0, INT_MAX, &cause);
335: if (cause != NULL) {
336: printf("%s: number %s\r\n", s, cause);
337: return;
338: }
339: vsetnum(i, value);
340: break;
341: case V_CHAR:
342: if (cp[0] != '\0' && cp[1] != '\0') {
343: printf("%s: character too big\r\n", s);
344: return;
345: }
346: vsetnum(i, *cp);
1.1 deraadt 347: }
1.29 nicm 348: vp->v_flags |= V_CHANGED;
1.1 deraadt 349: return;
350: }
1.5 deraadt 351: } else if ((cp = strchr(s, '?'))) {
1.1 deraadt 352: *cp = '\0';
1.29 nicm 353: if ((i = vlookup(s)) != -1) {
1.31 nicm 354: if (vprint(&vtable[i]) > 0)
355: printf("\r\n");
1.1 deraadt 356: return;
357: }
358: } else {
359: if (*s != '!')
1.29 nicm 360: i = vlookup(s);
1.1 deraadt 361: else
1.29 nicm 362: i = vlookup(s + 1);
363: if (i != -1) {
364: vp = &vtable[i];
365: if (vp->v_flags & V_READONLY) {
366: printf("%s: access denied\r\n", s);
367: return;
368: }
369: if ((vp->v_flags & V_TYPEMASK) != V_BOOL) {
370: printf("%s: not a boolean\r\n", s);
371: return;
372: }
373: vsetnum(i, *s != '!');
374: vp->v_flags |= V_CHANGED;
1.1 deraadt 375: return;
376: }
377: }
378: printf("%s: unknown variable\r\n", s);
379: }
380:
1.13 moritz 381: static char *
1.11 deraadt 382: vinterp(char *s, int stop)
1.1 deraadt 383: {
1.7 millert 384: char *p = s, c;
1.1 deraadt 385: int num;
386:
1.11 deraadt 387: while ((c = *s++) && c != stop) {
1.1 deraadt 388: switch (c) {
389:
390: case '^':
391: if (*s)
392: *p++ = *s++ - 0100;
393: else
394: *p++ = c;
395: break;
396:
397: case '\\':
398: num = 0;
399: c = *s++;
400: if (c >= '0' && c <= '7')
401: num = (num<<3)+(c-'0');
402: else {
1.7 millert 403: char *q = "n\nr\rt\tb\bf\f";
1.1 deraadt 404:
405: for (; *q; q++)
406: if (c == *q++) {
407: *p++ = *q;
408: goto cont;
409: }
410: *p++ = c;
411: cont:
412: break;
413: }
414: if ((c = *s++) >= '0' && c <= '7') {
415: num = (num<<3)+(c-'0');
416: if ((c = *s++) >= '0' && c <= '7')
417: num = (num<<3)+(c-'0');
418: else
419: s--;
420: } else
421: s--;
422: *p++ = num;
423: break;
424:
425: default:
426: *p++ = c;
427: }
1.11 deraadt 428: }
1.1 deraadt 429: *p = '\0';
430: return (c == stop ? s-1 : NULL);
431: }