value.c revision 113163
11553Srgrimes/*	$OpenBSD: value.c,v 1.7 2001/10/24 18:38:58 millert Exp $	*/
21553Srgrimes/*	$NetBSD: value.c,v 1.6 1997/02/11 09:24:09 mrg Exp $	*/
31553Srgrimes
41553Srgrimes/*
51553Srgrimes * Copyright (c) 1983, 1993
61553Srgrimes *	The Regents of the University of California.  All rights reserved.
71553Srgrimes *
81553Srgrimes * Redistribution and use in source and binary forms, with or without
91553Srgrimes * modification, are permitted provided that the following conditions
101553Srgrimes * are met:
111553Srgrimes * 1. Redistributions of source code must retain the above copyright
121553Srgrimes *    notice, this list of conditions and the following disclaimer.
131553Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
141553Srgrimes *    notice, this list of conditions and the following disclaimer in the
151553Srgrimes *    documentation and/or other materials provided with the distribution.
161553Srgrimes * 3. All advertising materials mentioning features or use of this software
171553Srgrimes *    must display the following acknowledgement:
181553Srgrimes *	This product includes software developed by the University of
191553Srgrimes *	California, Berkeley and its contributors.
201553Srgrimes * 4. Neither the name of the University nor the names of its contributors
211553Srgrimes *    may be used to endorse or promote products derived from this software
221553Srgrimes *    without specific prior written permission.
231553Srgrimes *
241553Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
251553Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
261553Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
271553Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
281553Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
291553Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
301553Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
311553Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
321553Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
331553Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
341553Srgrimes * SUCH DAMAGE.
351553Srgrimes */
361553Srgrimes
371553Srgrimes#include <sys/cdefs.h>
381553Srgrimes__FBSDID("$FreeBSD: head/usr.bin/tip/tip/value.c 113163 2003-04-06 08:30:25Z imp $");
391553Srgrimes
401553Srgrimes#ifndef lint
411553Srgrimes#if 0
421553Srgrimesstatic char sccsid[] = "@(#)value.c	8.1 (Berkeley) 6/6/93";
431553Srgrimesstatic char rcsid[] = "$OpenBSD: value.c,v 1.7 2001/10/24 18:38:58 millert Exp $";
441553Srgrimes#endif
451553Srgrimes#endif /* not lint */
461553Srgrimes
471553Srgrimes#include "tip.h"
481553Srgrimes
491553Srgrimes#define MIDDLE	35
501553Srgrimes
511553Srgrimesstatic value_t *vlookup();
521553Srgrimesstatic int col = 0;
531553Srgrimes
541553Srgrimes/*
551553Srgrimes * Variable manipulation
561553Srgrimes */
571553Srgrimesvoid
581553Srgrimesvinit()
591553Srgrimes{
601553Srgrimes	value_t *p;
611553Srgrimes	char *cp;
621553Srgrimes	FILE *f;
631553Srgrimes	char file[FILENAME_MAX];
641553Srgrimes
651553Srgrimes	for (p = vtable; p->v_name != NULL; p++) {
661553Srgrimes		if (p->v_type&ENVIRON)
671553Srgrimes			if ((cp = getenv(p->v_name)))
681553Srgrimes				p->v_value = cp;
691553Srgrimes		if (p->v_type&IREMOTE)
701553Srgrimes			setnumber(p->v_value, *address(p->v_value));
711553Srgrimes	}
721553Srgrimes	/*
731553Srgrimes	 * Read the .tiprc file in the HOME directory
741553Srgrimes	 *  for sets
751553Srgrimes	 */
761553Srgrimes	if (strlen(value(HOME)) + sizeof("/.tiprc") > sizeof(file)) {
771553Srgrimes		(void)fprintf(stderr, "Home directory path too long: %s\n",
781553Srgrimes			value(HOME));
791553Srgrimes	} else {
801553Srgrimes		snprintf(file, sizeof file, "%s/.tiprc", value(HOME));
811553Srgrimes		if ((f = fopen(file, "r")) != NULL) {
821553Srgrimes			char *tp;
831553Srgrimes
841553Srgrimes			while (fgets(file, sizeof(file)-1, f) != NULL) {
851553Srgrimes				if (vflag)
861553Srgrimes					printf("set %s", file);
871553Srgrimes				if ((tp = strrchr(file, '\n')))
8814961Smpp					*tp = '\0';
8914961Smpp				vlex(file);
901553Srgrimes			}
9114961Smpp			fclose(f);
921553Srgrimes		}
931553Srgrimes	}
941553Srgrimes	/*
951553Srgrimes	 * To allow definition of exception prior to fork
961553Srgrimes	 */
971553Srgrimes	vtable[EXCEPTIONS].v_access &= ~(WRITE<<PUBLIC);
981553Srgrimes}
991553Srgrimes
1001553Srgrimesstatic int vaccess();
1011553Srgrimes
1021553Srgrimes/*VARARGS1*/
1031553Srgrimesvoid
1041553Srgrimesvassign(p, v)
1051553Srgrimes	value_t *p;
1061553Srgrimes	char *v;
1071553Srgrimes{
1081553Srgrimes
1091553Srgrimes	if (!vaccess(p->v_access, WRITE)) {
1101553Srgrimes		printf("access denied\r\n");
1111553Srgrimes		return;
1121553Srgrimes	}
1131553Srgrimes	switch (p->v_type&TMASK) {
1141553Srgrimes
1151553Srgrimes	case STRING:
1161553Srgrimes		if (p->v_value && equal(p->v_value, v))
1171553Srgrimes			return;
1181553Srgrimes		if (!(p->v_type&(ENVIRON|INIT)))
1191553Srgrimes			free(p->v_value);
1201553Srgrimes		if ((p->v_value = strdup(v)) == NOSTR) {
1211553Srgrimes			printf("out of core\r\n");
1221553Srgrimes			return;
1231553Srgrimes		}
1241553Srgrimes		p->v_type &= ~(ENVIRON|INIT);
1251553Srgrimes		break;
1261553Srgrimes
1271553Srgrimes	case NUMBER:
1281553Srgrimes		if (number(p->v_value) == number(v))
1291553Srgrimes			return;
13014961Smpp		setnumber(p->v_value, number(v));
13114961Smpp		break;
13214961Smpp
13314961Smpp	case BOOL:
13414961Smpp		if (boolean(p->v_value) == (*v != '!'))
13514961Smpp			return;
13614961Smpp		setboolean(p->v_value, (*v != '!'));
13714961Smpp		break;
13814961Smpp
13914961Smpp	case CHAR:
14014961Smpp		if (character(p->v_value) == *v)
14114961Smpp			return;
14214961Smpp		setcharacter(p->v_value, *v);
14314961Smpp	}
14414961Smpp	p->v_access |= CHANGED;
14514961Smpp}
14614961Smpp
14714961Smppstatic void vprint();
14814961Smppstatic void vtoken();
1491553Srgrimes
1501553Srgrimesvoid
1511553Srgrimesvlex(s)
1521553Srgrimes	char *s;
1531553Srgrimes{
1541553Srgrimes	value_t *p;
1551553Srgrimes
1561553Srgrimes	if (equal(s, "all")) {
1571553Srgrimes		for (p = vtable; p->v_name; p++)
1581553Srgrimes			if (vaccess(p->v_access, READ))
1591553Srgrimes				vprint(p);
1601553Srgrimes	} else {
1614782Sache		char *cp;
1621553Srgrimes
1631553Srgrimes		do {
1641553Srgrimes			if ((cp = vinterp(s, ' ')))
1651553Srgrimes				cp++;
1661553Srgrimes			vtoken(s);
1671553Srgrimes			s = cp;
1681553Srgrimes		} while (s);
1691553Srgrimes	}
1701553Srgrimes	if (col > 0) {
1711553Srgrimes		printf("\r\n");
1724782Sache		col = 0;
1731553Srgrimes	}
1741553Srgrimes}
1751553Srgrimes
1761553Srgrimesstatic void
1771553Srgrimesvtoken(s)
1781553Srgrimes	char *s;
1791553Srgrimes{
1801553Srgrimes	value_t *p;
1811553Srgrimes	char *cp;
1821553Srgrimes	char *expand();
1831553Srgrimes
1841553Srgrimes	if ((cp = strchr(s, '='))) {
1851553Srgrimes		*cp = '\0';
1861553Srgrimes		if ((p = vlookup(s))) {
1871553Srgrimes			cp++;
1881553Srgrimes			if (p->v_type&NUMBER)
1891553Srgrimes				vassign(p, atoi(cp));
1901553Srgrimes			else {
1911553Srgrimes				if (strcmp(s, "record") == 0)
1921553Srgrimes					cp = expand(cp);
1931553Srgrimes				vassign(p, cp);
1941553Srgrimes			}
1951553Srgrimes			return;
1961553Srgrimes		}
1971553Srgrimes	} else if ((cp = strchr(s, '?'))) {
1981553Srgrimes		*cp = '\0';
1991553Srgrimes		if ((p = vlookup(s)) && vaccess(p->v_access, READ)) {
2001553Srgrimes			vprint(p);
2011553Srgrimes			return;
2021553Srgrimes		}
2031553Srgrimes	} else {
2041553Srgrimes		if (*s != '!')
2051553Srgrimes			p = vlookup(s);
2061553Srgrimes		else
2071553Srgrimes			p = vlookup(s+1);
2081553Srgrimes		if (p != NOVAL) {
2091553Srgrimes			vassign(p, s);
2101553Srgrimes			return;
2111553Srgrimes		}
2121553Srgrimes	}
2131553Srgrimes	printf("%s: unknown variable\r\n", s);
2141553Srgrimes}
2151553Srgrimes
2161553Srgrimesstatic void
2171553Srgrimesvprint(p)
2181553Srgrimes	value_t *p;
2191553Srgrimes{
2201553Srgrimes	char *cp;
2211553Srgrimes	extern char *interp();
2221553Srgrimes
2231553Srgrimes	if (col > 0 && col < MIDDLE)
2241553Srgrimes		while (col++ < MIDDLE)
2251553Srgrimes			putchar(' ');
2261553Srgrimes	col += size(p->v_name);
2271553Srgrimes	switch (p->v_type&TMASK) {
2281553Srgrimes
2291553Srgrimes	case BOOL:
2301553Srgrimes		if (boolean(p->v_value) == FALSE) {
2311553Srgrimes			col++;
2321553Srgrimes			putchar('!');
2331553Srgrimes		}
2341553Srgrimes		printf("%s", p->v_name);
2351553Srgrimes		break;
2361553Srgrimes
2371553Srgrimes	case STRING:
2381553Srgrimes		printf("%s=", p->v_name);
2391553Srgrimes		col++;
2401553Srgrimes		if (p->v_value) {
2411553Srgrimes			cp = interp(p->v_value, NULL);
2421553Srgrimes			col += size(cp);
2431553Srgrimes			printf("%s", cp);
2441553Srgrimes		}
2451553Srgrimes		break;
2461553Srgrimes
2471553Srgrimes	case NUMBER:
2481553Srgrimes		col += 6;
2491553Srgrimes		printf("%s=%-5ld", p->v_name, number(p->v_value));
2501553Srgrimes		break;
2511553Srgrimes
2521553Srgrimes	case CHAR:
2531553Srgrimes		printf("%s=", p->v_name);
2541553Srgrimes		col++;
2551553Srgrimes		if (p->v_value) {
2561553Srgrimes			cp = ctrl(character(p->v_value));
2571553Srgrimes			col += size(cp);
2581553Srgrimes			printf("%s", cp);
2591553Srgrimes		}
2601553Srgrimes		break;
2611553Srgrimes	}
2621553Srgrimes	if (col >= MIDDLE) {
2631553Srgrimes		col = 0;
2641553Srgrimes		printf("\r\n");
2651553Srgrimes		return;
2661553Srgrimes	}
2671553Srgrimes}
2681553Srgrimes
2691553Srgrimes
2701553Srgrimesstatic int
2711553Srgrimesvaccess(mode, rw)
2721553Srgrimes	unsigned mode, rw;
2731553Srgrimes{
2741553Srgrimes	if (mode & (rw<<PUBLIC))
2751553Srgrimes		return (1);
2761553Srgrimes	if (mode & (rw<<PRIVATE))
2771553Srgrimes		return (1);
2781553Srgrimes	return ((mode & (rw<<ROOT)) && getuid() == 0);
2791553Srgrimes}
2801553Srgrimes
2811553Srgrimesstatic value_t *
2821553Srgrimesvlookup(s)
2831553Srgrimes	char *s;
2841553Srgrimes{
2851553Srgrimes	value_t *p;
2861553Srgrimes
2871553Srgrimes	for (p = vtable; p->v_name; p++)
2881553Srgrimes		if (equal(p->v_name, s) || (p->v_abrev && equal(p->v_abrev, s)))
2891553Srgrimes			return (p);
2901553Srgrimes	return (NULL);
2911553Srgrimes}
2921553Srgrimes
2931553Srgrimeschar *
2941553Srgrimesvinterp(s, stop)
2951553Srgrimes	char *s;
2961553Srgrimes	char stop;
2971553Srgrimes{
2981553Srgrimes	char *p = s, c;
2991553Srgrimes	int num;
3001553Srgrimes
3011553Srgrimes	while ((c = *s++) && c != stop)
3021553Srgrimes		switch (c) {
3031553Srgrimes
3041553Srgrimes		case '^':
3051553Srgrimes			if (*s)
3061553Srgrimes				*p++ = *s++ - 0100;
3071553Srgrimes			else
3081553Srgrimes				*p++ = c;
3091553Srgrimes			break;
3101553Srgrimes
3111553Srgrimes		case '\\':
3121553Srgrimes			num = 0;
3131553Srgrimes			c = *s++;
3141553Srgrimes			if (c >= '0' && c <= '7')
3151553Srgrimes				num = (num<<3)+(c-'0');
3161553Srgrimes			else {
3171553Srgrimes				char *q = "n\nr\rt\tb\bf\f";
3181553Srgrimes
3191553Srgrimes				for (; *q; q++)
3201553Srgrimes					if (c == *q++) {
3211553Srgrimes						*p++ = *q;
3221553Srgrimes						goto cont;
3231553Srgrimes					}
3241553Srgrimes				*p++ = c;
3251553Srgrimes			cont:
3261553Srgrimes				break;
3271553Srgrimes			}
3281553Srgrimes			if ((c = *s++) >= '0' && c <= '7') {
3291553Srgrimes				num = (num<<3)+(c-'0');
3301553Srgrimes				if ((c = *s++) >= '0' && c <= '7')
3311553Srgrimes					num = (num<<3)+(c-'0');
3321553Srgrimes				else
3331553Srgrimes					s--;
3341553Srgrimes			} else
3351553Srgrimes				s--;
3361553Srgrimes			*p++ = num;
3371553Srgrimes			break;
3381553Srgrimes
3391553Srgrimes		default:
3401553Srgrimes			*p++ = c;
3411553Srgrimes		}
3421553Srgrimes	*p = '\0';
3431553Srgrimes	return (c == stop ? s-1 : NULL);
3441553Srgrimes}
3451553Srgrimes
3461553Srgrimes/*
3471553Srgrimes * assign variable s with value v (for NUMBER or STRING or CHAR types)
3481553Srgrimes */
3491553Srgrimesint
3501553Srgrimesvstring(s,v)
3511553Srgrimes	char *s;
3521553Srgrimes	char *v;
3531553Srgrimes{
3541553Srgrimes	value_t *p;
3551553Srgrimes	char *expand();
3561553Srgrimes
3571553Srgrimes	p = vlookup(s);
3581553Srgrimes	if (p == 0)
3591553Srgrimes		return (1);
3601553Srgrimes	if (p->v_type&NUMBER)
3611553Srgrimes		vassign(p, atoi(v));
3621553Srgrimes	else {
3631553Srgrimes		if (strcmp(s, "record") == 0)
3641553Srgrimes			v = expand(v);
3651553Srgrimes		vassign(p, v);
3661553Srgrimes	}
3671553Srgrimes	return (0);
3681553Srgrimes}
3691553Srgrimes