crontab.c

Go to the documentation of this file.
00001 /*      crontab 1.2 - user crontab manipulation         Author: Kees J. Bot
00002  *                                                              12 Jan 1997
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)       /* Minix can't fiddle with uids. */
00021 #endif
00022 
00023 static int opentab(int uid, char *file, int how)
00024 /* Open a crontab file under the given uid.  How is 'r' or 'w'.  Return
00025  * the result of open(2).
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         /* Standard Minix has no saved uid, so use the lousy old access(). */
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 /* Copy one open file to another.  Complain and exit on errors. */
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         /* Initialize current Time */
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                 /* Try to parse the new crontab file.  If the parsing
00205                  * succeeds then 'crontabs' will be non-null.
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                 /* Alert cron to the new situation. */
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  * $PchId: crontab.c,v 1.4 2000/07/17 18:54:50 philip Exp $
00258  */

Generated on Fri Apr 14 22:56:47 2006 for minix by  doxygen 1.4.6