1161754Sru/* $OpenBSD: value.c,v 1.14 2006/03/17 22:02:58 moritz Exp $ */ 288276Smarkm/* $NetBSD: value.c,v 1.6 1997/02/11 09:24:09 mrg Exp $ */ 388276Smarkm 4331722Seadler/* 57527Sjkh * Copyright (c) 1983, 1993 67527Sjkh * The Regents of the University of California. All rights reserved. 77527Sjkh * 87527Sjkh * Redistribution and use in source and binary forms, with or without 97527Sjkh * modification, are permitted provided that the following conditions 107527Sjkh * are met: 117527Sjkh * 1. Redistributions of source code must retain the above copyright 127527Sjkh * notice, this list of conditions and the following disclaimer. 137527Sjkh * 2. Redistributions in binary form must reproduce the above copyright 147527Sjkh * notice, this list of conditions and the following disclaimer in the 157527Sjkh * documentation and/or other materials provided with the distribution. 16161754Sru * 3. Neither the name of the University nor the names of its contributors 177527Sjkh * may be used to endorse or promote products derived from this software 187527Sjkh * without specific prior written permission. 197527Sjkh * 207527Sjkh * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 217527Sjkh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 227527Sjkh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 237527Sjkh * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 247527Sjkh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 257527Sjkh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 267527Sjkh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 277527Sjkh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 287527Sjkh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 297527Sjkh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 307527Sjkh * SUCH DAMAGE. 317527Sjkh */ 327527Sjkh 3388276Smarkm#include <sys/cdefs.h> 3488276Smarkm__FBSDID("$FreeBSD$"); 3588276Smarkm 367527Sjkh#ifndef lint 3728365Scharnier#if 0 387527Sjkhstatic char sccsid[] = "@(#)value.c 8.1 (Berkeley) 6/6/93"; 39161754Srustatic const char rcsid[] = "$OpenBSD: value.c,v 1.14 2006/03/17 22:02:58 moritz Exp $"; 4028365Scharnier#endif 417527Sjkh#endif /* not lint */ 427527Sjkh 437527Sjkh#include "tip.h" 447527Sjkh 457527Sjkh#define MIDDLE 35 467527Sjkh 47161754Srustatic value_t *vlookup(char *); 48161754Srustatic void vassign(value_t *, char *); 49161754Srustatic void vtoken(char *); 50161754Srustatic void vprint(value_t *); 51161754Srustatic int vaccess(unsigned int, unsigned int); 52161754Srustatic char *vinterp(char *, int); 537527Sjkh 54161754Srustatic size_t col = 0; 55161754Sru 567527Sjkh/* 577527Sjkh * Variable manipulation 587527Sjkh */ 5928365Scharniervoid 60161754Sruvinit(void) 617527Sjkh{ 62161754Sru char file[FILENAME_MAX], *cp; 6388276Smarkm value_t *p; 64161754Sru FILE *fp; 657527Sjkh 667527Sjkh for (p = vtable; p->v_name != NULL; p++) { 677527Sjkh if (p->v_type&ENVIRON) 6828365Scharnier if ((cp = getenv(p->v_name))) 697527Sjkh p->v_value = cp; 707527Sjkh if (p->v_type&IREMOTE) 7188276Smarkm setnumber(p->v_value, *address(p->v_value)); 727527Sjkh } 737527Sjkh /* 747527Sjkh * Read the .tiprc file in the HOME directory 757527Sjkh * for sets 767527Sjkh */ 77166911Sjls cp = value(HOME); 78166911Sjls if (cp == NULL) { 79166911Sjls (void)fprintf(stderr, 80166911Sjls "$HOME not set. Skipping check for ~/.tiprc\n"); 81166911Sjls } else if (strlen(cp) + sizeof("/.tiprc") > sizeof(file)) { 8288276Smarkm (void)fprintf(stderr, "Home directory path too long: %s\n", 83161754Sru value(HOME)); 8488276Smarkm } else { 8588276Smarkm snprintf(file, sizeof file, "%s/.tiprc", value(HOME)); 86161754Sru if ((fp = fopen(file, "r")) != NULL) { 8788276Smarkm char *tp; 887527Sjkh 89161754Sru while (fgets(file, sizeof(file)-1, fp) != NULL) { 9088276Smarkm if (vflag) 9188276Smarkm printf("set %s", file); 9288276Smarkm if ((tp = strrchr(file, '\n'))) 9388276Smarkm *tp = '\0'; 9488276Smarkm vlex(file); 9588276Smarkm } 96161754Sru fclose(fp); 977527Sjkh } 987527Sjkh } 997527Sjkh /* 1007527Sjkh * To allow definition of exception prior to fork 1017527Sjkh */ 1027527Sjkh vtable[EXCEPTIONS].v_access &= ~(WRITE<<PUBLIC); 1037527Sjkh} 1047527Sjkh 1057527Sjkh/*VARARGS1*/ 106161754Srustatic void 107161754Sruvassign(value_t *p, char *v) 1087527Sjkh{ 1097527Sjkh if (!vaccess(p->v_access, WRITE)) { 1107527Sjkh printf("access denied\r\n"); 1117527Sjkh return; 1127527Sjkh } 113161754Sru 1147527Sjkh switch (p->v_type&TMASK) { 1157527Sjkh case STRING: 1167527Sjkh if (p->v_value && equal(p->v_value, v)) 1177527Sjkh return; 1187527Sjkh if (!(p->v_type&(ENVIRON|INIT))) 1197527Sjkh free(p->v_value); 12088276Smarkm if ((p->v_value = strdup(v)) == NOSTR) { 1217527Sjkh printf("out of core\r\n"); 1227527Sjkh return; 1237527Sjkh } 1247527Sjkh p->v_type &= ~(ENVIRON|INIT); 1257527Sjkh break; 1267527Sjkh case NUMBER: 1277527Sjkh if (number(p->v_value) == number(v)) 1287527Sjkh return; 12988276Smarkm setnumber(p->v_value, number(v)); 1307527Sjkh break; 1317527Sjkh case BOOL: 1327527Sjkh if (boolean(p->v_value) == (*v != '!')) 1337527Sjkh return; 13488276Smarkm setboolean(p->v_value, (*v != '!')); 1357527Sjkh break; 1367527Sjkh case CHAR: 1377527Sjkh if (character(p->v_value) == *v) 1387527Sjkh return; 13988276Smarkm setcharacter(p->v_value, *v); 1407527Sjkh } 1417527Sjkh p->v_access |= CHANGED; 1427527Sjkh} 1437527Sjkh 14428365Scharniervoid 145161754Sruvlex(char *s) 1467527Sjkh{ 14788276Smarkm value_t *p; 148161754Sru char *cp; 1497527Sjkh 1507527Sjkh if (equal(s, "all")) { 1517527Sjkh for (p = vtable; p->v_name; p++) 1527527Sjkh if (vaccess(p->v_access, READ)) 1537527Sjkh vprint(p); 1547527Sjkh } else { 1557527Sjkh do { 15628365Scharnier if ((cp = vinterp(s, ' '))) 1577527Sjkh cp++; 1587527Sjkh vtoken(s); 1597527Sjkh s = cp; 1607527Sjkh } while (s); 1617527Sjkh } 1627527Sjkh if (col > 0) { 1637527Sjkh printf("\r\n"); 1647527Sjkh col = 0; 1657527Sjkh } 1667527Sjkh} 1677527Sjkh 1687527Sjkhstatic void 169161754Sruvtoken(char *s) 1707527Sjkh{ 17188276Smarkm value_t *p; 17288276Smarkm char *cp; 1737527Sjkh 17488276Smarkm if ((cp = strchr(s, '='))) { 1757527Sjkh *cp = '\0'; 17628365Scharnier if ((p = vlookup(s))) { 1777527Sjkh cp++; 1787527Sjkh if (p->v_type&NUMBER) 179161781Sru vassign(p, (char *)(intptr_t)atoi(cp)); 1807527Sjkh else { 1817527Sjkh if (strcmp(s, "record") == 0) 1827527Sjkh cp = expand(cp); 1837527Sjkh vassign(p, cp); 1847527Sjkh } 1857527Sjkh return; 1867527Sjkh } 18788276Smarkm } else if ((cp = strchr(s, '?'))) { 1887527Sjkh *cp = '\0'; 1897527Sjkh if ((p = vlookup(s)) && vaccess(p->v_access, READ)) { 1907527Sjkh vprint(p); 1917527Sjkh return; 1927527Sjkh } 1937527Sjkh } else { 1947527Sjkh if (*s != '!') 1957527Sjkh p = vlookup(s); 1967527Sjkh else 1977527Sjkh p = vlookup(s+1); 1987527Sjkh if (p != NOVAL) { 1997527Sjkh vassign(p, s); 2007527Sjkh return; 2017527Sjkh } 2027527Sjkh } 2037527Sjkh printf("%s: unknown variable\r\n", s); 2047527Sjkh} 2057527Sjkh 2067527Sjkhstatic void 207161754Sruvprint(value_t *p) 2087527Sjkh{ 20988276Smarkm char *cp; 2107527Sjkh 2117527Sjkh if (col > 0 && col < MIDDLE) 2127527Sjkh while (col++ < MIDDLE) 2137527Sjkh putchar(' '); 2147527Sjkh col += size(p->v_name); 2157527Sjkh switch (p->v_type&TMASK) { 2167527Sjkh 2177527Sjkh case BOOL: 2187527Sjkh if (boolean(p->v_value) == FALSE) { 2197527Sjkh col++; 2207527Sjkh putchar('!'); 2217527Sjkh } 2227527Sjkh printf("%s", p->v_name); 2237527Sjkh break; 2247527Sjkh 2257527Sjkh case STRING: 2267527Sjkh printf("%s=", p->v_name); 2277527Sjkh col++; 2287527Sjkh if (p->v_value) { 229129004Sstefanf cp = interp(p->v_value); 2307527Sjkh col += size(cp); 2317527Sjkh printf("%s", cp); 2327527Sjkh } 2337527Sjkh break; 2347527Sjkh 2357527Sjkh case NUMBER: 2367527Sjkh col += 6; 23788276Smarkm printf("%s=%-5ld", p->v_name, number(p->v_value)); 2387527Sjkh break; 2397527Sjkh 2407527Sjkh case CHAR: 2417527Sjkh printf("%s=", p->v_name); 2427527Sjkh col++; 2437527Sjkh if (p->v_value) { 2447527Sjkh cp = ctrl(character(p->v_value)); 2457527Sjkh col += size(cp); 2467527Sjkh printf("%s", cp); 2477527Sjkh } 2487527Sjkh break; 2497527Sjkh } 2507527Sjkh if (col >= MIDDLE) { 2517527Sjkh col = 0; 2527527Sjkh printf("\r\n"); 2537527Sjkh return; 2547527Sjkh } 2557527Sjkh} 2567527Sjkh 2577527Sjkhstatic int 258161754Sruvaccess(unsigned int mode, unsigned int rw) 2597527Sjkh{ 2607527Sjkh if (mode & (rw<<PUBLIC)) 2617527Sjkh return (1); 2627527Sjkh if (mode & (rw<<PRIVATE)) 2637527Sjkh return (1); 2647527Sjkh return ((mode & (rw<<ROOT)) && getuid() == 0); 2657527Sjkh} 2667527Sjkh 2677527Sjkhstatic value_t * 268161754Sruvlookup(char *s) 2697527Sjkh{ 27088276Smarkm value_t *p; 2717527Sjkh 2727527Sjkh for (p = vtable; p->v_name; p++) 2737527Sjkh if (equal(p->v_name, s) || (p->v_abrev && equal(p->v_abrev, s))) 2747527Sjkh return (p); 2757527Sjkh return (NULL); 2767527Sjkh} 2777527Sjkh 278161754Srustatic char * 279161754Sruvinterp(char *s, int stop) 2807527Sjkh{ 28188276Smarkm char *p = s, c; 2827527Sjkh int num; 2837527Sjkh 284161754Sru while ((c = *s++) && c != stop) { 2857527Sjkh switch (c) { 2867527Sjkh 2877527Sjkh case '^': 2887527Sjkh if (*s) 2897527Sjkh *p++ = *s++ - 0100; 2907527Sjkh else 2917527Sjkh *p++ = c; 2927527Sjkh break; 2937527Sjkh 2947527Sjkh case '\\': 2957527Sjkh num = 0; 2967527Sjkh c = *s++; 2977527Sjkh if (c >= '0' && c <= '7') 2987527Sjkh num = (num<<3)+(c-'0'); 2997527Sjkh else { 30088276Smarkm char *q = "n\nr\rt\tb\bf\f"; 3017527Sjkh 3027527Sjkh for (; *q; q++) 3037527Sjkh if (c == *q++) { 3047527Sjkh *p++ = *q; 3057527Sjkh goto cont; 3067527Sjkh } 3077527Sjkh *p++ = c; 3087527Sjkh cont: 3097527Sjkh break; 3107527Sjkh } 3117527Sjkh if ((c = *s++) >= '0' && c <= '7') { 3127527Sjkh num = (num<<3)+(c-'0'); 3137527Sjkh if ((c = *s++) >= '0' && c <= '7') 3147527Sjkh num = (num<<3)+(c-'0'); 3157527Sjkh else 3167527Sjkh s--; 3177527Sjkh } else 3187527Sjkh s--; 3197527Sjkh *p++ = num; 3207527Sjkh break; 3217527Sjkh 3227527Sjkh default: 3237527Sjkh *p++ = c; 3247527Sjkh } 325161754Sru } 3267527Sjkh *p = '\0'; 3277527Sjkh return (c == stop ? s-1 : NULL); 3287527Sjkh} 3297527Sjkh 3307527Sjkh/* 3317527Sjkh * assign variable s with value v (for NUMBER or STRING or CHAR types) 3327527Sjkh */ 33328365Scharnierint 334161754Sruvstring(char *s, char *v) 3357527Sjkh{ 33688276Smarkm value_t *p; 3377527Sjkh 338161754Sru p = vlookup(s); 3397527Sjkh if (p == 0) 3407527Sjkh return (1); 3417527Sjkh if (p->v_type&NUMBER) 342161781Sru vassign(p, (char *)(intptr_t)atoi(v)); 3437527Sjkh else { 3447527Sjkh if (strcmp(s, "record") == 0) 3457527Sjkh v = expand(v); 3467527Sjkh vassign(p, v); 3477527Sjkh } 3487527Sjkh return (0); 3497527Sjkh} 350