diff options
Diffstat (limited to 'contrib/ipfilter/lib/var.c')
-rw-r--r-- | contrib/ipfilter/lib/var.c | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/contrib/ipfilter/lib/var.c b/contrib/ipfilter/lib/var.c new file mode 100644 index 0000000..79b2517 --- /dev/null +++ b/contrib/ipfilter/lib/var.c @@ -0,0 +1,171 @@ +/* $NetBSD$ */ + +#include <ctype.h> + +#include "ipf.h" + +typedef struct variable { + struct variable *v_next; + char *v_name; + char *v_value; +} variable_t; + +static variable_t *vtop = NULL; + +static variable_t *find_var __P((char *)); +static char *expand_string __P((char *, int)); + + +static variable_t *find_var(name) +char *name; +{ + variable_t *v; + + for (v = vtop; v != NULL; v = v->v_next) + if (!strcmp(name, v->v_name)) + return v; + return NULL; +} + + +char *get_variable(string, after, line) +char *string, **after; +int line; +{ + char c, *s, *t, *value; + variable_t *v; + + s = string; + + if (*s == '{') { + s++; + for (t = s; *t != '\0'; t++) + if (*t == '}') + break; + if (*t == '\0') { + fprintf(stderr, "%d: { without }\n", line); + return NULL; + } + } else if (ISALPHA(*s)) { + for (t = s + 1; *t != '\0'; t++) + if (!ISALPHA(*t) && !ISDIGIT(*t) && (*t != '_')) + break; + } else { + fprintf(stderr, "%d: variables cannot start with '%c'\n", + line, *s); + return NULL; + } + + if (after != NULL) + *after = t; + c = *t; + *t = '\0'; + v = find_var(s); + *t = c; + if (v == NULL) { + fprintf(stderr, "%d: unknown variable '%s'\n", line, s); + return NULL; + } + + s = strdup(v->v_value); + value = expand_string(s, line); + if (value != s) + free(s); + return value; +} + + +static char *expand_string(oldstring, line) +char *oldstring; +int line; +{ + char c, *s, *p1, *p2, *p3, *newstring, *value; + int len; + + p3 = NULL; + newstring = oldstring; + + for (s = oldstring; *s != '\0'; s++) + if (*s == '$') { + *s = '\0'; + s++; + + switch (*s) + { + case '$' : + bcopy(s, s - 1, strlen(s)); + break; + default : + c = *s; + if (c == '\0') + return newstring; + + value = get_variable(s, &p3, line); + if (value == NULL) + return NULL; + + p2 = expand_string(value, line); + if (p2 == NULL) + return NULL; + + len = strlen(newstring) + strlen(p2); + if (p3 != NULL) { + if (c == '{' && *p3 == '}') + p3++; + len += strlen(p3); + } + p1 = malloc(len + 1); + if (p1 == NULL) + return NULL; + + *(s - 1) = '\0'; + strcpy(p1, newstring); + strcat(p1, p2); + if (p3 != NULL) + strcat(p1, p3); + + s = p1 + len - strlen(p3) - 1; + if (newstring != oldstring) + free(newstring); + newstring = p1; + break; + } + } + return newstring; +} + + +void set_variable(name, value) +char *name; +char *value; +{ + variable_t *v; + int len; + + if (name == NULL || value == NULL || *name == '\0') + return; + + v = find_var(name); + if (v != NULL) { + free(v->v_value); + v->v_value = strdup(value); + return; + } + + len = strlen(value); + + if ((*value == '"' && value[len - 1] == '"') || + (*value == '\'' && value[len - 1] == '\'')) { + value[len - 1] = '\0'; + value++; + len -=2; + } + + v = (variable_t *)malloc(sizeof(*v)); + if (v == NULL) + return; + v->v_name = strdup(name); + v->v_value = strdup(value); + v->v_next = vtop; + vtop = v; +} |