[comp.mail.elm] Elm 2.1 PL1 part 15 of 22

syd@dsinc.UUCP (Syd Weinstein) (12/13/88)

---- Cut Here and unpack ----
#!/bin/sh
# this is part 15 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file src/mailmsg2.c continued
#
CurArch=15
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
     exit 1; fi
( read Scheck
  if test "$Scheck" != $CurArch
  then echo "Please unpack part $Scheck next!"
       exit 1;
  else exit 0; fi
) < s2_seq_.tmp || exit 1
echo "x - Continuing file src/mailmsg2.c"
sed 's/^X//' << 'SHAR_EOF' >> src/mailmsg2.c
X	      
X	      sprintf(fname, "%s/%s", home, dead_letter);
X
X	      if ((deadfd = fopen(fname,"a")) == NULL) {
X		dprint(1, (debugfile,
X		   "\nAttempt to append to deadletter file '%s' failed: %s\n\r",
X		    fname, error_name(errno)));
X	        printf("Message not saved, Sorry.\n\r\n\r");
X		return('f');
X	      }
X	      else if ((messagefd = fopen(filename, "r")) == NULL) {
X		dprint(1, (debugfile,
X			"\nAttempt to read reply file '%s' failed: %s\n\r",
X			filename, error_name(errno)));
X	        printf("Message not saved, Sorry.\n\r\n\r");
X		return('f');
X	      }
X
X	      chown (fname, userid, groupid);
X	
X	      /* if we get here we're okay for everything, right? */
X
X	      while (fgets(buffer, LONG_SLEN, messagefd) != NULL)
X		fputs(buffer, deadfd);
X
X	      fclose(messagefd);
X	      fclose(deadfd);
X
X	      printf("Message saved in file \"$HOME/%s\"\n\r\n\r", dead_letter);
X
X	      return('f');	/* forget it! */
X	    }
X	    else switch (ch) {
X	      case '\r':
X	      case '\n': ch = 's';
X	      case 's' : printf("Send\n\r");			break;
X	      case 'e' : printf("Edit the message\n\r");	break;
X	      case 'h' : printf("Edit the headers\n\r");	break;
X	      default  : printf("\n\rI'm afraid I don't understand that - please answer again...\n\r");
X			 goto batch_reprompt;
X	    }
X
X	    return(ch);            /* send this baby or whatever!           */
X	  }
X	  else
X	    return('s');	   /*    SEND!  Yow!!                       */
X	}
X	else if (check_first) {    /* used to check strlen(infile) > 0 too? */
Xreprompt:
X	  MoveCursor(LINES,0);
X	  CleartoEOLN();
X	  ClearLine(LINES-1);
X
X	  if (user_level == 0) {
X	    PutLine0(LINES-2,0, "Please choose one of the following options by capitalized letter");
X	    PutLine1(LINES-1,0, "E)dit the message, edit the H)eaders, S)end it, or F)orget it: s%c",
X			   BACKSPACE);
X	  }
X	  else if (*form_letter == PREFORMATTED) 
X	    PutLine1(LINES-1, 0, 
X                 "Choose: edit H)eaders, S)end, or F)orget : s%c",
X	         BACKSPACE);
X	  else if (*form_letter == YES) 
X	    PutLine1(LINES-1, 0, 
X                 "Choose: E)dit form, edit H)eaders, S)end, or F)orget : s%c",
X	         BACKSPACE);
X	  else if (*form_letter == MAYBE) 
X	    PutLine1(LINES-1, 0, 
X        "Choose: E)dit msg, edit H)eaders, M)ake form, S)end, or F)orget : s%c",
X	     BACKSPACE);
X	  else
X	    PutLine1(LINES-1, 0, 
X	     "Please choose: E)dit msg, edit H)eaders, S)end, or F)orget : s%c",
X	     BACKSPACE);
X
X	  fflush(stdin);	/* wait for answer! */
X	  fflush(stdout);
X	  Raw(ON);	/* double check... testing only... */
X	  ch = ReadCh();
X	  ch = tolower(ch);
X
X	  switch (ch) {
X	     case 'f': Write_to_screen("Forget",0);
X	               set_error(
X          "Message kept - Can be restored at next F)orward, M)ail or R)eply ");
X		       break;
X
X	     case '\n' :
X	     case '\r' :
X	     case 's'  : Write_to_screen("Send",0);
X			 ch = 's';		/* make sure! */
X			 break;
X
X	     case 'm'  : if (*form_letter == MAYBE) {
X			   *form_letter = YES;
X		           switch (check_form_file(filename)) {
X			     case -1 : return('f');
X			     case 0  : *form_letter = MAYBE;  /* check later!*/
X				       error("No fields in form!");
X				       return('e');
X			     default : goto reprompt;
X	                   }
X			 }
X			 else {
X	                    Write_to_screen("%c??", 1, 07);	/* BEEP */
X			    sleep(1);
X		            goto reprompt;		/* yech */
X	                 }
X	     case 'e'  :  if (*form_letter != PREFORMATTED) {
X			    Write_to_screen("Edit",0);
X	 	            if (*form_letter == YES) 
X			      *form_letter = MAYBE;
X	                  }
X			  else {
X	                    Write_to_screen("%c??", 1, 07);	/* BEEP */
X			    sleep(1);
X		            goto reprompt;		/* yech */
X	                 }
X			 break;
X	     case 'h'  : Write_to_screen("Headers",0);
X			 break;
X
X	     default   : Write_to_screen("%c??", 1, 07);	/* BEEP */
X			 sleep(1);
X		         goto reprompt;		/* yech */
X	   }
X
X	   return(ch);
X	}
X	else return('s');
X}
X
XFILE *
X#ifdef ALLOW_BCC
X write_header_info(filename, long_to, long_cc, long_bcc, form)
X char *filename, *long_to, *long_cc, *long_bcc;
X#else
X write_header_info(filename, long_to, long_cc, form)
X char *filename, *long_to, *long_cc;
X#endif
Xint   form;
X{
X	/** Try to open filedesc as the specified filename.  If we can,
X	    then write all the headers into the file.  The routine returns
X	    'filedesc' if it succeeded, NULL otherwise.  Added the ability
X	    to have backquoted stuff in the users .elmheaders file!
X	**/
X
X	static FILE *filedesc;		/* our friendly file descriptor  */
X
X#ifdef SITE_HIDING
X	char  buffer[SLEN];
X	int   is_hidden_user;		/* someone we should know about?  */
X#endif
X
X	char  *get_arpa_date();
X
X	if ((filedesc = fopen(filename, "w")) == NULL) {
X	  dprint(1, (debugfile,
X	    "Attempt to open file %s for writing failed! (write_header_info)\n",
X	     filename));
X	  dprint(1, (debugfile, "** %s - %s **\n\n", error_name(errno),
X		 error_description(errno)));
X	  error2("Error %s encountered trying to write to %s", 
X		error_name(errno), filename);
X	  sleep(2);
X	  return(NULL);		/* couldn't open it!! */
X	}
X
X	chown (filename, userid, groupid);
X
X#ifdef SITE_HIDING
X	if ((is_hidden_user = is_a_hidden_user(username))) {
X	  /** this is the interesting part of this trick... **/
X	  sprintf(buffer, "From %s!%s %s\n",  HIDDEN_SITE_NAME,
X		  username, get_ctime_date());
X	  fprintf(filedesc, "%s", buffer);
X	  dprint(1,(debugfile, "\nadded: %s", buffer));
X	  /** so is this perverted or what? **/
X	}
X#endif
X
X
X	/** Subject moved to top of headers for mail because the
X	    pure System V.3 mailer, in its infinite wisdom, now
X	    assumes that anything the user sends is part of the 
X	    message body unless either:
X		1. the "-s" flag is used (although it doesn't seem
X		   to be supported on all implementations??)
X		2. the first line is "Subject:".  If so, then it'll
X		   read until a blank line and assume all are meant
X		   to be headers.
X	    So the gory solution here is to move the Subject: line
X	    up to the top.  I assume it won't break anyone elses program
X	    or anything anyway (besides, RFC-822 specifies that the *order*
X	    of headers is irrelevant).  Gahhhhh....
X	**/
X
X	fprintf(filedesc, "Subject: %s\n", subject);
X
X	  fprintf(filedesc, "To: %s\n", format_long(long_to, strlen("To:")));
X
X	fprintf(filedesc,"Date: %s\n", get_arpa_date());
X
X#ifndef DONT_ADD_FROM
X# ifdef SITE_HIDING
X	if (is_hidden_user)
X	  fprintf(filedesc,"From: %s <%s!%s!%s>\n", full_username,
X		  hostname, HIDDEN_SITE_NAME, username);
X	else
X# endif
X# ifdef  INTERNET_ADDRESS_FORMAT
X#  ifdef  USE_DOMAIN
X	fprintf(filedesc,"From: %s <%s@%s%s>\n", full_username, 
X		username, hostname, DOMAIN);
X#  else
X	fprintf(filedesc,"From: %s <%s@%s>\n", full_username,
X		username, hostname);
X#  endif
X# else
X	fprintf(filedesc,"From: %s <%s!%s>\n", full_username,
X		hostname, username);
X# endif
X#endif
X
X	if (cc[0] != '\0')
X	    fprintf(filedesc, "Cc: %s\n", format_long(long_cc, strlen("Cc: ")));
X
X#ifdef ALLOW_BCC
X	if (bcc[0] != '\0')
X	   fprintf(filedesc, "Bcc: %s\n", 
X		   format_long(long_bcc, strlen("Bcc: ")));
X#endif
X
X	if (strlen(action) > 0)
X	    fprintf(filedesc, "Action: %s\n", action);
X	
X	if (strlen(priority) > 0)
X	    fprintf(filedesc, "Priority: %s\n", priority);
X	
X	if (strlen(expires) > 0)
X	    fprintf(filedesc, "Expires: %s\n", expires);
X	
X	if (strlen(reply_to) > 0)
X	    fprintf(filedesc, "Reply-To: %s\n", reply_to);
X
X	if (strlen(in_reply_to) > 0)
X	    fprintf(filedesc, "In-Reply-To: %s\n", in_reply_to);
X
X	if (strlen(user_defined_header) > 0)
X	    fprintf(filedesc, "%s\n", user_defined_header);
X
X	add_mailheaders(filedesc);
X
X	if (form)
X	  fprintf(filedesc, "Content-Type: mailform\n");
X
X	fprintf(filedesc, "X-Mailer: Elm [version %s]\n\n", version_buff);
X
X	return((FILE *) filedesc);
X}
X
Xcopy_message_across(source, dest)
XFILE *source, *dest;
X{
X	/** copy the message in the file pointed to by source to the
X	    file pointed to by dest.  **/
X
X	int  crypted = FALSE;			/* are we encrypting?  */
X	int  encoded_lines = 0;			/* # lines encoded     */
X	char buffer[LONG_SLEN];			/* file reading buffer */
X
X	while (fgets(buffer, LONG_SLEN, source) != NULL) {
X	  if (buffer[0] == '[') {
X	    if (strncmp(buffer, START_ENCODE, strlen(START_ENCODE))==0)
X	      crypted = TRUE;
X	     else if (strncmp(buffer, END_ENCODE, strlen(END_ENCODE))==0)
X	      crypted = FALSE;
X	     else if (strncmp(buffer, DONT_SAVE, strlen(DONT_SAVE)) == 0)
X	      continue;	/* next line? */
X	    }
X	    else if (crypted) {
X	      if (! gotten_key++)
X	        getkey(ON);
X	      else if (! encoded_lines++)
X	        get_key_no_prompt();		/* reinitialize.. */
X	     
X	      encode(buffer);
X	    }
X	    fputs(buffer, dest);
X	  }
X}
X
Xint
Xverify_bounceback()
X{
X	char	ch;
X
X	/** Ensure the user wants to have a bounceback copy too.  (This is
X	    only called on messages that are greater than the specified 
X	    threshold hops and NEVER for non-uucp addresses.... Returns
X	    TRUE iff the user wants to bounce a copy back.... 
X	 **/
X
X	if (mail_only) {
X	  printf("Would you like a copy \"bounced\" off the remote? (y/n) ");
X	  CleartoEOLN();
X	  printf("n%c", BACKSPACE);
X	  fflush(stdin);				/* wait for answer! */
X	  fflush(stdout);
X	  ch = ReadCh();
X	  if (tolower(ch) != 'y') {
X	    printf("No\n\r");
X	    return(FALSE);
X	  }
X	  else
X	    printf("Yes - Bounceback included\n\r");
X	}
X	else {
X	  MoveCursor(LINES,0);
X	  CleartoEOLN();
X	  PutLine1(LINES,0, 
X		"\"Bounce\" a copy off the remote machine? (y/n) y%c",
X		BACKSPACE);
X	  fflush(stdin);	/* wait for answer! */
X	  fflush(stdout);
X	  ch = ReadCh();
X	  if (tolower(ch) != 'y') { 
X	    Write_to_screen("No", 0);
X	    fflush(stdout);
X	    return(FALSE);
X	  }
X	  Write_to_screen("Yes!", 0);
X	  fflush(stdout);
X	}
X
X	return(TRUE);
X}
SHAR_EOF
echo "File src/mailmsg2.c is complete"
chmod 0444 src/mailmsg2.c || echo "restore of src/mailmsg2.c fails"
echo "x - extracting src/mailtime.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > src/mailtime.c &&
X
Xstatic char rcsid[] = "@(#)$Id: mailtime.c,v 2.1 88/07/21 09:58:59 edc Exp $";
X
X/*******************************************************************************
X *  The Elm Mail System  -  $Revision: 2.1 $   $State: Exp $
X *
X * 			Copyright (c) 1986 Dave Taylor
X *******************************************************************************
X * Bug reports, patches, comments, suggetions should be sent to:
X *
X *	Syd Weinstein, Elm Corrdinator
X *	syd@dsinc.UUCP			dsinc!syd
X *
X *******************************************************************************
X * $Log:	mailtime.c,v $
X * Revision 2.1  88/07/21  09:58:59  edc
X * checked in with -k by syd at 88.09.15.20.28.59.
X * 
X * Revision 2.1  88/07/21  09:58:59  edc
X * Final hacks and cleanup to the 2.1 alpha test release.
X * 
X * Revision 2.0  88/06/27  17:25:18  edc
X * The original 2.0 gamma sources as leaked from HP
X * 
X *
X *
X ******************************************************************************/
X
X/** This set of routines is used to figure out when the user last read
X    their mail and to also figure out if a given message is new or not.
X
X**/
X
X#include "headers.h"
X
X#include <sys/types.h>
X#include <sys/stat.h>
X#ifdef BSD
X#  ifndef BSD4_1
X#    include <sys/time.h>
X#  else
X#    include <time.h>
X#    include <sys/timeb.h>
X#  endif
X#else
X#  include <time.h>
X#endif
X
Xresolve_received(entry)
Xstruct header_rec *entry;
X{
X	/** Entry has the data for computing the time and date the 
X	    message was received.  Fix it and return **/
X
X	switch (tolower(entry->month[0])) {
X	  case 'j' : if (tolower(entry->month[1]) == 'a')
X		       entry->received.month = JANUARY;
X		     else if (tolower(entry->month[2]) == 'n')
X	               entry->received.month = JUNE;
X		     else
X	               entry->received.month = JULY;
X	             break;
X	  case 'f' : entry->received.month = FEBRUARY;
X	 	     break;
X	  case 'm' : if (tolower(entry->month[2]) == 'r')
X	               entry->received.month = MARCH;
X		     else
X		       entry->received.month = MAY;
X	             break;
X	  case 'a' : if (tolower(entry->month[1]) == 'p')
X	               entry->received.month = APRIL;
X	             else
X	               entry->received.month = AUGUST;
X		     break;
X	  case 's' : entry->received.month = SEPTEMBER;
X		     break;
X	  case 'o' : entry->received.month = OCTOBER;
X		     break;
X	  case 'n' : entry->received.month = NOVEMBER;
X	  	     break;
X	  case 'd' : entry->received.month = DECEMBER;
X		     break;
X	}
X
X	sscanf(entry->day, "%d", &(entry->received.day));
X
X	sscanf(entry->year, "%d", &(entry->received.year));
X	if (entry->received.year > 100) entry->received.year -= 1900;
X
X	sscanf(entry->time, "%d:%d", &(entry->received.hour),
X	       &(entry->received.minute));
X}
X
Xget_mailtime()
X{
X	/** Instantiate the values of the last_read_mail stat
X	    variable based on the file access time/date of the
X	    file mailtime_file.  IF the file doesn't exist,
X	    then assume all mail is new. **/
X
X	struct stat buffer;
X	struct tm   *timebuf;
X	char   filename[SLEN];
X#ifdef BSD
X	extern struct tm *localtime();
X#endif
X
X	sprintf(filename, "%s/%s", home, mailtime_file);
X
X	if (stat(filename, &buffer) == -1) {
X	  last_read_mail.month = 0;
X	  last_read_mail.day = 0;
X	  last_read_mail.year = 0;
X	  last_read_mail.hour = 0;
X	  last_read_mail.minute = 0;
X	}
X	else {	/* stat okay... */
X	  timebuf = (struct tm *) localtime(&(buffer.st_mtime));
X	  
X	  last_read_mail.month = timebuf->tm_mon;
X	  last_read_mail.day = timebuf->tm_mday;
X	  last_read_mail.year = timebuf->tm_year;
X	  last_read_mail.hour = timebuf->tm_hour;
X	  last_read_mail.minute = timebuf->tm_min;
X	}
X}
X
Xupdate_mailtime()
X{
X	/** This routine updates the last modified time of the 
X	    .last_read_mail file in the users home directory.
X	    If the file doesn't exist, it creates it!! **/
X
X	char filename[SLEN];
X
X#ifdef BSD
X# ifdef BSD4_1
X	struct timeb  loc_time;
X	time_t tval;
X# else
X	struct timeval	tval[2];
X	struct timezone tzone;
X# endif
X#endif
X	
X	sprintf(filename, "%s/%s", home, mailtime_file);
X
X#ifdef BSD
X# ifdef BSD4_1
X	tval = (time_t) time((long *) 0);
X	if (utime(filename, &tval) == -1)
X# else
X	gettimeofday(&tval[0], &tzone);
X	gettimeofday(&tval[1], &tzone);
X
X	if (utimes(filename, tval) == -1)	/* note the "S" */
X# endif
X#else
X	if (utime(filename, (char *) NULL) == -1)	/* note no "S"  */
X#endif
X	/** That's what I like about programming for BSD & USG - the easy
X	    portability between 'em.  Especially the section 2 calls!! **/
X
X	  (void) creat(filename, 0777);
X}
X
Xnew_msg(entry)
Xstruct header_rec entry;
X{
X	/** Return true if the current message is NEW.  This can be
X	    easily tested by seeing 1) if we're reading the incoming
X	    mailbox and then, if so, 2) if the received_on_machine
X	    date is more recent than the last_read_mail date.
X	**/
X
X	if (mbox_specified != 0) return(FALSE);		/* not incoming */
X	
X	/** Two tests - if received is OLDER than last read mail, then
X	    immediately return FALSE.  If received is NEWER than last
X	    read mail then immediately return TRUE **/
X
X	if (entry.received.year < last_read_mail.year) 
X	  return(FALSE);				
X	
X	if (entry.received.year > last_read_mail.year) 
X	  return(TRUE);				
X	
X	if (entry.received.month < last_read_mail.month)
X	  return(FALSE);			
X
X	if (entry.received.month > last_read_mail.month)
X	  return(TRUE);			
X
X	if (entry.received.day < last_read_mail.day)
X	  return(FALSE);
X
X	if (entry.received.day > last_read_mail.day)
X	  return(TRUE);
X
X	if (entry.received.hour < last_read_mail.hour)		
X	  return(FALSE);		
X	
X	if (entry.received.hour > last_read_mail.hour)		
X	  return(TRUE);		
X	
X	if (entry.received.minute < last_read_mail.minute)
X	  return(FALSE);	
X
X	return(TRUE);
X}
SHAR_EOF
chmod 0444 src/mailtime.c || echo "restore of src/mailtime.c fails"
echo "x - extracting src/mkhdrs.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > src/mkhdrs.c &&
X
Xstatic char rcsid[] = "@(#)$Id: mkhdrs.c,v 2.1 88/07/21 09:59:01 edc Exp $";
X
X/*******************************************************************************
X *  The Elm Mail System  -  $Revision: 2.1 $   $State: Exp $
X *
X * 			Copyright (c) 1986 Dave Taylor
X *******************************************************************************
X * Bug reports, patches, comments, suggetions should be sent to:
X *
X *	Syd Weinstein, Elm Corrdinator
X *	syd@dsinc.UUCP			dsinc!syd
X *
X *******************************************************************************
X * $Log:	mkhdrs.c,v $
X * Revision 2.1  88/07/21  09:59:01  edc
X * checked in with -k by syd at 88.09.15.20.29.01.
X * 
X * Revision 2.1  88/07/21  09:59:01  edc
X * Final hacks and cleanup to the 2.1 alpha test release.
X * 
X * Revision 2.0  88/06/27  17:25:20  edc
X * The original 2.0 gamma sources as leaked from HP
X * 
X *
X *
X ******************************************************************************/
X
X/** This contains all the header generating routines for the ELM
X    program.
X
X**/
X
X#include <stdio.h>
X#include "headers.h"
X
Xextern char in_reply_to[SLEN];
X
Xchar *strcpy();
Xunsigned long sleep();
X
Xgenerate_reply_to(msg)
Xint msg;
X{
X	/** Generate an 'in-reply-to' message... **/
X	char buffer[SLEN];
X
X
X	if (msg == -1)		/* not a reply! */
X	  in_reply_to[0] = '\0';
X	else {
X	  if (chloc(header_table[msg].from, '!') != -1)
X	    tail_of(header_table[msg].from, buffer, FALSE);
X	  else
X	    strcpy(buffer, header_table[msg].from);
X	  sprintf(in_reply_to, "%s; from \"%s\" at %s %s, %s %s",
X		  header_table[msg].messageid,
X		  buffer,
X		  header_table[msg].month,
X		  header_table[msg].day,
X		  header_table[msg].year,
X		  header_table[msg].time);
X	}
X}
X
Xadd_mailheaders(filedesc)
XFILE *filedesc;
X{
X	/** Add the users .mailheaders file if available.  Allow backquoting 
X	    in the file, too, for fortunes, etc...*shudder*
X	**/
X
X	FILE *fd;
X	char filename[SLEN], buffer[LONG_SLEN];
X
X	sprintf(filename, "%s/%s", home, mailheaders);
X
X	if ((fd = fopen(filename, "r")) != NULL) {
X	  while (fgets(buffer, LONG_SLEN, fd) != NULL)
X	    if (strlen(buffer) < 2) {
X	      dprint(2, (debugfile,
X	         "Strlen of line from .elmheaders is < 2 (write_header_info)"));
X	      if (mail_only)
X	        printf("Warning: blank line in %s ignored!\r\n", filename);
X	      else {
X	        error1("Warning: blank line in %s ignored!", filename);
X	        sleep(2);
X	      }
X	    }
X	    else if (occurances_of(BACKQUOTE, buffer) >= 2) 
X	      expand_backquote(buffer, filedesc);
X	    else 
X	      fprintf(filedesc, "%s", buffer);
X
X	    fclose(fd);
X	}
X}
X
Xexpand_backquote(buffer, filedesc)
Xchar *buffer;
XFILE *filedesc;
X{
X	/** This routine is called with a line of the form:
X		Fieldname: `command`
X	    and is expanded accordingly..
X	**/
X
X	FILE *fd;
X	char command[SLEN], command_buffer[SLEN], fname[SLEN],
X	     prefix[SLEN];
X	register int i, j = 0;
X
X	for (i=0; buffer[i] != BACKQUOTE; i++)
X	  prefix[j++] = buffer[i];
X	prefix[j] = '\0';
X
X	j = 0;
X
X	for (i=chloc(buffer, BACKQUOTE)+1; buffer[i] != BACKQUOTE;i++)
X	  command[j++] = buffer[i];
X	command[j] = '\0';
X
X	sprintf(fname,"%s%d", temp_print, getpid());
X
X	sprintf(command_buffer, "%s > %s", command, fname);
X
X	system_call(command_buffer, SH);
X
X	if ((fd = fopen(fname, "r")) == NULL) {
X	  if (mail_only)
X	    printf("\nbackquoted command \"%s\" in .elmheaders failed\n", 
X		   command);
X	  else
X	    error1("backquoted command \"%s\" in .elmheaders failed", command);
X	  return;	
X	}
X
X	/* If we get a line that is less than 80 - length of prefix then we
X	   can toss it on the same line, otherwise, simply prepend each line
X	   *starting with this line* with a leading tab and cruise along */
X
X	if (fgets(command_buffer, SLEN, fd) == NULL) 
X	  fprintf(filedesc, prefix);
X	else {
X	  if (strlen(command_buffer) + strlen(prefix) < 80) 
X	    fprintf(filedesc, "%s%s", prefix, command_buffer);
X	  else
X	    fprintf(filedesc, "%s\n\t%s", prefix, command_buffer);
X	  
X	  while (fgets(command_buffer, SLEN, fd) != NULL) 
X	    fprintf(filedesc, "\t%s", command_buffer);
X	
X	  fclose(fd);
X	}
X
X	unlink(fname);	/* don't leave the temp file laying around! */
X}
SHAR_EOF
chmod 0444 src/mkhdrs.c || echo "restore of src/mkhdrs.c fails"
echo "x - extracting src/newmbox.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > src/newmbox.c &&
X
Xstatic char rcsid[] = "@(#)$Id: newmbox.c,v 2.1.1.2 88/09/23 syd Exp $";
X
X/*******************************************************************************
X *  The Elm Mail System  -  $Revision: 2.1 $   $State: Exp $
X *
X * 			Copyright (c) 1986 Dave Taylor
X *******************************************************************************
X * Bug reports, patches, comments, suggetions should be sent to:
X *
X *	Syd Weinstein, Elm Corrdinator
X *	syd@dsinc.UUCP			dsinc!syd
X *
X *******************************************************************************
X * $Log:	newmbox.c,v $
X * Revision 2.1  88/09/15  20:29:04  syd
X * checked in with -k by syd at 88.09.15.20.29.04.
X * 
X * 88/09/01 Rob Bernardo <gatech!pbhyf.PacBell.COM!rob>
X *  Resend: exiting in cooked mode fix
X *  fix alignment when new mail arrives in existing and in empty box
X *
X * 88/08/27 ssw
X *	add deluth patches
X *
X * Revision 2.1  88/07/21  09:59:02  edc
X * Final hacks and cleanup to the 2.1 alpha test release.
X * 
X * Revision 2.0  88/06/27  17:25:21  edc
X * The original 2.0 gamma sources as leaked from HP
X * 
X *
X *
X ******************************************************************************/
X
X/**  read new mailbox file  **/
X
X#include <ctype.h>
X
X#ifdef BSD
X#undef tolower		/* we have our own "tolower" routine instead! */
X#endif
X
X#include "headers.h"
X
X#include <sys/types.h>		
X#include <sys/stat.h>
X#include <errno.h>
X
X#ifdef BSD			/* Berkeley has library elsewhere... */
X#  ifndef BSD4_1
X#    include <sys/time.h>
X#  else
X#    include <time.h>
X#  endif
X#else
X#  include <time.h>
X#endif
X
Xextern int errno;
X
Xchar *error_name(), *error_description(), *strcpy(), *strncpy();
Xunsigned long sleep();
Xvoid rewind();
Xvoid  exit();
Xlong  bytes();
X
Xstruct header_rec *realloc();
X
Xint
Xnewmbox(stat, resync, main_screen)
Xint stat, resync, main_screen;
X{
X	/** Read a new mailbox file or resync on current file.
X
X	    Values of stat and what they mean;
X
X		stat = 0	- changing mailboxes from within program
X		stat = 1	- read default mailbox or infile for the 
X			          first time
X	        stat = 2	- read existing mailbox, new mail arrived
X	        stat = 3	- resync on existing mailbox...
X
X	    resync is TRUE iff we know the current mailbox has changed.  If
X	    it's set to true this means that we MUST READ SOMETHING, even 
X	    if it's the current mailbox again!!
X
X	    main_screen simply tells where the counting line should be.
X
X	**/
X
X	int  switching_to_default = 0, switching_from_default = 0;
X	int  iterations = 0, redraw = 0; /* for dealing with the '?' answer */
X	int  old_raw;
X	char buff[SLEN];
X
X	if (mbox_specified == 0 && stat == 0)
X	  switching_from_default++;
X
X	if (stat > 0) {
X	  if (stat == 1 && strlen(infile) == 0) {
X
X	    /* Subtlety - check to see if there's another instantiation
X	       of Elm (e.g. if the /tmp file is in use).  If so, DIE! */
X
X	    sprintf(infile, "%s%s", temp_mbox, username);
X	    if (access(infile, ACCESS_EXISTS) != -1) {
X	      error(
X	    "Hey!  An instantiation of Elm is already reading this mail!\n\r");
X	      fprintf(stderr,
X"\n\r     [if this is in error then you'll need to remove '%s%s']\n\r", 
X		  temp_mbox, username);
X	      Raw(OFF);
X              exit(1);
X            }
X            sprintf(infile, "%s%s", mailhome, username);
X	  }
X	  if (strlen(infile) == 0)	/* no filename yet?? */
X	    sprintf(infile,"%s%s",mailhome, username);
X	  if ((errno = can_access(infile, READ_ACCESS))) {
X	    if (strncmp(infile, mailhome, strlen(mailhome)) == 0) {
X	      /* oh wow.  incoming mailbox with no messages... */
X	      return(1);
X	    }
X	    error2("Can't open mailbox '%s' for reading [%s]", infile,
X		    error_name(errno));
X	    Raw(OFF);
X	    exit(1);
X	  }
X	}
X	else { 		 	/* get name of new mailbox! */
X	  MoveCursor(LINES-3, 30);
X	  CleartoEOS();
X	  PutLine0(LINES-3, 40, "(Use '?' to list your folders)");
X	  show_last_error();
Xask_again:
X	  buff[0] = '\0';
X	  if (iterations++ == 0) {
X	    PutLine0(LINES-2,0,"Name of new mailbox: ");
X	    (void) optionally_enter(buff, LINES-2, 21, FALSE);
X	    ClearLine(LINES-2);
X	  }
X	  else {
X	    printf("\n\rName of new mailbox: ");
X	    (void) optionally_enter(buff, -1, -1, FALSE);
X	  }
X	  if (strlen(buff) == 0) {
X	    if (resync && file_changed)
X	      strcpy(buff, infile);
X	    else
X	      return(redraw);
X	  }
X	  if (strcmp(buff, "?") == 0) {
X	    redraw = 1;		/* we'll need to clean the screen */
X	    if (( old_raw = RawState()) == ON)
X	        Raw(OFF);
X	    list_folders();
X	    if (old_raw == ON)
X	        Raw(ON);
X	    goto ask_again;
X	  }
X	  if (strcmp(buff, "!") == 0 ||
X		   strcmp(buff, "%") == 0) 	/* go to mailbox */
X	    sprintf(buff,"%s%s", mailhome, username);
X	  else if (! expand_filename(buff)) {
X	    error1("can't expand file %s", buff);
X	    if (resync && file_changed)
X	      strcpy(buff, infile);
X	    else
X	      return(FALSE);	
X	  }
X
X	  if (strcmp(buff, infile) == 0 && ! resync) { 
X	    error("already reading that mailbox!");
X	    return(FALSE);
X	  }
X
X	  if ((errno = can_access(buff, READ_ACCESS))) {
X	    dprint(2, (debugfile, 
X		     "Error: attempt to open %s as mailbox denied (%s)!\n",
X		     buff, "newmbox"));
X	    error1("Permission to open file %s denied", buff);
X	    if (resync && file_changed)
X	      strcpy(buff, infile);
X	    else
X	      return(FALSE);	
X	  }
X
X	  if (first_word(buff, mailhome)) {	/* a mail file! */
X	    mbox_specified = 0; 	  /* fake program to think that */
X	    stat = 1;		    	  /*     we're the default file */
X	    switching_to_default++;	  /*        remember this act!  */
X	  }
X
X	  if (resync && file_changed && strcmp(buff, infile) == 0)
X	    PutLine0(LINES-3,COLUMNS-40,"Resynchronizing file");
X	  else
X	    PutLine1(LINES-3,COLUMNS-40,"Mailbox: %s", buff);
X	  CleartoEOLN();
X	  strcpy(infile,buff);
X	  if (! switching_to_default) mbox_specified = 1;
X	
X	}
X
X	if (stat == 3) 
X	  switching_from_default = TRUE;
X
X	if (switching_from_default) {	/* we need to remove the tmp file */
X	    sprintf(buff, "%s%s", temp_mbox, username);
X	    if (access(buff, ACCESS_EXISTS) != -1)  /* is it there at all? */
X	      if (unlink(buff) != 0) {
X	        error1(
X	    "Sorry, but I can't seem to unlink your temp mail file [%s]\n\r",
X		error_name(errno));
X                silently_exit();
X	      }
X	}
X
X	clear_error();
X	clear_central_message();
X
X	header_page = 0;
X
X	if (mailfile != NULL)
X	  (void) fclose(mailfile);  /* close it first, to avoid too many open */
X
X	if ((mailfile = fopen(infile,"r")) == NULL) 
X	  message_count = 0;
X	else if (stat != 2) {          /* new mail file! */
X	  current = 1;
X	  save_file_stats(infile);
X	  message_count = read_headers(FALSE, main_screen);
X	  if (! message_count) current = 0;
X	}
X	else {	/* resync with current mail file */
X	  save_file_stats(infile);
X	  message_count = read_headers(TRUE, main_screen);
X	}
X
X	if (stat != 2)
X	  selected = 0;	/* we don't preselect new mailboxes, boss! */
X
X	return(TRUE);
X}
X
Xint
Xread_headers(rereading, main_screen)
Xint rereading, main_screen;
X{
X	/** Reads the headers into the header_table structure and leaves
X	    the file rewound for further I/O requests.   If the file being
X	    read is the default mailbox (ie incoming) then it is copied to
X	    a temp file and closed, to allow more mail to arrive during 
X	    the elm session.  If 'rereading' is set, the program will copy
X	    the status flags from the previous data structure to the new 
X	    one if possible.  This is (obviously) for re-reading a mailfile!
X	**/
X
X	FILE *temp;
X	struct header_rec *temp_struct;
X	char buffer[LONG_STRING], temp_filename[SLEN];
X	long fbytes = 0L, line_bytes = 0L;
X	register int line = 0, count = 0, subj = 0, copyit = 0, in_header = 1;
X	int count_x, count_y = 17, new_messages = 0, err;
X	int in_to_list = FALSE, forwarding_mail = FALSE, first_line = TRUE;
X
X	static int first_read = 0;
X
X	if (! first_read++) {
X	  ClearLine(LINES-1);
X	  ClearLine(LINES);
X	  if (rereading)
X	    PutLine2(LINES, 0, "Reading in %s, message: %d", infile, 
X		     message_count);
X	  else
X	    PutLine1(LINES, 0, "Reading in %s, message: 0", infile);
X	  count_x = LINES;
X          count_y = 22 + strlen(infile);
X	}
X	else {
X	  count_x = LINES-2;
X	  if (main_screen)
X	    PutLine0(LINES-2, 0, "Reading message: 0");
X	  else {
X	    PutLine0(LINES, 0, "\n");
X	    PutLine0(LINES, 0, "Reading message: 0");
X	    count_x = LINES;
X	  }
X	}
X
X	if (mbox_specified == 0) {
X	  lock(INCOMING);	/* ensure no mail arrives while we do this! */
X	  sprintf(temp_filename,"%s%s",temp_mbox, username);
X	  if (! rereading) {
X	    if (access(temp_filename, ACCESS_EXISTS) != -1) {
X	      /* Hey!  What the hell is this?  The temp file already exists? */
X	      /* Looks like a potential clash of processes on the same file! */
X	      unlock();				     /* so remove lock file! */
X	      error("What's this?  The temp mailbox already exists??");
X	      sleep(2);
X	      error("Ahhhh.....I give up");
X	      silently_exit();	/* leave without tampering with it! */
X	    }
X	    if ((temp = fopen(temp_filename,"w")) == NULL) {
X	     err = errno;
X	     unlock();	/* remove lock file! */
X	     Raw(OFF);
X	     Write_to_screen(
X		     "\nCouldn't open file %s for use as temp mailbox;\n", 1,
X	             temp_filename);
X	     Write_to_screen("** %s - %s **\n", 2,
X		     error_name(err), error_description(err));
X	     dprint(1, (debugfile,
X                "Error: Couldn't open file %s as temp mbox.  errno %s (%s)\n",
X	         temp_filename, error_name(err), "read_headers"));
X	     leave();
X	    }
X	   get_mailtime();
X	   copyit++;
X	   chown(temp_filename, userid, groupid);
X	   chmod(temp_filename, 0700);	/* shut off file for other people! */
X	 }
X	 else {
X	   if ((temp = fopen(temp_filename,"a")) == NULL) {
X	     err = errno;
X	     unlock();	/* remove lock file! */
X	     Raw(OFF);
X	     Write_to_screen(
X		     "\nCouldn't reopen file %s for use as temp mailbox;\n", 1,
X	             temp_filename);
X	     Write_to_screen("** %s - %s **\n", 2,
X		     error_name(err), error_description(err));
X	     dprint(1, (debugfile, 
X                "Error: Couldn't reopen file %s as temp mbox.  errno %s (%s)\n",
X	         temp_filename, error_name(err), "read_headers"));
X	     emergency_exit();
X	    }
X	   copyit++;
X	  }
X	}
X
X	if (rereading) {
X	   if (fseek(mailfile, mailfile_size, 0) == -1) {
X	     err = errno;
X	     Write_to_screen(
X		"\nCouldn't seek to %ld (end of mailbox) in %s!\n", 2,
X	     	mailfile_size, infile);	
X	     Write_to_screen("** %s - %s **\n", 2,
X		     error_name(err), error_description(err));
X	     dprint(1, (debugfile,
X     "Error: Couldn't seek to end of mailbox %s: (offset %ld) Errno %s (%s)\n",
X	        infile, mailfile_size, error_name(err), "read_headers"));
X	     emergency_exit();
X	   }
X	   count = message_count;		/* next available  */
X	   fbytes = mailfile_size;		/* start correctly */
X	}
X
X	/** find the size of the mailbox then unlock the file **/
X
X	mailfile_size = bytes(infile);
X	unlock();
X
X	/** now let's copy it all across accordingly... **/
X
X	while (fbytes < mailfile_size) {
X
X	  if (fgets(buffer, LONG_STRING, mailfile) == NULL) break;
X
X	  if (fbytes == 0L || first_line) { 	/* first line of file... */	
X	    if (! mbox_specified) {
X	      if (first_word(buffer, "Forward to ")) {
X	        set_central_message("Mail being forwarded to %s", 
X                   (char *) (buffer + 11));
X	        forwarding_mail = TRUE;
X	      }
X	    }
X
X	    /** flush leading blank lines before next test... **/
X	    if (strlen(buffer) == 1) {
X	      fbytes++;
X	      continue;	
X	    }
X	    else
X	      first_line = FALSE;
X	      	
X	    if (! first_word(buffer, "From ") && !forwarding_mail) {
X	      PutLine0(LINES, 0, 
X		  "\n\rMail file is corrupt!!  I can't read it!!\n\r\n\r");
X	      fflush(stderr);
X	      dprint(1, (debugfile, 
X			   "\n\n**** First mail header is corrupt!! ****\n\n"));
X	      dprint(1, (debugfile, "Line is;\n\t%s\n\n", buffer));
X              mail_only++;	/* to avoid leave() cursor motion */
X              leave();
X	    }
X	  }
X
X	  if (copyit) fputs(buffer, temp);
X	  line_bytes = (long) strlen(buffer); 
X	  line++;
X	  if (first_word(buffer,"From ")) {
X	
X	    /** try to allocate new headers, if needed... **/
X
X	    if (count >= max_headers) {
X	      max_headers += KLICK;
X	      if ((temp_struct = realloc(header_table, max_headers * 
X		   sizeof(struct header_rec))) == NULL) {
X	        error1(
X      "\n\r\n\rCouldn't allocate enough memory!  Failed on message #%d\n\r\n\r",
X			count);
X	        leave();
X	       }
X	       header_table = temp_struct;
X	     }
X	      
X	    if (real_from(buffer, &header_table[count])) {
X	      header_table[count].offset = (long) fbytes;
X	      header_table[count].index_number = count+1;
X	      if (! rereading || count >= message_count) 
X	        header_table[count].status = VISIBLE;     /* default status! */
X	      strcpy(header_table[count].subject, "");	/* clear subj    */
X	      strcpy(header_table[count].to, "");	/* clear to    */
X
X	      /* Set the number of lines for the _preceding_ message,
X	       * but only if there was a preceding message and
X	       * only if it wasn't calculated already. It would
X	       * have been calculated already if we are only
X	       * reading headers of new messages that have just arrived,
X	       * and the preceding message was one of the old ones.
X	       */
X	      if ((count) && (!rereading || count > message_count))
X	        header_table[count-1].lines = line;
X	      if (new_msg(header_table[count])) {
X	        header_table[count].status |= NEW;	/* new message!  */
X
X	        if (! new_messages++ && point_to_new && ! rereading &&
X	            sortby == RECEIVED_DATE) {
X		  current = count+1;
X	          get_page(current);	/* make sure we're ON that page! */
X	        }
X
X		/* Quick comment on that last conditional test...
X
X		   We want to move the current pointer to the first new
X		   message IF this is the first of the new messages, the
X		   user requested this feature, we're not rereading the 
X		   mailbox (imagine how THAT could screw the user up!),
X		   and we're not in some funky sorting mode (received-date is
X		   the default).  As always, I'm open to suggestions on
X		   other ways to have this work intelligently.
X		*/
X	
X	      }
X	      count++;
X	      subj = 0;
X	      line = 0;
X	      in_header = 1;
X	      PutLine1(count_x, count_y, "%d", count);
X	    }
X	  }
X	  else if (in_header) {
X	    if (first_word(buffer,">From:"))
X	      parse_arpa_from(buffer, header_table[count-1].from);
X	    else if (first_word(buffer,">From")) 
X	      forwarded(buffer, &header_table[count-1]); /* return address */
X	    else if (first_word(buffer,"Subject:") ||
X		     first_word(buffer,"Subj:") ||
X		     first_word(buffer,"Re:")) {
X	      if (! subj++) {
X	        remove_first_word(buffer);
X	        copy_sans_escape(header_table[count-1].subject, buffer, STRING);
X		remove_possible_trailing_spaces(header_table[count-1].subject);
X	      }
X	    }
X	    else if (first_word(buffer,"From:"))
X	      parse_arpa_from(buffer, header_table[count-1].from);
X
X	    else if (first_word(buffer, "Message-Id:") ||
X		     first_word(buffer, "Message-ID:")) {
X	      buffer[strlen(buffer)-1] = '\0';
X	      strcpy(header_table[count-1].messageid,
X		     (char *) buffer + 12);
X	    }
X
X	    else if (first_word(buffer, "Expires:"))
X	      process_expiration_date((char *) buffer + 9, 
X				      &(header_table[count-1].status));
X	    
X	    /** when it was sent... **/
X
X	    else if (first_word(buffer, "Date:")) 
X	      parse_arpa_date(buffer, &header_table[count-1]);
X
X	    /** some status things about the message... **/
X
X	    else if (first_word(buffer, "Priority:") || 
X		     first_word(buffer, "Importance: 2"))
X	      header_table[count-1].status |= URGENT;
X	    else if (first_word(buffer, "Sensitivity: 2"))
X	      header_table[count-1].status |= PRIVATE;
X	    else if (first_word(buffer, "Sensitivity: 3"))
X	      header_table[count-1].status |= CONFIDENTIAL;
X	    else if (first_word(buffer, "Content-Type: mailform"))
X	      header_table[count-1].status |= FORM_LETTER;
X	    else if (first_word(buffer, "Action:"))
X	      header_table[count-1].status |= ACTION;
X
X	    /** next let's see if it's to us or not... **/
X
X	    else if (first_word(buffer, "To:")) {
X	      in_to_list = TRUE;
X	      header_table[count-1].to[0] = '\0';	/* nothing yet */
X	      figure_out_addressee((char *) buffer +3, 
X				   header_table[count-1].to);
X	    }
X
X	    else if (buffer[0] == LINE_FEED || buffer[0] == '\0') {
X	      if (in_header) {
X	        in_header = 0;	/* in body of message! */
X	        fix_date(&header_table[count-1]);
X	      }
X	    }
X	    else if (in_to_list == TRUE) {
X	      if (whitespace(buffer[0]))
X	        figure_out_addressee(buffer, header_table[count-1].to);
X	      else in_to_list = FALSE;
X	    }
X	  }
X	  fbytes += (long) line_bytes;
X	}
X
X	header_table[count > 0? count-1:count].lines = line + 1;
X	if(count && ! current) current = 1;
X	
X	if (mbox_specified == 0) {
X	  unlock();	/* remove lock file! */
X	  fclose(mailfile);
X	  fclose(temp);
X	  if ((mailfile = fopen(temp_filename,"r")) == NULL) {
X	    err = errno;
X	    MoveCursor(LINES,0);
X	    Raw(OFF);
X	    Write_to_screen("\nAugh! Couldn't reopen %s as temp mail file;\n",
X	           1, temp_filename);
X	    Write_to_screen("** %s - %s **\n", 2, error_name(err),
X		   error_description(err));
X	    dprint(1, (debugfile,
X          "Error: Reopening %s as temp mail file failed!  errno %s (%s)\n",
X	           temp_filename, error_name(errno), "read_headers"));
X	    leave();
X	  }
X	}
X	else 
X          rewind(mailfile);
X
X	sort_mailbox(count, 1);	 		/* let's sort this baby now! */
X
X	return(count);
X}
SHAR_EOF
chmod 0444 src/newmbox.c || echo "restore of src/newmbox.c fails"
echo "x - extracting src/opt_utils.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > src/opt_utils.c &&
X
Xstatic char rcsid[] = "@(#)$Id: opt_utils.c,v 2.1.1.2 88/09/23 edc Exp $";
X
X/*******************************************************************************
X *  The Elm Mail System  -  $Revision: 2.1 $   $State: Exp $
X *
X * 			Copyright (c) 1986 Dave Taylor
X *******************************************************************************
X * Bug reports, patches, comments, suggetions should be sent to:
X *
X *	Syd Weinstein, Elm Corrdinator
X *	syd@dsinc.UUCP			dsinc!syd
X *
X *******************************************************************************
X * $Log:	opt_utils.c,v $
X * Revision 2.1  88/07/21  09:59:07  edc
X * checked in with -k by syd at 88.09.15.20.29.07.
X * 
X * Revision 2.1  88/07/21  09:59:07  edc
X * Final hacks and cleanup to the 2.1 alpha test release.
X * 
X * Revision 2.0  88/06/27  17:25:22  edc
X * The original 2.0 gamma sources as leaked from HP
X * 
X *
X *
X ******************************************************************************/
X
X/** This file contains routines that might be needed for the various
X     machines that the mailer can run on.  Please check the Makefile
X     for more help and/or information. 
X
X**/
X
X#include <stdio.h>
X#include "headers.h"
X
X#ifdef BSD
X# include <pwd.h>
X#endif
X
X#ifdef NEED_GETHOSTNAME
X#  include <sys/types.h>
X#  include <sys/utsname.h>
X#endif
X
X#ifdef NEED_GETHOSTNAME
X
Xgethostname(hostname,size) /* get name of current host */
Xint size;
Xchar *hostname;
X{
X	/** Return the name of the current host machine. **/
X
X	/** This routine compliments of Scott McGregor at the HP
X	    Corporate Computing Center **/
X     
X	int uname();
X	struct utsname name;
X
X	(void) uname(&name);
X	(void) strncpy(hostname,name.nodename,size-1);
X	hostname[size - 1] = '\0';
X
X}
X
X#endif
X
X#ifdef NEED_CUSERID
X
Xchar *cuserid(uname)
X     char *uname;
X{
X	/** Added for compatibility with Bell systems, this is the last-ditch
X	    attempt to get the users login name, after getlogin() fails.  It
X	    instantiates "uname" to the name of the user...(it also tries
X	    to use "getlogin" again, just for luck)
X	**/
X	/** This wasn't really compatible.  According to our man page, 
X	 ** It was inconsistent.  If the parameter is NULL then you return
X	 ** the name in a static area.  Else the ptr is supposed to be a
X	 ** pointer to l_cuserid bytes of memory [probally 9 bytes]...
X	 ** It's not mention what it should return if you copy the name
X	 ** into the array, so I chose NULL.
X	 ** 					Sept 20, 1988
X	 **					**WJL**
X	 **/
X
X  struct passwd *password_entry, *getpwuid();
X  char   *name, *getlogin();
X  static char buf[10];
X  register returnonly = 0;
X  
X  if (uname == NULL) ++returnonly;
X  
X  if ((name = getlogin()) != NULL) {
X    if (returnonly) {
X      return(name);
X    } else {
X      strcpy(uname, name);
X      return name;
X    }
X  } 
X  else 
X    if (( password_entry = getpwuid(getuid())) != NULL) 
X      {
X	if (returnonly) 
X	  {
X	    return(password_entry->pw_name);
X	  }
X	else 
X	  {
X	    strcpy(uname, password_entry->pw_name);
X	    return name;
X	  }
X      } 
X    else 
X      {
X	return NULL;
X      }
X}
X
X#endif
X
X#ifdef BSD
X
X/** some supplementary string functions for Berkeley Unix systems **/
X
Xstrspn(source, keys)
Xchar *source, *keys;
X{
X	/** This function returns the length of the substring of
X	    'source' (starting at zero) that consists ENTIRELY of
X	    characters from 'keys'.  This is used to skip over a
X	    defined set of characters with parsing, usually. 
X	**/
X
X	register int loc = 0, key_index = 0;
X
X	while (source[loc] != '\0') {
X	  key_index = 0;
X	  while (keys[key_index] != source[loc])
X	    if (keys[key_index++] == '\0')
X	      return(loc);
X	  loc++;
X	}
X
X	return(loc);
X}
X
Xstrcspn(source, keys)
Xchar *source, *keys;
X{
X	/** This function returns the length of the substring of
X	    'source' (starting at zero) that consists entirely of
X	    characters NOT from 'keys'.  This is used to skip to a
X	    defined set of characters with parsing, usually. 
X	    NOTE that this is the opposite of strspn() above
X	**/
X
X	register int loc = 0, key_index = 0;
X
X	while (source[loc] != '\0') {
X	  key_index = 0;
X	  while (keys[key_index] != '\0')
X	    if (keys[key_index++] == source[loc])
X	      return(loc);
X	  loc++;
X	}
X
X	return(loc);
X}
X
Xchar *strtok(source, keys)
Xchar *source, *keys;
X{
X	/** This function returns a pointer to the next word in source
X	    with the string considered broken up at the characters 
X	    contained in 'keys'.  Source should be a character pointer
X	    when this routine is first called, then NULL subsequently.
X	    When strtok has exhausted the source string, it will 
X	    return NULL as the next word. 
X
X	    WARNING: This routine will DESTROY the string pointed to
X	    by 'source' when first invoked.  If you want to keep the
X	    string, make a copy before using this routine!!
X	 **/
X
X	register int  last_ch;
X	static   char *sourceptr;
X		 char *return_value;
X
X	if (source != NULL)
X	  sourceptr = source;
X	
X	if (*sourceptr == '\0') 
X	  return(NULL);		/* we hit end-of-string last time!? */
X
X	sourceptr += strspn(sourceptr, keys);	/* skip leading crap */
X	
X	if (*sourceptr == '\0') 
X	  return(NULL);		/* we've hit end-of-string */
X
X	last_ch = strcspn(sourceptr, keys);	/* end of good stuff */
X
X	return_value = sourceptr;		/* and get the ret   */
X
X	sourceptr += last_ch;			/* ...value 	     */
X
X	if (*sourceptr != '\0')		/* don't forget if we're at END! */
X	  sourceptr++;			   /* and skipping for next time */
X
X	return_value[last_ch] = '\0';		/* ..ending right    */
X	
X	return((char *) return_value);		/* and we're outta here! */
X}
X
Xchar *strpbrk(source, keys)
Xchar *source, *keys;
X{
X	/** Returns a pointer to the first character of source that is any
X	    of the specified keys, or NULL if none of the keys are present
X	    in the source string. 
X	**/
X
X	register int loc = 0, key_index = 0;
X
X	while (source[loc] != '\0') {
X	  key_index = 0;
X	  while (keys[key_index] != '\0')
X	    if (keys[key_index++] == source[loc])
X	      return((char *) (source + loc));
X	  loc++;
X	}
X	
X	return(NULL);
X}
X
Xchar *strchr(buffer, ch)
Xchar *buffer, ch;
X{
X	/** Returns a pointer to the first occurance of the character
X	    'ch' in the specified string or NULL if it doesn't occur **/
X
X	char *address;
X
X	address = buffer;
X
X	while (*address != ch) {
X	  if (*address == '\0')
X	    return (NULL);
X	  address++;
X	}
X
X	return ( (char *) address);
X}
X
X#endif
SHAR_EOF
chmod 0444 src/opt_utils.c || echo "restore of src/opt_utils.c fails"
echo "x - extracting src/options.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > src/options.c &&
X
Xstatic char rcsid[] = "@(#)$Id: options.c,v 2.1 88/09/15 20:29:10 syd Exp $";
X
X/*******************************************************************************
X *  The Elm Mail System  -  $Revision: 2.1 $   $State: Exp $
X *
X * 			Copyright (c) 1986 Dave Taylor
X *******************************************************************************
X * Bug reports, patches, comments, suggetions should be sent to:
X *
X *	Syd Weinstein, Elm Corrdinator
X *	syd@dsinc.UUCP			dsinc!syd
X *
X *******************************************************************************
X * $Log:	options.c,v $
X * Revision 2.1  88/09/15  20:29:10  syd
X * checked in with -k by syd at 88.09.15.20.29.10.
X * 
X * 88/08/27 ssw
X *	add deluth patches
X *
X * 88/08/27 ssw
X *	split tolower and ReadCh due to macro calls
X *
X * Revision 2.1  88/07/21  09:59:08  edc
X * Final hacks and cleanup to the 2.1 alpha test release.
X * 
X * Revision 2.0  88/06/27  17:25:23  edc
X * The original 2.0 gamma sources as leaked from HP
X * 
X *
X *
X ******************************************************************************/
X
X/** This set of routines allows the alteration of a number of paramaters
X    in the Elm mailer, including the following;
X
X	calendar-file	<where to put calendar entries>
X	display pager	<how to page messages>
X	editor		<name of composition editor>
X	folder-dir	<folder directory>
X	sort-by		<how to sort mailboxes>
X	savefile	<file to save outbound message copies to>
X	printmail	<how to print messages>
X	full_username	<your full user name for outgoing mail>
X
X	arrow-cursor	<on or off>
X	menu-display    <on or off>
X
X	user-level	<BEGINNER|INTERMEDIATE|EXPERT>
X        names-only      <on or off>
X	
X    And others as they seem useful.
X
X**/
X
X#include "headers.h"
X
X#ifdef BSD
X#undef tolower
X#endif
X
X#undef onoff
X#define   onoff(n)	(n == 1? "ON ":"OFF")
X
Xchar *one_liner_for(), *level_name();
Xunsigned long sleep();
X
Xoptions()
X{
X	/** change options... **/
X
X	int ch;
X
X	display_options();
X
X	clearerr(stdin);
X
X	do {
X	  ClearLine(LINES-4);
X
X	  Centerline(LINES-4,
X	   "Select first letter of Option line, '>' to Save, or R)eturn");
X
X	  PutLine0(LINES-2, 0, "Command: ");
X
X	  ch = ReadCh();
X	  ch = tolower(ch);
X
X	  clear_error();	/* remove possible "sorting" message etc... */ 
X
X	  one_liner(one_liner_for(ch));
X
X	  switch (ch) {
X	    case 'c' : optionally_enter(calendar_file, 2, 23, FALSE);	break;
X	    case 'd' : optionally_enter(pager, 3, 23, FALSE); 		
X		       clear_pages = (equal(pager, "builtin+") || 
X			             equal(pager, "internal+")); 	break;
X	    case 'e' : optionally_enter(editor, 4, 23, FALSE);		break;
X	    case 'f' : optionally_enter(folders, 5, 23, FALSE);		break;
X	    case 's' : change_sort(6,23);				break;
X	    case 'o' : optionally_enter(savefile, 7, 23, FALSE);	break;
X	    case 'p' : optionally_enter(printout, 8, 23, FALSE);	break;
X	    case 'y' : optionally_enter(full_username, 9, 23, FALSE);	break;
X	    case 'a' : on_or_off(&arrow_cursor, 12, 23); 		break;
X	    case 'm' : on_or_off(&mini_menu, 13, 23);			
X		       headers_per_page = LINES - (mini_menu ? 13 : 8); break;
X
X	    case 'u' : switch_user_level(&user_level,15, 23);		break;
X	    case 'n' : on_or_off(&names_only, 16, 23);			break;
X	
X	    case '?' : options_help(); 
X	               PutLine0(LINES-2,0,"Command: ");			break;
X	   
X	    case '>' : printf("Save options in .elm/elmrc...");
X		       fflush(stdout);    save_options();		break;
X
X	    case 'x' :
X	    case 'r' :
X	    case ctrl('D'):
X	    case ctrl('M'):
X	    case ctrl('J'): return;
X	    case ctrl('L'): display_options();				break;
X	    default: error("Command unknown!");
X	  }
X
X	} while (ch != 'r');
X}
X	
Xdisplay_options()
X{
X	/** Display all the available options.. **/
X	
X	char *sort_name();
X	
X	ClearScreen();
SHAR_EOF
echo "End of part 15"
echo "File src/options.c is continued in part 16"
echo "16" > s2_seq_.tmp
exit 0
-- 
=====================================================================
Sydney S. Weinstein, CDP, CCP                   Elm Coordinator
Datacomp Systems, Inc.				Voice: (215) 947-9900
{allegra,bellcore,bpa,vu-vlsi}!dsinc!syd	FAX:   (215) 938-0235