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