1 /*
2 * Copyright (C) 1993-2005 by Darren Reed.
3 * See the IPFILTER.LICENCE file for details on licencing.
4 */
5
6 #include <ctype.h>
7
8 #include "ipf.h"
9
10 typedef struct variable {
11 struct variable *v_next;
12 char *v_name;
13 char *v_value;
14 } variable_t;
15
16 static variable_t *vtop = NULL;
17
18 static variable_t *find_var __P((char *));
19 static char *expand_string __P((char *, int));
20
21
find_var(name)22 static variable_t *find_var(name)
23 char *name;
24 {
25 variable_t *v;
26
27 for (v = vtop; v != NULL; v = v->v_next)
28 if (!strcmp(name, v->v_name))
29 return v;
30 return NULL;
31 }
32
33
get_variable(string,after,line)34 char *get_variable(string, after, line)
35 char *string, **after;
36 int line;
37 {
38 char c, *s, *t, *value;
39 variable_t *v;
40
41 s = string;
42
43 if (*s == '{') {
44 s++;
45 for (t = s; *t != '\0'; t++)
46 if (*t == '}')
47 break;
48 if (*t == '\0') {
49 fprintf(stderr, "%d: { without }\n", line);
50 return NULL;
51 }
52 } else if (ISALPHA(*s)) {
53 for (t = s + 1; *t != '\0'; t++)
54 if (!ISALPHA(*t) && !ISDIGIT(*t) && (*t != '_'))
55 break;
56 } else {
57 fprintf(stderr, "%d: variables cannot start with '%c'\n",
58 line, *s);
59 return NULL;
60 }
61
62 if (after != NULL)
63 *after = t;
64 c = *t;
65 *t = '\0';
66 v = find_var(s);
67 *t = c;
68 if (v == NULL) {
69 fprintf(stderr, "%d: unknown variable '%s'\n", line, s);
70 return NULL;
71 }
72
73 s = strdup(v->v_value);
74 value = expand_string(s, line);
75 if (value != s)
76 free(s);
77 return value;
78 }
79
80
expand_string(oldstring,line)81 static char *expand_string(oldstring, line)
82 char *oldstring;
83 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
set_variable(name,value)141 void set_variable(name, value)
142 char *name;
143 char *value;
144 {
145 variable_t *v;
146 int len;
147
148 if (name == NULL || value == NULL || *name == '\0')
149 return;
150
151 v = find_var(name);
152 if (v != NULL) {
153 free(v->v_value);
154 v->v_value = strdup(value);
155 return;
156 }
157
158 len = strlen(value);
159
160 if ((*value == '"' && value[len - 1] == '"') ||
161 (*value == '\'' && value[len - 1] == '\'')) {
162 value[len - 1] = '\0';
163 value++;
164 len -=2;
165 }
166
167 v = (variable_t *)malloc(sizeof(*v));
168 if (v == NULL)
169 return;
170 v->v_name = strdup(name);
171 v->v_value = strdup(value);
172 v->v_next = vtop;
173 vtop = v;
174 }
175