jail: Use re-entrant versions of lex & yacc, and lex's yylineno
This commit is contained in:
+17
-10
@@ -51,10 +51,10 @@ struct ipspec {
|
||||
unsigned flags;
|
||||
};
|
||||
|
||||
extern FILE *yyin;
|
||||
extern int yynerrs;
|
||||
|
||||
extern int yyparse(void);
|
||||
extern int yylex_init_extra(struct cflex *extra, void *scanner);
|
||||
extern int yylex_destroy(void *scanner);
|
||||
extern int yyparse(void *scanner);
|
||||
extern int yyset_in(FILE *fp, void *scanner);
|
||||
|
||||
struct cfjails cfjails = TAILQ_HEAD_INITIALIZER(cfjails);
|
||||
|
||||
@@ -127,7 +127,7 @@ static const struct ipspec intparams[] = {
|
||||
* Parse the jail configuration file.
|
||||
*/
|
||||
void
|
||||
load_config(void)
|
||||
load_config(const char *cfname)
|
||||
{
|
||||
struct cfjails wild;
|
||||
struct cfparams opp;
|
||||
@@ -135,19 +135,26 @@ load_config(void)
|
||||
struct cfparam *p, *vp, *tp;
|
||||
struct cfstring *s, *vs, *ns;
|
||||
struct cfvar *v, *vv;
|
||||
struct cflex cflex;
|
||||
char *ep;
|
||||
void *scanner;
|
||||
int did_self, jseq, pgen;
|
||||
|
||||
cflex.cfname = cfname;
|
||||
cflex.error = 0;
|
||||
yylex_init_extra(&cflex, &scanner);
|
||||
if (!strcmp(cfname, "-")) {
|
||||
cfname = "STDIN";
|
||||
yyin = stdin;
|
||||
cflex.cfname = "STDIN";
|
||||
yyset_in(stdin, scanner);
|
||||
} else {
|
||||
yyin = fopen(cfname, "r");
|
||||
if (!yyin)
|
||||
FILE *yfp = fopen(cfname, "r");
|
||||
if (!yfp)
|
||||
err(1, "%s", cfname);
|
||||
yyset_in(yfp, scanner);
|
||||
}
|
||||
if (yyparse() || yynerrs)
|
||||
if (yyparse(scanner) || cflex.error)
|
||||
exit(1);
|
||||
yylex_destroy(scanner);
|
||||
|
||||
/* Separate the wildcard jails out from the actual jails. */
|
||||
jseq = 0;
|
||||
|
||||
@@ -56,7 +56,6 @@ struct permspec {
|
||||
int rev;
|
||||
};
|
||||
|
||||
const char *cfname;
|
||||
int iflag;
|
||||
int note_remove;
|
||||
int verbose;
|
||||
@@ -138,6 +137,7 @@ main(int argc, char **argv)
|
||||
FILE *jfp;
|
||||
struct cfjail *j;
|
||||
char *JidFile;
|
||||
const char *cfname;
|
||||
size_t sysvallen;
|
||||
unsigned op, pi;
|
||||
int ch, docf, error, i, oldcl, sysval;
|
||||
@@ -287,7 +287,7 @@ main(int argc, char **argv)
|
||||
} else if (op == JF_STOP || op == JF_SHOW) {
|
||||
/* Just print list of all configured non-wildcard jails */
|
||||
if (op == JF_SHOW) {
|
||||
load_config();
|
||||
load_config(cfname);
|
||||
show_jails();
|
||||
exit(0);
|
||||
}
|
||||
@@ -300,7 +300,7 @@ main(int argc, char **argv)
|
||||
usage();
|
||||
if ((docf = !Rflag &&
|
||||
(!strcmp(cfname, "-") || stat(cfname, &st) == 0)))
|
||||
load_config();
|
||||
load_config(cfname);
|
||||
note_remove = docf || argc > 1 || wild_jail_name(argv[0]);
|
||||
} else if (argc > 1 || (argc == 1 && strchr(argv[0], '='))) {
|
||||
/* Single jail specified on the command line */
|
||||
@@ -348,7 +348,7 @@ main(int argc, char **argv)
|
||||
/* From the config file, perhaps with a specified jail */
|
||||
if (Rflag || !docf)
|
||||
usage();
|
||||
load_config();
|
||||
load_config(cfname);
|
||||
}
|
||||
|
||||
/* Find out which jails will be run. */
|
||||
|
||||
+29
-47
@@ -38,40 +38,32 @@ __FBSDID("$FreeBSD$");
|
||||
#include "jailp.h"
|
||||
#include "y.tab.h"
|
||||
|
||||
extern int yynerrs;
|
||||
#define YY_DECL int yylex(YYSTYPE *yylval, yyscan_t yyscanner)
|
||||
#define YY_EXTRA_TYPE struct cflex*
|
||||
|
||||
static ssize_t text2lval(size_t triml, size_t trimr, int tovar);
|
||||
extern YY_DECL;
|
||||
|
||||
static ssize_t text2lval(size_t triml, size_t trimr, int tovar,
|
||||
YYSTYPE *yylval, yyscan_t scanner);
|
||||
|
||||
static int instr;
|
||||
static int lineno = 1;
|
||||
|
||||
#define YY_DECL int yylex(void)
|
||||
%}
|
||||
|
||||
%option noyywrap
|
||||
%option noinput
|
||||
%option nounput
|
||||
%option reentrant
|
||||
%option yylineno
|
||||
|
||||
%start _ DQ
|
||||
|
||||
%%
|
||||
|
||||
/* Whitespace or equivalent */
|
||||
<_>[ \t]+ instr = 0;
|
||||
<_>#.* ;
|
||||
<_>\/\/.* ;
|
||||
<_>\/\*([^*]|(\*+([^*\/])))*\*+\/ {
|
||||
const char *s;
|
||||
|
||||
for (s = yytext; s < yytext + yyleng; s++)
|
||||
if (*s == '\n')
|
||||
lineno++;
|
||||
instr = 0;
|
||||
}
|
||||
<_>\n {
|
||||
lineno++;
|
||||
instr = 0;
|
||||
}
|
||||
<_>[ \t\r\n]+ instr = 0;
|
||||
<_>#.* instr = 0;
|
||||
<_>\/\/.* instr = 0;
|
||||
<_>\/\*([^*]|(\*+([^*\/])))*\*+\/ instr = 0;
|
||||
|
||||
/* Reserved tokens */
|
||||
<_>\+= {
|
||||
@@ -87,13 +79,13 @@ static int lineno = 1;
|
||||
<_,DQ>[A-Za-z0-9_!%&()\-.:<>?@\[\]^`|~]+ |
|
||||
<_,DQ>\\(.|\n|[0-7]{1,3}|x[0-9A-Fa-f]{1,2}) |
|
||||
<_,DQ>[$*+/\\] {
|
||||
(void)text2lval(0, 0, 0);
|
||||
(void)text2lval(0, 0, 0, yylval, yyscanner);
|
||||
return instr ? STR1 : (instr = 1, STR);
|
||||
}
|
||||
|
||||
/* Single and double quoted strings */
|
||||
<_>'([^\'\\]|\\(.|\n))*' {
|
||||
(void)text2lval(1, 1, 0);
|
||||
(void)text2lval(1, 1, 0, yylval, yyscanner);
|
||||
return instr ? STR1 : (instr = 1, STR);
|
||||
}
|
||||
<_>\"([^"\\]|\\(.|\n))*\" |
|
||||
@@ -102,7 +94,8 @@ static int lineno = 1;
|
||||
ssize_t atvar;
|
||||
|
||||
skip = yytext[0] == '"' ? 1 : 0;
|
||||
atvar = text2lval(skip, 1, 1);
|
||||
atvar = text2lval(skip, 1, 1, yylval,
|
||||
yyscanner);
|
||||
if (atvar < 0)
|
||||
BEGIN _;
|
||||
else {
|
||||
@@ -120,32 +113,32 @@ static int lineno = 1;
|
||||
|
||||
/* Variables, single-word or bracketed */
|
||||
<_,DQ>$[A-Za-z_][A-Za-z_0-9]* {
|
||||
(void)text2lval(1, 0, 0);
|
||||
(void)text2lval(1, 0, 0, yylval, yyscanner);
|
||||
return instr ? VAR1 : (instr = 1, VAR);
|
||||
}
|
||||
<_>$\{([^\n{}]|\\(.|\n))*\} |
|
||||
<DQ>$\{([^\n\"{}]|\\(.|\n))*\} {
|
||||
(void)text2lval(2, 1, 0);
|
||||
(void)text2lval(2, 1, 0, yylval, yyscanner);
|
||||
return instr ? VAR1 : (instr = 1, VAR);
|
||||
}
|
||||
|
||||
/* Partially formed bits worth complaining about */
|
||||
<_>\/\*([^*]|(\*+([^*\/])))*\** {
|
||||
warnx("%s line %d: unterminated comment",
|
||||
cfname, lineno);
|
||||
yynerrs++;
|
||||
yyextra->cfname, yylineno);
|
||||
yyextra->error = 1;
|
||||
}
|
||||
<_>'([^\n'\\]|\\.)* |
|
||||
<_>\"([^\n\"\\]|\\.)* {
|
||||
warnx("%s line %d: unterminated string",
|
||||
cfname, lineno);
|
||||
yynerrs++;
|
||||
yyextra->cfname, yylineno);
|
||||
yyextra->error = 1;
|
||||
}
|
||||
<_>$\{([^\n{}]|\\.)* |
|
||||
<DQ>$\{([^\n\"{}]|\\.)* {
|
||||
warnx("%s line %d: unterminated variable",
|
||||
cfname, lineno);
|
||||
yynerrs++;
|
||||
yyextra->cfname, yylineno);
|
||||
yyextra->error = 1;
|
||||
}
|
||||
|
||||
/* A hack because "<0>" rules aren't allowed */
|
||||
@@ -157,28 +150,19 @@ static int lineno = 1;
|
||||
|
||||
%%
|
||||
|
||||
void
|
||||
yyerror(const char *s)
|
||||
{
|
||||
if (!yytext)
|
||||
warnx("%s line %d: %s", cfname, lineno, s);
|
||||
else if (!yytext[0])
|
||||
warnx("%s: unexpected EOF", cfname);
|
||||
else
|
||||
warnx("%s line %d: %s: %s", cfname, lineno, yytext, s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy string from yytext to yylval, handling backslash escapes,
|
||||
* and optionally stopping at the beginning of a variable.
|
||||
*/
|
||||
static ssize_t
|
||||
text2lval(size_t triml, size_t trimr, int tovar)
|
||||
text2lval(size_t triml, size_t trimr, int tovar, YYSTYPE *yylval,
|
||||
yyscan_t scanner)
|
||||
{
|
||||
char *d;
|
||||
const char *s, *se;
|
||||
|
||||
yylval.cs = d = emalloc(yyleng - trimr - triml + 1);
|
||||
struct yyguts_t *yyg = scanner;
|
||||
yylval->cs = d = emalloc(yyleng - trimr - triml + 1);
|
||||
se = yytext + (yyleng - trimr);
|
||||
for (s = yytext + triml; s < se; s++, d++) {
|
||||
if (*s != '\\') {
|
||||
@@ -186,8 +170,6 @@ text2lval(size_t triml, size_t trimr, int tovar)
|
||||
*d = '\0';
|
||||
return s - yytext;
|
||||
}
|
||||
if (*s == '\n')
|
||||
lineno++;
|
||||
*d = *s;
|
||||
continue;
|
||||
}
|
||||
@@ -209,8 +191,8 @@ text2lval(size_t triml, size_t trimr, int tovar)
|
||||
case 'r': *d = '\r'; break;
|
||||
case 't': *d = '\t'; break;
|
||||
case 'v': *d = '\v'; break;
|
||||
case '\n': d--; lineno++; break;
|
||||
default: *d = *s; break;
|
||||
case '\n': d--; break;
|
||||
case 'x':
|
||||
*d = 0;
|
||||
if (s + 1 >= se)
|
||||
|
||||
@@ -197,6 +197,11 @@ struct cfdepend {
|
||||
unsigned flags;
|
||||
};
|
||||
|
||||
struct cflex {
|
||||
const char *cfname;
|
||||
int error;
|
||||
};
|
||||
|
||||
extern void *emalloc(size_t);
|
||||
extern void *erealloc(void *, size_t);
|
||||
extern char *estrdup(const char *);
|
||||
@@ -209,7 +214,7 @@ extern int next_command(struct cfjail *j);
|
||||
extern int finish_command(struct cfjail *j);
|
||||
extern struct cfjail *next_proc(int nonblock);
|
||||
|
||||
extern void load_config(void);
|
||||
extern void load_config(const char *cfname);
|
||||
extern struct cfjail *add_jail(void);
|
||||
extern void add_param(struct cfjail *j, const struct cfparam *p,
|
||||
enum intparam ipnum, const char *value);
|
||||
@@ -232,13 +237,9 @@ extern int start_state(const char *target, int docf, unsigned state,
|
||||
extern void requeue(struct cfjail *j, struct cfjails *queue);
|
||||
extern void requeue_head(struct cfjail *j, struct cfjails *queue);
|
||||
|
||||
extern void yyerror(const char *);
|
||||
extern int yylex(void);
|
||||
|
||||
extern struct cfjails cfjails;
|
||||
extern struct cfjails ready;
|
||||
extern struct cfjails depend;
|
||||
extern const char *cfname;
|
||||
extern int iflag;
|
||||
extern int note_remove;
|
||||
extern int paralimit;
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <err.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -57,6 +58,11 @@ static struct cfjail *global_jail;
|
||||
%type <ss> value
|
||||
%type <s> string
|
||||
|
||||
%pure-parser
|
||||
|
||||
%lex-param { void *scanner }
|
||||
%parse-param { void *scanner }
|
||||
|
||||
%%
|
||||
|
||||
/*
|
||||
@@ -221,3 +227,24 @@ string : STR
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
extern int YYLEX_DECL();
|
||||
|
||||
extern struct cflex *yyget_extra(void *scanner);
|
||||
extern int yyget_lineno(void *scanner);
|
||||
extern char *yyget_text(void *scanner);
|
||||
|
||||
static void
|
||||
YYERROR_DECL()
|
||||
{
|
||||
if (!yyget_text(scanner))
|
||||
warnx("%s line %d: %s",
|
||||
yyget_extra(scanner)->cfname, yyget_lineno(scanner), s);
|
||||
else if (!yyget_text(scanner)[0])
|
||||
warnx("%s: unexpected EOF",
|
||||
yyget_extra(scanner)->cfname);
|
||||
else
|
||||
warnx("%s line %d: %s: %s",
|
||||
yyget_extra(scanner)->cfname, yyget_lineno(scanner),
|
||||
yyget_text(scanner), s);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user