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
find_var(char * name)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
get_variable(char * string,char ** after,int line)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
expand_string(char * oldstring,int line)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
set_variable(char * name,char * value)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