/*
 * This file is part of the OLH system.
 *
 *      Lucien Van Elsen
 *	MIT Project Athena
 *
 * Copyright (C) 1990 by the Massachusetts Institute of Technology.
 * For copying and distribution information, see the file "mit-copyright.h".
 *
 *	$Source: /afs/sipb.mit.edu/project/sipb-athena/repository/src/olh/ascii/suggest.c,v $
 *	$Id: suggest.c,v 1.7 1995/05/27 07:49:59 yoav Exp $
 *	$Author: yoav $
 */

#ifndef lint
#ifndef SABER
static char *RCSid = "$Header: /afs/sipb.mit.edu/project/sipb-athena/repository/src/olh/ascii/suggest.c,v 1.7 1995/05/27 07:49:59 yoav Exp $";
#endif
#endif

#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/errno.h>
#if defined(_IBMR2) || defined(SYSV)
#include <termios.h>
#endif
#ifdef SYSV
#include <sys/fcntl.h>
#endif
#include "olh.h"

#ifdef __STDC__
# define        P(s) s
#else
# define P(s) ()
#endif

static void OLH_send_mail P((char *buffer , int bug_or_suggest ));
static int sendmail P((void ));

#undef P

void
take_bug_or_suggest(which)
     int which;
{
  char *buffer;
  int allocated;
  int used; 
  char line[LARGE_BUFFER];
  int done = FALSE;
  char ch;
  char *bug = "bug report";
  char *suggest = "suggestion";
#ifdef _IBMR2
  struct termios tiop;
#endif  
  allocated=LARGE_BUFFER;
  buffer = (char *) malloc(allocated * sizeof(char));
  
  if (which == OLH_SUGGEST) {
    paint_sugg();
    set_current_screen(SCR_SUGG);
  }
  else {
    paint_bugs();
    set_current_screen(SCR_SUGG);
  }

  nocbreak();
  echo();
  
  buffer[0] = '\0';
  used = 0;
  while ((fgets(line, LARGE_BUFFER, stdin) != NULL) &&
	 (strcmp(line, ".\n")))
    {
      if (used+=strlen(line) >= allocated)
	{
	  allocated+=LARGE_BUFFER;
	  buffer = (char *) realloc(buffer, allocated * sizeof(char));
	}
      strcat(buffer, line);
    }
  
  freopen("/dev/tty", "r+", stdin);
  
  noecho();
  cbreak();

  fprintf(stdout, "\n\n");
  
  if (strlen(buffer) == 0)
    {
      fprintf(stdout, "No %s to send.\n",(which == OLH_SUGGEST)?suggest:bug);
    }
  else
    while (! done)
      {
	fprintf(stdout,
		"Press 's' to send your %s, press '?' for other options: ",
		(which == OLH_SUGGEST)?suggest:bug);
	ch = fgetc(stdin);
	putchar('\n');
	switch (ch)
	  {
	  case 's':
	  case 'S':
	    fprintf(stdout, "\n\nSending...\n");
	    OLH_send_mail(buffer,which);
	    fprintf(stdout, "Your %s has been sent.\n\n",
		    (which == OLH_SUGGEST)?suggest:bug);
	    done = TRUE;
	    break;
	  case 'e':
	  case 'E':
	    fprintf(stdout,"\n\nInvoking editor...\n");
	    OLH_edit_buffer(&buffer);
	    break;
	  case 'C':
	  case 'c':
	    fprintf(stdout,
		    "\n\nYour %s has been cancelled.\n\n",
		    (which == OLH_SUGGEST)?suggest:bug);
	    done = TRUE;
	    break;
	  case 'L':
	  case 'l':
	    display_buffer(buffer);
	    wait_for_key(win_sugg_wait);
	    break;
	  default:
	    fprintf(stdout, "\n\nOptions:\n");
	    fprintf(stdout, "  s   Send\n");
	    fprintf(stdout, "  e   Edit\n");
	    fprintf(stdout, "  c   Cancel\n");
	    fprintf(stdout, "  l   List the text you entered\n\n");
	    break;
	  }
      }
  
  wait_for_key(win_sugg_wait);
  set_current_screen(SCR_PRIM);
}


