X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?a=blobdiff_plain;ds=sidebyside;f=lexer.l;fp=lexer.l;h=6af03455119af5b06c40af9146834c38247aaf29;hb=d481e8196cc08ec6761f3a26da16d1e02dbbc712;hp=0000000000000000000000000000000000000000;hpb=d3fc0b07114cea6ab2294bc6ce377bdc752a059d;p=userv.git diff --git a/lexer.l b/lexer.l new file mode 100644 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; +<> return tokv_eof; + + +%% + +const char *const builtinservicehelpstrings[]= { + "environment", + "parameter ", + "version", + "toplevel", + "override", + "reset", + "execute", + "help", + 0 +}; + +#include "parser.c" +