From: sources@anomaly.sbs.risc.net
Subject: v01i111 - ELM v2.3.11, Electronic Mail Reader - Part 11/20
Reply-To: sources@anomaly.sbs.risc.net
Organization: The Rhode Island Internet Systems Cooperative Network
Date: Sun, 13 Sep 1992 17:42:32 GMT
Followup-To: biz.sco.general


#!/bin/sh
# this is part.11 (part 11 of a multipart archive)
# do not concatenate these parts, unpack them in order with /bin/sh
# file src/domains.c continued
#
if test ! -r shar3_seq_.tmp; then
	echo "Please unpack part 1 first!"
	exit 1
fi
(read Scheck
 if test "$Scheck" != 11; then
	echo "Please unpack part $Scheck next!"
	exit 1
 else
	exit 0
 fi
) < shar3_seq_.tmp || exit 1
echo "x - Continuing file src/domains.c"
sed 's/^X//' << 'SHAR_EOF' >> src/domains.c &&
X}
X        
Xchar *match_and_expand_domain(domain, name, machine)
Xchar *domain, *name, *machine;
X{
X	/** Given the domain, try to find it in the domain file and
X   	    if found expand the entry and return the result as a 
X	    character string...
X	**/
X
X	static char address[SLEN];
X	char   buffer[SLEN], domainbuff[NLEN];
X	char   field1[NLEN], field2[NLEN], field3[NLEN];
X	char   *path, *template, *expanded, *mydomain;
X	int    matched = 0, in_percent = 0;
X	register int j = 0;
X
X	address[j] = '\0';
X
X	domainbuff[0] = '\0';
X	mydomain = (char *) domainbuff;		    /* set up buffer etc */
X
X	do { 
X	  rewind(domainfd);		           /* back to ground zero! */
X
X	  if (strlen(mydomain) > 0) {		   /* already in a domain! */
X	    mydomain++;		 		      /* skip leading '.' */
X	    while (*mydomain != '.' && *mydomain != ',') 
X	      mydomain++;	 		      /* next character   */
X	    if (*mydomain == ',')
X	      return (NULL);  			  /* didn't find domain!  */
X	  }
X	  else
X	    sprintf(mydomain, "%s,", domain);		/* match ENTIRELY! */
X
X	/* whip through file looking for the entry, please... */
X
X	while (fgets(buffer, SLEN, domainfd) != NULL) {
X	  if (buffer[0] == '#')				  /* skip comments */
X	    continue;
X	  if (strincmp(buffer, mydomain, strlen(mydomain)) == 0) { /* match? */
X	     matched++;	/* Gotcha!  Remember this momentous event! */
X	     break;
X	  }
X	}
X
X	if (! matched) 
X	   continue;		/* Nothing.  Not a sausage!  Step through! */
X
X	/** We've matched the domain! **/
X
X	no_ret(buffer);
X
X	(void) strtok(buffer, ",");	/* skip the domain info */
X
X	strcpy(field1, strtok(NULL, ","));	/* fun 		*/
X	strcpy(field2, strtok(NULL, ","));	/*    stuff     */
X	strcpy(field3, strtok(NULL, ","));	/*       eh?    */
X	
X	path = (char *) NULL;
X
X	/* now we merely need to figure out what permutation this is!
X	  
X           Fields are null if they have only a blank in them or are null.
X           If fields 2 and 3 are null, use field 1 as the template.
X            --else--
X           If field 3 is null and 2 is not, use field 2 as the template.
X            --else--
X           Field 3 is the template. */
X         
X
X	if (strcmp(field3," ") == 0 || field3[0] == '\0'){
X	  if (strcmp(field2," ") == 0 || field2[0] == '\0')
X	    template = (char *) field1;
X	  else {
X	    path     = (char *) field1;
X	    template = (char *) field2;
X	  }
X	}
X	else {
X	  path     = (char *) field1;
X	  template = (char *) field3;
X	}
X	dprint(1, (debugfile,
X	  "-> %s\n-> %s\n-> %s\n", field1, field2, field3));
X	dprint(1, (debugfile,
X	  "Path-> %s\nTemplate-> %s\n", path, template));
X
X	if (strlen(path) > 0 && path[0] == '>') 
X	   path++;	/* skip the '>' character, okay? */
X
X	j = 0;		 	/* address is zero, right now, right?? */
X	address[j] = '\0';	      /* make sure string is too! */
X
X	for (; *template; template++) {
X	  if (*template == '%') {
X	    if (! in_percent)			   /* just hit a NEW percent! */
X	      in_percent = 1;
X	    else {		  /* just another percent sign on the wall... */
X	      address[j++] = '%';
X	      address[j] = '\0';		     /* ALWAYS NULL terminate */
X	      in_percent = 0;
X	    }
X	  }
X	  else if (in_percent) {	       /* Hey! a real command string */
X	    in_percent = 0;
X	    switch (*template) {
X	      case USERNAME: strcat(address, name);		break;
X	      case RMTMNAME: strcat(address, machine);		break;
X	      case FULLNAME: strcat(address, machine);
X			     strcat(address, domain);		break;
X	      case NPATH   : 
X
X		 if ((expanded = find_path_to(machine, FALSE)) == NULL) {
X		    dprint(3, (debugfile,
X			    "\nCouldn't expand system path '%s' (%s)\n\n",
X			    machine, "domains"));
X	            error1("Couldn't find a path to %s!", machine);
X	            sleep(2);
X	            return(NULL);	/* failed!! */
X	         }
X	         strcat(address, expanded);	/* isn't this fun??? */
X
X	         break;
X
X	      case PPATH   : 
X
X		 if ((expanded = find_path_to(path, FALSE)) == NULL) {
X		    dprint(3, (debugfile,
X			"\nCouldn't expand system path '%s' (%s)\n\n",
X			path, "domains"));
X	            error1("Couldn't find a path to %s!", path);
X	            sleep(2);
X	            return(NULL);	/* failed!! */
X	         }
X	         strcat(address, expanded);	/* isn't this fun??? */
X
X	         break;
X
X	      case OBSOLETE:	/* fall through.. */
X	      default      : dprint(1, (debugfile,
X	     "\nError: Bad sequence in template file for domain '%s': %%%c\n\n",
X			domain, *template));
X	    }
X	    j = strlen(address);
X	  }
X	  else {
X	    address[j++] = *template;
X	    address[j] = '\0';			/* null terminate */
X	  }
X	}	
X
X	address[j] = '\0';
X
X	} while (strlen(address) < 1);
X
X	return( (char *) address);
X}
X#endif
SHAR_EOF
echo "File src/domains.c is complete" &&
# ============= src/edit.c ==============
echo "x - extracting src/edit.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > src/edit.c &&
X
Xstatic char rcsid[] = "@(#)$Id: edit.c,v 4.1.1.2 90/10/07 21:02:42 syd Exp $";
X
X/*******************************************************************************
X *  The Elm Mail System  -  $Revision: 4.1.1.2 $   $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:	edit.c,v $
X * Revision 4.1.1.2  90/10/07  21:02:42  syd
X * Fix EB29 using alternate editor all the time
X * From: Michael Clay
X * 
X * Revision 4.1.1.1  90/07/12  22:43:05  syd
X * Make it aware of the fact that we loose the cursor position on
X * some system calls, so set it far enough off an absolute move will
X * be done on the next cursor address, and then place it where we want it.
X * From: Syd, reported by Douglas Lamb
X * 
X * Revision 4.1  90/04/28  22:42:46  syd
X * checkin of Elm 2.3 as of Release PL0
X * 
X *
X ******************************************************************************/
X
X/** This routine is for allowing the user to edit their current folder
X    as they wish. 
X
X**/
X
X#include "headers.h"
X#include <errno.h>
X
Xextern int errno;
X
Xchar   *error_name(), *error_description(), *strcpy();
Xlong   bytes();
Xunsigned long sleep();
X
X#ifdef ALLOW_MAILBOX_EDITING
X
Xedit_mailbox()
X{
X	/** Allow the user to edit their folder, always resynchronizing
X	    afterwards.   Due to intense laziness on the part of the
X	    programmer, this routine will invoke $EDITOR on the entire
X	    file.  The mailer will ALWAYS resync on the folder
X	    even if nothing has changed since, not unreasonably, it's
X	    hard to figure out what occurred in the edit session...
X	
X	    Also note that if the user wants to edit their incoming
X	    mailbox they'll actually be editing the tempfile that is
X	    an exact copy.  More on how we resync in that case later
X	    in this code.
X	**/
X
X	FILE     *real_folder, *temp_folder;
X	char     edited_file[SLEN], buffer[SLEN];
X
X	if(folder_type == SPOOL) {
X	  if(save_file_stats(cur_folder) != 0) {
X	    error1("Problems saving permissions of folder %s!", cur_folder);
X	    Raw(ON);
X	    sleep(2);
X	    return(0);
X	  }
X	}
X	  
X	PutLine0(LINES-1,0,"Invoking editor...");
X
X	strcpy(edited_file, (folder_type == NON_SPOOL ? cur_folder : cur_tempfolder));
X	if (strcmp(editor, "builtin") == 0 || strcmp(editor, "none") == 0)
X	  sprintf(buffer, "%s %s", alternative_editor, edited_file);
X	else
X	  sprintf(buffer, "%s %s", editor, edited_file);
X
X	Raw(OFF);
X
X	if (system_call(buffer, SH, TRUE, FALSE) != 0) {
X	  error1("Problems invoking editor %s!", alternative_editor);
X	  Raw(ON);
X	  sleep(2);
X	  return(0);
X	}
X
X	Raw(ON);
X	SetXYLocation(0, 40);	/* a location not near the next request, so an absolute is used */
X
X	if (folder_type == SPOOL) {	/* uh oh... now the toughie...  */
X
X	  if (bytes(cur_folder) != mailfile_size) {
X
X	     /* SIGH.  We've received mail since we invoked the editor
X		on the folder.  We'll have to do some strange stuff to
X	        remedy the problem... */
X
X	     PutLine0(LINES, 0, "Warning: new mail received...");
X	     CleartoEOLN();
X
X	     if ((temp_folder = fopen(edited_file, "a")) == NULL) {
X	       dprint(1, (debugfile, 
X		    "Attempt to open \"%s\" to append failed in %s\n", 
X		    edited_file, "edit_mailbox"));
X	       set_error("Couldn't reopen tempfile. Edit LOST!");
X	       return(1);
X	     }
X	     /** Now let's lock the folder up and stream the new stuff 
X		 into the temp file... **/
X
X	     lock(OUTGOING);	
X	     if ((real_folder = fopen(cur_folder, "r")) == NULL) {
X	       dprint(1, (debugfile, 
X	           "Attempt to open \"%s\" for reading new mail failed in %s\n",
X 		   cur_folder, "edit_mailbox"));
X	       sprintf(buffer, "Couldn't open %s for reading!  Edit LOST!", 
X		       cur_folder);
X	       set_error(buffer);
X	       unlock();
X	       return(1);
X	     }
X	     if (fseek(real_folder, mailfile_size, 0) == -1) {
X	       dprint(1, (debugfile,
X			"Couldn't seek to end of cur_folder (offset %ld) (%s)\n",
X			mailfile_size, "edit_mailbox"));
X	       set_error("Couldn't seek to end of folder.  Edit LOST!");
X	       unlock();
X	       return(1);
X	     }
X	
X	     /** Now we can finally stream the new mail into the tempfile **/
X
X	     while (fgets(buffer, SLEN, real_folder) != NULL)
X	       fprintf(temp_folder, "%s", buffer);
X
X	     fclose(real_folder);
X	     fclose(temp_folder);
X
X 	   } else lock(OUTGOING);
X
X	   /* remove real mail_file and then
X	    * link or copy the edited mailfile to real mail_file */
X
X	   (void)unlink(cur_folder);
X
X	   if (link(edited_file, cur_folder) != 0)  {
X	     if (errno == EXDEV || errno == EEXIST) {
X	       /* attempt to link across file systems */
X   	       if (copy(edited_file, cur_folder) != 0) {
X		 Write_to_screen(
X		    "\n\rCouldn't copy %s to mailfile %s!\n\r",
X		    2, edited_file, cur_folder);
X		 Write_to_screen(
X		    "\n\rYou'll need to check out %s for your mail.\n\r",
X		    1, edited_file);
X		 Write_to_screen("** %s - %s. **\n\r", 2,
X		    error_name(errno), error_description(errno));
X		 unlock();					/* ciao!*/
X		 emergency_exit();
X	       }
X	     } else {
X		Write_to_screen("\n\rCouldn't link %s to mailfile %s!\n\r",2,
X		  edited_file, cur_folder);
X	        Write_to_screen(
X		  "\n\rYou'll need to check out %s for your mail.\n\r",
X		  1, edited_file);
X		Write_to_screen("** %s - %s. **\n\r", 2,
X		  error_name(errno), error_description(errno));
X	        unlock();					/* ciao!*/
X	        emergency_exit();
X	     }
X	   }
X
X	   /* restore file permissions before removing lock */
X
X	   if(restore_file_stats(cur_folder) != 1) {
X	     error1("Problems restoring permissions of folder %s!", cur_folder);
X	     Raw(ON);
X	     sleep(2);
X	   }
X	      
X	   unlock();
X	   unlink(edited_file);	/* remove the edited mailfile */
X	   error("Changes incorporated into new mail...");
X
X	} else 
X	  error("Resynchronizing with new version of folder...");
X
X	sleep(2);
X	ClearScreen();
X	newmbox(cur_folder, FALSE);
X	showscreen();
X	return(1);
X}
X
X#endif
SHAR_EOF
# ============= src/editmsg.c ==============
echo "x - extracting src/editmsg.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > src/editmsg.c &&
X
Xstatic char rcsid[] = "@(#)$Id: editmsg.c,v 4.1.1.4 91/01/07 20:36:26 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:	editmsg.c,v $
X * Revision 4.1.1.4  91/01/07  20:36:26  syd
X * Fix warning message on compiling editmsg on voidsig machines
X * From: Chip Salzenberg
X * 
X * Revision 4.1.1.3  90/07/12  22:43:08  syd
X * Make it aware of the fact that we loose the cursor position on
X * some system calls, so set it far enough off an absolute move will
X * be done on the next cursor address, and then place it where we want it.
X * From: Syd, reported by Douglas Lamb
X * 
X * Revision 4.1.1.2  90/06/21  21:14:09  syd
X * Force Carriage return on return from editor, as column is lost
X * From: Steve Cambell
X * 
X * Revision 4.1.1.1  90/06/09  23:33:06  syd
X * Only say cannot invoke on -1 error which is cannot do exec in system call
X * From: Syd
X * 
X * Revision 4.1  90/04/28  22:42:47  syd
X * checkin of Elm 2.3 as of Release PL0
X * 
X *
X ******************************************************************************/
X
X/** This contains routines to do with starting up and using an editor (or two)
X    from within Elm.  This stuff used to be in mailmsg2.c...
X**/
X
X#include "headers.h"
X#include <errno.h>
X#ifndef BSD
X/* BSD has already included setjmp.h in headers.h */
X#include <setjmp.h>
X#endif /* BSD */
X#include <signal.h>
X#include <ctype.h>
X
X#ifdef BSD
X#undef        tolower
X#endif
X
Xextern int errno;
X
Xchar *error_name(), *error_description(), *strcpy(), *format_long();
Xunsigned long sleep();
X
Xint
Xedit_the_message(filename, already_has_text)
Xchar *filename;
Xint  already_has_text;
X{
X	/** Invoke the users editor on the filename.  Return when done. 
X	    If 'already has text' then we can't use the no-editor option
X	    and must use 'alternative editor' (e.g. $EDITOR or default_editor)
X	    instead... **/
X
X	char buffer[SLEN];
X	register int stat, return_value = 0, old_raw;
X
X	buffer[0] = '\0';
X
X	if (strcmp(editor, "builtin") == 0 || strcmp(editor, "none") == 0) {
X	  if (already_has_text) 
X	    sprintf(buffer, "%s %s", alternative_editor, filename);
X	  else
X	    return(no_editor_edit_the_message(filename));
X	}
X
X	PutLine0(LINES, 0, "Invoking editor...");  fflush(stdout);
X	if (strlen(buffer) == 0)
X	  sprintf(buffer,"%s %s", editor, filename);
X
X	chown(filename, userid, groupid);	/* file was owned by root! */
X
X	if (( old_raw = RawState()) == ON)
X	  Raw(OFF);
X
X	if (cursor_control)
X	  transmit_functions(OFF);		/* function keys are local */
X
X	if ((stat = system_call(buffer, SH, TRUE, FALSE)) == -1) { 
X	  dprint(1,(debugfile, 
X		  "System call failed with stat %d (edit_the_message)\n", 
X		  stat));
X	  dprint(1, (debugfile, "** %s - %s **\n", error_name(errno), 
X		error_description(errno)));
X	  ClearLine(LINES-1);
X	  error1("Can't invoke editor '%s' for composition.", editor);
X	  sleep(2);
X	  return_value = 1;
X	}
X
X	if (old_raw == ON)
X	   Raw(ON);
X
X	SetXYLocation(0, 40);	/* a location not near the next request, so an absolute is used */
X	MoveCursor(LINES, 0);	/* dont know where we are, force last row, col 0 */
X
X	if (cursor_control)
X	  transmit_functions(ON);		/* function keys are local */
X	
X	return(return_value);
X}
X
Xstatic char simple_continue[] = "(Continue.)\n\r";
Xstatic char post_ed_continue[] = 
X"(Continue entering message.  Type ^D or '.' on a line by itself to end.)\n\r";
X
Xextern char to[VERY_LONG_STRING], cc[VERY_LONG_STRING], 
X	    expanded_to[VERY_LONG_STRING], expanded_cc[VERY_LONG_STRING], 
X	    bcc[VERY_LONG_STRING], expanded_bcc[VERY_LONG_STRING],
X            subject[SLEN];
X
Xint      interrupts_while_editing;	/* keep track 'o dis stuff         */
Xjmp_buf  edit_location;		        /* for getting back from interrupt */
X
Xchar *strip_commas();
Xlong  fsize();
X
Xint
Xno_editor_edit_the_message(filename)
Xchar *filename;
X{
X	/** If the current editor is set to either "builtin" or "none", then
X	    invoke this program instead.  As it turns out, this and the 
X	    routine above have a pretty incestuous relationship (!)...
X	**/
X
X	FILE *edit_fd;
X	char buffer[SLEN], editor_name[SLEN], buf[SLEN];
X	int      old_raw;
X#ifdef VOIDSIG
X	void	edit_interrupt();
X	void	(*oldint)(), (*oldquit)();
X#else
X	int	edit_interrupt();
X	int	(*oldint)(), (*oldquit)();
X#endif
X
X	if ((edit_fd = fopen(filename, "a")) == NULL) {
X	  error2("Couldn't open %s for appending [%s].", filename, 
X		  error_name(errno));
X	  sleep (2);
X	  dprint(1, (debugfile,
X		"Error encountered trying to open file %s;\n", filename));
X	  dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
X		    error_description(errno)));
X	  return(1);
X	}
X
X	/** is there already text in this file? **/
X
X	if (fsize(edit_fd) > 0L)
X	  strcpy(buf, "\n\rContinue entering message.");
X	else
X	  strcpy(buf, "\n\rEnter message.");
X	strcat(buf, "  Type Elm commands on lines by themselves.\n\r");
X	sprintf(buf + strlen(buf),
X    "Commands include:  ^D or '.' to end, %cp to list, %c? for help.\n\r\n\r",
X		escape_char, escape_char);
X	CleartoEOS();
X	Write_to_screen(buf, 0);
X
X	oldint  = signal(SIGINT,  edit_interrupt);
X	oldquit = signal(SIGQUIT, edit_interrupt);
X
X	interrupts_while_editing = 0;
X
X	if (setjmp(edit_location) != 0) {
X	  if (interrupts_while_editing > 1) {
X
X	    (void) signal(SIGINT,  oldint);
X	    (void) signal(SIGQUIT, oldquit);
X
X	    if (edit_fd != NULL)	/* insurance... */
X	      fclose(edit_fd);
X	    return(1);
X	  }
X	  goto more_input;	/* read input again, please! */
X	}
X	
Xmore_input: buffer[0] = '\0';
X
X	while (optionally_enter(buffer, -1,-1, FALSE, FALSE) == 0) {
X
X	  interrupts_while_editing = 0;	/* reset to zero... */
X
X	  if (strcmp(buffer, ".") == 0)
X	    break;	/* '.' is as good as a ^D to us dumb programs :-) */
X	  if (buffer[0] == escape_char) {
X	    switch (tolower(buffer[1])) {
X              case '?' : tilde_help();
X			 goto more_input;
X
X	      case TILDE_ESCAPE: move_left(buffer, 1); 
X			  	 goto tilde_input;	/*!!*/
X
X	      case 't' : get_with_expansion("\n\rTo: ",
X	      		   to, expanded_to, buffer);
X			 goto more_input;
X	      case 'b' : get_with_expansion("\n\rBcc: ",
X			   bcc, expanded_bcc, buffer);
X			 goto more_input;
X	      case 'c' : get_with_expansion("\n\rCc: ",
X			   cc, expanded_cc, buffer);
X			 goto more_input;
X	      case 's' : get_with_expansion("\n\rSubject: ",
X			   subject,NULL,buffer);
X   			 goto more_input;
X
X	      case 'h' : get_with_expansion("\n\rTo: ", to, expanded_to, NULL);	
X	                 get_with_expansion("Cc: ", cc, expanded_cc, NULL);
X	                 get_with_expansion("Bcc: ", bcc,expanded_bcc, NULL);
X	                 get_with_expansion("Subject: ", subject, NULL, NULL);
X			 goto more_input;
X
X	      case 'r' : read_in_file(edit_fd, (char *) buffer + 2, 1);
X		  	 goto more_input;
X	      case 'e' : if (strlen(emacs_editor) > 0) 
X	                   if (access(emacs_editor, ACCESS_EXISTS) == 0) {
X	                     strcpy(buffer, editor);
X			     strcpy(editor, emacs_editor);
X	  		     fclose(edit_fd);
X			     (void) edit_the_message(filename,0);
X			     strcpy(editor, buffer);
X			     edit_fd = fopen(filename, "a");
X                             Write_to_screen(post_ed_continue, 0);
X	                     goto more_input;
X		           }
X		           else
X	                     Write_to_screen(
X			"\n\r(Can't find Emacs on this system! Continue.)\n\r",
X			0);
X			 else
X			   Write_to_screen(
X			"\n\r(Don't know where Emacs would be. Continue.)\n\r",
X			0);	
X			 goto more_input;
X
X	       case 'v' : NewLine();
X			  strcpy(buffer, editor);
X			  strcpy(editor, default_editor);
X			  fclose(edit_fd);
X			  (void) edit_the_message(filename,0);
X			  strcpy(editor, buffer);
X			  edit_fd = fopen(filename, "a");
X                          Write_to_screen(post_ed_continue, 0);
X	                  goto more_input;
X
X	       case 'o' : Write_to_screen(
X			     "\n\rPlease enter the name of the editor: ", 0);
X			  editor_name[0] = '\0';
X			  optionally_enter(editor_name,-1,-1, FALSE, FALSE);
X			  NewLine();
X	                  if (strlen(editor_name) > 0) {
X	                    strcpy(buffer, editor);
X			    strcpy(editor, editor_name);
X			    fclose(edit_fd);
X			    (void) edit_the_message(filename,0);
X			    strcpy(editor, buffer);
X			    edit_fd = fopen(filename, "a");
X                            Write_to_screen(post_ed_continue, 0);
X	                    goto more_input;
X		          }
X	  		  Write_to_screen(simple_continue, 0);
X	                  goto more_input; 
X
X		case '<' : NewLine();
X			   if (strlen(buffer) < 3)
X			     Write_to_screen(
X		 "(You need to use a specific command here. Continue.)\n\r");
X			   else {
X			     sprintf(buf, " > %s%s.%d 2>&1", temp_dir, temp_edit, getpid());
X			     strcat(buffer, buf);
X			     if (( old_raw = RawState()) == ON)
X			       Raw(OFF);
X			     (void) system_call((char *) buffer+2, SH, TRUE, TRUE);
X			     if (old_raw == ON)
X			        Raw(ON);
X			     sprintf(buffer, "~r %s%s.%d", temp_dir, temp_edit, getpid());
X	      	             read_in_file(edit_fd, (char *) buffer + 3, 0);
X			     (void) unlink((char *) buffer+3);
X			     SetXYLocation(0, 40);	/* a location not near the next request, so an absolute is used */
X			     MoveCursor(LINES, 0);	/* and go to a known location, last row col 0 */
X			   }
X	                   goto more_input; 
X
X		case '!' : NewLine();
X			   if (( old_raw = RawState()) == ON)
X			     Raw(OFF);
X			   if (strlen(buffer) < 3) 
X			     (void) system_call(shell, USER_SHELL, TRUE, TRUE);
X			   else
X	                     (void) system_call((char *) buffer+2, USER_SHELL, TRUE, TRUE);
X			   if (old_raw == ON)
X			      Raw(ON);
X			   SetXYLocation(0, 40);	/* a location not near the next request, so an absolute is used */
X			   MoveCursor(LINES, 0);	/* and go to a known location, last row col 0 */
X	    		   Write_to_screen(simple_continue, 0);
X			   goto more_input;
X
X		 case 'm' : /* same as 'f' but with leading prefix added */
X
X	         case 'f' : /* this can be directly translated into a
X			       'readmsg' call with the same params! */
X			    NewLine();
X			    read_in_messages(edit_fd, (char *) buffer + 1);
X			    goto more_input;
X
X	         case 'p' : /* print out message so far.  Soooo simple! */
X			    print_message_so_far(edit_fd, filename);
X			    goto more_input;
X
X		 default  : sprintf(buf,
X			 "\n\r(Don't know what %c%c is. Try %c? for help.)\n\r",
X				    escape_char, buffer[1], escape_char);
X			    Write_to_screen(buf, 0);
X	       }
X	     }
X	     else {
Xtilde_input:
X	       fprintf(edit_fd, "%s\n", buffer);
X	       NewLine();
X	     }
X	  buffer[0] = '\0';
X	}
X
X
X	Write_to_screen("\n\r<end-of-message>\n\r\n\r\n\r\n\r", 0);
X
X	(void) signal(SIGINT,  oldint);
X	(void) signal(SIGQUIT, oldquit);
X
X	if (edit_fd != NULL)	/* insurance... */
X	  fclose(edit_fd);
X
X	return(0);
X}
X
Xtilde_help()
X{
X	/* a simple routine to print out what is available at this level */
X
X	char	buf[SLEN];
X
X	Write_to_screen("\n\r(Available options at this point are:\n\r\n\r", 0);
X	sprintf(buf, "\t%c?\tPrint this help menu.\n\r", escape_char);
X	Write_to_screen(buf, 0);
X	if (escape_char == TILDE_ESCAPE) /* doesn't make sense otherwise... */
X	  Write_to_screen(
X	      "\t~~\tAdd line prefixed by a single '~' character.\n\r", 0);
X
X	sprintf(buf,
X	  "\t%cb\tChange the addresses in the Blind-carbon-copy list.\n\r",
X	  escape_char);
X	Write_to_screen(buf, 0);
X
X	sprintf(buf,
X		"\t%cc\tChange the addresses in the Carbon-copy list.\n\r",
X		escape_char);
X	Write_to_screen(buf, 0);
X	sprintf(buf,
X	      "\t%ce\tInvoke the Emacs editor on the message, if possible.\n\r",
X		escape_char);
X	Write_to_screen(buf, 0);
X	sprintf(buf,
X		"\t%cf\tAdd the specified message or current.\n\r",
X		escape_char);
X	Write_to_screen(buf, 0);
X	sprintf(buf,
X	      "\t%ch\tChange all available headers (to, cc, bcc, subject).\n\r",
X		escape_char);
X	Write_to_screen(buf, 0);
X	sprintf(buf,
X		"\t%cm\tSame as '%cf', but with the current 'prefix'.\n\r",
X		escape_char, escape_char);
X	Write_to_screen(buf, 0);
X	sprintf(buf,
X		"\t%co\tInvoke a user specified editor on the message.\n\r",
X		escape_char);
X	Write_to_screen(buf, 0);
X	sprintf(buf,
X	      "\t%cp\tPrint out message as typed in so far.\n\r", escape_char);
X	Write_to_screen(buf, 0);
X	sprintf(buf,
X		"\t%cr\tRead in the specified file.\n\r", escape_char);
X	Write_to_screen(buf, 0);
X	sprintf(buf,
X		"\t%cs\tChange the subject of the message.\n\r", escape_char);
X	Write_to_screen(buf, 0);
X	sprintf(buf,
X		"\t%ct\tChange the addresses in the To list.\n\r",
X		escape_char);
X	Write_to_screen(buf, 0);
X	sprintf(buf,
X		"\t%cv\tInvoke the Vi visual editor on the message.\n\r",
X		escape_char);
X	Write_to_screen(buf, 0);
X	sprintf(buf,
X          "\t%c!\tExecute a unix command (or give a shell if no command).\n\r",
X	  escape_char);
X	Write_to_screen(buf, 0);
X	sprintf(buf,
X      "\t%c<\tExecute a unix command adding the output to the message.\n\r",
X	  escape_char);
X	Write_to_screen(buf, 0);
X	sprintf(buf,
X      "\t.  \tby itself on a line (or a control-D) ends the message.\n\r");
X	Write_to_screen(buf, 0);
X	Write_to_screen("Continue.)\n\r", 0);
X}
X
Xread_in_file(fd, filename, show_user_filename)
XFILE *fd;
Xchar *filename;
Xint   show_user_filename;
X{
X	/** Open the specified file and stream it in to the already opened 
X	    file descriptor given to us.  When we're done output the number
X	    of lines and characters we added, if any... **/
X
X	FILE *myfd;
X	char myfname[SLEN], buffer[SLEN];
X	register int n;
X	register int lines = 0, nchars = 0;
X
X	for ( n = 0 ; whitespace(filename[n]) ; n++ );
X
X	/** expand any shell variables, '~' or other notation... **/
X	/* temp copy of filename to buffer since expand_env is destructive */
X	strcpy(buffer, &filename[n]);
X	expand_env(myfname, buffer);
X
X	if (strlen(myfname) == 0) {
X	  Write_to_screen(
X	      "\n\r(No filename specified for file read! Continue.)\n\r", 0);
X	  return;
X	}
X
X	if ((myfd = fopen(myfname,"r")) == NULL) {
X	  Write_to_screen("\n\r(Couldn't read file '%s'! Continue.)\n\r", 1,
X		 myfname);
X	  return;
X	}
X
X	while (fgets(buffer, SLEN, myfd) != NULL) {
X	  n = strlen(buffer);
X	  if(buffer[n-1] == '\n') lines++;
X	  nchars += n;
X  	  fputs(buffer, fd);
X	  fflush(stdout);
X	}
X
X	fclose(myfd);
X
X	if (show_user_filename)
X	  sprintf(buffer,
X		"\n\r(Added %d line%s [%d char%s] from file %s. Continue.)\n\r",
X		lines, plural(lines), nchars, plural(nchars), myfname);
X	else
X	  sprintf(buffer,
X		"\n\r(Added %d line%s [%d char%s] to message. Continue.)\n\r",
X		lines, plural(lines), nchars, plural(nchars));
X	Write_to_screen(buffer, 0);
X
X	return;
X}
X
Xprint_message_so_far(edit_fd, filename)
XFILE *edit_fd;
Xchar *filename;
X{
X	/** This prints out the message typed in so far.  We accomplish
X	    this in a cheap manner - close the file, reopen it for reading,
X	    stream it to the screen, then close the file, and reopen it
X	    for appending.  Simple, but effective!
X
X	    A nice enhancement would be for this to -> page <- the message
X	    if it's sufficiently long.  Too much work for now, though.
X	**/
X	
X	char buffer[SLEN];
X
X	fclose(edit_fd);
X
X	if ((edit_fd = fopen(filename, "r")) == NULL) {
X	  Write_to_screen("\n\rMayday!  Mayday!  Mayday!\n\r", 0);
X	  Write_to_screen("\n\rPanic: Can't open file for reading!  Bail!\n\r",
X	      0);
X	  emergency_exit();
X	}
X
X	Write_to_screen("\n\rTo: %s\n\r", 1, format_long(to, 4));
X	Write_to_screen("Cc: %s\n\r", 1, format_long(cc, 4));
X	Write_to_screen("Bcc: %s\n\r", 1, format_long(bcc, 5));
X	Write_to_screen("Subject: %s\n\r\n\r", 1, subject);
X
X	while (fgets(buffer, SLEN, edit_fd) != NULL) {
X	  Write_to_screen(buffer, 0);
X	  CarriageReturn();
X        }
X
X	fclose(edit_fd);
X
X	if ((edit_fd = fopen(filename, "a")) == NULL) {
X	  Write_to_screen("Mayday!  Mayday!  Abandon Ship!  Aiiieeeeee\n\r", 0);
X	  Write_to_screen("\n\rPanic: Can't reopen file for appending!\n\r", 0);
X	  emergency_exit();
X	}
X
X	Write_to_screen("\n\r(Continue entering message.)\n\r", 0);
X}
X
Xread_in_messages(fd, buffer)
XFILE *fd;
Xchar *buffer;
X{
X	/** Read the specified messages into the open file.  If the
X	    first character of "buffer" is 'm' then prefix it, other-
X	    wise just stream it in straight...Since we're using the
X	    pipe to 'readmsg' we can also allow the user to specify
X	    patterns and such too...
X	**/
X
X	FILE *myfd, *popen();
X	char  local_buffer[SLEN], *arg;
X	register int add_prefix=0, mindex;
X	register int n;
X	int lines = 0, nchars = 0;
X
X	add_prefix = tolower(buffer[0]) == 'm';
X
X	/* strip whitespace to get argument */
X	for(arg = &buffer[1]; whitespace(*arg); arg++)
X		;
X
X	/* if no argument or begins with a digit, then retrieve the
X	 * appropriate message from the current folder, else
X	 * just take the arguments as a pattern for readmsg to match in 
X	 * the current folder.
X	 */
X	if(isdigit(*arg) || *arg == '\0') {
X	  if(message_count < 1) {
X	    Write_to_screen("(No messages to read in! Continue.)\n\r", 0);
X	    return;
X	  }
X	  if((mindex = atoi(arg)) == 0)	/* no argument - read in current msg */
X	    mindex = current;
X	  else if(mindex < 1 || mindex > message_count) {
X	    sprintf(local_buffer,
X	      "(Valid messsage numbers are between 1 and %d. Continue.)\n\r",
X	      message_count);
X	    Write_to_screen(local_buffer, 0);
X	    return;
X	  }
X
X	  sprintf(local_buffer, "%s -f %s %d", readmsg, cur_folder,
X		  headers[mindex-1]->index_number);
X
X	} else
X	  sprintf(local_buffer, "%s -f %s %s", readmsg, cur_folder, arg);
X
X
X	/* now get output of readmsg */
X	if ((myfd = popen(local_buffer, "r")) == NULL) {
X	   Write_to_screen("(Can't find 'readmsg' command! Continue.)\n\r",
X	       0);
X	   return;	
X	}
X
X	dprint(5, (debugfile, "** readmsg call: \"%s\" **\n", local_buffer));
X
X	while (fgets(local_buffer, SLEN, myfd) != NULL) {
X	  n = strlen(local_buffer);
X	  nchars += n;
X	  if (local_buffer[n-1] == '\n') lines++;
X	  if (add_prefix)
X	    fprintf(fd, "%s%s", prefixchars, local_buffer);
X	  else 
X	    fputs(local_buffer, fd);
X	}
X
X	pclose(myfd);
X	
X	if (lines == 0)
X	  sprintf(local_buffer,
X	 	 "(Couldn't add the requested message. Continue.)\n\r");
X	else
X	  sprintf(local_buffer,
X		"(Added %d line%s [%d char%s] to message. Continue.)\n\r",
X		lines, plural(lines), nchars, plural(nchars));
X	Write_to_screen(local_buffer, 0);
X
X	return;
X}
X
Xget_with_expansion(prompt, buffer, expanded_buffer, sourcebuf)
Xchar *prompt, *buffer, *expanded_buffer, *sourcebuf;
X{
X	/** This is used to prompt for a new value of the specified field.
X	    If expanded_buffer == NULL then we won't bother trying to expand
X	    this puppy out!  (sourcebuf could be an initial addition)
X	**/
X
X	Write_to_screen(prompt, 0);	fflush(stdout);	/* output! */
X
X	if (sourcebuf != NULL) {
X	  while (!whitespace(*sourcebuf) && *sourcebuf != '\0') 
X	    sourcebuf++;
X	  if (*sourcebuf != '\0') {
X	    while (whitespace(*sourcebuf)) 
X	      sourcebuf++;
X	    if (strlen(sourcebuf) > 0) {
X	      strcat(buffer, " ");
X	      strcat(buffer, sourcebuf);
X	    }
X	  }
X	}
X
X	optionally_enter(buffer, -1, -1, TRUE, FALSE);	/* already data! */
X
X	if(expanded_buffer != NULL) {
X	  build_address(strip_commas(buffer), expanded_buffer);
X	  if(*expanded_buffer != '\0') {
X	    if (*prompt == '\n')
X	      Write_to_screen("%s%s", 2, prompt, expanded_buffer);
X	    else
X	      Write_to_screen("\n\r%s%s", 2, prompt, expanded_buffer);
X	  }
X	}
X	NewLine();
X
X	return;
X}
X
X#ifdef VOIDSIG
Xvoid
X#else
Xint
X#endif
Xedit_interrupt()
X{
X	/** This routine is called when the user hits an interrupt key
X	    while in the builtin editor...it increments the number of 
X	    times an interrupt is hit and returns it.
X	**/
X
X	signal(SIGINT, edit_interrupt);
X	signal(SIGQUIT, edit_interrupt);
X
X	if (interrupts_while_editing++ == 0)
X	  Write_to_screen("(Interrupt. One more to cancel this letter.)\n\r",
X	  	0);
X	else
X	  Write_to_screen("(Interrupt. Letter cancelled.)\n\r", 0);
X
X	longjmp(edit_location, 1);		/* get back */
X}
SHAR_EOF
# ============= src/elm.c ==============
echo "x - extracting src/elm.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > src/elm.c &&
X
Xstatic char rcsid[] = "@(#)$Id: elm.c,v 4.1.1.1 90/12/19 09:44:06 syd Exp $";
X
X/*******************************************************************************
X *  The Elm Mail System  -  $Revision: 4.1.1.1 $   $State: Exp $
X *
X * This file and all associated files and documentation:
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:	elm.c,v $
X * Revision 4.1.1.1  90/12/19  09:44:06  syd
X * Fix not checking for mail before scanning
X * From: Syd via report from Joern Lubkoll
X * 
X * Revision 4.1  90/04/28  22:42:54  syd
X * checkin of Elm 2.3 as of Release PL0
X * 
X *
X ******************************************************************************/
X
X/* Main program of the ELM mail system! 
X*/
X
X#include "elm.h"
X
X#ifdef BSD
X#undef        toupper
X#undef        tolower
X#endif
X
Xlong bytes();
Xchar *format_long(), *parse_arguments();
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X	{
X	int  ch;
X	char address[SLEN], to_whom[SLEN], *req_mfile;
X	int  key_offset;        /** Position offset within keyboard string   **/
X	int  redraw, 		/** do we need to rewrite the entire screen? **/
X	     nucurr, 		/** change message list or just the current message pointer...   **/
X	     nufoot; 		/** clear lines 16 thru bottom and new menu  **/
X	int  i,j;      		/** Random counting variables (etc)          **/
X	int  pageon, 		/** for when we receive new mail...          **/
X	     last_in_folder;	/** for when we receive new mail too...      **/
X	long num;		/** another variable for fun..               **/
X	extern char version_buff[];
X	extern int errno;
X
X	req_mfile = parse_arguments(argc, argv, to_whom);
X
X	initialize(req_mfile);
X
X	if (mail_only) {
X	   dprint(3, (debugfile, "Mail-only: mailing to\n-> \"%s\"\n", 
X		   format_long(to_whom, 3)));
X	   if(!batch_only) {
X	     sprintf(address, "Send only mode [ELM %s]", version_buff);
X	     Centerline(1, address);
X	   }
X	   (void) sendmsg(to_whom, "", batch_subject, TRUE,
X	     (batch_only ? NO : allow_forms), FALSE); 
X	   leave(0);
X	} else if (check_only) {
X	   do_check_only(to_whom);
X	   leave(0);
X	}
X
X	ScreenSize(&LINES, &COLUMNS);
X
X	showscreen();
X
X	while (1) {
X	  redraw = 0;
X	  nufoot = 0;
X	  nucurr = 0;
X	  if ((num = bytes(cur_folder)) != mailfile_size) {
X	    dprint(2, (debugfile, "Just received %d bytes more mail (elm)\n", 
X		    num - mailfile_size));
X	    error("New mail has arrived! Hang on...");
X	    fflush(stdin);	/* just to be sure... */
X	    last_in_folder = message_count;
X	    pageon = header_page;
X
X	    if ((errno = can_access(cur_folder, READ_ACCESS)) != 0) {
X	      dprint(1, (debugfile,
X		    "Error: given file %s as folder - unreadable (%s)!\n", 
X		    cur_folder, error_name(errno)));
X	      fprintf(stderr,"Can't open folder '%s' for reading!\n", cur_folder);
X	      leave();
X	      }
X
X	    newmbox(cur_folder, TRUE);	/* last won't be touched! */
X	    clear_error();
X	    header_page = pageon;
X
X	    if (on_page(current))   /* do we REALLY have to rewrite? */
X	      showscreen();
X	    else {
X	      update_title();
X	      ClearLine(LINES-1);	     /* remove reading message... */
X	      error2("%d new message%s received.", 
X		     message_count - last_in_folder,
X		     plural(message_count - last_in_folder));
X	    }
X	    /* mailfile_size = num; */
X	    if (cursor_control)
X	      transmit_functions(ON);	/* insurance */
X	  }
X
X	  prompt("Command: ");
X
X	  CleartoEOLN();
X	  ch = GetPrompt();
X	  CleartoEOS();
X#ifdef DEBUG
X	  if (! movement_command(ch))
X	    dprint(4, (debugfile, "\nCommand: %c [%d]\n\n", ch, ch));
X#endif
X
X	  set_error("");	/* clear error buffer */
X
X	  MoveCursor(LINES-3,strlen("Command: "));
X
X	  switch (ch) {
X
X	    case '?' 	:  if (help(FALSE))
X	  		     redraw++;
X			   else
X			     nufoot++;
X			   break;
X
X	    case '$'    :  PutLine0(LINES-3, strlen("Command: "),
X	    		     "Resynchronize folder");
X			   redraw = resync();
X			   break;
X
Xnext_page:
X	    case '+'	:  /* move to next page if we're not on the last */
X			   if((selected &&
X			     ((header_page+1)*headers_per_page < selected))
X			   ||(!selected &&
X			     ((header_page+1)*headers_per_page<message_count))){
X
X			     header_page++;
X			     nucurr = NEW_PAGE;
X
X			     if(move_when_paged) {
X			       /* move to first message of new page */
X			       if(selected)
X				 current = visible_to_index(
X				   header_page * headers_per_page + 1) + 1;
X			       else
X				 current = header_page * headers_per_page + 1;
X			     }
X			   } else error("Already on last page.");
X			   break;
X
Xprev_page:
X	    case '-'	:  /* move to prev page if we're not on the first */
X			   if(header_page > 0) {
X			     header_page--;
X			     nucurr = NEW_PAGE;
X
X			     if(move_when_paged) {
X			       /* move to first message of new page */
X			       if(selected)
X				 current = visible_to_index(
X				   header_page * headers_per_page + 1) + 1;
X			       else
X				 current = header_page * headers_per_page + 1;
X			     }
X			   } else error("Already on first page.");
X			   break;
X
Xfirst_msg:
X	    case '='    :  if (selected)
X			     current = visible_to_index(1)+1;
X			   else
X			     current = 1;
X			   nucurr = get_page(current);
X			   break;
X
Xlast_msg:
X	    case '*'    :  if (selected) 
X			     current = (visible_to_index(selected)+1);
X			   else
X			     current = message_count;	
X			   nucurr = get_page(current);
X			   break;
X
X	    case '|'    :  Writechar('|'); 
X			   if (message_count < 1) {
X			     error("No mail to pipe!");
X			     fflush(stdin);
X			   } else {
X	    		     softkeys_off();
X                             redraw = do_pipe();		
X			     softkeys_on();
X			   }
X			   break;
X
X#ifdef ALLOW_SUBSHELL
X	    case '!'    :  Writechar('!'); 
X                           redraw = subshell();		
X			   break;
X#endif
X
X	    case '%'    :  if (current > 0) {
X			     get_return(address, current-1);
X			     clear_error();
X			     PutLine1(LINES,(COLUMNS-strlen(address))/2,
X				      "%.78s", address);	
X			   } else {
X			     error("No mail to get return address of!"); 
X			     fflush(stdin);
X			   }
X			   break;
X
X	    case '/'    :  /* scan mbox for string */
X			   if  (message_count < 1) {
X			     error("No mail to scan!");
X			     fflush(stdin);
X			   }
X			   else if (pattern_match())
X			     nucurr = get_page(current);
X			   else {
X			     error("pattern not found!");
X			     fflush(stdin);
X			   }
X			   break;
X
X	    case '<'    :  /* scan current message for calendar information */
X#ifdef ENABLE_CALENDAR
X			   if  (message_count < 1) {
X			     error("No mail to scan!");
X			     fflush(stdin);
X			   }
X			   else {
X			       PutLine0(LINES-3, strlen("Command: "), 	
X				   "Scan message for calendar entries...");
X			       scan_calendar();
X			   }
X#else
X	 		   error("Sorry. Calendar function disabled.");
X			   fflush(stdin);
X#endif
X			   break;
X
X	    case 'a'    :  if(alias()) redraw++;
X			   else nufoot++; 	
X			   define_softkeys(MAIN); 	break;
X			
X	    case 'b'    :  PutLine0(LINES-3, strlen("Command: "), 
X			     "Bounce message");
X			   fflush(stdout);
X			   if (message_count < 1) {
X	  		     error("No mail to bounce!");
X			     fflush(stdin);
X			   }
X			   else 
X			     nufoot = remail();
X			   break;
X
X	    case 'c'    :  PutLine0(LINES-3, strlen("Command: "), 
X			      "Change folder");
X			   define_softkeys(CHANGE);
X			   redraw = change_file();
X			   define_softkeys(MAIN);
X			   break;
X
X	    case ctrl('D') :
X	    case '^'    :
X	    case 'd'    :  if (message_count < 1) {
X			     error("No mail to delete!");
X			     fflush(stdin);
X			   }
X			   else {
X			     if(ch == ctrl('D')) {
X
X			       /* if current message did not become deleted,
X				* don't to move to the next undeleted msg. */
X			       if(!meta_match(DELETED)) break;
X
X			     } else 
X 			       delete_msg((ch == 'd'), TRUE);
X
X			     if (resolve_mode) 	/* move after mail resolved */
X			       if((i=next_message(current-1, TRUE)) != -1) {
X				 current = i+1;
X				 nucurr = get_page(current);
X			       }
X			   }
X			   break;
X
X
X#ifdef ALLOW_MAILBOX_EDITING
X	    case 'e'    :  PutLine0(LINES-3,strlen("Command: "),"Edit folder");
X			   if (current > 0) {
X			     edit_mailbox();
X	    		     if (cursor_control)
X			       transmit_functions(ON);	/* insurance */
X	   		   }
X			   else {
X			     error("Folder is empty!");
X			     fflush(stdin);
X			   }
X			   break;
X#else
X	    case 'e'    : error(
X		    "Folder editing isn't configured in this version of ELM.");
X			  fflush(stdin);
X			  break;
X#endif
X		
X	    case 'f'    :  PutLine0(LINES-3, strlen("Command: "), "Forward");
X			   define_softkeys(YESNO);
X			   if (current > 0) {
X			     if(forward()) redraw++;
X			     else nufoot++;
X			   } else {
X			     error("No mail to forward!");
X			     fflush(stdin);
X			   }
X			   define_softkeys(MAIN);
X			   break;
X
X	    case 'g'    :  PutLine0(LINES-3,strlen("Command: "), "Group reply");
X			   fflush(stdout);
X			   if (current > 0) {
X			     if (headers[current-1]->status & FORM_LETTER) {
X			       error("Can't group reply to a Form!!");
X			       fflush(stdin);
X			     }
X			     else {
X			       define_softkeys(YESNO);
X			       redraw = reply_to_everyone();	
X			       define_softkeys(MAIN);
X			     }
X			   }
X			   else {
X			     error("No mail to reply to!"); 
X			     fflush(stdin);
X			   }
X			   break;
X
X	    case 'h'    :  if (filter)
X			     PutLine0(LINES-3, strlen("Command: "), 
X				"Message with headers...");
X			   else
X			     PutLine0(LINES-3, strlen("Command: "),"Display message");
X			   if(current > 0) {
X			     fflush(stdout);
X			     j = filter;
X			     filter = FALSE;
X			     i = show_msg(current);
X			     while (i)
X				i = process_showmsg_cmd(i);
X			     filter = j;
X			     redraw++;
X			     (void)get_page(current);
X			   } else error("No mail to read!");
X			   break;
X
X	    case 'J'    :  if(current > 0) {
X			     if((i=next_message(current-1, FALSE)) != -1) {
X			       current = i+1;
X			       nucurr = get_page(current);
X			     } else error("No more messages below.");
X			   } else error("No mail in folder!");
X			   break;
X
Xnext_undel_msg:
X	    case 'j'    :  if(current > 0) {
X			     if((i=next_message(current-1, TRUE)) != -1) {
X			       current = i+1;
X			       nucurr = get_page(current);
X			     } else error("No more undeleted messages below.");
X			   } else error("No mail in folder!");
X			   break;
X
X	    case 'K'    :  if(current > 0) {
X			     if((i=prev_message(current-1, FALSE)) != -1) {
X			       current = i+1;
X			       nucurr = get_page(current);
X			     } else error("No more messages above.");
X			   } else error("No mail in folder!");
X			   break;
X
Xprev_undel_msg:
X	    case 'k'    :  if(current > 0) {
X			     if((i=prev_message(current-1, TRUE)) != -1) {
X			       current = i+1;
X			       nucurr = get_page(current);
X			     } else error("No more undeleted messages above.");
X			   } else error("No mail in folder!");
X			   break;
X
X	    case 'l'    :  PutLine0(LINES-3, strlen("Command: "),
X				   "Limit displayed messages by...");
X			   clear_error();
X			   if (limit() != 0) {
X			     get_page(current);
X			     redraw++;
X			   } else {
X			     nufoot++;
X			   }
X			   break;
X
X	    case 'm'    :  PutLine0(LINES-3, strlen("Command: "), "Mail");
X			   redraw = sendmsg("", "", "", TRUE,allow_forms,FALSE); 
X			   break;
X
X	    case ' '    : 
X	    case ctrl('J'):
X	    case ctrl('M'):PutLine0(LINES-3, strlen("Command: "), 
X	    		      "Display message");	
X			   fflush(stdout);
X			   if(current > 0 ) {
X			     define_softkeys(READ);
X
X			     i = show_msg(current);
X			     while (i)
X				i = process_showmsg_cmd(i);
X			     redraw++;
X			     (void)get_page(current);
X			   }else error ("No mail to read!");
X			   break;
X
X	    case 'n'    :  PutLine0(LINES-3,strlen("Command: "),"Next Message");
X			   fflush(stdout);
X			   define_softkeys(READ);
X
X			   if(current > 0 ) {
X			     define_softkeys(READ);
X
X			     i = show_msg(current);
X			     while (i)
X			       i = process_showmsg_cmd(i);
X			     redraw++;
X			     if (++current > message_count)
X			       current = message_count;
X			     (void)get_page(current);
X			   }else error ("No mail to read!");
X			   break;
X
X	    case 'o'    :  PutLine0(LINES-3, strlen("Command: "), "Options");
X			   if((i=options()) > 0)
X			     get_page(current);
X			   else if(i < 0)
X			     leave();
X			   redraw++;	/* always fix da screen... */
X			   break;
X
X	    case 'p'    :  PutLine0(LINES-3, strlen("Command: "), "Print mail");
X			   fflush(stdout);
X			   if (message_count < 1) {
X			     error("No mail to print!");
X			     fflush(stdin);
X			   }
X			   else
X			     print_msg();			
X			   break;
X
X	    case 'q'    :  PutLine0(LINES-3, strlen("Command: "), "Quit");
X
X			   if (mailfile_size != bytes(cur_folder)) {
X			     error("New Mail!  Quit cancelled...");
X			     fflush(stdin);
X	  		     if (folder_type == SPOOL) unlock();
X			   }
X			   else
X			     quit(TRUE);		
X
X			   break;
X
X	    case 'Q'    :  PutLine0(LINES-3, strlen("Command: "), "Quick quit");
X
X			   if (mailfile_size != bytes(cur_folder)) {
X			     error("New Mail!  Quick Quit cancelled...");
X	  		     if (folder_type == SPOOL) unlock();
X			   }
X			   else
X			     quit(FALSE);		
X
X			   break;
X
X	    case 'r'    :  PutLine0(LINES-3, strlen("Command: "), 
X			      "Reply to message");
X			   if (current > 0) 
X			     redraw = reply();	
X			   else {
X			     error("No mail to reply to!"); 
X			     fflush(stdin);
X			   }
X			   softkeys_on();
X			   break;
X
X	    case '>'    : /** backwards compatibility **/
X
X	    case 'C'	:
X	    case 's'    :  if  (message_count < 1) {
X			     error1("No mail to %s!",
X			       ch != 'C' ? "save" : "copy");
X			     fflush(stdin);
X			   }
X			   else {
X			     PutLine1(LINES-3, strlen("Command: "),
X				      "%s to folder",
X				      ch != 'C' ? "Save" : "Copy");
X			     PutLine0(LINES-3,COLUMNS-40,
X				"(Use '?' to list your folders)");
X			     if (save(&redraw, FALSE, (ch != 'C'))
X				 && resolve_mode && ch != 'C') {
X			       if((i=next_message(current-1, TRUE)) != -1) {
X				 current = i+1;
X				 nucurr = get_page(current);
X			       }
X			     }
X			   }
X			   ClearLine(LINES-2);		
X			   break;
X
X            case ctrl('T') :
X	    case 't'       :  if (message_count < 1) {
X				error("No mail to tag!");
X				fflush(stdin);
X			      }
X			      else if (ch == 't')
X				tag_message(TRUE); 
X			      else
X				meta_match(TAGGED);
X			      break;
X
X	    case 'u'    :  if (message_count < 1) {
X			     error("No mail to mark as undeleted!");
X			     fflush(stdin);
X			   }
X			   else {
X			     undelete_msg(TRUE);
X			     if (resolve_mode) 	/* move after mail resolved */
X			       if((i=next_message(current-1, FALSE)) != -1) {
X				 current = i+1;
X				 nucurr = get_page(current);
X			       }
X/*************************************************************************
X **  What we've done here is to special case the "U)ndelete" command to
X **  ignore whether the next message is marked for deletion or not.  The
X **  reason is obvious upon usage - it's a real pain to undelete a series
X **  of messages without this quirk.  Thanks to Jim Davis @ HPLabs for
X **  suggesting this more intuitive behaviour.
X **
X **  The old way, for those people that might want to see what the previous
X **  behaviour was to call next_message with TRUE, not FALSE.
X**************************************************************************/
X			   }
X			   break;
X
X	    case ctrl('U') : if (message_count < 1) {
X			       error("No mail to undelete!");
X			       fflush(stdin);
X			     }
X			     else 
X			       meta_match(UNDELETE);
X			     break;
X
X	    case 'X'    :  PutLine0(LINES-3, strlen("Command: "), "Quick Exit");
X                           fflush(stdout);
X			   leave();
X			   break;
X
X	    case ctrl('Q') :
X	    case 'x'    :  PutLine0(LINES-3, strlen("Command: "), "Exit");  
X                           fflush(stdout);
X			   exit_prog();
X			   break;
X
X	    case ctrl('L') : redraw++;	break;
X
X            case EOF :  leave();  /* Read failed, control tty died? */
X                        break;
X	    
X	    case '@'    : debug_screen();  redraw++;	break;
X	
X	    case '#'    : if (message_count) {
X			    debug_message(); 
X			    redraw++;	
X			  } 
X			  else {
X			    error("No mail to check.");
X			    fflush(stdin);
X			  }
X			  break;
X
X	    case NO_OP_COMMAND : break;	/* noop for timeout loop */
X
X	    case ESCAPE : if (cursor_control) {
X			    key_offset = 1;
X			    ch = ReadCh(); 
X  
X                            if ( ch == '[' || ch == 'O')
X                            {
X                              ch = ReadCh();
X                              key_offset++;
X                            }
X  
X			    if(ch == up[key_offset]) goto prev_undel_msg;
X			    else if(ch == down[key_offset]) goto next_undel_msg;
X			    else if(ch == right[key_offset]) goto next_page;
X			    else if(ch == left[key_offset]) goto prev_page;
X			    else if (hp_terminal) {
X			      switch (ch) {
X			      case 'U':		goto next_page;
X			      case 'V':		goto prev_page;
X			      case 'h': 	
X			      case 'H':		goto first_msg;
X			      case 'F':		goto last_msg;
X			      case 'A':
X			      case 'D':
X			      case 'i':		goto next_undel_msg;
X			      case 'B':
X			      case 'I':
X			      case 'C':		goto prev_undel_msg;
X			      default: PutLine2(LINES-3, strlen("Command: "), 
X					"%c%c", ESCAPE, ch);
X			      }
X			    } else /* false hit - output */
X			      PutLine2(LINES-3, strlen("Command: "), 
X					  "%c%c", ESCAPE, ch);
X			  }
X
X			  /* else fall into the default error message! */
X
X	    default	: if (ch > '0' && ch <= '9') {
X			    PutLine0(LINES-3, strlen("Command: "), 
X				    "New Current Message");
X			    i = read_number(ch);
X
X			    if( i > message_count)
X			      error("Not that many messages.");
X			    else if(selected
X				&& isoff(headers[i-1]->status, VISIBLE))
X			      error("Message not in limited display.");
X			    else {
X			      current = i;
X			      nucurr = get_page(current);
X			    }
X			  }
X			  else {
X	 		    error("Unknown command. Use '?' for help.");
X			    fflush(stdin);
X			  }
X	  }
X
X	  if (redraw)
X	    showscreen();
X
X	  if ((current < 1) || (selected && compute_visible(current) < 1)) {
X	    if (message_count > 0) {
X	      /* We are out of range! Get to first message! */
X	      if (selected)
X		current = compute_visible(1);
X	      else
X		current = 1;
X	    }
X	    else
X	      current = 0;
X	  }
X	  else if ((current > message_count)
X	       || (selected && compute_visible(current) > selected)) {
X	    if (message_count > 0) {
X	      /* We are out of range! Get to last (visible) message! */
X	      if (selected)
X		current = visible_to_index(selected)+1;
X	      else
X		current = message_count;
X	    }
X	    else
X	      current = 0;
X	  }
X	    
X	  if (nucurr == NEW_PAGE) 
X	    show_headers();
X	  else if (nucurr == SAME_PAGE)
X	    show_current();
X	  else if (nufoot) {
X	    if (mini_menu) {
X	      MoveCursor(LINES-7, 0);  
X              CleartoEOS();
X	      show_menu();
X	    }
X	    else {
X	      MoveCursor(LINES-4, 0);
X	      CleartoEOS();
X	    }
X	    show_last_error();	/* for those operations that have to
X				 * clear the footer except for a message.
X				 */
X	  }
X
X	} /* the BIG while loop! */
X}
X
Xdebug_screen()
X{
X	/**** spit out all the current variable settings and the table
X	      entries for the current 'n' items displayed. ****/
X
X	register int i, j;
X	char     buffer[SLEN];
X
X	ClearScreen();
X	Raw(OFF);
X
X	PutLine2(0,0,"Current message number = %d\t\t%d message(s) total\n",
X		current, message_count);
X	PutLine2(2,0,"Header_page = %d           \t\t%d possible page(s)\n",
X		header_page, (int) (message_count / headers_per_page) + 1);
X
X	PutLine1(4,0,"\nCurrent mailfile is %s.\n\n", cur_folder);
X
X	i = header_page*headers_per_page;	/* starting header */
X
X	if ((j = i + (headers_per_page-1)) >= message_count) 
X	  j = message_count-1;
X
X	Write_to_screen(
X"Num      From                 	Subject                         Lines  Offset\n\r\n\r",0);
X
X	while (i <= j) {
X	   sprintf(buffer, 
X	   "%3d  %-16.16s  %-40.40s  %4d  %d\n\r",
X		    i+1,
X		    headers[i]->from, 
X		    headers[i]->subject,
X		    headers[i]->lines,
X		    headers[i]->offset);
X	    Write_to_screen(buffer, 0);
X	  i++;
X	}
X	
X	Raw(ON);
X
X	PutLine0(LINES,0,"Press any key to return.");
X	(void) ReadCh();
X}
X
X
Xdebug_message()
X{
X	/**** Spit out the current message record.  Include EVERYTHING
X	      in the record structure. **/
X	
X	char buffer[SLEN];
X	register struct header_rec *current_header = headers[current-1];
X
X	ClearScreen();
X	Raw(OFF);
X
X	Write_to_screen("\t\t\t----- Message %d -----\n\r\n\r\n\r\n\r", 1,
X		current);
X
X	Write_to_screen("Lines : %-5d\t\t\tStatus: A  C  D  E  F  N  O  P  T  U  V\n\r", 1,
X		current_header->lines);
X	Write_to_screen("            \t\t\t        c  o  e  x  o  e  l  r  a  r  i\n\r", 0);
X	Write_to_screen("            \t\t\t        t  n  l  p  r  w  d  i  g  g  s\n\r", 0);
X	Write_to_screen("            \t\t\t        n  f  d  d  m        v  d  n  i\n\r", 0);
X
X	sprintf(buffer, 
X		"\n\rOffset: %ld\t\t\t        %d  %d  %d  %d  %d",
X		current_header->offset,
X		(current_header->status & ACTION) != 0,
X		(current_header->status & CONFIDENTIAL) != 0,
X		(current_header->status & DELETED) != 0,
X		(current_header->status & EXPIRED) != 0,
X		(current_header->status & FORM_LETTER) != 0);
X	sprintf(buffer + strlen(buffer),
X		"  %d  %d  %d  %d  %d  %d\n",
X		(current_header->status & NEW) != 0,
X		(current_header->status & UNREAD) != 0,
X		(current_header->status & PRIVATE) != 0,
X		(current_header->status & TAGGED) != 0,
X		(current_header->status & URGENT) != 0,
X		(current_header->status & VISIBLE) != 0);
X
X	Write_to_screen(buffer, 0);
X
X	sprintf(buffer, "\n\rReceived on: %d/%d/%d at %d:%02d\n\r",
X		current_header->received.month+1,
X		current_header->received.day,
X		current_header->received.year,
X		current_header->received.hour,
X		current_header->received.minute);
X	Write_to_screen(buffer, 0);
X
X	sprintf(buffer, "Message sent on: %s, %s %s, %s at %s\n\r",
X		current_header->dayname,
X		current_header->month,
X		current_header->day,
X		current_header->year,
X		current_header->time);
X	Write_to_screen(buffer, 0);
X	
X	Write_to_screen("From: %s\n\rSubject: %s", 2,
X		current_header->from,
X		current_header->subject);
X
X	Write_to_screen("\n\rPrimary Recipient: %s\nInternal Index Reference Number = %d\n\r", 2,
X		current_header->to,
X		current_header->index_number);
X
X	Write_to_screen("Message-ID: %s\n\r", 1,
X		strlen(current_header->messageid) > 0 ? 
X		current_header->messageid : "<none>");
X
X	Write_to_screen("Status: %s\n\r", 1, current_header->mailx_status);
X	
X	Raw(ON);
X
X	PutLine0(LINES,0,"Please Press any key to return.");
X	(void) ReadCh();
X}
X
Xdo_check_only(to_whom)
Xchar *to_whom;
X	{
X	char buffer[VERY_LONG_STRING];
X
X	dprint(3, (debugfile, "Check-only: checking \n-> \"%s\"\n", 
X		format_long(to_whom, 3)));
X	(void) build_address(strip_commas(to_whom), buffer); 
X	printf("Expands to: %s", format_long(buffer, strlen("Expands to: ")));
X	}
SHAR_EOF
# ============= src/encode.c ==============
echo "x - extracting src/encode.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > src/encode.c &&
X
Xstatic char rcsid[] = "@(#)$Id: encode.c,v 4.1 90/04/28 22:42:57 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:	encode.c,v $
X * Revision 4.1  90/04/28  22:42:57  syd
X * checkin of Elm 2.3 as of Release PL0
X * 
X *
X ******************************************************************************/
X
X/** This is a heavily mangled version of the 'cypher' program written by
X    person or persons unknown.  
X
X**/
X
X#include "headers.h"
X
X#define RS	94
X#define RN	4
X#define RMASK	0x7fff	/* use only 15 bits */
X
Xstatic char r[RS][RN];		/* rotors */
Xstatic char ir[RS][RN];		/* inverse rotors */
Xstatic char h[RS];		/* half rotor */
Xstatic char s[RS];		/* shuffle vector */
Xstatic int  p[RN];		/* rotor indices */
X
Xstatic char the_key[SLEN];	/* unencrypted key */
Xstatic char *encrypted_key;	/* encrypted key   */
X
Xchar *strncpy(), *strcpy();
Xunsigned long sleep();
X
X#define DECRYPT_PROMPT		"Enter decryption key: "
X#define FIRST_ENC_PROMPT	"Enter encryption key: "
X#define SECOND_ENC_PROMPT	"Please enter it again: "
X#define PROMPT_LINE		LINES-1
X
Xgetkey(send)
Xint send;
X{
X	/** this routine prompts for and returns an encode/decode
X	    key for use in the rest of the program. **/
X
X	char buffer[2][NLEN];
X
X	while (1) {
X	  PutLine0(PROMPT_LINE, 0, (send ? FIRST_ENC_PROMPT : DECRYPT_PROMPT));
X	  CleartoEOLN();
X	  optionally_enter(buffer[0], PROMPT_LINE,
X	    strlen(send ? FIRST_ENC_PROMPT : DECRYPT_PROMPT), FALSE, TRUE);
X	  if (send) {
X	    PutLine0(PROMPT_LINE, 0, SECOND_ENC_PROMPT);
X	    CleartoEOLN();
X	    optionally_enter(buffer[1], PROMPT_LINE, strlen(SECOND_ENC_PROMPT),
X	      FALSE, TRUE);
X	    if(strcmp(buffer[0], buffer[1]) != 0) {
X	      error("Your keys were not the same!");
X	      sleep(1);
X	      clear_error();
X	      continue;
X	    }
X	  }
X	  break;
X	}
X        strcpy(the_key, buffer[0]);	/* save unencrypted key */
X	makekey(buffer[0]);
X
X	setup();		/** initialize the rotors etc. **/
X
X	ClearLine(PROMPT_LINE);		
X	clear_error();
X}
X
Xget_key_no_prompt()
X{
X	/** This performs the same action as get_key, but assumes that
X	    the current value of 'the_key' is acceptable.  This is used
X	    when a message is encrypted twice... **/
X
X	char buffer[SLEN];
X
X	strcpy(buffer, the_key);
X
X	makekey( buffer );
X
X	setup();
X}
X
Xencode(line)
Xchar *line;
X{
X	/** encrypt or decrypt the specified line.  Uses the previously
X	    entered key... **/
X
X	register int i, j, ph = 0;
X
X	for (; *line; line++) {
X	  i = (int) *line;
X
X	  if ( (i >= ' ') && (i < '~') ) {
X	    i -= ' ';
X
X	    for ( j = 0; j < RN; j++ )		/* rotor forwards */
X	      i = r[(i+p[j])%RS][j];
X
X	    i = ((h[(i+ph)%RS])-ph+RS)%RS;	/* half rotor */
X
X	    for ( j--  ; j >= 0; j-- )		/* rotor backwards */
X	      i = (ir[i][j]+RS-p[j])%RS;
X
X	    j = 0;				/* rotate rotors */
X	    p[0]++;
X	    while ( p[j] == RS ) {
X	      p[j] = 0;
X	      j++;
X	      if ( j == RN ) break;
X	      p[j]++;
X            }
X  
X	    if ( ++ph == RS )
X	      ph = 0;
X
X	    i += ' ';
X	  }
X	  
X	  *line = (char) i;	/* replace with altered one */
X	}
X}
X
X
Xmakekey( rkey)
Xchar *rkey;
X{
X	/** encrypt the key using the system routine 'crypt' **/
X
X	char key[9], salt[2], *crypt();
X
X	strncpy( key, rkey, 8);
X	key[8] = '\0';
X	salt[0] = key[0];
X	salt[1] = key[1];
X#ifdef CRYPT
X	encrypted_key = crypt( key, salt);
X#else
X	encrypted_key = key;
X#endif
X}
X
X/*
X * shuffle rotors.
X * shuffle each of the rotors indiscriminately.  shuffle the half-rotor
X * using a special obvious and not very tricky algorithm which is not as
X * sophisticated as the one in crypt(1) and Oh God, I'm so depressed.
X * After all this is done build the inverses of the rotors.
X */
X
Xsetup()
X{
X	register long i, j, k, temp;
X	long seed;
X
X	for ( j = 0; j < RN; j++ ) {
X		p[j] = 0;
X		for ( i = 0; i < RS; i++ )
X			r[i][j] = i;
X	}
X
X	seed = 123;
X	for ( i = 0; i < 13; i++)		/* now personalize the seed */
X	  seed = (seed*encrypted_key[i] + i) & RMASK;
X
X	for ( i = 0; i < RS; i++ )		/* initialize shuffle vector */
X	  h[i] = s[i] = i;
X
X	for ( i = 0; i < RS; i++) {		/* shuffle the vector */
X	  seed = (5 * seed + encrypted_key[i%13]) & RMASK;;
X	  k = ((seed % 65521) & RMASK) % RS;
X	  temp = s[k];
X	  s[k] = s[i];
X	  s[i] = temp;
X	}
X
X	for ( i = 0; i < RS; i += 2 ) {	/* scramble the half-rotor */
X	  temp = h[s[i]];			/* swap rotor elements ONCE */
X	  h[s[i]] = h[s[i+1]];
X	  h[s[i+1]] = temp;
X	}
X
X	for ( j = 0; j < RN; j++) {			/* select a rotor */
X
X	  for ( i = 0; i < RS; i++) {		/* shuffle the vector */
X	    seed = (5 * seed + encrypted_key[i%13]) & RMASK;;
X	    k = ((seed % 65521) & RMASK) % RS;
X	    temp = r[i][j];
X	    r[i][j] = r[k][j];
X	    r[k][j] = temp;
X	  }
X
X	  for ( i = 0; i < RS; i++) 		/* create inverse rotors */
X	    ir[r[i][j]][j] = i;
X       }
X}
SHAR_EOF
# ============= src/errno.c ==============
echo "x - extracting src/errno.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > src/errno.c &&
X
Xstatic char rcsid[] = "@(#)$Id: errno.c,v 4.1 90/04/28 22:42:58 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:	errno.c,v $
X * Revision 4.1  90/04/28  22:42:58  syd
X * checkin of Elm 2.3 as of Release PL0
X * 
X *
X ******************************************************************************/
X
X/** This routine maps error numbers to error names and error messages.
X    These are all directly ripped out of the include file errno.h, and
X    are HOPEFULLY standardized across the different breeds of Unix!!
X
X    If (alas) yours are different, you should be able to use awk to
X    mangle your errno.h file quite simply...
X
X**/
X
X#include "headers.h"
X
Xchar *err_name[] = { 
X/* 0 */	        "NOERROR", "No error status currently",
X/* 1 */		"EPERM",   "Not super-user",
X/* 2 */		"ENOENT",  "No such file or directory",
X/* 3 */		"ESRCH",   "No such process",
X/* 4 */		"EINTR",   "Interrupted system call",
X/* 5 */		"EIO",     "I/O error",
X/* 6 */		"ENXIO",   "No such device or address",
X/* 7 */		"E2BIG",   "Arg list too long",
X/* 8 */		"ENOEXEC", "Exec format error",
X/* 9 */		"EBADF",   "Bad file number",
X/* 10 */	"ECHILD",  "No children",
X/* 11 */	"EAGAIN",  "No more processes",
X/* 12 */	"ENOMEM",  "Not enough core",
X/* 13 */	"EACCES",  "Permission denied",
X/* 14 */	"EFAULT",  "Bad address",
X/* 15 */	"ENOTBLK", "Block device required",
X/* 16 */	"EBUSY",   "Mount device busy",
X/* 17 */	"EEXIST",  "File exists",
X/* 18 */	"EXDEV",   "Cross-device link",
X/* 19 */	"ENODEV",  "No such device",
X/* 20 */	"ENOTDIR", "Not a directory",
SHAR_EOF
echo "End of  part 11"
echo "File src/errno.c is continued in part 12"
echo "12" > shar3_seq_.tmp
exit 0
Newsgroups: biz.sco.sources