io.c revision 15714
1272343Sngie/* 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. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#ifndef lint 35static const char copyright[] = 36"@(#) Copyright (c) 1989, 1993\n\ 37 The Regents of the University of California. All rights reserved.\n"; 38#endif /* not lint */ 39 40#ifndef lint 41static const char sccsid[] = "@(#)calendar.c 8.3 (Berkeley) 3/25/94"; 42#endif /* not lint */ 43 44#include <sys/param.h> 45#include <stdio.h> 46#include <ctype.h> 47#include <sys/types.h> 48#include <sys/stat.h> 49#include <unistd.h> 50#include <err.h> 51#include <errno.h> 52#include <locale.h> 53#include <string.h> 54#include <sys/uio.h> 55#include <sys/time.h> 56#include <stdlib.h> 57#include <pwd.h> 58#include <sys/wait.h> 59 60#include "pathnames.h" 61#include "calendar.h" 62 63 64char *calendarFile = "calendar"; /* default calendar file */ 65char *calendarHome = ".calendar"; /* HOME */ 66char *calendarNoMail = "nomail"; /* don't sent mail if this file exist */ 67 68struct iovec header[] = { 69 {"From: ", 6}, 70 {NULL, 0}, 71 {" (Reminder Service)\nTo: ", 24}, 72 {NULL, 0}, 73 {"\nSubject: ", 10}, 74 {NULL, 0}, 75 {"'s Calendar\nPrecedence: bulk\n\n", 30}, 76}; 77 78 79void 80cal() 81{ 82 register int printing; 83 register char *p; 84 FILE *fp; 85 int ch, l; 86 int month; 87 int day; 88 int var; 89 char buf[2048 + 1]; 90 91 if ((fp = opencal()) == NULL) 92 return; 93 for (printing = 0; fgets(buf, sizeof(buf), stdin) != NULL;) { 94 if ((p = strchr(buf, '\n')) != NULL) 95 *p = '\0'; 96 else 97 while ((ch = getchar()) != '\n' && ch != EOF); 98 for (l = strlen(buf); 99 l > 0 && isspace((unsigned char)buf[l - 1]); 100 l--) 101 ; 102 buf[l] = '\0'; 103 if (buf[0] == '\0') 104 continue; 105 if (strncmp(buf, "LANG=", 5) == 0) { 106 (void) setlocale(LC_ALL, buf + 5); 107 setnnames(); 108 continue; 109 } 110 if (buf[0] != '\t') { 111 printing = isnow(buf, &month, &day, &var) ? 1 : 0; 112 if ((p = strchr(buf, '\t')) == NULL) 113 continue; 114 if (p > buf && p[-1] == '*') 115 var = 1; 116 if (printing) 117 (void)fprintf(fp, "%.2d/%.2d%c%s\n", month, 118 day, var ? '*' : ' ', p); 119 } 120 else if (printing) 121 fprintf(fp, "%s\n", buf); 122 } 123 closecal(fp); 124} 125 126int 127getfield(p, endp, flags) 128 char *p, **endp; 129 int *flags; 130{ 131 int val, var; 132 char *start, savech; 133 134 for (; !isdigit((unsigned char)*p) && !isalpha((unsigned char)*p) && *p != '*'; ++p); 135 if (*p == '*') { /* `*' is current month */ 136 *flags |= F_ISMONTH; 137 *endp = p+1; 138 return (tp->tm_mon + 1); 139 } 140 if (isdigit((unsigned char)*p)) { 141 val = strtol(p, &p, 10); /* if 0, it's failure */ 142 for (; !isdigit((unsigned char)*p) && !isalpha((unsigned char)*p) && *p != '*'; ++p); 143 *endp = p; 144 return (val); 145 } 146 for (start = p; isalpha((unsigned char)*++p);); 147 148 /* Sunday-1 */ 149 if (*p == '+' || *p == '-') 150 for(; isdigit((unsigned char)*++p);); 151 152 savech = *p; 153 *p = '\0'; 154 155 /* Month */ 156 if ((val = getmonth(start)) != 0) 157 *flags |= F_ISMONTH; 158 159 /* Day */ 160 else if ((val = getday(start)) != 0) { 161 *flags |= F_ISDAY; 162 163 /* variable weekday */ 164 if ((var = getdayvar(start)) != 0) { 165 if (var <=5 && var >= -4) 166 val += var * 10; 167#ifdef DEBUG 168 printf("var: %d\n", var); 169#endif 170 } 171 } 172 173 /* Easter */ 174 else if ((val = geteaster(start, tp->tm_year + 1900)) != 0) 175 *flags |= F_EASTER; 176 177 /* Paskha */ 178 else if ((val = getpaskha(start, tp->tm_year + 1900)) != 0) 179 *flags |= F_EASTER; 180 181 /* undefined rest */ 182 else { 183 *p = savech; 184 return (0); 185 } 186 for (*p = savech; !isdigit((unsigned char)*p) && !isalpha((unsigned char)*p) && *p != '*'; ++p); 187 *endp = p; 188 return (val); 189} 190 191char path[MAXPATHLEN + 1]; 192 193FILE * 194opencal() 195{ 196 int fd, pdes[2]; 197 struct stat sbuf; 198 199 /* open up calendar file as stdin */ 200 if (!freopen(calendarFile, "r", stdin)) { 201 if (doall) { 202 if (chdir(calendarHome) != 0) 203 return (NULL); 204 if (stat(calendarNoMail, &sbuf) == 0) 205 return (NULL); 206 if (!freopen(calendarFile, "r", stdin)) 207 return (NULL); 208 } else { 209 chdir(getenv("HOME")); 210 if (!(chdir(calendarHome) == 0 && 211 freopen(calendarFile, "r", stdin))) 212 errx(1, "no calendar file: ``%s'' or ``~/%s/%s\n", calendarFile, calendarHome, calendarFile); 213 } 214 } 215 if (pipe(pdes) < 0) 216 return (NULL); 217 switch (vfork()) { 218 case -1: /* error */ 219 (void)close(pdes[0]); 220 (void)close(pdes[1]); 221 return (NULL); 222 case 0: 223 /* child -- stdin already setup, set stdout to pipe input */ 224 if (pdes[1] != STDOUT_FILENO) { 225 (void)dup2(pdes[1], STDOUT_FILENO); 226 (void)close(pdes[1]); 227 } 228 (void)close(pdes[0]); 229 execl(_PATH_CPP, "cpp", "-P", "-I.", _PATH_INCLUDE, NULL); 230 (void)fprintf(stderr, 231 "calendar: execl: %s: %s.\n", _PATH_CPP, strerror(errno)); 232 _exit(1); 233 } 234 /* parent -- set stdin to pipe output */ 235 (void)dup2(pdes[0], STDIN_FILENO); 236 (void)close(pdes[0]); 237 (void)close(pdes[1]); 238 239 /* not reading all calendar files, just set output to stdout */ 240 if (!doall) 241 return (stdout); 242 243 /* set output to a temporary file, so if no output don't send mail */ 244 (void)snprintf(path, sizeof(path), "%s/_calXXXXXX", _PATH_TMP); 245 if ((fd = mkstemp(path)) < 0) 246 return (NULL); 247 return (fdopen(fd, "w+")); 248} 249 250void 251closecal(fp) 252 FILE *fp; 253{ 254 struct stat sbuf; 255 int nread, pdes[2], status; 256 char buf[1024]; 257 258 if (!doall) 259 return; 260 261 (void)rewind(fp); 262 if (fstat(fileno(fp), &sbuf) || !sbuf.st_size) 263 goto done; 264 if (pipe(pdes) < 0) 265 goto done; 266 switch (vfork()) { 267 case -1: /* error */ 268 (void)close(pdes[0]); 269 (void)close(pdes[1]); 270 goto done; 271 case 0: 272 /* child -- set stdin to pipe output */ 273 if (pdes[0] != STDIN_FILENO) { 274 (void)dup2(pdes[0], STDIN_FILENO); 275 (void)close(pdes[0]); 276 } 277 (void)close(pdes[1]); 278 execl(_PATH_SENDMAIL, "sendmail", "-i", "-t", "-F", 279 "\"Reminder Service\"", "-f", "root", NULL); 280 (void)fprintf(stderr, 281 "calendar: %s: %s.\n", _PATH_SENDMAIL, strerror(errno)); 282 _exit(1); 283 } 284 /* parent -- write to pipe input */ 285 (void)close(pdes[0]); 286 287 header[1].iov_base = header[3].iov_base = pw->pw_name; 288 header[1].iov_len = header[3].iov_len = strlen(pw->pw_name); 289 writev(pdes[1], header, 7); 290 while ((nread = read(fileno(fp), buf, sizeof(buf))) > 0) 291 (void)write(pdes[1], buf, nread); 292 (void)close(pdes[1]); 293done: (void)fclose(fp); 294 (void)unlink(path); 295 while (wait(&status) >= 0); 296} 297 298