1161754Sru/*	$OpenBSD: value.c,v 1.14 2006/03/17 22:02:58 moritz Exp $	*/
288276Smarkm/*	$NetBSD: value.c,v 1.6 1997/02/11 09:24:09 mrg Exp $	*/
388276Smarkm
4331722Seadler/*
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.
16161754Sru * 3. Neither the name of the University nor the names of its contributors
177527Sjkh *    may be used to endorse or promote products derived from this software
187527Sjkh *    without specific prior written permission.
197527Sjkh *
207527Sjkh * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
217527Sjkh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
227527Sjkh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
237527Sjkh * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
247527Sjkh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
257527Sjkh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
267527Sjkh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
277527Sjkh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
287527Sjkh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
297527Sjkh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
307527Sjkh * SUCH DAMAGE.
317527Sjkh */
327527Sjkh
3388276Smarkm#include <sys/cdefs.h>
3488276Smarkm__FBSDID("$FreeBSD$");
3588276Smarkm
367527Sjkh#ifndef lint
3728365Scharnier#if 0
387527Sjkhstatic char sccsid[] = "@(#)value.c	8.1 (Berkeley) 6/6/93";
39161754Srustatic const char rcsid[] = "$OpenBSD: value.c,v 1.14 2006/03/17 22:02:58 moritz Exp $";
4028365Scharnier#endif
417527Sjkh#endif /* not lint */
427527Sjkh
437527Sjkh#include "tip.h"
447527Sjkh
457527Sjkh#define MIDDLE	35
467527Sjkh
47161754Srustatic value_t *vlookup(char *);
48161754Srustatic void vassign(value_t *, char *);
49161754Srustatic void vtoken(char *);
50161754Srustatic void vprint(value_t *);
51161754Srustatic int vaccess(unsigned int, unsigned int);
52161754Srustatic char *vinterp(char *, int);
537527Sjkh
54161754Srustatic size_t col = 0;
55161754Sru
567527Sjkh/*
577527Sjkh * Variable manipulation
587527Sjkh */
5928365Scharniervoid
60161754Sruvinit(void)
617527Sjkh{
62161754Sru	char file[FILENAME_MAX], *cp;
6388276Smarkm	value_t *p;
64161754Sru	FILE *fp;
657527Sjkh
667527Sjkh	for (p = vtable; p->v_name != NULL; p++) {
677527Sjkh		if (p->v_type&ENVIRON)
6828365Scharnier			if ((cp = getenv(p->v_name)))
697527Sjkh				p->v_value = cp;
707527Sjkh		if (p->v_type&IREMOTE)
7188276Smarkm			setnumber(p->v_value, *address(p->v_value));
727527Sjkh	}
737527Sjkh	/*
747527Sjkh	 * Read the .tiprc file in the HOME directory
757527Sjkh	 *  for sets
767527Sjkh	 */
77166911Sjls	cp = value(HOME);
78166911Sjls	if (cp == NULL) {
79166911Sjls		(void)fprintf(stderr,
80166911Sjls		    "$HOME not set. Skipping check for ~/.tiprc\n");
81166911Sjls	} else if (strlen(cp) + sizeof("/.tiprc") > sizeof(file)) {
8288276Smarkm		(void)fprintf(stderr, "Home directory path too long: %s\n",
83161754Sru		    value(HOME));
8488276Smarkm	} else {
8588276Smarkm		snprintf(file, sizeof file, "%s/.tiprc", value(HOME));
86161754Sru		if ((fp = fopen(file, "r")) != NULL) {
8788276Smarkm			char *tp;
887527Sjkh
89161754Sru			while (fgets(file, sizeof(file)-1, fp) != NULL) {
9088276Smarkm				if (vflag)
9188276Smarkm					printf("set %s", file);
9288276Smarkm				if ((tp = strrchr(file, '\n')))
9388276Smarkm					*tp = '\0';
9488276Smarkm				vlex(file);
9588276Smarkm			}
96161754Sru			fclose(fp);
977527Sjkh		}
987527Sjkh	}
997527Sjkh	/*
1007527Sjkh	 * To allow definition of exception prior to fork
1017527Sjkh	 */
1027527Sjkh	vtable[EXCEPTIONS].v_access &= ~(WRITE<<PUBLIC);
1037527Sjkh}
1047527Sjkh
1057527Sjkh/*VARARGS1*/
106161754Srustatic void
107161754Sruvassign(value_t *p, char *v)
1087527Sjkh{
1097527Sjkh	if (!vaccess(p->v_access, WRITE)) {
1107527Sjkh		printf("access denied\r\n");
1117527Sjkh		return;
1127527Sjkh	}
113161754Sru
1147527Sjkh	switch (p->v_type&TMASK) {
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	case NUMBER:
1277527Sjkh		if (number(p->v_value) == number(v))
1287527Sjkh			return;
12988276Smarkm		setnumber(p->v_value, number(v));
1307527Sjkh		break;
1317527Sjkh	case BOOL:
1327527Sjkh		if (boolean(p->v_value) == (*v != '!'))
1337527Sjkh			return;
13488276Smarkm		setboolean(p->v_value, (*v != '!'));
1357527Sjkh		break;
1367527Sjkh	case CHAR:
1377527Sjkh		if (character(p->v_value) == *v)
1387527Sjkh			return;
13988276Smarkm		setcharacter(p->v_value, *v);
1407527Sjkh	}
1417527Sjkh	p->v_access |= CHANGED;
1427527Sjkh}
1437527Sjkh
14428365Scharniervoid
145161754Sruvlex(char *s)
1467527Sjkh{
14788276Smarkm	value_t *p;
148161754Sru	char *cp;
1497527Sjkh
1507527Sjkh	if (equal(s, "all")) {
1517527Sjkh		for (p = vtable; p->v_name; p++)
1527527Sjkh			if (vaccess(p->v_access, READ))
1537527Sjkh				vprint(p);
1547527Sjkh	} else {
1557527Sjkh		do {
15628365Scharnier			if ((cp = vinterp(s, ' ')))
1577527Sjkh				cp++;
1587527Sjkh			vtoken(s);
1597527Sjkh			s = cp;
1607527Sjkh		} while (s);
1617527Sjkh	}
1627527Sjkh	if (col > 0) {
1637527Sjkh		printf("\r\n");
1647527Sjkh		col = 0;
1657527Sjkh	}
1667527Sjkh}
1677527Sjkh
1687527Sjkhstatic void
169161754Sruvtoken(char *s)
1707527Sjkh{
17188276Smarkm	value_t *p;
17288276Smarkm	char *cp;
1737527Sjkh
17488276Smarkm	if ((cp = strchr(s, '='))) {
1757527Sjkh		*cp = '\0';
17628365Scharnier		if ((p = vlookup(s))) {
1777527Sjkh			cp++;
1787527Sjkh			if (p->v_type&NUMBER)
179161781Sru				vassign(p, (char *)(intptr_t)atoi(cp));
1807527Sjkh			else {
1817527Sjkh				if (strcmp(s, "record") == 0)
1827527Sjkh					cp = expand(cp);
1837527Sjkh				vassign(p, cp);
1847527Sjkh			}
1857527Sjkh			return;
1867527Sjkh		}
18788276Smarkm	} else if ((cp = strchr(s, '?'))) {
1887527Sjkh		*cp = '\0';
1897527Sjkh		if ((p = vlookup(s)) && vaccess(p->v_access, READ)) {
1907527Sjkh			vprint(p);
1917527Sjkh			return;
1927527Sjkh		}
1937527Sjkh	} else {
1947527Sjkh		if (*s != '!')
1957527Sjkh			p = vlookup(s);
1967527Sjkh		else
1977527Sjkh			p = vlookup(s+1);
1987527Sjkh		if (p != NOVAL) {
1997527Sjkh			vassign(p, s);
2007527Sjkh			return;
2017527Sjkh		}
2027527Sjkh	}
2037527Sjkh	printf("%s: unknown variable\r\n", s);
2047527Sjkh}
2057527Sjkh
2067527Sjkhstatic void
207161754Sruvprint(value_t *p)
2087527Sjkh{
20988276Smarkm	char *cp;
2107527Sjkh
2117527Sjkh	if (col > 0 && col < MIDDLE)
2127527Sjkh		while (col++ < MIDDLE)
2137527Sjkh			putchar(' ');
2147527Sjkh	col += size(p->v_name);
2157527Sjkh	switch (p->v_type&TMASK) {
2167527Sjkh
2177527Sjkh	case BOOL:
2187527Sjkh		if (boolean(p->v_value) == FALSE) {
2197527Sjkh			col++;
2207527Sjkh			putchar('!');
2217527Sjkh		}
2227527Sjkh		printf("%s", p->v_name);
2237527Sjkh		break;
2247527Sjkh
2257527Sjkh	case STRING:
2267527Sjkh		printf("%s=", p->v_name);
2277527Sjkh		col++;
2287527Sjkh		if (p->v_value) {
229129004Sstefanf			cp = interp(p->v_value);
2307527Sjkh			col += size(cp);
2317527Sjkh			printf("%s", cp);
2327527Sjkh		}
2337527Sjkh		break;
2347527Sjkh
2357527Sjkh	case NUMBER:
2367527Sjkh		col += 6;
23788276Smarkm		printf("%s=%-5ld", p->v_name, number(p->v_value));
2387527Sjkh		break;
2397527Sjkh
2407527Sjkh	case CHAR:
2417527Sjkh		printf("%s=", p->v_name);
2427527Sjkh		col++;
2437527Sjkh		if (p->v_value) {
2447527Sjkh			cp = ctrl(character(p->v_value));
2457527Sjkh			col += size(cp);
2467527Sjkh			printf("%s", cp);
2477527Sjkh		}
2487527Sjkh		break;
2497527Sjkh	}
2507527Sjkh	if (col >= MIDDLE) {
2517527Sjkh		col = 0;
2527527Sjkh		printf("\r\n");
2537527Sjkh		return;
2547527Sjkh	}
2557527Sjkh}
2567527Sjkh
2577527Sjkhstatic int
258161754Sruvaccess(unsigned int mode, unsigned int rw)
2597527Sjkh{
2607527Sjkh	if (mode & (rw<<PUBLIC))
2617527Sjkh		return (1);
2627527Sjkh	if (mode & (rw<<PRIVATE))
2637527Sjkh		return (1);
2647527Sjkh	return ((mode & (rw<<ROOT)) && getuid() == 0);
2657527Sjkh}
2667527Sjkh
2677527Sjkhstatic value_t *
268161754Sruvlookup(char *s)
2697527Sjkh{
27088276Smarkm	value_t *p;
2717527Sjkh
2727527Sjkh	for (p = vtable; p->v_name; p++)
2737527Sjkh		if (equal(p->v_name, s) || (p->v_abrev && equal(p->v_abrev, s)))
2747527Sjkh			return (p);
2757527Sjkh	return (NULL);
2767527Sjkh}
2777527Sjkh
278161754Srustatic char *
279161754Sruvinterp(char *s, int stop)
2807527Sjkh{
28188276Smarkm	char *p = s, c;
2827527Sjkh	int num;
2837527Sjkh
284161754Sru	while ((c = *s++) && c != stop) {
2857527Sjkh		switch (c) {
2867527Sjkh
2877527Sjkh		case '^':
2887527Sjkh			if (*s)
2897527Sjkh				*p++ = *s++ - 0100;
2907527Sjkh			else
2917527Sjkh				*p++ = c;
2927527Sjkh			break;
2937527Sjkh
2947527Sjkh		case '\\':
2957527Sjkh			num = 0;
2967527Sjkh			c = *s++;
2977527Sjkh			if (c >= '0' && c <= '7')
2987527Sjkh				num = (num<<3)+(c-'0');
2997527Sjkh			else {
30088276Smarkm				char *q = "n\nr\rt\tb\bf\f";
3017527Sjkh
3027527Sjkh				for (; *q; q++)
3037527Sjkh					if (c == *q++) {
3047527Sjkh						*p++ = *q;
3057527Sjkh						goto cont;
3067527Sjkh					}
3077527Sjkh				*p++ = c;
3087527Sjkh			cont:
3097527Sjkh				break;
3107527Sjkh			}
3117527Sjkh			if ((c = *s++) >= '0' && c <= '7') {
3127527Sjkh				num = (num<<3)+(c-'0');
3137527Sjkh				if ((c = *s++) >= '0' && c <= '7')
3147527Sjkh					num = (num<<3)+(c-'0');
3157527Sjkh				else
3167527Sjkh					s--;
3177527Sjkh			} else
3187527Sjkh				s--;
3197527Sjkh			*p++ = num;
3207527Sjkh			break;
3217527Sjkh
3227527Sjkh		default:
3237527Sjkh			*p++ = c;
3247527Sjkh		}
325161754Sru	}
3267527Sjkh	*p = '\0';
3277527Sjkh	return (c == stop ? s-1 : NULL);
3287527Sjkh}
3297527Sjkh
3307527Sjkh/*
3317527Sjkh * assign variable s with value v (for NUMBER or STRING or CHAR types)
3327527Sjkh */
33328365Scharnierint
334161754Sruvstring(char *s, char *v)
3357527Sjkh{
33688276Smarkm	value_t *p;
3377527Sjkh
338161754Sru	p = vlookup(s);
3397527Sjkh	if (p == 0)
3407527Sjkh		return (1);
3417527Sjkh	if (p->v_type&NUMBER)
342161781Sru		vassign(p, (char *)(intptr_t)atoi(v));
3437527Sjkh	else {
3447527Sjkh		if (strcmp(s, "record") == 0)
3457527Sjkh			v = expand(v);
3467527Sjkh		vassign(p, v);
3477527Sjkh	}
3487527Sjkh	return (0);
3497527Sjkh}
350