diff options
author | mckusick <mckusick@FreeBSD.org> | 2010-04-28 05:33:59 +0000 |
---|---|---|
committer | mckusick <mckusick@FreeBSD.org> | 2010-04-28 05:33:59 +0000 |
commit | 3a0f5972a0de87aebef1af257922515700da4217 (patch) | |
tree | a65d36ab57a1e076de7e7a1d78add642fbd7062e /usr.bin/calendar/io.c | |
parent | f40c3a9dc50f808e512fcc9f9f738717013b483b (diff) | |
parent | a768cbcadec7189b9947e9f3cde39fe806bbc1d7 (diff) | |
download | FreeBSD-src-3a0f5972a0de87aebef1af257922515700da4217.zip FreeBSD-src-3a0f5972a0de87aebef1af257922515700da4217.tar.gz |
Update to current version of head.
Diffstat (limited to 'usr.bin/calendar/io.c')
-rw-r--r-- | usr.bin/calendar/io.c | 372 |
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]); |