/*                                                           */
/*  mail.c  -  Scott Teresi, Cary Newton  -  March 1996      */
/*             http://www.teresi.us                          */
/*  Simple mail reader program                               */
/*  Default directory is incoming directory under the user's */
/*  mail directory.                                          */
/*  Compile with gcc mail.c -lcurses -ltermcap               */
/*                                                           */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>	/* include string handling commands */
#include <curses.h>	/* include screen windowing interface */
#include <netdb.h>	/* internet functions */
#include <sys/types.h>
#include <netinet/in.h> /* socket functions */
#include <sys/socket.h>
#include <pwd.h>	/* password file functions */

#define LINE_SIZE 260	/* maximum line width */
#define MSG_LIST 5	/* number of message headers listed in header window */

#ifndef TRUE
#define TRUE 1		/* define TRUE to be a 1 */
#endif
#ifndef FALSE
#define FALSE 0		/* define FALSE to be a 0 */
#endif

/* structure definitions */

struct line_struct	       	/* structure for a screenful */
   {
      long int line_pos;	/* file position of each page start */
      int page_no;		/* page number of each page */
      struct line_struct *prev;	/* previous page */
      struct line_struct *next;	/* next page */
   };

struct mail_msg				/* structure for each message */
   {
      char from_date[LINE_SIZE];	/* first header line */
      char subject[LINE_SIZE];		/* subject line */
      long int msg_pos;			/* file position of each message */
      long int max_lines;		/* number of lines in message */
      long int max_pages;		/* number of pages in message */
      struct mail_msg *prev;		/* previous message */
      struct mail_msg *next;		/* next message */
      struct line_struct first_line;   	/* start of first page of the body */
   };


typedef struct line_struct LINE;
typedef struct mail_msg MAIL_MSG;
typedef int boolean;
LINE *cur_line, *prev_line, *next_line, first_line;
MAIL_MSG *cur_msg, *prev_msg, *next_msg, first_msg;

/* globals */

FILE *mail_file;
int HDR_SPACE;		/* height of header window */
int MSG_SPACE;		/* height of message window */
int LINES, COLS;	/* dimensions of screen set by curses */
int sel_msg;		/* current message number selected */
int top_line;		/* top line of message text being displayed */
WINDOW *headerwin,	/* curses window for message headers */
       *msgwin;		/* curses window for message text */

char *find_address(char *username);
char *get_from_line(MAIL_MSG *cur_msg);
char *get_subj_line(MAIL_MSG *cur_msg);
char *input_to_line();
char *input_subj_line();

/* beginning of program */

