1 /* $NetBSD: value.c,v 1.11 2004/04/23 22:11:44 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 35 static char sccsid[] = "@(#)value.c 8.1 (Berkeley) 6/6/93"; 36 #endif 37 __RCSID("$NetBSD: value.c,v 1.11 2004/04/23 22:11:44 christos 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((const 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 /*###226 [cc] warning: passing arg 1 of `interp' discards qualifiers from pointer target type%%%*/ 227 cp = interp(p->v_value); 228 col += strlen(cp); 229 printf("%s", cp); 230 } 231 break; 232 233 case NUMBER: 234 col += 6; 235 printf("%s=%-5d", p->v_name, (int)number(p->v_value)); 236 break; 237 238 case CHAR: 239 printf("%s=", p->v_name); 240 col++; 241 if (p->v_value) { 242 cp = ctrl(character(p->v_value)); 243 col += strlen(cp); 244 printf("%s", cp); 245 } 246 break; 247 } 248 if (col >= MIDDLE) { 249 col = 0; 250 printf("\r\n"); 251 return; 252 } 253 } 254 255 256 static int 257 vaccess(mode, rw) 258 unsigned mode, rw; 259 { 260 261 if (mode & (rw<<PUBLIC)) 262 return (1); 263 if (mode & (rw<<PRIVATE)) 264 return (1); 265 return ((mode & (rw<<ROOT)) && getuid() == 0); 266 } 267 268 static value_t * 269 vlookup(s) 270 const char *s; 271 { 272 value_t *p; 273 274 for (p = vtable; p->v_name; p++) 275 if (equal(p->v_name, s) || (p->v_abrev && equal(p->v_abrev, s))) 276 return (p); 277 return (NULL); 278 } 279 280 char * 281 vinterp(s, stp) 282 char *s; 283 char stp; 284 { 285 char *p = s, c; 286 int num; 287 288 while ((c = *s++) && c != stp) 289 switch (c) { 290 291 case '^': 292 if (*s) 293 *p++ = *s++ - 0100; 294 else 295 *p++ = c; 296 break; 297 298 case '\\': 299 num = 0; 300 c = *s++; 301 if (c >= '0' && c <= '7') 302 num = (num<<3)+(c-'0'); 303 else { 304 const char *q = "n\nr\rt\tb\bf\f"; 305 306 for (; *q; q++) 307 if (c == *q++) { 308 *p++ = *q; 309 goto cont; 310 } 311 *p++ = c; 312 cont: 313 break; 314 } 315 if ((c = *s++) >= '0' && c <= '7') { 316 num = (num<<3)+(c-'0'); 317 if ((c = *s++) >= '0' && c <= '7') 318 num = (num<<3)+(c-'0'); 319 else 320 s--; 321 } else 322 s--; 323 *p++ = num; 324 break; 325 326 default: 327 *p++ = c; 328 } 329 *p = '\0'; 330 return (c == stp ? s-1 : NULL); 331 } 332 333 /* 334 * assign variable s with value v (for NUMBER or STRING or CHAR types) 335 */ 336 337 int 338 vstring(s,v) 339 const char *s; 340 char *v; 341 { 342 value_t *p; 343 344 p = vlookup(s); 345 if (p == 0) 346 return (1); 347 if (p->v_type&NUMBER) 348 vassign(p, (char *)(long)atoi(v)); 349 else { 350 if (strcmp(s, "record") == 0) 351 v = expand(v); 352 vassign(p, v); 353 } 354 return (0); 355 } 356