Annotation of src/usr.bin/tip/value.c, Revision 1.31
1.31 ! nicm 1: /* $OpenBSD: value.c,v 1.30 2010/07/02 07:40:03 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.7 millert 294: value_t *p;
1.11 deraadt 295: char *cp;
1.1 deraadt 296:
1.31 ! nicm 297: if (strcmp(s, "all") == 0)
! 298: vprintall();
! 299: else {
1.1 deraadt 300: do {
1.5 deraadt 301: if ((cp = vinterp(s, ' ')))
1.1 deraadt 302: cp++;
303: vtoken(s);
304: s = cp;
305: } while (s);
306: }
307: }
308:
1.29 nicm 309: /* Set a variable from a token. */
1.1 deraadt 310: static void
1.11 deraadt 311: vtoken(char *s)
1.1 deraadt 312: {
1.29 nicm 313: value_t *vp;
314: int i, value;
315: char *cp;
316: const char *cause;
1.1 deraadt 317:
1.5 deraadt 318: if ((cp = strchr(s, '='))) {
1.1 deraadt 319: *cp = '\0';
1.29 nicm 320: if ((i = vlookup(s)) != -1) {
321: vp = &vtable[i];
322: if (vp->v_flags & V_READONLY) {
323: printf("access denied\r\n");
324: return;
325: }
1.1 deraadt 326: cp++;
1.29 nicm 327: switch (vp->v_flags & V_TYPEMASK) {
328: case V_STRING:
329: vsetstr(i, cp);
330: break;
331: case V_BOOL:
332: vsetnum(i, 1);
333: break;
334: case V_NUMBER:
335: value = strtonum(cp, 0, INT_MAX, &cause);
336: if (cause != NULL) {
337: printf("%s: number %s\r\n", s, cause);
338: return;
339: }
340: vsetnum(i, value);
341: break;
342: case V_CHAR:
343: if (cp[0] != '\0' && cp[1] != '\0') {
344: printf("%s: character too big\r\n", s);
345: return;
346: }
347: vsetnum(i, *cp);
1.1 deraadt 348: }
1.29 nicm 349: vp->v_flags |= V_CHANGED;
1.1 deraadt 350: return;
351: }
1.5 deraadt 352: } else if ((cp = strchr(s, '?'))) {
1.1 deraadt 353: *cp = '\0';
1.29 nicm 354: if ((i = vlookup(s)) != -1) {
1.31 ! nicm 355: if (vprint(&vtable[i]) > 0)
! 356: printf("\r\n");
1.1 deraadt 357: return;
358: }
359: } else {
360: if (*s != '!')
1.29 nicm 361: i = vlookup(s);
1.1 deraadt 362: else
1.29 nicm 363: i = vlookup(s + 1);
364: if (i != -1) {
365: vp = &vtable[i];
366: if (vp->v_flags & V_READONLY) {
367: printf("%s: access denied\r\n", s);
368: return;
369: }
370: if ((vp->v_flags & V_TYPEMASK) != V_BOOL) {
371: printf("%s: not a boolean\r\n", s);
372: return;
373: }
374: vsetnum(i, *s != '!');
375: vp->v_flags |= V_CHANGED;
1.1 deraadt 376: return;
377: }
378: }
379: printf("%s: unknown variable\r\n", s);
380: }
381:
1.13 moritz 382: static char *
1.11 deraadt 383: vinterp(char *s, int stop)
1.1 deraadt 384: {
1.7 millert 385: char *p = s, c;
1.1 deraadt 386: int num;
387:
1.11 deraadt 388: while ((c = *s++) && c != stop) {
1.1 deraadt 389: switch (c) {
390:
391: case '^':
392: if (*s)
393: *p++ = *s++ - 0100;
394: else
395: *p++ = c;
396: break;
397:
398: case '\\':
399: num = 0;
400: c = *s++;
401: if (c >= '0' && c <= '7')
402: num = (num<<3)+(c-'0');
403: else {
1.7 millert 404: char *q = "n\nr\rt\tb\bf\f";
1.1 deraadt 405:
406: for (; *q; q++)
407: if (c == *q++) {
408: *p++ = *q;
409: goto cont;
410: }
411: *p++ = c;
412: cont:
413: break;
414: }
415: if ((c = *s++) >= '0' && c <= '7') {
416: num = (num<<3)+(c-'0');
417: if ((c = *s++) >= '0' && c <= '7')
418: num = (num<<3)+(c-'0');
419: else
420: s--;
421: } else
422: s--;
423: *p++ = num;
424: break;
425:
426: default:
427: *p++ = c;
428: }
1.11 deraadt 429: }
1.1 deraadt 430: *p = '\0';
431: return (c == stop ? s-1 : NULL);
432: }