[mod.sources] v06i031: Elm mail system

sources-request@mirror.UUCP (06/30/86)

Submitted by: Dave Taylor <pyramid!hplabs!hpldat!taylor>
Mod.sources: Volume 6, Issue 31
Archive-name: elm/Part06

# Continuation of Shell Archive, created by hpldat!taylor

# This is part 6

# To unpack the enclosed files, please use this file as input to the
# Bourne (sh) shell.  This can be most easily done by the command;
#     sh < thisfilename


if [ ! -d src ]
then
  echo creating directory src
  mkdir src
fi

# ---------- file src/read_rc.c ----------

filename="src/read_rc.c"

if [ -f $filename ]
then
  echo File \"$filename\" already exists\!  Skipping...
  filename=/dev/null		# throw it away
else
  echo extracting file src/read_rc.c...
fi

cat << 'END-OF-FILE' > $filename
/**			read_rc.c			**/

/** (C) Copyright 1985, Dave Taylor			**/

/** This file contains programs to allow the user to have a .elmrc file
    in their home directory containing any of the following: 

	fullname= <username string>
	maildir = <directory>
	mailbox = <file>
	editor  = <editor>
	savemail= <savefile>
	calendar= <calendar file name>
	shell   = <shell>
	print   = <print command>
	weedout = <list of headers to weed out>
	prefix  = <copied message prefix string>
	pager   = <command to use for displaying messages>

	bounceback= <hop count threshold, or zero to disable>
	timeout = <seconds for main menu timeout or zero to disable>

	sortby  = <sent, received, from, size, subject>

	alternatives = <list of addresses that forward to us>

    and/or the logical arguments:
	
	autocopy    [on|off]
	copy        [on|off]	
	resolve     [on|off]
	weed        [on|off]
	noheader    [on|off]
	titles      [on|off]
	editout     [on|off]
	savebyname  [on|off]
	movepage    [on|off]
	pointnew    [on|off]
	hpkeypad    [on|off]
	hpsoftkeys  [on|off]
	signature   [on|off]
	alwaysleave [on|off]
	alwaysdel   [on|off]
	arrow	    [on|off]

    Lines starting with '#' are considered comments and are not checked
    any further!

    Modified 10/85 to know about "Environment" variables..
    Modified 12/85 for the 'prefix' option
    Modified  2/86 for the new 3.3 flags
**/

#include <stdio.h>
#include <ctype.h>

#ifdef BSD
#undef tolower
#endif

#include "headers.h"

char *shift_lower(), *strtok(), *getenv(), *malloc();

#define NOTWEEDOUT	0
#define WEEDOUT		1
#define ALTERNATIVES	2

read_rc_file()
{
	/** this routine does all the actual work of reading in the
	    .rc file... **/

	FILE *file;
	char buffer[SLEN], filename[SLEN];
	char word1[SLEN], word2[SLEN];
	int  errors = 0, last = NOTWEEDOUT;

	sprintf(filename,"%s/%s", home, elmrcfile);

	default_weedlist();

	alternative_addresses = NULL; 	/* none yet! */

	if ((file = fopen(filename, "r")) == NULL) {
	  dprint0(2,"Warning: User has no \".elmrc\" file (read_rc_file)\n");
	  return;	/* we're done! */
	}

	while (fgets(buffer, SLEN, file) != NULL) {
	  no_ret(buffer);	 	/* remove return */
	  if (buffer[0] == '#') { 	/* comment       */
	    last = NOTWEEDOUT;
	    continue;
	  }
	  if (strlen(buffer) < 2) {	/* empty line    */
	    last = NOTWEEDOUT;
	    continue;
	  }

	  breakup(buffer, word1, word2);

	  strcpy(word1, shift_lower(word1));	/* to lower case */

	  if (word2[0] == 0 && (last != WEEDOUT || last != ALTERNATIVES)) {
	    dprint1(2,"Error: Bad .elmrc entry in users file;\n-> \"%s\"\n",
		     buffer);
	    fprintf(stderr, "Badly formed line in \".elmrc\": %s\n", buffer);
	    errors++;
	    continue;
	  }
	
	  if (equal(word1,"maildir") || equal(word1,"folders")) {
	    expand_env(folders, word2);
	    last = NOTWEEDOUT;
	  }
	  else if (equal(word1, "fullname") || equal(word1,"username") ||
		   equal(word1, "name")) {
	    strcpy(full_username, word2);
	    last = NOTWEEDOUT;
	  }
	  else if (equal(word1, "prefix")) {
	    strcpy(prefixchars, word2);
	    last = NOTWEEDOUT;
	  }
	  else if (equal(word1, "shell")) {
	    expand_env(shell, word2);
	    last = NOTWEEDOUT;
	  }
	  else if (equal(word1, "sort") || equal(word1, "sortby")) {
	    strcpy(word2, shift_lower(word2));
	    if (equal(word2, "sent"))
	       sortby = SENT_DATE;
	    else if (equal(word2, "received") || equal(word2,"recieved"))
	       sortby = RECEIVED_DATE;
	    else if (equal(word2, "from") || equal(word2, "sender"))
	       sortby = SENDER;
	    else if (equal(word2, "size") || equal(word2, "lines"))
	      sortby = SIZE;
	    else if (equal(word2, "subject"))
	      sortby = SUBJECT;
	    else if (equal(word2, "reverse-sent") || equal(word2,"rev-sent"))
	       sortby = - SENT_DATE;
	    else if (strncmp(word2, "reverse-rec",11) == 0 || 
		     strncmp(word2,"rev-rec",7) == 0)
	       sortby = - RECEIVED_DATE;
	    else if (equal(word2, "reverse-from") || equal(word2, "rev-from")
	          || equal(word2,"reverse-sender")|| equal(word2,"rev-sender"))
	       sortby = - SENDER;
	    else if (equal(word2, "reverse-size") || equal(word2, "rev-size")
	          || equal(word2, "reverse-lines")|| equal(word2,"rev-lines"))
	      sortby = - SIZE;
	    else if (equal(word2, "reverse-subject") || 
		     equal(word2, "rev-subject"))
	      sortby = - SUBJECT;
	    else {
	     if (! errors)
	       printf("Error reading '.elmrc' file;\n");
	     printf("Don't know what sort key '%s' specifies!\n", word2);
	     errors++;
	     continue;
	   }
	  }
	  else if (equal(word1, "mailbox")) {
	    expand_env(mailbox, word2);
	    last = NOTWEEDOUT;
	  }
	  else if (equal(word1, "editor") || equal(word1,"mailedit")) {
	    expand_env(editor, word2);
	    last = NOTWEEDOUT;
	  }
	  else if (equal(word1, "savemail") || equal(word1, "saveto")) {
	    expand_env(savefile, word2);
	    last = NOTWEEDOUT;
	  }
	  else if (equal(word1, "calendar")) {
	    expand_env(calendar_file, word2);
	    last = NOTWEEDOUT;
	  }
	  else if (equal(word1, "print") || equal(word1, "printmail")) {
	    expand_env(printout, word2);
	    last = NOTWEEDOUT;
	  }
	  else if (equal(word1, "pager") || equal(word1, "page")) {
	    expand_env(pager, word2);
	    last = NOTWEEDOUT;
	  }
	  else if (equal(word1, "autocopy")) {
	    auto_copy = equal(shift_lower(word2), "on");
	    last = NOTWEEDOUT;
	  }
	  else if (equal(word1, "copy") || equal(word1, "auto_cc")) {
	    auto_cc = equal(shift_lower(word2), "on");
	    last = NOTWEEDOUT;
	  }
	  else if (equal(word1, "resolve")) {
	    resolve_mode = equal(shift_lower(word2), "on");
	    last = NOTWEEDOUT;
	  }
	  else if (equal(word1, "weed")) {
	    filter = equal(shift_lower(word2), "on");
	    last = NOTWEEDOUT;
	  }
	  else if (equal(word1, "noheader")) {
	    noheader = equal(shift_lower(word2), "on");
	    last = NOTWEEDOUT;
	  }
	  else if (equal(word1, "titles")) {
	    title_messages = equal(shift_lower(word2), "on");
	    last = NOTWEEDOUT;
	  }
	  else if (equal(word1, "editout")) {
	    edit_outbound = equal(shift_lower(word2), "on");
	    last = NOTWEEDOUT;
	  }
	  else if (equal(word1, "savebyname") || equal(word1, "savename")) {
	    save_by_name = equal(shift_lower(word2), "on");
	    last = NOTWEEDOUT;
	  }
	  else if (equal(word1, "movepage") || equal(word1, "page") ||
		   equal(word1, "movewhenpaged")) {
	    move_when_paged = equal(shift_lower(word2), "on");
	    last = NOTWEEDOUT;
	  }
	  else if (equal(word1, "pointnew") || equal(word1, "pointtonew")) {
	    point_to_new = equal(shift_lower(word2), "on");
	    last = NOTWEEDOUT;
	  }
	  else if (equal(word1, "keypad") || equal(word1, "hpkeypad")) {
	    hp_terminal = equal(shift_lower(word2), "on");
	    last = NOTWEEDOUT;
	  }
	  else if (equal(word1, "softkeys") || equal(word1, "hpsoftkeys")) {
	    hp_softkeys = hp_terminal = equal(shift_lower(word2), "on");
	    last = NOTWEEDOUT;
	  }
	  else if (equal(word1, "signature")) {
	    signature = equal(shift_lower(word2), "on");
	    last = NOTWEEDOUT;
	  }
	  else if (equal(word1, "arrow")) {
	    arrow_cursor = equal(shift_lower(word2), "on");
	    last = NOTWEEDOUT;
	  }
	  else if (equal(word1, "alwaysleave") || equal(word1, "leave")) {
	    always_leave = equal(shift_lower(word2), "on");
	    last = NOTWEEDOUT;
	  }
	  else if (equal(word1, "alwaysdelete") || equal(word1, "delete")) {
	    always_del = equal(shift_lower(word2), "on");
	    last = NOTWEEDOUT;
	  }
	  else if (equal(word1, "bounce") || equal(word1, "bounceback")) {
	    bounceback = atoi(word2);
	    if (bounceback > MAX_HOPS) {
	      fprintf(stderr,
	"Warning: bounceback is set to greater than %d (max-hops) - Ignored.\n",
		       MAX_HOPS);
	      bounceback = 0;
	    }
	    last = NOTWEEDOUT;
	  }
	  else if (equal(word1, "timeout")) {
	    timeout = atoi(word2);
	    if (timeout < 10) {
	      fprintf(stderr,
	   "Warning: timeout is set to less than 10 seconds - Ignored.\n");
	      timeout = 0;
	    }
	    last = NOTWEEDOUT;
	  }
	  else if (equal(word1, "weedout")) {
	    weedout(word2);
	    last = WEEDOUT;
	  }
	  else if (equal(word1, "alternatives")) {
	    alternatives(word2);
	    last = ALTERNATIVES;
	  }
	  else if (last == WEEDOUT)	/* could be multiple line weedout */
	    weedout(buffer);
	  else if (last == ALTERNATIVES)	/* multi-line addresses   */
	    alternatives(buffer);
	  else {
	    fprintf(stderr, "Unknown line from .rc file: %s\n", buffer);
	    errors++;
	  }
	}

	if (errors) 
	  exit(errors);
}
	
