00001
00002
00003
00004 #define nil ((void*)0)
00005 #include <sys/types.h>
00006 #include <stdio.h>
00007 #include <stdlib.h>
00008 #include <string.h>
00009 #include <signal.h>
00010 #include <time.h>
00011 #include <errno.h>
00012 #include <unistd.h>
00013 #include <fcntl.h>
00014 #include <pwd.h>
00015 #include <sys/stat.h>
00016 #include "misc.h"
00017 #include "tab.h"
00018
00019 #if __minix && !__minix_vmd
00020 #define seteuid(uid) ((uid),0)
00021 #endif
00022
00023 static int opentab(int uid, char *file, int how)
00024
00025
00026
00027 {
00028 uid_t safe_uid;
00029 int flags, r, err;
00030
00031 switch (how) {
00032 case 'r': flags= O_RDONLY; break;
00033 case 'w': flags= O_WRONLY | O_CREAT | O_TRUNC; break;
00034 default: errno= EINVAL; return -1;
00035 }
00036
00037 #if __minix && !__minix_vmd
00038
00039 if (uid != 0) {
00040 if (access(file, how == 'r' ? R_OK : W_OK) < 0) return -1;
00041 }
00042 #endif
00043
00044 safe_uid= geteuid();
00045 seteuid(uid);
00046 r= open(file, flags, 0666);
00047 err= errno;
00048 seteuid(safe_uid);
00049 errno= err;
00050 return r;
00051 }
00052
00053 static void copytab(int fd_in, char *file_in, int fd_out, char *file_out)
00054
00055 {
00056 ssize_t r, w;
00057 char buf[1024];
00058
00059 while ((r= read(fd_in, buf, sizeof(buf))) > 0) {
00060 w= 0;
00061 while (w < r) {
00062 if ((r= write(fd_out, buf+w, r-w)) <= 0) {
00063 fprintf(stderr,
00064 "%s: Write error on %s: %s\n",
00065 prog_name,
00066 file_out,
00067 r == 0 ? "End of file"
00068 : strerror(errno));
00069 exit(1);
00070 }
00071 w+= r;
00072 }
00073 }
00074 if (r < 0) {
00075 fprintf(stderr, "%s: Read error on %s: %s\n",
00076 prog_name, file_in, strerror(errno));
00077 exit(1);
00078 }
00079 }
00080
00081 static void usage(void)
00082 {
00083 fprintf(stderr,
00084 "Usage: %s -c [user] file # Change crontab\n"
00085 " %s -l [user] # List crontab\n"
00086 " %s -r [user] # Remove crontab\n"
00087 " %s -p # Tell cron to reload\n",
00088 prog_name, prog_name, prog_name, prog_name);
00089 exit(1);
00090 }
00091
00092 int main(int argc, char **argv)
00093 {
00094 int i;
00095 int cflag, lflag, rflag, pflag;
00096 uid_t uid;
00097 char *user, *file;
00098 struct passwd *pw;
00099 static char SPOOLDIR[]= "/usr/spool/crontabs";
00100 char tabfile[sizeof(SPOOLDIR) + NAME_MAX];
00101
00102 prog_name= strrchr(argv[0], '/');
00103 if (prog_name == nil) prog_name= argv[0]; else prog_name++;
00104
00105 cflag= lflag= rflag= pflag= 0;
00106 i= 1;
00107 while (i < argc && argv[i][0] == '-') {
00108 char *opt= argv[i++] + 1;
00109
00110 if (opt[0] == '-' && opt[1] == 0) break;
00111
00112 while (*opt != 0) switch (*opt++) {
00113 case 'c': cflag= 1; break;
00114 case 'l': lflag= 1; break;
00115 case 'r': rflag= 1; break;
00116 case 'p': pflag= 1; break;
00117 default: usage();
00118 }
00119 }
00120 if (cflag + lflag + rflag + pflag != 1) usage();
00121
00122 user= file= nil;
00123 if (!pflag && i < argc) user= argv[i++];
00124 if (cflag) {
00125 if (user == nil) usage();
00126 if (i < argc) {
00127 file= argv[i++];
00128 } else {
00129 file= user;
00130 user= nil;
00131 }
00132 }
00133 if (i != argc) usage();
00134
00135 if (geteuid() != 0) {
00136 fprintf(stderr, "%s: No root privileges?\n", prog_name);
00137 }
00138 uid= getuid();
00139 if (user == nil) {
00140 if ((pw= getpwuid(uid)) == nil) {
00141 fprintf(stderr,
00142 "%s: Don't know who you (uid %lu) are!\n",
00143 prog_name, (unsigned long) uid);
00144 exit(1);
00145 }
00146 } else {
00147 if ((pw= getpwnam(user)) == nil) {
00148 fprintf(stderr,
00149 "%s: Don't know who you (%s) are!\n",
00150 prog_name, user);
00151 exit(1);
00152 }
00153 }
00154 if (uid != 0 && pw->pw_uid != uid) {
00155 fprintf(stderr,
00156 "%s: Only root can change the crontabs of others!\n",
00157 prog_name);
00158 exit(1);
00159 }
00160 user= pw->pw_name;
00161 uid= pw->pw_uid;
00162 seteuid(uid);
00163 umask(0077);
00164
00165 selectlog(STDERR);
00166 sprintf(tabfile, "%s/%s", SPOOLDIR, user);
00167
00168 if (lflag) {
00169 int fd;
00170
00171 if ((fd= opentab(0, tabfile, 'r')) < 0) {
00172 fprintf(stderr, "%s: Can't open %s: %s\n",
00173 prog_name, tabfile, strerror(errno));
00174 exit(1);
00175 }
00176 copytab(fd, tabfile, 1, "stdout");
00177 close(fd);
00178 }
00179
00180 if (rflag) {
00181 seteuid(0);
00182 if (unlink(tabfile) < 0) {
00183 fprintf(stderr, "%s: Can't remove %s: %s\n",
00184 prog_name, tabfile, strerror(errno));
00185 exit(1);
00186 }
00187 seteuid(uid);
00188 printf("Crontab of %s removed\n", user);
00189 pflag= 1;
00190 }
00191
00192
00193 time(&now);
00194
00195 if (cflag) {
00196 int fd1, fd2;
00197
00198 if ((fd1= opentab(uid, file, 'r')) < 0) {
00199 fprintf(stderr, "%s: Can't open %s: %s\n",
00200 prog_name, file, strerror(errno));
00201 exit(1);
00202 }
00203
00204
00205
00206
00207 tab_parse(file, user);
00208 tab_purge();
00209 if (crontabs == nil) exit(1);
00210
00211 if ((fd2= opentab(0, tabfile, 'w')) < 0) {
00212 fprintf(stderr, "%s: Can't open %s: %s\n",
00213 prog_name, tabfile, strerror(errno));
00214 exit(1);
00215 }
00216 copytab(fd1, file, fd2, tabfile);
00217 close(fd1);
00218 close(fd2);
00219 printf("New crontab for %s installed\n", user);
00220 pflag= 1;
00221 }
00222
00223 if (pflag) {
00224
00225 FILE *fp;
00226
00227 seteuid(0);
00228 if ((fp= fopen(PIDFILE, "r")) != NULL) {
00229 unsigned long pid;
00230 int c;
00231
00232 pid= 0;
00233 while ((c= fgetc(fp)) != EOF && c != '\n') {
00234 if ((unsigned) (c - '0') >= 10) {
00235 pid= 0; break;
00236 }
00237 pid= 10*pid + (c - '0');
00238 if (pid >= 30000) { pid= 0; break; }
00239 }
00240 if (pid > 1 && kill((pid_t) pid, SIGHUP) == 0) {
00241 pflag= 0;
00242 }
00243 }
00244 seteuid(uid);
00245 if (pflag) {
00246 fprintf(stderr,
00247 "%s: Alerting cron has failed; cron still running?\n",
00248 prog_name);
00249 exit(1);
00250 }
00251 printf("Cron signalled to reload tables\n");
00252 }
00253 return 0;
00254 }
00255
00256
00257
00258