]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/jail/jaillex.l
zfs: merge openzfs/zfs@009d3288d
[FreeBSD/FreeBSD.git] / usr.sbin / jail / jaillex.l
1 %{
2 /*-
3  * SPDX-License-Identifier: BSD-2-Clause
4  *
5  * Copyright (c) 2011 James Gritton
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
33 #include <err.h>
34 #include <stddef.h>
35 #include <stdlib.h>
36 #include <string.h>
37
38 #include "jailp.h"
39 #include "y.tab.h"
40
41 #define YY_DECL int yylex(YYSTYPE *yylval, yyscan_t yyscanner)
42 #define YY_EXTRA_TYPE struct cflex*
43
44 extern YY_DECL;
45
46 static ssize_t text2lval(size_t triml, size_t trimr, int tovar,
47     YYSTYPE *yylval, yyscan_t scanner);
48
49 static int instr;
50 %}
51
52 %option noyywrap
53 %option noinput
54 %option nounput
55 %option reentrant
56 %option yylineno
57
58 %start _ DQ
59
60 %%
61
62                         /* Whitespace or equivalent */
63 <_>[ \t\r\n]+           instr = 0;
64 <_>#.*                  instr = 0;
65 <_>\/\/.*               instr = 0;
66 <_>\/\*([^*]|(\*+([^*\/])))*\*+\/ instr = 0;
67
68                         /* Reserved tokens */
69 <_>\+=                  {
70                                 instr = 0;
71                                 return PLEQ;
72                         }
73 <_>[,;={}]              {
74                                 instr = 0;
75                                 return yytext[0];
76                         }
77
78                         /* Atomic (unquoted) strings */
79 <_,DQ>[A-Za-z0-9_!%&()\-.:<>?@\[\]^`|~]+ |
80 <_,DQ>\\(.|\n|[0-7]{1,3}|x[0-9A-Fa-f]{1,2}) |
81 <_,DQ>[$*+/\\]          {
82                                 (void)text2lval(0, 0, 0, yylval, yyscanner);
83                                 return instr ? STR1 : (instr = 1, STR);
84                         }
85
86                         /* Single and double quoted strings */
87 <_>'([^\'\\]|\\(.|\n))*' {
88                                 (void)text2lval(1, 1, 0, yylval, yyscanner);
89                                 return instr ? STR1 : (instr = 1, STR);
90                         }
91 <_>\"([^"\\]|\\(.|\n))*\" |
92 <DQ>[^\"$\\]([^"\\]|\\(.|\n))*\" {
93                                 size_t skip;
94                                 ssize_t atvar;
95
96                                 skip = yytext[0] == '"' ? 1 : 0;
97                                 atvar = text2lval(skip, 1, 1, yylval,
98                                         yyscanner);
99                                 if (atvar < 0)
100                                         BEGIN _;
101                                 else {
102                                         /*
103                                          * The string has a variable inside it.
104                                          * Go into DQ mode to get the variable
105                                          * and then the rest of the string.
106                                          */
107                                         BEGIN DQ;
108                                         yyless(atvar);
109                                 }
110                                 return instr ? STR1 : (instr = 1, STR);
111                         }
112 <DQ>\"                  BEGIN _;
113
114                         /* Variables, single-word or bracketed */
115 <_,DQ>$[A-Za-z_][A-Za-z_0-9]* {
116                                 (void)text2lval(1, 0, 0, yylval, yyscanner);
117                                 return instr ? VAR1 : (instr = 1, VAR);
118                         }
119 <_>$\{([^\n{}]|\\(.|\n))*\} |
120 <DQ>$\{([^\n\"{}]|\\(.|\n))*\} {
121                                 (void)text2lval(2, 1, 0, yylval, yyscanner);
122                                 return instr ? VAR1 : (instr = 1, VAR);
123                         }
124
125                         /* Partially formed bits worth complaining about */
126 <_>\/\*([^*]|(\*+([^*\/])))*\** {
127                                 warnx("%s line %d: unterminated comment",
128                                     yyextra->cfname, yylineno);
129                                 yyextra->error = 1;
130                         }
131 <_>'([^\n'\\]|\\.)*     |
132 <_>\"([^\n\"\\]|\\.)*   {
133                                 warnx("%s line %d: unterminated string",
134                                     yyextra->cfname, yylineno);
135                                 yyextra->error = 1;
136                         }
137 <_>$\{([^\n{}]|\\.)*    |
138 <DQ>$\{([^\n\"{}]|\\.)* {
139                                 warnx("%s line %d: unterminated variable",
140                                     yyextra->cfname, yylineno);
141                                 yyextra->error = 1;
142                         }
143
144                         /* A hack because "<0>" rules aren't allowed */
145 <_>.                    return yytext[0];
146 .|\n                    {
147                                 BEGIN _;
148                                 yyless(0);
149                         }
150
151 %%
152
153 /*
154  * Copy string from yytext to yylval, handling backslash escapes,
155  * and optionally stopping at the beginning of a variable.
156  */
157 static ssize_t
158 text2lval(size_t triml, size_t trimr, int tovar, YYSTYPE *yylval,
159     yyscan_t scanner)
160 {
161         char *d;
162         const char *s, *se;
163
164         struct yyguts_t *yyg = scanner;
165         yylval->cs = d = emalloc(yyleng - trimr - triml + 1);
166         se = yytext + (yyleng - trimr);
167         for (s = yytext + triml; s < se; s++, d++) {
168                 if (*s != '\\') {
169                         if (tovar && *s == '$') {
170                                 *d = '\0';
171                                 return s - yytext;
172                         }
173                         *d = *s;
174                         continue;
175                 }
176                 s++;
177                 if (*s >= '0' && *s <= '7') {
178                         *d = *s - '0';
179                         if (s + 1 < se && s[1] >= '0' && s[1] <= '7') {
180                                 *d = 010 * *d + (*++s - '0');
181                                 if (s + 1 < se && s[1] >= '0' && s[1] <= '7')
182                                         *d = 010 * *d + (*++s - '0');
183                         }
184                         continue;
185                 }
186                 switch (*s) {
187                 case 'a':       *d = '\a';      break;
188                 case 'b':       *d = '\b';      break;
189                 case 'f':       *d = '\f';      break;
190                 case 'n':       *d = '\n';      break;
191                 case 'r':       *d = '\r';      break;
192                 case 't':       *d = '\t';      break;
193                 case 'v':       *d = '\v';      break;
194                 default:        *d = *s;        break;
195                 case '\n':      d--;            break;
196                 case 'x':
197                         *d = 0;
198                         if (s + 1 >= se)
199                                 break;
200                         if (s[1] >= '0' && s[1] <= '9')
201                                 *d = *++s - '0';
202                         else if (s[1] >= 'A' && s[1] <= 'F')
203                                 *d = *++s + (0xA - 'A');
204                         else if (s[1] >= 'a' && s[1] <= 'f')
205                                 *d = *++s + (0xa - 'a');
206                         else
207                                 break;
208                         if (s + 1 >= se)
209                                 break;
210                         if (s[1] >= '0' && s[1] <= '9')
211                                 *d = *d * 0x10 + (*++s - '0');
212                         else if (s[1] >= 'A' && s[1] <= 'F')
213                                 *d = *d * 0x10 + (*++s + (0xA - 'A'));
214                         else if (s[1] >= 'a' && s[1] <= 'f')
215                                 *d = *d * 0x10 + (*++s + (0xa - 'a'));
216                 }
217         }
218         *d = '\0';
219         return -1;
220 }