static void delete_cmd(void) { char n[MAX_FNAME]; log_it(RealUser, Pid, "DELETE", User); if (!glue_strings(n, sizeof n, SPOOL_DIR, User, '/')) { errx(ERROR_EXIT, "path too long"); } if (unlink(n) != 0) { if (errno == ENOENT) errx(ERROR_EXIT, "no crontab for `%s'", User); else err(ERROR_EXIT, "cannot unlink `%s'", n); } poke_daemon(); }
static void delete_cmd (void) { char n[MAX_FNAME]; log_it (RealUser, Pid, "DELETE", User); (void) snprintf (n, MAX_FNAME, CRON_TAB (User)); if (unlink (n)) { if (errno == ENOENT) fprintf (stderr, "no crontab for %s\n", User); else perror (n); exit (ERROR_EXIT); } poke_daemon (); }
/* returns 0 on success * -1 on syntax error * -2 on install error */ static int replace_cmd (void) { char n[MAX_FNAME], envstr[MAX_ENVSTR], tn[MAX_FNAME]; FILE *tmp; int ch, eof; entry *e; char **envp = env_init (); int n_header_lines; /* Number of #CRONTAB header lines we write */ (void) snprintf (n, MAX_FNAME, "tmp.%d", Pid); (void) snprintf (tn, MAX_FNAME, CRON_TAB (n)); if (!(tmp = fopen (tn, "w+"))) { fprintf (stderr, "Unable to create new crontab file '%s'.\n" "fopen() failed with errno=%s (%d)\n", tn, strerror (errno), errno); if (errno == EACCES) fprintf (stderr, "In order to have permission to create such files,\n" "Crontab normally is installed setuid either superuser or \n" "a user or group that owns the crontab files and " "directories.\n"); return (-2); } write_header_if_wanted (tmp, &n_header_lines); /* copy the crontab to the tmp */ rewind (NewCrontab); Set_LineNum (1); while (EOF != (ch = get_char (NewCrontab))) putc (ch, tmp); ftruncate (fileno (tmp), ftell (tmp)); fflush (tmp); rewind (tmp); if (ferror (tmp)) { fprintf (stderr, "%s: error while writing new crontab to %s\n", ProgramName, tn); fclose (tmp); unlink (tn); return (-2); } /* check the syntax of the file being installed. */ /* BUG: was reporting errors after the EOF if there were any errors * in the file proper -- kludged it by stopping after first error. * vix 31mar87 */ Set_LineNum (1 - n_header_lines); CheckErrorCount = 0; eof = FALSE; while (!CheckErrorCount && !eof) { switch (load_env (envstr, tmp)) { case ERR: eof = TRUE; break; case FALSE: e = load_entry (tmp, check_error, pw, envp); if (e) free (e); break; case TRUE: break; } } if (CheckErrorCount != 0) { fprintf (stderr, "errors in crontab file, can't install.\n"); fclose (tmp); unlink (tn); return (-1); } /* Why are we doing this? We just created this file, so if we're privileged to do a chown(), the file's owner is already root. (Maybe on some systems the file doesn't automatically get the creator's effective uid?) */ #ifdef HAVE_FCHOWN if (fchown (fileno (tmp), ROOT_UID, -1) < OK) #else if (chown (tn, ROOT_UID, -1) < OK) #endif { if (errno == EPERM) { /* This just means we aren't running as superuser. We already passed the test of having enough privilege to create the crontab file in the crontab directory, so the fact that we aren't superuser just means the system administrator wants the crontabs owned by the owner of Crontab, not root. So let it be. */ } else { perror ("chown"); fclose (tmp); unlink (tn); return (-2); } } #ifdef HAVE_FCHMOD if (fchmod (fileno (tmp), 0600) < OK) #else if (chmod (tn, 0600) < OK) #endif { perror ("chmod"); fclose (tmp); unlink (tn); return (-2); } if (fclose (tmp) == EOF) { perror ("fclose"); unlink (tn); return (-2); } (void) snprintf (n, sizeof (n), CRON_TAB (User)); if (rename (tn, n)) { fprintf (stderr, "%s: error renaming %s to %s\n", ProgramName, tn, n); perror ("rename"); unlink (tn); return (-2); } log_it (RealUser, Pid, "REPLACE", User); poke_daemon (); return (0); }
/* returns 0 on success * -1 on syntax error * -2 on install error */ static int replace_cmd(void) { char n[MAX_FNAME], n2[MAX_FNAME], envstr[MAX_ENVSTR], lastch; FILE *tmp, *fmaxtabsize; int ch, eof, fd; int error = 0; entry *e; sig_t oint, oabrt, oquit, ohup; uid_t file_owner; time_t now = time(NULL); char **envp = env_init(); size_t maxtabsize; struct stat statbuf; if (envp == NULL) { warn("Cannot allocate memory."); return (-2); } if (!glue_strings(TempFilename, sizeof TempFilename, SPOOL_DIR, "tmp.XXXXXXXXXX", '/')) { TempFilename[0] = '\0'; warnx("path too long"); return (-2); } if ((fd = mkstemp(TempFilename)) == -1 || !(tmp = fdopen(fd, "w+"))) { warn("cannot create `%s'", TempFilename); if (fd != -1) { (void)close(fd); (void)unlink(TempFilename); } TempFilename[0] = '\0'; return (-2); } ohup = signal(SIGHUP, SIG_IGN); oint = signal(SIGINT, SIG_IGN); oquit = signal(SIGQUIT, SIG_IGN); oabrt = signal(SIGABRT, SIG_IGN); /* Make sure that the crontab is not an unreasonable size. * * XXX This is subject to a race condition--the user could * add stuff to the file after we've checked the size but * before we slurp it in and write it out. We can't just move * the test to test the temp file we later create, because by * that time we've already filled up the crontab disk. Probably * the right thing to do is to do a bytecount in the copy loop * rather than stating the file we're about to read. */ (void)snprintf(n2, sizeof(n2), "%s/%s", CRONDIR, MAXTABSIZE_FILE); if ((fmaxtabsize = fopen(n2, "r")) != NULL) { if (fgets(n2, (int)sizeof(n2), fmaxtabsize) == NULL) { maxtabsize = 0; } else { maxtabsize = atoi(n2); } (void)fclose(fmaxtabsize); } else { maxtabsize = MAXTABSIZE_DEFAULT; } if (fstat(fileno(NewCrontab), &statbuf)) { warn("error stat'ing crontab input"); error = -2; goto done; } if ((uintmax_t)statbuf.st_size > (uintmax_t)maxtabsize) { warnx("%ld bytes is larger than the maximum size of %ld bytes", (long) statbuf.st_size, (long) maxtabsize); error = -2; goto done; } /* write a signature at the top of the file. * * VERY IMPORTANT: make sure NHEADER_LINES agrees with this code. */ (void)fprintf(tmp, "# DO NOT EDIT THIS FILE - edit the master and reinstall.\n"); (void)fprintf(tmp, "# (%s installed on %-24.24s)\n", Filename, ctime(&now)); (void)fprintf(tmp, "# (Cron version %s -- %s)\n", CRON_VERSION, "$NetBSD: crontab.c,v 1.3.8.1 2012/03/07 23:41:17 riz Exp $"); /* copy the crontab to the tmp */ (void)rewind(NewCrontab); Set_LineNum(1); lastch = EOF; while (EOF != (ch = get_char(NewCrontab))) (void)putc(lastch = ch, tmp); if (lastch != (char)EOF && lastch != '\n') { warnx("missing trailing newline in `%s'", Filename); error = -1; goto done; } if (ferror(NewCrontab)) { warn("error while reading `%s'", Filename); error = -2; goto done; } (void)ftruncate(fileno(tmp), ftell(tmp)); /* XXX this should be a NOOP - is */ (void)fflush(tmp); if (ferror(tmp)) { (void)fclose(tmp); warn("error while writing new crontab to `%s'", TempFilename); error = -2; goto done; } /* check the syntax of the file being installed. */ /* BUG: was reporting errors after the EOF if there were any errors * in the file proper -- kludged it by stopping after first error. * vix 31mar87 */ Set_LineNum(1 - NHEADER_LINES); CheckErrorCount = 0; eof = FALSE; while (!CheckErrorCount && !eof) { switch (load_env(envstr, tmp)) { case ERR: /* check for data before the EOF */ if (envstr[0] != '\0') { Set_LineNum(LineNumber + 1); check_error("premature EOF"); } eof = TRUE; break; case FALSE: e = load_entry(tmp, check_error, pw, envp); if (e) free(e); break; case TRUE: break; } } if (CheckErrorCount != 0) { warnx("errors in crontab file, can't install."); (void)fclose(tmp); error = -1; goto done; } file_owner = (getgid() == getegid()) ? ROOT_UID : pw->pw_uid; #ifdef HAVE_FCHOWN error = fchown(fileno(tmp), file_owner, (uid_t)-1); #else error = chown(TempFilename, file_owner, (gid_t)-1); #endif if (error < OK) { warn("cannot chown `%s'", TempFilename); (void)fclose(tmp); error = -2; goto done; } if (fclose(tmp) == EOF) { warn("error closing file"); error = -2; goto done; } if (!glue_strings(n, sizeof n, SPOOL_DIR, User, '/')) { warnx("path too long"); error = -2; goto done; } if (rename(TempFilename, n)) { warn("error renaming `%s' to `%s'", TempFilename, n); error = -2; goto done; } TempFilename[0] = '\0'; log_it(RealUser, Pid, "REPLACE", User); poke_daemon(); done: (void)signal(SIGHUP, ohup); (void)signal(SIGINT, oint); (void)signal(SIGQUIT, oquit); (void)signal(SIGABRT, oabrt); if (TempFilename[0]) { (void) unlink(TempFilename); TempFilename[0] = '\0'; } return (error); }