mirror of
https://salsa.debian.org/dskoll/remind.git
synced 2026-04-16 22:38:37 +02:00
Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
51dfd707a2 | ||
|
|
7c3bf8601b | ||
|
|
714195efe5 | ||
|
|
eaeca2d09b | ||
|
|
ffa3b13437 | ||
|
|
2551e98d11 | ||
|
|
1bfd7761bc | ||
|
|
de9cb1d0a3 | ||
|
|
b2d32b514a | ||
|
|
6e53fd6924 | ||
|
|
8296d2b962 | ||
|
|
d6e66ee1e6 | ||
|
|
a49532b9c5 | ||
|
|
57d87f4caf | ||
|
|
ec9b30c616 | ||
|
|
27d8a62ab6 | ||
|
|
5077814c4a | ||
|
|
ca795a352a | ||
|
|
e59fc36458 | ||
|
|
39e3657539 | ||
|
|
6031f70701 | ||
|
|
3567c9e55f | ||
|
|
26de4e3fd3 | ||
|
|
cd65c6144d | ||
|
|
7b64623115 |
6
configure
vendored
6
configure
vendored
@@ -4134,14 +4134,14 @@ if test "$GCC" = yes; then
|
||||
f=-flto=auto
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC supports $f" >&5
|
||||
printf %s "checking whether $CC supports $f... " >&6; }
|
||||
if $CC -E $f /dev/null > /dev/null 2>&1 ; then
|
||||
if $CC -Werror -E $f - < /dev/null > /dev/null 2>&1 ; then
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
printf "%s\n" "yes" >&6; }
|
||||
CFLAGS="$CFLAGS $f"
|
||||
f=-ffat-lto-objects
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC supports $f" >&5
|
||||
printf %s "checking whether $CC supports $f... " >&6; }
|
||||
if $CC -E $f /dev/null > /dev/null 2>&1 ; then
|
||||
if $CC -Werror -E $f - < /dev/null > /dev/null 2>&1 ; then
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
printf "%s\n" "yes" >&6; }
|
||||
CFLAGS="$CFLAGS $f"
|
||||
@@ -4213,7 +4213,7 @@ then :
|
||||
fi
|
||||
|
||||
|
||||
VERSION=04.02.07
|
||||
VERSION=04.02.08
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -50,12 +50,12 @@ if test "$GCC" = yes; then
|
||||
# Check for link-time optimization support
|
||||
f=-flto=auto
|
||||
AC_MSG_CHECKING([whether $CC supports $f])
|
||||
if $CC -E $f /dev/null > /dev/null 2>&1 ; then
|
||||
if $CC -Werror -E $f - < /dev/null > /dev/null 2>&1 ; then
|
||||
AC_MSG_RESULT([yes])
|
||||
CFLAGS="$CFLAGS $f"
|
||||
f=-ffat-lto-objects
|
||||
AC_MSG_CHECKING([whether $CC supports $f])
|
||||
if $CC -E $f /dev/null > /dev/null 2>&1 ; then
|
||||
if $CC -Werror -E $f - < /dev/null > /dev/null 2>&1 ; then
|
||||
AC_MSG_RESULT([yes])
|
||||
CFLAGS="$CFLAGS $f"
|
||||
else
|
||||
@@ -88,7 +88,7 @@ if test "$?" != 0 ; then
|
||||
fi
|
||||
AC_CHECK_FUNCS(setenv unsetenv glob mbstowcs setlocale initgroups)
|
||||
|
||||
VERSION=04.02.07
|
||||
VERSION=04.02.08
|
||||
AC_SUBST(VERSION)
|
||||
AC_SUBST(PERL)
|
||||
AC_SUBST(PERLARTIFACTS)
|
||||
|
||||
@@ -1,5 +1,36 @@
|
||||
CHANGES TO REMIND
|
||||
|
||||
* VERSION 4.2 Patch 8 - 2023-12-14
|
||||
|
||||
- NEW FEATURE: Add the $MaxLateMinutes system variable. This suppresses
|
||||
a queued time reminder if the current time is more than $MaxLateMinutes
|
||||
past the trigger time. (This typically only occurs if the computer
|
||||
has been suspended/hibernated and then resumed.)
|
||||
|
||||
- IMPROVEMENT: tkremind: If an error occurs during printing, catch it
|
||||
and change the Queue... button to Errors... (the same way errors in
|
||||
reminder files are handled.)
|
||||
|
||||
- IMPROVEMENT: rem2html: add the --utf8 flag to set the HTML charset to
|
||||
UTF-8.
|
||||
|
||||
- MINOR IMPROVEMENTS: Refactor some of the C code; use symbolic exit
|
||||
statuses and file descriptors for stdin/stdout/stderr where possible.
|
||||
|
||||
- BUG FIX: configure.in: Use better option detection so we don't use the
|
||||
unsupported option -ffat-lto-objects if compiling with clang instead of gcc.
|
||||
|
||||
- BUG FIXES: Many fixes to man pages, some by Jochen Sprickerhof
|
||||
|
||||
- MINOR BUG FIX: If Remind puts itself in the background, only close
|
||||
stdout/stderr if they are not associated with a terminal. If
|
||||
we close a descriptor, dup /dev/null onto it.
|
||||
|
||||
- MINOR BUG FIX: Catch SIGCONT when running in daemon/background mode.
|
||||
This forces the select() call to be interrupted so we can update the
|
||||
sleep time. This really only matters if the computer or the background
|
||||
Remind process is suspended and then resumed.
|
||||
|
||||
* VERSION 4.2 Patch 7 - 2023-10-09
|
||||
|
||||
- IMPROVEMENT: remind: On 32-bit systems, attempt to use a 64-bit time_t
|
||||
|
||||
@@ -10,7 +10,7 @@ FSET center(x) pad("", " ", (columns() - columns(x))/2) + x
|
||||
FSET right(x) pad("", " ", columns() - columns(x)) + x
|
||||
|
||||
MSG This is left-aligned.
|
||||
MSG [ansicolor(0,255,0)]This is also left-aligned.[ansicolor("")]
|
||||
MSG [ansicolor(0,255,0)]🌕 🌕 🌕 🌕 This is also left-aligned.[ansicolor("")]
|
||||
|
||||
MSG [center("This is centered.")]
|
||||
MSG [ansicolor(255,255,0) + center("🌕 🌕 🌕 🌕 This is also centered. ") + ansicolor("")]
|
||||
|
||||
@@ -458,7 +458,7 @@ JSON object. The keys that may be present in the JSON object are as
|
||||
follows:
|
||||
.TP
|
||||
.B date \fIYYYY-MM-DD\fR
|
||||
The \fbdate\fR key will \fIalways\fR be present; it is the trigger date
|
||||
The \fBdate\fR key will \fIalways\fR be present; it is the trigger date
|
||||
of the reminder expressed as a string in the format \fIYYYY-MM-DD\fR
|
||||
.TP
|
||||
.B filename \fIf\fR
|
||||
|
||||
@@ -2562,6 +2562,24 @@ updates \fB$LongDeg\fR, \fB$LongMin\fR and \fB$LongSec\fR. Similar
|
||||
rules apply to \fB$Latitude\fR, \fB$LatDeg\fR, \fB$LatMin\fR and \fB$LatSec\fR.
|
||||
.RE
|
||||
.TP
|
||||
.B $MaxLateMinutes
|
||||
This variable controls how \fBRemind\fR reacts to a computer being suspended
|
||||
and then woken. Normally, if a timed reminder is queued and then the
|
||||
computer suspended, and then the computer is woken \fIafter\fR the
|
||||
timed reminder's trigger time, \fBRemind\fR will triger the timer anyway,
|
||||
despite the fact that the trigger time has already passed.
|
||||
.RS
|
||||
.PP
|
||||
If you set \fB$MaxLateMinutes\fR to a non-zero integer between 1 and 1440,
|
||||
then \fBRemind\fR will \fInot\fR trigger a timed reminder whose trigger
|
||||
time is more than \fB$MaxLateMinutes\fR minutes in the past.
|
||||
.PP
|
||||
Note that \fBRemind\fR uses the value of \fB$MaxLateMinutes\fR that is in
|
||||
effect when it has finished reading the reminder file and puts itself in
|
||||
the background. Generally, you should set \fB$MaxLateMinutes\fR once
|
||||
near the beginning of the file and not change it after that.
|
||||
.RE
|
||||
.TP
|
||||
.B $MaxSatIter
|
||||
The maximum number of iterations for the \fBSATISFY\fR clause
|
||||
(described later.) Must be at least 10.
|
||||
|
||||
@@ -383,6 +383,16 @@ same thing.
|
||||
STATUS
|
||||
Return the number of queued reminders.
|
||||
|
||||
.TP
|
||||
QUEUE
|
||||
Returns the contents of the queue, printed between "NOTE queue" and
|
||||
"NOTE endqueue" lines.
|
||||
|
||||
.TP
|
||||
JSONQUEUE
|
||||
Returns the contents of the queue in JSON format, printed between
|
||||
"NOTE JSONQUEUE" and "NOTE ENDJSONQUEUE" lines.
|
||||
|
||||
.TP
|
||||
REREAD
|
||||
Re-read the reminder file
|
||||
@@ -416,6 +426,16 @@ NOTE queued \fIn\fR
|
||||
This line is emitted in response to a \fBSTATUS\fR command. The number
|
||||
\fIn\fR is the number of reminders in the queue.
|
||||
|
||||
.TP
|
||||
NOTE queue
|
||||
Indicates that queue contents are about to follow. The end of the
|
||||
queue is indicated by a NOTE endqueue line.
|
||||
|
||||
.TP
|
||||
NOTE JSONQUEUE
|
||||
Indicates that queue contents in JSON format are about to follow. The
|
||||
end of the queue is indicated by a NOTE ENDJSONQUEUE line.
|
||||
|
||||
.SH AUTHOR
|
||||
TkRemind was written by Dianne Skoll <dianne@skoll.ca>
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ use warnings;
|
||||
|
||||
use Getopt::Long;
|
||||
use JSON::MaybeXS;
|
||||
use Encode;
|
||||
|
||||
my %Options;
|
||||
|
||||
@@ -44,6 +45,11 @@ Print usage information
|
||||
|
||||
Print version
|
||||
|
||||
=item --utf8
|
||||
|
||||
Assume standard input is encoded in UTF-8; write UTF-8 data to standard
|
||||
output.
|
||||
|
||||
=item --backurl I<url>
|
||||
|
||||
When producing the small calendar for the previous month, make the
|
||||
@@ -154,6 +160,7 @@ Usage: remind -pp ... | rem2html [options]
|
||||
Options:
|
||||
|
||||
--help, -h Print usage information
|
||||
--utf8 Assume UTF-8 input and write UTF-8 output
|
||||
--man Show man page (requires "perldoc")
|
||||
--version Print version
|
||||
--backurl url Make the title on the previous month's small calendar
|
||||
@@ -197,6 +204,7 @@ sub parse_options
|
||||
local $SIG{__WARN__} = sub { print STDERR "$TIDY_PROGNAME: $_[0]\n"; };
|
||||
if (!GetOptions(\%Options, "help|h",
|
||||
"man",
|
||||
"utf8",
|
||||
"pngs",
|
||||
"version",
|
||||
"stylesheet=s",
|
||||
@@ -216,13 +224,22 @@ sub parse_options
|
||||
if ($stylesheet) {
|
||||
$Options{stylesheet} = smoosh($Options{imgbase}, $stylesheet);
|
||||
}
|
||||
if ($Options{utf8}) {
|
||||
binmode(STDIN, ':encoding(UTF-8)');
|
||||
binmode(STDOUT, ':encoding(UTF-8)');
|
||||
}
|
||||
}
|
||||
|
||||
sub start_output
|
||||
{
|
||||
return if ($Options{tableonly});
|
||||
|
||||
print("<html>\n<head>\n<title>" . $Options{title} . "</title>\n");
|
||||
print("<html>\n<head>\n");
|
||||
if ($Options{utf8}) {
|
||||
print '<meta charset="UTF-8">' . "\n";
|
||||
}
|
||||
|
||||
print("<title>" . $Options{title} . "</title>\n");
|
||||
if (!$Options{nostyle}) {
|
||||
if ($Options{stylesheet}) {
|
||||
print('<link rel="stylesheet" type="text/css" href="' .
|
||||
@@ -310,7 +327,12 @@ sub parse_input
|
||||
($y, $m, $d, $special, $tag, $duration, $time, $body) =
|
||||
($1, $2, $3, $4, $5, $6, $7, $8);
|
||||
} elsif (/\{/) {
|
||||
my $obj = decode_json($_);
|
||||
my $obj;
|
||||
if ($Options{utf8}) {
|
||||
$obj = decode_json(encode('UTF-8', $_, Encode::FB_DEFAULT));
|
||||
} else {
|
||||
$obj = decode_json($_);
|
||||
}
|
||||
next unless ($obj->{date} =~ /^(\d+)-(\d+)-(\d+)$/);
|
||||
$y = $1;
|
||||
$m = $2;
|
||||
|
||||
@@ -1280,7 +1280,7 @@ proc Status { stuff } {
|
||||
# None
|
||||
#---------------------------------------------------------------------------
|
||||
proc DoPrint {} {
|
||||
global Rem2PS Rem2PDF HaveRem2PDF PSCmd Option PrintStatus
|
||||
global Rem2PS Rem2PDF HaveRem2PDF PSCmd Option PrintStatus RemindErrors
|
||||
global CurMonth CurYear MonthNames
|
||||
|
||||
catch {destroy .p}
|
||||
@@ -1466,7 +1466,8 @@ proc DoPrint {} {
|
||||
append cmd " $fname"
|
||||
Status "Printing..."
|
||||
if {[catch {eval "exec $cmd"} err]} {
|
||||
tk_dialog .error Error "Error during printing: $err" error 0 Ok
|
||||
set RemindErrors [unique_lines $err]
|
||||
set_button_to_errors
|
||||
}
|
||||
DisplayTime
|
||||
}
|
||||
@@ -2702,9 +2703,14 @@ proc ShowQueue { file } {
|
||||
continue;
|
||||
}
|
||||
set obj [lsort -command sort_q $obj]
|
||||
set did 0
|
||||
foreach q $obj {
|
||||
$w.t insert end "$q\n"
|
||||
set did 1
|
||||
}
|
||||
if { $did == 0 } {
|
||||
$w.t insert end "(Queue is empty)\n"
|
||||
}
|
||||
}
|
||||
$w.t configure -state disabled
|
||||
}
|
||||
@@ -4048,13 +4054,17 @@ bind Balloon <Destroy> {
|
||||
catch { unset Balloon(helptext%W) }
|
||||
}
|
||||
|
||||
proc balloon_add_help { w txt } {
|
||||
proc balloon_set_help { w txt } {
|
||||
global Balloon
|
||||
if {"$txt" == ""} {
|
||||
catch { unset Balloon(helptext$w) }
|
||||
return
|
||||
}
|
||||
set Balloon(helptext$w) $txt
|
||||
}
|
||||
|
||||
proc balloon_add_help { w txt } {
|
||||
balloon_set_help $w $txt
|
||||
bindtags $w "Balloon [bindtags $w]"
|
||||
}
|
||||
|
||||
@@ -4206,9 +4216,11 @@ proc update_color_buttons { w } {
|
||||
}
|
||||
|
||||
proc set_button_to_queue {} {
|
||||
balloon_set_help .b.queue "See the queue of pending reminders (debugging purposes only)"
|
||||
.b.queue configure -text {Queue...} -command {DoQueue}
|
||||
}
|
||||
proc set_button_to_errors {} {
|
||||
balloon_set_help .b.queue "See the list of errors from the most recent operation"
|
||||
.b.queue configure -text {Errors...} -command {ShowErrors}
|
||||
}
|
||||
|
||||
|
||||
@@ -1218,7 +1218,7 @@ static void PrintLeft(char const *s, int width, char pad)
|
||||
if (!buf) {
|
||||
/* Uh-oh... cannot recover */
|
||||
fprintf(stderr, "%s\n", ErrMsg[E_NO_MEM]);
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
(void) mbstowcs(buf, s, len+1);
|
||||
@@ -1297,7 +1297,7 @@ static void PrintCentered(char const *s, int width, char *pad)
|
||||
if (!buf) {
|
||||
/* Uh-oh... cannot recover */
|
||||
fprintf(stderr, "%s\n", ErrMsg[E_NO_MEM]);
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
(void) mbstowcs(buf, s, len+1);
|
||||
@@ -1603,7 +1603,7 @@ static void GenerateCalEntries(int col)
|
||||
r=IncludeFile(InitialFile);
|
||||
if (r) {
|
||||
fprintf(ErrFp, "%s %s: %s\n", ErrMsg[E_ERR_READING], InitialFile, ErrMsg[r]);
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
while(1) {
|
||||
@@ -1611,7 +1611,7 @@ static void GenerateCalEntries(int col)
|
||||
if (r == E_EOF) return;
|
||||
if (r) {
|
||||
Eprint("%s: %s", ErrMsg[E_ERR_READING], ErrMsg[r]);
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
s = FindInitialToken(&tok, CurLine);
|
||||
|
||||
|
||||
16
src/dorem.c
16
src/dorem.c
@@ -1146,7 +1146,12 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int dse, int is_queue
|
||||
if (msg_command) {
|
||||
DoMsgCommand(msg_command, DBufValue(&buf));
|
||||
} else {
|
||||
printf("%s", DBufValue(&buf));
|
||||
/* Add a space before "NOTE endreminder" */
|
||||
if (Daemon < 0 && !strncmp(DBufValue(&buf), "NOTE endreminder", 16)) {
|
||||
printf(" %s", DBufValue(&buf));
|
||||
} else {
|
||||
printf("%s", DBufValue(&buf));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1194,7 +1199,7 @@ int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int dse, int *err)
|
||||
if (DontIssueAts > 1) {
|
||||
/* If two or more -a options, then *DO* issue ats that are in the
|
||||
future */
|
||||
if (tim->ttime < SystemTime(0) / 60) {
|
||||
if (tim->ttime < MinutesPastMidnight(0)) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
@@ -1202,13 +1207,6 @@ int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int dse, int *err)
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't trigger "old" timed reminders */
|
||||
/*** REMOVED...
|
||||
if (dse == DSEToday &&
|
||||
tim->ttime != NO_TIME &&
|
||||
tim->ttime < SystemTime(0) / 60) return 0;
|
||||
*** ...UNTIL HERE */
|
||||
|
||||
/* If "infinite delta" option is chosen, always trigger future reminders */
|
||||
if (InfiniteDelta || NextMode) return 1;
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse, int mode)
|
||||
{
|
||||
int diff = dse - DSEToday;
|
||||
int curtime = SystemTime(0) / 60;
|
||||
int curtime = MinutesPastMidnight(0);
|
||||
int err, done;
|
||||
int c;
|
||||
int d, m, y;
|
||||
@@ -894,7 +894,7 @@ int DoSubstFromString(char const *source, DynamicBuffer *dbuf,
|
||||
int r;
|
||||
|
||||
if (dse == NO_DATE) dse=DSEToday;
|
||||
if (tim == NO_TIME) tim=SystemTime(0)/60;
|
||||
if (tim == NO_TIME) tim=MinutesPastMidnight(0);
|
||||
CreateParser(source, &tempP);
|
||||
tempP.allownested = 0;
|
||||
tempTrig.typ = MSG_TYPE;
|
||||
|
||||
10
src/funcs.c
10
src/funcs.c
@@ -1421,28 +1421,28 @@ static int FRealtoday(func_info *info)
|
||||
static int FNow(func_info *info)
|
||||
{
|
||||
RetVal.type = TIME_TYPE;
|
||||
RETVAL = (int) ( SystemTime(0) / 60L );
|
||||
RETVAL = MinutesPastMidnight(0);
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int FRealnow(func_info *info)
|
||||
{
|
||||
RetVal.type = TIME_TYPE;
|
||||
RETVAL = (int) ( SystemTime(1) / 60L );
|
||||
RETVAL = MinutesPastMidnight(1);
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int FCurrent(func_info *info)
|
||||
{
|
||||
RetVal.type = DATETIME_TYPE;
|
||||
RETVAL = DSEToday * MINUTES_PER_DAY + (SystemTime(0) / 60);
|
||||
RETVAL = DSEToday * MINUTES_PER_DAY + MinutesPastMidnight(0);
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int FRealCurrent(func_info *info)
|
||||
{
|
||||
RetVal.type = DATETIME_TYPE;
|
||||
RETVAL = RealToday * MINUTES_PER_DAY + (SystemTime(1) / 60);
|
||||
RETVAL = RealToday * MINUTES_PER_DAY + MinutesPastMidnight(1);
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -2492,7 +2492,7 @@ static int FTimezone(func_info *info)
|
||||
|
||||
if (Nargs == 0) {
|
||||
dse = DSEToday;
|
||||
now = (SystemTime(0) / 60);
|
||||
now = MinutesPastMidnight(0);
|
||||
} else {
|
||||
if (!HASDATE(ARG(0))) return E_BAD_TYPE;
|
||||
dse = DATEPART(ARG(0));
|
||||
|
||||
@@ -50,6 +50,7 @@ EXTERN int LineNo;
|
||||
EXTERN int FreshLine;
|
||||
EXTERN uid_t TrustedUsers[MAX_TRUSTED_USERS];
|
||||
|
||||
EXTERN INIT( int MaxLateMinutes, 0);
|
||||
EXTERN INIT( int NumTrustedUsers, 0);
|
||||
EXTERN INIT( char const *MsgCommand, NULL);
|
||||
EXTERN INIT( char const *QueuedMsgCommand, NULL);
|
||||
|
||||
@@ -229,7 +229,7 @@ void InitRemind(int argc, char const *argv[])
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Invoked with a NULL argv[0]; bailing because that's just plain bizarre.\n");
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Parse the command-line options */
|
||||
@@ -765,7 +765,7 @@ void InitRemind(int argc, char const *argv[])
|
||||
|
||||
/* Figure out the offset from UTC */
|
||||
if (CalculateUTC)
|
||||
(void) CalcMinsFromUTC(DSEToday, SystemTime(0)/60,
|
||||
(void) CalcMinsFromUTC(DSEToday, MinutesPastMidnight(0),
|
||||
&MinsFromUTC, NULL);
|
||||
}
|
||||
|
||||
@@ -1002,7 +1002,7 @@ ProcessLongOption(char const *arg)
|
||||
{
|
||||
if (!strcmp(arg, "version")) {
|
||||
printf("%s\n", VERSION);
|
||||
exit(0);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
fprintf(ErrFp, "%s: Unknown long option --%s\n", ArgV[0], arg);
|
||||
}
|
||||
|
||||
31
src/main.c
31
src/main.c
@@ -181,14 +181,14 @@ static void DoReminders(void)
|
||||
|
||||
if (FileAccessDate < 0) {
|
||||
fprintf(ErrFp, "%s: `%s': %s.\n", ErrMsg[E_CANTACCESS], InitialFile, strerror(errno));
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
r=IncludeFile(InitialFile);
|
||||
if (r) {
|
||||
fprintf(ErrFp, "%s %s: %s\n", ErrMsg[E_ERR_READING],
|
||||
InitialFile, ErrMsg[r]);
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
while(1) {
|
||||
@@ -196,7 +196,7 @@ static void DoReminders(void)
|
||||
if (r == E_EOF) return;
|
||||
if (r) {
|
||||
Eprint("%s: %s", ErrMsg[E_ERR_READING], ErrMsg[r]);
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
s = FindInitialToken(&tok, CurLine);
|
||||
|
||||
@@ -749,17 +749,30 @@ int PushToken(char const *tok, ParsePtr p)
|
||||
/***************************************************************/
|
||||
long SystemTime(int realtime)
|
||||
{
|
||||
time_t tloc;
|
||||
time_t now;
|
||||
struct tm *t;
|
||||
|
||||
if (!realtime && (SysTime != -1L)) return SysTime;
|
||||
|
||||
(void) time(&tloc);
|
||||
t = localtime(&tloc);
|
||||
now = time(NULL);
|
||||
t = localtime(&now);
|
||||
return (long) t->tm_hour * 3600L + (long) t->tm_min * 60L +
|
||||
(long) t->tm_sec;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* MinutesPastMidnight */
|
||||
/* */
|
||||
/* Return the system time in minutes past midnight */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int MinutesPastMidnight(int realtime)
|
||||
{
|
||||
return (int) (SystemTime(realtime) / 60);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* SystemDate */
|
||||
@@ -771,11 +784,11 @@ long SystemTime(int realtime)
|
||||
/***************************************************************/
|
||||
int SystemDate(int *y, int *m, int *d)
|
||||
{
|
||||
time_t tloc;
|
||||
time_t now;
|
||||
struct tm *t;
|
||||
|
||||
(void) time(&tloc);
|
||||
t = localtime(&tloc);
|
||||
now = time(NULL);
|
||||
t = localtime(&now);
|
||||
|
||||
*d = t->tm_mday;
|
||||
*m = t->tm_mon;
|
||||
|
||||
@@ -72,6 +72,7 @@ void CreateParser (char const *s, ParsePtr p);
|
||||
void DestroyParser (ParsePtr p);
|
||||
int PushToken (char const *tok, ParsePtr p);
|
||||
long SystemTime (int realtime);
|
||||
int MinutesPastMidnight (int realtime);
|
||||
int SystemDate (int *y, int *m, int *d);
|
||||
int DoIf (ParsePtr p);
|
||||
int DoElse (ParsePtr p);
|
||||
|
||||
71
src/queue.c
71
src/queue.c
@@ -27,6 +27,7 @@
|
||||
#include <sys/select.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "globals.h"
|
||||
@@ -79,7 +80,7 @@ int QueueReminder(ParsePtr p, Trigger *trig,
|
||||
trig->noqueue ||
|
||||
tim->ttime == NO_TIME ||
|
||||
trig->typ == CAL_TYPE ||
|
||||
tim->ttime < SystemTime(0) / 60 ||
|
||||
tim->ttime < MinutesPastMidnight(0) ||
|
||||
((trig->typ == RUN_TYPE) && RunDisabled)) return OK;
|
||||
|
||||
qelem = NEW(QueuedRem);
|
||||
@@ -110,6 +111,36 @@ int QueueReminder(ParsePtr p, Trigger *trig,
|
||||
return OK;
|
||||
}
|
||||
|
||||
static void
|
||||
maybe_close(int fd)
|
||||
{
|
||||
int new_fd;
|
||||
/* Don't close descriptors connected to a TTY, except for stdin */
|
||||
if (fd && isatty(fd)) return;
|
||||
|
||||
(void) close(fd);
|
||||
if (fd != STDIN_FILENO) {
|
||||
new_fd = open("/dev/null", O_WRONLY);
|
||||
} else {
|
||||
new_fd = open("/dev/null", O_RDONLY);
|
||||
}
|
||||
|
||||
/* If the open failed... well... not much we can do */
|
||||
if (new_fd < 0) return;
|
||||
|
||||
/* If we got back the same fd as what we just closed, aces! */
|
||||
if (fd == new_fd) return;
|
||||
|
||||
(void) dup2(new_fd, fd);
|
||||
(void) close(new_fd);
|
||||
}
|
||||
|
||||
void
|
||||
SigContHandler(int d)
|
||||
{
|
||||
UNUSED(d);
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* HandleQueuedReminders */
|
||||
@@ -143,9 +174,10 @@ void HandleQueuedReminders(void)
|
||||
* processed correctly are RUN commands, provided they mail
|
||||
* the result back or use their own resource (as a window).
|
||||
*/
|
||||
if (!DontFork && (!isatty(1) || !isatty(2))) {
|
||||
close(1);
|
||||
close(2);
|
||||
if (!DontFork) {
|
||||
maybe_close(STDIN_FILENO);
|
||||
maybe_close(STDOUT_FILENO);
|
||||
maybe_close(STDERR_FILENO);
|
||||
}
|
||||
|
||||
/* If we're a daemon, get the mod time of initial file */
|
||||
@@ -160,7 +192,7 @@ void HandleQueuedReminders(void)
|
||||
/* Initialize the queue - initialize all the entries time of issue */
|
||||
|
||||
while (q) {
|
||||
q->tt.nexttime = (int) (SystemTime(1)/60 - 1);
|
||||
q->tt.nexttime = MinutesPastMidnight(1) - 1;
|
||||
q->tt.nexttime = CalculateNextTime(q);
|
||||
q = q->next;
|
||||
}
|
||||
@@ -169,6 +201,8 @@ void HandleQueuedReminders(void)
|
||||
sa.sa_handler = SigIntHandler;
|
||||
sa.sa_flags = 0;
|
||||
(void) sigaction(SIGINT, &sa, NULL);
|
||||
sa.sa_handler = SigContHandler;
|
||||
(void) sigaction(SIGCONT, &sa, NULL);
|
||||
}
|
||||
|
||||
/* Sit in a loop, issuing reminders when necessary */
|
||||
@@ -222,7 +256,7 @@ void HandleQueuedReminders(void)
|
||||
if (!Daemon) {
|
||||
int y, m, d;
|
||||
if (RealToday != SystemDate(&y, &m, &d)) {
|
||||
exit(0);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,10 +278,12 @@ void HandleQueuedReminders(void)
|
||||
/* Do NOT trigger the reminder if tt.nexttime is more than a
|
||||
minute in the past. This can happen if the clock is
|
||||
changed or a laptop awakes from hibernation.
|
||||
However, DO trigger if tt.nexttime == tt.ttime so all
|
||||
However, DO trigger if tt.nexttime == tt.ttime and we're
|
||||
within MaxLateTrigger minutes so all
|
||||
queued reminders are triggered at least once. */
|
||||
if ((SystemTime(1) - (q->tt.nexttime * 60) <= 60) ||
|
||||
(q->tt.nexttime == q->tt.ttime)) {
|
||||
(q->tt.nexttime == q->tt.ttime &&
|
||||
(MaxLateMinutes == 0 || SystemTime(1) - (q->tt.nexttime * 60) <= 60 * MaxLateMinutes))) {
|
||||
/* Trigger the reminder */
|
||||
CreateParser(q->text, &p);
|
||||
trig.typ = q->typ;
|
||||
@@ -256,7 +292,7 @@ void HandleQueuedReminders(void)
|
||||
if (Daemon < 0) {
|
||||
printf("NOTE reminder %s",
|
||||
SimpleTime(q->tt.ttime));
|
||||
printf("%s", SimpleTime(SystemTime(1)/60));
|
||||
printf("%s", SimpleTime(MinutesPastMidnight(1)));
|
||||
if (!*DBufValue(&q->tags)) {
|
||||
printf("*\n");
|
||||
} else {
|
||||
@@ -277,8 +313,17 @@ void HandleQueuedReminders(void)
|
||||
|
||||
/* Calculate the next trigger time */
|
||||
q->tt.nexttime = CalculateNextTime(q);
|
||||
|
||||
/* If trigger time is way in the past because computer has been
|
||||
suspended or hibernated, remove from queue */
|
||||
if (q->tt.nexttime != NO_TIME) {
|
||||
if (q->tt.ttime < MinutesPastMidnight(1) - MaxLateMinutes &&
|
||||
q->tt.nexttime < MinutesPastMidnight(1) - MaxLateMinutes) {
|
||||
q->tt.nexttime = NO_TIME;
|
||||
}
|
||||
}
|
||||
}
|
||||
exit(0);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
@@ -566,16 +611,16 @@ static void DaemonWait(struct timeval *sleep_tv)
|
||||
|
||||
/* If EOF on stdin, exit */
|
||||
if (feof(stdin)) {
|
||||
exit(0);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/* Read a line from stdin and interpret it */
|
||||
if (!fgets(cmdLine, sizeof(cmdLine), stdin)) {
|
||||
exit(0);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
if (!strcmp(cmdLine, "EXIT\n")) {
|
||||
exit(0);
|
||||
exit(EXIT_SUCCESS);
|
||||
} else if (!strcmp(cmdLine, "STATUS\n")) {
|
||||
int nqueued = 0;
|
||||
QueuedRem *q = QueueHead;
|
||||
|
||||
24
src/rem2ps.c
24
src/rem2ps.c
@@ -186,19 +186,19 @@ JSONToCalEntry(DynamicBuffer *buf)
|
||||
val = json_parse(DBufValue(buf), DBufLen(buf));
|
||||
if (!val) {
|
||||
fprintf(stderr, "Unable to parse JSON line `%s'\n", DBufValue(buf));
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (val->type != json_object) {
|
||||
fprintf(stderr, "Expecting JSON object; found `%s'\n",
|
||||
DBufValue(buf));
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
c = NEW(CalEntry);
|
||||
if (!c) {
|
||||
fprintf(stderr, "malloc failed - aborting.\n");
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
c->next = NULL;
|
||||
c->special = SPECIAL_NORMAL;
|
||||
@@ -221,7 +221,7 @@ JSONToCalEntry(DynamicBuffer *buf)
|
||||
c->entry = malloc(strlen(s)+1);
|
||||
if (!c->entry) {
|
||||
fprintf(stderr, "malloc failed - aborting.\n");
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
strcpy(c->entry, s);
|
||||
got_body = 1;
|
||||
@@ -253,7 +253,7 @@ JSONToCalEntry(DynamicBuffer *buf)
|
||||
|
||||
if (!got_body || !got_date) {
|
||||
fprintf(stderr, "Could not parse line `%s'\n", DBufValue(buf));
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
@@ -272,7 +272,7 @@ TextToCalEntry(DynamicBuffer *buf)
|
||||
CalEntry *c = NEW(CalEntry);
|
||||
if (!c) {
|
||||
fprintf(stderr, "malloc failed - aborting.\n");
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
c->next = NULL;
|
||||
c->special = SPECIAL_NORMAL;
|
||||
@@ -296,7 +296,7 @@ TextToCalEntry(DynamicBuffer *buf)
|
||||
c->entry = malloc(strlen(startOfBody) + 1);
|
||||
if (!c->entry) {
|
||||
fprintf(stderr, "malloc failed - aborting.\n");
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
strcpy(c->entry, startOfBody);
|
||||
|
||||
@@ -343,7 +343,7 @@ int main(int argc, char *argv[])
|
||||
DBufGets(&buf, stdin);
|
||||
if (first_line && (!strcmp(DBufValue(&buf), "["))) {
|
||||
fprintf(stderr, "Rem2PS: It appears that you have invoked Remind with the -ppp option.\n Please use either -p or -pp, but not -ppp.\n");
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
first_line = 0;
|
||||
if (!strcmp(DBufValue(&buf), PSBEGIN) ||
|
||||
@@ -361,7 +361,7 @@ int main(int argc, char *argv[])
|
||||
if (!validfile) {
|
||||
fprintf(stderr, "Rem2PS: Couldn't find any calendar data - are you\n");
|
||||
fprintf(stderr, " sure you fed me input produced by remind -p ...?\n");
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
printf("%%%%Trailer\n");
|
||||
printf("%%%%Pages: %d\n", validfile);
|
||||
@@ -486,7 +486,7 @@ void DoPsCal(void)
|
||||
while(1) {
|
||||
if (feof(stdin)) {
|
||||
fprintf(stderr, "Input from REMIND is corrupt!\n");
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
DBufGets(&buf, stdin);
|
||||
@@ -952,7 +952,7 @@ void Init(int argc, char *argv[])
|
||||
fprintf(stderr, " WxHin Specify size in inches (W and H are decimal numbers)\n");
|
||||
fprintf(stderr, " WxHcm Specify size in centimetres (W and H are decimal numbers)\n");
|
||||
fprintf(stderr, "Default media type is %s\n", DefaultPage[0].name);
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1033,7 +1033,7 @@ void Usage(char const *s)
|
||||
fprintf(stderr, "-e Make calendar fill entire page\n");
|
||||
fprintf(stderr, "-x Put day numbers on left instead of right\n");
|
||||
fprintf(stderr, "-o[lrtb] marg Specify left, right, top and bottom margins\n");
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
@@ -825,6 +825,7 @@ static SysVar SysVarArr[] = {
|
||||
{"LongMin", 1, SPECIAL_TYPE, longmin_func, 0, 0 },
|
||||
{"LongSec", 1, SPECIAL_TYPE, longsec_func, 0, 0 },
|
||||
{"March", 1, STR_TYPE, &DynamicMonthName[2], 0, 0 },
|
||||
{"MaxLateMinutes", 1, INT_TYPE, &MaxLateMinutes, 0, 1440 },
|
||||
{"MaxSatIter", 1, INT_TYPE, &MaxSatIter, 10, ANY },
|
||||
{"MaxStringLen", 1, INT_TYPE, &MaxStringLen, -1, ANY },
|
||||
{"May", 1, STR_TYPE, &DynamicMonthName[4], 0, 0 },
|
||||
|
||||
@@ -1060,7 +1060,7 @@ set a057 value("a05"+"6")
|
||||
"a05" + "6" => "a056"
|
||||
value("a056") => "SDFJHSDF KSJDFH KJSDFH KSJDFH"
|
||||
set a058 version()
|
||||
version() => "04.02.07"
|
||||
version() => "04.02.08"
|
||||
set a059 wkday(today())
|
||||
today() => 1991-02-16
|
||||
wkday(1991-02-16) => "Saturday"
|
||||
@@ -2644,7 +2644,7 @@ a086 4
|
||||
a109 2012-01-01
|
||||
a128 2018-02-03@16:45
|
||||
a039 "February"
|
||||
a058 "04.02.07"
|
||||
a058 "04.02.08"
|
||||
a077 "1992 92\n"
|
||||
a096 -4
|
||||
a119 -1
|
||||
@@ -2789,6 +2789,7 @@ Variable Value
|
||||
$LongMin 15
|
||||
$LongSec 0
|
||||
$March "March"
|
||||
$MaxLateMinutes 0 [0, 1440]
|
||||
$MaxSatIter 150 [10, Inf)
|
||||
$MaxStringLen 65535 [-1, Inf)
|
||||
$May "May"
|
||||
@@ -11695,4 +11696,4 @@ Can't open file: include_dir/ww
|
||||
Error reading include_dir/ww: Can't open file
|
||||
SECURITY: Won't read world-writable file or directory!
|
||||
Error reading include_dir/ww: No files matching *.rem
|
||||
04.02.07
|
||||
04.02.08
|
||||
|
||||
Reference in New Issue
Block a user