/*
 * CRONTAB
 *
 * usually setuid root, -c option only works if getuid() == geteuid()
 *
 * Copyright 1994 Matthew Dillon (dillon@apollo.west.oic.com)
 * May be distributed under the GNU General Public License
 *
 * Vladimir Oleynik <dzo@simtreas.ru> (C) 2002 to be used in busybox
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <dirent.h>
#include <fcntl.h>
#include <pwd.h>
#include <unistd.h>
#include <grp.h>
#include <syslog.h>
#include <signal.h>
#include <getopt.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/resource.h>

#ifndef CRONTABS
#define CRONTABS        "/var/spool/cron/crontabs"
#endif
#ifndef TMPDIR
#define TMPDIR          "/var/spool/cron"
#endif
#ifndef CRONUPDATE
#define CRONUPDATE      "cron.update"
#endif
#ifndef PATH_VI
#define PATH_VI         "/usr/bin/vi"   /* location of vi       */
#endif

#include "busybox.h"

static const char  *CDir = CRONTABS;

static void EditFile(const char *user, const char *file);
static int GetReplaceStream(const char *user, const char *file);
static int  ChangeUser(const char *user, short dochdir);

int
crontab_main(int ac, char **av)
{
    enum { NONE, EDIT, LIST, REPLACE, DELETE } option = NONE;
    const struct passwd *pas;
    const char *repFile = NULL;
    int repFd = 0;
    int i;
    char caller[256];           /* user that ran program */
    int   UserId;

    UserId = getuid();
    if ((pas = getpwuid(UserId)) == NULL)
	perror_msg_and_die("getpwuid");

    strncpy(caller, pas->pw_name, sizeof(caller));

    i = 1;
    if (ac > 1) {
	if (av[1][0] == '-' && av[1][1] == 0) {
	    option = REPLACE;
	    ++i;
	} else if (av[1][0] != '-') {
	    option = REPLACE;
	    ++i;
	    repFile = av[1];
	}
    }

    for (; i < ac; ++i) {
	char *ptr = av[i];

	if (*ptr != '-')
	    break;
	ptr += 2;

	switch(ptr[-1]) {
	case 'l':
	    if (ptr[-1] == 'l')
		option = LIST;
	    /* fall through */
	case 'e':
	    if (ptr[-1] == 'e')
		option = EDIT;
	    /* fall through */
	case 'd':
	    if (ptr[-1] == 'd')
		option = DELETE;
	    /* fall through */
	case 'u':
	    if (i + 1 < ac && av[i+1][0] != '-') {
		++i;
		if (getuid() == geteuid()) {
		    pas = getpwnam(av[i]);
		    if (pas) {
			UserId = pas->pw_uid;
		    } else {
			error_msg_and_die("user %s unknown", av[i]);
		    }
		} else {
		    error_msg_and_die("only the superuser may specify a user");
		}
	    }
	    break;
	case 'c':
	    if (getuid() == geteuid()) {
		CDir = (*ptr) ? ptr : av[++i];
	    } else {
		error_msg_and_die("-c option: superuser only");
	    }
	    break;
	default:
	    i = ac;
	    break;
	}
    }
    if (i != ac || option == NONE)
	show_usage();

    /*
     * Get password entry
     */

    if ((pas = getpwuid(UserId)) == NULL)
	perror_msg_and_die("getpwuid");

    /*
     * If there is a replacement file, obtain a secure descriptor to it.
     */

    if (repFile) {
	repFd = GetReplaceStream(caller, repFile);
	if (repFd < 0)
	    error_msg_and_die("unable to read replacement file");
    }

    /*
     * Change directory to our crontab directory
     */

    if (chdir(CDir) < 0)
	perror_msg_and_die("cannot change dir to %s", CDir);

    /*
     * Handle options as appropriate
     */

    switch(option) {
    case LIST:
	{
	    FILE *fi;
	    char buf[1024];

	    if ((fi = fopen(pas->pw_name, "r"))) {
		while (fgets(buf, sizeof(buf), fi) != NULL)
		    fputs(buf, stdout);
		fclose(fi);
	    } else {
		error_msg("no crontab for %s", pas->pw_name);
	    }
	}
	break;
    case EDIT:
	{
	    FILE *fi;
	    int fd;
	    int n;
	    char tmp[128];
	    char buf[1024];

	    snprintf(tmp, sizeof(tmp), TMPDIR "/crontab.%d", getpid());
	    if ((fd = open(tmp, O_RDWR|O_CREAT|O_TRUNC|O_EXCL, 0600)) >= 0) {
		chown(tmp, getuid(), getgid());
		if ((fi = fopen(pas->pw_name, "r"))) {
		    while ((n = fread(buf, 1, sizeof(buf), fi)) > 0)
			write(fd, buf, n);
		}
		EditFile(caller, tmp);
		remove(tmp);
		lseek(fd, 0L, 0);
		repFd = fd;
	    } else {
		error_msg_and_die("unable to create %s", tmp);
	    }

	}
	option = REPLACE;
	/* fall through */
    case REPLACE:
	{
	    char buf[1024];
	    char path[1024];
	    int fd;
	    int n;

	    snprintf(path, sizeof(path), "%s.new", pas->pw_name);
	    if ((fd = open(path, O_CREAT|O_TRUNC|O_EXCL|O_APPEND|O_WRONLY, 0600)) >= 0) {
		while ((n = read(repFd, buf, sizeof(buf))) > 0) {
		    write(fd, buf, n);
		}
		close(fd);
		rename(path, pas->pw_name);
	    } else {
		error_msg("unable to create %s/%s", CDir, buf);
	    }
	    close(repFd);
	}
	break;
    case DELETE:
	remove(pas->pw_name);
	break;
    case NONE:
    default:
	break;
    }

    /*
     *  Bump notification file.  Handle window where crond picks file up
     *  before we can write our entry out.
     */

    if (option == REPLACE || option == DELETE) {
	FILE *fo;
	struct stat st;

	while ((fo = fopen(CRONUPDATE, "a"))) {
	    fprintf(fo, "%s\n", pas->pw_name);
	    fflush(fo);
	    if (fstat(fileno(fo), &st) != 0 || st.st_nlink != 0) {
		fclose(fo);
		break;
	    }
	    fclose(fo);
	    /* loop */
	}
	if (fo == NULL) {
	    error_msg("unable to append to %s/%s", CDir, CRONUPDATE);
	}
    }
    return 0;
}

