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