chiark / gitweb /
Build arrangements changed some more - check in distritubed files.
[userv.git] / lexer.l
diff --git a/lexer.l b/lexer.l
new file mode 100644 (file)
index 0000000..6af0345
--- /dev/null
+++ b/lexer.l
@@ -0,0 +1,299 @@
+/*
+ *   Copyright (C)1996-1997,1999 Ian Jackson
+ *  
+ *   This is free software; you can redistribute it and/or modify it
+ *   under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *  
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *   General Public License for more details.
+ *  
+ *   You should have received a copy of the GNU General Public License
+ *   along with userv; if not, write to the Free Software
+ *   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+%{
+
+
+
+
+
+#include <syslog.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <string.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
+#include <fnmatch.h>
+#include <limits.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <errno.h>
+
+#include "config.h"
+#include "common.h"
+#include "daemon.h"
+#include "lib.h"
+#include "tokens.h"
+
+#define HYPHEN '-'
+
+typedef int directive_fnt(int dtoken);
+static directive_fnt df_reject, df_execute, df_executefrompath;
+static directive_fnt df_executefromdirectory, df_executebuiltin;
+static directive_fnt df_errorstostderr, df_errorstosyslog, df_errorstofile;
+static directive_fnt dfg_fdwant, dfg_setflag;
+static directive_fnt df_reset, df_cd, df_userrcfile, df_include;
+static directive_fnt df_includelookup, df_includedirectory;
+static directive_fnt df_message, df_error, df_quit, df_eof;
+static directive_fnt df_if, df_catchquit, df_errorspush;
+static directive_fnt dfi_includeuserrcfile, dfi_includeclientconfig;
+/* directive functions return:
+ *  0 for success having scanned up to and including end of line but not beyond,
+ *  or tokv_error or tokv_quit.
+ * They expect to parse the whitespace before their parameters (if any).
+ */
+
+typedef int parmcondition_fnt(int ctoken, char *const *parmvalues, int *rtrue);
+static parmcondition_fnt pcf_glob, pcf_range, pcf_grep;
+/* all conditional functions return tokv_error for failure or 0 for success
+ *  at parsing and testing, in which case *rtrue is set to 0 or 1.
+ *  On success they have scanned up to and including the condition's
+ *  terminating newline; the pcf_... functions expect to parse the whitespace
+ *  between the parameter name and the condition's arguments.
+ * Otherwise they return tokv_error.
+ * The parameter-based conditionals take a list of parameter values
+ * as obtained from the parameter functions and pa_parameter,
+ * and do _not_ free it.
+ */
+
+typedef int parameter_fnt(int ptoken, char ***rvalues);
+static parameter_fnt pf_service;
+static parameter_fnt pf_callinguser, pf_serviceuser;
+static parameter_fnt pf_callinggroup, pf_servicegroup;
+static parameter_fnt pf_callingusershell, pf_serviceusershell;
+/* Parameter functions return tokv_error or 0 for success at parsing
+ * and determining the value, in which case *rvalues is made to be
+ * a mallocd null-terminated array of pointers to mallocd strings.
+ * freeparm can be used to free such an array.
+ */
+
+typedef int builtinserviceparse_fnt(char ***rnewargs);
+static builtinserviceparse_fnt bispa_none, bispa_parameter;
+/* These parse the arguments to a builtin service, including the
+ * newline at the end of the line.  *rnewargs will initially be
+ * null, indicating that no arguments are to be set; the function
+ * may store a mallocd array of mallocd strings in it,
+ * containing the arguments it wishes to have set (null-pointer
+ * terminated).
+ */
+
+static int yylex(void);
+/* Returns a token (which may be an eof or error exception) */
+
+static directive_fnt *lr_dir;
+static parmcondition_fnt *lr_parmcond;
+static builtinserviceparse_fnt *lr_bispa;
+static builtinserviceexec_fnt *lr_bisexec;
+static parameter_fnt *lr_parameter;
+static int lr_loglevel, lr_logfacility, lr_min, lr_max, *lr_flag;
+static int lr_flagval, lr_controlend;
+static int lr_fdwant_readwrite; /* -1=never, 0=opt, 1=always */
+
+/* Forward declarations of things used in lexer and parser */
+
+struct parser_state {
+  int lineno, reportlineno, notedreferer, isinternal;
+  const char *filename;
+  struct stat filestab;
+  YY_BUFFER_STATE ybuf;
+  struct parser_state *upstate;
+};
+
+static struct parser_state *cstate;
+
+struct error_handling {
+  int handling; /* One of the error handling modes tokt_ehandlemode */
+  int logfacility, loglevel;
+  int filekeep; /* File is in use by higher-level errors-push, leave it open */
+  FILE *file;
+  char *filename;
+};
+
+static struct error_handling eh = { tokv_word_errorstostderr, 0,0,0,0,0 };
+
+static int dequote(char *inplace);
+
+#define YY_NO_UNPUT
+
+%}
+
+%option noyywrap
+
+%%
+
+reject { lr_dir= df_reject; return tokv_word_reject; }
+execute-from-directory { lr_dir= df_executefromdirectory; return tokv_word_executefromdirectory; }
+execute-from-path { lr_dir= df_executefrompath; return tokv_word_executefrompath; }
+execute-builtin { lr_dir= df_executebuiltin; return tokv_word_executebuiltin; }
+errors-to-stderr { lr_dir= df_errorstostderr; return tokv_word_errorstostderr; }
+errors-to-syslog { lr_dir= df_errorstosyslog; return tokv_word_errorstosyslog; }
+errors-to-file { lr_dir= df_errorstofile; return tokv_word_errorstofile; }
+require-fd { lr_dir= dfg_fdwant; lr_fdwant_readwrite=1; return tokv_word_requirefd; }
+allow-fd { lr_dir= dfg_fdwant; lr_fdwant_readwrite=0; return tokv_word_allowfd; }
+null-fd { lr_dir= dfg_fdwant; lr_fdwant_readwrite=0; return tokv_word_nullfd; }
+reject-fd { lr_dir= dfg_fdwant; lr_fdwant_readwrite=-1; return tokv_word_rejectfd; }
+ignore-fd { lr_dir= dfg_fdwant; lr_fdwant_readwrite=-1; return tokv_word_ignorefd; }
+set-environment { lr_dir= dfg_setflag; lr_flag= &setenvironment; lr_flagval= 1; return tokv_word_setenvironment; }
+no-set-environment { lr_dir= dfg_setflag; lr_flag= &setenvironment; lr_flagval= 0; return tokv_word_nosetenvironment; }
+suppress-args { lr_dir= dfg_setflag; lr_flag= &suppressargs; lr_flagval= 1; return tokv_word_suppressargs; }
+no-suppress-args { lr_dir= dfg_setflag; lr_flag= &suppressargs; lr_flagval= 0; return tokv_word_nosuppressargs; }
+disconnect-hup { lr_dir= dfg_setflag; lr_flag= &disconnecthup; lr_flagval= 1; return tokv_word_disconnecthup; }
+no-disconnect-hup { lr_dir= dfg_setflag; lr_flag= &disconnecthup; lr_flagval= 0; return tokv_word_nodisconnecthup; }
+cd { lr_dir= df_cd; return tokv_word_cd; }
+user-rcfile { lr_dir= df_userrcfile; return tokv_word_userrcfile; }
+include { lr_dir= df_include; return tokv_word_include; }
+include-ifexist { lr_dir= df_include; return tokv_word_includeifexist; }
+include-lookup { lr_dir= df_includelookup; return tokv_word_includelookup; }
+include-lookup-all { lr_dir= df_includelookup; return tokv_word_includelookupall; }
+include-directory { lr_dir= df_includedirectory; return tokv_word_includedirectory; }
+message { lr_dir= df_message; return tokv_word_message; }
+_include-sysconfig { lr_dir= df_include; return tokv_word_includesysconfig; }
+_include-user-rcfile { lr_dir= dfi_includeuserrcfile; return tokv_word_includeuserrcfile; }
+_include-client-config { lr_dir= dfi_includeclientconfig; return tokv_word_includeclientconfig; }
+quit { lr_dir= df_quit; return tokv_word_quit; }
+eof { lr_dir= df_eof; return tokv_word_eof; }
+if { lr_dir= df_if; return tokv_word_if; }
+catch-quit { lr_dir= df_catchquit; return tokv_word_catchquit; }
+errors-push { lr_dir= df_errorspush; return tokv_word_errorspush; }
+elif { lr_controlend= tokv_word_if; return tokv_word_elif; }
+else { lr_controlend= tokv_word_if; return tokv_word_else; }
+fi { lr_controlend= tokv_word_if; return tokv_word_fi; }
+hctac { lr_controlend= tokv_word_catchquit; return tokv_word_hctac; }
+srorre { lr_controlend= tokv_word_errorspush; return tokv_word_srorre; }
+glob { lr_parmcond= pcf_glob; return tokv_word_glob; }
+range { lr_parmcond= pcf_range; return tokv_word_range; }
+grep { lr_parmcond= pcf_grep; return tokv_word_grep; }
+environment { lr_bispa= bispa_none; lr_bisexec= bisexec_environment; return tokv_word_environment; }
+parameter { lr_bispa= bispa_parameter; lr_bisexec= bisexec_parameter; return tokv_word_parameter; }
+version { lr_bispa= bispa_none; lr_bisexec= bisexec_version; return tokv_word_version; }
+toplevel { lr_bispa= bispa_none; lr_bisexec= bisexec_toplevel; return tokv_word_toplevel; }
+override { lr_bispa= bispa_none; lr_bisexec= bisexec_override; return tokv_word_override; }
+reset { lr_bispa= bispa_none; lr_bisexec= bisexec_reset; lr_dir= df_reset; return tokv_word_reset; }
+execute { lr_bispa= bispa_none; lr_bisexec= bisexec_execute; lr_dir= df_execute; return tokv_word_execute; }
+help { lr_bispa= bispa_none; lr_bisexec= bisexec_help; return tokv_word_help; }
+service { lr_parameter= pf_service; return tokv_word_service; }
+calling-user { lr_parameter= pf_callinguser; return tokv_word_callinguser; }
+calling-group { lr_parameter= pf_callinggroup; return tokv_word_callinggroup; }
+calling-user-shell { lr_parameter= pf_callingusershell; return tokv_word_callingusershell; }
+service-user { lr_parameter= pf_serviceuser; return tokv_word_serviceuser; }
+service-group { lr_parameter= pf_servicegroup; return tokv_word_servicegroup; }
+service-user-shell { lr_parameter= pf_serviceusershell; return tokv_word_serviceusershell; }
+debug { lr_loglevel= LOG_DEBUG; return tokv_syslog_debug; }
+info { lr_loglevel= LOG_INFO; return tokv_syslog_info; }
+notice { lr_loglevel= LOG_NOTICE; return tokv_syslog_notice; }
+warn(ing)? { lr_loglevel= LOG_WARNING; return tokv_syslog_warning; }
+err { lr_loglevel= LOG_ERR; return tokv_syslog_err; }
+crit { lr_loglevel= LOG_CRIT; return tokv_syslog_crit; }
+alert { lr_loglevel= LOG_ALERT; return tokv_syslog_alert; }
+emerg|panic { lr_loglevel= LOG_EMERG; return tokv_syslog_emerg; }
+auth(priv)?|security { lr_logfacility= LOG_AUTHPRIV; return tokv_syslog_authpriv; }
+cron { lr_logfacility= LOG_CRON; return tokv_syslog_cron; }
+daemon { lr_logfacility= LOG_DAEMON; return tokv_syslog_daemon; }
+kern(el)? { lr_logfacility= LOG_KERN; return tokv_syslog_kern; }
+lpr { lr_logfacility= LOG_LPR; return tokv_syslog_lpr; }
+mail { lr_logfacility= LOG_MAIL; return tokv_syslog_mail; }
+news { lr_logfacility= LOG_NEWS; return tokv_syslog_news; }
+syslog { lr_logfacility= LOG_SYSLOG; return tokv_syslog_syslog; }
+user { lr_logfacility= LOG_USER; return tokv_syslog_user; }
+uucp { lr_logfacility= LOG_UUCP; return tokv_syslog_uucp; }
+local0 { lr_logfacility= LOG_LOCAL0; return tokv_syslog_local0; }
+local1 { lr_logfacility= LOG_LOCAL1; return tokv_syslog_local1; }
+local2 { lr_logfacility= LOG_LOCAL2; return tokv_syslog_local2; }
+local3 { lr_logfacility= LOG_LOCAL3; return tokv_syslog_local3; }
+local4 { lr_logfacility= LOG_LOCAL4; return tokv_syslog_local4; }
+local5 { lr_logfacility= LOG_LOCAL5; return tokv_syslog_local5; }
+local6 { lr_logfacility= LOG_LOCAL6; return tokv_syslog_local6; }
+local7 { lr_logfacility= LOG_LOCAL7; return tokv_syslog_local7; }
+read { return tokv_word_read; }
+write { return tokv_word_write; }
+\$ { return tokv_dollar; }
+\( { return tokv_openparen; }
+\) { return tokv_closeparen; }
+\! { return tokv_not; }
+\& { return tokv_and; }
+\| { return tokv_or; }
+error { lr_dir= df_error; lr_loglevel= LOG_ERR; return tokv_word_error; }
+
+
+
+[0-9]{1,8}             {
+                         char *ep;
+                         lr_min=lr_max= (int)strtoul(yytext,&ep,10);
+                         assert(!*ep);
+                         return tokv_ordinal;
+                       }
+[0-9]{1,8}-[0-9]{1,8}  {
+                         char *ep;
+                         lr_min= (int)strtoul(yytext,&ep,10);
+                         assert(*ep == HYPHEN);
+                         assert(*++ep);
+                         lr_max= (int)strtoul(ep,&ep,10);
+                         assert(!*ep);
+                         if (lr_max < lr_min) {
+                           parseerrprint("fd range has min > max");
+                           return tokv_error;
+                         }
+                         return tokv_fdrange;
+                       }
+[0-9]{1,8}-            {
+                         char *ep;
+                         lr_min= (int)strtoul(yytext,&ep,10);
+                         assert(*ep == HYPHEN);
+                         assert(!*++ep);
+                         lr_max=-1;
+                         return tokv_fdstoend;
+                       }
+[\ \t]+                        return tokv_lwsp;
+[\ \t]*\n              cstate->lineno++; return tokv_newline;
+[\ \t]*\#[^\n]*\n      cstate->lineno++; return tokv_newline;
+[\ \t]*\#[^\n]*                {
+                         parseerrprint("missing newline at eof after comment");
+                         return tokv_error;
+                       }
+\"([^\\\"\n]|\\[a-z]|\\[0-9]{3}|\\x[0-9A-Fa-f]{2}|\\[[:punct:]]|\\[ \t]*\n)*\" {
+                         return dequote(yytext);
+                       }
+\".*                   {
+                         parseerrprint("misquoted or unterminated string");
+                         return tokv_error;
+                       }
+[^\ \t\n]+             return tokv_barestring;
+<<EOF>>                        return tokv_eof;
+
+
+%%
+
+const char *const builtinservicehelpstrings[]= {
+  "environment",
+  "parameter <parameter>",
+  "version",
+  "toplevel",
+  "override",
+  "reset",
+  "execute",
+  "help",
+   0
+};
+
+#include "parser.c"
+