REMIND 2.2 03/05
David F. Skoll
dfs at doe.carleton.ca
Sat Nov 17 05:47:44 AEST 1990
#!/bin/sh
# This is part 03 of Remind-2.2
if touch 2>&1 | fgrep 'amc' > /dev/null
then TOUCH=touch
else TOUCH=true
fi
# ============= main.c ==============
if test X"$1" != X"-c" -a -f 'main.c'; then
echo "File already exists: skipping 'main.c'"
else
echo "x - extracting main.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > main.c &&
X/***************************************************************/
X/* */
X/* REMIND - version 2.2 */
X/* */
X/* By David Skoll - 13 Novemeber 1990 */
X/* */
X/* (C) 1990 by David Skoll - all rights reserved */
X/* */
X/***************************************************************/
X
X#include <stdio.h>
X#include <string.h>
X#include <ctype.h>
X#ifndef UNIX
X#include <stdlib.h>
X#include <dos.h>
X#include <stdarg.h>
X#else
X#include <varargs.h>
X#include <sys/types.h>
X#ifdef SYSV
X#include <time.h>
X#else
X#include <sys/time.h>
X#endif
X#endif
X#include "defines.h"
X#include "protos.h"
X
X
X/* List of months */
Xchar *MonthName[] = {
X "January", "February", "March", "April", "May", "June",
X "July", "August", "September", "October", "November", "December"
X};
X
X/* List of weekdays */
Xchar *DayName[] = {
X "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"
X};
X
X/* List of recognized tokens */
X
XToken keywd[] = {
X { "BANNER", Banner_t, 0 },
X { "OMIT", Omit_t, 0 },
X { "REM", Rem_t, 0 },
X { "January", Month_t, 0 },
X { "February", Month_t, 1 },
X { "March", Month_t, 2 },
X { "April", Month_t, 3 },
X { "May", Month_t, 4 },
X { "June", Month_t, 5 },
X { "July", Month_t, 6 },
X { "August", Month_t, 7 },
X { "September", Month_t, 8 },
X { "October", Month_t, 9 },
X { "November", Month_t, 10 },
X { "December", Month_t, 11 },
X { "Monday", WkDay_t, 0 },
X { "Tuesday", WkDay_t, 1 },
X { "Wednesday", WkDay_t, 2 },
X { "Thursday", WkDay_t, 3 },
X { "Friday", WkDay_t, 4 },
X { "Saturday", WkDay_t, 5 },
X { "Sunday", WkDay_t, 6 },
X { "MSG", Msg_t, 0 },
X { "RUN", Run_t, 0 },
X { "ONCE", Once_t, 0 },
X { "INCLUDE", Include_t, 0},
X { "AT", At_t, 0}
X};
X
X/* List of days in month - Feb MUST be 29 for CheckDate to work. */
Xint MonthDays[] = {
X 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
X};
X
X/* Index of the first day of each month. First array is non-leap-year;
X second is leap-year. */
Xint MonthIndex[2][12] = {
X { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 },
X { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }
X};
X
X/* Global ommissions array */
Xint FullOmitArray[FOMITSIZE];
X
X/* Global partial omissions array */
Xint PartOmitArray[POMITSIZE];
X
X/* Define the working buffers */
Xchar Line[512], WorkBuf[512];
Xchar TmpBuf[512];
Xint Fresh; /* True if the contents of Line are fresh */
X
X/* Global variables */
Xint Purge, Debug, Verbose, IgRun, IgOnce;
Xint LastRun;
Xchar FileName[200];
Xint CurLine;
Xchar Banner[200] = "Reminders for %w, %d%s %m, %y%o:";
Xint NumEmitted, NumRem;
Xint NumFullOmit, NumPartOmit;
Xint JulianToday, RealToday;
Xint CurYear, CurMon, CurDay;
Xint QueueAts, PrintAts, NumAtsQueued;
Xint Calendar, CalTime, CalWidth, SimpleCalendar;
X
Xstatic int JulFirst; /* Julian date of 1 Jan Current_year */
Xstatic int FirstYear;
X#ifndef UNIX
Xint int_comp(int *a, int *b) { return *a - *b; }
X#else
Xint int_comp(a, b)
X int *a;
X int *b;
X{ return *a - *b; }
X#endif
X
X/***************************************************************/
X/* */
X/* Output */
X/* Output a string with line separators. */
X/* */
X/***************************************************************/
X#ifndef UNIX
Xvoid Output(char *s)
X#else
Xvoid Output(s)
Xchar *s;
X#endif
X{
X while (*s) {
X if (*s == '\n') putchar('\\');
X putchar(*s++);
X }
X putchar('\n');
X}
X
X/***************************************************************/
X/* */
X/* int MoveBack(...) */
X/* */
X/* Move back by specified number of days, skipping holidays */
X/* */
X/***************************************************************/
X#ifndef UNIX
Xint MoveBack (int jul, int back, int d, int m, int y, int omit)
X#else
Xint MoveBack (jul, back, d, m, y, omit)
X int jul;
X int back;
X int d;
X int m;
X int y;
X int omit;
X#endif
X{
X int temp;
X
X if (!NumFullOmit && !NumPartOmit && !omit) return jul - back;
X while (back) {
X jul--;
X if (omit & 1 << (jul % 7)) continue; /* Omitted due to weekday */
X
X /* Omit if in fully-specified omit list */
X if (NumFullOmit && bsearch(&jul, FullOmitArray, NumFullOmit, sizeof(int), int_comp)) continue;
X
X if (NumPartOmit) {
X d--;
X if (d == 0) {
X m--;
X if (m < 0) {
X y--;
X m = 11;
X }
X d = DaysInMonth(m, y);
X }
X temp = (m << 5) + d;
X if (bsearch(&temp, PartOmitArray, NumPartOmit, sizeof(int), int_comp)) continue;
X }
X back--;
X }
X return jul;
X}
X
X/***************************************************************/
X/* */
X/* int ProcessLine() */
X/* */
X/* Process the line in the "Line" buffer. */
X/* */
X/* Normally returns 0. Returns 1 only if we're in Calendar */
X/* mode and we hit a reminder which should be placed in the */
X/* calendar. */
X/* */
X/***************************************************************/
X#ifndef UNIX
Xint ProcessLine(void)
X#else
Xint ProcessLine()
X#endif
X{
X char *s = Line;
X Token tok;
X int i;
X
X while (isspace(*s)) s++;
X
X /* Skip comments and blank lines */
X if (*s == '#' || *s == 0) {
X if (Purge && TopLevel()) Output(Line);
X return 0;
X }
X
X tok = ParseToken(&s);
X switch(tok.type) {
X case Banner_t: DoBanner(&s);
X if (Purge && TopLevel()) Output(Line);
X break;
X
X case Omit_t: i = DoGlobalOmit(&s);
X if (Purge && TopLevel())
X if (i < 0) Eprint("Purged '%s'\n", Line);
X else Output(Line);
X break;
X
X case Rem_t: i = DoRem(&s);
X if (Calendar) return i;
X if (Purge && TopLevel())
X if (i < 0) Eprint("Purged '%s'\n", Line);
X else Output(Line);
X NumRem++;
X break;
X
X case Include_t: if (Purge && TopLevel()) Output(Line);
X DoInclude(&s);
X break;
X
X
X default: if (Purge && TopLevel()) Output(Line);
X Eprint("Unknown command '%s'\n", tok.str);
X }
X return 0;
X}
X
X/***************************************************************/
X/* */
X#ifndef UNIX
X/* void Eprint(const char *f, ...) */
X#else
X/* void Eprint(va_alist) */
X#endif
X/* */
X/* Prints an error message. */
X/* */
X/***************************************************************/
X#ifndef UNIX
Xvoid Eprint(const char *f, ...)
X#else
X/*VARARGS0*/
Xvoid Eprint(va_alist)
Xva_dcl
X#endif
X{
X#ifndef UNIX
X va_list args;
X#else
X va_list args;
X char *f;
X#endif
X
X#ifndef UNIX
X if (Verbose & Fresh) {
X#else
X if (Verbose & Fresh) {
X#endif
X fprintf(stderr, "\n--- %s\n", Line);
X Fresh = 0;
X }
X if (Verbose) fprintf(stderr, "--- ");
X fprintf(stderr, "%s(%d): ", FileName, CurLine);
X#ifndef UNIX
X va_start(args, f);
X#else
X va_start(args);
X f = va_arg(args, char *);
X#endif
X vfprintf(stderr, f, args);
X#ifdef UNIX
X va_end(args);
X#endif
X}
X
X
X/***************************************************************/
X/* */
X/* int DoBanner(char **s) */
X/* */
X/* Sets the "Reminders for..." banner. */
X/* */
X/***************************************************************/
X#ifndef UNIX
Xint DoBanner(char **s)
X#else
Xint DoBanner(s)
X char **s;
X#endif
X{
X if (Purge) return 0;
X while (isspace(**s)) (*s)++;
X strcpy(Banner, *s);
X if (! *Banner)
X {
X if (Debug) Eprint("Empty banner.\n");
X strcpy(Banner, "Reminders for %w, %d%s %m, %y%o:");
X }
X if (NumRem && Debug) Eprint("Warning: Banner after reminder.\n");
X return 0;
X}
X
X/***************************************************************/
X/* */
X/* int CheckDate(int d, int m, int y) */
X/* */
X/* Checks that a date is valid - returns 0 for OK, 1 for BAD. */
X/* */
X/* If y=-1, just checks that month & day are valid, giving */
X/* benefit of the doubt for February 29. */
X/* */
X/* No point in checking if month is valid - months are named */
X/* and thus a month out of range can never be entered into */
X/* the system. */
X/* */
X/***************************************************************/
X#ifndef UNIX
Xint CheckDate(int d, int m, int y)
X#else
Xint CheckDate(d, m, y)
X int d;
X int m;
X int y;
X#endif
X{
X if (y == -1)
X if (d > 0 && d <= MonthDays[m]) return 0; else return 1;
X else
X if (y < BASE || y > BASE + 85) return 1;
X else if (d > 0 && d <= DaysInMonth(m, y)) return 0; else return 1;
X}
X
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, 1 if problem. */
X/* */
X/***************************************************************/
X#ifndef UNIX
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
X tok.type = Unknown_t;
X while(tok.type != Eol_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 case Eol_t: break;
X default: Eprint("Invalid token '%s' for OMIT command.\n", tok.str);
X return 1;
X }
X }
X
X if (d == -1 || m == -1 || CheckDate(d, m, y)) {
X Eprint("Invalid date specification.\n");
X return 1;
X }
X
X if (y == -1) { /* Only mm-dd specified */
X if (NumPartOmit == POMITSIZE) {
X Eprint("Too many partially-specified OMITs.\n");
X return 1;
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 } else { /* All three specified */
X if (NumFullOmit == FOMITSIZE) {
X Eprint("Too many fully-specified OMITs.\n");
X return 1;
X }
X omit = Julian(d, m, y);
X if (omit < JulianToday) {
X if (Debug) Eprint("Omit has expired.\n");
X return -1;
X }
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 }
X return 0;
X}
X
X/***************************************************************/
X/* */
X/* int strnicmp(char *s1, char*s1, int n) */
X/* */
X/* Compares first n chars of string ignoring case. */
X/* */
X/***************************************************************/
X#ifndef UNIX
Xint strncmpi(char *s1, char *s2, int n)
X#else
Xint strncmpi(s1, s2, n)
X char *s1;
X char *s2;
X int n;
X#endif
X{
X register int u1, u2;
X while (n)
X {
X if (!*s1 || !*s2) return upper(*s1) - upper(*s2);
X u1 = upper(*s1);
X u2 = upper(*s2);
X if (u1 != u2) return (u1 - u2);
X n--;
X s1++;
X s2++;
X }
X return 0;
X}
X
X/***************************************************************/
X/* */
X/* ParseToken(char **s); */
X/* */
X/* Parse the next token and adjust the character pointer. */
X/* */
X/***************************************************************/
X#ifndef UNIX
XToken ParseToken(char **s)
X#else
XToken ParseToken(s)
X char **s;
X#endif
X{
X
X Token tok;
X char *t = TmpBuf;
X int i, h, m;
X int len;
X char *colon = (char *) NULL;
X
X *t = 0;
X tok.str = TmpBuf;
X
X /* Skip blank space */
X while (isspace(**s)) (*s)++;
X
X /* End of line ? */
X if (**s == 0) {
X tok.type = Eol_t;
X tok.val = 0;
X return tok;
X }
X
X /* Grab a space-delimited token */
X while (**s != 0 && !isspace(**s)) {
X *t++ = **s;
X (*s)++;
X }
X *t = 0;
X len = t - TmpBuf;
X
X /* Check if it's a built-in token */
X for (i=0; i < sizeof(keywd)/sizeof(keywd[0]); i++)
X if (len >= 3 && !strncmpi(TmpBuf, keywd[i].str, len)) return keywd[i];
X
X /* ARGH. Check for "AT" as special case: < 3 chars */
X if (len == 2 && !strncmpi(TmpBuf, "AT", 2)) {
X tok.type = At_t;
X return tok;
X }
X
X tok.type = Unknown_t;
X
X /* If it's a comment, ignore the rest of the line */
X if (*(tok.str) == '#') {
X tok.type = Eol_t;
X return tok;
X }
X
X /* Check if it's a number (optional +/-/* ahead of number */
X t = TmpBuf;
X if (isdigit(*t)) {
X while (*++t){
X if (*t == ':') {
X if (colon) return tok; else colon = t;
X } else if (!isdigit(*t)) return tok;
X }
X }
X else if (*t == '+' || *t == '-' || *t == '*') {
X if (!isdigit(*++t)) return tok;
X while (*++t) if (!isdigit(*t)) return tok;
X }
X else return tok;
X
X /* OK, here we have a number - either a pure number, a delta, a time,
X back or a repeat marker */
X
X if (colon) { /* got a time here */
X h = atoi(TmpBuf);
X m = atoi(colon + 1);
X if (h >= 0 && h <= 23 && m >= 0 && m <= 59) {
X tok.type = Time_t;
X tok.val = 60*h+m;
X }
X else return tok;
X }
X else if (*TmpBuf == '+') {
X tok.type = Delta_t;
X tok.val = atoi(TmpBuf + 1);
X }
X else if (*TmpBuf == '-') {
X tok.type = Back_t;
X tok.val = atoi(TmpBuf + 1);
X }
X else if (*TmpBuf == '*') {
X tok.type = Repeat_t;
X tok.val = atoi(TmpBuf + 1);
X }
X else {
X tok.val = atoi(TmpBuf);
X if (tok.val > 0 && tok.val <= 31) tok.type = Day_t;
X else if (tok.val >= 100) tok.type = Year_t;
X else {
X tok.type = Year_t;
X tok.val += 1900;
X }
X }
X return tok;
X}
X
X/***************************************************************/
X/* */
X/* int FromJulian(int jul, int *d, int *m, int *y) */
X/* */
X/* Convert a date from Julian to normal form. Returns */
X/* 0 if conversion ok, -1 otherwise. */
X/* */
X/***************************************************************/
X#ifndef UNIX
Xint FromJulian(int jul, int *d, int *m, int *y)
X#else
Xint FromJulian(jul, d, m, y)
X int jul;
X int *d;
X int *m;
X int *y;
X#endif
X{
X int t;
X
X if (jul < 0) return 1;
X
X if (jul >= JulFirst && JulFirst != -1) {
X *y = FirstYear;
X jul -= JulFirst;
X } else *y = BASE;
X
X *m = 0;
X
X t = DaysInYear(*y);
X while (jul >= t) {
X jul -= t;
X (*y)++;
X t = DaysInYear(*y);
X }
X
X t = DaysInMonth(*m, *y);
X while (jul >= t) {
X jul -= t;
X (*m)++;
X t = DaysInMonth(*m, *y);
X }
X *d = jul + 1;
X return 0;
X}
X
X/***************************************************************/
X/* */
X/* int Julian(d, m, y) */
X/* */
X/* Converts a date to the number of days after Jan 1 1990. */
X/* Returns -1 if date is before Jan 1 1990. */
X/* */
X/***************************************************************/
X#ifndef UNIX
Xint Julian(int d, int m, int y)
X#else
Xint Julian(d, m, y)
X int d;
X int m;
X int y;
X#endif
X{
X int iy;
X int jul = 0;
X
X if (y < BASE) return -1;
X if (JulFirst == -1 || y < FirstYear)
X for (iy = BASE; iy < y; iy++) jul += DaysInYear(iy);
X else {
X jul = JulFirst;
X for (iy = FirstYear; iy < y; iy++) jul += DaysInYear(iy);
X }
X
X return jul + MonthIndex[IsLeapYear(y)][m] + d - 1;
X}
X
X/***************************************************************/
X/* */
X/* int FindTodaysDate(int *d, int *m, int *y) */
X/* */
X/* Obtains today's date. Returns Julian date or -1 for */
X/* failure. */
X/* */
X/***************************************************************/
X#ifndef UNIX
Xint FindTodaysDate(int *d, int *m, int *y)
X#else
Xint FindTodaysDate(d, m, y)
X int *d;
X int *m;
X int *y;
X#endif
X{
X#ifndef UNIX
X struct dosdate_t buf;
X
X _dos_getdate(&buf);
X
X *d = buf.day;
X *m = buf.month - 1;
X *y = buf.year;
X#else
X time_t tloc;
X struct tm *t;
X
X (void) time(&tloc);
X t = localtime(&tloc);
X
X *d = t->tm_mday;
X *m = t->tm_mon;
X *y = t->tm_year + 1900;
X
X#endif
X if (CheckDate(*d, *m, *y)) return -1;
X return Julian(*d, *m, *y);
X}
X
X#ifndef UNIX
Xint main(int argc, char *argv[])
X#else
Xint main(argc, argv)
X int argc;
X char *argv[];
X#endif
X{
X#ifdef UNIX
X#ifdef SYSV
X pid_t pid;
X#else
X int pid;
X#endif
X#endif
X
X NumEmitted = 0;
X NumRem = 0;
X JulFirst = -1; /* Initialize JulFirst so it's not used by Julian */
X
X JulianToday = FindTodaysDate(&CurDay, &CurMon, &CurYear);
X if (JulianToday < 0) {
X fprintf(stderr, "remind: System date is illegal - Ensure that year is at least %d.\n", BASE);
X return 1;
X }
X
X RealToday = JulianToday;
X
X initialize(argc, argv);
X
X FirstYear = CurYear;
X JulFirst = Julian(1, 0, CurYear); /* Do expensive computation once */
X FirstYear = CurYear;
X
X if (Calendar) {
X DoCalendar();
X return 0;
X }
X while (1) {
X if (ReadLine()) break;
X ProcessLine();
X }
X if (NumEmitted == 0 && NumAtsQueued == 0 && !Purge && !Debug)
X printf("No reminders.\n");
X#ifdef UNIX
X if (NumEmitted == 0 && NumAtsQueued != 0 && !Purge && !Debug)
X printf("%d reminder%s queued for later today.\n", NumAtsQueued,
X (NumAtsQueued == 1) ? "" : "s");
X
X if (NumAtsQueued) {
X pid = fork();
X if (pid == -1) Eprint("Can't fork to perform ATs!\n");
X if (pid != 0) return 0;
X HandleQueuedAts();
X }
X#endif
X}
X/***************************************************************/
X/* */
X/* SystemTime */
X/* */
X/* Returns current system time in seconds past midnight. */
X/* */
X/***************************************************************/
X#ifndef UNIX
Xlong SystemTime(void)
X#else
Xlong SystemTime()
X#endif
X{
X#ifdef UNIX
X time_t tloc;
X struct tm *t;
X
X (void) time(&tloc);
X t = localtime(&tloc);
X return (long) t->tm_hour * 3600L + (long) t->tm_min * 60L + (long) t->tm_sec;
X
X#else
X struct dostime_t tloc;
X _dos_gettime(&tloc);
X return (long) tloc.hour * 3600L + (long) tloc.minute * 60L + (long) tloc.second;
X#endif
X}
SHAR_EOF
$TOUCH -am 1115165290 main.c &&
chmod 0600 main.c ||
echo "restore of main.c failed"
set `wc -c main.c`;Wc_c=$1
if test "$Wc_c" != "21719"; then
echo original size 21719, current size $Wc_c
fi
fi
# ============= nextdate.c ==============
if test X"$1" != X"-c" -a -f 'nextdate.c'; then
echo "File already exists: skipping 'nextdate.c'"
else
echo "x - extracting nextdate.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > nextdate.c &&
X#include "defines.h"
X#include "globals.h"
X#include "protos.h"
X
X/***************************************************************/
X/* */
X/* int 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/* */
X/* This function tries to find the next date satisfying */
X/* the given constraints. Returns */
X/* 0 for success. Returns non-zero if a constraint would */
X/* be violated. Note that if DAY and WEEKDAY are both */
X/* constrained, then MONTH and YEAR may be violated. */
X/* Otherwise, all constraints are honoured. */
X/* The starting point for the search is thisday, etc. */
X/* */
X/* If inc is non-zero, then the search begins from the day */
X/* after the specified date. Note that this function assumes */
X/* that the given date is valid. */
X/* */
X/***************************************************************/
X#ifndef UNIX
Xint TryNextDate(int *retday, int *retmon, int *retyr,
X int d, int m, int y,
X int conday, int conmon, int conyr,
X int wkday, int cons, int inc)
X#else
Xint TryNextDate(retday, retmon, retyr, d, m, y, conday, conmon, conyr,
X wkday, cons, inc)
X int *retday, *retmon, *retyr, d, m, y, conday, conmon, conyr, wkday, cons, inc;
X
X#endif
X
X{
X int jul, jul2;
X int dd = d, mm = m, yy = y;
X
X if (inc)
X {
X d++;
X if (d > DaysInMonth(m, y)) {
X m++; d = 1;
X if (m > 11) {
X y++; m = 0;
X }
X }
X }
X
X
X switch (cons & 15) {
X
X case 0: /* No constraints - just use the start date */
X *retday = d;
X *retmon = m;
X *retyr = y;
X return 0;
X
X case 1: /* Day constrained to be d */
X *retday = conday;
X if (d > conday) {
X m++;
X if (m > 11) {y++; m=0;}
X }
X while (conday > DaysInMonth(m, y)) {
X m++;
X if (m > 11) {y++; m=0;}
X }
X *retmon = m;
X *retyr = y;
X return 0;
X
X case 2: /* Month constrained to be m */
X *retmon = conmon;
X if (m > conmon) {y++; d = 1;}
X else if (m < conmon) d = 1;
X *retday = d;
X *retyr = y;
X return 0;
X
X case 3: /* Month and day constrained */
X *retmon = conmon;
X *retday = conday;
X if (m > conmon || (m == conmon && d > conday)) y++;
X while (conday > DaysInMonth(conmon, y)) y++;
X *retyr = y;
X return 0;
X
X case 4: /* Year alone constrained */
X if (y > conyr) return 1;
X *retyr = conyr;
X if (y < conyr) {
X *retmon = 0;
X *retday = 1;
X }
X else {
X *retmon = m;
X *retday = d;
X }
X return 0;
X
X case 5: /* Year and day constrained */
X if (y > conyr) return 1;
X *retyr = conyr;
X *retday = conday;
X if (y < conyr) {
X *retmon = 0;
X return 0;
X }
X if (d > conday) {
X m++;
X if (m > 11) return 1;
X }
X while (conday > DaysInMonth(m, y)) {
X m++;
X if (m > 11) return 1;
X }
X *retmon = m;
X return 0;
X
X case 6: /* Year and month constrained */
X if (y > conyr || (y == conyr && m > conmon)) return 1;
X *retyr = conyr;
X *retmon = conmon;
X if (y < conyr || (y == conyr && m < conmon)) {
X *retday = 1;
X return 0;
X }
X *retday = d;
X return 0;
X
X case 7: /* Year, month and day constrained */
X *retday = conday;
X *retmon = conmon;
X *retyr = conyr;
X if (y > conyr || (y == conyr && m > conmon) ||
X (y == conyr && m == conmon && d > conday)) return 1;
X return 0;
X
X case 8: /* Only the weekday constrained. Let's go to Julian mode */
X jul = Julian(d, m, y);
X while (!(wkday & (1 << (jul % 7)))) jul++;
X FromJulian(jul, retday, retmon, retyr);
X return 0;
X
X case 9: /* GASP! day and weekday constrained .. bleah! */
X /* First, try last month. */
X jul2 = Julian(d, m, y);
X if (m != 0 || y != BASE)
X {
X mm--;
X if (mm < 0) {yy--; mm = 11;}
X
X /* If there are fewer days in month than required, it
X can't possibly match. */
X if (conday <= DaysInMonth(mm, yy)) {
X jul = Julian(conday, mm, yy);
X while (!(wkday & (1 << (jul % 7)))) jul++;
X if (jul >= jul2) { /* SUCCESS! */
X FromJulian(jul, retday, retmon, retyr);
X return 0;
X }
X }
X }
X /* Didn't work - try this month */
X if (conday <= DaysInMonth(m, y)) {
X jul = Julian(conday, m, y);
X while (!(wkday & (1 << (jul % 7)))) jul++;
X if (jul >= jul2) { /* SUCCESS! */
X FromJulian(jul, retday, retmon, retyr);
X return 0;
X }
X }
X /* Argh! Try next available month */
X mm = m;
X yy = y;
X do {
X mm++;
X if (mm > 11) {mm = 0; yy++;}
X } while (conday > DaysInMonth(mm, yy));
X jul = Julian(conday, mm, yy);
X while (!(wkday & (1 << (jul % 7)))) jul++;
X FromJulian(jul, retday, retmon, retyr);
X return 0;
X
X case 10: /* Month and Weekday constrained */
X if (m < conmon) {
X jul = Julian(1, conmon, y);
X while (!(wkday & (1 << (jul % 7)))) jul++;
X FromJulian(jul, retday, retmon, retyr);
X return 0;
X } else if (m == conmon) {
X jul = Julian(d, conmon, y);
X while (!(wkday & (1 << (jul % 7)))) jul++;
X FromJulian(jul, retday, retmon, retyr);
X if (*retmon != conmon) {
X jul = Julian(1, conmon, y+1);
X while (!(wkday & (1 << (jul % 7)))) jul++;
X FromJulian(jul, retday, retmon, retyr);
X }
X return 0;
X } else { /* m > conmon */
X jul = Julian(1, conmon, y+1);
X while (!(wkday & (1 << (jul % 7)))) jul++;
X FromJulian(jul, retday, retmon, retyr);
X return 0;
X }
X
X case 11: /* Day, Month and Weekday constrained */
X jul2 = Julian(d, m, y);
X
X /* Blip up to next valid year */
X while (conday > DaysInMonth(m, y)) y++;
X
X /* Try this year */
X jul = Julian(conday, conmon, y);
X while (!(wkday & (1 << (jul % 7)))) jul++;
X if (jul >= jul2) {
X FromJulian(jul, retday, retmon, retyr);
X return 0;
X }
X
X /* Must be next year */
X jul = Julian(conday, conmon, y+1);
X while (!(wkday & (1 << (jul % 7)))) jul++;
X FromJulian(jul, retday, retmon, retyr);
X return 0;
X
X case 12: /* Weekday and year specified */
X if (y > conyr) return 1;
X if (y == conyr) {mm = m; dd = d;} else {mm = 0; dd = 1;}
X jul = Julian(dd, mm, conyr);
X while (!(wkday & (1 << (jul % 7)))) jul++;
X FromJulian(jul, retday, retmon, retyr);
X return 0;
X
X case 13: /* Weekday, year and day specified */
X if (y > conyr+1 || (y > conyr && m>0)) return 1;
X jul2 = Julian(d, m, y);
X if (y > conyr ) {
X jul = Julian(conday, 11, conyr);
X while (!(wkday & (1 << (jul % 7)))) jul++;
X if (jul >= jul2) {
X FromJulian(jul, retday, retmon, retyr);
X return 0;
X }
X } else if (y < conyr) {
X jul = Julian(conday, 0, conyr);
X while (!(wkday & (1 << (jul % 7)))) jul++;
X FromJulian(jul, retday, retmon, retyr);
X return 0;
X }
X else {
X /* Try last month */
X if (m > 0) {
X mm = m - 1;
X while (conday > DaysInMonth(mm, y)) mm--;
X jul = Julian(conday, mm, y);
X while (!(wkday & (1 << (jul % 7)))) jul++;
X if (jul >= jul2) {
X FromJulian(jul, retday, retmon, retyr);
X return 0;
X }
X }
X /* Try this month */
X if (conday <= DaysInMonth(m,y)) {
X jul = Julian(conday, m, y);
X while (!(wkday & (1 << (jul % 7)))) jul++;
X if (jul >= jul2) {
X FromJulian(jul, retday, retmon, retyr);
X return 0;
X }
X }
X /* Try next month */
X if (m == 11) return 1;
X m++;
X while (conday > DaysInMonth(m, y)) m++;
X jul = Julian(conday, m, y);
X while (!(wkday & (1 << (jul % 7)))) jul++;
X FromJulian(jul, retday, retmon, retyr);
X return 0;
X }
X
X case 14: /* Weekday, Month and Year specified */
X if (y > conyr || (y == conyr && m > conmon)) return 1;
X if (conyr > y || (conyr == y && conmon > m)) {
X jul = Julian(1, conmon, conyr);
X while (!(wkday & (1 << (jul % 7)))) jul++;
X FromJulian(jul, retday, retmon, retyr);
X return 0;
X } else {
X jul = Julian(d, m, y);
X while (!(wkday & (1 << (jul % 7)))) jul++;
X FromJulian(jul, retday, retmon, retyr);
X if (*retmon == conmon) return 0; else return 1;
X
X }
X
X case 15: /* Weekday, day, month and year specified */
X jul2 = Julian(d, m, y);
X jul = Julian(conday, conmon, conyr);
X while (!(wkday & (1 << (jul % 7)))) jul++;
X FromJulian(jul, retday, retmon, retyr);
X if (jul < jul2) return 1;
X return 0;
X }
X}
SHAR_EOF
$TOUCH -am 1115093690 nextdate.c &&
chmod 0600 nextdate.c ||
echo "restore of nextdate.c failed"
set `wc -c nextdate.c`;Wc_c=$1
if test "$Wc_c" != "8637"; then
echo original size 8637, 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#ifndef UNIX
Xint CheckDate (int d, int m, int y);
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);
Xvoid Eprint(const char *f, ...);
Xint FindTodaysDate(int *d, int *m, int *y);
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);
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 d, int m, int y, int omit);
Xvoid OpenFile (char *s);
Xvoid Output (char *s);
XToken ParseToken (char **s);
Xint ProcessLine (void);
Xint ReadLine (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 ();
Xint DoBanner ();
Xvoid DoCalendar ();
Xint DoGlobalOmit();
Xvoid DoInclude ();
Xint DoRem ();
Xint DoSubst ();
Xvoid Eprint();
Xint FindTodaysDate();
Xint FromJulian ();
Xint GetTriggerDate();
Xvoid HandleQueuedAts();
Xvoid initialize ();
Xint int_comp ();
Xint Julian ();
Xint MoveBack ();
Xvoid OpenFile ();
Xvoid Output ();
XToken ParseToken ();
Xint ProcessLine ();
Xint ReadLine ();
Xvoid SigHupHandler();
Xlong SystemTime ();
Xint TopLevel ();
Xint TryNextDate ();
X#endif
X
SHAR_EOF
$TOUCH -am 1115095890 protos.h &&
chmod 0600 protos.h ||
echo "restore of protos.h failed"
set `wc -c protos.h`;Wc_c=$1
if test "$Wc_c" != "1717"; then
echo original size 1717, 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 1113132790 remind-all.csh &&
chmod 0700 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 1116131490 remind-all.sh &&
chmod 0700 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
echo "End of part 3, continue with part 4"
exit 0
More information about the Alt.sources
mailing list