io.c (200628) | io.c (205821) |
---|---|
1/* | 1/*- |
2 * Copyright (c) 1989, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. --- 29 unchanged lines hidden (view full) --- 39 40#if 0 41#ifndef lint 42static char sccsid[] = "@(#)calendar.c 8.3 (Berkeley) 3/25/94"; 43#endif 44#endif 45 46#include <sys/cdefs.h> | 2 * Copyright (c) 1989, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. --- 29 unchanged lines hidden (view full) --- 39 40#if 0 41#ifndef lint 42static char sccsid[] = "@(#)calendar.c 8.3 (Berkeley) 3/25/94"; 43#endif 44#endif 45 46#include <sys/cdefs.h> |
47__FBSDID("$FreeBSD: head/usr.bin/calendar/io.c 200628 2009-12-17 08:42:44Z rse $"); | 47__FBSDID("$FreeBSD: head/usr.bin/calendar/io.c 205821 2010-03-29 06:49:20Z edwin $"); |
48 | 48 |
49#include <sys/types.h> | |
50#include <sys/param.h> 51#include <sys/stat.h> | 49#include <sys/param.h> 50#include <sys/stat.h> |
52#include <sys/time.h> 53#include <sys/uio.h> | |
54#include <sys/wait.h> 55#include <ctype.h> 56#include <err.h> 57#include <errno.h> 58#include <langinfo.h> 59#include <locale.h> 60#include <pwd.h> 61#include <stdio.h> 62#include <stdlib.h> 63#include <string.h> 64#include <unistd.h> 65 66#include "pathnames.h" 67#include "calendar.h" 68 | 51#include <sys/wait.h> 52#include <ctype.h> 53#include <err.h> 54#include <errno.h> 55#include <langinfo.h> 56#include <locale.h> 57#include <pwd.h> 58#include <stdio.h> 59#include <stdlib.h> 60#include <string.h> 61#include <unistd.h> 62 63#include "pathnames.h" 64#include "calendar.h" 65 |
69/* 70 * Event sorting related functions: 71 * - Use event_add() to create a new event 72 * - Use event_continue() to add more text to the last added event 73 * - Use event_print_all() to display them in time chronological order 74 */ 75static struct event *event_add(struct event *, int, int, char *, int, char *); 76static void event_continue(struct event *events, char *txt); 77static void event_print_all(FILE *fp, struct event *events); 78struct event { 79 int month; 80 int day; 81 int var; 82 char *date; 83 char *text; 84 struct event *next; 85}; 86 | |
87const char *calendarFile = "calendar"; /* default calendar file */ 88const char *calendarHomes[] = {".calendar", _PATH_INCLUDE}; /* HOME */ 89const char *calendarNoMail = "nomail"; /* don't sent mail if this file exist */ 90 91char path[MAXPATHLEN]; 92 | 66const char *calendarFile = "calendar"; /* default calendar file */ 67const char *calendarHomes[] = {".calendar", _PATH_INCLUDE}; /* HOME */ 68const char *calendarNoMail = "nomail"; /* don't sent mail if this file exist */ 69 70char path[MAXPATHLEN]; 71 |
93struct fixs neaster, npaskha; | 72struct fixs neaster, npaskha, ncny, nfullmoon, nnewmoon; 73struct fixs nmarequinox, nsepequinox, njunsolstice, ndecsolstice; |
94 | 74 |
95struct iovec header[] = { 96 {"From: ", 6}, 97 {NULL, 0}, 98 {" (Reminder Service)\nTo: ", 24}, 99 {NULL, 0}, 100 {"\nSubject: ", 10}, 101 {NULL, 0}, 102 {"'s Calendar\nPrecedence: bulk\n\n", 30}, 103}; 104 | 75#define REPLACE(string, slen, struct_) \ 76 if (strncasecmp(buf, (string), (slen)) == 0 && buf[(slen)]) { \ 77 if (struct_.name != NULL) \ 78 free(struct_.name); \ 79 if ((struct_.name = strdup(buf + (slen))) == NULL) \ 80 errx(1, "cannot allocate memory"); \ 81 struct_.len = strlen(buf + (slen)); \ 82 continue; \ 83 } |
105void 106cal(void) 107{ | 84void 85cal(void) 86{ |
108 int printing; 109 char *p; | 87 char *pp, p; |
110 FILE *fp; 111 int ch, l; | 88 FILE *fp; 89 int ch, l; |
112 int month; 113 int day; 114 int var; | 90 int count, i; 91 int month[MAXCOUNT]; 92 int day[MAXCOUNT]; 93 int year[MAXCOUNT]; 94 char **extradata; /* strings of 20 length */ 95 int flags; |
115 static int d_first = -1; 116 char buf[2048 + 1]; | 96 static int d_first = -1; 97 char buf[2048 + 1]; |
117 struct event *events = NULL; | 98 struct event *events[MAXCOUNT]; 99 struct tm tm; 100 char dbuf[80]; |
118 | 101 |
102 extradata = (char **)calloc(MAXCOUNT, sizeof(char *)); 103 for (i = 0; i < MAXCOUNT; i++) { 104 extradata[i] = (char *)calloc(1, 20); 105 } 106 107 /* Unused */ 108 tm.tm_sec = 0; 109 tm.tm_min = 0; 110 tm.tm_hour = 0; 111 tm.tm_wday = 0; 112 113 count = 0; |
|
119 if ((fp = opencal()) == NULL) 120 return; | 114 if ((fp = opencal()) == NULL) 115 return; |
121 for (printing = 0; fgets(buf, sizeof(buf), stdin) != NULL;) { 122 if ((p = strchr(buf, '\n')) != NULL) 123 *p = '\0'; | 116 while (fgets(buf, sizeof(buf), stdin) != NULL) { 117 if ((pp = strchr(buf, '\n')) != NULL) 118 *pp = '\0'; |
124 else | 119 else |
120 /* Flush this line */ |
|
125 while ((ch = getchar()) != '\n' && ch != EOF); 126 for (l = strlen(buf); 127 l > 0 && isspace((unsigned char)buf[l - 1]); 128 l--) 129 ; 130 buf[l] = '\0'; 131 if (buf[0] == '\0') 132 continue; | 121 while ((ch = getchar()) != '\n' && ch != EOF); 122 for (l = strlen(buf); 123 l > 0 && isspace((unsigned char)buf[l - 1]); 124 l--) 125 ; 126 buf[l] = '\0'; 127 if (buf[0] == '\0') 128 continue; |
129 130 /* Parse special definitions: LANG, Easter, Paskha etc */ |
|
133 if (strncmp(buf, "LANG=", 5) == 0) { 134 (void)setlocale(LC_ALL, buf + 5); 135 d_first = (*nl_langinfo(D_MD_ORDER) == 'd'); 136 setnnames(); 137 continue; 138 } | 131 if (strncmp(buf, "LANG=", 5) == 0) { 132 (void)setlocale(LC_ALL, buf + 5); 133 d_first = (*nl_langinfo(D_MD_ORDER) == 'd'); 134 setnnames(); 135 continue; 136 } |
139 if (strncasecmp(buf, "Easter=", 7) == 0 && buf[7]) { 140 if (neaster.name != NULL) 141 free(neaster.name); 142 if ((neaster.name = strdup(buf + 7)) == NULL) 143 errx(1, "cannot allocate memory"); 144 neaster.len = strlen(buf + 7); | 137 REPLACE("Easter=", 7, neaster); 138 REPLACE("Paskha=", 7, npaskha); 139 REPLACE("ChineseNewYear=", 15, ncny); 140 REPLACE("NewMoon=", 8, nnewmoon); 141 REPLACE("FullMoon=", 9, nfullmoon); 142 REPLACE("MarEquinox=", 11, nmarequinox); 143 REPLACE("SepEquinox=", 11, nsepequinox); 144 REPLACE("JunSolstice=", 12, njunsolstice); 145 REPLACE("DecSolstice=", 12, ndecsolstice); 146 if (strncmp(buf, "SEQUENCE=", 9) == 0) { 147 setnsequences(buf + 9); |
145 continue; 146 } | 148 continue; 149 } |
147 if (strncasecmp(buf, "Paskha=", 7) == 0 && buf[7]) { 148 if (npaskha.name != NULL) 149 free(npaskha.name); 150 if ((npaskha.name = strdup(buf + 7)) == NULL) 151 errx(1, "cannot allocate memory"); 152 npaskha.len = strlen(buf + 7); 153 continue; 154 } 155 if (buf[0] != '\t') { 156 printing = isnow(buf, &month, &day, &var) ? 1 : 0; 157 if ((p = strchr(buf, '\t')) == NULL) 158 continue; 159 if (p > buf && p[-1] == '*') 160 var = 1; 161 if (printing) { 162 struct tm tm; 163 char dbuf[80]; | |
164 | 150 |
165 if (d_first < 0) 166 d_first = 167 (*nl_langinfo(D_MD_ORDER) == 'd'); 168 tm.tm_sec = 0; /* unused */ 169 tm.tm_min = 0; /* unused */ 170 tm.tm_hour = 0; /* unused */ 171 tm.tm_wday = 0; /* unused */ 172 tm.tm_mon = month - 1; 173 tm.tm_mday = day; 174 tm.tm_year = tp->tm_year; /* unused */ 175 (void)strftime(dbuf, sizeof(dbuf), 176 d_first ? "%e %b" : "%b %e", &tm); 177 events = event_add(events, month, day, dbuf, 178 var, p); 179 } 180 } else { 181 if (printing) 182 event_continue(events, buf); 183 } 184 } 185 186 event_print_all(fp, events); 187 closecal(fp); 188} 189 190static struct event * 191event_add(struct event *events, int month, int day, 192 char *date, int var, char *txt) 193{ 194 struct event *e; 195 196 /* 197 * Creating a new event: 198 * - Create a new event 199 * - Copy the machine readable day and month 200 * - Copy the human readable and language specific date 201 * - Copy the text of the event 202 */ 203 e = (struct event *)calloc(1, sizeof(struct event)); 204 if (e == NULL) 205 errx(1, "event_add: cannot allocate memory"); 206 e->month = month; 207 e->day = day; 208 e->var = var; 209 e->date = strdup(date); 210 if (e->date == NULL) 211 errx(1, "event_add: cannot allocate memory"); 212 e->text = strdup(txt); 213 if (e->text == NULL) 214 errx(1, "event_add: cannot allocate memory"); 215 e->next = events; 216 217 return e; 218} 219 220static void 221event_continue(struct event *e, char *txt) 222{ 223 char *text; 224 225 /* 226 * Adding text to the event: 227 * - Save a copy of the old text (unknown length, so strdup()) 228 * - Allocate enough space for old text + \n + new text + 0 229 * - Store the old text + \n + new text 230 * - Destroy the saved copy. 231 */ 232 text = strdup(e->text); 233 if (text == NULL) 234 errx(1, "event_continue: cannot allocate memory"); 235 236 free(e->text); 237 e->text = (char *)malloc(strlen(text) + strlen(txt) + 3); 238 if (e->text == NULL) 239 errx(1, "event_continue: cannot allocate memory"); 240 strcpy(e->text, text); 241 strcat(e->text, "\n"); 242 strcat(e->text, txt); 243 free(text); 244 245 return; 246} 247 248static void 249event_print_all(FILE *fp, struct event *events) 250{ 251 struct event *e, *e_next; 252 int daycounter; 253 int day, month; 254 255 /* 256 * Print all events: 257 * - We know the number of days to be counted (f_dayAfter + f_dayBefore) 258 * - We know the current day of the year ("now" - f_dayBefore + counter) 259 * - We know the number of days in the year (yrdays, set in settime()) 260 * - So we know the date on which the current daycounter is on the 261 * calendar in days and months. 262 * - Go through the list of events, and print all matching dates 263 */ 264 for (daycounter = 0; daycounter <= f_dayAfter + f_dayBefore; 265 daycounter++) { 266 day = tp->tm_yday - f_dayBefore + daycounter; 267 if (day < 0) 268 day += yrdays; 269 if (day >= yrdays) 270 day -= yrdays; 271 | |
272 /* | 151 /* |
273 * When we know the day of the year, we can determine the day 274 * of the month and the month. | 152 * If the line starts with a tab, the data has to be 153 * added to the previous line |
275 */ | 154 */ |
276 month = 1; 277 while (month <= 12) { 278 if (day <= cumdays[month]) 279 break; 280 month++; | 155 if (buf[0] == '\t') { 156 for (i = 0; i < count; i++) 157 event_continue(events[i], buf); 158 continue; |
281 } | 159 } |
282 month--; 283 day -= cumdays[month]; | |
284 | 160 |
285#ifdef DEBUG 286 fprintf(stderr, "event_print_allmonth: %d, day: %d\n", 287 month, day); 288#endif | 161 /* Get rid of leading spaces (non-standard) */ 162 while (isspace(buf[0])) 163 memcpy(buf, buf + 1, strlen(buf) - 1); |
289 | 164 |
290 /* 291 * Go through all events and print the text of the matching 292 * dates 293 */ 294 for (e = events; e != NULL; e = e_next) { 295 e_next = e->next; | 165 /* No tab in the line, then not a valid line */ 166 if ((pp = strchr(buf, '\t')) == NULL) 167 continue; |
296 | 168 |
297 if (month != e->month || day != e->day) 298 continue; | 169 /* Trim spaces in front of the tab */ 170 while (isspace(pp[-1])) 171 pp--; |
299 | 172 |
300 (void)fprintf(fp, "%s%c%s\n", e->date, 301 e->var ? '*' : ' ', e->text); | 173 p = *pp; 174 *pp = '\0'; 175 if ((count = parsedaymonth(buf, year, month, day, &flags, 176 extradata)) == 0) 177 continue; 178 *pp = p; 179 if (count < 0) { 180 /* Show error status based on return value */ 181 fprintf(stderr, "Ignored: %s\n", buf); 182 if (count == -1) 183 continue; 184 count = -count + 1; |
302 } | 185 } |
303 } 304} | |
305 | 186 |
306int 307getfield(char *p, char **endp, int *flags) 308{ 309 int val, var; 310 char *start, savech; | 187 /* Find the last tab */ 188 while (pp[1] == '\t') 189 pp++; |
311 | 190 |
312 for (; !isdigit((unsigned char)*p) && !isalpha((unsigned char)*p) 313 && *p != '*'; ++p) 314 ; 315 if (*p == '*') { /* `*' is current month */ 316 *flags |= F_ISMONTH; 317 *endp = p + 1; 318 return (tp->tm_mon + 1); 319 } 320 if (isdigit((unsigned char)*p)) { 321 val = strtol(p, &p, 10); /* if 0, it's failure */ 322 for (; !isdigit((unsigned char)*p) 323 && !isalpha((unsigned char)*p) && *p != '*'; ++p); 324 *endp = p; 325 return (val); 326 } 327 for (start = p; isalpha((unsigned char)*++p);); | 191 if (d_first < 0) 192 d_first = (*nl_langinfo(D_MD_ORDER) == 'd'); |
328 | 193 |
329 /* Sunday-1 */ 330 if (*p == '+' || *p == '-') 331 for(; isdigit((unsigned char)*++p);) 332 ; 333 334 savech = *p; 335 *p = '\0'; 336 337 /* Month */ 338 if ((val = getmonth(start)) != 0) 339 *flags |= F_ISMONTH; 340 341 /* Day */ 342 else if ((val = getday(start)) != 0) { 343 *flags |= F_ISDAY; 344 345 /* variable weekday */ 346 if ((var = getdayvar(start)) != 0) { 347 if (var <= 5 && var >= -4) 348 val += var * 10; 349#ifdef DEBUG 350 printf("var: %d\n", var); 351#endif | 194 for (i = 0; i < count; i++) { 195 tm.tm_mon = month[i] - 1; 196 tm.tm_mday = day[i]; 197 tm.tm_year = year[i] - 1900; 198 (void)strftime(dbuf, sizeof(dbuf), 199 d_first ? "%e %b" : "%b %e", &tm); 200 if (debug) 201 fprintf(stderr, "got %s\n", pp); 202 events[i] = event_add(year[i], month[i], day[i], dbuf, 203 ((flags &= F_VARIABLE) != 0) ? 1 : 0, pp, 204 extradata[i]); |
352 } 353 } 354 | 205 } 206 } 207 |
355 /* Easter */ 356 else if ((val = geteaster(start, tp->tm_year + 1900)) != 0) 357 *flags |= F_EASTER; 358 359 /* Paskha */ 360 else if ((val = getpaskha(start, tp->tm_year + 1900)) != 0) 361 *flags |= F_EASTER; 362 363 /* undefined rest */ 364 else { 365 *p = savech; 366 return (0); 367 } 368 for (*p = savech; !isdigit((unsigned char)*p) 369 && !isalpha((unsigned char)*p) && *p != '*'; ++p) 370 ; 371 *endp = p; 372 return (val); | 208 event_print_all(fp); 209 closecal(fp); |
373} 374 375FILE * 376opencal(void) 377{ 378 uid_t uid; 379 size_t i; 380 int fd, found, pdes[2]; --- 119 unchanged lines hidden (view full) --- 500 execl(_PATH_SENDMAIL, "sendmail", "-i", "-t", "-F", 501 "\"Reminder Service\"", (char *)NULL); 502 warn(_PATH_SENDMAIL); 503 _exit(1); 504 } 505 /* parent -- write to pipe input */ 506 (void)close(pdes[0]); 507 | 210} 211 212FILE * 213opencal(void) 214{ 215 uid_t uid; 216 size_t i; 217 int fd, found, pdes[2]; --- 119 unchanged lines hidden (view full) --- 337 execl(_PATH_SENDMAIL, "sendmail", "-i", "-t", "-F", 338 "\"Reminder Service\"", (char *)NULL); 339 warn(_PATH_SENDMAIL); 340 _exit(1); 341 } 342 /* parent -- write to pipe input */ 343 (void)close(pdes[0]); 344 |
508 header[1].iov_base = header[3].iov_base = pw->pw_name; 509 header[1].iov_len = header[3].iov_len = strlen(pw->pw_name); 510 writev(pdes[1], header, 7); | 345 write(pdes[1], "From: \"Reminder Service\" <", 26); 346 write(pdes[1], pw->pw_name, strlen(pw->pw_name)); 347 write(pdes[1], ">\nTo: <", 7); 348 write(pdes[1], pw->pw_name, strlen(pw->pw_name)); 349 write(pdes[1], ">\nSubject: ", 12); 350 write(pdes[1], dayname, strlen(dayname)); 351 write(pdes[1], "'s Calendar\nPrecedence: bulk\n\n", 30); 352 |
511 while ((nread = read(fileno(fp), buf, sizeof(buf))) > 0) 512 (void)write(pdes[1], buf, nread); 513 (void)close(pdes[1]); 514done: (void)fclose(fp); 515 (void)unlink(path); 516 while (wait(&status) >= 0); 517} | 353 while ((nread = read(fileno(fp), buf, sizeof(buf))) > 0) 354 (void)write(pdes[1], buf, nread); 355 (void)close(pdes[1]); 356done: (void)fclose(fp); 357 (void)unlink(path); 358 while (wait(&status) >= 0); 359} |