[net.sources] visual calendar and activities programs, part 1

me%pinot@zehntel.UUCP (Mike Essex) (01/30/87)

echo x - README
sed 's/^X//' >README <<'*-*-END-of-README-*-*'
X			VCAL AND FRIENDS                  1/29/87
X
Xdef.:  a set of calendar and appointment utility programs to replace
X       the traditional paper calendar.
X       
XVcal and friends allow the user to view a calendar, enter dates and
Xtimes of activities, set times for prompts to the CRT and to produce
Xlists of a month's activities.  Multiple data files may be used to
Xallow the user to have one calendar for personal activities, one for
Xbusiness activities, one for project milestones, etc.
X
XThese programs are written in 'C' and run under UNIX.  To date they
Xhave been compiled and execute on the following systems:
X
XDEC PDP 11/70	UNIX Version 7
XDEC VAX 11/750	UNIX BSD 4.2 and 4.3
XSun 2/170	UNIX BSD 4.2
XSun 3/160	UNIX BSD 4.2
XSun 3/260 	UNIX BSD 4.2
X
XIncluded in this package are six source files, six manual files, a
Xmakefile and this introduction.  The makefile is for use with the
Xstandard "make" utility on a VAX 11/750 under BSD 4.3.  For use with
Xa PDP 11/70 BSD Version 7 change the makefile library entry from
X"termlib" to "termcap".
X
XAll the "vcal" files have been combined here with the "shar" script.
XSince the combined size of the files are greater than 65,000
Xcharacters they have been broken into two parts for transmission.
XPart 1 contains makefile, appts.c, autocall.c and callme.c along
Xwith the manual pages for these.  Part 2 contains eappts.c, lcal.c
Xand vcal.c and their manual pages.
X
XSynopsis of files:
X
Xappts		displays the current or specified day's activities
X
Xautocall	starts background reminder processes for each of the
X		current day's activities
X
Xcallme		starts a background reminder process for a specified
X		time and activity
X
Xeappts		allows activities to be entered into a data file from
X		the command line
X
Xlcal		produces a tabular listing of the current or specified
X		month's activities
X
Xvcal		visual calendar displaying the current or specified
X		month's activities; allows entries to be added, changed
X		or deleted
X
Xmakefile	makefile for all of the "vcal" programs
X
Xmanual pages:	appts.l autocall.l callme.l eappts.l lcal.l vcal.l
X
XComments and suggestions will be appreciated and considered.
X
XMike Essex  (~me)
X
X     ....!ucbvax!zehntel!me
X     ....!decvax!sytek!zehntel!me
X     ...."zehntel!me"@BERKELEY
*-*-END-of-README-*-*
echo x - makefile
sed 's/^X//' >makefile <<'*-*-END-of-makefile-*-*'
X.SUFFIXES:     .c
X
XLIBS	      = -ltermcap
X
XLINKER	      = cc
XCC	      = cc
XAR	      = ar
XNM            = nm
X
XMAKEFILE      = makefile
X
XSRCS	      = $.c
X
XOBJS	      = $.o
X
XPROGRAMS      = appts\
X		autocall\
X		eappts\
X		callme\
X		vcal\
X		lcal
X
X
Xall:		$(PROGRAMS)
X
Xappts:	appts.c
X	$(CC) -O -o appts appts.c
X
Xautocall:	autocall.c
X	$(CC) -O -o autocall autocall.c
X
Xcallme:	callme.c
X	$(CC) -O -o callme callme.c
X
Xeappts:	eappts.c
X	$(CC) -O -o eappts eappts.c
X
Xvcal:	vcal.c
X	$(CC) -O -o vcal vcal.c  $(LIBS)
X
Xlcal:	lcal.c
X	$(CC) -O -o lcal lcal.c
X
*-*-END-of-makefile-*-*
echo x - appts.c
sed 's/^X//' >appts.c <<'*-*-END-of-appts.c-*-*'
X/*
X * Module:	appts.c
X *
X * Purpose:	Displays current or specified date's appointments
X *
X * Author:	Mike Essex
X *
X * Date:	Sep. 16, 1986
X *
X * Includes:
X *	time.h, stdio.h, ctype.h
X *
X * Discussion:
X *	This program reads a designated data file or, by default,
X *	the .appointments file in the user's home directory and
X *	displays the current days appointments if no command line
X *	arguement is given.  An optional numeric month, day and
X *	year arguement may be specified to display appointments
X *	for a different day.  Output is standard out.
X *
X * Edit History
X * ==== =======
X *
X * Date      Who	What
X * ----      ---	----------------------------------------------
X * 11/26/86  me		added multi-datafile capability
X * 11/26/86  me		fixed 'home' bug
X * 12/08/86  me		modified "No appointments" to print filenames
X *
X */
X
X#include <time.h>
X#include <stdio.h>
X#include <ctype.h>
X
Xint		monthdata[1000];
Xint		daydata[1000];
Xint		yeardata[1000];
Xint		timedata[1000];
Xlong		juliedata[1000];
Xchar		*msgdata[1000];
Xint		month,day,year,hour,mhour,min,sec,dow,ampm;
Xint		argvindex;
Xlong		julie;
Xint		maxentries = 1000;
Xint		cntr;
Xchar	*dlist[8] = {"x","Mon","Tue","Wed","Thu","Fri","Sat","Sun"};
Xint	mdays[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
X
X
X
X/*
X * Procedure:	main()
X *
X * Function:	initializes values, gets current day, parses command
X *		line arguements, loads file data, outputs table
X */
X
Xmain(argc,argv)
X
Xint		argc;
Xchar		*argv[];
X
X{
X    int		go,none,cntr,cnt,timeout,status,nowtime;
X    int		loaddata();
X    int		wday;
X    int		atoi();
X    int		setdow();
X    int		tempmonth,tempday,tempyear;
X    int		maxindex;
X    int		holdargvi,holdmaxi;
X    long	setjulie();
X
X    timeset();
X
X    if (argc > 3) {
X	tempmonth = atoi(argv[1]);
X	tempday = atoi(argv[2]);
X	tempyear = atoi(argv[3]);
X	if (tempmonth && tempday && tempyear){
X	    month = tempmonth;
X	    day = tempday;
X	    year = tempyear;
X	    if (year < 100) year += 1900;
X	    if (argc > 4) {
X		argvindex = 4;
X		maxindex = argc;
X	    }
X	    else {
X		argvindex = 0;
X		maxindex = 1;
X	    }
X	}
X	else {
X	    if (tempmonth || tempday || tempyear) {
X		printf("Syntax error:  Incorrect date arguments\n");
X		exit(1);
X	    }
X	    else {
X		argvindex = 1;
X		maxindex = argc;
X	    }
X	}
X    }
X    else {
X        if (argc == 1) {
X	    argvindex = 0;
X	    maxindex = argc;
X	}
X	else {
X	    argvindex = 1;
X	    maxindex = argc;
X	}
X    }
X
X    julie = setjulie(month,day,year);
X    wday = setdow(month,day,year);
X
X
X    go = 1;
X    holdargvi = argvindex;
X    holdmaxi = maxindex;
X    while (go) {
X	printf("-------------------------------------------------------------------------------\n");
X	printf("|                       Appointments for %-3.3s  %2d/%2d/%4d                      |\n",dlist[wday],month,day,year);
X
X
X	while (argvindex < maxindex) {
X	    cnt = loaddata(argv[argvindex]);
X	    cntr = 0;
X	    none = 1;
X	    while (cntr < cnt) {
X		if (juliedata[cntr] == julie) {
X		    printf("| %4d  %-69.69s |\n",timedata[cntr],msgdata[cntr]);
X		    none = 0;
X		};
X		cntr++;
X	    }
X	    if (none) {
X		if (argvindex == 0) {
X		    printf("| No appointments today.                                                      |\n");
X		}
X		else {
X		    printf("| No appointments in:  %-40.40s               |\n",argv[argvindex]);
X		}
X	    }
X	    argvindex++;
X	}
X	printf("-------------------------------------------------------------------------------\n");
X	if ((wday == 5) || (wday == 6)) {
X	    wday++;
X	    julie++;
X	    date(julie);
X	    go = 1;
X	}
X	else {
X	    go = 0;
X	}
X    argvindex = holdargvi;
X    maxindex = holdmaxi;
X    }
X    exit(0);
X} /* main */
X
X
X/*
X * Procedure:	timeset()
X *
X * Function:	Gets current time and date
X *
X * Return Values:
X *	loads time and date info into global variables
X *
X */
X
Xtimeset()
X
X{
X    struct	tm *localtime();
X
X    struct tm *tp;		/* time structure */
X    long	tloc;		/* number of seconds since 1970 */
X
X    time(&tloc);	/* fills tloc */
X
X    tp = localtime(&tloc);
X
X    dow =	tp->tm_wday;
X    year =	tp->tm_year;
X    month =	tp->tm_mon + 1;
X    day =	tp->tm_mday;
X    hour = tp->tm_hour;
X    mhour = tp->tm_hour;
X    min = tp->tm_min;
X    sec = tp->tm_sec;
X
X    year += 1900;
X
X    if (sec >= 30)
X    {
X	min += 1;	/* round up minutes */
X	if (min == 60)
X	{
X	mhour += 1;
X	min = 0;
X	}
X    }
X
X    if (hour > 12)
X    {
X	hour -= 12;
X    }
X    if (hour >= 12)
X    {
X	ampm = 0;
X    }
X    else {
X	ampm = 1;
X    }
X} /* timeset */
X
X
X/*
X * Procedure:	loaddata()
X *
X * Function:	loads appointment data from ~/.appointments file
X *
X * Return Values:
X *	various global arrays loaded with appointment data
X *
X */
X
Xloaddata(filename)
X
Xchar	*filename;
X{
X    char	basedata[80];
X    char	tmpbuf[80];
X    char	*getenv();
X    FILE 	*fptr;
X    char	home[80];
X    int		i,j,k,l,field;
X    long	setjulie();
X    char	*malloc();
X
X    i = 0;
X    while (i < maxentries) {
X	daydata[i] = 0;
X	monthdata[i] = 0;
X	yeardata[i] = 0;
X	msgdata[i] = 0;
X	i++;
X    }
X
X    if (argvindex == 0) {
X	strcpy(home,getenv("HOME"));
X	strcat(home,"/.appointments");
X    }
X    else {
X	strcpy(home,filename);
X    }
X
X    if ((fptr = fopen(home,"r")) != NULL) {
X	i = 0;
X	while((fgets(basedata,80,fptr) != NULL)) {
X
X	    basedata[strlen(basedata)-1] = NULL;
X
X	    j = 0;
X	    k = 0;
X	    field = 0;
X	    while (basedata[j] != NULL ) {
X                 
X                if (basedata[j] != ',') {
X
X		    tmpbuf[k++] = basedata[j];
X		}
X		else {
X		    switch (field) {
X
X			case 0 : {
X			    tmpbuf[k] = NULL;
X			    monthdata[i] = atoi(tmpbuf);
X			    k = 0;
X			    break;
X			}
X			case 1 : {
X			    tmpbuf[k] = NULL;
X			    daydata[i] = atoi(tmpbuf);
X			    k = 0;
X			    break;
X			}
X			case 2 : {
X			    tmpbuf[k] = NULL;
X			    yeardata[i] = atoi(tmpbuf);
X			    k = 0;
X			    break;
X			}
X			case 3 : {
X			    tmpbuf[k] = NULL;
X			    timedata[i] = atoi(tmpbuf);
X			    k = 0;
X			    break;
X			}
X		    }
X		    field++;
X		}
X		j++;
X	    }
X	    tmpbuf[k] = NULL;
X	    msgdata[i] = malloc(40);
X	    strcpy(msgdata[i],tmpbuf);
X	    juliedata[i] = setjulie(monthdata[i],daydata[i],yeardata[i]);
X
X	    if (i >= maxentries) {
X		printf("Warning:  Over 1000 entries in %s file.  Data truncated.\n",filename);
X		break;
X	    }
X	    i++;
X	}
X	fclose(fptr);
X    }
X    else {
X	printf("Error:  cannot open %s file\n",filename);
X	exit(1);
X    }
X    return(i);
X} /* loaddata */
X
X
X/*
X * Procedure:	setdow(tmonth,tday,tyear)
X *
X * Function:	<short functional description>
X *
X * Parameters:
X *	p1	- int - month
X *	p2	- int - day
X *	p3	- int - year
X *
X * Return Values:
X *	interger value representing day of week with 1=sat, . . ., etc
X *
X */
X
Xsetdow(tmonth,tday,tyear)
X
Xint 		tmonth,tday,tyear;
X
X{
X
X    int		mcnt;
X    long	days;
X    int		tdow;
X    int		smonth,sday,syear;
X
X    smonth = 1;
X    sday = 1;
X    syear = 1979;
X
X    if ((tmonth == smonth) && (tyear == syear)) {
X	days = abs(sday - tday);
X    }
X    else {
X        days = mdays[smonth] - sday;
X        if (tyear == syear) {
X            while (++smonth < tmonth) {
X	        days += mdays[smonth];
X	        if ((smonth == 2) && ((syear % 4) == 0)) days++;
X	    }
X        }
X        else {
X            while (++smonth < 13) {
X	        days += mdays[smonth];
X                if ((smonth == 2) && ((syear % 4) == 0)) days++;
X            }
X	    while (++syear < tyear) {
X	        days += 365;
X	        if ((syear % 4) == 0 ) days ++;
X            }
X    
X	    mcnt = 0;
X            while (++mcnt < tmonth) {
X	        days += mdays[mcnt];
X	        if ((mcnt == 2) && ((tyear % 4) == 0)) days++;
X	    }
X        }
X        days += tday;
X    }
X
X    tdow = ((days%7) + 1);
X
X    return(tdow);
X} /* setdow */
X
X
X/*
X * Procedure:	setjulie(tmonth,tday,tyear)
X *
X * Function:	calculates the julian date
X *
X * Parameters:
X *	p1	- int - month
X *	p2	- int - day
X *	p2	- int - year
X *
X * Return Values:
X *	julian date as a long
X *
X */
X
Xlong setjulie(tmonth,tday,tyear)
X
Xint		tmonth,tday,tyear;
X
X{
X
X    int		mcnt;
X    long	days;
X    int		tdow;
X    int		smonth,sday,syear;
X
X    smonth = 1;
X    sday = 1;
X    syear = 1979;
X
X    if ((tmonth == smonth) && (tyear == syear)) {
X	days = abs(sday - tday);
X    }
X    else {
X        days = mdays[smonth] - sday;
X        if (tyear == syear) {
X            while (++smonth < tmonth) {
X	        days += mdays[smonth];
X	        if ((smonth == 2) && ((syear % 4) == 0)) days++;
X	    }
X        }
X        else {
X            while (++smonth < 13) {
X	        days += mdays[smonth];
X                if ((smonth == 2) && ((syear % 4) == 0)) days++;
X            }
X	    while (++syear < tyear) {
X	        days += 365;
X	        if ((syear % 4) == 0 ) days ++;
X            }
X    
X	    mcnt = 0;
X            while (++mcnt < tmonth) {
X	        days += mdays[mcnt];
X	        if ((mcnt == 2) && ((tyear % 4) == 0)) days++;
X	    }
X        }
X        days += tday;
X    }
X
X    return(days);
X} /* setjulie */
X
X
X/*
X * Procedure:	date(days)
X *
X * Function:	calculates the current month, day and year
X *
X * Parameters:
X *	p1	- int - number days offset from 1,1,1979
X *
X * Return Values:
X *	sets global variable, month, day and year to calc value
X *
X */
X
Xdate(days)
X
Xlong   days;
X
X{
X
X    int    cnt;
X
X    month = 1;
X    day = 1;
X    year = 1979;
X
X    while (days--) {
X	if (++day > mdays[month]) {
X	    day = 1;
X	    if (++month > 12) {
X		month = 1;
X		year++;
X	    }
X	    if ((month == 2) && !(year % 4)) {
X		day--;
X	    }
X	}
X    }
X} /* date */
*-*-END-of-appts.c-*-*
echo x - autocall.c
sed 's/^X//' >autocall.c <<'*-*-END-of-autocall.c-*-*'
X/*
X * Module:	autocall.c
X *
X * Purpose:	notifies user at specified day and time of an
X *		appointment
X *
X * Author:	Mike Essex
X *
X * Date:	Sep 19, 1986
X *
X * Includes:
X *	time.h, stdio.h, signal.h
X *
X * Discussion:
X *	This program spawns background processes for each of the
X *	current date's entries in the user's ~/.appointments file.
X *      At the specified time of day the process outputs the
X *	message associated with the entry and dies.
X * 
X *
X * Edit History
X * ==== =======
X *
X * Date      Who	What
X * ----      ---	----------------------------------------------
X * 12/1/86   me		added multi-datafile capability
X * 12/1/86   me		changed 'home' from *home[80] to home[80]
X * 12/1/86   me		changed int maxentries to #define MAXENTRIES
X *
X */
X
X#include <time.h>
X#include <stdio.h>
X#include <signal.h>
X
X#define		MAXENTRIES 1000
X
Xint		monthdata[MAXENTRIES];
Xint		daydata[MAXENTRIES];
Xint		yeardata[MAXENTRIES];
Xint		timedata[MAXENTRIES];
Xchar		*msgdata[MAXENTRIES];
Xint		month,day,year,hour,mhour,min,sec,dow,ampm;
Xint		cntr;
Xint		argvindex;
X
X
X/*
X * Procedure:	main()
X *
X * Function:	initializes variables, calls data load, calculates
X *		sleep time for message, forks message process
X */
X
Xmain(argc,argv)
X
Xint	argc;
Xchar	*argv[];
X
X{
X    int		cnt,timeout,status,nowtime;
X    int		loaddata();
X
X    signal(SIGINT,SIG_IGN);
X    signal(SIGQUIT,SIG_IGN);
X
X    if (argc > 1) {
X	argvindex = 1;
X    }
X    else {
X	argvindex = 0;
X    }
X    while (argvindex <= argc) {
X	cntr = 0;
X	if ((cnt = loaddata(argv[argvindex])) != 0 ) {
X	    timeset();
X	    while (cntr < cnt) {
X		nowtime = (mhour * 60) + min;
X		if ((monthdata[cntr] == month) && (daydata[cntr] == day)
X		&& (yeardata[cntr] == year) && (timedata[cntr] > nowtime)) {
X		    timeout = (timedata[cntr] - nowtime) * 60;
X		    if ( timeout > 300 ) {
X			timeout -= 300;
X		    }
X		    if ((status = fork()) == 0) {
X			ringer(timeout,msgdata[cntr]);
X			exit(0);
X		    }
X		    else {
X			if (status < 0) {
X			    printf("Error:  Cannot start new autocall process\n");
X			}
X		    }
X		}
X		cntr++;
X	    }
X	}
X	argvindex++;
X    }
X    exit(0);
X} /* main */
X
X
X
X/*
X * Procedure:	timeset()
X *
X * Function:	sets current date and time
X *
X * Return Values:
X *	sets global varialbes to date and time
X */
X
Xtimeset()
X
X{
X    struct	tm *localtime();
X
X    struct tm *tp;		/* time structure */
X    long	tloc;		/* number of seconds since 1970 */
X
X    time(&tloc);	/* fills tloc */
X
X    tp = localtime(&tloc);
X
X    dow =	tp->tm_wday;
X    year =	tp->tm_year;
X    month =	tp->tm_mon + 1;
X    day =	tp->tm_mday;
X    hour = tp->tm_hour;
X    mhour = tp->tm_hour;
X    min = tp->tm_min;
X    sec = tp->tm_sec;
X
X    year += 1900;
X
X    if (sec >= 30)
X    {
X	min += 1;	/* round up minutes */
X	if (min == 60)
X	{
X	mhour += 1;
X	hour += 1;
X	min = 0;
X	}
X    }
X
X    if (hour > 12)
X    {
X	hour -= 12;
X    }
X    if (mhour >= 12)
X    {
X	ampm = 1;
X    }
X    else {
X	ampm = 0;
X    }
X} /* timeset */
X
X
X
X/*
X * Procedure:	loaddata()
X *
X * Function:	load appointments data
X *
X * Return Values:
X *	loads various global arrays with appointment data
X *
X * Discussion:
X *	opens ~/.appointments file and inputs data, then puts
X *	it into appropriate arrays
X */
X
Xloaddata(datafile)
X
Xchar	*datafile;
X{
X    char	basedata[80];
X    char	tmpbuf[80];
X    char	*getenv();
X    FILE 	*fptr;
X    char	home[80];
X    int		msgtime,i,j,k,l,field;
X    char	*malloc();
X
X    i = 0;
X    while (i < MAXENTRIES) {
X	daydata[i] = 0;
X	monthdata[i] = 0;
X	yeardata[i] = 0;
X	msgdata[i] = 0;
X	i++;
X    }
X
X    if (argvindex == 0) {
X	strcpy(home,getenv("HOME"));
X	strcat(home,"/.appointments");
X    }
X    else {
X	strcpy(home,datafile);
X    }
X
X    if ((fptr = fopen(home,"r")) != NULL) {
X	i = 0;
X	while((fgets(basedata,80,fptr) != NULL)) {
X
X	    basedata[strlen(basedata)-1] = NULL;
X
X	    j = 0;
X	    k = 0;
X	    field = 0;
X	    while (basedata[j] != NULL ) {
X                 
X                if (basedata[j] != ',') {
X
X		    tmpbuf[k++] = basedata[j];
X		}
X		else {
X		    switch (field) {
X
X			case 0 : {
X			    tmpbuf[k] = NULL;
X			    monthdata[i] = atoi(tmpbuf);
X			    k = 0;
X			    break;
X			}
X			case 1 : {
X			    tmpbuf[k] = NULL;
X			    daydata[i] = atoi(tmpbuf);
X			    k = 0;
X			    break;
X			}
X			case 2 : {
X			    tmpbuf[k] = NULL;
X			    yeardata[i] = atoi(tmpbuf);
X			    k = 0;
X			    break;
X			}
X			case 3 : {
X			    tmpbuf[k] = NULL;
X			    msgtime = atoi(tmpbuf);
X			    timedata[i] = ((msgtime / 100 ) * 60) + (msgtime % 100);
X			    k = 0;
X			    break;
X			}
X		    }
X		    field++;
X		}
X		j++;
X	    }
X	    tmpbuf[k] = NULL;
X	    msgdata[i] = malloc(40);
X	    strcpy(msgdata[i],tmpbuf);
X
X	    if (i >= MAXENTRIES) {
X		printf("Warning:  Over 1000 entries in %s file.  Data truncated.\n",datafile);
X		break;
X	    }
X	    i++;
X	}
X	fclose(fptr);
X    }
X    else {
X	printf("Error:  cannot open %s file.\n",datafile);
X    }
X    return(i);
X} /* loaddata */
X
X
X/*
X * Procedure:	ringer(delay,message)
X *
X * Function:	outputs appointment message at appropriate time
X *
X * Parameters:
X *	p1	- int - delay time in seconds
X *	p2	- char pointer - pointer to appointment message
X *
X * Discussion:
X *	Takes in delay time and sleeps until delay is completed.
X *	Then it outputs the message to standard out and dies.
X */
X
Xringer(delay,message)
X
X    int		delay;
X    char	*message;
X{
X    sleep(delay);
X    timeset();
X    printf("\r\nTime %d:%02d %2s    ", hour, min, (ampm == 0 ? "AM" : "PM"));
X    printf("Activity scheduled:  %s \r\n\n",message);
X} /* ringer */
*-*-END-of-autocall.c-*-*
echo x - callme.c
sed 's/^X//' >callme.c <<'*-*-END-of-callme.c-*-*'
X/*
X * Module:	callme.c
X *
X * Purpose:	prompts user at time of an appointment
X *
X * Author:	Mike Essex
X *
X * Date:	Sep. 16, 1986
X *
X * Includes:
X *	time.h, stdio.h, signal.h
X *
X * Discussion:
X *	Takes in time and message from commands line, sleeps an
X *	appropriate amount of time and then displays message.
X * 
X *
X * Edit History
X * ==== =======
X *
X * Date      Who	What
X * ----      ---	----------------------------------------------
X *
X */
X
X
X#include <time.h>
X#include <stdio.h>
X#include <signal.h>
X
Xint		mindata,timedata;
Xchar		msgdata[512];
Xint		month,day,year,hour,mhour,min,sec,dow,ampm;
X
X
X/*
X * Procedure:	main.c
X *
X * Function:	parses command line, calculates delay and starts
X *		background process for message.
X */
X
Xmain(argc,argv)
X
Xint		argc;
Xchar		*argv[];
X
X{
X    int		i,timeout,status,nowtime;
X
X    signal(SIGINT,SIG_IGN);
X    signal(SIGQUIT,SIG_IGN);
X
X    if (argc < 3) {
X	printf("\r\n          Syntax error:  Incorrect number of arguments          \r\n");
X	printf("          Syntax:  callme (time) (message)                        \r\n\n");
X	exit(1);
X    }
X
X    timedata = atoi(argv[1]);
X    mindata = (60*(timedata/100)) + (timedata % 100);
X    i = 2;
X    while (i < argc) {
X        strcat(msgdata,argv[i++]);
X	strcat(msgdata," ");
X    }
X    timeset();
X    nowtime = (mhour * 60) + min;
X    if ( mindata > nowtime) {
X	timeout = (mindata - nowtime) * 60;
X	if ( timeout > 300 ) {
X	    timeout -= 300;
X	}
X	if ((status = fork()) == 0) {
X	    ringer(timeout,msgdata);
X	    exit(0);
X	}
X	else {
X	    if (status < 0) {
X		printf("* Cannot start new sleeper process *\n");
X	    }
X	}
X    }
X    else {
X	printf("It is already past %d\n",timedata);
X    }
X    exit(0);
X} /* main */
X
X
X
X/*
X * Procedure:	timeset()
X *
X * Function:	loads current time
X *
X * Return Values:
X *	sets global variables for time and date
X */
X
Xtimeset()
X
X{
X    struct	tm *localtime();
X
X    struct tm *tp;		/* time structure */
X    long	tloc;		/* number of seconds since 1970 */
X
X    time(&tloc);	/* fills tloc */
X
X    tp = localtime(&tloc);
X
X    dow =	tp->tm_wday;
X    year =	tp->tm_year;
X    month =	tp->tm_mon + 1;
X    day =	tp->tm_mday;
X    hour = tp->tm_hour;
X    mhour = tp->tm_hour;
X    min = tp->tm_min;
X    sec = tp->tm_sec;
X
X    year += 1900;
X
X    if (sec >= 30)
X    {
X	min += 1;	/* round up minutes */
X	if (min == 60)
X	{
X	mhour += 1;
X	hour += 1;
X	min = 0;
X	}
X    }
X
X    if (hour > 12)
X    {
X	hour -= 12;
X    }
X    if (mhour >= 12)
X    {
X	ampm = 1;
X    }
X    else {
X	ampm = 0;
X    }
X} /* timeset */
X
X
X
X/*
X * Procedure:	ringer(delay,message)
X *
X * Function:	prompts user with message at appropriate time
X *
X * Parameters:
X *	p1	- int - delay time
X *	p2	- character pointer - pointer to message
X * Discussion:
X *	sleeps specified amount of time, then outputs message and dies.
X */
X
Xringer(delay,message)
X
X    int		delay;
X    char	*message;
X{
X    sleep(delay);
X    timeset();
X    printf("\r\n                                                                               \r\n"); 
X    printf("Time %d:%02d %2s   ", hour, min, (ampm == 0 ? "AM" : "PM"));
X    printf("Activity scheduled:  %-41.41s ",message);
X    printf("\r\n                                                                               \r\n"); 
X} /* ringer */
*-*-END-of-callme.c-*-*
echo x - appts.l
sed 's/^X//' >appts.l <<'*-*-END-of-appts.l-*-*'
X.TH APPTS 1 
X.SH NAME
Xappts \- display current or selected day's appointments
X.SH SYNOPSIS
X.B appts 
X[ month day year ] [ filename(s) ]
X.sp
Xwhere
X.I        month
Xis a numeric value between 1 and 12,
X.I        day
Xis a numeric value between 1 and 31,
X.I        year
Xis a numeric four digit value and
X.I        filename(s)
Xis the name of the data file(s) to access.
X.SH DESCRIPTION
X.I Appts
Xis a program which uses the data stored by "vcal" or "eappts" to
Xdisplay the user's appointments to standard out.
X.PP
XWhen a date argument is present,
X.I appts
Xwill display appointments for the requested month, day and year.
XThe default argument values are the current month, day and year.
XWhen one or more filename arguments are used,
Xthose data files will be searched.
X.PP
XFive companion programs are available to use with the
X.I appts
Xprogram.  These are:
X.br
X.sp
X.nf
Xvcal            calendar and notes program
Xeappts          enter appointments from the UNIX command line
Xautocall        set appointment reminders for the current day
Xlcal            displays month's appointments in tablular form
Xcallme          sets a reminder prompt
X.fi
X.sp
XFor further information on these, reference the appropriate "man"
Xentries.
X.SH AUTHOR
XMike Essex
X.SH FILES
Xappts
X.br
X~/.appointments
X.br
X.SH "SEE ALSO"
Xvcal(1), eappts(1), autocall(1), lcal(1), callme(1)
X.SH BUGS
XThere are year 2000 time bombs.
*-*-END-of-appts.l-*-*
echo x - autocall.l
sed 's/^X//' >autocall.l <<'*-*-END-of-autocall.l-*-*'
X.TH AUTOCALL 1 
X.SH NAME
Xautocall \- appointment reminder program
X.SH SYNOPSIS
X.B autocall [ filename(s) ]
X.SH DESCRIPTION
X.I Autocall
Xis a program which will start appointment reminders running in
Xthe background.  At the desired time the user will be reminded
Xthat it is time for the appointment.
X.I Autocall
Xsearches ~/.appointments by default or if filename(s) are
Xspecified it accesses those files.
X.PP
XData used by
X.I autocall
Xmay be entered using either of two companion programs.
XThese are:
X.br
X.sp
X.nf
Xvcal            calendar and notes program
Xeappts          enter appointments from the UNIX command line
X.fi
X.sp
XFor further information on these, reference the appropriate "man"
Xentries.
X.SH AUTHOR
XMike Essex
X.SH FILES
Xautocall
X.br
X~/.appointments
X.br
X.SH "SEE ALSO"
Xvcal(1), eappts(1), callme(1), lcal(1), appts(1)
*-*-END-of-autocall.l-*-*
echo x - callme.l
sed 's/^X//' >callme.l <<'*-*-END-of-callme.l-*-*'
X.TH CALLME 1 
X.SH NAME
Xcallme \- appointment reminder program
X.SH SYNOPSIS
X.B callme
X(time) (message)
X.SH DESCRIPTION
X.I Callme
Xis a program which will start appointment reminders running in
Xthe background.  At the desired time the user will be reminded
Xthat it is time for the appointment.  The time and message for the
Xcall are entered on the command line.  The time must be entered in
X24 hour time with no colon.
X.SH AUTHOR
XMike Essex
X.SH "SEE ALSO"
Xautocall(1), vcal(1), callme(1), lcal(1), appts(1), eappts(1)
*-*-END-of-callme.l-*-*
exit