libc, libutil: remove compat hacks
[minix.git] / commands / crontab / crontab.c
blob6797ae28c794e4cb3e217a59b184b274694b2435
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"
19 #if __minix && !__minix_vmd
20 #define seteuid(uid) ((uid),0) /* Minix can't fiddle with uids. */
21 #endif
23 static int opentab(int uid, char *file, int how)
24 /* Open a crontab file under the given uid. How is 'r' or 'w'. Return
25 * the result of open(2).
28 uid_t safe_uid;
29 int flags, r, err;
31 switch (how) {
32 case 'r': flags= O_RDONLY; break;
33 case 'w': flags= O_WRONLY | O_CREAT | O_TRUNC; break;
34 default: errno= EINVAL; return -1;
37 #if __minix && !__minix_vmd
38 /* Standard Minix has no saved uid, so use the lousy old access(). */
39 if (uid != 0) {
40 if (access(file, how == 'r' ? R_OK : W_OK) < 0) return -1;
42 #endif
44 safe_uid= geteuid();
45 seteuid(uid);
46 r= open(file, flags, 0666);
47 err= errno;
48 seteuid(safe_uid);
49 errno= err;
50 return r;
53 static void copytab(int fd_in, char *file_in, int fd_out, char *file_out)
54 /* Copy one open file to another. Complain and exit on errors. */
56 ssize_t r, w;
57 char buf[1024];
59 while ((r= read(fd_in, buf, sizeof(buf))) > 0) {
60 w= 0;
61 while (w < r) {
62 if ((r= write(fd_out, buf+w, r-w)) <= 0) {
63 fprintf(stderr,
64 "%s: Write error on %s: %s\n",
65 prog_name,
66 file_out,
67 r == 0 ? "End of file"
68 : strerror(errno));
69 exit(1);
71 w+= r;
74 if (r < 0) {
75 fprintf(stderr, "%s: Read error on %s: %s\n",
76 prog_name, file_in, strerror(errno));
77 exit(1);
81 static void usage(void)
83 fprintf(stderr,
84 "Usage: %s -c [user] file # Change crontab\n"
85 " %s -l [user] # List crontab\n"
86 " %s -r [user] # Remove crontab\n"
87 " %s -p # Tell cron to reload\n",
88 prog_name, prog_name, prog_name, prog_name);
89 exit(1);
92 int main(int argc, char **argv)
94 int i;
95 int cflag, lflag, rflag, pflag;
96 uid_t uid;
97 char *user, *file;
98 struct passwd *pw;
99 static char SPOOLDIR[]= "/usr/spool/crontabs";
100 char tabfile[sizeof(SPOOLDIR) + NAME_MAX];
102 prog_name= strrchr(argv[0], '/');
103 if (prog_name == nil) prog_name= argv[0]; else prog_name++;
105 cflag= lflag= rflag= pflag= 0;
106 i= 1;
107 while (i < argc && argv[i][0] == '-') {
108 char *opt= argv[i++] + 1;
110 if (opt[0] == '-' && opt[1] == 0) break; /* -- */
112 while (*opt != 0) switch (*opt++) {
113 case 'c': cflag= 1; break;
114 case 'l': lflag= 1; break;
115 case 'r': rflag= 1; break;
116 case 'p': pflag= 1; break;
117 default: usage();
120 if (cflag + lflag + rflag + pflag != 1) usage();
122 user= file= nil;
123 if (!pflag && i < argc) user= argv[i++];
124 if (cflag) {
125 if (user == nil) usage();
126 if (i < argc) {
127 file= argv[i++];
128 } else {
129 file= user;
130 user= nil;
133 if (i != argc) usage();
135 if (geteuid() != 0) {
136 fprintf(stderr, "%s: No root privileges?\n", prog_name);
138 uid= getuid();
139 if (user == nil) {
140 if ((pw= getpwuid(uid)) == nil) {
141 fprintf(stderr,
142 "%s: Don't know who you (uid %lu) are!\n",
143 prog_name, (unsigned long) uid);
144 exit(1);
146 } else {
147 if ((pw= getpwnam(user)) == nil) {
148 fprintf(stderr,
149 "%s: Don't know who you (%s) are!\n",
150 prog_name, user);
151 exit(1);
154 if (uid != 0 && pw->pw_uid != uid) {
155 fprintf(stderr,
156 "%s: Only root can change the crontabs of others!\n",
157 prog_name);
158 exit(1);
160 user= pw->pw_name;
161 uid= pw->pw_uid;
162 seteuid(uid);
163 umask(0077);
165 selectlog(STDERR);
166 sprintf(tabfile, "%s/%s", SPOOLDIR, user);
168 if (lflag) {
169 int fd;
171 if ((fd= opentab(0, tabfile, 'r')) < 0) {
172 fprintf(stderr, "%s: Can't open %s: %s\n",
173 prog_name, tabfile, strerror(errno));
174 exit(1);
176 copytab(fd, tabfile, 1, "stdout");
177 close(fd);
180 if (rflag) {
181 seteuid(0);
182 if (unlink(tabfile) < 0) {
183 fprintf(stderr, "%s: Can't remove %s: %s\n",
184 prog_name, tabfile, strerror(errno));
185 exit(1);
187 seteuid(uid);
188 printf("Crontab of %s removed\n", user);
189 pflag= 1;
192 /* Initialize current Time */
193 time(&now);
195 if (cflag) {
196 int fd1, fd2;
198 if ((fd1= opentab(uid, file, 'r')) < 0) {
199 fprintf(stderr, "%s: Can't open %s: %s\n",
200 prog_name, file, strerror(errno));
201 exit(1);
204 /* Try to parse the new crontab file. If the parsing
205 * succeeds then 'crontabs' will be non-null.
207 tab_parse(file, user);
208 tab_purge();
209 if (crontabs == nil) exit(1);
211 if ((fd2= opentab(0, tabfile, 'w')) < 0) {
212 fprintf(stderr, "%s: Can't open %s: %s\n",
213 prog_name, tabfile, strerror(errno));
214 exit(1);
216 copytab(fd1, file, fd2, tabfile);
217 close(fd1);
218 close(fd2);
219 printf("New crontab for %s installed\n", user);
220 pflag= 1;
223 if (pflag) {
224 /* Alert cron to the new situation. */
225 FILE *fp;
227 seteuid(0);
228 if ((fp= fopen(PIDFILE, "r")) != NULL) {
229 unsigned long pid;
230 int c;
232 pid= 0;
233 while ((c= fgetc(fp)) != EOF && c != '\n') {
234 if ((unsigned) (c - '0') >= 10) {
235 pid= 0; break;
237 pid= 10*pid + (c - '0');
238 if (pid >= 30000) { pid= 0; break; }
240 if (pid > 1 && kill((pid_t) pid, SIGHUP) == 0) {
241 pflag= 0;
244 seteuid(uid);
245 if (pflag) {
246 fprintf(stderr,
247 "%s: Alerting cron has failed; cron still running?\n",
248 prog_name);
249 exit(1);
251 printf("Cron signalled to reload tables\n");
253 return 0;
257 * $PchId: crontab.c,v 1.4 2000/07/17 18:54:50 philip Exp $