1 /* $FreeBSD$ */ 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 15 typedef struct variable { 16 struct variable *v_next; 17 char *v_name; 18 char *v_value; 19 } variable_t; 20 21 static variable_t *vtop = NULL; 22 23 static variable_t *find_var(char *); 24 static char *expand_string(char *, int); 25 26 27 static 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 39 char *get_variable(char *string, char **after, int line) 40 { 41 char c, *s, *t, *value; 42 variable_t *v; 43 44 s = string; 45 46 if (*s == '{') { 47 s++; 48 for (t = s; *t != '\0'; t++) 49 if (*t == '}') 50 break; 51 if (*t == '\0') { 52 fprintf(stderr, "%d: { without }\n", line); 53 return (NULL); 54 } 55 } else if (ISALPHA(*s)) { 56 for (t = s + 1; *t != '\0'; t++) 57 if (!ISALPHA(*t) && !ISDIGIT(*t) && (*t != '_')) 58 break; 59 } else { 60 fprintf(stderr, "%d: variables cannot start with '%c'\n", 61 line, *s); 62 return (NULL); 63 } 64 65 if (after != NULL) 66 *after = t; 67 c = *t; 68 *t = '\0'; 69 v = find_var(s); 70 *t = c; 71 if (v == NULL) { 72 fprintf(stderr, "%d: unknown variable '%s'\n", line, s); 73 return (NULL); 74 } 75 76 s = strdup(v->v_value); 77 value = expand_string(s, line); 78 if (value != s) 79 free(s); 80 return (value); 81 } 82 83 84 static char *expand_string(char *oldstring, int line) 85 { 86 char c, *s, *p1, *p2, *p3, *newstring, *value; 87 int len; 88 89 p3 = NULL; 90 newstring = oldstring; 91 92 for (s = oldstring; *s != '\0'; s++) 93 if (*s == '$') { 94 *s = '\0'; 95 s++; 96 97 switch (*s) 98 { 99 case '$' : 100 bcopy(s, s - 1, strlen(s)); 101 break; 102 default : 103 c = *s; 104 if (c == '\0') 105 return (newstring); 106 107 value = get_variable(s, &p3, line); 108 if (value == NULL) 109 return (NULL); 110 111 p2 = expand_string(value, line); 112 if (p2 == NULL) 113 return (NULL); 114 115 len = strlen(newstring) + strlen(p2); 116 if (p3 != NULL) { 117 if (c == '{' && *p3 == '}') 118 p3++; 119 len += strlen(p3); 120 } 121 p1 = malloc(len + 1); 122 if (p1 == NULL) 123 return (NULL); 124 125 *(s - 1) = '\0'; 126 strcpy(p1, newstring); 127 strcat(p1, p2); 128 if (p3 != NULL) 129 strcat(p1, p3); 130 131 s = p1 + len - strlen(p3) - 1; 132 if (newstring != oldstring) 133 free(newstring); 134 newstring = p1; 135 break; 136 } 137 } 138 return (newstring); 139 } 140 141 142 void set_variable(char *name, char *value) 143 { 144 variable_t *v; 145 int len; 146 147 if (name == NULL || value == NULL || *name == '\0') 148 return; 149 150 v = find_var(name); 151 if (v != NULL) { 152 free(v->v_value); 153 v->v_value = strdup(value); 154 return; 155 } 156 157 len = strlen(value); 158 159 if ((*value == '"' && value[len - 1] == '"') || 160 (*value == '\'' && value[len - 1] == '\'')) { 161 value[len - 1] = '\0'; 162 value++; 163 len -=2; 164 } 165 166 v = (variable_t *)malloc(sizeof(*v)); 167 if (v == NULL) 168 return; 169 v->v_name = strdup(name); 170 v->v_value = strdup(value); 171 v->v_next = vtop; 172 vtop = v; 173 } 174