
/*
 *  SENDMAIL.C
 *
 *  $Header: Beta:src/uucp/src/dmail/RCS/sendmail.c,v 1.1 90/02/02 12:04:06 dillon Exp Locker: dillon $
 *
 *  (C) Copyright 1985-1990 by Matthew Dillon,  All Rights Reserved.
 *
 *  Global Routines:	DO_REPLY()
 *			DO_MAIL()
 *
 *  Static Routines:	WORD_SIZE()
 *			FOPEN_SCRATCH()
 *			FREOPEN_SCRATCH()
 *			FCLOSE_SCRATCH()
 *			FTERMINATE_SCRATCH()
 *			DELETE_SCRATCH()
 *			RUN_VI()
 *			SEND_MAIL()
 *
 *
 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
#ifdef UNIX
#include <sys/ioctl.h>
#endif
#include <sys/time.h>
#include <signal.h>
#include "dmail.h"
#include "config.h"

#ifdef AMIGA
#include <dos.h>

struct XFORKENV {
    long    env_priority;
    long    env_stack;
    long    env_stdin;
    long    env_stdout;
    long    env_console;
    long    env_msgport;
};

#endif

FILE *fi;
char file[64];

void fclose_scratch();
void fopen_scratch();
void copy_header();
void send_mail();

do_reply(garbage, itext)
char *garbage;
{
    int i, j;
    int anyargs  = 0;
    int to_field, cc_field;
    int len;
    char *ptr;
    static char buf[1024];
    char scr;
    char *istr;

    if (!(istr = get_var(LEVEL_SET, "_headchar")))
	istr = ">";
    if (push_base()) {
	push_break();
	pop_base();
	fclose_scratch();
	puts ("ABORTED, no mail sent");
	unlink(file);
	pop_break();
	return (-1);
    }
    fopen_scratch();
    strcpy (buf, "To: ");
    for (i = 1; i < ac; ++i) {
	if (*av[i] >= '0'  &&  *av[i] <= '9') {
	    if ((j = indexof(atoi(av[i]))) < 0) {
		puts ("No such message");
		fclose_scratch();
		unlink(file);
		pop_break();
		return (-1);
	    }
	    Current = j;
	} else {
	    if (anyargs)
		strcat (buf, ", ");
	    anyargs = 1;
	    strcat (buf, av[i]);
	}
    }
    len = strlen(buf);
    switch (itext) {
    case R_FORWARD:
	strcat (buf, "\n");
	fputs (buf, fi);
	fputs ("Subject: \n", fi);
	break;
    case R_INCLUDE:
    case R_REPLY:
	if (anyargs) {
	    strcat (buf, ", ");
	    len = strlen(buf);
	}
	buf[len] = 0;
	if (Current >= 0) {
	    char *rf = get_var(LEVEL_SET, "replyfields");
	    if (rf == NULL)
		rf = "";
	    while (*rf) {       /* attempt to find the fields listed */
		char *re;
		char *ptr;
		char c;
		for (re = rf; *re && *re != ' ' && *re != 9; ++re);
		c = *re;
		*re = 0;
		ptr = get_field(rf);
		if (*ptr) {
		    *re = c;
		    sprintf (buf + len, "%s\n", ptr);
		    break;
		}
		*re = c;
		while (*re == ' ' || *re == 9)
		    ++re;
		rf = re;
	    }
	    if (*rf == 0) {
		sprintf (buf + len, "%.*s\n",
			word_size(Entry[Current].from), Entry[Current].from);
	    }
	}
	fputs (buf, fi);
	fputs ("Cc: ", fi);
	ptr = get_field ("To:");
	to_field = (*ptr) ? 1 : 0;
	fputs (ptr, fi);
	scr = *(ptr + strlen(ptr) - 1);
	ptr = get_field ("Cc:");
	cc_field = (*ptr) ? 1 : 0;
	if (cc_field) {
	    if (scr == '\n') {
		fputs ("         ", fi);
	    }
	    if (to_field)
		fputs (", ", fi);
	    fputs (ptr, fi);
	}
	fputs ("\nSubject: Re: ", fi);
	fputs (get_field ("Subject:"), fi);
	fputs ("\n", fi);
	break;
    case R_MAIL:
	fputs (buf, fi);
	fputs ("\n", fi);
	fputs ("Cc: \n", fi);
	fputs ("Bcc: \n", fi);
	fputs ("Subject: \n", fi);
	break;
    default:
	puts ("INTERNAL STUPID MAIL ERROR: REPLY");
	break;
    }
    fputs ("\n\n", fi);
    if (itext == R_FORWARD  ||  itext == R_INCLUDE) {
	position_current();
	if (itext == R_FORWARD) {
	    if (Current >= 0)
		fprintf (fi, "ORIGINALLY From %s\n", Entry[Current].from);
	} else {
	    skip_to_data (m_fi);
	}
	while ((fgets (Buf, MAXFIELDSIZE, m_fi) != NULL) && !isfrom(Buf)) {
	    if (itext == R_INCLUDE)
		fputs(istr, fi);
	    fputs (Buf, fi);
	}
	fputs ("\n", fi);
    }
    copy_header (fi);
    fclose_scratch();
    if (itext != R_MAIL) {
	push_break();
	if (Current >= 0) {
	    Entry[Current].status |= ST_SCR;
	    write_file("t:Original", O_CREAT | O_TRUNC, ST_SCR, 0);
	    Entry[Current].status &= ~ST_SCR;
	}
	pop_break();
    }
    j = -1;
