#if !defined(lint) && !defined(SABER)
static char  *rcsid = "$Id: submit.c,v 1.6 92/09/16 13:01:04 miki Exp Locker: miki $";
#endif

#include <stdlib.h>
#include <stdio.h>
#include <sys/signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>	/*for getpid */
#include <strings.h>
#include <sys/param.h> /* MAXPATHLEN */
#include <time.h>	/* for ctime */
#include <sys/wait.h>

#define BITBUCKET "/tmp"


void usage();
void onintr();
extern char *mktemp();
extern char *getenv();


FILE *infile = NULL;
FILE *outfile = NULL;
FILE *usrfile = NULL;
char *ofname = "/tmp/submit_start_XXXXXX";
char outlog[MAXPATHLEN+1], errlog[MAXPATHLEN+1], usrin[MAXPATHLEN+1];

main(argc, argv)
char **argv;
int argc;
{
	extern int optind;	/* getopt */
	extern char *optarg;	/* getopt */
	int c;
	int nocopy_flag = 0;	/* Don't copy to homedir results */
	int nomail_flag = 0;	/* No mail on job completion */
	int errflag = 0;
	mode_t oumask;
	pid_t pid;
	char *shell, *shell1;
	time_t clock;
	struct tm *tim;
	int min, hour;
	char buf[10];
	char mail_buf[10];

	/* Setup output files depository */
	pid = getpid();
	sprintf(outlog, "%s/%d.out", BITBUCKET, pid);
	sprintf(errlog, "%s/%d.stderr", BITBUCKET, pid);
	sprintf(usrin, "%s/%d.in", BITBUCKET, pid);
	while ((c = getopt (argc, argv, "cmo:e:")) != EOF)
		switch (c) {
		case 'c': 	/* User wants logs left in 'bitbucket' */
			nocopy_flag++;
			break;
			
		case 'm':
			nomail_flag++;
			break;

		case 'o':
			strcpy(outlog, optarg);
			break;

		case 'e':
			strcpy(errlog, optarg);
			break;
			
		default:
			errflag++;
		}
	if (errflag) {
		usage();
		exit(-1);
		/* NOTREACHED */
	}
	/* end while */
	/* Need to process other arguments on lime */
	
	if(((argc - optind) < 0 || (argc - optind) > 1)) {
		usage();
		exit(-1);
		/* NOTREACHED */
	}
	if((argc - optind) == 1) {
		infile = fopen(argv[optind], "r");
		if (infile == NULL) {
			perror(argv[optind]);
			exit(-2);
		}
	} else infile = stdin;

        /* Open the usrfile where user input is copied */
	usrfile =fopen(usrin, "w");
	if (usrfile == NULL) {
	           perror(usrin);
                   exit(-3);
                       /* NOTREACHED */
               }

	/* Setup output file */
	(void) signal(SIGINT, onintr);
	ofname = mktemp(ofname);
	if((outfile = fopen(ofname, "w")) == NULL) {
			perror(ofname);
			exit(-3);
			/* NOTREACHED */
		}
	/* We need to muck with SHELL environ.... */
	oumask = umask(0);
	(void) umask(oumask);
	(void) fprintf(outfile, "umask %.1o\n", oumask);
	
	shell = getenv("SHELL");
	if(!shell) shell = "/bin/csh";

	(void) fprintf(outfile, "exec > %s 2>&1\n", errlog);
	(void) fprintf(outfile, "exec > %s 2>&1\n", outlog);

	/* This is also important for /bin/sh as an error in the file will not
	 *  cause us to totally lose out oookies and can possibly send an error
	 */

	(void) fprintf(outfile, "%s  %s\n", shell, usrin);
	while((c = getc(infile)) != EOF) {
		putc(c, usrfile);
	}

	(void) fprintf(outfile, "exec > /dev/null 2>&1\n");
	fprintf(outfile, "/bin/rm -f %s\n", usrin);
	(void) fprintf(outfile, "retstatus=0\n");
	if(!nocopy_flag) {
		fprintf(outfile, "/bin/cp %s %s\n", outlog, "$HOME");
		fprintf(outfile, "if [ $? != 0 ]; then\n");
		fprintf(outfile, "\tretstatus=1\nfi\n");
		fprintf(outfile, "/bin/cp %s %s\n", errlog, "$HOME");
		fprintf(outfile, "if [ $? != 0 ]; then\n");
		fprintf(outfile, "\tretstatus=1\nfi\n");
		fprintf(outfile, "if [ $retstatus = 0 ]; then\n\t/bin/rm -f %s %s\nfi\n", outlog, errlog);
	}

        /* Get time stamp for mail and at invocation the same way */
	clock = time((time_t *) 0);
	tim = localtime(&clock);
	min = tim->tm_min+2;
	hour = tim->tm_hour +((min >=60) ? 1 : 0);
	min %= 60;
	if (min < 10)
	  sprintf(mail_buf, "%d%s%s%d", hour, ":", "0", min);
	else   sprintf(mail_buf, "%d%s%d", hour, ":",  min);
	if (min < 10)
	  sprintf(buf, "%d%s%d", hour, "0", min);
	else   sprintf(buf, "%d%d", hour,  min);
	clock = time((time_t *) 0);


	if(!nomail_flag) {
		if (!nocopy_flag)
			fprintf(outfile, "if [ $retstatus = 0 ]; then\n");
		fprintf(outfile, "	/usr/ucb/mail -s 'submitted job at %.11s%s' $USER << __MAIL__\n", ctime(&clock), mail_buf);
		fprintf(outfile, "Your submitted job at %.11s%s is completed.\n", ctime(&clock), mail_buf);
		fprintf(outfile, "The output log and error log may be found in\n");
		if(nocopy_flag)
			fprintf(outfile, "%s and %s.\n", outlog, errlog);
		else
			fprintf(outfile, "/mit/$USER/%d.out and /mit/$USER/%d.err\n", pid, pid);
		fprintf(outfile, "__MAIL__\n");
		/* else for the retstatus - could not copy...., but wanted to*/
		if (!nocopy_flag) {
			fprintf(outfile, "else\n");
			fprintf(outfile, "	/usr/ucb/mail -s 'submitted job' $USER << __MAIL__\n");
			fprintf(outfile, "Your submitted job at %.11s%s is completed.\n", ctime(&clock), mail_buf);
			fprintf(outfile, "The output log and error log could not be copied and were left in\n");

				fprintf(outfile, "%s and %s.\n", outlog, errlog);
			fprintf(outfile, "__MAIL__\n");

			fprintf(outfile, "fi\n");
		}
	}	/* nomail_flag */



	fclose(outfile);

	/* Submit to at .... */

	if((pid = fork()) == 0) {

		/* This is a hack to ensure that we do the wrapping for at */
		putenv("SHELL=/bin/sh"); 
#ifdef SOLARIS
               execl("/usr/bin/at", "at", "-f" , ofname, buf, (char *) 0); 
#else
		execl("/usr/bin/at", "at", buf, ofname, (char *) 0); 
#endif
/*		execl("/usr/ucb/printenv", "printenv", (char *) 0);*/
		exit(1);
	}
	while(wait((union wait *)0) != pid) 
		; /* Do nothing */

	unlink(ofname);
	return 0;
}

     
void
usage() 
{
	printf("Unknown option..\n");
	printf("submit [-c] [-m] [-o] [-e]\n");
}

void
onintr()
{
	if(outfile != NULL) {
		fclose(outfile);
		unlink(ofname);
	}
	exit(-3);
}

/* Open problem - what if they cause shell to bail out? Invoke subshell? */
