-- Added "-z0" option to Remind for "daemonized" control by Tk front-end.

This commit is contained in:
dfs
1998-03-02 19:38:33 +00:00
parent c1e4e42763
commit 67aab59d19
3 changed files with 293 additions and 26 deletions

View File

@@ -11,7 +11,7 @@
#
#--------------------------------------------------------------
# $Id: tkremind,v 1.4 1998-03-01 20:43:23 dfs Exp $
# $Id: tkremind,v 1.5 1998-03-02 19:38:33 dfs Exp $
# the next line restarts using wish \
exec wish "$0" "$@"
@@ -25,6 +25,7 @@ set ConfirmQuit 0
# Remind program to execute -- supply full path if you want
set Remind "remind"
#set Remind "/home/dfs/Remind/src/remind"
# Rem2PS program to execute -- supply full path if you want
set Rem2PS "rem2ps"
@@ -52,6 +53,9 @@ set EnglishDayNames {Sunday Monday Tuesday Wednesday Thursday Friday Saturday}
set CurMonth -1
set CurYear -1
# Background reminder counter
set BgCounter 0
# Absolutely today -- unlike the CurMonth and CurYear, these won't change
set TodayMonth -1
set TodayYear -1
@@ -192,7 +196,7 @@ proc ColumnNumber { firstDay mondayFirst day } {
# dayNames -- names of weekdays in current language {Sun .. Sat}
#---------------------------------------------------------------------------
proc CreateCalWindow { firstDay mondayFirst daysInMonth month year dayNames } {
global CurMonth CurYear TodayMonth TodayYear TodayDay
global CurMonth CurYear TodayMonth TodayYear TodayDay DaemonFile
catch { destroy .h }
catch { destroy .b }
@@ -239,13 +243,19 @@ proc CreateCalWindow { firstDay mondayFirst daysInMonth month year dayNames } {
button .b.goto -text {Go To Date...} -command {GotoDialog}
button .b.print -text {Print...} -command {DoPrint}
button .b.quit -text {Quit} -command {Quit}
label .b.status -text "" -width 10 -relief sunken
label .b.status -text "" -width 25 -relief sunken
label .b.nqueued -text "" -width 20 -relief sunken
pack .b.prev .b.this .b.next .b.goto .b.print .b.quit -side left -fill x
pack .b.status -side left -fill x -expand 1
pack .b.nqueued -side left -fill x
pack .h -side top -expand 1 -fill both
pack .b -side top -fill x -expand 0
wm title . "TkRemind - $month $year"
wm iconname . "$month $year"
catch {
puts $DaemonFile "STATUS"
flush $DaemonFile
}
}
#---------------------------------------------------------------------------
@@ -860,6 +870,7 @@ proc ModifyDay {d firstDay} {
puts $f ""
close $f
FillCalWindow
RestartBackgroundRemindDaemon
return 0
}
}
@@ -1373,6 +1384,140 @@ proc BrowseForFileRead {w {dir ""}} {
$w.entry delete 0 end
}
#---------------------------------------------------------------------------
# StartBackgroundRemindDaemon
# Arguments:
# none
# Returns:
# nothing
# Description:
# Starts a background Remind daemon to handle timed reminders
#---------------------------------------------------------------------------
proc StartBackgroundRemindDaemon {} {
global Remind DaemonFile ReminderFile
set problem [catch { set DaemonFile [open "|$Remind -z0 $ReminderFile" "r+"] } err]
if {$problem} {
tk_dialog .error Error "Can't start Remind daemon in background: $err" error 0 OK
} else {
fileevent $DaemonFile readable "DaemonReadable $DaemonFile"
puts $DaemonFile "STATUS"
flush $DaemonFile
}
}
#---------------------------------------------------------------------------
# StopBackgroundRemindDaemon
# Arguments:
# none
# Returns:
# nothing
# Description:
# Stops the background Remind daemon
#---------------------------------------------------------------------------
proc StopBackgroundRemindDaemon {} {
global DaemonFile
catch {
puts $DaemonFile "EXIT"
flush $DaemonFile
close $DaemonFile
}
}
#---------------------------------------------------------------------------
# RestartBackgroundRemindDaemon
# Arguments:
# none
# Returns:
# nothing
# Description:
# Restarts the background Remind daemon
#---------------------------------------------------------------------------
proc RestartBackgroundRemindDaemon {} {
global DaemonFile
catch {
puts $DaemonFile "REREAD"
flush $DaemonFile
}
}
#---------------------------------------------------------------------------
# DaemonReadable
# Arguments:
# file -- file channel that is readable
# Returns:
# nothing
# Description:
# Reads data from the Remind daemon and handles it appropriately
#---------------------------------------------------------------------------
proc DaemonReadable { file } {
set line ""
catch { set line [gets $file] }
switch -glob $line {
"NOTE reminder*" {
scan $line "NOTE reminder %s %s" time now
IssueBackgroundReminder $file $time $now
}
"NOTE reread" {
puts $file "STATUS"
flush $file
}
"NOTE queued*" {
scan $line "NOTE queued %d" n
if {$n == 1} {
.b.nqueued configure -text "1 reminder queued"
} else {
.b.nqueued configure -text "$n reminders queued"
}
}
default {
puts "Unknown message from daemon: $line\n"
}
}
}
#---------------------------------------------------------------------------
# IssueBackgroundReminder
# Arguments:
# file -- file channel that is readable
# time -- time of reminder
# now -- current time according to Remind daemon
# Returns:
# nothing
# Description:
# Reads a background reminder from daemon and pops up window.
#---------------------------------------------------------------------------
proc IssueBackgroundReminder { file time now } {
global BgCounter
set msg ""
set line ""
while (1) {
gets $file line
if {$line == "NOTE endreminder"} {
break
}
if {$msg != ""} {
append msg "\n";
}
append msg $line
}
incr BgCounter
set w .bg$BgCounter
toplevel $w
wm iconname $w "Reminder"
wm title $w "Timed reminder ($time)"
label $w.l -text "Reminder for $time issued at $now"
message $w.msg -width 6i -text $msg
button $w.ok -text "OK" -command "destroy $w"
pack $w.l -side top
pack $w.msg -side top -expand 1 -fill both
pack $w.ok -side top
CenterWindow $w
# reread status
puts $file "STATUS"
flush $file
}
proc main {} {
wm withdraw .
puts "\nTkRemind Copyright (c) 1996-1998 by David F. Skoll\n"
@@ -1389,12 +1534,7 @@ proc main {} {
wm geometry . ${x}x600
update
}
proc t {} {
catch { destroy .foo }
toplevel .foo
CreateModifyDialog .foo 20 1
StartBackgroundRemindDaemon
}
main

View File

@@ -12,7 +12,7 @@
/***************************************************************/
#include "config.h"
static char const RCSID[] = "$Id: init.c,v 1.7 1998-03-01 20:43:56 dfs Exp $";
static char const RCSID[] = "$Id: init.c,v 1.8 1998-03-02 19:38:40 dfs Exp $";
#define L_IN_INIT 1
#include <stdio.h>
@@ -258,9 +258,16 @@ char *argv[];
case 'z':
case 'Z':
DontFork = 1;
PARSENUM(Daemon, arg);
if (Daemon<5) Daemon=5;
else if (Daemon>60) Daemon=60;
if (*arg == '0') {
PARSENUM(Daemon, arg);
if (Daemon == 0) Daemon = -1;
else if (Daemon < 5) Daemon = 5;
else if (Daemon > 60) Daemon = 60;
} else {
PARSENUM(Daemon, arg);
if (Daemon<5) Daemon=5;
else if (Daemon>60) Daemon=60;
}
break;
case 'a':

View File

@@ -10,7 +10,7 @@
/***************************************************************/
#include "config.h"
static char const RCSID[] = "$Id: queue.c,v 1.4 1998-02-10 03:15:54 dfs Exp $";
static char const RCSID[] = "$Id: queue.c,v 1.5 1998-03-02 19:38:40 dfs Exp $";
/* We only want object code generated if we have queued reminders */
#ifdef HAVE_QUEUED
@@ -20,6 +20,10 @@ static char const RCSID[] = "$Id: queue.c,v 1.4 1998-02-10 03:15:54 dfs Exp $";
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
@@ -67,6 +71,8 @@ PRIVATE void CheckInitialFile ARGS ((void));
PRIVATE int CalculateNextTime ARGS ((QueuedRem *q));
PRIVATE QueuedRem *FindNextReminder ARGS ((void));
PRIVATE int CalculateNextTimeUsingSched ARGS ((QueuedRem *q));
PRIVATE void DaemonWait ARGS ((unsigned int sleeptime));
PRIVATE void reread ARGS((void));
/***************************************************************/
/* */
@@ -154,7 +160,7 @@ void HandleQueuedReminders()
}
/* If we're a daemon, get the mod time of initial file */
if (Daemon) {
if (Daemon > 0) {
if (stat(InitialFile, &StatBuf)) {
fprintf(ErrFp, "Cannot stat %s - not running as daemon!\n",
InitialFile);
@@ -183,35 +189,60 @@ void HandleQueuedReminders()
/* If no more reminders to issue, we're done unless we're a daemon. */
if (!q && !Daemon) break;
if (Daemon && !q)
TimeToSleep = (long) 60*Daemon;
else
if (Daemon && !q) {
if (Daemon < 0) {
/* Sleep until midnight */
TimeToSleep = (long) 1440*60L - SystemTime(0);
} else {
TimeToSleep = (long) 60*Daemon;
}
} else {
TimeToSleep = (long) q->tt.nexttime * 60L - SystemTime(0);
}
while (TimeToSleep > 0L) {
SleepTime = (unsigned) ((TimeToSleep > 30000L) ? 30000 : TimeToSleep);
if (Daemon && SleepTime > 60*Daemon) SleepTime = 60*Daemon;
if (Daemon > 0 && SleepTime > 60*Daemon) SleepTime = 60*Daemon;
sleep(SleepTime);
if (Daemon >= 0) {
sleep(SleepTime);
} else {
DaemonWait(SleepTime);
}
if (Daemon && SleepTime) CheckInitialFile();
if (Daemon> 0 && SleepTime) CheckInitialFile();
if (Daemon && !q)
TimeToSleep = (long) 60*Daemon;
else
if (Daemon && !q) {
if (Daemon < 0) {
/* Sleep until midnight */
TimeToSleep = (long) 1440*60L - SystemTime(0);
} else {
TimeToSleep = (long) 60*Daemon;
}
} else {
TimeToSleep = (long) q->tt.nexttime * 60L - SystemTime(0);
}
}
/* Trigger the reminder */
CreateParser(q->text, &p);
trig.typ = q->typ;
RunDisabled = q->RunDisabled;
if (Daemon < 0) {
printf("NOTE reminder %s ",
SimpleTime(q->tt.ttime));
printf("%s\n", SimpleTime(SystemTime(0)/60));
}
#ifdef OS2_POPUP
(void) TriggerReminder(&p, &trig, &q->tt, JulianToday, 1);
#else
(void) TriggerReminder(&p, &trig, &q->tt, JulianToday);
#endif
if (Daemon < 0) {
printf("NOTE endreminder\n");
}
fflush(stdout);
/* Calculate the next trigger time */
@@ -349,8 +380,9 @@ static void CheckInitialFile()
if (stat(InitialFile, &StatBuf) == 0) tim = StatBuf.st_mtime;
if (tim != FileModTime ||
RealToday != SystemDate(&y, &m, &d))
execvp(ArgV[0], ArgV);
RealToday != SystemDate(&y, &m, &d)) {
reread();
}
}
/***************************************************************/
@@ -415,4 +447,92 @@ QueuedRem *q;
}
}
/***************************************************************/
/* */
/* DaemonWait */
/* */
/* Sleep or read command from stdin in "daemon -1" mode */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE void DaemonWait(unsigned int sleeptime)
#else
static DaemonWait(sleeptime)
unsigned int sleeptime
#endif
{
fd_set readSet;
struct timeval timeout;
int retval;
int y, m, d;
char cmdLine[256];
FD_ZERO(&readSet);
FD_SET(0, &readSet);
timeout.tv_sec = sleeptime;
timeout.tv_usec = 0;
retval = select(1, &readSet, NULL, NULL, &timeout);
/* If date has rolled around, restart */
if (RealToday != SystemDate(&y, &m, &d)) {
printf("NOTE reread\n");
fflush(stdout);
reread();
}
/* If nothing readable or interrupted system call, return */
if (retval <= 0) return;
/* If stdin not readable, return */
if (!FD_ISSET(0, &readSet)) return;
/* If EOF on stdin, exit */
if (feof(stdin)) {
exit(0);
}
/* Read a line from stdin and interpret it */
if (!fgets(cmdLine, sizeof(cmdLine), stdin)) {
exit(0);
}
if (!strcmp(cmdLine, "EXIT\n")) {
exit(0);
} else if (!strcmp(cmdLine, "STATUS\n")) {
int nqueued = 0;
QueuedRem *q = QueueHead;
while(q) {
if (q->tt.nexttime != NO_TIME) {
nqueued++;
}
q = q->next;
}
printf("NOTE queued %d\n", nqueued);
fflush(stdout);
} else if (!strcmp(cmdLine, "REREAD\n")) {
printf("NOTE reread\n");
fflush(stdout);
reread();
} else {
printf("ERR Invalid daemon command: %s", cmdLine);
fflush(stdout);
}
}
/***************************************************************/
/* */
/* reread */
/* */
/* Restarts Remind if date rolls over or REREAD cmd received */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE void reread(void)
#else
static reread()
#endif
{
execvp(ArgV[0], ArgV);
}
#endif /* HAVE_QUEUED from way at the top */