loop:
    ++j;
    if (run_vi() || j) {
	push_break();
	switch (do_ask()) {
	case 1:
	    puts ("SENDING.. wait");
	    send_mail();
	    {
		FILE *li = fopen(file, "r");
		char buf[128], *ptr = NULL;

		if (li) {
		    while (fgets(buf, 128, li) && buf[0] != '\n') {
			if (strncmp(buf, "Farchive:", 9) == 0) {
			    buf[strlen(buf)-1] = '\0';
			    for (ptr = buf + 9; *ptr == ' '; ++ptr);
			    if (ptr[0] == '$')
				ptr = get_var(LEVEL_SET, ptr+1);
			    break;
			}
		    }
		    fclose(li);
		}
		archive_mail(ptr);
	    }
	    unlink(file);
	    break;
	case 2:
	    pop_break();
	    goto loop;
	default:
	    unlink (file);
	    break;
	}
	pop_base();
	pop_break();
    } else {
	puts ("File not modified or ABORTED, no mail sent");
	unlink(file);
	pop_base();
    }
    unlink ("#");
}

do_ask()
{
    char in[256];

    if (!S_ask)
	return (1);
    fputs ("\n(Send, Vi, Quit) ?", stdout);
    fflush(stdout);
    gets (in);
    switch (in[0]) {
    case 's':
    case 'S':
	return (1);
    case 'q':
    case 'Q':
	puts ("ABORT, no mail sent");
	return (3);
    case 'v':
    case 'V':
    default:
	return (2);
    }
}



static void
copy_header(fi)
FILE *fi;
{
    FILE *fs;
    char *ptr;
    char *tmp = NULL;

    if (ptr = get_var (LEVEL_SET, "header")) {
	push_break();
	fs = fopen(ptr, "r");
	if (fs == NULL) {   /*  check uulib:    */
	    tmp = malloc(strlen(ptr) + strlen(MakeConfigPath(UULIB, "")) + 1);
	    sprintf(tmp, "%s%s", MakeConfigPath(UULIB, ""), ptr);
	    fs = fopen(tmp, "r");
	}
	if (fs) {
	    while (fgets (Buf, MAXFIELDSIZE, fs) != NULL)
		fputs (Buf, fi);
	    fclose (fs);
	} else {
	    printf ("Cannot open header file %d %s\n", strlen(ptr), ptr);
	    perror ("fopen");
	}
	if (tmp)
	    free(tmp);
	pop_break();
    }
}


static void
fopen_scratch()
{
    static int c;
    int fd;

    sprintf(file, "t:dmt%d%d", getpid(), c++);
    fd = open(file, O_RDWR|O_CREAT|O_TRUNC, 0700);
    if (fd < 0) {
	perror ("Dmail, cannot open scratch file");
	done (1);
    }
#ifdef AMIGA	    /*	fix bug in Lattice C fdopen */
    fi = fopen("nil:", "w");
    fclose(fi);
#endif
    fi = fdopen(fd, "w+");
}

static void
fclose_scratch()
{
    if (fi != NULL) {
	fflush (fi);
	fclose (fi);
	fi = NULL;
    }
}


static
word_size(str)
register char *str;
{
    register int size = 0;

    while (*str) {
	if (*str == ' ')
	    return (size);
	++str;
	++size;
    }
    return (size);
}


