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