1 /* $NetBSD: value.c,v 1.10 2003/08/07 11:16:20 agc 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 35 static char sccsid[] = "@(#)value.c 8.1 (Berkeley) 6/6/93"; 36 #endif 37 __RCSID("$NetBSD: value.c,v 1.10 2003/08/07 11:16:20 agc Exp $"); 38 #endif /* not lint */ 39 40 #include "tip.h" 41 42 #define MIDDLE 35 43 44 static int col = 0; 45 46 static int vaccess __P((unsigned, unsigned)); 47 static void vassign __P((value_t *, char *)); 48 static value_t *vlookup __P((char *)); 49 static void vprint __P((value_t *)); 50 static void vtoken __P((char *)); 51 52 /* 53 * Variable manipulation 54 */ 55 void 56 vinit() 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 snprintf(file, sizeof(file), "%s/.tiprc", 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 printf("set %s", file); 81 if ((tp = strrchr(file, '\n')) != NULL) 82 *tp = '\0'; 83 vlex(file); 84 } 85 fclose(f); 86 } 87 /* 88 * To allow definition of exception prior to fork 89 */ 90 vtable[EXCEPTIONS].v_access &= ~(WRITE<<PUBLIC); 91 } 92 93 void 94 vassign(p, v) 95 value_t *p; 96 char *v; 97 { 98 99 if (!vaccess(p->v_access, WRITE)) { 100 printf("access denied\r\n"); 101 return; 102 } 103 switch (p->v_type&TMASK) { 104 105 case STRING: 106 if (p->v_value && equal(p->v_value, v)) 107 return; 108 if (!(p->v_type&(ENVIRON|INIT))) 109 free(p->v_value); 110 if ((p->v_value = strdup(v)) == NULL) { 111 printf("out of core\r\n"); 112 return; 113 } 114 p->v_type &= ~(ENVIRON|INIT); 115 break; 116 117 case NUMBER: 118 if (number(p->v_value) == number(v)) 119 return; 120 setnumber(p->v_value, number(v)); 121 break; 122 123 case BOOL: 124 if (boolean(p->v_value) == (*v != '!')) 125 return; 126 setboolean(p->v_value, (*v != '!')); 127 break; 128 129 case CHAR: 130 if (character(p->v_value) == *v) 131 return; 132 setcharacter(p->v_value, *v); 133 } 134 p->v_access |= CHANGED; 135 } 136 137 void 138 vlex(s) 139 char *s; 140 { 141 value_t *p; 142 143 if (equal(s, "all")) { 144 for (p = vtable; p->v_name; p++) 145 if (vaccess(p->v_access, READ)) 146 vprint(p); 147 } else { 148 char *cp; 149 150 do { 151 if ((cp = vinterp(s, ' ')) != NULL) 152 cp++; 153 vtoken(s); 154 s = cp; 155 } while (s); 156 } 157 if (col > 0) { 158 printf("\r\n"); 159 col = 0; 160 } 161 } 162 163 static void 164 vtoken(s) 165 char *s; 166 { 167 value_t *p; 168 char *cp; 169 170 if ((cp = strchr(s, '=')) != NULL) { 171 *cp = '\0'; 172 if ((p = vlookup(s)) != NULL) { 173 cp++; 174 if (p->v_type&NUMBER) 175 vassign(p, (char *)(long)atoi(cp)); 176 else { 177 if (strcmp(s, "record") == 0) 178 cp = expand(cp); 179 vassign(p, cp); 180 } 181 return; 182 } 183 } else if ((cp = strchr(s, '?')) != NULL) { 184 *cp = '\0'; 185 if ((p = vlookup(s)) && vaccess(p->v_access, READ)) { 186 vprint(p); 187 return; 188 } 189 } else { 190 if (*s != '!') 191 p = vlookup(s); 192 else 193 p = vlookup(s+1); 194 if (p != NULL) { 195 vassign(p, s); 196 return; 197 } 198 } 199 printf("%s: unknown variable\r\n", s); 200 } 201 202 static void 203 vprint(p) 204 value_t *p; 205 { 206 char *cp; 207 208 if (col > 0 && col < MIDDLE) 209 while (col++ < MIDDLE) 210 putchar(' '); 211 col += strlen(p->v_name); 212 switch (p->v_type&TMASK) { 213 214 case BOOL: 215 if (boolean(p->v_value) == FALSE) { 216 col++; 217 putchar('!'); 218 } 219 printf("%s", p->v_name); 220 break; 221 222 case STRING: 223 printf("%s=", p->v_name); 224 col++; 225 if (p->v_value) { 226 cp = interp(p->v_value); 227 col += strlen(cp); 228 printf("%s", cp); 229 } 230 break; 231 232 case NUMBER: 233 col += 6; 234 printf("%s=%-5d", p->v_name, (int)number(p->v_value)); 235 break; 236 237 case CHAR: 238 printf("%s=", p->v_name); 239 col++; 240 if (p->v_value) { 241 cp = ctrl(character(p->v_value)); 242 col += strlen(cp); 243 printf("%s", cp); 244 } 245 break; 246 } 247 if (col >= MIDDLE) { 248 col = 0; 249 printf("\r\n"); 250 return; 251 } 252 } 253 254 255 static int 256 vaccess(mode, rw) 257 unsigned mode, rw; 258 { 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 267 static value_t * 268 vlookup(s) 269 char *s; 270 { 271 value_t *p; 272 273 for (p = vtable; p->v_name; p++) 274 if (equal(p->v_name, s) || (p->v_abrev && equal(p->v_abrev, s))) 275 return (p); 276 return (NULL); 277 } 278 279 char * 280 vinterp(s, stop) 281 char *s; 282 char stop; 283 { 284 char *p = s, c; 285 int num; 286 287 while ((c = *s++) && c != stop) 288 switch (c) { 289 290 case '^': 291 if (*s) 292 *p++ = *s++ - 0100; 293 else 294 *p++ = c; 295 break; 296 297 case '\\': 298 num = 0; 299 c = *s++; 300 if (c >= '0' && c <= '7') 301 num = (num<<3)+(c-'0'); 302 else { 303 char *q = "n\nr\rt\tb\bf\f"; 304 305 for (; *q; q++) 306 if (c == *q++) { 307 *p++ = *q; 308 goto cont; 309 } 310 *p++ = c; 311 cont: 312 break; 313 } 314 if ((c = *s++) >= '0' && c <= '7') { 315 num = (num<<3)+(c-'0'); 316 if ((c = *s++) >= '0' && c <= '7') 317 num = (num<<3)+(c-'0'); 318 else 319 s--; 320 } else 321 s--; 322 *p++ = num; 323 break; 324 325 default: 326 *p++ = c; 327 } 328 *p = '\0'; 329 return (c == stop ? s-1 : NULL); 330 } 331 332 /* 333 * assign variable s with value v (for NUMBER or STRING or CHAR types) 334 */ 335 336 int 337 vstring(s,v) 338 char *s; 339 char *v; 340 { 341 value_t *p; 342 343 p = vlookup(s); 344 if (p == 0) 345 return (1); 346 if (p->v_type&NUMBER) 347 vassign(p, (char *)(long)atoi(v)); 348 else { 349 if (strcmp(s, "record") == 0) 350 v = expand(v); 351 vassign(p, v); 352 } 353 return (0); 354 } 355