weedout(string)
char *string;
{
	/** This routine is called with a list of headers to weed out.   **/

	char *strptr, *header, *cp, *wp;

	strptr = string;

	while ((header = strtok(strptr, "\t ,\"'")) != NULL) {
	  if (strlen(header) > 0) {
	    if ((weedlist[weedcount] = malloc(strlen(header) + 1)) == NULL) {
	      fprintf(stderr,
		      "Too many weed headers - out of memory!  Leaving...\n");
	      exit(1);
	    }
	    for (cp = header, wp = weedlist[weedcount]; *cp != '\0'; cp++)
	      *wp++ = (*cp == '_') ? ' ' : *cp;
	    weedcount++;
	  }
	  strptr = NULL;
	}
}

alternatives(string)
char *string;
{
	/** This routine is called with a list of alternative addresses
	    that you may receive mail from (forwarded) **/

	char *strptr, *address;
	struct addr_rec *current_record, *previous_record;

	previous_record = NULL;

	strptr = (char *) string;

	while ((address = strtok(strptr, "\t ,\"'")) != NULL) {
	  if (previous_record == NULL) {
	    previous_record = (struct addr_rec *) 
			       malloc(sizeof *alternative_addresses);

	    strcpy(previous_record->address, address);
	    previous_record->next = NULL;
	    alternative_addresses = previous_record;
	  }
	  else {
	    current_record = (struct addr_rec *) 
			       malloc(sizeof *alternative_addresses);
	  
	    strcpy(current_record->address, address);
	    current_record->next = NULL;
	    previous_record->next = current_record;
	    previous_record = current_record;
	  }
	  strptr = (char *) NULL;
	}
}

default_weedlist()
{
	/** Install the default headers to weed out!  Many gracious 
	    thanks to John Lebovitz for this dynamic method of 
	    allocation!
	**/

	static char *default_list[] = { ">From", "In-Reply-To:",
		       "References:", "Newsgroups:", "Received:",
		       "Apparently-To:", "Message-Id:", NULL
		     };

	for (weedcount = 0; default_list[weedcount] != NULL; weedcount++) {
	  if ((weedlist[weedcount] = 
	      malloc(strlen(default_list[weedcount]) + 1)) == NULL) {
	    fprintf(stderr, 
	       "\n\rNot enough memory for default weedlist.  Leaving.\n\r");
	    leave(1);
	  }
	  strcpy(weedlist[weedcount], default_list[weedcount]);
	}
}

int
matches_weedlist(buffer)
char *buffer;
{
	/** returns true iff the first 'n' characters of 'buffer' 
	    match an entry of the weedlist **/
	
	register int i;

	for (i=0;i < weedcount; i++)
	  if (strncmp(buffer, weedlist[i], strlen(weedlist[i])) == 0) 
	    return(1);

	return(0);
}

breakup(buffer, word1, word2)
char *buffer, *word1, *word2;
{
	/** This routine breaks buffer down into word1, word2 where 
	    word1 is alpha characters only, and there is an equal
	    sign delimiting the two...
		alpha = beta
	    For lines with more than one 'rhs', word2 is set to the
	    entire string...
	**/

	register int i;
	
	for (i=0;i<strlen(buffer) && isalpha(buffer[i]); i++)
	  word1[i] = buffer[i];

	word1[i++] = '\0';	/* that's the first word! */

	/** spaces before equal sign? **/

	while (buffer[i] == ' ' || buffer[i] == '\t') i++;

	if (buffer[i] == '=') i++;

	/** spaces after equal sign? **/

	while (buffer[i] == ' ' || buffer[i] == '\t') i++;

	if (i < strlen(buffer))
	  strcpy(word2, (char *) (buffer + i));
	else
	  word2[0] = '\0';
}

