var.c revision 255332
1251767Sgibbs/* $FreeBSD: head/contrib/ipfilter/lib/var.c 255332 2013-09-06 23:11:19Z cy $ */ 2251767Sgibbs 3251767Sgibbs/* 4251767Sgibbs * Copyright (C) 2012 by Darren Reed. 5251767Sgibbs * 6251767Sgibbs * See the IPFILTER.LICENCE file for details on licencing. 7251767Sgibbs * 8251767Sgibbs * $Id$ 9251767Sgibbs */ 10251767Sgibbs 11251767Sgibbs#include <ctype.h> 12251767Sgibbs 13251767Sgibbs#include "ipf.h" 14251767Sgibbs 15251767Sgibbstypedef struct variable { 16251767Sgibbs struct variable *v_next; 17251767Sgibbs char *v_name; 18251767Sgibbs char *v_value; 19251767Sgibbs} variable_t; 20251767Sgibbs 21251767Sgibbsstatic variable_t *vtop = NULL; 22251767Sgibbs 23251767Sgibbsstatic variable_t *find_var __P((char *)); 24251767Sgibbsstatic char *expand_string __P((char *, int)); 25251767Sgibbs 26251767Sgibbs 27251767Sgibbsstatic variable_t *find_var(name) 28251767Sgibbs char *name; 29251767Sgibbs{ 30251767Sgibbs variable_t *v; 31251767Sgibbs 32251767Sgibbs for (v = vtop; v != NULL; v = v->v_next) 33251767Sgibbs if (!strcmp(name, v->v_name)) 34251767Sgibbs return v; 35251767Sgibbs return NULL; 36251767Sgibbs} 37251767Sgibbs 38251767Sgibbs 39251767Sgibbschar *get_variable(string, after, line) 40251767Sgibbs char *string, **after; 41251767Sgibbs int line; 42251767Sgibbs{ 43251767Sgibbs char c, *s, *t, *value; 44251767Sgibbs variable_t *v; 45251767Sgibbs 46251767Sgibbs s = string; 47251767Sgibbs 48251767Sgibbs if (*s == '{') { 49251767Sgibbs s++; 50251767Sgibbs for (t = s; *t != '\0'; t++) 51251767Sgibbs if (*t == '}') 52251767Sgibbs break; 53251767Sgibbs if (*t == '\0') { 54251767Sgibbs fprintf(stderr, "%d: { without }\n", line); 55251767Sgibbs return NULL; 56251767Sgibbs } 57251767Sgibbs } else if (ISALPHA(*s)) { 58251767Sgibbs for (t = s + 1; *t != '\0'; t++) 59251767Sgibbs if (!ISALPHA(*t) && !ISDIGIT(*t) && (*t != '_')) 60251767Sgibbs break; 61251767Sgibbs } else { 62251767Sgibbs fprintf(stderr, "%d: variables cannot start with '%c'\n", 63251767Sgibbs line, *s); 64251767Sgibbs return NULL; 65251767Sgibbs } 66251767Sgibbs 67251767Sgibbs if (after != NULL) 68251767Sgibbs *after = t; 69251767Sgibbs c = *t; 70251767Sgibbs *t = '\0'; 71251767Sgibbs v = find_var(s); 72251767Sgibbs *t = c; 73251767Sgibbs if (v == NULL) { 74251767Sgibbs fprintf(stderr, "%d: unknown variable '%s'\n", line, s); 75251767Sgibbs return NULL; 76251767Sgibbs } 77251767Sgibbs 78251767Sgibbs s = strdup(v->v_value); 79251767Sgibbs value = expand_string(s, line); 80251767Sgibbs if (value != s) 81251767Sgibbs free(s); 82251767Sgibbs return value; 83251767Sgibbs} 84251767Sgibbs 85251767Sgibbs 86251767Sgibbsstatic char *expand_string(oldstring, line) 87251767Sgibbs char *oldstring; 88251767Sgibbs int line; 89251767Sgibbs{ 90251767Sgibbs char c, *s, *p1, *p2, *p3, *newstring, *value; 91251767Sgibbs int len; 92251767Sgibbs 93251767Sgibbs p3 = NULL; 94251767Sgibbs newstring = oldstring; 95251767Sgibbs 96251767Sgibbs for (s = oldstring; *s != '\0'; s++) 97251767Sgibbs if (*s == '$') { 98251767Sgibbs *s = '\0'; 99251767Sgibbs s++; 100251767Sgibbs 101251767Sgibbs switch (*s) 102251767Sgibbs { 103251767Sgibbs case '$' : 104251767Sgibbs bcopy(s, s - 1, strlen(s)); 105251767Sgibbs break; 106251767Sgibbs default : 107251767Sgibbs c = *s; 108251767Sgibbs if (c == '\0') 109251767Sgibbs return newstring; 110251767Sgibbs 111251767Sgibbs value = get_variable(s, &p3, line); 112251767Sgibbs if (value == NULL) 113251767Sgibbs return NULL; 114251767Sgibbs 115251767Sgibbs p2 = expand_string(value, line); 116251767Sgibbs if (p2 == NULL) 117251767Sgibbs return NULL; 118251767Sgibbs 119251767Sgibbs len = strlen(newstring) + strlen(p2); 120251767Sgibbs if (p3 != NULL) { 121251767Sgibbs if (c == '{' && *p3 == '}') 122251767Sgibbs p3++; 123251767Sgibbs len += strlen(p3); 124251767Sgibbs } 125251767Sgibbs p1 = malloc(len + 1); 126251767Sgibbs if (p1 == NULL) 127251767Sgibbs return NULL; 128251767Sgibbs 129251767Sgibbs *(s - 1) = '\0'; 130251767Sgibbs strcpy(p1, newstring); 131251767Sgibbs strcat(p1, p2); 132251767Sgibbs if (p3 != NULL) 133251767Sgibbs strcat(p1, p3); 134251767Sgibbs 135251767Sgibbs s = p1 + len - strlen(p3) - 1; 136251767Sgibbs if (newstring != oldstring) 137251767Sgibbs free(newstring); 138251767Sgibbs newstring = p1; 139251767Sgibbs break; 140251767Sgibbs } 141251767Sgibbs } 142251767Sgibbs return newstring; 143251767Sgibbs} 144251767Sgibbs 145251767Sgibbs 146251767Sgibbsvoid set_variable(name, value) 147251767Sgibbs char *name; 148251767Sgibbs char *value; 149251767Sgibbs{ 150251767Sgibbs variable_t *v; 151251767Sgibbs int len; 152251767Sgibbs 153251767Sgibbs if (name == NULL || value == NULL || *name == '\0') 154251767Sgibbs return; 155251767Sgibbs 156251767Sgibbs v = find_var(name); 157251767Sgibbs if (v != NULL) { 158251767Sgibbs free(v->v_value); 159251767Sgibbs v->v_value = strdup(value); 160251767Sgibbs return; 161251767Sgibbs } 162251767Sgibbs 163251767Sgibbs len = strlen(value); 164251767Sgibbs 165251767Sgibbs if ((*value == '"' && value[len - 1] == '"') || 166251767Sgibbs (*value == '\'' && value[len - 1] == '\'')) { 167251767Sgibbs value[len - 1] = '\0'; 168251767Sgibbs value++; 169251767Sgibbs len -=2; 170251767Sgibbs } 171251767Sgibbs 172251767Sgibbs v = (variable_t *)malloc(sizeof(*v)); 173251767Sgibbs if (v == NULL) 174251767Sgibbs return; 175251767Sgibbs v->v_name = strdup(name); 176251767Sgibbs v->v_value = strdup(value); 177251767Sgibbs v->v_next = vtop; 178251767Sgibbs vtop = v; 179251767Sgibbs} 180251767Sgibbs