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