Beispiel #1
0
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();
}
Beispiel #2
0
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 ();
}
Beispiel #3
0
/* 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);
}
Beispiel #4
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);
}