1*ab25eeb5Syz155240 /*
2*ab25eeb5Syz155240 * Copyright (C) 1993-2005 by Darren Reed.
3*ab25eeb5Syz155240 * See the IPFILTER.LICENCE file for details on licencing.
4*ab25eeb5Syz155240 */
5*ab25eeb5Syz155240
67c478bd9Sstevel@tonic-gate #include <ctype.h>
77c478bd9Sstevel@tonic-gate
87c478bd9Sstevel@tonic-gate #include "ipf.h"
97c478bd9Sstevel@tonic-gate
107c478bd9Sstevel@tonic-gate typedef struct variable {
117c478bd9Sstevel@tonic-gate struct variable *v_next;
127c478bd9Sstevel@tonic-gate char *v_name;
137c478bd9Sstevel@tonic-gate char *v_value;
147c478bd9Sstevel@tonic-gate } variable_t;
157c478bd9Sstevel@tonic-gate
167c478bd9Sstevel@tonic-gate static variable_t *vtop = NULL;
177c478bd9Sstevel@tonic-gate
187c478bd9Sstevel@tonic-gate static variable_t *find_var __P((char *));
197c478bd9Sstevel@tonic-gate static char *expand_string __P((char *, int));
207c478bd9Sstevel@tonic-gate
217c478bd9Sstevel@tonic-gate
find_var(name)227c478bd9Sstevel@tonic-gate static variable_t *find_var(name)
237c478bd9Sstevel@tonic-gate char *name;
247c478bd9Sstevel@tonic-gate {
257c478bd9Sstevel@tonic-gate variable_t *v;
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate for (v = vtop; v != NULL; v = v->v_next)
287c478bd9Sstevel@tonic-gate if (!strcmp(name, v->v_name))
297c478bd9Sstevel@tonic-gate return v;
307c478bd9Sstevel@tonic-gate return NULL;
317c478bd9Sstevel@tonic-gate }
327c478bd9Sstevel@tonic-gate
337c478bd9Sstevel@tonic-gate
get_variable(string,after,line)347c478bd9Sstevel@tonic-gate char *get_variable(string, after, line)
357c478bd9Sstevel@tonic-gate char *string, **after;
367c478bd9Sstevel@tonic-gate int line;
377c478bd9Sstevel@tonic-gate {
387c478bd9Sstevel@tonic-gate char c, *s, *t, *value;
397c478bd9Sstevel@tonic-gate variable_t *v;
407c478bd9Sstevel@tonic-gate
417c478bd9Sstevel@tonic-gate s = string;
427c478bd9Sstevel@tonic-gate
437c478bd9Sstevel@tonic-gate if (*s == '{') {
447c478bd9Sstevel@tonic-gate s++;
457c478bd9Sstevel@tonic-gate for (t = s; *t != '\0'; t++)
467c478bd9Sstevel@tonic-gate if (*t == '}')
477c478bd9Sstevel@tonic-gate break;
487c478bd9Sstevel@tonic-gate if (*t == '\0') {
497c478bd9Sstevel@tonic-gate fprintf(stderr, "%d: { without }\n", line);
507c478bd9Sstevel@tonic-gate return NULL;
517c478bd9Sstevel@tonic-gate }
52*ab25eeb5Syz155240 } else if (ISALPHA(*s)) {
537c478bd9Sstevel@tonic-gate for (t = s + 1; *t != '\0'; t++)
54*ab25eeb5Syz155240 if (!ISALPHA(*t) && !ISDIGIT(*t) && (*t != '_'))
557c478bd9Sstevel@tonic-gate break;
567c478bd9Sstevel@tonic-gate } else {
577c478bd9Sstevel@tonic-gate fprintf(stderr, "%d: variables cannot start with '%c'\n",
587c478bd9Sstevel@tonic-gate line, *s);
597c478bd9Sstevel@tonic-gate return NULL;
607c478bd9Sstevel@tonic-gate }
617c478bd9Sstevel@tonic-gate
627c478bd9Sstevel@tonic-gate if (after != NULL)
637c478bd9Sstevel@tonic-gate *after = t;
647c478bd9Sstevel@tonic-gate c = *t;
657c478bd9Sstevel@tonic-gate *t = '\0';
667c478bd9Sstevel@tonic-gate v = find_var(s);
677c478bd9Sstevel@tonic-gate *t = c;
687c478bd9Sstevel@tonic-gate if (v == NULL) {
697c478bd9Sstevel@tonic-gate fprintf(stderr, "%d: unknown variable '%s'\n", line, s);
707c478bd9Sstevel@tonic-gate return NULL;
717c478bd9Sstevel@tonic-gate }
727c478bd9Sstevel@tonic-gate
737c478bd9Sstevel@tonic-gate s = strdup(v->v_value);
747c478bd9Sstevel@tonic-gate value = expand_string(s, line);
757c478bd9Sstevel@tonic-gate if (value != s)
767c478bd9Sstevel@tonic-gate free(s);
777c478bd9Sstevel@tonic-gate return value;
787c478bd9Sstevel@tonic-gate }
797c478bd9Sstevel@tonic-gate
807c478bd9Sstevel@tonic-gate
expand_string(oldstring,line)817c478bd9Sstevel@tonic-gate static char *expand_string(oldstring, line)
827c478bd9Sstevel@tonic-gate char *oldstring;
837c478bd9Sstevel@tonic-gate int line;
847c478bd9Sstevel@tonic-gate {
857c478bd9Sstevel@tonic-gate char c, *s, *p1, *p2, *p3, *newstring, *value;
867c478bd9Sstevel@tonic-gate int len;
877c478bd9Sstevel@tonic-gate
887c478bd9Sstevel@tonic-gate p3 = NULL;
897c478bd9Sstevel@tonic-gate newstring = oldstring;
907c478bd9Sstevel@tonic-gate
917c478bd9Sstevel@tonic-gate for (s = oldstring; *s != '\0'; s++)
927c478bd9Sstevel@tonic-gate if (*s == '$') {
937c478bd9Sstevel@tonic-gate *s = '\0';
947c478bd9Sstevel@tonic-gate s++;
957c478bd9Sstevel@tonic-gate
967c478bd9Sstevel@tonic-gate switch (*s)
977c478bd9Sstevel@tonic-gate {
987c478bd9Sstevel@tonic-gate case '$' :
997c478bd9Sstevel@tonic-gate bcopy(s, s - 1, strlen(s));
1007c478bd9Sstevel@tonic-gate break;
1017c478bd9Sstevel@tonic-gate default :
1027c478bd9Sstevel@tonic-gate c = *s;
103*ab25eeb5Syz155240 if (c == '\0')
104*ab25eeb5Syz155240 return newstring;
105*ab25eeb5Syz155240
1067c478bd9Sstevel@tonic-gate value = get_variable(s, &p3, line);
1077c478bd9Sstevel@tonic-gate if (value == NULL)
1087c478bd9Sstevel@tonic-gate return NULL;
1097c478bd9Sstevel@tonic-gate
1107c478bd9Sstevel@tonic-gate p2 = expand_string(value, line);
1117c478bd9Sstevel@tonic-gate if (p2 == NULL)
1127c478bd9Sstevel@tonic-gate return NULL;
1137c478bd9Sstevel@tonic-gate
1147c478bd9Sstevel@tonic-gate len = strlen(newstring) + strlen(p2);
1157c478bd9Sstevel@tonic-gate if (p3 != NULL) {
1167c478bd9Sstevel@tonic-gate if (c == '{' && *p3 == '}')
1177c478bd9Sstevel@tonic-gate p3++;
1187c478bd9Sstevel@tonic-gate len += strlen(p3);
1197c478bd9Sstevel@tonic-gate }
1207c478bd9Sstevel@tonic-gate p1 = malloc(len + 1);
1217c478bd9Sstevel@tonic-gate if (p1 == NULL)
1227c478bd9Sstevel@tonic-gate return NULL;
1237c478bd9Sstevel@tonic-gate
1247c478bd9Sstevel@tonic-gate *(s - 1) = '\0';
1257c478bd9Sstevel@tonic-gate strcpy(p1, newstring);
1267c478bd9Sstevel@tonic-gate strcat(p1, p2);
1277c478bd9Sstevel@tonic-gate if (p3 != NULL)
1287c478bd9Sstevel@tonic-gate strcat(p1, p3);
1297c478bd9Sstevel@tonic-gate
130*ab25eeb5Syz155240 s = p1 + len - strlen(p3) - 1;
1317c478bd9Sstevel@tonic-gate if (newstring != oldstring)
1327c478bd9Sstevel@tonic-gate free(newstring);
1337c478bd9Sstevel@tonic-gate newstring = p1;
1347c478bd9Sstevel@tonic-gate break;
1357c478bd9Sstevel@tonic-gate }
1367c478bd9Sstevel@tonic-gate }
1377c478bd9Sstevel@tonic-gate return newstring;
1387c478bd9Sstevel@tonic-gate }
1397c478bd9Sstevel@tonic-gate
1407c478bd9Sstevel@tonic-gate
set_variable(name,value)1417c478bd9Sstevel@tonic-gate void set_variable(name, value)
1427c478bd9Sstevel@tonic-gate char *name;
1437c478bd9Sstevel@tonic-gate char *value;
1447c478bd9Sstevel@tonic-gate {
1457c478bd9Sstevel@tonic-gate variable_t *v;
1467c478bd9Sstevel@tonic-gate int len;
1477c478bd9Sstevel@tonic-gate
1487c478bd9Sstevel@tonic-gate if (name == NULL || value == NULL || *name == '\0')
1497c478bd9Sstevel@tonic-gate return;
1507c478bd9Sstevel@tonic-gate
1517c478bd9Sstevel@tonic-gate v = find_var(name);
1527c478bd9Sstevel@tonic-gate if (v != NULL) {
1537c478bd9Sstevel@tonic-gate free(v->v_value);
1547c478bd9Sstevel@tonic-gate v->v_value = strdup(value);
1557c478bd9Sstevel@tonic-gate return;
1567c478bd9Sstevel@tonic-gate }
1577c478bd9Sstevel@tonic-gate
1587c478bd9Sstevel@tonic-gate len = strlen(value);
1597c478bd9Sstevel@tonic-gate
1607c478bd9Sstevel@tonic-gate if ((*value == '"' && value[len - 1] == '"') ||
1617c478bd9Sstevel@tonic-gate (*value == '\'' && value[len - 1] == '\'')) {
1627c478bd9Sstevel@tonic-gate value[len - 1] = '\0';
1637c478bd9Sstevel@tonic-gate value++;
1647c478bd9Sstevel@tonic-gate len -=2;
1657c478bd9Sstevel@tonic-gate }
1667c478bd9Sstevel@tonic-gate
1677c478bd9Sstevel@tonic-gate v = (variable_t *)malloc(sizeof(*v));
1687c478bd9Sstevel@tonic-gate if (v == NULL)
1697c478bd9Sstevel@tonic-gate return;
1707c478bd9Sstevel@tonic-gate v->v_name = strdup(name);
1717c478bd9Sstevel@tonic-gate v->v_value = strdup(value);
1727c478bd9Sstevel@tonic-gate v->v_next = vtop;
1737c478bd9Sstevel@tonic-gate vtop = v;
1747c478bd9Sstevel@tonic-gate }
175