1 /* $OpenBSD: value.c,v 1.14 2006/03/17 22:02:58 moritz Exp $ */ 2 /* $NetBSD: value.c,v 1.6 1997/02/11 09:24:09 mrg Exp $ */ 3 4 /*- 5 * SPDX-License-Identifier: BSD-3-Clause 6 * 7 * Copyright (c) 1983, 1993 8 * The Regents of the University of California. All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #include <sys/cdefs.h> 36 __FBSDID("$FreeBSD$"); 37 38 #ifndef lint 39 #if 0 40 static char sccsid[] = "@(#)value.c 8.1 (Berkeley) 6/6/93"; 41 static const char rcsid[] = "$OpenBSD: value.c,v 1.14 2006/03/17 22:02:58 moritz Exp $"; 42 #endif 43 #endif /* not lint */ 44 45 #include "tip.h" 46 47 #define MIDDLE 35 48 49 static value_t *vlookup(char *); 50 static void vassign(value_t *, char *); 51 static void vtoken(char *); 52 static void vprint(value_t *); 53 static int vaccess(unsigned int, unsigned int); 54 static char *vinterp(char *, int); 55 56 static size_t col = 0; 57 58 /* 59 * Variable manipulation 60 */ 61 void 62 vinit(void) 63 { 64 char file[FILENAME_MAX], *cp; 65 value_t *p; 66 FILE *fp; 67 68 for (p = vtable; p->v_name != NULL; p++) { 69 if (p->v_type&ENVIRON) 70 if ((cp = getenv(p->v_name))) 71 p->v_value = cp; 72 if (p->v_type&IREMOTE) { 73 switch (p->v_type&TMASK) { 74 case STRING: 75 p->v_value = *(char **)p->v_value; 76 break; 77 case NUMBER: 78 setnumber(p->v_value, *(long *)p->v_value); 79 break; 80 case BOOL: 81 setboolean(p->v_value, *(short *)p->v_value); 82 break; 83 case CHAR: 84 setcharacter(p->v_value, *(char *)p->v_value); 85 break; 86 } 87 } 88 } 89 /* 90 * Read the .tiprc file in the HOME directory 91 * for sets 92 */ 93 cp = value(HOME); 94 if (cp == NULL) { 95 (void)fprintf(stderr, 96 "$HOME not set. Skipping check for ~/.tiprc\n"); 97 } else if (strlen(cp) + sizeof("/.tiprc") > sizeof(file)) { 98 (void)fprintf(stderr, "Home directory path too long: %s\n", 99 value(HOME)); 100 } else { 101 snprintf(file, sizeof file, "%s/.tiprc", value(HOME)); 102 if ((fp = fopen(file, "r")) != NULL) { 103 char *tp; 104 105 while (fgets(file, sizeof(file)-1, fp) != NULL) { 106 if (vflag) 107 printf("set %s", file); 108 if ((tp = strrchr(file, '\n'))) 109 *tp = '\0'; 110 vlex(file); 111 } 112 fclose(fp); 113 } 114 } 115 /* 116 * To allow definition of exception prior to fork 117 */ 118 vtable[EXCEPTIONS].v_access &= ~(WRITE<<PUBLIC); 119 } 120 121 /*VARARGS1*/ 122 static void 123 vassign(value_t *p, char *v) 124 { 125 if (!vaccess(p->v_access, WRITE)) { 126 printf("access denied\r\n"); 127 return; 128 } 129 130 switch (p->v_type&TMASK) { 131 case STRING: 132 if (p->v_value && equal(p->v_value, v)) 133 return; 134 if (!(p->v_type&(ENVIRON|INIT))) 135 free(p->v_value); 136 if ((p->v_value = strdup(v)) == NOSTR) { 137 printf("out of core\r\n"); 138 return; 139 } 140 p->v_type &= ~(ENVIRON|INIT); 141 break; 142 case NUMBER: 143 if (number(p->v_value) == number(v)) 144 return; 145 setnumber(p->v_value, number(v)); 146 break; 147 case BOOL: 148 if (boolean(p->v_value) == (*v != '!')) 149 return; 150 setboolean(p->v_value, (*v != '!')); 151 break; 152 case CHAR: 153 if (character(p->v_value) == *v) 154 return; 155 setcharacter(p->v_value, *v); 156 } 157 p->v_access |= CHANGED; 158 } 159 160 void 161 vlex(char *s) 162 { 163 value_t *p; 164 char *cp; 165 166 if (equal(s, "all")) { 167 for (p = vtable; p->v_name; p++) 168 if (vaccess(p->v_access, READ)) 169 vprint(p); 170 } else { 171 do { 172 if ((cp = vinterp(s, ' '))) 173 cp++; 174 vtoken(s); 175 s = cp; 176 } while (s); 177 } 178 if (col > 0) { 179 printf("\r\n"); 180 col = 0; 181 } 182 } 183 184 static void 185 vtoken(char *s) 186 { 187 value_t *p; 188 char *cp; 189 190 if ((cp = strchr(s, '='))) { 191 *cp = '\0'; 192 if ((p = vlookup(s))) { 193 cp++; 194 if (p->v_type&NUMBER) 195 vassign(p, (char *)(intptr_t)atoi(cp)); 196 else { 197 if (strcmp(s, "record") == 0) 198 cp = expand(cp); 199 vassign(p, cp); 200 } 201 return; 202 } 203 } else if ((cp = strchr(s, '?'))) { 204 *cp = '\0'; 205 if ((p = vlookup(s)) && vaccess(p->v_access, READ)) { 206 vprint(p); 207 return; 208 } 209 } else { 210 if (*s != '!') 211 p = vlookup(s); 212 else 213 p = vlookup(s+1); 214 if (p != NOVAL) { 215 vassign(p, s); 216 return; 217 } 218 } 219 printf("%s: unknown variable\r\n", s); 220 } 221 222 static void 223 vprint(value_t *p) 224 { 225 char *cp; 226 227 if (col > 0 && col < MIDDLE) 228 while (col++ < MIDDLE) 229 putchar(' '); 230 col += size(p->v_name); 231 switch (p->v_type&TMASK) { 232 233 case BOOL: 234 if (boolean(p->v_value) == FALSE) { 235 col++; 236 putchar('!'); 237 } 238 printf("%s", p->v_name); 239 break; 240 241 case STRING: 242 printf("%s=", p->v_name); 243 col++; 244 if (p->v_value) { 245 cp = interp(p->v_value); 246 col += size(cp); 247 printf("%s", cp); 248 } 249 break; 250 251 case NUMBER: 252 col += 6; 253 printf("%s=%-5ld", p->v_name, number(p->v_value)); 254 break; 255 256 case CHAR: 257 printf("%s=", p->v_name); 258 col++; 259 if (p->v_value) { 260 cp = ctrl(character(p->v_value)); 261 col += size(cp); 262 printf("%s", cp); 263 } 264 break; 265 } 266 if (col >= MIDDLE) { 267 col = 0; 268 printf("\r\n"); 269 return; 270 } 271 } 272 273 static int 274 vaccess(unsigned int mode, unsigned int rw) 275 { 276 if (mode & (rw<<PUBLIC)) 277 return (1); 278 if (mode & (rw<<PRIVATE)) 279 return (1); 280 return ((mode & (rw<<ROOT)) && getuid() == 0); 281 } 282 283 static value_t * 284 vlookup(char *s) 285 { 286 value_t *p; 287 288 for (p = vtable; p->v_name; p++) 289 if (equal(p->v_name, s) || (p->v_abrev && equal(p->v_abrev, s))) 290 return (p); 291 return (NULL); 292 } 293 294 static char * 295 vinterp(char *s, int 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 } 342 *p = '\0'; 343 return (c == stop ? s-1 : NULL); 344 } 345 346 /* 347 * assign variable s with value v (for NUMBER or STRING or CHAR types) 348 */ 349 int 350 vstring(char *s, char *v) 351 { 352 value_t *p; 353 354 p = vlookup(s); 355 if (p == 0) 356 return (1); 357 if (p->v_type&NUMBER) 358 vassign(p, (char *)(intptr_t)atoi(v)); 359 else { 360 if (strcmp(s, "record") == 0) 361 v = expand(v); 362 vassign(p, v); 363 } 364 return (0); 365 } 366