chiark / gitweb /
0c6416d7f0266a02f753b2cd45aedd79e47db59b
[userv.git] / lexer.l.m4
1 dnl  userv - lexer.l.m4
2 dnl  lexer, passed through m4 with defs from langauge.i4
3 /* userv is
4  * Copyright 1996-2017 Ian Jackson <ian@davenant.greenend.org.uk>.
5  * Copyright 2000      Ben Harris <bjh21@cam.ac.uk>
6  * Copyright 2016-2017 Peter Benie <pjb1008@cam.ac.uk>
7  *
8  * This is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with userv; if not, see <http://www.gnu.org/licenses/>.
20  */
21
22 %{
23 include(language.i4)
24
25 #include <syslog.h>
26 #include <assert.h>
27 #include <stdio.h>
28 #include <stdarg.h>
29 #include <ctype.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <pwd.h>
33 #include <grp.h>
34 #include <fnmatch.h>
35 #include <limits.h>
36 #include <dirent.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <time.h>
40 #include <errno.h>
41
42 #include "config.h"
43 #include "common.h"
44 #include "daemon.h"
45 #include "lib.h"
46 #include "both.h"
47 #include "tokens.h"
48
49 #define HYPHEN '-'
50
51 typedef int directive_fnt(int dtoken);
52 static directive_fnt df_reject, df_execute, df_executefrompath;
53 static directive_fnt df_executefromdirectory, df_executebuiltin;
54 static directive_fnt df_errorstostderr, df_errorstosyslog, df_errorstofile;
55 static directive_fnt dfg_fdwant, dfg_setflag, dfg_lookupquotemode;
56 static directive_fnt df_reset, df_cd, df_userrcfile, df_include;
57 static directive_fnt df_includelookup, df_includedirectory;
58 static directive_fnt df_message, df_error, df_quit, df_eof;
59 static directive_fnt df_if, df_catchquit, df_errorspush;
60 static directive_fnt dfi_includeuserrcfile, dfi_includeclientconfig;
61 /* directive functions return:
62  *  0 for success having scanned up to and including end of line but not beyond,
63  *  or tokv_error or tokv_quit.
64  * They expect to parse the whitespace before their parameters (if any).
65  */
66
67 typedef int parmcondition_fnt(int ctoken, char *const *parmvalues, int *rtrue);
68 static parmcondition_fnt pcf_glob, pcf_range, pcf_grep;
69 /* all conditional functions return tokv_error for failure or 0 for success
70  *  at parsing and testing, in which case *rtrue is set to 0 or 1.
71  *  On success they have scanned up to and including the condition's
72  *  terminating newline; the pcf_... functions expect to parse the whitespace
73  *  between the parameter name and the condition's arguments.
74  * Otherwise they return tokv_error.
75  * The parameter-based conditionals take a list of parameter values
76  * as obtained from the parameter functions and pa_parameter,
77  * and do _not_ free it.
78  */
79
80 typedef int parameter_fnt(int ptoken, char ***rvalues);
81 static parameter_fnt pf_service;
82 static parameter_fnt pf_callinguser, pf_serviceuser;
83 static parameter_fnt pf_callinggroup, pf_servicegroup;
84 static parameter_fnt pf_callingusershell, pf_serviceusershell;
85 /* Parameter functions return tokv_error or 0 for success at parsing
86  * and determining the value, in which case *rvalues is made to be
87  * a mallocd null-terminated array of pointers to mallocd strings.
88  * freeparm can be used to free such an array.
89  */
90
91 typedef int builtinserviceparse_fnt(char ***rnewargs);
92 static builtinserviceparse_fnt bispa_none, bispa_parameter;
93 /* These parse the arguments to a builtin service, including the
94  * newline at the end of the line.  *rnewargs will initially be
95  * null, indicating that no arguments are to be set; the function
96  * may store a mallocd array of mallocd strings in it,
97  * containing the arguments it wishes to have set (null-pointer
98  * terminated).
99  */
100
101 static int yylex(void);
102 /* Returns a token (which may be an eof or error exception) */
103
104 static directive_fnt *lr_dir;
105 static parmcondition_fnt *lr_parmcond;
106 static builtinserviceparse_fnt *lr_bispa;
107 static builtinserviceexec_fnt *lr_bisexec;
108 static parameter_fnt *lr_parameter;
109 static int lr_loglevel, lr_logfacility, lr_min, lr_max, *lr_flag;
110 static int lr_flagval, lr_controlend;
111 static int lr_fdwant_readwrite; /* -1=never, 0=opt, 1=always */
112
113 /* Forward declarations of things used in lexer and parser */
114
115 struct parser_state {
116   int lineno, reportlineno, notedreferer, isinternal;
117   const char *filename;
118   struct stat filestab;
119   YY_BUFFER_STATE ybuf;
120   struct parser_state *upstate;
121 };
122
123 static struct parser_state *cstate;
124
125 struct error_handling {
126   int handling; /* One of the error handling modes tokt_ehandlemode */
127   int logfacility, loglevel;
128   int filekeep; /* File is in use by higher-level errors-push, leave it open */
129   FILE *file;
130   char *filename;
131 };
132
133 static struct error_handling eh = { tokv_word_errorstostderr, 0,0,0,0,0 };
134
135 static int dequote(char *inplace);
136 static void countnewlines(void);
137
138 #define YY_NO_INPUT
139
140 %}
141
142 %option noyywrap
143 %option nounput
144
145 %%
146
147 dnl simple words
148 undivert(3)
149 changequote({*,*})
150 {*
151 [0-9]{1,8}              {
152                           char *ep;
153                           lr_min=lr_max= (int)strtoul(yytext,&ep,10);
154                           assert(!*ep);
155                           return tokv_ordinal;
156                         }
157 [0-9]{1,8}-[0-9]{1,8}   {
158                           char *ep;
159                           lr_min= (int)strtoul(yytext,&ep,10);
160                           assert(*ep == HYPHEN);
161                           ep++;  assert(*ep);
162                           lr_max= (int)strtoul(ep,&ep,10);
163                           assert(!*ep);
164                           if (lr_max < lr_min)
165                             return parseerrprint("fd range has min > max");
166                           return tokv_fdrange;
167                         }
168 [0-9]{1,8}-             {
169                           char *ep;
170                           lr_min= (int)strtoul(yytext,&ep,10);
171                           assert(*ep == HYPHEN);
172                           ep++;  assert(!*ep);
173                           lr_max=-1;
174                           return tokv_fdstoend;
175                         }
176 ([\ \t]*\\[\ \t]*\n[\ \t]*)+    countnewlines(); return tokv_lwsp;
177 [\ \t]+                         return tokv_lwsp;
178 [\ \t]*\n               cstate->lineno++; return tokv_newline;
179 [\ \t]*\#[^\n]*\n       cstate->lineno++; return tokv_newline;
180 [\ \t]*\#[^\n]*         return parseerrprint("missing newline at eof after comment");
181 \"([^\\\"\n]|\\[a-z]|\\[0-9]{3}|\\x[0-9A-Fa-f]{2}|\\[[:punct:]]|\\[ \t]*\n)*\" {
182                           countnewlines();
183                           return dequote(yytext);
184                         }
185 [^\ \t\n\\\"]+          return tokv_barestring;
186 <<EOF>>                 return tokv_eof;
187 \"                      return parseerrprint("misquoted or unterminated string");
188 \\                      return parseerrprint("unexpected backslash");
189 .                       abort(); /* expect lex warning "rule cannot be matched" */
190 *}
191 changequote(`,')
192 %%
193
194 const char *const builtinservicehelpstrings[]= {
195 undivert(5)dnl
196    0
197 };
198 `
199 #include "parser.c"
200 '
201 divert(-1)
202 undivert