expand_env(dest, buffer)
char *dest, *buffer;
{
	/** expand possible metacharacters in buffer and then copy
	    to dest... 
	    This routine knows about "~" being the home directory,
	    and "$xxx" being an environment variable.
	**/

	char  *word, *string, next_word[SLEN];
	
	if (buffer[0] == '/') {
	  dest[0] = '/';
	  dest[1] = '\0';
	}
	else
	  dest[0] = '\0';
	string = (char *) buffer;

	while ((word = strtok(string, "/")) != NULL) {
	  if (word[0] == '$') {
#ifdef SUN
	    next_word[0] = '\0';
	    if (getenv((char *) (word + 1)) != NULL)
#endif
	    strcpy(next_word, getenv((char *) (word + 1)));
	    if (strlen(next_word) == 0)
	      leave(fprintf(stderr, 
		    "\n\rCan't expand environment variable '%s'\n\r",
		    word));
	  }
	  else if (word[0] == '~' && word[1] == '\0')
	    strcpy(next_word, home);
	  else
	    strcpy(next_word, word);

	  sprintf(dest, "%s%s%s", dest, (strlen(dest) > 0? "/":""),
		          next_word);

	  string = (char *) NULL;
	}
}
END-OF-FILE

if [ "$filename" != "/dev/null" ]
then
  size=`wc -c < $filename`

  if [ $size != 12722 ]
  then
    echo $filename changed - should be 12722 bytes, not $size bytes
  fi

  chmod 644 $filename
fi

# ---------- file src/hdrconfg.c ----------

filename="src/hdrconfg.c"

if [ -f $filename ]
then
  echo File \"$filename\" already exists\!  Skipping...
  filename=/dev/null		# throw it away
else
  echo extracting file src/hdrconfg.c...
fi

cat << 'END-OF-FILE' > $filename

/**			hdrconfg.c			**/

/**   This file contains the routines necessary to be able to modify
      the mail headers of messages on the way off the machine.  The
      headers currently supported for modification are:

	Subject:
	To:
	Cc:
	Reply-To:

	Expiration-Date:
	Priority:
        In-Reply-To:
	Action:
	Security:
	
      (C) Copyright 1985, Dave Taylor
**/

#include <stdio.h>
#include "headers.h"

#include <ctype.h>

#ifdef BSD
#undef toupper
#endif

/* these are all defined in the mailout file! */

extern char subject[SLEN], action[SLEN], in_reply_to[SLEN], expires[SLEN], 
	    priority[SLEN], reply_to[SLEN];
extern char to[VERY_LONG_STRING], cc[VERY_LONG_STRING];

edit_headers()
{
	/** Edit headers.  **/

	int unexpanded_to = TRUE, unexpanded_cc = TRUE;
	char c, expanded_to[VERY_LONG_STRING], expanded_cc[VERY_LONG_STRING];
	
	if (mail_only) goto outta_here;		/* how did we get HERE??? */

#ifdef INTERNET_ADDRESS_FORMAT
# ifdef DOMAINS
	sprintf(reply_to, "%s <%s@%s%s>", full_username,
		username, hostname, DOMAIN);
# else
	sprintf(reply_to, "%s <%s@%s>", full_username,
		username, hostname);
# endif
#else
	sprintf(reply_to, "%s <%s!%s>", full_username,
		hostname, username);
#endif

	display_headers();

	do {
	  PutLine0(LINES-1,0,"Choice: ");
	  CleartoEOLN();
	  c = toupper(getchar());
	  clear_error();
	  switch (c) {
	    case ctrl('M'):
	    case 'Q' : goto outta_here;
	    case ctrl('L') : display_headers();
		       break;
	    case 'T' : if (optionally_enter(to, 2, 9, TRUE) == -1)
	                 goto outta_here;
	    	       build_address(strip_commas(to), expanded_to);
		       unexpanded_to = FALSE; 
		       break;
	    case 'S' : if (optionally_enter(subject, 4, 9, FALSE) == -1)
			 goto outta_here;
		       break;
	    case 'C' : if (optionally_enter(cc, 5, 9, TRUE) == -1)
			 goto outta_here;
	  	       build_address(strip_commas(cc), expanded_cc);
		       unexpanded_cc = FALSE;
		       break;
	    case 'R' : if (optionally_enter(reply_to, 7, 11, FALSE) == -1)
			 goto outta_here;
		       break;
	    case 'A' : if (optionally_enter(action, 8, 9, FALSE) == -1)
			 goto outta_here;
		       break;
	    case 'E' : enter_date(9, 17, expires);
		       break;
	    case 'P' : if (optionally_enter(priority, 10,10, FALSE) == -1)
			 goto outta_here;
		       break;
	    case 'I' : if (strlen(in_reply_to > 0)) {
	                 if (optionally_enter(in_reply_to, 11,13, FALSE) == -1)
			   goto outta_here;
			 break;		
		       }
		       /** else fall through as an error **/
	    default  : error("Unknown header being specified!");
	  }
	} while (TRUE);

outta_here:	/* this section re-expands aliases before we leave... */

	if (unexpanded_to)
	  build_address(strip_commas(to), expanded_to);
	if (unexpanded_cc)
	  build_address(strip_commas(cc), expanded_cc);

	strcpy(to, expanded_to);
	strcpy(cc, expanded_cc);
}

display_headers()
{
	ClearScreen();

	Centerline(0,"Message Header Edit Screen");

	PutLine1(2,0,"To     : %s", to);
	PutLine1(4,0,"Subject: %s", subject);
	PutLine1(5,0,"Cc     : %s", cc);
	PutLine1(7,0,"Reply-To: %s", reply_to);
	PutLine1(8,0,"Action : %s", action);
	PutLine1(9,0,"Expiration-Date: %s", expires);
	PutLine1(10,0,"Priority: %s", priority);
	if (strlen(in_reply_to) > 0)
	  PutLine1(11,0,"In-Reply-To: %s", in_reply_to);

	Centerline(LINES-5, 
	"Choose First Letter of Header or <return> from Editing Headers");
}

enter_date(x, y, buffer)
int x, y;
char *buffer;
{
	/** Enter the number of days this message is valid for, then
	    display at (x,y) the actual date of expiration.  This 
	    routine relies heavily on the routine 'days_ahead()' in
	    the file date.c
	**/

	int days;

	PutLine0(LINES-1,0, "How many days in the future should it expire? ");
	CleartoEOLN();
	Raw(OFF);
	gets(buffer, SLEN);
	Raw(ON);
	sscanf(buffer, "%d", &days);
	if (days < 1)
	  error("That doesn't make sense!");
	else if (days > 14)
	  error("Expiration date must be within two weeks of today");
	else {
	  days_ahead(days, buffer);
	  PutLine0(x, y, buffer);
	}
}
END-OF-FILE

if [ "$filename" != "/dev/null" ]
then
  size=`wc -c < $filename`

  if [ $size != 4054 ]
  then
    echo $filename changed - should be 4054 bytes, not $size bytes
  fi

  chmod 644 $filename
fi

# ---------- file src/help.c ----------

filename="src/help.c"

if [ -f $filename ]
then
  echo File \"$filename\" already exists\!  Skipping...
  filename=/dev/null		# throw it away
else
  echo extracting file src/help.c...
fi

cat << 'END-OF-FILE' > $filename
/**			help.c			**/

/*** help routine for ELM program 

     (C) Copyright 1985, Dave Taylor

***/

#include <ctype.h>
#include "headers.h"

