[net.sources] Suntools alarmer

black@unc.UUCP (01/22/86)

Here's a neat little program I recently came up with for
all you Sun users out there.

#----------------------  CUT HERE  ----------------------
#! /bin/sh
#
#  This is a shell archive.  Use /bin/sh to unpack.
#
echo "extracting README (210 bytes)"
sed 's/^X //' << '***FUBAR***' > README
X This archive contains the following files:
X 
X 	README
X 	Makefile
X 	alarm.c		source code
X 	alarm.l		unformatted man entry
X 	alarm.man	formatted man entry
X 	alarm_off	icon file
X 	alarm_on	icon file
X 	alarm_on2	icon file
X 
***FUBAR***
echo "extracting Makefile (197 bytes)"
sed 's/^X //' << '***FUBAR***' > Makefile
X #
X #  Makefile for suntools alarmer
X #
X BIN	= alarm
X SRC	= $(BIN).c
X CC	= cc
X COPTS	= 
X ICON	= -DICON_DIR="/usr/local/lib/icons"
X STRIP	= strip
X 
X $(BIN)	: $(SRC)
X 	cc -o $@ $(ICON) $(CFLAGS) $?
X 	$(STRIP) $@
***FUBAR***
echo "extracting alarm.L (3038 bytes)"
sed 's/^X //' << '***FUBAR***' > alarm.L
X .TH ALARM L "21 January 1986"
X .SH NAME
X alarm \- a periodic alarmer for suntools
X .SH SYNOPSIS
X \f3alarm\fP [\f3-h\fP \f2min\fP] [\f3alarmdb\fP]
X .SH DESCRIPTION
X .LP
X \f2alarm\fP reads an alarm database and signals the user whenever
X one of the alarms becomes active.  If \f3alarmdb\fP is not
X specified, ~/.alarm will be used.
X .LP
X The format of the lines in the alarm database is as follows:
X .LP
X .RS
X date    time    message
X .RE
X .LP
X Lines starting with a # and blank lines are ignored.  `date' can be any of
X the following.  Minimum abbreviations are in caps, and case is insignificant:
X .LP
X .RS
X .nf
X Sundays       Mondays      Tuesdays       Wednesdays
X THursdays     Fridays      SAturdays
X .fi
X .LP
X Daily         Any
X .LP
X month/day
X .RE
X .LP
X Specifying `month/day' creates a "one-shot" alarm; the others are periodic.
X `time' is in the form hour:minute (based on a 24-hour clock; 0:00 - 23:59).
X `message' is anything you want.  The program will read in this file, and
X when an alarm is to go off, it will do one of the following:
X .RS
X .TP
X 1)
X if the window is closed (iconic), the icon will
X flash to indicate an alarm.  Open the window to
X acknowledge the alarm.  Now, since the window is
X open,
X .TP
X 2)
X if the window is open, the entire line will be written out.
X .RE
X .LP
X If you change your alarm database (~/.alarm or `alarmdb'), you have to tell
X the program to re-read the file (if you wish).  To do this, run ~/.alarmreset,
X which the alarm program creates when it starts up.
X .SH OPTIONS
X .LP
X There is only one option:
X .TP
X \f3-h\fP \f2min\fP
X Specify the initial history value, in minutes.  \f2alarm\fP will
X signal alarms in the last \f2min\fP minutes when initially starting
X up.  The default time is 60 minutes.
X .SH ENVIRONMENT
X .LP
X \f2alarm\fP looks at the environment variable ICONDIR for the directory
X containing the icons.  The default directory is defined in the Makefile.
X .SH "SAMPLE \f3~/.alarm\fP FILE"
X .nf
X #
X #  alarm database for /usr/local/bin/alarm
X #
X #  copyright 1986 Exploding Penguin Software
X #
X .sp
X #
X #  Weekly alarms
X #
X mon     10:50   GRIP meeting at 11:00
X wed     12:20   Tech meeting at 12:30.
X fri     11:50   Faculty meeting at 12:00
X .sp
X #
X #  Daily alarms
X #
X daily   16:50   Time to go home!
X daily   17:00   What are you still doing here?
X .sp
X #
X #  One-time alarms
X #
X 1/22    15:50   Bentley seminar at 4:00.
X 1/24    15:20   Seminar at 3:30.
X .fi
X .SH BUGS
X .LP
X Invalid dates and time are accepted (4/38 = 5/8; 5:80 = 6:20).  Error checking
X is only done on the format of the input, not on the values contained therein.
X .LP
X The program may or may not work correctly when Daylight Savings Time goes into
X effect.  It also may or may not work in different time zones.  These cases
X have not been tested.  If you have any problems, please contact the author.
X .SH FILES
X .LP
X .ta 2.8i
X .nf
X /usr/local/bin/alarm	The program
X $ICONDIR/alarm_off	Icon for quiescent state
X $ICONDIR/alarm_on	Icons for active state
X $ICONDIR/alarm_on2	   (toggles between these two)
X ~/.alarm	Alarm database
X ~/.alarmreset	Alarm signaller
X .fi
X .SH AUTHOR
X .LP
X Samuel Black (black@unc)
***FUBAR***
echo "extracting alarm.c (9756 bytes)"
sed 's/^X //' << '***FUBAR***' > alarm.c
X #include <stdio.h>
X #include <pwd.h>
X #include <sgtty.h>
X #include <ctype.h>
X #include <signal.h>
X #include <setjmp.h>
X #include <sys/file.h>
X #include <sys/time.h>
X #include <sys/types.h>
X #include <sys/timeb.h>
X 
X #ifdef DEBUG
X #	define DEB(x)	fprintf/**/x
X #else
X #	define DEB(x)
X #endif DEBUG
X 
X #define when		break; case
X #define otherwise	break; default
X #define nitems(x)	(sizeof(x) / sizeof(x[0]))
X 
X #define IOCTL(op, par)			\
X 	if (ioctl(0, op, par) < 0)	\
X 	{				\
X 		perror("tty");		\
X 		exit(-1);		\
X 	}
X 
X #define NEW(t)	(t *) malloc(sizeof(t))
X #define FREENODE			\
X 	{				\
X 		TIMES *tmp = alarms;	\
X 					\
X 		alarms = alarms->next;	\
X 		free(tmp);		\
X 	}
X 
X #define CONFIG_FILE	".alarm"
X #define RESET_FILE	".alarmreset"
X #define RESET		"kill -%d %ld"
X #define SIGREAD		SIGEMT
X 
X #define QUERY		"\033[11t"
X #define RESPONSE	"\033[%dt"
X #define ICONIC		2
X 
X #define SIGNAL(x)	printf(alarm_/**/x)
X #define ICON_DIR	"/unc/black/icons"
X #define IMAGE		"\033]I%s/alarm_%s\033\134"
X #define IHEADER		"\033]L\033\134"
X 
X /*
X **  Time constants
X */
X #define SPM	 60			/* seconds per minute */
X #define SPH	(60 * SPM)		/* seconds per hour */
X #define SPD	(24 * SPH)		/* seconds per day */
X #define LOOK	(SPD >> 1)
X #define JAN_86	504921600L		/* 1 January, 1986 */
X 
X /*
X **  Types
X */
X #define STRLEN		80
X typedef char STRING[STRLEN];
X 
X typedef struct TIMES		/* the TIMES structure */
X {
X 	int time;		/* how many seconds into the epoch */
X 	STRING message;
X 	struct TIMES *next;
X } TIMES;
X 
X static TIMES *read_alarm_file();
X static TIMES *insert();
X static long gettime();
X static int iconic();
X static void usage();
X static void setup_term();
X static void lowercase();
X static long date_to_time();
X int reset_term();
X int reset_alarm();
X long time();
X 
X jmp_buf env;
X char *pname;
X 
X /*
X **  This program is a SUN alarmer.  It reads an alarm database,
X **  then flashes the alarm bell whenever the appropriate time
X **  occurs.
X */
X 
X main(argc, argv)
X int argc;
X char *argv[];
X {
X 	STRING	alarm_on,	/* alarm on icon (normal) */
X 		alarm_inv,	/* alarm on icon (inverted) */
X 		alarm_off;	/* alarm off icon */
X 	STRING alarmdb;		/* alarm file name */
X 	STRING reset;		/* reset file name */
X 	int rfile;
X 	TIMES *alarms;		/* alarm structure */
X 	long getpid();
X 	char *getenv();
X 	struct passwd *getpwuid();
X 	struct passwd *p_entry;
X 	int history = -SPH;
X 	int i;
X 	char *icon_dir;
X 
X 	pname = *argv;
X 
X 	if ( (p_entry = getpwuid(getuid())) )
X 	{
X 		sprintf(alarmdb, "%s/%s", p_entry->pw_dir, CONFIG_FILE);
X 		sprintf(reset, "%s/%s", p_entry->pw_dir, RESET_FILE);
X 	}
X 	else
X 	{
X 		perror("getuid");
X 		exit(-1);
X 	}
X 
X 	/*
X 	**  Take the arguments.  The only legal one now is an
X 	**  optional database file.  If one is not given, use
X 	**  the default.
X 	*/
X 	while (--argc)
X 		if (**++argv == '-')
X 			switch ((*argv)[1])
X 			{
X 				when 'h':  i = atoi(*++argv);
X 					   if ((i >= 0) && (i <= SPM))
X 						history = -60 * i;
X 					   --argc;
X 				otherwise: usage(pname);
X 			}
X 		else
X 			strcpy(alarmdb, *argv);
X 
X 
X 	/*
X 	**  Enable the user to signal this process
X 	*/
X 	if ((rfile = open(reset, O_TRUNC | O_WRONLY | O_CREAT, 0700)) == -1)
X 	{
X 		perror("open");
X 		exit(-1);
X 	}
X 	else
X 	{
X 		sprintf(reset, RESET, SIGREAD, getpid());
X 		write(rfile, reset, strlen(reset));
X 		close(rfile);
X 	}
X 
X 	/*
X 	**  Set up the icons
X 	*/
X 	if (!(icon_dir = getenv("ICONDIR")))
X 		icon_dir = ICON_DIR;
X 	sprintf(alarm_on,  IMAGE, icon_dir, "on");
X 	sprintf(alarm_inv, IMAGE, icon_dir, "on2");
X 	sprintf(alarm_off, IMAGE, icon_dir, "off");
X 
X 	/*
X 	**  Read in the alarm file.
X 	*/
X 	DEB((stderr, "About to read alarm file\n"));
X 	alarms = read_alarm_file(alarmdb, history);
X 
X 	/*
X 	**  Set up the icon and the tty driver.
X 	*/
X 	setup_term();
X 	printf(IHEADER);
X 	SIGNAL(off);
X 	fflush(stdout);
X 
X 	/*
X 	**  Set up signal trapping.
X 	*/
X 	for (i = SIGHUP; i <= SIGPROF; ++i)
X 		signal(i, reset_term);
X 
X 	signal(SIGREAD, reset_alarm);
X 
X 	/*
X 	**  Trap SIGREAD.
X 	*/
X 	if (setjmp(env))
X 	{
X 		while (alarms)
X 			FREENODE;
X 		alarms = read_alarm_file(alarmdb, 0);
X 		signal(SIGREAD, reset_alarm);
X 	}
X 
X 	/*
X 	**  Repeat ad nauseum.
X 	*/
X 	for (;;)
X 	{
X 		/*
X 		**  Sleep until the next alarm.
X 		*/
X 		if (alarms->time > time(0))
X 		{
X 			DEB((stderr, "Sleeping for %ld seconds.\n",
X 				alarms->time - time(0)));
X 			sleep((int) (alarms->time - time(0)));
X 		}
X 		else
X 			DEB((stderr, "Not sleeping.\n"));
X 
X 		/*
X 		**  Check to see if we need to re-read the file.
X 		*/
X 		if (!alarms->next)
X 		{
X 			FREENODE;
X 			alarms = read_alarm_file(alarmdb, 0);
X 		}
X 		else
X 		{
X 			/*
X 			**  Indicate the alarm, and wait for the user
X 			**  to open the window.
X 			*/
X 			while (iconic())
X 			{
X 				SIGNAL(on);
X 				SIGNAL(inv);
X 			}
X 
X 			/*
X 			**  Dump ALL current alarm messages.
X 			*/
X 			putchar('\n');
X 			do
X 			{
X 				puts(alarms->message);
X 				FREENODE;
X 			} while (alarms->next && (alarms->time <= time(0)));
X 
X 			/*
X 			**  Turn the clock off.
X 			*/
X 			SIGNAL(off);
X 			fflush(stdout);
X 		}
X 	}
X }
X 
X struct sgttyb save_tty;
X 
X static void
X setup_term()
X {
X 	struct sgttyb tty;
X 
X 	IOCTL(TIOCGETP, &tty);
X 	save_tty = tty;
X 
X 	tty.sg_flags &= ~ECHO;
X 	tty.sg_flags |= CBREAK;
X 
X 	IOCTL(TIOCSETP, &tty);
X }
X 
X int
X reset_term(sig)
X int sig;
X {
X 	IOCTL(TIOCSETP, &save_tty);
X 	exit(sig);
X }
X 
X int
X reset_alarm()
X {
X 	longjmp(env);
X }
X 
X int daily;
X int cwday,	/* day of week */
X     cday,	/* day of month */
X     cmonth,	/* month of year */
X     cyear;	/* year */
X int TZ;		/* difference to GMT */
X 
X static TIMES *
X read_alarm_file(fname, history)
X STRING fname;
X int history;
X {
X 	FILE *fopen();
X 	struct tm *localtime();
X 	FILE *alarmdb;
X 	TIMES *alarms, *cur;
X 	char input[160];
X 	long ctime;		/* current time-of-day */
X 	long itime;		/* alarm entry time-of-day */
X 	long rtime;		/* relative to current time-of-day */
X 	struct tm *ltime;
X 	struct timeb tp;
X 
X 	/*
X 	**  Open the alarm database
X 	*/
X 	if (!(alarmdb = fopen(fname, "r")))
X 	{
X 		perror(fname);
X 		usage(pname);
X 	}
X 
X 	/*
X 	**  Calculate the current time of day.
X 	*/
X 	ftime(&tp);
X 	ctime = tp.time;
X 	TZ = tp.timezone * SPM;
X 	ltime = localtime(&ctime);
X 	DEB((stderr, "Current time = %ld\n", ctime));
X 	cmonth = ltime->tm_mon + 1;
X 	cday = ltime->tm_mday;
X 	cyear = ltime->tm_year;
X 	cwday = ltime->tm_wday - 7;
X 	DEB((stderr, "cmonth = %d, cday = %d, cyear = %d, cwday = %d\n",
X 		cmonth, cday, cyear, cwday));
X 
X 	/*
X 	**  Read the alarms file and put each alarm
X 	**  in the structure, sorted by time.  Only
X 	**  alarms in the next 12 hours are entered.
X 	*/
X 	alarms = NEW(TIMES);
X 	alarms->time = ctime + LOOK;
X 	strcpy(alarms->message, "12 hour timer interrupt");
X 	alarms->next = NULL;
X 
X 	while (fgets(input, sizeof(input), alarmdb))
X 	{
X 		input[strlen(input) - 1] = '\0';
X 		rtime = (itime = gettime(input)) - ctime;
X 
X 		if (daily)
X 		{
X 			if (rtime > LOOK)
X 			{
X 				rtime -= SPD;
X 				itime -= SPD;
X 			}
X 			else if (rtime < -LOOK)
X 			{
X 				rtime += SPD;
X 				itime += SPD;
X 			}
X 		}
X 
X 		if ((rtime < LOOK) && (rtime >= history))
X 		{
X 			cur = NEW(TIMES);
X 			cur->time = itime;
X 			strcpy(cur->message, input);
X 
X 			alarms = insert(alarms, cur);
X 		}
X 	}
X 
X 	fclose(alarmdb);
X 	traverse(alarms);
X 	return(alarms);
X }
X 
X #define ISDAY(s) !strncmp(dow, s, strlen(dow))
X 
X static long
X gettime(input)
X char *input;
X {
X 	int date[5];
X 	STRING dow;	/* for weekly or daily alarms */
X 	static STRING days[] =
X 	{
X 		"sundays",
X 		"mondays",
X 		"tuesdays",
X 		"wednesdays",
X 		"thursdays",
X 		"fridays",
X 		"saturdays"
X 	};
X 
X 	daily = 0;
X 	if ((sscanf(input, "%s", dow) != 1) || (*dow == '#'))
X 		return(0L);
X 	if (isdigit(*dow))
X 		sscanf(input, "%d/%d %d:%d %[^\n]",
X 			&date[0], &date[1], &date[3], &date[4]);
X 	else
X 	{
X 		register int i;
X 
X 		sscanf(input, "%s %d:%d %[^\n]", dow, &date[3], &date[4]);
X 		lowercase(dow);
X 		*date = cmonth;
X 
X 		if (ISDAY("any") || ISDAY("daily"))
X 		{
X 			date[1] = cday;
X 			daily = 1;
X 		}
X 		else
X 		{
X 			for (i = 0; i < nitems(days); ++i)
X 				if (ISDAY(days[i]))
X 				{
X 					date[1] = cday + ((i - cwday) % 7);
X 					break;
X 				}
X 			if (i == nitems(days))
X 			{
X 				fprintf(stderr,
X 					"'%s' is an invalid alarm entry.\n",
X 					input);
X 				return(0L);
X 			}
X 		}
X 
X 		DEB((stderr, "periodic reminder: %s becomes %d/%d\n",
X 				dow, date[0], date[1]));
X 	}
X 
X 	if ((date[0] > cmonth) || ((date[0] == cmonth) && (date[1] >= cday)))
X 		date[2] = cyear;
X 	else
X 		date[2] = cyear + 1;
X 
X 	return(date_to_time(date));
X }
X 
X static void
X lowercase(str)
X char *str;
X {
X 	for ( ; *str; ++str)
X 		if (isupper(*str))
X 			*str = tolower(*str);
X }
X 
X /*
X **  Take an array of [month day year hour minute]
X **  and return the number of seconds since the epoch.
X */
X static long
X date_to_time(date)
X int *date;
X {
X 	static int corr[] =
X 	{
X 		0, 1, -1, 0, 0, 1, 1, 2, 3, 3, 4, 4
X 	};
X 	int month  = *date - 1;
X 	int day  = *++date - 1;
X 	int year = *++date;
X 	int hour = *++date;
X 	int min = *++date;
X 	int leap = ((month > 1) && (dysize(year) == 366));
X 	register int ydisp = (30 * month + day + corr[month]) * SPD;
X 	register int i;
X 
X 	if (leap)
X 		ydisp += SPD;
X 
X 	for (i = 86; i < year; ++i)
X 		ydisp += (SPD + dysize(i));
X 
X 	DEB((stderr, "Time for %d/%d, %d at %d:%2d = %ld\n",
X 			month+1, day+1, year, hour, min,
X 			JAN_86 + TZ + ydisp + (hour * SPH) + (min * SPM)));
X 
X 	return(JAN_86 + TZ + ydisp + (hour * SPH) + (min * SPM));
X }
X 
X /*
X **  Perform an insertion sort.
X */
X static TIMES *
X insert(node, el)
X TIMES *node, *el;
X {
X 	TIMES *last = NULL;
X 	TIMES *root = node;
X 
X 	DEB((stderr, "Inserting node.  time = %ld, msg = '%s'\n",
X 			el->time, el->message));
X 	while (node->next && (node->time < el->time))
X 	{
X 		last = node;
X 		node = node->next;
X 	}
X 
X 	el->next = node;
X 	if (last)
X 		last->next = el;
X 	else
X 		root = el;
X 
X 	return(root);
X }
X 
X traverse(alarms)
X TIMES *alarms;
X {
X #ifdef DEBUG
X 	putc('\n', stderr);
X 	for ( ; alarms; alarms = alarms->next)
X 		fprintf(stderr, "alarm at time = %ld; msg = %s\n",
X 			alarms->time, alarms->message);
X #endif DEBUG
X }
X 
X static int
X iconic()
X {
X 	int ans;
X 
X 	IOCTL(TIOCFLUSH, 0);
X 	printf(QUERY);
X 	scanf(RESPONSE, &ans);
X 
X 	return(ans == ICONIC);
X }
X 
X static void
X usage(pname)
X char *pname;
X {
X 	printf("usage: %s [-h history] [alarmfile]\n", pname);
X 	exit(-1);
X }
***FUBAR***
echo "extracting alarm.man (3702 bytes)"
sed 's/^X //' << '***FUBAR***' > alarm.man
X 
X 
X 
X ALARM(L)          UNKNOWN SECTION OF THE MANUAL          ALARM(L)
X 
X 
X 
X NAME
X      alarm - a periodic alarmer for suntools
X 
X SYNOPSIS
X      alarm [-h _m_i_n] [alarmdb]
X 
X DESCRIPTION
X      _a_l_a_r_m reads an alarm database and signals the user  whenever
X      one  of the alarms becomes active.  If alarmdb is not speci-
X      fied, ~/.alarm will be used.
X 
X      The format of the lines in the alarm database is as follows:
X 
X           date    time    message
X 
X      Lines starting with a # and blank lines are ignored.  `date'
X      can  be  any of the following.  Minimum abbreviations are in
X      caps, and case is insignificant:
X 
X           Sundays       Mondays      Tuesdays       Wednesdays
X           THursdays     Fridays      SAturdays
X 
X           Daily         Any
X 
X           month/day
X 
X      Specifying `month/day' creates a "one-shot" alarm; the  oth-
X      ers  are periodic.  `time' is in the form hour:minute (based
X      on a 24-hour clock; 0:00 - 23:59).   `message'  is  anything
X      you  want.   The program will read in this file, and when an
X      alarm is to go off, it will do one of the following:
X 
X           1)   if the window is closed (iconic),  the  icon  will
X                flash  to  indicate  an alarm.  Open the window to
X                acknowledge the alarm.  Now, since the  window  is
X                open,
X 
X           2)   if the window is open, the  entire  line  will  be
X                written out.
X 
X      If you change your alarm database (~/.alarm  or  `alarmdb'),
X      you  have  to  tell  the program to re-read the file (if you
X      wish).  To do this, run ~/.alarmreset, which the alarm  pro-
X      gram creates when it starts up.
X 
X OPTIONS
X      There is only one option:
X 
X      -h _m_i_n
X           Specify the initial history value, in  minutes.   _a_l_a_r_m
X           will  signal  alarms  in the last _m_i_n minutes when ini-
X           tially starting up.  The default time is 60 minutes.
X 
X 
X 
X ITC Release 1.0          21 January 1986                        1
X 
X 
X 
X 
X 
X 
X ALARM(L)          UNKNOWN SECTION OF THE MANUAL          ALARM(L)
X 
X 
X 
X ENVIRONMENT
X      _a_l_a_r_m looks at the  environment  variable  ICONDIR  for  the
X      directory  containing  the  icons.  The default directory is
X      defined in the Makefile.
X 
X SAMPLE ~/.alarm FILE
X      #
X      #  alarm database for /usr/local/bin/alarm
X      #
X      #  copyright 1986 Exploding Penguin Software
X      #
X 
X      #
X      #  Weekly alarms
X      #
X      mon     10:50   GRIP meeting at 11:00
X      wed     12:20   Tech meeting at 12:30.
X      fri     11:50   Faculty meeting at 12:00
X 
X      #
X      #  Daily alarms
X      #
X      daily   16:50   Time to go home!
X      daily   17:00   What are you still doing here?
X 
X      #
X      #  One-time alarms
X      #
X      1/22    15:50   Bentley seminar at 4:00.
X      1/24    15:20   Seminar at 3:30.
X 
X BUGS
X      Invalid dates and time are accepted  (4/38  =  5/8;  5:80  =
X      6:20).   Error  checking  is  only done on the format of the
X      input, not on the values contained therein.
X 
X      The program may or may not work correctly when Daylight Sav-
X      ings  Time goes into effect.  It also may or may not work in
X      different time zones.  These cases have not been tested.  If
X      you have any problems, please contact the author.
X 
X FILES
X      /usr/local/bin/alarm        The program
X      $ICONDIR/alarm_off          Icon for quiescent state
X      $ICONDIR/alarm_on           Icons for active state
X      $ICONDIR/alarm_on2             (toggles between these two)
X      ~/.alarm                    Alarm database
X      ~/.alarmreset               Alarm signaller
X 
X AUTHOR
X      Samuel Black (black@unc)
X 
X 
X 
X 
X ITC Release 1.0          21 January 1986                        2
X 
X 
X 
***FUBAR***
echo "extracting alarm_off (1933 bytes)"
sed 's/^X //' << '***FUBAR***' > alarm_off
X /* Format_version=1, Width=64, Height=64, Depth=1, Valid_bits_per_item=16
X  */
X 	0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,
X 	0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,
X 	0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,
X 	0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0xFFA2,0x2222,
X 	0x8888,0x8887,0xFFF8,0x8888,0x8888,0x889F,0xFFFC,0x8888,
X 	0x2222,0x227F,0xFFFF,0x2222,0x2222,0x22FF,0xFFFF,0xA222,
X 	0x8888,0x89FF,0xFFFF,0xC888,0x8888,0x8BFF,0xFFFF,0xE888,
X 	0x2222,0x2FE0,0x0FFF,0xF222,0x2222,0x3F00,0x01FF,0xFA22,
X 	0x8888,0xFC04,0x307F,0xFC88,0x8888,0xF80C,0x483F,0xFC88,
X 	0x2223,0xE004,0x080F,0xFE22,0x2223,0xC004,0x3007,0xFE22,
X 	0x888B,0x8004,0x4003,0xFE88,0x888F,0x800E,0x7803,0xFF88,
X 	0x2227,0x0000,0x0001,0xFF22,0x222E,0x0000,0x0000,0xFFA2,
X 	0x888E,0x0001,0x8000,0xFF88,0x889C,0x0001,0x8000,0x7F88,
X 	0x223C,0x0001,0x8000,0x7FA2,0x223C,0x6001,0x800C,0x7FA2,
X 	0x88B8,0x9001,0x8012,0x3F88,0x88B8,0x9001,0x8004,0x3F88,
X 	0x2238,0x7001,0x8002,0x3FA2,0x2238,0x1001,0x8012,0x3FA2,
X 	0x88B8,0x6000,0xE00C,0x3F88,0x88B8,0x0000,0x3000,0x3F88,
X 	0x2238,0x0000,0x1C00,0x3F22,0x2238,0x0000,0x0700,0x3E22,
X 	0x88B8,0x0000,0x0380,0x3E88,0x889C,0x0000,0x00E0,0x7C88,
X 	0x223C,0x0000,0x0070,0x7E22,0x223C,0x0000,0x0010,0x7A22,
X 	0x888E,0x0000,0x0000,0xF888,0x888E,0x0000,0x0000,0xE888,
X 	0x2227,0x0001,0x8001,0xE222,0x2227,0x8002,0x0003,0xE222,
X 	0x888B,0x8003,0x8003,0x8888,0x8889,0xC002,0x4007,0x8888,
X 	0x2223,0xE002,0x400F,0x2222,0x2222,0xF801,0x803F,0x2222,
X 	0x8888,0xFC00,0x007F,0x8888,0x8888,0xBF00,0x01F1,0x8888,
X 	0x2222,0x7FE0,0x0FE1,0xE222,0x2222,0x63FF,0xFF80,0xE222,
X 	0x8888,0xE0FF,0xFE00,0xE888,0x8888,0xC01F,0xF000,0x6888,
X 	0x2223,0xC000,0x0000,0x7222,0x2223,0xC000,0x0000,0x7222,
X 	0x888F,0xFFFF,0xFFFF,0xFE88,0x888F,0xFFFF,0xFFFF,0xFE88,
X 	0x222F,0x0000,0x0000,0x1E22,0x222F,0xFFFF,0xFFFF,0xFE22,
X 	0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,
X 	0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222
***FUBAR***
echo "extracting alarm_on (1933 bytes)"
sed 's/^X //' << '***FUBAR***' > alarm_on
X /* Format_version=1, Width=64, Height=64, Depth=1, Valid_bits_per_item=16
X  */
X 	0x8888,0x8887,0xF088,0x8888,0x8888,0x88BF,0xFE88,0x8888,
X 	0x2222,0x22F8,0x0FA2,0x2222,0x2222,0x23C0,0x01E2,0x2222,
X 	0x8888,0x8F00,0x0078,0x8888,0x8888,0x8E00,0x0038,0x8888,
X 	0x2222,0x2C00,0x001A,0x2222,0x2222,0x3800,0x000E,0x2222,
X 	0x8888,0xB004,0x0006,0x8888,0x8888,0xB000,0x5006,0x8888,
X 	0x2222,0x600C,0x6803,0x2222,0x2222,0x6004,0x4803,0x2222,
X 	0x8888,0xE004,0x4803,0x8888,0x8888,0xC004,0x4801,0x8888,
X 	0x2222,0xC000,0x0001,0xA222,0x2222,0xC000,0x0001,0xA222,
X 	0x8888,0xC480,0x1001,0x8888,0x8888,0xC494,0x0111,0x8888,
X 	0x2222,0xC49A,0x30A1,0xA222,0x2222,0xC492,0x1041,0xA222,
X 	0x8888,0xC492,0x10A1,0x8888,0x8888,0xC312,0x1111,0x8888,
X 	0x2222,0xC000,0x0001,0xA222,0x2222,0xC000,0x0001,0xA222,
X 	0x8888,0xC000,0x0001,0x8888,0x8888,0xC008,0x9801,0x8888,
X 	0x2222,0xC008,0xA401,0xA222,0x2222,0xC00A,0xB801,0xA222,
X 	0x8888,0xC00A,0xA001,0x8888,0x8888,0xC005,0x1C01,0x8888,
X 	0x2222,0xC000,0x0001,0xA222,0x2223,0x8000,0x0000,0xE222,
X 	0x8889,0x8800,0x0008,0xC888,0x888B,0x1E51,0x239E,0x6888,
X 	0x2227,0x0869,0x2408,0x7222,0x223E,0x0841,0x2308,0x3E22,
X 	0x88B8,0x0841,0x6088,0x0E88,0x88E0,0x0640,0xA706,0x0388,
X 	0x23C0,0x0000,0x0000,0x01E2,0x23C0,0x0000,0x0000,0x01E2,
X 	0x89FF,0xFFFF,0xFFFF,0xFFC8,0x8980,0x0000,0x0000,0x00C8,
X 	0x2380,0x0000,0x0000,0x00E2,0x2380,0x0000,0x0000,0x00E2,
X 	0x8980,0x0000,0x0000,0x00C8,0x89FF,0xFFFF,0xFFFF,0xFFC8,
X 	0x2380,0x0000,0x0000,0x00E2,0x23FF,0xFFFF,0xFFFF,0xFFE2,
X 	0x888E,0x0388,0x8888,0x8888,0x888C,0x0188,0x8888,0x8888,
X 	0x2238,0x00E2,0x2222,0x2222,0x2238,0x00E2,0x2222,0x2222,
X 	0x8898,0x00C8,0x8888,0x8888,0x8898,0x00C8,0x8888,0x8888,
X 	0x2238,0x00E2,0x2222,0x2222,0x222C,0x01A2,0x2222,0x2222,
X 	0x888E,0x0388,0x8888,0x8888,0x888F,0x0788,0x8888,0x8888,
X 	0x2223,0xFE22,0x2222,0x2222,0x2222,0xFA22,0x2222,0x2222,
X 	0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,
X 	0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222
***FUBAR***
echo "extracting alarm_on2 (1933 bytes)"
sed 's/^X //' << '***FUBAR***' > alarm_on2
X /* Format_version=1, Width=64, Height=64, Depth=1, Valid_bits_per_item=16
X  */
X 	0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,
X 	0x2222,0x2227,0xF222,0x2222,0x2222,0x223F,0xFE22,0x2222,
X 	0x8888,0x88FF,0xFF88,0x8888,0x8888,0x89FF,0xFFC8,0x8888,
X 	0x2222,0x23FF,0xFFE2,0x2222,0x2222,0x27FF,0xFFF2,0x2222,
X 	0x8888,0x8FFB,0xFFF8,0x8888,0x8888,0x8FFF,0xAFF8,0x8888,
X 	0x2222,0x1FF3,0x97FC,0x2222,0x2222,0x1FFB,0xB7FC,0x2222,
X 	0x8888,0x9FFB,0xB7FC,0x8888,0x8888,0xBFFB,0xB7FE,0x8888,
X 	0x2222,0x3FFF,0xFFFE,0x2222,0x2222,0x3FFF,0xFFFE,0x2222,
X 	0x8888,0xBB7F,0xEFFE,0x8888,0x8888,0xBB6B,0xFEEE,0x8888,
X 	0x2222,0x3B65,0xCF5E,0x2222,0x2222,0x3B6D,0xEFBE,0x2222,
X 	0x8888,0xBB6D,0xEF5E,0x8888,0x8888,0xBCED,0xEEEE,0x8888,
X 	0x2222,0x3FFF,0xFFFE,0x2222,0x2222,0x3FFF,0xFFFE,0x2222,
X 	0x8888,0xBFFF,0xFFFE,0x8888,0x8888,0xBFF7,0x67FE,0x8888,
X 	0x2222,0x3FF7,0x5BFE,0x2222,0x2222,0x3FF5,0x47FE,0x2222,
X 	0x8888,0xBFF5,0x5FFE,0x8888,0x8888,0xBFFA,0xE3FE,0x8888,
X 	0x2222,0x3FFF,0xFFFE,0x2222,0x2222,0x7FFF,0xFFFF,0x2222,
X 	0x8888,0x77FF,0xFFF7,0x8888,0x8888,0xE1AE,0xDC61,0x8888,
X 	0x2222,0xF796,0xDBF7,0xA222,0x2223,0xF7BE,0xDCF7,0xE222,
X 	0x888F,0xF7BE,0x9F77,0xF888,0x889F,0xF9BF,0x58F9,0xFC88,
X 	0x223F,0xFFFF,0xFFFF,0xFE22,0x223F,0xFFFF,0xFFFF,0xFE22,
X 	0x8880,0x0000,0x0000,0x0088,0x88FF,0xFFFF,0xFFFF,0xFF88,
X 	0x227F,0xFFFF,0xFFFF,0xFF22,0x227F,0xFFFF,0xFFFF,0xFF22,
X 	0x88FF,0xFFFF,0xFFFF,0xFF88,0x8880,0x0000,0x0000,0x0088,
X 	0x227F,0xFFFF,0xFFFF,0xFF22,0x2222,0x2222,0x27FF,0x2222,
X 	0x8888,0x8888,0x8FFF,0x8888,0x8888,0x8888,0x8FFF,0x8888,
X 	0x2222,0x2222,0x2FFF,0xA222,0x2222,0x2222,0x2FFF,0xA222,
X 	0x8888,0x8888,0x8FFF,0x8888,0x8888,0x8888,0x8FFF,0x8888,
X 	0x2222,0x2222,0x23FE,0x2222,0x2222,0x2222,0x23FE,0x2222,
X 	0x8888,0x8888,0x88F8,0x8888,0x8888,0x8888,0x8888,0x8888,
X 	0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,
X 	0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,
X 	0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222,0x2222
***FUBAR***
echo "end of shar file"
exit

black@unc.UUCP (01/24/86)

Whoops; I posted the alarmer with a couple of bugs in it.  Here's
a diff for the changes:


473c473
<       int leap = ((month > 1) && (dysize(year) == 366));
---
>       int leap = ((month > 1) && (dysize(1900 + year) == 366));
481c481
<               ydisp += (SPD + dysize(i));
---
>               ydisp += (SPD * dysize(i));

----------------------------------

	You can't spell 'geek' without a double-E.
			- Jon Bentley

	...!{decvax,ihnp4}!mcnc!unc!black	(usenet)
	black%unc@csnet-relay.csnet		(arpanet)

----------------------------------