home *** CD-ROM | disk | FTP | other *** search
- From: dfs@doe.carleton.ca (David F. Skoll)
- Newsgroups: alt.sources
- Subject: REMIND 2.3.0 3/4
- Message-ID: <dfs.666901128@data>
- Date: 18 Feb 91 18:18:48 GMT
-
- #!/bin/sh
- # This is part 03 of Remind 2.3.0
- if touch 2>&1 | fgrep 'amc' > /dev/null
- then TOUCH=touch
- else TOUCH=true
- fi
- # ============= omits.c ==============
- if test X"$1" != X"-c" -a -f 'omits.c'; then
- echo "File already exists: skipping 'omits.c'"
- else
- echo "x - extracting omits.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > omits.c &&
- X/***************************************************************/
- X/* */
- X/* OMITS.C */
- X/* */
- X/* By David Skoll - 12 February 1991 */
- X/* */
- X/* Handle all code related to global OMITs */
- X/* */
- X/***************************************************************/
- X#include <stdio.h>
- X#ifndef UNIX
- X#include <stdlib.h>
- X#endif
- X
- X#ifndef NO_MALLOC_H
- X#include <malloc.h>
- X#endif
- X
- X#include "defines.h"
- X#include "protos.h"
- X#include "globals.h"
- X
- X/* Define an OMIT stack buffer */
- Xtypedef struct omit_stack {
- X struct omit_stack *next;
- X int NumFullOmit;
- X int NumPartOmit;
- X int Omits[1];
- X} OmitBuffer;
- X
- X/* Variables that we only want visible here */
- Xstatic OmitBuffer *OmitStack = (OmitBuffer *) NULL;
- X
- X/***************************************************************/
- X/* */
- X/* int DoGlobalOmit(char **s) */
- X/* */
- X/* Add an entry to the global ommissions array. Either */
- X/* a fully-specified date, or a mm-yy type date. */
- X/* Return 0 if OK, -1 if date is in past, -2 if problem. */
- X/* */
- X/***************************************************************/
- X#ifdef __STDC__
- Xint DoGlobalOmit(char **s)
- X#else
- Xint DoGlobalOmit(s)
- X char **s;
- X#endif
- X{
- X int d = -1, m = -1, y = -1;
- X int omit;
- X int *ptr;
- X Token tok;
- X char *olds = *s;
- X
- X tok.type = Unknown_t;
- X while(tok.type != Eol_t && tok.type != Run_t && tok.type != Msg_t) {
- X tok = ParseToken(s);
- X switch (tok.type) {
- X case Year_t: y = tok.val; break;
- X case Month_t: m = tok.val; break;
- X case Day_t: d = tok.val; break;
- X
- X case Delta_t:
- X case Eol_t:
- X case Msg_t:
- X case Run_t: break;
- X default: Eprint("Invalid token '%s' for OMIT command.\n", tok.str);
- X return -2;
- X }
- X }
- X
- X if (d == -1 || m == -1 || CheckDate(d, m, y)) {
- X Eprint("Invalid date specification.\n");
- X return -2;
- X }
- X
- X if (y == -1) { /* Only mm-dd specified */
- X if (NumPartOmit == POMITSIZE) {
- X Eprint("Too many partially-specified OMITs.\n");
- X return -2;
- X }
- X omit = (m << 5) + d;
- X ptr = PartOmitArray + NumPartOmit;
- X NumPartOmit++;
- X while (ptr > PartOmitArray && *(ptr-1) > omit) {
- X *ptr = *(ptr-1);
- X ptr--;
- X }
- X *ptr = omit;
- X
- X /* Check if the bonehead already has it - if so, delete it */
- X if (ptr > PartOmitArray && *(ptr-1) == *ptr) {
- X if (Debug) Eprint("Duplicated partially-specified OMIT.\n");
- X NumPartOmit--;
- X while (ptr < NumPartOmit+PartOmitArray) {
- X *ptr = *(ptr + 1);
- X ptr++;
- X }
- X }
- X /* If we got a DELTA, a MSG or a RUN, then execute DoRem */
- X if (tok.type == Delta_t || tok.type == Run_t || tok.type == Msg_t)
- X return DoRem(&olds);
- X } else { /* All three specified */
- X if (NumFullOmit == FOMITSIZE) {
- X Eprint("Too many fully-specified OMITs.\n");
- X return -2;
- X }
- X omit = Julian(d, m, y);
- X
- X ptr = FullOmitArray + NumFullOmit;
- X NumFullOmit++;
- X while (ptr > FullOmitArray && *(ptr-1) > omit) {
- X *ptr = *(ptr-1);
- X ptr--;
- X }
- X *ptr = omit;
- X
- X /* Check if the bonehead already has it - if so, delete it */
- X if (ptr > FullOmitArray && *(ptr-1) == *ptr) {
- X if (Debug) Eprint("Duplicated fully-specified OMIT.\n");
- X NumFullOmit--;
- X while (ptr < NumFullOmit+FullOmitArray) {
- X *ptr = *(ptr + 1);
- X ptr++;
- X }
- X }
- X if (omit < JulianToday) {
- X if (Debug) Eprint("Omit has expired.\n");
- X return -1;
- X }
- X /* If we got a DELTA, a MSG or a RUN, then execute DoRem */
- X if (tok.type == Delta_t || tok.type == Run_t || tok.type == Msg_t)
- X return DoRem(&olds);
- X }
- X return 0;
- X}
- X
- X/***************************************************************/
- X/* */
- X/* PushOmitContext */
- X/* */
- X/* Push the Global OMIT context onto a stack. */
- X/* */
- X/* Returns 0 for success, 1 for failure. */
- X/* */
- X/***************************************************************/
- X#ifdef __STDC__
- Xint PushOmitContext(void)
- X#else
- Xint PushOmitContext()
- X#endif
- X{
- X OmitBuffer *new = (OmitBuffer *) malloc( sizeof(OmitBuffer) +
- X (NumFullOmit + NumPartOmit - 1) * sizeof(int));
- X
- X if (!new) {
- X Eprint("Unable to allocate memory for PUSH-OMIT-CONTEXT.\n");
- X return 1;
- X }
- X
- X new->NumFullOmit = NumFullOmit;
- X new->NumPartOmit = NumPartOmit;
- X
- X CopyInts(FullOmitArray, &(new->Omits[0]), NumFullOmit);
- X CopyInts(PartOmitArray, &(new->Omits[NumFullOmit]), NumPartOmit);
- X
- X new->next = OmitStack;
- X OmitStack = new;
- X
- X return 0;
- X}
- X
- X/***************************************************************/
- X/* */
- X/* PopOmitContext */
- X/* */
- X/* Restore the OMIT context from the stack. */
- X/* */
- X/* Returns 0 for success, 1 for failure. */
- X/* */
- X/***************************************************************/
- X#ifdef __STDC__
- Xint PopOmitContext(void)
- X#else
- Xint PopOmitContext()
- X#endif
- X{
- X
- X OmitBuffer *temp;
- X
- X if (!OmitStack) {
- X Eprint("No saved contexts for POP-OMIT-CONTEXT.\n");
- X return 1;
- X }
- X
- X NumFullOmit = OmitStack->NumFullOmit;
- X NumPartOmit = OmitStack->NumPartOmit;
- X
- X CopyInts(&(OmitStack->Omits[0]), FullOmitArray, NumFullOmit);
- X CopyInts(&(OmitStack->Omits[NumFullOmit]), PartOmitArray, NumPartOmit);
- X
- X temp = OmitStack->next;
- X free(OmitStack);
- X OmitStack = temp;
- X return 0;
- X}
- X
- X/***************************************************************/
- X/* */
- X/* ClearOmitContext */
- X/* */
- X/* Get rid of all global OMITS. */
- X/* */
- X/***************************************************************/
- X#ifdef __STDC__
- Xvoid ClearOmitContext(void)
- X#else
- Xvoid ClearOmitContext()
- X#endif
- X{
- X NumFullOmit = NumPartOmit = 0;
- X}
- X
- X/***************************************************************/
- X/* */
- X/* CopyInts */
- X/* */
- X/* Copy integer values from one array to another. */
- X/* */
- X/***************************************************************/
- X#ifdef __STDC__
- Xvoid CopyInts(int *from, int *to, int count)
- X#else
- Xvoid CopyInts(from, to, count)
- Xint *from, *to, count;
- X#endif
- X{
- X while (count--) *to++ = *from++;
- X}
- X
- X/***************************************************************/
- X/* */
- X/* FreeStackedOmits */
- X/* */
- X/* Get rid of all the stacked OMIT contexts */
- X/* */
- X/***************************************************************/
- X#ifdef __STDC__
- Xvoid FreeStackedOmits(void)
- X#else
- Xvoid FreeStackedOmits()
- X#endif
- X{
- X OmitBuffer *current = OmitStack, *next;
- X
- X if (current && Debug) Eprint("Warning - more PUSH-OMIT-CONTEXTs than POP-OMIT-CONTEXTs\n");
- X
- X while (current) {
- X next = current->next;
- X free(current);
- X current = next;
- X }
- X
- X OmitStack = (OmitBuffer *) NULL;
- X}
- X
- X/***************************************************************/
- X/* */
- X/* IsOmitted */
- X/* */
- X/* Returns non-zero if the julian date should be omitted, 0 */
- X/* otherwise. */
- X/* */
- X/***************************************************************/
- X#ifdef __STDC__
- Xint IsOmitted(int jul, int localomit)
- X#else
- Xint IsOmitted(jul, localomit)
- Xint jul, localomit;
- X#endif
- X{
- X int d, m, y;
- X
- X /* Check if we should omit because of local omit */
- X if (localomit & 1 << (jul % 7)) return 1;
- X
- X /* Check if we should omit because of fully-specified global omit */
- X if (NumFullOmit && my_bsearch(jul, FullOmitArray, NumFullOmit)) return 1;
- X
- X /* Check if we should omit because of partially-specified global omits */
- X if (NumPartOmit) {
- X FromJulian(jul, &d, &m, &y);
- X if (my_bsearch((m << 5)+d, PartOmitArray, NumPartOmit)) return 1;
- X }
- X
- X /* Looks cool - don't omit */
- X return 0;
- X}
- X
- X/***************************************************************/
- X/* */
- X/* my_bsearch */
- X/* */
- X/* A simplified version of bsearch() for people whose library */
- X/* does not have the full version. This only works when */
- X/* searching a sorted array of integers. */
- X/* */
- X/***************************************************************/
- X#ifdef __STDC__
- Xint *my_bsearch(int key, int *array, int number)
- X#else
- Xint *my_bsearch(key, array, number)
- Xint key, *array, number;
- X#endif
- X{
- X int top = number - 1;
- X int bot = 0;
- X int mid;
- X
- X while (top >= bot) {
- X mid = (top+bot)/2;
- X if (*(array+mid) == key) return array+mid;
- X else if (*(array+mid) > key) top = mid-1;
- X else bot = mid+1;
- X }
- X
- X /* Oh, well - unsuccessful search. Return NULL */
- X return NULL;
- X}
- SHAR_EOF
- $TOUCH -am 0218130591 omits.c &&
- chmod 0600 omits.c ||
- echo "restore of omits.c failed"
- set `wc -c omits.c`;Wc_c=$1
- if test "$Wc_c" != "10630"; then
- echo original size 10630, current size $Wc_c
- fi
- fi
- # ============= protos.h ==============
- if test X"$1" != X"-c" -a -f 'protos.h'; then
- echo "File already exists: skipping 'protos.h'"
- else
- echo "x - extracting protos.h (Text)"
- sed 's/^X//' << 'SHAR_EOF' > protos.h &&
- X
- X/* Function Prototypes go here */
- X
- X#ifdef __STDC__
- Xint CheckDate (int d, int m, int y);
- Xvoid ClearOmitContext(void);
- Xvoid CopyInts (int *from, int *to, int count);
- Xint DoBanner (char **s);
- Xvoid DoCalendar (void);
- Xint DoGlobalOmit(char **s);
- Xvoid DoInclude (char **s);
- Xint DoRem (char **s);
- Xint DoSubst (char *src, char *dst, int d, int m, int y, int jul, enum Token_t t, int tim, int mode);
- Xint FindTodaysDate(int *d, int *m, int *y);
- Xvoid FreeStackedOmits (void);
- Xint FromJulian (int jul, int *d, int *m, int *y);
- Xint GetTriggerDate (int d, int m, int y, int wd, int cons, int back, int repeat, int omit, int skip);
- Xint IsOmitted (int jul, int localomit);
- Xvoid HandleQueuedAts(void);
- Xvoid initialize (int argc, char *argv[]);
- Xint int_comp (int *, int *);
- Xint Julian (int d, int m, int y);
- Xint MoveBack (int jul, int back, int omit);
- Xint *my_bsearch (int key, int *array, int number);
- Xvoid OpenFile (char *s);
- Xvoid Output (char *s);
- XToken ParseToken (char **s);
- Xint PopOmitContext (void);
- Xint PushOmitContext (void);
- Xint ProcessLine (void);
- Xint ReadLine (void);
- Xvoid SigIntHandler (void);
- Xlong SystemTime (void);
- Xint TopLevel (void);
- Xint TryNextDate(int *retday, int *retmon, int *retyr,
- X int startday, int startmon, int startyr,
- X int conday, int conmon, int conyr,
- X int wkday, int cons, int inc);
- X#else
- Xint CheckDate ();
- Xvoid ClearOmitContext();
- Xvoid CopyInts ();
- Xint DoBanner ();
- Xvoid DoCalendar ();
- Xint DoGlobalOmit();
- Xvoid DoInclude ();
- Xint DoRem ();
- Xint DoSubst ();
- Xint FindTodaysDate();
- Xvoid FreeStackedOmits();
- Xint FromJulian ();
- Xint GetTriggerDate();
- Xint IsOmitted ();
- Xvoid HandleQueuedAts();
- Xvoid initialize ();
- Xint int_comp ();
- Xint Julian ();
- Xint MoveBack ();
- Xint *my_bsearch ();
- Xvoid OpenFile ();
- Xvoid Output ();
- XToken ParseToken ();
- Xint PopOmitContext ();
- Xint ProcessLine ();
- Xint PushOmitContext ();
- Xint ReadLine ();
- Xvoid SigIntHandler();
- Xlong SystemTime ();
- Xint TopLevel ();
- Xint TryNextDate ();
- X#endif
- X
- X#ifndef UNIX
- Xvoid Eprint(const char *f, ...);
- X#else
- Xvoid Eprint();
- X#endif
- SHAR_EOF
- $TOUCH -am 0218130591 protos.h &&
- chmod 0600 protos.h ||
- echo "restore of protos.h failed"
- set `wc -c protos.h`;Wc_c=$1
- if test "$Wc_c" != "2210"; then
- echo original size 2210, current size $Wc_c
- fi
- fi
- # ============= remind-all.csh ==============
- if test X"$1" != X"-c" -a -f 'remind-all.csh'; then
- echo "File already exists: skipping 'remind-all.csh'"
- else
- echo "x - extracting remind-all.csh (Text)"
- sed 's/^X//' << 'SHAR_EOF' > remind-all.csh &&
- X#!/bin/csh -f
- X
- X# Shell script to mail all users reminders.
- X
- X# Run it AFTER MIDNIGHT so that date is correct!
- X# On our system, we have the following in our crontab:
- X# 05 5 * * * /usr/share/lib/remind/remind-all > /dev/null 2>&1
- X
- X# Also, you MUST use the -r and -q options on REMIND, otherwise SEVERE
- X# security hole could develop. I recommend making this script
- X# readable and executable only by root to minimize security problems.
- X# DO NOT make the script setuid!
- X
- X# The following line gets a list of users for systems using SUN's
- X# NIS service:
- Xset USERS = `ypcat passwd | awk -F: '{print $1}'`
- X
- X# The following line gets a list of users by examining /etc/passwd:
- X# set USERS = `awk -F: '{print $1}' /etc/passwd`
- X
- X# If neither of the above methods works, you must come up with some
- X# way of getting a list of users on the system
- X
- X# Set the following variables as appropriate for your system
- Xset REMIND = /usr/local/bin/remind
- Xset MAIL = /usr/ucb/mail
- Xset CMP = /usr/bin/cmp
- Xset RM = "/usr/bin/rm -f"
- X
- Xset EMPTY = /tmp/Empty.$$
- Xset FULL = /tmp/Full.$$
- X
- X# Create the dummy empty reminder file
- X$REMIND -rq /dev/null > $EMPTY
- X
- X# Scan each user's directory for a .reminders file
- Xforeach i ($USERS)
- X if (-r ~$i/.reminders) then
- X
- X# echo "$i has a .reminders file." DEBUGGING PURPOSES ONLY
- X
- X $REMIND -rq ~$i/.reminders > $FULL
- X $CMP -s $EMPTY $FULL
- X if ($status != 0) then
- X
- X# echo "Sending mail to $i" DEBUGGING PURPOSES ONLY
- X
- X $MAIL -s "Reminders" $i < $FULL
- X endif
- X $RM $FULL
- X endif
- Xend
- X
- X$RM $EMPTY
- SHAR_EOF
- $TOUCH -am 0218130591 remind-all.csh &&
- chmod 0600 remind-all.csh ||
- echo "restore of remind-all.csh failed"
- set `wc -c remind-all.csh`;Wc_c=$1
- if test "$Wc_c" != "1568"; then
- echo original size 1568, current size $Wc_c
- fi
- fi
- # ============= remind-all.sh ==============
- if test X"$1" != X"-c" -a -f 'remind-all.sh'; then
- echo "File already exists: skipping 'remind-all.sh'"
- else
- echo "x - extracting remind-all.sh (Text)"
- sed 's/^X//' << 'SHAR_EOF' > remind-all.sh &&
- X# Shell script to mail all users reminders.
- X
- X# Thanks to Bill Aten for this script.
- X
- X# Run it AFTER MIDNIGHT so that date is correct!
- X# On our system, we have the following in our crontab:
- X# 02 00 * * * /usr/local/adm/remind-all >/dev/null 2>&1
- X
- X# Also, you MUST use the -r and -q options on REMIND, otherwise a SEVERE
- X# security hole could develop. I recommend making this script
- X# readable and executable only by root to minimize security problems.
- X# DO NOT make the script setuid!
- X
- X# The following line gets a list of users for systems using SUN's
- X# NIS service:
- X# USERS=`ypcat passwd | awk -F: '{print $1}'`
- X
- X# The following line gets a list of users by examining /etc/passwd:
- XUSERS=`awk -F: '{print $1}' /etc/passwd`
- X
- X# If neither of the above methods works, you must come up with some
- X# way of getting a list of users on the system
- X
- X# Set the following variables as appropriate for your system
- XREMIND=/usr/local/bin/remind
- XMAIL=/usr/bin/mail
- XCMP=/bin/cmp
- XRM="/bin/rm -f"
- X
- XEMPTY=/tmp/Empty.$$
- XFULL=/tmp/Full.$$
- X
- X# Create the dummy empty reminder file
- X$REMIND -rq /dev/null > $EMPTY
- X
- X# Scan each user's directory for a .reminders file
- Xfor i in $USERS
- Xdo
- XHOME=`grep \^$i: /etc/passwd | awk -F: '{print $6}'`
- X if [ -r $HOME/.reminders ]; then
- X
- X# echo "$i has a .reminders file." DEBUGGING PURPOSES ONLY
- X
- X $REMIND -rq $HOME/.reminders > $FULL
- X if `$CMP -s $EMPTY $FULL`; then
- X : do nothing
- X else
- X
- X# echo "Sending mail to $i" DEBUGGING PURPOSES ONLY
- X
- X $MAIL -s "Reminders" $i < $FULL
- X fi
- X $RM $FULL
- X fi
- Xdone
- X
- X$RM $EMPTY
- SHAR_EOF
- $TOUCH -am 0218130591 remind-all.sh &&
- chmod 0600 remind-all.sh ||
- echo "restore of remind-all.sh failed"
- set `wc -c remind-all.sh`;Wc_c=$1
- if test "$Wc_c" != "1589"; then
- echo original size 1589, current size $Wc_c
- fi
- fi
- # ============= remind.1 ==============
- if test X"$1" != X"-c" -a -f 'remind.1'; then
- echo "File already exists: skipping 'remind.1'"
- else
- echo "x - extracting remind.1 (Text)"
- sed 's/^X//' << 'SHAR_EOF' > remind.1 &&
- X.TH REMIND 1 "18 February 1991"
- X.UC 4
- X.SH NAME
- Xremind \- a sophisticated reminder service
- X.SH SYNOPSIS
- X.B remind
- X[\fB\-n | \fB\-d\fR | \fB\-p\fR | \fB\-c\fR\fIn\fR [\fB\-w\fR\fIn\fR | \fB\-s\fR]]
- X[\fB\-voraq\fR]
- X.I filename
- X[\fIdate\fR]
- X.SH DESCRIPTION
- X.B remind
- Xreads the supplied
- X.I filename
- Xfor a list of reminders, and then issues reminders appropriate for
- Xthe current date.
- XEach reminder can consist of a message sent to standard output, or
- Xa program to be executed.
- X.SH OPTIONS
- X.TP
- X.B \-n
- XThe \fB\-n\fR flag causes \fBremind\fR to print the \fInext\fR occurrence
- Xof each reminder in a simple calendar format. You can sort this by date by
- Xpiping the output through \fBsort(1)\fR.
- X.TP
- X.B \-d
- XThe
- X.B \-d
- Xflag causes
- X.B remind
- Xto enter a debugging mode.
- XIn this mode, each reminder in the reminder file is examined and its
- Xtrigger date is printed to standard output. Also, some consistency
- Xchecking is done, and warnings are issued about constructs which could
- Xresult in slow execution times.
- X.TP
- X.B \-p
- XThe
- X.B \-p
- Xflag causes
- X.B remind
- Xto go into
- X.I purge
- Xmode. This mode is incompatible with the
- X.B \-d
- Xflag. It causes
- X.B remind
- Xto scan the reminder file and echo all reminders which have not expired
- Xto the standard output. All expired reminders are echoed to the standard
- Xerror stream.
- X.TP
- X.B \-c\fR\fIn\fR
- XThe
- X.B \-c
- Xflag causes \fBremind\fR to generate a calendar with reminders indicated on
- Xthe calendar. The calendar printout is formatted and sent to standard output.
- XIf you supply a number \fIn\fR from 1 to 12,
- Xthen a calendar will be generated for
- X\fIn\fR months, starting with the current month. The default is to
- Xproduce a calendar for one month only. The
- X.B \-c
- Xoption is not compatible with the \fB\-p\fR or \fB\-d\fR options.
- X.TP
- X.B \-w\fR\fIn\fR
- XThe \fB\-w\fR flag, when used in conjunction with \fB\-c\fR,
- Xcauses \fBremind\fR to format the calendar for a device
- Xwhose output width is \fIn\fR columns. The default is to produce a calendar
- Xfor an 80-column device.
- X.TP
- X.B \-s
- XThe \fB\-s\fB flag, when used in conjunction with \fB\-c\fR,
- Xcauses \fBremind\fR to send an unformatted "simple
- Xcalendar" listing to standard output. This can be used if you wish to
- Xformat the calendar with another program rather than using \fBremind\fR's
- Xbuilt-in calendar format.
- X.TP
- X.B \-v
- XThe
- X.B \-v
- Xflag causes the debugging messages caused by
- X.B \-d
- Xto be printed in a verbose manner. Also, any error messages issued by
- X.B remind
- Xare printed in verbose format.
- X.TP
- X.B \-o
- XThe
- X.B \-o
- Xflag causes
- X.B remind
- Xto ignore any
- X.B ONCE
- Xdirectives in the reminder file.
- X.TP
- X.B \-r
- XThe
- X.B \-r
- Xflag causes
- X.B remind
- Xto ignore any
- X.B RUN
- Xdirectives in the reminder file.
- X.TP
- X.B \-a
- XThe
- X.B \-a
- Xoption causes
- X.B remind
- Xnot to issue
- X.B AT
- Xreminders when the reminder file is read and processed, providing the
- X.B AT
- Xreminders would normally be queued. This allows you to have
- X.B remind
- Xqueue
- X.B AT
- Xreminders without triggering them when it reads the file.
- X.TP
- X.B \-q
- XThe
- X.B \-q
- Xflag causes
- X.B remind
- Xnot to queue
- X.B AT
- Xreminders for triggering later in the day. This prevents
- X.B remind
- Xfrom running as a daemon and popping up reminders as they are triggered.
- X.PP
- XIf you supply a
- X.I date
- Xon the command line, it must consist of
- X.I day month year
- Xwhere
- X.I day
- Xis the day of the month,
- X.I month
- Xis (at least the first three letters of) the English name of the month,
- Xand
- X.I year
- Xis a year (all 4 digits) from 1990 to 2075. These components can appear
- Xin any order, but must be separated by spaces. If a date is supplied,
- X.B remind
- Xuses it rather than the actual system date as its notion of "today." You
- Xcan use this feature to test how reminders will appear in the future, or
- Xto produce a calendar for any month you choose.
- X.SH REMINDER FILES
- X.B Remind
- Xuses scripts called
- X.I reminder files
- Xto control its operation. A sample reminder file is shown below:
- X.PP
- X.nf
- X #!/usr/local/bin/remind
- X # Sample file
- X BANNER Hi there. Here are your reminders:
- X
- X # First some birthdays
- X REM 6 Jan MSG David's birthday.
- X REM 23 Nov +10 MSG El's birthday is %a.
- X
- X # Next some housekeeping
- X REM 1 -1 OMIT Sat Sun RUN do_backup
- X
- X # Introduce some holidays
- X OMIT 25 Dec +2 MSG %"Christmas%" is %b.
- X OMIT 1 July MSG Canada Day
- X OMIT 22 Nov 1990 # American Thanksgiving
- X
- X # Business things
- X REM 23 Nov 1990 +2 AT 10:00 +30 *15 MSG \\
- X %"Meeting with Bill%" at %1 %b.%_Bring papers!
- X
- X.fi
- X.PP
- XNote that
- X.B remind
- Xignores blank lines and lines beginning with "#". If the character '\\'
- Xis the LAST character on the line, it is treated as a continuation
- Xcharacter. You can string many lines together using this character.
- XNote that if you use line continuation, then
- X.B remind
- Xuses the line number of the last line when printing diagnostic messages.
- X.PP
- XCommands, names of months, etc. can be typed in any
- Xmixture of upper- and lower-case. The convention I use is to
- Xuse upper-case for
- X.B remind
- Xtokens like
- X.I
- XMSG, OMIT,
- Xetc., and mixed case for other words like
- X.I January
- Xand
- X.I Sunday.
- X.SH THE REM COMMAND
- XThe most-used command in a reminder file is the
- X.I REM
- Xcommand. This command is used to denote a reminder. There are many
- Xforms of the
- X.I REM
- Xcommand; they are represented by:
- X.PP
- X.RS
- XREM [ONCE] [\fIdate_spec\fR]
- X[\fIdelta\fR]
- X[\fIback\fR]
- X[\fIrepeat\fR]
- X[\fISKIP\fR | \fIBEFORE\fR | \fIAFTER\fR]
- X[OMIT \fIomit_list\fR]
- X[AT \fItime\fR [\fItdelta\fR] [\fItrepeat\fR]]
- X[UNTIL \fIexpiry_date\fR]
- XMSG|RUN
- X.I body
- X.RE
- X.PP
- XThe parts of the \fIREM\fR command can be specified in any order, except
- Xthat the \fIbody\fR must come immediately after the \fIMSG\fR or \fIRUN\fR
- Xkeyword.
- X.SH DATE SPECIFICATIONS
- XThe
- X.I date_spec
- Xconsists of zero to four parts. These parts are
- X.I day
- X(day of month),
- X.I month
- X(month name),
- X.I year
- Xand
- X.I weekday.
- X.I Month
- Xand
- X.I weekday
- Xare the English names of months and weekdays. At least the first three
- Xcharacters must be used. Case is irrelevant. The following are examples
- Xof the various parts of a
- X.I date_spec:
- X.TP
- X.I day:
- X1, 22, 31, 14, 3
- X.TP
- X.I month:
- XJANUARY, feb, March, ApR, may, Aug
- X.TP
- X.I year:
- X1990, 1993, 2030, 95 (interpreted as 1995). The year can range
- Xfrom 1990 to 2075.
- X.TP
- X.I weekday:
- XMonday, tue, Wed, THU, Friday, saturday, sundAy
- X.PP
- XNote that there can be several
- X.I weekday
- Xcomponents separated by spaces in a
- X.I date_spec.
- X.PP
- X.B INTERPRETATION OF DATE SPECIFICATIONS
- X.PP
- XThe following examples show how date specifications are interpreted.
- X.PP
- X1. Null date specification - the reminder is triggered every day.
- XThe trigger date for a specific run is simply the current system date.
- X.PP
- X2. Only
- X.I day
- Xpresent. The reminder is triggered on the specified day of each month.
- XThe trigger date for a particular run is the closest such day to the
- Xcurrent system date. For example:
- X.nf
- X REM 1 MSG First of every month.
- X REM 31 MSG 31st of every month that has 31 days.
- X.fi
- X.PP
- X3. Only
- X.I month
- Xpresent. The reminder is triggered every day of the specified month.
- XExample:
- X.nf
- X REM Feb MSG Every day in February
- X.fi
- X.PP
- X4.
- X.I day
- Xand
- X.I month
- Xpresent. Examples:
- X.nf
- X REM 6 Jan MSG Every 6th of January
- X REM Feb 29 MSG Every 29th of February
- X.fi
- X.PP
- X5. Only
- X.I year
- Xpresent. Example:
- X.nf
- X REM 1991 MSG Every day in 1991
- X.fi
- X.PP
- X6.
- X.I year
- Xand
- X.I day
- Xpresent. Examples:
- X.nf
- X REM 1 1990 MSG 1st of every month in 1990
- X REM 1992 23 MSG 23rd of every month in 1992
- X.fi
- X.PP
- X7.
- X.I year
- Xand
- X.I month
- Xpresent. Examples:
- X.nf
- X REM Feb 1991 MSG Every day in Feb 1991
- X REM 1992 September MSG Every day in Sept 1992
- X.fi
- X.PP
- X8.
- X.I year, month
- Xand
- X.I day
- Xpresent. Examples:
- X.nf
- X REM 8 Jan 1991 MSG 8th January 1991.
- X REM 1992 March 9 MSG 9th March 1992.
- X.fi
- X.PP
- X9.
- X.I weekday
- Xonly. Examples:
- X.nf
- X REM Sat MSG Every Saturday
- X REM Mon Tue Wed Thu Fri MSG Every working day
- X REM Monday Wednesday MSG Every Monday and Wednesday
- X.fi
- X.PP
- X10.
- X.I weekday
- Xand
- X.I day
- Xpresent. Examples:
- X.nf
- X REM Sat 1 MSG First Saturday of every month
- X REM Mon Tue Wed Thu Fri 15 \\
- X MSG 1st working day after 15th of every month
- X.fi
- X.PP
- X11.
- X.I weekday
- Xand
- X.I month
- Xpresent. Examples:
- X.nf
- X REM Mon March MSG Every Monday in March
- X REM Mon Tue Wed Thu Fri Feb MSG Every working day in February
- X.fi
- X.PP
- X12.
- X.I weekday, month
- Xand
- X.I day
- Xpresent. Examples:
- X.nf
- X REM Mon 1 March MSG First Monday in March
- X REM Sat Sun 15 July MSG First Sat or Sun on or after 15 July
- X.fi
- X.PP
- X13.
- X.I weekday
- Xand
- X.I year
- Xpresent. Example:
- X.nf
- X REM Sat Sun 1991 MSG Every Saturday and Sunday in 1991
- X.fi
- X.PP
- X14.
- X.I weekday, day
- Xand
- X.I year
- Xpresent. Examples:
- X.nf
- X REM Mon 15 1990 MSG 1st Mon after 15th of every month in 1990
- X REM Mon Tue Wed Thu Fri 1 1990 \\
- X MSG 1st working day of every month in 1990
- X.fi
- X.PP
- X15.
- X.I weekday, month
- Xand
- X.I year
- Xpresent. Example:
- X.nf
- X REM Mon Wed 1991 Feb MSG Every Mon and Wed in Feb 1991.
- X.fi
- X.PP
- X16.
- X.I weekday, day, month
- Xand
- X.I year
- Xpresent. Example:
- X.nf
- X REM Mon Tue Wed Thu Fri 28 Oct 1990 \\
- X MSG 1st working day on or after 28 October 1990.
- X.fi
- X.PP
- XNote that when
- X.I weekday
- Xand
- X.I day
- Xare specified,
- X.B remind
- Xchooses the first date on or after the specified
- X.I day
- Xwhich also satisfies the
- X.I weekday
- Xconstraint. It does this by picking the first date on or after the specified
- X.I day
- Xwhich is listed in the list of
- X.I weekdays.
- XThus, a reminder like:
- X.PP
- X.nf
- X REM Mon Tue 28 Oct 1990 MSG Hi
- X.fi
- X.PP
- Xwould be issued only on Monday, 29 October, 1990. It would not be issued
- Xon Tuesday, 30 October, 1990, since the 29th is the first date to satisfy
- Xthe
- X.I weekday
- Xconstraints.
- X.PP
- X.B BACKWARD SCANNING
- X.PP
- XSometimes, you need to incorporate "backward scanning" into your date
- Xspecification. This is accomplished with the
- X.I back
- Xpart of the reminder specification. If present, the
- X.I back
- Xis specified as a number preceded by one or two minus signs. This causes
- X.B remind
- Xto compute the trigger date as usual, and then move back the specified
- Xnumber of days. For example:
- X.PP
- X.nf
- X REM Mon 1 -7 MSG Last Monday of every month.
- X.fi
- X.PP
- XThis works by finding the first Monday of every month, and then moving
- X"back" seven days. This results in the last Monday of the previous
- Xmonth. (Warning: If you have global
- X.I OMITs,
- Xthis might not work - see
- Xthe
- X.I OMIT
- Xcommand. In this case, you can use the "definite \fIback\fR" which consists
- Xof a number preceded by two minus signs like \-\-7)
- X.PP
- XAnother example is:
- X.PP
- X.nf
- X REM 1 -1 MSG Last day of every month.
- X.fi
- X.PP
- XSince we don't know how many days are in a month, to get to the last day
- Xof a month, we go to the first day of the next month and then move back
- Xone day.
- X.PP
- X.B Remind
- Xwill automatically scan forwards and backwards until it finds a suitable
- Xtrigger date. Note that large
- X.I back
- Xvalues can lead to a lot of backtracking and slow the execution of
- X.B remind.
- X.PP
- X.B ADVANCE WARNING
- X.PP
- X.B Remind
- Xcan warn you of an upcoming reminder as far in advance as you desire. This
- Xis specified by a
- X.I delta,
- Xwhich is a positive number preceded by one or two "+" signs. For example:
- X.PP
- X.nf
- X REM 8 Jan 1992 +3 MSG Test1
- X REM 1 +1 MSG Test2
- X.fi
- X.PP
- XThe reminder "Test1" will be triggered on the 8th of January, 1992, as well
- Xas the 3 days preceding it. All told, "Test1" will be triggered on the
- X5th through the 8th of January, 1992.
- X.PP
- XThe reminder "Test2" will be triggered on the first day of every month, as
- Xwell as the day before. In effect, "Test2" will be triggered on the first
- Xand last day of every month.
- X.PP
- X.I Delta
- Xand
- X.I back
- Xcan be combined:
- X.PP
- X.nf
- X REM Mon 1 --7 ++3 MSG Test3
- X.fi
- X.PP
- XThe reminder "Test3" will be triggered on the last Monday of every month,
- Xas well as the three days preceding it.
- X.PP
- XSee "The OMIT Command" for an explanation of the distinction between the "-"
- Xand "--" forms of the \fIback\fR, and the "+" and "++" forms of the
- X\fIdelta\fR.
- X.PP
- X.B REPEATING REMINDERS
- X.PP
- XThe
- X.I repeat
- Xcomponent in a reminder is a number preceded by an asterisk; for example,
- X"*14". The
- X.I repeat
- Xis used to remind you of events which occur regularly after a specified
- Xstart date. For example, suppose you get paid every second Thursday,
- Xand that your last payday was 8 November 1990. The following reminder
- Xwould remind you of each payday 3 days in advance:
- X.PP
- X.nf
- X REM 8 Nov 1990 *14 +3 MSG Payday is %b!
- X.fi
- X.PP
- XThe
- X.I repeat
- Xcomponent of "*14" would cause the reminder to be triggered every 14
- Xdays from the start date.
- X.PP
- XIn order to use a
- X.I repeat,
- Xyou must fully specify the start date. That means that if
- Xyou use a
- X.I repeat,
- Xyou must specify the
- X.I month, day
- Xand
- X.I year.
- XYou can also specify
- X.I weekday, back
- Xand
- X.I local OMITs
- Xbut these only affect the calculation of the start date. Once the
- Xstart date is calculated, the reminder is issued regularly every
- X.I repeat
- Xdays. Note, in particular, that once the start date is calculated,
- X.B remind
- Xignores local and global
- X.I OMITs
- Xwhen calculating the trigger date. The final trigger date is strictly
- Xa multiple of
- X.I repeat
- Xdays from the start date. The only exceptions are those cases covered
- Xby the \fIBEFORE, AFTER\fR and \fISKIP\fR keywords, discussed in the
- Xnext section.
- X.PP
- X.B THE BEFORE, AFTER AND SKIP KEYWORDS
- X.PP
- XShould a reminder's trigger date happen to fall on an OMITted day, the
- Xdefault action is to go ahead and trigger the reminder anyway. For example,
- Xsuppose you have a meeting every Tuesday. Consider the following:
- X.PP
- X.nf
- X OMIT 1 Jan MSG New Year's Day
- X OMIT 25 December MSG Christmas
- X REM Tue AT 13:00 MSG Code review meeting.
- X.fi
- X.PP
- XEven though Christmas 1990 is on a Tuesday, you will still be reminded
- Xof a code review meeting on that day. Surely that is not desirable. You
- Xcan tell \fBremind\fR to skip reminders which fall on OMITted days with the
- X.I SKIP
- Xkeyword. Assuming we have the same \fIOMIT\fR commands, then:
- X.PP
- X.nf
- X REM Tue SKIP AT 13:00 MSG Code review meeting.
- X.fi
- X.PP
- Xwould be triggered every Tuesday, but not on Christmas or New Year's
- XDay, because both of these holidays happen to fall on Tuesdays.
- X.PP
- XIn some situations, we don't want to skip the reminder; we want to move
- Xit to just before or just after a holiday. Consider these examples:
- X.PP
- X.nf
- X REM Fri AFTER OMIT Sat Sun MSG Do your backup!
- X.fi
- X.PP
- XThis reminder is normally triggered every Friday. However, if a particular
- XFriday happens to be a holiday, it will be triggered on the Monday after
- Xthe holiday instead. Note that the \fIAFTER\fR keyword keeps scanning
- Xforwards until it hits a day which is not in the global or local \fIOMIT\fR
- Xlists. (Of course, if both the Friday and Monday are holidays, then the
- Xreminder would be deferred until Tuesday, and so on.)
- X.PP
- X.nf
- X REM Fri BEFORE MSG Do your backup!
- X.fi
- X.PP
- XThis is similar, except that the reminder is issued on the previous Thursday
- Xif a particular Friday happens to be a holiday. This form, too, will
- Xmove back to Wednesday if Thursday also happens to be a holiday, and so on.
- X.PP
- XNote: These keywords skip both local and global \fIOMIT\fRs. Also,
- X\fBremind\fR will complain about certain illegal constructions, such as:
- X.PP
- X.nf
- X REM Mon SKIP OMIT Mon MSG Impossible!
- X.fi
- X.PP
- XIf \fBremind\fR makes too many attempts to find a trigger date for
- Xcertain forms, it assumes that no satisfiable date exists, and will warn
- Xyou to check the date specification. In practice, this should never happen.
- X.PP
- X.B THE UNTIL KEYWORD
- X.PP
- XThe \fIUNTIL\fR keyword can be used to force a reminder to expire at a
- Xparticular date. It must be followed by a \fIyear\fR, \fImonth\fR and
- X\fIday\fR specifying the expiry date. Here are some examples:
- X.PP
- XSuppose you have a conference from 25 Feb 1991 to 1 March 1991. You
- Xcould use:
- X.PP
- X.nf
- X REM 25 Feb 1991 *1 UNTIL 1 Mar 1991 MSG Conference today!
- X.fi
- X.PP
- XYou must include the "*1" to have the reminder repeated every day
- Xduring the conference. If you did not include the "*1", then the
- Xreminder would only have been issued on 25 Feb 1991.
- X.PP
- XSuppose you have jury duty from 4-15 March 1991, not including weekends.
- XSuppose further that you wish to be reminded of this duty starting on 1
- XMarch 1991 (hence the "++3"): (See the section "Substitution" for an
- Xexplanation of all the percent signs.)
- X.PP
- X.nf
- X REM 4 Mar 1991 ++3 *1 OMIT Sat Sun SKIP UNTIL 15 Mar 1991 \\
- X MSG %"Jury duty%" %b.
- X.fi
- X.PP
- XFinally, suppose you have a class every Tuesday and Thursday until 30 May
- X1991:
- X.PP
- X.nf
- X REM Tue Thu UNTIL 30 May 1991 MSG Class tonight.
- X.fi
- X.PP
- X.B THE MSG KEYWORD
- X.PP
- XThe
- X.I MSG
- Xkeyword causes the remaining part of the line to be passed through a
- Xsubstitution filter and then printed to standard output whenever the
- Xreminder is triggered. See the section "Substitution" for more information
- Xabout the substitution filter.
- X.PP
- X.B THE RUN KEYWORD
- X.PP
- XThe
- X.I RUN
- Xkeyword causes the remaining part of the line to be passed through the
- Xsubstitution filter and then passed to the default shell for execution
- Xwhenever the reminder is triggered. If the
- X.B \-r
- Xcommand-line option is specified, all
- X.I REM
- Xcommands with the
- X.I RUN
- Xkeyword are ignored.
- X.PP
- X.B
- XGETTING REMINDED ONLY ONCE PER DAY
- X.PP
- XIf you run
- X.B remind
- Xfrom your
- X.I .login
- Xscript, you may only want certain reminders to be run once per day, not
- Xonce per login. Typically, this is used to control
- X.I RUN
- Xcommands so that they only execute once per day. To specify this,
- Xplace the
- X.I ONCE
- Xkeyword in the reminder file. When
- X.B remind
- Xencounters a
- X.I ONCE
- Xkeyword, it checks the last-access date of the reminder file. If it is
- Xequal to the current date,
- X.B remind
- Xassumes that the reminder file has already been run once, and ignores the
- Xreminder. If you start
- X.B remind
- Xwith the
- X.B \-o
- Xcommand-line option,
- X.B remind
- Xignores the
- X.I ONCE
- Xkeyword.
- X.PP
- X.B LOCALLY OMITTING WEEKDAYS
- X.PP
- XA
- X.I REM
- Xcommand containing the
- X.I OMIT
- Xkeyword followed by a list of weekdays causes the
- X.I delta
- Xand
- X.I back
- Xto ignore the specified weekdays when counting days. This is called a
- X.I local OMIT.
- XFor example:
- X.PP
- X.nf
- X REM 1 +1 OMIT Sat Sun MSG Test4
- X.fi
- X.PP
- XThis reminder prints "Test4" on the first day of every month, as well
- Xas the previous day. If, however, the first day of the month falls on
- Xa Sunday or Monday, the reminder is also triggered on the previous
- XFriday, since the
- X.I delta
- Xof +1 does not count Saturdays or Sundays when moving backwards. Here's
- Xanother example:
- X.PP
- X.nf
- X REM 1 -1 +1 OMIT Sat Sun MSG Test5
- X.fi
- X.PP
- XThis reminder is triggered on the last working day of each month, as well
- Xas the working day preceding it. Let's look at it in detail:
- X.PP
- XThe
- X.I day
- Xof "1" specifies the first day of each month. The
- X.I back
- Xof "-1" tells
- X.B remind
- Xto go backwards by one day, not counting Saturday and Sunday as it moves.
- XThis takes us the the last working day of the preceding month, which is the
- Xtrigger date. The
- X.I delta
- Xof "+1" ensures that the reminder will be triggered on the day preceding
- Xthis trigger date also. Finally, if the trigger date happens to be
- Xa Monday, the
- X.I delta
- Xcombined with the
- X.I local OMIT
- Xcauses the reminder to be triggered on the Friday (and Saturday and Sunday)
- Xpreceding the trigger date.
- X.PP
- X.B THE AT KEYWORD
- X.PP
- XReminders with the
- X.I AT
- Xkeyword are called "timed reminders" or "AT reminders." The
- X.I AT
- Xkeyword must be followed by a
- X.I time,
- Xwhich is a time in 24-hour format, from 0:00 to 23:59. The
- X.I time
- Xmust be of the form \fIhh\fR:\fImm\fR.
- XAlso, after the
- X.I AT
- Xkeyword, you can supply a
- X.I tdelta
- Xand a
- X.I trepeat.
- XThese have the same form as a
- X.I delta
- Xand a
- X.I repeat.
- XIn other words, a
- X.I tdelta
- Xis a number preceded by a "+" sign, and a
- X.I trepeat
- Xis a number preceded by an asterisk.
- X.PP
- XWhen
- X.B remind
- Xencounters a timed reminder, it examines the actual trigger date. This
- Xis the date specified by the date_spec, not counting any
- X.I delta
- Xwhich may be present. If the trigger date is the same as the current
- Xdate, the timed reminder will be placed on a queue in addition to
- Xbeing triggered like a normal reminder. (If you supply the
- X.B \-a
- Xcommand-line option, a timed reminder which would be queued will not
- Xbe triggered like a normal reminder.) After
- X.B remind
- Xhas finished processing the reminder file, it starts up a background
- Xprocess to trigger all the queued timed reminders. As each reminder's
- Xtrigger time is reached, it is triggered. Thus, you can have
- X.B remind
- Xissue reminders just before important meetings or time-sensitive tasks.
- X.PP
- XThe
- X.I tdelta
- Xand
- X.I trepeat
- Xare interpreted in minutes. This is how they work:
- X.PP
- X.nf
- X REM AT 17:00 +60 *15 MSG Hello!
- X.fi
- X.PP
- XThis timed reminder has a trigger time of 5:00pm. It is also triggered
- Xone hour before 5:00pm (because of the
- X.I tdelta
- Xof +60)
- Xand every 15 minutes thereafter until 5:00pm (because of the
- X.I trepeat
- Xof +15.) All told, the reminder would be triggered at 4:00pm, 4:15pm,
- X4:30pm, 4:45pm and 5:00pm.
- X.PP
- X.nf
- X REM Fri AT 17:00 +45 *30 MSG Work ends at 5!!
- X.fi
- X.PP
- XThis timed reminder would be placed on the queue every Friday. It
- Xwould be triggered at 4:15pm, 4:45pm and 5:00pm every Friday. Note
- Xthat a timed reminder is always triggered at the time specified
- Xafter the
- X.I AT
- Xkeyword, even if the
- X.I tdelta
- Xis not a multiple of
- X.I trepeat.
- X.PP
- XIf a reminder has a regular
- X.I delta,
- Xit will not be queued unless the current system date equals the actual
- Xtrigger date. Thus:
- X.PP
- X.nf
- X REM Fri +1 AT 17:00 MSG Go home at 5:00!
- X.fi
- X.PP
- XOn Thursdays, this reminder would simply be treated as a regular reminder
- Xand printed. On Fridays, however, it would be queued for timed triggering.
- XNote that the
- X.B \-q
- Xcommand-line option causes
- X.B remind
- Xto treat timed reminders as normal reminders, and not queue them.
- X.SH THE OMIT COMMAND
- X.I OMIT
- Xexists as a separate command as well as a keyword within a
- X.I REM
- Xstatement. When used as a separate command, it is called a
- X.I global OMIT,
- Xand has the following form:
- X.RS
- XOMIT
- X.I day
- X.I month
- X[
- X.I year
- X]
- X.RE
- XThe arguments can be specified in any order.
- X.PP
- XThe form without the
- X.I year
- Xcomponent is used for holidays which fall on the same date each year.
- XFor example:
- X.PP
- X.nf
- X OMIT 25 December # Christmas
- X OMIT 1 January # New Year's Day
- X.fi
- X.PP
- X(Note that
- X.I OMIT
- Xcan have a following comment on the same line, unlike the
- X.I REM
- Xcommand.)
- X.PP
- XThe form with the
- X.I year
- Xcomponent is used for holidays which vary from year to year. For example:
- X.PP
- X.nf
- X OMIT 12 October 1990 # Columbus Day 1990
- X OMIT 22 November 1990 # Thanksgiving Day 1990
- X.fi
- X.PP
- XIn its debugging messages,
- X.B remind
- Xcalls the first form a
- X.I partially-specified global OMIT
- Xand the second form a
- X.I fully-specified global OMIT.
- X.PP
- XThe dates specified by
- X.I global OMITs
- Xare omitted by the
- X.I back
- Xand
- X.I delta
- Xportions of a reminders, in addition to any
- X.I local OMITs.
- XFor example:
- X.PP
- X.nf
- X OMIT 25 December
- X REM 26 +1 OMIT Sat Sun MSG Test6
- X.fi
- X.PP
- XThis would issue a reminder on the 26th of each month, as well as the
- Xpreceding working day. Also, on the 24th of December 1990, the reminder
- Xwould be issued. Even though the 25th of December 1990 is a Tuesday, the
- X.I global OMIT
- Xwould cause the
- X.I delta
- Xto skip it.
- X.PP
- XHowever, if you use the "--" and "++" forms of \fIback\fR and \fIdelta\fR,
- Xthen OMITted days are not skipped - strict date subtraction is performed.
- XThus, to have a reminder issued on the last Monday of every month, regardless
- Xof any \fIglobal OMITs\fR in force, you could use:
- X.PP
- X.nf
- X REM 1 Mon --7 MSG Forced to be last Monday in month
- X.fi
- X.PP
- XIf you want the reminder to be issued on the last Monday of every month,
- Xunless it is a holiday, in which case the reminder should be issued the
- Xfollowing Tuesday, use:
- X.PP
- X.nf
- X REM 1 Mon --7 AFTER MSG Example!
- X.fi
- X.PP
- X.I Global OMITs
- Xare in force for all reminders following them in the reminder file until
- Xa CLEAR-OMIT-CONTEXT or POP-OMIT-CONTEXT command is encountered. Thus,
- Xyou could have a series of reminders for which
- X.I global OMITs
- Xare inappropriate (such as birthdays or reminders which rely on
- X.I back
- Xto get to a specific weekday) ahead of any
- X.I global OMITs,
- Xwith business reminders (for which omission of holidays is appropriate)
- Xfollowing the
- X.I global OMITs.
- X.PP
- XFor convenience, you can include a \fIdelta\fR and a \fIMSG\fR or \fIRUN\fR
- Xtoken in a global \fIOMIT\fR. This is useful to avoid duplication of holiday
- Xentries. For example, the line:
- X.PP
- X.nf
- X OMIT 25 Dec +2 MSG %"Christmas%" is %b.
- X.fi
- X.PP
- Xis exactly equivalent to:
- X.PP
- X.nf
- X OMIT 25 Dec
- X REM 25 Dec +2 MSG %"Christmas%" is %b.
- X.fi
- X.SH CONTROLLING THE OMIT CONTEXT
- XIn many cases, it is convenient to temporarily change the \fIglobal OMITs\fR
- Xwhich are in force. This allows you to easily isolate holidays to act only
- Xon certain reminders, or to temporarily introduce a \fIglobal OMIT\fR for a
- Xspecial-case reminder. Three commands allow you to do this:
- X.PP
- X.I CLEAR-OMIT-CONTEXT
- Xdeletes all the \fIglobal OMITs\fR and starts you off with a clean slate.
- X.PP
- X.I PUSH-OMIT-CONTEXT
- Xsaves all the \fIglobal OMITs\fR on an internal stack and leaves the current
- X\fIglobal OMITs\fR in effect.
- X.PP
- X.I POP-OMIT-CONTEXT
- Xrestores the \fIglobal OMITs\fR which were in effect at the time of the last
- Xmatching \fIPUSH-OMIT-CONTEXT\fR command.
- X.PP
- XSuppose you have a block of reminders which require a clear OMIT context
- Xto work properly, and which also introduce several \fIglobal OMITs\fR which
- Xyou don't want to affect any other reminders. The following fragment shows
- Xhow to isolate these reminders:
- X.PP
- X.nf
- X # Sample fragment
- X PUSH-OMIT-CONTEXT # Save for later
- X CLEAR-OMIT-CONTEXT # Start out with clean slate
- X
- X # Block of reminders goes here
- X
- X POP-OMIT-CONTEXT # Restore the saved OMITs
- X # Remaining reminders go here
- X.fi
- X.SH THE INCLUDE COMMAND
- XThe
- X.I INCLUDE
- Xcommand has the following form:
- X.PP
- X.RS
- XINCLUDE
- X.I filename
- X.RE
- X.PP
- XThis causes
- X.B remind
- Xto suspend the current file and read the contents of the specified
- X.I filename.
- XOnce that file has been read,
- X.B remind
- Xcontinues reading the original file from where it left off.
- X.I INCLUDE
- Xcommands can be nested to a depth of 10.
- X.PP
- X.I INCLUDE
- Xallows you or someone else to maintain a file of holidays or system-wide
- Xreminders that everyone should get. For example, your reminder file could
- Xlook something like this:
- X.PP
- X.nf
- X #!/usr/local/bin/remind
- X #
- X # Place personal stuff here - birthdays, etc.
- X
- X # Now get system-wide global OMITS (holidays)
- X INCLUDE /usr/share/holidays
- X
- X # and system-wide reminders
- X INCLUDE /usr/share/reminders
- X
- X # Place local business stuff here.
- X.fi
- X.PP
- XThe
- X.I ONCE
- Xkeyword operates on the last-access date of the top-level file.
- XThe access dates of
- X.I INCLUDEd
- Xfiles are not used to control the operation of the
- X.I ONCE
- Xkeyword.
- X.SH SUBSTITUTION
- XBefore being processed, the body of a
- X.I REM
- Xcommand is passed through a substitution filter. The filter scans for
- Xsequences "%x" (where "x" is any letter and certain other characters)
- Xand performs substitutions as
- Xshown below. (All dates refer to the trigger date of the reminder.)
- X.TP
- X.B %a
- Xis replaced with "on \fIweekday, day month, year\fR"
- X.RS
- XFor example, consider the reminder:
- X.PP
- XREM 18 Oct 1990 +4 MSG Meeting with Bob %a.
- X.PP
- XOn 16 October 1990, it would print "Meeting with Bob on Thursday, 18 October,
- X1990."
- X.PP
- XOn 17 October 1990, it would print "Meeting with Bob tomorrow."
- X.PP
- XOn 18 October 1990, it would print "Meeting with Bob today."
- X.RE
- X.TP
- X.B %b
- Xis replaced with "in \fIdiff\fR day's time" where
- X.I diff
- Xis the
- X.B actual
- Xnumber of days between the current date and the trigger date.
- X(\fIOMITs\fR have no effect.)
- X.RS
- XFor example, consider:
- X.PP
- XREM 18 Oct 1990 +4 MSG Meeting with Bob %b.
- X.PP
- XOn 16 October 1990, it would print "Meeting with Bob in 2 days' time."
- X.PP
- XOn 17 October 1990, it would print "Meeting with Bob tomorrow."
- X.PP
- XOn 18 October 1990, it would print "Meeting with Bob today."
- X.RE
- X.TP
- X.B %c
- Xis replaced with "on \fIweekday\fR"
- X.RS
- XExample: REM 18 Oct 1990 +4 MSG Meeting with Bob %c.
- X.PP
- XOn 16 October 1990, it would print "Meeting with Bob on Thursday."
- X.PP
- XOn 17 October 1990, it would print "Meeting with Bob tomorrow."
- X.PP
- XOn 18 October 1990, it would print "Meeting with Bob today."
- X.RE
- X.TP
- X.B %d
- Xis replaced with "\fIday\fR", the day of the month.
- X.TP
- X.B %e
- Xis replaced with "on \fIdd/mm/yyyy\fR"
- X.TP
- X.B %f
- Xis replaced with "on \fImm/dd/yyyy\fR"
- X.TP
- X.B %g
- Xis replaced with "on \fIweekday, day month\fR"
- X.TP
- X.B %h
- Xis replaced with "on \fIdd/mm\fR"
- X.TP
- X.B %i
- Xis replaced with "on \fImm/dd\fR"
- X.TP
- X.B %j
- Xis replaced with "on \fIweekday, month day-th, year\fR" This form appends the
- Xcharacters "st", "nd", "rd" or "th" to the day of the month, as appropriate.
- X.TP
- X.B %k
- Xis replaced with "on \fIweekday, month day-th\fR"
- X.TP
- X.B %l
- Xis replaced with "on \fIyyyy/mm/dd\fR"
- X.TP
- X.B %m
- Xis replaced with "\fImonth\fR", the name of the month.
- X.TP
- X.B %n
- Xis replaced with the number (1 to 12) of the month.
- X.TP
- X.B %o
- Xis replaced with " (today)" if and only if the current system date is the same
- Xas the date being used by
- X.B remind
- Xas the current date. Recall that you can specify a date for
- X.B remind
- Xto use on the command line. This substitution is not generally useful in a
- X.I REM
- Xcommand, but is useful in a
- X.I BANNER
- Xstatement. (See the section "The BANNER Command.)
- X.TP
- X.B %p
- Xis replaced with "s" if the
- X.I diff
- Xbetween the current date and the trigger date is not 1. You can use this
- Xto construct reminders like:
- X.RS
- XREM 1 Jan +4 MSG %x day%p to go before New Year!
- X.RE
- X.TP
- X.B %q
- Xis replaced with "'s" if the
- X.I diff
- Xbetween the trigger date and the current date is 1. Otherwise, it is replaced
- Xwith "s'" This can be used as follows:
- X.RS
- XREM 1 Jan +4 MSG New Year in %x day%q time!
- X.RE
- X.TP
- X.B %r
- Xis replaced with the day of the month (01 to 31) padded with a leading zero
- Xif needed to pad to two digits.
- X.TP
- X.B %s
- Xis replaced with "st", "nd", "rd" or "th" depending on the day of the month.
- X.TP
- X.B %t
- Xis replaced with the number of the month (01 to 12) padded to two digits
- Xwith a leading zero.
- X.TP
- X.B %u
- Xis replaced with "on \fIweekday, day-th month, year\fR" This is similar
- Xto
- X.B %a
- Xexcept that "st", "nd", "rd" or "th" is added to the
- X.I day
- Xas appropriate.
- X.TP
- X.B %v
- Xis replaced with "on \fIweekday, day-th month\fR"
- X.TP
- X.B %w
- Xis replaced with "\fIweekday\fR", the name of the day of the week.
- X.TP
- X.B %x
- Xis replaced with the
- X.I diff
- Xbetween the current date and the trigger date. The
- X.I diff
- Xis defined as the actual number of days between these two dates;
- X.I OMITs
- Xare not counted. (Strict date subtraction is performed.)
- X.TP
- X.B %y
- Xis replaced with "\fIyear\fR", the year of the trigger date.
- X.TP
- X.B %z
- Xis replaced with "\fIyy\fR", the last two digits of the year.
- X.TP
- X.B %_
- X(percent-underscore) is replaced with a newline. You can use this to
- Xachieve multi-line reminders.
- X.TP
- X.B %1
- Xis replaced with "now", "\fIm\fR minutes from now", "\fIm\fR minutes ago",
- X"\fIh\fR hours from now", "\fIh\fR hours ago", "\fIh\fR hours and \fIm\fR
- Xminutes from now" or "\fIh\fR hours and \fIm\fR minutes ago", as appropriate
- Xfor a timed reminder. Note that unless you specify the \fB\-a\fR option,
- Xtimed reminders will be triggered like normal reminders, and thus a timed
- Xreminder which occurred earlier in the day may be triggered. This
- Xcauses the need for the "...ago" forms.
- X.TP
- X.B %2
- Xis replaced with "\fIhh\fR:\fImm\fRam" or "..pm" depending on the
- X.I AT
- Xtime of the reminder.
- X.TP
- X.B %3
- Xis replaced with "\fIhh\fR:\fImm\fR" in 24-hour format.
- X.TP
- X.B %4
- Xis replaced with "\fImm\fR" where \fImm\fR is the number of minutes between
- X"now" and the time specified by \fIAT\fR. If the \fIAT\fR time is
- Xearlier than the current time, then the result is negative.
- X.TP
- X.B %5
- Xis replaced with "\fIma\fR" where \fIma\fR is the absolute value of the number
- Xproduced by \fB%4\fR.
- X.TP
- X.B %6
- Xis replaced with "ago" or "from now", depending on the relationship between
- Xthe \fIAT\fR time and the current time.
- X.TP
- X.B %7
- Xis replaced with the number of hours between the \fIAT\fR time and the
- Xcurrent time. It is always non-negative.
- X.TP
- X.B %8
- Xis replaced with the number of minutes between the \fIAT\fR time and
- Xthe current time, after the hours (\fB%7\fR) have been subtracted out.
- XThis is a number ranging from 0 to 59.
- X.TP
- X.B %9
- Xis replaced with "s" if the value produced by \fB%8\fR is not 1.
- X.TP
- X.B %0
- Xis replaced with "s" if the value produced by \fB%7\fR is not 1.
- X.TP
- X.B %!
- Xis replaced with "is" if the current time is before the \fIAT\fR time,
- Xor "was" if it is after.
- X.TP
- X.B
- X%"
- X(percent-doublequote) is removed. This sequence is not
- Xused by the substitution filter,
- Xbut is used to tell \fBremind\fR which text to include in a calendar
- Xentry when the \fB\-c\fR option is chosen. See the section "Producing
- Xa Calendar"
- X.PP
- XNotes:
- X.TP
- Xo
- X.B Remind
- Xnormally prints a blank line after each reminder; if the last character
- Xof the body is '%', the blank line will not be printed.
- X.TP
- Xo
- XSubstitutions a, b, c, e, f, g, h, i, j, k, l, u and v all are replaced
- Xwith "today" if the current date equals the trigger date, or "tomorrow"
- Xif the trigger date is one day after the current date. Thus, they are
- X.B not
- Xthe same as substitutions built up from the simpler %w, %y, etc.
- Xsequences.
- X.TP
- Xo
- XAny of the substitutions dealing with time (0 through 9 and '!')
- Xproduce undefined results if used in a reminder which does not have
- Xan \fIAT\fR keyword. Also, if a reminder has a \fIdelta\fR and may
- Xbe triggered on several days, the time substitutions ignore the date. Thus,
- Xthe \fB%1\fR substitution may report that a meeting is in 15 minutes, for
- Xexample, even though it may only be in 2 days time, because a \fIdelta\fR has
- Xtriggered the reminder. It is recommended that you use the time substitutions
- Xonly in timed reminders with no \fIdelta\fR which are designed to be
- Xqueued for timed activation.
- X.TP
- Xo
- XCapital letters can be used in the substitution sequence, in which case
- Xthe first character of the substituted string is capitalized (if it is
- Xnormally a lower-case letter.)
- X.TP
- Xo
- XAll other characters following a "%" sign are simply copied. In particular,
- Xto get a "%" sign out, use "%%" in the body. To start the body of a reminder
- Xwith a space, use "% ", since
- X.B remind
- Xnormally scans for the first non-space character after a
- X.I MSG
- Xor
- X.I RUN
- Xtoken.
- X.SH PRODUCING A CALENDAR
- XIf you provide the \fB\-c\fR option, the \fBremind\fR will scan your
- Xreminder file and produce a calendar with your reminders entered on the
- Xappropriate dates.
- X.PP
- XWhen you produce a calendar, \fBremind\fR will pass the text
- Xthrough the substitution mechanism. However, you may indicate to \fBremind\fR
- Xwhich portions of the text should be placed in the calendar. This is done
- Xwith the \fB%"\fR sequence. Here's an example:
- X.PP
- X.nf
- X REM 6 Jan +6 MSG %"David's birthday%" is %a.
- X.fi
- X.PP
- XWhen you run \fBremind\fR normally, it executes the reminder as if the
- X.B
- X%"
- Xsequences were not there. When you produce a calendar with the \fB\-c\fR
- Xoption, however, only the text "David's birthday" is entered into the
- Xcalendar. For convenience, timed reminders are sorted by time before
- Xbeing entered into the calendar, and the time of each reminder is printed
- Xbefore the reminder text.
- X.PP
- XNote that by default, only \fIMSG\fR reminders are included in the calendar;
- X\fIRUN\fR reminders are ignored. However, if you explicitly place the %"
- Xescape sequences in a \fIRUN\fR reminder, then it will be included in the
- Xcalendar.
- XIf you indicate empty text for the calendar entry
- Xwith the sequence \fB%"%"\fR, then the reminder is ignored when producing
- Xthe calendar, whether is is a \fIMSG\fR or \fIRUN\fR type.
- X.PP
- XIf your reminder file has errors in it, when you produce a calendar, you
- Xwill get many error messages apparently coming from the file "*cache*"
- XThis is because \fBremind\fR caches the reminder file for efficient
- Xproduction of the calendar. Thus, you should check that your reminder
- Xfile is error-free (by running \fBremind\fR with the \fB\-d\fR option)
- Xbefore attempting to produce a calendar.
- X.PP
- XThe "Simple Calendar" format is useful if you want to format the calendar
- Xwith another program. You can save this output to a file or pipe it to
- Xyour formatting program. The output format is:
- X.PP
- X.nf
- X yyyy/mm/dd: hr:min \fIbody\fR
- X.fi
- X.PP
- XThe \fIhr:min\fR portion is present only if the reminder has an \fIAT\fR
- Xclause. You can produce this format by using the \fB\-s\fR option in
- Xconjunction with the \fB-c\fR option. The \fB\-n\fR option produces
- Xa listing in this format also; however, it is not sorted by date, and
- Xindicates the next occurrence of each reminder in the reminder file.
- X.SH THE BANNER COMMAND
- XWhen
- X.B remind
- Xissues reminders, it normally prints a message saying:
- X.PP
- X"Reminders for \fIweekday, day-th month, year\fR (today):"
- X.PP
- X(If you supply a date on the command line different from the system date,
- Xthe "(today)" portion is omitted.)
- X.PP
- XYou can change this default to anything you want with the
- X.I BANNER
- Xcommand. It should appear in the reminder file before any
- X.I REM
- Xcommands. (This is not enforced, but a
- X.I BANNER
- Xcommand encountered after a reminder has been triggered will be ignored.)
- X.PP
- XThe format of
- X.I BANNER
- Xis:
- X.PP
- XBANNER
- X.I string
- X.PP
- XThe
- X.I string
- Xis passed through the substitution mechanism described before, using the
- Xcurrent date and time for substitution. The standard banner is described by:
- X.PP
- X.nf
- X BANNER Reminders for %w, %d%s %m, %y%o:
- X.fi
- X.PP
- XYou can have a blank banner by using:
- X.PP
- X.nf
- X BANNER %
- X.fi
- X.PP
- X.SH PURGING REMINDER FILES
- XYou should periodically purge your reminder file of "expired"
- X.I REM
- Xcommands and global
- X.I OMITs.
- XThese are reminders which took place in the past and can never occur
- Xagain, or
- X.I OMITs
- Xwhich are for past years. Of course, only
- X.I REMs
- Xand
- X.I OMITs
- Xwith the
- X.I year
- Xspecified can ever expire.
- X.PP
- XTo purge your reminder file, run
- X.B remind
- Xin
- X.I purge
- Xmode. This mode simply echoes non-expired lines to standard output, and
- Xexpired lines to standard error. Thus, to purge a file, you could type:
- X.PP
- X.nf
- X REMIND -p notes.old > notes.new
- X.fi
- X.PP
- XThe file "notes.new" would contain all non-expired lines from "notes.old."
- XAll expired lines are echoed to the screen.
- X.I INCLUDEd
- Xfiles are read and processed, but not purged. You must purge each
- X.I INCLUDEd
- Xfile separately.
- X.PP
- XYou can supply a date on the command line when purging, but beware: If you
- Xsupply a date in the future, you may inadvertently purge lines which have not
- Xreally expired yet.
- X.SH DEBUGGING A REMINDER FILE
- XThe debug command-line option \-d is used to debug reminder files. It tells
- Xyou useful information about the reminder file. It displays the trigger date
- Xof each reminder, and places an asterisk by those which would be issued
- Xon the current date. It also informs you of
- X.I OMITs
- Xwhich have expired, and gives warnings about situations which could lead
- Xto long execution times or unexpected results.
- X.PP
- XAll debugging messages are sent to standard error.
- X.SH EXAMPLES OF REMINDERS
- XThis section is a sampling of what you can do with \fBremind\fR.
- X.PP
- X.nf
- X REM 5 Feb 1991 AT 14:00 +45 *30 \\
- X RUN mail -s "Meeting at %2" $LOGNAME </dev/null &
- X.fi
- X.PP
- XOn 5 February, 1991, this reminder will mail
- Xyou reminders of a 2:00pm meeting at 1:15,
- X1:45 and 2:00. The subject of the mail message will be "Meeting at 2:00pm"
- Xand the body of the message will be blank.
- X.PP
- X.nf
- X REM AT 17:00 RUN echo "5:00pm - GO HOME!" | xless -g +0+0 &
- X.fi
- X.PP
- XThis reminder will pop up an xless window at 5:00pm every day. The xless
- Xwindow will contain the line "5:00pm - GO HOME!"
- X.PP
- X.nf
- X REM AT 23:59 RUN (sleep 120; remind -a .reminders) &
- X.fi
- X.PP
- XThis reminder will run at one minute to midnight. It will cause a new
- Xremind process to start at one minute past midnight. This allows you to
- Xhave a continuous reminder service so you can work through the night and
- Xstill get timed reminders for early in the morning.
- X.PP
- X.nf
- X remind -c12 /dev/null 1 Jan 1991
- X.fi
- X.PP
- XThis invocation of \fBremind\fR will cause it to print a calendar for
- X1991, with all entries left blank.
- X.SH AUTHOR
- XDavid F. Skoll
- X.SH BUGS
- X.B Remind
- Xwas originally written for MS-DOS and ported to UNIX. It does some things
- Xin an ungainly way.
- X.PP
- XDate calculation algorithms are fairly "brute force."
- X.PP
- XThe MS-DOS version of \fBremind\fR does not support queuing or timed
- Xactivation of reminders. It does, however, support the other semantics
- Xof the \fIAT\fR keyword.
- X.PP
- X.B Remind
- Xhas some built-in limits on total line length (511 characters),
- Xthe length of an expanded \fIREM\fR body (511 characters), the number
- Xof global \fIOMIT\fRs, etc.
- SHAR_EOF
- $TOUCH -am 0218130591 remind.1 &&
- chmod 0600 remind.1 ||
- echo "restore of remind.1 failed"
- set `wc -c remind.1`;Wc_c=$1
- if test "$Wc_c" != "40229"; then
- echo original size 40229, current size $Wc_c
- fi
- fi
- echo "End of part 3, continue with part 4"
- exit 0
-