help()
{
	/** Process the top-level request for help from the user **/

	char ch;		/* character buffer for input */
	char *s;		/* string pointer...	      */

	MoveCursor(LINES-7,0);
	CleartoEOS();

	Centerline(LINES-7, "ELM Help System");
	Centerline(LINES-5,
           "Press keys you want help for, '?' for a list, or '.' to end");

	PutLine0(LINES-3, 0, "Help on key: ");

	do {
	  MoveCursor(LINES-3, strlen("Help on key: "));
	  ch = tolower(ReadCh());
	  
	  if (ch == '.') return(0);	/* zero means footer rewrite only */

	  s = "Unknown command.  Use '?' for a list of commands...";

	  switch (ch) {

	    case '?': display_helpfile();	return(1);

	    case '!': s = 
   "! = Escape to the Unix shell of your choice, or just to enter commands";
	       break;
	    case '@': s = 
       "@ = Debug - display a summary of the notes on the header page";
	       break;
	    case '|': s = 
 "| = Pipe the current message or tagged messages to the command specified";
	       break;
	    case '#': s = 
      "# = Debug - display all information known about current message";
	      break;
	    case '%': s = 
   "% = Debug - display the computed return address of the current message";
	       break;
	    case '*': s = "* = Go to the last message in the current mailbox";
	       break;
	    case '-': s = 
	       "- = Go to the previous page of messages in the current mailbox";
	       break;
	    case '=': s = 
                  "'=' = Go to the first message in the current mailbox";
	       break;
	    case ' ': 
	    case '+': s = 
		"+ = Go to the next page of messages in the current mailbox";
	       break;
	    case '/': s = "/ = Search for specified pattern in mailbox";
	       break;
	    case '<': s = 
	       "< = Scan current message for calendar entries (if enabled)";
	       break;
	    case '>': s = 
	       "> = Save current message or tagged messages to specified file";
	       break;
	    case '^': s = 
	       "^ = Toggle the Delete/Undelete status of the current message";
	       break;
	    case 'a': s = 
       "a = Enter the alias sub-menu section.  Create and display aliases";
	       break;
	    case 'b': s = 
    "b = Bounce (remail) a message to someone as if you have never seen it";
	       break;
	    case 'c': s = 
       "c = Change mailboxes, leaving the current mailbox as if 'quitting'";
	       break;
	    case 'd': s = "d = Mark the current message for future deletion";
	       break;
	    case 'e': s = 
       "e = Invoke the editor on the entire mailbox, resync'ing when done";
	       break;
	    case 'f': s = 
      "f = Forward the current message to someone, return address is yours";
	       break;
	    case 'g': s = 
 "g = Group reply not only to the sender, but to everyone who received msg";
	       break;
	    case 'h': s = 
	       "h = Display message with all Headers (ignore weedout list)";
	       break;
	    case 'j': s = 
       "j = Go to the next message.  This is the same as the DOWN arrow";
	       break;
	    case 'k': s = 
       "k = Go to the previous message.  This is the same as the UP arrow";
	       break;
	    case 'm': s = 
               "m = Create and send mail to the specified person or persons";
	       break;
	    case 'n': s = 
               "n = Read the current message, then move current to next messge";
	       break;
	    case 'o': s = "o = Go to the options submenu";
	       break;
	    case 'p': s = 
		"p = Print the current message or the tagged messages";
	       break;
	    case 'q': s = 
		"q = Quit the mailer, asking about deletion, saving, etc";
	       break;
	    case 'r': s = 
  "r = Reply to the message.  This only sends to the originator of the message";
	       break;
	    case 's': s = 
               "s = Save current message or tagged messages to specified file";
	       break;
	    case 't': s = 
               "t = Tag a message for further operations (or untag if tagged)";
	       break;
	    case 'u': s = "u = Undelete - remove the deletion mark on the message";
	       break;
	    case 'x': s = "x = Exit the mail system quickly";
	       break;
    	
	    case '\n':
	    case '\r': s = "<return> = Read the current message";
	       break;
    
	    case ctrl('L'): s = "^L = Rewrite the screen";	
	       break;
            case ctrl('?'):					    /* DEL */
	    case ctrl('Q'): s = "Exit the mail system quickly";
	       break;
	    default : if (isdigit(ch)) 
	            s = "<number> = Make specified number the current message";
	  }

	  ClearLine(LINES-1);
	  Centerline(LINES-1, s);

	} while (ch != '.');
	
	/** we'll never actually get here, but that's okay... **/

	return(0);
}

display_helpfile()
{
	/*** Help me!  Read file 'helpfile' and echo to screen ***/

	FILE *hfile;
	char buffer[SLEN];
	int  lines=0;

	sprintf(buffer, "%s/%s", helphome, helpfile);
	if ((hfile = fopen(buffer,"r")) == NULL) {
	  dprint1(1,"Error: Couldn't open helpfile %s (help)\n", buffer);
	  error1("couldn't open helpfile %s",buffer);
	  return(FALSE);
	}
	
	ClearScreen();

	while (fgets(buffer, SLEN, hfile) != NULL) {
	  if (lines > LINES-3) {
	    PutLine0(LINES,0,"Press any key to continue: ");
	    (void) ReadCh();
	    lines = 0;
	    ClearScreen();
	    Write_to_screen("%s\r", 1, buffer);
	  }
	  else 
	    Write_to_screen("%s\r", 1, buffer);

	  lines++;
	}

        PutLine0(LINES,0,"Press any key to return: ");

	(void) ReadCh();
	clear_error();

	return(TRUE);
}
END-OF-FILE

if [ "$filename" != "/dev/null" ]
then
  size=`wc -c < $filename`

  if [ $size != 5576 ]
  then
    echo $filename changed - should be 5576 bytes, not $size bytes
  fi

  chmod 644 $filename
fi

# ---------- file src/initialize.c ----------

filename="src/initialize.c"

if [ -f $filename ]
then
  echo File \"$filename\" already exists\!  Skipping...
  filename=/dev/null		# throw it away
else
  echo extracting file src/initialize.c...
fi

cat << 'END-OF-FILE' > $filename
/**		initialize.c		**/

/***** Initialize - read in all the defaults etc etc 
       (C) Copyright 1985 Dave Taylor
*****/

#include "headers.h"

#ifdef BSD
#  include <sgtty.h>
#else
#  include <termio.h>
#endif

#include <pwd.h>

#ifdef BSD
#  include <sys/time.h>
#else
#  include <time.h>
#endif

#include <signal.h>
#include <ctype.h>
#include <errno.h>

#ifdef BSD
#undef tolower
#endif


extern int errno;		/* system error number on failure */

char *error_name(), *error_description();

char *expand_logname(), *getenv(), *getlogin();

