|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1989 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms are permitted ! 6: * provided that: (1) source distributions retain this entire copyright ! 7: * notice and comment, and (2) distributions including binaries display ! 8: * the following acknowledgement: ``This product includes software ! 9: * developed by the University of California, Berkeley and its contributors'' ! 10: * in the documentation or other materials provided with the distribution ! 11: * and in all advertising materials mentioning features or use of this ! 12: * software. Neither the name of the University nor the names of its ! 13: * contributors may be used to endorse or promote products derived ! 14: * from this software without specific prior written permission. ! 15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 16: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 18: */ ! 19: ! 20: #ifndef lint ! 21: char copyright[] = ! 22: "@(#) Copyright (c) 1989 The Regents of the University of California.\n\ ! 23: All rights reserved.\n"; ! 24: #endif /* not lint */ ! 25: ! 26: #ifndef lint ! 27: static char sccsid[] = "@(#)calendar.c 4.10 (Berkeley) 6/1/90"; ! 28: #endif /* not lint */ ! 29: ! 30: #include <sys/param.h> ! 31: #include <sys/time.h> ! 32: #include <sys/stat.h> ! 33: #include <sys/file.h> ! 34: #include <sys/uio.h> ! 35: #include <pwd.h> ! 36: #include <errno.h> ! 37: #include <tzfile.h> ! 38: #include <stdio.h> ! 39: #include <ctype.h> ! 40: #include <unistd.h> ! 41: #include <string.h> ! 42: #include "pathnames.h" ! 43: ! 44: extern int errno; ! 45: struct passwd *pw; ! 46: int doall; ! 47: ! 48: main(argc, argv) ! 49: int argc; ! 50: char **argv; ! 51: { ! 52: extern int optind; ! 53: int ch; ! 54: ! 55: while ((ch = getopt(argc, argv, "-a")) != EOF) ! 56: switch(ch) { ! 57: case '-': /* backward contemptible */ ! 58: case 'a': ! 59: if (getuid()) { ! 60: (void)fprintf(stderr, ! 61: "calendar: %s\n", strerror(EPERM)); ! 62: exit(1); ! 63: } ! 64: doall = 1; ! 65: break; ! 66: case '?': ! 67: default: ! 68: usage(); ! 69: } ! 70: argc -= optind; ! 71: argv += optind; ! 72: ! 73: if (argc) ! 74: usage(); ! 75: ! 76: settime(); ! 77: if (doall) ! 78: while (pw = getpwent()) { ! 79: (void)setegid(pw->pw_gid); ! 80: (void)seteuid(pw->pw_uid); ! 81: if (!chdir(pw->pw_dir)) ! 82: cal(); ! 83: (void)seteuid(0); ! 84: } ! 85: else ! 86: cal(); ! 87: exit(0); ! 88: } ! 89: ! 90: cal() ! 91: { ! 92: register int printing; ! 93: register char *p; ! 94: FILE *fp, *opencal(); ! 95: int ch; ! 96: char buf[2048 + 1]; ! 97: ! 98: if (!(fp = opencal())) ! 99: return; ! 100: for (printing = 0; fgets(buf, sizeof(buf), stdin);) { ! 101: if (p = index(buf, '\n')) ! 102: *p = '\0'; ! 103: else ! 104: while ((ch = getchar()) != '\n' && ch != EOF); ! 105: if (buf[0] == '\0') ! 106: continue; ! 107: if (buf[0] != '\t') ! 108: printing = isnow(buf) ? 1 : 0; ! 109: if (printing) ! 110: (void)fprintf(fp, "%s\n", buf); ! 111: } ! 112: closecal(fp); ! 113: } ! 114: ! 115: struct iovec header[] = { ! 116: "From: ", 6, ! 117: NULL, 0, ! 118: " (Reminder Service)\nTo: ", 24, ! 119: NULL, 0, ! 120: "\nSubject: ", 10, ! 121: NULL, 0, ! 122: "'s Calendar\nPrecedence: bulk\n\n", 30, ! 123: }; ! 124: ! 125: /* 1-based month, 0-based days, cumulative */ ! 126: int daytab[][14] = { ! 127: 0, 0, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364, ! 128: 0, 0, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365, ! 129: }; ! 130: struct tm *tp; ! 131: int *cumdays, offset, yrdays; ! 132: char dayname[10]; ! 133: ! 134: settime() ! 135: { ! 136: time_t now, time(); ! 137: ! 138: (void)time(&now); ! 139: tp = localtime(&now); ! 140: if (isleap(tp->tm_year + 1900)) { ! 141: yrdays = DAYSPERLYEAR; ! 142: cumdays = daytab[1]; ! 143: } else { ! 144: yrdays = DAYSPERNYEAR; ! 145: cumdays = daytab[0]; ! 146: } ! 147: /* Friday displays Monday's events */ ! 148: offset = tp->tm_wday == 6 ? 3 : 1; ! 149: header[5].iov_base = dayname; ! 150: header[5].iov_len = strftime(dayname, sizeof(dayname), "%A", tp); ! 151: } ! 152: ! 153: /* ! 154: * Possible date formats include any combination of: ! 155: * 3-charmonth (January, Jan, Jan) ! 156: * 3-charweekday (Friday, Monday, mon.) ! 157: * numeric month or day (1, 2, 04) ! 158: * ! 159: * Any character may separate them, or they may not be separated. Any line, ! 160: * following a line that is matched, that starts with "whitespace", is shown ! 161: * along with the matched line. ! 162: */ ! 163: isnow(endp) ! 164: char *endp; ! 165: { ! 166: int day, flags, month, v1, v2; ! 167: ! 168: #define F_ISMONTH 0x01 ! 169: #define F_ISDAY 0x02 ! 170: flags = 0; ! 171: /* didn't recognize anything, skip it */ ! 172: if (!(v1 = getfield(endp, &endp, &flags))) ! 173: return(0); ! 174: if (flags&F_ISDAY || v1 > 12) { ! 175: /* found a day */ ! 176: day = v1; ! 177: /* if no recognizable month, assume just a day alone */ ! 178: if (!(month = getfield(endp, &endp, &flags))) ! 179: month = tp->tm_mon; ! 180: } else if (flags&F_ISMONTH) { ! 181: month = v1; ! 182: /* if no recognizable day, assume the first */ ! 183: if (!(day = getfield(endp, &endp, &flags))) ! 184: day = 1; ! 185: } else { ! 186: v2 = getfield(endp, &endp, &flags); ! 187: if (flags&F_ISMONTH) { ! 188: day = v1; ! 189: month = v2; ! 190: } else { ! 191: /* F_ISDAY set, v2 > 12, or no way to tell */ ! 192: month = v1; ! 193: /* if no recognizable day, assume the first */ ! 194: day = v2 ? v2 : 1; ! 195: } ! 196: } ! 197: day = cumdays[month] + day; ! 198: ! 199: /* if today or today + offset days */ ! 200: if (day >= tp->tm_yday && day <= tp->tm_yday + offset) ! 201: return(1); ! 202: /* if number of days left in this year + days to event in next year */ ! 203: if (yrdays - tp->tm_yday + day <= offset) ! 204: return(1); ! 205: return(0); ! 206: } ! 207: ! 208: getfield(p, endp, flags) ! 209: char *p, **endp; ! 210: int *flags; ! 211: { ! 212: int val; ! 213: char *start, savech; ! 214: ! 215: if (*p == '*') { /* `*' is current month */ ! 216: *flags |= F_ISMONTH; ! 217: return(tp->tm_mon); ! 218: } ! 219: if (isdigit(*p)) { ! 220: val = strtol(p, &p, 10); /* if 0, it's failure */ ! 221: for (; !isdigit(*p) && !isalpha(*p); ++p); ! 222: *endp = p; ! 223: return(val); ! 224: } ! 225: for (start = p; isalpha(*++p);); ! 226: savech = *p; ! 227: *p = '\0'; ! 228: if (val = getmonth(start)) ! 229: *flags |= F_ISMONTH; ! 230: else if (val = getday(start)) ! 231: *flags |= F_ISDAY; ! 232: else ! 233: return(0); ! 234: for (*p = savech; !isdigit(*p) && !isalpha(*p); ++p); ! 235: *endp = p; ! 236: return(val); ! 237: } ! 238: ! 239: char path[MAXPATHLEN + 1]; ! 240: ! 241: FILE * ! 242: opencal() ! 243: { ! 244: int fd, pdes[2]; ! 245: char *mktemp(); ! 246: ! 247: /* open up calendar file as stdin */ ! 248: if (!freopen("calendar", "r", stdin)) { ! 249: if (doall) ! 250: return((FILE *)NULL); ! 251: (void)fprintf(stderr, "calendar: no calendar file.\n"); ! 252: exit(1); ! 253: } ! 254: if (pipe(pdes) < 0) ! 255: return(NULL); ! 256: switch (vfork()) { ! 257: case -1: /* error */ ! 258: (void)close(pdes[0]); ! 259: (void)close(pdes[1]); ! 260: return(NULL); ! 261: case 0: ! 262: /* child -- stdin already setup, set stdout to pipe input */ ! 263: if (pdes[1] != STDOUT_FILENO) { ! 264: (void)dup2(pdes[1], STDOUT_FILENO); ! 265: (void)close(pdes[1]); ! 266: } ! 267: (void)close(pdes[0]); ! 268: execl(_PATH_CPP, "cpp", "-I.", _PATH_INCLUDE, NULL); ! 269: _exit(1); ! 270: } ! 271: /* parent -- set stdin to pipe output */ ! 272: (void)dup2(pdes[0], STDIN_FILENO); ! 273: (void)close(pdes[0]); ! 274: (void)close(pdes[1]); ! 275: ! 276: /* not reading all calendar files, just set output to stdout */ ! 277: if (!doall) ! 278: return(stdout); ! 279: ! 280: /* set output to a temporary file, so if no output don't send mail */ ! 281: (void)sprintf(path, "%s/_calXXXXXX", _PATH_TMP); ! 282: if ((fd = mkstemp(path)) < 0) ! 283: return(NULL); ! 284: return(fdopen(fd, "w+")); ! 285: } ! 286: ! 287: closecal(fp) ! 288: FILE *fp; ! 289: { ! 290: struct stat sbuf; ! 291: int nread, pdes[2], status; ! 292: char buf[1024], *mktemp(); ! 293: ! 294: if (!doall) ! 295: return; ! 296: ! 297: (void)rewind(fp); ! 298: if (fstat(fileno(fp), &sbuf) || !sbuf.st_size) ! 299: goto done; ! 300: if (pipe(pdes) < 0) ! 301: goto done; ! 302: switch (vfork()) { ! 303: case -1: /* error */ ! 304: (void)close(pdes[0]); ! 305: (void)close(pdes[1]); ! 306: goto done; ! 307: case 0: ! 308: /* child -- set stdin to pipe output */ ! 309: if (pdes[0] != STDIN_FILENO) { ! 310: (void)dup2(pdes[0], STDIN_FILENO); ! 311: (void)close(pdes[0]); ! 312: } ! 313: (void)close(pdes[1]); ! 314: execl(_PATH_SENDMAIL, "sendmail", "-i", "-t", "-F", ! 315: "\"Reminder Service\"", "-f", "root", NULL); ! 316: (void)fprintf(stderr, "calendar: %s: %s.\n", ! 317: _PATH_SENDMAIL, strerror(errno)); ! 318: _exit(1); ! 319: } ! 320: /* parent -- write to pipe input */ ! 321: (void)close(pdes[0]); ! 322: ! 323: header[1].iov_base = header[3].iov_base = pw->pw_name; ! 324: header[1].iov_len = header[3].iov_len = strlen(pw->pw_name); ! 325: writev(pdes[1], header, 7); ! 326: while ((nread = read(fileno(fp), buf, sizeof(buf))) > 0) ! 327: (void)write(pdes[1], buf, nread); ! 328: (void)close(pdes[1]); ! 329: done: (void)fclose(fp); ! 330: (void)unlink(path); ! 331: while (wait(&status) >= 0); ! 332: } ! 333: ! 334: static char *months[] = { ! 335: "jan", "feb", "mar", "apr", "may", "jun", ! 336: "jul", "aug", "sep", "oct", "nov", "dec", NULL, ! 337: }; ! 338: getmonth(s) ! 339: register char *s; ! 340: { ! 341: register char **p; ! 342: ! 343: for (p = months; *p; ++p) ! 344: if (!strncasecmp(s, *p, 3)) ! 345: return((p - months) + 1); ! 346: return(0); ! 347: } ! 348: ! 349: static char *days[] = { ! 350: "sun", "mon", "tue", "wed", "thu", "fri", "sat", NULL, ! 351: }; ! 352: getday(s) ! 353: register char *s; ! 354: { ! 355: register char **p; ! 356: ! 357: for (p = days; *p; ++p) ! 358: if (!strncasecmp(s, *p, 3)) ! 359: return((p - days) + 1); ! 360: return(0); ! 361: } ! 362: ! 363: usage() ! 364: { ! 365: (void)fprintf(stderr, "usage: calendar [-a]\n"); ! 366: exit(1); ! 367: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.