int main(int argc, char *argv[])
   {
   int  i;
   char mail_in_file[260];	/* file containing mail messages */
   char	line[LINE_SIZE];	/* single line of text input from file */
   int  page_no;		/* page number of current line */
   long int file_pos = 0;	/* position of a line of text in file */
   int	scrnlines;		/* number of lines so far in page read */
   int msg_count = 0;		/* number of messages in file */
   boolean print_header,	/* does user want header output? */
	   on_header,		/* is header info currently being read? */
	   storinglines,	/* is first line of message body being read? */
           file_OK;		/* file has some mail messages in it */
   char key;			/* next character in buffer */
   char *from_address;		/* parsed address of who letter is from */
   char *from_string;		/* entire username+address of person */
   char *subject;		/* subject */
   char tempfile[50];		/* temporary file used to store msg to send */
   char machine_name[256];	/* account you're in */
   char *to_string;		/* who to send message to */
   struct hostent *hp;
   char dummystr[50];
   char *str;

   from_address = (char *) malloc(sizeof(char) * LINE_SIZE);
   from_string = (char *) malloc(sizeof(char) * LINE_SIZE);
   subject = (char *) malloc(sizeof(char) * LINE_SIZE);
   str = (char *) malloc(sizeof(char) * LINE_SIZE);
   to_string = (char *) malloc(sizeof(char) * LINE_SIZE);

   strcpy(mail_in_file, "/usr/spool/mail/scott");
   /* strcpy(mail_in_file, "/home/scott/c/wlloyd"); */

   /* strcpy(mail_in_file, getenv("HOME"));
   strcat(mail_in_file, "/mail/incoming"); */	/* default mail file */

   /* check for valid usage of switches */

   if ((argc > 4) ||		/* check input syntax */
       ((argc == 2) && (argv[1][1] != 'i')) ||
       ((argc == 3) && (argv[1][1] != 'f')) ||
       ((argc == 4) && ((argv[1][1] != 'i') || (argv[2][1] != 'f'))) )
   {
      fprintf(stderr, "Usage: %s [-i] [-f filename]\n", argv[0]);
      exit(1);
   }

   print_header = FALSE;	/* check if user wants headers output */
   if (((argc == 2) && (argv[1][1] == 'i')) ||
       ((argc == 4) && (argv[1][1] == 'i')))
      print_header = TRUE;

   if (argc == 3)		/* find alternate mail files for input */
      strcpy(mail_in_file, argv[2]);
   if (argc == 4)
      strcpy(mail_in_file, argv[3]);

   if ((mail_file = fopen(mail_in_file, "r")) == NULL)
   {
      fprintf(stderr, "%s: your mail file %s does not exist.\n", argv[0],
            mail_in_file);
      exit(1);
   }

   initscr();	/* start curses routines */

   COLS = COLS + 1;
   HDR_SPACE = MSG_LIST * 2 + 1;	/* window space for list of headers */
   MSG_SPACE = LINES - HDR_SPACE;	/* window space for message text */
   cur_msg = &first_msg;		/* set msg pointer at start of list */

   strcpy(cur_msg->from_date,"");
   prev_msg = NULL;			/* initialize variables */
   prev_line = NULL;
   on_header = FALSE;
   storinglines = FALSE;
   file_OK = FALSE;


   /* routine to find file positions of each line and message header */

   while (fgets(line, COLS, mail_file) != NULL)	/* read to EOF */ 
  {
      if (strncmp(line, "From ", 5) == 0)	/* see if at start of header */
      {
         if (strlen(cur_msg->from_date) != 0)	/* see if not first header */
         {
            cur_line->prev->next = NULL;
            cur_msg->max_pages = page_no;
            next_msg = (MAIL_MSG *) malloc(sizeof(MAIL_MSG));	/* init next */
            cur_msg->next = next_msg;
            prev_msg = cur_msg;
            cur_msg = next_msg;			/* advance pointer */
         }
         set_msg_link(cur_msg, file_pos, line, "", prev_msg, NULL);
         cur_line = &cur_msg->first_line;
         cur_msg->max_lines = 0;
         scrnlines = 0;
         page_no = 1;
         msg_count ++;

         file_OK = TRUE;
         on_header = TRUE;
         storinglines = FALSE;
      }
      if ((strncmp(line, "Subject: ", 9) == 0) && on_header)	/* read subj */
      {
         line[COLS-6] = '\0';	/* cut subject string short enough */
         line[COLS-7] = '\n';   /* last char on screen must be a return */
         if (line[COLS-8] == '\n')
            line[COLS-7] = '\0';
         strcpy(cur_msg->subject, line);
      }
      if ((strncmp(line, "From ", 5) == 0) && print_header)
      {
         storinglines = TRUE;
      }
      if ((line[0] == '\n') && on_header && !print_header)
      {
         storinglines = TRUE;
         on_header = FALSE;
         file_pos = ftell(mail_file);
         fgets(line, COLS, mail_file);	/* skip over the \n */
      }
      if (storinglines)
      {
	 scrnlines ++;			/* count message body to be output */
         cur_msg->max_lines ++;		/* count number of lines in message */
         set_line_link(cur_line, file_pos, page_no, prev_line, NULL);
         prev_line = cur_line;
         cur_line->next = (LINE *) malloc(sizeof(LINE));
         cur_line = cur_line->next;
         cur_line->prev = prev_line;
         if (scrnlines == MSG_SPACE)	/* end of a page is reached */
         {
            page_no ++;
            scrnlines = 0;
         }
      }

      file_pos = ftell(mail_file);	/* watch file pos of start of msgs */
   }
   cur_line->prev->next = NULL;
   cur_msg->max_pages = page_no;

   if (!file_OK)			/* no messages found in file */
   {
      fprintf(stderr, "%s: file %s is not a mail file.\n", argv[0],
            mail_in_file);
      exit(1);
   }


   /* set up windows for displaying messages */

   headerwin = newwin(HDR_SPACE, COLS-1, 0, 0);
   msgwin = newwin(MSG_SPACE-1, COLS-1, HDR_SPACE, 0);
   sel_msg = 1;
   top_line = 1;
   display_headers(headerwin, &first_msg, msg_count);
   display_message(msgwin, headerwin, &first_msg, &top_line);

   raw();		/* bypass kernel key processing */
   noecho();		/* turn off screen echo of input */


   /* main input loop */

   while(1)
   {
      key = getch();	/* get user's command */
      switch (key)
      {
         case -1 : break;	/* no key pressed */
         case 'u':
         case 'U': sel_msg --;				/* up a message */
                   top_line = 1;
                   display_headers(headerwin, &first_msg, msg_count);
                   display_message(msgwin, headerwin, &first_msg, &top_line);
                   break;
         case 'd':
         case 'D': sel_msg ++;				/* down a message */
                   top_line = 1;
                   display_headers(headerwin, &first_msg, msg_count);
                   display_message(msgwin, headerwin, &first_msg, &top_line);
                   break;
         case 'B':
         case  2 : top_line = top_line - MSG_SPACE;	/* up a page */
                   display_message(msgwin, headerwin, &first_msg, &top_line);
                   break;
         case 'F':
         case  6 :
         case  32: top_line = top_line + MSG_SPACE;	/* down a page */
                   display_message(msgwin, headerwin, &first_msg, &top_line);
                   break;
         case 'b': top_line --;				/* up a line */
                   display_message(msgwin, headerwin, &first_msg, &top_line);
                   break;
         case 'f':
         case 13 : top_line ++;				/* down a message */
                   display_message(msgwin, headerwin, &first_msg, &top_line);
                   break;
         case 't':
         case 'T': top_line = 1;			/* top of message */
                   display_message(msgwin, headerwin, &first_msg, &top_line);
                   break;
         case 'q':
         case 'Q':
         case  3 : scrollok(msgwin, 1);			/* quit routine */
                   scroll(msgwin);
                   wmove(msgwin, MSG_SPACE-1, 0);
                   wprintw(msgwin, "\n");
                   wrefresh(msgwin);
                   endwin();
                   exit(0);
                   break;
         case 27 : key = getch();
                   switch (key)
                   {
                   case 91: key = getch();
                            switch (key)
                            {
                            case 65: sel_msg --;	/* up arrow */
                                     top_line = 1;
                                     display_headers(headerwin, &first_msg,
                                           msg_count);
                                     display_message(msgwin, headerwin,
                                           &first_msg, &top_line);
                                     break;
                            case 66: sel_msg ++;	/* down arrow */
                                     top_line = 1;
                                     display_headers(headerwin, &first_msg,
                                           msg_count);
                                     display_message(msgwin, headerwin,
                                           &first_msg, &top_line);
                                     break;
                            case 67: top_line = top_line + MSG_SPACE;
							/* right arrow */
                                     display_message(msgwin, headerwin,
                                           &first_msg, &top_line);
                                     break;
                            case 68: top_line = top_line - MSG_SPACE;
							/* left arrow */
                                     display_message(msgwin, headerwin,
                                           &first_msg, &top_line);
                                     break;
                            default: break;
                            }
                   default: break;
                   }
                   break;
         case 's':
         case 'S': strcpy(to_string, (char *) input_to_line());
                   strcpy(subject, (char *) input_subj_line());
                   strcpy(dummystr, subject);
                   strcpy(subject, "Subject: ");
                   strcat(subject, dummystr);
                   strcpy(tempfile, "/tmp/mailfile.XXXXXX");
                   mktemp(tempfile);
                   sprintf(dummystr, "emacs %s", tempfile);
                   system(dummystr);
                   touchwin(headerwin); touchwin(msgwin);
                   wrefresh(headerwin); wrefresh(msgwin);
                   str = getpwuid(getuid())->pw_name;
                   strcat(str, "@");
                   gethostname(machine_name, sizeof(machine_name));
                   strcat(str, machine_name);
                   send_message(str, find_address(to_string), to_string,
                         subject, tempfile, &first_msg, &top_line);
                   unlink(tempfile);
                   break;
         case 'r':
         case 'R':
         case 'i':					/* reply routine */
         case 'I': cur_msg = &first_msg;
                   for (i = 1; i < sel_msg; i++)
                      cur_msg = cur_msg->next;
                   from_address = find_address(cur_msg->from_date);
                   if (strlen(from_address) > 0)
                   {
                      strcpy(from_string, (char *) get_from_line(&first_msg));
                      strcpy(subject, (char *) get_subj_line(&first_msg));
                      strcpy(tempfile, "/tmp/mailfile.XXXXXX");
                      mktemp(tempfile);
                      if ((key == 'i') || (key == 'I'))	/* include cur. msg */
                         include_message(&first_msg, tempfile);
                      sprintf(dummystr, "emacs %s", tempfile);
                      system(dummystr);
                      touchwin(headerwin); touchwin(msgwin);	/* curses */
                      wrefresh(headerwin); wrefresh(msgwin);
                      str = getpwuid(getuid())->pw_name;    /* get user info */
                      strcat(str, "@");
                      gethostname(machine_name, sizeof(machine_name));
                      strcat(str, machine_name);
                      send_message(str, from_address, from_string, subject,
                            tempfile, &first_msg, &top_line);
                      unlink(tempfile);		/* delete the temp file */
                   }
                   break;
         case '/':
         case '?': display_help(msgwin);	/* show help screen */
            while(1)
            {
               key = getch();
                  if (key > 0)
                     break;
            }
            display_message(msgwin, headerwin, &first_msg, &top_line);
         default: break;
      }
   }

}   /* end of main procedure */





