===================================================================
RCS file: /cvs/cvs/blind/parse.y,v
retrieving revision 1.6
retrieving revision 1.19
diff -u -p -r1.6 -r1.19
--- blind/parse.y	2022/03/20 23:03:01	1.6
+++ blind/parse.y	2022/04/17 21:23:34	1.19
@@ -16,28 +16,17 @@
 
 %{
 #include <sys/queue.h>
-#include <sys/stat.h>
 
-#include <stdio.h>        
-#include <stdarg.h>
-#include <unistd.h>
 #include <ctype.h>
-        
+#include <stdarg.h>
+#include <stdio.h>
+
 #include "blind.h"
+#include "config.h"
 #include "log.h"
 
-TAILQ_HEAD(files, file)		 files = TAILQ_HEAD_INITIALIZER(files);
-static struct file {
-	TAILQ_ENTRY(file)	 entry;
-      	FILE			*stream;
-	char			*name;
-	size_t			 ungetpos;
-	size_t			 ungetsize;
-	u_char			*ungetbuf;
-	int			 eof_reached;
-	int			 lineno;
-	int			 errors;
-} *file, *top;
+#define EXPAND_ON	1
+#define EXPAND_OFF	2
 
 int		lookup(char *);
 int		igetc(void);
@@ -48,32 +37,33 @@ int		kw_cmp(const void *, const void *);
 int		yyparse(void);
 int		yylex(void);
 int		yyerror(const char *, ...)
-        __attribute__((__format__ (printf, 1, 2)))
-        __attribute__((__nonnull__ (1)));
+		__attribute__((__format__ (printf, 1, 2)))
+		__attribute__((__nonnull__ (1)));
 
+int		symset(const char *, const char *, int);
+char	       *symget(const char *);
+
 int		config_load(struct blind *);
-struct file    *config_push(const char *);
-int		config_pop(void);
-int		config_perm(int, const char *);
+int		config_close(void);
 
+static int			expanding;
+static int			errors = 0;
+struct blind		       *env = NULL;
+static struct file	       *f = NULL;
 
-TAILQ_HEAD(symhead, sym)	 symhead = TAILQ_HEAD_INITIALIZER(symhead);
+TAILQ_HEAD(symhead, sym)	symhead = TAILQ_HEAD_INITIALIZER(symhead);
 struct sym {
-	TAILQ_ENTRY(sym)	 entry;
-	int			 used;
-	int			 persist;
-	char			*nam;
-	char			*val;
+	TAILQ_ENTRY(sym)      	entry;
+	int			used;
+	int			persist;
+	char		       *nam;
+	char		       *val;
 };
-char	       *symget(const char *);
 
-struct blind   *env = NULL;
-static int	errors = 0;
-
 typedef struct {
 	union {
-		int64_t	 number;
-		char	*string;
+		int64_t		number;
+		char	       *string;
 	} v;
 	int lineno;
 } YYSTYPE;
@@ -88,26 +78,44 @@ typedef struct {
 
 grammar	:
 	| grammar '\n'
-        | grammar set '\n'
-        | grammar error '\n'	{ file->errors++; }
-        ;
+	| grammar varset '\n'
+	| grammar set '\n'
+	| grammar error '\n'	{ errors++; }
+	;
 
+varset	: STRING '=' STRING {
+		char *s = $1;
+		while (*s++) {
+                        if (isspace((unsigned char)*s)) {
+                                yyerror("macro contain whitespace");
+                                free($1);
+                                free($3);
+                                YYERROR;
+                        }
+                }
+                if (symset($1, $3, 0) == -1)
+                        log_fatal("cannot store variable");
+                free($1);
+                free($3);
+}
+;               
+
 set	: SET EXPIRE NUMBER {
-        env->bl_ttl = $3;
+	env->bl_ttl = $3;
 }
 | SET ACTION ENABLE {
-        env->bl_opt |= BL_OPT_ACTION;
+	env->bl_opt |= BL_OPT_ACTION;
  }
 | SET ACTION DISABLE {
-        env->bl_opt |= !BL_OPT_ACTION;
+	env->bl_opt |= !BL_OPT_ACTION;
  }
 ;
 
 %%
 
 struct keywords {
-	const char	*k_name;
-	int		 k_val;
+	const char	       *k_name;
+	int			k_val;
 };
 
 int
@@ -116,12 +124,12 @@ yyerror(const char *fmt, ...)
 	va_list		 ap;
 	char		*msg;
 
-	file->errors++;
+	errors++;
 	va_start(ap, fmt);
 	if (vasprintf(&msg, fmt, ap) == -1)
 		log_fatal("yyerror vasprintf");
 	va_end(ap);
-        log_info("%s:%d: %s", file->name, yylval.lineno, msg);
+	log_info("%s:%d: %s", f->name, yylval.lineno, msg);
 	free(msg);
 	return (0);
 }
@@ -154,12 +162,46 @@ lookup(char *s)
 		return (STRING);
 }
 
