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