/* display list of message headers */

display_headers(WINDOW *window, MAIL_MSG *cur_msg, int msg_count)

{
   int top_scrn = 1;		/* start message text at first line */
   int i, j;
   char dummystr[LINE_SIZE], spaces[LINE_SIZE];

   if ((sel_msg < 1) || (sel_msg > msg_count))
   {				/* message outside of limits */
      putc('\a', stdout);	/* beep */
      fflush(stdout);
      if (sel_msg < 1)
         sel_msg = 1;
      if (sel_msg > msg_count)
          sel_msg = msg_count;
   }     
   else				/* else, highlight next message */
   {
      werase(window);
      wmove(window, 0, 0);
      while(1)
      {
         if ((top_scrn-1) % MSG_LIST == 0)
            if ((top_scrn <= sel_msg) && (sel_msg < (top_scrn+MSG_LIST)))
               break;		/* find first message header for window */
         top_scrn ++;
         cur_msg = cur_msg->next;
      }

      for (i = 0; i < MSG_LIST; i ++)	/* list MSG_LIST num. of msg headers */
      {
         if (sel_msg == (top_scrn + i))
            wstandout(window);		/* highlight selected msg */
         strcpy(dummystr, cur_msg->from_date);
         dummystr[strlen(dummystr)-1] = '\0';
         strcpy(spaces, "");
         for (j = strlen(dummystr); j < COLS-2; j ++)
            strcat(spaces, " ");
         wprintw(window, "%s%s\n", dummystr, spaces);
         strcpy(dummystr, cur_msg->subject);
         if (strlen(cur_msg->subject) == 0)
            strcpy(dummystr, "Subject: <None>\n");
         dummystr[strlen(dummystr)-1] = '\0';
         strcpy(spaces, "");
         for (j = strlen(dummystr); j < COLS-7; j ++)
            strcat(spaces, " ");
         wprintw(window, "     %s%s\n", dummystr, spaces);
         if (sel_msg == (top_scrn + i))
            wstandend(window);

         cur_msg = cur_msg->next;
         if (cur_msg == NULL)
            break;
      }

      wmove(window, HDR_SPACE-1, 0);	/* go to status bar and re-print */
      wstandout(window);
      wprintw(window, "Press ? for list of available commands.                                         \n");
      wstandend(window);

      wmove(window, 0, 0);
      wrefresh(window);			/* output the new window */
   }
}



