home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2788 < prev    next >
Internet Message Format  |  1991-02-19  |  61KB

  1. From: dfs@doe.carleton.ca (David F. Skoll)
  2. Newsgroups: alt.sources
  3. Subject: REMIND 2.3.0 3/4
  4. Message-ID: <dfs.666901128@data>
  5. Date: 18 Feb 91 18:18:48 GMT
  6.  
  7. #!/bin/sh
  8. # This is part 03 of Remind 2.3.0
  9. if touch 2>&1 | fgrep 'amc' > /dev/null
  10.  then TOUCH=touch
  11.  else TOUCH=true
  12. fi
  13. # ============= omits.c ==============
  14. if test X"$1" != X"-c" -a -f 'omits.c'; then
  15.     echo "File already exists: skipping 'omits.c'"
  16. else
  17. echo "x - extracting omits.c (Text)"
  18. sed 's/^X//' << 'SHAR_EOF' > omits.c &&
  19. X/***************************************************************/
  20. X/*                                                             */
  21. X/*  OMITS.C                                                    */
  22. X/*                                                             */
  23. X/*  By David Skoll - 12 February 1991                          */
  24. X/*                                                             */
  25. X/*  Handle all code related to global OMITs                    */
  26. X/*                                                             */
  27. X/***************************************************************/
  28. X#include <stdio.h>
  29. X#ifndef UNIX
  30. X#include <stdlib.h>
  31. X#endif
  32. X
  33. X#ifndef NO_MALLOC_H
  34. X#include <malloc.h>
  35. X#endif
  36. X
  37. X#include "defines.h"
  38. X#include "protos.h"
  39. X#include "globals.h"
  40. X
  41. X/* Define an OMIT stack buffer */
  42. Xtypedef struct omit_stack {
  43. X   struct omit_stack *next;
  44. X   int NumFullOmit;
  45. X   int NumPartOmit;
  46. X   int Omits[1];
  47. X} OmitBuffer;
  48. X
  49. X/* Variables that we only want visible here */
  50. Xstatic OmitBuffer *OmitStack = (OmitBuffer *) NULL;
  51. X
  52. X/***************************************************************/
  53. X/*                                                             */
  54. X/*  int DoGlobalOmit(char **s)                                 */
  55. X/*                                                             */
  56. X/*  Add an entry to the global ommissions array.  Either       */
  57. X/*  a fully-specified date, or a mm-yy type date.              */
  58. X/*  Return 0 if OK, -1 if date is in past, -2 if problem.      */
  59. X/*                                                             */
  60. X/***************************************************************/
  61. X#ifdef __STDC__
  62. Xint DoGlobalOmit(char **s)
  63. X#else
  64. Xint DoGlobalOmit(s)
  65. X     char **s;
  66. X#endif
  67. X{
  68. X   int d = -1, m = -1, y = -1;
  69. X   int omit;
  70. X   int *ptr;
  71. X   Token tok;
  72. X   char *olds = *s;
  73. X
  74. X   tok.type = Unknown_t;
  75. X   while(tok.type != Eol_t && tok.type != Run_t && tok.type != Msg_t) {
  76. X      tok = ParseToken(s);
  77. X      switch (tok.type) {
  78. X     case Year_t:  y = tok.val; break;
  79. X     case Month_t: m = tok.val; break;
  80. X     case Day_t:   d = tok.val; break;
  81. X
  82. X     case Delta_t:
  83. X     case Eol_t:
  84. X     case Msg_t:
  85. X     case Run_t: break;
  86. X     default:      Eprint("Invalid token '%s' for OMIT command.\n", tok.str);
  87. X               return -2;
  88. X      }
  89. X   }
  90. X
  91. X   if (d == -1 || m == -1 || CheckDate(d, m, y)) {
  92. X      Eprint("Invalid date specification.\n");
  93. X      return -2;
  94. X   }
  95. X
  96. X   if (y == -1) { /* Only mm-dd specified */
  97. X      if (NumPartOmit == POMITSIZE) {
  98. X     Eprint("Too many partially-specified OMITs.\n");
  99. X     return -2;
  100. X      }
  101. X      omit = (m << 5) + d;
  102. X      ptr = PartOmitArray + NumPartOmit;
  103. X      NumPartOmit++;
  104. X      while (ptr > PartOmitArray && *(ptr-1) > omit) {
  105. X     *ptr = *(ptr-1);
  106. X     ptr--;
  107. X      }
  108. X      *ptr = omit;
  109. X
  110. X      /* Check if the bonehead already has it - if so, delete it */
  111. X      if (ptr > PartOmitArray && *(ptr-1) == *ptr) {
  112. X     if (Debug) Eprint("Duplicated partially-specified OMIT.\n");
  113. X     NumPartOmit--;
  114. X     while (ptr < NumPartOmit+PartOmitArray) {
  115. X        *ptr = *(ptr + 1);
  116. X        ptr++;
  117. X     }
  118. X      }
  119. X      /* If we got a DELTA, a MSG or a RUN, then execute DoRem */
  120. X      if (tok.type == Delta_t || tok.type == Run_t || tok.type == Msg_t)
  121. X          return DoRem(&olds);
  122. X   } else { /* All three specified */
  123. X      if (NumFullOmit == FOMITSIZE) {
  124. X     Eprint("Too many fully-specified OMITs.\n");
  125. X     return -2;
  126. X      }
  127. X      omit = Julian(d, m, y);
  128. X
  129. X      ptr = FullOmitArray + NumFullOmit;
  130. X      NumFullOmit++;
  131. X      while (ptr > FullOmitArray && *(ptr-1) > omit) {
  132. X     *ptr = *(ptr-1);
  133. X     ptr--;
  134. X      }
  135. X      *ptr = omit;
  136. X
  137. X      /* Check if the bonehead already has it - if so, delete it */
  138. X      if (ptr > FullOmitArray && *(ptr-1) == *ptr) {
  139. X     if (Debug) Eprint("Duplicated fully-specified OMIT.\n");
  140. X     NumFullOmit--;
  141. X     while (ptr < NumFullOmit+FullOmitArray) {
  142. X        *ptr = *(ptr + 1);
  143. X        ptr++;
  144. X     }
  145. X      }
  146. X      if (omit < JulianToday) {
  147. X     if (Debug) Eprint("Omit has expired.\n");
  148. X     return -1;
  149. X      }
  150. X      /* If we got a DELTA, a MSG or a RUN, then execute DoRem */
  151. X      if (tok.type == Delta_t || tok.type == Run_t || tok.type == Msg_t)
  152. X         return DoRem(&olds);
  153. X   }
  154. X   return 0;
  155. X}
  156. X
  157. X/***************************************************************/
  158. X/*                                                             */
  159. X/* PushOmitContext                                             */
  160. X/*                                                             */
  161. X/* Push the Global OMIT context onto a stack.                  */
  162. X/*                                                             */
  163. X/* Returns 0 for success, 1 for failure.                       */
  164. X/*                                                             */
  165. X/***************************************************************/
  166. X#ifdef __STDC__
  167. Xint PushOmitContext(void)
  168. X#else
  169. Xint PushOmitContext()
  170. X#endif
  171. X{
  172. X   OmitBuffer *new = (OmitBuffer *) malloc( sizeof(OmitBuffer) +
  173. X                     (NumFullOmit + NumPartOmit - 1) * sizeof(int));
  174. X
  175. X   if (!new) {
  176. X      Eprint("Unable to allocate memory for PUSH-OMIT-CONTEXT.\n");
  177. X      return 1;
  178. X   }
  179. X
  180. X   new->NumFullOmit = NumFullOmit;
  181. X   new->NumPartOmit = NumPartOmit;
  182. X
  183. X   CopyInts(FullOmitArray, &(new->Omits[0]), NumFullOmit);
  184. X   CopyInts(PartOmitArray, &(new->Omits[NumFullOmit]), NumPartOmit);
  185. X
  186. X   new->next = OmitStack;
  187. X   OmitStack = new;
  188. X
  189. X   return 0;
  190. X}
  191. X
  192. X/***************************************************************/
  193. X/*                                                             */
  194. X/* PopOmitContext                                              */
  195. X/*                                                             */
  196. X/* Restore the OMIT context from the stack.                    */
  197. X/*                                                             */
  198. X/* Returns 0 for success, 1 for failure.                       */
  199. X/*                                                             */
  200. X/***************************************************************/
  201. X#ifdef __STDC__
  202. Xint PopOmitContext(void)
  203. X#else
  204. Xint PopOmitContext()
  205. X#endif
  206. X{
  207. X
  208. X   OmitBuffer *temp;
  209. X
  210. X   if (!OmitStack) {
  211. X      Eprint("No saved contexts for POP-OMIT-CONTEXT.\n");
  212. X      return 1;
  213. X   }
  214. X
  215. X   NumFullOmit = OmitStack->NumFullOmit;
  216. X   NumPartOmit = OmitStack->NumPartOmit;
  217. X
  218. X   CopyInts(&(OmitStack->Omits[0]), FullOmitArray, NumFullOmit);
  219. X   CopyInts(&(OmitStack->Omits[NumFullOmit]), PartOmitArray, NumPartOmit);
  220. X
  221. X   temp = OmitStack->next;
  222. X   free(OmitStack);
  223. X   OmitStack = temp;
  224. X   return 0;
  225. X}
  226. X
  227. X/***************************************************************/
  228. X/*                                                             */
  229. X/*  ClearOmitContext                                           */
  230. X/*                                                             */
  231. X/*  Get rid of all global OMITS.                               */
  232. X/*                                                             */
  233. X/***************************************************************/
  234. X#ifdef __STDC__
  235. Xvoid ClearOmitContext(void)
  236. X#else
  237. Xvoid ClearOmitContext()
  238. X#endif
  239. X{
  240. X   NumFullOmit = NumPartOmit = 0;
  241. X}
  242. X
  243. X/***************************************************************/
  244. X/*                                                             */
  245. X/*  CopyInts                                                   */
  246. X/*                                                             */
  247. X/*  Copy integer values from one array to another.             */
  248. X/*                                                             */
  249. X/***************************************************************/
  250. X#ifdef __STDC__
  251. Xvoid CopyInts(int *from, int *to, int count)
  252. X#else
  253. Xvoid CopyInts(from, to, count)
  254. Xint *from, *to, count;
  255. X#endif
  256. X{
  257. X   while (count--) *to++ = *from++;
  258. X}
  259. X
  260. X/***************************************************************/
  261. X/*                                                             */
  262. X/*  FreeStackedOmits                                           */
  263. X/*                                                             */
  264. X/*  Get rid of all the stacked OMIT contexts                   */
  265. X/*                                                             */
  266. X/***************************************************************/
  267. X#ifdef __STDC__
  268. Xvoid FreeStackedOmits(void)
  269. X#else
  270. Xvoid FreeStackedOmits()
  271. X#endif
  272. X{
  273. X   OmitBuffer *current = OmitStack, *next;
  274. X
  275. X   if (current && Debug) Eprint("Warning - more PUSH-OMIT-CONTEXTs than POP-OMIT-CONTEXTs\n");
  276. X
  277. X   while (current) {
  278. X      next = current->next;
  279. X      free(current);
  280. X      current = next;
  281. X   }
  282. X
  283. X   OmitStack = (OmitBuffer *) NULL;
  284. X}
  285. X
  286. X/***************************************************************/
  287. X/*                                                             */
  288. X/* IsOmitted                                                   */
  289. X/*                                                             */
  290. X/* Returns non-zero if the julian date should be omitted, 0    */
  291. X/* otherwise.                                                  */
  292. X/*                                                             */
  293. X/***************************************************************/
  294. X#ifdef __STDC__
  295. Xint IsOmitted(int jul, int localomit)
  296. X#else
  297. Xint IsOmitted(jul, localomit)
  298. Xint jul, localomit;
  299. X#endif
  300. X{
  301. X   int d, m, y;
  302. X
  303. X   /* Check if we should omit because of local omit */
  304. X   if (localomit & 1 << (jul % 7)) return 1;
  305. X
  306. X   /* Check if we should omit because of fully-specified global omit */
  307. X   if (NumFullOmit && my_bsearch(jul, FullOmitArray, NumFullOmit)) return 1;
  308. X
  309. X   /* Check if we should omit because of partially-specified global omits */
  310. X   if (NumPartOmit) {
  311. X      FromJulian(jul, &d, &m, &y);
  312. X      if (my_bsearch((m << 5)+d, PartOmitArray, NumPartOmit)) return 1;
  313. X   }
  314. X
  315. X   /* Looks cool - don't omit */
  316. X   return 0;
  317. X}
  318. X
  319. X/***************************************************************/
  320. X/*                                                             */
  321. X/*  my_bsearch                                                 */
  322. X/*                                                             */
  323. X/*  A simplified version of bsearch() for people whose library */
  324. X/*  does not have the full version.  This only works when      */
  325. X/*  searching a sorted array of integers.                      */
  326. X/*                                                             */
  327. X/***************************************************************/
  328. X#ifdef __STDC__
  329. Xint *my_bsearch(int key, int *array, int number)
  330. X#else
  331. Xint *my_bsearch(key, array, number)
  332. Xint key, *array, number;
  333. X#endif
  334. X{
  335. X   int top = number - 1;
  336. X   int bot = 0;
  337. X   int mid;
  338. X
  339. X   while (top >= bot) {
  340. X      mid = (top+bot)/2;
  341. X      if (*(array+mid) == key) return array+mid;
  342. X      else if (*(array+mid) > key) top = mid-1;
  343. X      else bot = mid+1;
  344. X   }
  345. X
  346. X   /* Oh, well - unsuccessful search.  Return NULL */
  347. X   return NULL;
  348. X}
  349. SHAR_EOF
  350. $TOUCH -am 0218130591 omits.c &&
  351. chmod 0600 omits.c ||
  352. echo "restore of omits.c failed"
  353. set `wc -c omits.c`;Wc_c=$1
  354. if test "$Wc_c" != "10630"; then
  355.     echo original size 10630, current size $Wc_c
  356. fi
  357. fi
  358. # ============= protos.h ==============
  359. if test X"$1" != X"-c" -a -f 'protos.h'; then
  360.     echo "File already exists: skipping 'protos.h'"
  361. else
  362. echo "x - extracting protos.h (Text)"
  363. sed 's/^X//' << 'SHAR_EOF' > protos.h &&
  364. X
  365. X/* Function Prototypes go here */
  366. X
  367. X#ifdef __STDC__
  368. Xint   CheckDate   (int d,   int m,  int y);
  369. Xvoid  ClearOmitContext(void);
  370. Xvoid  CopyInts    (int *from, int *to, int count);
  371. Xint   DoBanner    (char **s);
  372. Xvoid  DoCalendar  (void);
  373. Xint   DoGlobalOmit(char **s);
  374. Xvoid  DoInclude   (char **s);
  375. Xint   DoRem       (char **s);
  376. Xint   DoSubst     (char *src, char *dst, int d, int m, int y, int jul, enum Token_t t, int tim, int mode);
  377. Xint   FindTodaysDate(int *d, int *m, int *y);
  378. Xvoid  FreeStackedOmits (void);
  379. Xint   FromJulian  (int jul, int *d, int *m, int *y);
  380. Xint   GetTriggerDate (int d, int m, int y, int wd, int cons, int back, int repeat, int omit, int skip);
  381. Xint   IsOmitted   (int jul, int localomit);
  382. Xvoid  HandleQueuedAts(void);
  383. Xvoid  initialize  (int argc, char *argv[]);
  384. Xint   int_comp    (int *, int *);
  385. Xint   Julian      (int d,   int m,  int y);
  386. Xint   MoveBack    (int jul, int back, int omit);
  387. Xint   *my_bsearch (int key, int *array, int number);
  388. Xvoid  OpenFile    (char *s);
  389. Xvoid  Output      (char *s);
  390. XToken ParseToken  (char **s);
  391. Xint   PopOmitContext (void);
  392. Xint   PushOmitContext (void);
  393. Xint   ProcessLine (void);
  394. Xint   ReadLine    (void);
  395. Xvoid  SigIntHandler (void);
  396. Xlong  SystemTime  (void);
  397. Xint   TopLevel    (void);
  398. Xint   TryNextDate(int *retday, int *retmon, int *retyr,
  399. X          int startday, int startmon, int startyr,
  400. X          int conday, int conmon, int conyr,
  401. X          int wkday, int cons, int inc);
  402. X#else
  403. Xint   CheckDate   ();
  404. Xvoid  ClearOmitContext();
  405. Xvoid  CopyInts    ();
  406. Xint   DoBanner    ();
  407. Xvoid  DoCalendar  ();
  408. Xint   DoGlobalOmit();
  409. Xvoid  DoInclude   ();
  410. Xint   DoRem       ();
  411. Xint   DoSubst     ();
  412. Xint   FindTodaysDate();
  413. Xvoid  FreeStackedOmits();
  414. Xint   FromJulian  ();
  415. Xint   GetTriggerDate();
  416. Xint   IsOmitted   ();
  417. Xvoid  HandleQueuedAts();
  418. Xvoid  initialize  ();
  419. Xint   int_comp    ();
  420. Xint   Julian      ();
  421. Xint   MoveBack    ();
  422. Xint  *my_bsearch  ();
  423. Xvoid  OpenFile    ();
  424. Xvoid  Output      ();
  425. XToken ParseToken  ();
  426. Xint   PopOmitContext ();
  427. Xint   ProcessLine ();
  428. Xint   PushOmitContext ();
  429. Xint   ReadLine    ();
  430. Xvoid  SigIntHandler();
  431. Xlong  SystemTime  ();
  432. Xint   TopLevel    ();
  433. Xint   TryNextDate ();
  434. X#endif
  435. X
  436. X#ifndef UNIX
  437. Xvoid  Eprint(const char *f, ...);
  438. X#else
  439. Xvoid  Eprint();
  440. X#endif
  441. SHAR_EOF
  442. $TOUCH -am 0218130591 protos.h &&
  443. chmod 0600 protos.h ||
  444. echo "restore of protos.h failed"
  445. set `wc -c protos.h`;Wc_c=$1
  446. if test "$Wc_c" != "2210"; then
  447.     echo original size 2210, current size $Wc_c
  448. fi
  449. fi
  450. # ============= remind-all.csh ==============
  451. if test X"$1" != X"-c" -a -f 'remind-all.csh'; then
  452.     echo "File already exists: skipping 'remind-all.csh'"
  453. else
  454. echo "x - extracting remind-all.csh (Text)"
  455. sed 's/^X//' << 'SHAR_EOF' > remind-all.csh &&
  456. X#!/bin/csh -f
  457. X
  458. X# Shell script to mail all users reminders.
  459. X
  460. X# Run it AFTER MIDNIGHT so that date is correct!
  461. X# On our system, we have the following in our crontab:
  462. X# 05 5 * * * /usr/share/lib/remind/remind-all > /dev/null 2>&1
  463. X
  464. X# Also, you MUST use the -r and -q options on REMIND, otherwise SEVERE
  465. X# security hole could develop.  I recommend making this script
  466. X# readable and executable only by root to minimize security problems.
  467. X# DO NOT make the script setuid!
  468. X
  469. X# The following line gets a list of users for systems using SUN's
  470. X# NIS service:
  471. Xset USERS  = `ypcat passwd | awk -F: '{print $1}'`
  472. X
  473. X# The following line gets a list of users by examining /etc/passwd:
  474. X# set USERS = `awk -F: '{print $1}' /etc/passwd`
  475. X
  476. X# If neither of the above methods works, you must come up with some
  477. X# way of getting a list of users on the system
  478. X
  479. X# Set the following variables as appropriate for your system
  480. Xset REMIND = /usr/local/bin/remind
  481. Xset MAIL   = /usr/ucb/mail
  482. Xset CMP    = /usr/bin/cmp
  483. Xset RM     = "/usr/bin/rm -f"
  484. X
  485. Xset EMPTY  = /tmp/Empty.$$
  486. Xset FULL   = /tmp/Full.$$
  487. X
  488. X# Create the dummy empty reminder file
  489. X$REMIND -rq /dev/null > $EMPTY
  490. X
  491. X# Scan each user's directory for a .reminders file
  492. Xforeach i ($USERS)
  493. X   if (-r ~$i/.reminders) then
  494. X
  495. X#     echo "$i has a .reminders file."     DEBUGGING PURPOSES ONLY
  496. X
  497. X      $REMIND -rq ~$i/.reminders > $FULL
  498. X      $CMP -s $EMPTY $FULL
  499. X      if ($status != 0) then
  500. X
  501. X#        echo "Sending mail to $i"         DEBUGGING PURPOSES ONLY
  502. X
  503. X         $MAIL -s "Reminders" $i < $FULL
  504. X      endif
  505. X      $RM $FULL
  506. X   endif
  507. Xend
  508. X
  509. X$RM $EMPTY
  510. SHAR_EOF
  511. $TOUCH -am 0218130591 remind-all.csh &&
  512. chmod 0600 remind-all.csh ||
  513. echo "restore of remind-all.csh failed"
  514. set `wc -c remind-all.csh`;Wc_c=$1
  515. if test "$Wc_c" != "1568"; then
  516.     echo original size 1568, current size $Wc_c
  517. fi
  518. fi
  519. # ============= remind-all.sh ==============
  520. if test X"$1" != X"-c" -a -f 'remind-all.sh'; then
  521.     echo "File already exists: skipping 'remind-all.sh'"
  522. else
  523. echo "x - extracting remind-all.sh (Text)"
  524. sed 's/^X//' << 'SHAR_EOF' > remind-all.sh &&
  525. X# Shell script to mail all users reminders.
  526. X
  527. X# Thanks to Bill Aten for this script.
  528. X
  529. X# Run it AFTER MIDNIGHT so that date is correct!
  530. X# On our system, we have the following in our crontab:
  531. X# 02 00 * * * /usr/local/adm/remind-all >/dev/null 2>&1
  532. X
  533. X# Also, you MUST use the -r and -q options on REMIND, otherwise a SEVERE
  534. X# security hole could develop.  I recommend making this script
  535. X# readable and executable only by root to minimize security problems.
  536. X# DO NOT make the script setuid!
  537. X
  538. X# The following line gets a list of users for systems using SUN's
  539. X# NIS service:
  540. X# USERS=`ypcat passwd | awk -F: '{print $1}'`
  541. X
  542. X# The following line gets a list of users by examining /etc/passwd:
  543. XUSERS=`awk -F: '{print $1}' /etc/passwd`
  544. X
  545. X# If neither of the above methods works, you must come up with some
  546. X# way of getting a list of users on the system
  547. X
  548. X# Set the following variables as appropriate for your system
  549. XREMIND=/usr/local/bin/remind
  550. XMAIL=/usr/bin/mail
  551. XCMP=/bin/cmp
  552. XRM="/bin/rm -f"
  553. X
  554. XEMPTY=/tmp/Empty.$$
  555. XFULL=/tmp/Full.$$
  556. X
  557. X# Create the dummy empty reminder file
  558. X$REMIND -rq /dev/null > $EMPTY
  559. X
  560. X# Scan each user's directory for a .reminders file
  561. Xfor i in $USERS
  562. Xdo
  563. XHOME=`grep \^$i: /etc/passwd | awk -F: '{print $6}'`
  564. X   if [ -r $HOME/.reminders ]; then
  565. X
  566. X#     echo "$i has a .reminders file."     DEBUGGING PURPOSES ONLY
  567. X
  568. X      $REMIND -rq $HOME/.reminders > $FULL
  569. X      if `$CMP -s $EMPTY $FULL`; then
  570. X         : do nothing
  571. X      else
  572. X
  573. X#        echo "Sending mail to $i"         DEBUGGING PURPOSES ONLY
  574. X
  575. X         $MAIL -s "Reminders" $i < $FULL
  576. X      fi
  577. X      $RM $FULL
  578. X   fi
  579. Xdone
  580. X
  581. X$RM $EMPTY
  582. SHAR_EOF
  583. $TOUCH -am 0218130591 remind-all.sh &&
  584. chmod 0600 remind-all.sh ||
  585. echo "restore of remind-all.sh failed"
  586. set `wc -c remind-all.sh`;Wc_c=$1
  587. if test "$Wc_c" != "1589"; then
  588.     echo original size 1589, current size $Wc_c
  589. fi
  590. fi
  591. # ============= remind.1 ==============
  592. if test X"$1" != X"-c" -a -f 'remind.1'; then
  593.     echo "File already exists: skipping 'remind.1'"
  594. else
  595. echo "x - extracting remind.1 (Text)"
  596. sed 's/^X//' << 'SHAR_EOF' > remind.1 &&
  597. X.TH REMIND 1 "18 February 1991"
  598. X.UC 4
  599. X.SH NAME
  600. Xremind \- a sophisticated reminder service
  601. X.SH SYNOPSIS
  602. X.B remind
  603. X[\fB\-n | \fB\-d\fR | \fB\-p\fR | \fB\-c\fR\fIn\fR [\fB\-w\fR\fIn\fR | \fB\-s\fR]]
  604. X[\fB\-voraq\fR]
  605. X.I filename
  606. X[\fIdate\fR]
  607. X.SH DESCRIPTION
  608. X.B remind
  609. Xreads the supplied
  610. X.I filename
  611. Xfor a list of reminders, and then issues reminders appropriate for
  612. Xthe current date.
  613. XEach reminder can consist of a message sent to standard output, or
  614. Xa program to be executed.
  615. X.SH OPTIONS
  616. X.TP
  617. X.B \-n
  618. XThe \fB\-n\fR flag causes \fBremind\fR to print the \fInext\fR occurrence
  619. Xof each reminder in a simple calendar format.  You can sort this by date by
  620. Xpiping the output through \fBsort(1)\fR.
  621. X.TP
  622. X.B \-d
  623. XThe
  624. X.B \-d
  625. Xflag causes
  626. X.B remind
  627. Xto enter a debugging mode.
  628. XIn this mode, each reminder in the reminder file is examined and its
  629. Xtrigger date is printed to standard output.  Also, some consistency
  630. Xchecking is done, and warnings are issued about constructs which could
  631. Xresult in slow execution times.
  632. X.TP
  633. X.B \-p
  634. XThe
  635. X.B \-p
  636. Xflag causes
  637. X.B remind
  638. Xto go into
  639. X.I purge
  640. Xmode.  This mode is incompatible with the
  641. X.B \-d
  642. Xflag.  It causes
  643. X.B remind
  644. Xto scan the reminder file and echo all reminders which have not expired
  645. Xto the standard output.  All expired reminders are echoed to the standard
  646. Xerror stream.
  647. X.TP
  648. X.B \-c\fR\fIn\fR
  649. XThe
  650. X.B \-c
  651. Xflag causes \fBremind\fR to generate a calendar with reminders indicated on
  652. Xthe calendar.  The calendar printout is formatted and sent to standard output.
  653. XIf you supply a number \fIn\fR from 1 to 12, 
  654. Xthen a calendar will be generated for
  655. X\fIn\fR months, starting with the current month.  The default is to
  656. Xproduce a calendar for one month only.  The
  657. X.B \-c
  658. Xoption is not compatible with the \fB\-p\fR or \fB\-d\fR options.
  659. X.TP
  660. X.B \-w\fR\fIn\fR
  661. XThe \fB\-w\fR flag, when used in conjunction with \fB\-c\fR,
  662. Xcauses \fBremind\fR to format the calendar for a device
  663. Xwhose output width is \fIn\fR columns.  The default is to produce a calendar
  664. Xfor an 80-column device.
  665. X.TP
  666. X.B \-s
  667. XThe \fB\-s\fB flag, when used in conjunction with \fB\-c\fR,
  668. Xcauses \fBremind\fR to send an unformatted "simple
  669. Xcalendar" listing to standard output.  This can be used if you wish to
  670. Xformat the calendar with another program rather than using \fBremind\fR's
  671. Xbuilt-in calendar format.
  672. X.TP
  673. X.B \-v
  674. XThe
  675. X.B \-v
  676. Xflag causes the debugging messages caused by
  677. X.B \-d
  678. Xto be printed in a verbose manner.  Also, any error messages issued by
  679. X.B remind
  680. Xare printed in verbose format.
  681. X.TP
  682. X.B \-o
  683. XThe
  684. X.B \-o
  685. Xflag causes
  686. X.B remind
  687. Xto ignore any
  688. X.B ONCE
  689. Xdirectives in the reminder file.
  690. X.TP
  691. X.B \-r
  692. XThe
  693. X.B \-r
  694. Xflag causes
  695. X.B remind
  696. Xto ignore any
  697. X.B RUN
  698. Xdirectives in the reminder file.
  699. X.TP
  700. X.B \-a
  701. XThe
  702. X.B \-a
  703. Xoption causes
  704. X.B remind
  705. Xnot to issue
  706. X.B AT
  707. Xreminders when the reminder file is read and processed, providing the
  708. X.B AT
  709. Xreminders would normally be queued.  This allows you to have
  710. X.B remind
  711. Xqueue
  712. X.B AT
  713. Xreminders without triggering them when it reads the file.
  714. X.TP
  715. X.B \-q
  716. XThe
  717. X.B \-q
  718. Xflag causes
  719. X.B remind
  720. Xnot to queue
  721. X.B AT
  722. Xreminders for triggering later in the day.  This prevents
  723. X.B remind
  724. Xfrom running as a daemon and popping up reminders as they are triggered.
  725. X.PP
  726. XIf you supply a
  727. X.I date
  728. Xon the command line, it must consist of
  729. X.I day month year
  730. Xwhere
  731. X.I day
  732. Xis the day of the month,
  733. X.I month
  734. Xis (at least the first three letters of) the English name of the month,
  735. Xand
  736. X.I year
  737. Xis a year (all 4 digits) from 1990 to 2075.  These components can appear
  738. Xin any order, but must be separated by spaces.  If a date is supplied,
  739. X.B remind
  740. Xuses it rather than the actual system date as its notion of "today."  You
  741. Xcan use this feature to test how reminders will appear in the future, or
  742. Xto produce a calendar for any month you choose.
  743. X.SH REMINDER FILES
  744. X.B Remind
  745. Xuses scripts called
  746. X.I reminder files
  747. Xto control its operation.  A sample reminder file is shown below:
  748. X.PP
  749. X.nf
  750. X    #!/usr/local/bin/remind
  751. X    # Sample file
  752. X    BANNER Hi there.  Here are your reminders:
  753. X
  754. X    # First some birthdays
  755. X    REM 6 Jan MSG David's birthday.
  756. X    REM 23 Nov +10 MSG El's birthday is %a.
  757. X
  758. X    # Next some housekeeping
  759. X    REM 1 -1 OMIT Sat Sun RUN do_backup
  760. X
  761. X    # Introduce some holidays
  762. X    OMIT 25 Dec +2 MSG %"Christmas%" is %b.
  763. X    OMIT  1 July MSG Canada Day
  764. X    OMIT 22 Nov 1990    # American Thanksgiving
  765. X
  766. X    # Business things
  767. X    REM 23 Nov 1990 +2 AT 10:00 +30 *15 MSG \\
  768. X    %"Meeting with Bill%" at %1 %b.%_Bring papers!
  769. X
  770. X.fi
  771. X.PP
  772. XNote that
  773. X.B remind
  774. Xignores blank lines and lines beginning with "#".  If the character '\\'
  775. Xis the LAST character on the line, it is treated as a continuation
  776. Xcharacter.  You can string many lines together using this character.
  777. XNote that if you use line continuation, then
  778. X.B remind
  779. Xuses the line number of the last line when printing diagnostic messages.
  780. X.PP
  781. XCommands, names of months, etc. can be typed in any
  782. Xmixture of upper- and lower-case.  The convention I use is to
  783. Xuse upper-case for
  784. X.B remind
  785. Xtokens like
  786. X.I
  787. XMSG, OMIT,
  788. Xetc., and mixed case for other words like
  789. X.I January
  790. Xand
  791. X.I Sunday.
  792. X.SH THE REM COMMAND
  793. XThe most-used command in a reminder file is the
  794. X.I REM
  795. Xcommand.  This command is used to denote a reminder.  There are many
  796. Xforms of the
  797. X.I REM
  798. Xcommand; they are represented by:
  799. X.PP
  800. X.RS
  801. XREM [ONCE] [\fIdate_spec\fR]
  802. X[\fIdelta\fR]
  803. X[\fIback\fR]
  804. X[\fIrepeat\fR]
  805. X[\fISKIP\fR | \fIBEFORE\fR | \fIAFTER\fR]
  806. X[OMIT \fIomit_list\fR]
  807. X[AT \fItime\fR [\fItdelta\fR] [\fItrepeat\fR]]
  808. X[UNTIL \fIexpiry_date\fR]
  809. XMSG|RUN
  810. X.I body
  811. X.RE
  812. X.PP
  813. XThe parts of the \fIREM\fR command can be specified in any order, except
  814. Xthat the \fIbody\fR must come immediately after the \fIMSG\fR or \fIRUN\fR
  815. Xkeyword.
  816. X.SH DATE SPECIFICATIONS
  817. XThe
  818. X.I date_spec
  819. Xconsists of zero to four parts.  These parts are
  820. X.I day
  821. X(day of month),
  822. X.I month
  823. X(month name),
  824. X.I year
  825. Xand
  826. X.I weekday.
  827. X.I Month
  828. Xand
  829. X.I weekday
  830. Xare the English names of months and weekdays.  At least the first three
  831. Xcharacters must be used.  Case is irrelevant.  The following are examples
  832. Xof the various parts of a
  833. X.I date_spec:
  834. X.TP
  835. X.I day:
  836. X1, 22, 31, 14, 3
  837. X.TP
  838. X.I month:
  839. XJANUARY, feb, March, ApR, may, Aug
  840. X.TP
  841. X.I year:
  842. X1990, 1993, 2030, 95 (interpreted as 1995).  The year can range
  843. Xfrom 1990 to 2075.
  844. X.TP
  845. X.I weekday:
  846. XMonday, tue, Wed, THU, Friday, saturday, sundAy
  847. X.PP
  848. XNote that there can be several
  849. X.I weekday
  850. Xcomponents separated by spaces in a
  851. X.I date_spec.
  852. X.PP
  853. X.B INTERPRETATION OF DATE SPECIFICATIONS
  854. X.PP
  855. XThe following examples show how date specifications are interpreted.
  856. X.PP
  857. X1. Null date specification - the reminder is triggered every day.
  858. XThe trigger date for a specific run is simply the current system date.
  859. X.PP
  860. X2. Only
  861. X.I day
  862. Xpresent.  The reminder is triggered on the specified day of each month.
  863. XThe trigger date for a particular run is the closest such day to the
  864. Xcurrent system date.  For example:
  865. X.nf
  866. X    REM 1 MSG First of every month.
  867. X    REM 31 MSG 31st of every month that has 31 days.
  868. X.fi
  869. X.PP
  870. X3. Only
  871. X.I month
  872. Xpresent.  The reminder is triggered every day of the specified month.
  873. XExample:
  874. X.nf
  875. X    REM Feb MSG Every day in February
  876. X.fi
  877. X.PP
  878. X4.
  879. X.I day
  880. Xand
  881. X.I month
  882. Xpresent.  Examples:
  883. X.nf
  884. X    REM 6 Jan MSG Every 6th of January
  885. X    REM Feb 29 MSG Every 29th of February
  886. X.fi
  887. X.PP
  888. X5.  Only
  889. X.I year
  890. Xpresent. Example:
  891. X.nf
  892. X    REM 1991 MSG Every day in 1991
  893. X.fi
  894. X.PP
  895. X6.
  896. X.I year
  897. Xand
  898. X.I day
  899. Xpresent.  Examples:
  900. X.nf
  901. X    REM 1 1990 MSG 1st of every month in 1990
  902. X    REM 1992 23 MSG 23rd of every month in 1992
  903. X.fi
  904. X.PP
  905. X7.
  906. X.I year
  907. Xand
  908. X.I month
  909. Xpresent.  Examples:
  910. X.nf
  911. X    REM Feb 1991 MSG Every day in Feb 1991
  912. X    REM 1992 September MSG Every day in Sept 1992
  913. X.fi
  914. X.PP
  915. X8.
  916. X.I year, month
  917. Xand
  918. X.I day
  919. Xpresent.  Examples:
  920. X.nf
  921. X    REM 8 Jan 1991 MSG 8th January 1991.
  922. X    REM 1992 March 9 MSG 9th March 1992.
  923. X.fi
  924. X.PP
  925. X9.
  926. X.I weekday
  927. Xonly.  Examples:
  928. X.nf
  929. X    REM Sat MSG Every Saturday
  930. X    REM Mon Tue Wed Thu Fri MSG Every working day
  931. X    REM Monday Wednesday MSG Every Monday and Wednesday
  932. X.fi
  933. X.PP
  934. X10.
  935. X.I weekday
  936. Xand
  937. X.I day
  938. Xpresent.  Examples:
  939. X.nf
  940. X    REM Sat 1 MSG First Saturday of every month
  941. X    REM Mon Tue Wed Thu Fri 15 \\
  942. X        MSG 1st working day after 15th of every month
  943. X.fi
  944. X.PP
  945. X11.
  946. X.I weekday
  947. Xand
  948. X.I month
  949. Xpresent.  Examples:
  950. X.nf
  951. X    REM Mon March MSG Every Monday in March
  952. X    REM Mon Tue Wed Thu Fri Feb MSG Every working day in February
  953. X.fi
  954. X.PP
  955. X12.
  956. X.I weekday, month
  957. Xand
  958. X.I day
  959. Xpresent.  Examples:
  960. X.nf
  961. X    REM Mon 1 March MSG First Monday in March
  962. X    REM Sat Sun 15 July MSG First Sat or Sun on or after 15 July
  963. X.fi
  964. X.PP
  965. X13.
  966. X.I weekday
  967. Xand
  968. X.I year
  969. Xpresent.  Example:
  970. X.nf
  971. X    REM Sat Sun 1991 MSG Every Saturday and Sunday in 1991
  972. X.fi
  973. X.PP
  974. X14.
  975. X.I weekday, day
  976. Xand
  977. X.I year
  978. Xpresent.  Examples:
  979. X.nf
  980. X    REM Mon 15 1990 MSG 1st Mon after 15th of every month in 1990
  981. X    REM Mon Tue Wed Thu Fri 1 1990 \\
  982. X        MSG 1st working day of every month in 1990
  983. X.fi
  984. X.PP
  985. X15.
  986. X.I weekday, month
  987. Xand
  988. X.I year
  989. Xpresent.  Example:
  990. X.nf
  991. X    REM Mon Wed 1991 Feb MSG Every Mon and Wed in Feb 1991.
  992. X.fi
  993. X.PP
  994. X16.
  995. X.I weekday, day, month
  996. Xand
  997. X.I year
  998. Xpresent.  Example:
  999. X.nf
  1000. X    REM Mon Tue Wed Thu Fri 28 Oct 1990 \\
  1001. X        MSG 1st working day on or after 28 October 1990.
  1002. X.fi
  1003. X.PP
  1004. XNote that when
  1005. X.I weekday
  1006. Xand
  1007. X.I day
  1008. Xare specified,
  1009. X.B remind
  1010. Xchooses the first date on or after the specified
  1011. X.I day
  1012. Xwhich also satisfies the
  1013. X.I weekday
  1014. Xconstraint.  It does this by picking the first date on or after the specified
  1015. X.I day
  1016. Xwhich is listed in the list of
  1017. X.I weekdays.
  1018. XThus, a reminder like:
  1019. X.PP
  1020. X.nf
  1021. X    REM Mon Tue 28 Oct 1990 MSG Hi
  1022. X.fi
  1023. X.PP
  1024. Xwould be issued only on Monday, 29 October, 1990.  It would not be issued
  1025. Xon Tuesday, 30 October, 1990, since the 29th is the first date to satisfy
  1026. Xthe
  1027. X.I weekday
  1028. Xconstraints.
  1029. X.PP
  1030. X.B BACKWARD SCANNING
  1031. X.PP
  1032. XSometimes, you need to incorporate "backward scanning" into your date
  1033. Xspecification.  This is accomplished with the
  1034. X.I back
  1035. Xpart of the reminder specification.  If present, the
  1036. X.I back
  1037. Xis specified as a number preceded by one or two minus signs.  This causes
  1038. X.B remind
  1039. Xto compute the trigger date as usual, and then move back the specified
  1040. Xnumber of days.  For example:
  1041. X.PP
  1042. X.nf
  1043. X    REM Mon 1 -7 MSG Last Monday of every month.
  1044. X.fi
  1045. X.PP
  1046. XThis works by finding the first Monday of every month, and then moving
  1047. X"back" seven days.  This results in the last Monday of the previous
  1048. Xmonth.  (Warning:  If you have global 
  1049. X.I OMITs, 
  1050. Xthis might not work - see
  1051. Xthe 
  1052. X.I OMIT 
  1053. Xcommand.  In this case, you can use the "definite \fIback\fR" which consists
  1054. Xof a number preceded by two minus signs like \-\-7)
  1055. X.PP
  1056. XAnother example is:
  1057. X.PP
  1058. X.nf
  1059. X    REM 1 -1 MSG Last day of every month.
  1060. X.fi
  1061. X.PP
  1062. XSince we don't know how many days are in a month, to get to the last day
  1063. Xof a month, we go to the first day of the next month and then move back
  1064. Xone day.
  1065. X.PP
  1066. X.B Remind
  1067. Xwill automatically scan forwards and backwards until it finds a suitable
  1068. Xtrigger date.  Note that large
  1069. X.I back
  1070. Xvalues can lead to a lot of backtracking and slow the execution of
  1071. X.B remind.
  1072. X.PP
  1073. X.B ADVANCE WARNING
  1074. X.PP
  1075. X.B Remind
  1076. Xcan warn you of an upcoming reminder as far in advance as you desire.  This
  1077. Xis specified by a
  1078. X.I delta,
  1079. Xwhich is a positive number preceded by one or two "+" signs.  For example:
  1080. X.PP
  1081. X.nf
  1082. X    REM 8 Jan 1992 +3 MSG Test1
  1083. X    REM 1 +1 MSG Test2
  1084. X.fi
  1085. X.PP
  1086. XThe reminder "Test1" will be triggered on the 8th of January, 1992, as well
  1087. Xas the 3 days preceding it.  All told, "Test1" will be triggered on the
  1088. X5th through the 8th of January, 1992.
  1089. X.PP
  1090. XThe reminder "Test2" will be triggered on the first day of every month, as
  1091. Xwell as the day before.  In effect, "Test2" will be triggered on the first
  1092. Xand last day of every month.
  1093. X.PP
  1094. X.I Delta
  1095. Xand
  1096. X.I back
  1097. Xcan be combined:
  1098. X.PP
  1099. X.nf
  1100. X    REM Mon 1 --7 ++3 MSG Test3
  1101. X.fi
  1102. X.PP
  1103. XThe reminder "Test3" will be triggered on the last Monday of every month,
  1104. Xas well as the three days preceding it.
  1105. X.PP
  1106. XSee "The OMIT Command" for an explanation of the distinction between the "-"
  1107. Xand "--" forms of the \fIback\fR, and the "+" and "++" forms of the
  1108. X\fIdelta\fR.
  1109. X.PP
  1110. X.B REPEATING REMINDERS
  1111. X.PP
  1112. XThe
  1113. X.I repeat
  1114. Xcomponent in a reminder is a number preceded by an asterisk; for example,
  1115. X"*14".  The
  1116. X.I repeat
  1117. Xis used to remind you of events which occur regularly after a specified
  1118. Xstart date.  For example, suppose you get paid every second Thursday,
  1119. Xand that your last payday was 8 November 1990.  The following reminder
  1120. Xwould remind you of each payday 3 days in advance:
  1121. X.PP
  1122. X.nf
  1123. X    REM 8 Nov 1990 *14 +3 MSG Payday is %b!
  1124. X.fi
  1125. X.PP
  1126. XThe
  1127. X.I repeat
  1128. Xcomponent of "*14" would cause the reminder to be triggered every 14
  1129. Xdays from the start date.
  1130. X.PP
  1131. XIn order to use a
  1132. X.I repeat,
  1133. Xyou must fully specify the start date.  That means that if
  1134. Xyou use a
  1135. X.I repeat,
  1136. Xyou must specify the
  1137. X.I month, day
  1138. Xand
  1139. X.I year.
  1140. XYou can also specify
  1141. X.I weekday, back
  1142. Xand
  1143. X.I local OMITs
  1144. Xbut these only affect the calculation of the start date.  Once the
  1145. Xstart date is calculated, the reminder is issued regularly every
  1146. X.I repeat
  1147. Xdays.  Note, in particular, that once the start date is calculated,
  1148. X.B remind
  1149. Xignores local and global
  1150. X.I OMITs
  1151. Xwhen calculating the trigger date.  The final trigger date is strictly
  1152. Xa multiple of
  1153. X.I repeat
  1154. Xdays from the start date.  The only exceptions are those cases covered
  1155. Xby the \fIBEFORE, AFTER\fR and \fISKIP\fR keywords, discussed in the
  1156. Xnext section.
  1157. X.PP
  1158. X.B THE BEFORE, AFTER AND SKIP KEYWORDS
  1159. X.PP
  1160. XShould a reminder's trigger date happen to fall on an OMITted day, the
  1161. Xdefault action is to go ahead and trigger the reminder anyway.  For example,
  1162. Xsuppose you have a meeting every Tuesday.  Consider the following:
  1163. X.PP
  1164. X.nf
  1165. X    OMIT 1 Jan MSG New Year's Day
  1166. X    OMIT 25 December MSG Christmas
  1167. X    REM Tue AT 13:00 MSG Code review meeting.
  1168. X.fi
  1169. X.PP
  1170. XEven though Christmas 1990 is on a Tuesday, you will still be reminded
  1171. Xof a code review meeting on that day.  Surely that is not desirable.  You
  1172. Xcan tell \fBremind\fR to skip reminders which fall on OMITted days with the
  1173. X.I SKIP
  1174. Xkeyword.  Assuming we have the same \fIOMIT\fR commands, then:
  1175. X.PP
  1176. X.nf
  1177. X    REM Tue SKIP AT 13:00 MSG Code review meeting.
  1178. X.fi
  1179. X.PP
  1180. Xwould be triggered every Tuesday, but not on Christmas or New Year's
  1181. XDay, because both of these holidays happen to fall on Tuesdays.
  1182. X.PP
  1183. XIn some situations, we don't want to skip the reminder; we want to move
  1184. Xit to just before or just after a holiday.  Consider these examples:
  1185. X.PP
  1186. X.nf
  1187. X    REM Fri AFTER OMIT Sat Sun MSG Do your backup!
  1188. X.fi
  1189. X.PP
  1190. XThis reminder is normally triggered every Friday.  However, if a particular
  1191. XFriday happens to be a holiday, it will be triggered on the Monday after
  1192. Xthe holiday instead.  Note that the \fIAFTER\fR keyword keeps scanning
  1193. Xforwards until it hits a day which is not in the global or local \fIOMIT\fR
  1194. Xlists.  (Of course, if both the Friday and Monday are holidays, then the
  1195. Xreminder would be deferred until Tuesday, and so on.)
  1196. X.PP
  1197. X.nf
  1198. X    REM Fri BEFORE MSG Do your backup!
  1199. X.fi
  1200. X.PP
  1201. XThis is similar, except that the reminder is issued on the previous Thursday
  1202. Xif a particular Friday happens to be a holiday.  This form, too, will
  1203. Xmove back to Wednesday if Thursday also happens to be a holiday, and so on.
  1204. X.PP
  1205. XNote:  These keywords skip both local and global \fIOMIT\fRs.  Also,
  1206. X\fBremind\fR will complain about certain illegal constructions, such as:
  1207. X.PP
  1208. X.nf
  1209. X    REM Mon SKIP OMIT Mon MSG Impossible!
  1210. X.fi
  1211. X.PP
  1212. XIf \fBremind\fR makes too many attempts to find a trigger date for
  1213. Xcertain forms, it assumes that no satisfiable date exists, and will warn
  1214. Xyou to check the date specification.  In practice, this should never happen.
  1215. X.PP
  1216. X.B THE UNTIL KEYWORD
  1217. X.PP
  1218. XThe \fIUNTIL\fR keyword can be used to force a reminder to expire at a
  1219. Xparticular date.  It must be followed by a \fIyear\fR, \fImonth\fR and
  1220. X\fIday\fR specifying the expiry date.  Here are some examples:
  1221. X.PP
  1222. XSuppose you have a conference from 25 Feb 1991 to 1 March 1991.  You
  1223. Xcould use:
  1224. X.PP
  1225. X.nf
  1226. X    REM 25 Feb 1991 *1 UNTIL 1 Mar 1991 MSG Conference today!
  1227. X.fi
  1228. X.PP
  1229. XYou must include the "*1" to have the reminder repeated every day
  1230. Xduring the conference.  If you did not include the "*1", then the
  1231. Xreminder would only have been issued on 25 Feb 1991.
  1232. X.PP
  1233. XSuppose you have jury duty from 4-15 March 1991, not including weekends.
  1234. XSuppose further that you wish to be reminded of this duty starting on 1
  1235. XMarch 1991 (hence the "++3"):  (See the section "Substitution" for an
  1236. Xexplanation of all the percent signs.)
  1237. X.PP
  1238. X.nf
  1239. X    REM 4 Mar 1991 ++3 *1 OMIT Sat Sun SKIP UNTIL 15 Mar 1991 \\
  1240. X    MSG %"Jury duty%" %b.
  1241. X.fi
  1242. X.PP
  1243. XFinally, suppose you have a class every Tuesday and Thursday until 30 May
  1244. X1991:
  1245. X.PP
  1246. X.nf
  1247. X    REM Tue Thu UNTIL 30 May 1991 MSG Class tonight.
  1248. X.fi
  1249. X.PP
  1250. X.B THE MSG KEYWORD
  1251. X.PP
  1252. XThe
  1253. X.I MSG
  1254. Xkeyword causes the remaining part of the line to be passed through a
  1255. Xsubstitution filter and then printed to standard output whenever the
  1256. Xreminder is triggered.  See the section "Substitution" for more information
  1257. Xabout the substitution filter.
  1258. X.PP
  1259. X.B THE RUN KEYWORD
  1260. X.PP
  1261. XThe
  1262. X.I RUN
  1263. Xkeyword causes the remaining part of the line to be passed through the
  1264. Xsubstitution filter and then passed to the default shell for execution
  1265. Xwhenever the reminder is triggered.  If the
  1266. X.B \-r
  1267. Xcommand-line option is specified, all
  1268. X.I REM
  1269. Xcommands with the
  1270. X.I RUN
  1271. Xkeyword are ignored.
  1272. X.PP
  1273. X.B
  1274. XGETTING REMINDED ONLY ONCE PER DAY
  1275. X.PP
  1276. XIf you run
  1277. X.B remind
  1278. Xfrom your
  1279. X.I .login
  1280. Xscript, you may only want certain reminders to be run once per day, not
  1281. Xonce per login.  Typically, this is used to control
  1282. X.I RUN
  1283. Xcommands so that they only execute once per day.  To specify this,
  1284. Xplace the
  1285. X.I ONCE
  1286. Xkeyword in the reminder file.  When
  1287. X.B remind
  1288. Xencounters a
  1289. X.I ONCE
  1290. Xkeyword, it checks the last-access date of the reminder file.  If it is
  1291. Xequal to the current date,
  1292. X.B remind
  1293. Xassumes that the reminder file has already been run once, and ignores the
  1294. Xreminder.  If you start
  1295. X.B remind
  1296. Xwith the
  1297. X.B \-o
  1298. Xcommand-line option,
  1299. X.B remind
  1300. Xignores the
  1301. X.I ONCE
  1302. Xkeyword.
  1303. X.PP
  1304. X.B LOCALLY OMITTING WEEKDAYS
  1305. X.PP
  1306. XA
  1307. X.I REM
  1308. Xcommand containing the
  1309. X.I OMIT
  1310. Xkeyword followed by a list of weekdays causes the
  1311. X.I delta
  1312. Xand
  1313. X.I back
  1314. Xto ignore the specified weekdays when counting days.  This is called a
  1315. X.I local OMIT.
  1316. XFor example:
  1317. X.PP
  1318. X.nf
  1319. X    REM 1 +1 OMIT Sat Sun MSG Test4
  1320. X.fi
  1321. X.PP
  1322. XThis reminder prints "Test4" on the first day of every month, as well
  1323. Xas the previous day.  If, however, the first day of the month falls on
  1324. Xa Sunday or Monday, the reminder is also triggered on the previous
  1325. XFriday, since the
  1326. X.I delta
  1327. Xof +1 does not count Saturdays or Sundays when moving backwards.  Here's
  1328. Xanother example:
  1329. X.PP
  1330. X.nf
  1331. X    REM 1 -1 +1 OMIT Sat Sun MSG Test5
  1332. X.fi
  1333. X.PP
  1334. XThis reminder is triggered on the last working day of each month, as well
  1335. Xas the working day preceding it.  Let's look at it in detail:
  1336. X.PP
  1337. XThe
  1338. X.I day
  1339. Xof "1" specifies the first day of each month.  The
  1340. X.I back
  1341. Xof "-1" tells
  1342. X.B remind
  1343. Xto go backwards by one day, not counting Saturday and Sunday as it moves.
  1344. XThis takes us the the last working day of the preceding month, which is the
  1345. Xtrigger date.  The
  1346. X.I delta
  1347. Xof "+1" ensures that the reminder will be triggered on the day preceding
  1348. Xthis trigger date also.  Finally, if the trigger date happens to be
  1349. Xa Monday, the
  1350. X.I delta
  1351. Xcombined with the
  1352. X.I local OMIT
  1353. Xcauses the reminder to be triggered on the Friday (and Saturday and Sunday)
  1354. Xpreceding the trigger date.
  1355. X.PP
  1356. X.B THE AT KEYWORD
  1357. X.PP
  1358. XReminders with the
  1359. X.I AT
  1360. Xkeyword are called "timed reminders" or "AT reminders."  The
  1361. X.I AT
  1362. Xkeyword must be followed by a
  1363. X.I time,
  1364. Xwhich is a time in 24-hour format, from 0:00 to 23:59.  The
  1365. X.I time
  1366. Xmust be of the form \fIhh\fR:\fImm\fR.
  1367. XAlso, after the
  1368. X.I AT
  1369. Xkeyword, you can supply a
  1370. X.I tdelta
  1371. Xand a
  1372. X.I trepeat.
  1373. XThese have the same form as a
  1374. X.I delta
  1375. Xand a
  1376. X.I repeat.
  1377. XIn other words, a
  1378. X.I tdelta
  1379. Xis a number preceded by a "+" sign, and a
  1380. X.I trepeat
  1381. Xis a number preceded by an asterisk.
  1382. X.PP
  1383. XWhen
  1384. X.B remind
  1385. Xencounters a timed reminder, it examines the actual trigger date.  This
  1386. Xis the date specified by the date_spec, not counting any
  1387. X.I delta
  1388. Xwhich may be present.  If the trigger date is the same as the current
  1389. Xdate, the timed reminder will be placed on a queue in addition to
  1390. Xbeing triggered like a normal reminder.  (If you supply the
  1391. X.B \-a
  1392. Xcommand-line option, a timed reminder which would be queued will not
  1393. Xbe triggered like a normal reminder.)  After
  1394. X.B remind
  1395. Xhas finished processing the reminder file, it starts up a background
  1396. Xprocess to trigger all the queued timed reminders.  As each reminder's
  1397. Xtrigger time is reached, it is triggered.  Thus, you can have
  1398. X.B remind
  1399. Xissue reminders just before important meetings or time-sensitive tasks.
  1400. X.PP
  1401. XThe
  1402. X.I tdelta
  1403. Xand
  1404. X.I trepeat
  1405. Xare interpreted in minutes.  This is how they work:
  1406. X.PP
  1407. X.nf
  1408. X    REM AT 17:00 +60 *15 MSG Hello!
  1409. X.fi
  1410. X.PP
  1411. XThis timed reminder has a trigger time of 5:00pm.  It is also triggered
  1412. Xone hour before 5:00pm (because of the
  1413. X.I tdelta
  1414. Xof +60)
  1415. Xand every 15 minutes thereafter until 5:00pm (because of the
  1416. X.I trepeat
  1417. Xof +15.)  All told, the reminder would be triggered at 4:00pm, 4:15pm,
  1418. X4:30pm, 4:45pm and 5:00pm.
  1419. X.PP
  1420. X.nf
  1421. X    REM Fri AT 17:00 +45 *30 MSG Work ends at 5!!
  1422. X.fi
  1423. X.PP
  1424. XThis timed reminder would be placed on the queue every Friday.  It
  1425. Xwould be triggered at 4:15pm, 4:45pm and 5:00pm every Friday.  Note
  1426. Xthat a timed reminder is always triggered at the time specified
  1427. Xafter the
  1428. X.I AT
  1429. Xkeyword, even if the
  1430. X.I tdelta
  1431. Xis not a multiple of
  1432. X.I trepeat.
  1433. X.PP
  1434. XIf a reminder has a regular
  1435. X.I delta,
  1436. Xit will not be queued unless the current system date equals the actual
  1437. Xtrigger date.  Thus:
  1438. X.PP
  1439. X.nf
  1440. X    REM Fri +1 AT 17:00 MSG Go home at 5:00!
  1441. X.fi
  1442. X.PP
  1443. XOn Thursdays, this reminder would simply be treated as a regular reminder
  1444. Xand printed.  On Fridays, however, it would be queued for timed triggering.
  1445. XNote that the
  1446. X.B \-q
  1447. Xcommand-line option causes
  1448. X.B remind
  1449. Xto treat timed reminders as normal reminders, and not queue them.
  1450. X.SH THE OMIT COMMAND
  1451. X.I OMIT
  1452. Xexists as a separate command as well as a keyword within a
  1453. X.I REM
  1454. Xstatement.  When used as a separate command, it is called a
  1455. X.I global OMIT,
  1456. Xand has the following form:
  1457. X.RS
  1458. XOMIT
  1459. X.I day
  1460. X.I month
  1461. X[
  1462. X.I year
  1463. X]
  1464. X.RE
  1465. XThe arguments can be specified in any order.
  1466. X.PP
  1467. XThe form without the
  1468. X.I year
  1469. Xcomponent is used for holidays which fall on the same date each year.
  1470. XFor example:
  1471. X.PP
  1472. X.nf
  1473. X    OMIT 25 December    # Christmas
  1474. X    OMIT  1 January        # New Year's Day
  1475. X.fi
  1476. X.PP
  1477. X(Note that
  1478. X.I OMIT
  1479. Xcan have a following comment on the same line, unlike the
  1480. X.I REM
  1481. Xcommand.)
  1482. X.PP
  1483. XThe form with the
  1484. X.I year
  1485. Xcomponent is used for holidays which vary from year to year.  For example:
  1486. X.PP
  1487. X.nf
  1488. X    OMIT 12 October 1990    # Columbus Day 1990
  1489. X    OMIT 22 November 1990    # Thanksgiving Day 1990
  1490. X.fi
  1491. X.PP
  1492. XIn its debugging messages,
  1493. X.B remind
  1494. Xcalls the first form a
  1495. X.I partially-specified global OMIT
  1496. Xand the second form a
  1497. X.I fully-specified global OMIT.
  1498. X.PP
  1499. XThe dates specified by
  1500. X.I global OMITs
  1501. Xare omitted by the
  1502. X.I back
  1503. Xand
  1504. X.I delta
  1505. Xportions of a reminders, in addition to any
  1506. X.I local OMITs.
  1507. XFor example:
  1508. X.PP
  1509. X.nf
  1510. X    OMIT 25 December
  1511. X    REM 26 +1 OMIT Sat Sun MSG Test6
  1512. X.fi
  1513. X.PP
  1514. XThis would issue a reminder on the 26th of each month, as well as the
  1515. Xpreceding working day.  Also, on the 24th of December 1990, the reminder
  1516. Xwould be issued.  Even though the 25th of December 1990 is a Tuesday, the
  1517. X.I global OMIT
  1518. Xwould cause the
  1519. X.I delta
  1520. Xto skip it.
  1521. X.PP
  1522. XHowever, if you use the "--" and "++" forms of \fIback\fR and \fIdelta\fR,
  1523. Xthen OMITted days are not skipped - strict date subtraction is performed.
  1524. XThus, to have a reminder issued on the last Monday of every month, regardless
  1525. Xof any \fIglobal OMITs\fR in force, you could use:
  1526. X.PP
  1527. X.nf
  1528. X    REM 1 Mon --7 MSG Forced to be last Monday in month
  1529. X.fi
  1530. X.PP
  1531. XIf you want the reminder to be issued on the last Monday of every month,
  1532. Xunless it is a holiday, in which case the reminder should be issued the
  1533. Xfollowing Tuesday, use:
  1534. X.PP
  1535. X.nf
  1536. X    REM 1 Mon --7 AFTER MSG Example!
  1537. X.fi
  1538. X.PP
  1539. X.I Global OMITs
  1540. Xare in force for all reminders following them in the reminder file until
  1541. Xa CLEAR-OMIT-CONTEXT or POP-OMIT-CONTEXT command is encountered.  Thus,
  1542. Xyou could have a series of reminders for which
  1543. X.I global OMITs
  1544. Xare inappropriate (such as birthdays or reminders which rely on
  1545. X.I back
  1546. Xto get to a specific weekday) ahead of any
  1547. X.I global OMITs,
  1548. Xwith business reminders (for which omission of holidays is appropriate)
  1549. Xfollowing the
  1550. X.I global OMITs.
  1551. X.PP
  1552. XFor convenience, you can include a \fIdelta\fR and a \fIMSG\fR or \fIRUN\fR
  1553. Xtoken in a global \fIOMIT\fR.  This is useful to avoid duplication of holiday
  1554. Xentries.  For example, the line:
  1555. X.PP
  1556. X.nf
  1557. X    OMIT 25 Dec +2 MSG %"Christmas%" is %b.
  1558. X.fi
  1559. X.PP
  1560. Xis exactly equivalent to:
  1561. X.PP
  1562. X.nf
  1563. X    OMIT 25 Dec
  1564. X    REM 25 Dec +2 MSG %"Christmas%" is %b.
  1565. X.fi
  1566. X.SH CONTROLLING THE OMIT CONTEXT
  1567. XIn many cases, it is convenient to temporarily change the \fIglobal OMITs\fR
  1568. Xwhich are in force.  This allows you to easily isolate holidays to act only
  1569. Xon certain reminders, or to temporarily introduce a \fIglobal OMIT\fR for a
  1570. Xspecial-case reminder.  Three commands allow you to do this:
  1571. X.PP
  1572. X.I CLEAR-OMIT-CONTEXT
  1573. Xdeletes all the \fIglobal OMITs\fR and starts you off with a clean slate.
  1574. X.PP
  1575. X.I PUSH-OMIT-CONTEXT
  1576. Xsaves all the \fIglobal OMITs\fR on an internal stack and leaves the current
  1577. X\fIglobal OMITs\fR in effect.
  1578. X.PP
  1579. X.I POP-OMIT-CONTEXT
  1580. Xrestores the \fIglobal OMITs\fR which were in effect at the time of the last
  1581. Xmatching \fIPUSH-OMIT-CONTEXT\fR command.
  1582. X.PP
  1583. XSuppose you have a block of reminders which require a clear OMIT context
  1584. Xto work properly, and which also introduce several \fIglobal OMITs\fR which
  1585. Xyou don't want to affect any other reminders.  The following fragment shows
  1586. Xhow to isolate these reminders:
  1587. X.PP
  1588. X.nf
  1589. X    # Sample fragment
  1590. X    PUSH-OMIT-CONTEXT   # Save for later
  1591. X    CLEAR-OMIT-CONTEXT  # Start out with clean slate
  1592. X
  1593. X    # Block of reminders goes here
  1594. X
  1595. X    POP-OMIT-CONTEXT    # Restore the saved OMITs
  1596. X    # Remaining reminders go here
  1597. X.fi
  1598. X.SH THE INCLUDE COMMAND
  1599. XThe
  1600. X.I INCLUDE
  1601. Xcommand has the following form:
  1602. X.PP
  1603. X.RS
  1604. XINCLUDE
  1605. X.I filename
  1606. X.RE
  1607. X.PP
  1608. XThis causes
  1609. X.B remind
  1610. Xto suspend the current file and read the contents of the specified
  1611. X.I filename.
  1612. XOnce that file has been read,
  1613. X.B remind
  1614. Xcontinues reading the original file from where it left off.
  1615. X.I INCLUDE
  1616. Xcommands can be nested to a depth of 10.
  1617. X.PP
  1618. X.I INCLUDE
  1619. Xallows you or someone else to maintain a file of holidays or system-wide
  1620. Xreminders that everyone should get.  For example, your reminder file could
  1621. Xlook something like this:
  1622. X.PP
  1623. X.nf
  1624. X    #!/usr/local/bin/remind
  1625. X    #
  1626. X    # Place personal stuff here - birthdays, etc.
  1627. X
  1628. X    # Now get system-wide global OMITS (holidays)
  1629. X    INCLUDE /usr/share/holidays
  1630. X
  1631. X    # and system-wide reminders
  1632. X    INCLUDE /usr/share/reminders
  1633. X
  1634. X    # Place local business stuff here.
  1635. X.fi
  1636. X.PP
  1637. XThe
  1638. X.I ONCE
  1639. Xkeyword operates on the last-access date of the top-level file.
  1640. XThe access dates of
  1641. X.I INCLUDEd
  1642. Xfiles are not used to control the operation of the
  1643. X.I ONCE
  1644. Xkeyword.
  1645. X.SH SUBSTITUTION
  1646. XBefore being processed, the body of a
  1647. X.I REM
  1648. Xcommand is passed through a substitution filter.  The filter scans for
  1649. Xsequences "%x" (where "x" is any letter and certain other characters)
  1650. Xand performs substitutions as
  1651. Xshown below.  (All dates refer to the trigger date of the reminder.)
  1652. X.TP
  1653. X.B %a
  1654. Xis replaced with "on \fIweekday, day month, year\fR"
  1655. X.RS
  1656. XFor example, consider the reminder:
  1657. X.PP
  1658. XREM 18 Oct 1990 +4 MSG Meeting with Bob %a.
  1659. X.PP
  1660. XOn 16 October 1990, it would print "Meeting with Bob on Thursday, 18 October,
  1661. X1990."
  1662. X.PP
  1663. XOn 17 October 1990, it would print "Meeting with Bob tomorrow."
  1664. X.PP
  1665. XOn 18 October 1990, it would print "Meeting with Bob today."
  1666. X.RE
  1667. X.TP
  1668. X.B %b
  1669. Xis replaced with "in \fIdiff\fR day's time" where
  1670. X.I diff
  1671. Xis the
  1672. X.B actual
  1673. Xnumber of days between the current date and the trigger date.
  1674. X(\fIOMITs\fR have no effect.)
  1675. X.RS
  1676. XFor example, consider:
  1677. X.PP
  1678. XREM 18 Oct 1990 +4 MSG Meeting with Bob %b.
  1679. X.PP
  1680. XOn 16 October 1990, it would print "Meeting with Bob in 2 days' time."
  1681. X.PP
  1682. XOn 17 October 1990, it would print "Meeting with Bob tomorrow."
  1683. X.PP
  1684. XOn 18 October 1990, it would print "Meeting with Bob today."
  1685. X.RE
  1686. X.TP
  1687. X.B %c
  1688. Xis replaced with "on \fIweekday\fR"
  1689. X.RS
  1690. XExample: REM 18 Oct 1990 +4 MSG Meeting with Bob %c.
  1691. X.PP
  1692. XOn 16 October 1990, it would print "Meeting with Bob on Thursday."
  1693. X.PP
  1694. XOn 17 October 1990, it would print "Meeting with Bob tomorrow."
  1695. X.PP
  1696. XOn 18 October 1990, it would print "Meeting with Bob today."
  1697. X.RE
  1698. X.TP
  1699. X.B %d
  1700. Xis replaced with "\fIday\fR", the day of the month.
  1701. X.TP
  1702. X.B %e
  1703. Xis replaced with "on \fIdd/mm/yyyy\fR"
  1704. X.TP
  1705. X.B %f
  1706. Xis replaced with "on \fImm/dd/yyyy\fR"
  1707. X.TP
  1708. X.B %g
  1709. Xis replaced with "on \fIweekday, day month\fR"
  1710. X.TP
  1711. X.B %h
  1712. Xis replaced with "on \fIdd/mm\fR"
  1713. X.TP
  1714. X.B %i
  1715. Xis replaced with "on \fImm/dd\fR"
  1716. X.TP
  1717. X.B %j
  1718. Xis replaced with "on \fIweekday, month day-th, year\fR"  This form appends the
  1719. Xcharacters "st", "nd", "rd" or "th" to the day of the month, as appropriate.
  1720. X.TP
  1721. X.B %k
  1722. Xis replaced with "on \fIweekday, month day-th\fR"
  1723. X.TP
  1724. X.B %l
  1725. Xis replaced with "on \fIyyyy/mm/dd\fR"
  1726. X.TP
  1727. X.B %m
  1728. Xis replaced with "\fImonth\fR", the name of the month.
  1729. X.TP
  1730. X.B %n
  1731. Xis replaced with the number (1 to 12) of the month.
  1732. X.TP
  1733. X.B %o
  1734. Xis replaced with " (today)" if and only if the current system date is the same
  1735. Xas the date being used by
  1736. X.B remind
  1737. Xas the current date.  Recall that you can specify a date for
  1738. X.B remind
  1739. Xto use on the command line.  This substitution is not generally useful in a
  1740. X.I REM
  1741. Xcommand, but is useful in a
  1742. X.I BANNER
  1743. Xstatement.  (See the section "The BANNER Command.)
  1744. X.TP
  1745. X.B %p
  1746. Xis replaced with "s" if the
  1747. X.I diff
  1748. Xbetween the current date and the trigger date is not 1.  You can use this
  1749. Xto construct reminders like:
  1750. X.RS
  1751. XREM 1 Jan +4 MSG %x day%p to go before New Year!
  1752. X.RE
  1753. X.TP
  1754. X.B %q
  1755. Xis replaced with "'s" if the
  1756. X.I diff
  1757. Xbetween the trigger date and the current date is 1.  Otherwise, it is replaced
  1758. Xwith "s'"  This can be used as follows:
  1759. X.RS
  1760. XREM 1 Jan +4 MSG New Year in %x day%q time!
  1761. X.RE
  1762. X.TP
  1763. X.B %r
  1764. Xis replaced with the day of the month (01 to 31) padded with a leading zero
  1765. Xif needed to pad to two digits.
  1766. X.TP
  1767. X.B %s
  1768. Xis replaced with "st", "nd", "rd" or "th" depending on the day of the month.
  1769. X.TP
  1770. X.B %t
  1771. Xis replaced with the number of the month (01 to 12) padded to two digits
  1772. Xwith a leading zero.
  1773. X.TP
  1774. X.B %u
  1775. Xis replaced with "on \fIweekday, day-th month, year\fR"  This is similar
  1776. Xto
  1777. X.B %a
  1778. Xexcept that "st", "nd", "rd" or "th" is added to the
  1779. X.I day
  1780. Xas appropriate.
  1781. X.TP
  1782. X.B %v
  1783. Xis replaced with "on \fIweekday, day-th month\fR"
  1784. X.TP
  1785. X.B %w
  1786. Xis replaced with "\fIweekday\fR", the name of the day of the week.
  1787. X.TP
  1788. X.B %x
  1789. Xis replaced with the
  1790. X.I diff
  1791. Xbetween the current date and the trigger date.  The
  1792. X.I diff
  1793. Xis defined as the actual number of days between these two dates;
  1794. X.I OMITs
  1795. Xare not counted.  (Strict date subtraction is performed.)
  1796. X.TP
  1797. X.B %y
  1798. Xis replaced with "\fIyear\fR", the year of the trigger date.
  1799. X.TP
  1800. X.B %z
  1801. Xis replaced with "\fIyy\fR", the last two digits of the year.
  1802. X.TP
  1803. X.B %_
  1804. X(percent-underscore) is replaced with a newline.  You can use this to
  1805. Xachieve multi-line reminders.
  1806. X.TP
  1807. X.B %1
  1808. Xis replaced with "now", "\fIm\fR minutes from now", "\fIm\fR minutes ago",
  1809. X"\fIh\fR hours from now", "\fIh\fR hours ago", "\fIh\fR hours and \fIm\fR
  1810. Xminutes from now" or "\fIh\fR hours and \fIm\fR minutes ago", as appropriate
  1811. Xfor a timed reminder.  Note that unless you specify the \fB\-a\fR option,
  1812. Xtimed reminders will be triggered like normal reminders, and thus a timed
  1813. Xreminder which occurred earlier in the day may be triggered.  This
  1814. Xcauses the need for the "...ago" forms.
  1815. X.TP
  1816. X.B %2
  1817. Xis replaced with "\fIhh\fR:\fImm\fRam" or "..pm" depending on the
  1818. X.I AT
  1819. Xtime of the reminder.
  1820. X.TP
  1821. X.B %3
  1822. Xis replaced with "\fIhh\fR:\fImm\fR" in 24-hour format.
  1823. X.TP
  1824. X.B %4
  1825. Xis replaced with "\fImm\fR" where \fImm\fR is the number of minutes between
  1826. X"now" and the time specified by \fIAT\fR.  If the \fIAT\fR time is
  1827. Xearlier than the current time, then the result is negative.
  1828. X.TP
  1829. X.B %5
  1830. Xis replaced with "\fIma\fR" where \fIma\fR is the absolute value of the number
  1831. Xproduced by \fB%4\fR.
  1832. X.TP
  1833. X.B %6
  1834. Xis replaced with "ago" or "from now", depending on the relationship between
  1835. Xthe \fIAT\fR time and the current time.
  1836. X.TP
  1837. X.B %7
  1838. Xis replaced with the number of hours between the \fIAT\fR time and the
  1839. Xcurrent time.  It is always non-negative.
  1840. X.TP
  1841. X.B %8
  1842. Xis replaced with the number of minutes between the \fIAT\fR time and
  1843. Xthe current time, after the hours (\fB%7\fR) have been subtracted out.
  1844. XThis is a number ranging from 0 to 59.
  1845. X.TP
  1846. X.B %9
  1847. Xis replaced with "s" if the value produced by \fB%8\fR is not 1.
  1848. X.TP
  1849. X.B %0
  1850. Xis replaced with "s" if the value produced by \fB%7\fR is not 1.
  1851. X.TP
  1852. X.B %!
  1853. Xis replaced with "is" if the current time is before the \fIAT\fR time,
  1854. Xor "was" if it is after.
  1855. X.TP
  1856. X.B 
  1857. X%"
  1858. X(percent-doublequote) is removed.  This sequence is not 
  1859. Xused by the substitution filter,
  1860. Xbut is used to tell \fBremind\fR which text to include in a calendar
  1861. Xentry when the \fB\-c\fR option is chosen.  See the section "Producing
  1862. Xa Calendar"
  1863. X.PP
  1864. XNotes:
  1865. X.TP
  1866. Xo
  1867. X.B Remind
  1868. Xnormally prints a blank line after each reminder; if the last character
  1869. Xof the body is '%', the blank line will not be printed.
  1870. X.TP
  1871. Xo
  1872. XSubstitutions a, b, c, e, f, g, h, i, j, k, l, u and v all are replaced
  1873. Xwith "today" if the current date equals the trigger date, or "tomorrow"
  1874. Xif the trigger date is one day after the current date.  Thus, they are
  1875. X.B not
  1876. Xthe same as substitutions built up from the simpler %w, %y, etc.
  1877. Xsequences.
  1878. X.TP
  1879. Xo
  1880. XAny of the substitutions dealing with time (0 through 9 and '!')
  1881. Xproduce undefined results if used in a reminder which does not have
  1882. Xan \fIAT\fR keyword.  Also, if a reminder has a \fIdelta\fR and may
  1883. Xbe triggered on several days, the time substitutions ignore the date.  Thus,
  1884. Xthe \fB%1\fR substitution may report that a meeting is in 15 minutes, for
  1885. Xexample, even though it may only be in 2 days time, because a \fIdelta\fR has
  1886. Xtriggered the reminder.  It is recommended that you use the time substitutions
  1887. Xonly in timed reminders with no \fIdelta\fR which are designed to be
  1888. Xqueued for timed activation.
  1889. X.TP 
  1890. Xo
  1891. XCapital letters can be used in the substitution sequence, in which case
  1892. Xthe first character of the substituted string is capitalized (if it is
  1893. Xnormally a lower-case letter.)
  1894. X.TP 
  1895. Xo
  1896. XAll other characters following a "%" sign are simply copied.  In particular,
  1897. Xto get a "%" sign out, use "%%" in the body.  To start the body of a reminder
  1898. Xwith a space, use "% ", since
  1899. X.B remind
  1900. Xnormally scans for the first non-space character after a
  1901. X.I MSG
  1902. Xor
  1903. X.I RUN
  1904. Xtoken.
  1905. X.SH PRODUCING A CALENDAR
  1906. XIf you provide the \fB\-c\fR option, the \fBremind\fR will scan your
  1907. Xreminder file and produce a calendar with your reminders entered on the
  1908. Xappropriate dates.
  1909. X.PP
  1910. XWhen you produce a calendar, \fBremind\fR will pass the text
  1911. Xthrough the substitution mechanism.  However, you may indicate to \fBremind\fR
  1912. Xwhich portions of the text should be placed in the calendar.  This is done
  1913. Xwith the \fB%"\fR sequence.  Here's an example:
  1914. X.PP
  1915. X.nf
  1916. X    REM 6 Jan +6 MSG %"David's birthday%" is %a.
  1917. X.fi
  1918. X.PP
  1919. XWhen you run \fBremind\fR normally, it executes the reminder as if the
  1920. X.B 
  1921. X%"
  1922. Xsequences were not there.  When you produce a calendar with the \fB\-c\fR
  1923. Xoption, however, only the text "David's birthday" is entered into the
  1924. Xcalendar.  For convenience, timed reminders are sorted by time before
  1925. Xbeing entered into the calendar, and the time of each reminder is printed
  1926. Xbefore the reminder text.
  1927. X.PP
  1928. XNote that by default, only \fIMSG\fR reminders are included in the calendar; 
  1929. X\fIRUN\fR reminders are ignored.  However, if you explicitly place the %"
  1930. Xescape sequences in a \fIRUN\fR reminder, then it will be included in the
  1931. Xcalendar.
  1932. XIf you indicate empty text for the calendar entry
  1933. Xwith the sequence \fB%"%"\fR, then the reminder is ignored when producing
  1934. Xthe calendar, whether is is a \fIMSG\fR or \fIRUN\fR type.
  1935. X.PP
  1936. XIf your reminder file has errors in it, when you produce a calendar, you
  1937. Xwill get many error messages apparently coming from the file "*cache*"
  1938. XThis is because \fBremind\fR caches the reminder file for efficient
  1939. Xproduction of the calendar.  Thus, you should check that your reminder
  1940. Xfile is error-free (by running \fBremind\fR with the \fB\-d\fR option)
  1941. Xbefore attempting to produce a calendar.
  1942. X.PP
  1943. XThe "Simple Calendar" format is useful if you want to format the calendar
  1944. Xwith another program.  You can save this output to a file or pipe it to
  1945. Xyour formatting program.  The output format is:
  1946. X.PP
  1947. X.nf
  1948. X    yyyy/mm/dd: hr:min \fIbody\fR
  1949. X.fi
  1950. X.PP
  1951. XThe \fIhr:min\fR portion is present only if the reminder has an \fIAT\fR
  1952. Xclause.  You can produce this format by using the \fB\-s\fR option in
  1953. Xconjunction with the \fB-c\fR option.  The \fB\-n\fR option produces
  1954. Xa listing in this format also; however, it is not sorted by date, and
  1955. Xindicates the next occurrence of each reminder in the reminder file.
  1956. X.SH THE BANNER COMMAND
  1957. XWhen
  1958. X.B remind
  1959. Xissues reminders, it normally prints a message saying:
  1960. X.PP
  1961. X"Reminders for \fIweekday, day-th month, year\fR (today):"
  1962. X.PP
  1963. X(If you supply a date on the command line different from the system date,
  1964. Xthe "(today)" portion is omitted.)
  1965. X.PP
  1966. XYou can change this default to anything you want with the
  1967. X.I BANNER
  1968. Xcommand.  It should appear in the reminder file before any
  1969. X.I REM
  1970. Xcommands.  (This is not enforced, but a
  1971. X.I BANNER
  1972. Xcommand encountered after a reminder has been triggered will be ignored.)
  1973. X.PP
  1974. XThe format of
  1975. X.I BANNER
  1976. Xis:
  1977. X.PP
  1978. XBANNER
  1979. X.I string
  1980. X.PP
  1981. XThe
  1982. X.I string
  1983. Xis passed through the substitution mechanism described before, using the
  1984. Xcurrent date and time for substitution.  The standard banner is described by:
  1985. X.PP
  1986. X.nf
  1987. X    BANNER Reminders for %w, %d%s %m, %y%o:
  1988. X.fi
  1989. X.PP
  1990. XYou can have a blank banner by using:
  1991. X.PP
  1992. X.nf
  1993. X    BANNER %
  1994. X.fi
  1995. X.PP
  1996. X.SH PURGING REMINDER FILES
  1997. XYou should periodically purge your reminder file of "expired"
  1998. X.I REM
  1999. Xcommands and global
  2000. X.I OMITs.
  2001. XThese are reminders which took place in the past and can never occur
  2002. Xagain, or
  2003. X.I OMITs
  2004. Xwhich are for past years.  Of course, only
  2005. X.I REMs
  2006. Xand
  2007. X.I OMITs
  2008. Xwith the
  2009. X.I year
  2010. Xspecified can ever expire.
  2011. X.PP
  2012. XTo purge your reminder file, run
  2013. X.B remind
  2014. Xin
  2015. X.I purge
  2016. Xmode.  This mode simply echoes non-expired lines to standard output, and
  2017. Xexpired lines to standard error.  Thus, to purge a file, you could type:
  2018. X.PP
  2019. X.nf
  2020. X    REMIND -p notes.old > notes.new
  2021. X.fi
  2022. X.PP
  2023. XThe file "notes.new" would contain all non-expired lines from "notes.old."
  2024. XAll expired lines are echoed to the screen.
  2025. X.I INCLUDEd
  2026. Xfiles are read and processed, but not purged.  You must purge each
  2027. X.I INCLUDEd
  2028. Xfile separately.
  2029. X.PP
  2030. XYou can supply a date on the command line when purging, but beware:  If you
  2031. Xsupply a date in the future, you may inadvertently purge lines which have not
  2032. Xreally expired yet.
  2033. X.SH DEBUGGING A REMINDER FILE
  2034. XThe debug command-line option \-d is used to debug reminder files.  It tells
  2035. Xyou useful information about the reminder file.  It displays the trigger date
  2036. Xof each reminder, and places an asterisk by those which would be issued
  2037. Xon the current date.  It also informs you of
  2038. X.I OMITs
  2039. Xwhich have expired, and gives warnings about situations which could lead
  2040. Xto long execution times or unexpected results.
  2041. X.PP
  2042. XAll debugging messages are sent to standard error.
  2043. X.SH EXAMPLES OF REMINDERS
  2044. XThis section is a sampling of what you can do with \fBremind\fR.
  2045. X.PP
  2046. X.nf
  2047. X    REM 5 Feb 1991 AT 14:00 +45 *30 \\
  2048. X    RUN mail -s "Meeting at %2" $LOGNAME </dev/null &
  2049. X.fi
  2050. X.PP
  2051. XOn 5 February, 1991, this reminder will mail 
  2052. Xyou reminders of a 2:00pm meeting at 1:15, 
  2053. X1:45 and 2:00.  The subject of the mail message will be "Meeting at 2:00pm"
  2054. Xand the body of the message will be blank.
  2055. X.PP
  2056. X.nf
  2057. X    REM AT 17:00 RUN echo "5:00pm - GO HOME!" | xless -g +0+0 &
  2058. X.fi
  2059. X.PP
  2060. XThis reminder will pop up an xless window at 5:00pm every day.  The xless
  2061. Xwindow will contain the line "5:00pm - GO HOME!"
  2062. X.PP
  2063. X.nf
  2064. X    REM AT 23:59 RUN (sleep 120; remind -a .reminders) &
  2065. X.fi
  2066. X.PP
  2067. XThis reminder will run at one minute to midnight.  It will cause a new
  2068. Xremind process to start at one minute past midnight.  This allows you to
  2069. Xhave a continuous reminder service so you can work through the night and
  2070. Xstill get timed reminders for early in the morning.
  2071. X.PP
  2072. X.nf
  2073. X    remind -c12 /dev/null 1 Jan 1991
  2074. X.fi
  2075. X.PP
  2076. XThis invocation of \fBremind\fR will cause it to print a calendar for
  2077. X1991, with all entries left blank.
  2078. X.SH AUTHOR
  2079. XDavid F. Skoll
  2080. X.SH BUGS
  2081. X.B Remind
  2082. Xwas originally written for MS-DOS and ported to UNIX.  It does some things
  2083. Xin an ungainly way.
  2084. X.PP
  2085. XDate calculation algorithms are fairly "brute force."
  2086. X.PP
  2087. XThe MS-DOS version of \fBremind\fR does not support queuing or timed
  2088. Xactivation of reminders.  It does, however, support the other semantics
  2089. Xof the \fIAT\fR keyword.
  2090. X.PP
  2091. X.B Remind
  2092. Xhas some built-in limits on total line length (511 characters),
  2093. Xthe length of an expanded \fIREM\fR body (511 characters), the number
  2094. Xof global \fIOMIT\fRs, etc.
  2095. SHAR_EOF
  2096. $TOUCH -am 0218130591 remind.1 &&
  2097. chmod 0600 remind.1 ||
  2098. echo "restore of remind.1 failed"
  2099. set `wc -c remind.1`;Wc_c=$1
  2100. if test "$Wc_c" != "40229"; then
  2101.     echo original size 40229, current size $Wc_c
  2102. fi
  2103. fi
  2104. echo "End of part 3, continue with part 4"
  2105. exit 0
  2106.