summaryrefslogtreecommitdiffstats
path: root/usr.bin/calendar/io.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/calendar/io.c')
-rw-r--r--usr.bin/calendar/io.c372
1 files changed, 105 insertions, 267 deletions
diff --git a/usr.bin/calendar/io.c b/usr.bin/calendar/io.c
index 03f28fe..42abca6 100644
--- a/usr.bin/calendar/io.c
+++ b/usr.bin/calendar/io.c
@@ -1,4 +1,4 @@
-/*
+/*-
* Copyright (c) 1989, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
@@ -10,10 +10,6 @@
* 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.
@@ -46,11 +42,8 @@ static char sccsid[] = "@(#)calendar.c 8.3 (Berkeley) 3/25/94";
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/uio.h>
#include <sys/wait.h>
#include <ctype.h>
#include <err.h>
@@ -66,62 +59,61 @@ __FBSDID("$FreeBSD$");
#include "pathnames.h"
#include "calendar.h"
-/*
- * Event sorting related functions:
- * - Use event_add() to create a new event
- * - Use event_continue() to add more text to the last added event
- * - Use event_print_all() to display them in time chronological order
- */
-static struct event *event_add(struct event *, int, int, char *, int, char *);
-static void event_continue(struct event *events, char *txt);
-static void event_print_all(FILE *fp, struct event *events);
-struct event {
- int month;
- int day;
- int var;
- char *date;
- char *text;
- struct event *next;
-};
-
const char *calendarFile = "calendar"; /* default calendar file */
const char *calendarHomes[] = {".calendar", _PATH_INCLUDE}; /* HOME */
const char *calendarNoMail = "nomail"; /* don't sent mail if this file exist */
char path[MAXPATHLEN];
-struct fixs neaster, npaskha;
-
-struct iovec header[] = {
- {"From: ", 6},
- {NULL, 0},
- {" (Reminder Service)\nTo: ", 24},
- {NULL, 0},
- {"\nSubject: ", 10},
- {NULL, 0},
- {"'s Calendar\nPrecedence: bulk\n\n", 30},
-};
-
+struct fixs neaster, npaskha, ncny, nfullmoon, nnewmoon;
+struct fixs nmarequinox, nsepequinox, njunsolstice, ndecsolstice;
+
+#define REPLACE(string, slen, struct_) \
+ if (strncasecmp(buf, (string), (slen)) == 0 && buf[(slen)]) { \
+ if (struct_.name != NULL) \
+ free(struct_.name); \
+ if ((struct_.name = strdup(buf + (slen))) == NULL) \
+ errx(1, "cannot allocate memory"); \
+ struct_.len = strlen(buf + (slen)); \
+ continue; \
+ }
void
cal(void)
{
- int printing;
- char *p;
+ char *pp, p;
FILE *fp;
int ch, l;
- int month;
- int day;
- int var;
+ int count, i;
+ int month[MAXCOUNT];
+ int day[MAXCOUNT];
+ int year[MAXCOUNT];
+ char **extradata; /* strings of 20 length */
+ int flags;
static int d_first = -1;
char buf[2048 + 1];
- struct event *events = NULL;
+ struct event *events[MAXCOUNT];
+ struct tm tm;
+ char dbuf[80];
+
+ extradata = (char **)calloc(MAXCOUNT, sizeof(char *));
+ for (i = 0; i < MAXCOUNT; i++) {
+ extradata[i] = (char *)calloc(1, 20);
+ }
+
+ /* Unused */
+ tm.tm_sec = 0;
+ tm.tm_min = 0;
+ tm.tm_hour = 0;
+ tm.tm_wday = 0;
+ count = 0;
if ((fp = opencal()) == NULL)
return;
- for (printing = 0; fgets(buf, sizeof(buf), stdin) != NULL;) {
- if ((p = strchr(buf, '\n')) != NULL)
- *p = '\0';
+ while (fgets(buf, sizeof(buf), stdin) != NULL) {
+ if ((pp = strchr(buf, '\n')) != NULL)
+ *pp = '\0';
else
+ /* Flush this line */
while ((ch = getchar()) != '\n' && ch != EOF);
for (l = strlen(buf);
l > 0 && isspace((unsigned char)buf[l - 1]);
@@ -130,246 +122,87 @@ cal(void)
buf[l] = '\0';
if (buf[0] == '\0')
continue;
+
+ /* Parse special definitions: LANG, Easter, Paskha etc */
if (strncmp(buf, "LANG=", 5) == 0) {
(void)setlocale(LC_ALL, buf + 5);
d_first = (*nl_langinfo(D_MD_ORDER) == 'd');
setnnames();
continue;
}
- if (strncasecmp(buf, "Easter=", 7) == 0 && buf[7]) {
- if (neaster.name != NULL)
- free(neaster.name);
- if ((neaster.name = strdup(buf + 7)) == NULL)
- errx(1, "cannot allocate memory");
- neaster.len = strlen(buf + 7);
- continue;
- }
- if (strncasecmp(buf, "Paskha=", 7) == 0 && buf[7]) {
- if (npaskha.name != NULL)
- free(npaskha.name);
- if ((npaskha.name = strdup(buf + 7)) == NULL)
- errx(1, "cannot allocate memory");
- npaskha.len = strlen(buf + 7);
+ REPLACE("Easter=", 7, neaster);
+ REPLACE("Paskha=", 7, npaskha);
+ REPLACE("ChineseNewYear=", 15, ncny);
+ REPLACE("NewMoon=", 8, nnewmoon);
+ REPLACE("FullMoon=", 9, nfullmoon);
+ REPLACE("MarEquinox=", 11, nmarequinox);
+ REPLACE("SepEquinox=", 11, nsepequinox);
+ REPLACE("JunSolstice=", 12, njunsolstice);
+ REPLACE("DecSolstice=", 12, ndecsolstice);
+ if (strncmp(buf, "SEQUENCE=", 9) == 0) {
+ setnsequences(buf + 9);
continue;
}
- if (buf[0] != '\t') {
- printing = isnow(buf, &month, &day, &var) ? 1 : 0;
- if ((p = strchr(buf, '\t')) == NULL)
- continue;
- if (p > buf && p[-1] == '*')
- var = 1;
- if (printing) {
- struct tm tm;
- char dbuf[80];
-
- if (d_first < 0)
- d_first =
- (*nl_langinfo(D_MD_ORDER) == 'd');
- tm.tm_sec = 0; /* unused */
- tm.tm_min = 0; /* unused */
- tm.tm_hour = 0; /* unused */
- tm.tm_wday = 0; /* unused */
- tm.tm_mon = month - 1;
- tm.tm_mday = day;
- tm.tm_year = tp->tm_year; /* unused */
- (void)strftime(dbuf, sizeof(dbuf),
- d_first ? "%e %b" : "%b %e", &tm);
- events = event_add(events, month, day, dbuf,
- var, p);
- }
- } else {
- if (printing)
- event_continue(events, buf);
- }
- }
-
- event_print_all(fp, events);
- closecal(fp);
-}
-
-static struct event *
-event_add(struct event *events, int month, int day,
- char *date, int var, char *txt)
-{
- struct event *e;
-
- /*
- * Creating a new event:
- * - Create a new event
- * - Copy the machine readable day and month
- * - Copy the human readable and language specific date
- * - Copy the text of the event
- */
- e = (struct event *)calloc(1, sizeof(struct event));
- if (e == NULL)
- errx(1, "event_add: cannot allocate memory");
- e->month = month;
- e->day = day;
- e->var = var;
- e->date = strdup(date);
- if (e->date == NULL)
- errx(1, "event_add: cannot allocate memory");
- e->text = strdup(txt);
- if (e->text == NULL)
- errx(1, "event_add: cannot allocate memory");
- e->next = events;
-
- return e;
-}
-
-static void
-event_continue(struct event *e, char *txt)
-{
- char *text;
-
- /*
- * Adding text to the event:
- * - Save a copy of the old text (unknown length, so strdup())
- * - Allocate enough space for old text + \n + new text + 0
- * - Store the old text + \n + new text
- * - Destroy the saved copy.
- */
- text = strdup(e->text);
- if (text == NULL)
- errx(1, "event_continue: cannot allocate memory");
-
- free(e->text);
- e->text = (char *)malloc(strlen(text) + strlen(txt) + 3);
- if (e->text == NULL)
- errx(1, "event_continue: cannot allocate memory");
- strcpy(e->text, text);
- strcat(e->text, "\n");
- strcat(e->text, txt);
- free(text);
-
- return;
-}
-
-static void
-event_print_all(FILE *fp, struct event *events)
-{
- struct event *e, *e_next;
- int daycounter;
- int day, month;
-
- /*
- * Print all events:
- * - We know the number of days to be counted (f_dayAfter + f_dayBefore)
- * - We know the current day of the year ("now" - f_dayBefore + counter)
- * - We know the number of days in the year (yrdays, set in settime())
- * - So we know the date on which the current daycounter is on the
- * calendar in days and months.
- * - Go through the list of events, and print all matching dates
- */
- for (daycounter = 0; daycounter <= f_dayAfter + f_dayBefore;
- daycounter++) {
- day = tp->tm_yday - f_dayBefore + daycounter;
- if (day < 0)
- day += yrdays;
- if (day >= yrdays)
- day -= yrdays;
/*
- * When we know the day of the year, we can determine the day
- * of the month and the month.
+ * If the line starts with a tab, the data has to be
+ * added to the previous line
*/
- month = 1;
- while (month <= 12) {
- if (day <= cumdays[month])
- break;
- month++;
+ if (buf[0] == '\t') {
+ for (i = 0; i < count; i++)
+ event_continue(events[i], buf);
+ continue;
}
- month--;
- day -= cumdays[month];
-#ifdef DEBUG
- fprintf(stderr, "event_print_allmonth: %d, day: %d\n",
- month, day);
-#endif
+ /* Get rid of leading spaces (non-standard) */
+ while (isspace(buf[0]))
+ memcpy(buf, buf + 1, strlen(buf) - 1);
- /*
- * Go through all events and print the text of the matching
- * dates
- */
- for (e = events; e != NULL; e = e_next) {
- e_next = e->next;
+ /* No tab in the line, then not a valid line */
+ if ((pp = strchr(buf, '\t')) == NULL)
+ continue;
- if (month != e->month || day != e->day)
- continue;
+ /* Trim spaces in front of the tab */
+ while (isspace(pp[-1]))
+ pp--;
- (void)fprintf(fp, "%s%c%s\n", e->date,
- e->var ? '*' : ' ', e->text);
+ p = *pp;
+ *pp = '\0';
+ if ((count = parsedaymonth(buf, year, month, day, &flags,
+ extradata)) == 0)
+ continue;
+ *pp = p;
+ if (count < 0) {
+ /* Show error status based on return value */
+ fprintf(stderr, "Ignored: %s\n", buf);
+ if (count == -1)
+ continue;
+ count = -count + 1;
}
- }
-}
-int
-getfield(char *p, char **endp, int *flags)
-{
- int val, var;
- char *start, savech;
+ /* Find the last tab */
+ while (pp[1] == '\t')
+ pp++;
- for (; !isdigit((unsigned char)*p) && !isalpha((unsigned char)*p)
- && *p != '*'; ++p)
- ;
- if (*p == '*') { /* `*' is current month */
- *flags |= F_ISMONTH;
- *endp = p + 1;
- return (tp->tm_mon + 1);
- }
- if (isdigit((unsigned char)*p)) {
- val = strtol(p, &p, 10); /* if 0, it's failure */
- for (; !isdigit((unsigned char)*p)
- && !isalpha((unsigned char)*p) && *p != '*'; ++p);
- *endp = p;
- return (val);
- }
- for (start = p; isalpha((unsigned char)*++p););
-
- /* Sunday-1 */
- if (*p == '+' || *p == '-')
- for(; isdigit((unsigned char)*++p);)
- ;
-
- savech = *p;
- *p = '\0';
-
- /* Month */
- if ((val = getmonth(start)) != 0)
- *flags |= F_ISMONTH;
-
- /* Day */
- else if ((val = getday(start)) != 0) {
- *flags |= F_ISDAY;
+ if (d_first < 0)
+ d_first = (*nl_langinfo(D_MD_ORDER) == 'd');
- /* variable weekday */
- if ((var = getdayvar(start)) != 0) {
- if (var <= 5 && var >= -4)
- val += var * 10;
-#ifdef DEBUG
- printf("var: %d\n", var);
-#endif
+ for (i = 0; i < count; i++) {
+ tm.tm_mon = month[i] - 1;
+ tm.tm_mday = day[i];
+ tm.tm_year = year[i] - 1900;
+ (void)strftime(dbuf, sizeof(dbuf),
+ d_first ? "%e %b" : "%b %e", &tm);
+ if (debug)
+ fprintf(stderr, "got %s\n", pp);
+ events[i] = event_add(year[i], month[i], day[i], dbuf,
+ ((flags &= F_VARIABLE) != 0) ? 1 : 0, pp,
+ extradata[i]);
}
}
- /* Easter */
- else if ((val = geteaster(start, tp->tm_year + 1900)) != 0)
- *flags |= F_EASTER;
-
- /* Paskha */
- else if ((val = getpaskha(start, tp->tm_year + 1900)) != 0)
- *flags |= F_EASTER;
-
- /* undefined rest */
- else {
- *p = savech;
- return (0);
- }
- for (*p = savech; !isdigit((unsigned char)*p)
- && !isalpha((unsigned char)*p) && *p != '*'; ++p)
- ;
- *endp = p;
- return (val);
+ event_print_all(fp);
+ closecal(fp);
}
FILE *
@@ -505,9 +338,14 @@ closecal(FILE *fp)
/* 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);
+ write(pdes[1], "From: \"Reminder Service\" <", 26);
+ write(pdes[1], pw->pw_name, strlen(pw->pw_name));
+ write(pdes[1], ">\nTo: <", 7);
+ write(pdes[1], pw->pw_name, strlen(pw->pw_name));
+ write(pdes[1], ">\nSubject: ", 12);
+ write(pdes[1], dayname, strlen(dayname));
+ write(pdes[1], "'s Calendar\nPrecedence: bulk\n\n", 30);
+
while ((nread = read(fileno(fp), buf, sizeof(buf))) > 0)
(void)write(pdes[1], buf, nread);
(void)close(pdes[1]);
OpenPOWER on IntegriCloud