xref: /original-bsd/usr.bin/tip/value.c (revision 6c57d260)
1 /*	value.c	4.1	81/05/09	*/
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 		case STRING:
177 			printf("%s=", p->v_name);
178 			col++;
179 			if (p->v_value) {
180 				cp = interp(p->v_value);
181 				col += size(cp);
182 				printf("%s", cp);
183 			}
184 			break;
185 		case NUMBER:
186 			col += 6;
187 			printf("%s=%-5d", p->v_name, number(p->v_value));
188 			break;
189 		case CHAR:
190 			printf("%s=", p->v_name);
191 			col++;
192 			if (p->v_value) {
193 				cp = ctrl(character(p->v_value));
194 				col += size(cp);
195 				printf("%s", cp);
196 			}
197 			break;
198 	}
199 	if (col >= MIDDLE) {
200 		col = 0;
201 		printf("\r\n");
202 		return;
203 	}
204 }
205 
206 
207 static int
208 vaccess(mode, rw)
209 register unsigned mode, rw;
210 {
211 	if (mode & (rw<<PUBLIC))
212 		return(1);
213 	if (mode & (rw<<PRIVATE))
214 		return(1);
215 	return((mode & (rw<<ROOT)) && getuid() == 0);
216 }
217 
218 static value_t *
219 vlookup(s)
220 register char *s;
221 {
222 	register value_t *p;
223 
224 	for (p = vtable; p->v_name; p++)
225 		if (equal(p->v_name, s) || (p->v_abrev && equal(p->v_abrev, s)))
226 			return(p);
227 	return(NULL);
228 }
229 
230 char *
231 vinterp(s, stop)
232 register char *s;
233 char stop;
234 {
235 	register char *p = s, c;
236 	int num;
237 
238 	while ((c = *s++) && c != stop) switch(c)
239 	{
240 		case '^':
241 			if (*s)
242 				*p++ = *s++ - 0100;
243 			else
244 				*p++ = c;
245 			break;
246 
247 		case '\\':
248 			num = 0;
249 			c = *s++;
250 			if (c >= '0' && c <= '7')
251 				num = (num<<3)+(c-'0');
252 			else {
253 				register char *q = "n\nr\rt\tb\bf\f";
254 
255 				for (; *q; q++)
256 					if (c == *q++) {
257 						*p++ = *q;
258 						goto cont;
259 					}
260 				*p++ = c;
261 			cont:
262 				break;
263 			}
264 			if ((c = *s++) >= '0' && c <= '7') {
265 				num = (num<<3)+(c-'0');
266 				if ((c = *s++) >= '0' && c <= '7')
267 					num = (num<<3)+(c-'0');
268 				else
269 					s--;
270 			} else
271 				s--;
272 			*p++ = num;
273 			break;
274 
275 		default:
276 			*p++ = c;
277 	}
278 	*p = '\0';
279 	return(c == stop ? s-1 : NULL);
280 }
281