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