xref: /netbsd-src/usr.bin/tip/value.c (revision a64eb75968122dac18b01ea6066d32418d7ac9fe)
1*a64eb759Schristos /*	$NetBSD: value.c,v 1.15 2013/10/21 14:47:46 christos Exp $	*/
239801cccSjtc 
361f28255Scgd /*
439801cccSjtc  * Copyright (c) 1983, 1993
539801cccSjtc  *	The Regents of the University of California.  All rights reserved.
661f28255Scgd  *
761f28255Scgd  * Redistribution and use in source and binary forms, with or without
861f28255Scgd  * modification, are permitted provided that the following conditions
961f28255Scgd  * are met:
1061f28255Scgd  * 1. Redistributions of source code must retain the above copyright
1161f28255Scgd  *    notice, this list of conditions and the following disclaimer.
1261f28255Scgd  * 2. Redistributions in binary form must reproduce the above copyright
1361f28255Scgd  *    notice, this list of conditions and the following disclaimer in the
1461f28255Scgd  *    documentation and/or other materials provided with the distribution.
1589aaa1bbSagc  * 3. Neither the name of the University nor the names of its contributors
1661f28255Scgd  *    may be used to endorse or promote products derived from this software
1761f28255Scgd  *    without specific prior written permission.
1861f28255Scgd  *
1961f28255Scgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2061f28255Scgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2161f28255Scgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2261f28255Scgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2361f28255Scgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2461f28255Scgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2561f28255Scgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2661f28255Scgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2761f28255Scgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2861f28255Scgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2961f28255Scgd  * SUCH DAMAGE.
3061f28255Scgd  */
3161f28255Scgd 
32e37283e1Slukem #include <sys/cdefs.h>
3361f28255Scgd #ifndef lint
3439801cccSjtc #if 0
3539801cccSjtc static char sccsid[] = "@(#)value.c	8.1 (Berkeley) 6/6/93";
3639801cccSjtc #endif
37*a64eb759Schristos __RCSID("$NetBSD: value.c,v 1.15 2013/10/21 14:47:46 christos Exp $");
3861f28255Scgd #endif /* not lint */
3961f28255Scgd 
4061f28255Scgd #include "tip.h"
4161f28255Scgd 
4261f28255Scgd #define MIDDLE	35
4361f28255Scgd 
4461f28255Scgd static int col = 0;
4561f28255Scgd 
46c4341bc3Schristos static	int	vaccess(int, int);
4758c2151fSperry static	void	vassign(value_t *, char *);
4858c2151fSperry static	value_t *vlookup(const char *);
4958c2151fSperry static	void	vprint(value_t *);
5058c2151fSperry static	void	vtoken(char *);
51e37283e1Slukem 
5261f28255Scgd /*
5361f28255Scgd  * Variable manipulation
5461f28255Scgd  */
55e37283e1Slukem void
vinit(void)5658c2151fSperry vinit(void)
5761f28255Scgd {
58e37283e1Slukem 	value_t *p;
59e37283e1Slukem 	char *cp;
6061f28255Scgd 	FILE *f;
61e37283e1Slukem 	char file[MAXPATHLEN];
6261f28255Scgd 
6361f28255Scgd 	for (p = vtable; p->v_name != NULL; p++) {
6461f28255Scgd 		if (p->v_type&ENVIRON)
65e37283e1Slukem 			if ((cp = getenv(p->v_name)) != NULL)
6661f28255Scgd 				p->v_value = cp;
6761f28255Scgd 		if (p->v_type&IREMOTE)
6888caf985Scgd 			setnumber(p->v_value, *address(p->v_value));
6961f28255Scgd 	}
7061f28255Scgd 	/*
7161f28255Scgd 	 * Read the .tiprc file in the HOME directory
7261f28255Scgd 	 *  for sets
7361f28255Scgd 	 */
74ffe34450Schristos 	(void)snprintf(file, sizeof(file), "%s/.tiprc", (char *)value(HOME));
7561f28255Scgd 	if ((f = fopen(file, "r")) != NULL) {
76e37283e1Slukem 		char *tp;
7761f28255Scgd 
7861f28255Scgd 		while (fgets(file, sizeof(file)-1, f) != NULL) {
7961f28255Scgd 			if (vflag)
80ffe34450Schristos 				(void)printf("set %s", file);
81e37283e1Slukem 			if ((tp = strrchr(file, '\n')) != NULL)
8261f28255Scgd 				*tp = '\0';
8361f28255Scgd 			vlex(file);
8461f28255Scgd 		}
85ffe34450Schristos 		(void)fclose(f);
8661f28255Scgd 	}
8761f28255Scgd 	/*
8861f28255Scgd 	 * To allow definition of exception prior to fork
8961f28255Scgd 	 */
9061f28255Scgd 	vtable[EXCEPTIONS].v_access &= ~(WRITE<<PUBLIC);
9161f28255Scgd }
9261f28255Scgd 
93e37283e1Slukem void
vassign(value_t * p,char * v)9458c2151fSperry vassign(value_t *p, char *v)
9561f28255Scgd {
9661f28255Scgd 
97c4341bc3Schristos 	if (!vaccess(p->v_access, (unsigned int)WRITE)) {
98ffe34450Schristos 		(void)printf("access denied\r\n");
9961f28255Scgd 		return;
10061f28255Scgd 	}
10161f28255Scgd 	switch (p->v_type&TMASK) {
10261f28255Scgd 
10361f28255Scgd 	case STRING:
104*a64eb759Schristos 		if (p->v_value && strcmp(p->v_value, v) == 0)
10561f28255Scgd 			return;
10661f28255Scgd 		if (!(p->v_type&(ENVIRON|INIT)))
10761f28255Scgd 			free(p->v_value);
108e37283e1Slukem 		if ((p->v_value = strdup(v)) == NULL) {
109ffe34450Schristos 			(void)printf("out of core\r\n");
11061f28255Scgd 			return;
11161f28255Scgd 		}
11261f28255Scgd 		p->v_type &= ~(ENVIRON|INIT);
11361f28255Scgd 		break;
11461f28255Scgd 
11561f28255Scgd 	case NUMBER:
11661f28255Scgd 		if (number(p->v_value) == number(v))
11761f28255Scgd 			return;
11888caf985Scgd 		setnumber(p->v_value, number(v));
11961f28255Scgd 		break;
12061f28255Scgd 
12161f28255Scgd 	case BOOL:
12261f28255Scgd 		if (boolean(p->v_value) == (*v != '!'))
12361f28255Scgd 			return;
12488caf985Scgd 		setboolean(p->v_value, (*v != '!'));
12561f28255Scgd 		break;
12661f28255Scgd 
12761f28255Scgd 	case CHAR:
12861f28255Scgd 		if (character(p->v_value) == *v)
12961f28255Scgd 			return;
13088caf985Scgd 		setcharacter(p->v_value, *v);
13161f28255Scgd 	}
13261f28255Scgd 	p->v_access |= CHANGED;
13361f28255Scgd }
13461f28255Scgd 
135e37283e1Slukem void
vlex(char * s)13658c2151fSperry vlex(char *s)
13761f28255Scgd {
138e37283e1Slukem 	value_t *p;
13961f28255Scgd 
140*a64eb759Schristos 	if (strcmp(s, "all") == 0) {
14161f28255Scgd 		for (p = vtable; p->v_name; p++)
14261f28255Scgd 			if (vaccess(p->v_access, READ))
14361f28255Scgd 				vprint(p);
14461f28255Scgd 	} else {
145e37283e1Slukem 		char *cp;
14661f28255Scgd 
14761f28255Scgd 		do {
148e37283e1Slukem 			if ((cp = vinterp(s, ' ')) != NULL)
14961f28255Scgd 				cp++;
15061f28255Scgd 			vtoken(s);
15161f28255Scgd 			s = cp;
15261f28255Scgd 		} while (s);
15361f28255Scgd 	}
15461f28255Scgd 	if (col > 0) {
155ffe34450Schristos 		(void)printf("\r\n");
15661f28255Scgd 		col = 0;
15761f28255Scgd 	}
15861f28255Scgd }
15961f28255Scgd 
16061f28255Scgd static void
vtoken(char * s)16158c2151fSperry vtoken(char *s)
16261f28255Scgd {
163e37283e1Slukem 	value_t *p;
164e37283e1Slukem 	char *cp;
16561f28255Scgd 
166e37283e1Slukem 	if ((cp = strchr(s, '=')) != NULL) {
16761f28255Scgd 		*cp = '\0';
168e37283e1Slukem 		if ((p = vlookup(s)) != NULL) {
16961f28255Scgd 			cp++;
17061f28255Scgd 			if (p->v_type&NUMBER)
17104abeda6Smrg 				vassign(p, (char *)(long)atoi(cp));
17261f28255Scgd 			else {
17361f28255Scgd 				if (strcmp(s, "record") == 0)
17461f28255Scgd 					cp = expand(cp);
17561f28255Scgd 				vassign(p, cp);
17661f28255Scgd 			}
17761f28255Scgd 			return;
17861f28255Scgd 		}
179e37283e1Slukem 	} else if ((cp = strchr(s, '?')) != NULL) {
18061f28255Scgd 		*cp = '\0';
18161f28255Scgd 		if ((p = vlookup(s)) && vaccess(p->v_access, READ)) {
18261f28255Scgd 			vprint(p);
18361f28255Scgd 			return;
18461f28255Scgd 		}
18561f28255Scgd 	} else {
18661f28255Scgd 		if (*s != '!')
18761f28255Scgd 			p = vlookup(s);
18861f28255Scgd 		else
18961f28255Scgd 			p = vlookup(s+1);
190e37283e1Slukem 		if (p != NULL) {
19161f28255Scgd 			vassign(p, s);
19261f28255Scgd 			return;
19361f28255Scgd 		}
19461f28255Scgd 	}
195ffe34450Schristos 	(void)printf("%s: unknown variable\r\n", s);
19661f28255Scgd }
19761f28255Scgd 
19861f28255Scgd static void
vprint(value_t * p)19958c2151fSperry vprint(value_t *p)
20061f28255Scgd {
201e37283e1Slukem 	char *cp;
20261f28255Scgd 
20361f28255Scgd 	if (col > 0 && col < MIDDLE)
20461f28255Scgd 		while (col++ < MIDDLE)
205ffe34450Schristos 			(void)putchar(' ');
206e37283e1Slukem 	col += strlen(p->v_name);
20761f28255Scgd 	switch (p->v_type&TMASK) {
20861f28255Scgd 
20961f28255Scgd 	case BOOL:
21061f28255Scgd 		if (boolean(p->v_value) == FALSE) {
21161f28255Scgd 			col++;
212ffe34450Schristos 			(void)putchar('!');
21361f28255Scgd 		}
214ffe34450Schristos 		(void)printf("%s", p->v_name);
21561f28255Scgd 		break;
21661f28255Scgd 
21761f28255Scgd 	case STRING:
218ffe34450Schristos 		(void)printf("%s=", p->v_name);
21961f28255Scgd 		col++;
22061f28255Scgd 		if (p->v_value) {
221e37283e1Slukem 			cp = interp(p->v_value);
222e37283e1Slukem 			col += strlen(cp);
223ffe34450Schristos 			(void)printf("%s", cp);
22461f28255Scgd 		}
22561f28255Scgd 		break;
22661f28255Scgd 
22761f28255Scgd 	case NUMBER:
22861f28255Scgd 		col += 6;
229ffe34450Schristos 		(void)printf("%s=%-5d", p->v_name, (int)number(p->v_value));
23061f28255Scgd 		break;
23161f28255Scgd 
23261f28255Scgd 	case CHAR:
233ffe34450Schristos 		(void)printf("%s=", p->v_name);
23461f28255Scgd 		col++;
23561f28255Scgd 		if (p->v_value) {
23661f28255Scgd 			cp = ctrl(character(p->v_value));
237e37283e1Slukem 			col += strlen(cp);
238ffe34450Schristos 			(void)printf("%s", cp);
23961f28255Scgd 		}
24061f28255Scgd 		break;
24161f28255Scgd 	}
24261f28255Scgd 	if (col >= MIDDLE) {
24361f28255Scgd 		col = 0;
244ffe34450Schristos 		(void)printf("\r\n");
24561f28255Scgd 		return;
24661f28255Scgd 	}
24761f28255Scgd }
24861f28255Scgd 
24961f28255Scgd 
25061f28255Scgd static int
vaccess(int mode,int rw)251c4341bc3Schristos vaccess(int mode, int rw)
25261f28255Scgd {
253923d7551Smrg 
25461f28255Scgd 	if (mode & (rw<<PUBLIC))
25561f28255Scgd 		return (1);
25661f28255Scgd 	if (mode & (rw<<PRIVATE))
25761f28255Scgd 		return (1);
25861f28255Scgd 	return ((mode & (rw<<ROOT)) && getuid() == 0);
25961f28255Scgd }
26061f28255Scgd 
26161f28255Scgd static value_t *
vlookup(const char * s)26258c2151fSperry vlookup(const char *s)
26361f28255Scgd {
264e37283e1Slukem 	value_t *p;
26561f28255Scgd 
26661f28255Scgd 	for (p = vtable; p->v_name; p++)
267*a64eb759Schristos 		if (strcmp(p->v_name, s) == 0 ||
268*a64eb759Schristos 		    (p->v_abrev && strcmp(p->v_abrev, s) == 0))
26961f28255Scgd 			return (p);
27061f28255Scgd 	return (NULL);
27161f28255Scgd }
27261f28255Scgd 
27361f28255Scgd char *
vinterp(char * s,char stp)27458c2151fSperry vinterp(char *s, char stp)
27561f28255Scgd {
276e37283e1Slukem 	char *p = s, c;
27761f28255Scgd 	int num;
27861f28255Scgd 
2794f6045fcSchristos 	while ((c = *s++) && c != stp)
28061f28255Scgd 		switch (c) {
28161f28255Scgd 
28261f28255Scgd 		case '^':
28361f28255Scgd 			if (*s)
28461f28255Scgd 				*p++ = *s++ - 0100;
28561f28255Scgd 			else
28661f28255Scgd 				*p++ = c;
28761f28255Scgd 			break;
28861f28255Scgd 
28961f28255Scgd 		case '\\':
29061f28255Scgd 			num = 0;
29161f28255Scgd 			c = *s++;
29261f28255Scgd 			if (c >= '0' && c <= '7')
29361f28255Scgd 				num = (num<<3)+(c-'0');
29461f28255Scgd 			else {
2954f6045fcSchristos 				const char *q = "n\nr\rt\tb\bf\f";
29661f28255Scgd 
29761f28255Scgd 				for (; *q; q++)
29861f28255Scgd 					if (c == *q++) {
29961f28255Scgd 						*p++ = *q;
30061f28255Scgd 						goto cont;
30161f28255Scgd 					}
30261f28255Scgd 				*p++ = c;
30361f28255Scgd 			cont:
30461f28255Scgd 				break;
30561f28255Scgd 			}
30661f28255Scgd 			if ((c = *s++) >= '0' && c <= '7') {
30761f28255Scgd 				num = (num<<3)+(c-'0');
30861f28255Scgd 				if ((c = *s++) >= '0' && c <= '7')
30961f28255Scgd 					num = (num<<3)+(c-'0');
31061f28255Scgd 				else
31161f28255Scgd 					s--;
31261f28255Scgd 			} else
31361f28255Scgd 				s--;
31461f28255Scgd 			*p++ = num;
31561f28255Scgd 			break;
31661f28255Scgd 
31761f28255Scgd 		default:
31861f28255Scgd 			*p++ = c;
31961f28255Scgd 		}
32061f28255Scgd 	*p = '\0';
3214f6045fcSchristos 	return (c == stp ? s-1 : NULL);
32261f28255Scgd }
32361f28255Scgd 
32461f28255Scgd /*
32561f28255Scgd  * assign variable s with value v (for NUMBER or STRING or CHAR types)
32661f28255Scgd  */
32761f28255Scgd 
328e37283e1Slukem int
vstring(const char * s,char * v)32958c2151fSperry vstring(const char *s, char *v)
33061f28255Scgd {
331e37283e1Slukem 	value_t *p;
33261f28255Scgd 
33361f28255Scgd 	p = vlookup(s);
33461f28255Scgd 	if (p == 0)
33561f28255Scgd 		return (1);
33661f28255Scgd 	if (p->v_type&NUMBER)
33704abeda6Smrg 		vassign(p, (char *)(long)atoi(v));
33861f28255Scgd 	else {
33961f28255Scgd 		if (strcmp(s, "record") == 0)
34061f28255Scgd 			v = expand(v);
34161f28255Scgd 		vassign(p, v);
34261f28255Scgd 	}
34361f28255Scgd 	return (0);
34461f28255Scgd }
345