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