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