1/* $FreeBSD: stable/11/contrib/ipfilter/lib/var.c 369245 2021-02-09 13:47:46Z git2svn $ */ 2 3/* 4 * Copyright (C) 2012 by Darren Reed. 5 * 6 * See the IPFILTER.LICENCE file for details on licencing. 7 * 8 * $Id$ 9 */ 10 11#include <ctype.h> 12 13#include "ipf.h" 14 15typedef struct variable { 16 struct variable *v_next; 17 char *v_name; 18 char *v_value; 19} variable_t; 20 21static variable_t *vtop = NULL; 22 23static variable_t *find_var(char *); 24static char *expand_string(char *, int); 25 26 27static variable_t *find_var(name) 28 char *name; 29{ 30 variable_t *v; 31 32 for (v = vtop; v != NULL; v = v->v_next) 33 if (!strcmp(name, v->v_name)) 34 return v; 35 return NULL; 36} 37 38 39char *get_variable(string, after, line) 40 char *string, **after; 41 int line; 42{ 43 char c, *s, *t, *value; 44 variable_t *v; 45 46 s = string; 47 48 if (*s == '{') { 49 s++; 50 for (t = s; *t != '\0'; t++) 51 if (*t == '}') 52 break; 53 if (*t == '\0') { 54 fprintf(stderr, "%d: { without }\n", line); 55 return NULL; 56 } 57 } else if (ISALPHA(*s)) { 58 for (t = s + 1; *t != '\0'; t++) 59 if (!ISALPHA(*t) && !ISDIGIT(*t) && (*t != '_')) 60 break; 61 } else { 62 fprintf(stderr, "%d: variables cannot start with '%c'\n", 63 line, *s); 64 return NULL; 65 } 66 67 if (after != NULL) 68 *after = t; 69 c = *t; 70 *t = '\0'; 71 v = find_var(s); 72 *t = c; 73 if (v == NULL) { 74 fprintf(stderr, "%d: unknown variable '%s'\n", line, s); 75 return NULL; 76 } 77 78 s = strdup(v->v_value); 79 value = expand_string(s, line); 80 if (value != s) 81 free(s); 82 return value; 83} 84 85 86static char *expand_string(oldstring, line) 87 char *oldstring; 88 int line; 89{ 90 char c, *s, *p1, *p2, *p3, *newstring, *value; 91 int len; 92 93 p3 = NULL; 94 newstring = oldstring; 95 96 for (s = oldstring; *s != '\0'; s++) 97 if (*s == '$') { 98 *s = '\0'; 99 s++; 100 101 switch (*s) 102 { 103 case '$' : 104 bcopy(s, s - 1, strlen(s)); 105 break; 106 default : 107 c = *s; 108 if (c == '\0') 109 return newstring; 110 111 value = get_variable(s, &p3, line); 112 if (value == NULL) 113 return NULL; 114 115 p2 = expand_string(value, line); 116 if (p2 == NULL) 117 return NULL; 118 119 len = strlen(newstring) + strlen(p2); 120 if (p3 != NULL) { 121 if (c == '{' && *p3 == '}') 122 p3++; 123 len += strlen(p3); 124 } 125 p1 = malloc(len + 1); 126 if (p1 == NULL) 127 return NULL; 128 129 *(s - 1) = '\0'; 130 strcpy(p1, newstring); 131 strcat(p1, p2); 132 if (p3 != NULL) 133 strcat(p1, p3); 134 135 s = p1 + len - strlen(p3) - 1; 136 if (newstring != oldstring) 137 free(newstring); 138 newstring = p1; 139 break; 140 } 141 } 142 return newstring; 143} 144 145 146void set_variable(name, value) 147 char *name; 148 char *value; 149{ 150 variable_t *v; 151 int len; 152 153 if (name == NULL || value == NULL || *name == '\0') 154 return; 155 156 v = find_var(name); 157 if (v != NULL) { 158 free(v->v_value); 159 v->v_value = strdup(value); 160 return; 161 } 162 163 len = strlen(value); 164 165 if ((*value == '"' && value[len - 1] == '"') || 166 (*value == '\'' && value[len - 1] == '\'')) { 167 value[len - 1] = '\0'; 168 value++; 169 len -=2; 170 } 171 172 v = (variable_t *)malloc(sizeof(*v)); 173 if (v == NULL) 174 return; 175 v->v_name = strdup(name); 176 v->v_value = strdup(value); 177 v->v_next = vtop; 178 vtop = v; 179} 180