xref: /freebsd/sbin/ipf/libipf/var.c (revision 2a63c3be)
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