/* display message text */

display_message(WINDOW *msgwin, WINDOW *headerwin, MAIL_MSG *cur_msg,
                int *top_line)

{
   int i;
   char line[LINE_SIZE];
   int top_page, bot_page;		/* page range being displayed */

   for (i = 1; i < sel_msg; i ++)	/* point to selected message */
      cur_msg = cur_msg->next;

   if (*top_line < 1)			/* keep top_line within range */
   {
      *top_line = 1;
      putc('\a', stdout);
      fflush(stdout);
   }
   if ((*top_line + MSG_SPACE > cur_msg->max_lines) && (*top_line != 1))
   {
      *top_line = *top_line - (MSG_SPACE - (cur_msg->max_lines-*top_line)) + 1;
				/* top_line minus remaining empty space */
      putc('\a', stdout);
      fflush(stdout);
   }

   cur_line = &cur_msg->first_line;
   for (i = 1; i < *top_line; i ++)	/* point to the top line in window */
      cur_line = cur_line->next;

   top_page = cur_line->page_no;

   i = 1;				/* count of lines output to screen */
   werase(msgwin);
   wmove(msgwin, 0, 0);
   while ((i < MSG_SPACE) && (cur_line != NULL))
   {
      fseek(mail_file, cur_line->line_pos, 0);
      fgets(line, COLS, mail_file);	/* get a line from mail file */
      wmove(msgwin, i-1, 0);
      wprintw(msgwin, "%s", line);	/* output the line */
      bot_page = cur_line->page_no;
      cur_line = cur_line->next;
      i ++;
   }

   wmove(headerwin, HDR_SPACE-1, 64);	/* indicate pages displayed */
   wstandout(headerwin);
   if (top_page == bot_page)
      wprintw(headerwin, "Page: %d/%d   ", top_page, cur_msg->max_pages);
   else
      wprintw(headerwin, "Page: %d-%d/%d   ", top_page, bot_page,
            cur_msg->max_pages);
   wstandend(headerwin);
   wrefresh(headerwin);
   wrefresh(msgwin);
}