initialize(initscreen_too)
int initscreen_too;
{
	/** initialize the whole ball of wax.   If "initscreen_too" then
	    call init_screen where appropriate..
	**/
	struct passwd *pass, *getpwnam();

	register int i;
	int      quit_signal(), term_signal(), ill_signal(),
		 fpe_signal(),  bus_signal(),  segv_signal(),
	         alarm_signal(), pipe_signal();
	char     buffer[SLEN], *cp;
	
	userid  = getuid();
	groupid = getgid();	

	strcpy(home,((cp = getenv("HOME")) == NULL)? "" : cp);
	strcpy(shell,((cp = getenv("SHELL")) == NULL)? "" : cp);
	strcpy(pager,((cp = getenv("PAGER")) == NULL)? default_pager : cp);

	if (debug) {		/* setup for dprintf statements! */
	  char filename[SLEN];
	  sprintf(filename, "%s/%s", home, DEBUG);
	  if ((debugfile = fopen(filename, "w")) == NULL) {
	    debug = 0;	/* otherwise 'leave' will try to log! */
	    leave(fprintf(stderr,"Could not open file %s for debug output!\n",
		  filename));
	  }
	  chown(filename, userid, groupid); /* file owned by user */

	  fprintf(debugfile, "Debug output of the ELM program.  Version %s\n\n",
		  VERSION);
	}

	if (initscreen_too)	/* don't set up unless we need to! */
	  InitScreen();

	signal(SIGINT,  SIG_IGN);
	signal(SIGQUIT, quit_signal);		/* Quit signal 	            */
	signal(SIGTERM, term_signal); 		/* Terminate signal         */
	signal(SIGILL,  ill_signal);		/* Illegal instruction      */
	signal(SIGFPE,  fpe_signal);		/* Floating point exception */
	signal(SIGBUS,  bus_signal);		/* Bus error  		    */
	signal(SIGSEGV, segv_signal);		/* Segmentation Violation   */
	signal(SIGALRM, alarm_signal);		/* Process Timer Alarm	    */
	signal(SIGPIPE, pipe_signal);		/* Illegal Pipe Operation   */

	get_connections();	      /* who do we talk to directly?? */

	open_domain_file();		/* if we got it, we want it!  */

	get_term_chars();
	
	gethostname(hostname, sizeof(hostname));
	if ((cp = getlogin()) == NULL)
	  cuserid(username);
	else
	  strcpy(username, cp);

	/* now let's get the full username.. */

	if ((pass = getpwnam(username)) == NULL) {
	  error("Couldn't read password entry??");
	  strcpy(full_username, username);
	}
	else {
	  for (i=0; pass->pw_gecos[i] != '\0' && pass->pw_gecos[i] != ',';
	       i++)
	      if (pass->pw_gecos[i] == '&') {
	        full_username[i] = '\0';
	        strcat(full_username, expand_logname());
	        i = strlen(full_username) - 2;
	      }
	      else
	        full_username[i] = pass->pw_gecos[i];
	  full_username[i] = '\0'; 
	}

	if ((cp = getenv("EDITOR")) == NULL)
	  strcpy(editor,default_editor);
	else
	  strcpy(editor, cp);

	if (! mail_only) {
	  mailbox[0] = '\0';
	  strcpy(prefixchars, "> "); 	/* default message prefix */
	}

	/* get the default calendar file name loaded... */

	sprintf(calendar_file, "%s/%s", home, dflt_calendar_file);

	read_rc_file();		/* reading the .elmrc next... */

	/** now try to expand the specified filename... **/

	if (strlen(infile) > 0) {
	  (void) expand_filename(infile);
	  if ((errno = can_access(infile, READ_ACCESS))) {
	    dprint2(1,"Error: given file %s as mailbox - unreadable (%s)!\n", 
		     infile, error_name(errno));
	    fprintf(stderr,"Can't open mailbox '%s' for reading!\n", infile);
	    exit(1);
	  }
	}

	/** check to see if the user has defined a LINES or COLUMNS
	    value different to that in the termcap entry (for
	    windowing systems, of course!) **/

	if ((cp = getenv("LINES")) != NULL && isdigit(*cp)) {
	  sscanf(cp, "%d", &LINES);
	  LINES -= 1;	/* kludge for HP Window system? ... */
	}

	if ((cp = getenv("COLUMNS")) != NULL && isdigit(*cp))
	  sscanf(cp, "%d", &COLUMNS);

	/** fix the shell if needed **/

	if (shell[0] != '/') {
	   sprintf(buffer, "/bin/%s", shell);
	   strcpy(shell, buffer);
	}

	if (! mail_only) {
	  mailbox_defined = (mailbox[0] != '\0'); 

	  /* get the cursor control keys... */

	  if ((cp = return_value_of("ku")) == NULL || strlen(cp) != 2)
	    cursor_control = FALSE;
	  else {
	    strcpy(up, cp);
	    if ((cp = return_value_of("kd")) == NULL || strlen(cp) != 2)
	      cursor_control = FALSE;
	    else {
	      strcpy(down, cp);
	      cursor_control = TRUE;
	      transmit_functions(ON);
	    }
	  }

	  strcpy(start_highlight, "->");
	  end_highlight[0] = '\0';

	  if (!arrow_cursor) {	/* try to use inverse bar instead */
	    if ((cp = return_value_of("so")) != NULL) {
	      strcpy(start_highlight, cp);
	      if ((cp = return_value_of("se")) == NULL)
	        strcpy(start_highlight, "->");
	      else {
	        strcpy(end_highlight, cp);
	        has_highlighting = TRUE;
	      }
	    }
	  }
	}

	if (read_aliases)
  	  read_alias_files();

	if (! mail_only) {
	  if (mini_menu)
	    headers_per_page = LINES - 13;
	  else
	    headers_per_page = LINES -  8;	/* 5 more headers! */

	  newmbox(1,FALSE, TRUE);	/* read in the mailbox! */
	}

	init_findnode();	/* set up the path alias stuff */

	dprint0(2,"\n-- end of initialization phase --\n");

	dprint3(2,"\thostname = %s\n\tusername = %s\n\tfull_username = \"%s\"\n",
	         hostname, username, full_username);

	dprint3(2,"\thome = %s\n\teditor = %s\n\tmailbox = %s\n",
		 home, editor, mailbox);

	dprint3(2,"\tinfile = %s\n\tfolder-dir = %s\n\tprintout = \"%s\"\n",
		 infile, folders, printout);
	
	dprint3(2,"\tsavefile = %s\n\tprefix = \"%s\"\n\tshell = %s\n",
		savefile, prefixchars, shell);
	
	dprint0(1,"-- beginning execution phase --\n\n");
}

get_term_chars()
{
	/** This routine sucks out the special terminal characters
	    ERASE and KILL for use in the input routine.  The meaning 
            of the characters are (dare I say it?) fairly obvious... **/

#ifdef BSD
	struct sgttyb term_buffer;

# define TCGETA	TIOCGETP

#else 
	struct termio term_buffer;
#endif

	if (ioctl(STANDARD_INPUT, TCGETA, &term_buffer) == -1) {
	  dprint1(1,"Error: %s encountered on ioctl call (get_term_chars)\n", 
		   error_name(errno));
	  /* set to defaults for terminal driver */
	  backspace = BACKSPACE;
	  kill_line = ctrl('U');
	}
	else {
#ifdef BSD
	  backspace = term_buffer.sg_erase;
	  kill_line = term_buffer.sg_kill;
#else
	  backspace = term_buffer.c_cc[VERASE];
	  kill_line = term_buffer.c_cc[VKILL];
#endif
	}
}

char *expand_logname()
{
	/** Return logname in a nice format (for expanding "&" in the
	    /etc/passwd file) **/

	static char buffer[SLEN];
	register int i;

	if (strlen(username) == 0)
	  buffer[0] = '\0';
	else {
	  buffer[0] = toupper(username[0]);

	  for (i=1; username[i] != '\0'; i++)
	    buffer[i] = tolower(username[i]);

	  buffer[i] = '\0';
	}

	return( (char *) buffer);	
}
END-OF-FILE

if [ "$filename" != "/dev/null" ]
then
  size=`wc -c < $filename`

  if [ $size != 7108 ]
  then
    echo $filename changed - should be 7108 bytes, not $size bytes
  fi

  chmod 644 $filename
fi

# ---------- file src/args.c ----------

filename="src/args.c"

if [ -f $filename ]
then
  echo File \"$filename\" already exists\!  Skipping...
  filename=/dev/null		# throw it away
else
  echo extracting file src/args.c...
fi

cat << 'END-OF-FILE' > $filename
/**			args.c			**/

/** starting argument parsing routines for ELM system...

    (C) Copyright 1986 Dave Taylor
**/

#include "headers.h"

#define DONE		0
#define ERROR		-1

extern char *optional_arg;		/* optional argument as we go */
extern int   opt_index;			/* argnum + 1 when we leave   */

