xref: /illumos-gate/usr/src/cmd/ipf/lib/common/var.c (revision ab25eeb5)
1*ab25eeb5Syz /*
2*ab25eeb5Syz  * Copyright (C) 1993-2005  by Darren Reed.
3*ab25eeb5Syz  * See the IPFILTER.LICENCE file for details on licencing.
4*ab25eeb5Syz  */
5*ab25eeb5Syz 
67c478bd9Sstevel@tonic-gate #include <ctype.h>
77c478bd9Sstevel@tonic-gate 
87c478bd9Sstevel@tonic-gate #include "ipf.h"
97c478bd9Sstevel@tonic-gate 
107c478bd9Sstevel@tonic-gate typedef	struct	variable	{
117c478bd9Sstevel@tonic-gate 	struct	variable	*v_next;
127c478bd9Sstevel@tonic-gate 	char	*v_name;
137c478bd9Sstevel@tonic-gate 	char	*v_value;
147c478bd9Sstevel@tonic-gate } variable_t;
157c478bd9Sstevel@tonic-gate 
167c478bd9Sstevel@tonic-gate static	variable_t	*vtop = NULL;
177c478bd9Sstevel@tonic-gate 
187c478bd9Sstevel@tonic-gate static variable_t *find_var __P((char *));
197c478bd9Sstevel@tonic-gate static char *expand_string __P((char *, int));
207c478bd9Sstevel@tonic-gate 
217c478bd9Sstevel@tonic-gate 
find_var(name)227c478bd9Sstevel@tonic-gate static variable_t *find_var(name)
237c478bd9Sstevel@tonic-gate char *name;
247c478bd9Sstevel@tonic-gate {
257c478bd9Sstevel@tonic-gate 	variable_t *v;
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate 	for (v = vtop; v != NULL; v = v->v_next)
287c478bd9Sstevel@tonic-gate 		if (!strcmp(name, v->v_name))
297c478bd9Sstevel@tonic-gate 			return v;
307c478bd9Sstevel@tonic-gate 	return NULL;
317c478bd9Sstevel@tonic-gate }
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate 
get_variable(string,after,line)347c478bd9Sstevel@tonic-gate char *get_variable(string, after, line)
357c478bd9Sstevel@tonic-gate char *string, **after;
367c478bd9Sstevel@tonic-gate int line;
377c478bd9Sstevel@tonic-gate {
387c478bd9Sstevel@tonic-gate 	char c, *s, *t, *value;
397c478bd9Sstevel@tonic-gate 	variable_t *v;
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate 	s = string;
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate 	if (*s == '{') {
447c478bd9Sstevel@tonic-gate 		s++;
457c478bd9Sstevel@tonic-gate 		for (t = s; *t != '\0'; t++)
467c478bd9Sstevel@tonic-gate 			if (*t == '}')
477c478bd9Sstevel@tonic-gate 				break;
487c478bd9Sstevel@tonic-gate 		if (*t == '\0') {
497c478bd9Sstevel@tonic-gate 			fprintf(stderr, "%d: { without }\n", line);
507c478bd9Sstevel@tonic-gate 			return NULL;
517c478bd9Sstevel@tonic-gate 		}
52*ab25eeb5Syz 	} else if (ISALPHA(*s)) {
537c478bd9Sstevel@tonic-gate 		for (t = s + 1; *t != '\0'; t++)
54*ab25eeb5Syz 			if (!ISALPHA(*t) && !ISDIGIT(*t) && (*t != '_'))
557c478bd9Sstevel@tonic-gate 				break;
567c478bd9Sstevel@tonic-gate 	} else {
577c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%d: variables cannot start with '%c'\n",
587c478bd9Sstevel@tonic-gate 			line, *s);
597c478bd9Sstevel@tonic-gate 		return NULL;
607c478bd9Sstevel@tonic-gate 	}
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate 	if (after != NULL)
637c478bd9Sstevel@tonic-gate 		*after = t;
647c478bd9Sstevel@tonic-gate 	c = *t;
657c478bd9Sstevel@tonic-gate 	*t = '\0';
667c478bd9Sstevel@tonic-gate 	v = find_var(s);
677c478bd9Sstevel@tonic-gate 	*t = c;
687c478bd9Sstevel@tonic-gate 	if (v == NULL) {
697c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%d: unknown variable '%s'\n", line, s);
707c478bd9Sstevel@tonic-gate 		return NULL;
717c478bd9Sstevel@tonic-gate 	}
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate 	s = strdup(v->v_value);
747c478bd9Sstevel@tonic-gate 	value = expand_string(s, line);
757c478bd9Sstevel@tonic-gate 	if (value != s)
767c478bd9Sstevel@tonic-gate 		free(s);
777c478bd9Sstevel@tonic-gate 	return value;
787c478bd9Sstevel@tonic-gate }
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate 
expand_string(oldstring,line)817c478bd9Sstevel@tonic-gate static char *expand_string(oldstring, line)
827c478bd9Sstevel@tonic-gate char *oldstring;
837c478bd9Sstevel@tonic-gate int line;
847c478bd9Sstevel@tonic-gate {
857c478bd9Sstevel@tonic-gate 	char c, *s, *p1, *p2, *p3, *newstring, *value;
867c478bd9Sstevel@tonic-gate 	int len;
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate 	p3 = NULL;
897c478bd9Sstevel@tonic-gate 	newstring = oldstring;
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate 	for (s = oldstring; *s != '\0'; s++)
927c478bd9Sstevel@tonic-gate 		if (*s == '$') {
937c478bd9Sstevel@tonic-gate 			*s = '\0';
947c478bd9Sstevel@tonic-gate 			s++;
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate 			switch (*s)
977c478bd9Sstevel@tonic-gate 			{
987c478bd9Sstevel@tonic-gate 			case '$' :
997c478bd9Sstevel@tonic-gate 				bcopy(s, s - 1, strlen(s));
1007c478bd9Sstevel@tonic-gate 				break;
1017c478bd9Sstevel@tonic-gate 			default :
1027c478bd9Sstevel@tonic-gate 				c = *s;
103*ab25eeb5Syz 				if (c == '\0')
104*ab25eeb5Syz 					return newstring;
105*ab25eeb5Syz 
1067c478bd9Sstevel@tonic-gate 				value = get_variable(s, &p3, line);
1077c478bd9Sstevel@tonic-gate 				if (value == NULL)
1087c478bd9Sstevel@tonic-gate 					return NULL;
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate 				p2 = expand_string(value, line);
1117c478bd9Sstevel@tonic-gate 				if (p2 == NULL)
1127c478bd9Sstevel@tonic-gate 					return NULL;
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate 				len = strlen(newstring) + strlen(p2);
1157c478bd9Sstevel@tonic-gate 				if (p3 != NULL) {
1167c478bd9Sstevel@tonic-gate 					if (c == '{' && *p3 == '}')
1177c478bd9Sstevel@tonic-gate 						p3++;
1187c478bd9Sstevel@tonic-gate 					len += strlen(p3);
1197c478bd9Sstevel@tonic-gate 				}
1207c478bd9Sstevel@tonic-gate 				p1 = malloc(len + 1);
1217c478bd9Sstevel@tonic-gate 				if (p1 == NULL)
1227c478bd9Sstevel@tonic-gate 					return NULL;
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 				*(s - 1) = '\0';
1257c478bd9Sstevel@tonic-gate 				strcpy(p1, newstring);
1267c478bd9Sstevel@tonic-gate 				strcat(p1, p2);
1277c478bd9Sstevel@tonic-gate 				if (p3 != NULL)
1287c478bd9Sstevel@tonic-gate 					strcat(p1, p3);
1297c478bd9Sstevel@tonic-gate 
130*ab25eeb5Syz 				s = p1 + len - strlen(p3) - 1;
1317c478bd9Sstevel@tonic-gate 				if (newstring != oldstring)
1327c478bd9Sstevel@tonic-gate 					free(newstring);
1337c478bd9Sstevel@tonic-gate 				newstring = p1;
1347c478bd9Sstevel@tonic-gate 				break;
1357c478bd9Sstevel@tonic-gate 			}
1367c478bd9Sstevel@tonic-gate 		}
1377c478bd9Sstevel@tonic-gate 	return newstring;
1387c478bd9Sstevel@tonic-gate }
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate 
set_variable(name,value)1417c478bd9Sstevel@tonic-gate void set_variable(name, value)
1427c478bd9Sstevel@tonic-gate char *name;
1437c478bd9Sstevel@tonic-gate char *value;
1447c478bd9Sstevel@tonic-gate {
1457c478bd9Sstevel@tonic-gate 	variable_t *v;
1467c478bd9Sstevel@tonic-gate 	int len;
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 	if (name == NULL || value == NULL || *name == '\0')
1497c478bd9Sstevel@tonic-gate 		return;
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate 	v = find_var(name);
1527c478bd9Sstevel@tonic-gate 	if (v != NULL) {
1537c478bd9Sstevel@tonic-gate 		free(v->v_value);
1547c478bd9Sstevel@tonic-gate 		v->v_value = strdup(value);
1557c478bd9Sstevel@tonic-gate 		return;
1567c478bd9Sstevel@tonic-gate 	}
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate 	len = strlen(value);
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate 	if ((*value == '"' && value[len - 1] == '"') ||
1617c478bd9Sstevel@tonic-gate 	    (*value == '\'' && value[len - 1] == '\'')) {
1627c478bd9Sstevel@tonic-gate 		value[len - 1] = '\0';
1637c478bd9Sstevel@tonic-gate 		value++;
1647c478bd9Sstevel@tonic-gate 		len -=2;
1657c478bd9Sstevel@tonic-gate 	}
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate 	v = (variable_t *)malloc(sizeof(*v));
1687c478bd9Sstevel@tonic-gate 	if (v == NULL)
1697c478bd9Sstevel@tonic-gate 		return;
1707c478bd9Sstevel@tonic-gate 	v->v_name = strdup(name);
1717c478bd9Sstevel@tonic-gate 	v->v_value = strdup(value);
1727c478bd9Sstevel@tonic-gate 	v->v_next = vtop;
1737c478bd9Sstevel@tonic-gate 	vtop = v;
1747c478bd9Sstevel@tonic-gate }
175