/* show help screen */

display_help(WINDOW *msgwin)
{
   werase(msgwin);
   wmove(msgwin, 0, 0);
   wprintw(msgwin, "                    M A I L   R E A D E R   C O M M A N D S\n\n");
   wprintw(msgwin, "U, u: up a message        F, space: forward a page\n");
   wprintw(msgwin, "D, d: down a message      B: back a page\n");
   wprintw(msgwin, "f: foward a line          T, t: top of message\n");
   wprintw(msgwin, "b: back a line\n");
   wprintw(msgwin, "\nR, r: reply to a sender   I, i: reply and include current message\n");
   wprintw(msgwin, "S, s: send a message\n");
   wprintw(msgwin, "Q, q: quit program");
   wstandout(msgwin);
   wprintw(msgwin, "\n\nHit a key to return to mail reader.\n");
   wstandend(msgwin);
   wrefresh(msgwin);
}




/* find the address to send message to */

char *find_address(char *username)
{
   int i;
   int index;
   char *from_hoststring, *from_string, *machine_name;
   struct hostent *from_hostname;
   struct in_addr from_addr;

   from_hoststring = (char *) malloc(sizeof(char) * 100);
   from_string = (char *) malloc(sizeof(char) * 100);
   machine_name = (char *) malloc(sizeof(char) * 100);

   index = strcspn(username, "@");		/* locate @ sign */

   if (index == strlen(username))		/* no @ in from line */
   {
      gethostname(from_hoststring, 100);	/* get host name of */
   }						/* current system */
   else
   {
      index ++;
      strcpy(from_string, &username[index]);
      from_string[strcspn(from_string, " ")] = '\0';
      strcpy(from_hoststring, from_string);
   }

   if ((from_hostname = (struct hostent *) gethostbyname(from_hoststring))
         == NULL)
   {
      werase(msgwin);
      wmove(msgwin, 1, 0);
      wprintw(msgwin, "Could not locate host %s\n", from_hoststring);
      wrefresh(msgwin);
      return "";
   }
   else
   {
      bcopy(from_hostname->h_addr, &from_addr, from_hostname->h_length);
      return (char *) inet_ntoa(from_addr);
   }
}




/* parse from line */

char *get_from_line(MAIL_MSG *cur_msg)
{
   int i;
   char *from_string;

   from_string = (char *) malloc(sizeof(char) * 100);

   for (i = 1; i < sel_msg; i++)
      cur_msg = cur_msg->next;

   strcpy(from_string, &cur_msg->from_date[5]);
   from_string[strcspn(from_string, " ")] = '\0';
   return from_string;
}




/* prepare subject line */

