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