1145519Sdarrenr/* $FreeBSD$ */ 2145510Sdarrenr 3170268Sdarrenr/* 4255332Scy * Copyright (C) 2012 by Darren Reed. 5255332Scy * 6255332Scy * See the IPFILTER.LICENCE file for details on licencing. 7255332Scy * 8255332Scy * $Id$ 9255332Scy */ 10170268Sdarrenr 11145510Sdarrenr#include <ctype.h> 12145510Sdarrenr 13145510Sdarrenr#include "ipf.h" 14145510Sdarrenr 15145510Sdarrenrtypedef struct variable { 16145510Sdarrenr struct variable *v_next; 17145510Sdarrenr char *v_name; 18145510Sdarrenr char *v_value; 19145510Sdarrenr} variable_t; 20145510Sdarrenr 21145510Sdarrenrstatic variable_t *vtop = NULL; 22145510Sdarrenr 23145510Sdarrenrstatic variable_t *find_var __P((char *)); 24145510Sdarrenrstatic char *expand_string __P((char *, int)); 25145510Sdarrenr 26145510Sdarrenr 27145510Sdarrenrstatic variable_t *find_var(name) 28255332Scy char *name; 29145510Sdarrenr{ 30145510Sdarrenr variable_t *v; 31145510Sdarrenr 32145510Sdarrenr for (v = vtop; v != NULL; v = v->v_next) 33145510Sdarrenr if (!strcmp(name, v->v_name)) 34145510Sdarrenr return v; 35145510Sdarrenr return NULL; 36145510Sdarrenr} 37145510Sdarrenr 38145510Sdarrenr 39145510Sdarrenrchar *get_variable(string, after, line) 40255332Scy char *string, **after; 41255332Scy int line; 42145510Sdarrenr{ 43145510Sdarrenr char c, *s, *t, *value; 44145510Sdarrenr variable_t *v; 45145510Sdarrenr 46145510Sdarrenr s = string; 47145510Sdarrenr 48145510Sdarrenr if (*s == '{') { 49145510Sdarrenr s++; 50145510Sdarrenr for (t = s; *t != '\0'; t++) 51145510Sdarrenr if (*t == '}') 52145510Sdarrenr break; 53145510Sdarrenr if (*t == '\0') { 54145510Sdarrenr fprintf(stderr, "%d: { without }\n", line); 55145510Sdarrenr return NULL; 56145510Sdarrenr } 57145510Sdarrenr } else if (ISALPHA(*s)) { 58145510Sdarrenr for (t = s + 1; *t != '\0'; t++) 59145510Sdarrenr if (!ISALPHA(*t) && !ISDIGIT(*t) && (*t != '_')) 60145510Sdarrenr break; 61145510Sdarrenr } else { 62145510Sdarrenr fprintf(stderr, "%d: variables cannot start with '%c'\n", 63145510Sdarrenr line, *s); 64145510Sdarrenr return NULL; 65145510Sdarrenr } 66145510Sdarrenr 67145510Sdarrenr if (after != NULL) 68145510Sdarrenr *after = t; 69145510Sdarrenr c = *t; 70145510Sdarrenr *t = '\0'; 71145510Sdarrenr v = find_var(s); 72145510Sdarrenr *t = c; 73145510Sdarrenr if (v == NULL) { 74145510Sdarrenr fprintf(stderr, "%d: unknown variable '%s'\n", line, s); 75145510Sdarrenr return NULL; 76145510Sdarrenr } 77145510Sdarrenr 78145510Sdarrenr s = strdup(v->v_value); 79145510Sdarrenr value = expand_string(s, line); 80145510Sdarrenr if (value != s) 81145510Sdarrenr free(s); 82145510Sdarrenr return value; 83145510Sdarrenr} 84145510Sdarrenr 85145510Sdarrenr 86145510Sdarrenrstatic char *expand_string(oldstring, line) 87255332Scy char *oldstring; 88255332Scy int line; 89145510Sdarrenr{ 90145510Sdarrenr char c, *s, *p1, *p2, *p3, *newstring, *value; 91145510Sdarrenr int len; 92145510Sdarrenr 93145510Sdarrenr p3 = NULL; 94145510Sdarrenr newstring = oldstring; 95145510Sdarrenr 96145510Sdarrenr for (s = oldstring; *s != '\0'; s++) 97145510Sdarrenr if (*s == '$') { 98145510Sdarrenr *s = '\0'; 99145510Sdarrenr s++; 100145510Sdarrenr 101145510Sdarrenr switch (*s) 102145510Sdarrenr { 103145510Sdarrenr case '$' : 104145510Sdarrenr bcopy(s, s - 1, strlen(s)); 105145510Sdarrenr break; 106145510Sdarrenr default : 107145510Sdarrenr c = *s; 108145510Sdarrenr if (c == '\0') 109145510Sdarrenr return newstring; 110145510Sdarrenr 111145510Sdarrenr value = get_variable(s, &p3, line); 112145510Sdarrenr if (value == NULL) 113145510Sdarrenr return NULL; 114145510Sdarrenr 115145510Sdarrenr p2 = expand_string(value, line); 116145510Sdarrenr if (p2 == NULL) 117145510Sdarrenr return NULL; 118145510Sdarrenr 119145510Sdarrenr len = strlen(newstring) + strlen(p2); 120145510Sdarrenr if (p3 != NULL) { 121145510Sdarrenr if (c == '{' && *p3 == '}') 122145510Sdarrenr p3++; 123145510Sdarrenr len += strlen(p3); 124145510Sdarrenr } 125145510Sdarrenr p1 = malloc(len + 1); 126145510Sdarrenr if (p1 == NULL) 127145510Sdarrenr return NULL; 128145510Sdarrenr 129145510Sdarrenr *(s - 1) = '\0'; 130145510Sdarrenr strcpy(p1, newstring); 131145510Sdarrenr strcat(p1, p2); 132145510Sdarrenr if (p3 != NULL) 133145510Sdarrenr strcat(p1, p3); 134145510Sdarrenr 135145510Sdarrenr s = p1 + len - strlen(p3) - 1; 136145510Sdarrenr if (newstring != oldstring) 137145510Sdarrenr free(newstring); 138145510Sdarrenr newstring = p1; 139145510Sdarrenr break; 140145510Sdarrenr } 141145510Sdarrenr } 142145510Sdarrenr return newstring; 143145510Sdarrenr} 144145510Sdarrenr 145145510Sdarrenr 146145510Sdarrenrvoid set_variable(name, value) 147255332Scy char *name; 148255332Scy char *value; 149145510Sdarrenr{ 150145510Sdarrenr variable_t *v; 151145510Sdarrenr int len; 152145510Sdarrenr 153145510Sdarrenr if (name == NULL || value == NULL || *name == '\0') 154145510Sdarrenr return; 155145510Sdarrenr 156145510Sdarrenr v = find_var(name); 157145510Sdarrenr if (v != NULL) { 158145510Sdarrenr free(v->v_value); 159145510Sdarrenr v->v_value = strdup(value); 160145510Sdarrenr return; 161145510Sdarrenr } 162145510Sdarrenr 163145510Sdarrenr len = strlen(value); 164145510Sdarrenr 165145510Sdarrenr if ((*value == '"' && value[len - 1] == '"') || 166145510Sdarrenr (*value == '\'' && value[len - 1] == '\'')) { 167145510Sdarrenr value[len - 1] = '\0'; 168145510Sdarrenr value++; 169145510Sdarrenr len -=2; 170145510Sdarrenr } 171145510Sdarrenr 172145510Sdarrenr v = (variable_t *)malloc(sizeof(*v)); 173145510Sdarrenr if (v == NULL) 174145510Sdarrenr return; 175145510Sdarrenr v->v_name = strdup(name); 176145510Sdarrenr v->v_value = strdup(value); 177145510Sdarrenr v->v_next = vtop; 178145510Sdarrenr vtop = v; 179145510Sdarrenr} 180