char *get_subj_line(MAIL_MSG *cur_msg)
{
   int i;
   char *re_subj;

   re_subj = (char *) malloc(LINE_SIZE);

   for (i = 1; i < sel_msg; i++)
      cur_msg = cur_msg->next;

   strcpy(re_subj, "Subject: RE: ");
   if (strlen(cur_msg->subject) != 0)
      strcat(re_subj, &cur_msg->subject[strcspn(cur_msg->subject, " ")+1]);

   return re_subj;
}




/* get input from user (who to send msg to) */

char *input_to_line()
{
   char *to_address;

   to_address = (char *) malloc(sizeof(char) * LINE_SIZE);

   echo();
   noraw();

   werase(msgwin);
   wmove(msgwin, 1, 0);
   wprintw(msgwin, "Enter the address of the recipient.\n");
   wrefresh(msgwin);
   gets(to_address);

   noecho();
   raw();

   return to_address;
}




/* get input from user (subject) */

char *input_subj_line()
{
   char *subject;

   subject = (char *) malloc(sizeof(char) * LINE_SIZE);

   echo();
   noraw();

   wmove(msgwin, 3, 0);
   wprintw(msgwin, "Subject:\n");
   wrefresh(msgwin);
   gets(subject);

   noecho();
   raw();

   return subject;
}




/* put message into temporary file */

include_message(MAIL_MSG *cur_msg, char *tempfile)
{
   FILE *fp;
   LINE *cur_line;
   char line[LINE_SIZE], caratstr[LINE_SIZE];
   int i;

   for (i = 1; i < sel_msg; i ++)	/* point to selected message */
      cur_msg = cur_msg->next;

   caratstr[0] = '>';
   caratstr[1] = ' ';
   caratstr[2] = '\0';

   fp = fopen(tempfile, "w");
   fprintf(fp, caratstr);
   fprintf(fp, cur_msg->from_date);
   fprintf(fp, caratstr);
   fprintf(fp, cur_msg->subject);

   cur_line = &cur_msg->first_line;
   while(cur_line != NULL)
   {
      fseek(mail_file, cur_line->line_pos, 0);
      fgets(line, COLS-2, mail_file);	/* get a line from mail file */
      fprintf(fp, caratstr);
      fprintf(fp, line);
      cur_line = cur_line->next;
   }

   fclose(fp);
}




/* send the message over internet */

