xref: /original-bsd/usr.bin/tip/value.c (revision fbed46ce)
1 /*	value.c	4.3	81/11/29	*/
2 #include "tip.h"
3 
4 #define MIDDLE	35
5 
6 static value_t *vlookup();
7 static int col = 0;
8 
9 /*
10  * Variable manipulation
11  */
12 vinit()
13 {
14 	register value_t *p;
15 	register char *cp;
16 	FILE *f;
17 	char file[256];
18 
19 	for (p = vtable; p->v_name != NULL; p++) {
20 		if (p->v_type&ENVIRON)
21 			if (cp = getenv(p->v_name))
22 				p->v_value = cp;
23 		if (p->v_type&IREMOTE)
24 			number(p->v_value) = *address(p->v_value);
25 	}
26 	/*
27 	 * Read the .tiprc file in the HOME directory
28 	 *  for sets
29 	 */
30 	strcpy(file, value(HOME));
31 	strcat(file, "/.tiprc");
32 	if ((f = fopen(file, "r")) != NULL) {
33 		register char *tp;
34 
35 		while (fgets(file, sizeof(file)-1, f) != NULL) {
36 			if (vflag)
37 				printf("set %s", file);
38 			if (tp = rindex(file, '\n'))
39 				*tp = '\0';
40 			vlex(file);
41 		}
42 		fclose(f);
43 	}
44 	/*
45 	 * To allow definition of exception prior to fork
46 	 */
47 	vtable[EXCEPTIONS].v_access &= ~(WRITE<<PUBLIC);
48 }
49 
50 /*VARARGS1*/
51 vassign(p, v)
52 	register value_t *p;
53 	char *v;
54 {
55 
56 	if (!vaccess(p->v_access, WRITE)) {
57 		printf("access denied\r\n");
58 		return;
59 	}
60 	switch (p->v_type&TMASK) {
61 
62 	case STRING:
63 		if (equal(p->v_value, v))
64 			return;
65 		if (!(p->v_type&(ENVIRON|INIT)))
66 			free(p->v_value);
67 		if ((p->v_value = malloc(size(v)+1)) == NOSTR) {
68 			printf("out of core\r\n");
69 			return;
70 		}
71 		p->v_type &= ~(ENVIRON|INIT);
72 		strcpy(p->v_value, v);
73 		break;
74 
75 	case NUMBER:
76 		if (number(p->v_value) == number(v))
77 			return;
78 		number(p->v_value) = number(v);
79 		break;
80 
81 	case BOOL:
82 		if (boolean(p->v_value) == (*v != '!'))
83 			return;
84 		boolean(p->v_value) = (*v != '!');
85 		break;
86 
87 	case CHAR:
88 		if (character(p->v_value) == *v)
89 			return;
90 		character(p->v_value) = *v;
91 	}
92 	p->v_access |= CHANGED;
93 }
94 
95 vlex(s)
96 	register char *s;
97 {
98 	register value_t *p;
99 
100 	if (equal(s, "all")) {
101 		for (p = vtable; p->v_name; p++)
102 			if (vaccess(p->v_access, READ))
103 				vprint(p);
104 	} else {
105 		register char *cp;
106 
107 		do {
108 			if (cp = vinterp(s, ' '))
109 				cp++;
110 			vtoken(s);
111 			s = cp;
112 		} while (s);
113 	}
114 	if (col > 0) {
115 		printf("\r\n");
116 		col = 0;
117 	}
118 }
119 
120 static int
121 vtoken(s)
122 	register char *s;
123 {
124 	register value_t *p;
125 	register char *cp;
126 
127 	if (cp = index(s, '=')) {
128 		*cp = '\0';
129 		if (p = vlookup(s)) {
130 			cp++;
131 			if (p->v_type&NUMBER)
132 				vassign(p, atoi(cp));
133 			else
134 				vassign(p, cp);
135 			return;
136 		}
137 	} else if (cp = index(s, '?')) {
138 		*cp = '\0';
139 		if ((p = vlookup(s)) && vaccess(p->v_access, READ)) {
140 			vprint(p);
141 			return;
142 		}
143 	} else {
144 		if (*s != '!')
145 			p = vlookup(s);
146 		else
147 			p = vlookup(s+1);
148 		if (p != NOVAL) {
149 			vassign(p, s);
150 			return;
151 		}
152 	}
153 	printf("%s: unknown variable\r\n", s);
154 }
155 
156 static int
157 vprint(p)
158 	register value_t *p;
159 {
160 	register char *cp;
161 	extern char *interp(), *ctrl();
162 
163 	if (col > 0 && col < MIDDLE)
164 		while (col++ < MIDDLE)
165 			putchar(' ');
166 	col += size(p->v_name);
167 	switch (p->v_type&TMASK) {
168 
169 	case BOOL:
170 		if (boolean(p->v_value) == FALSE) {
171 			col++;
172 			putchar('!');
173 		}
174 		printf("%s", p->v_name);
175 		break;
176 
177 	case STRING:
178 		printf("%s=", p->v_name);
179 		col++;
180 		if (p->v_value) {
181 			cp = interp(p->v_value);
182 			col += size(cp);
183 			printf("%s", cp);
184 		}
185 		break;
186 
187 	case NUMBER:
188 		col += 6;
189 		printf("%s=%-5d", p->v_name, number(p->v_value));
190 		break;
191 
192 	case CHAR:
193 		printf("%s=", p->v_name);
194 		col++;
195 		if (p->v_value) {
196 			cp = ctrl(character(p->v_value));
197 			col += size(cp);
198 			printf("%s", cp);
199 		}
200 		break;
201 	}
202 	if (col >= MIDDLE) {
203 		col = 0;
204 		printf("\r\n");
205 		return;
206 	}
207 }
208 
209 
210 static int
211 vaccess(mode, rw)
212 	register unsigned mode, rw;
213 {
214 	if (mode & (rw<<PUBLIC))
215 		return (1);
216 	if (mode & (rw<<PRIVATE))
217 		return (1);
218 	return ((mode & (rw<<ROOT)) && getuid() == 0);
219 }
220 
221 static value_t *
222 vlookup(s)
223 	register char *s;
224 {
225 	register value_t *p;
226 
227 	for (p = vtable; p->v_name; p++)
228 		if (equal(p->v_name, s) || (p->v_abrev && equal(p->v_abrev, s)))
229 			return (p);
230 	return (NULL);
231 }
232 
233 char *
234 vinterp(s, stop)
235 	register char *s;
236 	char stop;
237 {
238 	register char *p = s, c;
239 	int num;
240 
241 	while ((c = *s++) && c != stop)
242 		switch (c) {
243 
244 		case '^':
245 			if (*s)
246 				*p++ = *s++ - 0100;
247 			else
248 				*p++ = c;
249 			break;
250 
251 		case '\\':
252 			num = 0;
253 			c = *s++;
254 			if (c >= '0' && c <= '7')
255 				num = (num<<3)+(c-'0');
256 			else {
257 				register char *q = "n\nr\rt\tb\bf\f";
258 
259 				for (; *q; q++)
260 					if (c == *q++) {
261 						*p++ = *q;
262 						goto cont;
263 					}
264 				*p++ = c;
265 			cont:
266 				break;
267 			}
268 			if ((c = *s++) >= '0' && c <= '7') {
269 				num = (num<<3)+(c-'0');
270 				if ((c = *s++) >= '0' && c <= '7')
271 					num = (num<<3)+(c-'0');
272 				else
273 					s--;
274 			} else
275 				s--;
276 			*p++ = num;
277 			break;
278 
279 		default:
280 			*p++ = c;
281 		}
282 	*p = '\0';
283 	return (c == stop ? s-1 : NULL);
284 }
285