diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2019-05-04 12:32:38 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2019-05-04 13:44:34 +0300 |
commit | 90d064900d35975950587882a00cfe92b26d94bd (patch) | |
tree | a965baa2375487805390985f5b074e1478bb2f10 | |
parent | d844bc635b0a216e9a8df68e3bc879ca3e536ed9 (diff) | |
download | rush-90d064900d35975950587882a00cfe92b26d94bd.tar.gz rush-90d064900d35975950587882a00cfe92b26d94bd.tar.bz2 |
Add testcases for the new rc syntax
* src/Makefile.am (EXTRA_DIST): Add cfgram.output
(AM_YFLAGS): Produce state map.
* src/cf.c (vcferror): Finalize the stringbuf.
* src/cf.h (cflex_pushargs,cflex_popargs)
(skiptoeol,restorenormal): New protos.
* src/cfgram.y: Provide textual token descriptions.
Minor fixes in the grammar.
* src/cflex.l: Various fixes.
* tests/Makefile.am: Move old tests to the legacy/ subdirectory.
Add new tests.
53 files changed, 1763 insertions, 123 deletions
diff --git a/src/.gitignore b/src/.gitignore index aaf3634..8be1637 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -8,5 +8,5 @@ rwopt.h cfgram.h cfgram.c cflex.c -y.output -y.tab.c +*.output +*.tab.c diff --git a/src/Makefile.am b/src/Makefile.am index 45cb983..160541e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -30,14 +30,18 @@ rush_SOURCES=\ rushopt.h\ socket.c\ transform.c\ - cflex.l cfgram.y cf.h cf.c + cflex.l\ + cfgram.y\ + cfgram.h\ + cf.h\ + cf.c rushlast_SOURCES=rushlast.c rlopt.h rushwho_SOURCES=rushwho.c rwopt.h rushlast.c: rlopt.h rushwho.c: rwopt.h -EXTRA_DIST = rush-po rushopt.opt rlopt.opt rwopt.opt getopt.m4 defconf.sed -AM_CPPFLAGS=-I$(top_srcdir)/gnu -I$(top_builddir)/gnu -I$(top_srcdir)/lib +EXTRA_DIST = rush-po rushopt.opt rlopt.opt rwopt.opt getopt.m4 defconf.sed cfgram.output +AM_CPPFLAGS=-I$(top_srcdir) -I$(top_srcdir)/gnu -I$(top_builddir)/gnu -I$(top_srcdir)/lib LDADD=../lib/librush.a ../gnu/libgnu.a @LTLIBINTL@ AM_INSTALLCHECK_STD_OPTIONS_EXEMPT=rush-po @@ -75,7 +79,7 @@ SUFFIXES=.opt .c .h .opt.h: $(AM_V_GEN)m4 -s $(srcdir)/getopt.m4 $< | sed '1d' > $@ -AM_YFLAGS=-dt +AM_YFLAGS=-dtv AM_LFLAGS=-d cflex.c: cfgram.h cfgram.h: cfgram.c @@ -1,3 +1,19 @@ +/* This file is part of GNU Rush. + Copyright (C) 2008-2019 Sergey Poznyakoff + + GNU Rush 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 3, or (at your option) + any later version. + + GNU Rush 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 GNU Rush. If not, see <http://www.gnu.org/licenses/>. */ + #include <rush.h> #include <cf.h> @@ -116,6 +132,7 @@ vcferror(struct cfloc const *loc, char const *fmt, va_list ap) cfloc_format(loc, &sb); stringbuf_add_array(&sb, ": ", 2); stringbuf_add_string(&sb, fmt); + stringbuf_finish(&sb); vlogmsg(LOG_ERR, sb.buffer, ap); stringbuf_free(&sb); } @@ -1,3 +1,19 @@ +/* This file is part of GNU Rush. + Copyright (C) 2008-2019 Sergey Poznyakoff + + GNU Rush 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 3, or (at your option) + any later version. + + GNU Rush 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 GNU Rush. If not, see <http://www.gnu.org/licenses/>. */ + struct stringbuf { char *buffer; size_t size; @@ -85,6 +101,10 @@ void cfgram_debug(int v); void cflex_setup(CFSTREAM *cf, char const *filename, int line); int cflex_include(char const *filename, struct cfloc const *loc); +void cflex_pushargs(void); +void cflex_popargs(void); +void skiptoeol(void); +void restorenormal(void); int cfparse_old(CFSTREAM *cf, char const *filename, int line); diff --git a/src/cfgram.y b/src/cfgram.y index 7d11111..052dae6 100644 --- a/src/cfgram.y +++ b/src/cfgram.y @@ -1,3 +1,19 @@ +/* This file is part of GNU Rush. + Copyright (C) 2008-2019 Sergey Poznyakoff + + GNU Rush 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 3, or (at your option) + any later version. + + GNU Rush 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 GNU Rush. If not, see <http://www.gnu.org/licenses/>. */ + %{ #include <rush.h> #include <cf.h> @@ -21,7 +37,7 @@ static void add_name_list(struct name_entry *head, enum envar_type type); regex_t regex; struct rush_rule rule; struct test_node *node; - struct { + struct strlist { char **argv; size_t argc; } strlist; @@ -44,30 +60,30 @@ static void add_name_list(struct name_entry *head, enum envar_type type); } arglist; } -%token <str> STRING -%token <str> IDENT -%token <num> NUMBER - -%token PREFACE -%token RULE -%token GLOBAL -%token EOL -%token SET -%token MAP -%token UNSET -%token MATCH -%token FALLTHROUGH -%token INCLUDE -%token LIMITS -%token CLRENV -%token SETENV -%token UNSETENV -%token KEEPENV -%token DELETE -%token EXIT -%token <attrib> ATTRIB -%token <global_attrib> GLATTRIB -%token BOGUS +%token <str> STRING "string" +%token <str> IDENT "identifier" +%token <num> NUMBER "number" + +%token PREFACE "\"rush VERSION\"" +%token RULE "\"rule\"" +%token GLOBAL "\"global\"" +%token EOL "end of line" +%token SET "\"set\"" +%token MAP "\"map\"" +%token UNSET "\"unset\"" +%token MATCH "\"match\"" +%token FALLTHROUGH "\"fallthrough\"" +%token INCLUDE "\"input\"" +%token LIMITS "\"limits\"" +%token CLRENV "\"clrenv\"" +%token SETENV "\"setenv\"" +%token UNSETENV "\"unsetenv\"" +%token KEEPENV "\"keepenv\"" +%token DELETE "\"delete\"" +%token EXIT "\"exit\"" +%token <attrib> ATTRIB "rule attribute" +%token <global_attrib> GLATTRIB "global attribute" +%token BOGUS "erroneous token" %left OR %left AND @@ -75,7 +91,7 @@ static void add_name_list(struct name_entry *head, enum envar_type type); %nonassoc EQ NE LT LE GT GE '~' IN MEMBER %type <intval> fdescr index -%type <str> literal string value defval +%type <str> literal string value defval ruleid %type <regex> regex %type <node> expr compound_cond simple_cond %type <range> range @@ -86,7 +102,7 @@ static void add_name_list(struct name_entry *head, enum envar_type type); %type <arglist> arglist %% -rcfile : PREFACE EOL rulelist +rcfile : PREFACE EOL content { if (errors) YYERROR; @@ -98,8 +114,12 @@ rcfile : PREFACE EOL rulelist } ; +content : /* empty */ + | rulelist + ; + rulelist : rule - | rulelist rule + | rulelist rule ; rule : rulehdr rulebody @@ -155,13 +175,20 @@ arg : literal } ; -rulehdr : RULE IDENT EOL +rulehdr : RULE ruleid EOL { current_rule = new_rush_rule(); current_rule->tag = $2; } ; +ruleid : /* empty */ + { + $$ = NULL; + } + | string + ; + rulebody : stmt | rulebody stmt ; @@ -175,6 +202,12 @@ stmt : match_stmt EOL | include_stmt EOL | flowctl_stmt EOL | attrib_stmt EOL + | error { skiptoeol(); } EOL + { + restorenormal(); + yyerrok; + yyclearin; + } ; /* ****************** @@ -235,7 +268,7 @@ expr : string '~' regex } | string NE literal { - $$ = new_test_node(test_cmpn); + $$ = new_test_node(test_cmps); $$->v.cmp.op = cmp_ne; $$->v.cmp.larg = $1; $$->v.cmp.rarg.str = $3; @@ -343,6 +376,16 @@ set_stmt : SET index value node->v.xf.pattern = NULL; node->v.xf.trans = compile_transform_expr($4, re_flags); } + | SET index string '~' value + { + struct transform_node *node; + + node = new_transform_node(current_rule, transform_set); + node->target.type = target_arg; + node->target.v.arg = $2; + node->v.xf.pattern = $3; + node->v.xf.trans = compile_transform_expr($5, re_flags); + } | SET IDENT value { struct transform_node *node; @@ -379,6 +422,24 @@ set_stmt : SET index value node->v.xf.pattern = NULL; node->v.xf.trans = compile_transform_expr($4, re_flags); } + | SET IDENT string '~' value + { + struct transform_node *node; + + node = new_transform_node(current_rule, transform_set); + if (strcmp($2, "command") == 0) { + node->target.type = target_command; + free($2); + } else if (strcmp($2, "program") == 0) { + node->target.type = target_program; + free($2); + } else { + node->target.type = target_var; + node->target.v.name = $2; + } + node->v.xf.pattern = $3; + node->v.xf.trans = compile_transform_expr($5, re_flags); + } | UNSET IDENT { struct transform_node *node = @@ -608,18 +669,19 @@ attrib_stmt : ATTRIB string } ; -strlist : arglist +strlist : '(' { cflex_pushargs(); } arglist ')' { int i; struct argval *arg; - $$.argc = $1.argc; - $$.argv = xcalloc($1.argc + 1, sizeof($$.argv[0])); - for (i = 0, arg = $1.head; i < $1.argc; i++, arg = arg->next) { + cflex_popargs(); + $$.argc = $3.argc; + $$.argv = xcalloc($3.argc + 1, sizeof($$.argv[0])); + for (i = 0, arg = $3.head; i < $3.argc; i++, arg = arg->next) { $$.argv[i] = arg->strval; arg->strval = NULL; } - arglist_free($1.head); + arglist_free($3.head); } ; diff --git a/src/cflex.l b/src/cflex.l index 39e3231..a6f03c2 100644 --- a/src/cflex.l +++ b/src/cflex.l @@ -1,3 +1,19 @@ +/* This file is part of GNU Rush. + Copyright (C) 2008-2019 Sergey Poznyakoff + + GNU Rush 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 3, or (at your option) + any later version. + + GNU Rush 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 GNU Rush. If not, see <http://www.gnu.org/licenses/>. */ + %{ #include <rush.h> #include <sys/stat.h> @@ -90,8 +106,6 @@ static void straychar(int); (result) = cfstream_read(input_stream, buf, max_size) %} -%option nounput -%option noinput %x NORMAL ARGS INMATCH QSTR VAR %% <INITIAL>{ @@ -125,9 +139,8 @@ rush[ \t]+2\.0[ \t]*$ { "<=" return tok(LE); ">" return tok(GT); ">=" return tok(GE); -"~" return tok('~'); -"in" { BEGIN(ARGS); return tok(IN); } -"member" { BEGIN(ARGS); return tok(MEMBER); } +"in" return tok(IN); +"member" return tok(MEMBER); } <NORMAL>{ @@ -154,17 +167,21 @@ rush[ \t]+2\.0[ \t]*$ { BEGIN(ARGS); return tok(GLATTRIB); } else { - return tok(BOGUS); + yylval.str = xstrdup(yytext); + return tok(IDENT); } } +. { straychar(yytext[0]); skiptoeol(); } } <ARGS,INMATCH>{ -[0-9]+ { yylval.num.strval = xstrdup(yytext); +[+-]?[0-9]+ { yylval.num.strval = xstrdup(yytext); yylval.num.intval = atoi(yytext); return tok(NUMBER); } -[A-Za-z_+-][A-Za-z_0-9-]* { yylval.str = xstrdup(yytext); +[A-Za-z_][A-Za-z0-9_-]* { yylval.str = xstrdup(yytext); return tok(IDENT); } +[A-Za-z_+-][A-Za-z0-9_-]* { yylval.str = xstrdup(yytext); + return tok(STRING); } \$[A-Za-z_][A-Za-z_0-9-]* { yylval.str = xstrdup(yytext); return tok(STRING); } \$\{[A-Za-z_][A-Za-z_0-9-]*\} { yylval.str = xstrdup(yytext); @@ -216,6 +233,7 @@ rush[ \t]+2\.0[ \t]*$ { strtoul(yytext + yyleng - 2, NULL, 16)); pushstart(QSTR); } +"~"|"("|")"|"["|"]" return tok(yytext[0]); } <QSTR>{ @@ -243,7 +261,8 @@ rush[ \t]+2\.0[ \t]*$ { stringbuf_add_char(&sb, strtoul(yytext + yyleng - 2, NULL, 16)); } -\n { yyerror("unescaped newline in quoted string"); return BOGUS; } +\n { advance_line(1); + yyerror("unescaped newline in quoted string"); } } <VAR>{ @@ -286,7 +305,8 @@ rush[ \t]+2\.0[ \t]*$ { [^}\"\$%]+ { stringbuf_add_array(&sb, yytext, yyleng); } } -<NORMAL,INMATCH,ARGS,VAR,QSTR>. { straychar(yytext[0]); return tok(BOGUS); } +<INMATCH,ARGS,VAR,QSTR>. { straychar(yytext[0]); + return tok(BOGUS); } %% void straychar(int c) @@ -307,6 +327,33 @@ straychar(int c) start_name[YY_START]); } } + +void +skiptoeol(void) +{ + int c; + extern int yychar; + + if (yychar == EOL) + return; + c = input(); + if (c == EOF) + return; + do { + if (c == '\n') { + break; + } + } while ((c = input()) != EOF); + unput('\n'); +} + +void +restorenormal(void) +{ + while (start_tos) + popstart(); + BEGIN(NORMAL); +} /* Input_Stream context stack */ struct inpctx { @@ -468,6 +515,18 @@ yywrap(void) } void +cflex_pushargs(void) +{ + pushstart(ARGS); +} + +void +cflex_popargs(void) +{ + popstart(); +} + +void trimws(char *s) { size_t len = strlen(s); diff --git a/src/config.c b/src/config.c index b6a8b16..448bbdd 100644 --- a/src/config.c +++ b/src/config.c @@ -790,7 +790,7 @@ _parse_exit(input_buf_ptr ibuf, struct rush_rule *rule, } else error_fd = 2; if (val[0] == '@') { - if (val[1] != '@') + if (val[1] == '@') rule->error = new_error(error_fd, val + 1, 1); else { int n = string_to_error_index(val + 1); @@ -624,6 +624,13 @@ rush_transform(struct transform_node *node, struct rush_request *req) case target_arg: /* Single command line argument */ + if (node->target.v.arg == req->argc) { + req->argv = xrealloc(req->argv, + (req->argc + 2) + * sizeof(req->argv[0])); + req->argc++; + req->argv[req->argc] = NULL; + } arg_no = get_arg_no(node->target.v.arg, req); target_ptr = &req->argv[arg_no]; target_src = req->argv[arg_no]; diff --git a/tests/Makefile.am b/tests/Makefile.am index 597a601..c0877e8 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -39,27 +39,50 @@ $(srcdir)/package.m4: $(top_srcdir)/configure.ac ## ------------ ## TESTSUITE_AT = \ + testsuite.at\ + null.at\ argc.at\ - backref.at\ - chdir.at\ command.at\ - delete.at\ - env.at\ - error.at\ - fallthrough.at\ - interactive.at\ - gid.at\ - map.at\ - match.at\ + matcharg.at\ matchprog.at\ - newgrp.at\ + uid.at\ + user.at\ + in.at\ + gid.at\ + group.at\ + and.at\ + or.at\ + compound.at\ set.at\ - setvar.at\ - testsuite.at\ + delete.at\ transform.at\ - uid.at\ - unsetvar.at\ - umask.at + map.at\ + umask.at\ + newgrp.at\ + chdir.at\ + interactive.at\ + fallthrough.at\ + error.at\ + legacy/argc.at\ + legacy/backref.at\ + legacy/chdir.at\ + legacy/command.at\ + legacy/delete.at\ + legacy/env.at\ + legacy/error.at\ + legacy/fallthrough.at\ + legacy/interactive.at\ + legacy/gid.at\ + legacy/map.at\ + legacy/match.at\ + legacy/matchprog.at\ + legacy/newgrp.at\ + legacy/set.at\ + legacy/setvar.at\ + legacy/transform.at\ + legacy/uid.at\ + legacy/unsetvar.at\ + legacy/umask.at TESTSUITE = $(srcdir)/testsuite M4=m4 diff --git a/tests/and.at b/tests/and.at new file mode 100644 index 0000000..b32a7e2 --- /dev/null +++ b/tests/and.at @@ -0,0 +1,53 @@ +# This file is part of GNU Rush. +# Copyright (C) 2019 Sergey Poznyakoff +# +# GNU Rush 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 3, or (at your option) +# any later version. +# +# GNU Rush 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 GNU Rush. If not, see <http://www.gnu.org/licenses/>. + +AT_SETUP([and]) +AT_KEYWORDS([match and]) + +AT_RUSH_TEST([ +rush 2.0 +rule + match \$0 == "/bin/ls" && \$1 ~ "^/usr" +], +[cmdline,argv,prog], + +[/bin/ls /usr/lib], +[0], +[{ + "cmdline":"/bin/ls /usr/lib", + "argv":[[ + "/bin/ls", + "/usr/lib" + ]], + "prog":null +} +], +[], + +[/bin/ls /lib], +[1], +[], +[rush: Error: no matching rule for "/bin/ls /lib", user $MY_USER +], + +[/bin/stat /usr/lib], +[1], +[], +[rush: Error: no matching rule for "/bin/stat /usr/lib", user $MY_USER +]) + +AT_CLEANUP + diff --git a/tests/argc.at b/tests/argc.at index f401cd0..9dd017b 100644 --- a/tests/argc.at +++ b/tests/argc.at @@ -1,5 +1,5 @@ # This file is part of GNU Rush. -# Copyright (C) 2008-2019 Sergey Poznyakoff +# Copyright (C) 2019 Sergey Poznyakoff # # GNU Rush is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -18,8 +18,9 @@ AT_SETUP([argc]) AT_KEYWORDS([argc]) AT_RUSH_TEST([ +rush 2.0 rule - argc 2 + match \$argc == 2 ], [cmdline,argv,prog,interactive,fork,acct], diff --git a/tests/chdir.at b/tests/chdir.at index d1c45ee..fc7e7db 100644 --- a/tests/chdir.at +++ b/tests/chdir.at @@ -18,8 +18,9 @@ AT_SETUP([chdir]) AT_KEYWORDS([chdir]) AT_RUSH_TEST([ +rush 2.0 rule - chdir $PWD + chdir "$PWD" ], [home_dir], [command], diff --git a/tests/command.at b/tests/command.at index 1425025..17f1824 100644 --- a/tests/command.at +++ b/tests/command.at @@ -1,5 +1,5 @@ # This file is part of GNU Rush. -# Copyright (C) 2008-2019 Sergey Poznyakoff +# Copyright (C) 2019 Sergey Poznyakoff # # GNU Rush is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -18,8 +18,9 @@ AT_SETUP([command]) AT_KEYWORDS([command]) AT_RUSH_TEST([ +rush 2.0 rule - command echo[[:space:]]+foo$ + match \$command ~ "echo[[:space:]]+foo$" ], [cmdline,argv,prog,interactive,fork,acct], @@ -45,4 +46,32 @@ rule [rush: Error: no matching rule for "/usr/bin/echo foo bar", user $MY_USER ]) +AT_RUSH_TEST([ +rush 2.0 +rule + match \$command == "/bin/ls" +], +[cmdline,argv,prog,interactive,fork,acct], + +[/bin/ls], +[0], +[{ + "cmdline":"/bin/ls", + "argv":[[ + "/bin/ls" + ]], + "prog":null, + "interactive":0, + "fork":-1, + "acct":-1 +} +], +[], + +[/bin/ls /], +[1], +[], +[rush: Error: no matching rule for "/bin/ls /", user $MY_USER +]) + AT_CLEANUP diff --git a/tests/compound.at b/tests/compound.at new file mode 100644 index 0000000..af61c3a --- /dev/null +++ b/tests/compound.at @@ -0,0 +1,72 @@ +# This file is part of GNU Rush. +# Copyright (C) 2019 Sergey Poznyakoff +# +# GNU Rush 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 3, or (at your option) +# any later version. +# +# GNU Rush 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 < |