diff --git a/configure b/configure index d5fa86e4..d060f009 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.71 for remind 04.03.07. +# Generated by GNU Autoconf 2.71 for remind 05.00.00. # # # Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation, @@ -608,8 +608,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='remind' PACKAGE_TARNAME='remind' -PACKAGE_VERSION='04.03.07' -PACKAGE_STRING='remind 04.03.07' +PACKAGE_VERSION='05.00.00' +PACKAGE_STRING='remind 05.00.00' PACKAGE_BUGREPORT='' PACKAGE_URL='https://dianne.skoll.ca/projects/remind/' @@ -1264,7 +1264,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures remind 04.03.07 to adapt to many kinds of systems. +\`configure' configures remind 05.00.00 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1326,7 +1326,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of remind 04.03.07:";; + short | recursive ) echo "Configuration of remind 05.00.00:";; esac cat <<\_ACEOF @@ -1414,7 +1414,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -remind configure 04.03.07 +remind configure 05.00.00 generated by GNU Autoconf 2.71 Copyright (C) 2021 Free Software Foundation, Inc. @@ -1864,7 +1864,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by remind $as_me 04.03.07, which was +It was created by remind $as_me 05.00.00, which was generated by GNU Autoconf 2.71. Invocation command line was $ $0$ac_configure_args_raw @@ -4703,7 +4703,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by remind $as_me 04.03.07, which was +This file was extended by remind $as_me 05.00.00, which was generated by GNU Autoconf 2.71. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -4768,7 +4768,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -remind config.status 04.03.07 +remind config.status 05.00.00 configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" diff --git a/configure.in b/configure.in index ebe1aecc..2ae953a8 100644 --- a/configure.in +++ b/configure.in @@ -1,6 +1,6 @@ dnl Process this file with autoconf to produce a configure script. -AC_INIT(remind, 04.03.07, , , https://dianne.skoll.ca/projects/remind/) +AC_INIT(remind, 05.00.00, , , https://dianne.skoll.ca/projects/remind/) AC_CONFIG_SRCDIR([src/queue.c]) cat <<'EOF' diff --git a/docs/WHATSNEW b/docs/WHATSNEW index 288f5144..a4711bf3 100644 --- a/docs/WHATSNEW +++ b/docs/WHATSNEW @@ -1,5 +1,62 @@ CHANGES TO REMIND +* VERSION 5.0 Patch 0 - 2024-??-?? + +* MAJOR CHANGE: The expression evaluation engine has been completely replaced + with a new one that splits parsing and evaluating into two separate steps. + It also features short-circuit evaluation of &&, ||, iif() and choose(). + This should speed up expression-heavy reminder files. + + NOTE INCOMPATIBILITY: In expressions with side-effects, the short-circuit + evaluation might change the result you get. For example, consider + running the following file through "remind file.rem 2024-06-04" + + SET a trig("Mon +7") || trig("Thu +7") + MSG trig = [trig()] + + Older Remind versions will output: + + trig = 2024-06-06 + + whereas this version outputs: + + trig = 2024-06-10 + + because the second part of the "||" expression is not evaluated. The vast + majority of Remind expressions do not have side-effects and should yield + the same results as before. + + The newer expression engine also permits recursive functions, but + these are not recommended. Still, if you want to, you can do: + + fset factorial(n) iif(n <= 1, 1, n*factorial(n-1)) + + and it will work for values of n that don't cause integer overflow. + +* NEW FEATURE: Add EXPR OFF command to completely disable expression + evaluation. Useful if you INCLUDE files that you don't expect to + contain expressions and may come from slightly untrustworthy sources. + +* NEW FEATURE: Add $ExpressionTimeLimit system variable to enforce a + maximum limit on how long evaluating an expression is allowed to take. + +* NEW FEATURE: Add --max-execution-time=n command-line option to terminate + Remind if it runs for more than n seconds. + +* CHANGE: Make the command-line option "-ifoo" equivalent to "-ifoo=0" + +* CHANGE: Permit a literal [ in a reminder by using the sequence [[ + The old ["["] still works. + +* BUG FIX: In "purge" mode, Remind would sometimes purge reminders with + a relative "SCANFROM" which haven't actually expired. This has been fixed. + +* BUG FIX: Disallow something like: FSET func(x, x) expr + which shouldn't have been allowed in the first place. + +* BUG FIX: Replace leading spaces with tabs in Makefiles (per Emanuele Torre + and Tim Chase) + * VERSION 4.3 Patch 7 - 2024-04-29 * IMPROVEMENT: build.tk: Add a note if build.tk obtains default settings diff --git a/man/remind.1.in b/man/remind.1.in index 11ba8628..38462979 100644 --- a/man/remind.1.in +++ b/man/remind.1.in @@ -468,7 +468,11 @@ resources. Note that the limit \fIn\fR is approximate and \fBRemind\fR might execute for one or two more seconds before it is killed. If \fIn\fR is specified as zero, then no limit is applied, just as if the option had not been used at all. - +.PP +If a limit is applied, it applies only to the foreground run of \fBRemind\fR. +If \fBRemind\fR finishes processing the script and then starts handling +queued reminders, the time limit is reset to no limit. +.PP .SH REMINDER FILES .PP \fBRemind\fR uses scripts to control its operation. You can use any @@ -4214,6 +4218,14 @@ with square brackets. For example: This evaluates the expression "mydate", where "mydate" is presumably some pre-computed variable, and then "pastes" the result into the command-line for the parser to process. +.PP +If you want a literal "[" character for some reason, simply use "[[". For +example: +.PP +.nf + REM MSG Here are [[square] brackets! +.fi + .PP A formal description of this is: When \fBRemind\fR encounters a "pasted-in" expression, it evaluates the expression, and coerces the diff --git a/src/init.c b/src/init.c index 575e3cdb..f265ba4b 100644 --- a/src/init.c +++ b/src/init.c @@ -1014,8 +1014,17 @@ AddTrustedUser(char const *username) NumTrustedUsers++; } -static void -limit_execution_time(int t) +static pid_t LimiterPid = (pid_t) -1; + +void unlimit_execution_time(void) +{ + if (LimiterPid != (pid_t) -1) { + kill(LimiterPid, SIGTERM); + LimiterPid = (pid_t) -1; + } +} + +static void limit_execution_time(int t) { pid_t parent = getpid(); @@ -1026,6 +1035,7 @@ limit_execution_time(int t) } if (pid > 0) { + LimiterPid = pid; /* In the parent */ return; } diff --git a/src/main.c b/src/main.c index 57d789c2..91cf4f34 100644 --- a/src/main.c +++ b/src/main.c @@ -57,6 +57,9 @@ static void DoReminders(void); void exitfunc(void) { + /* Kill any execution-time-limiter process */ + unlimit_execution_time(); + fflush(stdout); fflush(stderr); if (DebugFlag & DB_PARSE_EXPR) { diff --git a/src/protos.h b/src/protos.h index 2893a89c..f70996c8 100644 --- a/src/protos.h +++ b/src/protos.h @@ -62,6 +62,7 @@ expr_node *parse_expression(char const **e, int *r, Var *locals); int evaluate_expression(expr_node *node, Value *locals, Value *ans, int *nonconst); int evaluate_expr_node(expr_node *node, Value *locals, Value *ans, int *nonconst); void print_expr_tree(expr_node *node, FILE *fp); +void unlimit_execution_time(void); expr_node *free_expr_tree(expr_node *node); int EvalExpr (char const **e, Value *v, ParsePtr p); int DoCoerce (char type, Value *v); diff --git a/src/queue.c b/src/queue.c index 057c2d93..a3f96e55 100644 --- a/src/queue.c +++ b/src/queue.c @@ -313,6 +313,9 @@ void HandleQueuedReminders(void) /* Disable any potential pending SIGALRMs */ alarm(0); + /* Un-limit execution time */ + unlimit_execution_time(); + /* Turn off sorting -- otherwise, TriggerReminder has no effect! */ SortByDate = 0; diff --git a/tests/test.cmp b/tests/test.cmp index e245b262..10cc50a5 100644 --- a/tests/test.cmp +++ b/tests/test.cmp @@ -1023,7 +1023,7 @@ set a057 value("a05"+"6") "a05" + "6" => "a056" value("a056") => "SDFJHSDF KSJDFH KJSDFH KSJDFH" set a058 version() -version() => "04.03.07" +version() => "05.00.00" set a059 wkday(today()) today() => 1991-02-16 wkday(1991-02-16) => "Saturday" @@ -2612,7 +2612,7 @@ a086 4 a109 2012-01-01 a128 2018-02-03@16:45 a039 "February" -a058 "04.03.07" +a058 "05.00.00" a077 "1992 92\n" a096 -4 a119 -1 @@ -11806,7 +11806,7 @@ SECURITY: Won't read world-writable file or directory! Error reading include_dir/ww: Can't open file SECURITY: Won't read world-writable file or directory! Error reading include_dir/ww: No files matching *.rem -04.03.07 +05.00.00 NOTE JSONQUEUE [{"priority":2,"eventstart":"VOLATILE","time":"23:59","nexttime":"23:59","tdelta":0,"trep":0,"rundisabled":0,"ntrig":1,"filename":"../tests/queue2.rem","lineno":1,"type":"MSG_TYPE","body":"XXXX"},{"priority":999,"eventstart":"VOLATILE","time":"23:58","nexttime":"23:58","tdelta":0,"trep":0,"rundisabled":0,"ntrig":1,"filename":"../tests/queue1.rem","lineno":5,"type":"MSG_TYPE","body":"quux"},{"priority":42,"eventstart":"VOLATILE","time":"23:57","nexttime":"23:57","tdelta":0,"trep":0,"rundisabled":0,"ntrig":1,"filename":"../tests/queue1.rem","lineno":4,"type":"MSG_TYPE","body":"bar"},{"priority":5000,"eventstart":"VOLATILE","time":"23:56","nexttime":"23:56","tdelta":0,"trep":0,"rundisabled":0,"ntrig":1,"filename":"../tests/queue1.rem","lineno":3,"type":"MSG_TYPE","body":"foo"}] NOTE ENDJSONQUEUE