io.c revision 13840
113840Swosch/* 213840Swosch * Copyright (c) 1989, 1993, 1994 313840Swosch * The Regents of the University of California. All rights reserved. 413840Swosch * 513840Swosch * Redistribution and use in source and binary forms, with or without 613840Swosch * modification, are permitted provided that the following conditions 713840Swosch * are met: 813840Swosch * 1. Redistributions of source code must retain the above copyright 913840Swosch * notice, this list of conditions and the following disclaimer. 1013840Swosch * 2. Redistributions in binary form must reproduce the above copyright 1113840Swosch * notice, this list of conditions and the following disclaimer in the 1213840Swosch * documentation and/or other materials provided with the distribution. 1313840Swosch * 3. All advertising materials mentioning features or use of this software 1413840Swosch * must display the following acknowledgement: 1513840Swosch * This product includes software developed by the University of 1613840Swosch * California, Berkeley and its contributors. 1713840Swosch * 4. Neither the name of the University nor the names of its contributors 1813840Swosch * may be used to endorse or promote products derived from this software 1913840Swosch * without specific prior written permission. 2013840Swosch * 2113840Swosch * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2213840Swosch * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2313840Swosch * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2413840Swosch * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2513840Swosch * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2613840Swosch * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2713840Swosch * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2813840Swosch * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2913840Swosch * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3013840Swosch * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3113840Swosch * SUCH DAMAGE. 3213840Swosch */ 3313840Swosch 3413840Swosch#ifndef lint 3513840Swoschstatic char copyright[] = 3613840Swosch"@(#) Copyright (c) 1989, 1993\n\ 3713840Swosch The Regents of the University of California. All rights reserved.\n"; 3813840Swosch#endif /* not lint */ 3913840Swosch 4013840Swosch#ifndef lint 4113840Swoschstatic char sccsid[] = "@(#)calendar.c 8.3 (Berkeley) 3/25/94"; 4213840Swosch#endif /* not lint */ 4313840Swosch 4413840Swosch#include <sys/param.h> 4513840Swosch#include <stdio.h> 4613840Swosch#include <ctype.h> 4713840Swosch#include <sys/types.h> 4813840Swosch#include <sys/stat.h> 4913840Swosch#include <unistd.h> 5013840Swosch#include <err.h> 5113840Swosch#include <errno.h> 5213840Swosch#include <string.h> 5313840Swosch#include <sys/uio.h> 5413840Swosch#include <sys/time.h> 5513840Swosch#include <stdlib.h> 5613840Swosch#include <pwd.h> 5713840Swosch#include <sys/wait.h> 5813840Swosch 5913840Swosch#include "pathnames.h" 6013840Swosch#include "calendar.h" 6113840Swosch 6213840Swosch 6313840Swoschchar *calendarFile = "calendar"; /* default calendar file */ 6413840Swoschchar *calendarHome = ".calendar"; /* HOME */ 6513840Swoschchar *calendarNoMail = "nomail"; /* don't sent mail if this file exist */ 6613840Swosch 6713840Swoschstruct iovec header[] = { 6813840Swosch "From: ", 6, 6913840Swosch NULL, 0, 7013840Swosch " (Reminder Service)\nTo: ", 24, 7113840Swosch NULL, 0, 7213840Swosch "\nSubject: ", 10, 7313840Swosch NULL, 0, 7413840Swosch "'s Calendar\nPrecedence: bulk\n\n", 30, 7513840Swosch}; 7613840Swosch 7713840Swosch 7813840Swoschvoid 7913840Swoschcal() 8013840Swosch{ 8113840Swosch register int printing; 8213840Swosch register char *p; 8313840Swosch FILE *fp; 8413840Swosch int ch; 8513840Swosch char buf[2048 + 1]; 8613840Swosch 8713840Swosch if ((fp = opencal()) == NULL) 8813840Swosch return; 8913840Swosch for (printing = 0; fgets(buf, sizeof(buf), stdin) != NULL;) { 9013840Swosch if ((p = strchr(buf, '\n')) != NULL) 9113840Swosch *p = '\0'; 9213840Swosch else 9313840Swosch while ((ch = getchar()) != '\n' && ch != EOF); 9413840Swosch if (buf[0] == '\0') 9513840Swosch continue; 9613840Swosch if (buf[0] != '\t') 9713840Swosch printing = isnow(buf) ? 1 : 0; 9813840Swosch if (printing) 9913840Swosch (void)fprintf(fp, "%s\n", buf); 10013840Swosch } 10113840Swosch closecal(fp); 10213840Swosch} 10313840Swosch 10413840Swoschint 10513840Swoschgetfield(p, endp, flags) 10613840Swosch char *p, **endp; 10713840Swosch int *flags; 10813840Swosch{ 10913840Swosch int val, var; 11013840Swosch char *start, savech; 11113840Swosch 11213840Swosch for (; !isdigit(*p) && !isalpha(*p) && *p != '*'; ++p); 11313840Swosch if (*p == '*') { /* `*' is current month */ 11413840Swosch *flags |= F_ISMONTH; 11513840Swosch *endp = p+1; 11613840Swosch return (tp->tm_mon + 1); 11713840Swosch } 11813840Swosch if (isdigit(*p)) { 11913840Swosch val = strtol(p, &p, 10); /* if 0, it's failure */ 12013840Swosch for (; !isdigit(*p) && !isalpha(*p) && *p != '*'; ++p); 12113840Swosch *endp = p; 12213840Swosch return (val); 12313840Swosch } 12413840Swosch for (start = p; isalpha(*++p);); 12513840Swosch 12613840Swosch /* Sunday-1 */ 12713840Swosch if (*p == '+' || *p == '-') 12813840Swosch for(; isdigit(*++p);); 12913840Swosch 13013840Swosch savech = *p; 13113840Swosch *p = '\0'; 13213840Swosch 13313840Swosch /* Month */ 13413840Swosch if ((val = getmonth(start)) != 0) 13513840Swosch *flags |= F_ISMONTH; 13613840Swosch 13713840Swosch /* Day */ 13813840Swosch else if ((val = getday(start)) != 0) { 13913840Swosch *flags |= F_ISDAY; 14013840Swosch 14113840Swosch /* variable weekday */ 14213840Swosch if ((var = getdayvar(start)) != 0) { 14313840Swosch if (var <=5 && var >= -4) 14413840Swosch val += var * 10; 14513840Swosch#ifdef DEBUG 14613840Swosch printf("var: %d\n", var); 14713840Swosch#endif 14813840Swosch } 14913840Swosch } 15013840Swosch 15113840Swosch /* Easter */ 15213840Swosch else if ((val = geteaster(start, tp->tm_year + 1900)) != 0) 15313840Swosch *flags |= F_EASTER; 15413840Swosch 15513840Swosch /* undefined rest */ 15613840Swosch else { 15713840Swosch *p = savech; 15813840Swosch return (0); 15913840Swosch } 16013840Swosch for (*p = savech; !isdigit(*p) && !isalpha(*p) && *p != '*'; ++p); 16113840Swosch *endp = p; 16213840Swosch return (val); 16313840Swosch} 16413840Swosch 16513840Swoschchar path[MAXPATHLEN + 1]; 16613840Swosch 16713840SwoschFILE * 16813840Swoschopencal() 16913840Swosch{ 17013840Swosch int fd, pdes[2]; 17113840Swosch struct stat sbuf; 17213840Swosch 17313840Swosch /* open up calendar file as stdin */ 17413840Swosch if (!freopen(calendarFile, "r", stdin)) { 17513840Swosch if (doall) { 17613840Swosch if (chdir(calendarHome) != 0) 17713840Swosch return (NULL); 17813840Swosch if (stat(calendarNoMail, &sbuf) == 0) 17913840Swosch return (NULL); 18013840Swosch if (!freopen(calendarFile, "r", stdin)) 18113840Swosch return (NULL); 18213840Swosch } else { 18313840Swosch chdir(getenv("HOME")); 18413840Swosch if (!(chdir(calendarHome) == 0 && 18513840Swosch freopen(calendarFile, "r", stdin))) 18613840Swosch errx(1, "no calendar file: ``%s'' or ``~/%s/%s\n", calendarFile, calendarHome, calendarFile); 18713840Swosch } 18813840Swosch } 18913840Swosch if (pipe(pdes) < 0) 19013840Swosch return (NULL); 19113840Swosch switch (vfork()) { 19213840Swosch case -1: /* error */ 19313840Swosch (void)close(pdes[0]); 19413840Swosch (void)close(pdes[1]); 19513840Swosch return (NULL); 19613840Swosch case 0: 19713840Swosch /* child -- stdin already setup, set stdout to pipe input */ 19813840Swosch if (pdes[1] != STDOUT_FILENO) { 19913840Swosch (void)dup2(pdes[1], STDOUT_FILENO); 20013840Swosch (void)close(pdes[1]); 20113840Swosch } 20213840Swosch (void)close(pdes[0]); 20313840Swosch execl(_PATH_CPP, "cpp", "-P", "-I.", _PATH_INCLUDE, NULL); 20413840Swosch (void)fprintf(stderr, 20513840Swosch "calendar: execl: %s: %s.\n", _PATH_CPP, strerror(errno)); 20613840Swosch _exit(1); 20713840Swosch } 20813840Swosch /* parent -- set stdin to pipe output */ 20913840Swosch (void)dup2(pdes[0], STDIN_FILENO); 21013840Swosch (void)close(pdes[0]); 21113840Swosch (void)close(pdes[1]); 21213840Swosch 21313840Swosch /* not reading all calendar files, just set output to stdout */ 21413840Swosch if (!doall) 21513840Swosch return (stdout); 21613840Swosch 21713840Swosch /* set output to a temporary file, so if no output don't send mail */ 21813840Swosch (void)snprintf(path, sizeof(path), "%s/_calXXXXXX", _PATH_TMP); 21913840Swosch if ((fd = mkstemp(path)) < 0) 22013840Swosch return (NULL); 22113840Swosch return (fdopen(fd, "w+")); 22213840Swosch} 22313840Swosch 22413840Swoschvoid 22513840Swoschclosecal(fp) 22613840Swosch FILE *fp; 22713840Swosch{ 22813840Swosch struct stat sbuf; 22913840Swosch int nread, pdes[2], status; 23013840Swosch char buf[1024]; 23113840Swosch 23213840Swosch if (!doall) 23313840Swosch return; 23413840Swosch 23513840Swosch (void)rewind(fp); 23613840Swosch if (fstat(fileno(fp), &sbuf) || !sbuf.st_size) 23713840Swosch goto done; 23813840Swosch if (pipe(pdes) < 0) 23913840Swosch goto done; 24013840Swosch switch (vfork()) { 24113840Swosch case -1: /* error */ 24213840Swosch (void)close(pdes[0]); 24313840Swosch (void)close(pdes[1]); 24413840Swosch goto done; 24513840Swosch case 0: 24613840Swosch /* child -- set stdin to pipe output */ 24713840Swosch if (pdes[0] != STDIN_FILENO) { 24813840Swosch (void)dup2(pdes[0], STDIN_FILENO); 24913840Swosch (void)close(pdes[0]); 25013840Swosch } 25113840Swosch (void)close(pdes[1]); 25213840Swosch execl(_PATH_SENDMAIL, "sendmail", "-i", "-t", "-F", 25313840Swosch "\"Reminder Service\"", "-f", "root", NULL); 25413840Swosch (void)fprintf(stderr, 25513840Swosch "calendar: %s: %s.\n", _PATH_SENDMAIL, strerror(errno)); 25613840Swosch _exit(1); 25713840Swosch } 25813840Swosch /* parent -- write to pipe input */ 25913840Swosch (void)close(pdes[0]); 26013840Swosch 26113840Swosch header[1].iov_base = header[3].iov_base = pw->pw_name; 26213840Swosch header[1].iov_len = header[3].iov_len = strlen(pw->pw_name); 26313840Swosch writev(pdes[1], header, 7); 26413840Swosch while ((nread = read(fileno(fp), buf, sizeof(buf))) > 0) 26513840Swosch (void)write(pdes[1], buf, nread); 26613840Swosch (void)close(pdes[1]); 26713840Swoschdone: (void)fclose(fp); 26813840Swosch (void)unlink(path); 26913840Swosch while (wait(&status) >= 0); 27013840Swosch} 27113840Swosch 272