static
run_vi()
{
#ifdef UNIX
    char buf[64];
    int ret, pid = 0;
#endif
    struct stat stat1, stat2;
    char *argv[3];

    argv[0] = visual;
    argv[1] = file;
    argv[2] = NULL;
    if (push_base()) {
	push_break();
	pop_base();
#ifdef UNIX
	if (pid) {
	    kill (pid, SIGKILL);
	    sprintf (buf, "t:Ex%d", pid); unlink (buf);
	    sprintf (buf, "t:Rx%d", pid); unlink (buf);
	    wait(0);
	    system ("clear; reset ; clear");
	    pid = 0;
	}
#endif
	pop_break();
	return (0);
    }
    stat1.st_mtime = stat2.st_mtime = stat1.st_ctime = stat2.st_ctime = 0;
    stat (file, &stat1);
    if (S_novibreak)
	push_break();

#ifdef UNIX
    pid = vfork();
    if (!pid) {
	execv (visual, argv);
	printf ("Cannot exec visual: %s\n", visual);
	_exit (1);
    }
    while ((ret = wait(0)) > 0) {
	if (ret == pid)
	    break;
    }
#endif
#ifdef AMIGA
    {
	short i;
	static char buf[128];

	strcpy(buf, argv[0]);
	for (i = 1; argv[i]; ++i) {
	    strcat(buf, " ");
	    strcat(buf, argv[i]);
	}
	Execute(buf, NULL, NULL);
    }
#endif
    if (S_novibreak)
	pop_break();
    stat (file, &stat2);
    pop_base();
    return (!(stat1.st_mtime==stat2.st_mtime));
}


#ifdef UNIX

static void
send_mail()
{
    int fd, stdin_fd;
    char *argv[6];

    push_break();
    argv[0] = S_sendmail;
    argv[1] = "-t";
    argv[2] = "-oem";
    argv[3] = "-i";
    if (S_verbose) {
	argv[4] = "-v";
	argv[5] = NULL;
    } else {
	argv[4] = NULL;
    }

    fd = open (file, O_RDONLY, 0);
    if (fd < 0) {
	perror ("Dmail, Cannot open scratch file");
	done (1);
    }
    lseek(fd, 0L, 0);

    stdin_fd = dup (0);
    dup2 (fd, 0);       /* STDIN = message file */
    close(fd);          /* don't need message file anymore  */
    if (!fork()) {
	int fd = open("/dev/tty", O_RDWR, 0);
	if (fd >= 0) {
	    ioctl(fd, TIOCNOTTY, 0);
	    close(fd);
	    freopen("/dev/null", "w", stdout);
	    freopen("/dev/null", "w", stderr);
	}
	execv (S_sendmail, argv);
	printf ("Unable to exec sendmail: %s\n", S_sendmail);
	_exit (1);
    }
    dup2 (stdin_fd, 0);     /* restore STDIN    */
    close(stdin_fd);
    if (S_verbose) {
	puts ("Waiting for sendmail...");
	wait (0);
	puts ("Sendmail done");
    }
    pop_break();
}

#endif
#ifdef AMIGA

static void
send_mail()
{
    static char Buf[256];

    push_break();
    sprintf(Buf, "%s < %s%s -f %s", S_sendmail, file, (S_verbose ? " -v" : ""), user_name);

    printf("Sending\n", Buf);
    if (Execute(Buf, NULL, NULL) == 0)
	printf("Unable to run: %s\n", Buf);

    pop_break();
}

#endif





static
archive_mail(ptr)
char *ptr;
{
    FILE *ifi, *ofi;
    long tim = time(NULL);

    if (!ptr)
	ptr = get_var(LEVEL_SET, "archive");
    if (ptr == NULL || *ptr == '\0')
	return(-1);
    ifi = fopen(file, "r");
    if (ifi == NULL) {
	puts ("Cannot open scratch file");
	return(-1);
    }
    ofi = fopen(ptr, "a");
    if (ofi == NULL) {
	puts ("Cannot open archive file");
	fclose(ifi);
	return(-1);
    }
    sprintf (Buf, "\nFrom %s (ARCHIVE)\n", user_name);
    fputs (Buf, ofi);
    sprintf (Buf, "Date: %s", ctime(&tim));
    fputs (Buf, ofi);
    while (fgets (Buf, MAXFIELDSIZE, ifi))
	fputs (Buf, ofi);
    fclose(ofi);
    fclose(ifi);
    return (1);
}


