From: sources@anomaly.sbs.risc.net
Newsgroups: biz.sco.sources
Subject: v01i113 - ELM v2.3.11, Electronic Mail Reader - Part 13/20
Date: 13 Sep 92 17:43:37 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.13 (part 13 of a multipart archive)
# do not concatenate these parts, unpack them in order with /bin/sh
# file src/help.c continued
#
if test ! -r shar3_seq_.tmp; then
	echo "Please unpack part 1 first!"
	exit 1
fi
(read Scheck
 if test "$Scheck" != 13; then
	echo "Please unpack part $Scheck next!"
	exit 1
 else
	exit 0
 fi
) < shar3_seq_.tmp || exit 1
echo "x - Continuing file src/help.c"
sed 's/^X//' << 'SHAR_EOF' >> src/help.c &&
X		      break;
X
X	    case '#': if(!pager_help) s = 
X	    "# = Debug - display all information known about current message.";
X		      break;
X
X	    case '%': s = 
X     "% = Debug - display the computed return address of the current message.";
X		      break;
X
X	    case '*': if(!pager_help)
X		       s = "* = Go to the last message in the current folder.";
X		      break;
X
X	    case '-': if(!pager_help) s = 
X"- = Go to the previous page of messages.  This is the same as the LEFT arrow.";
X		      break;
X
X	    case '=': if(!pager_help) s = 
X			"'=' = Go to the first message in the current folder.";
X		      break;
X
X	    case ' ': if(pager_help) s =
X  "<space> = Display next screen of current message (or first screen of next).";
X		      else s = "<space> = Display the current message.";
X		      break;
X
X	    case '+': if(!pager_help)
X	    		s = 
X  "+ = Go to the next page of messages.  This is the same as the RIGHT arrow.";
X		      break;
X
X	    case '/': if(!pager_help)
X			s = "/ = Search for specified pattern in folder.";
X		      break;
X
X	    case '<': s = 
X	       "< = Scan current message for calendar entries (if enabled).";
X		      break;
X
X	    case '>': s = 
X	       "> = Save current message or tagged messages to specified file.";
X		      break;
X
X	    case '^': if(!pager_help) s = 
X	       "^ = Toggle the Delete/Undelete status of the current message.";
X		      break;
X
X	    case 'a': if(!pager_help) s = 
X	   "a = Enter the alias sub-menu section.  Create and display aliases.";
X		      break;
X
X	    case 'b': s = 
X      "b = Bounce (remail) a message to someone as if you have never seen it.";
X		      break;
X
X	    case 'C': s = 
X               "C = Copy current message or tagged messages to specified file.";
X		      break;
X
X	    case 'c': if(!pager_help) s = 
X	 "c = Change folders, leaving the current folder as if 'quitting'.";
X		      break;
X
X	    case 'd': s = "d = Mark the current message for future deletion.";
X		      break;
X
X	    case ctrl('D') : if(!pager_help) s =
X	      "^D = Mark for deletion all messages with the specified pattern.";
X		      break;
X
X	    case 'e': if(!pager_help) s = 
X     "e = Invoke the editor on the entire folder, resynchronizing when done.";
X		      break;
X
X	    case 'f': s = 
X	"f = Forward the current message to someone, return address is yours.";
X		      break;
X
X	    case 'g': s = 
X   "g = Group reply not only to the sender, but to everyone who received msg.";
X		      break;
X
X	    case 'h': s = 
X		 "h = Display message with all Headers (ignore weedout list).";
X	              break;
X
X	    case 'i': if(pager_help) s = "i = Return to the index.";
X		      break;
X
X	    case 'J': s = "J = Go to the next message.";
X		      break;
X
X	    case 'j': s = 
X  "j = Go to the next undeleted message.  This is the same as the DOWN arrow.";
X		      break;
X
X	    case 'K': s = "K = Go to the previous message.";
X		      break;
X
X	    case 'k': s = 
X"k = Go to the previous undeleted message.  This is the same as the UP arrow.";
X		      break;
X
X	    case 'l': if(!pager_help) s =
X               "l = Limit displayed messages based on the specified criteria.";
X		      break;
X
X	    case 'm': s = 
X		 "m = Create and send mail to the specified person or persons.";
X		      break;
X
X	    case 'n': if(pager_help)
X			s = "n = Display the next message.";
X		      else
X			s = 
X	   "n = Display the current message, then move current to next messge.";
X		      break;
X
X	    case 'o': if(!pager_help) s = "o = Go to the options submenu.";
X	              break;
X
X	    case 'p': s = 
X		      "p = Print the current message or the tagged messages.";
X	              break;
X
X	    case 'q': if(pager_help) s = 
X			"q = Quit the pager and return to the index.";
X		      else s =
X		    "q = Quit the mailer, asking about deletion, saving, etc.";
X		      break;
X
X	    case 'r': s = 
X"r = Reply to the message.  This only sends to the originator of the message.";
X	              break;
X
X	    case 's': s = 
X               "s = Save current message or tagged messages to specified file.";
X		      break;
X
X	    case 't': s = 
X               "t = Tag a message for further operations (or untag if tagged).";
X		      break;
X
X	    case ctrl('T') : if(!pager_help) s =
X			    "^T = Tag all messages with the specified pattern.";
X		      break;
X
X	    case 'u': s =
X		      "u = Undelete - remove the deletion mark on the message.";
X		      break;
X
X	    case 'x': s = "x = Exit the mail system quickly.";
X		      break;
X
X	    case 'Q': if(!pager_help) s = 
X		"Q = Quick quit the mailer, save read, leave unread, delete deleted.";
X		      break;
X
X	    case '\n':
X	    case '\r': if(pager_help)
X			 s =
X  "<return> = Display current message, or (builtin pager only) scroll forward.";
X		       else
X			 s = "<return> = Display the current message.";
X		       break;
X
X	    case ctrl('L'): if(!pager_help) s = "^L = Rewrite the screen.";	
X		       break;
X
X            case ctrl('?'):					    /* DEL */
X	    case ctrl('Q'): if(!pager_help) s = "Exit the mail system quickly.";
X		       break;
X
X	    default : if (isdigit(ch) && !pager_help) 
X	            s = "<number> = Make specified number the current message.";
X	  }
X
X	  ClearLine(info_line);
X	  Centerline(info_line, s);
X
X	} while (ch != '.');
X	
X	/** we'll never actually get here, but that's okay... **/
X
X	return(0);
X}
X
Xdisplay_helpfile(section)
Xint section;
X{
X	/*** Help me!  Read file 'helpfile.<section>' and echo to screen ***/
X
X	char buffer[SLEN];
X
X	sprintf(buffer, "%s/%s.%d", helphome, helpfile, section);
X	return(display_file(buffer));
X}
X
Xdisplay_file(file)
Xchar *file;
X{
X	/*** Display file to screen ***/
X
X	FILE *fileptr;
X	int  lines=0;
X	char buffer[SLEN];
X
X	if ((fileptr = fopen(file,"r")) == NULL) {
X	  dprint(1, (debugfile,
X		 "Error: Couldn't open file %s (help)\n", file));
X	  error1("Couldn't open file %s.",file);
X	  return(FALSE);
X	}
X	
X	ClearScreen();
X
X	while (fgets(buffer, SLEN, fileptr) != NULL) {
X	  if (lines > LINES-3) {
X	    PutLine0(LINES,0,"Press <space> to continue, 'q' to return.");
X	    if(ReadCh() == 'q') {
X	      clear_error();
X	      fclose(fileptr);
X	      return(TRUE);
X	    }
X	    lines = 0;
X	    ClearScreen();
X	    Write_to_screen("%s\r", 1, buffer);
X	  }
X	  else 
X	    Write_to_screen("%s\r", 1, buffer);
X
X	  lines += strlen(buffer)/COLUMNS + 1;
X	}
X
X        PutLine0(LINES,0,"Press any key to return.");
X
X	(void) ReadCh();
X	clear_error();
X
X	fclose(fileptr);
X	return(TRUE);
X}
SHAR_EOF
echo "File src/help.c is complete" &&
# ============= src/in_utils.c ==============
echo "x - extracting src/in_utils.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > src/in_utils.c &&
X
Xstatic char rcsid[] = "@(#)$Id: in_utils.c,v 4.1 90/04/28 22:43:13 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:	in_utils.c,v $
X * Revision 4.1  90/04/28  22:43:13  syd
X * checkin of Elm 2.3 as of Release PL0
X * 
X *
X ******************************************************************************/
X
X/** Mindless I/O routines for ELM 
X	
X**/
X
X#include "headers.h"
X#include <errno.h>
X#include <ctype.h>
X
X#ifdef BSD
X#  undef tolower
X#endif
X
Xextern int errno;		/* system error number */
X
Xunsigned alarm();
X
X#define isstopchar(c)		(c == ' ' || c == '\t' || c == '/')
X#define isslash(c)		(c == '/')
X#define erase_a_char()		{ Writechar(BACKSPACE); Writechar(' '); \
X			          Writechar(BACKSPACE); fflush(stdout); }
X
Xint
Xwant_to(question, dflt)
Xchar *question, dflt;
X{
X	/** Ask 'question' on LINES-2 left enough to just leave room for an
X	    answer, returning the answer in lower case.
X	    Echo answer as full "Yes" or "No".  'dflt' is the 
X	    default answer if <return> is pressed. (Note: 'dflt' is also what 
X	    will be returned if <return> is pressed!)
X	**/
X	register int ch, cols;
X
X	cols = COLUMNS - (strlen(question) + 5 );	/* 5 for "Yes." + 1 */
X
X	MoveCursor(LINES-3, cols);
X	CleartoEOLN();
X	PutLine3(LINES-3, cols,"%s%c%c", question, dflt, BACKSPACE);
X	fflush(stdout);
X	fflush(stdin);
X
X	ch = ReadCh();
X	ch = tolower(ch);
X
X	while (!( ch == 'y' || ch == 'n' || ch == '\n' || ch == '\r')) {
X	  ch = ReadCh();
X	  ch = tolower(ch);
X	}
X	if(ch == '\n' || ch == '\r')
X	  ch = dflt;
X
X	if(ch == 'y')
X	  Write_to_screen("Yes.", 0);
X	else
X	  Write_to_screen("No.", 0);
X
X	return(ch);
X}
X
Xint
Xread_number(ch)
Xchar ch;
X{
X	/** Read a number, where 'ch' is the leading digit! **/
X	
X	char buff[NLEN];
X	int  num;
X
X	buff[0] = ch;
X	buff[1] = '\0';
X
X	PutLine0(LINES-3, COLUMNS-40,"Set current message to :");
X	if (optionally_enter(buff, LINES-3, COLUMNS-15, TRUE, FALSE) == -1)
X	  return(current);
X
X	sscanf(buff,"%d", &num);
X	return(num);
X}
X
Xint
Xoptionally_enter(string, x, y, append_current, passwd)
Xchar *string;
Xint  x,y, append_current, passwd;
X{
X	/** This will display the string on the screen and allow the user to
X	    either accept it (by pressing RETURN) or alter it according to
X	    what the user types.   The various flags are:
X	         string    is the buffer to use (with optional initial value)
X	 	 x,y	   is the location we're at on the screen (-1,-1 means
X			   that we can't use this info and need to find out
X			   the current location)
X		 append_current  means that we have an initial string and that
X			   the cursor should be placed at the END of the line,
X			   not the beginning (the default).
X		 passwd	   accept non-printing characters and do not echo
X			   entered characters.
X	      
X	    If we hit an interrupt or EOF we'll return non-zero.
X	**/
X
X	int ch;
X	register int ch_count = 0, iindex = 0, escaped = OFF;
X
X	clearerr(stdin);
X
X	if(!passwd) {
X	  if(!(x >=0 && y >= 0))
X	    GetXYLocation(&x, &y);
X	  PutLine1(x, y, "%s", string);	
X	}
X
X	CleartoEOLN();
X
X	if (! append_current) {
X	  MoveCursor(x,y);
X	}
X	else
X	  iindex = strlen(string);
X
X	if (cursor_control)
X	  transmit_functions(OFF);
X
X	/** now we have the screen as we want it and the cursor in the 
X	    right place, we can loop around on the input and return the
X	    string as soon as the user presses <RETURN>
X	**/
X
X	do {
X	  ch = getchar();
X
X	  if (ch == ctrl('D') || ch == EOF) {		/* we've hit EOF */
X	    if (cursor_control)
X	      transmit_functions(ON);
X	    return(1);
X	  }
X
X	  if (ch_count++ == 0) {
X	    if (ch == '\n' || ch == '\r') {
X	      if (cursor_control)
X	        transmit_functions(ON);
X	      return(0);
X	    }
X	    else if (! append_current) {
X	      CleartoEOLN();
X	      iindex = (append_current? strlen(string) : 0);
X	    }
X	  }
X
X	  /* the following is converted from a case statement to
X	     allow the variable characters (backspace, kill_line
X	     and break) to be processed.  Case statements in
X	     C require constants as labels, so it failed ...
X	  */
X
X	  if (ch == backspace &&
X	    (!escaped || (!isprint(ch) && !passwd))) {
X	    /* This is tricky. Here we are dealing with all situations
X	     * under which a backspace (really whatever erase char is
X	     * set to, not necessarily \b) erases the previous character.
X	     * It will erase unless escaped, because if it's escaped
X	     * it is taken literally. There is one exception to that --
X	     * if backspace would be rejected (we don't accept non-printing
X	     * characters in non-passwd mode), we accept it here as an
X	     * erasing character, for it if got rejected there would
X	     * be no way of erasing a preceding backslash. */
X	    escaped = OFF;
X	    if (iindex > 0) {
X	      if(!passwd)
X		Writechar(BACKSPACE);
X  	      iindex--;
X	    }
X	    if(!passwd) {
X	      Writechar(' ');
X	      Writechar(BACKSPACE);
X	      fflush(stdout);
X	    }
X	  }
X	  else if (ch == EOF || ch == '\n' || ch == '\r') {
X	    escaped = OFF;
X	    string[iindex] = '\0';
X	    if (cursor_control)
X	      transmit_functions(ON);
X	    return(0);
X	  }
X	  else if (!passwd && ch == ctrl('W')) {	/* back up a word! */
X	    escaped = OFF;
X	    if (iindex == 0)
X	      continue;		/* no point staying here.. */
X	    iindex--;
X	    if (isslash(string[iindex])) {
X	      erase_a_char();
X	    }
X	    else {
X	      while (iindex >= 0 && isspace(string[iindex])) {
X	        iindex--;
X	        erase_a_char();
X	      }
X
X	      while (iindex >= 0 && ! isstopchar(string[iindex])) {
X	        iindex--;
X	        erase_a_char();
X	      }
X	      iindex++;	/* and make sure we point at the first AVAILABLE slot */
X	    }
X	  }
X	  else if (!passwd && ch == ctrl('R')) {
X	    escaped = OFF;
X	    string[iindex] = '\0';
X	    PutLine1(x,y, "%s", string);	
X	    CleartoEOLN();
X	  }
X	  else if (!escaped && ch == kill_line) {
X	    /* needed to test if escaped since kill_line character could
X	     * be a desired valid printing character */
X	    escaped = OFF;
X	    if(!passwd) {
X	      MoveCursor(x,y);
X	      CleartoEOLN();
X	    }
X	    iindex = 0;
X	  }
X	  else if (ch == '\0') {
X	    escaped = OFF;
X	    if (cursor_control)
X	      transmit_functions(ON);
X	    fflush(stdin); 	/* remove extraneous chars, if any */
X	    string[0] = '\0'; /* clean up string, and... */
X	    return(-1);
X	  }
X	  else if (!passwd && !isprint(ch)) {
X	    /* non-printing character - warn with bell*/
X	    /* don't turn off escaping backslash since current character
X	     * doesn't "use it up".
X	     */
X	    Writechar('\007');
X	  }
X	  else {  /* default case */
X	      if(escaped && (ch == backspace || ch == kill_line)) {
X		/* if last character was a backslash,
X		 * and if this character is escapable
X		 * simply write this character over it even if
X		 * this character is a backslash.
X		 */
X		if(!passwd)
X		  Writechar(BACKSPACE);
X		iindex--;
X		string[iindex++] = ch;
X		if(!passwd)
X		  Writechar(ch);
X	        escaped = OFF;
X	      } else {
X		string[iindex++] = ch;
X		if(!passwd)
X		  Writechar(ch);
X		escaped = ( ch == '\\' ? ON : OFF);
X	      }
X	  }
X	} while (iindex < SLEN);
X
X	string[iindex] = '\0';
X
X	if (cursor_control)
X	  transmit_functions(ON);
X
X	return(0);
X}
X
Xint
Xpattern_enter(string, alt_string, x, y, alternate_prompt)
Xchar *string, *alt_string, *alternate_prompt;
Xint  x,y;
X{
X	/** This function is functionally similar to the routine
X	    optionally-enter, but if the first character pressed
X	    is a '/' character, then the alternate prompt and string
X	    are used rather than the normal one.  This routine 
X	    returns 1 if alternate was used, 0 if not
X	**/
X
X	int ch;
X	register iindex = 0, escaped = OFF;
X
X	PutLine1(x, y, "%s", string);	
X	CleartoEOLN();
X	MoveCursor(x,y);
X
X	if (cursor_control)
X	  transmit_functions(OFF);
X
X	ch = getchar();
X
X	if (ch == '\n' || ch == '\r') {
X	  if (cursor_control)
X	    transmit_functions(ON);
X	  return(0);	/* we're done.  No change needed */
X	}
X	
X	if (ch == '/') {
X	  PutLine1(x, 0, "%s", alternate_prompt);
X	  CleartoEOLN();
X	  (void) optionally_enter(alt_string, x, strlen(alternate_prompt)+1,
X		 FALSE, FALSE);
X	  return(1);
X	}
X
X	CleartoEOLN();
X
X	iindex = 0;
X
X	if (ch == kill_line) {
X	  MoveCursor(x,y);
X          CleartoEOLN();
X	  iindex = 0;
X	}
X	else if (ch != backspace) {
X	  if(ch == '\\') escaped = ON;
X	  Writechar(ch);
X	  string[iindex++] = ch;
X	}
X	else if (iindex > 0) {
X	  iindex--;
X	  erase_a_char();
X	}
X	else {
X	  Writechar(' ');
X	  Writechar(BACKSPACE);
X	}
X
X	do {
X	  fflush(stdout);
X	  ch = getchar();
X
X	  /* the following is converted from a case statement to
X	     allow the variable characters (backspace, kill_line
X	     and break) to be processed.  Case statements in
X	     C require constants as labels, so it failed ...
X	  */
X
X	    if (ch == backspace &&
X	      (!escaped || !isprint(ch)) ) {
X	      /* This is tricky. Here we are dealing with all situations
X	       * under which a backspace (really whatever erase char is
X	       * set to, not necessarily \b) erases the previous character.
X	       * It will erase unless escaped, because if it's escaped
X	       * it is taken literally. There is one exception to that --
X	       * if backspace would be rejected (we don't accept non-printing
X	       * characters in non-passwd mode), we accept it here as an
X	       * erasing character, for it if got rejected there would
X	       * be no way of erasing a preceding backslash. */
X	      escaped = OFF;
X              if (iindex > 0) {
X		iindex--;
X		erase_a_char();
X	      }
X	      else {
X		Writechar(' ');
X		Writechar(BACKSPACE);
X	      }
X	    }
X	    else if (ch == '\n' || ch == '\r') {
X	      escaped = OFF;
X	      string[iindex] = '\0';
X	      if (cursor_control)
X	        transmit_functions(ON);
X	      return(0);
X	    }
X	    else if (ch == ctrl('W')) {
X	      escaped = OFF;
X	      if (iindex == 0)
X	        continue;		/* no point staying here.. */
X	      iindex--;
X	      if (isslash(string[iindex])) {
X	        erase_a_char();
X	      }
X	      else {
X	        while (iindex >= 0 && isspace(string[iindex])) {
X	          iindex--;
X	          erase_a_char();
X	        }
X
X	        while (iindex >= 0 && ! isstopchar(string[iindex])) {
X	          iindex--;
X	          erase_a_char();
X	        }
X	        iindex++;/* and make sure we point at the first AVAILABLE slot */
X	      }
X	    }
X	    else if (ch == ctrl('R')) {
X	      escaped = OFF;
X	      string[iindex] = '\0';
X	      PutLine1(x,y, "%s", string);	
X	      CleartoEOLN();
X	    }
X	    else if (!escaped && ch == kill_line) {
X	      /* needed to test if escaped since kill_line character could
X	       * be a desired valid printing character */
X	      escaped = OFF;
X	      MoveCursor(x,y);
X              CleartoEOLN();
X	      iindex = 0;
X	    }
X	    else if (ch == '\0') {
X	      escaped = OFF;
X	      if (cursor_control)
X	        transmit_functions(ON);
X	      fflush(stdin); 	/* remove extraneous chars, if any */
X	      string[0] = '\0'; /* clean up string, and... */
X	      return(-1);
X	    }
X	    else if (!isprint(ch)) {
X	      /* non-printing character - warn with bell*/
X	      /* don't turn off escaping backslash since current character
X	       * doesn't "use it up".
X	       */
X	      Writechar('\007');
X	    }
X	    else {  /* default case */
X		if(escaped && (ch == backspace || ch == kill_line)) {
X		  /* if last character was a backslash,
X		   * and if this character is escapable
X		   * simply write this character over it even if
X		   * this character is a backslash.
X		   */
X		  Writechar(BACKSPACE);
X		  iindex--;
X		  string[iindex++] = ch;
X		  Writechar(ch);
X		  escaped = OFF;
X		} else {
X		  string[iindex++] = ch;
X		  Writechar(ch);
X		  escaped = ( ch == '\\' ? ON : OFF);
X		}
X	    }
X	} while (iindex < SLEN);
X
X	string[iindex] = '\0';
X
X	if (cursor_control)
X	  transmit_functions(ON);
X	return(0);
X}
X
Xint
XGetPrompt()
X{
X	/** This routine does a read/timeout for a single character.
X	    The way that this is determined is that the routine to
X	    read a character is called, then the "errno" is checked
X	    against EINTR (interrupted call).  If they match, this
X	    returns NO_OP_COMMAND otherwise it returns the normal
X	    command.  On BSD systems, the EINTR will never be returned
X	    so we instead longjmp from the signal handler.
X	**/
X
X	int ch;
X
X	if (timeout > 0) {
X	  alarm((unsigned) timeout);
X#ifdef	BSD
X	  if (setjmp(GetPromptBuf)) {
X	    InGetPrompt = 0;
X	    ch = NO_OP_COMMAND;
X	    alarm((unsigned) 0);
X	  }
X	  else {
X	    InGetPrompt = 1;
X	    ch = ReadCh();
X	    InGetPrompt = 0;
X	    alarm((unsigned) 0);
X	  }
X#else
X	    errno = 0;	/* we actually have to do this.  *sigh*  */
X	    ch = ReadCh();
X	    if (errno == EINTR) ch = NO_OP_COMMAND;
X	    alarm((unsigned) 0);
X#endif
X	}
X	else
X	  ch = ReadCh();
X
X	return(ch);
X}
SHAR_EOF
# ============= src/init.c ==============
echo "x - extracting src/init.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > src/init.c &&
X
Xstatic char rcsid[] = "@(#)$Id: init.c,v 4.1.1.4 90/12/05 14:34:08 syd Exp $";
X
X/*******************************************************************************
X *  The Elm Mail System  -  $Revision: 4.1.1.4 $   $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:	init.c,v $
X * Revision 4.1.1.4  90/12/05  14:34:08  syd
X * fix dropping of unused vars, dropped to much
X * From: Syd
X * 
X * Revision 4.1.1.3  90/10/24  15:33:11  syd
X * Remove variables no longer used
X * From: W. David Higgins
X * 
X * Revision 4.1.1.2  90/08/02  21:57:56  syd
X * The newly introduced function 'stricmp' has a name conflict with a libc
X * function under SunOS 4.1.  Changed name to istrcmp.
X * From: scs@lokkur.dexter.mi.us (Steve Simmons)
X * 
X * Revision 4.1.1.1  90/07/12  23:19:17  syd
X * Make domain name checking case independent
X * From: Syd, reported by Steven Baur
X * 
X * Revision 4.1  90/04/28  22:43:15  syd
X * checkin of Elm 2.3 as of Release PL0
X * 
X *
X ******************************************************************************/
X
X/***** Initialize - read in all the defaults etc etc 
X*****/
X
X#include "headers.h"
X#include "patchlevel.h"
X
X#ifdef TERMIOS
X#  include <termios.h>
X   typedef struct termios term_buff;
X#else
X# ifdef TERMIO
X#  include <termio.h>
X#  define tcgetattr(fd,buf)	ioctl((fd),TCGETA,(buf))
X   typedef struct termio term_buff;
X# else
X#  include <sgtty.h>
X#  define tcgetattr(fd,buf)	ioctl((fd),TIOCGETP,(buf))
X   typedef struct sgttyb term_buff;
X# endif
X#endif
X
X#ifdef PWDINSYS
X#  include <sys/pwd.h>
X#else
X#  include <pwd.h>
X#endif
X
X#ifdef I_TIME
X#  include <time.h>
X#endif
X#ifdef I_SYSTIME
X#  include <sys/time.h>
X#endif
X
X#include <signal.h>
X#include <ctype.h>
X#include <errno.h>
X
X#ifdef BSD
X#undef toupper
X#undef tolower
X#endif
X
Xextern int errno;		/* system error number on failure */
Xextern char version_buff[];
X
Xchar *error_name(), *error_description();
X
Xchar *getenv(), *getlogin(), *strcpy(), *strcat(), *index();
Xunsigned short getgid(), getuid(); 
Xvoid exit();
X#ifndef	_POSIX_SOURCE
Xstruct passwd *getpwuid();
X#endif
Xchar *get_full_name();
X
X#ifdef VOIDSIG
X  void
X#else
X  int
X#endif
X#ifdef SIGTSTP
X	sig_user_stop(), sig_return_from_user_stop(),
X#endif
X	quit_signal(), term_signal(), ill_signal(),
X	fpe_signal(),  bus_signal(),  segv_signal(),
X	alarm_signal(), pipe_signal(), hup_signal();
X
Xinitialize(requestedmfile)
Xchar *requestedmfile;	/* first mail file to open, empty if the default */
X{
X	/** initialize the whole ball of wax.
X	**/
X	struct passwd *pass;
X	register int i, hostlen, domlen; 
X
X#if defined(SIGVEC) & defined(SV_INTERRUPT)
X	struct sigvec alarm_vec;
X#endif
X	char     buffer[SLEN], *cp;
X
X	sprintf(version_buff, "%s PL%d", VERSION, PATCHLEVEL);
X	Raw(ON);
X
X	/* save original user and group ids */
X	userid  = getuid();
X	groupid = getgid();	
X
X	/* make all newly created files private */
X	original_umask = umask(077);
X
X	/* Get username (logname), home (login directory), and full_username
X	 * (part of GCOS) field from the password entry for this user id.
X	 * Full_username will get overridden by fullname in elmrc, if defined.
X	 */
X
X	if((pass = getpwuid(userid)) == NULL) {
X	  error("You have no password entry!");
X	  Raw(OFF);
X	  exit(1);
X	}
X	strcpy(username, pass->pw_name);
X	strcpy(home, pass->pw_dir);
X
X	if((cp = get_full_name(username)) != NULL)
X	  strcpy(full_username, cp);
X	else
X	  strcpy(full_username, username);	/* fall back on logname */
X
X#ifdef DEBUG
X	if (debug) {		/* setup for dprint() statements! */
X	  char newfname[SLEN], filename[SLEN];
X
X	  sprintf(filename, "%s/%s", home, DEBUGFILE);
X	  if (access(filename, ACCESS_EXISTS) == 0) {	/* already one! */
X	    sprintf(newfname,"%s/%s", home, OLDEBUG);
X	    (void) rename(filename, newfname);
X	  }
X
X	  /* Note what we just did up there: we always save the old
X	     version of the debug file as OLDEBUG, so users can mail
X	     copies of bug files without trashing 'em by starting up
X	     the mailer.  Dumb, subtle, but easy enough to do!
X 	  */
X
X	  if ((debugfile = fopen(filename, "w")) == NULL) {
X	    debug = 0;	/* otherwise 'leave' will try to log! */
X	    leave(fprintf(stderr,"Could not open file %s for debug output!\n",
X		  filename));
X	  }
X	  chown(filename, userid, groupid); /* file owned by user */
X
X	  fprintf(debugfile, 
X     "Debug output of the ELM program (at debug level %d).  Version %s\n\n",
X		  debug, version_buff);
X	}
X#endif
X
X	/*
X	 * If debug level is fairly low, ignore keyboard signals
X	 * until the screen is set up.
X	 */
X	if (debug < 5) {
X	  signal(SIGINT,  SIG_IGN);
X	  signal(SIGQUIT, SIG_IGN);
X	}
X
X	if(!check_only && !batch_only) {
X	  if ((i = InitScreen()) < 0) {
X	    if (i == -1) {
X	      printf( 
X"Sorry, but you must specify what type of terminal you're on if you want to\n");
X	      printf( 
X"run the \"elm\" program. (You need your environment variable \"TERM\" set.)\n"
X		     );
X	      dprint(1,(debugfile,"No $TERM variable in environment!\n"));
X	    }
X	    else if (i == -2) {
X	      printf(
X"You need a cursor-addressable terminal to run \"elm\" and I can't find any\n");
X	      printf(
X"kind of termcap entry for \"%s\" - check your \"TERM\" setting...\n",
X		   getenv("TERM"));
X	      dprint(1,
X		(debugfile,"$TERM variable is an unknown terminal type!\n"));
X	    } else {
X	      printf("Failed trying to initialize your terminal entry: unknown return code %d\n", i);
X	      dprint(1, (debugfile, "Initscreen returned unknown code: %d\n",
X		  i));
X	    }
X	    Raw(OFF);
X	    exit(1);	/* all the errors share this exit statement */
X	  }
X	}
X
X	if (debug < 5) {	/* otherwise let the system trap 'em! */
X	  signal(SIGQUIT, quit_signal);		/* Quit signal 	            */
X	  signal(SIGTERM, term_signal); 	/* Terminate signal         */
X	  signal(SIGILL,  ill_signal);		/* Illegal instruction      */
X	  signal(SIGFPE,  fpe_signal);		/* Floating point exception */
X	  signal(SIGBUS,  bus_signal);		/* Bus error  		    */
X	  signal(SIGSEGV, segv_signal);		/* Segmentation Violation   */
X	  signal(SIGHUP,  hup_signal);		/* HangUp (line dropped)    */
X	}
X	else {
X	  dprint(3,(debugfile,
X  "\n*** Elm-Internal Signal Handlers Disabled due to debug level %d ***\n\n",
X		    debug));
X	}
X#if defined(SIGVEC) & defined(SV_INTERRUPT)
X	alarm_vec.sv_handler = alarm_signal;
X	alarm_vec.sv_flags = SV_INTERRUPT;
X	sigvec (SIGALRM, &alarm_vec, (struct sigvec *)0);	/* Process Timer Alarm	    */
X#else
X	signal(SIGALRM, alarm_signal);		/* Process Timer Alarm      */
X#endif
X	signal(SIGPIPE, pipe_signal);		/* Illegal Pipe Operation   */
X#ifdef SIGTSTP
X	signal(SIGTSTP, sig_user_stop);		/* Suspend signal from tty  */
X	signal(SIGCONT, sig_return_from_user_stop);	/* Continue Process */
X#endif
X
X	get_term_chars();
X
X	/*
X	 * Get the host name as per configured behavior.
X	 */
X#ifdef HOSTCOMPILED
X	strncpy(hostname, HOSTNAME, sizeof(hostname) - 1);
X	hostname[sizeof(hostname) - 1] = '\0';
X#else
X	gethostname(hostname, sizeof(hostname));
X#endif
X
X	/*
X	 * now get the domain name, used to build the full name
X	 */
X	gethostdomain(hostdomain, sizeof(hostdomain));
X
X	/*
X	 * now the tough part:
X	 *	we need to make three variables out of this stuff:
X	 *	hostname = just the hostname, as in bangpaths,
X	 *		this is whatever the user gave us so far,
X	 *		we wont change this one
X	 *	hostdomain = this is the domain considered local to this
X	 *		machine, and should be what we got above.
X	 *	hostfullname = this is the full FQDN of this machine,
X	 *		and is a strange combination of the first two.
X	 *	if tail(hostname) == hostdomain
X	 *		then hostfullname = hostname
X	 *			ie: node.ld.domain.type, ld.domain.type -> node.ld.domain.type
X	 *	else if hostname == hostdomain + 1
X	 *		then hostfullname = hostname
X	 *			ie: domain.type, .domain.type -> domain.type
X	 *	
X	 *	else hostfullname = hostname + hostdomain
X	 *			ie: host, .domain.type -> host.domain.type
X	 * lost yet?
X	 */
X	hostlen = strlen(hostname);
X	domlen = strlen(hostdomain);
X	if (hostlen >= domlen) {
X	  if (istrcmp(&hostname[hostlen - domlen], hostdomain) == 0)
X	    strcpy(hostfullname, hostname);
X	  else {
X	    strcpy(hostfullname, hostname);
X	    strcat(hostfullname, hostdomain);
X	  }
X	} else {
X	  if (istrcmp(hostname, hostdomain + 1) == 0)
X	    strcpy(hostfullname, hostname);
X	  else {
X	    strcpy(hostfullname, hostname);
X	    strcat(hostfullname, hostdomain);
X	  }
X	}
X
X	/* Determine the default mail file name.
X	 * 
X	 * First look for an environment variable MAIL, then
X	 * use then mailhome if it is not found
X	 */
X	if ((cp = getenv("MAIL")) == NULL)
X		sprintf(defaultfile, "%s%s", mailhome, username);
X	else
X		strcpy(defaultfile, cp);
X
X	/* Determine options that might be set in the .elm/elmrc */
X	read_rc_file();
X
X	/* Determine the mail file to read */
X	if (*requestedmfile == '\0')
X	  strcpy(requestedmfile, defaultfile);
X	else if(!expand_filename(requestedmfile, FALSE)) {
X	    Raw(OFF);
X	    exit(0);
X        }
X	if (check_size)
X	  if(check_mailfile_size(requestedmfile) != 0) {
X	      Raw(OFF);
X	      exit(0);
X	  }
X
X	/* check for permissions only if not send only mode file */
X	if (! mail_only) {
X	  if ((errno = can_access(requestedmfile, READ_ACCESS)) != 0) {
X	    if (strcmp(requestedmfile, defaultfile) != 0 || errno != ENOENT) {
X	      dprint(1, (debugfile,
X		    "Error: given file %s as folder - unreadable (%s)!\n", 
X		    requestedmfile, error_name(errno)));
X	      fprintf(stderr,"Can't open folder '%s' for reading!\n",
X		    requestedmfile);
X	      Raw(OFF);
X	      exit(1);
X	    }
X	  }
X	}
X
X	/** check to see if the user has defined a LINES or COLUMNS
X	    value different to that in the termcap entry (for
X	    windowing systems, of course!) **/
X
X	ScreenSize(&LINES, &COLUMNS);
X
X	if ((cp = getenv("LINES")) != NULL && isdigit(*cp)) {
X	  sscanf(cp, "%d", &LINES);
X	  LINES -= 1;	/* kludge for HP Window system? ... */
X	}
X
X	if ((cp = getenv("COLUMNS")) != NULL && isdigit(*cp))
X	  sscanf(cp, "%d", &COLUMNS);
X
X	/** fix the shell if needed **/
X
X	if (shell[0] != '/') {
X	   sprintf(buffer, "/bin/%s", shell);
X	   strcpy(shell, buffer);
X	}
X
X	if (! mail_only && ! check_only) {
X
X	  /* get the cursor control keys... */
X
X	  cursor_control = FALSE;
X
X	  if ((cp = return_value_of("ku")) != NULL) {
X	    strcpy(up, cp);
X	    if ((cp = return_value_of("kd")) != NULL) {
X	      strcpy(down, cp);
X	      if ((cp = return_value_of("kl")) != NULL) {
X		strcpy(left, cp);
X		if ((cp = return_value_of("kr")) != NULL) {
X		  strcpy(right, cp);
X		  cursor_control = TRUE;
X		  transmit_functions(ON);
X		}
X	      }
X	    }
X	  }
X	  if (!arrow_cursor) 	/* try to use inverse bar instead */
X	    if (return_value_of("so") != NULL && return_value_of("se") != NULL)
X	        has_highlighting = TRUE;
X	}
X
X	/** clear the screen **/
X	if(!check_only && !batch_only)
X	  ClearScreen();
X
X	if (! mail_only && ! check_only) {
X	  if (mini_menu)
X	    headers_per_page = LINES - 13;
X	  else
X	    headers_per_page = LINES -  8;	/* 5 more headers! */
X
X	  newmbox(requestedmfile, FALSE);	/* read in the folder! */
X	}
X
X#ifdef DEBUG
X	if (debug >= 2 && debug < 10) {
X	  fprintf(debugfile,
X"hostname = %-20s \tusername = %-20s \tfullname = %-20s\n",
X	         hostname, username, full_username);
X
X	  fprintf(debugfile,
X"home     = %-20s \teditor   = %-20s \trecvd_mail  = %-20s\n",
X		 home, editor, recvd_mail);
X
X	  fprintf(debugfile,
X"cur_folder   = %-20s \tfolders  = %-20s \tprintout = %-20s\n",
X		 cur_folder, folders, printout);
X	
X	  fprintf(debugfile,
X"sent_mail = %-20s \tprefix   = %-20s \tshell    = %-20s\n\n",
X		sent_mail, prefixchars, shell);
X	
X	  if (local_signature[0])
X	    fprintf(debugfile, "local_signature = \"%s\"\n",
X			local_signature);
X	  if (remote_signature[0])
X	    fprintf(debugfile, "remote_signature = \"%s\"\n",
X			remote_signature);
X	  if (local_signature[0] || remote_signature[0])
X	    fprintf(debugfile, "\n");
X	}
X#endif
X}
X
Xget_term_chars()
X{
X	/** This routine sucks out the special terminal characters
X	    ERASE and KILL for use in the input routine.  The meaning 
X            of the characters are (dare I say it?) fairly obvious... **/
X
X	term_buff term_buffer;
X
X	if (tcgetattr(STANDARD_INPUT,&term_buffer) == -1) {
X	  dprint(1, (debugfile,
X		   "Error: %s encountered on ioctl call (get_term_chars)\n", 
X		   error_name(errno)));
X	  /* set to defaults for terminal driver */
X	  backspace = BACKSPACE;
X	  kill_line = ctrl('U');
X	}
X	else {
X#if defined(TERMIO) || defined(TERMIOS)
X	  backspace = term_buffer.c_cc[VERASE];
X	  kill_line = term_buffer.c_cc[VKILL];
X#else
X	  backspace = term_buffer.sg_erase;
X	  kill_line = term_buffer.sg_kill;
X#endif
X	}
X}
SHAR_EOF
# ============= src/leavembox.c ==============
echo "x - extracting src/leavembox.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > src/leavembox.c &&
X
Xstatic char rcsid[] = "@(#)$Id: leavembox.c,v 4.1.1.6 90/12/06 13:38:55 syd Exp $";
X
X/*******************************************************************************
X *  The Elm Mail System  -  $Revision: 4.1.1.6 $   $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:	leavembox.c,v $
X * Revision 4.1.1.6  90/12/06  13:38:55  syd
X * disable stop signal around writeback to avoid corrupted file
X * From: Syd via report from Tom Davis <tdd@endure.cl.msu.edu>
X * 
X * Revision 4.1.1.5  90/10/10  12:49:46  syd
X * Fix calling sequence to copy_message calls for
X * new MMDF argument
X * From: Syd
X * 
X * Revision 4.1.1.4  90/08/15  21:00:07  syd
X * Change elm to not delete empty folders on a resync
X * From: Syd
X * 
X * Revision 4.1.1.3  90/06/21  22:51:52  syd
X * Add time.h to includes as some OSs include needed substructure only
X * from time.h
X * From: Syd
X * 
X * Revision 4.1.1.2  90/06/21  22:48:14  syd
X * patch to fix up the Log headers.
X * From: pdc%lunch.wpd@sgi.com (Paul Close)
X * 
X * Revision 4.1.1.1  90/06/09  21:33:23  syd
X * Some flock()s refuse to exclusively lock a fd open for read-only access.
X * From: pdc%lunch.wpd@sgi.com (Paul Close)
X * 
X * Revision 4.1  90/04/28  22:43:18  syd
X * checkin of Elm 2.3 as of Release PL0
X * 
X *
X ******************************************************************************/
X
X/** leave current folder, updating etc. as needed...
X  
X**/
X
X#include "headers.h"
X#include <sys/types.h>
X#include <sys/stat.h>
X#ifdef LOCK_BY_FLOCK
X#include <sys/file.h>
X#endif
X#include <errno.h>
X#ifdef I_TIME
X#  include <time.h>
X#endif
X#ifdef I_SYSTIME
X#  include <sys/time.h>
X#endif
X
X
X/**********
X   Since a number of machines don't seem to bother to define the utimbuf
X   structure for some *very* obscure reason.... 
X
X   Suprise, though, BSD has a different utime() entirely...*sigh*
X**********/
X
X#ifndef BSD
X# ifdef NOUTIMBUF
X
Xstruct utimbuf {
X	time_t	actime;		/** access time       **/ 
X	time_t	modtime;	/** modification time **/
X       };
X
X
X# endif /* NOUTIMBUF */
X#endif /* BSD */
X
Xextern int errno;
X
Xchar *error_name(), *error_description(), *strcpy(), *rindex();
Xunsigned short getegid();
X#ifndef	_POSIX_SOURCE
Xunsigned long sleep();
X#endif
X
Xint
Xleave_mbox(resyncing, quitting, prompt)
Xint resyncing, quitting, prompt;
X{
X	/** Close folder, deleting some messages, storing others in mbox,
X	    and keeping others, as directed by user input and elmrc options.
X
X	    Return	1	Folder altered
X			0	Folder not altered
X			-1	New mail arrived during the process and
X					closing was aborted.
X	    If "resyncing" we are just writing out folder to reopen it. We
X		therefore only consider deletes and keeps, not stores to mbox.
X		Also we don't remove NEW status so that it can be preserved
X		across the resync.
X
X	    If "quitting" and "prompt" is false, then no prompting is done.
X		Otherwise prompting is dependent upon the variable
X		question_me, as set by an elmrc option.  This behavior makes
X		the 'q' command prompt just like 'c' and '$', while
X		retaining the 'Q' command for a quick exit that never
X		prompts.
X	**/
X
X	FILE *temp;
X	char temp_keep_file[SLEN], buffer[SLEN];
X	struct stat    buf;		/* stat command  */
X#ifdef BSD
X	time_t utime_buffer[2];		/* utime command */
X#else
X	struct utimbuf utime_buffer;	/* utime command */
X#endif
X#ifdef VOIDSIG
X	void	(*oldstop)();
X#else
X	int	(*oldstop)();
X#endif
X	register int to_delete = 0, to_store = 0, to_keep = 0, i,
X		     marked_deleted, marked_read, marked_unread,
X		     last_sortby, ask_questions,  asked_storage_q,
X		     num_chgd_status, need_to_copy;
X	char answer;
X	long bytes();
X
X	dprint(1, (debugfile, "\n\n-- leaving folder --\n\n"));
X
X	if (message_count == 0)
X	  return(0);	/* nothing changed */
X
X	ask_questions = ((quitting && !prompt) ? FALSE : question_me);
X
X	/* YES or NO on softkeys */
X	if (hp_softkeys && ask_questions) {
X	  define_softkeys(YESNO);
X	  softkeys_on();
X	}
X
X	/* Clear the exit dispositions of all messages, just in case
X	 * they were left set by a previous call to this function
X	 * that was interrupted by the receipt of new mail.
X	 */
X	for(i = 0; i < message_count; i++)
X	  headers[i]->exit_disposition = UNSET;
X	  
X	/* Determine if deleted messages are really to be deleted */
X
X	/* we need to know if there are none, or one, or more to delete */
X	for (marked_deleted=0, i=0; i<message_count && marked_deleted<2; i++)
X	  if (ison(headers[i]->status, DELETED))
X	    marked_deleted++;
X
X        if(marked_deleted) {
X	  answer = (always_del ? 'y' : 'n');	/* default answer */
X	  if(ask_questions) {
X	    sprintf(buffer, "Delete message%s? (y/n) ", plural(marked_deleted));
X	    answer = want_to(buffer, answer);
X	  }
X
X	  if(answer == 'y') {
X	    for (i = 0; i < message_count; i++) {
X	      if (ison(headers[i]->status, DELETED)) {
X		headers[i]->exit_disposition = DELETE;
X		to_delete++;
X	      }
X	    }
X	  }
X	}
X	dprint(3, (debugfile, "Messages to delete: %d\n", to_delete));
X
X	/* If this is a non spool file, or if we are merely resyncing,
X	 * all messages with an unset disposition (i.e. not slated for
X	 * deletion) are to be kept.
X	 * Otherwise, we need to determine if read and unread messages
X	 * are to be stored or kept.
X	 */
X	if(folder_type == NON_SPOOL || resyncing) {
X	  to_store = 0;
X	  for (i = 0; i < message_count; i++) {
X	    if(headers[i]->exit_disposition == UNSET) {
X	      headers[i]->exit_disposition = KEEP;
X	      to_keep++;
X	    }
X	  }
X	} else {
X
X	  /* Let's first see if user wants to store read messages 
X	   * that aren't slated for deletion */
X
X	  asked_storage_q = FALSE;
X
X	  /* we need to know if there are none, or one, or more marked read */
X	  for (marked_read=0, i=0; i < message_count && marked_read < 2; i++) {
X	    if((isoff(headers[i]->status, UNREAD))
X	      && (headers[i]->exit_disposition == UNSET))
X		marked_read++;
X	  }
X	  if(marked_read) {
X	    answer = (always_store ? 'y' : 'n');	/* default answer */
X	    if(ask_questions) {
X	      sprintf(buffer, "Move read message%s to \"received\" folder? (y/n) ",
X	        plural(marked_read));
X	      answer = want_to(buffer, answer);
X	      asked_storage_q = TRUE;
X	    }
X
X	    for (i = 0; i < message_count; i++) {
X	      if((isoff(headers[i]->status, UNREAD)) 
X		&& (headers[i]->exit_disposition == UNSET)) {
X
X		  if(answer == 'y') {
X		    headers[i]->exit_disposition = STORE;
X		    to_store++;
X		  } else {
X		    headers[i]->exit_disposition = KEEP;
X		    to_keep++;
X		  }
X	      }
X	    } 
X	  }
X
X	  /* If we asked the user if read messages should be stored,
X	   * and if the user wanted them kept instead, then certainly the
X	   * user would want the unread messages kept as well.
X	   */
X	  if(asked_storage_q && answer == 'n') {
X
X	    for (i = 0; i < message_count; i++) {
X	      if((ison(headers[i]->status, UNREAD))
X		&& (headers[i]->exit_disposition == UNSET)) {
X		  headers[i]->exit_disposition = KEEP;
X		  to_keep++;
X	      }
X	    }
X
X	  } else {
X
X	    /* Determine if unread messages are to be kept */
X
X	    /* we need to know if there are none, or one, or more unread */
X	    for (marked_unread=0, i=0; i<message_count && marked_unread<2; i++)
X	      if((ison(headers[i]->status, UNREAD))
X		&& (headers[i]->exit_disposition == UNSET))
X		  marked_unread++;
X
X	    if(marked_unread) {
X	      answer = (always_keep ? 'y' : 'n');	/* default answer */
X	      if(ask_questions) {
X		sprintf(buffer,
X		  "Keep unread message%s in incoming mailbox? (y/n) ",
X		  plural(marked_unread));
X		answer = want_to(buffer, answer);
X	      }
X
X	      for (i = 0; i < message_count; i++) {
X		if((ison(headers[i]->status, UNREAD))
X		  && (headers[i]->exit_disposition == UNSET)) {
X
X		    if(answer == 'n') {
X		      headers[i]->exit_disposition = STORE;
X		      to_store++;
X		    } else {
X		      headers[i]->exit_disposition = KEEP;
X		      to_keep++;
X		    }
X	      
X		}
X	      }
X	    }
X	  }
X	}
X
X	dprint(3, (debugfile, "Messages to store: %d\n", to_store));
X	dprint(3, (debugfile, "Messages to keep: %d\n", to_keep));
X
X	if(to_delete + to_store + to_keep != message_count) {
X	  dprint(1, (debugfile,
X	  "Error: %d to delete + %d to store + %d to keep != %d message cnt\n",
X	    to_delete, to_store, to_keep, message_count));
X	  error("Something wrong in message counts! Folder unchanged.");
X	  emergency_exit();
X	}
X	  
X
X	/* If we are not resyncing, we are leaving the mailfile and
X	 * the new messages are new no longer. Note that this changes
X	 * their status.
X	 */
X	if(!resyncing) {
X	  for (i = 0; i < message_count; i++) {
X	    if (ison(headers[i]->status, NEW)) {
X	      clearit(headers[i]->status, NEW);
X	      headers[i]->status_chgd = TRUE;
X	    }
X	  }
X	}
X
X	/* If all messages are to be kept and none have changed status
X	 * we don't need to do anything because the current folder won't
X	 * be changed by our writing it out - unless we are resyncing, in
X	 * which case we force the writing out of the mailfile.
X	 */
X
X	for (num_chgd_status = 0, i = 0; i < message_count; i++)
X	  if(headers[i]->status_chgd == TRUE)
X	    num_chgd_status++;
X	
X	if(!to_delete && !to_store && !num_chgd_status && !resyncing) {
X	  dprint(3, (debugfile, "Folder keep as is!\n"));
X	  error("Folder unchanged.");
X	  return(0);
X	}
X
X	/** we have to check to see what the sorting order was...so that
X	    the order in which we write messages is the same as the order
X	    of the messages originally.
X	    We only need to do this if there are any messages to be
X	    written out (either to keep or to store). **/
X
X	if ((to_keep || to_store ) && sortby != MAILBOX_ORDER) {
X	  last_sortby = sortby;
X	  sortby = MAILBOX_ORDER;
X	  sort_mailbox(message_count, FALSE);
X	  sortby = last_sortby;
X	}
X
X	/* Formulate message as to number of keeps, stores, and deletes.
X	 * This is only complex so that the message is good English.
X	 */
X	if (to_keep > 0) {
X	  if (to_store > 0) {
X	    if (to_delete > 0)
X	      sprintf(buffer,
X	            "[Keeping %d message%s, storing %d, and deleting %d.]", 
X		    to_keep, plural(to_keep), to_store, to_delete);
X	    else
X	      sprintf(buffer, "[Keeping %d message%s and storing %d.]", 
X		    to_keep, plural(to_keep), to_store);
X	  } else {
X	    if (to_delete > 0)
X	      sprintf(buffer, "[Keeping %d message%s and deleting %d.]", 
X		    to_keep, plural(to_keep), to_delete);
X	    else
X	      sprintf(buffer, "[Keeping %s.]",
X		    to_keep > 1 ? "all messages" : "message");
X	  }
X	} else if (to_store > 0) {
X	  if (to_delete > 0)
X	    sprintf(buffer, "[Storing %d message%s and deleting %d.]", 
X		  to_store, plural(to_store), to_delete);
X	  else 
X	    sprintf(buffer, "[Storing %s.]",
X		  to_store > 1? "all messages" : "message");
X
X	} else {
X	  if (to_delete > 0)
X	    sprintf(buffer, "[Deleting all messages.]");
X	  else
X	    buffer[0] = '\0';
X	}
X	/* NOTE: don't use variable "buffer" till message is output later */
X
X	/** next, let's lock the file up and make one last size check **/
X
X	if (folder_type == SPOOL)
X	  lock(OUTGOING);
X	
X	if (mailfile_size != bytes(cur_folder)) {
X	  unlock();
X	  error("New mail has just arrived. Resynchronizing...");
X	  return(-1);
X	}
X	
X	/* Everything's GO - so ouput that user message and go to it. */
X
X#ifdef SIGTSTP
X	oldstop = signal(SIGTSTP, SIGIGN);
X#endif
X	
X	dprint(2, (debugfile, "Action: %s\n", buffer));
X	error(buffer);
X
X	/* Store messages slated for storage in received mail folder */
X	if (to_store > 0) {
X	  if ((errno = can_open(recvd_mail, "a"))) {
X	    error1(
X	      "Permission to append to %s denied!  Leaving folder intact.\n",
X	      recvd_mail);
X	    dprint(1, (debugfile,
X	      "Error: Permission to append to folder %s denied!! (%s)\n",
X	      recvd_mail, "leavembox"));
X	    dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
X	      error_description(errno)));
X	    unlock();
X#ifdef SIGTSTP
X	    signal(SIGTSTP, oldstop);
X#endif
X	    return(0);
X	  }
X	  if ((temp = fopen(recvd_mail,"a")) == NULL) {
X	    unlock();
X	    dprint(1, (debugfile, "Error: could not append to file %s\n", 
X	      recvd_mail));
X	    dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
X	      error_description(errno)));
X	    sprintf(buffer, "Could not append to folder %s!", recvd_mail);
X	    Centerline(LINES-1, buffer);
X	    emergency_exit();
X	  }
X	  dprint(2, (debugfile, "Storing message%s ", plural(to_store)));
X	  for (i = 0; i < message_count; i++) {
X	    if(headers[i]->exit_disposition == STORE) {
X	      current = i+1;
X	      dprint(2, (debugfile, "#%d, ", current));
X	      copy_message("", temp, FALSE, FALSE, TRUE, FALSE, FALSE);
X	    }
X	  }
X	  fclose(temp);
X	  dprint(2, (debugfile, "\n\n"));
X	  chown(recvd_mail, userid, groupid);
X	}
X
X	/* If there are any messages to keep, first copy them to a
X	 * temp file, then remove original and copy whole temp file over.
X	 */
X	if (to_keep > 0) {
X	  sprintf(temp_keep_file, "%s%s%d", temp_dir, temp_file, getpid());
X	  if ((errno = can_open(temp_keep_file, "w"))) {
X	    error1(
X"Permission to create temp file %s for writing denied! Leaving folder intact.",
X	      temp_keep_file);
X	    dprint(1, (debugfile,
X	      "Error: Permission to create temp file %s denied!! (%s)\n",
X	      temp_keep_file, "leavembox"));
X	    dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
X	      error_description(errno)));
X	    unlock();
X#ifdef SIGTSTP
X	    signal(SIGTSTP, oldstop);
X#endif
X	    return(0);
X	  }
X	  if ((temp = fopen(temp_keep_file,"w")) == NULL) {
X	    unlock();
X	    dprint(1, (debugfile, "Error: could not create file %s\n", 
X	      temp_keep_file));
X	    dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
X	      error_description(errno)));
X	    sprintf(buffer, "Could not create temp file %s!", temp_keep_file);
X	    Centerline(LINES-1, buffer);
X	    emergency_exit();
X	  }
X	  dprint(2, (debugfile, "Copying to temp file message%s to be kept ",
X	    plural(to_keep)));
X	  for (i = 0; i < message_count; i++) {
X	    if(headers[i]->exit_disposition == KEEP) {
X	      current = i+1;
X	      dprint(2, (debugfile, "#%d, ", current));
X	      copy_message("", temp, FALSE, FALSE, TRUE, FALSE, FALSE);
X	    }
X	  }
X	  if ( fclose(temp) == EOF ) {
X	    Write_to_screen("\n\rClose failed on temp keep file in leavembox\n\r", 0);
X	    perror(temp_keep_file);
X	    dprint(2, (debugfile, "\n\rfclose err on temp_keep_file - leavembox\n\r"));
X	    rm_temps_exit();
X	  }
X	  dprint(2, (debugfile, "\n\n"));
X
X	} else if (folder_type == NON_SPOOL && !keep_empty_files && !resyncing) {
X
X	  /* i.e. if no messages were to be kept and this is not a spool
X	   * folder and we aren't keeping empty non-spool folders,
X	   * simply remove the old original folder and that's it!
X	   */
X	  (void)unlink(cur_folder);
X#ifdef SIGTSTP
X	  signal(SIGTSTP, oldstop);
X#endif
X	  return(1);
X	}
X
X	/* Otherwise we have some work left to do! */
X
X	/* Get original permissions and access time of the original
X	 * mail folder before we remove it.
X	 */
X	if(save_file_stats(cur_folder) != 0) {
X	  error1("Problems saving permissions of folder %s!", cur_folder);
X	  sleep(2);
X	}
X	  
X        if (stat(cur_folder, &buf) != 0) {
X	  dprint(1, (debugfile, "Error: errno %s attempting to stat file %s\n", 
X		     error_name(errno), cur_folder));
X          error3("Error %s (%s) on stat(%s).", error_name(errno), 
X		error_description(errno), cur_folder);
X	}
X
X	/* Close and remove the original folder.
X	 * However, if we are going to copy a temp file of kept messages
X	 * to it, and this is a locked (spool) mailbox, we need to keep
X	 * it locked during this process. Unfortunately,
X	 * if we did our LOCK_BY_FLOCK, unlinking the original will kill the
X	 * lock, so we have to resort to copying the temp file to the original
X	 * file while keeping the original open.
X	 * Also, if the file has a link count > 1, then it has links, so to
X	 * prevent destroying the links, we do a copy back, even though its
X	 * slower.
X	 */
X
X	fclose(mailfile);
X
X	if(to_keep) {
X#ifdef LOCK_BY_FLOCK
X	  need_to_copy = (folder_type == SPOOL ? TRUE : FALSE);
X#else
X	  need_to_copy = FALSE;
X#endif
X	  if (buf.st_nlink > 1)
X	    need_to_copy = TRUE;
X
X	  if(!need_to_copy) {
X	    unlink(cur_folder);
X	    if (link(temp_keep_file, cur_folder) != 0) {
X	      if(errno == EXDEV || errno == EEXIST) {
X		/* oops - can't link across file systems - use copy instead */
X		need_to_copy = TRUE;
X	      } else {
X		dprint(1, (debugfile, "link(%s, %s) failed (leavembox)\n", 
X		       temp_keep_file, cur_folder));
X		dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
X			  error_description(errno)));
X		error2("Link failed! %s - %s.", error_name(errno),
X		  error_description(errno));
X		unlock();
X		emergency_exit();
X	      }
X	    }
X	  }
X
X	  if(need_to_copy) {
X
X	    if (copy(temp_keep_file, cur_folder) != 0) {
X
X	      /* copy to cur_folder failed - try to copy to special file */
X	      dprint(1, (debugfile, "leavembox: copy(%s, %s) failed;",
X		      temp_keep_file, cur_folder));
X	      dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
X		   error_description(errno)));
X	      error("Couldn't modify folder!");
X	      sleep(1);
X	      sprintf(cur_folder,"%s/%s", home, unedited_mail);
X	      if (copy(temp_keep_file, cur_folder) != 0) {
X
X		/* couldn't copy to special file either */
X		dprint(1, (debugfile, 
X			"leavembox: couldn't copy to %s either!!  Help;", 
X			cur_folder));
X		dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
X			error_description(errno)));
X		error("Can't copy mailbox, system trouble!!!");
X		unlock();
X		emergency_exit();
X	      } else {
X		dprint(1, (debugfile,
X			"\nWoah! Confused - Saved mail in %s (leavembox)\n", 
X			cur_folder));
X		error1("Saved mail in %s.", cur_folder);
X		sleep(1);
X	      }
X	    }
X	  }
X
X	  /* link or copy complete - remove temp keep file */
X	  unlink(temp_keep_file);
X
X	} else if(folder_type == SPOOL || keep_empty_files || resyncing) {
X
X	  /* if this is an empty spool file, or if this is an empty non spool 
X	   * file and we keep empty non spool files (we always keep empty
X	   * spool files), create an empty file */
X
X	  if(folder_type == NON_SPOOL)
X	    error1("Keeping empty folder '%s'.", cur_folder);
X	  temp = fopen(cur_folder, "w");
X	  fclose(temp);
X	}
X
X	/* restore permissions and access times of folder */
X
X	if(restore_file_stats(cur_folder) != 1) {
X	  error1("Problems restoring permissions of folder %s!", cur_folder);
X	  sleep(2);
X	}
X
X#ifdef BSD
X	utime_buffer[0]     = buf.st_atime;
X	utime_buffer[1]     = buf.st_mtime;
X#else
X	utime_buffer.actime = buf.st_atime;
X	utime_buffer.modtime= buf.st_mtime;
X#endif
X
X#ifdef BSD
X	if (utime(cur_folder, utime_buffer) != 0) {
X#else
X	if (utime(cur_folder, &utime_buffer) != 0) {
X#endif
X	  dprint(1, (debugfile, 
X		 "Error: encountered error doing utime (leavmbox)\n"));
X	  dprint(1, (debugfile, "** %s - %s **\n", error_name(errno), 
X		   error_description(errno)));
X	  error2("Error %s trying to change file %s access time.", 
X		   error_name(errno), cur_folder);
X	}
X
X
X	mailfile_size = bytes(cur_folder);
X	unlock();	/* remove the lock on the file ASAP! */
X
X#ifdef SIGTSTP
X	signal(SIGTSTP, oldstop);
X#endif
X	return(1);	
X}
X
Xstatic int  lock_state = OFF;
X
Xstatic char lock_name[SLEN];
X
Xchar *
Xmk_lockname(file_to_lock)
Xchar *file_to_lock;
X{
X	/** Create the proper name of the lock file for file_to_lock,
X	    which is presumed to be a spool file full path (see
X	    get_folder_type()), and put it in the static area lock_name.
X	    Return lock_name for informational purposes.
X	 **/
X
X#ifdef XENIX
X	/* lock is /tmp/[basename of file_to_lock].mlk */
X	sprintf(lock_name, "/tmp/%.10s.mlk", rindex(file_to_lock, '/')+1);
X#else
X	/* lock is [file_to_lock].lock */
X	sprintf(lock_name, "%s.lock", file_to_lock);
X#endif
X	return(lock_name);
X}
X
X
Xstatic int flock_fd,	/* file descriptor for flocking mailbox itself */
X	   create_fd;	/* file descriptor for creating lock file */
X
Xlock(direction)
Xint direction;
X{
X      /** Create lock file to ensure that we don't get any mail 
X	  while altering the folder contents!
X	  If it already exists sit and spin until 
X	     either the lock file is removed...indicating new mail
X	  or
X	     we have iterated MAX_ATTEMPTS times, in which case we
X	     either fail or remove it and make our own (determined
X	     by if REMOVE_AT_LAST is defined in header file
X
X	  If direction == INCOMING then DON'T remove the lock file
X	  on the way out!  (It'd mess up whatever created it!).
X
X	  But if that succeeds and if we are also locking by flock(),
X	  follow a similar algorithm. Now if we can't lock by flock(),
X	  we DO need to remove the lock file, since if we got this far,
X	  we DID create it, not another process.
X      **/
X
X      register int create_iteration = 0,
X		   flock_iteration = 0;
X      char pid_buffer[SHORT];
X
X#ifndef	LOCK_FLOCK_ONLY		/* { LOCK_FLOCK_ONLY	*/
X      /* formulate lock file name */
X      mk_lockname(cur_folder);
X
X#ifdef PIDCHECK
X      /** first, try to read the lock file, and if possible, check the pid.
X	  If we can validate that the pid is no longer active, then remove
X	  the lock file.
X       **/
X      if((create_fd=open(lock_name,O_RDONLY)) != -1) {
X	if (read(create_fd, pid_buffer, SHORT) > 0) {
X	  create_iteration = atoi(pid_buffer);
X	  if (create_iteration) {
X	    if (kill(create_iteration, 0)) {
X	      close(create_fd);
X	      if (unlink(lock_name) != 0) {
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, "lock"));
X		PutLine1(LINES, 0, 
X		  "\n\rCouldn't remove the current lock file %s\n\r", lock_name);
X		PutLine2(LINES, 0, "** %s - %s **\n\r", error_name(errno),
X		  error_description(errno));
X		if (direction == INCOMING)
X		  leave();
X		else
X		  emergency_exit();
X	      }
X	    }
X	  }
X	}
X	create_iteration = 0;
X      }
X#endif
X	      
X      /* try to assert create lock file MAX_ATTEMPTS times */
X      do {
X
X	errno = 0;
X	if((create_fd=open(lock_name,O_WRONLY | O_CREAT | O_EXCL,0444)) != -1)
X	  break;
X	else {
X	  if(errno != EEXIST) {
X	    /* Creation of lock failed NOT because it already exists!!! */
X
X	    if (direction == OUTGOING) {
X	      dprint(1, (debugfile, 
X		"Error encountered attempting to create lock %s\n", lock_name));
X	      dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
X		    error_description(errno)));
X	      MoveCursor(LINES, 0);
X	      printf(
X	   "\n\rError encountered while attempting to create lock file %s;\n\r",
X		lock_name);
X	      printf("** %s - %s.**\n\r\n\r",
X		error_name(errno), error_description(errno));
X	    } else {	/* incoming - permission denied in the middle?  Odd. */
X	      dprint(1, (debugfile,
X	       "Can't create lock file: creat(%s) raises error %s (lock)\n", 
X		lock_name, error_name(errno)));
X	      error1(
X	       "Can't create lock file! Need write permission in \"%s\".\n\r",
X		mailhome);
X	    }
X	    leave();
X	  }
X	}
X	dprint(2, (debugfile,"File '%s' already exists!  Waiting...(lock)\n", 
X	  lock_name));
X	error1(
X	  "Waiting to read mailbox while mail is being received: attempt #%d",
X	  create_iteration);
X	sleep(5);
X      } while (create_iteration++ < MAX_ATTEMPTS);
X      clear_error();
X
X      if(errno != 0) {
X	
X	/* we weren't able to create the lock file */
X
X#ifdef REMOVE_AT_LAST
X
X	/** time to waste the lock file!  Must be there in error! **/
X	dprint(2, (debugfile, 
X	   "Warning: I'm giving up waiting - removing lock file(lock)\n"));
X	if (direction == INCOMING)
X	  PutLine0(LINES, 0,"\nTimed out - removing current lock file...");
X	else
X	  error("Throwing away the current lock file!");
X
X	if (unlink(lock_name) != 0) {
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, "lock"));
X	  PutLine1(LINES, 0, 
X	    "\n\rCouldn't remove the current lock file %s\n\r", lock_name);
X	  PutLine2(LINES, 0, "** %s - %s **\n\r", error_name(errno),
X	    error_description(errno));
X	  if (direction == INCOMING)
X	    leave();
X	  else
X	    emergency_exit();
X	}
X
X	/* we've removed the bad lock, let's try to assert lock once more */
X	if((create_fd=open(lock_name,O_WRONLY | O_CREAT | O_EXCL,0444)) == -1){
X
X	  /* still can't lock it - just give up */
X	  dprint(1, (debugfile, 
X	    "Error encountered attempting to create lock %s\n", lock_name));
X	  dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
X	    error_description(errno)));
X	  MoveCursor(LINES, 0);
X	  printf(
X	  "\n\rError encountered while attempting to create lock file %s;\n\r",
X	    lock_name);
X	  printf("** %s - %s.**\n\r\n\r", error_name(errno),
X	    error_description(errno));
X	  leave();
X	}
X#else
X	/* Okay...we die and leave, not updating the mailfile mbox or
X	   any of those! */
X
X	if (direction == INCOMING) {
X	  PutLine1(LINES, 0, "\n\r\n\rGiving up after %d iterations.\n\r", 
X	    create_iteration);
X	  PutLine0(LINES, 0, 
X	  "\n\rPlease try to read your mail again in a few minutes.\n\r\n\r");
X	  dprint(1, (debugfile, 
X	    "Warning: bailing out after %d iterations...(lock)\n",
X	    create_iteration));
X	  leave_locked(0);
X	} else {
X	  dprint(1, (debugfile, 
X	   "Warning: after %d iterations, timed out! (lock)\n",
X	   create_iteration));
X	  leave(error("Timed out on locking mailbox.  Leaving program."));
X	}
X#endif
X      }
X
X      /* If we're here we successfully created the lock file */
X      dprint(5,
X	(debugfile, "Lock %s %s for file %s on.\n", lock_name,
X	(direction == INCOMING ? "incoming" : "outgoing"), cur_folder));
X
X      /* Place the pid of Elm into the lock file for SVR3.2 and its ilk */
X      sprintf(pid_buffer, "%d", getpid());
X      write(create_fd, pid_buffer, strlen(pid_buffer));
X
X      (void)close(create_fd);
X#endif				/* } LOCK_FLOCK_ONLY */
X
X#ifdef LOCK_BY_FLOCK
X      /* Now we also need to lock the file with flock(2) */
X
X      /* Open mail file separately for locking */
X      if((flock_fd = open(cur_folder, O_RDWR)) < 0) {
X	dprint(1, (debugfile, 
X	    "Error encountered attempting to reopen %s for lock\n", cur_folder));
X	dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
X	    error_description(errno)));
X	MoveCursor(LINES, 0);
X	printf(
X "\n\rError encountered while attempting to reopen mailbox %s for lock;\n\r", 
X	      cur_folder);
X	printf("** %s - %s.**\n\r\n\r", error_name(errno),
X	      error_description(errno));
X	(void)unlink(lock_name);
X	leave();
X      }
X
X      /* try to assert lock MAX_ATTEMPTS times */
X      do {
X
X	errno = 0;
X	if(flock(flock_fd, LOCK_NB | LOCK_EX) != -1)
X	  break;
X	else {
X	  if(errno != EWOULDBLOCK && errno != EAGAIN) {
X
X	    /* Creation of lock failed NOT because it already exists!!! */
X
X	    dprint(1, (debugfile, 
X		  "Error encountered attempting to flock %s\n", cur_folder));
X	    dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
X		  error_description(errno)));
X	    MoveCursor(LINES, 0);
X	    printf(
X	 "\n\rError encountered while attempting to flock mailbox %s;\n\r", 
X		  cur_folder);
X	    printf("** %s - %s.**\n\r\n\r", error_name(errno),
X		  error_description(errno));
X	    (void)unlink(lock_name);
X	    leave();
X	  }
X	}
X	dprint(2, (debugfile,
X	  "Mailbox '%s' already locked!  Waiting...(lock)\n", cur_folder));
X	error1(
X	  "Waiting to read mailbox while mail is being received: attempt #%d",
X	  flock_iteration);
X	sleep(5);
X      } while (flock_iteration++ < MAX_ATTEMPTS);
X      clear_error();
X
X      if(errno != 0) {
X
X	/* We couldn't lock the file. We die and leave not updating
X	 * the mailfile mbox or any of those! */
X
X	if (direction == INCOMING) {
X	  PutLine1(LINES, 0, "\n\r\n\rGiving up after %d iterations.\n\r", 
X	    flock_iteration);
X	  PutLine0(LINES, 0, 
X	  "\n\rPlease try to read your mail again in a few minutes.\n\r\n\r");
X	  dprint(1, (debugfile, 
X	    "Warning: bailing out after %d iterations...(lock)\n",
X	    flock_iteration));
X	} else {
X	  dprint(1, (debugfile, 
X	   "Warning: after %d iterations, timed out! (lock)\n",
X	   flock_iteration));
X	}
X#ifndef	LOCK_FLOCK_ONLY
X	(void)unlink(lock_name);
X#endif
X	leave(error("Timed out on locking mailbox. Leaving program."));
X      }
X
X      /* We locked the file */
X      dprint(5,
X	(debugfile, "Lock %s on file %s on.\n",
X	(direction == INCOMING ? "incoming" : "outgoing"), cur_folder));
X#endif
X
X      dprint(5,
X	(debugfile, "Lock %s for file %s on successfully.\n",
SHAR_EOF
echo "End of  part 13"
echo "File src/leavembox.c is continued in part 14"
echo "14" > shar3_seq_.tmp
exit 0
Newsgroups: biz.sco.sources