/*
 * print the mail
 */

#include <stdio.h>
#include <ctype.h>
#include <signal.h>
#include <setjmp.h>
#include <string.h>
#include "mail.h"

extern char *home, mbox[], *mailfile, *Mailpgm, maildir[], *my_name;
extern char NoLetter[], lettmp[], from[], tz[16], *unalias ();
extern char deadansw[], lfil[256], PREPEND[], *malloc (), *getenv ();
extern char *frflsh (), *strtok (), resub[80], reto[80], subject[70];
extern int forward, flgf, delflg, flge, error, nlet, flgp, flgl, sflag;
extern int DestSub, changed, (*saveint) (), savdead (), umsave, ttyin;
extern int (*setsig ())();
extern long iop;
extern FILE *answf, *tmpf, *logf, *malf, *readinput ();

jmp_buf sjbuf;

int jjb;
int Mflag = 0;

printmail (argc, argv)
char **argv;
{
  int flg, i, j, print, aret, goerr = 0, oi, k, c;
  int ansletno, imax;
  int bsw = 0;
  char *bptr;
  char *p, *getarg (), *expand (), hbuf[256], tobuf[TOSIZE], *rp;
  char temp[10], sprompt[80], *tempans, resp[LSIZE], *strpbrk ();
  char *whom, *hmbox;
  extern char *optarg;
  FILE *textfp;

  if (argv[1][0] == '+')
  {
    forward = 1;
    argc--;
    argv++;
  }
  hmbox = malloc (strlen (home) + strlen (mbox) + 1);
  cat (hmbox, home, mbox);
  if (equal (argv[1], "-f") && argc == 2)
  {
    flgf = 1;
    mailfile = hmbox;
    goto jumpstart;
  }
  while ((c = getopt (argc, argv, "u:s:f:rpqiex")) != EOF)
    switch (c)
    {
    case 'f':
      flgf = 1;
      if (*optarg == '.' || *optarg == '/')
      {
	mailfile = malloc (strlen (optarg) + 1);
	strcpy (mailfile, optarg);
      }
      else
      {
	mailfile = malloc (strlen (home) + strlen (optarg) + 1);
	cat (mailfile, home, "/");
	strcat (mailfile, optarg);
      }
      break;
    case 'p':
      flgp++;
      flgl = 0;
    case 'q':
      delflg = 0;
    case 'i':
      break;
    case 'r':
      forward = 1;
      break;
    case 'e':
      flge = 1;
      break;
    case 's':
      sflag = 1;
      strcpy (subject, optarg);
      break;
    case 'u':
      mailfile = malloc (strlen (maildir) + strlen (optarg) + 1);
      cat (mailfile, maildir, optarg);
      my_name = optarg;
      flgf = 1;
      break;
    case '?':
      goerr++;
    }
  if (goerr)
  {
    fprintf (stderr, "usage: %s [-lrpq] [-u user] [-s subject] [-f file] [persons]\n",
	     Mailpgm);
    error = 2;
    done ();
  }

jumpstart:
  /* speed up malloc()s by getting and freeing a big block */
  for (i = 0, c = 3000; i < 30; i++, c -= 100)
  {
    if ((p = malloc (c)) != NULL)
    {
      free (p);
      break;
    }
  }

  if (!flgf)
  {
    mailfile = getenv ("MAIL");
    if ((mailfile == NULL) || (strlen (mailfile) == 0))
    {
      mailfile = malloc (strlen (maildir) + strlen (my_name) + 1);
      cat (mailfile, maildir, my_name);
    }
  }

  /* Open mailfile and set up array of letters and temp file */
  if (openmail () < 0)
    return;

  /*
   * puts("edmail 1.4  01/29/88  Copyright 1987 by Ed Carp  Use '?' for
   * help\n"); puts("edmail 1.5  11/30/89  Copyright 1987 by Ed Carp     Use
   * '?' for help\n"); puts("edmail 1.6  12/31/89  Copyright 1987 by Ed Carp
   * Use '?' for help\n");
  puts ("edmail 1.7  08/07/92  Copyright 1987 by Ed Carp     Use '?' for help\n");
   */
  puts ("edmail 1.8  08/29/92  Copyright 1987 by Ed Carp     Use '?' for help\n");
  print = 1;
  i = 0;
  if (setjmp (sjbuf) == 0)
  {
    /* Print optional mail index */
    if (flgl)
    {
      toc ();
      print = 0;
      i = -1;
    }
  }
  imax = nlet - 1;
  for (;;)
  {
    j = forward ? i : nlet - i - 1;
    if (setjmp (sjbuf) == 0 && print != 0 && ismail (i))
    {
      frflsh (0);
      copylet (j, stdout, ORDINARY, "");
    }
    if (flgp)
    {
      if (++i < nlet)
	continue;
      break;
    }
    setjmp (sjbuf);

    /* Build prompt message */
    sprompt[0] = '\0';
    if (newmail ())
    {
      strcat (sprompt, sprompt[0] ? "; " : "[");
      strcat (sprompt, "new mail arrived");
    }
    if (i == nlet)
    {
      strcat (sprompt, sprompt[0] ? "; " : "[");
      strcat (sprompt, "EOF");
    }
    if (!ismail (i) && i != nlet)
    {
      strcat (sprompt, sprompt[0] ? "; " : "[");
      strcat (sprompt, "unpositioned");
    }
    if (i == imax && ismail (i))
    {
      strcat (sprompt, sprompt[0] ? "; " : "[");
      strcat (sprompt, "last");
    }
    if (flgl && ismail (i))
    {
      strcat (sprompt, sprompt[0] ? "; " : "[");
      sprintf (temp, "%d", SHOW (i));
      strcat (sprompt, temp);
    }
    if (sprompt[0])
      strcat (sprompt, "] ");
    strcat (sprompt, "? ");
    fputs (sprompt, stdout);
    fflush (stdout);

    if (fgets (resp, LSIZE, stdin) == NULL)
      break;

    print = 1;
    DestSub = 0;
    /* Select letter by its number */
    if (isdigit (resp[0]))
    {
      flgl = 1;
      k = atoi (resp) - 1;
      if (k < 0 || k >= nlet)
      {
	print = 0;
	fprintf (stderr, "Letter %d does not exist\n", SHOW (k));
	continue;
      }
      i = k;
      j = forward ? i : nlet - i - 1;
      tempans = strpbrk (resp, "prawsmMdu");
      if (!tempans)
	continue;
      strcpy (resp, tempans);
      print = 0;
    }
    switch (resp[0])
    {
    case '?':			       /* Request help */
      print = 0;
      help ();
      break;
    case 'p':			       /* Print current letter */
      print = 1;
      if (!ismail (i))
      {
	fprintf (stderr, NoLetter);
	break;
      }
      rp = resp + 1;
      while (*rp && *rp != '\n' && isspace (*rp))
	++rp;
      if (*rp == '|')
      {
	++rp;
	pipelet (j, rp);
	print = 0;
      }
      break;
    case 'x':			       /* Exit without updating mailfile */
      changed = 0;
    case 'q':			       /* Quit */
      goto donep;
    case '>':			       /* Advance to next undeleted letter */
      oi = i;
      do
      {
	++i;
	j = forward ? i : nlet - i - 1;
      }
      while (i < nlet && let[j].change == 'd');
      if (i == nlet)
      {
	fprintf (stderr,
		 "Could not advance to undeleted letter\n");
	i = oi;
	print = 0;
      }
      break;
    case '<':			       /* Back up to undeleted letter */
      oi = i;
      do
      {
	--i;
	j = forward ? i : nlet - i - 1;
      }
      while (i >= 0 && let[j].change == 'd');
      if (i < 0)
      {
	fprintf (stderr,
		 "Could not back up to undeleted letter\n");
	i = oi;
	print = 0;
      }
      break;
    case '+':
    case '\n':			       /* Advance to next letter */
      ++i;
      if (!ismail (i))
      {
	fprintf (stderr, "Can't go past last letter\n");
	--i;
	print = 0;
      }
      break;
    case '-':			       /* Back up to previous letter */
      if (!ismail (i))
      {
	fprintf (stderr, "Can't backup if unpositioned\n");
	print = 0;
      }
      else if (i == 0)
      {
	fprintf (stderr, "Can't backup from first letter\n");
	print = 0;
      }
      else
	--i;
      break;
    case 'r':
    case 'a':			       /* Answer mail.  To send answers, we
				        * must trick the sendmail routine
				        * into sending letter number (nlet+1)
				        * of the answer file. */
      if (!ismail (i))
      {
	fprintf (stderr, NoLetter);
	break;
      }
      whom = let[j].sender;

      /*
       * if (!*(whom = frflsh(0))) { fprintf(stderr, "Cannot compute
       * respondee\n"); break; }
       */
      printf ("To: %s\n", unalias (whom, 0));
      while (strncmp (let[j].subject, "Re: ", 4) == 0)
      {
	let[j].subject += 4;
      }
      sprintf (resub, "Subject: Re: %s\n", let[j].subject);
      printf (resub);
      sprintf (reto, "In-Reply-To: Your message of %s\n", let[j].postmark);
      printf (reto);
      fflush (stdout);

      /* Get text of response from standard input */
      saveint = setsig (SIGINT, savdead);
      textfp = readinput (stdin, whom);
      resub[0] = NULL;
      reto[0] = NULL;
      setsig (SIGINT, saveint);
      fprintf (stdout, "\n");
      if (textfp == NULL)
	break;

      /*
       * Use the next free letter position, but do not increment nlet.
       * "ansletno" will be the number of the letter. Don't forget to put the
       * end of the file in let[ansletno+1].adr. Also, always position write
       * pointer at address of end of last letter.
       */
      ansletno = nlet;
      if ((answf = fopen (lettmp, "r+")) == NULL)
      {
	fprintf (stderr, "Cannot open %s\n", lettmp);
	break;
      }
      if (fseek (answf, let[nlet].adr, 0) == -1)
	fprintf (stderr, "SEEK ERROR!!!\n");
      time (&iop);
      sprintf (hbuf, "%s%s %24.24s%s\n", from, my_name, ctime (&iop), tz);
      hbuf[255] = 0;
      /* Prefix input with `From' header */
      strcpy (whom, finddest (whom, ""));
      envelope (answf, hbuf, whom, textfp);

      /*
       * Here is where we trick the sendmail routine.
       */
      let[ansletno + 1].adr = let[nlet].adr + Readio.r_size;
      let[ansletno].llns = Readio.r_lines;
      fclose (tmpf);
      tmpf = fopen (lettmp, "r");
      if (error)
      {
	if (storedead (ansletno, deadansw))
	  fprintf (stdout, "%s: cannot create %s\n", Mailpgm, deadansw);
	break;
      }

      /* Write log entry */
      if (logf != NULL)
	copylet (ansletno, logf, ORDINARY, "");
      if (DestSub)
	/* printf("Sending to: %s\n\n", whom); */
	flg = 0;
      for (p = whom; (p = getarg (lfil, p)) != NULL;)
	if (send (ansletno, lfil, 0) != TRUE)
	{
	  fprintf (stderr, "Cannot send to %s\n", lfil);
	  flg++;
	}
      if (flg)
      {
	print = 0;
	if (storedead (ansletno, deadansw))
	  fprintf (stdout, "%s: cannot create %s\n", Mailpgm, deadansw);
      }
      else
      {
	let[j].change = resp[0];
	changed++;
	i++;
      }
      break;
    case 'w':
    case 's':			       /* Save letter in file */
      if (!ismail (i))
      {
	fprintf (stderr, NoLetter);
	break;
      }
      if (resp[1] == '\n' || resp[1] == '\0')
	cat (resp + 1, hmbox, "");
      else if (resp[1] != ' ')
      {
	printf ("invalid command\n");
	print = 0;
	continue;
      }
      if (!sindex (lfil, "mbox"))
	umask (umsave);
      flg = 0;
      for (p = resp + 1; (p = getarg (lfil, p)) != NULL;)
      {
      loop:
	if ((aret = legal (lfil)))
	  malf = fopen (lfil, "a");
	if ((malf == NULL) || (aret == 0))
	{
	  fprintf (stderr, "%s: cannot append to %s\n", Mailpgm, lfil);
	  if (!ttyin)
	  {
	    flg++;
	    continue;
	  }
	  reenter (lfil, sizeof (lfil));
	  if (lfil[0] == '\0')
	  {
	    /* never mind ... */
	    printf ("Message not saved\n");
	    flg = 1;
	    goto nevermind;
	  }
	  goto loop;
	}
	if (aret == 2)
	{
	  /*
	   * on some systems, only root can use chown() :(
	   */
	  setuid (0);
	  chown (lfil, getuid (), getgid ());
	  setuid (realid);
	}
	copylet (j, malf, resp[0] == 'w' ? ZAP : ORDINARY, "");
	fclose (malf);
      }
    nevermind:
      if (flg)
	print = 0;
      else
      {
	let[j].change = resp[0];
	changed++;
	i++;
      }
      umask (MASK);
      break;
    case 'm':			       /* Forward letter */
      if (!ismail (i))
      {
	fprintf (stderr, NoLetter);
	break;
      }
      if (resp[1] == '\n' || resp[1] == '\0')
      {
	printf ("Must specify recipient\n");
	print = 0;
	continue;
      }
      if (resp[1] != ' ')
      {
	printf ("Invalid command\n");
	print = 0;
	continue;
      }
      strcpy (resp + 1, finddest (resp + 1, ""));

      if (DestSub)
	/* printf("Sending to: %s\n\n", resp+1); */

	if (logf != NULL)
	  copylet (j, logf, ORDINARY, "");

      flg = 0;
      for (p = resp + 1; (p = getarg (lfil, p)) != NULL;)
	if (sendrmt (j, lfil) != TRUE)
	  flg++;		       /* couldn't send it */
      if (flg)
	print = 0;
      else
      {
	let[j].change = resp[0];
	changed++;
	i++;
      }
      break;
    case 'M':			       /* Forward letter with prepended
				        * commentary */
      if (!ismail (i))
      {
	fprintf (stderr, NoLetter);
	break;
      }
      if (resp[1] == '\n' || resp[1] == '\0')
      {
	printf ("Must specify recipient\n");
	print = 0;
	continue;
      }
      if (resp[1] != ' ')
      {
	printf ("Invalid command\n");
	print = 0;
	continue;
      }
      for (rp = resp + 1; *rp && isspace (*rp); rp++)
	;
      strcpy (tobuf, rp);

      /* Get text of comment from standard input */
      saveint = setsig (SIGINT, savdead);
      jjb = j;
      Mflag = 1;
      textfp = readinput (stdin, tobuf);
      Mflag = 0;
      setsig (SIGINT, saveint);
      if (textfp == NULL)
	break;

      /*
       * fprintf(textfp, "\n"); copylet(j, textfp, ORDINARY, ">");
       */

      /*
       * Use the next free letter position, but do not increment nlet.
       * "ansletno" will be the number of the letter. Don't forget to put the
       * end of the file in let[ansletno+1].adr. Also, always position write
       * pointer at address of end of last letter.
       */
      ansletno = nlet;
      if ((answf = fopen (lettmp, "r+")) == NULL)
      {
	fprintf (stderr, "Cannot open %s\n", lettmp);
	break;
      }
      if (fseek (answf, let[nlet].adr, 0) == -1)
	fprintf (stderr, "SEEK ERROR!!!\n");
      time (&iop);
      sprintf (hbuf, "%s%s %24.24s%s\n", from, my_name, ctime (&iop), tz);
      hbuf[255] = '\0';
      strcpy (tobuf, finddest (tobuf, ""));
      envelope (answf, hbuf, tobuf, textfp);

      /*
       * Here is where we trick the sendmail routine.
       */
      let[ansletno + 1].adr = let[nlet].adr + Readio.r_size;
      let[ansletno].llns = Readio.r_lines;
      fclose (tmpf);
      tmpf = fopen (lettmp, "r");
      if (error)
      {
	if (storedead (ansletno, deadansw))
	  fprintf (stdout, "%s: cannot create %s\n", Mailpgm, deadansw);
	break;
      }
      if (logf != NULL)
	copylet (ansletno, logf, ORDINARY, "");

      /*
       * if (DestSub) printf("Sending to: %s\n\n", tobuf, 0);
       */

      flg = 0;
      for (p = tobuf; (p = getarg (lfil, p)) != NULL;)
	if (sendrmt (ansletno, lfil) != TRUE)
	{
	  fprintf (stderr, "Cannot send to %s\n", lfil);
	  flg++;
	}
      if (flg)
      {
	print = 0;
	if (storedead (ansletno, deadansw))
	  fprintf (stdout, "%s: cannot create %s\n", Mailpgm, deadansw);
      }
      else
      {
	let[j].change = resp[0];
	changed++;
	i++;
      }
      break;
    case '!':			       /* Escape to the shell */
      umask (umsave);
      mysystem (resp + 1);
      umask (MASK);
      print = 0;
      break;
    case 'c':			       /* chdir */
      rp = strtok (resp, " \t\n");
      if (equal (rp, "cd"))
      {
	if (mailfile[0] != '/')
	{
	  fprintf (stderr, "Can't `cd' unless mail file begins with '/' (cd! overrides)\n",
		   mailfile);
	  goto after;
	}
      }
      else if (!equal (rp, "cd!"))
	goto dflt;

      /* Parse directory out of response */
      rp = strtok (NULL, " \t\n");
      expand (rp, EX_UNIQ);
      rp = strtok (rp, " \t\n");
      p = (rp && *rp) ? rp : home;
      if (chdir (p) != -1)
	fprintf (stderr, "%s\n", p);
      else
	fprintf (stderr, "%s: Bad directory\n", p);
    after:
      print = 0;
      break;
    case 'd':			       /* Delete current letter */
      if (!ismail (i))
      {
	fprintf (stderr, NoLetter);
	break;
      }
      let[j].change = resp[0];
      changed++;
      i++;
      if (resp[1] == 'q')
	goto donep;
      break;
    case 'u':			       /* Undelete current letter */
      if (!ismail (i))
      {
	fprintf (stderr, NoLetter);
	break;
      }
      if (let[j].change == 0)
      {
	fprintf (stderr, "Letter %d was never deleted\n", SHOW (i));
      }
      else
      {
	let[j].change = 0;
	print = 0;
	i++;
      }
      break;
    case 'h':
    case 'l':			       /* List table of contents */
      print = 0;
      flgl = 1;
      toc ();
      break;
    case 'f':			       /* Save changes and reopen current
				        * mailfile */
      /* Copy remaining mail back to mailfile */
      if (changed)
      {
	copyback ();
	printf ("Changes saved in %s\n", mailfile);
      }
      fclose (tmpf);
      if ((tmpf = fopen (lettmp, "w")) == NULL)
      {
	fprintf (stderr,
		 "%s: cannot open %s for writing\n", Mailpgm, lettmp);
	error = 2;
	return;
      }

      /* Reopen mailfile */
      if (openmail () < 0)
	return;
      imax = nlet - 1;
      if (flgl)
	toc ();

      /* Initialize current position to null */
      print = 0;
      i = -1;
      break;
    default:
    dflt:
      print = 0;
      fprintf (stderr, "Type ? for list of valid commands\n");
      break;
    }
  }
donep:
  if (changed)
    copyback ();
}
