#include <sys/param.h>
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <pwd.h>
#include <malloc.h>
#include <unistd.h>

/*
 * This program gets rcmd.`hostname` tickets in a temporary file, chowns
 * them to "daemon", changes its uid to "daemon", gets rcmd.`hostname`
 * AFS tokens with the Kerberos tickets, saves a mail message into the
 * news.answers queue, then destroys the tokens and the tickets.
 *
 * The purpose of switching to "daemon" is so that this program can't,
 * inadvertantly or otherwise, do damage to the local filesystem.
 *
 * I'm using "daemon" rather than "nobody" because setuid() rejects
 * nobody's UID as invalid.
 */

#define DEFAULT_FOLDER "inbox"

#define USERNAME "daemon"

#define TICKET_VAR_PREFIX "KRBTKFILE="
#define TICKET_VAR_PREFIX_LEN 10

#define HOME_VAR "HOME=/afs/sipb.mit.edu/project/periodic-postings/news.answers"
     
#define KSRVTGT_CMD "/usr/local/bin/ksrvtgt rcmd %s -l 10"
#define KSRVTGT_CMD_LEN 34

#define AKLOG_CMD "/bin/athena/aklog sipb.mit.edu"

#define RCVSTORE_CMD "/usr/athena/etc/rcvstore +%s"
#define RCVSTORE_CMD_LEN 26

#define UNLOG_CMD "/bin/athena/unlog"

#define KDESTROY_CMD "/usr/athena/bin/kdestroy"

main(argc, argv)
int argc;
char *argv[];
{
     char ticket_file[L_tmpnam + TICKET_VAR_PREFIX_LEN];
     char ksrvtgt_cmd[KSRVTGT_CMD_LEN + MAXHOSTNAMELEN + 1];
     char hostname[MAXHOSTNAMELEN];
     char *folder = DEFAULT_FOLDER;
     char *rcvstore_cmd = 0;
     int exit_val = 0;
     struct passwd *pwent;
     extern char *optarg;
     extern int optind, opterr;
     int c;

     while ((c = getopt(argc, argv, "f:")) != EOF) {
	  switch (c) {
	  case 'f':
	       folder = optarg;
	       break;
	  default:
	       fprintf(stderr, "Usage: %s [ -f folder ]\n", argv[0]);
	       exit(1);
	  }
     }
     
     if (! (pwent = getpwnam(USERNAME))) {
	  fprintf(stderr, "Couldn't find passwd entry for %s\n", USERNAME);
	  exit(1);
     }

     /* set environment variables */
     
     (void) strcpy(ticket_file, TICKET_VAR_PREFIX);
     (void) tmpnam(ticket_file + TICKET_VAR_PREFIX_LEN);

     if (putenv(ticket_file)) {
	  fprintf(stderr, "Couldn't do: putenv(%s)\n", ticket_file);
	  exit(1);
     }

     if (putenv(HOME_VAR)) {
	  fprintf(stderr, "Couldn't do: putenv(%s)\n", HOME_VAR);
	  exit(1);
     }

     /* Get tickets */

     if (gethostname(hostname, sizeof(hostname)) < 0) {
	  perror("gethostname");
	  exit(1);
     }

     (void) sprintf(ksrvtgt_cmd, KSRVTGT_CMD, hostname);

     if (system(ksrvtgt_cmd)) {
	  fprintf(stderr, "Couldn't execute: %s\n", ksrvtgt_cmd);
	  exit_val++;
	  goto finished;
     }

     /* make them owned by the non-root user we're going to do the */
     /* work as */
     
     if (chown(ticket_file + TICKET_VAR_PREFIX_LEN, pwent->pw_uid,
	       pwent->pw_gid) < 0) {
	  perror("chown");
	  exit_val++;
	  goto finished;
     }

     /* switch to that user */
     
     if (setgid(pwent->pw_gid) < 0) {
	  perror("setgid");
	  exit_val++;
	  goto finished;
     }

     if (setuid(pwent->pw_uid) < 0) {
	  perror("setuid");
	  exit_val++;
	  goto finished;
     }

     /* get AFS tokens */
     
     if (system(AKLOG_CMD)) {
	  fprintf(stderr, "Couldn't execute: %s\n", AKLOG_CMD);
	  exit_val++;
	  goto finished;
     }

     /* file the message */

     if (! (rcvstore_cmd = malloc(RCVSTORE_CMD_LEN + strlen(folder) + 1))) {
	  fprintf(stderr, "Couldn't malloc %d.\n",
		  RCVSTORE_CMD_LEN + strlen(folder) + 1);
	  exit_val++;
	  goto finished;
     }

     (void) sprintf(rcvstore_cmd, RCVSTORE_CMD, folder);

     if (system(rcvstore_cmd)) {
	  fprintf(stderr, "Couldn't execute: %s\n", rcvstore_cmd);
	  exit_val++;
	  goto finished;
     }

finished:

     /* clean up */

     if (rcvstore_cmd) {
	  (void) free(rcvstore_cmd);
     }

     (void) system(UNLOG_CMD);
     (void) system(KDESTROY_CMD);
     exit(exit_val);
}
