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