141edb306SCy Schubert
241edb306SCy Schubert /*
341edb306SCy Schubert * Copyright (C) 2012 by Darren Reed.
441edb306SCy Schubert *
541edb306SCy Schubert * See the IPFILTER.LICENCE file for details on licencing.
641edb306SCy Schubert *
741edb306SCy Schubert * $Id$
841edb306SCy Schubert */
941edb306SCy Schubert
1041edb306SCy Schubert #include <ctype.h>
1141edb306SCy Schubert
1241edb306SCy Schubert #include "ipf.h"
1341edb306SCy Schubert
1441edb306SCy Schubert typedef struct variable {
1541edb306SCy Schubert struct variable *v_next;
1641edb306SCy Schubert char *v_name;
1741edb306SCy Schubert char *v_value;
1841edb306SCy Schubert } variable_t;
1941edb306SCy Schubert
2041edb306SCy Schubert static variable_t *vtop = NULL;
2141edb306SCy Schubert
2241edb306SCy Schubert static variable_t *find_var(char *);
2341edb306SCy Schubert static char *expand_string(char *, int);
2441edb306SCy Schubert
2541edb306SCy Schubert
find_var(char * name)262ac057ddSJohn Baldwin static variable_t *find_var(char *name)
2741edb306SCy Schubert {
2841edb306SCy Schubert variable_t *v;
2941edb306SCy Schubert
3041edb306SCy Schubert for (v = vtop; v != NULL; v = v->v_next)
3141edb306SCy Schubert if (!strcmp(name, v->v_name))
322582ae57SCy Schubert return (v);
332582ae57SCy Schubert return (NULL);
3441edb306SCy Schubert }
3541edb306SCy Schubert
3641edb306SCy Schubert
get_variable(char * string,char ** after,int line)37efeb8bffSCy Schubert char *get_variable(char *string, char **after, int line)
3841edb306SCy Schubert {
3941edb306SCy Schubert char c, *s, *t, *value;
4041edb306SCy Schubert variable_t *v;
4141edb306SCy Schubert
4241edb306SCy Schubert s = string;
4341edb306SCy Schubert
4441edb306SCy Schubert if (*s == '{') {
4541edb306SCy Schubert s++;
4641edb306SCy Schubert for (t = s; *t != '\0'; t++)
4741edb306SCy Schubert if (*t == '}')
4841edb306SCy Schubert break;
4941edb306SCy Schubert if (*t == '\0') {
5041edb306SCy Schubert fprintf(stderr, "%d: { without }\n", line);
512582ae57SCy Schubert return (NULL);
5241edb306SCy Schubert }
5341edb306SCy Schubert } else if (ISALPHA(*s)) {
5441edb306SCy Schubert for (t = s + 1; *t != '\0'; t++)
5541edb306SCy Schubert if (!ISALPHA(*t) && !ISDIGIT(*t) && (*t != '_'))
5641edb306SCy Schubert break;
5741edb306SCy Schubert } else {
5841edb306SCy Schubert fprintf(stderr, "%d: variables cannot start with '%c'\n",
5941edb306SCy Schubert line, *s);
602582ae57SCy Schubert return (NULL);
6141edb306SCy Schubert }
6241edb306SCy Schubert
6341edb306SCy Schubert if (after != NULL)
6441edb306SCy Schubert *after = t;
6541edb306SCy Schubert c = *t;
6641edb306SCy Schubert *t = '\0';
6741edb306SCy Schubert v = find_var(s);
6841edb306SCy Schubert *t = c;
6941edb306SCy Schubert if (v == NULL) {
7041edb306SCy Schubert fprintf(stderr, "%d: unknown variable '%s'\n", line, s);
712582ae57SCy Schubert return (NULL);
7241edb306SCy Schubert }
7341edb306SCy Schubert
7441edb306SCy Schubert s = strdup(v->v_value);
7541edb306SCy Schubert value = expand_string(s, line);
7641edb306SCy Schubert if (value != s)
7741edb306SCy Schubert free(s);
782582ae57SCy Schubert return (value);
7941edb306SCy Schubert }
8041edb306SCy Schubert
8141edb306SCy Schubert
expand_string(char * oldstring,int line)82efeb8bffSCy Schubert static char *expand_string(char *oldstring, int line)
8341edb306SCy Schubert {
8441edb306SCy Schubert char c, *s, *p1, *p2, *p3, *newstring, *value;
8541edb306SCy Schubert int len;
8641edb306SCy Schubert
8741edb306SCy Schubert p3 = NULL;
8841edb306SCy Schubert newstring = oldstring;
8941edb306SCy Schubert
9041edb306SCy Schubert for (s = oldstring; *s != '\0'; s++)
9141edb306SCy Schubert if (*s == '$') {
9241edb306SCy Schubert *s = '\0';
9341edb306SCy Schubert s++;
9441edb306SCy Schubert
9541edb306SCy Schubert switch (*s)
9641edb306SCy Schubert {
9741edb306SCy Schubert case '$' :
9841edb306SCy Schubert bcopy(s, s - 1, strlen(s));
9941edb306SCy Schubert break;
10041edb306SCy Schubert default :
10141edb306SCy Schubert c = *s;
10241edb306SCy Schubert if (c == '\0')
1032582ae57SCy Schubert return (newstring);
10441edb306SCy Schubert
10541edb306SCy Schubert value = get_variable(s, &p3, line);
10641edb306SCy Schubert if (value == NULL)
1072582ae57SCy Schubert return (NULL);
10841edb306SCy Schubert
10941edb306SCy Schubert p2 = expand_string(value, line);
11041edb306SCy Schubert if (p2 == NULL)
1112582ae57SCy Schubert return (NULL);
11241edb306SCy Schubert
11341edb306SCy Schubert len = strlen(newstring) + strlen(p2);
11441edb306SCy Schubert if (p3 != NULL) {
11541edb306SCy Schubert if (c == '{' && *p3 == '}')
11641edb306SCy Schubert p3++;
11741edb306SCy Schubert len += strlen(p3);
11841edb306SCy Schubert }
11941edb306SCy Schubert p1 = malloc(len + 1);
12041edb306SCy Schubert if (p1 == NULL)
1212582ae57SCy Schubert return (NULL);
12241edb306SCy Schubert
12341edb306SCy Schubert *(s - 1) = '\0';
12441edb306SCy Schubert strcpy(p1, newstring);
12541edb306SCy Schubert strcat(p1, p2);
12641edb306SCy Schubert if (p3 != NULL)
12741edb306SCy Schubert strcat(p1, p3);
12841edb306SCy Schubert
12941edb306SCy Schubert s = p1 + len - strlen(p3) - 1;
13041edb306SCy Schubert if (newstring != oldstring)
13141edb306SCy Schubert free(newstring);
13241edb306SCy Schubert newstring = p1;
13341edb306SCy Schubert break;
13441edb306SCy Schubert }
13541edb306SCy Schubert }
1362582ae57SCy Schubert return (newstring);
13741edb306SCy Schubert }
13841edb306SCy Schubert
13941edb306SCy Schubert
set_variable(char * name,char * value)140efeb8bffSCy Schubert void set_variable(char *name, char *value)
14141edb306SCy Schubert {
14241edb306SCy Schubert variable_t *v;
14341edb306SCy Schubert int len;
14441edb306SCy Schubert
14541edb306SCy Schubert if (name == NULL || value == NULL || *name == '\0')
14641edb306SCy Schubert return;
14741edb306SCy Schubert
14841edb306SCy Schubert v = find_var(name);
14941edb306SCy Schubert if (v != NULL) {
15041edb306SCy Schubert free(v->v_value);
15141edb306SCy Schubert v->v_value = strdup(value);
15241edb306SCy Schubert return;
15341edb306SCy Schubert }
15441edb306SCy Schubert
15541edb306SCy Schubert len = strlen(value);
15641edb306SCy Schubert
15741edb306SCy Schubert if ((*value == '"' && value[len - 1] == '"') ||
15841edb306SCy Schubert (*value == '\'' && value[len - 1] == '\'')) {
15941edb306SCy Schubert value[len - 1] = '\0';
16041edb306SCy Schubert value++;
16141edb306SCy Schubert len -=2;
16241edb306SCy Schubert }
16341edb306SCy Schubert
16441edb306SCy Schubert v = (variable_t *)malloc(sizeof(*v));
16541edb306SCy Schubert if (v == NULL)
16641edb306SCy Schubert return;
16741edb306SCy Schubert v->v_name = strdup(name);
16841edb306SCy Schubert v->v_value = strdup(value);
16941edb306SCy Schubert v->v_next = vtop;
17041edb306SCy Schubert vtop = v;
17141edb306SCy Schubert }
172