1 /* 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)value.c 8.1 (Berkeley) 6/6/93 34 * $FreeBSD: src/usr.bin/tip/tip/value.c,v 1.5.2.1 2000/07/01 12:24:23 ps Exp $ 35 */ 36 37 #include "tip.h" 38 39 #define MIDDLE 35 40 41 static value_t *vlookup(char *); 42 int vstring(char *, char *); 43 void vlex(char *); 44 void vassign(value_t *, char *); 45 46 static int col = 0; 47 48 /* 49 * Variable manipulation 50 */ 51 void 52 vinit(void) 53 { 54 value_t *p; 55 char *cp; 56 FILE *f; 57 char file[256]; 58 59 for (p = vtable; p->v_name != NULL; p++) { 60 if (p->v_type&ENVIRON) 61 if ((cp = getenv(p->v_name))) 62 p->v_value = cp; 63 if (p->v_type&IREMOTE) { 64 if (p->v_type&STRING) 65 p->v_value = *(char **) address(p->v_value); 66 else 67 number(p->v_value) = *address(p->v_value); 68 } 69 } 70 /* 71 * Read the .tiprc file in the HOME directory 72 * for sets 73 */ 74 strcpy(file, value(HOME)); 75 strcat(file, "/.tiprc"); 76 if ((f = fopen(file, "r")) != NULL) { 77 char *tp; 78 79 while (fgets(file, sizeof(file)-1, f) != NULL) { 80 if (vflag) 81 printf("set %s", file); 82 if ((tp = rindex(file, '\n'))) 83 *tp = '\0'; 84 vlex(file); 85 } 86 fclose(f); 87 } 88 /* 89 * To allow definition of exception prior to fork 90 */ 91 vtable[EXCEPTIONS].v_access &= ~(WRITE<<PUBLIC); 92 } 93 94 static int vaccess(unsigned, unsigned); 95 96 /*VARARGS1*/ 97 void 98 vassign(value_t *p, char *v) 99 { 100 101 if (!vaccess(p->v_access, WRITE)) { 102 printf("access denied\r\n"); 103 return; 104 } 105 switch (p->v_type&TMASK) { 106 107 case STRING: 108 if (p->v_value && equal(p->v_value, v)) 109 return; 110 if (!(p->v_type&(ENVIRON|INIT))) 111 free(p->v_value); 112 if ((p->v_value = malloc(size(v)+1)) == NULL) { 113 printf("out of core\r\n"); 114 return; 115 } 116 p->v_type &= ~(ENVIRON|INIT); 117 strcpy(p->v_value, v); 118 break; 119 120 case NUMBER: 121 if (number(p->v_value) == number(v)) 122 return; 123 number(p->v_value) = number(v); 124 break; 125 126 case BOOL: 127 if (boolean(p->v_value) == (*v != '!')) 128 return; 129 boolean(p->v_value) = (*v != '!'); 130 break; 131 132 case CHAR: 133 if (character(p->v_value) == *v) 134 return; 135 character(p->v_value) = *v; 136 } 137 p->v_access |= CHANGED; 138 } 139 140 static void vprint(value_t *); 141 static void vtoken(char *); 142 143 void 144 vlex(char *s) 145 { 146 value_t *p; 147 148 if (equal(s, "all")) { 149 for (p = vtable; p->v_name; p++) 150 if (vaccess(p->v_access, READ)) 151 vprint(p); 152 } else { 153 char *cp; 154 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 168 static void 169 vtoken(char *s) 170 { 171 value_t *p; 172 char *cp; 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, (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 = 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 != NULL) { 199 vassign(p, s); 200 return; 201 } 202 } 203 printf("%s: unknown variable\r\n", s); 204 } 205 206 static void 207 vprint(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=%-5d", 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 257 258 static int 259 vaccess(unsigned mode, unsigned rw) 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(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(char *s, char stop) 281 { 282 char *p = s, c; 283 int num; 284 285 while ((c = *s++) && c != stop) 286 switch (c) { 287 288 case '^': 289 if (*s) 290 *p++ = *s++ - 0100; 291 else 292 *p++ = c; 293 break; 294 295 case '\\': 296 num = 0; 297 c = *s++; 298 if (c >= '0' && c <= '7') 299 num = (num<<3)+(c-'0'); 300 else { 301 char *q = "n\nr\rt\tb\bf\f"; 302 303 for (; *q; q++) 304 if (c == *q++) { 305 *p++ = *q; 306 goto cont; 307 } 308 *p++ = c; 309 cont: 310 break; 311 } 312 if ((c = *s++) >= '0' && c <= '7') { 313 num = (num<<3)+(c-'0'); 314 if ((c = *s++) >= '0' && c <= '7') 315 num = (num<<3)+(c-'0'); 316 else 317 s--; 318 } else 319 s--; 320 *p++ = num; 321 break; 322 323 default: 324 *p++ = c; 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 */ 333 334 int 335 vstring(char *s, char *v) 336 { 337 value_t *p; 338 339 p = vlookup(s); 340 if (p == NULL) 341 return (1); 342 if (p->v_type&NUMBER) 343 vassign(p, (char *)(intptr_t)atoi(v)); 344 else { 345 if (strcmp(s, "record") == 0) 346 v = expand(v); 347 vassign(p, v); 348 } 349 return (0); 350 } 351