AUSAM/source/S/alarm.c

Compare this file to the similar file:
Show the results in this format:

/*
 *
 *	Can be run in two ways (depending on its name(argv[0]))
 *
 *	alarm - send a message to the terminal at the specified time
 *
 *	runat - execc the given command and arguments at the specified time
 *
 *	Times are specified in the form: Fri Jun 1 9:53:14 1979
 *	Any of the arguments (except for the hours:minutes) may be ommited,
 *	the current date, month, year, being assumed.
 *	The arguments may be specified in any order.
 *	Alarm (Runat) also recognises "am", "pm", and "tomorrow" as valid
 *	arguments.
 *
 *					Michael Rourke - June 1979
 */

#include <stdio.h>
#include <date.h>

#define MAXSLEEP 65535l
#define SECINDAY 86400l
#define SECINHOUR 3600l
#define SECINMIN 60l

int daysinmonth[]
{
	31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
char *dayandmonth[]
{
	"jan", "feb", "mar", "apr", "may", "jun",
	"jul", "aug", "sep", "oct", "nov", "dec",
	"sun", "mon", "tue", "wed", "thu", "fri", "sat",
	"tom", "am", "pm"
};
int hour, minute, second, day, year, dayofweek, month, nargs, relative;
char sdayofweek, syear, smonth, sday, stime, runat, srelative, spm, pm;
long mtime(), time(), systime;
struct date *localtime(), *tim;

main(argc, argv)
register int argc;
register char *argv[];
{
	long ttime;

	runat = (argv[0][0] == 'r');
	systime = time();
	tim = localtime(systime);
	day = tim->d_dyofmon;
	year = tim->d_year + 1900;
	month = tim->d_month;
	if((argc == 1) || getargs(argc, argv) || (runat && ((argc - nargs - 1) == 0)) || ( ! runat && (nargs != argc)))
		if(runat)
		{
			fprintf(stderr, "Usage:\nrunat [day] [month] [date] hours:minutes[:seconds] [year] : command\n");
			fprintf(stderr, "runat +minutes : command\n");
		}
		else
		{
			fprintf(stderr, "Usage:\nalarm [day] [month] [date] hours:minutes[:seconds] [year]\n");
			fprintf(stderr, "alarm +minutes\n");
		}
	else
	{
		if((ttime = mtime() - systime) <= 0)
		{
			fprintf(stderr, "This time has already passed\n");
			exit(-1);
		}
		go(ttime, argc - nargs - 1, &argv[nargs+1]);
	}
}

getargs(argc, argv)
int argc;
register char *argv[];
{
	int thour, tmin, tsec, tint, k, ch,  found;
	register int j, arg;
	char tstr[3];

	for(arg = 1; (arg < argc) && (argv[arg][0] != ':'); arg++)
	{
		thour = tmin = tsec = tint = 0;
		if(argv[arg][0] >= 'A')		/* a string */
		{
			for(j = 0; argv[arg][j] && j < 3; j++)	/* map upper to lower case */
				if((argv[arg][j] >= 'A') && (argv[arg][j] <= 'Z'))
					tstr[j] = argv[arg][j] + 'a' - 'A';
				else
					tstr[j] = argv[arg][j];
			found = 0;
			for(j = 0; (j < 12 + 7 + 3) && (! found); j++)	/* look for string */
				for(k = 0; k < 3; k++)
					if(tstr[k] != dayandmonth[j][k])
						break;
					else if( ! dayandmonth[j][k + 1])
						found++;
			if(found)
				if(--j < 12)	/* a month */
				{
					smonth++;
					month = j;
				}
				else if(j < 12 + 7)	/* a day of week */
				{
					sdayofweek++;
					dayofweek = j - 12;
				}
				else switch(j)
				{
					case 12 + 7:
						/* tomorrow */
						sdayofweek++;
						dayofweek = (tim->d_dyofwk + 1) % 7;
						break;
					case 12 + 7 + 1:
						/* am */
						spm++;
						break;
					case 12 + 7 + 2:
						/* pm */
						spm++;
						pm++;
						break;
				}
			else
			{
				fprintf(stderr, "Unidentified argument: \"%s\"\n", argv[arg]);
				return(1);
			}
		} 
		else if(sscanf(argv[arg], "%d:%d:%d", &thour, &tmin, &tsec) > 1)	/* the time */
		{
			if((thour >= 0) && (thour < 24) && (tmin >= 0) && (tmin < 60) && (tsec >= 0) && (tsec < 60))
			{
				stime++;
				hour = thour;
				minute = tmin;
				second = tsec;
			}
			else
			{
				fprintf(stderr, "Time out of range\n");
				return(1);
			}
		}
		else if(sscanf(argv[arg], "+%d%c", &tint, &ch) == 1)	/* a relative time */
		{
			srelative++;
			relative = tint * SECINMIN;
		}
		else if(sscanf(argv[arg], "%d%c", &tint, &ch) == 1)	/* a date or year */
			if(tint > 31)	/* year */
			{
				syear++;
				year = tint;
			}
			else if((tint > 0) && (tint <= 31))	/* day */
			{
				sday++;
				day = tint;
			}
			else
			{
				fprintf(stderr, "Date out of range\n");
				return(1);
			}
		else
		{
			fprintf(stderr, "Unidentified argument: \"%s\"\n", argv[arg]);
			return(1);
		}
		if((sday > 1) || (syear > 1) || (smonth > 1) || (sdayofweek > 1) || (stime > 1) || (srelative > 1) || (spm > 1))
		{
			fprintf(stderr, "Repeated argument: \"%s\"\n", argv[arg]);
			return(1);
		}
	}
	nargs = arg;
	if(srelative)
		return((arg != 2) || (runat && (argv[arg][0] != ':')));
	else
		return(( ! stime) || (runat && (argv[arg][0] != ':')));
}

long mtime()
{
	register int i, disp, days 0;

	if(srelative)
		return(systime + relative);
	for(i = 1970; i < year; i++)
		if(i % 4)
			days =+ 365l;
		else
			days =+ 366l;	/* a leap year */
	if(year % 4 == 0)
		daysinmonth[1] = 29;
	for(i = 0; i < month; i++)
		days =+ daysinmonth[i];
	days =+ day - 1;		/* days since 1 Jan 1970 */
	if(sdayofweek && ! sday) {
		disp = dayofweek - tim->d_dyofwk;
		if(disp < 0)
			disp =+ 7;
		days =+ disp;
	}
	if(pm)
		hour =+ 12;
	return(days * SECINDAY + hour * SECINHOUR + minute * SECINMIN + second);
}

go(wait, argc, argv)
long wait;
int argc;
char *argv[];
{
	register unsigned shortw, longw, i;

	switch(fork()) {
		case -1:
			fprintf(stderr, "Cannot fork\n");
			exit(-1);
		case 0:
			/* child */
			break;
		default:
			/* parent */
			fprintf(stderr, "It is now %s", ctime(systime));
			if(runat)
				fprintf(stderr, "Runat is set for %s",ctime(systime+wait));
			else
				fprintf(stderr, "Alarm is set for %s",ctime(systime+wait));
			exit(0);
	}
	signal(2, 1);
	signal(3, 1);
	longw = wait / MAXSLEEP;
	shortw = wait % MAXSLEEP;
	for(i = 0; i < longw; i++)
		sleep(MAXSLEEP);
	sleep(shortw);
	if(runat)
	{
		argv[argc] = 0;
		execc(*argv, argv);
		fprintf(stderr, "\nrunat: cannot execc \"%s\"\n", *argv);
	}
	else
		fprintf(stderr, "\07\nWarning, the time is %s\07",ijtime());
	exit(0);
}