send_message(char *from_string, char *to_address, char *to_string,
             char *subject, char *tempfile, int first_msg_addr,
             int top_line_addr)
{
   int sd;	/* socket descriptor */
   struct sockaddr_in sockinfo;
   int i, j;
   int len;
   char str[200];
   char buffer[200];
   char errormsg[80];
   boolean error = FALSE;
   char *dummystr;
   FILE *mail_msg;
   char tmpStr[80];
   time_t theTime;
   struct tm *t_time;


   dummystr = (char *) malloc(LINE_SIZE);

   if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
   {
      strcpy(errormsg, "Error: socket could not be opened.\n");
      error_alert(errormsg, msgwin, headerwin, first_msg_addr, top_line_addr);
      error = TRUE;
   }

   bzero((char *) &sockinfo, sizeof(sockinfo));
   sockinfo.sin_family = AF_INET;
   sockinfo.sin_addr.s_addr = inet_addr(to_address);	/* specify address */
   sockinfo.sin_port = htons(25);

   if (connect(sd, (struct sockaddr *) &sockinfo, sizeof(sockinfo)) == -1)
   {
      strcpy(errormsg, "Error: bad connection.\n");
      error_alert(errormsg, msgwin, headerwin, first_msg_addr, top_line_addr);
      error = TRUE;
   }

   if (!error)
   {
   read(sd, buffer, sizeof(buffer));

   strcpy(str, "HELO\n");
   write(sd, str, strlen(str));
   len = read(sd, buffer, sizeof(buffer));
   buffer[len] = '\0';

   strcpy(str, "MAIL FROM: ");		/* send the MAIL FROM: line */
   strcat(str, from_string);
   i = strlen(str);
   str[i] = '\n';
   str[i+1] = '\0';
   write(sd, str, strlen(str));
   len = read(sd, buffer, sizeof(buffer));
   buffer[len] = '\0';

   strcpy(str, "RCPT TO: ");		/* send the RCPT TO: line */
   strcat(str, to_string);
   i = strlen(str);
   str[i] = '\n';
   str[i+1] = '\0';
   write(sd, str, strlen(str));
   len = read(sd, buffer, sizeof(buffer));
   buffer[len] = '\0';

   if (!(strncmp(buffer, "250", 3) == 0))
   {
      werase(msgwin);
      wmove(msgwin, 1, 0);
      wprintw(msgwin, "User does not exist!\n");
      wrefresh(msgwin);
   }
   else
   {
   strcpy(str, "DATA\n");		/* begin sending DATA */
   write(sd, str, strlen(str));
   len = read(sd, buffer, sizeof(buffer));
   buffer[len] = '\0';

   strcpy(str, "From: ");		/* output a From: line */
   strcat(str, from_string);
   i = strlen(str);
   str[i] = '\n';
   str[i+1] = '\0';
   write(sd, str, strlen(str));

   strcpy(str, "To: ");			/* output a To: line */
   strcat(str, to_string);
   i = strlen(str);
   str[i] = '\n';
   str[i+1] = '\0';
   write(sd, str, strlen(str));

   strcpy(str, subject);		/* output subject */
   i = strlen(str);
   if (str[i-1] != '\n')
   {
      str[i] = '\n';
      str[i+1] = '\0';
   }
   write(sd, str, strlen(str));

   time(&theTime);			/* get system time */
   t_time = (struct tm *) localtime(&theTime);
   strftime(tmpStr, 80, "Date: %a, %d %b %Y %H:%M:%S  %z\n", t_time);
   write(sd, tmpStr, strlen(tmpStr));

   strcpy(str, "\n");
   write(sd, str, strlen(str));

   mail_msg = fopen(tempfile, "r");
   while (fgets(buffer, 80, mail_msg) != NULL)	/* output tempfile contents */
   {
      if ((buffer[0] == '.') && (buffer[1] == '\n'))
      {
         buffer[1] = '.';			/* fix a . on line by itself */
         buffer[2] = '\n';
      }
      if (strncmp(buffer, "From", 4) == 0)
      {
         strcpy(dummystr, buffer);		/* detect another From line */
         buffer[0] = '>';
         buffer[1] = '\0';
         strcat(buffer, dummystr);
      }
      write(sd, buffer, strlen(buffer));
   }
   fclose(mail_msg);
   buffer[0] = '\n';			/* indicate end of message */
   buffer[1] = '.';
   buffer[2] = '\n';
   write(sd, buffer, strlen(buffer));
   len = read(sd, buffer, sizeof(buffer));
   buffer[len] = '\0';

   strcpy(str, "quit\n");		/* quit sending mail */
   write(sd, str, strlen(str));
   len = read(sd, buffer, sizeof(buffer));
   buffer[len] = '\0';

   werase(msgwin);
   wmove(msgwin, 1, 0);
   wprintw(msgwin, "Message sent.");
   wrefresh(msgwin);
   }
   }

   close(sd);
}




/* socket error subroutine */

error_alert(char *errormsg, WINDOW *msgwin, WINDOW *headerwin,
            int first_msg_addr, int top_line_addr)
{
   int key;

   werase(msgwin);
   wmove(msgwin, 0, 0);
   wprintw(msgwin, errormsg);
   wrefresh(msgwin);
   while(1)
   {
      key = getch();
         if (key > 0)
            break;
   }
   key = getch();
   key = getch();
   key = getch();
   display_message(msgwin, headerwin, (MAIL_MSG *) first_msg_addr,
         (int *) top_line_addr);
}




/* initialize each line pointer */

set_line_link(LINE *link, long int line_pos, int page_no,
              LINE *prev, LINE *next)
{
   link->line_pos = line_pos;
   link->page_no  = page_no;
   link->prev     = prev;
   link->next     = next;
}



/* initialize each message pointer */

set_msg_link(MAIL_MSG *link, long int msg_pos,
             char *from_date, char *subject,
             MAIL_MSG *prev, MAIL_MSG *next)
{
   link->msg_pos = msg_pos;
   strcpy(link->from_date, from_date);
   strcpy(link->subject, subject);
   link->prev    = prev;
   link->next    = next;

   link->first_line.line_pos = 0;	/* init first line */
   link->first_line.page_no  = 0;
   link->first_line.next     = NULL;
   link->first_line.prev     = NULL;
}

