xref: /freebsd/usr.sbin/jail/jaillex.l (revision 1d386b48a555f61cb7325543adbbb5c3f3407a66)
12671ee73SJamie Gritton %{
22671ee73SJamie Gritton /*-
34d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
41de7b4b8SPedro F. Giffuni  *
5d8352076SJamie Gritton  * Copyright (c) 2011 James Gritton
62671ee73SJamie Gritton  * All rights reserved.
72671ee73SJamie Gritton  *
82671ee73SJamie Gritton  * Redistribution and use in source and binary forms, with or without
92671ee73SJamie Gritton  * modification, are permitted provided that the following conditions
102671ee73SJamie Gritton  * are met:
112671ee73SJamie Gritton  * 1. Redistributions of source code must retain the above copyright
122671ee73SJamie Gritton  *    notice, this list of conditions and the following disclaimer.
132671ee73SJamie Gritton  * 2. Redistributions in binary form must reproduce the above copyright
142671ee73SJamie Gritton  *    notice, this list of conditions and the following disclaimer in the
152671ee73SJamie Gritton  *    documentation and/or other materials provided with the distribution.
162671ee73SJamie Gritton  *
172671ee73SJamie Gritton  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
182671ee73SJamie Gritton  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
192671ee73SJamie Gritton  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
202671ee73SJamie Gritton  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
212671ee73SJamie Gritton  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
222671ee73SJamie Gritton  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
232671ee73SJamie Gritton  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
242671ee73SJamie Gritton  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
252671ee73SJamie Gritton  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
262671ee73SJamie Gritton  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
272671ee73SJamie Gritton  * SUCH DAMAGE.
282671ee73SJamie Gritton  */
292671ee73SJamie Gritton 
302671ee73SJamie Gritton #include <sys/cdefs.h>
312671ee73SJamie Gritton #include <err.h>
322671ee73SJamie Gritton #include <stddef.h>
332671ee73SJamie Gritton #include <stdlib.h>
342671ee73SJamie Gritton #include <string.h>
352671ee73SJamie Gritton 
362671ee73SJamie Gritton #include "jailp.h"
372671ee73SJamie Gritton #include "y.tab.h"
382671ee73SJamie Gritton 
39*086e0149SJamie Gritton #define YY_DECL int yylex(YYSTYPE *yylval, yyscan_t yyscanner)
40*086e0149SJamie Gritton #define YY_EXTRA_TYPE struct cflex*
412671ee73SJamie Gritton 
42*086e0149SJamie Gritton extern YY_DECL;
43*086e0149SJamie Gritton 
44*086e0149SJamie Gritton static ssize_t text2lval(size_t triml, size_t trimr, int tovar,
45*086e0149SJamie Gritton     YYSTYPE *yylval, yyscan_t scanner);
462671ee73SJamie Gritton 
472671ee73SJamie Gritton static int instr;
482671ee73SJamie Gritton %}
492671ee73SJamie Gritton 
50a9a39d40SBaptiste Daroussin %option noyywrap
51a7880d59SJung-uk Kim %option noinput
52a7880d59SJung-uk Kim %option nounput
53*086e0149SJamie Gritton %option reentrant
54*086e0149SJamie Gritton %option yylineno
55a7880d59SJung-uk Kim 
562671ee73SJamie Gritton %start _ DQ
572671ee73SJamie Gritton 
582671ee73SJamie Gritton %%
592671ee73SJamie Gritton 
602671ee73SJamie Gritton 			/* Whitespace or equivalent */
61*086e0149SJamie Gritton <_>[ \t\r\n]+		instr = 0;
62*086e0149SJamie Gritton <_>#.*			instr = 0;
63*086e0149SJamie Gritton <_>\/\/.*		instr = 0;
64*086e0149SJamie Gritton <_>\/\*([^*]|(\*+([^*\/])))*\*+\/ instr = 0;
652671ee73SJamie Gritton 
662671ee73SJamie Gritton 			/* Reserved tokens */
672671ee73SJamie Gritton <_>\+=			{
682671ee73SJamie Gritton 				instr = 0;
692671ee73SJamie Gritton 				return PLEQ;
702671ee73SJamie Gritton 			}
712671ee73SJamie Gritton <_>[,;={}]		{
722671ee73SJamie Gritton 				instr = 0;
732671ee73SJamie Gritton 				return yytext[0];
742671ee73SJamie Gritton 			}
752671ee73SJamie Gritton 
762671ee73SJamie Gritton 			/* Atomic (unquoted) strings */
772671ee73SJamie Gritton <_,DQ>[A-Za-z0-9_!%&()\-.:<>?@\[\]^`|~]+ |
782671ee73SJamie Gritton <_,DQ>\\(.|\n|[0-7]{1,3}|x[0-9A-Fa-f]{1,2}) |
792671ee73SJamie Gritton <_,DQ>[$*+/\\]		{
80*086e0149SJamie Gritton 				(void)text2lval(0, 0, 0, yylval, yyscanner);
812671ee73SJamie Gritton 				return instr ? STR1 : (instr = 1, STR);
822671ee73SJamie Gritton 			}
832671ee73SJamie Gritton 
842671ee73SJamie Gritton 			/* Single and double quoted strings */
852671ee73SJamie Gritton <_>'([^\'\\]|\\(.|\n))*' {
86*086e0149SJamie Gritton 				(void)text2lval(1, 1, 0, yylval, yyscanner);
872671ee73SJamie Gritton 				return instr ? STR1 : (instr = 1, STR);
882671ee73SJamie Gritton 			}
892671ee73SJamie Gritton <_>\"([^"\\]|\\(.|\n))*\" |
902671ee73SJamie Gritton <DQ>[^\"$\\]([^"\\]|\\(.|\n))*\" {
912671ee73SJamie Gritton 				size_t skip;
922671ee73SJamie Gritton 				ssize_t atvar;
932671ee73SJamie Gritton 
942671ee73SJamie Gritton 				skip = yytext[0] == '"' ? 1 : 0;
95*086e0149SJamie Gritton 				atvar = text2lval(skip, 1, 1, yylval,
96*086e0149SJamie Gritton 					yyscanner);
972671ee73SJamie Gritton 				if (atvar < 0)
982671ee73SJamie Gritton 					BEGIN _;
992671ee73SJamie Gritton 				else {
1002671ee73SJamie Gritton 					/*
1012671ee73SJamie Gritton 					 * The string has a variable inside it.
1022671ee73SJamie Gritton 					 * Go into DQ mode to get the variable
1032671ee73SJamie Gritton 					 * and then the rest of the string.
1042671ee73SJamie Gritton 					 */
1052671ee73SJamie Gritton 					BEGIN DQ;
1062671ee73SJamie Gritton 					yyless(atvar);
1072671ee73SJamie Gritton 				}
1082671ee73SJamie Gritton 				return instr ? STR1 : (instr = 1, STR);
1092671ee73SJamie Gritton 			}
1102671ee73SJamie Gritton <DQ>\"			BEGIN _;
1112671ee73SJamie Gritton 
1122671ee73SJamie Gritton 			/* Variables, single-word or bracketed */
1132671ee73SJamie Gritton <_,DQ>$[A-Za-z_][A-Za-z_0-9]* {
114*086e0149SJamie Gritton 				(void)text2lval(1, 0, 0, yylval, yyscanner);
1152671ee73SJamie Gritton 				return instr ? VAR1 : (instr = 1, VAR);
1162671ee73SJamie Gritton 			}
1172671ee73SJamie Gritton <_>$\{([^\n{}]|\\(.|\n))*\} |
1182671ee73SJamie Gritton <DQ>$\{([^\n\"{}]|\\(.|\n))*\} {
119*086e0149SJamie Gritton 				(void)text2lval(2, 1, 0, yylval, yyscanner);
1202671ee73SJamie Gritton 				return instr ? VAR1 : (instr = 1, VAR);
1212671ee73SJamie Gritton 			}
1222671ee73SJamie Gritton 
1232671ee73SJamie Gritton 			/* Partially formed bits worth complaining about */
1242671ee73SJamie Gritton <_>\/\*([^*]|(\*+([^*\/])))*\** {
1252671ee73SJamie Gritton 				warnx("%s line %d: unterminated comment",
126*086e0149SJamie Gritton 				    yyextra->cfname, yylineno);
127*086e0149SJamie Gritton 				yyextra->error = 1;
1282671ee73SJamie Gritton 			}
1292671ee73SJamie Gritton <_>'([^\n'\\]|\\.)*	|
1302671ee73SJamie Gritton <_>\"([^\n\"\\]|\\.)*	{
1312671ee73SJamie Gritton 				warnx("%s line %d: unterminated string",
132*086e0149SJamie Gritton 				    yyextra->cfname, yylineno);
133*086e0149SJamie Gritton 				yyextra->error = 1;
1342671ee73SJamie Gritton 			}
1352671ee73SJamie Gritton <_>$\{([^\n{}]|\\.)*	|
1362671ee73SJamie Gritton <DQ>$\{([^\n\"{}]|\\.)*	{
1372671ee73SJamie Gritton 				warnx("%s line %d: unterminated variable",
138*086e0149SJamie Gritton 				    yyextra->cfname, yylineno);
139*086e0149SJamie Gritton 				yyextra->error = 1;
1402671ee73SJamie Gritton 			}
1412671ee73SJamie Gritton 
1422671ee73SJamie Gritton 			/* A hack because "<0>" rules aren't allowed */
1432671ee73SJamie Gritton <_>.			return yytext[0];
1442671ee73SJamie Gritton .|\n			{
1452671ee73SJamie Gritton 				BEGIN _;
1462671ee73SJamie Gritton 				yyless(0);
1472671ee73SJamie Gritton 			}
1482671ee73SJamie Gritton 
1492671ee73SJamie Gritton %%
1502671ee73SJamie Gritton 
1512671ee73SJamie Gritton /*
1522671ee73SJamie Gritton  * Copy string from yytext to yylval, handling backslash escapes,
1532671ee73SJamie Gritton  * and optionally stopping at the beginning of a variable.
1542671ee73SJamie Gritton  */
1552671ee73SJamie Gritton static ssize_t
156*086e0149SJamie Gritton text2lval(size_t triml, size_t trimr, int tovar, YYSTYPE *yylval,
157*086e0149SJamie Gritton     yyscan_t scanner)
1582671ee73SJamie Gritton {
1592671ee73SJamie Gritton 	char *d;
1602671ee73SJamie Gritton 	const char *s, *se;
1612671ee73SJamie Gritton 
162*086e0149SJamie Gritton 	struct yyguts_t *yyg = scanner;
163*086e0149SJamie Gritton 	yylval->cs = d = emalloc(yyleng - trimr - triml + 1);
1642671ee73SJamie Gritton 	se = yytext + (yyleng - trimr);
1652671ee73SJamie Gritton 	for (s = yytext + triml; s < se; s++, d++) {
1662671ee73SJamie Gritton 		if (*s != '\\') {
1672671ee73SJamie Gritton 			if (tovar && *s == '$') {
1682671ee73SJamie Gritton 				*d = '\0';
1692671ee73SJamie Gritton 				return s - yytext;
1702671ee73SJamie Gritton 			}
1712671ee73SJamie Gritton 			*d = *s;
1722671ee73SJamie Gritton 			continue;
1732671ee73SJamie Gritton 		}
1742671ee73SJamie Gritton 		s++;
1752671ee73SJamie Gritton 		if (*s >= '0' && *s <= '7') {
1762671ee73SJamie Gritton 			*d = *s - '0';
1772671ee73SJamie Gritton 			if (s + 1 < se && s[1] >= '0' && s[1] <= '7') {
1782671ee73SJamie Gritton 				*d = 010 * *d + (*++s - '0');
1792671ee73SJamie Gritton 				if (s + 1 < se && s[1] >= '0' && s[1] <= '7')
1802671ee73SJamie Gritton 					*d = 010 * *d + (*++s - '0');
1812671ee73SJamie Gritton 			}
1822671ee73SJamie Gritton 			continue;
1832671ee73SJamie Gritton 		}
1842671ee73SJamie Gritton 		switch (*s) {
1852671ee73SJamie Gritton 		case 'a':	*d = '\a';	break;
1862671ee73SJamie Gritton 		case 'b':	*d = '\b';	break;
1872671ee73SJamie Gritton 		case 'f':	*d = '\f';	break;
1882671ee73SJamie Gritton 		case 'n':	*d = '\n';	break;
1892671ee73SJamie Gritton 		case 'r':	*d = '\r';	break;
1902671ee73SJamie Gritton 		case 't':	*d = '\t';	break;
1912671ee73SJamie Gritton 		case 'v':	*d = '\v';	break;
1922671ee73SJamie Gritton 		default:	*d = *s;	break;
193*086e0149SJamie Gritton 		case '\n':	d--;		break;
1942671ee73SJamie Gritton 		case 'x':
1952671ee73SJamie Gritton 			*d = 0;
1962671ee73SJamie Gritton 			if (s + 1 >= se)
1972671ee73SJamie Gritton 				break;
1982671ee73SJamie Gritton 			if (s[1] >= '0' && s[1] <= '9')
1992671ee73SJamie Gritton 				*d = *++s - '0';
2002671ee73SJamie Gritton 			else if (s[1] >= 'A' && s[1] <= 'F')
2012671ee73SJamie Gritton 				*d = *++s + (0xA - 'A');
2026bd211bbSJamie Gritton 			else if (s[1] >= 'a' && s[1] <= 'f')
2032671ee73SJamie Gritton 				*d = *++s + (0xa - 'a');
2042671ee73SJamie Gritton 			else
2052671ee73SJamie Gritton 				break;
2062671ee73SJamie Gritton 			if (s + 1 >= se)
2072671ee73SJamie Gritton 				break;
2082671ee73SJamie Gritton 			if (s[1] >= '0' && s[1] <= '9')
2092671ee73SJamie Gritton 				*d = *d * 0x10 + (*++s - '0');
2102671ee73SJamie Gritton 			else if (s[1] >= 'A' && s[1] <= 'F')
2112671ee73SJamie Gritton 				*d = *d * 0x10 + (*++s + (0xA - 'A'));
212acf8ec56SJamie Gritton 			else if (s[1] >= 'a' && s[1] <= 'f')
2132671ee73SJamie Gritton 				*d = *d * 0x10 + (*++s + (0xa - 'a'));
2142671ee73SJamie Gritton 		}
2152671ee73SJamie Gritton 	}
2162671ee73SJamie Gritton 	*d = '\0';
2172671ee73SJamie Gritton 	return -1;
2182671ee73SJamie Gritton }
219