static int
GetReplaceStream(const char *user, const char *file)
{
    int filedes[2];
    int pid;
    int fd;
    int n;
    char buf[1024];

    if (pipe(filedes) < 0) {
	perror("pipe");
	return(-1);
    }
    if ((pid = fork()) < 0) {
	perror("fork");
	return(-1);
    }
    if (pid > 0) {
	/*
	 * PARENT
	 */

	close(filedes[1]);
	if (read(filedes[0], buf, 1) != 1) {
	    close(filedes[0]);
	    filedes[0] = -1;
	}
	return(filedes[0]);
    }

    /*
     * CHILD
     */

    close(filedes[0]);

    if (ChangeUser(user, 0) < 0)
	exit(0);

    fd = open(file, O_RDONLY);
    if (fd < 0) {
	error_msg("unable to open %s", file);
	exit(0);
    }
    buf[0] = 0;
    write(filedes[1], buf, 1);
    while ((n = read(fd, buf, sizeof(buf))) > 0) {
	write(filedes[1], buf, n);
    }
    exit(0);
}

static void
EditFile(const char *user, const char *file)
{
    int pid;

    if ((pid = fork()) == 0) {
	/*
	 * CHILD - change user and run editor
	 */
	char *ptr;
	char visual[1024];

	if (ChangeUser(user, 1) < 0)
	    exit(0);
	if ((ptr = getenv("VISUAL")) == NULL || strlen(ptr) > 256)
	    ptr = PATH_VI;

	snprintf(visual, sizeof(visual), "%s %s", ptr, file);
	execl("/bin/sh", "/bin/sh", "-c", visual, NULL);
	perror("exec");
	exit(0);
    }
    if (pid < 0) {
	/*
	 * PARENT - failure
	 */
	perror_msg_and_die("fork");
    }
    wait4(pid, NULL, 0, NULL);
}

static void
log(const char *ctl, ...)
{
    va_list va;
    char buf[1024];

    va_start(va, ctl);
    vsnprintf(buf, sizeof(buf), ctl, va);
    syslog(LOG_NOTICE, "%s",buf );
    va_end(va);
}

static int
ChangeUser(const char *user, short dochdir)
{
    struct passwd *pas;

    /*
     * Obtain password entry and change privilages
     */

    if ((pas = getpwnam(user)) == 0) {
	log("failed to get uid for %s", user);
	return(-1);
    }
    setenv("USER", pas->pw_name, 1);
    setenv("HOME", pas->pw_dir, 1);
    setenv("SHELL", "/bin/sh", 1);

    /*
     * Change running state to the user in question
     */

    if (initgroups(user, pas->pw_gid) < 0) {
	log("initgroups failed: %s %m", user);
	return(-1);
    }
    if (setregid(pas->pw_gid, pas->pw_gid) < 0) {
	log("setregid failed: %s %d", user, pas->pw_gid);
	return(-1);
    }
    if (setreuid(pas->pw_uid, pas->pw_uid) < 0) {
	log("setreuid failed: %s %d", user, pas->pw_uid);
	return(-1);
    }
    if (dochdir) {
	if (chdir(pas->pw_dir) < 0) {
	    if (chdir(TMPDIR) < 0) {
		log("chdir failed: %s %s", user, pas->pw_dir);
		log("chdir failed: %s " TMPDIR, user);
		return(-1);
	    }
	}
    }
    return(pas->pw_uid);
}