+int
+symset(const char *nam, const char *val, int persist)
+{
+	struct sym	*sym;
 
-#define START_EXPAND	1
-#define DONE_EXPAND	2
+	TAILQ_FOREACH(sym, &symhead, entry) {
+		if (strcmp(nam, sym->nam) == 0)
+			break;
+	}
 
-static int	expanding;
+	if (sym != NULL) {
+		if (sym->persist == 1)
+			return (0);
+		else {
+			free(sym->nam);
+			free(sym->val);
+			TAILQ_REMOVE(&symhead, sym, entry);
+			free(sym);
+		}
+	}
+	if ((sym = calloc(1, sizeof(*sym))) == NULL)
+		return (-1);
 
+	sym->nam = strdup(nam);
+	if (sym->nam == NULL) {
+		free(sym);
+		return (-1);
+	}
+	sym->val = strdup(val);
+	if (sym->val == NULL) {
+		free(sym->nam);
+		free(sym);
+		return (-1);
+	}
+	sym->used = 0;
+	sym->persist = persist;
+	TAILQ_INSERT_TAIL(&symhead, sym, entry);
+	return (0);
+}
+
 char *
 symget(const char *nam)
 {
@@ -180,14 +222,14 @@ igetc(void)
 	int	c;
 
 	while (1) {
-		if (file->ungetpos > 0)
-			c = file->ungetbuf[--file->ungetpos];
+		if (f->unpos > 0)
+			c = f->unbuf[--f->unpos];
 		else
-			c = getc(file->stream);
+			c = getc(f->stream);
 
-		if (c == START_EXPAND)
+		if (c == EXPAND_ON)
 			expanding = 1;
-		else if (c == DONE_EXPAND)
+		else if (c == EXPAND_OFF)
 			expanding = 0;
 		else
 			break;
@@ -204,7 +246,7 @@ lgetc(int quotec)
 		if ((c = igetc()) == EOF) {
 			yyerror("reached end of file while parsing "
 			    "quoted string");
-			if (file == top || config_pop() == EOF)
+                        if (config_close() == EOF)
 				return (EOF);
 			return (quotec);
 		}
@@ -217,8 +259,8 @@ lgetc(int quotec)
 			c = next;
 			break;
 		}
-		yylval.lineno = file->lineno;
-		file->lineno++;
+		yylval.lineno = f->lineno;
+		f->lineno++;
 	}
 
 	if (c == EOF) {
@@ -227,12 +269,12 @@ lgetc(int quotec)
 		 * count right if last line in included file is syntactically
 		 * invalid and has no newline.
 		 */
-		if (file->eof_reached == 0) {
-			file->eof_reached = 1;
+		if (f->eof == 0) {
+			f->eof = 1;
 			return ('\n');
 		}
 		while (c == EOF) {
-			if (file == top || config_pop() == EOF)
+                        if (config_close() == EOF)
 				return (EOF);
 			c = igetc();
 		}
@@ -246,14 +288,14 @@ lungetc(int c)
 	if (c == EOF)
 		return;
 
-	if (file->ungetpos >= file->ungetsize) {
-		void *p = reallocarray(file->ungetbuf, file->ungetsize, 2);
+	if (f->unpos >= f->unsize) {
+		void *p = reallocarray(f->unbuf, f->unsize, 2);
 		if (p == NULL)
 			log_fatal("cannot reallocate memory");
-		file->ungetbuf = p;
-		file->ungetsize *= 2;
+		f->unbuf = p;
+		f->unsize *= 2;
 	}
-	file->ungetbuf[file->ungetpos++] = c;
+	f->unbuf[f->unpos++] = c;
 }
 
 int
@@ -265,7 +307,7 @@ findeol(void)
 	while (1) {
 		c = lgetc(0);
 		if (c == '\n') {
-			file->lineno++;
+			f->lineno++;
 			break;
 		}
 		if (c == EOF)
@@ -287,7 +329,7 @@ top:
 	while ((c = lgetc(0)) == ' ' || c == '\t')
 		; /* nothing */
 
-	yylval.lineno = file->lineno;
+	yylval.lineno = f->lineno;
 	if (c == '#')
 		while ((c = lgetc(0)) != '\n' && c != EOF)
 			; /* nothing */
@@ -314,12 +356,12 @@ top:
 			return (findeol());
 		}
 		p = val + strlen(val) - 1;
-		lungetc(DONE_EXPAND);
+		lungetc(EXPAND_OFF);
 		while (p >= val) {
 			lungetc((unsigned char)*p);
 			p--;
 		}
-		lungetc(START_EXPAND);
+		lungetc(EXPAND_ON);
 		goto top;
 	}
 
@@ -331,7 +373,7 @@ top:
 			if ((c = lgetc(quotec)) == EOF)
 				return (0);
 			if (c == '\n') {
-				file->lineno++;
+				f->lineno++;
 				continue;
 			} else if (c == '\\') {
 				if ((next = lgetc(quotec)) == EOF)
@@ -340,7 +382,7 @@ top:
 				    next == '\t')
 					c = next;
 				else if (next == '\n') {
-					file->lineno++;
+					f->lineno++;
 					continue;
 				} else
 					lungetc(next);
@@ -369,7 +411,7 @@ top:
 	if (c == '-' || isdigit(c)) {
 		do {
 			*p++ = c;
-			if ((size_t)(p-buf) >= sizeof(buf)) {
+                       		if ((size_t)(p-buf) >= sizeof(buf)) {
 				yyerror("string too long");
 				return (findeol());
 			}
@@ -428,8 +470,8 @@ nodigits:
 		return (token);
 	}
 	if (c == '\n') {
-		yylval.lineno = file->lineno;
-		file->lineno++;
+		yylval.lineno = f->lineno;
+		f->lineno++;
 	}
 	if (c == EOF)
 		return (0);
@@ -439,104 +481,56 @@ nodigits:
 int
 config_load(struct blind *temp)
 {
-        env = temp;
-        errors = 0;
+	env = temp;
+	errors = 0;
 
-        if ((file = config_push(env->bl_conf)) == NULL) {
-                //       config_purge(PURGE_ALL);
-                return (-1);
+	if ((f = calloc(1, sizeof(struct file))) == NULL) {
+		log_debug("cannot allocate memory");
+		return (-1);
+	}
+	if ((f->name = strdup(env->bl_conf)) == NULL) {
+		log_debug("cannot duplicate name");
+		free(f);
+		return (-1);
         }
-        top = file;
+	if ((f->stream = fopen(f->name, "r")) == NULL) {
+		log_debug("cannot open config file");
+		free(f->name);
+		free(f);
+		return (-1);
+	}
+	if (config_perm(fileno(f->stream), f->name)) {
+		fclose(f->stream);
+		free(f->name);
+		free(f);
+		return (-1);
+	}
+	f->lineno = 1;
+	f->unsize = 16;
+	if ((f->unbuf = malloc(f->unsize)) == NULL) {
+		log_debug("cannot allocate buffer");
+		fclose(f->stream);
+		free(f->name);
+		free(f);
+		return (-1);
+	}
 
-        yyparse();
+	yyparse();
+	// setup
 
-        errors = file->errors;
-        config_pop();
+	if (errors)
+		return (-1);
 
-        // setup
-
-        if (errors) {
-                //	config_purge(PURGE_ALL);
-                return (-1);
-        }
-
-        return (0);
+	return (0);
 }
 
-struct file *
-config_push(const char *name)
-{
-        struct file *nfile;
-
-        if ((nfile = calloc(1, sizeof(struct file))) == NULL) {
-                log_debug("cannot allocate memory");
-                return (NULL);
-        }
-        if ((nfile->name = strdup(name)) == NULL) {
-                log_debug("cannot duplicate name");
-                free(nfile);
-                return (NULL);
-        }
-        if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
-                log_debug("cannot open config file");
-                free(nfile->name);
-                free(nfile);
-                return (NULL);
-        }
-        if (config_perm(fileno(nfile->stream), nfile->name)) {
-                fclose(nfile->stream);
-                free(nfile->name);
-                free(nfile);
-                return (NULL);
-        }
-        nfile->lineno = TAILQ_EMPTY(&files) ? 1 : 0;
-        nfile->ungetsize = 16;
-        nfile->ungetbuf = malloc(nfile->ungetsize);
-        if (nfile->ungetbuf == NULL) {
-                log_debug("cannot allocate buffer");
-                fclose(nfile->stream);
-                free(nfile->name);
-                free(nfile);
-                return (NULL);
-        }
-        TAILQ_INSERT_TAIL(&files, nfile, entry);
-        return (nfile);
-}
-
 int
-config_pop(void)
+config_close(void)
 {
-        struct file *prv;
+	fclose(f->stream);
+	free(f->name);
+	free(f->unbuf);
+	free(f);
 
-        if ((prv = TAILQ_PREV(file, files, entry)) != NULL)
-                prv->errors += file->errors;
-
-        TAILQ_REMOVE(&files, file, entry);
-        fclose(file->stream);
-        free(file->name);
-        free(file->ungetbuf);
-        free(file);
-        file = prv;
-        
-        return (file ? 0 : EOF);
-}
-
-int
-config_perm(int fd, const char *name)
-{
-        struct stat st;
-
-        if (fstat(fd, &st)) {
-                log_debug("cannot stat config file");
-                return (-1);
-        }
-        if (st.st_uid != 0 && st.st_uid != getuid()) {
-                log_debug("not root or current user owned");
-                return (-1);
-        }
-        if (st.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)) {
-                log_debug("insecure config file");
-                return (-1);
-        }
-        return (0);
+	return (EOF);
 }