mirror of
https://salsa.debian.org/dskoll/remind.git
synced 2026-04-16 14:28:40 +02:00
Compare commits
65 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e3297fe751 | ||
|
|
58ca741a1c | ||
|
|
14dbbc7bb4 | ||
|
|
df55c4032b | ||
|
|
3768155a20 | ||
|
|
2f3b9cadf4 | ||
|
|
2c79a6531a | ||
|
|
be5c856f4b | ||
|
|
712a333f08 | ||
|
|
b753e84c8c | ||
|
|
4b4acaadbb | ||
|
|
8a52f9b67d | ||
|
|
e372606281 | ||
|
|
c443d0a9da | ||
|
|
42c9ae9ea8 | ||
|
|
dac9bb4187 | ||
|
|
812d926f66 | ||
|
|
45831ea69f | ||
|
|
354e1d236b | ||
|
|
ac478039cf | ||
|
|
96f5799e6f | ||
|
|
e21479f696 | ||
|
|
25dc883e15 | ||
|
|
bfb1374ee3 | ||
|
|
cacd8f9792 | ||
|
|
3e9053a3c6 | ||
|
|
5fa357fec2 | ||
|
|
f109c3d696 | ||
|
|
b097ce7279 | ||
|
|
1297854935 | ||
|
|
0a1d0011f6 | ||
|
|
20db1be0a0 | ||
|
|
143f1d6144 | ||
|
|
358f6c9497 | ||
|
|
ca26544be8 | ||
|
|
5ceffddd5b | ||
|
|
8e3ddb96b3 | ||
|
|
377de36b35 | ||
|
|
4395e2f7ed | ||
|
|
1d0cc31b10 | ||
|
|
4b4b2ddcd4 | ||
|
|
3c9b5b786e | ||
|
|
08f1bea6ce | ||
|
|
a2cc5943e0 | ||
|
|
895ac6f0f7 | ||
|
|
759ca0253e | ||
|
|
0ca368c8d9 | ||
|
|
a467cc1b84 | ||
|
|
c65fd826a5 | ||
|
|
bd6f4e1b43 | ||
|
|
169520914f | ||
|
|
a163a0c446 | ||
|
|
295aeb0ed8 | ||
|
|
9b2fdad56c | ||
|
|
7a1184d3c5 | ||
|
|
b036244316 | ||
|
|
5ad5366e8a | ||
|
|
244677e524 | ||
|
|
f5a094a973 | ||
|
|
5681ebdb12 | ||
|
|
664fa5f08f | ||
|
|
14edec5eae | ||
|
|
6adfd2e739 | ||
|
|
34409f7a7d | ||
|
|
7e13d1052c |
19
.gitignore
vendored
19
.gitignore
vendored
@@ -1,16 +1,17 @@
|
||||
*.bak
|
||||
*.o
|
||||
*~
|
||||
.gitignore
|
||||
TAGS
|
||||
autom4te.cache
|
||||
config.log
|
||||
config.status
|
||||
src/Makefile
|
||||
www/Makefile
|
||||
*.o
|
||||
src/config.h
|
||||
src/remind
|
||||
rem2html/Makefile
|
||||
src/*.tar.gz*
|
||||
tests/test.out
|
||||
.gitignore
|
||||
*~
|
||||
src/Makefile
|
||||
src/config.h
|
||||
src/rem2ps
|
||||
src/remind
|
||||
src/version.h
|
||||
TAGS
|
||||
tests/test.out
|
||||
www/Makefile
|
||||
|
||||
@@ -3,7 +3,7 @@ THE REMIND COPYRIGHT
|
||||
1. REMIND refers to the entire set of files and documentation in the
|
||||
REMIND package.
|
||||
|
||||
2. REMIND is Copyright 1992-2020 Dianne Skoll, except where noted in
|
||||
2. REMIND is Copyright 1992-2021 Dianne Skoll, except where noted in
|
||||
individual files.
|
||||
|
||||
3. DISTRIBUTION AND USE
|
||||
|
||||
3
Makefile
3
Makefile
@@ -18,7 +18,8 @@ install:
|
||||
@echo "* *"
|
||||
@echo "*********************"
|
||||
@echo ""
|
||||
@cd src && $(MAKE) install
|
||||
@$(MAKE) -C src install
|
||||
@$(MAKE) -C rem2html install
|
||||
|
||||
clean:
|
||||
find . -name '*~' -exec rm {} \;
|
||||
|
||||
49
configure
vendored
49
configure
vendored
@@ -626,6 +626,7 @@ VERSION
|
||||
EGREP
|
||||
GREP
|
||||
CPP
|
||||
PERL
|
||||
SET_MAKE
|
||||
LN_S
|
||||
INSTALL_DATA
|
||||
@@ -3274,6 +3275,46 @@ $as_echo "no" >&6; }
|
||||
SET_MAKE="MAKE=${MAKE-make}"
|
||||
fi
|
||||
|
||||
# Extract the first word of "perl", so it can be a program name with args.
|
||||
set dummy perl; ac_word=$2
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
$as_echo_n "checking for $ac_word... " >&6; }
|
||||
if ${ac_cv_path_PERL+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
case $PERL in
|
||||
[\\/]* | ?:[\\/]*)
|
||||
ac_cv_path_PERL="$PERL" # Let the user override the test with a path.
|
||||
;;
|
||||
*)
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for as_dir in $PATH
|
||||
do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_path_PERL="$as_dir/$ac_word$ac_exec_ext"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
IFS=$as_save_IFS
|
||||
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
PERL=$ac_cv_path_PERL
|
||||
if test -n "$PERL"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5
|
||||
$as_echo "$PERL" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -3820,7 +3861,7 @@ _ACEOF
|
||||
|
||||
|
||||
|
||||
for ac_header in sys/file.h glob.h wctype.h locale.h
|
||||
for ac_header in sys/types.h sys/file.h glob.h wctype.h locale.h
|
||||
do :
|
||||
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
|
||||
@@ -3991,9 +4032,10 @@ _ACEOF
|
||||
fi
|
||||
done
|
||||
|
||||
VERSION=03.03.06
|
||||
VERSION=03.03.09
|
||||
|
||||
ac_config_files="$ac_config_files src/Makefile www/Makefile src/version.h"
|
||||
|
||||
ac_config_files="$ac_config_files src/Makefile www/Makefile src/version.h rem2html/Makefile"
|
||||
|
||||
cat >confcache <<\_ACEOF
|
||||
# This file is a shell script that caches the results of configure
|
||||
@@ -4689,6 +4731,7 @@ do
|
||||
"src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
|
||||
"www/Makefile") CONFIG_FILES="$CONFIG_FILES www/Makefile" ;;
|
||||
"src/version.h") CONFIG_FILES="$CONFIG_FILES src/version.h" ;;
|
||||
"rem2html/Makefile") CONFIG_FILES="$CONFIG_FILES rem2html/Makefile" ;;
|
||||
|
||||
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
|
||||
esac
|
||||
|
||||
@@ -49,6 +49,7 @@ AC_PROG_CC
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_LN_S
|
||||
AC_PROG_MAKE_SET
|
||||
AC_PATH_PROG([PERL], [perl])
|
||||
|
||||
dnl Checks for libraries.
|
||||
dnl Replace `main' with a function in -lm:
|
||||
@@ -61,7 +62,7 @@ AC_CHECK_SIZEOF(unsigned int)
|
||||
AC_CHECK_SIZEOF(unsigned long)
|
||||
|
||||
dnl Checks for header files.
|
||||
AC_CHECK_HEADERS(sys/file.h glob.h wctype.h locale.h)
|
||||
AC_CHECK_HEADERS(sys/types.h sys/file.h glob.h wctype.h locale.h)
|
||||
|
||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_STRUCT_TM
|
||||
@@ -75,6 +76,7 @@ if test "$GCC" = yes; then
|
||||
fi
|
||||
|
||||
AC_CHECK_FUNCS(setenv unsetenv glob mbstowcs setlocale)
|
||||
VERSION=03.03.06
|
||||
VERSION=03.03.09
|
||||
AC_SUBST(VERSION)
|
||||
AC_OUTPUT(src/Makefile www/Makefile src/version.h)
|
||||
AC_SUBST(PERL)
|
||||
AC_OUTPUT(src/Makefile www/Makefile src/version.h rem2html/Makefile)
|
||||
|
||||
@@ -1,5 +1,64 @@
|
||||
CHANGES TO REMIND
|
||||
|
||||
* VERSION 3.3 Patch 9 - 2021-10-14
|
||||
|
||||
- NEW FEATURE: Add "-+username" option to tell Remind to trust files owned by
|
||||
"username" and allow RUN directives in them. Idea courtesy of Ian! D. Allen
|
||||
|
||||
- NEW FEATURE: Add "-u+username" variant to tell Remind to switch users to
|
||||
"username" without disabling RUN directices. Idea courtesy of Ian! D. Allen
|
||||
|
||||
- CHANGE: rem2html: rem2html has been moved out of the www/ directory into
|
||||
its own rem2html/ directory. If your system has the prerequisites
|
||||
(namely Perl, Getopt::Long and JSON::Any) then rem2html will be installed
|
||||
by "make install".
|
||||
|
||||
- CHANGE: Remove "cm2rem". It was about 20 years obsolete.
|
||||
|
||||
- CHANGE: rem2html: Use inline data: URL images for moon images by default,
|
||||
thus producing a completely stand-alone HTML file.
|
||||
|
||||
- CHANGE: Remove unnecessary spaces from "remind -pp" JSON output.
|
||||
|
||||
- DOCUMENTATION FIX: Various man page fixes and tweaks.
|
||||
|
||||
- BUG FIX: rem2html: Tweak the default CSS stylesheet; more rational
|
||||
handling of rem2html command-line options.
|
||||
|
||||
- BUG FIX: remind: "remind -c" would sometimes highlight *two* days as
|
||||
"today"; this has been fixed.
|
||||
|
||||
- BUG FIX: Add a missing #ifdef...#endif and remove a C99-ism. This once again
|
||||
allows Remind to be compiled with some very old C compilers.
|
||||
|
||||
* VERSION 3.3 Patch 8 - 2021-09-13
|
||||
|
||||
- NEW FEATURE: remind: Add INCLUDECMD command
|
||||
|
||||
- NEW FEATURE: remind: Add shellescape() built-in function
|
||||
|
||||
- BUG FIX: tkremind: TkRemind would sometimes fill in incorrect initial
|
||||
values for the reminder-editing form if you clicked on a TkRemind-created
|
||||
reminder to edit it. This has been fixed.
|
||||
|
||||
- BUG FIX: tkremind: Get back better error messages from Remind if you
|
||||
try to create a reminder with an invalid date specification.
|
||||
|
||||
- BUG FIX: remind: Catch integer overflow if we try to evaluate $IntMin * -1
|
||||
|
||||
- DOC UPDATES: remind: Minor man page fixes
|
||||
|
||||
* VERSION 3.3 Patch 7 - 2021-05-10
|
||||
|
||||
- MINOR FIX: Refuse to run "make test" as root --- it would fail
|
||||
anyway with an obscure message.
|
||||
|
||||
- BUG FIX: Remind would sometimes compute incorrect trigger date for:
|
||||
REM Tue 29 Feb MSG ...
|
||||
|
||||
- BUG FIX: Remind would sometimes compute incorrect trigger date for
|
||||
a date spec like: Tue 31 2021 MSG ...
|
||||
|
||||
* VERSION 3.3 Patch 6 - 2021-03-30
|
||||
|
||||
- test/test.rem: Change local to en_US.utf-8 only if current locale
|
||||
|
||||
25
man/cm2rem.1
25
man/cm2rem.1
@@ -1,25 +0,0 @@
|
||||
.TH CM2REM 1 "18 October 1999"
|
||||
.UC 4
|
||||
.SH NAME
|
||||
cm2rem.tcl \- Convert Sun's "cm" input file to Remind format
|
||||
.SH SYNOPSIS
|
||||
.B cm2rem.tcl < cm_file > remind_file
|
||||
.SH DESCRIPTION
|
||||
\fBcm2rem.tcl\fR reads the Sun calendar manager data file and converts
|
||||
it into a \fBRemind\fR script. Note that \fBcm2rem.tcl\fR can convert
|
||||
\fIonly\fR version 3 calendar manager files. If you are using version 4
|
||||
files, there should be a system utility to convert them to version 3 files.
|
||||
.SH AUTHOR
|
||||
\fBcm2rem.tcl\fR was written by Dianne Skoll <dianne@skoll.ca>.
|
||||
.SH BUGS
|
||||
Not all of the Sun calendar manager options are respected. In particular,
|
||||
nothing is done for e-mail actions. Also, the resulting Remind script
|
||||
is not editable with \fBTkRemind\fR; you can only edit it with a text
|
||||
editor.
|
||||
.PP
|
||||
\fBcm2rem.tcl\fR requires Tcl/Tk version 8.0 or higher. The
|
||||
\fBtclsh\fR interpreter must be on your \fBpath\fR.
|
||||
|
||||
.SH SEE ALSO
|
||||
\fBremind(1)\fR, \fBtkremind(1)\fR
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.TH REM 1 "1 January 2020"
|
||||
.TH REM 1 "1 January 2021"
|
||||
.UC 4
|
||||
.SH NAME
|
||||
rem \- Invoke Remind with a default filename
|
||||
|
||||
@@ -475,7 +475,7 @@ present and the value will be the type of SPECIAL (such as SHADE, COLOR,
|
||||
MOON, etc.)
|
||||
.TP
|
||||
.B tags \fIdata\fR
|
||||
If any TAG clauses are present, the \fBtag\fR key will be present and consist
|
||||
If any TAG clauses are present, the \fBtags\fR key will be present and consist
|
||||
of a comma-separated list of tags.
|
||||
.TP
|
||||
.B time \fIt\fR
|
||||
|
||||
89
man/remind.1
89
man/remind.1
@@ -1,4 +1,4 @@
|
||||
.TH REMIND 1 "1 January 2020"
|
||||
.TH REMIND 1 "1 January 2021"
|
||||
.UC 4
|
||||
.SH NAME
|
||||
remind \- a sophisticated reminder service
|
||||
@@ -31,7 +31,8 @@ ignore them for now and skip to the section "REMINDER FILES".
|
||||
.B \-n
|
||||
The \fB\-n\fR option causes \fBRemind\fR to print the \fBnext\fR occurrence
|
||||
of each reminder in a simple calendar format. You can sort this by
|
||||
date by piping the output through \fBsort(1)\fR.
|
||||
date by piping the output through \fBsort(1)\fR. Note that the \fB\-n\fR
|
||||
option causes any \fB\-g\fR option to be \fIignored\fR.
|
||||
.TP
|
||||
.B \-j\fR[\fIn\fR]
|
||||
Runs \fBRemind\fR in "purge" mode to get rid of expired reminders.
|
||||
@@ -39,7 +40,7 @@ See the section PURGE MODE for details.
|
||||
.TP
|
||||
.B \-r
|
||||
The \fB\-r\fR option disables \fBRUN\fR directives and the \fBshell()\fR
|
||||
function. As of Remind 3.00.17, using \fB\-u\fR implies \fB\-r\fR.
|
||||
function.
|
||||
.TP
|
||||
.B \-c\fI[flags]\fIn\fR
|
||||
The \fB\-c\fR option causes \fBRemind\fR to produce a calendar that is
|
||||
@@ -250,6 +251,7 @@ The optional \fBa\fR and \fBd\fR characters specify the sort order
|
||||
(ascending or descending) for the date, time and priority fields. See
|
||||
the section "SORTING REMINDERS" for more information.
|
||||
|
||||
Note that \fB\-g\fR is \fIignored\fR if you use the \fB\-n\fR option.
|
||||
.TP
|
||||
\fB\-b\fR[\fIn\fR]
|
||||
Set the time format for the calendar and simple-calendar outputs. \fIN\fR
|
||||
@@ -308,7 +310,11 @@ and user name, respectively, of the specified user. LOGNAME is also
|
||||
set to the specified user name. This option is meant for
|
||||
use in shell scripts that mail reminders to all users. Note that
|
||||
as of Remind 3.00.17, using \fB\-u\fR implies \fB\-r\fR -- the RUN
|
||||
directive and shell() functions are disabled.
|
||||
directive and shell() functions are disabled. However, if you prefix
|
||||
\fIname\fR with a \fB+\fR-sign, then RUN and shell() are \fInot\fR
|
||||
disabled. That is, \fB\-uwhatever\fR switches the user to \fBwhatever\fR
|
||||
and disables RUN, whereas \fB\-u+whatever\fR switches the user to
|
||||
\fBwhatever\fR but leaves RUN enabled.
|
||||
.PP
|
||||
.RS
|
||||
Non-root users can also use the \fB\-u\fR option. However, in this
|
||||
@@ -316,6 +322,13 @@ case, it only changes the environment variables as described above.
|
||||
It does not change the effective uid or gid.
|
||||
.RE
|
||||
.TP
|
||||
\fB\-+\fIusername\fR
|
||||
Causes \fBRemind\fR to trust files owned by the user \fIusername\fR.
|
||||
Normally, if \fBRemind\fR reads a file that you do not own, it disables
|
||||
RUN and the shell() function. This option causes it to also trust files
|
||||
owned by \fIusername\fR. You can supply multiple \fB\-+\fR options
|
||||
to trust multiple users, up to a limit of 20 trusted users.
|
||||
.TP
|
||||
\fB-y\fR
|
||||
Causes \fBRemind\fR to synthesize a tag for any reminder that lacks a
|
||||
TAG clause.
|
||||
@@ -349,7 +362,7 @@ it as YYYY-MM-DD or YYYY/MM/DD. You can even supply a date and
|
||||
time on the command line as one argument: YYYY-MM-DD@HH:MM.
|
||||
.PP
|
||||
In addition, you can supply a \fIrepeat\fR parameter, which has the
|
||||
form *\fInum\fR. This causes \fBRemind\fR to be run \fInum\fR times,
|
||||
form *\fIrep\fR. This causes \fBRemind\fR to be run \fIrep\fR times,
|
||||
with the date incrementing on each iteration. You may have to enclose
|
||||
the parameter in quotes to avoid shell expansion. See the subsection
|
||||
"Repeated Execution" in the section "CALENDAR MODE" for more
|
||||
@@ -618,7 +631,7 @@ present. Examples:
|
||||
.nf
|
||||
REM Sat 1 MSG First Saturday of every month
|
||||
REM Mon Tue Wed Thu Fri 15 \\
|
||||
MSG 1st working day after 15th of every month
|
||||
MSG 1st working day on or after 15th of every month
|
||||
.fi
|
||||
.PP
|
||||
11.
|
||||
@@ -1579,6 +1592,53 @@ It will not run set-uid. If it reads a file you don't own, it will
|
||||
disable RUN and the shell() function. And if it is run as \fIroot\fR,
|
||||
it will only read files owned by \fIroot\fR.
|
||||
.PP
|
||||
Note that if \fBRemind\fR reads standard input, it does \fInot\fR
|
||||
attempt to check the ownership of standard input, even if it is
|
||||
coming from a file, and hence does \fInot\fR disable RUN and shell()
|
||||
in this situation.
|
||||
|
||||
.SH THE INCLUDECMD COMMAND
|
||||
.PP
|
||||
\fBRemind\fR allows you to execute a shell command and evaluate the
|
||||
output of that command as if it were an included file. For example,
|
||||
you could have scripts that extract reminders out of a database and print
|
||||
them on stdout as REM commands. Here is an example:
|
||||
.PP
|
||||
.nf
|
||||
INCLUDECMD extract_reminders_for dfs
|
||||
.fi
|
||||
.PP
|
||||
We assume that the command "extract_reminders_for" extracts reminders out
|
||||
of a central database for the named user. Another use-case of INCLUDECMD
|
||||
is if you have your reminders stored in a file in some non-Remind format;
|
||||
you can write a command that transforms them to Remind format and then
|
||||
Remind can "include" the file with an appropriate INCLUDECMD command.
|
||||
.PP
|
||||
Note that if RUN is disabled, then INCLUDECMD will fail with the error
|
||||
message "RUN disabled"
|
||||
.PP
|
||||
INCLUDECMD passes the rest of the line to \fBpopen\fR(3), meaning that
|
||||
the command is executed by the shell. As such, shell metacharacters
|
||||
may need escaping or arguments quoting, depending on what you're trying
|
||||
to do. Remind itself does not perform any modification of the command
|
||||
line (apart from the normal [expr] expression-pasting mechanism).
|
||||
.PP
|
||||
If the command passed to INCLUDECMD begins with an exclamation mark "!",
|
||||
then Remind disables \fBRUN\fR for the output of the command. If you are
|
||||
running a command whose output you don't quite trust, you should
|
||||
prefix it with "!" so that any RUN commands it emits fail.
|
||||
.PP
|
||||
An \fBINCLUDECMD\fR command counts towards the INCLUDE nesting depth.
|
||||
For any given Remind run, a given INCLUDECMD command is only executed
|
||||
once and the results are cached. For example, if you generate a
|
||||
calendar, each unique INCLUDECMD command is run just once, not once
|
||||
for each day of the produced calendar. "Uniqueness" is determined by
|
||||
looking at the command that will be passed to the shell, so if (for example)
|
||||
your INCLUDECMD uses expression-pasting that results in differences depending
|
||||
on the value of \fBtoday()\fR, then each \fIunique\fR version of the
|
||||
command will be executed once.
|
||||
.PP
|
||||
|
||||
.SH THE BANNER COMMAND
|
||||
.PP
|
||||
When \fBRemind\fR first issues a reminder, it prints a message like this:
|
||||
@@ -2851,6 +2911,23 @@ If \fImaxlen\fR is specified, then \fBshell()\fR returns the first
|
||||
\fImaxlen\fR is specified as a negative number, then \fIall\fR the
|
||||
output from \fIcmd\fR is returned.
|
||||
.RE
|
||||
.TP
|
||||
.B shellescape(s_str)
|
||||
Returns \fIstr\fR with all shell metacharacters such as " ", "*", etc
|
||||
escaped with a backslash. For example:
|
||||
.PP
|
||||
.nf
|
||||
SET a shellescape("a b*? c&d$e")
|
||||
.fi
|
||||
.RS
|
||||
.PP
|
||||
will set \fBa\fR to:
|
||||
.RE
|
||||
.PP
|
||||
.nf
|
||||
"a\\ b\\*\\?\\ c\\&d\\$e"
|
||||
.fi
|
||||
|
||||
.TP
|
||||
.B slide(d_start, i_amt [,s_wkday...])
|
||||
This function is the inverse of \fBnonomitted\fR. It adds \fIamt\fR
|
||||
|
||||
29
rem2html/Makefile.in
Normal file
29
rem2html/Makefile.in
Normal file
@@ -0,0 +1,29 @@
|
||||
# Set by configure - don't touch.
|
||||
srcdir=@srcdir@
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
mandir=@mandir@
|
||||
bindir=@bindir@
|
||||
datadir=@datadir@
|
||||
datarootdir=@datarootdir@
|
||||
PERL=@PERL@
|
||||
PERLMODS_NEEDED=JSON::Any Getopt::Long
|
||||
all:
|
||||
true
|
||||
|
||||
install:
|
||||
@if test "$(PERL)" = "" ; then \
|
||||
echo "Not installing rem2html; Perl is required"; exit 0; fi; \
|
||||
for m in $(PERLMODS_NEEDED) ; \
|
||||
do \
|
||||
perl -M$$m -e 1 > /dev/null 2>&1; \
|
||||
if test $$? != 0 ; then echo "Not installing rem2html; missing $$m"; exit 0; fi; \
|
||||
done; \
|
||||
echo "Installing rem2html in $(DESTDIR)$(bindir)"; \
|
||||
mkdir -p $(DESTDIR)$(bindir) && sed -e 's|^#!perl|#!$(PERL)|' < rem2html > $(DESTDIR)$(bindir)/rem2html && chmod 755 $(DESTDIR)$(bindir)/rem2html && exit 0; \
|
||||
exit 1;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
12
rem2html/README.rem2html
Normal file
12
rem2html/README.rem2html
Normal file
@@ -0,0 +1,12 @@
|
||||
REM2HTML
|
||||
--------
|
||||
|
||||
rem2html is a Perl script that transforms the output of `remind -pp
|
||||
...' to HTML. Type `perl rem2html --help' for usage information.
|
||||
|
||||
rem2html requires the Perl modules `JSON::Any' and `Getopt::Long'. It
|
||||
will not be installed unless you have those modules as well as Perl
|
||||
itself.
|
||||
|
||||
--
|
||||
Dianne Skoll
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/perl
|
||||
#!perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
@@ -16,15 +16,20 @@ my($days, $shades, $moons, $classes, $Month, $Year, $Numdays, $Firstwkday, $Mond
|
||||
my $TIDY_PROGNAME = $0;
|
||||
$TIDY_PROGNAME =~ s|^.*/||;
|
||||
|
||||
# rem2html -- convert the output of "remind -p" to HTML
|
||||
# rem2html -- convert the output of "remind -pp" to HTML
|
||||
|
||||
=head1 NAME
|
||||
|
||||
rem2html - Convert the output of "remind -p" to HTML
|
||||
rem2html - Convert the output of "remind -pp" to HTML
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
remind -p ... | rem2html [options]
|
||||
remind -pp ... | rem2html [options]
|
||||
|
||||
You can also use the old interchange format as below, but the -pp
|
||||
version is preferred.
|
||||
|
||||
remind -p ... | rem2html [options]
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
@@ -50,13 +55,21 @@ month name a link to I<url>.
|
||||
|
||||
=item --imgbase I<url>
|
||||
|
||||
When creating URLs for images and the stylesheet, use
|
||||
I<url> as the base URL.
|
||||
When creating URLs for the stylesheet or external images, use I<url>
|
||||
as the base URL.
|
||||
|
||||
=item --pngs
|
||||
|
||||
Normally, rem2html uses inline "data:" URLs for the moon phase images,
|
||||
yielding a standalone HTML file. The C<--pngs> option makes it use
|
||||
external images named firstquarter.png, fullmoon.png, lastquarter.png
|
||||
and newmoon.png, which are expected to live in C<--imgbase>.
|
||||
|
||||
=item --stylesheet I<url.css>
|
||||
|
||||
Use I<url.css> as the stylesheet. If this option is used,
|
||||
I<url.css> is I<not> interpreted relative to B<imgbase>.
|
||||
I<url.css> is interpreted relative to B<imgbase> I<unless> it start
|
||||
with a "/".
|
||||
|
||||
=item --nostyle
|
||||
|
||||
@@ -97,9 +110,9 @@ sub usage
|
||||
$exit_status = 1;
|
||||
}
|
||||
print STDERR <<"EOM";
|
||||
$TIDY_PROGNAME: Produce an HTML calendar from the output of "remind -p"
|
||||
$TIDY_PROGNAME: Produce an HTML calendar from the output of "remind -pp"
|
||||
|
||||
Usage: remind -p ... | rem2html [options]
|
||||
Usage: remind -pp ... | rem2html [options]
|
||||
|
||||
Options:
|
||||
|
||||
@@ -110,6 +123,8 @@ Options:
|
||||
entry a link to <url>
|
||||
--forwurl url Same as --backurl, but for the next month's small calendar
|
||||
--imgbase url Base URL of images and default stylesheet file
|
||||
--pngs Use external .PNG images for moon phases rater than
|
||||
inline data: URLs
|
||||
--stylesheet url.css URL of CSS stylesheet. If specified, imgbase is NOT
|
||||
prepended to url.css
|
||||
--nostyle Produce basic HTML that does not use a CSS stylesheet
|
||||
@@ -121,11 +136,31 @@ EOM
|
||||
exit($exit_status);
|
||||
}
|
||||
|
||||
sub smoosh
|
||||
{
|
||||
my ($first, $second) = @_;
|
||||
return $second unless defined ($first);
|
||||
return $second if $first eq '';
|
||||
return $second if ($second =~ m|^/|); # Absolute path given for second
|
||||
|
||||
# Squash multiple slashes
|
||||
$first =~ s|/+|/|g;
|
||||
|
||||
# Special case
|
||||
return "/$second" if ($first eq '/');
|
||||
|
||||
# Delete trailing slash
|
||||
$first =~ s|/$||;
|
||||
|
||||
return "$first/$second";
|
||||
}
|
||||
|
||||
sub parse_options
|
||||
{
|
||||
local $SIG{__WARN__} = sub { print STDERR "$TIDY_PROGNAME: $_[0]\n"; };
|
||||
if (!GetOptions(\%Options, "help|h",
|
||||
"man",
|
||||
"pngs",
|
||||
"version",
|
||||
"stylesheet=s",
|
||||
"nostyle",
|
||||
@@ -138,45 +173,40 @@ sub parse_options
|
||||
"tableonly")) {
|
||||
usage(1);
|
||||
}
|
||||
$Options{'title'} ||= 'HTML Calendar';
|
||||
$Options{title} ||= 'HTML Calendar';
|
||||
|
||||
# Fix up imgbase
|
||||
my $imgbase = '%IMAGEBASE%';
|
||||
if ($imgbase ne '%' . 'IMAGEBASE' . '%') {
|
||||
$Options{'imgbase'} ||= $imgbase;
|
||||
} else {
|
||||
$Options{'imgbase'} ||= '';
|
||||
my $stylesheet = $Options{stylesheet};
|
||||
if ($stylesheet) {
|
||||
$Options{stylesheet} = smoosh($Options{imgbase}, $stylesheet);
|
||||
}
|
||||
|
||||
$Options{'imgbase'} =~ s|/+$||;
|
||||
my $stylesheet = $Options{'imgbase'};
|
||||
$stylesheet .= '/' if ($stylesheet ne '');
|
||||
$stylesheet .= 'rem-default.css';
|
||||
$Options{'stylesheet'} ||= $stylesheet;
|
||||
}
|
||||
|
||||
sub start_output
|
||||
{
|
||||
return if ($Options{'tableonly'});
|
||||
return if ($Options{tableonly});
|
||||
|
||||
print("<html>\n<head>\n<title>" . $Options{'title'} . "</title>\n");
|
||||
if (!$Options{'nostyle'}) {
|
||||
if ($Options{'stylesheet'}) {
|
||||
print('<link rel="stylesheet" type="text/css" href="' .
|
||||
$Options{'stylesheet'} . '">' . "\n");
|
||||
}
|
||||
print("<html>\n<head>\n<title>" . $Options{title} . "</title>\n");
|
||||
if (!$Options{nostyle}) {
|
||||
if ($Options{stylesheet}) {
|
||||
print('<link rel="stylesheet" type="text/css" href="' .
|
||||
$Options{stylesheet} . '">' . "\n");
|
||||
} else {
|
||||
print("<style>\n");
|
||||
print default_stylesheet();
|
||||
print("</style>\n");
|
||||
}
|
||||
}
|
||||
print("</head>\n<body>\n");
|
||||
if ($Options{'prologue'}) {
|
||||
print $Options{'prologue'} . "\n";
|
||||
if ($Options{prologue}) {
|
||||
print $Options{prologue} . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub end_output
|
||||
{
|
||||
return if ($Options{'tableonly'});
|
||||
if ($Options{'epilogue'}) {
|
||||
print $Options{'epilogue'} . "\n";
|
||||
return if ($Options{tableonly});
|
||||
if ($Options{epilogue}) {
|
||||
print $Options{epilogue} . "\n";
|
||||
}
|
||||
print("</body>\n</html>\n");
|
||||
}
|
||||
@@ -222,7 +252,7 @@ sub parse_input
|
||||
|
||||
$found_data = 1;
|
||||
my $class;
|
||||
if ($Options{'nostyle'}) {
|
||||
if ($Options{nostyle}) {
|
||||
$class = '';
|
||||
} else {
|
||||
$class = ' class="rem-entry"';
|
||||
@@ -301,7 +331,7 @@ sub small_calendar
|
||||
}
|
||||
}
|
||||
|
||||
if ($Options{'nostyle'}) {
|
||||
if ($Options{nostyle}) {
|
||||
print "<td width=\"14%\">\n";
|
||||
print "<table border=\"0\">\n";
|
||||
print "<caption>";
|
||||
@@ -316,7 +346,7 @@ sub small_calendar
|
||||
print "</caption>\n";
|
||||
|
||||
my $class;
|
||||
if ($Options{'nostyle'}) {
|
||||
if ($Options{nostyle}) {
|
||||
print '<tr>';
|
||||
$class = ' align="right"';
|
||||
} else {
|
||||
@@ -338,7 +368,7 @@ sub small_calendar
|
||||
if ($col == 0) {
|
||||
print("<tr>\n");
|
||||
}
|
||||
if ($Options{'nostyle'}) {
|
||||
if ($Options{nostyle}) {
|
||||
print("<td align=\"right\" width=\"14%\"> </td>");
|
||||
} else {
|
||||
print("<td class=\"rem-sc-empty-cell\"> </td>");
|
||||
@@ -350,7 +380,7 @@ sub small_calendar
|
||||
print("<tr>\n");
|
||||
}
|
||||
$col++;
|
||||
if ($Options{'nostyle'}) {
|
||||
if ($Options{nostyle}) {
|
||||
print("<td align=\"right\" width=\"14%\">$day</td>");
|
||||
} else {
|
||||
print("<td class=\"rem-sc-cell\">$day</td>");
|
||||
@@ -362,7 +392,7 @@ sub small_calendar
|
||||
}
|
||||
if ($col) {
|
||||
while ($col < 7) {
|
||||
if ($Options{'nostyle'}) {
|
||||
if ($Options{nostyle}) {
|
||||
print("<td align=\"right\" width=\"14%\"> </td>");
|
||||
} else {
|
||||
print("<td class=\"rem-sc-empty-cell\"> </td>");
|
||||
@@ -391,7 +421,7 @@ sub output_calendar
|
||||
|
||||
# Start the table
|
||||
my $class;
|
||||
if ($Options{'nostyle'}) {
|
||||
if ($Options{nostyle}) {
|
||||
print '<table width="100%" border="1" cellspacing=\"0\"><caption>' .
|
||||
$Month . ' ' . $Year . '</caption>' . "\n";
|
||||
print '<tr>';
|
||||
@@ -415,23 +445,23 @@ sub output_calendar
|
||||
|
||||
# Start the calendar rows
|
||||
my $col = 0;
|
||||
if ($Options{'nostyle'}) {
|
||||
if ($Options{nostyle}) {
|
||||
print "<tr>\n";
|
||||
} else {
|
||||
print "<tr class=\"rem-cal-row\">\n";
|
||||
}
|
||||
if ($first_col > 0) {
|
||||
small_calendar($Prevmon, $Prevlen, $Options{'backurl'},
|
||||
small_calendar($Prevmon, $Prevlen, $Options{backurl},
|
||||
($Firstwkday - $Prevlen + 35) % 7);
|
||||
$col++;
|
||||
}
|
||||
|
||||
if ($last_col == 6 && $first_col > 0) {
|
||||
small_calendar($Nextmon, $Nextlen, $Options{'forwurl'},
|
||||
small_calendar($Nextmon, $Nextlen, $Options{forwurl},
|
||||
($Firstwkday + $Numdays) % 7);
|
||||
$col++;
|
||||
}
|
||||
if ($Options{'nostyle'}) {
|
||||
if ($Options{nostyle}) {
|
||||
$class = ' width="14%"';
|
||||
} else {
|
||||
$class = ' class="rem-empty"';
|
||||
@@ -448,7 +478,7 @@ sub output_calendar
|
||||
$col = 0;
|
||||
print "</tr>\n";
|
||||
if ($day < $Numdays) {
|
||||
if ($Options{'nostyle'}) {
|
||||
if ($Options{nostyle}) {
|
||||
print "<tr>\n";
|
||||
} else {
|
||||
print "<tr class=\"rem-cal-row\">\n";
|
||||
@@ -461,13 +491,13 @@ sub output_calendar
|
||||
while ($col < 7) {
|
||||
if ($col == 5) {
|
||||
if ($first_col == 0) {
|
||||
small_calendar($Prevmon, $Prevlen, $Options{'backurl'},
|
||||
small_calendar($Prevmon, $Prevlen, $Options{backurl},
|
||||
($Firstwkday - $Prevlen + 35) % 7);
|
||||
} else {
|
||||
print("<td$class> </td>\n");
|
||||
}
|
||||
} elsif ($col == 6) {
|
||||
small_calendar($Nextmon, $Nextlen, $Options{'forwurl'},
|
||||
small_calendar($Nextmon, $Nextlen, $Options{forwurl},
|
||||
($Firstwkday + $Numdays) % 7);
|
||||
} else {
|
||||
print("<td$class> </td>\n");
|
||||
@@ -479,17 +509,17 @@ sub output_calendar
|
||||
|
||||
# Add a row for small calendars if they were not yet done!
|
||||
if ($first_col == 0 && $last_col == 6) {
|
||||
if ($Options{'nostyle'}) {
|
||||
if ($Options{nostyle}) {
|
||||
print "<tr>\n";
|
||||
} else {
|
||||
print "<tr class=\"rem-cal-row\">\n";
|
||||
}
|
||||
small_calendar($Prevmon, $Prevlen, $Options{'backurl'},
|
||||
small_calendar($Prevmon, $Prevlen, $Options{backurl},
|
||||
($Firstwkday - $Prevlen + 35) % 7);
|
||||
for (my $i=0; $i<5; $i++) {
|
||||
print("<td$class> </td>\n");
|
||||
}
|
||||
small_calendar($Nextmon, $Nextlen, $Options{'forwurl'},
|
||||
small_calendar($Nextmon, $Nextlen, $Options{forwurl},
|
||||
($Firstwkday + $Numdays) % 7);
|
||||
print("</tr>\n");
|
||||
}
|
||||
@@ -506,7 +536,7 @@ sub draw_day_cell
|
||||
$week = ' ' . $weeks->{$day};
|
||||
}
|
||||
my $class;
|
||||
if ($Options{'nostyle'}) {
|
||||
if ($Options{nostyle}) {
|
||||
$class = $classes->[$day] || '';
|
||||
} else {
|
||||
$class = $classes->[$day] || "rem-cell";
|
||||
@@ -532,33 +562,46 @@ sub draw_day_cell
|
||||
my $alt;
|
||||
my $title;
|
||||
if ($phase == 0) {
|
||||
$img = 'newmoon.png';
|
||||
if ($Options{pngs}) {
|
||||
$img = smoosh($Options{imgbase}, 'newmoon.png');
|
||||
} else {
|
||||
$img = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAGQAAABkABchkaRQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAC6SURBVDiNpdNNbsIwFATgL0HKolchHKBX6yFaBOEyoPYUabvOIVKJRaCL2JX5TRNGGvnJ8ozGz89cYoElPvET+BX2yivn/1Bggw5HHMKa1h2qcPZC/JEIhvh+brIZIY6sorhMYo9hh3KGFzzfa84NZNjDt9OG/ZcH1BlaPE1IAG0+URhxzNGESKPFaHJs9Q0Ziww7HnvGeXSrJhis0jiFfjwnj3I0WRv+TKtr4hQl3lDrZ6QN9Wt654hfWfGDmBpUwDkAAAAASUVORK5CYII=';
|
||||
}
|
||||
$title = 'New Moon';
|
||||
$alt = 'new';
|
||||
} elsif ($phase == 1) {
|
||||
$img = 'firstquarter.png';
|
||||
if ($Options{pngs}) {
|
||||
$img = smoosh($Options{imgbase}, 'firstquarter.png');
|
||||
} else {
|
||||
$img = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAGQAAABkABchkaRQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAADfSURBVDiNndM9TsNAFATgzy5yjZSAE85JBygETgENUPF3iBCitHAFQkcIhZ/Ryn9gRlrZmp2Z3ef3TBOHOMULPrDBMrhpi/4HI5xjix2+4nmJRbx/Yh7ahvkpRPVV4QDXwT3UQy46zGkAZDgK/iytefvHgCrkJsqZUH6cLnNbABSxd5Jhhf1IbkMXv8Qux7hH1Ic1xvk/jBWy6gavumvtwx7ectwZXkKh7MA95XgObeOtpI2U4zl0kGbpxgiPvwQUcXLrKFchc82f6Ur0PK49azOnmOI4TBu84zm4SV38DeIVYkrYJyNbAAAAAElFTkSuQmCC';
|
||||
}
|
||||
$title = 'First Quarter';
|
||||
$alt = '1st';
|
||||
} elsif ($phase == 2) {
|
||||
$img = 'fullmoon.png';
|
||||
if ($Options{pngs}) {
|
||||
$img = smoosh($Options{imgbase}, 'fullmoon.png');
|
||||
} else {
|
||||
$img = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAGQAAABkABchkaRQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAADlSURBVDiNrdNBUsJAEAXQlyw4hq4hwWPqTixET6ELkZ16CcAq7oFLqXExjaYgQVNlV/Viev7/6XT/4TjGuME7PiLXUatb8N8xwB12SFjiIXIZtU/MAntEfgvQE4YtHxhiHpjXQ5H7uLhEcaLLAleBvd0Xx9Ha/BdyU+Q5OBV5OKmj7a4YBWdSyNPe4aKHAHkzqcQZNj3JgnNexqE8heyIAulffuFF3kTfIVbBVeu/xoXGGsn2TLJJ/mqkafNiINszySYZdbS90GHlvcgsWktY4TFy7ecxTdvIzahxHQLbyFXUqkPwF2ASRNYgB/PXAAAAAElFTkSuQmCC';
|
||||
}
|
||||
$alt = 'full';
|
||||
$title = 'Full Moon';
|
||||
} else {
|
||||
$img = 'lastquarter.png';
|
||||
if ($Options{pngs}) {
|
||||
$img = smoosh($Options{imgbase}, 'lastquarter.png');
|
||||
} else {
|
||||
$img = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAGQAAABkABchkaRQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAADmSURBVDiNndMxTsNAEIXhzy5yCyQ6FAgcE7oQheQWUAAl5BIkREoZrgB0GFNkHBl7bURGsryaee/3jHeXdpxjghU+8InXyI0S+n0MMEeBEi+4jfV3vAvMQtsyL0J0j2GtViaeRRMyj8IlsgY8BSijE2Kur/hy09wHKMJrEolhwtwHKDHOsI4OLnoAXfl1jiNsOkR9keE4P8D4q4scbzg5xIxtjie709f1E7siC+9+Gx/8fxvPKtEsklcJSBdgWhcN8ByFR5z+AWgd5QpyE+OUWOJO+zJNU+Z6jHAdgHe7K73CuD5zFT9nCmRDIssCaAAAAABJRU5ErkJggg==';
|
||||
}
|
||||
$alt = 'last';
|
||||
$title = 'Last Quarter';
|
||||
}
|
||||
if ($Options{'imgbase'}) {
|
||||
$img = $Options{'imgbase'} . '/' . $img;
|
||||
}
|
||||
if ($Options{'nostyle'}) {
|
||||
if ($Options{nostyle}) {
|
||||
print("<div style=\"float: left\"><img border=\"0\" width=\"16\" height=\"16\" alt=\"$alt\" title=\"$title\" src=\"$img\">$msg</div>");
|
||||
} else {
|
||||
print("<div class=\"rem-moon\"><img width=\"16\" height=\"16\" alt=\"$alt\" title=\"$title\" src=\"$img\">$msg</div>");
|
||||
}
|
||||
}
|
||||
|
||||
if ($Options{'nostyle'}) {
|
||||
if ($Options{nostyle}) {
|
||||
print "<div style=\"float: right\">$day$week</div>\n";
|
||||
print "<p> </p>\n";
|
||||
} else {
|
||||
@@ -581,13 +624,13 @@ sub escape_html
|
||||
}
|
||||
|
||||
parse_options();
|
||||
if ($Options{'help'}) {
|
||||
if ($Options{help}) {
|
||||
usage(0);
|
||||
exit(0);
|
||||
} elsif ($Options{'man'}) {
|
||||
} elsif ($Options{man}) {
|
||||
system("perldoc $0");
|
||||
exit(0);
|
||||
} elsif ($Options{'version'}) {
|
||||
} elsif ($Options{version}) {
|
||||
print "rem2html version $rem2html_version.\n";
|
||||
exit(0);
|
||||
}
|
||||
@@ -612,3 +655,81 @@ if ($found_something) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
sub default_stylesheet
|
||||
{
|
||||
return <<'EOF';
|
||||
table.rem-cal {
|
||||
font-family: helvetica, arial, sans-serif;
|
||||
font-size: 12pt;
|
||||
}
|
||||
|
||||
table.rem-sc-table {
|
||||
font-family: helvetica, arial, sans-serif;
|
||||
font-size: 10pt;
|
||||
width: 95%;
|
||||
float: left;
|
||||
}
|
||||
|
||||
caption.rem-cal-caption {
|
||||
font-size: 14pt;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
th.rem-cal-hdr {
|
||||
width: 14%;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
vertical-align: top;
|
||||
}
|
||||
td.rem-empty, td.rem-cell, td.rem-small-calendar {
|
||||
width: 14%;
|
||||
height: 7em;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
vertical-align: top;
|
||||
}
|
||||
td.rem-today {
|
||||
width: 14%;
|
||||
height: 7em;
|
||||
border-style: solid;
|
||||
border-width: 2px;
|
||||
border-color: #EE3333;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
table.rem-cal {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
div.rem-daynumber {
|
||||
float: right;
|
||||
text-align: right;
|
||||
vertical-align: top;
|
||||
font-size: 14pt;
|
||||
}
|
||||
|
||||
p.rem-entry {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
div.rem-moon {
|
||||
float: left;
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
th.rem-sc-hdr {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
td.rem-sc-empty-cell, td.rem-sc-cell {
|
||||
text-align: right;
|
||||
width: 14%;
|
||||
}
|
||||
|
||||
caption.rem-sc-caption {
|
||||
font-size: 12pt;
|
||||
}
|
||||
EOF
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
Files in this directory:
|
||||
|
||||
tkremind -- Tcl/Tk graphical calendar using Remind as engine
|
||||
cm2rem.tcl -- Convert Sun's "cm" calendar manager files to Remind.
|
||||
|
||||
@@ -1,358 +0,0 @@
|
||||
#!/bin/sh
|
||||
# -*-Mode: TCL;-*-
|
||||
|
||||
#--------------------------------------------------------------
|
||||
# cm2rem.tcl
|
||||
#
|
||||
# A cheesy Tcl script to convert Sun's "cm" calendar manager
|
||||
# files (version 3 only) to Remind format.
|
||||
#
|
||||
# This file is part of REMIND.
|
||||
# Copyright (C) 1992-2018 by Dianne Skoll
|
||||
#
|
||||
#--------------------------------------------------------------
|
||||
|
||||
# the next line restarts using tclsh \
|
||||
exec tclsh "$0" "$@"
|
||||
|
||||
set i 0
|
||||
foreach month {January February March April May June
|
||||
July August September October November December} {
|
||||
incr i
|
||||
set MonthNum($month) $i
|
||||
set FullMonth([string range $month 0 2]) $month
|
||||
}
|
||||
|
||||
#***********************************************************************
|
||||
# %PROCEDURE: convertParens
|
||||
# %ARGUMENTS:
|
||||
# line -- a line read from a cm file
|
||||
# %RETURNS:
|
||||
# A new line with all ( and ) outside quotes converted to { and }.
|
||||
# This cheap trick allows us to use Tcl's built-in list manipulation
|
||||
# functions to munge the line.
|
||||
#***********************************************************************
|
||||
proc convertParens { line } {
|
||||
# Convert all ( and ) to { and } unless they are inside a quoted
|
||||
# string
|
||||
set out ""
|
||||
set len [string length $line]
|
||||
set inQuotes 0
|
||||
for {set i 0} {$i < $len} {incr i} {
|
||||
set char [string range $line $i $i]
|
||||
if {$char == "\\" && $inQuotes} {
|
||||
append out $char
|
||||
incr i
|
||||
set char [string range $line $i $i]
|
||||
append out $char
|
||||
continue
|
||||
}
|
||||
|
||||
if {$char == "(" && !$inQuotes} {
|
||||
set char \{
|
||||
}
|
||||
|
||||
if {$char == ")" && !$inQuotes} {
|
||||
set char \}
|
||||
}
|
||||
|
||||
if {$char == "\""} {
|
||||
set inQuotes [expr !$inQuotes]
|
||||
}
|
||||
|
||||
append out $char
|
||||
}
|
||||
return $out
|
||||
}
|
||||
|
||||
#***********************************************************************
|
||||
# %PROCEDURE: processLine
|
||||
# %ARGUMENTS:
|
||||
# line -- a line read from a cm file
|
||||
# %RETURNS:
|
||||
# Nothing
|
||||
# %DESCRIPTION:
|
||||
# Processes a single line from the file, possibly writing a reminder
|
||||
# in Remind format to stdout
|
||||
#***********************************************************************
|
||||
proc processLine { line } {
|
||||
global Attributes
|
||||
global FullMonth
|
||||
|
||||
catch {unset Attributes}
|
||||
|
||||
# Only convert lines which start with "(add"
|
||||
if {[string range $line 0 3] != "(add"} {
|
||||
return
|
||||
}
|
||||
set line [convertParens $line]
|
||||
# Convert it to a list. CAREFUL: Potential security problem if
|
||||
# $line contains something nasty.
|
||||
|
||||
eval set line $line
|
||||
|
||||
set Attributes(body) ""
|
||||
foreach {key val} $line {
|
||||
switch -exact -- $key {
|
||||
"add" {
|
||||
set Attributes(date) $val
|
||||
}
|
||||
"what:" {
|
||||
append Attributes(body) $val
|
||||
}
|
||||
"details:" {
|
||||
append Attributes(body) $val
|
||||
}
|
||||
"duration:" {
|
||||
set Attributes(duration) $val
|
||||
}
|
||||
"period:" {
|
||||
set Attributes(period) $val
|
||||
}
|
||||
"ntimes:" {
|
||||
set Attributes(ntimes) $val
|
||||
}
|
||||
"attributes:" {
|
||||
set Attributes(action) $val
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if {[info exists Attributes(action)]} {
|
||||
# Nuke quotes and commas in action
|
||||
regsub -all {[,\"]} $Attributes(action) { } Attributes(action)
|
||||
|
||||
# Add spaces to pairs
|
||||
regsub -all \}\{ $Attributes(action) \}\ \{ Attributes(action)
|
||||
|
||||
# Add another pair of brackets to make a proper list
|
||||
set Attributes(action) "{$Attributes(action)}"
|
||||
|
||||
# Convert to a real Tcl list
|
||||
eval set Attributes(action) $Attributes(action)
|
||||
}
|
||||
# Split out date into month, day, year, time parts
|
||||
scan $Attributes(date) "%s%s%s%s%s" wkday month day time year
|
||||
set time [string range $time 0 4]
|
||||
set Attributes(wkday) $wkday
|
||||
set Attributes(month) $FullMonth($month)
|
||||
set Attributes(day) $day
|
||||
set Attributes(time) $time
|
||||
set Attributes(year) $year
|
||||
|
||||
# Convert newlines in body to spaces
|
||||
set body $Attributes(body)
|
||||
regsub -all "\n" $body " " body
|
||||
|
||||
# TODO: Escape BODY to get rid of [] chars.
|
||||
set Attributes(body) $body
|
||||
|
||||
# Convert to Reminder format
|
||||
convertReminder
|
||||
}
|
||||
|
||||
#***********************************************************************
|
||||
# %PROCEDURE: convertReminder
|
||||
# %ARGUMENTS:
|
||||
# None -- uses global Attributes variable which must be filled in
|
||||
# %RETURNS:
|
||||
# Nothing
|
||||
# %DESCRIPTION:
|
||||
# Converts a reminder to Remind format.
|
||||
#***********************************************************************
|
||||
proc convertReminder {} {
|
||||
global Attributes
|
||||
switch -exact $Attributes(period) {
|
||||
single { convertSingleReminder }
|
||||
daily { convertDailyReminder }
|
||||
weekly { convertWeeklyReminder }
|
||||
monthly { convertMonthlyReminder }
|
||||
yearly { convertYearlyReminder }
|
||||
default {
|
||||
puts "\# Unable to convert reminder with period $Attributes(period)"
|
||||
puts "\# Body is: $Attributes(body)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#***********************************************************************
|
||||
# %PROCEDURE: convertSingleReminder
|
||||
# %ARGUMENTS:
|
||||
# None -- uses global Attributes variable which must be filled in
|
||||
# %RETURNS:
|
||||
# Nothing
|
||||
# %DESCRIPTION:
|
||||
# Converts a reminder with "single" period to Remind format.
|
||||
#***********************************************************************
|
||||
proc convertSingleReminder {} {
|
||||
global Attributes
|
||||
puts "REM $Attributes(day) $Attributes(month) $Attributes(year) [at][duration]MSG $Attributes(body)"
|
||||
}
|
||||
|
||||
#***********************************************************************
|
||||
# %PROCEDURE: convertDailyReminder
|
||||
# %ARGUMENTS:
|
||||
# None -- uses global Attributes variable which must be filled in
|
||||
# %RETURNS:
|
||||
# Nothing
|
||||
# %DESCRIPTION:
|
||||
# Converts a reminder with "daily" period to Remind format.
|
||||
#***********************************************************************
|
||||
proc convertDailyReminder {} {
|
||||
global Attributes
|
||||
set ntimes [expr $Attributes(ntimes) - 1]
|
||||
if {$ntimes <= 1} {
|
||||
convertSingleReminder
|
||||
return
|
||||
}
|
||||
set until [getUntilDate $Attributes(day) $Attributes(month) $Attributes(year) $ntimes]
|
||||
|
||||
puts "REM $Attributes(day) $Attributes(month) $Attributes(year) *1 [at][duration]UNTIL $until MSG $Attributes(body)"
|
||||
}
|
||||
|
||||
#***********************************************************************
|
||||
# %PROCEDURE: convertWeeklyReminder
|
||||
# %ARGUMENTS:
|
||||
# None -- uses global Attributes variable which must be filled in
|
||||
# %RETURNS:
|
||||
# Nothing
|
||||
# %DESCRIPTION:
|
||||
# Converts a reminder with "daily" period to Remind format.
|
||||
#***********************************************************************
|
||||
proc convertWeeklyReminder {} {
|
||||
global Attributes
|
||||
set ntimes [expr $Attributes(ntimes) - 1]
|
||||
if {$ntimes <= 1} {
|
||||
convertSingleReminder
|
||||
return
|
||||
}
|
||||
set until [getUntilDate $Attributes(day) $Attributes(month) $Attributes(year) [expr $ntimes * 7]]
|
||||
|
||||
puts "REM $Attributes(day) $Attributes(month) $Attributes(year) *7 [at][duration]UNTIL $until MSG $Attributes(body)"
|
||||
}
|
||||
|
||||
#***********************************************************************
|
||||
# %PROCEDURE: convertMonthlyReminder
|
||||
# %ARGUMENTS:
|
||||
# None -- uses global Attributes variable which must be filled in
|
||||
# %RETURNS:
|
||||
# Nothing
|
||||
# %DESCRIPTION:
|
||||
# Converts a reminder with "monthly" period to Remind format.
|
||||
#***********************************************************************
|
||||
proc convertMonthlyReminder {} {
|
||||
global Attributes
|
||||
set ntimes [expr $Attributes(ntimes) - 1]
|
||||
if {$ntimes <= 1} {
|
||||
convertSingleReminder
|
||||
return
|
||||
}
|
||||
|
||||
# If repetition > 1000, it's infinite
|
||||
if {$ntimes > 1000} {
|
||||
puts "REM $Attributes(day) [at][duration]MSG $Attributes(body)"
|
||||
return
|
||||
}
|
||||
|
||||
### UNTIL date is fudged!
|
||||
set until [getUntilDate $Attributes(day) $Attributes(month) $Attributes(year) [expr $ntimes * 30]]
|
||||
|
||||
puts "REM $Attributes(day) [at][duration]UNTIL $until MSG $Attributes(body)"
|
||||
}
|
||||
|
||||
#***********************************************************************
|
||||
# %PROCEDURE: convertYearlyReminder
|
||||
# %ARGUMENTS:
|
||||
# None -- uses global Attributes variable which must be filled in
|
||||
# %RETURNS:
|
||||
# Nothing
|
||||
# %DESCRIPTION:
|
||||
# Converts a reminder with "yearly" period to Remind format.
|
||||
#***********************************************************************
|
||||
proc convertYearlyReminder {} {
|
||||
global Attributes
|
||||
|
||||
# No special handling of ntimes et al.
|
||||
puts "REM $Attributes(day) $Attributes(month) [at][duration]MSG $Attributes(body)"
|
||||
|
||||
}
|
||||
|
||||
#***********************************************************************
|
||||
# %PROCEDURE: at
|
||||
# %ARGUMENTS:
|
||||
# None -- uses Attributes global variable
|
||||
# %RETURNS:
|
||||
# A string providing the correct AT clause for a timed reminder.
|
||||
#***********************************************************************
|
||||
proc at {} {
|
||||
global Attributes
|
||||
if {![info exists Attributes(time)]} {
|
||||
return ""
|
||||
}
|
||||
if {"$Attributes(time)" == ""} {
|
||||
return ""
|
||||
}
|
||||
|
||||
return "AT $Attributes(time) "
|
||||
}
|
||||
|
||||
#***********************************************************************
|
||||
# %PROCEDURE: duration
|
||||
# %ARGUMENTS:
|
||||
# None -- uses Attributes global variable
|
||||
# %RETURNS:
|
||||
# A string providing the correct DURATION clause for a timed reminder.
|
||||
#***********************************************************************
|
||||
proc duration {} {
|
||||
global Attributes
|
||||
if {![info exists Attributes(duration)]} {
|
||||
return ""
|
||||
}
|
||||
if {"$Attributes(duration)" == ""} {
|
||||
return ""
|
||||
}
|
||||
set h [expr $Attributes(duration) / 3600]
|
||||
set remainder [expr $Attributes(duration) - $h*3600]
|
||||
set m [expr $remainder / 60]
|
||||
return "DURATION [format "%d:%02d " $h $m]"
|
||||
}
|
||||
|
||||
#***********************************************************************
|
||||
# %PROCEDURE: getUntilDate
|
||||
# %ARGUMENTS:
|
||||
# day, month, year -- a date
|
||||
# days -- number of days to add to date
|
||||
# %RETURNS:
|
||||
# The date which is "days" later than supplied date in a correct UNTIL
|
||||
# format.
|
||||
#***********************************************************************
|
||||
proc getUntilDate { day month year days } {
|
||||
global RemindPipe
|
||||
global MonthNum
|
||||
set date "'$year/$MonthNum($month)/$day'"
|
||||
puts $RemindPipe "MSG \[trigger($date + $days)\]%"
|
||||
puts $RemindPipe "flush"
|
||||
flush $RemindPipe
|
||||
gets $RemindPipe line
|
||||
return $line
|
||||
}
|
||||
|
||||
catch {wm withdraw .}
|
||||
# Start a Remind process to issue reminders
|
||||
if {[catch {set RemindPipe [open "|remind -" "r+"]} err]} {
|
||||
puts stderr "Error: Cannot run Remind: $err"
|
||||
exit 1
|
||||
}
|
||||
|
||||
puts $RemindPipe "banner %"
|
||||
flush $RemindPipe
|
||||
|
||||
# Write some blurb
|
||||
puts "\# Reminder file converted from \"cm\" data by cm2rem.tcl"
|
||||
puts ""
|
||||
|
||||
while {[gets stdin line] >= 0} {
|
||||
processLine $line
|
||||
}
|
||||
exit 0
|
||||
@@ -1005,8 +1005,8 @@ proc FillCalWindow {} {
|
||||
ConfigureCalWindow $monthName $year $firstWkday $daysInMonth
|
||||
set offset [CalEntryOffset $firstWkday]
|
||||
|
||||
set fntag "x"
|
||||
while { [gets $file line] >= 0 } {
|
||||
set fntag "x"
|
||||
# Ignore unless begins with left brace
|
||||
if { ! [string match "\{*" $line]} {
|
||||
continue
|
||||
@@ -1017,7 +1017,11 @@ proc FillCalWindow {} {
|
||||
}
|
||||
|
||||
if {[dict exists $obj filename]} {
|
||||
set fntag [string cat "FILE_" [dict get $obj lineno] "_" [dict get $obj filename]]
|
||||
set fname [dict get $obj filename]
|
||||
# Don't make INCLUDECMD output editable
|
||||
if {![string match "*|" $fname]} {
|
||||
set fntag [string cat "FILE_" [dict get $obj lineno] "_" $fname]
|
||||
}
|
||||
}
|
||||
|
||||
set date [dict get $obj date]
|
||||
@@ -1087,13 +1091,17 @@ proc FillCalWindow {} {
|
||||
continue
|
||||
}
|
||||
.cal.t$n configure -state normal
|
||||
if {[regexp {TKTAG([0-9]+)} $tag all tagno]} {
|
||||
if {[regexp {TKTAG([0-9]+)} $tag all tagno] && "$fntag" != "x"} {
|
||||
.cal.t$n insert end [string trim $stuff] [list REM TAGGED "TKTAG$tagno" "date_$date" $extratags $fntag]
|
||||
.cal.t$n tag bind "TKTAG$tagno" <Enter> "TaggedEnter .cal.t$n"
|
||||
.cal.t$n tag bind "TKTAG$tagno" <Leave> "TaggedLeave .cal.t$n"
|
||||
set TagToObj(TKTAG$tagno) $obj
|
||||
} else {
|
||||
.cal.t$n insert end [string trim $stuff] [list REM $extratags $fntag]
|
||||
if {"$fntag" == "x" } {
|
||||
.cal.t$n insert end [string trim $stuff] [list REM $extratags]
|
||||
} else {
|
||||
.cal.t$n insert end [string trim $stuff] [list REM $extratags $fntag]
|
||||
}
|
||||
}
|
||||
.cal.t$n insert end "\n"
|
||||
.cal.t$n configure -state disabled
|
||||
@@ -1837,6 +1845,7 @@ proc ModifyDay {d firstDay} {
|
||||
set oldFocus [focus]
|
||||
while {1} {
|
||||
grab .mod
|
||||
raise .mod
|
||||
focus .mod.entry
|
||||
set ModifyDialogResult -1
|
||||
tkwait variable ModifyDialogResult
|
||||
@@ -1983,7 +1992,7 @@ proc CreateReminder {w} {
|
||||
|
||||
# Check it out!
|
||||
global Remind
|
||||
set f [open "|$Remind -arq -e -" r+]
|
||||
set f [open "|$Remind -arq -e - 2>&1" r+]
|
||||
puts $f "BANNER %"
|
||||
puts $f "$rem MSG %"
|
||||
puts $f "MSG %_%_%_%_"
|
||||
@@ -2001,13 +2010,17 @@ proc CreateReminder {w} {
|
||||
return $rem
|
||||
}
|
||||
|
||||
# We used to return YYYY-MM-DD, but reverted to
|
||||
# day monthname year because this lets Remind produce
|
||||
# much better error messages.
|
||||
proc consolidate {y m d} {
|
||||
global MonthNames
|
||||
if {![regexp {^[0-9]+$} $m]} {
|
||||
set m [lsearch -exact $MonthNames $m]
|
||||
incr m
|
||||
}
|
||||
return [format "%04d-%02d-%02d" $y $m $d]
|
||||
set mname [lindex $MonthNames [expr $m-1]]
|
||||
return "$d $mname $y"
|
||||
}
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
@@ -2804,7 +2817,7 @@ proc ReadTaggedOptions { tag date } {
|
||||
lappend ans -text-day2 $d
|
||||
}
|
||||
if {[dict exists $obj m]} {
|
||||
set mm [dict get $obj m]
|
||||
set m [dict get $obj m]
|
||||
set mm [string trimleft $m 0]
|
||||
lappend ans -text-mon1 [lindex $MonthNames [expr $mm -1]]
|
||||
lappend ans -text-mon2 [lindex $MonthNames [expr $mm -1]]
|
||||
@@ -3194,6 +3207,7 @@ proc EditTaggedReminder { w } {
|
||||
tkwait visibility .mod
|
||||
set oldFocus [focus]
|
||||
while {1} {
|
||||
raise .mod
|
||||
grab .mod
|
||||
focus .mod.entry
|
||||
set ModifyDialogResult -1
|
||||
|
||||
@@ -18,11 +18,10 @@ INSTALL_PROGRAM=@INSTALL_PROGRAM@
|
||||
INSTALL_DATA=@INSTALL_DATA@
|
||||
|
||||
PROGS= remind rem2ps
|
||||
SCRIPTS= $(srcdir)/../scripts/tkremind $(srcdir)/../scripts/cm2rem.tcl
|
||||
SCRIPTS= $(srcdir)/../scripts/tkremind
|
||||
|
||||
MANS= $(srcdir)/../man/rem2ps.1 $(srcdir)/../man/remind.1 \
|
||||
$(srcdir)/../man/tkremind.1 $(srcdir)/../man/cm2rem.1 \
|
||||
$(srcdir)/../man/rem.1
|
||||
$(srcdir)/../man/tkremind.1 $(srcdir)/../man/rem.1
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .o
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* The code for generating a calendar. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -268,7 +268,7 @@ void PrintJSONKeyPairInt(char const *name, int val)
|
||||
{
|
||||
printf("\"");
|
||||
PrintJSONString(name);
|
||||
printf("\":%d, ", val);
|
||||
printf("\":%d,", val);
|
||||
}
|
||||
|
||||
void PrintJSONKeyPairString(char const *name, char const *val)
|
||||
@@ -282,7 +282,7 @@ void PrintJSONKeyPairString(char const *name, char const *val)
|
||||
PrintJSONString(name);
|
||||
printf("\":\"");
|
||||
PrintJSONString(val);
|
||||
printf("\", ");
|
||||
printf("\",");
|
||||
}
|
||||
|
||||
void PrintJSONKeyPairDate(char const *name, int jul)
|
||||
@@ -295,7 +295,7 @@ void PrintJSONKeyPairDate(char const *name, int jul)
|
||||
FromJulian(jul, &y, &m, &d);
|
||||
printf("\"");
|
||||
PrintJSONString(name);
|
||||
printf("\":\"%04d-%02d-%02d\", ", y, m+1, d);
|
||||
printf("\":\"%04d-%02d-%02d\",", y, m+1, d);
|
||||
|
||||
}
|
||||
|
||||
@@ -313,7 +313,7 @@ void PrintJSONKeyPairDateTime(char const *name, int dt)
|
||||
i = k % 60;
|
||||
printf("\"");
|
||||
PrintJSONString(name);
|
||||
printf("\":\"%04d-%02d-%02dT%02d:%02d\", ", y, m+1, d, h, i);
|
||||
printf("\":\"%04d-%02d-%02dT%02d:%02d\",", y, m+1, d, h, i);
|
||||
|
||||
}
|
||||
|
||||
@@ -328,7 +328,7 @@ void PrintJSONKeyPairTime(char const *name, int t)
|
||||
i = t % 60;
|
||||
printf("\"");
|
||||
PrintJSONString(name);
|
||||
printf("\":\"%02d:%02d\", ", h, i);
|
||||
printf("\":\"%02d:%02d\",", h, i);
|
||||
|
||||
}
|
||||
|
||||
@@ -797,7 +797,7 @@ static int WriteCalendarRow(void)
|
||||
PrintLeft("", ColSpaces, ' ');
|
||||
else {
|
||||
sprintf(buf, "%d ", d+i-wd);
|
||||
if (OrigJul+i == RealToday) {
|
||||
if (Julian(y, m, d+i-wd) == RealToday) {
|
||||
PrintLeft(buf, ColSpaces-1, '*');
|
||||
PutChar(' ');
|
||||
} else {
|
||||
@@ -1239,6 +1239,7 @@ static void GenerateCalEntries(int col)
|
||||
case T_Else: r=DoElse(&p); break;
|
||||
case T_EndIf: r=DoEndif(&p); break;
|
||||
case T_Include: r=DoInclude(&p); break;
|
||||
case T_IncludeCmd: r=DoIncludeCmd(&p); break;
|
||||
case T_Exit: DoExit(&p); break;
|
||||
case T_Set: r=DoSet(&p); break;
|
||||
case T_Fset: r=DoFset(&p); break;
|
||||
@@ -1664,7 +1665,9 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
if(!e->filename) {
|
||||
if (e->text) free(e->text);
|
||||
if (e->raw_text) free(e->raw_text);
|
||||
#ifdef REM_USE_WCHAR
|
||||
if (e->wc_text) free(e->wc_text);
|
||||
#endif
|
||||
free(e);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
@@ -1753,7 +1756,7 @@ static void WriteSimpleEntryProtocol2(CalEntry *e, int today)
|
||||
printf("\"%s\"", EnglishDayName[i]);
|
||||
}
|
||||
}
|
||||
printf("], ");
|
||||
printf("],");
|
||||
}
|
||||
if (e->trig.d != NO_DAY) {
|
||||
PrintJSONKeyPairInt("d", e->trig.d);
|
||||
@@ -1806,7 +1809,7 @@ static void WriteSimpleEntryProtocol2(CalEntry *e, int today)
|
||||
printf("\"%s\"", EnglishDayName[i]);
|
||||
}
|
||||
}
|
||||
printf("], ");
|
||||
printf("],");
|
||||
}
|
||||
PrintJSONKeyPairDate("until", e->trig.until);
|
||||
if (e->trig.once != NO_ONCE) {
|
||||
@@ -1875,7 +1878,7 @@ static void WriteSimpleEntries(int col, int jul)
|
||||
}
|
||||
}
|
||||
DidADay = 1;
|
||||
printf("{\"date\":\"%04d-%02d-%02d\", ", y, m+1, d);
|
||||
printf("{\"date\":\"%04d-%02d-%02d\",", y, m+1, d);
|
||||
WriteSimpleEntryProtocol2(e, jul);
|
||||
printf("}");
|
||||
if (PsCal != PSCAL_LEVEL3) {
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
/* Define if you have the <sys/file.h> header file. */
|
||||
#undef HAVE_SYS_FILE_H
|
||||
|
||||
/* Define if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define if you have the <glob.h> header file */
|
||||
#undef HAVE_GLOB_H
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* which you can customize. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* which you can customize. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
24
src/dorem.c
24
src/dorem.c
@@ -7,7 +7,7 @@
|
||||
/* commands. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -24,10 +24,6 @@
|
||||
#include "protos.h"
|
||||
#include "expr.h"
|
||||
|
||||
/* Define the shell characters not to escape */
|
||||
static char const DontEscapeMe[] =
|
||||
"1234567890_-=+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@.,";
|
||||
|
||||
static int ParseTimeTrig (ParsePtr s, TimeTrig *tim, int save_in_globals);
|
||||
static int ParseLocalOmit (ParsePtr s, Trigger *t);
|
||||
static int ParseScanFrom (ParsePtr s, Trigger *t, int type);
|
||||
@@ -1230,24 +1226,16 @@ int DoMsgCommand(char const *cmd, char const *msg)
|
||||
DynamicBuffer execBuffer;
|
||||
|
||||
DynamicBuffer buf;
|
||||
char const *s;
|
||||
|
||||
DBufInit(&buf);
|
||||
DBufInit(&execBuffer);
|
||||
|
||||
/* Escape shell characters in msg INCLUDING WHITESPACE! */
|
||||
for (s=msg; *s; s++) {
|
||||
if (isspace(*s) || !strchr(DontEscapeMe, *s)) {
|
||||
if (DBufPutc(&buf, '\\') != OK) {
|
||||
r = E_NO_MEM;
|
||||
goto finished;
|
||||
}
|
||||
}
|
||||
if (DBufPutc(&buf, *s) != OK) {
|
||||
r = E_NO_MEM;
|
||||
goto finished;
|
||||
}
|
||||
/* Escape shell characters in msg */
|
||||
if (ShellEscape(msg, &buf) != OK) {
|
||||
r = E_NO_MEM;
|
||||
goto finished;
|
||||
}
|
||||
|
||||
msg = DBufValue(&buf);
|
||||
|
||||
/* Do "%s" substitution */
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* reminders are triggered. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* buffers. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Declaration of functions for manipulating dynamic buffers */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Error definitions. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* This file contains routines to parse and evaluate */
|
||||
/* expressions. */
|
||||
/* */
|
||||
/* Copyright 1992-2020 by Dianne Skoll */
|
||||
/* Copyright 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -940,6 +940,11 @@ static int Multiply(void)
|
||||
}
|
||||
|
||||
if (v1.type == INT_TYPE && v2.type == INT_TYPE) {
|
||||
/* Prevent floating-point exception */
|
||||
if ((v2.v.val == -1 && v1.v.val == INT_MIN) ||
|
||||
(v1.v.val == -1 && v2.v.val == INT_MIN)) {
|
||||
return E_2HIGH;
|
||||
}
|
||||
int old = v1.v.val;
|
||||
v1.v.val *= v2.v.val;
|
||||
if (v2.v.val != 0) {
|
||||
|
||||
285
src/files.c
285
src/files.c
@@ -7,7 +7,7 @@
|
||||
/* files. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -40,8 +40,9 @@
|
||||
#include "err.h"
|
||||
|
||||
|
||||
/* Convenient macro for closing files */
|
||||
/* Convenient macros for closing files */
|
||||
#define FCLOSE(fp) (((fp)&&((fp)!=stdin)) ? (fclose(fp),(fp)=NULL) : ((fp)=NULL))
|
||||
#define PCLOSE(fp) (((fp)&&((fp)!=stdin)) ? (pclose(fp),(fp)=NULL) : ((fp)=NULL))
|
||||
|
||||
/* Define the structures needed by the file caching system */
|
||||
typedef struct cache {
|
||||
@@ -91,12 +92,12 @@ static FILE *fp;
|
||||
static IncludeStruct IStack[INCLUDE_NEST];
|
||||
static int IStackPtr = 0;
|
||||
|
||||
static int ReadLineFromFile (void);
|
||||
static int CacheFile (char const *fname);
|
||||
static int ReadLineFromFile (int use_pclose);
|
||||
static int CacheFile (char const *fname, int use_pclose);
|
||||
static void DestroyCache (CachedFile *cf);
|
||||
static int CheckSafety (void);
|
||||
static int PopFile (void);
|
||||
|
||||
static int IncludeCmd(char const *);
|
||||
static void OpenPurgeFile(char const *fname, char const *mode)
|
||||
{
|
||||
DynamicBuffer fname_buf;
|
||||
@@ -167,7 +168,7 @@ int ReadLine(void)
|
||||
}
|
||||
|
||||
/* Not cached. Read from the file. */
|
||||
return ReadLineFromFile();
|
||||
return ReadLineFromFile(0);
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -177,7 +178,7 @@ int ReadLine(void)
|
||||
/* Read a line from the file pointed to by fp. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static int ReadLineFromFile(void)
|
||||
static int ReadLineFromFile(int use_pclose)
|
||||
{
|
||||
int l;
|
||||
char copy_buffer[4096];
|
||||
@@ -200,7 +201,11 @@ static int ReadLineFromFile(void)
|
||||
return E_IO_ERR;
|
||||
}
|
||||
if (feof(fp)) {
|
||||
FCLOSE(fp);
|
||||
if (use_pclose) {
|
||||
PCLOSE(fp);
|
||||
} else {
|
||||
FCLOSE(fp);
|
||||
}
|
||||
if ((DBufLen(&buf) == 0) &&
|
||||
(DBufLen(&LineBuffer) == 0) && PurgeMode) {
|
||||
if (PurgeFP != NULL && PurgeFP != stdout) fclose(PurgeFP);
|
||||
@@ -248,7 +253,11 @@ static int ReadLineFromFile(void)
|
||||
if (PurgeFP != stdout) fclose(PurgeFP);
|
||||
PurgeFP = NULL;
|
||||
}
|
||||
FCLOSE(fp);
|
||||
if (use_pclose) {
|
||||
PCLOSE(fp);
|
||||
} else {
|
||||
FCLOSE(fp);
|
||||
}
|
||||
DBufFree(&LineBuffer);
|
||||
CurLine = DBufValue(&LineBuffer);
|
||||
}
|
||||
@@ -282,9 +291,6 @@ int OpenFile(char const *fname)
|
||||
PurgeFP = NULL;
|
||||
}
|
||||
|
||||
/* Assume we own the file for now */
|
||||
RunDisabled &= ~RUN_NOTOWNER;
|
||||
|
||||
/* If it's in the cache, get it from there. */
|
||||
|
||||
while (h) {
|
||||
@@ -297,7 +303,9 @@ int OpenFile(char const *fname)
|
||||
LineNo = 0;
|
||||
if (!h->ownedByMe) {
|
||||
RunDisabled |= RUN_NOTOWNER;
|
||||
}
|
||||
} else {
|
||||
RunDisabled &= ~RUN_NOTOWNER;
|
||||
}
|
||||
if (FileName) return OK; else return E_NO_MEM;
|
||||
}
|
||||
h = h->next;
|
||||
@@ -306,6 +314,7 @@ int OpenFile(char const *fname)
|
||||
/* If it's a dash, then it's stdin */
|
||||
if (!strcmp(fname, "-")) {
|
||||
fp = stdin;
|
||||
RunDisabled &= ~RUN_NOTOWNER;
|
||||
if (PurgeMode) {
|
||||
PurgeFP = stdout;
|
||||
}
|
||||
@@ -325,7 +334,7 @@ int OpenFile(char const *fname)
|
||||
CLine = NULL;
|
||||
if (ShouldCache) {
|
||||
LineNo = 0;
|
||||
r = CacheFile(fname);
|
||||
r = CacheFile(fname, 0);
|
||||
if (r == OK) {
|
||||
fp = NULL;
|
||||
CLine = CachedFiles->cache;
|
||||
@@ -353,7 +362,7 @@ int OpenFile(char const *fname)
|
||||
/* Returns an indication of success or failure. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static int CacheFile(char const *fname)
|
||||
static int CacheFile(char const *fname, int use_pclose)
|
||||
{
|
||||
int r;
|
||||
CachedFile *cf;
|
||||
@@ -368,14 +377,22 @@ static int CacheFile(char const *fname)
|
||||
cf = NEW(CachedFile);
|
||||
if (!cf) {
|
||||
ShouldCache = 0;
|
||||
FCLOSE(fp);
|
||||
if (use_pclose) {
|
||||
PCLOSE(fp);
|
||||
} else {
|
||||
FCLOSE(fp);
|
||||
}
|
||||
return E_NO_MEM;
|
||||
}
|
||||
cf->cache = NULL;
|
||||
cf->filename = StrDup(fname);
|
||||
if (!cf->filename) {
|
||||
ShouldCache = 0;
|
||||
FCLOSE(fp);
|
||||
if (use_pclose) {
|
||||
PCLOSE(fp);
|
||||
} else {
|
||||
FCLOSE(fp);
|
||||
}
|
||||
free(cf);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
@@ -388,11 +405,15 @@ static int CacheFile(char const *fname)
|
||||
|
||||
/* Read the file */
|
||||
while(fp) {
|
||||
r = ReadLineFromFile();
|
||||
r = ReadLineFromFile(use_pclose);
|
||||
if (r) {
|
||||
DestroyCache(cf);
|
||||
ShouldCache = 0;
|
||||
FCLOSE(fp);
|
||||
if (use_pclose) {
|
||||
PCLOSE(fp);
|
||||
} else {
|
||||
FCLOSE(fp);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
/* Skip blank chars */
|
||||
@@ -406,7 +427,11 @@ static int CacheFile(char const *fname)
|
||||
DBufFree(&LineBuffer);
|
||||
DestroyCache(cf);
|
||||
ShouldCache = 0;
|
||||
FCLOSE(fp);
|
||||
if (use_pclose) {
|
||||
PCLOSE(fp);
|
||||
} else {
|
||||
FCLOSE(fp);
|
||||
}
|
||||
return E_NO_MEM;
|
||||
}
|
||||
cl = cf->cache;
|
||||
@@ -416,7 +441,11 @@ static int CacheFile(char const *fname)
|
||||
DBufFree(&LineBuffer);
|
||||
DestroyCache(cf);
|
||||
ShouldCache = 0;
|
||||
FCLOSE(fp);
|
||||
if (use_pclose) {
|
||||
PCLOSE(fp);
|
||||
} else {
|
||||
FCLOSE(fp);
|
||||
}
|
||||
return E_NO_MEM;
|
||||
}
|
||||
cl = cl->next;
|
||||
@@ -428,7 +457,11 @@ static int CacheFile(char const *fname)
|
||||
if (!cl->text) {
|
||||
DestroyCache(cf);
|
||||
ShouldCache = 0;
|
||||
FCLOSE(fp);
|
||||
if (use_pclose) {
|
||||
PCLOSE(fp);
|
||||
} else {
|
||||
FCLOSE(fp);
|
||||
}
|
||||
return E_NO_MEM;
|
||||
}
|
||||
}
|
||||
@@ -471,9 +504,6 @@ static int PopFile(void)
|
||||
{
|
||||
IncludeStruct *i;
|
||||
|
||||
/* Assume we own the file for now */
|
||||
RunDisabled &= ~RUN_NOTOWNER;
|
||||
|
||||
if (!Hush && NumIfs) Eprint("%s", ErrMsg[E_MISS_ENDIF]);
|
||||
if (!IStackPtr) return E_EOF;
|
||||
i = &IStack[IStackPtr-1];
|
||||
@@ -500,8 +530,10 @@ static int PopFile(void)
|
||||
STRSET(FileName, i->filename);
|
||||
if (!i->ownedByMe) {
|
||||
RunDisabled |= RUN_NOTOWNER;
|
||||
} else {
|
||||
RunDisabled &= ~RUN_NOTOWNER;
|
||||
}
|
||||
if (!CLine && (i->offset != -1L)) {
|
||||
if (!CLine && (i->offset != -1L || !strcmp(i->filename, "-"))) {
|
||||
/* We must open the file, then seek to specified position */
|
||||
if (strcmp(i->filename, "-")) {
|
||||
fp = fopen(i->filename, "r");
|
||||
@@ -544,6 +576,64 @@ int DoInclude(ParsePtr p)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* DoIncludeCmd */
|
||||
/* */
|
||||
/* The INCLUDECMD command. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int DoIncludeCmd(ParsePtr p)
|
||||
{
|
||||
DynamicBuffer buf;
|
||||
int r;
|
||||
int ch;
|
||||
char append_buf[2];
|
||||
int seen_nonspace = 0;
|
||||
|
||||
append_buf[1] = 0;
|
||||
|
||||
DBufInit(&buf);
|
||||
|
||||
while(1) {
|
||||
ch = ParseChar(p, &r, 0);
|
||||
if (r) {
|
||||
DBufFree(&buf);
|
||||
return r;
|
||||
}
|
||||
if (!ch) {
|
||||
break;
|
||||
}
|
||||
if (isspace(ch) && !seen_nonspace) {
|
||||
continue;
|
||||
}
|
||||
seen_nonspace = 1;
|
||||
/* Convert \n to ' ' to better handle line continuation */
|
||||
if (ch == '\n') {
|
||||
ch = ' ';
|
||||
}
|
||||
append_buf[0] = (char) ch;
|
||||
if (DBufPuts(&buf, append_buf) != OK) {
|
||||
DBufFree(&buf);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
}
|
||||
|
||||
if (RunDisabled) {
|
||||
DBufFree(&buf);
|
||||
return E_RUN_DISABLED;
|
||||
}
|
||||
|
||||
if ( (r=IncludeCmd(DBufValue(&buf))) ) {
|
||||
DBufFree(&buf);
|
||||
return r;
|
||||
}
|
||||
DBufFree(&buf);
|
||||
NumIfs = 0;
|
||||
IfFlags = 0;
|
||||
return OK;
|
||||
}
|
||||
|
||||
#ifdef HAVE_GLOB
|
||||
static int SetupGlobChain(char const *dirname, IncludeStruct *i)
|
||||
{
|
||||
@@ -664,6 +754,127 @@ static int SetupGlobChain(char const *dirname, IncludeStruct *i)
|
||||
}
|
||||
#endif
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* IncludeCmd */
|
||||
/* */
|
||||
/* Process the INCLUDECMD command - actually do the command */
|
||||
/* inclusion. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static int IncludeCmd(char const *cmd)
|
||||
{
|
||||
IncludeStruct *i;
|
||||
DynamicBuffer buf;
|
||||
FILE *fp2;
|
||||
int r;
|
||||
CachedFile *h;
|
||||
char const *fname;
|
||||
int old_flag;
|
||||
|
||||
FreshLine = 1;
|
||||
if (IStackPtr+1 >= INCLUDE_NEST) return E_NESTED_INCLUDE;
|
||||
i = &IStack[IStackPtr];
|
||||
|
||||
/* Use "cmd|" as the filename */
|
||||
DBufInit(&buf);
|
||||
if (DBufPuts(&buf, cmd) != OK) {
|
||||
DBufFree(&buf);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
if (DBufPuts(&buf, "|") != OK) {
|
||||
DBufFree(&buf);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
fname = DBufValue(&buf);
|
||||
|
||||
if (FileName) {
|
||||
i->filename = StrDup(FileName);
|
||||
if (!i->filename) {
|
||||
DBufFree(&buf);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
} else {
|
||||
i->filename = NULL;
|
||||
}
|
||||
i->ownedByMe = 1;
|
||||
i->LineNo = LineNo;
|
||||
i->NumIfs = NumIfs;
|
||||
i->IfFlags = IfFlags;
|
||||
i->CLine = CLine;
|
||||
i->offset = -1L;
|
||||
i->chain = NULL;
|
||||
if (fp) {
|
||||
i->offset = ftell(fp);
|
||||
FCLOSE(fp);
|
||||
}
|
||||
IStackPtr++;
|
||||
|
||||
/* If the file is cached, use it */
|
||||
h = CachedFiles;
|
||||
while(h) {
|
||||
if (!strcmp(fname, h->filename)) {
|
||||
if (DebugFlag & DB_TRACE_FILES) {
|
||||
fprintf(ErrFp, "Reading command `%s': Found in cache\n", fname);
|
||||
}
|
||||
CLine = h->cache;
|
||||
STRSET(FileName, fname);
|
||||
DBufFree(&buf);
|
||||
LineNo = 0;
|
||||
if (!h->ownedByMe) {
|
||||
RunDisabled |= RUN_NOTOWNER;
|
||||
} else {
|
||||
RunDisabled &= ~RUN_NOTOWNER;
|
||||
}
|
||||
if (FileName) return OK; else return E_NO_MEM;
|
||||
}
|
||||
h = h->next;
|
||||
}
|
||||
|
||||
if (DebugFlag & DB_TRACE_FILES) {
|
||||
fprintf(ErrFp, "Executing `%s' for INCLUDECMD and caching as `%s'\n",
|
||||
cmd, fname);
|
||||
}
|
||||
|
||||
/* Not found in cache */
|
||||
|
||||
/* If cmd starts with !, then disable RUN within the cmd output */
|
||||
if (cmd[0] == '!') {
|
||||
fp2 = popen(cmd+1, "r");
|
||||
} else {
|
||||
fp2 = popen(cmd, "r");
|
||||
}
|
||||
if (!fp2) {
|
||||
DBufFree(&buf);
|
||||
return E_CANT_OPEN;
|
||||
}
|
||||
fp = fp2;
|
||||
LineNo = 0;
|
||||
|
||||
/* Temporarily turn of file tracing */
|
||||
old_flag = DebugFlag;
|
||||
DebugFlag &= (~DB_TRACE_FILES);
|
||||
|
||||
if (cmd[0] == '!') {
|
||||
RunDisabled |= RUN_NOTOWNER;
|
||||
}
|
||||
r = CacheFile(fname, 1);
|
||||
|
||||
DebugFlag = old_flag;
|
||||
if (r == OK) {
|
||||
fp = NULL;
|
||||
CLine = CachedFiles->cache;
|
||||
LineNo = 0;
|
||||
STRSET(FileName, fname);
|
||||
DBufFree(&buf);
|
||||
return OK;
|
||||
}
|
||||
DBufFree(&buf);
|
||||
/* We failed */
|
||||
PopFile();
|
||||
return E_CANT_OPEN;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* IncludeFile */
|
||||
@@ -828,7 +1039,8 @@ int TopLevel(void)
|
||||
/* root, we refuse to open files not owned by root. */
|
||||
/* We also reject world-writable files, no matter */
|
||||
/* who we're running as. */
|
||||
/* As a side effect, if we don't own the file, we disable RUN */
|
||||
/* As a side effect, if we don't own the file, or it's not */
|
||||
/* owned by a trusted user, we disable RUN */
|
||||
/***************************************************************/
|
||||
static int CheckSafety(void)
|
||||
{
|
||||
@@ -866,9 +1078,22 @@ static int CheckSafety(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If file is not owned by me, disable RUN command */
|
||||
if (statbuf.st_uid != geteuid()) {
|
||||
RunDisabled |= RUN_NOTOWNER;
|
||||
/* If file is not owned by me or a trusted user, disable RUN command */
|
||||
|
||||
/* Assume unsafe */
|
||||
RunDisabled |= RUN_NOTOWNER;
|
||||
if (statbuf.st_uid == geteuid()) {
|
||||
/* Owned by me... safe */
|
||||
RunDisabled &= ~RUN_NOTOWNER;
|
||||
} else {
|
||||
int i;
|
||||
for (i=0; i<NumTrustedUsers; i++) {
|
||||
if (statbuf.st_uid == TrustedUsers[i]) {
|
||||
/* Owned by a trusted user... safe */
|
||||
RunDisabled &= ~RUN_NOTOWNER;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
26
src/funcs.c
26
src/funcs.c
@@ -6,7 +6,7 @@
|
||||
/* expressions. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -151,6 +151,7 @@ static int FWeekno (func_info *);
|
||||
static int FWkday (func_info *);
|
||||
static int FWkdaynum (func_info *);
|
||||
static int FYear (func_info *);
|
||||
static int FShellescape (func_info *);
|
||||
|
||||
static int CleanUpAfterFunc (func_info *);
|
||||
static int CheckArgs (BuiltinFunc *f, int nargs);
|
||||
@@ -267,6 +268,7 @@ BuiltinFunc Func[] = {
|
||||
{ "realtoday", 0, 0, 0, FRealtoday },
|
||||
{ "sgn", 1, 1, 1, FSgn },
|
||||
{ "shell", 1, 2, 0, FShell },
|
||||
{ "shellescape", 1, 1, 1, FShellescape },
|
||||
{ "slide", 2, NO_MAX, 0, FSlide },
|
||||
{ "strlen", 1, 1, 1, FStrlen },
|
||||
{ "substr", 2, 3, 1, FSubstr },
|
||||
@@ -1072,6 +1074,28 @@ static int FOstype(func_info *info)
|
||||
return RetStrVal("UNIX", info);
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* FShellescape - escape shell meta-characters */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static int FShellescape(func_info *info)
|
||||
{
|
||||
DynamicBuffer buf;
|
||||
int r;
|
||||
|
||||
ASSERT_TYPE(0, STR_TYPE);
|
||||
DBufInit (&buf);
|
||||
if (ShellEscape(ARG(0).v.str, &buf) != OK) {
|
||||
DBufFree(&buf);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
|
||||
r = RetStrVal(DBufValue(&buf), info);
|
||||
DBufFree(&buf);
|
||||
return r;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* FUpper - convert string to upper-case */
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
/* globals.h and err.h */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
/* MK_GLOBALS. Also contains useful macro definitions. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -21,6 +21,12 @@
|
||||
#define INIT(var, val) var
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#define MAX_TRUSTED_USERS 20
|
||||
|
||||
#define MINUTES_PER_DAY 1440
|
||||
|
||||
#define DaysInYear(y) (((y) % 4) ? 365 : ((!((y) % 100) && ((y) % 400)) ? 365 : 366 ))
|
||||
@@ -36,6 +42,9 @@ EXTERN int CurMon;
|
||||
EXTERN int CurYear;
|
||||
EXTERN int LineNo;
|
||||
EXTERN int FreshLine;
|
||||
EXTERN uid_t TrustedUsers[MAX_TRUSTED_USERS];
|
||||
|
||||
EXTERN INIT( int NumTrustedUsers, 0);
|
||||
EXTERN INIT( char const *MsgCommand, NULL);
|
||||
EXTERN INIT( int ShowAllErrors, 0);
|
||||
EXTERN INIT( int DebugFlag, 0);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Support for the Hebrew calendar */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/* Derived from code written by Amos Shapir in 1978; revised */
|
||||
/* 1985. */
|
||||
|
||||
60
src/init.c
60
src/init.c
@@ -7,7 +7,7 @@
|
||||
/* in normal mode. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -89,6 +89,7 @@ static void ChgUser(char const *u);
|
||||
static void InitializeVar(char const *str);
|
||||
|
||||
static char const *BadDate = "Illegal date on command line\n";
|
||||
static void AddTrustedUser(char const *username);
|
||||
|
||||
static DynamicBuffer default_filename_buf;
|
||||
|
||||
@@ -114,7 +115,7 @@ static char const *DefaultFilename(void)
|
||||
s = getenv("HOME");
|
||||
if (!s) {
|
||||
fprintf(stderr, "HOME environment variable not set. Unable to determine reminder file.\n");
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
DBufPuts(&default_filename_buf, s);
|
||||
DBufPuts(&default_filename_buf, "/.reminders");
|
||||
@@ -172,7 +173,7 @@ void InitRemind(int argc, char const *argv[])
|
||||
if (getgid() != getegid() ||
|
||||
getuid() != geteuid()) {
|
||||
fprintf(ErrFp, "\nRemind should not be installed set-uid or set-gid.\nCHECK YOUR SYSTEM SECURITY.\n");
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
y = NO_YR;
|
||||
@@ -183,7 +184,7 @@ void InitRemind(int argc, char const *argv[])
|
||||
RealToday = SystemDate(&CurYear, &CurMon, &CurDay);
|
||||
if (RealToday < 0) {
|
||||
fprintf(ErrFp, ErrMsg[M_BAD_SYS_DATE], BASE);
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
JulianToday = RealToday;
|
||||
FromJulian(JulianToday, &CurYear, &CurMon, &CurDay);
|
||||
@@ -217,6 +218,10 @@ void InitRemind(int argc, char const *argv[])
|
||||
}
|
||||
while (*arg) {
|
||||
switch(*arg++) {
|
||||
case '+':
|
||||
AddTrustedUser(arg);
|
||||
while(*arg) arg++;
|
||||
break;
|
||||
|
||||
case '@':
|
||||
UseVTColors = 1;
|
||||
@@ -330,8 +335,12 @@ void InitRemind(int argc, char const *argv[])
|
||||
|
||||
case 'u':
|
||||
case 'U':
|
||||
ChgUser(arg);
|
||||
RunDisabled = RUN_CMDLINE;
|
||||
if (*arg == '+') {
|
||||
ChgUser(arg+1);
|
||||
} else {
|
||||
RunDisabled = RUN_CMDLINE;
|
||||
ChgUser(arg);
|
||||
}
|
||||
while (*arg) arg++;
|
||||
break;
|
||||
case 'z':
|
||||
@@ -535,7 +544,7 @@ void InitRemind(int argc, char const *argv[])
|
||||
if (!InvokedAsRem) {
|
||||
if (i >= argc) {
|
||||
Usage();
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
InitialFile = argv[i++];
|
||||
} else {
|
||||
@@ -649,7 +658,7 @@ void InitRemind(int argc, char const *argv[])
|
||||
#ifndef L_USAGE_OVERRIDE
|
||||
void Usage(void)
|
||||
{
|
||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2020 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2021 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||
#ifdef BETA
|
||||
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
||||
#endif
|
||||
@@ -682,7 +691,7 @@ void Usage(void)
|
||||
fprintf(ErrFp, " -m Start calendar with Monday rather than Sunday\n");
|
||||
fprintf(ErrFp, " -y Synthesize tags for tagless reminders\n");
|
||||
fprintf(ErrFp, " -j[n] Run in 'purge' mode. [n = INCLUDE depth]\n");
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif /* L_USAGE_OVERRIDE */
|
||||
/***************************************************************/
|
||||
@@ -711,23 +720,23 @@ static void ChgUser(char const *user)
|
||||
|
||||
if (!pwent) {
|
||||
fprintf(ErrFp, ErrMsg[M_BAD_USER], user);
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (!myuid && setgid(pwent->pw_gid)) {
|
||||
fprintf(ErrFp, ErrMsg[M_NO_CHG_GID], pwent->pw_gid);
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (!myuid && setuid(pwent->pw_uid)) {
|
||||
fprintf(ErrFp, ErrMsg[M_NO_CHG_UID], pwent->pw_uid);
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
home = malloc(strlen(pwent->pw_dir) + 6);
|
||||
if (!home) {
|
||||
fprintf(ErrFp, "%s", ErrMsg[M_NOMEM_ENV]);
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
sprintf(home, "HOME=%s", pwent->pw_dir);
|
||||
putenv(home);
|
||||
@@ -735,7 +744,7 @@ static void ChgUser(char const *user)
|
||||
shell = malloc(strlen(pwent->pw_shell) + 7);
|
||||
if (!shell) {
|
||||
fprintf(ErrFp, "%s", ErrMsg[M_NOMEM_ENV]);
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
sprintf(shell, "SHELL=%s", pwent->pw_shell);
|
||||
putenv(shell);
|
||||
@@ -744,14 +753,14 @@ static void ChgUser(char const *user)
|
||||
username = malloc(strlen(pwent->pw_name) + 6);
|
||||
if (!username) {
|
||||
fprintf(ErrFp, "%s", ErrMsg[M_NOMEM_ENV]);
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
sprintf(username, "USER=%s", pwent->pw_name);
|
||||
putenv(username);
|
||||
logname= malloc(strlen(pwent->pw_name) + 9);
|
||||
if (!logname) {
|
||||
fprintf(ErrFp, "%s", ErrMsg[M_NOMEM_ENV]);
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
sprintf(logname, "LOGNAME=%s", pwent->pw_name);
|
||||
putenv(logname);
|
||||
@@ -838,6 +847,25 @@ static void InitializeVar(char const *str)
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
AddTrustedUser(char const *username)
|
||||
{
|
||||
struct passwd *pwent;
|
||||
if (NumTrustedUsers >= MAX_TRUSTED_USERS) {
|
||||
fprintf(stderr, "Too many trusted users (%d max)\n",
|
||||
MAX_TRUSTED_USERS);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
pwent = getpwnam(username);
|
||||
if (!pwent) {
|
||||
fprintf(ErrFp, ErrMsg[M_BAD_USER], username);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
TrustedUsers[NumTrustedUsers] = pwent->pw_uid;
|
||||
NumTrustedUsers++;
|
||||
}
|
||||
|
||||
#if defined(__APPLE__) || defined(__CYGWIN__)
|
||||
static char const pmsg1[] = {
|
||||
0x4c, 0x62, 0x68, 0x20, 0x6e, 0x63, 0x63, 0x72, 0x6e, 0x65, 0x20,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Header file for language support for various languages. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* */
|
||||
/* REMIND is Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* REMIND is Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* This file is Copyright (C) 1993 by Mogens Lynnerup. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
/* Further corrections by Erik-Jan Vens */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Support for the English language. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* This file is Copyright (C) 1993-1998 by Mikko Silvonen. */
|
||||
/* REMIND is Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* REMIND is Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -527,7 +527,7 @@ EXTERN char *ErrMsg[] =
|
||||
#define L_USAGE_OVERRIDE 1
|
||||
void Usage(void)
|
||||
{
|
||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2020 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2021 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||
#ifdef BETA
|
||||
fprintf(ErrFp, ">>>> BETAVERSIO <<<<\n");
|
||||
#endif
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* */
|
||||
/* REMIND is Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* REMIND is Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* This file is Copyright (C) 1993 by Laurent Duperval and */
|
||||
/* Dianne Skoll. */
|
||||
/* */
|
||||
@@ -359,7 +359,7 @@ EXTERN char *ErrMsg[] =
|
||||
#define L_USAGE_OVERRIDE 1
|
||||
void Usage(void)
|
||||
{
|
||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2020 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2021 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||
#ifdef BETA
|
||||
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
||||
#endif
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
/* I don't speak German. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Support for the Icelandic language. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* Translated by Björn Davíðsson (bjossi@snerpa.is) */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
/* This file is part of REMIND. */
|
||||
/* It is Copyright (C) 1996 by Valerio Aimale */
|
||||
/* */
|
||||
/* Remind is copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Remind is copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* This file is Copyright (C) 1993 by Trygve Randen. */
|
||||
/* Remind is Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Remind is Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
/* Polish. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -397,7 +397,7 @@ EXTERN char *ErrMsg[] =
|
||||
#define L_USAGE_OVERRIDE 1
|
||||
void Usage(void)
|
||||
{
|
||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2020 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2021 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||
#ifdef BETA
|
||||
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
||||
#endif
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* */
|
||||
/* REMIND is Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* REMIND is Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* This file is Copyright (C) 1996 by Marco Paganini and */
|
||||
/* Dianne Skoll. */
|
||||
/* */
|
||||
@@ -257,7 +257,7 @@ EXTERN char *ErrMsg[] =
|
||||
#define L_USAGE_OVERRIDE 1
|
||||
void Usage(void)
|
||||
{
|
||||
fprintf(ErrFp, "\nREMIND %s (versao %s) (C) 1992-2020 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||
fprintf(ErrFp, "\nREMIND %s (versao %s) (C) 1992-2021 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||
#ifdef BETA
|
||||
fprintf(ErrFp, ">>>> VERSAO BETA <<<<\n");
|
||||
#endif
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* */
|
||||
/* REMIND is Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* REMIND is Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* This file is Copyright (C) 1996-1998 by Liviu Daia */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
/* Author: Rafa Couto <rafacouto@biogate.com> */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
11
src/main.c
11
src/main.c
@@ -6,7 +6,7 @@
|
||||
/* routines, etc. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -243,6 +243,15 @@ static void DoReminders(void)
|
||||
r=DoInclude(&p);
|
||||
purge_handled = 1;
|
||||
break;
|
||||
case T_IncludeCmd:
|
||||
/* In purge mode, include closes file, so we
|
||||
need to echo it here! */
|
||||
if (PurgeMode) {
|
||||
PurgeEchoLine("%s\n", CurLine);
|
||||
}
|
||||
r=DoIncludeCmd(&p);
|
||||
purge_handled = 1;
|
||||
break;
|
||||
case T_Exit: DoExit(&p); break;
|
||||
case T_Flush: r=DoFlush(&p); break;
|
||||
case T_Set: r=DoSet(&p); break;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Calculations for figuring out moon phases. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* the data structures for OMITted dates. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Function Prototypes. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -45,6 +45,7 @@ int CopyValue (Value *dest, const Value *src);
|
||||
int ReadLine (void);
|
||||
int OpenFile (char const *fname);
|
||||
int DoInclude (ParsePtr p);
|
||||
int DoIncludeCmd (ParsePtr p);
|
||||
int IncludeFile (char const *fname);
|
||||
int GetAccessDate (char const *file);
|
||||
int SetAccessDate (char const *fname, int jul);
|
||||
@@ -161,3 +162,4 @@ void PrintJSONKeyPairDate(char const *name, int jul);
|
||||
void PrintJSONKeyPairDateTime(char const *name, int dt);
|
||||
void PrintJSONKeyPairTime(char const *name, int t);
|
||||
void System(char const *cmd);
|
||||
int ShellEscape(char const *in, DynamicBuffer *out);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Queue up reminders for subsequent execution. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Routines for sorting reminders by trigger date */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
17
src/token.c
17
src/token.c
@@ -6,7 +6,7 @@
|
||||
/* classifying the tokens parsed. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -62,6 +62,7 @@ Token TokArray[] = {
|
||||
{ "if", 2, T_If, 0 },
|
||||
{ "iftrig", 6, T_IfTrig, 0 },
|
||||
{ "include", 3, T_Include, 0 },
|
||||
{ "includecmd", 10, T_IncludeCmd, 0 },
|
||||
{ "january", 3, T_Month, 0 },
|
||||
{ "july", 3, T_Month, 6 },
|
||||
{ "june", 3, T_Month, 5 },
|
||||
@@ -172,6 +173,10 @@ void FindToken(char const *s, Token *tok)
|
||||
int top, bot, mid, r, max;
|
||||
int l;
|
||||
|
||||
#if LANG != ENGLISH
|
||||
size_t i;
|
||||
#endif
|
||||
|
||||
tok->type = T_Illegal;
|
||||
if (! *s) {
|
||||
tok->type = T_Empty;
|
||||
@@ -229,11 +234,11 @@ void FindToken(char const *s, Token *tok)
|
||||
/* If language is other than English, search the DayNames[] and MonthNames[]
|
||||
array. */
|
||||
#if LANG != ENGLISH
|
||||
for (size_t x=0; x<(sizeof(NonEnglishToks) / sizeof(Token)); x++) {
|
||||
if (l >= NonEnglishToks[x].MinLen &&
|
||||
!TokStrCmp(&NonEnglishToks[x], s)) {
|
||||
tok->type = NonEnglishToks[x].type;
|
||||
tok->val = NonEnglishToks[x].val;
|
||||
for (i=0; i<(sizeof(NonEnglishToks) / sizeof(Token)); i++) {
|
||||
if (l >= NonEnglishToks[i].MinLen &&
|
||||
!TokStrCmp(&NonEnglishToks[i], s)) {
|
||||
tok->type = NonEnglishToks[i].type;
|
||||
tok->val = NonEnglishToks[i].val;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Routines for figuring out the trigger date of a reminder */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#define GOT_YR 4
|
||||
#define GOT_WD 8
|
||||
|
||||
#define ADVANCE_TO_WD(x, wd) while (! ((wd) & (1 << ((x)%7)))) (x)++
|
||||
|
||||
static int JYear(int jul);
|
||||
static int JMonth(int jul);
|
||||
static int NextSimpleTrig(int startdate, Trigger *trig, int *err);
|
||||
@@ -58,9 +60,10 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
||||
if (trig->wd != NO_WD) typ |= GOT_WD;
|
||||
switch(typ) {
|
||||
case 0:
|
||||
return startdate;
|
||||
|
||||
case GOT_WD:
|
||||
if (trig->wd != NO_WD)
|
||||
while(! (trig->wd & (1 << (startdate%7)))) startdate++;
|
||||
ADVANCE_TO_WD(startdate, trig->wd);
|
||||
return startdate;
|
||||
|
||||
case GOT_DAY:
|
||||
@@ -83,12 +86,12 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
||||
else return -1;
|
||||
|
||||
case GOT_DAY+GOT_MON:
|
||||
if (m > trig->m || (m == trig->m && d > trig->d)) y++;
|
||||
if (trig->d > MonthDays[trig->m]) {
|
||||
*err = E_BAD_DATE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (m > trig->m || (m == trig->m && d > trig->d)) y++;
|
||||
/* Take care of Feb. 29 */
|
||||
while (trig->d > DaysInMonth(trig->m, y)) y++;
|
||||
return Julian(y, trig->m, trig->d);
|
||||
@@ -121,19 +124,19 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
||||
if (y > trig->y) return -1;
|
||||
if (y < trig->y) j = Julian(trig->y, 0, 1);
|
||||
else j = startdate;
|
||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
||||
ADVANCE_TO_WD(j, trig->wd);
|
||||
if (JYear(j) > trig->y) return -1;
|
||||
return j;
|
||||
|
||||
case GOT_MON+GOT_WD:
|
||||
if (m == trig->m) {
|
||||
j = startdate;
|
||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
||||
ADVANCE_TO_WD(j, trig->wd);
|
||||
if (JMonth(j) == trig->m) return j;
|
||||
}
|
||||
if (m >= trig->m) j = Julian(y+1, trig->m, 1);
|
||||
else j = Julian(y, trig->m, 1);
|
||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
||||
ADVANCE_TO_WD(j, trig->wd);
|
||||
return j; /* Guaranteed to be within the month */
|
||||
|
||||
case GOT_DAY+GOT_WD:
|
||||
@@ -144,7 +147,7 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
||||
/* If there are fewer days in previous month, no match */
|
||||
if (trig->d <= DaysInMonth(m2, y2)) {
|
||||
j = Julian(y2, m2, trig->d);
|
||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
||||
ADVANCE_TO_WD(j, trig->wd);
|
||||
if (j >= startdate) return j;
|
||||
|
||||
}
|
||||
@@ -153,7 +156,7 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
||||
/* Try this month */
|
||||
if (trig->d <= DaysInMonth(m, y)) {
|
||||
j = Julian(y, m, trig->d);
|
||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
||||
ADVANCE_TO_WD(j, trig->wd);
|
||||
if (j >= startdate) return j;
|
||||
}
|
||||
|
||||
@@ -162,18 +165,18 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
||||
if (m2 > 11) { m2 = 0; y++; }
|
||||
while (trig->d > DaysInMonth(m2, y)) m2++;
|
||||
j = Julian(y, m2, trig->d);
|
||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
||||
ADVANCE_TO_WD(j, trig->wd);
|
||||
return j;
|
||||
|
||||
case GOT_WD+GOT_YR+GOT_DAY:
|
||||
if (y > trig->y+1 || (y > trig->y && m>0)) return -1;
|
||||
if (y > trig->y) {
|
||||
j = Julian(trig->y, 11, trig->d);
|
||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
||||
ADVANCE_TO_WD(j, trig->wd);
|
||||
if (j >= startdate) return j;
|
||||
} else if (y < trig->y) {
|
||||
j = Julian(trig->y, 0, trig->d);
|
||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
||||
ADVANCE_TO_WD(j, trig->wd);
|
||||
return j;
|
||||
} else {
|
||||
/* Try last month */
|
||||
@@ -181,14 +184,16 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
||||
m2 = m-1;
|
||||
while (trig->d > DaysInMonth(m2, trig->y)) m2--;
|
||||
j = Julian(trig->y, m2, trig->d);
|
||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
||||
ADVANCE_TO_WD(j, trig->wd);
|
||||
if (JYear(j) > trig->y) return -1;
|
||||
if (j >= startdate) return j;
|
||||
}
|
||||
}
|
||||
/* Try this month */
|
||||
if (trig->d <= DaysInMonth(m, trig->y)) {
|
||||
j = Julian(trig->y, m, trig->d);
|
||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
||||
ADVANCE_TO_WD(j, trig->wd);
|
||||
if (JYear(j) > trig->y) return -1;
|
||||
if (j >= startdate) return j;
|
||||
}
|
||||
|
||||
@@ -197,7 +202,8 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
||||
m++;
|
||||
while (trig->d > DaysInMonth(m, trig->d)) m++;
|
||||
j = Julian(trig->y, m, trig->d);
|
||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
||||
ADVANCE_TO_WD(j, trig->wd);
|
||||
if (JYear(j) > trig->y) return -1;
|
||||
return j;
|
||||
|
||||
case GOT_DAY+GOT_MON+GOT_WD:
|
||||
@@ -215,31 +221,32 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
||||
|
||||
/* Try last year */
|
||||
j = Julian(y, trig->m, trig->d);
|
||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
||||
ADVANCE_TO_WD(j, trig->wd);
|
||||
if (j >= startdate) return j;
|
||||
|
||||
/* Try this year */
|
||||
y++;
|
||||
while (trig->d > DaysInMonth(trig->m, y)) y++;
|
||||
j = Julian(y, trig->m, trig->d);
|
||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
||||
ADVANCE_TO_WD(j, trig->wd);
|
||||
if (j >= startdate) return j;
|
||||
|
||||
/* Must be next year */
|
||||
y++;
|
||||
while (trig->d > DaysInMonth(trig->m, y)) y++;
|
||||
j = Julian(y, trig->m, trig->d);
|
||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
||||
ADVANCE_TO_WD(j, trig->wd);
|
||||
return j;
|
||||
|
||||
case GOT_WD+GOT_MON+GOT_YR:
|
||||
if (y > trig->y || (y == trig->y && m > trig->m)) return -1;
|
||||
if (trig->y > y || (trig->y == y && trig->m > m)) {
|
||||
j = Julian(trig->y, trig->m, 1);
|
||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
||||
ADVANCE_TO_WD(j, trig->wd);
|
||||
return j;
|
||||
} else {
|
||||
j = startdate;
|
||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
||||
ADVANCE_TO_WD(j, trig->wd);
|
||||
FromJulian(j, &y2, &m2, &d2);
|
||||
if (m2 == trig->m) return j; else return -1;
|
||||
}
|
||||
@@ -250,7 +257,7 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
||||
return -1;
|
||||
}
|
||||
j = Julian(trig->y, trig->m, trig->d);
|
||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
||||
ADVANCE_TO_WD(j, trig->wd);
|
||||
return j;
|
||||
|
||||
default:
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Type definitions all dumped here. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -150,7 +150,7 @@ typedef Parser *ParsePtr; /* Pointer to parser structure */
|
||||
enum TokTypes
|
||||
{ T_Illegal,
|
||||
/* Commands first */
|
||||
T_Rem, T_Push, T_Pop, T_Preserve, T_Include, T_If, T_Else, T_EndIf,
|
||||
T_Rem, T_Push, T_Pop, T_Preserve, T_Include, T_IncludeCmd, T_If, T_Else, T_EndIf,
|
||||
T_IfTrig, T_ErrMsg,
|
||||
T_Set, T_UnSet, T_Fset, T_Omit, T_Banner, T_Exit,
|
||||
T_WkDay,
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* functions. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
18
src/utils.c
18
src/utils.c
@@ -5,11 +5,15 @@
|
||||
/* Useful utility functions. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
static char const DontEscapeMe[] =
|
||||
"1234567890_-=+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@.,/";
|
||||
|
||||
#include "config.h"
|
||||
#include "err.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
@@ -146,3 +150,15 @@ int _private_unminus_overflow(int a, int b)
|
||||
if (a < 0 && b < 0) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ShellEscape(char const *in, DynamicBuffer *out)
|
||||
{
|
||||
while(*in) {
|
||||
if (!strchr(DontEscapeMe, *in)) {
|
||||
if (DBufPutc(out, '\\') != OK) return E_NO_MEM;
|
||||
}
|
||||
if (DBufPutc(out, *in++) != OK) return E_NO_MEM;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* user- and system-defined variables. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
#!/bin/sh
|
||||
cd /home/dfs/Software/Remind.git || exit 1
|
||||
|
||||
rm -f .git/COMMIT_EDITMSG .git/*~
|
||||
|
||||
git update-server-info && cd .git && rsync --exclude HEADER.html --archive --verbose --progress --delete ./ dianne.skoll.ca:web/projects/remind/git/Remind.git/
|
||||
exit $?
|
||||
|
||||
27
tests/test-for-backends.rem
Normal file
27
tests/test-for-backends.rem
Normal file
@@ -0,0 +1,27 @@
|
||||
# This file is designed for testing how back-ends
|
||||
# handle SPECIALs, including SPECIALS they don't understand
|
||||
# If you're writing a back-end, test it by feeding it the output
|
||||
# of: remind -pp test-for-backends.rem
|
||||
|
||||
# Color and shade
|
||||
REM 1 SPECIAL COLOR 128 0 0 Red
|
||||
REM 2 SPECIAL COLOUR 0 128 0 British Green
|
||||
REM 3 SPECIAL SHADE 192 192 255
|
||||
|
||||
# Moon
|
||||
REM [moondate(0)] SPECIAL MOON 0 -1 -1 [moontime(0)]
|
||||
REM [moondate(1)] SPECIAL MOON 1 -1 -1 [moontime(1)]
|
||||
REM [moondate(2)] SPECIAL MOON 2 -1 -1 [moontime(2)]
|
||||
REM [moondate(3)] SPECIAL MOON 3 -1 -1 [moontime(3)]
|
||||
|
||||
# Week
|
||||
REM Monday SPECIAL WEEK (W[weekno()])
|
||||
|
||||
# PostScript
|
||||
REM Wed PS Border Border 2 div moveto /Helvetica-Oblique findfont 6 scalefont setfont (oof!) show
|
||||
|
||||
# A SPECIAL that should be ignored
|
||||
REM 15 SPECIAL RANDOM-STUFF ignore me and be happy
|
||||
|
||||
# A normal reminder
|
||||
REM 16 MSG A normal reminder
|
||||
@@ -7,13 +7,22 @@
|
||||
# in the build directory.
|
||||
#
|
||||
# This file is part of REMIND.
|
||||
# Copyright (C) 1992-2018 Dianne Skoll
|
||||
# Copyright (C) 1992-2021 Dianne Skoll
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
DIR=`dirname $0`
|
||||
cd $DIR
|
||||
if test $? != 0 ; then
|
||||
echo ""
|
||||
echo "Unable to cd $DIR" >&2
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test `id -u` = 0 ; then
|
||||
echo ""
|
||||
echo "*** Please do not run the test suite as root; it will fail."
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -56,6 +65,14 @@ echo "" >> ../tests/test.out
|
||||
|
||||
chmod 644 include_dir/04cantread.rem
|
||||
|
||||
# Feb 29 bug
|
||||
echo "Feb 29 Bug Test" >> ../tests/test.out
|
||||
echo 'REM Sun 29 Feb MSG [$T]' | ../src/remind -dt - 1 feb 2021 >> ../tests/test.out 2>&1
|
||||
|
||||
# Day Weekday Year out-of-year bug
|
||||
echo "Mon 31 Dec Bug Test" >> ../tests/test.out
|
||||
echo 'REM Mon 31 2021 MSG [$T]' | ../src/remind -dt - 31 dec 2021 >> ../tests/test.out 2>&1
|
||||
|
||||
echo "Color Test" >> ../tests/test.out
|
||||
../src/remind -ccl ../tests/colors.rem 1 aug 2007 >> ../tests/test.out 2>&1
|
||||
|
||||
@@ -290,14 +307,21 @@ rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE
|
||||
EOF
|
||||
|
||||
# If we're already in a utf-8 locale, do
|
||||
# nothing
|
||||
|
||||
if ! echo $LC_ALL | grep -i utf-8 > /dev/null 2>&1 ; then
|
||||
export LC_ALL=en_US.utf-8
|
||||
# nothing; otherwise, set LC_ALL
|
||||
OK=0
|
||||
if echo $LC_ALL | grep -i utf-8 > /dev/null 2>&1 ; then
|
||||
OK=1
|
||||
fi
|
||||
|
||||
if ! echo $LANG | grep -i utf-8 > /dev/null 2>&1 ; then
|
||||
export LANG=en_US.utf-8
|
||||
if test -z "$LC_ALL" ; then
|
||||
if echo $LANG | grep -i utf-8 > /dev/null 2>&1 ; then
|
||||
export LC_ALL="$LANG"
|
||||
OK=1
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$OK" = 0 ; then
|
||||
export LC_ALL=en_US.utf-8
|
||||
fi
|
||||
|
||||
../src/remind -w128 -c ../tests/utf-8.rem 1 Nov 2019 >> ../tests/test.out
|
||||
|
||||
1255
tests/test.cmp
1255
tests/test.cmp
File diff suppressed because it is too large
Load Diff
@@ -15,9 +15,40 @@ REM Wed UNTIL 15 Feb 1991 SATISFY [trigdate() > '1990-01-01'] MSG wookie
|
||||
# bad AT
|
||||
REM AT 0:00 0:01 0:02 MSG foo
|
||||
|
||||
# Includecmd
|
||||
INCLUDECMD echo REM 16 Feb 1991 MSG Blork
|
||||
INCLUDECMD echo REM 18 Feb 1991 MSG Blork
|
||||
|
||||
# Includecmd with continuation line
|
||||
INCLUDECMD echo REM 18 Feb 1991 MSG This line is \
|
||||
continued so there
|
||||
|
||||
# This should work
|
||||
INCLUDECMD echo INCLUDECMD echo INCLUDECMD echo INCLUDECMD echo INCLUDECMD echo INCLUDECMD echo INCLUDECMD echo MSG Yippee
|
||||
|
||||
# This should fail
|
||||
INCLUDECMD echo INCLUDECMD echo INCLUDECMD echo INCLUDECMD echo INCLUDECMD echo INCLUDECMD echo INCLUDECMD echo INCLUDECMD echo MSG Yippee
|
||||
REM MSG Today is [hebday(today())] [hebmon(today())] [hebyear(today())]
|
||||
fset _h(x, y) trigger(hebdate(x,y))
|
||||
|
||||
# Test case from Remind mailing list
|
||||
set mltest "a b"
|
||||
INCLUDECMD printf 'REM %s\n' [mltest]
|
||||
|
||||
# Disabling RUN in an !includecmd
|
||||
INCLUDECMD !echo MSG foo
|
||||
INCLUDECMD !echo MSG foo
|
||||
INCLUDECMD !echo INCLUDECMD echo MSG foo
|
||||
INCLUDECMD !echo INCLUDECMD echo MSG foo
|
||||
INCLUDECMD !echo MSG foo
|
||||
INCLUDECMD !echo MSG foo
|
||||
|
||||
# INCLUDECMD with RUN disabled
|
||||
RUN OFF
|
||||
INCLUDECMD echo MSG foo
|
||||
RUN ON
|
||||
INCLUDECMD echo MSG foo
|
||||
|
||||
[_h(1, "Tishrey")] MSG Rosh Hashana 1
|
||||
[_h(2, "Tishrey")] MSG Rosh Hashana 2
|
||||
[_h(3, "Tishrey")] MSG Tzom Gedalia
|
||||
@@ -551,8 +582,15 @@ set a $IntMin * 2
|
||||
set a $IntMin * $IntMin
|
||||
set a $IntMin * $IntMax
|
||||
set a $IntMin / (-1)
|
||||
set a $IntMin * (-1)
|
||||
set a (-1) * $IntMin
|
||||
set a abs($IntMin)
|
||||
|
||||
# Shellescape
|
||||
set a shellescape(" !\"#$%%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~")
|
||||
|
||||
msg [a]
|
||||
|
||||
# Don't want Remind to queue reminders
|
||||
EXIT
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "Unconfiguring Remind..."
|
||||
echo rm -f config.cache config.log config.status src/Makefile src/config.h src/version.h www/Makefile
|
||||
rm -f config.cache config.log config.status src/Makefile src/config.h src/version.h www/Makefile
|
||||
echo rm -f config.cache config.log config.status src/Makefile src/config.h src/version.h www/Makefile rem2html/Makefile
|
||||
rm -f config.cache config.log config.status src/Makefile src/config.h src/version.h www/Makefile rem2html/Makefile
|
||||
exit 0
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
# The complete path to where the scripts actually live, as seen by
|
||||
# the UNIX operating system.
|
||||
SCRIPTDIR = /var/www/cgi-bin
|
||||
SCRIPTDIR = /usr/lib/cgi-bin
|
||||
|
||||
# Where the scripts live as seen by the web browser.
|
||||
CGIDIR = /cgi-bin
|
||||
@@ -17,7 +17,7 @@ HTMLDIR = /var/www/remind
|
||||
# Where you stick images and CSS files, as seen by UNIX
|
||||
IMAGEDIR = /var/www/remind/resources
|
||||
|
||||
# Where images are, as seen by web browers
|
||||
# Where images and CSS fiels are, as seen by web browers
|
||||
IMAGEBASE = /remind/resources
|
||||
|
||||
# Set by configure - don't touch.
|
||||
@@ -32,7 +32,7 @@ datarootdir=@datarootdir@
|
||||
# Where do Remind and Rem2PS executables live?
|
||||
REMIND = $(bindir)/remind
|
||||
REM2PS = $(bindir)/rem2ps
|
||||
|
||||
REM2HTML = $(bindir)/rem2html
|
||||
# If your Web server requires CGI programs to have a .cgi suffix, use
|
||||
# the next line. Otherwise, comment it out
|
||||
CGISUFFIX=.cgi
|
||||
@@ -46,14 +46,8 @@ SEDSCRIPT = -e 's@%CGIDIR%@$(CGIDIR)@g' \
|
||||
-e 's@%REMIND%@$(REMIND)@g' \
|
||||
-e 's@%IMAGEBASE%@$(IMAGEBASE)@g' \
|
||||
-e 's@%REM2PS%@$(REM2PS)@g' \
|
||||
-e 's@%REM2HTML%@$(REM2HTML)@g' \
|
||||
-e 's@cal_dispatch@cal_dispatch$(CGISUFFIX)@g' \
|
||||
-e 's@rem2html@rem2html$(CGISUFFIX)@g'
|
||||
|
||||
SEDSCRIPT2 = -e 's@%CGIDIR%@$(CGIDIR)@g' \
|
||||
-e 's@%SCRIPTDIR%@$(SCRIPTDIR)@g' \
|
||||
-e 's@%REMIND%@$(REMIND)@g' \
|
||||
-e 's@%IMAGEBASE%@$(IMAGEBASE)@g' \
|
||||
-e 's@%REM2PS%@$(REM2PS)@g'
|
||||
|
||||
all:
|
||||
@echo "Edit the Makefile; then type 'make install' to install"
|
||||
@@ -72,7 +66,6 @@ install:
|
||||
cp blank.rem $(DESTDIR)$(SCRIPTDIR)/blank.rem
|
||||
sed $(SEDSCRIPT) < calendar.html-DIST > $(DESTDIR)$(HTMLDIR)/calendar.html
|
||||
sed $(SEDSCRIPT) < hebhtml > $(DESTDIR)$(SCRIPTDIR)/hebhtml
|
||||
sed $(SEDSCRIPT2) < rem2html > $(DESTDIR)$(SCRIPTDIR)/rem2html$(CGISUFFIX)
|
||||
chmod 644 $(DESTDIR)$(SCRIPTDIR)/sunrise.rem
|
||||
chmod 644 $(DESTDIR)$(SCRIPTDIR)/moon.rem
|
||||
chmod 644 $(DESTDIR)$(SCRIPTDIR)/hebdate.rem
|
||||
@@ -80,20 +73,14 @@ install:
|
||||
chmod 644 $(DESTDIR)$(SCRIPTDIR)/blank.rem
|
||||
chmod 644 $(DESTDIR)$(HTMLDIR)/calendar.html
|
||||
chmod 755 $(DESTDIR)$(SCRIPTDIR)/cal_dispatch$(CGISUFFIX)
|
||||
chmod 755 $(DESTDIR)$(SCRIPTDIR)/rem2html$(CGISUFFIX)
|
||||
chmod 755 $(DESTDIR)$(SCRIPTDIR)/calps $(DESTDIR)$(SCRIPTDIR)/hebdate \
|
||||
$(DESTDIR)$(SCRIPTDIR)/hebps $(DESTDIR)$(SCRIPTDIR)/moon \
|
||||
$(DESTDIR)$(SCRIPTDIR)/sunrise $(DESTDIR)$(SCRIPTDIR)/sunset \
|
||||
$(DESTDIR)$(SCRIPTDIR)/hebhtml \
|
||||
$(DESTDIR)$(SCRIPTDIR)/rem2html$(CGISUFFIX)
|
||||
|
||||
-mkdir -p $(DESTDIR)$(IMAGEDIR)
|
||||
cp firstquarter.png fullmoon.png lastquarter.png newmoon.png rem-default.css $(DESTDIR)$(IMAGEDIR)
|
||||
chmod 644 $(DESTDIR)$(IMAGEDIR)/firstquarter.png \
|
||||
$(DESTDIR)$(IMAGEDIR)/fullmoon.png \
|
||||
$(DESTDIR)$(IMAGEDIR)/lastquarter.png \
|
||||
$(DESTDIR)$(IMAGEDIR)/newmoon.png \
|
||||
$(DESTDIR)$(IMAGEDIR)/rem-default.css
|
||||
cp rem-default.css *.png $(DESTDIR)$(IMAGEDIR)
|
||||
chmod 644 $(DESTDIR)$(IMAGEDIR)/rem-default.css $(DESTDIR)$(IMAGEDIR)/*.png
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -19,9 +19,7 @@ server:
|
||||
1) Edit the Makefile in this directory. See the comments in the Makefile
|
||||
for details.
|
||||
|
||||
2) Edit the first line of "rem2html" to reflect the location of
|
||||
Perl on your system. (Oh yeah, you need Perl for the
|
||||
HTML Hebrew calendar...)
|
||||
2) Make sure "rem2html" is installed.
|
||||
|
||||
3) Type "make install"
|
||||
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
REM2HTML
|
||||
--------
|
||||
|
||||
Rem2HTML is a Perl script that transforms the output of `remind -p
|
||||
...' to HTML. Type `perl rem2html --help' for usage information.
|
||||
|
||||
Typical usage: remind -p ~/.reminders | rem2html > file.html
|
||||
|
||||
You may have to edit the "#!/usr/bin/perl" line to reflect the
|
||||
location of your Perl interpreter.
|
||||
|
||||
--
|
||||
Dianne Skoll
|
||||
@@ -18,7 +18,7 @@ set lastyear iif(lastmon==12, thisyear-1, thisyear)
|
||||
set nextmon mon(nextmon)
|
||||
set lastmon mon(lastmon)
|
||||
BANNER %
|
||||
REM RUN $REMIND -iHTML=1 -p $DIR/hebdate.rem %m %y | $DIR/rem2html --forwurl "cal_dispatch?hebhtml+[nextmon]+[nextyear]" --backurl "cal_dispatch?hebhtml+[lastmon]+[lastyear]"
|
||||
REM RUN $REMIND -iHTML=1 -p $DIR/hebdate.rem %m %y | %REM2HTML% --forwurl "cal_dispatch?hebhtml+[nextmon]+[nextyear]" --backurl "cal_dispatch?hebhtml+[lastmon]+[lastyear]" --imgbase "%IMAGEBASE%" --stylesheet rem-default.css --pngs
|
||||
EOR
|
||||
|
||||
else
|
||||
@@ -33,7 +33,7 @@ set lastyear iif(lastmon==12, thisyear-1, thisyear)
|
||||
set nextmon mon(nextmon)
|
||||
set lastmon mon(lastmon)
|
||||
BANNER %
|
||||
REM RUN $REMIND -iHTML=1 -p $DIR/hebdate.rem %m %y | $DIR/rem2html --forwurl "cal_dispatch?hebhtml+[nextmon]+[nextyear]" --backurl "cal_dispatch?hebhtml+[lastmon]+[lastyear]"
|
||||
REM RUN $REMIND -iHTML=1 -p $DIR/hebdate.rem %m %y | %REM2HTML% --forwurl "cal_dispatch?hebhtml+[nextmon]+[nextyear]" --backurl "cal_dispatch?hebhtml+[lastmon]+[lastyear]" --imgbase "%IMAGEBASE%" --stylesheet rem-default.css --pngs
|
||||
EOR
|
||||
|
||||
fi
|
||||
|
||||
@@ -49,6 +49,10 @@ div.rem-daynumber {
|
||||
font-size: 14pt;
|
||||
}
|
||||
|
||||
p.rem-entry {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
div.rem-moon {
|
||||
float: left;
|
||||
text-align: left;
|
||||
@@ -66,4 +70,4 @@ td.rem-sc-empty-cell, td.rem-sc-cell {
|
||||
|
||||
caption.rem-sc-caption {
|
||||
font-size: 12pt;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user