Home | History | Annotate | Line # | Download | only in tip
value.c revision 1.9
      1 /*	$NetBSD: value.c,v 1.9 1998/07/12 09:59:30 mrg Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1983, 1993
      5  *	The Regents of the University of California.  All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *	This product includes software developed by the University of
     18  *	California, Berkeley and its contributors.
     19  * 4. Neither the name of the University nor the names of its contributors
     20  *    may be used to endorse or promote products derived from this software
     21  *    without specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  * SUCH DAMAGE.
     34  */
     35 
     36 #include <sys/cdefs.h>
     37 #ifndef lint
     38 #if 0
     39 static char sccsid[] = "@(#)value.c	8.1 (Berkeley) 6/6/93";
     40 #endif
     41 __RCSID("$NetBSD: value.c,v 1.9 1998/07/12 09:59:30 mrg Exp $");
     42 #endif /* not lint */
     43 
     44 #include "tip.h"
     45 
     46 #define MIDDLE	35
     47 
     48 static int col = 0;
     49 
     50 static	int	vaccess __P((unsigned, unsigned));
     51 static	void	vassign __P((value_t *, char *));
     52 static	value_t *vlookup __P((char *));
     53 static	void	vprint __P((value_t *));
     54 static	void	vtoken __P((char *));
     55 
     56 /*
     57  * Variable manipulation
     58  */
     59 void
     60 vinit()
     61 {
     62 	value_t *p;
     63 	char *cp;
     64 	FILE *f;
     65 	char file[MAXPATHLEN];
     66 
     67 	for (p = vtable; p->v_name != NULL; p++) {
     68 		if (p->v_type&ENVIRON)
     69 			if ((cp = getenv(p->v_name)) != NULL)
     70 				p->v_value = cp;
     71 		if (p->v_type&IREMOTE)
     72 			setnumber(p->v_value, *address(p->v_value));
     73 	}
     74 	/*
     75 	 * Read the .tiprc file in the HOME directory
     76 	 *  for sets
     77 	 */
     78 	snprintf(file, sizeof(file), "%s/.tiprc", value(HOME));
     79 	if ((f = fopen(file, "r")) != NULL) {
     80 		char *tp;
     81 
     82 		while (fgets(file, sizeof(file)-1, f) != NULL) {
     83 			if (vflag)
     84 				printf("set %s", file);
     85 			if ((tp = strrchr(file, '\n')) != NULL)
     86 				*tp = '\0';
     87 			vlex(file);
     88 		}
     89 		fclose(f);
     90 	}
     91 	/*
     92 	 * To allow definition of exception prior to fork
     93 	 */
     94 	vtable[EXCEPTIONS].v_access &= ~(WRITE<<PUBLIC);
     95 }
     96 
     97 void
     98 vassign(p, v)
     99 	value_t *p;
    100 	char *v;
    101 {
    102 
    103 	if (!vaccess(p->v_access, WRITE)) {
    104 		printf("access denied\r\n");
    105 		return;
    106 	}
    107 	switch (p->v_type&TMASK) {
    108 
    109 	case STRING:
    110 		if (p->v_value && equal(p->v_value, v))
    111 			return;
    112 		if (!(p->v_type&(ENVIRON|INIT)))
    113 			free(p->v_value);
    114 		if ((p->v_value = strdup(v)) == NULL) {
    115 			printf("out of core\r\n");
    116 			return;
    117 		}
    118 		p->v_type &= ~(ENVIRON|INIT);
    119 		break;
    120 
    121 	case NUMBER:
    122 		if (number(p->v_value) == number(v))
    123 			return;
    124 		setnumber(p->v_value, number(v));
    125 		break;
    126 
    127 	case BOOL:
    128 		if (boolean(p->v_value) == (*v != '!'))
    129 			return;
    130 		setboolean(p->v_value, (*v != '!'));
    131 		break;
    132 
    133 	case CHAR:
    134 		if (character(p->v_value) == *v)
    135 			return;
    136 		setcharacter(p->v_value, *v);
    137 	}
    138 	p->v_access |= CHANGED;
    139 }
    140 
    141 void
    142 vlex(s)
    143 	char *s;
    144 {
    145 	value_t *p;
    146 
    147 	if (equal(s, "all")) {
    148 		for (p = vtable; p->v_name; p++)
    149 			if (vaccess(p->v_access, READ))
    150 				vprint(p);
    151 	} else {
    152 		char *cp;
    153 
    154 		do {
    155 			if ((cp = vinterp(s, ' ')) != NULL)
    156 				cp++;
    157 			vtoken(s);
    158 			s = cp;
    159 		} while (s);
    160 	}
    161 	if (col > 0) {
    162 		printf("\r\n");
    163 		col = 0;
    164 	}
    165 }
    166 
    167 static void
    168 vtoken(s)
    169 	char *s;
    170 {
    171 	value_t *p;
    172 	char *cp;
    173 
    174 	if ((cp = strchr(s, '=')) != NULL) {
    175 		*cp = '\0';
    176 		if ((p = vlookup(s)) != NULL) {
    177 			cp++;
    178 			if (p->v_type&NUMBER)
    179 				vassign(p, (char *)(long)atoi(cp));
    180 			else {
    181 				if (strcmp(s, "record") == 0)
    182 					cp = expand(cp);
    183 				vassign(p, cp);
    184 			}
    185 			return;
    186 		}
    187 	} else if ((cp = strchr(s, '?')) != NULL) {
    188 		*cp = '\0';
    189 		if ((p = vlookup(s)) && vaccess(p->v_access, READ)) {
    190 			vprint(p);
    191 			return;
    192 		}
    193 	} else {
    194 		if (*s != '!')
    195 			p = vlookup(s);
    196 		else
    197 			p = vlookup(s+1);
    198 		if (p != NULL) {
    199 			vassign(p, s);
    200 			return;
    201 		}
    202 	}
    203 	printf("%s: unknown variable\r\n", s);
    204 }
    205 
    206 static void
    207 vprint(p)
    208 	value_t *p;
    209 {
    210 	char *cp;
    211 
    212 	if (col > 0 && col < MIDDLE)
    213 		while (col++ < MIDDLE)
    214 			putchar(' ');
    215 	col += strlen(p->v_name);
    216 	switch (p->v_type&TMASK) {
    217 
    218 	case BOOL:
    219 		if (boolean(p->v_value) == FALSE) {
    220 			col++;
    221 			putchar('!');
    222 		}
    223 		printf("%s", p->v_name);
    224 		break;
    225 
    226 	case STRING:
    227 		printf("%s=", p->v_name);
    228 		col++;
    229 		if (p->v_value) {
    230 			cp = interp(p->v_value);
    231 			col += strlen(cp);
    232 			printf("%s", cp);
    233 		}
    234 		break;
    235 
    236 	case NUMBER:
    237 		col += 6;
    238 		printf("%s=%-5d", p->v_name, (int)number(p->v_value));
    239 		break;
    240 
    241 	case CHAR:
    242 		printf("%s=", p->v_name);
    243 		col++;
    244 		if (p->v_value) {
    245 			cp = ctrl(character(p->v_value));
    246 			col += strlen(cp);
    247 			printf("%s", cp);
    248 		}
    249 		break;
    250 	}
    251 	if (col >= MIDDLE) {
    252 		col = 0;
    253 		printf("\r\n");
    254 		return;
    255 	}
    256 }
    257 
    258 
    259 static int
    260 vaccess(mode, rw)
    261 	unsigned mode, rw;
    262 {
    263 
    264 	if (mode & (rw<<PUBLIC))
    265 		return (1);
    266 	if (mode & (rw<<PRIVATE))
    267 		return (1);
    268 	return ((mode & (rw<<ROOT)) && getuid() == 0);
    269 }
    270 
    271 static value_t *
    272 vlookup(s)
    273 	char *s;
    274 {
    275 	value_t *p;
    276 
    277 	for (p = vtable; p->v_name; p++)
    278 		if (equal(p->v_name, s) || (p->v_abrev && equal(p->v_abrev, s)))
    279 			return (p);
    280 	return (NULL);
    281 }
    282 
    283 char *
    284 vinterp(s, stop)
    285 	char *s;
    286 	char stop;
    287 {
    288 	char *p = s, c;
    289 	int num;
    290 
    291 	while ((c = *s++) && c != stop)
    292 		switch (c) {
    293 
    294 		case '^':
    295 			if (*s)
    296 				*p++ = *s++ - 0100;
    297 			else
    298 				*p++ = c;
    299 			break;
    300 
    301 		case '\\':
    302 			num = 0;
    303 			c = *s++;
    304 			if (c >= '0' && c <= '7')
    305 				num = (num<<3)+(c-'0');
    306 			else {
    307 				char *q = "n\nr\rt\tb\bf\f";
    308 
    309 				for (; *q; q++)
    310 					if (c == *q++) {
    311 						*p++ = *q;
    312 						goto cont;
    313 					}
    314 				*p++ = c;
    315 			cont:
    316 				break;
    317 			}
    318 			if ((c = *s++) >= '0' && c <= '7') {
    319 				num = (num<<3)+(c-'0');
    320 				if ((c = *s++) >= '0' && c <= '7')
    321 					num = (num<<3)+(c-'0');
    322 				else
    323 					s--;
    324 			} else
    325 				s--;
    326 			*p++ = num;
    327 			break;
    328 
    329 		default:
    330 			*p++ = c;
    331 		}
    332 	*p = '\0';
    333 	return (c == stop ? s-1 : NULL);
    334 }
    335 
    336 /*
    337  * assign variable s with value v (for NUMBER or STRING or CHAR types)
    338  */
    339 
    340 int
    341 vstring(s,v)
    342 	char *s;
    343 	char *v;
    344 {
    345 	value_t *p;
    346 
    347 	p = vlookup(s);
    348 	if (p == 0)
    349 		return (1);
    350 	if (p->v_type&NUMBER)
    351 		vassign(p, (char *)(long)atoi(v));
    352 	else {
    353 		if (strcmp(s, "record") == 0)
    354 			v = expand(v);
    355 		vassign(p, v);
    356 	}
    357 	return (0);
    358 }
    359