mirror of
https://git.FreeBSD.org/src.git
synced 2025-02-04 17:15:50 +00:00
- handle events that move around from year to year, i.e.,
``the last Monday in April' - handle easter new options -f calendarfile -A days -B days Calendar HOME directory ~/.calendar don't sent mail if ~/.calendar/nomail exist
This commit is contained in:
parent
4ad1bd1e33
commit
c9c822e632
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=13840
@ -1,6 +1,7 @@
|
||||
# @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
|
||||
PROG= calendar
|
||||
SRCS= calendar.c io.c day.c ostern.c
|
||||
INTER= de_DE.ISO_8859-1
|
||||
SHAREDIR= /usr/share/calendar
|
||||
TEXTMODE?= 444
|
||||
|
@ -1,5 +1,5 @@
|
||||
.\" Copyright (c) 1989, 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
@ -11,8 +11,8 @@
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the University of
|
||||
.\" California, Berkeley and its contributors.
|
||||
.\" This product includes software developed by the University of
|
||||
.\" California, Berkeley and its contributors.
|
||||
.\" 4. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
@ -29,7 +29,7 @@
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)calendar.1 8.1 (Berkeley) 6/29/93
|
||||
.\" @(#)calendar.1 8.1 (Berkeley) 6/29/93
|
||||
.\"
|
||||
.Dd June 29, 1993
|
||||
.Dt CALENDAR 1
|
||||
@ -40,6 +40,9 @@
|
||||
.Sh SYNOPSIS
|
||||
.Nm calendar
|
||||
.Op Fl a
|
||||
.Op Fl A Ar num
|
||||
.Op Fl B Ar num
|
||||
.Op Fl f Ar calendarfile
|
||||
.Sh DESCRIPTION
|
||||
.Nm Calendar
|
||||
checks the current directory for a file named
|
||||
@ -54,6 +57,20 @@ The following options are available:
|
||||
Process the ``calendar'' files of all users and mail the results
|
||||
to them.
|
||||
This requires super-user privileges.
|
||||
.It Fl A Ar num
|
||||
print lines from today and next
|
||||
.Ar num
|
||||
days (forward, future)
|
||||
|
||||
.It Fl B Ar num
|
||||
print lines from today and previous
|
||||
.Ar num
|
||||
days (backward, past)
|
||||
.It Fl f Pa calendarfile
|
||||
use
|
||||
.Pa calendarfile
|
||||
as default calendar file.
|
||||
|
||||
.El
|
||||
.Pp
|
||||
Lines should begin with a month and day.
|
||||
@ -65,6 +82,11 @@ A month without a day matches the first of that month.
|
||||
Two numbers default to the month followed by the day.
|
||||
Lines with leading tabs default to the last entered date, allowing
|
||||
multiple line specifications for a single date.
|
||||
``Easter'', may be followed by an positive or negative integer, is
|
||||
Easter for this year. Weekdays may be followed by ``-4'' ... ``+5'' (aliases
|
||||
last, first, second, third, fourth) for moving events like
|
||||
``the last Monday in April''
|
||||
|
||||
By convention, dates followed by an asterisk are not fixed, i.e., change
|
||||
from year to year.
|
||||
.Pp
|
||||
@ -83,17 +105,46 @@ are ignored.
|
||||
.Pp
|
||||
Some possible calendar entries:
|
||||
.Bd -unfilled -offset indent
|
||||
#include <calendar.usholiday>
|
||||
#include <calendar.birthday>
|
||||
#include <calendar.usholiday>
|
||||
#include <calendar.birthday>
|
||||
|
||||
6/15 ... June 15 (if ambiguous, will default to month/day).
|
||||
Jun. 15 ... June 15.
|
||||
15 June ... June 15.
|
||||
Thursday ... Every Thursday.
|
||||
June ... Every June 1st.
|
||||
15 * ... 15th of every month.
|
||||
|
||||
May Sun+2 ... second Sunday in May (Muttertag)
|
||||
04/SunLast ... last Sunday in April, summer time in Europe
|
||||
Easter ... Easter
|
||||
Easter-2 ... Good Friday (2 days before Easter)
|
||||
|
||||
6/15 ... June 15 (if ambiguous, will default to month/day).
|
||||
Jun. 15 ... June 15.
|
||||
15 June ... June 15.
|
||||
Thursday ... Every Thursday.
|
||||
June ... Every June 1st.
|
||||
15 * ... 15th of every month.
|
||||
.Ed
|
||||
.Sh FILES
|
||||
|
||||
.Pp
|
||||
.Bl -tag -width calendar.christian -compact
|
||||
.It Pa calendar
|
||||
file in current directory
|
||||
|
||||
.It Pa ~/.calendar
|
||||
.Pa calendar
|
||||
HOME directory.
|
||||
.Nm calendar
|
||||
did a chdir into this directory if exist.
|
||||
|
||||
|
||||
.It Pa ~/.calendar/calendar
|
||||
file in calendar HOME directory, used if no calendar file
|
||||
in current directory.
|
||||
|
||||
.It Pa ~/.calendar/nomail
|
||||
don't send mail if
|
||||
.Pa ~/.calendar/nomail
|
||||
exist.
|
||||
.El
|
||||
|
||||
The following default calendar files are provided:
|
||||
.Pp
|
||||
.Bl -tag -width calendar.christian -compact
|
||||
@ -122,6 +173,10 @@ Strongly oriented toward rock 'n' roll.
|
||||
U.S. holidays.
|
||||
This calendar should be updated yearly by the local system administrator
|
||||
so that roving holidays are set correctly for the current year.
|
||||
|
||||
.It Pa calendar.german
|
||||
German calendar.
|
||||
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr at 1 ,
|
||||
@ -139,7 +194,7 @@ first on the line.
|
||||
A
|
||||
.Nm
|
||||
command appeared in Version 7 AT&T UNIX.
|
||||
|
||||
.Sh BUGS
|
||||
.Nm Calendar
|
||||
doesn't handle events that move around from year to year, i.e.,
|
||||
``the last Monday in April''.
|
||||
doesn't handle Jewish holidays and moon phases.
|
||||
|
@ -41,37 +41,23 @@ static char copyright[] =
|
||||
static char sccsid[] = "@(#)calendar.c 8.3 (Berkeley) 3/25/94";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <err.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "pathnames.h"
|
||||
#include "calendar.h"
|
||||
|
||||
struct passwd *pw;
|
||||
int doall;
|
||||
int doall = 0;
|
||||
time_t f_time = 0;
|
||||
|
||||
void cal __P((void));
|
||||
void closecal __P((FILE *));
|
||||
int getday __P((char *));
|
||||
int getfield __P((char *, char **, int *));
|
||||
int getmonth __P((char *));
|
||||
int isnow __P((char *));
|
||||
FILE *opencal __P((void));
|
||||
void settime __P((void));
|
||||
void usage __P((void));
|
||||
#define isleap(y) (((y) % 4) == 0 && ((y) % 100) != 0 || ((y) % 400) == 0)
|
||||
int f_dayAfter = 0; /* days after current date */
|
||||
int f_dayBefore = 0; /* days before current date */
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
@ -81,7 +67,7 @@ main(argc, argv)
|
||||
extern int optind;
|
||||
int ch;
|
||||
|
||||
while ((ch = getopt(argc, argv, "-a")) != EOF)
|
||||
while ((ch = getopt(argc, argv, "?-af:t:A:B:")) != EOF)
|
||||
switch (ch) {
|
||||
case '-': /* backward contemptible */
|
||||
case 'a':
|
||||
@ -91,6 +77,24 @@ main(argc, argv)
|
||||
}
|
||||
doall = 1;
|
||||
break;
|
||||
|
||||
|
||||
case 'f': /* other calendar file */
|
||||
calendarFile = optarg;
|
||||
break;
|
||||
|
||||
case 't': /* other date, undocumented, for tests */
|
||||
f_time = Mktime (optarg);
|
||||
break;
|
||||
|
||||
case 'A': /* days after current date */
|
||||
f_dayAfter = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'B': /* days before current date */
|
||||
f_dayBefore = atoi(optarg);
|
||||
break;
|
||||
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
@ -101,7 +105,12 @@ main(argc, argv)
|
||||
if (argc)
|
||||
usage();
|
||||
|
||||
settime();
|
||||
/* use current time */
|
||||
if (f_time <= 0)
|
||||
(void)time(&f_time);
|
||||
|
||||
settime(f_time);
|
||||
|
||||
if (doall)
|
||||
while ((pw = getpwent()) != NULL) {
|
||||
(void)setegid(pw->pw_gid);
|
||||
@ -115,297 +124,13 @@ main(argc, argv)
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void
|
||||
cal()
|
||||
{
|
||||
register int printing;
|
||||
register char *p;
|
||||
FILE *fp;
|
||||
int ch;
|
||||
char buf[2048 + 1];
|
||||
|
||||
if ((fp = opencal()) == NULL)
|
||||
return;
|
||||
for (printing = 0; fgets(buf, sizeof(buf), stdin) != NULL;) {
|
||||
if ((p = strchr(buf, '\n')) != NULL)
|
||||
*p = '\0';
|
||||
else
|
||||
while ((ch = getchar()) != '\n' && ch != EOF);
|
||||
if (buf[0] == '\0')
|
||||
continue;
|
||||
if (buf[0] != '\t')
|
||||
printing = isnow(buf) ? 1 : 0;
|
||||
if (printing)
|
||||
(void)fprintf(fp, "%s\n", buf);
|
||||
}
|
||||
closecal(fp);
|
||||
}
|
||||
|
||||
struct iovec header[] = {
|
||||
"From: ", 6,
|
||||
NULL, 0,
|
||||
" (Reminder Service)\nTo: ", 24,
|
||||
NULL, 0,
|
||||
"\nSubject: ", 10,
|
||||
NULL, 0,
|
||||
"'s Calendar\nPrecedence: bulk\n\n", 30,
|
||||
};
|
||||
|
||||
/* 1-based month, 0-based days, cumulative */
|
||||
int daytab[][14] = {
|
||||
0, -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364,
|
||||
0, -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365,
|
||||
};
|
||||
struct tm *tp;
|
||||
int *cumdays, offset, yrdays;
|
||||
char dayname[10];
|
||||
|
||||
void
|
||||
settime()
|
||||
{
|
||||
time_t now;
|
||||
|
||||
(void)time(&now);
|
||||
tp = localtime(&now);
|
||||
if (isleap(tp->tm_year + 1900)) {
|
||||
yrdays = 366;
|
||||
cumdays = daytab[1];
|
||||
} else {
|
||||
yrdays = 365;
|
||||
cumdays = daytab[0];
|
||||
}
|
||||
/* Friday displays Monday's events */
|
||||
offset = tp->tm_wday == 5 ? 3 : 1;
|
||||
header[5].iov_base = dayname;
|
||||
header[5].iov_len = strftime(dayname, sizeof(dayname), "%A", tp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Possible date formats include any combination of:
|
||||
* 3-charmonth (January, Jan, Jan)
|
||||
* 3-charweekday (Friday, Monday, mon.)
|
||||
* numeric month or day (1, 2, 04)
|
||||
*
|
||||
* Any character may separate them, or they may not be separated. Any line,
|
||||
* following a line that is matched, that starts with "whitespace", is shown
|
||||
* along with the matched line.
|
||||
*/
|
||||
int
|
||||
isnow(endp)
|
||||
char *endp;
|
||||
{
|
||||
int day, flags, month, v1, v2;
|
||||
|
||||
#define F_ISMONTH 0x01
|
||||
#define F_ISDAY 0x02
|
||||
flags = 0;
|
||||
/* didn't recognize anything, skip it */
|
||||
if (!(v1 = getfield(endp, &endp, &flags)))
|
||||
return (0);
|
||||
if (flags & F_ISDAY || v1 > 12) {
|
||||
/* found a day */
|
||||
day = v1;
|
||||
/* if no recognizable month, assume just a day alone */
|
||||
if (!(month = getfield(endp, &endp, &flags)))
|
||||
month = tp->tm_mon + 1;
|
||||
} else if (flags & F_ISMONTH) {
|
||||
month = v1;
|
||||
/* if no recognizable day, assume the first */
|
||||
if (!(day = getfield(endp, &endp, &flags)))
|
||||
day = 1;
|
||||
} else {
|
||||
v2 = getfield(endp, &endp, &flags);
|
||||
if (flags & F_ISMONTH) {
|
||||
day = v1;
|
||||
month = v2;
|
||||
} else {
|
||||
/* F_ISDAY set, v2 > 12, or no way to tell */
|
||||
month = v1;
|
||||
/* if no recognizable day, assume the first */
|
||||
day = v2 ? v2 : 1;
|
||||
}
|
||||
}
|
||||
if (flags & F_ISDAY)
|
||||
day = tp->tm_mday + (((day - 1) - tp->tm_wday + 7) % 7);
|
||||
day = cumdays[month] + day;
|
||||
|
||||
/* if today or today + offset days */
|
||||
if (day >= tp->tm_yday && day <= tp->tm_yday + offset)
|
||||
return (1);
|
||||
/* if number of days left in this year + days to event in next year */
|
||||
if (yrdays - tp->tm_yday + day <= offset)
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
getfield(p, endp, flags)
|
||||
char *p, **endp;
|
||||
int *flags;
|
||||
{
|
||||
int val;
|
||||
char *start, savech;
|
||||
|
||||
for (; !isdigit(*p) && !isalpha(*p) && *p != '*'; ++p);
|
||||
if (*p == '*') { /* `*' is current month */
|
||||
*flags |= F_ISMONTH;
|
||||
*endp = p+1;
|
||||
return (tp->tm_mon + 1);
|
||||
}
|
||||
if (isdigit(*p)) {
|
||||
val = strtol(p, &p, 10); /* if 0, it's failure */
|
||||
for (; !isdigit(*p) && !isalpha(*p) && *p != '*'; ++p);
|
||||
*endp = p;
|
||||
return (val);
|
||||
}
|
||||
for (start = p; isalpha(*++p););
|
||||
savech = *p;
|
||||
*p = '\0';
|
||||
if ((val = getmonth(start)) != 0)
|
||||
*flags |= F_ISMONTH;
|
||||
else if ((val = getday(start)) != 0)
|
||||
*flags |= F_ISDAY;
|
||||
else {
|
||||
*p = savech;
|
||||
return (0);
|
||||
}
|
||||
for (*p = savech; !isdigit(*p) && !isalpha(*p) && *p != '*'; ++p);
|
||||
*endp = p;
|
||||
return (val);
|
||||
}
|
||||
|
||||
char path[MAXPATHLEN + 1];
|
||||
|
||||
FILE *
|
||||
opencal()
|
||||
{
|
||||
int fd, pdes[2];
|
||||
|
||||
/* open up calendar file as stdin */
|
||||
if (!freopen("calendar", "r", stdin)) {
|
||||
if (doall)
|
||||
return (NULL);
|
||||
errx(1, "no calendar file in current directory.");
|
||||
}
|
||||
if (pipe(pdes) < 0)
|
||||
return (NULL);
|
||||
switch (vfork()) {
|
||||
case -1: /* error */
|
||||
(void)close(pdes[0]);
|
||||
(void)close(pdes[1]);
|
||||
return (NULL);
|
||||
case 0:
|
||||
/* child -- stdin already setup, set stdout to pipe input */
|
||||
if (pdes[1] != STDOUT_FILENO) {
|
||||
(void)dup2(pdes[1], STDOUT_FILENO);
|
||||
(void)close(pdes[1]);
|
||||
}
|
||||
(void)close(pdes[0]);
|
||||
execl(_PATH_CPP, "cpp", "-P", "-I.", _PATH_INCLUDE, NULL);
|
||||
(void)fprintf(stderr,
|
||||
"calendar: execl: %s: %s.\n", _PATH_CPP, strerror(errno));
|
||||
_exit(1);
|
||||
}
|
||||
/* parent -- set stdin to pipe output */
|
||||
(void)dup2(pdes[0], STDIN_FILENO);
|
||||
(void)close(pdes[0]);
|
||||
(void)close(pdes[1]);
|
||||
|
||||
/* not reading all calendar files, just set output to stdout */
|
||||
if (!doall)
|
||||
return (stdout);
|
||||
|
||||
/* set output to a temporary file, so if no output don't send mail */
|
||||
(void)snprintf(path, sizeof(path), "%s/_calXXXXXX", _PATH_TMP);
|
||||
if ((fd = mkstemp(path)) < 0)
|
||||
return (NULL);
|
||||
return (fdopen(fd, "w+"));
|
||||
}
|
||||
|
||||
void
|
||||
closecal(fp)
|
||||
FILE *fp;
|
||||
{
|
||||
struct stat sbuf;
|
||||
int nread, pdes[2], status;
|
||||
char buf[1024];
|
||||
|
||||
if (!doall)
|
||||
return;
|
||||
|
||||
(void)rewind(fp);
|
||||
if (fstat(fileno(fp), &sbuf) || !sbuf.st_size)
|
||||
goto done;
|
||||
if (pipe(pdes) < 0)
|
||||
goto done;
|
||||
switch (vfork()) {
|
||||
case -1: /* error */
|
||||
(void)close(pdes[0]);
|
||||
(void)close(pdes[1]);
|
||||
goto done;
|
||||
case 0:
|
||||
/* child -- set stdin to pipe output */
|
||||
if (pdes[0] != STDIN_FILENO) {
|
||||
(void)dup2(pdes[0], STDIN_FILENO);
|
||||
(void)close(pdes[0]);
|
||||
}
|
||||
(void)close(pdes[1]);
|
||||
execl(_PATH_SENDMAIL, "sendmail", "-i", "-t", "-F",
|
||||
"\"Reminder Service\"", "-f", "root", NULL);
|
||||
(void)fprintf(stderr,
|
||||
"calendar: %s: %s.\n", _PATH_SENDMAIL, strerror(errno));
|
||||
_exit(1);
|
||||
}
|
||||
/* parent -- write to pipe input */
|
||||
(void)close(pdes[0]);
|
||||
|
||||
header[1].iov_base = header[3].iov_base = pw->pw_name;
|
||||
header[1].iov_len = header[3].iov_len = strlen(pw->pw_name);
|
||||
writev(pdes[1], header, 7);
|
||||
while ((nread = read(fileno(fp), buf, sizeof(buf))) > 0)
|
||||
(void)write(pdes[1], buf, nread);
|
||||
(void)close(pdes[1]);
|
||||
done: (void)fclose(fp);
|
||||
(void)unlink(path);
|
||||
while (wait(&status) >= 0);
|
||||
}
|
||||
|
||||
static char *months[] = {
|
||||
"jan", "feb", "mar", "apr", "may", "jun",
|
||||
"jul", "aug", "sep", "oct", "nov", "dec", NULL,
|
||||
};
|
||||
|
||||
int
|
||||
getmonth(s)
|
||||
register char *s;
|
||||
{
|
||||
register char **p;
|
||||
|
||||
for (p = months; *p; ++p)
|
||||
if (!strncasecmp(s, *p, 3))
|
||||
return ((p - months) + 1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static char *days[] = {
|
||||
"sun", "mon", "tue", "wed", "thu", "fri", "sat", NULL,
|
||||
};
|
||||
|
||||
int
|
||||
getday(s)
|
||||
register char *s;
|
||||
{
|
||||
register char **p;
|
||||
|
||||
for (p = days; *p; ++p)
|
||||
if (!strncasecmp(s, *p, 3))
|
||||
return ((p - days) + 1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr, "usage: calendar [-a]\n");
|
||||
(void)fprintf(stderr,
|
||||
"usage: calendar [-a] [-A days] [-B days] [-f calendarfile]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
|
370
usr.bin/calendar/day.c
Normal file
370
usr.bin/calendar/day.c
Normal file
@ -0,0 +1,370 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <sys/uio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "pathnames.h"
|
||||
#include "calendar.h"
|
||||
|
||||
struct tm *tp;
|
||||
int *cumdays, offset, yrdays;
|
||||
char dayname[10];
|
||||
|
||||
|
||||
/* 1-based month, 0-based days, cumulative */
|
||||
int daytab[][14] = {
|
||||
{ 0, -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364 },
|
||||
{ 0, -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
|
||||
};
|
||||
|
||||
static char *days[] = {
|
||||
"sun", "mon", "tue", "wed", "thu", "fri", "sat", NULL,
|
||||
};
|
||||
|
||||
static char *months[] = {
|
||||
"jan", "feb", "mar", "apr", "may", "jun",
|
||||
"jul", "aug", "sep", "oct", "nov", "dec", NULL,
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
void
|
||||
settime(now)
|
||||
time_t now;
|
||||
{
|
||||
|
||||
tp = localtime(&now);
|
||||
if ( isleap(tp->tm_year + 1900) ) {
|
||||
yrdays = 366;
|
||||
cumdays = daytab[1];
|
||||
} else {
|
||||
yrdays = 365;
|
||||
cumdays = daytab[0];
|
||||
}
|
||||
/* Friday displays Monday's events */
|
||||
offset = tp->tm_wday == 5 ? 3 : 1;
|
||||
header[5].iov_base = dayname;
|
||||
header[5].iov_len = strftime(dayname, sizeof(dayname), "%A", tp);
|
||||
}
|
||||
|
||||
/* convert Day[/Month][/Year] into unix time (since 1970)
|
||||
* Day: tow digits, Month: two digits, Year: digits
|
||||
*/
|
||||
time_t Mktime (date)
|
||||
char *date;
|
||||
{
|
||||
time_t t;
|
||||
int len;
|
||||
struct tm tm;
|
||||
|
||||
(void)time(&t);
|
||||
tp = localtime(&t);
|
||||
|
||||
len = strlen(date);
|
||||
tm.tm_sec = 0;
|
||||
tm.tm_min = 0;
|
||||
tm.tm_hour = 0;
|
||||
tm.tm_mday = tp->tm_mday;
|
||||
tm.tm_mon = tp->tm_mon;
|
||||
tm.tm_year = tp->tm_year;
|
||||
|
||||
|
||||
/* day */
|
||||
*(date+2) = NULL;
|
||||
tm.tm_mday = atoi(date);
|
||||
|
||||
/* month */
|
||||
if (len >= 4) {
|
||||
*(date+5) = NULL;
|
||||
tm.tm_mon = atoi(date+3) - 1;
|
||||
}
|
||||
|
||||
/* Year */
|
||||
if (len >= 7) {
|
||||
tm.tm_year = atoi(date+6);
|
||||
|
||||
/* tm_year up 1900 ... */
|
||||
if (tm.tm_year > 1900)
|
||||
tm.tm_year -= 1900;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
printf("Mktime: %d %d %d %s\n", (int)mktime(&tm), (int)t, len,
|
||||
asctime(&tm));
|
||||
#endif
|
||||
return(mktime(&tm));
|
||||
}
|
||||
|
||||
/*
|
||||
* Possible date formats include any combination of:
|
||||
* 3-charmonth (January, Jan, Jan)
|
||||
* 3-charweekday (Friday, Monday, mon.)
|
||||
* numeric month or day (1, 2, 04)
|
||||
*
|
||||
* Any character may separate them, or they may not be separated. Any line,
|
||||
* following a line that is matched, that starts with "whitespace", is shown
|
||||
* along with the matched line.
|
||||
*/
|
||||
int
|
||||
isnow(endp)
|
||||
char *endp;
|
||||
{
|
||||
int day, flags, month, v1, v2;
|
||||
|
||||
/*
|
||||
* CONVENTION
|
||||
*
|
||||
* Month: 1-12
|
||||
* Monthname: Jan .. Dec
|
||||
* Day: 1-31
|
||||
* Weekday: Mon-Sun
|
||||
*
|
||||
*/
|
||||
|
||||
flags = 0;
|
||||
|
||||
/* read first field */
|
||||
/* didn't recognize anything, skip it */
|
||||
if (!(v1 = getfield(endp, &endp, &flags)))
|
||||
return (0);
|
||||
|
||||
/* Easter or Easter depending days */
|
||||
if (flags & F_EASTER)
|
||||
day = v1;
|
||||
|
||||
/*
|
||||
* 1. {Weekday,Day} XYZ ...
|
||||
*
|
||||
* where Day is > 12
|
||||
*/
|
||||
else if (flags & F_ISDAY || v1 > 12) {
|
||||
|
||||
/* found a day; day: 1-31 or weekday: 1-7 */
|
||||
day = v1;
|
||||
|
||||
/* {Day,Weekday} {Month,Monthname} ... */
|
||||
/* if no recognizable month, assume just a day alone
|
||||
* in other words, find month or use current month */
|
||||
if (!(month = getfield(endp, &endp, &flags)))
|
||||
month = tp->tm_mon + 1;
|
||||
}
|
||||
|
||||
/* 2. {Monthname} XYZ ... */
|
||||
else if (flags & F_ISMONTH) {
|
||||
month = v1;
|
||||
|
||||
/* Monthname {day,weekday} */
|
||||
/* if no recognizable day, assume the first day in month */
|
||||
if (!(day = getfield(endp, &endp, &flags)))
|
||||
day = 1;
|
||||
}
|
||||
|
||||
/* Hm ... */
|
||||
else {
|
||||
v2 = getfield(endp, &endp, &flags);
|
||||
|
||||
/*
|
||||
* {Day} {Monthname} ...
|
||||
* where Day <= 12
|
||||
*/
|
||||
if (flags & F_ISMONTH) {
|
||||
day = v1;
|
||||
month = v2;
|
||||
}
|
||||
|
||||
/* {Month} {Weekday,Day} ... */
|
||||
else {
|
||||
/* F_ISDAY set, v2 > 12, or no way to tell */
|
||||
month = v1;
|
||||
/* if no recognizable day, assume the first */
|
||||
day = v2 ? v2 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* convert Weekday into *next* Day,
|
||||
* e.g.: 'Sunday' -> 22
|
||||
* 'SunayLast' -> ??
|
||||
*/
|
||||
if (flags & F_ISDAY) {
|
||||
#if DEBUG
|
||||
fprintf(stderr, "\nday: %d %s month %d\n", day, endp, month);
|
||||
#endif
|
||||
|
||||
/* variable weekday, SundayLast, MondayFirst ... */
|
||||
if (day < 0 || day >= 10) {
|
||||
|
||||
/* negative offset; last, -4 .. -1 */
|
||||
if (day < 0) {
|
||||
v1 = day/10 - 1; /* offset -4 ... -1 */
|
||||
day = 10 + (day % 10); /* day 1 ... 7 */
|
||||
|
||||
/* day, eg '22th' */
|
||||
v2 = tp->tm_mday + (((day - 1) - tp->tm_wday + 7) % 7);
|
||||
|
||||
/* (month length - day) / 7 + 1 */
|
||||
if (((int)((cumdays[month+1] -
|
||||
cumdays[month] - v2) / 7) + 1) == -v1)
|
||||
/* bingo ! */
|
||||
day = v2;
|
||||
|
||||
/* set to yesterday */
|
||||
else
|
||||
day = tp->tm_mday - 1;
|
||||
}
|
||||
|
||||
/* first, second ... +1 ... +5 */
|
||||
else {
|
||||
v1 = day/10; /* offset: +1 (first Sunday) ... */
|
||||
day = day % 10;
|
||||
|
||||
/* day, eg '22th' */
|
||||
v2 = tp->tm_mday + (((day - 1) - tp->tm_wday + 7) % 7);
|
||||
|
||||
/* Hurrah! matched */
|
||||
if ( ((v2 - 1 + 7) / 7) == v1 )
|
||||
day = v2;
|
||||
|
||||
/* set to yesterday */
|
||||
else
|
||||
day = tp->tm_mday - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* wired */
|
||||
else {
|
||||
day = tp->tm_mday + (((day - 1) - tp->tm_wday + 7) % 7);
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
fprintf(stderr, "day2: yday %d %d\n", day, tp->tm_yday);
|
||||
#endif
|
||||
if (!(flags & F_EASTER))
|
||||
day = cumdays[month] + day;
|
||||
|
||||
/* if today or today + offset days */
|
||||
if (day >= tp->tm_yday - f_dayBefore &&
|
||||
day <= tp->tm_yday + offset + f_dayAfter)
|
||||
return (1);
|
||||
|
||||
/* if number of days left in this year + days to event in next year */
|
||||
if (yrdays - tp->tm_yday + day <= offset + f_dayAfter ||
|
||||
/* a year backward, eg. 6 Jan and 10 days before -> 27. Dec */
|
||||
tp->tm_yday + day - f_dayBefore < 0
|
||||
)
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
getmonth(s)
|
||||
register char *s;
|
||||
{
|
||||
register char **p;
|
||||
|
||||
for (p = months; *p; ++p)
|
||||
if (!strncasecmp(s, *p, 3))
|
||||
return ((p - months) + 1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
getday(s)
|
||||
register char *s;
|
||||
{
|
||||
register char **p;
|
||||
|
||||
for (p = days; *p; ++p)
|
||||
if (!strncasecmp(s, *p, 3))
|
||||
return ((p - days) + 1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* return offset for variable weekdays
|
||||
* -1 -> last weekday in month
|
||||
* +1 -> first weekday in month
|
||||
* ... etc ...
|
||||
*/
|
||||
int
|
||||
getdayvar(s)
|
||||
register char *s;
|
||||
{
|
||||
register int offset;
|
||||
|
||||
|
||||
offset = strlen(s);
|
||||
|
||||
|
||||
/* Sun+1 or Wednesday-2
|
||||
* ^ ^ */
|
||||
|
||||
/* printf ("x: %s %s %d\n", s, s + offset - 2, offset); */
|
||||
switch(*(s + offset - 2)) {
|
||||
case '-':
|
||||
return(-(atoi(s + offset - 1)));
|
||||
break;
|
||||
case '+':
|
||||
return(atoi(s + offset - 1));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* some aliases: last, first, second, third, fourth
|
||||
*/
|
||||
|
||||
/* last */
|
||||
if (offset > 4 && !strcasecmp(s + offset - 4, "last"))
|
||||
return(-1);
|
||||
else if (offset > 5 && !strcasecmp(s + offset - 5, "first"))
|
||||
return(+1);
|
||||
else if (offset > 6 && !strcasecmp(s + offset - 6, "second"))
|
||||
return(+2);
|
||||
else if (offset > 5 && !strcasecmp(s + offset - 5, "third"))
|
||||
return(+3);
|
||||
else if (offset > 6 && !strcasecmp(s + offset - 6, "fourth"))
|
||||
return(+4);
|
||||
|
||||
|
||||
/* no offset detected */
|
||||
return(0);
|
||||
}
|
271
usr.bin/calendar/io.c
Normal file
271
usr.bin/calendar/io.c
Normal file
@ -0,0 +1,271 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1989, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)calendar.c 8.3 (Berkeley) 3/25/94";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/time.h>
|
||||
#include <stdlib.h>
|
||||
#include <pwd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include "pathnames.h"
|
||||
#include "calendar.h"
|
||||
|
||||
|
||||
char *calendarFile = "calendar"; /* default calendar file */
|
||||
char *calendarHome = ".calendar"; /* HOME */
|
||||
char *calendarNoMail = "nomail"; /* don't sent mail if this file exist */
|
||||
|
||||
struct iovec header[] = {
|
||||
"From: ", 6,
|
||||
NULL, 0,
|
||||
" (Reminder Service)\nTo: ", 24,
|
||||
NULL, 0,
|
||||
"\nSubject: ", 10,
|
||||
NULL, 0,
|
||||
"'s Calendar\nPrecedence: bulk\n\n", 30,
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
cal()
|
||||
{
|
||||
register int printing;
|
||||
register char *p;
|
||||
FILE *fp;
|
||||
int ch;
|
||||
char buf[2048 + 1];
|
||||
|
||||
if ((fp = opencal()) == NULL)
|
||||
return;
|
||||
for (printing = 0; fgets(buf, sizeof(buf), stdin) != NULL;) {
|
||||
if ((p = strchr(buf, '\n')) != NULL)
|
||||
*p = '\0';
|
||||
else
|
||||
while ((ch = getchar()) != '\n' && ch != EOF);
|
||||
if (buf[0] == '\0')
|
||||
continue;
|
||||
if (buf[0] != '\t')
|
||||
printing = isnow(buf) ? 1 : 0;
|
||||
if (printing)
|
||||
(void)fprintf(fp, "%s\n", buf);
|
||||
}
|
||||
closecal(fp);
|
||||
}
|
||||
|
||||
int
|
||||
getfield(p, endp, flags)
|
||||
char *p, **endp;
|
||||
int *flags;
|
||||
{
|
||||
int val, var;
|
||||
char *start, savech;
|
||||
|
||||
for (; !isdigit(*p) && !isalpha(*p) && *p != '*'; ++p);
|
||||
if (*p == '*') { /* `*' is current month */
|
||||
*flags |= F_ISMONTH;
|
||||
*endp = p+1;
|
||||
return (tp->tm_mon + 1);
|
||||
}
|
||||
if (isdigit(*p)) {
|
||||
val = strtol(p, &p, 10); /* if 0, it's failure */
|
||||
for (; !isdigit(*p) && !isalpha(*p) && *p != '*'; ++p);
|
||||
*endp = p;
|
||||
return (val);
|
||||
}
|
||||
for (start = p; isalpha(*++p););
|
||||
|
||||
/* Sunday-1 */
|
||||
if (*p == '+' || *p == '-')
|
||||
for(; isdigit(*++p););
|
||||
|
||||
savech = *p;
|
||||
*p = '\0';
|
||||
|
||||
/* Month */
|
||||
if ((val = getmonth(start)) != 0)
|
||||
*flags |= F_ISMONTH;
|
||||
|
||||
/* Day */
|
||||
else if ((val = getday(start)) != 0) {
|
||||
*flags |= F_ISDAY;
|
||||
|
||||
/* variable weekday */
|
||||
if ((var = getdayvar(start)) != 0) {
|
||||
if (var <=5 && var >= -4)
|
||||
val += var * 10;
|
||||
#ifdef DEBUG
|
||||
printf("var: %d\n", var);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Easter */
|
||||
else if ((val = geteaster(start, tp->tm_year + 1900)) != 0)
|
||||
*flags |= F_EASTER;
|
||||
|
||||
/* undefined rest */
|
||||
else {
|
||||
*p = savech;
|
||||
return (0);
|
||||
}
|
||||
for (*p = savech; !isdigit(*p) && !isalpha(*p) && *p != '*'; ++p);
|
||||
*endp = p;
|
||||
return (val);
|
||||
}
|
||||
|
||||
char path[MAXPATHLEN + 1];
|
||||
|
||||
FILE *
|
||||
opencal()
|
||||
{
|
||||
int fd, pdes[2];
|
||||
struct stat sbuf;
|
||||
|
||||
/* open up calendar file as stdin */
|
||||
if (!freopen(calendarFile, "r", stdin)) {
|
||||
if (doall) {
|
||||
if (chdir(calendarHome) != 0)
|
||||
return (NULL);
|
||||
if (stat(calendarNoMail, &sbuf) == 0)
|
||||
return (NULL);
|
||||
if (!freopen(calendarFile, "r", stdin))
|
||||
return (NULL);
|
||||
} else {
|
||||
chdir(getenv("HOME"));
|
||||
if (!(chdir(calendarHome) == 0 &&
|
||||
freopen(calendarFile, "r", stdin)))
|
||||
errx(1, "no calendar file: ``%s'' or ``~/%s/%s\n", calendarFile, calendarHome, calendarFile);
|
||||
}
|
||||
}
|
||||
if (pipe(pdes) < 0)
|
||||
return (NULL);
|
||||
switch (vfork()) {
|
||||
case -1: /* error */
|
||||
(void)close(pdes[0]);
|
||||
(void)close(pdes[1]);
|
||||
return (NULL);
|
||||
case 0:
|
||||
/* child -- stdin already setup, set stdout to pipe input */
|
||||
if (pdes[1] != STDOUT_FILENO) {
|
||||
(void)dup2(pdes[1], STDOUT_FILENO);
|
||||
(void)close(pdes[1]);
|
||||
}
|
||||
(void)close(pdes[0]);
|
||||
execl(_PATH_CPP, "cpp", "-P", "-I.", _PATH_INCLUDE, NULL);
|
||||
(void)fprintf(stderr,
|
||||
"calendar: execl: %s: %s.\n", _PATH_CPP, strerror(errno));
|
||||
_exit(1);
|
||||
}
|
||||
/* parent -- set stdin to pipe output */
|
||||
(void)dup2(pdes[0], STDIN_FILENO);
|
||||
(void)close(pdes[0]);
|
||||
(void)close(pdes[1]);
|
||||
|
||||
/* not reading all calendar files, just set output to stdout */
|
||||
if (!doall)
|
||||
return (stdout);
|
||||
|
||||
/* set output to a temporary file, so if no output don't send mail */
|
||||
(void)snprintf(path, sizeof(path), "%s/_calXXXXXX", _PATH_TMP);
|
||||
if ((fd = mkstemp(path)) < 0)
|
||||
return (NULL);
|
||||
return (fdopen(fd, "w+"));
|
||||
}
|
||||
|
||||
void
|
||||
closecal(fp)
|
||||
FILE *fp;
|
||||
{
|
||||
struct stat sbuf;
|
||||
int nread, pdes[2], status;
|
||||
char buf[1024];
|
||||
|
||||
if (!doall)
|
||||
return;
|
||||
|
||||
(void)rewind(fp);
|
||||
if (fstat(fileno(fp), &sbuf) || !sbuf.st_size)
|
||||
goto done;
|
||||
if (pipe(pdes) < 0)
|
||||
goto done;
|
||||
switch (vfork()) {
|
||||
case -1: /* error */
|
||||
(void)close(pdes[0]);
|
||||
(void)close(pdes[1]);
|
||||
goto done;
|
||||
case 0:
|
||||
/* child -- set stdin to pipe output */
|
||||
if (pdes[0] != STDIN_FILENO) {
|
||||
(void)dup2(pdes[0], STDIN_FILENO);
|
||||
(void)close(pdes[0]);
|
||||
}
|
||||
(void)close(pdes[1]);
|
||||
execl(_PATH_SENDMAIL, "sendmail", "-i", "-t", "-F",
|
||||
"\"Reminder Service\"", "-f", "root", NULL);
|
||||
(void)fprintf(stderr,
|
||||
"calendar: %s: %s.\n", _PATH_SENDMAIL, strerror(errno));
|
||||
_exit(1);
|
||||
}
|
||||
/* parent -- write to pipe input */
|
||||
(void)close(pdes[0]);
|
||||
|
||||
header[1].iov_base = header[3].iov_base = pw->pw_name;
|
||||
header[1].iov_len = header[3].iov_len = strlen(pw->pw_name);
|
||||
writev(pdes[1], header, 7);
|
||||
while ((nread = read(fileno(fp), buf, sizeof(buf))) > 0)
|
||||
(void)write(pdes[1], buf, nread);
|
||||
(void)close(pdes[1]);
|
||||
done: (void)fclose(fp);
|
||||
(void)unlink(path);
|
||||
while (wait(&status) >= 0);
|
||||
}
|
||||
|
94
usr.bin/calendar/ostern.c
Normal file
94
usr.bin/calendar/ostern.c
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 1995 Wolfram Schneider. Public domain.
|
||||
*
|
||||
* $Id: ostern.c,v 1.2 1996/02/01 13:05:12 wosch Exp $
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* return year day for Easter */
|
||||
|
||||
int easter (year)
|
||||
int year; /* 0 ... abcd, NOT since 1900 */
|
||||
{
|
||||
|
||||
int e_a, e_b, e_c, e_d, e_e,e_f, e_g, e_h, e_i, e_k,
|
||||
e_l, e_m, e_n, e_p, e_q;
|
||||
|
||||
/* silly, but it works */
|
||||
e_a = year % 19;
|
||||
e_b = year / 100;
|
||||
e_c = year % 100;
|
||||
|
||||
e_d = e_b / 4;
|
||||
e_e = e_b % 4;
|
||||
e_f = (e_b + 8) / 25;
|
||||
e_g = (e_b + 1 - e_f) / 3;
|
||||
e_h = ((19 * e_a) + 15 + e_b - (e_d + e_g)) % 30;
|
||||
e_i = e_c / 4;
|
||||
e_k = e_c % 4;
|
||||
e_l = (32 + 2 * e_e + 2 * e_i - (e_h + e_k)) % 7;
|
||||
e_m = (e_a + 11 * e_h + 22 * e_l) / 451;
|
||||
e_n = (e_h + e_l + 114 - (7 * e_m)) / 31;
|
||||
e_p = (e_h + e_l + 114 - (7 * e_m)) % 31;
|
||||
e_p = e_p + 1;
|
||||
|
||||
e_q = 31 + 28;
|
||||
|
||||
if (e_k == 0 && e_c != 0)
|
||||
e_q += 1;
|
||||
|
||||
if (e_n == 4)
|
||||
e_q += 31;
|
||||
|
||||
e_q += e_p;
|
||||
|
||||
#if DEBUG
|
||||
printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", e_a , e_b , e_c , e_d , e_e , e_f , e_g , e_h , e_i , e_k , e_l , e_m , e_n , e_p , e_q);
|
||||
#endif
|
||||
|
||||
return (e_q);
|
||||
}
|
||||
|
||||
/* return year day for Easter or easter depending days
|
||||
* Match: Easter([+-][0-9]+)?
|
||||
* e.g: Easter-2 is Good Friday (2 days before Easter)
|
||||
*/
|
||||
|
||||
int
|
||||
geteaster(s, year)
|
||||
char *s;
|
||||
int year;
|
||||
{
|
||||
register int offset = 0;
|
||||
|
||||
#define EASTER "easter"
|
||||
#define EASTERNAMELEN (sizeof(EASTER) - 1)
|
||||
|
||||
/* no easter */
|
||||
if (strncasecmp(s, EASTER, EASTERNAMELEN))
|
||||
return(0);
|
||||
|
||||
#if DEBUG
|
||||
printf("%s %d %d\n", s, year, EASTERNAMELEN);
|
||||
#endif
|
||||
|
||||
/* Easter+1 or Easter-2
|
||||
* ^ ^ */
|
||||
|
||||
switch(*(s + EASTERNAMELEN)) {
|
||||
|
||||
case '-':
|
||||
offset = -(atoi(s + EASTERNAMELEN + 1));
|
||||
break;
|
||||
|
||||
case '+':
|
||||
offset = atoi(s + EASTERNAMELEN + 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
return (easter(year) + offset);
|
||||
}
|
@ -36,5 +36,6 @@
|
||||
#include <paths.h>
|
||||
|
||||
#define _PATH_CPP "/usr/bin/cpp"
|
||||
|
||||
/* XXX -- fix when cpp parses arguments rationally */
|
||||
#define _PATH_INCLUDE "-I/usr/share/calendar"
|
||||
|
Loading…
x
Reference in New Issue
Block a user