From: sources@anomaly.sbs.risc.net
Newsgroups: biz.sco.sources
Subject: v01i114 - ELM v2.3.11, Electronic Mail Reader - Part 14/20
Date: 13 Sep 92 17:44:10 GMT
Reply-To: sources@anomaly.sbs.risc.net
Followup-To: biz.sco.general
Organization: The Rhode Island Internet Systems Cooperative Network


#!/bin/sh
# this is part.14 (part 14 of a multipart archive)
# do not concatenate these parts, unpack them in order with /bin/sh
# file src/leavembox.c continued
#
if test ! -r shar3_seq_.tmp; then
	echo "Please unpack part 1 first!"
	exit 1
fi
(read Scheck
 if test "$Scheck" != 14; then
	echo "Please unpack part $Scheck next!"
	exit 1
 else
	exit 0
 fi
) < shar3_seq_.tmp || exit 1
echo "x - Continuing file src/leavembox.c"
sed 's/^X//' << 'SHAR_EOF' >> src/leavembox.c &&
X	(direction == INCOMING ? "incoming" : "outgoing"), cur_folder));
X      lock_state = ON;
X      return(0);
X}
X
Xint
Xunlock()
X{
X	/** Remove the lock file!    This must be part of the interrupt
X	    processing routine to ensure that the lock file is NEVER
X	    left sitting in the mailhome directory!
X
X	    If also using flock(), remove the file lock as well.
X	 **/
X
X	int retcode = 0;
X
X	dprint(5,
X	  (debugfile, "Lock %s for file %s %s off.\n",
X	    (*lock_name ? lock_name : "none"), cur_folder,
X	    (lock_state == ON ? "going" : "already")));
X
X	if(lock_state == ON) {
X
X#ifdef LOCK_BY_FLOCK
X	  if((retcode = flock(flock_fd, LOCK_UN)) == -1) {
X	    dprint(1, (debugfile,
X	      "Error %s (%s)\n\ttrying to unlock file %s (%s)\n", 
X	      error_name(errno), error_description(errno), cur_folder, "unlock"));
X
X	    /* try to force unlock by closing file */
X	    if(close(flock_fd) == -1) {
X	      dprint(1, (debugfile,
X	  "Error %s (%s)\n\ttrying to force unlock file %s via close() (%s)\n", 
X	      error_name(errno), error_description(errno), cur_folder, "unlock"));
X	      error1("Couldn't unlock my own mailbox %s!", cur_folder);
X	      return(retcode);
X	    }
X	  }
X	  (void)close(flock_fd);
X#endif
X#ifdef	LOCK_FLOCK_ONLY	/* { LOCK_FLOCK_ONLY */
X	  *lock_name = '\0';		/* null lock file name */
X	   lock_state = OFF;		/* indicate we don't have a lock on */
X#else
X	  if((retcode = unlink(lock_name)) == 0) {	/* remove lock file */
X	    *lock_name = '\0';		/* null lock file name */
X	    lock_state = OFF;		/* indicate we don't have a lock on */
X	  } else {
X	    dprint(1, (debugfile,
X	      "Error %s (%s)\n\ttrying to unlink file %s (%s)\n", 
X	      error_name(errno), error_description(errno), lock_name,"unlock"));
X	      error1("Couldn't remove my own lock file %s!", lock_name);
X	  }
X#endif	/* } LOCK_FLOCK_ONLY */
X	}
X	return(retcode);
X}
SHAR_EOF
echo "File src/leavembox.c is complete" &&
# ============= src/limit.c ==============
echo "x - extracting src/limit.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > src/limit.c &&
X
Xstatic char rcsid[] = "@(#)$Id: limit.c,v 4.1 90/04/28 22:43:21 syd Exp $";
X
X/*******************************************************************************
X *  The Elm Mail System  -  $Revision: 4.1 $   $State: Exp $
X *
X * 			Copyright (c) 1986, 1987 Dave Taylor
X * 			Copyright (c) 1988, 1989, 1990 USENET Community Trust
X *******************************************************************************
X * Bug reports, patches, comments, suggestions should be sent to:
X *
X *	Syd Weinstein, Elm Coordinator
X *	elm@DSI.COM			dsinc!elm
X *
X *******************************************************************************
X * $Log:	limit.c,v $
X * Revision 4.1  90/04/28  22:43:21  syd
X * checkin of Elm 2.3 as of Release PL0
X * 
X *
X ******************************************************************************/
X
X/** This stuff is inspired by MH and dmail and is used to 'select'
X    a subset of the existing mail in the folder based on one of a
X    number of criteria.  The basic tricks are pretty easy - we have
X    as status of VISIBLE associated with each header stored in the
X    (er) mind of the computer (!) and simply modify the commands to
X    check that flag...the global variable `selected' is set to the
X    number of messages currently selected, or ZERO if no select.
X**/
X
X#include "headers.h"
X
X#define TO		1
X#define FROM		2
X
Xchar *shift_lower();
X
Xint
Xlimit()
X{
X	/** returns non-zero if we changed selection criteria = need redraw **/
X	
X	char criteria[STRING], first[STRING], rest[STRING], msg[STRING];
X	static char prompt[] = "Enter criteria or '?' for help: ";
X	int  last_selected, all;
X
X	last_selected = selected;
X	all = 0;
X
X	if (selected) {
X	  PutLine1(LINES-2, 0, 
X		"Already have selection criteria - add more? (y/n) n%c",
X		BACKSPACE);
X	  criteria[0] = ReadCh();
X	  if (tolower(criteria[0]) == 'y') {
X	    Write_to_screen("Yes.", 0);
X	    PutLine0(LINES-3, COLUMNS-30, "Adding criteria...");
X	  } else {
X	    Write_to_screen("No.", 0);
X	    selected = 0;
X	    PutLine0(LINES-3, COLUMNS-30, "Change criteria...");
X	  }
X	}
X
X	while(1) {
X	  PutLine1(LINES-2, 0, prompt);
X	  CleartoEOLN();
X
X	  criteria[0] = '\0';
X	  optionally_enter(criteria, LINES-2, strlen(prompt), FALSE, FALSE);
X	  error("");
X	  
X	  if (strlen(criteria) == 0) {
X	    /* no change */
X	    selected = last_selected;
X	    return(FALSE);	
X	  }
X
X	  split_word(criteria, first, rest);
X
X	  if (equal(first, "?")) {
X	     if(last_selected)
X	       error(
X	          "Enter: {\"subject\",\"to\",\"from\"} [pattern] OR \"all\"");
X	     else
X	       error("Enter: {\"subject\",\"to\",\"from\"} [pattern]");
X	     continue;
X	  } else if (equal(first, "all")) {
X	    all++;
X	    selected = 0;
X	  }
X	  else if (equal(first, "subj") || equal(first, "subject"))
X	    selected = limit_selection(SUBJECT, rest, selected);
X	  else if (equal(first, "to"))
X	    selected = limit_selection(TO, rest, selected);
X	  else if (equal(first, "from"))
X	    selected = limit_selection(FROM, rest, selected);
X	  else {
X	    error1("\"%s\" not a valid criterion.", first);
X	    continue;
X	  }
X	  break;
X	}
X
X	if(all && last_selected)
X	  strcpy(msg, "Returned to unlimited display.");
X	else if(selected)
X	  sprintf(msg, "%d message%s selected.", selected, plural(selected));
X	else
X	  strcpy(msg, "No messages selected.");
X	set_error(msg);
X
X	/* we need a redraw if there had been a selection or there is now. */
X	if(last_selected || selected) {
X	  /* if current message won't be on new display, go to first message */
X	  if(selected && !(headers[current-1]->status & VISIBLE))
X	    current = visible_to_index(1)+1;
X	  return(TRUE);
X	} else {
X	  return(FALSE);
X	}
X}
X
Xint
Xlimit_selection(based_on, pattern, additional_criteria)
Xint based_on, additional_criteria;
Xchar *pattern;
X{
X	/** Given the type of criteria, and the pattern, mark all
X	    non-matching headers as ! VISIBLE.  If additional_criteria,
X	    don't mark as visible something that isn't currently!
X	**/
X
X	register int iindex, count = 0;
X
X	dprint(2, (debugfile, "\n\n\n**limit on %d - '%s' - (%s) **\n\n",
X		   based_on, pattern, additional_criteria?"add'tl":"base"));
X
X	if (based_on == SUBJECT) {
X	  for (iindex = 0; iindex < message_count; iindex++)
X	    if (! in_string(shift_lower(headers[iindex]->subject), pattern))
X	      headers[iindex]->status &= ~VISIBLE;
X	    else if (additional_criteria && 	
X		     !(headers[iindex]->status & VISIBLE))
X	      headers[iindex]->status &= ~VISIBLE;	/* shut down! */
X	    else { /* mark it as readable */
X	      headers[iindex]->status |= VISIBLE;
X	      count++;
X	      dprint(5, (debugfile,
X		     "  Message %d (%s from %s) marked as visible\n",
X			iindex, headers[iindex]->subject,
X			headers[iindex]->from));
X	    }
X	}
X	else if (based_on == FROM) {
X	  for (iindex = 0; iindex < message_count; iindex++)
X	    if (! in_string(shift_lower(headers[iindex]->from), pattern))
X	      headers[iindex]->status &= ~VISIBLE;
X	    else if (additional_criteria && 	
X		     !(headers[iindex]->status & VISIBLE))
X	      headers[iindex]->status &= ~VISIBLE;	/* shut down! */
X	    else { /* mark it as readable */
X	      headers[iindex]->status |= VISIBLE;
X	      count++;
X	      dprint(5, (debugfile, 
X			"  Message %d (%s from %s) marked as visible\n",
X			iindex, headers[iindex]->subject,
X			headers[iindex]->from));
X	    }
X	}
X	else if (based_on == TO) {
X	  for (iindex = 0; iindex < message_count; iindex++)
X	    if (! in_string(shift_lower(headers[iindex]->to), pattern))
X	      headers[iindex]->status &= ~VISIBLE;
X	    else if (additional_criteria && 	
X		     !(headers[iindex]->status & VISIBLE))
X	      headers[iindex]->status &= ~VISIBLE;	/* shut down! */
X	    else { /* mark it as readable */
X	      headers[iindex]->status |= VISIBLE;
X	      count++;
X	      dprint(5, (debugfile,
X			"  Message %d (%s from %s) marked as visible\n",
X			iindex, headers[iindex]->subject,
X			headers[iindex]->from));
X	    }
X	}
X
X	dprint(4, (debugfile, "\n** returning %d selected **\n\n\n", count));
X
X	return(count);
X}
X
Xint
Xnext_message(iindex, skipdel)
Xregister int iindex, skipdel;
X{
X	/** Given 'iindex', this routine will return the actual iindex into the
X	    array of the NEXT message, or '-1' iindex is the last.
X	    If skipdel, return the iindex for the NEXT undeleted message.
X	    If selected, return the iindex for the NEXT message marked VISIBLE.
X	**/
X
X	register int remember_for_debug;
X
X	if(iindex < 0) return(-1);	/* invalid argument value! */
X
X	remember_for_debug = iindex;
X
X	for(iindex++;iindex < message_count; iindex++)
X	  if (((headers[iindex]->status & VISIBLE) || (!selected))
X	    && (!(headers[iindex]->status & DELETED) || (!skipdel))) {
X	      dprint(9, (debugfile, "[Next%s%s: given %d returning %d]\n", 
X		  (skipdel ? " undeleted" : ""),
X		  (selected ? " visible" : ""),
X		  remember_for_debug+1, iindex+1));
X	      return(iindex);
X	  }
X	return(-1);
X}
X
Xint
Xprev_message(iindex, skipdel)
Xregister int iindex, skipdel;
X{
X	/** Like next_message, but the PREVIOUS message. **/
X
X	register int remember_for_debug;
X
X	if(iindex >= message_count) return(-1);	/* invalid argument value! */
X
X	remember_for_debug = iindex;
X	for(iindex--; iindex >= 0; iindex--)
X	  if (((headers[iindex]->status & VISIBLE) || (!selected))
X	    && (!(headers[iindex]->status & DELETED) || (!skipdel))) {
X	      dprint(9, (debugfile, "[Previous%s%s: given %d returning %d]\n", 
X		  (skipdel ? " undeleted" : ""),
X		  (selected ? " visible" : ""),
X		  remember_for_debug+1, iindex+1));
X	      return(iindex);
X	  }
X	return(-1);
X}
X
X
Xint
Xcompute_visible(message)
Xint message;
X{
X	/** return the 'virtual' iindex of the specified message in the
X	    set of messages - that is, if we have the 25th message as
X	    the current one, but it's #2 based on our limit criteria,
X	    this routine, given 25, will return 2.
X	**/
X
X	register int iindex, count = 0;
X
X	if (! selected) return(message);
X
X	if (message < 1) message = 1;	/* normalize */
X
X	for (iindex = 0; iindex < message; iindex++)
X	   if (headers[iindex]->status & VISIBLE) 
X	     count++;
X
X	dprint(4, (debugfile,
X		"[compute-visible: displayed message %d is actually %d]\n",
X		count, message));
X
X	return(count);
X}
X
Xint
Xvisible_to_index(message)
Xint message;
X{
X	/** Given a 'virtual' iindex, return a real one.  This is the
X	    flip-side of the routine above, and returns (message_count+1)
X	    if it cannot map the virtual iindex requested (too big) 
X	**/
X
X	register int iindex = 0, count = 0;
X
X	for (iindex = 0; iindex < message_count; iindex++) {
X	   if (headers[iindex]->status & VISIBLE) 
X	     count++;
X	   if (count == message) {
X	     dprint(4, (debugfile,
X		     "visible-to-index: (up) index %d is displayed as %d\n",
X		     message, iindex));
X	     return(iindex);
X	   }
X	}
X
X	dprint(4, (debugfile, "index %d is NOT displayed!\n", message));
X
X	return(message_count+1);
X}
SHAR_EOF
# ============= src/mailmsg1.c ==============
echo "x - extracting src/mailmsg1.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > src/mailmsg1.c &&
X
Xstatic char rcsid[] = "@(#)$Id: mailmsg1.c,v 4.1.1.1 90/06/05 20:52:21 syd Exp $";
X
X/*******************************************************************************
X *  The Elm Mail System  -  $Revision: 4.1.1.1 $   $State: Exp $
X *
X * 			Copyright (c) 1986, 1987 Dave Taylor
X * 			Copyright (c) 1988, 1989, 1990 USENET Community Trust
X *******************************************************************************
X * Bug reports, patches, comments, suggestions should be sent to:
X *
X *	Syd Weinstein, Elm Coordinator
X *	elm@DSI.COM			dsinc!elm
X *
X *******************************************************************************
X * $Log:	mailmsg1.c,v $
X * Revision 4.1.1.1  90/06/05  20:52:21  syd
X * Fixes the 'g' Group Reply command to send to the cc list also.
X * A bad variable name caused it to be ignored.
X * From: chip@chinacat.Unicom.COM (Chip Rosenthal)
X * 
X * Revision 4.1  90/04/28  22:43:26  syd
X * checkin of Elm 2.3 as of Release PL0
X * 
X *
X ******************************************************************************/
X
X/** Interface to allow mail to be sent to users.  Part of ELM  **/
X
X
X#include "headers.h"
X
X/** strings defined for the hdrconfg routines **/
X
Xchar subject[SLEN], in_reply_to[SLEN], expires[SLEN], 
X     action[SLEN], priority[SLEN], reply_to[SLEN], to[VERY_LONG_STRING], 
X     cc[VERY_LONG_STRING], expanded_to[VERY_LONG_STRING], 
X     expanded_cc[VERY_LONG_STRING], user_defined_header[SLEN],
X     bcc[VERY_LONG_STRING], expanded_bcc[VERY_LONG_STRING];
X
Xchar *format_long(), *strip_commas(), *tail_of_string(), *strcpy();
Xunsigned long sleep();
X
Xint
Xsendmsg(given_to, given_cc, given_subject, edit_message, form_letter, replying)
Xchar *given_to, *given_cc, *given_subject;
Xint   edit_message, form_letter, replying;
X{
X	/** Prompt for fields and then call mail() to send the specified
X	    message.  If 'edit_message' is true then don't allow the
X            message to be edited. 'form_letter' can be "YES" "NO" or "MAYBE".
X	    if YES, then add the header.  If MAYBE, then add the M)ake form
X	    option to the last question (see mailsg2.c) etc. etc. 
X	    if (replying) then add an In-Reply-To: header...
X	    Return TRUE if the main part of the screen has been changed
X	    (useful for knowing whether a redraw is needed.
X	**/
X
X	int  copy_msg = FALSE, is_a_response = FALSE;
X
X	/* First: zero all current global message strings */
X
X	cc[0] = bcc[0] = reply_to[0] = expires[0] = '\0';
X	action[0] = priority[0] = user_defined_header[0] = in_reply_to[0] ='\0';
X	expanded_to[0] = expanded_cc[0] = expanded_bcc[0] = '\0';
X
X	strcpy(subject, given_subject);		/* copy given subject */
X	strcpy(to, given_to);			/* copy given to:     */
X	strcpy(cc, given_cc);			/*  and so on..       */
X
X	/******* And now the real stuff! *******/
X
X	copy_msg=copy_the_msg(&is_a_response); /* copy msg into edit buffer? */
X
X	if (get_to(to, expanded_to) == 0)   /* get the To: address and expand */
X	  return(0);
X	if ( cc[0] != '\0' )			/* expand out CC addresses */
X	  build_address(strip_commas(cc), expanded_cc);
X
X	/** if we're batchmailing, let's send it and GET OUTTA HERE! **/
X
X	if (batch_only) {
X	  return(mail(FALSE, FALSE, form_letter));
X	}
X
X	display_to(expanded_to);	/* display the To: field on screen... */
X
X	dprint(3, (debugfile, "\nMailing to \"%s\"\n", expanded_to));
X  
X	if (get_subject(subject) == 0)	    /* get the Subject: field */
X	  return(0);
X
X	dprint(4, (debugfile, "Subject is %s\n", subject));
X
X	if (prompt_for_cc) {
X	  if (get_copies(cc, expanded_to, expanded_cc, copy_msg) == 0)
X	    return(0);
X
X	  if (strlen(cc) > 0)
X	    dprint(4, (debugfile, "Copies to %s\n", expanded_cc));
X	}
X
X	MoveCursor(LINES,0);	/* so you know you've hit <return> ! */
X
X	/** generate the In-Reply-To: header... **/
X
X	if (is_a_response && replying)
X	  generate_reply_to(current-1);
X
X	/* and mail that puppy outta here! */
X	
X	return(mail(copy_msg, edit_message, form_letter));
X}
X
Xget_to(to_field, address)
Xchar *to_field, *address;
X{
X	/** prompt for the "To:" field, expanding into address if possible.
X	    This routine returns ZERO if errored, or non-zero if okay **/
X
X	if (strlen(to_field) == 0) {
X	  if (user_level < 2) {
X	    PutLine0(LINES-2, 0, "Send the message to: ");
X	    (void) optionally_enter(to_field, LINES-2, 21, FALSE, FALSE); 
X	  }
X	  else {
X	    PutLine0(LINES-2, 0, "To: ");
X	    (void) optionally_enter(to_field, LINES-2, 4, FALSE, FALSE); 
X	  }
X	  if (strlen(to_field) == 0) {
X	    ClearLine(LINES-2);	
X	    return(0);
X	  }
X	  (void) build_address(strip_commas(to_field), address); 
X	}
X	else if (mail_only) 
X	  (void) build_address(strip_commas(to_field), address); 
X	else 
X	  strcpy(address, to_field);
X	
X	if (strlen(address) == 0) {	/* bad address!  Removed!! */
X	  ClearLine(LINES-2);
X	  return(0);
X	}
X
X	return(1);		/* everything is okay... */
X}
X
Xget_subject(subject_field)
Xchar *subject_field;
X{
X	char	ch;
X
X	/** get the subject and return non-zero if all okay... **/
X	int len = 9, prompt_line;
X
X	prompt_line = mail_only ? 4 : LINES-2;
X
X	if (user_level == 0) {
X	  PutLine0(prompt_line,0,"Subject of message: ");
X	  len = 20;
X	}
X	else
X	  PutLine0(prompt_line,0,"Subject: ");
X
X	CleartoEOLN();
X
X	if(optionally_enter(subject_field, prompt_line, len, TRUE, FALSE)==-1){
X	  /** User hit the BREAK key! **/
X	  MoveCursor(prompt_line,0); 	
X	  CleartoEOLN();
X	  error("Mail not sent.");
X	  return(0);
X	}
X
X	if (strlen(subject_field) == 0) {	/* zero length subject?? */
X	  PutLine1(prompt_line,0,
X	    "No subject - Continue with message? (y/n) n%c", BACKSPACE);
X
X	  ch = ReadCh();
X	  if (tolower(ch) != 'y') {	/* user says no! */
X	    Write_to_screen("No.", 0);
X	    ClearLine(prompt_line);
X	    error("Mail not sent.");
X	    return(0);
X	  }
X	  else {
X	    Write_to_screen("Yes.", 0);
X	    PutLine0(prompt_line,0,"Subject: <none>");
X	    CleartoEOLN();
X	  }
X	}
X
X	return(1);		/** everything is cruising along okay **/
X}
X
Xget_copies(cc_field, address, addressII, copy_message)
Xchar *cc_field, *address, *addressII;
Xint   copy_message;
X{
X	/** Get the list of people that should be cc'd, returning ZERO if
X	    any problems arise.  Address and AddressII are for expanding
X	    the aliases out after entry! 
X	    If 'bounceback' is nonzero, add a cc to ourselves via the remote
X	    site, but only if hops to machine are > bounceback threshold.
X	    If copy-message, that means that we're going to have to invoke
X	    a screen editor, so we'll need to delay after displaying the
X	    possibly rewritten Cc: line...
X	**/
X	int prompt_line;
X
X	prompt_line = mail_only ? 5 : LINES - 1;
X	PutLine0(prompt_line,0,"Copies to: ");
X
X	fflush(stdout);
X
X	if (optionally_enter(cc_field, prompt_line, 11, FALSE, FALSE) == -1) {
X	  ClearLine(prompt_line-1);
X	  ClearLine(prompt_line);
X	  
X	  error("Mail not sent.");
X	  return(0);
X	}
X	
X	/** The following test is that if the build_address routine had
X	    reason to rewrite the entry given, then, if we're mailing only
X	    print the new Cc line below the old one.  If we're not, then
X	    assume we're in screen mode and replace the incorrect entry on
X	    the line above where we are (e.g. where we originally prompted
X	    for the Cc: field).
X	**/
X
X	if (build_address(strip_commas(cc_field), addressII)) {
X	  PutLine1(prompt_line, 11, "%s", addressII);
X	  if ((strcmp(editor, "builtin") != 0 && strcmp(editor, "none") != 0)
X	      || copy_message)
X	    sleep(2);
X	}
X
X	if (strlen(address) + strlen(addressII) > VERY_LONG_STRING) {
X	  dprint(2, (debugfile, 
X		"String length of \"To:\" + \"Cc\" too long! (get_copies)\n"));
X	  error("Too many people. Copies ignored.");
X	  sleep(2);
X	  cc_field[0] = '\0';
X	}
X
X	return(1);		/* everything looks okay! */
X}
X	
Xint
Xcopy_the_msg(is_a_response)
Xint *is_a_response;
X{
X	/** Returns True iff the user wants to copy the message being
X	    replied to into the edit buffer before invoking the editor! 
X	    Sets "is_a_response" to true if message is a response...
X	**/
X
X	int answer = FALSE;
X
X	if (forwarding)
X	  answer = TRUE;
X	else if (strlen(to) > 0 && !mail_only) {  /* predefined 'to' line! */
X	  if (auto_copy) 
X	    answer = TRUE;
X	  else 
X	    answer = (want_to("Copy message? (y/n) ", 'n') == 'y');
X	  *is_a_response = TRUE;
X	}
X
X	return(answer);
X}
X
Xstatic int to_line, to_col;
X
Xdisplay_to(address)
Xchar *address;
X{
X	/** Simple routine to display the "To:" line according to the
X	    current configuration (etc) 			      
X	 **/
X	register int open_paren;
X
X	to_line = mail_only ? 3 : LINES - 3;
X	to_col = mail_only ? 0 : COLUMNS - 50;
X	if (names_only)
X	  if ((open_paren = chloc(address, '(')) > 0) {
X	    if (open_paren < chloc(address, ')')) {
X	      output_abbreviated_to(address);
X	      return;
X	    } 
X	  }
X	if(mail_only)
X	  if(strlen(address) > 80)
X	    PutLine1(to_line, to_col, "To: (%s)", 
X	        tail_of_string(address, 75));
X	  else
X	    PutLine1(to_line, to_col, "To: %s", address);
X	else if (strlen(address) > 45) 
X	  PutLine1(to_line, to_col, "To: (%s)", 
X	      tail_of_string(address, 40));
X	else {
X	  if (strlen(address) > 30) 
X	    PutLine1(to_line, to_col, "To: %s", address);
X	  else
X	    PutLine1(to_line, to_col, "          To: %s", address);
X	  CleartoEOLN();
X	}
X}
X
Xoutput_abbreviated_to(address)
Xchar *address;
X{
X	/** Output just the fields in parens, separated by commas if need
X	    be, and up to COLUMNS-50 characters...This is only used if the
X	    user is at level BEGINNER.
X	**/
X
X	char newaddress[LONG_STRING];
X	register int iindex, newindex = 0, in_paren = 0, add_len;
X
X	iindex = 0;
X
X	add_len = strlen(address);
X	while (newindex < 55 && iindex < add_len) {
X	  if (address[iindex] == '(') in_paren++;
X	  else if (address[iindex] == ')') { 
X	    in_paren--;
X	    if (iindex < add_len-4) {
X	      newaddress[newindex++] = ',';
X	      newaddress[newindex++] = ' ';
X	    }
X	  }
X	  
X	  /* copy if in_paren but not at the opening outer parens */
X	  if (in_paren && !(address[iindex] == '(' && in_paren == 1))
X	      newaddress[newindex++] = address[iindex];
X	     
X	  iindex++;
X	}
X
X	newaddress[newindex] = '\0';
X
X	if (mail_only)
X	  if (strlen(newaddress) > 80) 
X	    PutLine1(to_line, to_col, "To: (%s)", 
X	       tail_of_string(newaddress, 60));
X	  else
X	    PutLine1(to_line, to_col, "To: %s", newaddress);
X	else if (strlen(newaddress) > 50) 
X	   PutLine1(to_line, to_col, "To: (%s)", 
X	       tail_of_string(newaddress, 40));
X	 else {
X	   if (strlen(newaddress) > 30)
X	     PutLine1(to_line, to_col, "To: %s", newaddress);
X	   else
X	     PutLine1(to_line, to_col, "          To: %s", newaddress);
X	   CleartoEOLN();
X	 }
X
X	return;
X}
SHAR_EOF
# ============= src/mailmsg2.c ==============
echo "x - extracting src/mailmsg2.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > src/mailmsg2.c &&
X
Xstatic char rcsid[] = "@(#)$Id: mailmsg2.c,v 4.1.1.8 90/10/07 19:48:10 syd Exp $";
X
X/*******************************************************************************
X *  The Elm Mail System  -  $Revision: 4.1.1.8 $   $State: Exp $
X *
X * 			Copyright (c) 1986, 1987 Dave Taylor
X * 			Copyright (c) 1988, 1989, 1990 USENET Community Trust
X *******************************************************************************
X * Bug reports, patches, comments, suggestions should be sent to:
X *
X *	Syd Weinstein, Elm Coordinator
X *	elm@DSI.COM			dsinc!elm
X *
X *******************************************************************************
X * $Log:	mailmsg2.c,v $
X * Revision 4.1.1.8  90/10/07  19:48:10  syd
X * fix the bounce problem reported earlier when using MMDF submit as the MTA.
X * From: Jim Clausing <jac%brahms.tinton.ccur.com@RELAY.CS.NET>
X * 
X * Revision 4.1.1.7  90/08/15  22:02:36  syd
X * deal with several of the problems that have come up trying to use the MMDF
X * submit program directly rather than going through the sendmail stub
X * included with MMDF.  This should take care of the problem of not being
X * able to send mail to usernames beginning with "i" and with the
X * 'No valid author specified' problem.
X * From: jac%brahms.tinton.ccur.com@RELAY.CS.NET
X * 
X * Revision 4.1.1.6  90/07/12  23:19:20  syd
X * Make domain name checking case independent
X * From: Syd, reported by Steven Baur
X * 
X * Revision 4.1.1.5  90/07/12  22:52:42  syd
X * When Elm is compiled with the NO_XHEADER symbol defined, it failed
X * to put a blank line between the message header and message body.
X * From: mca@medicus.medicus.com (Mark Adams)
X * 
X * Revision 4.1.1.4  90/06/26  16:18:24  syd
X * Make it encode lines that are [...] if not one of the reserved lines.
X * It was messing up decoding
X * From: Syd via report from Lenny Tropiano
X * 
X * Revision 4.1.1.3  90/06/21  21:07:48  syd
X * Fix XHEAD define
X * From: Syd
X * 
X * Revision 4.1.1.2  90/06/09  23:20:24  syd
X * fix typo
X * 
X * Revision 4.1.1.1  90/06/09  22:28:39  syd
X * Allow use of submit with mmdf instead of sendmail stub
X * From: martin <martin@hppcmart.grenoble.hp.com>
X * 
X * Revision 4.1  90/04/28  22:43:28  syd
X * checkin of Elm 2.3 as of Release PL0
X * 
X *
X ******************************************************************************/
X
X/** Interface to allow mail to be sent to users.  Part of ELM  **/
X
X#include "headers.h"
X#include <errno.h>
X#include <ctype.h>
X
X#ifdef BSD 
X#undef tolower
X#undef toupper
X#endif
X
Xextern int errno;
Xextern char version_buff[];
X
Xchar *error_name(), *error_description(), *strip_parens();
Xchar *strcat(), *strcpy(), *index();
Xchar *format_long(), *strip_commas(), *tail_of_string(); 
X
Xunsigned long sleep();
X
X#ifdef SITE_HIDING 
X char *get_ctime_date();
X#endif
XFILE *write_header_info();
X
X/* these are all defined in the mailmsg1.c file! */
X
Xextern char subject[SLEN], in_reply_to[SLEN], expires[SLEN], 
X            action[SLEN], priority[SLEN], reply_to[SLEN], to[VERY_LONG_STRING], 
X	    cc[VERY_LONG_STRING], expanded_to[VERY_LONG_STRING], 
X	    expanded_cc[VERY_LONG_STRING], user_defined_header[SLEN],
X	    bcc[VERY_LONG_STRING], expanded_bcc[VERY_LONG_STRING];
X
X
Xint  gotten_key;
Xchar *bounce_off_remote();
X
Xmail(copy_msg, edit_message, form)
Xint  copy_msg, edit_message, form;
X{
X	/** Given the addresses and various other miscellany (specifically, 
X	    'copy-msg' indicates whether a copy of the current message should 
X	    be included, 'edit_message' indicates whether the message should 
X	    be edited) this routine will invoke an editor for the user and 
X	    then actually mail off the message. 'form' can be YES, NO, or
X	    MAYBE.  YES=add "Content-Type: mailform" header, MAYBE=add the
X	    M)ake form option to last question, and NO=don't worry about it!
X	    Also, if 'copy_msg' = FORM, then grab the form temp file and use
X	    that...
X	    Return TRUE if the main part of the screen has been changed
X	    (useful for knowing whether a redraw is needed.
X	**/
X
X	FILE *reply, *real_reply; /* second is post-input buffer */
X	char *whole_msg_file, *tempnam();
X	char filename[SLEN], fname[SLEN], copy_file[SLEN],
X             very_long_buffer[VERY_LONG_STRING], mailerflags[NLEN];
X	int ch, sys_status;
X	register int retransmit = FALSE; 
X	int      already_has_text = FALSE;		/* we need an ADDRESS */
X	int	 signature_done = FALSE;
X	int	 need_redraw = 0;
X
X	static int cancelled_msg = 0;
X
X	dprint(4, (debugfile, "\nMailing to \"%s\" (with%s editing)\n",
X		  expanded_to, edit_message? "" : "out"));
X	
X	gotten_key = 0;		/* ignore previously gotten encryption key */
X
X	/** first generate the temporary filename **/
X
X	sprintf(filename,"%s%s%d", temp_dir, temp_file, getpid());
X
X	/** if possible, let's try to recall the last message? **/
X
X	if (! batch_only && copy_msg != FORM && user_level != 0)
X	  retransmit = recall_last_msg(filename, copy_msg, &cancelled_msg, 
X		       &already_has_text);
X
X	/** if we're not retransmitting, create the file.. **/
X
X	if (! retransmit)
X	  if ((reply = fopen(filename,"w")) == NULL) {
X	    dprint(1, (debugfile, 
X               "Attempt to write to temp file %s failed with error %s (mail)\n",
X		 filename, error_name(errno)));
X	    if(batch_only)
X	      printf("Could not create file %s (%s).\n",filename,
X		 error_name(errno));
X	    else
X	      error2("Could not create file %s (%s).",filename,
X		 error_name(errno));
X	    return(need_redraw);
X	  }
X
X	chown (filename, userid, groupid);
X
X	/* copy the message from standard input */
X	if (batch_only) {
X	  while (fgets(very_long_buffer, VERY_LONG_STRING, stdin) != NULL) 
X	    fprintf(reply, "%s", very_long_buffer);
X	}
X
X	if (copy_msg == FORM) {
X	  sprintf(fname, "%s%s%d", temp_dir, temp_form_file, getpid());
X	  fclose(reply);	/* we can't retransmit a form! */
X	  if (access(fname,ACCESS_EXISTS) != 0) {
X	    if(batch_only)
X	      printf("Couldn't find forms file!\n");
X	    else
X	      error("Couldn't find forms file!");
X	    return(need_redraw);
X	  }
X	  dprint(4, (debugfile, "-- renaming existing file %s to file %s --\n",
X		  fname, filename));
X	  rename(fname, filename);
X	}
X	else if (copy_msg && ! retransmit) {  /* if retransmit we have it! */
X	  if (attribution[0]) {
X	    fprintf(reply, attribution, headers[current-1]->from);
X	    fputc('\n', reply);
X	  }
X	  else if (forwarding) {
X	    fputs("Forwarded message:\n", reply);
X	  }
X	  if (edit_message) {
X	    copy_message(prefixchars, reply, noheader,FALSE,FALSE,TRUE,FALSE);
X	    already_has_text = TRUE;	/* we just added it, right? */
X	  }
X	  else
X	    copy_message("", reply, noheader, FALSE, FALSE, TRUE, FALSE);
X	}
X
X        /* append signature now if we are going to use an external editor */
X	/* Don't worry about the remote/local determination too much */
X
X        if (already_has_text || 
X           (strcmp(editor,"builtin") != 0 && strcmp(editor,"none") != 0)) {
X	     signature_done = TRUE;
X             if (!retransmit && copy_msg != FORM) 
X	       already_has_text |= append_sig(reply);
X	}
X
X	if (! retransmit && copy_msg != FORM)
X	  if (reply != NULL)
X	    (void) fclose(reply);	/* on replies, it won't be open! */
X
X	/** Edit the message **/
X
X	if (edit_message)
X	  create_readmsg_file();	/* for "readmsg" routine */
X
X	ch = edit_message? 'e' : ' ';	/* drop through if needed... */
X
X	/* calculate default save_file name */
X	if(auto_cc) {
X	  if(save_by_name) {
X	    if(force_name) {
X	      strcpy(copy_file, "=");	/* signals save by 'to' logname */
X	    } else {
X	      strcpy(copy_file, "=?");	/* conditional save by 'to' logname */
X	    }
X	  } else {
X	    strcpy(copy_file, "<");	/* signals save to sentmail */
X	  }
X	} else *copy_file = '\0';	/* signals to not save a copy */
X
X
X	if (! batch_only) {
X	  do {
X	    switch (ch) {
X	      case 'e': need_redraw = 1;
X			if (edit_the_message(filename, already_has_text)) {
X			  cancelled_msg = TRUE;
X			  return(need_redraw);
X			}
X			break;
X
X	      case 'c': if (name_copy_file(copy_file))
X			  need_redraw = 1;
X			break;
X
X	      case 'h': edit_headers();
X			need_redraw = 1;
X			break;
X
X#ifdef ALLOW_SUBSHELL
X	      case '!': if (subshell()) {
X			  ClearScreen();
X			  need_redraw = 1;
X			}
X			break;
X#endif
X
X	      default : /* do nothing */ ;
X	    }
X
X	    /** ask that silly question again... **/
X  
X	    if ((ch = verify_transmission(filename, &form)) == 'f') {
X	      cancelled_msg = TRUE;
X	      return(need_redraw);
X	    }
X
X	  } while (ch != 's');
X
X	  if (form == YES) 
X	    if (format_form(filename) < 1) {
X	      cancelled_msg = TRUE;
X	      return(need_redraw);
X	    }
X
X	  if ((reply = fopen(filename,"r")) == NULL) {
X	      dprint(1, (debugfile,
X	    "Attempt to open file %s for reading failed with error %s (mail)\n",
X                filename, error_name(errno)));
X	      error1("Could not open reply file (%s).", error_name(errno));
X	      return(need_redraw);
X	  }
X	}
X	else if ((reply = fopen(filename,"r")) == NULL) {
X	  dprint(1, (debugfile, 
X	    "Attempt to open file %s for reading failed with error %s (mail)\n",
X             filename, error_name(errno)));
X	  printf("Could not open reply file (%s).\n", error_name(errno));
X	  return(need_redraw);
X	}
X
X	cancelled_msg = FALSE;	/* it ain't cancelled, is it? */
X
X	/** ask about bounceback if the user wants us to.... **/
X
X	if (uucp_hops(to) > bounceback && bounceback > 0 && copy_msg != FORM) 
X	  if (verify_bounceback() == TRUE) {
X	    if (strlen(cc) > 0) strcat(expanded_cc, ", ");
X	    strcat(expanded_cc, bounce_off_remote(to));
X	  }
X
X	/** grab a copy if the user so desires... **/
X
X	if (*copy_file) /* i.e. if copy_file contains a name */
X	  save_copy(expanded_to, expanded_cc, expanded_bcc,
X	       filename, copy_file, form);
X
X	/** write all header information into whole_msg_file **/
X
X	if((whole_msg_file=tempnam(temp_dir, "snd.")) == NULL) {
X	  dprint(1, (debugfile, "couldn't make temp file nam! (mail)\n"));
X	  if(batch_only)
X	    printf("Sorry - couldn't make temp file name!\n");
X	  else if(mail_only)
X	    error("Sorry - couldn't make temp file name.");
X	  else
X	    set_error("Sorry - couldn't make temp file name.");
X	  return(need_redraw);
X	}
X
X	/** try to write headers to new temp file **/
X
X	dprint(6, (debugfile, "Composition file='%s' and mail buffer='%s'\n", 
X		    filename, whole_msg_file));
X
X	dprint(2,(debugfile,"--\nTo: %s\nCc: %s\nBcc: %s\nSubject: %s\n---\n", 
X		  expanded_to, expanded_cc, expanded_bcc, subject));
X
X	if ((real_reply=
X	   write_header_info(whole_msg_file, expanded_to,
X	     expanded_cc, expanded_bcc, form == YES, FALSE)) == NULL) {
X
X	  /** IT FAILED!!  MEIN GOTT!  Use a dumb mailer instead! **/
X
X	  dprint(3, (debugfile, "** write_header failed: %s\n", 
X		 error_name(errno)));
X
X	  if (cc[0] != '\0')  		/* copies! */
X	    sprintf(expanded_to,"%s %s", expanded_to, expanded_cc);
X
X	  quote_args(very_long_buffer, strip_parens(strip_commas(expanded_to)));
X	  strcpy(expanded_to, very_long_buffer);
X
X	  sprintf(very_long_buffer, "( (%s -s \"%s\" %s ; %s %s) & ) < %s",
X		  mailx, subject, expanded_to, remove_cmd, filename, filename);
X
X	  if(batch_only)
X	    printf("Message sent using dumb mailer %s.\n", mailx);
X	  else
X	    error1("Message sent using dumb mailer %s.", mailx);
X	  sleep(2);	/* ensure time to see this prompt! */
X
X	}
X	else {
X
X	  copy_message_across(reply, real_reply, FALSE);
X
X          /* Append signature if not done earlier */
X
X          if (!signature_done && !retransmit && copy_msg != FORM)
X               append_sig(real_reply);
X
X	  fclose(real_reply);
X
X	  if (cc[0] != '\0')  				         /* copies! */
X	    sprintf(expanded_to,"%s %s", expanded_to, expanded_cc);
X
X	  if (bcc[0] != '\0') {
X	    strcat(expanded_to, " ");
X	    strcat(expanded_to, expanded_bcc);
X	  }
X
X	  remove_hostbang(expanded_to);
X
X	  if (strcmp(sendmail, mailer) == 0
X#ifdef SITE_HIDING
X	      && ! is_a_hidden_user(username))
X#else
X	     					)
X#endif
X		
X	    strcpy(mailerflags, (sendmail_verbose ? smflagsv : smflags));
X	  else if (strcmp(submitmail, mailer) == 0)
X	    strcpy(mailerflags, submitflags);
X	  else
X	    mailerflags[0] ='\0';
X
X	  if (strcmp(submitmail, mailer) == 0)
X	    strcpy(expanded_to, " ");
X	  else {
X	    quote_args(very_long_buffer, strip_parens(strip_commas(expanded_to)));
X	    strcpy(expanded_to, very_long_buffer);
X	  }
X
X	  sprintf(very_long_buffer,"( (%s %s %s ; %s %s) & ) < %s", 
X		mailer, mailerflags, expanded_to,
X		remove_cmd, whole_msg_file, whole_msg_file);
X	}
X	
X	fclose(reply);
X
X	if(batch_only)
X	  printf("Sending mail...\n");
X	else {
X	  PutLine0(LINES,0,"Sending mail...");
X	  CleartoEOLN();
X	}
X
X	/* Take note of mailer return value */
X
X	if ( sys_status = system_call(very_long_buffer, SH, FALSE, FALSE) ) {
X		/* problem case: */
X		if (mail_only || batch_only)
X		   printf("\r\nmailer returned error status %d\r\n", sys_status);
X		else {
X		   sprintf(very_long_buffer, "mailer returned error status %d", sys_status);
X		   set_error(very_long_buffer);
X		}
X	} else {
X		/* Success case: */
X		if(batch_only)
X		  printf("Mail sent!\n");
X		else if(mail_only)
X		  error("Mail sent!");
X		else
X		  set_error("Mail sent!");
X	}
X
X	/* Unlink temp file now.
X	 * This is a precaution in case the message was encrypted.
X	 * I.e. even though this file is readable by the owner only,
X	 * encryption is supposed to hide things even from someone
X	 * with root privelges. The best we can do is not let this
X	 * file just hang after we're finished with it.
X	 */
X	(void)unlink(filename);
X
X	return(need_redraw);
X}
X
X/*
X * remove_hostbang - Given an expanded list of addresses, remove all
X * occurrences of "thishost!" at the beginning of addresses.
X * This hack is useful in itself, but it is required now because of the
X * kludge disallowing alias expansion on return addresses.
X */
X
Xremove_hostbang(addrs)
Xchar *addrs;
X{
X	int i, j, hlen, flen;
X
X	if ((hlen = strlen(hostname)) < 1)
X	  return;
X
X	flen = strlen(hostfullname);
X	i = j = 0;
X
X	while (addrs[i]) {
X	  if (i == 0 || isspace(addrs[i - 1])) {
X	    if (strncmp(&addrs[i], hostname, hlen) == 0 &&
X	      addrs[i + hlen] == '!') {
X	        i += hlen + 1;
X	        continue;
X	    }
X	    if (strncmp(&addrs[i], hostfullname, flen) == 0 &&
X	      addrs[i + flen] == '!') {
X	        i += flen + 1;
X	        continue;
X	    }
X	  }
X	  addrs[j++] = addrs[i++];
X	}
X	addrs[j] = 0;
X}
X
Xmail_form(address, subj)
Xchar *address, *subj;
X{
X	/** copy the appropriate variables to the shared space... */
X
X	strcpy(subject, subj);
X	strcpy(to, address);
X	strcpy(expanded_to, address);
X
X	return(mail(FORM, NO, NO));
X}
X
Xint
Xrecall_last_msg(filename, copy_msg, cancelled_msg, already_has_text)
Xchar *filename;
Xint  copy_msg, *cancelled_msg, *already_has_text;
X{
X	char ch;
X
X	/** If filename exists and we've recently cancelled a message,
X	    the ask if the user wants to use that message instead!  This
X	    routine returns TRUE if the user wants to retransmit the last
X	    message, FALSE otherwise...
X	**/
X
X	register int retransmit = FALSE;
X
X	if (access(filename, EDIT_ACCESS) == 0 && *cancelled_msg) {
X	  Raw(ON);
X	  CleartoEOLN();
X	  if (copy_msg)
X	    PutLine1(LINES-1,0,"Recall last kept message instead? (y/n) y%c",
X		     BACKSPACE);
X	  else
X	    PutLine1(LINES-1,0,"Recall last kept message? (y/n) y%c", 
X		     BACKSPACE);
X	  fflush(stdout);
X	  ch = ReadCh();
X	  if (tolower(ch) != 'n') {
X	    Write_to_screen("Yes.",0);	
X            retransmit++;
X	    *already_has_text = TRUE;
X	  }
X	  else 
X	    Write_to_screen("No.",0);	
X
X	  fflush(stdout);
X
X	  *cancelled_msg = 0;
X	}
X
X	return(retransmit);
X}
X
Xint
Xverify_transmission(filename, form_letter)
Xchar *filename;
Xint  *form_letter;
X{
X	/** Ensure the user wants to send this.  This routine returns
X	    the character entered.  Modified compliments of Steve Wolf 
X	    to add the'dead.letter' feature.
X	    Also added form letter support... 
X	**/
X
X	FILE *deadfd, *messagefd;
X	char ch, buffer[SLEN], fname[SLEN];
X	int x_coord, y_coord;
X
X	while(1) {
X	  /* clear bottom part of screen */
X	  MoveCursor(LINES-2,0);
X	  CleartoEOS();
X
X	  /* display prompt and menu according to
X	   * user level and what's available on the menu */
X	  if (user_level == 0) {
X	    PutLine0(LINES-2,0,
X      "Please choose one of the following options by parenthesized letter: s");
X	    GetXYLocation(&x_coord, &y_coord);
X	    y_coord--;	/* backspace over default answer */
X	    Centerline(LINES-1,
X	      "e)dit message, edit h)eaders, s)end it, or f)orget it.");
X	  } else {
X	    PutLine0(LINES-2, 0, "And now: s");
X	    GetXYLocation(&x_coord, &y_coord);
X	    y_coord--;	/* backspace over default answer */
X	    if (*form_letter == PREFORMATTED)  {
X	       strcpy(buffer, "Choose ");
X	    } else if (*form_letter == YES) {
X	       strcpy(buffer, "Choose e)dit form, ");
X	    } else if (*form_letter == MAYBE)  {
X	       strcpy(buffer, "Choose e)dit msg, m)ake form, ");
X	    } else {
X	       strcpy(buffer, "Choose e)dit message, ");
X	    }
X#ifdef ALLOW_SUBSHELL
X	    strcat(buffer, "!)shell, ");
X#endif
X	    strcat(buffer, "h)eaders, c)opy file, s)end, or f)orget.");
X	    Centerline(LINES-1, buffer);
X	  }
X
X	  /* wait for answer */
X	  fflush(stdin);
X	  fflush(stdout);
X	  Raw(ON);	/* double check... testing only... */
X	  MoveCursor(x_coord, y_coord);
X	  ch = ReadCh();
X	  ch = tolower(ch);
X
X	  /* process answer */
X	  switch (ch) {
X	     case 'f': Write_to_screen("Forget",0);
X		       if (mail_only) {
X			 /** try to save it as a dead letter file **/
X			 save_file_stats(fname);
X			 sprintf(fname, "%s/%s", home, dead_letter);
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			   error("Message not saved, Sorry.");
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			   error("Message not saved, Sorry.");
X			 } else {
X			   /* if we get here we're okay for everything */
X			   while (fgets(buffer, SLEN, messagefd) != NULL)
X			     fputs(buffer, deadfd);
X
X			   fclose(messagefd);
X			   fclose(deadfd);
X			   restore_file_stats(fname);
X
X			   error1("Message saved in file \"$HOME/%s\".",
X			     dead_letter);
X
X			}
X		       } else if (user_level != 0)
X			set_error("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 : continue;
X	                   }
X			 }
X			 else {
X	                    Write_to_screen("%c??", 1, 07);	/* BEEP */
X			    sleep(1);
X		            continue;
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		            continue;
X	                 }
X			 break;
X
X	     case 'h'  : Write_to_screen("Headers",0);
X			 break;
X
X	     case 'c'  : Write_to_screen("Copy file",0);
X			 break;
X
X	     case '!'  : break;
X
X	     default   : Write_to_screen("%c??", 1, 07);	/* BEEP */
X			 sleep(1);
X		         continue;
X	   }
X
X	   return(ch);
X	}
X}
X
XFILE *
Xwrite_header_info(filename, long_to, long_cc, long_bcc, form, copy)
Xchar *filename, *long_to, *long_cc, *long_bcc;
Xint   form, copy;
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	    If copy is TRUE, then treat this as the saved copy of outbound
X	    mail.
X	**/
X
X	char opentype[2];
X	long time(), thetime;
X	char *ctime();
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#ifdef MMDF
X	int   is_submit_mailer;		/* using submit means change From: */
X#endif /* MMDF */
X
X	char  *get_arpa_date();
X
X	if(copy)
X	    strcpy(opentype, "a");
X	else
X	    strcpy(opentype, "w");
X
X	save_file_stats(filename);
X	if ((filedesc = fopen(filename, opentype)) == 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	restore_file_stats(filename);
X
X	if(copy) {	/* Add top line that mailer would add */
X#ifdef MMDF
X	  fprintf(filedesc, MSG_SEPERATOR);
X#endif /* MMDF */
X	  thetime = time((long *) 0);
X	  fprintf(filedesc,"From %s %s", username, ctime(&thetime));
X	}
X
X#ifdef SITE_HIDING
X	if ( !copy && (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 MMDF
X	is_submit_mailer = (strcmp(submitmail,mailer) == 0);
X#endif /* MMDF */
X# ifdef SITE_HIDING
X#    ifdef MMDF
X	if (is_submit_mailer)
X	  fprintf(filedesc,"From: %s <%s>\n", full_username, username);
X	else
X#    endif /* MMDF */
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	  fprintf(filedesc,"From: %s <%s!%s>\n", full_username,
X		  hostname, username);
X# else
X#  ifdef  INTERNET
X#   ifdef  USE_DOMAIN
X#    ifdef MMDF
X	if (is_submit_mailer)
X	  fprintf(filedesc,"From: %s <%s>\n", full_username, username);
X	else
X#    endif /* MMDF */
X	  fprintf(filedesc,"From: %s <%s@%s>\n", full_username, 
X		username, hostfullname);
X#   else
X#    ifdef MMDF
X	if (is_submit_mailer)
X	  fprintf(filedesc,"From: %s <%s>\n", full_username, username);
X	else
X#    endif /* MMDF */
X	fprintf(filedesc,"From: %s <%s@%s>\n", full_username,
X		username, hostname);
X#   endif
X#  else
X#    ifdef MMDF
X	if (is_submit_mailer)
X	  fprintf(filedesc,"From: %s <%s>\n", full_username, username);
X	else
X#    endif /* MMDF */
X	fprintf(filedesc,"From: %s <%s!%s>\n", full_username,
X		hostname, username);
X#  endif
X# endif
X#endif
X
X	if (cc[0] != '\0')
X	    fprintf(filedesc, "Cc: %s\n", format_long(long_cc, strlen("Cc: ")));
X
X	if (copy && (bcc[0] != '\0'))
X	    fprintf(filedesc, "Bcc: %s\n", format_long(long_bcc, strlen("Bcc: ")));
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#ifndef NO_XHEADER
X	fprintf(filedesc, "X-Mailer: ELM [version %s]\n", version_buff);
X#endif /* !NO_XHEADER */
X
X	putc('\n', filedesc);
X
X	return((FILE *) filedesc);
X}
X
Xcopy_message_across(source, dest, copy)
XFILE *source, *dest;
Xint copy;
X{
X	/** Copy the message in the file pointed to by source to the
X	    file pointed to by dest.
X	    If copy is TRUE, treat as a saved copy of outbound mail. **/
X
X	int  crypted = FALSE;			/* are we encrypting?  */
X	int  encoded_lines = 0;			/* # lines encoded     */
X	char buffer[SLEN];			/* file reading buffer */
X
X	while (fgets(buffer, 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	          || (strncmp(buffer, DONT_SAVE2, strlen(DONT_SAVE2)) == 0)) {
X	      if(copy) break;  /* saved copy doesn't want anything after this */
X	      else 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	      encode(buffer);
X	      encoded_lines++;
X	    }
X	  }
X	  else if (crypted) {
X	    if (batch_only) {
X	      printf(
X		"Sorry. Cannot send encrypted mail in \"batch mode\".\n\r");
X	      leave();
X	    } else if (! gotten_key++)
X	      getkey(ON);
X	    else if (! encoded_lines)
X	      get_key_no_prompt();		/* reinitialize.. */
X	    encode(buffer);
X	    encoded_lines++;
X	  }
X
X	  if (copy && (strncmp(buffer, "From ", 5) == 0))
X	    /* Add in the > to a From on our copy */
X	    fprintf(dest, ">%s", buffer);
X
X	  else if (!copy && strcmp(buffer, ".\n") == 0)
X	    /* Because some mail transport agents take a lone period to
X	     * mean EOF, we add a blank space on outbound message.
X	     */
X	    fputs(". \n", dest);
X  	  else
X  	    if (fputs(buffer, dest) == EOF) {
X		Write_to_screen("\n\rWrite failed in copy_message_across\n\r", 0);
X		emergency_exit();
X	    }
X	} 
X#ifdef MMDF
X	if (copy) fputs(MSG_SEPERATOR, dest);
X#else
X	if (copy) fputs("\n", dest);	/* ensure a blank line at the end */
X#endif /* MMDF */
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	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	return(TRUE);
X}
X
X
Xint
Xappend_sig(file)
XFILE *file;
X{
X	/* Append the correct signature file to file.  Return TRUE if
X           we append anything.  */
X
X        /* Look at the to and cc list to determine which one to use */
X
X	/* We could check the bcc list too, but we don't want people to
X           know about bcc, even indirectly */
X
X	/* Some people claim that  user@anything.same_domain should be 
X	   considered local.  Since it's not the same machine, better be 
X           safe and use the remote sig (presumably it has more complete
X           information).  You can't necessarily finger someone in the
X           same domain. */
X
X	  if (!batch_only && (local_signature[0] || remote_signature[0])) {
X
X            char filename2[SLEN];
X	    char *sig;
X
X  	    if (index(expanded_to, '!') || index(expanded_cc,'!'))
X              sig = remote_signature;		/* ! always means remote */
X            else {
X	      /* check each @ for @thissite.domain */
X	      /* if any one is different than this, then use remote sig */
X	      int len;
X	      char *ptr;
X	      char sitename[SLEN];
X	      sprintf(sitename,"@%s",hostfullname);
X	      len = strlen(sitename);
X              sig = local_signature;
X              for (ptr = index(expanded_to,'@'); ptr;  /* check To: list */
X	          ptr = index(ptr+1,'@')) {
X		if (strincmp(ptr,sitename,len) != 0
X		    || (*(ptr+len) != ',' && *(ptr+len) != 0
X		    && *(ptr+len) != ' ')) {
X	          sig = remote_signature;
X                  break;
X                }
X              }
X              if (sig == local_signature)		   /* still local? */ 
X                for (ptr = index(expanded_cc,'@'); ptr;   /* check Cc: */
X		    ptr = index(ptr+1,'@')) {
X		  if (strincmp(ptr,sitename,len) != 0
X		      || (*(ptr+len) != ',' && *(ptr+len) != 0 
X		      && *(ptr+len) != ' ')) {
X	            sig = remote_signature;
X                    break;
X                  }
X                }
X            }
X
X            if (sig[0]) {  /* if there is a signature file */
X	      if (sig_dashes) /* dashes are optional */
X	        fprintf(file, "\n-- \n");  /* News 2.11 compatibility? */
X	      if (sig[0] != '/')
X	        sprintf(filename2, "%s/%s", home, sig);
X	      else
X	        strcpy(filename2, sig);
X	      (void) append(file, filename2);
X
X              return TRUE;
X            }
X          }
X
Xreturn FALSE;
X
X}
SHAR_EOF
# ============= src/mailtime.c ==============
echo "x - extracting src/mailtime.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > src/mailtime.c &&
X
Xstatic char rcsid[] = "@(#)$Id: mailtime.c,v 4.1 90/04/28 22:43:31 syd Exp $";
X
X/*******************************************************************************
X *  The Elm Mail System  -  $Revision: 4.1 $   $State: Exp $
X *
X * 			Copyright (c) 1986, 1987 Dave Taylor
X * 			Copyright (c) 1988, 1989, 1990 USENET Community Trust
X *******************************************************************************
X * Bug reports, patches, comments, suggestions should be sent to:
X *
X *	Syd Weinstein, Elm Coordinator
X *	elm@DSI.COM			dsinc!elm
X *
X *******************************************************************************
X * $Log:	mailtime.c,v $
X * Revision 4.1  90/04/28  22:43:31  syd
X * checkin of Elm 2.3 as of Release PL0
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 I_TIME
X#  include <time.h>
X#endif
X#ifdef I_SYSTIME
X#  include <sys/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}
SHAR_EOF
# ============= src/mkhdrs.c ==============
echo "x - extracting src/mkhdrs.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > src/mkhdrs.c &&
X
Xstatic char rcsid[] = "@(#)$Id: mkhdrs.c,v 4.1 90/04/28 22:43:32 syd Exp $";
X
X/*******************************************************************************
X *  The Elm Mail System  -  $Revision: 4.1 $   $State: Exp $
X *
X * 			Copyright (c) 1986, 1987 Dave Taylor
X * 			Copyright (c) 1988, 1989, 1990 USENET Community Trust
X *******************************************************************************
X * Bug reports, patches, comments, suggestions should be sent to:
X *
X *	Syd Weinstein, Elm Coordinator
X *	elm@DSI.COM			dsinc!elm
X *
X *******************************************************************************
X * $Log:	mkhdrs.c,v $
X * Revision 4.1  90/04/28  22:43:32  syd
X * checkin of Elm 2.3 as of Release PL0
X * 
X *
X ******************************************************************************/
X
X/** This contains all the header generating routines for the ELM
X    program.
X
X**/
X
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(headers[msg]->from, '!') != -1)
X	    tail_of(headers[msg]->from, buffer, 0);
X	  else
X	    strcpy(buffer, headers[msg]->from);
X	  sprintf(in_reply_to, "%s; from \"%s\" at %s %s, %s %s",
X                  headers[msg]->messageid[0] == '\0'? "<no.id>":
X		  headers[msg]->messageid,
X		  buffer,
X		  headers[msg]->month,
X		  headers[msg]->day,
X		  headers[msg]->year,
X		  headers[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[SLEN];
X
X	sprintf(filename, "%s/%s", home, mailheaders);
X
X	if ((fd = fopen(filename, "r")) != NULL) {
X	  while (fgets(buffer, SLEN, fd) != NULL)
X	    if (strlen(buffer) < 2) {
X	      dprint(2, (debugfile,
X	         "Strlen of line from .elmheaders is < 2 (write_header_info)"));
X	      error1("Warning: blank line in %s ignored!", filename);
X	      sleep(2);
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%s%d", temp_dir, temp_print, getpid());
X
X	sprintf(command_buffer, "%s > %s", command, fname);
X
X	system_call(command_buffer, SH, FALSE, FALSE);
X
X	if ((fd = fopen(fname, "r")) == NULL) {
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
# ============= src/newmbox.c ==============
echo "x - extracting src/newmbox.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > src/newmbox.c &&
X
Xstatic char rcsid[] = "@(#)$Id: newmbox.c,v 4.1.1.5 90/10/24 15:46:47 syd Exp $";
X
X/*******************************************************************************
X *  The Elm Mail System  -  $Revision: 4.1.1.5 $   $State: Exp $
X *
X * 			Copyright (c) 1988, USENET Community Trust
X * 			Copyright (c) 1988, 1989, 1990 USENET Community Trust
X *******************************************************************************
X * Bug reports, patches, comments, suggestions should be sent to:
X *
X *	Syd Weinstein, Elm Coordinator
X *	elm@DSI.COM			dsinc!elm
X *
X *******************************************************************************
X * $Log:	newmbox.c,v $
X * Revision 4.1.1.5  90/10/24  15:46:47  syd
X * Init time zone variable to avoid garbage strings
X * From: Norman J. Meluch
X * 
X * Revision 4.1.1.4  90/10/10  12:53:42  syd
X * allow words in either case
X * quickie fix
X * From: Syd
X * 
X * Revision 4.1.1.3  90/10/07  19:54:56  syd
X * fix where x.400 type mailers cause Elm to tag all messages as urgent.
X * From: ldk@udev.cdc.com (ld kelley x-6857)
X * 
X * Revision 4.1.1.2  90/06/26  20:18:06  syd
X * Fix double word
X * From: Peter Kendell <pete@tcom.stc.co.uk>
X * 
X * 
X * Revision 4.1.1.1  90/06/21  21:10:33  syd
X * Add another fixed mailbox id
X * From: Syd
X * 
X * Revision 4.1  90/04/28  22:43:34  syd
X * checkin of Elm 2.3 as of Release PL0
X * 
X *
X ******************************************************************************/
X
X/**  read new folder **/
X
X#include <ctype.h>
X#include "headers.h"
X
X#ifdef BSD
X#undef tolower		/* we have our own "tolower" routine instead! */
X#endif
X
X#include <sys/types.h>		
X#include <sys/stat.h>
X#include <errno.h>
X
X#ifdef I_TIME
X#  include <time.h>
X#endif
X#ifdef I_SYSTIME
X#  include <sys/time.h>
X#endif
X
Xextern int errno;
X
Xchar *error_name(), *error_description();
Xchar *malloc(), *realloc(), *strcpy(), *strncpy(), *rindex(), *index();
Xunsigned long sleep();
Xvoid rewind();
Xvoid exit();
Xlong bytes();
X
Xint
Xnewmbox(new_file, adds_only)
Xchar *new_file;
Xint adds_only;
X{
X	/** Read a folder.
X
X	    new_file	- name of folder  to read. It is up to the calling
X			  function to make sure that the file can be
X			  read by the user. This is not checked in this
X			  function. The reason why it is not checked here
X			  is due to the situation where the user wants to
X			  change folders: the new folder must be checked
X			  for access *before* leaving the old one, which
X			  is before this function gets called.
X	    adds_only	- set if we only want to read newly added messages to
X				same old folder.
X
X	**/
X
X	int  same_file;
X	int  new_folder_type;
X	int err;
X	char new_tempfile[SLEN];
X
X	/* determine type of new mailfile and calculate temp file name */
X	if((new_folder_type = get_folder_type(new_file)) == SPOOL)
X	  mk_temp_mail_fn(new_tempfile, new_file);
X	else
X	  *new_tempfile = '\0';
X
X	/* determine whether we are changing files */
X	same_file = !(strcmp(new_file, cur_folder));
X
X	/* If we are changing files and we are changing to a spool file,
X	 * make sure there isn't a temp file for it, because if
X	 * there is, someone else is using ELM to read the new file,
X	 * and we don't want to be reading it at the same time.
X	 */
X	if((new_folder_type == SPOOL) && (!same_file)) {
X	  if (access(new_tempfile, ACCESS_EXISTS) != -1) {
X	    if(folder_type != NO_NAME) ClearScreen();
X	    Centerline(15,
X	      "Hey! An instantiation of ELM is already reading this mail!");
X	    Centerline(17,
X	      "If this is in error, then you'll need to save a copy of");
X	    Centerline(18, "the following file then remove it:");
X	    Centerline(19, new_tempfile);
X	    MoveCursor(LINES, 0);  /* so shell prompt upon exit is on newline */
X	    silently_exit();
X	  }
X	}
X
X	/* If we were reading a spool file and we are not just reading
X	 * in the additional new messages to the same file, we need to
X	 * remove the corresponding tempfile.
X	 */
X
X	if((folder_type == SPOOL) && !adds_only) {
X	  if (access(cur_tempfolder, ACCESS_EXISTS) != -1) {
X	    if (unlink(cur_tempfolder) != 0) {
X	      error2("Sorry, can't unlink the temp file %s [%s]!\n\r",
X	        cur_tempfolder, error_name(errno));
X	      silently_exit();
X	    }
X	  }
X	}
X
X	/* Okay! Now establish this new file as THE file */
SHAR_EOF
echo "End of  part 14"
echo "File src/newmbox.c is continued in part 15"
echo "15" > shar3_seq_.tmp
exit 0
Newsgroups: biz.sco.sources