value.c revision 129004
188276Smarkm/*	$OpenBSD: value.c,v 1.7 2001/10/24 18:38:58 millert Exp $	*/
288276Smarkm/*	$NetBSD: value.c,v 1.6 1997/02/11 09:24:09 mrg Exp $	*/
388276Smarkm
47527Sjkh/*
57527Sjkh * Copyright (c) 1983, 1993
67527Sjkh *	The Regents of the University of California.  All rights reserved.
77527Sjkh *
87527Sjkh * Redistribution and use in source and binary forms, with or without
97527Sjkh * modification, are permitted provided that the following conditions
107527Sjkh * are met:
117527Sjkh * 1. Redistributions of source code must retain the above copyright
127527Sjkh *    notice, this list of conditions and the following disclaimer.
137527Sjkh * 2. Redistributions in binary form must reproduce the above copyright
147527Sjkh *    notice, this list of conditions and the following disclaimer in the
157527Sjkh *    documentation and/or other materials provided with the distribution.
167527Sjkh * 3. All advertising materials mentioning features or use of this software
177527Sjkh *    must display the following acknowledgement:
187527Sjkh *	This product includes software developed by the University of
197527Sjkh *	California, Berkeley and its contributors.
207527Sjkh * 4. Neither the name of the University nor the names of its contributors
217527Sjkh *    may be used to endorse or promote products derived from this software
227527Sjkh *    without specific prior written permission.
237527Sjkh *
247527Sjkh * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
257527Sjkh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
267527Sjkh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
277527Sjkh * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
287527Sjkh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
297527Sjkh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
307527Sjkh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
317527Sjkh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
327527Sjkh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
337527Sjkh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
347527Sjkh * SUCH DAMAGE.
357527Sjkh */
367527Sjkh
3788276Smarkm#include <sys/cdefs.h>
3888276Smarkm__FBSDID("$FreeBSD: head/usr.bin/tip/tip/value.c 129004 2004-05-06 13:25:09Z stefanf $");
3988276Smarkm
407527Sjkh#ifndef lint
4128365Scharnier#if 0
427527Sjkhstatic char sccsid[] = "@(#)value.c	8.1 (Berkeley) 6/6/93";
4388276Smarkmstatic char rcsid[] = "$OpenBSD: value.c,v 1.7 2001/10/24 18:38:58 millert Exp $";
4428365Scharnier#endif
457527Sjkh#endif /* not lint */
467527Sjkh
477527Sjkh#include "tip.h"
487527Sjkh
497527Sjkh#define MIDDLE	35
507527Sjkh
517527Sjkhstatic value_t *vlookup();
527527Sjkhstatic int col = 0;
537527Sjkh
547527Sjkh/*
557527Sjkh * Variable manipulation
567527Sjkh */
5728365Scharniervoid
587527Sjkhvinit()
597527Sjkh{
6088276Smarkm	value_t *p;
6188276Smarkm	char *cp;
627527Sjkh	FILE *f;
6388276Smarkm	char file[FILENAME_MAX];
647527Sjkh
657527Sjkh	for (p = vtable; p->v_name != NULL; p++) {
667527Sjkh		if (p->v_type&ENVIRON)
6728365Scharnier			if ((cp = getenv(p->v_name)))
687527Sjkh				p->v_value = cp;
697527Sjkh		if (p->v_type&IREMOTE)
7088276Smarkm			setnumber(p->v_value, *address(p->v_value));
717527Sjkh	}
727527Sjkh	/*
737527Sjkh	 * Read the .tiprc file in the HOME directory
747527Sjkh	 *  for sets
757527Sjkh	 */
7688276Smarkm	if (strlen(value(HOME)) + sizeof("/.tiprc") > sizeof(file)) {
7788276Smarkm		(void)fprintf(stderr, "Home directory path too long: %s\n",
7888276Smarkm			value(HOME));
7988276Smarkm	} else {
8088276Smarkm		snprintf(file, sizeof file, "%s/.tiprc", value(HOME));
8188276Smarkm		if ((f = fopen(file, "r")) != NULL) {
8288276Smarkm			char *tp;
837527Sjkh
8488276Smarkm			while (fgets(file, sizeof(file)-1, f) != NULL) {
8588276Smarkm				if (vflag)
8688276Smarkm					printf("set %s", file);
8788276Smarkm				if ((tp = strrchr(file, '\n')))
8888276Smarkm					*tp = '\0';
8988276Smarkm				vlex(file);
9088276Smarkm			}
9188276Smarkm			fclose(f);
927527Sjkh		}
937527Sjkh	}
947527Sjkh	/*
957527Sjkh	 * To allow definition of exception prior to fork
967527Sjkh	 */
977527Sjkh	vtable[EXCEPTIONS].v_access &= ~(WRITE<<PUBLIC);
987527Sjkh}
997527Sjkh
1007527Sjkhstatic int vaccess();
1017527Sjkh
1027527Sjkh/*VARARGS1*/
10328365Scharniervoid
1047527Sjkhvassign(p, v)
10588276Smarkm	value_t *p;
1067527Sjkh	char *v;
1077527Sjkh{
1087527Sjkh
1097527Sjkh	if (!vaccess(p->v_access, WRITE)) {
1107527Sjkh		printf("access denied\r\n");
1117527Sjkh		return;
1127527Sjkh	}
1137527Sjkh	switch (p->v_type&TMASK) {
1147527Sjkh
1157527Sjkh	case STRING:
1167527Sjkh		if (p->v_value && equal(p->v_value, v))
1177527Sjkh			return;
1187527Sjkh		if (!(p->v_type&(ENVIRON|INIT)))
1197527Sjkh			free(p->v_value);
12088276Smarkm		if ((p->v_value = strdup(v)) == NOSTR) {
1217527Sjkh			printf("out of core\r\n");
1227527Sjkh			return;
1237527Sjkh		}
1247527Sjkh		p->v_type &= ~(ENVIRON|INIT);
1257527Sjkh		break;
1267527Sjkh
1277527Sjkh	case NUMBER:
1287527Sjkh		if (number(p->v_value) == number(v))
1297527Sjkh			return;
13088276Smarkm		setnumber(p->v_value, number(v));
1317527Sjkh		break;
1327527Sjkh
1337527Sjkh	case BOOL:
1347527Sjkh		if (boolean(p->v_value) == (*v != '!'))
1357527Sjkh			return;
13688276Smarkm		setboolean(p->v_value, (*v != '!'));
1377527Sjkh		break;
1387527Sjkh
1397527Sjkh	case CHAR:
1407527Sjkh		if (character(p->v_value) == *v)
1417527Sjkh			return;
14288276Smarkm		setcharacter(p->v_value, *v);
1437527Sjkh	}
1447527Sjkh	p->v_access |= CHANGED;
1457527Sjkh}
1467527Sjkh
1477527Sjkhstatic void vprint();
14888276Smarkmstatic void vtoken();
1497527Sjkh
15028365Scharniervoid
1517527Sjkhvlex(s)
15288276Smarkm	char *s;
1537527Sjkh{
15488276Smarkm	value_t *p;
1557527Sjkh
1567527Sjkh	if (equal(s, "all")) {
1577527Sjkh		for (p = vtable; p->v_name; p++)
1587527Sjkh			if (vaccess(p->v_access, READ))
1597527Sjkh				vprint(p);
1607527Sjkh	} else {
16188276Smarkm		char *cp;
1627527Sjkh
1637527Sjkh		do {
16428365Scharnier			if ((cp = vinterp(s, ' ')))
1657527Sjkh				cp++;
1667527Sjkh			vtoken(s);
1677527Sjkh			s = cp;
1687527Sjkh		} while (s);
1697527Sjkh	}
1707527Sjkh	if (col > 0) {
1717527Sjkh		printf("\r\n");
1727527Sjkh		col = 0;
1737527Sjkh	}
1747527Sjkh}
1757527Sjkh
1767527Sjkhstatic void
1777527Sjkhvtoken(s)
17888276Smarkm	char *s;
1797527Sjkh{
18088276Smarkm	value_t *p;
18188276Smarkm	char *cp;
1827527Sjkh	char *expand();
1837527Sjkh
18488276Smarkm	if ((cp = strchr(s, '='))) {
1857527Sjkh		*cp = '\0';
18628365Scharnier		if ((p = vlookup(s))) {
1877527Sjkh			cp++;
1887527Sjkh			if (p->v_type&NUMBER)
18988276Smarkm				vassign(p, atoi(cp));
1907527Sjkh			else {
1917527Sjkh				if (strcmp(s, "record") == 0)
1927527Sjkh					cp = expand(cp);
1937527Sjkh				vassign(p, cp);
1947527Sjkh			}
1957527Sjkh			return;
1967527Sjkh		}
19788276Smarkm	} else if ((cp = strchr(s, '?'))) {
1987527Sjkh		*cp = '\0';
1997527Sjkh		if ((p = vlookup(s)) && vaccess(p->v_access, READ)) {
2007527Sjkh			vprint(p);
2017527Sjkh			return;
2027527Sjkh		}
2037527Sjkh	} else {
2047527Sjkh		if (*s != '!')
2057527Sjkh			p = vlookup(s);
2067527Sjkh		else
2077527Sjkh			p = vlookup(s+1);
2087527Sjkh		if (p != NOVAL) {
2097527Sjkh			vassign(p, s);
2107527Sjkh			return;
2117527Sjkh		}
2127527Sjkh	}
2137527Sjkh	printf("%s: unknown variable\r\n", s);
2147527Sjkh}
2157527Sjkh
2167527Sjkhstatic void
2177527Sjkhvprint(p)
21888276Smarkm	value_t *p;
2197527Sjkh{
22088276Smarkm	char *cp;
2217527Sjkh
2227527Sjkh	if (col > 0 && col < MIDDLE)
2237527Sjkh		while (col++ < MIDDLE)
2247527Sjkh			putchar(' ');
2257527Sjkh	col += size(p->v_name);
2267527Sjkh	switch (p->v_type&TMASK) {
2277527Sjkh
2287527Sjkh	case BOOL:
2297527Sjkh		if (boolean(p->v_value) == FALSE) {
2307527Sjkh			col++;
2317527Sjkh			putchar('!');
2327527Sjkh		}
2337527Sjkh		printf("%s", p->v_name);
2347527Sjkh		break;
2357527Sjkh
2367527Sjkh	case STRING:
2377527Sjkh		printf("%s=", p->v_name);
2387527Sjkh		col++;
2397527Sjkh		if (p->v_value) {
240129004Sstefanf			cp = interp(p->v_value);
2417527Sjkh			col += size(cp);
2427527Sjkh			printf("%s", cp);
2437527Sjkh		}
2447527Sjkh		break;
2457527Sjkh
2467527Sjkh	case NUMBER:
2477527Sjkh		col += 6;
24888276Smarkm		printf("%s=%-5ld", p->v_name, number(p->v_value));
2497527Sjkh		break;
2507527Sjkh
2517527Sjkh	case CHAR:
2527527Sjkh		printf("%s=", p->v_name);
2537527Sjkh		col++;
2547527Sjkh		if (p->v_value) {
2557527Sjkh			cp = ctrl(character(p->v_value));
2567527Sjkh			col += size(cp);
2577527Sjkh			printf("%s", cp);
2587527Sjkh		}
2597527Sjkh		break;
2607527Sjkh	}
2617527Sjkh	if (col >= MIDDLE) {
2627527Sjkh		col = 0;
2637527Sjkh		printf("\r\n");
2647527Sjkh		return;
2657527Sjkh	}
2667527Sjkh}
2677527Sjkh
2687527Sjkh
2697527Sjkhstatic int
2707527Sjkhvaccess(mode, rw)
27188276Smarkm	unsigned mode, rw;
2727527Sjkh{
2737527Sjkh	if (mode & (rw<<PUBLIC))
2747527Sjkh		return (1);
2757527Sjkh	if (mode & (rw<<PRIVATE))
2767527Sjkh		return (1);
2777527Sjkh	return ((mode & (rw<<ROOT)) && getuid() == 0);
2787527Sjkh}
2797527Sjkh
2807527Sjkhstatic value_t *
2817527Sjkhvlookup(s)
28288276Smarkm	char *s;
2837527Sjkh{
28488276Smarkm	value_t *p;
2857527Sjkh
2867527Sjkh	for (p = vtable; p->v_name; p++)
2877527Sjkh		if (equal(p->v_name, s) || (p->v_abrev && equal(p->v_abrev, s)))
2887527Sjkh			return (p);
2897527Sjkh	return (NULL);
2907527Sjkh}
2917527Sjkh
2927527Sjkhchar *
2937527Sjkhvinterp(s, stop)
29488276Smarkm	char *s;
2957527Sjkh	char stop;
2967527Sjkh{
29788276Smarkm	char *p = s, c;
2987527Sjkh	int num;
2997527Sjkh
3007527Sjkh	while ((c = *s++) && c != stop)
3017527Sjkh		switch (c) {
3027527Sjkh
3037527Sjkh		case '^':
3047527Sjkh			if (*s)
3057527Sjkh				*p++ = *s++ - 0100;
3067527Sjkh			else
3077527Sjkh				*p++ = c;
3087527Sjkh			break;
3097527Sjkh
3107527Sjkh		case '\\':
3117527Sjkh			num = 0;
3127527Sjkh			c = *s++;
3137527Sjkh			if (c >= '0' && c <= '7')
3147527Sjkh				num = (num<<3)+(c-'0');
3157527Sjkh			else {
31688276Smarkm				char *q = "n\nr\rt\tb\bf\f";
3177527Sjkh
3187527Sjkh				for (; *q; q++)
3197527Sjkh					if (c == *q++) {
3207527Sjkh						*p++ = *q;
3217527Sjkh						goto cont;
3227527Sjkh					}
3237527Sjkh				*p++ = c;
3247527Sjkh			cont:
3257527Sjkh				break;
3267527Sjkh			}
3277527Sjkh			if ((c = *s++) >= '0' && c <= '7') {
3287527Sjkh				num = (num<<3)+(c-'0');
3297527Sjkh				if ((c = *s++) >= '0' && c <= '7')
3307527Sjkh					num = (num<<3)+(c-'0');
3317527Sjkh				else
3327527Sjkh					s--;
3337527Sjkh			} else
3347527Sjkh				s--;
3357527Sjkh			*p++ = num;
3367527Sjkh			break;
3377527Sjkh
3387527Sjkh		default:
3397527Sjkh			*p++ = c;
3407527Sjkh		}
3417527Sjkh	*p = '\0';
3427527Sjkh	return (c == stop ? s-1 : NULL);
3437527Sjkh}
3447527Sjkh
3457527Sjkh/*
3467527Sjkh * assign variable s with value v (for NUMBER or STRING or CHAR types)
3477527Sjkh */
34828365Scharnierint
3497527Sjkhvstring(s,v)
35088276Smarkm	char *s;
35188276Smarkm	char *v;
3527527Sjkh{
35388276Smarkm	value_t *p;
3547527Sjkh	char *expand();
3557527Sjkh
35688276Smarkm	p = vlookup(s);
3577527Sjkh	if (p == 0)
3587527Sjkh		return (1);
3597527Sjkh	if (p->v_type&NUMBER)
36088276Smarkm		vassign(p, atoi(v));
3617527Sjkh	else {
3627527Sjkh		if (strcmp(s, "record") == 0)
3637527Sjkh			v = expand(v);
3647527Sjkh		vassign(p, v);
3657527Sjkh	}
3667527Sjkh	return (0);
3677527Sjkh}
368