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