xref: /minix/minix/commands/crontab/crontab.c (revision 0a6a1f1d)
1 /*	crontab 1.2 - user crontab manipulation		Author: Kees J. Bot
2  *								12 Jan 1997
3  */
4 #define nil ((void*)0)
5 #include <sys/types.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <signal.h>
10 #include <time.h>
11 #include <errno.h>
12 #include <unistd.h>
13 #include <fcntl.h>
14 #include <pwd.h>
15 #include <sys/stat.h>
16 #include "misc.h"
17 #include "tab.h"
18 
19 static int opentab(int uid, char *file, int how)
20 /* Open a crontab file under the given uid.  How is 'r' or 'w'.  Return
21  * the result of open(2).
22  */
23 {
24 	uid_t safe_uid;
25 	int flags, r, err;
26 
27 	switch (how) {
28 	case 'r':	flags= O_RDONLY;			break;
29 	case 'w':	flags= O_WRONLY | O_CREAT | O_TRUNC;	break;
30 	default:	errno= EINVAL;				return -1;
31 	}
32 
33 	safe_uid= geteuid();
34 	seteuid(uid);
35 	r= open(file, flags, 0666);
36 	err= errno;
37 	seteuid(safe_uid);
38 	errno= err;
39 	return r;
40 }
41 
42 static void copytab(int fd_in, char *file_in, int fd_out, char *file_out)
43 /* Copy one open file to another.  Complain and exit on errors. */
44 {
45 	ssize_t r, w;
46 	char buf[1024];
47 
48 	while ((r= read(fd_in, buf, sizeof(buf))) > 0) {
49 		w= 0;
50 		while (w < r) {
51 			if ((r= write(fd_out, buf+w, r-w)) <= 0) {
52 				fprintf(stderr,
53 				"%s: Write error on %s: %s\n",
54 					prog_name,
55 					file_out,
56 					r == 0 ? "End of file"
57 							: strerror(errno));
58 				exit(1);
59 			}
60 			w+= r;
61 		}
62 	}
63 	if (r < 0) {
64 		fprintf(stderr, "%s: Read error on %s: %s\n",
65 			prog_name, file_in, strerror(errno));
66 		exit(1);
67 	}
68 }
69 
70 static void usage(void)
71 {
72 	fprintf(stderr,
73 		"Usage: %s -c [user] file  # Change crontab\n"
74 		"       %s -l [user]       # List crontab\n"
75 		"       %s -r [user]       # Remove crontab\n"
76 		"       %s -p              # Tell cron to reload\n",
77 		prog_name, prog_name, prog_name, prog_name);
78 	exit(1);
79 }
80 
81 int main(int argc, char **argv)
82 {
83 	int i;
84 	int cflag, lflag, rflag, pflag;
85 	uid_t uid;
86 	char *user, *file;
87 	struct passwd *pw;
88 	static char SPOOLDIR[]= "/usr/spool/crontabs";
89 	char tabfile[sizeof(SPOOLDIR) + NAME_MAX];
90 
91 	prog_name= strrchr(argv[0], '/');
92 	if (prog_name == nil) prog_name= argv[0]; else prog_name++;
93 
94 	cflag= lflag= rflag= pflag= 0;
95 	i= 1;
96 	while (i < argc && argv[i][0] == '-') {
97 		char *opt= argv[i++] + 1;
98 
99 		if (opt[0] == '-' && opt[1] == 0) break;	/* -- */
100 
101 		while (*opt != 0) switch (*opt++) {
102 		case 'c':	cflag= 1;	break;
103 		case 'l':	lflag= 1;	break;
104 		case 'r':	rflag= 1;	break;
105 		case 'p':	pflag= 1;	break;
106 		default:	usage();
107 		}
108 	}
109 	if (cflag + lflag + rflag + pflag != 1) usage();
110 
111 	user= file= nil;
112 	if (!pflag && i < argc) user= argv[i++];
113 	if (cflag) {
114 		if (user == nil) usage();
115 		if (i < argc) {
116 			file= argv[i++];
117 		} else {
118 			file= user;
119 			user= nil;
120 		}
121 	}
122 	if (i != argc) usage();
123 
124 	if (geteuid() != 0) {
125 		fprintf(stderr, "%s: No root privileges?\n", prog_name);
126 	}
127 	uid= getuid();
128 	if (user == nil) {
129 		if ((pw= getpwuid(uid)) == nil) {
130 			fprintf(stderr,
131 				"%s: Don't know who you (uid %lu) are!\n",
132 				prog_name, (unsigned long) uid);
133 			exit(1);
134 		}
135 	} else {
136 		if ((pw= getpwnam(user)) == nil) {
137 			fprintf(stderr,
138 				"%s: Don't know who you (%s) are!\n",
139 				prog_name, user);
140 			exit(1);
141 		}
142 	}
143 	if (uid != 0 && pw->pw_uid != uid) {
144 		fprintf(stderr,
145 		"%s: Only root can change the crontabs of others!\n",
146 			prog_name);
147 		exit(1);
148 	}
149 	user= pw->pw_name;
150 	uid= pw->pw_uid;
151 	seteuid(uid);
152 	umask(0077);
153 
154 	selectlog(STDERR);
155 	sprintf(tabfile, "%s/%s", SPOOLDIR, user);
156 
157 	if (lflag) {
158 		int fd;
159 
160 		if ((fd= opentab(0, tabfile, 'r')) < 0) {
161 			fprintf(stderr, "%s: Can't open %s: %s\n",
162 				prog_name, tabfile, strerror(errno));
163 			exit(1);
164 		}
165 		copytab(fd, tabfile, 1, "stdout");
166 		close(fd);
167 	}
168 
169 	if (rflag) {
170 		seteuid(0);
171 		if (unlink(tabfile) < 0) {
172 			fprintf(stderr, "%s: Can't remove %s: %s\n",
173 				prog_name, tabfile, strerror(errno));
174 			exit(1);
175 		}
176 		seteuid(uid);
177 		printf("Crontab of %s removed\n", user);
178 		pflag= 1;
179 	}
180 
181 	/* Initialize current Time */
182 	time(&now);
183 
184 	if (cflag) {
185 		int fd1, fd2;
186 
187 		if ((fd1= opentab(uid, file, 'r')) < 0) {
188 			fprintf(stderr, "%s: Can't open %s: %s\n",
189 				prog_name, file, strerror(errno));
190 			exit(1);
191 		}
192 
193 		/* Try to parse the new crontab file.  If the parsing
194 		 * succeeds then 'crontabs' will be non-null.
195 		 */
196 		tab_parse(file, user);
197 		tab_purge();
198 		if (crontabs == nil) exit(1);
199 
200 		if ((fd2= opentab(0, tabfile, 'w')) < 0) {
201 			fprintf(stderr, "%s: Can't open %s: %s\n",
202 				prog_name, tabfile, strerror(errno));
203 			exit(1);
204 		}
205 		copytab(fd1, file, fd2, tabfile);
206 		close(fd1);
207 		close(fd2);
208 		printf("New crontab for %s installed\n", user);
209 		pflag= 1;
210 	}
211 
212 	if (pflag) {
213 		/* Alert cron to the new situation. */
214 		FILE *fp;
215 
216 		seteuid(0);
217 		if ((fp= fopen(PIDFILE, "r")) != NULL) {
218 			unsigned long pid;
219 			int c;
220 
221 			pid= 0;
222 			while ((c= fgetc(fp)) != EOF && c != '\n') {
223 				if ((unsigned) (c - '0') >= 10) {
224 					pid= 0; break;
225 				}
226 				pid= 10*pid + (c - '0');
227 				if (pid >= 30000) { pid= 0; break; }
228 			}
229 			if (pid > 1 && kill((pid_t) pid, SIGHUP) == 0) {
230 				pflag= 0;
231 			}
232 		}
233 		seteuid(uid);
234 		if (pflag) {
235 			fprintf(stderr,
236 			"%s: Alerting cron has failed; cron still running?\n",
237 				prog_name);
238 			exit(1);
239 		}
240 		printf("Cron signalled to reload tables\n");
241 	}
242 	return 0;
243 }
244 
245 /*
246  * $PchId: crontab.c,v 1.4 2000/07/17 18:54:50 philip Exp $
247  */
248