parse_arguments(argc, argv, to_whom)
int argc;
char *argv[], *to_whom;
{
	/** set flags according to what was given to program.  If we are 
	    fed a name or series of names, put them into the 'to_whom' buffer
	    and set "mail_only" to TRUE **/

	register int c = 0, check_size = 0;

	infile[0] = '\0';
	to_whom[0] = '\0';
	batch_subject[0] = '\0';

	while ((c = get_options(argc, argv, "?acd:f:hkKms:z")) > 0) {
	   switch (c) {
	     case 'a' : arrow_cursor++;		break;
	     case 'c' : check_only++;		break;
	     case 'd' : debug = atoi(optional_arg);	break;
	     case 'f' : strcpy(infile, optional_arg); 
	                mbox_specified = 2;  break;
	     case '?' :
	     case 'h' : args_help();
	     case 'k' : hp_terminal++;	break;
	     case 'K' : hp_terminal++; hp_softkeys++;	break;
	     case 'm' : mini_menu = 0;	break;
	     case 's' : strcpy(batch_subject, optional_arg);	break;
	     case 'z' : check_size++;   break;
	    }
	 }

	 if (c == ERROR) {
	   printf(
	    "Usage: %s [achkKmz] [-d level] [-f file] [-s subject] <names>\n\n",
	     argv[0]);
	   args_help();
	}

	if (opt_index < argc) {
	  while (opt_index < argc) {
	    sprintf(to_whom, "%s%s%s", to_whom, 
	            to_whom[0] != '\0'? " " : "", argv[opt_index]);
	    mail_only++;
	    opt_index++;
	  }
	  check_size = 0;	/* NEVER do this if we're mailing!! */
	}

	 if (strlen(batch_subject) > 0 && ! mail_only) 
	   exit(printf(
     "\n\rDon't understand specifying a subject and no-one to send to!\n\r"));

	if (!isatty(fileno(stdin)) && strlen(batch_subject) == 0 && !check_only)
	  strcpy(batch_subject, DEFAULT_BATCH_SUBJECT);

	if (check_size)
	  check_mailfile_size();
}

args_help()
{
	/**  print out possible starting arguments... **/

	printf("\nPossible Starting Arguments for ELM program:\n\n");
	printf("\targ\t\t\tMeaning\n");
	printf("\t -a \t\tArrow - use the arrow pointer regardless\n");
	printf("\t -c \t\tCheckalias - check the given aliases only\n");
	printf("\t -dn\t\tDebug - set debug level to 'n'\n");
	printf("\t -fx\t\tFile - read file 'x' rather than mailbox\n");
	printf("\t -h \t\tHelp - give this list of options\n");
	printf("\t -k \t\tKeypad - enable HP 2622 terminal keyboard\n");
	printf("\t -K \t\tKeypad&softkeys - enable use of softkeys + \"-k\"\n");
	printf("\t -m \t\tMenu - Turn off menu, using more of the screen\n");
	printf("\t -sx\t\tSubject 'x' - for batchmailing\n");
	printf("\t -z \t\tZero - don't enter Elm if no mail is pending\n");
	printf("\n");
	printf("\n");
	exit(1);
}
END-OF-FILE

if [ "$filename" != "/dev/null" ]
then
  size=`wc -c < $filename`

  if [ $size != 2813 ]
  then
    echo $filename changed - should be 2813 bytes, not $size bytes
  fi

  chmod 644 $filename
fi

# ---------- file src/INDEX ----------

filename="src/INDEX"

if [ -f $filename ]
then
  echo File \"$filename\" already exists\!  Skipping...
  filename=/dev/null		# throw it away
else
  echo extracting file src/INDEX...
fi

cat << 'END-OF-FILE' > $filename
Centerline()                             strings.c:411
ClearScreen()                            curses.c:208
CleartoEOLN()                            curses.c:716
CleartoEOS()                             curses.c:751
CursorDown()                             curses.c:317
CursorLeft()                             curses.c:344
CursorRight()                            curses.c:371
CursorUp()                               curses.c:291
EndBold()                                curses.c:411
EndHalfbright()                          curses.c:462
EndInverse()                             curses.c:487
EndMemlock()                             curses.c:538
EndUnderline()                           curses.c:437
HasMemlock()                             curses.c:500
InitScreen()                             curses.c:85
MoveCursor()                             curses.c:232
PutLine0()                               curses.c:614
PutLine1()                               curses.c:668
PutLine2()                               curses.c:684
PutLine3()                               curses.c:700
Raw()                                    curses.c:782
ReadCh()                                 curses.c:821
ScreenSize()                             curses.c:197
StartBold()                              curses.c:398
StartHalfbright()                        curses.c:450
StartInverse()                           curses.c:474
StartMemlock()                           curses.c:512
StartUnderline()                         curses.c:424
Write_to_screen()                        curses.c:588
Writechar()                              curses.c:556
add_alias()                              alias.c:69
add_current_alias()                      alias.c:115
add_site()                               addr_utils.c:62
add_to_alias_text()                      alias.c:163
alarm_signal()                           signals.c:52
alias()                                  alias.c:203
args_help()                              args.c:74
argv_zero()                              strings.c:429
binary_search()                          aliasdb.c:141
bounce_off_remote()                      bounceback.c:37
build_address()                          addr_utils.c:172
build_header_line()                      screen.c:197
bus_signal()                             signals.c:38
bytes()                                  file_utils.c:24
calendar_line()                          calendar.c:133
can_access()                             file_utils.c:51
change_sort()                            options.c:178
chloc()                                  strings.c:334
clean_up()                               strings.c:391
clear_bottom_of_screen()                 showmsg_cmd.c:116
clear_central_message()                  output_utils.c:107
clear_error()                            output_utils.c:22
clear_key()                              softkeys.c:113
compare_dates()                          date.c:291
compare_headers()                        sort.c:41
copy_message()                           fileio.c:14
copy_message_across()                    mailmsg2.c:452
copy_the_msg()                           mailmsg1.c:212
copy_to_self()                           utils.c:133
cuserid()                                opt_utils.c:67
days_ahead()                             date.c:180
define_key()                             softkeys.c:78
define_softkeys()                        softkeys.c:7
delete()                                 delete.c:10
display()                                showmsg.c:100
display_central_message()                output_utils.c:96
display_headers()                        hdrconfg.c:115
display_options()                        options.c:106
display_title()                          showmsg.c:351
display_to()                             mailmsg1.c:236
edit_headers()                           hdrconfg.c:36
edit_mailbox()                           edit.c:15
edit_the_message()                       mailmsg2.c:261
emergency_exit()                         utils.c:18
encode()                                 encode.c:81
enter_date()                             hdrconfg.c:135
error()                                  output_utils.c:35
error1()                                 output_utils.c:47
error2()                                 output_utils.c:57
error_description()                      errno.c:69
error_name()                             errno.c:54
expand_domain()                          domains.c:53
expand_filename()                        file.c:144
expand_group()                           aliaslib.c:66
expand_site()                            aliasdb.c:52
expand_system()                          aliaslib.c:51
explode()                                domains.c:76
extract_info()                           calendar.c:77
find()                                   aliaslib.c:107
find_old_current()                       sort.c:130
find_path_to()                           aliasdb.c:217
findnode()                               aliasdb.c:15
fix_date()                               date.c:257
fix_header_page()                        screen.c:259
fix_time()                               date.c:270
format_long()                            strings.c:134
format_long()                            strings.c:22
forward()                                reply.c:94
forwarded()                              addr_utils.c:295
fpe_signal()                             signals.c:31
from_matches()                           pattern.c:124
full_month()                             date.c:153
generate_reply_to()                      mkhdrs.c:14
get_address_from()                       addr_utils.c:87
get_alias_address()                      aliaslib.c:12
get_and_expand_everyone()                reply.c:124
get_arpa_date()                          date.c:110
get_connections()                        connect_to.c:13
get_copies()                             mailmsg1.c:167
get_date()                               date.c:50
get_entry()                              aliasdb.c:173
get_existing_address()                   return_addr.c:271
get_key_no_prompt()                      encode.c:66
get_line()                               aliaslib.c:148
get_mailtime()                           mailtime.c:63
get_options()                            args.c:98
get_page()                               utils.c:108
get_return()                             return_addr.c:195
get_return_name()                        reply.c:289
get_subject()                            mailmsg1.c:118
get_to()                                 mailmsg1.c:89
get_word()                               strings.c:309
gethostname()                            opt_utils.c:21
getkey()                                 encode.c:25
hash_it()                                aliaslib.c:133
help()                                   help.c:11
if()                                     addr_utils.c:548
if()                                     strings.c:488
ill_signal()                             signals.c:24
in_string()                              strings.c:74
init_findnode()                          aliasdb.c:191
initialize()                             initialize.c:37
install_aliases()                        alias.c:294
isa3270()                                opt_utils.c:40
leave()                                  utils.c:44
leave_locked()                           utils.c:78
leave_mbox()                             leavembox.c:26
lock()                                   leavembox.c:306
mail()                                   mailmsg2.c:24
main()                                   elm.c:12
makekey()                                encode.c:123
match_and_expand_domain()                domains.c:123
match_in_message()                       pattern.c:147
meta_match()                             pattern.c:18
month_number()                           date.c:342
move_left()                              strings.c:223
new_msg()                                mailtime.c:120
newmbox()                                newmbox.c:27
notes_machine()                          notesfile.c:117
num_enter()                              options.c:161
okay_address()                           reply.c:188
on_or_off()                              options.c:137
on_page()                                screen.c:280
one_liner()                              options.c:225
open_domain_file()                       domains.c:37
optimize_and_add()                       reply.c:222
optimize_arpa()                          return_addr.c:112
optimize_cmplx_arpa()                    return_addr.c:48
optimize_return()                        return_addr.c:28
optimize_usenet()                        return_addr.c:148
optionally_enter()                       input_utils.c:65
options()                                options.c:30
outchar()                                curses.c:837
parse_arguments()                        args.c:15
parse_arpa_date()                        addr_utils.c:388
parse_arpa_from()                        addr_utils.c:331
pattern_enter()                          input_utils.c:185
pattern_match()                          pattern.c:82
printable_chars()                        strings.c:54
process_showmsg_command()                showmsg_cmd.c:32
prompt()                                 output_utils.c:67
prompt1()                                output_utils.c:76
quit()                                   quit.c:13
quit_signal()                            signals.c:12
read_alias_files()                       alias.c:15
read_headers()                           newmbox.c:138
read_notesfile()                         notesfile.c:18
read_number()                            input_utils.c:40
read_rc_file()                           read_rc.c:68
read_uuname()                            connect_to.c:79
real_from()                              addr_utils.c:244
real_notes_header()                      notesfile.c:78
recall_last_msg()                        mailmsg2.c:224
remail()                                 remail.c:16
remove_domains()                         addr_utils.c:47
remove_first_word()                      strings.c:239
remove_through_ch()                      calendar.c:167
reply()                                  reply.c:26
reply_to_everyone()                      reply.c:58
resolve_received()                       mailtime.c:18
resync()                                 quit.c:23
return_value_of()                        curses.c:158
reverse()                                strings.c:292
save()                                   file.c:20
save_copy()                              savecopy.c:24
save_message()                           file.c:106
scan_calendar()                          calendar.c:44
segv_signal()                            signals.c:45
send()                                   mailmsg1.c:16
set_central_message()                    output_utils.c:87
set_error()                              output_utils.c:29
setup()                                  encode.c:144
shift_lower()                            strings.c:345
show_alias_menu()                        alias.c:191
show_current()                           screen.c:140
show_headers()                           screen.c:74
show_last_error()                        output_utils.c:15
show_line()                              showmsg.c:260
show_menu()                              screen.c:59
show_message()                           showmsg.c:62
show_msg()                               showmsg.c:24
show_msg_status()                        delete.c:36
show_msg_tag()                           delete.c:59
show_new_status()                        delete.c:70
show_status()                            screen.c:292
showscreen()                             screen.c:11
softkeys_off()                           softkeys.c:103
softkeys_on()                            softkeys.c:92
sort_mailbox()                           sort.c:14
sort_name()                              sort.c:78
sort_one_liner()                         options.c:233
strchr()                                 opt_utils.c:194
strcspn()                                opt_utils.c:106
strip_commas()                           strings.c:185
strip_parens()                           strings.c:200
strpbrk()                                opt_utils.c:173
strspn()                                 opt_utils.c:84
strtok()                                 opt_utils.c:129
subject_matches()                        pattern.c:136
subshell()                               syscall.c:15
suffix()                                 date.c:85
system_call()                            syscall.c:49
tag_message()                            delete.c:47
tail_of()                                strings.c:91
tail_of_string()                         strings.c:255
talk_to()                                addr_utils.c:20
term_signal()                            signals.c:18
tgetstr()                                curses.c:82
tolower()                                strings.c:28
toupper()                                strings.c:43
translate_return()                       addr_utils.c:118
transmit_functions()                     curses.c:177
undelete()                               delete.c:27
unlock()                                 leavembox.c:414
update_mailtime()                        mailtime.c:94
update_title()                           screen.c:39
uucp_hops()                              bounceback.c:17
valid_date()                             date.c:230
valid_name()                             validname.c:17
verify_bounceback()                      mailmsg2.c:484
verify_transmission()                    mailmsg2.c:297
want_to()                                input_utils.c:13
weedout()                                read_rc.c:293
words_in_string()                        strings.c:366
write_header_info()                      mailmsg2.c:363
END-OF-FILE

