Annotation of src/usr.bin/calendar/calendar.c, Revision 1.15
1.15 ! pjanzen 1: /* $OpenBSD: calendar.c,v 1.14 2000/11/21 14:01:38 aaron Exp $ */
1.1 deraadt 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
1.5 millert 37: static const char copyright[] =
1.1 deraadt 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
1.5 millert 44: static const char sccsid[] = "@(#)calendar.c 8.3 (Berkeley) 3/25/94";
45: #else
1.15 ! pjanzen 46: static char rcsid[] = "$OpenBSD: calendar.c,v 1.14 2000/11/21 14:01:38 aaron Exp $";
1.1 deraadt 47: #endif
48: #endif /* not lint */
49:
1.15 ! pjanzen 50: #include <sys/stat.h>
! 51: #include <sys/types.h>
! 52: #include <sys/wait.h>
1.1 deraadt 53: #include <err.h>
54: #include <errno.h>
1.5 millert 55: #include <locale.h>
1.15 ! pjanzen 56: #include <login_cap.h>
1.1 deraadt 57: #include <pwd.h>
1.15 ! pjanzen 58: #include <signal.h>
1.1 deraadt 59: #include <stdio.h>
60: #include <stdlib.h>
61: #include <string.h>
1.5 millert 62: #include <time.h>
1.12 pjanzen 63: #include <tzfile.h>
1.1 deraadt 64: #include <unistd.h>
65:
66: #include "pathnames.h"
1.5 millert 67: #include "calendar.h"
1.1 deraadt 68:
1.15 ! pjanzen 69: char *calendarFile = "calendar"; /* default calendar file */
! 70: char *calendarHome = ".calendar"; /* HOME */
! 71: char *calendarNoMail = "nomail"; /* don't sent mail if this file exists */
! 72:
1.1 deraadt 73: struct passwd *pw;
1.5 millert 74: int doall = 0;
75: time_t f_time = 0;
1.1 deraadt 76:
1.5 millert 77: int f_dayAfter = 0; /* days after current date */
78: int f_dayBefore = 0; /* days before current date */
1.1 deraadt 79:
1.12 pjanzen 80: struct specialev spev[NUMEV];
81:
1.15 ! pjanzen 82: void childsig __P((int));
! 83:
1.1 deraadt 84: int
85: main(argc, argv)
86: int argc;
87: char *argv[];
88: {
1.15 ! pjanzen 89: int ch;
1.1 deraadt 90: char *caldir;
91:
1.12 pjanzen 92: (void)setlocale(LC_ALL, "");
1.5 millert 93:
1.7 deraadt 94: while ((ch = getopt(argc, argv, "-af:t:A:B:")) != -1)
1.1 deraadt 95: switch (ch) {
96: case '-': /* backward contemptible */
97: case 'a':
1.5 millert 98: if (getuid())
1.13 millert 99: errx(1, "%s", strerror(EPERM));
1.1 deraadt 100: doall = 1;
101: break;
1.5 millert 102:
103: case 'f': /* other calendar file */
104: calendarFile = optarg;
105: break;
106:
107: case 't': /* other date, undocumented, for tests */
1.12 pjanzen 108: if ((f_time = Mktime(optarg)) <= 0)
1.11 pjanzen 109: errx(1, "specified date is outside allowed range");
1.5 millert 110: break;
111:
112: case 'A': /* days after current date */
113: f_dayAfter = atoi(optarg);
114: break;
115:
116: case 'B': /* days before current date */
117: f_dayBefore = atoi(optarg);
118: break;
119:
1.1 deraadt 120: default:
121: usage();
122: }
123: argc -= optind;
124: argv += optind;
125:
126: if (argc)
127: usage();
128:
1.5 millert 129: /* use current time */
130: if (f_time <= 0)
131: (void)time(&f_time);
132:
1.12 pjanzen 133: if (f_dayBefore) {
134: /* Move back in time and only look forwards */
135: f_dayAfter += f_dayBefore;
136: f_time -= SECSPERDAY * f_dayBefore;
137: f_dayBefore = 0;
138: }
139: settime(&f_time);
1.5 millert 140:
1.10 millert 141: if (doall) {
1.15 ! pjanzen 142: pid_t kid, deadkid;
! 143: int kidstat, kidreaped, runningkids;
! 144: int acstat;
! 145: struct stat sbuf;
! 146: time_t t;
! 147: unsigned int sleeptime;
! 148:
! 149: signal(SIGCHLD, childsig);
! 150: runningkids = 0;
! 151: t = time(NULL);
1.1 deraadt 152: while ((pw = getpwent()) != NULL) {
1.15 ! pjanzen 153: acstat = 0;
! 154: /* Avoid unnecessary forks. The calendar file is only
! 155: * opened as the user later; if it can't be opened,
! 156: * it's no big deal. Also, get to correct directory.
! 157: * Note that in an NFS environment root may get EACCES
! 158: * on a chdir(), in which case we have to fork. As long as
! 159: * we can chdir() we can stat(), unless the user is
! 160: * modifying permissions while this is running.
! 161: */
! 162: if (chdir(pw->pw_dir)) {
! 163: if (errno == EACCES)
! 164: acstat = 1;
! 165: else
! 166: continue;
! 167: }
! 168: if (stat(calendarFile, &sbuf) != 0) {
! 169: if (chdir(calendarHome)) {
! 170: if (errno == EACCES)
! 171: acstat = 1;
! 172: else
! 173: continue;
! 174: }
! 175: if (stat(calendarNoMail, &sbuf) == 0 ||
! 176: stat(calendarFile, &sbuf) != 0)
! 177: continue;
! 178: }
! 179: sleeptime = USERTIMEOUT;
! 180: switch ((kid = fork())) {
! 181: case -1: /* error */
! 182: warn("fork");
! 183: continue;
! 184: case 0: /* child */
! 185: (void)setlocale(LC_ALL, "");
! 186: if (setusercontext(NULL, pw, pw->pw_uid,
! 187: LOGIN_SETALL ^ LOGIN_SETLOGIN))
! 188: err(1, "unable to set user context (uid %d)",
! 189: (int)pw->pw_uid);
! 190: if (acstat) {
! 191: if (chdir(pw->pw_dir) ||
! 192: stat(calendarFile, &sbuf) != 0 ||
! 193: chdir(calendarHome) ||
! 194: stat(calendarNoMail, &sbuf) == 0 ||
! 195: stat(calendarFile, &sbuf) != 0)
! 196: exit(0);
! 197: }
1.1 deraadt 198: cal();
1.15 ! pjanzen 199: exit(0);
! 200: }
! 201: /* parent: wait a reasonable time, then kill child if
! 202: * necessary.
! 203: */
! 204: runningkids++;
! 205: kidreaped = 0;
! 206: do {
! 207: sleeptime = sleep(sleeptime);
! 208: /* Note that there is the possibility, if the sleep
! 209: * stops early due to some other signal, of the child
! 210: * terminating and not getting detected during the next
! 211: * sleep. In that unlikely worst case, we just sleep
! 212: * too long for that user.
! 213: */
! 214: for (;;) {
! 215: deadkid = waitpid(-1, &kidstat, WNOHANG);
! 216: if (deadkid <= 0)
! 217: break;
! 218: runningkids--;
! 219: if (deadkid == kid) {
! 220: kidreaped = 1;
! 221: sleeptime = 0;
! 222: }
! 223: }
! 224: } while (sleeptime);
! 225:
! 226: if (!kidreaped) {
! 227: /* It doesn't _really_ matter if the kill fails, e.g.
! 228: * if there's only a zombie now.
! 229: */
! 230: (void)kill(kid, SIGTERM);
! 231: warnx("uid %d did not finish in time", (int)pw->pw_uid);
1.12 pjanzen 232: }
1.15 ! pjanzen 233: if (time(NULL) - t >= SECSPERDAY)
! 234: errx(2, "'calendar -a' took more than a day; stopped at uid %d",
! 235: (int)pw->pw_uid);
! 236: }
! 237: for (;;) {
! 238: deadkid = waitpid(-1, &kidstat, WNOHANG);
! 239: if (deadkid <= 0)
! 240: break;
! 241: runningkids--;
1.1 deraadt 242: }
1.15 ! pjanzen 243: if (runningkids)
! 244: warnx(
! 245: "%d child processes still running when 'calendar -a' finished", runningkids);
1.10 millert 246: }
1.1 deraadt 247: else if ((caldir = getenv("CALENDAR_DIR")) != NULL) {
1.5 millert 248: if(!chdir(caldir))
249: cal();
1.1 deraadt 250: } else
251: cal();
1.5 millert 252:
1.1 deraadt 253: exit(0);
254: }
255:
256:
257: void
258: usage()
259: {
1.5 millert 260: (void)fprintf(stderr,
1.14 aaron 261: "usage: calendar [-a] [-A num] [-B num] [-t [[[cc]yy][mm]]dd] "
262: "[-f calendarfile]\n");
1.1 deraadt 263: exit(1);
1.15 ! pjanzen 264: }
! 265:
! 266:
! 267: void
! 268: childsig(sig)
! 269: int sig;
! 270: {
1.1 deraadt 271: }