xref: /illumos-gate/usr/src/cmd/ipf/lib/common/var.c (revision ab25eeb5)
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