if [ "$filename" != "/dev/null" ]
then
  size=`wc -c < $filename`

  if [ $size != 13953 ]
  then
    echo $filename changed - should be 13953 bytes, not $size bytes
  fi

  chmod 644 $filename
fi

# ---------- file src/showmsg.c ----------

filename="src/showmsg.c"

if [ -f $filename ]
then
  echo File \"$filename\" already exists\!  Skipping...
  filename=/dev/null		# throw it away
else
  echo extracting file src/showmsg.c...
fi

cat << 'END-OF-FILE' > $filename
/** 			showmsg.c			**/

/** This file contains all the routines needed to display the specified
    message.

   These routines (C) Copyright 1986 Dave Taylor 

   Modified 6/86 to use pager variable!!!   Hurrah!!!!
**/


#include "headers.h"
#include <ctype.h>
#include <errno.h>

#ifdef BSD
#undef tolower
#endif

extern int errno;

char *error_name();

int    memory_lock = FALSE;	/* is it available?? */
int    pipe_abort  = FALSE;	/* did we receive a SIGNAL(SIGPIPE)? */

int
show_msg(number)
int number;
{
	/*** display number'th message.  Get starting and ending lines
	     of message from headers data structure, then fly through
	     the file, displaying only those lines that are between the
	     two!
		Returns non-zero iff screen was changed
	***/

	dprint0(8, "show_msg called\n");

	if (number > message_count) {
	  error1("Only %d messages!", message_count);
	  return(0);
	}
	else if (number < 1) {
	  error("you can't read THAT message!");
	  return(0);
	}

	clearit(header_table[number-1].status, NEW);   /* it's been read now! */

	memory_lock = FALSE;

	/* some explaination for that last one - We COULD use memory locking
	   to speed up the paging, but the action of "ClearScreen" on a screen
	   with memory lock turned on seems to vary considerably (amazingly so)
	   so it's safer to only allow memory lock to be a viable bit of
	   trickery when dumping text to the screen in scroll mode.
	   Philosophical arguments should be forwarded to Bruce at the 
	   University of Walamazoo, Australia, via ACSNet  *wry chuckle* */

	return(show_message(header_table[number-1].lines, 
	       header_table[number-1].offset,number));
}

int
show_message(lines, file_loc, msgnumber)
int lines, msgnumber;
long file_loc;
{
	/*** Show the indicated range of lines from mailfile
	     for message 'msgnumber' by using 'display'
	     Returns non-zero iff screen was altered.
	***/

	dprint3(9,"show_message(%d,%ld,%d)\n", lines, file_loc, msgnumber);

	if (fseek(mailfile, file_loc, 0) != 0) {
	  dprint2(1,"Error: seek %d bytes into file, errno %s (show_message)\n",
		  file_loc, error_name(errno));
	  error1("ELM failed seeking %d bytes into file (%s)",
		  file_loc, error_name(errno));	
	  return(0);
	}

	/* next read will get 'this' line so must be at end of previous */

	Raw(OFF);
	display(lines, msgnumber);
	Raw(ON);
	if (memory_lock) EndMemlock();	/* turn it off!! */

	return(1);	/* we did it boss! */
}
	

