[comp.sources.unix] v22i077: ELM mail syste, release 2.3, Part18/26

rsalz@uunet.uu.net (Rich Salz) (06/05/90)

Submitted-by: Syd Weinstein <syd@dsinc.dsi.com>
Posting-number: Volume 22, Issue 77
Archive-name: elm2.3/part18

---- Cut Here and unpack ----
#!/bin/sh
# this is part 18 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file src/mailmsg2.c continued
#
CurArch=18
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
     exit 1; fi
( read Scheck
  if test "$Scheck" != $CurArch
  then echo "Please unpack part $Scheck next!"
       exit 1;
  else exit 0; fi
) < s2_seq_.tmp || exit 1
echo "x - Continuing file src/mailmsg2.c"
sed 's/^X//' << 'SHAR_EOF' >> src/mailmsg2.c
X	  if (verify_bounceback() == TRUE) {
X	    if (strlen(cc) > 0) strcat(expanded_cc, ", ");
X	    strcat(expanded_cc, bounce_off_remote(to));
X	  }
X
X	/** grab a copy if the user so desires... **/
X
X	if (*copy_file) /* i.e. if copy_file contains a name */
X	  save_copy(expanded_to, expanded_cc, expanded_bcc,
X	       filename, copy_file, form);
X
X	/** write all header information into whole_msg_file **/
X
X	if((whole_msg_file=tempnam(temp_dir, "snd.")) == NULL) {
X	  dprint(1, (debugfile, "couldn't make temp file nam! (mail)\n"));
X	  if(batch_only)
X	    printf("Sorry - couldn't make temp file name!\n");
X	  else if(mail_only)
X	    error("Sorry - couldn't make temp file name.");
X	  else
X	    set_error("Sorry - couldn't make temp file name.");
X	  return(need_redraw);
X	}
X
X	/** try to write headers to new temp file **/
X
X	dprint(6, (debugfile, "Composition file='%s' and mail buffer='%s'\n", 
X		    filename, whole_msg_file));
X
X	dprint(2,(debugfile,"--\nTo: %s\nCc: %s\nBcc: %s\nSubject: %s\n---\n", 
X		  expanded_to, expanded_cc, expanded_bcc, subject));
X
X	if ((real_reply=
X	   write_header_info(whole_msg_file, expanded_to,
X	     expanded_cc, expanded_bcc, form == YES, FALSE)) == NULL) {
X
X	  /** IT FAILED!!  MEIN GOTT!  Use a dumb mailer instead! **/
X
X	  dprint(3, (debugfile, "** write_header failed: %s\n", 
X		 error_name(errno)));
X
X	  if (cc[0] != '\0')  		/* copies! */
X	    sprintf(expanded_to,"%s %s", expanded_to, expanded_cc);
X
X	  quote_args(very_long_buffer, strip_parens(strip_commas(expanded_to)));
X	  strcpy(expanded_to, very_long_buffer);
X
X	  sprintf(very_long_buffer, "( (%s -s \"%s\" %s ; %s %s) & ) < %s",
X		  mailx, subject, expanded_to, remove_cmd, filename, filename);
X
X	  if(batch_only)
X	    printf("Message sent using dumb mailer %s.\n", mailx);
X	  else
X	    error1("Message sent using dumb mailer %s.", mailx);
X	  sleep(2);	/* ensure time to see this prompt! */
X
X	}
X	else {
X
X	  copy_message_across(reply, real_reply, FALSE);
X
X          /* Append signature if not done earlier */
X
X          if (!signature_done && !retransmit && copy_msg != FORM)
X               append_sig(real_reply);
X
X	  fclose(real_reply);
X
X	  if (cc[0] != '\0')  				         /* copies! */
X	    sprintf(expanded_to,"%s %s", expanded_to, expanded_cc);
X
X	  if (bcc[0] != '\0') {
X	    strcat(expanded_to, " ");
X	    strcat(expanded_to, expanded_bcc);
X	  }
X
X	  remove_hostbang(expanded_to);
X
X	  if (strcmp(sendmail, mailer) == 0
X#ifdef SITE_HIDING
X	      && ! is_a_hidden_user(username))
X#else
X	     					)
X#endif
X		
X	     strcpy(mailerflags, (sendmail_verbose ? smflagsv : smflags));
X	  else
X	     mailerflags[0] ='\0';
X
X	  quote_args(very_long_buffer, strip_parens(strip_commas(expanded_to)));
X	  strcpy(expanded_to, very_long_buffer);
X
X	  sprintf(very_long_buffer,"( (%s %s %s ; %s %s) & ) < %s", 
X		mailer, mailerflags, expanded_to,
X		remove_cmd, whole_msg_file, whole_msg_file);
X	}
X	
X	fclose(reply);
X
X	if(batch_only)
X	  printf("Sending mail...\n");
X	else {
X	  PutLine0(LINES,0,"Sending mail...");
X	  CleartoEOLN();
X	}
X
X	/* Take note of mailer return value */
X
X	if ( sys_status = system_call(very_long_buffer, SH, FALSE, FALSE) ) {
X		/* problem case: */
X		if (mail_only || batch_only)
X		   printf("\r\nmailer returned error status %d\r\n", sys_status);
X		else {
X		   sprintf(very_long_buffer, "mailer returned error status %d", sys_status);
X		   set_error(very_long_buffer);
X		}
X	} else {
X		/* Success case: */
X		if(batch_only)
X		  printf("Mail sent!\n");
X		else if(mail_only)
X		  error("Mail sent!");
X		else
X		  set_error("Mail sent!");
X	}
X
X	/* Unlink temp file now.
X	 * This is a precaution in case the message was encrypted.
X	 * I.e. even though this file is readable by the owner only,
X	 * encryption is supposed to hide things even from someone
X	 * with root privelges. The best we can do is not let this
X	 * file just hang after we're finished with it.
X	 */
X	(void)unlink(filename);
X
X	return(need_redraw);
X}
X
X/*
X * remove_hostbang - Given an expanded list of addresses, remove all
X * occurrences of "thishost!" at the beginning of addresses.
X * This hack is useful in itself, but it is required now because of the
X * kludge disallowing alias expansion on return addresses.
X */
X
Xremove_hostbang(addrs)
Xchar *addrs;
X{
X	int i, j, hlen, flen;
X
X	if ((hlen = strlen(hostname)) < 1)
X	  return;
X
X	flen = strlen(hostfullname);
X	i = j = 0;
X
X	while (addrs[i]) {
X	  if (i == 0 || isspace(addrs[i - 1])) {
X	    if (strncmp(&addrs[i], hostname, hlen) == 0 &&
X	      addrs[i + hlen] == '!') {
X	        i += hlen + 1;
X	        continue;
X	    }
X	    if (strncmp(&addrs[i], hostfullname, flen) == 0 &&
X	      addrs[i + flen] == '!') {
X	        i += flen + 1;
X	        continue;
X	    }
X	  }
X	  addrs[j++] = addrs[i++];
X	}
X	addrs[j] = 0;
X}
X
Xmail_form(address, subj)
Xchar *address, *subj;
X{
X	/** copy the appropriate variables to the shared space... */
X
X	strcpy(subject, subj);
X	strcpy(to, address);
X	strcpy(expanded_to, address);
X
X	return(mail(FORM, NO, NO));
X}
X
Xint
Xrecall_last_msg(filename, copy_msg, cancelled_msg, already_has_text)
Xchar *filename;
Xint  copy_msg, *cancelled_msg, *already_has_text;
X{
X	char ch;
X
X	/** If filename exists and we've recently cancelled a message,
X	    the ask if the user wants to use that message instead!  This
X	    routine returns TRUE if the user wants to retransmit the last
X	    message, FALSE otherwise...
X	**/
X
X	register int retransmit = FALSE;
X
X	if (access(filename, EDIT_ACCESS) == 0 && *cancelled_msg) {
X	  Raw(ON);
X	  CleartoEOLN();
X	  if (copy_msg)
X	    PutLine1(LINES-1,0,"Recall last kept message instead? (y/n) y%c",
X		     BACKSPACE);
X	  else
X	    PutLine1(LINES-1,0,"Recall last kept message? (y/n) y%c", 
X		     BACKSPACE);
X	  fflush(stdout);
X	  ch = ReadCh();
X	  if (tolower(ch) != 'n') {
X	    Write_to_screen("Yes.",0);	
X            retransmit++;
X	    *already_has_text = TRUE;
X	  }
X	  else 
X	    Write_to_screen("No.",0);	
X
X	  fflush(stdout);
X
X	  *cancelled_msg = 0;
X	}
X
X	return(retransmit);
X}
X
Xint
Xverify_transmission(filename, form_letter)
Xchar *filename;
Xint  *form_letter;
X{
X	/** Ensure the user wants to send this.  This routine returns
X	    the character entered.  Modified compliments of Steve Wolf 
X	    to add the'dead.letter' feature.
X	    Also added form letter support... 
X	**/
X
X	FILE *deadfd, *messagefd;
X	char ch, buffer[SLEN], fname[SLEN];
X	int x_coord, y_coord;
X
X	while(1) {
X	  /* clear bottom part of screen */
X	  MoveCursor(LINES-2,0);
X	  CleartoEOS();
X
X	  /* display prompt and menu according to
X	   * user level and what's available on the menu */
X	  if (user_level == 0) {
X	    PutLine0(LINES-2,0,
X      "Please choose one of the following options by parenthesized letter: s");
X	    GetXYLocation(&x_coord, &y_coord);
X	    y_coord--;	/* backspace over default answer */
X	    Centerline(LINES-1,
X	      "e)dit message, edit h)eaders, s)end it, or f)orget it.");
X	  } else {
X	    PutLine0(LINES-2, 0, "And now: s");
X	    GetXYLocation(&x_coord, &y_coord);
X	    y_coord--;	/* backspace over default answer */
X	    if (*form_letter == PREFORMATTED)  {
X	       strcpy(buffer, "Choose ");
X	    } else if (*form_letter == YES) {
X	       strcpy(buffer, "Choose e)dit form, ");
X	    } else if (*form_letter == MAYBE)  {
X	       strcpy(buffer, "Choose e)dit msg, m)ake form, ");
X	    } else {
X	       strcpy(buffer, "Choose e)dit message, ");
X	    }
X#ifdef ALLOW_SUBSHELL
X	    strcat(buffer, "!)shell, ");
X#endif
X	    strcat(buffer, "h)eaders, c)opy file, s)end, or f)orget.");
X	    Centerline(LINES-1, buffer);
X	  }
X
X	  /* wait for answer */
X	  fflush(stdin);
X	  fflush(stdout);
X	  Raw(ON);	/* double check... testing only... */
X	  MoveCursor(x_coord, y_coord);
X	  ch = ReadCh();
X	  ch = tolower(ch);
X
X	  /* process answer */
X	  switch (ch) {
X	     case 'f': Write_to_screen("Forget",0);
X		       if (mail_only) {
X			 /** try to save it as a dead letter file **/
X			 save_file_stats(fname);
X			 sprintf(fname, "%s/%s", home, dead_letter);
X			 if ((deadfd = fopen(fname,"a")) == NULL) {
X			   dprint(1, (debugfile,
X		   "\nAttempt to append to deadletter file '%s' failed: %s\n\r",
X			       fname, error_name(errno)));
X			   error("Message not saved, Sorry.");
X			 }
X			 else if ((messagefd = fopen(filename, "r")) == NULL) {
X			   dprint(1, (debugfile,
X			     "\nAttempt to read reply file '%s' failed: %s\n\r",
X				   filename, error_name(errno)));
X			   error("Message not saved, Sorry.");
X			 } else {
X			   /* if we get here we're okay for everything */
X			   while (fgets(buffer, SLEN, messagefd) != NULL)
X			     fputs(buffer, deadfd);
X
X			   fclose(messagefd);
X			   fclose(deadfd);
X			   restore_file_stats(fname);
X
X			   error1("Message saved in file \"$HOME/%s\".",
X			     dead_letter);
X
X			}
X		       } else if (user_level != 0)
X			set_error("Message kept. Can be restored at next f)orward, m)ail or r)eply.");
X		       break;
X
X	     case '\n' :
X	     case '\r' :
X	     case 's'  : Write_to_screen("Send",0);
X			 ch = 's';		/* make sure! */
X			 break;
X
X	     case 'm'  : if (*form_letter == MAYBE) {
X			   *form_letter = YES;
X		           switch (check_form_file(filename)) {
X			     case -1 : return('f');
X			     case 0  : *form_letter = MAYBE;  /* check later!*/
X				       error("No fields in form!");
X				       return('e');
X			     default : continue;
X	                   }
X			 }
X			 else {
X	                    Write_to_screen("%c??", 1, 07);	/* BEEP */
X			    sleep(1);
X		            continue;
X	                 }
X	     case 'e'  :  if (*form_letter != PREFORMATTED) {
X			    Write_to_screen("Edit",0);
X	 	            if (*form_letter == YES) 
X			      *form_letter = MAYBE;
X	                  }
X			  else {
X	                    Write_to_screen("%c??", 1, 07);	/* BEEP */
X			    sleep(1);
X		            continue;
X	                 }
X			 break;
X
X	     case 'h'  : Write_to_screen("Headers",0);
X			 break;
X
X	     case 'c'  : Write_to_screen("Copy file",0);
X			 break;
X
X	     case '!'  : break;
X
X	     default   : Write_to_screen("%c??", 1, 07);	/* BEEP */
X			 sleep(1);
X		         continue;
X	   }
X
X	   return(ch);
X	}
X}
X
XFILE *
Xwrite_header_info(filename, long_to, long_cc, long_bcc, form, copy)
Xchar *filename, *long_to, *long_cc, *long_bcc;
Xint   form, copy;
X{
X	/** Try to open filedesc as the specified filename.  If we can,
X	    then write all the headers into the file.  The routine returns
X	    'filedesc' if it succeeded, NULL otherwise.  Added the ability
X	    to have backquoted stuff in the users .elmheaders file!
X	    If copy is TRUE, then treat this as the saved copy of outbound
X	    mail.
X	**/
X
X	char opentype[2];
X	long time(), thetime;
X	char *ctime();
X	static FILE *filedesc;		/* our friendly file descriptor  */
X
X#ifdef SITE_HIDING
X	char  buffer[SLEN];
X	int   is_hidden_user;		/* someone we should know about?  */
X#endif
X
X	char  *get_arpa_date();
X
X	if(copy)
X	    strcpy(opentype, "a");
X	else
X	    strcpy(opentype, "w");
X
X	save_file_stats(filename);
X	if ((filedesc = fopen(filename, opentype)) == NULL) {
X	  dprint(1, (debugfile,
X	    "Attempt to open file %s for writing failed! (write_header_info)\n",
X	     filename));
X	  dprint(1, (debugfile, "** %s - %s **\n\n", error_name(errno),
X		 error_description(errno)));
X	  error2("Error %s encountered trying to write to %s.", 
X		error_name(errno), filename);
X	  sleep(2);
X	  return(NULL);		/* couldn't open it!! */
X	}
X
X	restore_file_stats(filename);
X
X	if(copy) {	/* Add top line that mailer would add */
X#ifdef MMDF
X	  fprintf(filedesc, MSG_SEPERATOR);
X#endif /* MMDF */
X	  thetime = time((long *) 0);
X	  fprintf(filedesc,"From %s %s", username, ctime(&thetime));
X	}
X
X#ifdef SITE_HIDING
X	if ( !copy && (is_hidden_user = is_a_hidden_user(username))) {
X	  /** this is the interesting part of this trick... **/
X	  sprintf(buffer, "From %s!%s %s\n",  HIDDEN_SITE_NAME,
X		  username, get_ctime_date());
X	  fprintf(filedesc, "%s", buffer);
X	  dprint(1,(debugfile, "\nadded: %s", buffer));
X	  /** so is this perverted or what? **/
X	}
X#endif
X
X
X	/** Subject moved to top of headers for mail because the
X	    pure System V.3 mailer, in its infinite wisdom, now
X	    assumes that anything the user sends is part of the 
X	    message body unless either:
X		1. the "-s" flag is used (although it doesn't seem
X		   to be supported on all implementations??)
X		2. the first line is "Subject:".  If so, then it'll
X		   read until a blank line and assume all are meant
X		   to be headers.
X	    So the gory solution here is to move the Subject: line
X	    up to the top.  I assume it won't break anyone elses program
X	    or anything anyway (besides, RFC-822 specifies that the *order*
X	    of headers is irrelevant).  Gahhhhh....
X	**/
X
X	fprintf(filedesc, "Subject: %s\n", subject);
X
X	  fprintf(filedesc, "To: %s\n", format_long(long_to, strlen("To:")));
X
X	fprintf(filedesc,"Date: %s\n", get_arpa_date());
X
X#ifndef DONT_ADD_FROM
X# ifdef SITE_HIDING
X	if (is_hidden_user)
X	  fprintf(filedesc,"From: %s <%s!%s!%s>\n", full_username,
X		  hostname, HIDDEN_SITE_NAME, username);
X	else
X# else
X#  ifdef  INTERNET
X#   ifdef  USE_DOMAIN
X	fprintf(filedesc,"From: %s <%s@%s>\n", full_username, 
X		username, hostfullname);
X#   else
X	fprintf(filedesc,"From: %s <%s@%s>\n", full_username,
X		username, hostname);
X#   endif
X#  else
X	fprintf(filedesc,"From: %s <%s!%s>\n", full_username,
X		hostname, username);
X#  endif
X# endif
X#endif
X
X	if (cc[0] != '\0')
X	    fprintf(filedesc, "Cc: %s\n", format_long(long_cc, strlen("Cc: ")));
X
X	if (copy && (bcc[0] != '\0'))
X	    fprintf(filedesc, "Bcc: %s\n", format_long(long_bcc, strlen("Bcc: ")));
X
X	if (strlen(action) > 0)
X	    fprintf(filedesc, "Action: %s\n", action);
X	
X	if (strlen(priority) > 0)
X	    fprintf(filedesc, "Priority: %s\n", priority);
X	
X	if (strlen(expires) > 0)
X	    fprintf(filedesc, "Expires: %s\n", expires);
X	
X	if (strlen(reply_to) > 0)
X	    fprintf(filedesc, "Reply-To: %s\n", reply_to);
X
X	if (strlen(in_reply_to) > 0)
X	    fprintf(filedesc, "In-Reply-To: %s\n", in_reply_to);
X
X	if (strlen(user_defined_header) > 0)
X	    fprintf(filedesc, "%s\n", user_defined_header);
X
X	add_mailheaders(filedesc);
X
X	if (form)
X	  fprintf(filedesc, "Content-Type: mailform\n");
X
X#ifndef NOXHEADER
X	fprintf(filedesc, "X-Mailer: ELM [version %s]\n\n", version_buff);
X#endif /* !NOXHEADER */
X
X	return((FILE *) filedesc);
X}
X
Xcopy_message_across(source, dest, copy)
XFILE *source, *dest;
Xint copy;
X{
X	/** Copy the message in the file pointed to by source to the
X	    file pointed to by dest.
X	    If copy is TRUE, treat as a saved copy of outbound mail. **/
X
X	int  crypted = FALSE;			/* are we encrypting?  */
X	int  encoded_lines = 0;			/* # lines encoded     */
X	char buffer[SLEN];			/* file reading buffer */
X
X	while (fgets(buffer, SLEN, source) != NULL) {
X	  if (buffer[0] == '[') {
X	    if (strncmp(buffer, START_ENCODE, strlen(START_ENCODE))==0)
X	      crypted = TRUE;
X	    else if (strncmp(buffer, END_ENCODE, strlen(END_ENCODE))==0)
X	      crypted = FALSE;
X	    else if ((strncmp(buffer, DONT_SAVE, strlen(DONT_SAVE)) == 0)
X	          || (strncmp(buffer, DONT_SAVE2, strlen(DONT_SAVE2)) == 0)) {
X	      if(copy) break;  /* saved copy doesn't want anything after this */
X	      else continue;   /* next line? */
X	    }
X	  }
X	  else if (crypted) {
X	    if (batch_only) {
X	      printf(
X		"Sorry. Cannot send encrypted mail in \"batch mode\".\n\r");
X	      leave();
X	    } else if (! gotten_key++)
X	      getkey(ON);
X	    else if (! encoded_lines)
X	      get_key_no_prompt();		/* reinitialize.. */
X	    encode(buffer);
X	    encoded_lines++;
X	  }
X
X	  if (copy && (strncmp(buffer, "From ", 5) == 0))
X	    /* Add in the > to a From on our copy */
X	    fprintf(dest, ">%s", buffer);
X
X	  else if (!copy && strcmp(buffer, ".\n") == 0)
X	    /* Because some mail transport agents take a lone period to
X	     * mean EOF, we add a blank space on outbound message.
X	     */
X	    fputs(". \n", dest);
X  	  else
X  	    if (fputs(buffer, dest) == EOF) {
X		Write_to_screen("\n\rWrite failed in copy_message_across\n\r", 0);
X		emergency_exit();
X	    }
X	} 
X#ifdef MMDF
X	if (copy) fputs(MSG_SEPERATOR, dest);
X#else
X	if (copy) fputs("\n", dest);	/* ensure a blank line at the end */
X#endif /* MMDF */
X}
X
Xint
Xverify_bounceback()
X{
X	char	ch;
X
X	/** Ensure the user wants to have a bounceback copy too.  (This is
X	    only called on messages that are greater than the specified 
X	    threshold hops and NEVER for non-uucp addresses.... Returns
X	    TRUE iff the user wants to bounce a copy back.... 
X	 **/
X
X	MoveCursor(LINES,0);
X	CleartoEOLN();
X	PutLine1(LINES,0, 
X	      "\"Bounce\" a copy off the remote machine? (y/n) y%c",
X	      BACKSPACE);
X	fflush(stdin);	/* wait for answer! */
X	fflush(stdout);
X	ch = ReadCh();
X	if (tolower(ch) != 'y') { 
X	  Write_to_screen("No.", 0);
X	  fflush(stdout);
X	  return(FALSE);
X	}
X	Write_to_screen("Yes.", 0);
X	fflush(stdout);
X
X	return(TRUE);
X}
X
X
Xint
Xappend_sig(file)
XFILE *file;
X{
X	/* Append the correct signature file to file.  Return TRUE if
X           we append anything.  */
X
X        /* Look at the to and cc list to determine which one to use */
X
X	/* We could check the bcc list too, but we don't want people to
X           know about bcc, even indirectly */
X
X	/* Some people claim that  user@anything.same_domain should be 
X	   considered local.  Since it's not the same machine, better be 
X           safe and use the remote sig (presumably it has more complete
X           information).  You can't necessarily finger someone in the
X           same domain. */
X
X	  if (!batch_only && (local_signature[0] || remote_signature[0])) {
X
X            char filename2[SLEN];
X	    char *sig;
X
X  	    if (index(expanded_to, '!') || index(expanded_cc,'!'))
X              sig = remote_signature;		/* ! always means remote */
X            else {
X	      /* check each @ for @thissite.domain */
X	      /* if any one is different than this, then use remote sig */
X	      int len;
X	      char *ptr;
X	      char sitename[SLEN];
X	      sprintf(sitename,"@%s",hostfullname);
X	      len = strlen(sitename);
X              sig = local_signature;
X              for (ptr = index(expanded_to,'@'); ptr;  /* check To: list */
X	          ptr = index(ptr+1,'@')) {
X		if (strncmp(ptr,sitename,len) != 0
X		    || (*(ptr+len) != ',' && *(ptr+len) != 0
X		    && *(ptr+len) != ' ')) {
X	          sig = remote_signature;
X                  break;
X                }
X              }
X              if (sig == local_signature)		   /* still local? */ 
X                for (ptr = index(expanded_cc,'@'); ptr;   /* check Cc: */
X		    ptr = index(ptr+1,'@')) {
X		  if (strncmp(ptr,sitename,len) != 0
X		      || (*(ptr+len) != ',' && *(ptr+len) != 0 
X		      && *(ptr+len) != ' ')) {
X	            sig = remote_signature;
X                    break;
X                  }
X                }
X            }
X
X            if (sig[0]) {  /* if there is a signature file */
X	      if (sig_dashes) /* dashes are optional */
X	        fprintf(file, "\n-- \n");  /* News 2.11 compatibility? */
X	      if (sig[0] != '/')
X	        sprintf(filename2, "%s/%s", home, sig);
X	      else
X	        strcpy(filename2, sig);
X	      (void) append(file, filename2);
X
X              return TRUE;
X            }
X          }
X
Xreturn FALSE;
X
X}
SHAR_EOF
echo "File src/mailmsg2.c is complete"
chmod 0444 src/mailmsg2.c || echo "restore of src/mailmsg2.c fails"
echo "x - extracting src/mailtime.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > src/mailtime.c &&
X
Xstatic char rcsid[] = "@(#)$Id: mailtime.c,v 4.1 90/04/28 22:43:31 syd Exp $";
X
X/*******************************************************************************
X *  The Elm Mail System  -  $Revision: 4.1 $   $State: Exp $
X *
X * 			Copyright (c) 1986, 1987 Dave Taylor
X * 			Copyright (c) 1988, 1989, 1990 USENET Community Trust
X *******************************************************************************
X * Bug reports, patches, comments, suggestions should be sent to:
X *
X *	Syd Weinstein, Elm Coordinator
X *	elm@DSI.COM			dsinc!elm
X *
X *******************************************************************************
X * $Log:	mailtime.c,v $
X * Revision 4.1  90/04/28  22:43:31  syd
X * checkin of Elm 2.3 as of Release PL0
X * 
X *
X ******************************************************************************/
X
X/** This set of routines is used to figure out when the user last read
X    their mail and to also figure out if a given message is new or not.
X
X**/
X
X#include "headers.h"
X
X#include <sys/types.h>
X#include <sys/stat.h>
X#ifdef I_TIME
X#  include <time.h>
X#endif
X#ifdef I_SYSTIME
X#  include <sys/time.h>
X#endif
X
Xresolve_received(entry)
Xstruct header_rec *entry;
X{
X	/** Entry has the data for computing the time and date the 
X	    message was received.  Fix it and return **/
X
X	switch (tolower(entry->month[0])) {
X	  case 'j' : if (tolower(entry->month[1]) == 'a')
X		       entry->received.month = JANUARY;
X		     else if (tolower(entry->month[2]) == 'n')
X	               entry->received.month = JUNE;
X		     else
X	               entry->received.month = JULY;
X	             break;
X	  case 'f' : entry->received.month = FEBRUARY;
X	 	     break;
X	  case 'm' : if (tolower(entry->month[2]) == 'r')
X	               entry->received.month = MARCH;
X		     else
X		       entry->received.month = MAY;
X	             break;
X	  case 'a' : if (tolower(entry->month[1]) == 'p')
X	               entry->received.month = APRIL;
X	             else
X	               entry->received.month = AUGUST;
X		     break;
X	  case 's' : entry->received.month = SEPTEMBER;
X		     break;
X	  case 'o' : entry->received.month = OCTOBER;
X		     break;
X	  case 'n' : entry->received.month = NOVEMBER;
X	  	     break;
X	  case 'd' : entry->received.month = DECEMBER;
X		     break;
X	}
X
X	sscanf(entry->day, "%d", &(entry->received.day));
X
X	sscanf(entry->year, "%d", &(entry->received.year));
X	if (entry->received.year > 100) entry->received.year -= 1900;
X
X	sscanf(entry->time, "%d:%d", &(entry->received.hour),
X	       &(entry->received.minute));
X}
SHAR_EOF
chmod 0444 src/mailtime.c || echo "restore of src/mailtime.c fails"
echo "x - extracting src/mkhdrs.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > src/mkhdrs.c &&
X
Xstatic char rcsid[] = "@(#)$Id: mkhdrs.c,v 4.1 90/04/28 22:43:32 syd Exp $";
X
X/*******************************************************************************
X *  The Elm Mail System  -  $Revision: 4.1 $   $State: Exp $
X *
X * 			Copyright (c) 1986, 1987 Dave Taylor
X * 			Copyright (c) 1988, 1989, 1990 USENET Community Trust
X *******************************************************************************
X * Bug reports, patches, comments, suggestions should be sent to:
X *
X *	Syd Weinstein, Elm Coordinator
X *	elm@DSI.COM			dsinc!elm
X *
X *******************************************************************************
X * $Log:	mkhdrs.c,v $
X * Revision 4.1  90/04/28  22:43:32  syd
X * checkin of Elm 2.3 as of Release PL0
X * 
X *
X ******************************************************************************/
X
X/** This contains all the header generating routines for the ELM
X    program.
X
X**/
X
X#include "headers.h"
X
Xextern char in_reply_to[SLEN];
X
Xchar *strcpy();
Xunsigned long sleep();
X
Xgenerate_reply_to(msg)
Xint msg;
X{
X	/** Generate an 'in-reply-to' message... **/
X	char buffer[SLEN];
X
X
X	if (msg == -1)		/* not a reply! */
X	  in_reply_to[0] = '\0';
X	else {
X	  if (chloc(headers[msg]->from, '!') != -1)
X	    tail_of(headers[msg]->from, buffer, 0);
X	  else
X	    strcpy(buffer, headers[msg]->from);
X	  sprintf(in_reply_to, "%s; from \"%s\" at %s %s, %s %s",
X                  headers[msg]->messageid[0] == '\0'? "<no.id>":
X		  headers[msg]->messageid,
X		  buffer,
X		  headers[msg]->month,
X		  headers[msg]->day,
X		  headers[msg]->year,
X		  headers[msg]->time);
X	}
X}
X
Xadd_mailheaders(filedesc)
XFILE *filedesc;
X{
X	/** Add the users .mailheaders file if available.  Allow backquoting 
X	    in the file, too, for fortunes, etc...*shudder*
X	**/
X
X	FILE *fd;
X	char filename[SLEN], buffer[SLEN];
X
X	sprintf(filename, "%s/%s", home, mailheaders);
X
X	if ((fd = fopen(filename, "r")) != NULL) {
X	  while (fgets(buffer, SLEN, fd) != NULL)
X	    if (strlen(buffer) < 2) {
X	      dprint(2, (debugfile,
X	         "Strlen of line from .elmheaders is < 2 (write_header_info)"));
X	      error1("Warning: blank line in %s ignored!", filename);
X	      sleep(2);
X	    }
X	    else if (occurances_of(BACKQUOTE, buffer) >= 2) 
X	      expand_backquote(buffer, filedesc);
X	    else 
X	      fprintf(filedesc, "%s", buffer);
X
X	    fclose(fd);
X	}
X}
X
Xexpand_backquote(buffer, filedesc)
Xchar *buffer;
XFILE *filedesc;
X{
X	/** This routine is called with a line of the form:
X		Fieldname: `command`
X	    and is expanded accordingly..
X	**/
X
X	FILE *fd;
X	char command[SLEN], command_buffer[SLEN], fname[SLEN],
X	     prefix[SLEN];
X	register int i, j = 0;
X
X	for (i=0; buffer[i] != BACKQUOTE; i++)
X	  prefix[j++] = buffer[i];
X	prefix[j] = '\0';
X
X	j = 0;
X
X	for (i=chloc(buffer, BACKQUOTE)+1; buffer[i] != BACKQUOTE;i++)
X	  command[j++] = buffer[i];
X	command[j] = '\0';
X
X	sprintf(fname,"%s%s%d", temp_dir, temp_print, getpid());
X
X	sprintf(command_buffer, "%s > %s", command, fname);
X
X	system_call(command_buffer, SH, FALSE, FALSE);
X
X	if ((fd = fopen(fname, "r")) == NULL) {
X	  error1("Backquoted command \"%s\" in elmheaders failed.", command);
X	  return;	
X	}
X
X	/* If we get a line that is less than 80 - length of prefix then we
X	   can toss it on the same line, otherwise, simply prepend each line
X	   *starting with this line* with a leading tab and cruise along */
X
X	if (fgets(command_buffer, SLEN, fd) == NULL) 
X	  fprintf(filedesc, prefix);
X	else {
X	  if (strlen(command_buffer) + strlen(prefix) < 80) 
X	    fprintf(filedesc, "%s%s", prefix, command_buffer);
X	  else
X	    fprintf(filedesc, "%s\n\t%s", prefix, command_buffer);
X	  
X	  while (fgets(command_buffer, SLEN, fd) != NULL) 
X	    fprintf(filedesc, "\t%s", command_buffer);
X	
X	  fclose(fd);
X	}
X
X	unlink(fname);	/* don't leave the temp file laying around! */
X}
SHAR_EOF
chmod 0444 src/mkhdrs.c || echo "restore of src/mkhdrs.c fails"
echo "x - extracting src/newmbox.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > src/newmbox.c &&
X
Xstatic char rcsid[] = "@(#)$Id: newmbox.c,v 4.1 90/04/28 22:43:34 syd Exp $";
X
X/*******************************************************************************
X *  The Elm Mail System  -  $Revision: 4.1 $   $State: Exp $
X *
X * 			Copyright (c) 1988, USENET Community Trust
X * 			Copyright (c) 1988, 1989, 1990 USENET Community Trust
X *******************************************************************************
X * Bug reports, patches, comments, suggestions should be sent to:
X *
X *	Syd Weinstein, Elm Coordinator
X *	elm@DSI.COM			dsinc!elm
X *
X *******************************************************************************
X * $Log:	newmbox.c,v $
X * Revision 4.1  90/04/28  22:43:34  syd
X * checkin of Elm 2.3 as of Release PL0
X * 
X *
X ******************************************************************************/
X
X/**  read new folder **/
X
X#include <ctype.h>
X#include "headers.h"
X
X#ifdef BSD
X#undef tolower		/* we have our own "tolower" routine instead! */
X#endif
X
X#include <sys/types.h>		
X#include <sys/stat.h>
X#include <errno.h>
X
X#ifdef I_TIME
X#  include <time.h>
X#endif
X#ifdef I_SYSTIME
X#  include <sys/time.h>
X#endif
X
Xextern int errno;
X
Xchar *error_name(), *error_description();
Xchar *malloc(), *realloc(), *strcpy(), *strncpy(), *rindex(), *index();
Xunsigned long sleep();
Xvoid rewind();
Xvoid exit();
Xlong bytes();
X
Xint
Xnewmbox(new_file, adds_only)
Xchar *new_file;
Xint adds_only;
X{
X	/** Read a folder.
X
X	    new_file	- name of folder  to read. It is up to the calling
X			  function to make sure that the file can be
X			  read by the user. This is not checked in this
X			  function. The reason why it is not checked here
X			  is due to the situation where the user wants to
X			  change folders: the new folder must be checked
X			  for access *before* leaving the old one, which
X			  is before this function gets called.
X	    adds_only	- set if we only want to read newly added messages to
X				same old folder.
X
X	**/
X
X	int  same_file;
X	int  new_folder_type;
X	int err;
X	char new_tempfile[SLEN];
X
X	/* determine type of new mailfile and calculate temp file name */
X	if((new_folder_type = get_folder_type(new_file)) == SPOOL)
X	  mk_temp_mail_fn(new_tempfile, new_file);
X	else
X	  *new_tempfile = '\0';
X
X	/* determine whether we are changing files */
X	same_file = !(strcmp(new_file, cur_folder));
X
X	/* If we are changing files and we are changing to a spool file,
X	 * make sure there isn't a temp file for it, because if
X	 * there is, someone else is using ELM to read the new file,
X	 * and we don't want to be reading it at the same time.
X	 */
X	if((new_folder_type == SPOOL) && (!same_file)) {
X	  if (access(new_tempfile, ACCESS_EXISTS) != -1) {
X	    if(folder_type != NO_NAME) ClearScreen();
X	    Centerline(15,
X	      "Hey! An instantiation of ELM is already reading this mail!");
X	    Centerline(17,
X	      "If this is in error, then you'll need to save a copy of the");
X	    Centerline(18, "the following file then remove it:");
X	    Centerline(19, new_tempfile);
X	    MoveCursor(LINES, 0);  /* so shell prompt upon exit is on newline */
X	    silently_exit();
X	  }
X	}
X
X	/* If we were reading a spool file and we are not just reading
X	 * in the additional new messages to the same file, we need to
X	 * remove the corresponding tempfile.
X	 */
X
X	if((folder_type == SPOOL) && !adds_only) {
X	  if (access(cur_tempfolder, ACCESS_EXISTS) != -1) {
X	    if (unlink(cur_tempfolder) != 0) {
X	      error2("Sorry, can't unlink the temp file %s [%s]!\n\r",
X	        cur_tempfolder, error_name(errno));
X	      silently_exit();
X	    }
X	  }
X	}
X
X	/* Okay! Now establish this new file as THE file */
X	strcpy(cur_folder, new_file);
X	folder_type = new_folder_type;
X	strcpy(cur_tempfolder, new_tempfile);
X
X	clear_error();
X	clear_central_message();
X
X	if (mailfile != NULL)
X	  (void) fclose(mailfile);  /* close it first, to avoid too many open */
X
X	if ((mailfile = fopen(cur_folder,"r")) == NULL)  {
X	  if (errno != ENOENT ) { /* error on anything but file not exist */
X	    err = errno;
X	    Write_to_screen("\n\rfail on open in newmbox, open %s failed!!\n\r", 1,
X		    cur_folder);
X	    Write_to_screen("** %s - %s. **\n\r", 2,
X		    error_name(err), error_description(err));
X	    dprint(1, (debugfile, "fail on open in newbox, file %s!!\n",
X		    cur_folder));
X	    rm_temps_exit();
X	  }
X	  else {
X	    mailfile_size = 0;         /* must non-existant folder */
X	    message_count = 0;
X	    selected = 0;
X	  }
X	} else {                          /* folder exists, read headers */
X	  read_headers(adds_only);
X	}
X
X	if(!same_file)		/* limit mode off if this is a new file */
X	  selected = 0;
X	if (!adds_only)		/* limit mode off if recreating headers */
X	  selected = 0;		/* because we loose the 'Visible' flag */
X
X	dprint(1, (debugfile,
X	  "New folder %s type %s temp file %s (%s)\n", cur_folder, 
X	  (folder_type == SPOOL ? "spool" : "non-spool"),
X	  (*cur_tempfolder ? cur_tempfolder : "none"), "newmbox"));
X
X	return(0);
X}
X
Xint
Xget_folder_type(filename)
Xchar *filename;
X{
X	/** returns the type of mailfile filename is
X	    NO_NAME = no name
X	    SPOOL = consisting only of mailhome plus base file name
X		    (no intervening directory name)
X	    NON_SPOOL = a name that is not SPOOL type above
X	 **/
X
X	char *last_slash;
X
X	/* if filename is null or is of zero length */
X	if((filename == NULL) || (*filename == '\0'))
X	  return(NO_NAME);
X
X	/* if filename begins with mailhome,
X	 * and there is a slash in filename,
X	 * and there is a filename after it (i.e. last slash is not last char),
X	 * and the last character of mailhome is last slash in filename,
X	 * it's a spool file .
X	 */
X	if((first_word(filename, mailhome)) &&
X	  ((last_slash = rindex(filename, '/')) != NULL) &&
X	  (*(last_slash+1) != '\0') &&
X	  (filename + strlen(mailhome) - 1 == last_slash))
X	    return(SPOOL);
X	/* if file name == default mailbox, its a spool file also
X	 * even if its not in the spool directory. (SVR4)
X	 */
X	if (strcmp(filename, defaultfile) == 0)
X	    return(SPOOL);
X
X	return(NON_SPOOL);
X}
X
Xmk_temp_mail_fn(tempfn, mbox)
Xchar *tempfn, *mbox;
X{
X	/** create in tempfn the name of the temp file corresponding to
X	    mailfile mbox. Mbox is presumed to be a file in mailhome;
X	    Strangeness may result if it is not!
X	 **/
X
X	char *cp;
X
X	sprintf(tempfn, "%s%s", default_temp, temp_mbox);
X	if((cp = rindex(mbox, '/')) != NULL) {
X	  cp++;
X	  if (strcmp(cp, "mbox") == 0 || strcmp(cp, "mailbox") == 0 ||
X		*cp == '.')
X	    strcat(tempfn, username);
X	  else
X	    strcat(tempfn, cp);
X	}
X}
X
Xint
Xread_headers(add_new_only)
Xint add_new_only;
X{
X	/** Reads the headers into the headers[] array and leaves the
X	    file rewound for further I/O requests.   If the file being
X	    read is a mail spool file (ie incoming) then it is copied to
X	    a temp file and closed, to allow more mail to arrive during 
X	    the elm session.  If 'add_new_only' is set, the program will copy
X	    the status flags from the previous data structure to the new 
X	    one if possible and only read in newly added messages.
X	**/
X
X	FILE *temp;
X	struct header_rec *current_header = NULL;
X	char buffer[LONG_STRING], *c;
X	long fbytes = 0L, line_bytes = 0L;
X	register int line = 0, count = 0, another_count,
X	  subj = 0, copyit = 0, in_header = 0;
X	int count_x, count_y = 17, err;
X	int in_to_list = FALSE, forwarding_mail = FALSE, first_line = TRUE;
X
X	static int first_read = 0;
X#ifdef MMDF
X        int newheader = 0;
X#endif /* MMDF */
X
X	if (folder_type == SPOOL) {
X	  lock(INCOMING);	/* ensure no mail arrives while we do this! */
X	  if (! add_new_only) {
X	    if (access(cur_tempfolder, ACCESS_EXISTS) != -1) {
X	      /* Hey!  What the hell is this?  The temp file already exists? */
X	      /* Looks like a potential clash of processes on the same file! */
X	      unlock();				     /* so remove lock file! */
X	      error("What's this?  The temp folder already exists??");
X	      sleep(2);
X	      error("Ahhhh... I give up.");
X	      silently_exit();	/* leave without tampering with it! */
X	    }
X	    if ((temp = fopen(cur_tempfolder,"w")) == NULL) {
X	     err = errno;
X	     unlock();	/* remove lock file! */
X	     Raw(OFF);
X	     Write_to_screen(
X		     "\n\rCouldn't open file %s for use as temp file.\n\r",
X		     1, cur_tempfolder);
X	     Write_to_screen("** %s - %s. **\n\r", 2,
X		     error_name(err), error_description(err));
X	     dprint(1, (debugfile,
X                "Error: Couldn't open file %s as temp mbox.  errno %s (%s)\n",
X	         cur_tempfolder, error_name(err), "read_headers"));
X	     rm_temps_exit();
X	    }
X	   copyit++;
X	   chown(cur_tempfolder, userid, groupid);
X	   chmod(cur_tempfolder, 0700);	/* shut off file for other people! */
X	 }
X	 else {
X	   if ((temp = fopen(cur_tempfolder,"a")) == NULL) {
X	     err = errno;
X	     unlock();	/* remove lock file! */
X	     Raw(OFF);
X	     Write_to_screen(
X		     "\n\rCouldn't reopen file %s for use as temp file.\n\r",
X		     1, cur_tempfolder);
X	     Write_to_screen("** %s - %s. **\n\r", 2,
X		     error_name(err), error_description(err));
X	     dprint(1, (debugfile, 
X                "Error: Couldn't reopen file %s as temp mbox.  errno %s (%s)\n",
X	         cur_tempfolder, error_name(err), "read_headers"));
X	     rm_temps_exit();
X	    }
X	   copyit++;
X	  }
X	}
X
X	if (! first_read++) {
X	  ClearLine(LINES-1);
X	  ClearLine(LINES);
X	  if (add_new_only)
X	    PutLine2(LINES, 0, "Reading in %s, message: %d", cur_folder, 
X		     message_count);
X	  else
X	    PutLine1(LINES, 0, "Reading in %s, message: 0", cur_folder);
X	  count_x = LINES;
X          count_y = 22 + strlen(cur_folder);
X	}
X	else {
X	  count_x = LINES-2;
X	  PutLine0(LINES-2, 0, "Reading message: 0");
X	}
X
X	if (add_new_only) {
X	   if (fseek(mailfile, mailfile_size, 0) == -1) {
X	     err = errno;
X	     Write_to_screen(
X		"\n\rCouldn't seek to %ld (end of folder) in %s!\n\r", 2,
X	     	mailfile_size, cur_folder);	
X	     Write_to_screen("** %s - %s. **\n\r", 2,
X		     error_name(err), error_description(err));
X	     dprint(1, (debugfile,
X     "Error: Couldn't seek to end of folder %s: (offset %ld) Errno %s (%s)\n",
X	        cur_folder, mailfile_size, error_name(err), "read_headers"));
X	     emergency_exit();
X	   }
X	   count = message_count;		/* next available  */
X	   fbytes = mailfile_size;		/* start correctly */
X	}
X
X	/** find the size of the folder then unlock the file **/
X
X	mailfile_size = bytes(cur_folder);
X	unlock();
X
X	/** now let's copy it all across accordingly... **/
X
X	while (fbytes < mailfile_size) {
X
X	  if (fgets(buffer, LONG_STRING, mailfile) == NULL) break;
X
X	  if (copyit)
X	    if (fputs(buffer, temp) == EOF) {
X		err = errno;
X		Write_to_screen("\n\rWrite to tempfile %s failed!!\n\r", 1,
X				cur_tempfolder);
X		Write_to_screen("** %s - %s. **\n\r", 2,
X				error_name(err), error_description(err));
X		dprint(1, (debugfile, "Can't write to tempfile %s!!\n",
X			   cur_tempfolder));
X		rm_temps_exit();
X	    }
X	  line_bytes = (long) strlen(buffer); 
X
X	  /* Fix below to increment line count ONLY if we got a full line.
X	   * Input lines longer than the fgets buffer size would
X	   * get counted each time a subsequent part of them was
X	   * read in. This meant that when the faulty line count was used
X	   * to display the message, part of the next message
X	   * was displayed at the end of the message.
X	   */
X	  if(buffer[strlen(buffer)-1] == '\n') line++;
X
X	  if (fbytes == 0L || first_line) { 	/* first line of file... */	
X	    if (folder_type == SPOOL) {
X	      if (first_word(buffer, "Forward to ")) {
X	        set_central_message("Mail being forwarded to %s", 
X                   (char *) (buffer + 11));
X	        forwarding_mail = TRUE;
X	      }
X	    }
X
X	    /** flush leading blank lines before next test... **/
X	    if (strlen(buffer) == 1) {
X	      fbytes++;
X	      continue;	
X	    }
X	    else
X	      first_line = FALSE;
X	      	
X#ifdef MMDF
X	    if (!forwarding_mail && strcmp(buffer, MSG_SEPERATOR) != 0 ) {
X#else
X	    if (! first_word(buffer, "From ") && !forwarding_mail) {
X#endif /* MMDF */
X	      PutLine0(LINES, 0,
X		  "\n\rFolder is corrupt!!  I can't read it!!\n\r\n\r");
X	      fflush(stderr);
X	      dprint(1, (debugfile, 
X			   "\n\n**** First mail header is corrupt!! ****\n\n"));
X	      dprint(1, (debugfile, "Line is;\n\t%s\n\n", buffer));
X              mail_only++;	/* to avoid leave() cursor motion */
X              leave();
X	    }
X	  }
X
X#ifdef MMDF
X	  if (strcmp(buffer, MSG_SEPERATOR) == 0) {
X            newheader = !newheader;
X#else
X	  if (first_word(buffer,"From ")) {
X#endif /* MMDF */
X	    /** allocate new header pointers, if needed... **/
X
X	    if (count >= max_headers) {
X	      struct header_rec **new_headers;
X	      int new_max;
X
X	      new_max = max_headers + KLICK;
X	      if (max_headers == 0) {
X		new_headers = (struct header_rec **)
X		  malloc(new_max * sizeof(struct header_rec *));
X	      }
X	      else {
X		new_headers = (struct header_rec **)
X		  realloc(headers, new_max * sizeof(struct header_rec *));
X	      }
X	      if (new_headers == NULL) {
X	        error1(
X      "\n\r\n\rCouldn't allocate enough memory! Message #%d.\n\r\n\r",
X			count);
X	        leave();
X	      }
X	      headers = new_headers;
X	      while (max_headers < new_max)
X		headers[max_headers++] = NULL;
X	    }
X	      
X	    /** allocate new header structure, if needed... **/
X
X	    if (headers[count] == NULL) {
X	      struct header_rec *h;
X
X	      if ((h = (struct header_rec *)
X			malloc(sizeof(struct header_rec))) == NULL) {
X	        error1(
X      "\n\r\n\rCouldn't allocate enough memory! Message #%d.\n\r\n\r",
X			count);
X	        leave();
X	      }
X	      headers[count] = h;
X	    }
X
X	    if (real_from(buffer, headers[count])) {
X	      current_header = headers[count];
X
X	      current_header->offset = (long) fbytes;
X	      current_header->index_number = count+1;
X	      /* set default status - always 'visible'  - and
X	       * if a spool file, presume 'new', otherwise
X	       * 'read', for the time being until overridden
X	       * by a Status: header.
X	       * We presume 'read' for nonspool mailfile messages
X	       * to be compatible messages stored with older versions of elm,
X	       * which didn't support a Status: header.
X	       */
X	      if(folder_type == SPOOL)
X		current_header->status = VISIBLE | NEW | UNREAD;
X	      else
X		current_header->status = VISIBLE;
X
X	      strcpy(current_header->subject, "");	/* clear subj    */
X	      strcpy(current_header->to, "");		/* clear to    */
X	      strcpy(current_header->mailx_status, "");	/* clear status flags */
X	      strcpy(current_header->messageid, "<no.id>"); /* set no id into message id */
X	      current_header->encrypted = 0;		/* clear encrypted */
X	      current_header->exit_disposition = UNSET;
X	      current_header->status_chgd = FALSE;
X
X	      /* Set the number of lines for the _preceding_ message,
X	       * but only if there was a preceding message and
X	       * only if it wasn't calculated already. It would
X	       * have been calculated already if we are only
X	       * reading headers of new messages that have just arrived,
X	       * and the preceding message was one of the old ones.
X	       */
X	      if ((count) && (!add_new_only || count > message_count))
X	        headers[count-1]->lines = line;
X
X	      count++;
X	      subj = 0;
X	      line = 0;
X	      in_header = 1;
X	      PutLine1(count_x, count_y, "%d", count);
X#ifdef MMDF
X	    } else if (newheader) {
X	      current_header = headers[count];
X
X	      current_header->offset = (long) fbytes;
X	      current_header->index_number = count+1;
X
X	      /* set default status - always 'visible'  - and
X	       * if a spool file, presume 'new', otherwise
X	       * 'read', for the time being until overridden
X	       * by a Status: header.
X	       * We presume 'read' for nonspool mailfile messages
X	       * to be compatible messages stored with older versions of elm,
X	       * which didn't support a Status: header.
X	       */
X	      if(folder_type == SPOOL)
X		current_header->status = VISIBLE | NEW | UNREAD;
X	      else
X		current_header->status = VISIBLE;
X
X	      strcpy(current_header->from, "");		/* clear from    */
X	      strcpy(current_header->dayname, "");	/* clear dayname */
X	      strcpy(current_header->month, "");	/* clear month   */
X	      strcpy(current_header->day, "");		/* clear day     */
X	      strcpy(current_header->time, "");		/* clear time    */
X	      strcpy(current_header->year, "");		/* clear year    */
X	      strcpy(current_header->subject, "");	/* clear subj    */
X	      strcpy(current_header->to, "");		/* clear to    */
X	      strcpy(current_header->mailx_status, "");	/* clear status flags */
X	      strcpy(current_header->messageid, "<no.id>"); /* set no id into message id */
X	      current_header->encrypted = 0;		/* clear encrypted */
X	      current_header->exit_disposition = UNSET;
X	      current_header->status_chgd = FALSE;
X
X	      /* Set the number of lines for the _preceding_ message,
X	       * but only if there was a preceding message and
X	       * only if it wasn't calculated already. It would
X	       * have been calculated already if we are only
X	       * reading headers of new messages that have just arrived,
X	       * and the preceding message was one of the old ones.
X	       */
X	      if ((count) && (!add_new_only || count > message_count))
X	        headers[count-1]->lines = line;
X
X	      count++;
X	      subj = 0;
X	      line = 0;
X	      in_header = 1;
X	      PutLine1(count_x, count_y, "%d", count);
X	      dprint(1, (debugfile, 
X			   "\n\n**** Added header record ****\n\n"));
X#endif /* MMDF */
X	    } else if (count == 0) {
X	      /* if this is the first "From" in file but the "From" line is
X	       * not of the proper format, we've got a corrupt folder.
X	       */
X	      PutLine0(LINES, 0,
X		  "\n\rFolder is corrupt!!  I can't read it!!\n\r\n\r");
X	      fflush(stderr);
X	      dprint(1, (debugfile, 
X			   "\n\n**** First mail header is corrupt!! ****\n\n"));
X	      dprint(1, (debugfile, "Line is;\n\t%s\n\n", buffer));
X              mail_only++;	/* to avoid leave() cursor motion */
X              leave();
X	    }
X	  }
X	  else if (in_header) {
X#ifdef MMDF
X	    if (first_word(buffer,"From "))
X	      real_from(buffer, current_header);
X#endif /* MMDF */
X	    if (first_word(buffer,">From:"))
X	      parse_arpa_who(buffer, current_header->from, FALSE);
X	    else if (first_word(buffer,">From")) 
X	      forwarded(buffer, current_header); /* return address */
X	    else if (first_word(buffer,"Subject:") ||
X		     first_word(buffer,"Subj:") ||
X		     first_word(buffer,"Re:")) {
X	      if (! subj++) {
X	        remove_first_word(buffer);
X	        copy_sans_escape(current_header->subject, buffer, STRING);
X		remove_possible_trailing_spaces(current_header->subject);
X	      }
X	    }
X	    else if (first_word(buffer,"From:")) {
X#ifdef MMDF
X	      parse_arpa_who(buffer, current_header->from, TRUE);
X	      dprint(1, (debugfile, 
X			   "\n\n**** Calling parse_arpa_who for from ****\n\n"));
X#else
X	      parse_arpa_who(buffer, current_header->from, FALSE);
X#endif /* MMDF */
X
X	    }
X	    else if (first_word(buffer, "Message-Id:") ||
X		     first_word(buffer, "Message-ID:")) {
X	      buffer[strlen(buffer)-1] = '\0';
X	      strcpy(current_header->messageid,
X		     (char *) buffer + 12);
X	    }
X
X	    else if (first_word(buffer, "Expires:"))
X	      process_expiration_date((char *) buffer + 9, 
X				      &(current_header->status));
X	    
X	    /** when it was sent... **/
X
X	    else if (first_word(buffer, "Date:")) {
X	      dprint(1, (debugfile, 
X			   "\n\n**** Calling parse_arpa_date ****\n\n"));
X	      remove_first_word(buffer);
X	      parse_arpa_date(buffer, current_header);
X	    }
X
X	    /** some status things about the message... **/
X
X	    else if (first_word(buffer, "Priority:") || 
X		     first_word(buffer, "Importance: 2"))
X	      current_header->status |= URGENT;
X	    else if (first_word(buffer, "Sensitivity: 2"))
X	      current_header->status |= PRIVATE;
X	    else if (first_word(buffer, "Sensitivity: 3"))
X	      current_header->status |= CONFIDENTIAL;
X	    else if (first_word(buffer, "Content-Type: mailform"))
X	      current_header->status |= FORM_LETTER;
X	    else if (first_word(buffer, "Action:"))
X	      current_header->status |= ACTION;
X
X	    /** next let's see if it's to us or not... **/
X
X	    else if (first_word(buffer, "To:")) {
X	      in_to_list = TRUE;
X	      current_header->to[0] = '\0';	/* nothing yet */
X	      figure_out_addressee((char *) buffer +3, 
X				   current_header->to);
X	    }
X	    else if (first_word(buffer, "Status:")) {
X	      remove_first_word(buffer);
X	      strncpy(current_header->mailx_status, buffer, WLEN-1);
X	      current_header->mailx_status[WLEN-1] ='\0';
X
X	      c = index(current_header->mailx_status, '\n');
X	      if (c != NULL)
X		*c = '\0';
X	      remove_possible_trailing_spaces(current_header->mailx_status);
X
X	      /* Okay readjust the status. If there's an 'R', message
X	       * is read; if there is no 'R' but there is an 'O', message
X	       * is unread. In any case it isn't new because a new message
X	       * wouldn't have a Status: header.
X	       */
X	      if (index(current_header->mailx_status, 'R') != NULL)
X		current_header->status &= ~(NEW | UNREAD);
X	      else if (index(current_header->mailx_status, 'O') != NULL) {
X		current_header->status &= ~NEW;
X		current_header->status |= UNREAD;
X	      }
X	    }
X
X	    else if (buffer[0] == LINE_FEED || buffer[0] == '\0') {
X	      if (in_header) {
X	        in_header = 0;	/* in body of message! */
X	        fix_date(current_header);
X	      }
X	    }
X	    else if (in_header) {
X	       if ((!whitespace(buffer[0])) && index(buffer, ':') == NULL) {
X	        in_header = 0;	/* in body of message! */
X	        fix_date(current_header);
X	      }
X	    }
X	    else if (in_to_list == TRUE) {
X	      if (whitespace(buffer[0]))
X	        figure_out_addressee(buffer, current_header->to);
SHAR_EOF
echo "End of part 18"
echo "File src/newmbox.c is continued in part 19"
echo "19" > s2_seq_.tmp
exit 0

exit 0 # Just in case...
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.