static void
OLH_send_mail(buffer,bug_or_suggest)
     char *buffer;
     int bug_or_suggest;
{
  int fd;

  char *suggest_to = 	"To: olh-suggest\n";
  char *bug_to =	"To: bug-olh\n";
  char *suggest_s =	"Subject: Ascii OLH suggestion\n\n";
  char *bug_s =		"Subject: Ascii OLH Bug Report\n\n";

  char *sep1 = "\n-----------\ncurrent menupath: ";
  char *sep2 = "currently selected: ";

  char info[512],s[512];
  char *curr_selection;
  FILE *f,*mach_f;

  fd = sendmail();
  if (fd < 0) {
    fprintf(stderr,"Error starting up sendmail.\n");
    close(fd);
    return;
  }
  f = fdopen(fd,"w");
  if (bug_or_suggest == OLH_SUGGEST) {
    write(fd,suggest_to,strlen(suggest_to));
    write(fd,suggest_s,strlen(suggest_s));
  }
  if (bug_or_suggest == OLH_BUG) {
    write(fd,bug_to,strlen(bug_to));
    write(fd,bug_s,strlen(bug_s));
  }

  fprintf(f,"%s\n%s%s",buffer,sep1,menupath);

  if (current[current_menu] != 0) {
    curr_selection = field_value(nth_entry(menu[current_menu],
					   current[current_menu]), POINTER);
    fprintf(f,"%s%s\n",sep2,curr_selection);
  }
  else
    fprintf(f,"\n");

  fprintf(f,"Version: %s\n",VERSION);

  mach_f = popen("machtype -c -d -M -v","r");
  info[0] = '\0';
  if (mach_f != NULL) {
    while (fgets(s,512,mach_f) != NULL) {
      strncat(info,s,strlen(s)-1);
      strcat(info, ", ");
    }
    info[strlen(info) -2] = '\0';
  }
  pclose(mach_f);
  fprintf(f,"Machine information: %s\n",info);


  fclose(f);
  wait(0);  /* clean up sendmail process */
  return;
}  


/*
 * Function:    sendmail() forks a sendmail process to send mail to someone.
 *
 * Returns:     A file descriptor of a pipe to the sendmail process.
 * Notes:
 *      First, create a pipe so we can fork a sendmail child process.
 *      Then execute the fork, logging an error if we are unable to do.
 *      As usual in a situtation like this, check the process ID returned
 *      by fork().  If it is zero, we are in the child, so we execl
 *      sendmail with the appropriate arguments.  Otherwise, close
 *      the zeroth file descriptor, which is for reading.  Then construct
 *      the mail address and write it to sendmail.  Finally, return the
 *      file descriptor so the message can be sent.
 */

static int
sendmail()
{
  int fildes[2];        /* File descriptor array. */
  char *args[3];

  args[0] = "sendmail";
  args[1] = "-t";
  args[2] = NULL;

  (void) pipe(fildes);
  switch (fork())
    {
    case -1:            /* error */
      perror("mail");
      printf("sendmail: error starting process.\n");
      return(-1);
    case 0:             /* child */
      (void) close(fildes[1]);
      (void) close(0);
      (void) dup2(fildes[0], 0);
#ifdef __NetBSD__
      execv("/usr/sbin/sendmail", args);
#else
      execv("/usr/lib/sendmail", args);
#endif
      perror("sendmail: exec");
      exit(1);
    default:
      (void) close(fildes[0]);
      return(fildes[1]);
    }
}

void
OLH_edit_buffer(buffer)
     char **buffer;
{
  char *tmp_filename[15];
  int fd, len, blen, pid;
  struct stat statb;
  char *editor;

  strcpy(tmp_filename,"/tmp/olhXXXXXX");
  mktemp(tmp_filename);
  fd = open(tmp_filename,O_WRONLY|O_CREAT|O_TRUNC,0600);

  if (fd < 0) {
    fprintf(stderr,"olh_ascii: error opening file %s: %s\n", tmp_filename,
	    sys_errlist[errno]);
    return;
  }
  blen = strlen(*buffer);
  len = write(fd,*buffer,blen);
  if (len != blen) {
    fprintf(stderr,"olh_ascii: error writing to file %s: %s\n",
	    tmp_filename, sys_errlist[errno]);
    close(fd);
    return;
  }
  close(fd);

  editor = getenv("EDITOR");
  if (editor == NULL)
    editor = "emacs";

  if ((pid = fork()) == -1) {
    perror("olh_ascii: error forking editor: ");
    return;
  }
  else
    if (pid == 0) {
      execlp(editor, editor, tmp_filename, NULL);
      fprintf(stderr,"olh_ascii: error exec'ing %s: %s", editor,
	      sys_errlist[errno]);
      return;
    }
    else
      while(wait(0) != pid)
	;

  fd = open(tmp_filename,O_RDONLY,0600);
  if (fd < 0) {
    fprintf(stderr,"olh_ascii: error open file %s: %s\n", tmp_filename,
	    sys_errlist[errno]);
    return;
  }
  if (fstat(fd,&statb) < 0) {
    fprintf(stderr,"olh_ascii: error stat'ing file %s: %s\n", tmp_filename,
	    sys_errlist[errno]);
    return;
  }
  *buffer = realloc(*buffer,statb.st_size+1);
  if (*buffer == NULL) {
    fprintf(stderr,"olh_ascii: error in realloc\n");
    close(fd);
    return;
  }
  len = read(fd,*buffer,statb.st_size);
  if (len != statb.st_size) {
    fprintf(stderr,"olh_ascii: error reading file %s: %s\n", tmp_filename,
	    sys_errlist[errno]);
  }

  close(fd);
  unlink(tmp_filename);
  (*buffer)[statb.st_size] = '\0';
/* whew- made it past all those possible errors... */
  return;
}