/** This next one is the 'pipe' file descriptor for writing to the 
    pager process... **/

FILE   *output_pipe;		

int
display(lines, msgnum)
int lines, msgnum;
{
	/** Display specified number of lines from file mailfile.
	    Note: This routine MUST be placed at the first line 
	    of the input file! 
	    Returns the same as the routine above (namely zero or one)
	**/

	char buffer[VERY_LONG_STRING], *full_month();

	int lines_displayed = 0;	
	int lines_on_screen = 0;		/* display    */
	int crypted = 0, gotten_key = 0;	/* encryption */
	int weed_header, weeding_out = 0;	/* weeding    */ 
	int mail_sent;				/* misc use   */

	dprint3(4,"displaying %d lines from message %d using %s\n", 
		lines, msgnum, pager);

	pipe_abort = FALSE;

	if ((output_pipe = popen(pager,"w")) == NULL) {
	  error2("Can't create pipe to %s [%s]", pager, 
		  error_name(errno));
	  dprint2(1,"\n*** Can't create pipe to %s - error %s ***\n\n",
	   	  pager, error_name(errno));
	  return(0);
	}
	dprint1(4,"Opened a write-only pipe to routine %s \n", pager);

	if (title_messages) {

	  mail_sent = (strncmp(header_table[msgnum-1].from, "To:", 3) == 0);

	  tail_of(header_table[msgnum-1].from, buffer, FALSE);
	  fprintf(output_pipe, "%s #%d %s %s\t%s", 
		   notesfile? "Note" : "Message", msgnum, 
		   mail_sent? "to" : "from", buffer,
		   strlen(buffer) > 16? "" : "\t");
	  fprintf(output_pipe," %s %s %s, %d at %s\n\r%s",
		  notesfile? "Posted" : "Mailed",
     		  full_month(header_table[msgnum-1].month), 
		  header_table[msgnum-1].day, 
	          atoi(header_table[msgnum-1].year) + 1900,
	          header_table[msgnum-1].time,
		  filter? "": "\n\n");

	  if (! mail_sent && matches_weedlist("To:") && filter &&
	      strcmp(header_table[current-1].to,username) != 0 &&
	      strlen(header_table[current-1].to) > 0)
	    fprintf(output_pipe, "\n(message addressed to %s)\n\n", 
		    header_table[current-1].to);
	
	  /** The test above is: if we didn't originally send the mail
	      (e.g. we're not reading "mail.sent") AND the user is currently
	      weeding out the "To:" line (otherwise they'll get it twice!)
	      AND the user is actually weeding out headers AND the message 
	      wasn't addressed to the user AND the 'to' address is non-zero 
	      (consider what happens when the message doesn't HAVE a "To:" 
	      line...the value is NULL but it doesn't match the username 
	      either.  We don't want to display something ugly like 
	      "(message addressed to )" which will just clutter up the 
	      display!).

	      And you thought programming was EASY!!!!
	  **/
	}

	weed_header = filter;	/* allow us to change it after header */

	ClearScreen();

	if (cursor_control) transmit_functions(OFF);

	while (lines > 0 && pipe_abort == FALSE) {

	    if (fgets(buffer, VERY_LONG_STRING, mailfile) == NULL) {
	      if (lines_displayed == 0) {

		/* AUGH!  Why do we get this occasionally???  */

	        dprint0(1,
	   	  "\n\n** Out of Sync!!  EOF with nothing read (display) **\n");
		dprint0(1,"\nLeaving with all temp files intact!\n");
		error("Internal error: out of sync!");
	        pclose(output_pipe);	/* close pipe NOW! */
		emergency_exit();

	      }
	      pclose(output_pipe);
	      if (lines == 0 && pipe_abort == FALSE) {	/* displayed it all */
	        PutLine0(LINES,0,"Press <return> to return to Elm: ");
	        Raw(ON);
	        (void) ReadCh();
	        Raw(OFF);
	      }
	      return(TRUE);
	    }

	    if (strlen(buffer) > 0) 
              no_ret(buffer);

	    if (strlen(buffer) == 0) {
	      weed_header = 0;		/* past header! */
	      weeding_out = 0;
	    }

	    lines--;
	    lines_displayed++;

	    if (notesfile) {	/* treat notes differently! */

	      if (filter && (first_word(buffer, NOTES_HEADER) ||
	          first_word(buffer, NOTES_FOOTER)) ) 

	        /*** weed this line out of the display! ***/;

	      else 
		show_line(buffer);
	    }

	    else { /* "normal" message */

	      if (weed_header && matches_weedlist(buffer)) 
	        weeding_out = 1;	 /* aha!  We don't want to see this! */
	      else if (buffer[0] == '[') {
	        if (strcmp(buffer, START_ENCODE)==0)
		  crypted++;
	        else if (strcmp(buffer, END_ENCODE)==0)
	          crypted--;
	        else if (crypted) {
                  encode(buffer);
	          show_line(buffer);
	        }
	        else
	          show_line(buffer);
	      }
	      else if (crypted) {
	        if (! gotten_key++) getkey(OFF);
	        encode(buffer);
	        show_line(buffer); 
	      }
	      else if (weeding_out) {
	        weeding_out = (whitespace(buffer[0]));	/* 'n' line weed */
	        if (! weeding_out) 	/* just turned on! */
	          show_line(buffer);
	      } 
	      else
	        show_line(buffer);
	    }
	  }

        if (cursor_control) transmit_functions(ON);

	pclose(output_pipe);
	if (lines == 0 && pipe_abort == FALSE) {  	/* displayed it all! */
	  PutLine0(LINES,0,"Press <return> to return to Elm: ");
	  Raw(ON);
	  (void) ReadCh();
	  Raw(OFF);
	}
	return(TRUE);
}

show_line(buffer) 	
char *buffer;
{
	/** Hands the given line to the output pipe **/ 
	
	errno = 0;
	fprintf(output_pipe, "%s\n", buffer);
	
	if (errno != 0)
	  dprint1(1,"\terror %s hit!\n", error_name(errno));
}
END-OF-FILE

if [ "$filename" != "/dev/null" ]
then
  size=`wc -c < $filename`

  if [ $size != 7704 ]
  then
    echo $filename changed - should be 7704 bytes, not $size bytes
  fi

  chmod 666 $filename
fi

# ---------- file src/mkhdrs.c ----------

filename="src/mkhdrs.c"

if [ -f $filename ]
then
  echo File \"$filename\" already exists\!  Skipping...
  filename=/dev/null		# throw it away
else
  echo extracting file src/mkhdrs.c...
fi

cat << 'END-OF-FILE' > $filename
/**			mkhdrs.c		**/

/** This contains all the header generating routines for the ELM
    program.

    (C) Copyright 1985 Dave Taylor

**/

#include <stdio.h>
#include "headers.h"

extern char in_reply_to[SLEN];

generate_reply_to(msg)
int msg;
{
	/** Generate an 'in-reply-to' message... **/
	char buffer[SLEN];


	if (msg == -1)		/* not a reply! */
	  in_reply_to[0] = '\0';
	else {
	  if (chloc(header_table[msg].from, '!') != -1)
	    tail_of(header_table[msg].from, buffer, FALSE);
	  else
	    strcpy(buffer, header_table[msg].from);
	  sprintf(in_reply_to, "Message from \"%s\" of %s %s, %s at %s",
		  buffer,
		  header_table[msg].month,
		  header_table[msg].day,
		  header_table[msg].year,
		  header_table[msg].time);
	}
}
END-OF-FILE

if [ "$filename" != "/dev/null" ]
then
  size=`wc -c < $filename`

  if [ $size != 737 ]
  then
    echo $filename changed - should be 737 bytes, not $size bytes
  fi

  chmod 644 $filename
fi

echo end of this archive file....
exit 0