aboutsummaryrefslogtreecommitdiff
path: root/usr.sbin/jail/jailparse.y
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/jail/jailparse.y')
-rw-r--r--usr.sbin/jail/jailparse.y276
1 files changed, 276 insertions, 0 deletions
diff --git a/usr.sbin/jail/jailparse.y b/usr.sbin/jail/jailparse.y
new file mode 100644
index 000000000000..048cfcf11c2b
--- /dev/null
+++ b/usr.sbin/jail/jailparse.y
@@ -0,0 +1,276 @@
+%{
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2011 James Gritton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <err.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "jailp.h"
+
+#ifdef DEBUG
+#define YYDEBUG 1
+#endif
+
+static struct cfjail *current_jail;
+static struct cfjail *global_jail;
+%}
+
+%union {
+ struct cfparam *p;
+ struct cfstrings *ss;
+ struct cfstring *s;
+ char *cs;
+}
+
+%token PLEQ
+%token <cs> STR STR1 VAR VAR1
+
+%type <p> param name
+%type <ss> value
+%type <s> string
+
+%pure-parser
+
+%lex-param { void *scanner }
+%parse-param { void *scanner }
+
+%%
+
+/*
+ * A config file is a list of jails and parameters. Parameters are
+ * added to the current jail, otherwise to a global pesudo-jail.
+ */
+conf :
+ | conf jail
+ | conf param ';'
+ {
+ if (!special_param($2, scanner)) {
+ struct cfjail *j = current_jail;
+
+ if (j == NULL) {
+ if (global_jail == NULL) {
+ global_jail = add_jail();
+ global_jail->name = estrdup("*");
+ }
+ j = global_jail;
+ }
+ TAILQ_INSERT_TAIL(&j->params, $2, tq);
+ }
+ }
+ | conf ';'
+ ;
+
+jail : jail_name '{' conf '}'
+ {
+ current_jail = current_jail->cfparent;
+ }
+ ;
+
+jail_name : STR
+ {
+ struct cfjail *j = add_jail();
+
+ if (current_jail == NULL)
+ j->name = $1;
+ else {
+ /*
+ * A nested jail definition becomes
+ * a hierarchically-named sub-jail.
+ */
+ size_t parentlen = strlen(current_jail->name);
+ j->name = emalloc(parentlen + strlen($1) + 2);
+ strcpy(j->name, current_jail->name);
+ j->name[parentlen++] = '.';
+ strcpy(j->name + parentlen, $1);
+ free($1);
+ }
+ j->cfparent = current_jail;
+ current_jail = j;
+ }
+ ;
+
+/*
+ * Parameters have a name and an optional list of value strings,
+ * which may have "+=" or "=" preceding them.
+ */
+param : name
+ {
+ $$ = $1;
+ }
+ | name '=' value
+ {
+ $$ = $1;
+ TAILQ_CONCAT(&$$->val, $3, tq);
+ free($3);
+ }
+ | name PLEQ value
+ {
+ $$ = $1;
+ TAILQ_CONCAT(&$$->val, $3, tq);
+ $$->flags |= PF_APPEND;
+ free($3);
+ }
+ | name value
+ {
+ $$ = $1;
+ TAILQ_CONCAT(&$$->val, $2, tq);
+ $$->flags |= PF_NAMEVAL;
+ free($2);
+ }
+ | error
+ ;
+
+/*
+ * A parameter has a fixed name. A variable definition looks just like a
+ * parameter except that the name is a variable.
+ */
+name : STR
+ {
+ $$ = emalloc(sizeof(struct cfparam));
+ $$->name = $1;
+ TAILQ_INIT(&$$->val);
+ $$->flags = 0;
+ }
+ | VAR
+ {
+ $$ = emalloc(sizeof(struct cfparam));
+ $$->name = $1;
+ TAILQ_INIT(&$$->val);
+ $$->flags = PF_VAR;
+ }
+ ;
+
+value : string
+ {
+ $$ = emalloc(sizeof(struct cfstrings));
+ TAILQ_INIT($$);
+ TAILQ_INSERT_TAIL($$, $1, tq);
+ }
+ | value ',' string
+ {
+ $$ = $1;
+ TAILQ_INSERT_TAIL($$, $3, tq);
+ }
+ ;
+
+/*
+ * Strings may be passed in pieces, because of quoting and/or variable
+ * interpolation. Reassemble them into a single string.
+ */
+string : STR
+ {
+ $$ = emalloc(sizeof(struct cfstring));
+ $$->s = $1;
+ $$->len = strlen($1);
+ STAILQ_INIT(&$$->vars);
+ }
+ | VAR
+ {
+ struct cfvar *v;
+
+ $$ = emalloc(sizeof(struct cfstring));
+ $$->s = estrdup("");
+ $$->len = 0;
+ STAILQ_INIT(&$$->vars);
+ v = emalloc(sizeof(struct cfvar));
+ v->name = $1;
+ v->pos = 0;
+ STAILQ_INSERT_TAIL(&$$->vars, v, tq);
+ }
+ | string STR1
+ {
+ size_t len1;
+
+ $$ = $1;
+ len1 = strlen($2);
+ $$->s = erealloc($$->s, $$->len + len1 + 1);
+ strcpy($$->s + $$->len, $2);
+ free($2);
+ $$->len += len1;
+ }
+ | string VAR1
+ {
+ struct cfvar *v;
+
+ $$ = $1;
+ v = emalloc(sizeof(struct cfvar));
+ v->name = $2;
+ v->pos = $$->len;
+ STAILQ_INSERT_TAIL(&$$->vars, v, tq);
+ }
+ ;
+
+%%
+
+extern int YYLEX_DECL();
+
+static void
+YYERROR_DECL()
+{
+ struct cflex *cflex = yyget_extra(scanner);
+
+ if (!yyget_text(scanner))
+ warnx("%s line %d: %s",
+ cflex->cfname, yyget_lineno(scanner), s);
+ else if (!yyget_text(scanner)[0])
+ warnx("%s: unexpected EOF",
+ cflex->cfname);
+ else
+ warnx("%s line %d: %s: %s",
+ cflex->cfname, yyget_lineno(scanner),
+ yyget_text(scanner), s);
+ cflex->error = 1;
+}
+
+/* Handle special parameters (i.e. the include directive).
+ * Return true if the parameter was specially handled.
+ */
+static int
+special_param(struct cfparam *p, void *scanner)
+{
+ if ((p->flags & (PF_VAR | PF_APPEND | PF_NAMEVAL)) != PF_NAMEVAL
+ || strcmp(p->name, ".include"))
+ return 0;
+ struct cfstring *s;
+ TAILQ_FOREACH(s, &p->val, tq) {
+ if (STAILQ_EMPTY(&s->vars))
+ include_config(scanner, s->s);
+ else {
+ warnx("%s line %d: "
+ "variables not permitted in '.include' filename",
+ yyget_extra(scanner)->cfname,
+ yyget_lineno(scanner));
+ yyget_extra(scanner)->error = 1;
+ }
+ }
+ free_param_strings(p);
+ free(p);
+ return 1;
+}