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