diff options
Diffstat (limited to 'usr.sbin/jail/jaillex.l')
-rw-r--r-- | usr.sbin/jail/jaillex.l | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/usr.sbin/jail/jaillex.l b/usr.sbin/jail/jaillex.l new file mode 100644 index 0000000..93bd7c4 --- /dev/null +++ b/usr.sbin/jail/jaillex.l @@ -0,0 +1,232 @@ +%{ +/*- + * Copyright (c) 2010 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> +__FBSDID("$FreeBSD$"); + +#include <err.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +#include "jailp.h" +#include "y.tab.h" + +#define YY_NO_UNPUT + +extern int yynerrs; + +static ssize_t text2lval(size_t triml, size_t trimr, int tovar); + +static int instr; +static int lineno = 1; +%} + +%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; + } + + /* Reserved tokens */ +<_>\+= { + instr = 0; + return PLEQ; + } +<_>[,;={}] { + instr = 0; + return yytext[0]; + } + + /* Atomic (unquoted) strings */ +<_,DQ>[A-Za-z0-9_!%&()\-.:<>?@\[\]^`|~]+ | +<_,DQ>\\(.|\n|[0-7]{1,3}|x[0-9A-Fa-f]{1,2}) | +<_,DQ>[$*+/\\] { + (void)text2lval(0, 0, 0); + return instr ? STR1 : (instr = 1, STR); + } + + /* Single and double quoted strings */ +<_>'([^\'\\]|\\(.|\n))*' { + (void)text2lval(1, 1, 0); + return instr ? STR1 : (instr = 1, STR); + } +<_>\"([^"\\]|\\(.|\n))*\" | +<DQ>[^\"$\\]([^"\\]|\\(.|\n))*\" { + size_t skip; + ssize_t atvar; + + skip = yytext[0] == '"' ? 1 : 0; + atvar = text2lval(skip, 1, 1); + if (atvar < 0) + BEGIN _; + else { + /* + * The string has a variable inside it. + * Go into DQ mode to get the variable + * and then the rest of the string. + */ + BEGIN DQ; + yyless(atvar); + } + return instr ? STR1 : (instr = 1, STR); + } +<DQ>\" BEGIN _; + + /* Variables, single-word or bracketed */ +<_,DQ>$[A-Za-z_][A-Za-z_0-9]* { + (void)text2lval(1, 0, 0); + return instr ? VAR1 : (instr = 1, VAR); + } +<_>$\{([^\n{}]|\\(.|\n))*\} | +<DQ>$\{([^\n\"{}]|\\(.|\n))*\} { + (void)text2lval(2, 1, 0); + return instr ? VAR1 : (instr = 1, VAR); + } + + /* Partially formed bits worth complaining about */ +<_>\/\*([^*]|(\*+([^*\/])))*\** { + warnx("%s line %d: unterminated comment", + cfname, lineno); + yynerrs++; + } +<_>'([^\n'\\]|\\.)* | +<_>\"([^\n\"\\]|\\.)* { + warnx("%s line %d: unterminated string", + cfname, lineno); + yynerrs++; + } +<_>$\{([^\n{}]|\\.)* | +<DQ>$\{([^\n\"{}]|\\.)* { + warnx("%s line %d: unterminated variable", + cfname, lineno); + yynerrs++; + } + + /* A hack because "<0>" rules aren't allowed */ +<_>. return yytext[0]; +.|\n { + BEGIN _; + yyless(0); + } + +%% + +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) +{ + char *d; + const char *s, *se; + + yylval.cs = d = emalloc(yyleng - trimr - triml + 1); + se = yytext + (yyleng - trimr); + for (s = yytext + triml; s < se; s++, d++) { + if (*s != '\\') { + if (tovar && *s == '$') { + *d = '\0'; + return s - yytext; + } + if (*s == '\n') + lineno++; + *d = *s; + continue; + } + s++; + if (*s >= '0' && *s <= '7') { + *d = *s - '0'; + if (s + 1 < se && s[1] >= '0' && s[1] <= '7') { + *d = 010 * *d + (*++s - '0'); + if (s + 1 < se && s[1] >= '0' && s[1] <= '7') + *d = 010 * *d + (*++s - '0'); + } + continue; + } + switch (*s) { + case 'a': *d = '\a'; break; + case 'b': *d = '\b'; break; + case 'f': *d = '\f'; break; + case 'n': *d = '\n'; break; + 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 'x': + *d = 0; + if (s + 1 >= se) + break; + if (s[1] >= '0' && s[1] <= '9') + *d = *++s - '0'; + else if (s[1] >= 'A' && s[1] <= 'F') + *d = *++s + (0xA - 'A'); + else if (s[1] >= 'a' && s[1] <= 'a') + *d = *++s + (0xa - 'a'); + else + break; + if (s + 1 >= se) + break; + if (s[1] >= '0' && s[1] <= '9') + *d = *d * 0x10 + (*++s - '0'); + else if (s[1] >= 'A' && s[1] <= 'F') + *d = *d * 0x10 + (*++s + (0xA - 'A')); + else if (s[1] >= 'a' && s[1] <= 'a') + *d = *d * 0x10 + (*++s + (0xa - 'a')); + } + } + *d = '\0'; + return -1; +} |