[comp.sources.bugs] Mush 6.4 to 6.5 Patch Kit, Part 2 of 6

schaefer@ogccse.ogc.edu (Barton E. Schaefer) (04/29/89)

Part 2 of the Mush 6.5 Upgrade Kit.  Read the instructions in part 1.
---------------------------------------------------------------------------
Prereq: Part1
*** mush-6.4/kit.check	Tue Apr 18 17:29:04 1989
--- kit.check	Tue Apr 18 17:29:04 1989
***************
*** 1 ****
!  Part1 
--- 1 ----
!  Part1-check 
*** mush-6.4/mail.c	Fri Mar 24 10:15:22 1989
--- mail.c	Thu Apr 13 16:52:40 1989
***************
*** 11,17 ****
   *    add_to_letter()	adds the next line to letter --determine ~ escapes.
   *    finish_up_letter()  prompts for Cc:, verifies user really wants to send
   *    send_it()		invokes mailer, sends to record file, expands aliases,
!  *			adds own_hdrs.
   *    rm_edfile()	signals are directed here. remove letter, longjmp
   *
   * The flow of control in this file is NOT obvious to allow for both text
--- 11,17 ----
   *    add_to_letter()	adds the next line to letter --determine ~ escapes.
   *    finish_up_letter()  prompts for Cc:, verifies user really wants to send
   *    send_it()		invokes mailer, sends to record file, expands aliases,
!  *    add_headers()	adds all headers to a FILE *
   *    rm_edfile()	signals are directed here. remove letter, longjmp
   *
   * The flow of control in this file is NOT obvious to allow for both text
***************
*** 32,38 ****
  static int killme;
  static u_long flags;
  static SIGRET (*oldterm)(), (*oldint)(), (*oldquit)();
! static void send_it();
  static jmp_buf cntrl_c_buf;
  FILE *ed_fp;
  char *edfile;
--- 32,39 ----
  static int killme;
  static u_long flags;
  static SIGRET (*oldterm)(), (*oldint)(), (*oldquit)();
! static int send_it();
! static long add_headers();
  static jmp_buf cntrl_c_buf;
  FILE *ed_fp;
  char *edfile;
***************
*** 184,196 ****
  		}
  		to += Strcpy(to, buf);
  		if (firstchar == 'R') {
! 		    if (pcc) /* if there was a previous cc, append ", " */
! 			*cc++ = ',', *cc++ = ' ';
! 		    if (pcc = cc_to(n, buf))
  			if (strlen(pcc) + (cc - Cc) > sizeof(Cc) - 1)
  			    print("# Cc's exceeded at msg %d\n", n);
  			else
  			    cc += Strcpy(cc, pcc);
  		}
  		/* remove redundant addresses now, or headers could get too
  		 * long before the list runs out (it still might)
--- 185,199 ----
  		}
  		to += Strcpy(to, buf);
  		if (firstchar == 'R') {
! 		    if (pcc = cc_to(n, buf)) {
! 			/* if there was a previous cc, append ", " */
! 			if (cc != Cc)
! 			    *cc++ = ',', *cc++ = ' ';
  			if (strlen(pcc) + (cc - Cc) > sizeof(Cc) - 1)
  			    print("# Cc's exceeded at msg %d\n", n);
  			else
  			    cc += Strcpy(cc, pcc);
+ 		    }
  		}
  		/* remove redundant addresses now, or headers could get too
  		 * long before the list runs out (it still might)
***************
*** 340,346 ****
  	    Bcc[0] = '\0';
  
      if (ison(glob_flags, REDIRECT)) {
! 	send_it(); /* doesn't return */
  	return 0;
      }
      /* if (!*to) then prompting will be done */
--- 343,349 ----
  	    Bcc[0] = '\0';
  
      if (ison(glob_flags, REDIRECT)) {
! 	(void) send_it();
  	return 0;
      }
      /* if (!*to) then prompting will be done */
***************
*** 418,423 ****
--- 421,433 ----
  	oldterm = signal(SIGTERM, rm_edfile);
      }
  
+     if ((isoff(flags, FORWARD) || ison(flags, EDIT)) &&
+ 	    do_set(set_options, "edit_hdrs")) {
+ 	turnon(flags, EDIT_HDRS);
+ 	if (add_headers(NULL, &ed_fp, 1, flags) == (long) -1)
+ 	    return -1;
+     }
+ 
      /* if flags call for it, include current message (with header?) */
      if (ison(flags, INCLUDE) || ison(flags,FORWARD) || ison(flags,INCLUDE_H)) {
  	long copy_flgs = 0, is_forw = ison(flags, FORWARD);
***************
*** 458,464 ****
  #endif /* SUNTOOL */
      }
      if (ison(glob_flags, WARNING)) {
! 	if (escape && !strncmp(escape, DEF_ESCAPE, 1))
  	    wprint("(escape character is set to `%c')\n", *escape);
  	if (wrapcolumn && wrapcolumn < 20)
  	    wprint("(warning: wrapping only %d columns from the left!)\n",
--- 468,474 ----
  #endif /* SUNTOOL */
      }
      if (ison(glob_flags, WARNING)) {
! 	if (escape && strncmp(escape, DEF_ESCAPE, 1))
  	    wprint("(escape character is set to `%c')\n", *escape);
  	if (wrapcolumn && wrapcolumn < 20)
  	    wprint("(warning: wrapping only %d columns from the left!)\n",
***************
*** 472,496 ****
  #endif /* SUNTOOL */
      /* do an "if" again in case editor not found and EDIT turned off */
  					ison(flags, EDIT)) {
! 	char *argv[3];
! 	if (!(argv[0] = do_set(set_options, "visual")) || !*argv[0])
! 	    argv[0] = DEF_EDITOR;
! 	argv[1] = edfile;
! 	argv[2] = NULL;
! 	print("Starting \"%s\"...\n", argv[0]);
! 	fclose(ed_fp);
! 	ed_fp = NULL_FILE;
! 	execute(argv);
! 	turnoff(flags, EDIT);
! 	turnoff(flags, FORWARD); /* forwarded messages must be unedited */
! 	/* upon exit of editor, user must now type ^D or "." to send */
! 	if (istool)
! 	    return 0;
! 	if (!(ed_fp = fopen(edfile, "r+"))) {
! 	    error("can't reopen %s", edfile);
! 	    return -1;
! 	}
! 	(void) fseek(ed_fp, 0L, 2);
  	puts("continue editing letter or ^D to send");
      } else if (ison(flags, FORWARD) &&
  #ifdef SUNTOOL
--- 482,510 ----
  #endif /* SUNTOOL */
      /* do an "if" again in case editor not found and EDIT turned off */
  					ison(flags, EDIT)) {
! 	char **argv, *edit;
! 	int argc;
! 	if (!(edit = do_set(set_options, "visual")) || !*edit)
! 	    edit = DEF_EDITOR;
! 	(void) sprintf(line, "%s %s", edit, edfile);
! 	if ((argv = mk_argv(line, &argc, FALSE)) && argc > 0) {
! 	    print("Starting \"%s\"...\n", argv[0]);
! 	    fclose(ed_fp);
! 	    ed_fp = NULL_FILE;
! 	    execute(argv);
! 	    free_vec(argv);
! 	    turnoff(flags, EDIT);
! 	    turnoff(flags, FORWARD); /* forwarded messages must be unedited */
! 	    /* upon exit of editor, user must now type ^D or "." to send */
! 	    if (istool)
! 		return 0;
! 	    if (!(ed_fp = fopen(edfile, "r+"))) {
! 		error("can't reopen %s", edfile);
! 		return -1;
! 	    }
! 	    (void) fseek(ed_fp, 0L, 2);
! 	} else
! 	    print("Unable to start \"%s\"\n", edit);
  	puts("continue editing letter or ^D to send");
      } else if (ison(flags, FORWARD) &&
  #ifdef SUNTOOL
***************
*** 554,559 ****
--- 568,574 ----
      ":cmd\t\tRun the mail command \"cmd\".",
      "u\t\tedit previous line in file.",
      "E[!]\t\tClear contents of letter after saving to dead.letter [unless !].",
+     "|cmd\t\tPipe the message through the unix command \"cmd\".",
      0
  };
  
***************
*** 625,631 ****
      p = &line[2];
      skipspaces(0);
      switch (line[1]) {
! 	case 'v' : case 'p': case 'e': {
  	    if (!*p || *p == 'i' && !p[1])
  		switch (line[1]) {
  		    case 'p' :
--- 640,646 ----
      p = &line[2];
      skipspaces(0);
      switch (line[1]) {
! 	case 'v' : case 'p': case 'e' : case '|' : {
  	    if (!*p || *p == 'i' && !p[1])
  		switch (line[1]) {
  		    case 'p' :
***************
*** 636,674 ****
  		    when 'v' :
  			if (p = do_set(set_options, "visual"))
  			    break;
  		    default :
  			if (!(p = do_set(set_options, "editor")) || !*p)
  			    p = DEF_EDITOR;
  		}
! 	    if (line[1] == 'p') {
  		rewind(ed_fp);
  		(void) do_pager(p, TRUE); /* start the pager "p" */
! 		do_pager(sprintf(buf, "To: %s\n", To), FALSE);
! 		if (Subject[0])
! 		    do_pager(sprintf(buf, "Subject: %s\n", Subject), FALSE);
! 		if (Cc[0])
! 		    do_pager(sprintf(buf, "Cc: %s\n", Cc), FALSE);
! 		if (Bcc[0])
! 		    do_pager(sprintf(buf, "Bcc: %s\n", Bcc), FALSE);
! 		do_pager(strcpy(buf, "--------\nMessage contains:\n"), FALSE);
  		while (fgets(buf, sizeof(buf), ed_fp))
  		    if (do_pager(buf, FALSE) == EOF)
  			break;
  		(void) do_pager(NULL, FALSE); /* end pager */
  	    } else {
! 		char *argv[3];
! 		argv[0] = p;
! 		argv[1] = edfile;
! 		argv[2] = NULL;
! 		fclose(ed_fp);
! 		ed_fp = NULL_FILE;
! 		execute(argv); /* tool will return even tho editor isn't done */
! 		if (istool)
! 		    return 1;
! 		if (!(ed_fp = fopen(edfile, "r+"))) {
! 		    error("can't reopen %s", edfile);
! 		    return -1;
! 		}
  	    }
  	}
  	when '$': {
--- 651,700 ----
  		    when 'v' :
  			if (p = do_set(set_options, "visual"))
  			    break;
+ 			/* else fall through */
  		    default :
  			if (!(p = do_set(set_options, "editor")) || !*p)
  			    p = DEF_EDITOR;
+ 		    when '|' :
+ 			wprint("No command for pipe\n");
+ 			return 1;
  		}
! 	    if (line[1] == 'p' || line[1] == '|') {
  		rewind(ed_fp);
  		(void) do_pager(p, TRUE); /* start the pager "p" */
! 		if (isoff(flags, EDIT_HDRS)) {
! 		    do_pager(sprintf(buf, "To: %s\n", To), FALSE);
! 		    if (Subject[0])
! 			do_pager(sprintf(buf, "Subject: %s\n", Subject), FALSE);
! 		    if (Cc[0])
! 			do_pager(sprintf(buf, "Cc: %s\n", Cc), FALSE);
! 		    if (Bcc[0])
! 			do_pager(sprintf(buf, "Bcc: %s\n", Bcc), FALSE);
! 		    do_pager(strcpy(buf, "--------\nMessage contains:\n"),
! 			FALSE);
! 		}
  		while (fgets(buf, sizeof(buf), ed_fp))
  		    if (do_pager(buf, FALSE) == EOF)
  			break;
  		(void) do_pager(NULL, FALSE); /* end pager */
  	    } else {
! 		char **argv;
! 		int argc;
! 		(void) sprintf(buf, "%s %s", p, edfile);
! 		if ((argv = mk_argv(buf, &argc, FALSE)) && argc > 0) {
! 		    fclose(ed_fp);
! 		    ed_fp = NULL_FILE;
! 		    execute(argv);
! 		    free_vec(argv);
! 		    /* tool will return even tho editor isn't done */
! 		    if (istool)
! 			return 1;
! 		    if (!(ed_fp = fopen(edfile, "r+"))) {
! 			error("can't reopen %s", edfile);
! 			return -1;
! 		    }
! 		} else
! 		    wprint("Unable to start \"%s\"\n", p);
  	    }
  	}
  	when '$': {
***************
*** 742,747 ****
--- 768,777 ----
  	    char *h = (line[1] == 't')? To : (line[1] == 'c')? Cc : Bcc;
  	    char *Prompt = line[1] == 't'? "To: " :
  			   line[1] == 'c'? "Cc: " : "Bcc: ";
+ 	    if (ison(flags, EDIT_HDRS)) {
+ 		wprint("You must use an editor to change your headers.\n");
+ 		break;
+ 	    }
  #ifdef SUNTOOL
  	    if (!*p && istool) {
  		turnon(get_hdr_field, CC_FIELD);
***************
*** 773,778 ****
--- 803,812 ----
  	    }
  	}
  	when 's':
+ 	    if (ison(flags, EDIT_HDRS)) {
+ 		wprint("You must use an editor to change your headers.\n");
+ 		break;
+ 	    }
  #ifdef SUNTOOL
  	    if (!*p && istool) {
  		turnon(get_hdr_field, SUBJECT);
***************
*** 788,793 ****
--- 822,831 ----
  		else
  		    (void) strcpy(Subject, p);
  	when 'h':
+ 	    if (ison(flags, EDIT_HDRS)) {
+ 		wprint("You must use an editor to change your headers.\n");
+ 		break;
+ 	    }
  #ifdef SUNTOOL
  	    if (istool) {
  		turnon(get_hdr_field, TO_FIELD);
***************
*** 913,918 ****
--- 951,960 ----
  	 }
  	/* break;  not here cuz of "return" (lint). */
  	case 'E':
+ 	    if (ison(flags, EDIT_HDRS)) {
+ 		wprint("You must use an editor to empty the message buffer.\n");
+ 		break;
+ 	    }
  	    if (*p != '!' && !do_set(set_options, "nosave"))
  		dead_letter();
  	    if (emptyfile(&ed_fp, edfile) == -1)
***************
*** 987,993 ****
  
      /* forwarded mail has no additional personalized text */
      if (ison(flags, FORWARD)) {
! 	send_it();
  	turnoff(glob_flags, IS_GETTING);
  	return 1;
      }
--- 1029,1035 ----
  
      /* forwarded mail has no additional personalized text */
      if (ison(flags, FORWARD)) {
! 	(void) send_it();
  	turnoff(glob_flags, IS_GETTING);
  	return 1;
      }
***************
*** 994,1008 ****
  
      if (isoff(glob_flags, REDIRECT)) {
  	if (!istool) {
! 	    if (do_set(set_options, "askcc")) {
  		if (p = set_header("Cc: ", Cc, 1))
  		    (void) strcpy(Cc, p);
  	    }
- #ifdef MMDF
- 	    /* Give some sort of indication that the end was seen */
- 	    else
- 		wprint("EOT\n");
- #endif /* MMDF */
  	}
  	/* ~v on the Cc line asks for verification, first initialize p! */
  	p = NULL;
--- 1036,1045 ----
  
      if (isoff(glob_flags, REDIRECT)) {
  	if (!istool) {
! 	    if (isoff(flags, EDIT_HDRS) && do_set(set_options, "askcc")) {
  		if (p = set_header("Cc: ", Cc, 1))
  		    (void) strcpy(Cc, p);
  	    }
  	}
  	/* ~v on the Cc line asks for verification, first initialize p! */
  	p = NULL;
***************
*** 1054,1060 ****
      if (istool)
  	lock_cursors();
  #endif /* SUNTOOL */
!     send_it();
      turnoff(glob_flags, IS_GETTING);
      return 1;
  }
--- 1091,1098 ----
      if (istool)
  	lock_cursors();
  #endif /* SUNTOOL */
!     if (!send_it())
! 	return 0;
      turnoff(glob_flags, IS_GETTING);
      return 1;
  }
***************
*** 1069,1075 ****
   * 6. copy the letter right into the array of file pointers (step 1).
   * 7. close the mailer and other files (step 1) and remove the edit-file.
   */
! static void
  send_it()
  {
      register char *p, *b, *addr_list;
--- 1107,1113 ----
   * 6. copy the letter right into the array of file pointers (step 1).
   * 7. close the mailer and other files (step 1) and remove the edit-file.
   */
! static int
  send_it()
  {
      register char *p, *b, *addr_list;
***************
*** 1076,1085 ****
--- 1114,1128 ----
  #ifdef MAXFILES
      register int size = MAXFILES - 1;
      FILE *files[MAXFILES];
+     char *names[MAXFILES];
  #else
      register int size = getdtablesize() - 1;
      FILE *files[30];  /* 30 should be sufficiently large enough */
+     char *names[30];
  #endif /* MAXFILES */
+ #ifdef VERBOSE_ARG
+     SIGRET (*oldchld)();
+ #endif /* VERBOSE_ARG */
      int next_file = 1; /* reserve files[0] for the mail delivery program */
      int log_file = -1; /* the index into the files array for mail logging */
      char buf[3*HDRSIZ];
***************
*** 1086,1091 ****
--- 1129,1164 ----
      char expand = !do_set(set_options, "no_expand");
      int fork_err = 0;
  
+     /* If edit_hdrs, make sure the correct headers exist and are intact
+      * before bothering to continue (return 0 to allow user to correct errors).
+      */
+     if (ison(flags, EDIT_HDRS)) {
+ 	/* fool header_field into thinking that the file is the folder */
+ 	FILE *save_tmpf = tmpf;
+ 	long old_offset = msg[msg_cnt].m_offset;
+ 	int err = 0;
+ 
+ 	tmpf = ed_fp;
+ 	msg[msg_cnt].m_offset = 0L;
+ 	if (!(p = header_field(msg_cnt, "to"))) {
+ 	    wprint("You must have a To: header to send mail.\n(continue)\n");
+ 	    err++;
+ 	} else {
+ 	    (void) strcpy(To, p);
+ 	    Cc[0] = Bcc[0] = 0;
+ 	    if (p = header_field(msg_cnt, "cc"))
+ 		(void) strcpy(Cc, p);
+ 	    if (p = header_field(msg_cnt, "bcc"))
+ 		(void) strcpy(Bcc, p);
+ 	    if (p = header_field(msg_cnt, "fcc"))
+ 		(void) strcat(Bcc, p);
+ 	}
+ 	msg[msg_cnt].m_offset = old_offset;
+ 	tmpf = save_tmpf;
+ 	if (err)
+ 	    return 0;
+     }
+ 
      if (!istool) {
  	(void) signal(SIGINT, oldint);
  	(void) signal(SIGQUIT, oldquit);
***************
*** 1096,1108 ****
  	p = MAIL_DELIVERY;
  
  #ifdef VERBOSE_ARG
!     if (ison(flags, VERBOSE) || do_set(set_options, "verbose"))
  #ifdef MMDF
  	b = &buf[strlen(sprintf(buf, "%s%s", p, VERBOSE_ARG))];
  #else /* MMDF */
  	b = &buf[strlen(sprintf(buf, "%s %s", p, VERBOSE_ARG))];
  #endif /* MMDF */
!     else
  #endif /* VERBOSE_ARG */
  	b = buf + Strcpy(buf, p);
  #ifdef METOO_ARG
--- 1169,1183 ----
  	p = MAIL_DELIVERY;
  
  #ifdef VERBOSE_ARG
!     if (ison(flags, VERBOSE) || do_set(set_options, "verbose")) {
! 	turnon(flags, VERBOSE); /* prevent fork when "verbose" has changed */
! 	oldchld = signal(SIGCHLD, SIG_DFL); /* let pclose() do the wait() */
  #ifdef MMDF
  	b = &buf[strlen(sprintf(buf, "%s%s", p, VERBOSE_ARG))];
  #else /* MMDF */
  	b = &buf[strlen(sprintf(buf, "%s %s", p, VERBOSE_ARG))];
  #endif /* MMDF */
!     } else
  #endif /* VERBOSE_ARG */
  	b = buf + Strcpy(buf, p);
  #ifdef METOO_ARG
***************
*** 1127,1143 ****
  	print("address expansion failed for To: line.\n");
  	rm_edfile(-1);
      } else {
! 	next_file += find_files(p, files+next_file, size - next_file);
  	if (expand)
  	    (void) strcpy(To, p);
  	rm_cmts_in_addr(p);
  	skipspaces(0);
  	if (!*p) {
! 	    print("There must be at least 1 legal recipient on the To line\n");
  	    while (--next_file > 0)
! 		fclose(files[next_file]);
  	    rm_edfile(-2);
! 	    return;
  	}
  	b += Strcpy(b, p);
      }
--- 1202,1223 ----
  	print("address expansion failed for To: line.\n");
  	rm_edfile(-1);
      } else {
! 	next_file +=
! 	    find_files(p, files+next_file, names+next_file, size-next_file);
  	if (expand)
  	    (void) strcpy(To, p);
  	rm_cmts_in_addr(p);
  	skipspaces(0);
  	if (!*p) {
! 	    print("There must be at least 1 legal recipient on the To line.\n");
  	    while (--next_file > 0)
! 		if (names[next_file]) {
! 		    close_lock(names[next_file], files[next_file]);
! 		    xfree(names[next_file]);
! 		} else
! 		    pclose(files[next_file]);
  	    rm_edfile(-2);
! 	    return 0;
  	}
  	b += Strcpy(b, p);
      }
***************
*** 1145,1154 ****
  	if (!(p = alias_to_address(Cc))) {
  	    print("address expansion failed for Cc: line.\n");
  	    while (--next_file > 0)
! 		fclose(files[next_file]);
  	    rm_edfile(-1);
  	} else {
! 	    next_file += find_files(p, files+next_file, size - next_file);
  	    if (expand)
  		(void) strcpy(Cc, p);
  	    rm_cmts_in_addr(p);
--- 1225,1239 ----
  	if (!(p = alias_to_address(Cc))) {
  	    print("address expansion failed for Cc: line.\n");
  	    while (--next_file > 0)
! 		if (names[next_file]) {
! 		    close_lock(names[next_file], files[next_file]);
! 		    xfree(names[next_file]);
! 		} else
! 		    pclose(files[next_file]);
  	    rm_edfile(-1);
  	} else {
! 	    next_file +=
! 	      find_files(p, files+next_file, names+next_file, size-next_file);
  	    if (expand)
  		(void) strcpy(Cc, p);
  	    rm_cmts_in_addr(p);
***************
*** 1171,1180 ****
  	if (!(p = alias_to_address(Bcc))) {
  	    print("address expansion failed for Bcc: line.\n");
  	    while (--next_file > 0)
! 		fclose(files[next_file]);
  	    rm_edfile(-1);
  	} else {
! 	    next_file += find_files(p, files+next_file, size - next_file);
  	    (void) strcpy(Bcc, p);
  	    rm_cmts_in_addr(p);
  	    skipspaces(0);
--- 1256,1270 ----
  	if (!(p = alias_to_address(Bcc))) {
  	    print("address expansion failed for Bcc: line.\n");
  	    while (--next_file > 0)
! 		if (names[next_file]) {
! 		    close_lock(names[next_file], files[next_file]);
! 		    xfree(names[next_file]);
! 		} else
! 		    pclose(files[next_file]);
  	    rm_edfile(-1);
  	} else {
! 	    next_file +=
! 	      find_files(p, files+next_file, names+next_file, size-next_file);
  	    (void) strcpy(Bcc, p);
  	    rm_cmts_in_addr(p);
  	    skipspaces(0);
***************
*** 1202,1212 ****
  	    case  0:  /* the child will send the letter. ignore signals */
  #ifdef SYSV
  		if (setpgrp() == -1)
! 		    error("setpgrp");
  #endif /* SYSV */
! #ifdef MMDF
  		(void) signal(SIGCHLD, SIG_DFL);
- #endif /* MMDF */
  		(void) signal(SIGINT, SIG_IGN);
  		(void) signal(SIGHUP, SIG_IGN);
  		(void) signal(SIGQUIT, SIG_IGN);
--- 1292,1302 ----
  	    case  0:  /* the child will send the letter. ignore signals */
  #ifdef SYSV
  		if (setpgrp() == -1)
! #else /* SYSV */
! 		if (setpgrp(0, getpid()) == -1)
  #endif /* SYSV */
! 		    error("setpgrp");
  		(void) signal(SIGCHLD, SIG_DFL);
  		(void) signal(SIGINT, SIG_IGN);
  		(void) signal(SIGHUP, SIG_IGN);
  		(void) signal(SIGQUIT, SIG_IGN);
***************
*** 1238,1249 ****
  		}
  #endif /* SUNTOOL */
  		while (--next_file > 0)
! 		    fclose(files[next_file]);
! #ifdef MMDF
! 		if (!fork_err)
! 		    (void) wait((int *) 0);
! #endif /* MMDF */
! 		return;
  	}
  
  #ifdef MMDF
--- 1328,1339 ----
  		}
  #endif /* SUNTOOL */
  		while (--next_file > 0)
! 		    if (names[next_file]) {
! 			close_lock(names[next_file], files[next_file]);
! 			xfree(names[next_file]);
! 		    } else
! 			pclose(files[next_file]);
! 		return 1;
  	}
  
  #ifdef MMDF
***************
*** 1256,1262 ****
  	if (isoff(flags, VERBOSE) && debug < 3)
  	    exit(-1);
  	else
! 	    return;
      }
  
      if (ison(flags, VERBOSE))
--- 1346,1352 ----
  	if (isoff(flags, VERBOSE) && debug < 3)
  	    exit(-1);
  	else
! 	    return 1;
      }
  
      if (ison(flags, VERBOSE))
***************
*** 1275,1283 ****
      if (p = do_set(set_options, "logfile")) {
  	if (!*p)
  	    p = "~/mail.log";
! 	(void) strcpy(buf, p);
  	log_file = next_file;
! 	next_file += find_files(buf, files+next_file, size - next_file);
  	if (log_file == next_file)
  	    log_file = -1;
      }
--- 1365,1377 ----
      if (p = do_set(set_options, "logfile")) {
  	if (!*p)
  	    p = "~/mail.log";
! 	if (!index("~|/+", *p))
! 	    (void) sprintf(buf, "%s/%s", do_set(set_options, "cwd"), p);
! 	else
! 	    (void) strcpy(buf, p);
  	log_file = next_file;
! 	next_file +=
! 	    find_files(buf, files+next_file, names+next_file, size-next_file);
  	if (log_file == next_file)
  	    log_file = -1;
      }
***************
*** 1286,1382 ****
       * the letter in a format such that mail can be read from it
       */
      if (p = do_set(set_options, "record")) {
  	if (!*p)
  	    p = "~/record";
! 	(void) strcpy(buf, p);
! 	next_file += find_files(buf, files+next_file, size - next_file);
      }
  
!     /* Make folders conform to RFC-822 by adding From: and Date: headers.
!      * Some older mailers (binmail, execmail, delivermail), don't add
!      * these headers, so add them for #define OLD_MAILER.  Also add them
!      * with the "Resent-" prefix when forwarding.
!      */
!     {
! 	time_t t;
! 	char From_buf[256], *pF = From_buf, date_str[64];
! 	char *host = NULL;
! 	
! 	if (ourname)
! 	    host = ourname[0];
! 
! 	if (ison(flags, FORWARD))
! 	    pF += Strcpy(From_buf, "Resent-");
! 	pF += Strcpy(pF, "From: ");
! #ifdef UUCP
! 	if (host && *host)
! 	    pF += strlen(sprintf(pF, "%s!", host));
! #endif /* UUCP */
! 	pF += Strcpy(pF, login);
! #ifndef UUCP
! 	if (host && *host)
! 	    pF += strlen(sprintf(pF, "@%s", host));
! #endif /* UUCP */
! 	if (p = do_set(set_options, "realname"))
! 	    pF += strlen(sprintf(pF, " (%s)", p));
! 	*pF++ = '\n', *pF++ = 0;
! 	(void) time(&t);
! 	for (size = 0; size < next_file; size++) {
! #ifndef OLD_MAILER
! 	    if (size == 0 && isoff(flags, FORWARD))
! 		continue;
! #endif /* OLD_MAILER */
! 	    if (size > 0) {
  #ifndef MSG_SEPARATOR
! 		fprintf(files[size], "From %s %s", login, ctime(&t));
  #else /* MSG_SEPARATOR */
  #ifdef MMDF
! 		fputs(MSG_SEPARATOR, files[size]);
  #else /* MMDF */
! 		fprintf(files[size], "%s\n", MSG_SEPARATOR);
  #endif /* MMDF */
  #endif /* MSG_SEPARATOR */
- 	    }
- 	    fputs(From_buf, files[size]);
- 	    fprintf(files[size], "%sDate: %s\n",
- 		ison(flags, FORWARD) ? "Resent-" : "", rfc_date(date_str));
- 	}
-     }
  
-     /* first print users own message headers */
-     if (own_hdrs && !do_set(set_options, "no_hdrs")) {
- 	struct options *opts;
- 	for (opts = own_hdrs; opts; opts = opts->next)
- 	    for (size = 0; size < next_file; size++)
- 		fprintf(files[size], "%s %s\n", opts->option, opts->value);
-     }
- 
-     wrap_addrs(To, 80);
-     wrap_addrs(Cc, 80);
-     wrap_addrs(Bcc, 80);
-     /* send the header stuff to sendmail and end header with a blank line */
-     for (size = 0; size < next_file; size++) {
- 	if (*in_reply_to)
- 	    fprintf(files[size], "In-Reply-To: %s\n", in_reply_to);
- 	fprintf(files[size], "X-Mailer: %s\n", VERSION);
- 	fprintf(files[size], "%sTo: %s\n",
- 	    ison(flags, FORWARD) ? "Resent-" : "", To);
- 	if (*Subject && isoff(flags, FORWARD))
- 	    fprintf(files[size], "Subject: %s\n", Subject);
- 	if (*Cc)
- 	    fprintf(files[size], "%sCc: %s\n",
- 		ison(flags, FORWARD) ? "Resent-" : "", Cc);
- 	if (size > 0) {
- 	    /* Do not send these to mail transfer agent */
- 	    if (*Bcc)
- 		fprintf(files[size], "%sBcc: %s\n",
- 		ison(flags, FORWARD) ? "Resent-" : "", Bcc);
- 	    fprintf(files[size], "Status: OR\n");
- 	}
- 	if (isoff(flags, FORWARD))
- 	    fputc('\n', files[size]);
-     }
- 
      /* if redirection, ed_fp = stdin, else rewind the file just made */
      if (isoff(glob_flags, REDIRECT))
  	rewind(ed_fp);
--- 1380,1412 ----
       * the letter in a format such that mail can be read from it
       */
      if (p = do_set(set_options, "record")) {
+ 	int foundit;
  	if (!*p)
  	    p = "~/record";
! 	if (!index("~|/+", *p))
! 	    (void) sprintf(buf, "%s/%s", do_set(set_options, "cwd"), p);
! 	else
! 	    (void) strcpy(buf, p);
! 	next_file +=
! 	    find_files(buf, files+next_file, names+next_file, size-next_file);
      }
  
!     /* First, put the message separator in... */
!     for (size = 1; size < next_file; size++)
  #ifndef MSG_SEPARATOR
! 	{
! 	    time_t t;
! 	    (void) time(&t);
! 	    fprintf(files[size], "From %s %s", login, ctime(&t));
! 	}
  #else /* MSG_SEPARATOR */
  #ifdef MMDF
! 	fputs(MSG_SEPARATOR, files[size]);
  #else /* MMDF */
! 	fprintf(files[size], "%s\n", MSG_SEPARATOR);
  #endif /* MMDF */
  #endif /* MSG_SEPARATOR */
  
      /* if redirection, ed_fp = stdin, else rewind the file just made */
      if (isoff(glob_flags, REDIRECT))
  	rewind(ed_fp);
***************
*** 1383,1399 ****
      else
  	ed_fp = stdin;
  
      /* Read from stdin or the edfile till EOF and send it all to the mailer
       * and other open files/folders/programs. Check for "From " at the
       * beginnings of these lines to prevent creating new messages in folders.
-      * If forwarding, skip the leading From_ line of the forwarded message.
       */
  #ifndef MSG_SEPARATOR
      if (ison(flags, FORWARD) && fgets(buf, sizeof buf, ed_fp)) {
  	if (strncmp(buf, "From ", 5) != 0)
  	    rewind(ed_fp); /* No From_ line (should never happen) */
      }
! #endif /* !MSG_SEPARATOR */
      while (fgets(buf, sizeof buf, ed_fp))
  	for (size = 0; size < next_file; size++) {
  	    if (size == log_file)
--- 1413,1438 ----
      else
  	ed_fp = stdin;
  
+     {
+ 	long offset = add_headers(ed_fp, files, next_file, flags);
+ 	if (offset == -1)
+ 	    offset = 0L;
+ 	(void) fseek(ed_fp, offset, L_SET);
+     }
+ 
      /* Read from stdin or the edfile till EOF and send it all to the mailer
       * and other open files/folders/programs. Check for "From " at the
       * beginnings of these lines to prevent creating new messages in folders.
       */
  #ifndef MSG_SEPARATOR
+     /* If forwarding, skip the leading From_ line of the forwarded message.
+      * (this isn't done for edit_hdrs since FORWARD wouldn't be set.)
+      */
      if (ison(flags, FORWARD) && fgets(buf, sizeof buf, ed_fp)) {
  	if (strncmp(buf, "From ", 5) != 0)
  	    rewind(ed_fp); /* No From_ line (should never happen) */
      }
! #endif /* MSG_SEPARATOR */
      while (fgets(buf, sizeof buf, ed_fp))
  	for (size = 0; size < next_file; size++) {
  	    if (size == log_file)
***************
*** 1402,1408 ****
  	    if (!strncmp(buf, "From ", 5))
  		fputc('>', files[size]);
  #endif /* MSG_SEPARATOR */
! 	    fputs(buf, files[size]);
  	}
  
      /* loop thru the open files (except for the first: the mail delivery agent)
--- 1441,1466 ----
  	    if (!strncmp(buf, "From ", 5))
  		fputc('>', files[size]);
  #endif /* MSG_SEPARATOR */
! 	    if (fputs(buf, files[size]) == EOF) {
! 		if (size == 0) {
! 		    error("Lost connection to MTA");
! 		    dead_letter();
! 		    break;
! 		} else {
! 		    /* Drop this file, but continue writing others */
! 		    error("Write failed");
! 		    if (names[size]) {
! 			close_lock(names[size], files[size]);
! 			xfree(names[size]);
! 		    }
! 		    if (size < --next_file) {
! 			names[size] = names[next_file];
! 			files[size--] = files[next_file];
! 		    }
! 		    files[next_file] = NULL_FILE;
! 		    names[next_file] = NULL;
! 		}
! 	    }
  	}
  
      /* loop thru the open files (except for the first: the mail delivery agent)
***************
*** 1410,1446 ****
       * Then close the files.  If the file was a popened program, the sigchld
       * that the program generates will close the file.
       */
- #ifdef END_MSG_SEP
      for (size = 1; size < next_file; size++) {
  	fputs(END_MSG_SEP, files[size]);
- 	if (files[size])
- 	    fclose(files[size]);
-     }
- #else /* !END_MSG_SEP */
-     for (size = 1; size < next_file; size++)
- 	if (files[size]) {
- 	    fputc('\n', files[size]);
- 	    fclose(files[size]);
- 	}
  #endif /* END_MSG_SEP */
  
- #ifdef MMDF
      if (debug < 3) {
  	int reply_code = pclose(files[0]);
  	Debug("pclose reply_code = %d\n", reply_code);
! 	rm_edfile((reply_code >> 8) == 9 ? 0 : -1);
      } else
  	rm_edfile(0);
- #else /* MMDF */
-     rm_edfile(0);
-     if (debug < 3)
- 	(void) pclose(files[0]);
- #endif /* MMDF */
  
      if ((ison(flags, VERBOSE) || debug > 2) && isoff(glob_flags, REDIRECT))
  	wprint("sent.\n");
      else
  	exit(0); /* not a user exit -- a child exit */
  }
  
  /* ARGSUSED */
--- 1468,1723 ----
       * Then close the files.  If the file was a popened program, the sigchld
       * that the program generates will close the file.
       */
      for (size = 1; size < next_file; size++) {
+ #ifdef END_MSG_SEP
  	fputs(END_MSG_SEP, files[size]);
  #endif /* END_MSG_SEP */
+ 	if (names[size]) {
+ #ifndef END_MSG_SEP
+ 	    fputc('\n', files[size]);
+ #endif /* !END_MSG_SEP */
+ 	    close_lock(names[size], files[size]);
+ 	    xfree(names[size]);
+ 	} else
+ 	    pclose(files[size]);
+     }
  
      if (debug < 3) {
  	int reply_code = pclose(files[0]);
  	Debug("pclose reply_code = %d\n", reply_code);
! 	rm_edfile((reply_code == (MTA_EXIT << 8))? 0 : -1);
      } else
  	rm_edfile(0);
  
+ #ifdef VERBOSE_ARG
+     if (ison(flags, VERBOSE))
+ 	(void) signal(SIGCHLD, oldchld);
+ #endif /* VERBOSE_ARG */
+ 
      if ((ison(flags, VERBOSE) || debug > 2) && isoff(glob_flags, REDIRECT))
  	wprint("sent.\n");
      else
  	exit(0); /* not a user exit -- a child exit */
+     return 1;
+ }
+ 
+ /*
+  * Add the necessary headers to make a file a legitimate mail message.
+  * This could be for a file which the user will edit (via edit_hdrs) or
+  * for delivery to an MTA.
+  * Make folders conform to RFC-822 by adding From: and Date: headers.
+  * Prefix certain header with the "Resent-" prefix when forwarding.
+  * Return offset of fp if we're parsing it for headers (for delivery to MTA).
+  */
+ static long
+ add_headers(fp, files, size, flags)
+ FILE *fp, *files[];
+ int size;
+ u_long flags;
+ {
+     char buf[256], From_buf[256], *pF = From_buf, date_str[64];
+     char *host = NULL, *p, *subj = NULL;
+     int i, for_editor = (fp == NULL_FILE);
+     int got_date = for_editor, got_from = for_editor;
+ 
+     buf[0] = 0;
+     if (ourname)
+ 	host = ourname[0];
+     if (for_editor)
+ 	turnoff(flags,FORWARD); /* forwarded messages must not be edited */
+ 
+     /* [Re]create a From: header -- if not for the editor, use this to check
+      * to see if the user has changed the previously created one in the editor.
+      * If his is not legitimate, warn user and use this header.
+      */
+     if (ison(flags, FORWARD))
+ 	pF += Strcpy(From_buf, "Resent-");
+     pF += Strcpy(pF, "From: ");
+ #ifdef UUCP
+     if (host && *host)
+ 	pF += strlen(sprintf(pF, "%s!", host));
+ #endif /* UUCP */
+     pF += Strcpy(pF, login);
+ #ifndef UUCP
+     if (host && *host)
+ 	pF += strlen(sprintf(pF, "@%s", host));
+ #endif /* UUCP */
+     if ((p = do_set(set_options, "realname")) ||
+ 	(p = do_set(set_options, "name")))
+ 	pF += strlen(sprintf(pF, " (%s)", p));
+     *pF++ = '\n', *pF++ = 0;
+ 
+     if (for_editor) {
+ 	for (i = 0; i < size; i++) {
+ 	    fputs(From_buf, files[i]);
+ 	    fprintf(files[i], "%sDate: %s\n",
+ 		ison(flags, FORWARD) ? "Resent-" : "", rfc_date(date_str));
+ 	    if (*in_reply_to)
+ 		fprintf(files[i], "In-Reply-To: %s\n", in_reply_to);
+ 	}
+ 
+ 	/* first print users own message headers */
+ 	if (own_hdrs && !do_set(set_options, "no_hdrs")) {
+ 	    struct options *opts;
+ 	    for (opts = own_hdrs; opts; opts = opts->next)
+ 		for (i = 0; i < size; i++) {
+ 		    p = opts->value;
+ 		    skipspaces(0);
+ 		    if (*p)
+ 			fprintf(files[i], "%s %s\n", opts->option, p);
+ 		}
+ 	}
+ 
+ 	if (!do_set(set_options, "no_expand")) {
+ 	    /* for edit_hdrs, print the headers followed by a blank line */
+ 	    if (!(p = alias_to_address(To))) {
+ 		wprint("To: alias expansion failed.\n");
+ 		return -1;
+ 	    } else
+ 		(void) strcpy(To, p);
+ 	    if (Cc[0])
+ 		if (!(p = alias_to_address(Cc))) {
+ 		    wprint("Cc: alias expansion failed.\n");
+ 		    return -1;
+ 		} else
+ 		    (void) strcpy(Cc, p);
+ 	    if (Bcc[0])
+ 		if (!(p = alias_to_address(Bcc))) {
+ 		    wprint("Bcc: alias expansion failed.\n");
+ 		    return -1;
+ 		} else
+ 		    (void) strcpy(Bcc, p);
+ 	}
+     } else
+ 	/* if not for the editor and the user doesn't use edit_hdrs,
+ 	 * add his own_hdrs by hand here. (also take care of in-reply-to)
+ 	 */
+ 	if (isoff(flags, EDIT_HDRS) && own_hdrs &&
+ 	    !do_set(set_options, "no_hdrs")) {
+ 	    struct options *opts;
+ 	    for (opts = own_hdrs; opts; opts = opts->next)
+ 		for (i = 0; i < size; i++) {
+ 		    p = opts->value;
+ 		    skipspaces(0);
+ 		    /* user can't set his own from: and date: headers */
+ 		    if (*p && lcase_strncmp(opts->option, "from:", 5) &&
+ 			lcase_strncmp(opts->option, "date:", 5))
+ 			fprintf(files[i], "%s %s\n", opts->option, p);
+ 		}
+ 	    if (*in_reply_to)
+ 		for (i = 0; i < size; i++)
+ 		    fprintf(files[i], "In-Reply-To: %s\n", in_reply_to);
+ 	}
+ 
+     if (!for_editor && ison(flags, EDIT_HDRS)) {
+ 	/*
+ 	 * copy the headers of the message removing special headers.
+ 	 */
+ 	int print_hdr = FALSE;
+ 	rewind(fp);
+ 	while (fgets(buf, sizeof(buf), fp)) {
+ 	    (void) no_newln(buf);
+ 	    if (!buf[0])
+ 		break;
+ 	    /* if the first char is NOT a space, it MUST be a new header.
+ 	     * Otherwise, it is considered part of the message body.
+ 	     */
+ 	    if (!isspace(buf[0])) {
+ 		print_hdr = TRUE;
+ 		if (!(p = any(buf, " \t:")) || isspace(*p))
+ 		    break; /* this is not a legitimate header */
+ 		skipspaces(1);
+ 		if (!*p)
+ 		    print_hdr = FALSE; /* blank headers are not allowed */
+ 		p = buf;
+ 		if (!lcase_strncmp(buf, "resent-", 7)) {
+ 		    if (ison(flags, EDIT_HDRS))
+ 	    wprint("You can't use \"Resent-\" headers in edited messages.");
+ 		    p += 7;
+ 		}
+ 		if (!lcase_strncmp(p, "to:", 3) ||
+ 		    !lcase_strncmp(p, "cc:", 3) ||
+ 		    !lcase_strncmp(p, "bcc:", 4) ||
+ 		    !lcase_strncmp(p, "fcc:", 4) ||
+ 		    !lcase_strncmp(p, "x-mailer:", 9) ||
+ 		    !lcase_strncmp(p, "status:", 7))
+ 		    print_hdr = FALSE;
+ 		else if (!lcase_strncmp(p, "date:", 5))
+ 		    if (got_date)
+ 			wprint("You can't change or add date headers.\n");
+ 		    else {
+ 			got_date = TRUE;
+ 			(void) sprintf(buf, "%sDate: %s", ison(flags, FORWARD)?
+ 			    "Resent-" : "", rfc_date(date_str));
+ 		    }
+ 		else if (!lcase_strncmp(p, "subject:", 8))
+ 		    (print_hdr = FALSE), strdup(subj, p);
+ 		else if (!lcase_strncmp(p, "from:", 5)) {
+ 		    if (got_from) {
+ 			wprint("You can't set your own From: header.\n");
+ 			print_hdr = FALSE;
+ 		    } else {
+ 			(void) strcpy(buf, From_buf);
+ 			(void) no_newln(buf);
+ 			got_from = TRUE;
+ #ifdef PICKY_MAILER
+ 			/* don't send From: to mta -- fool "for loop" below
+ 			 * by initializing the loop at files[1], not files[0]
+ 			 */
+ 			if (!for_editor)
+ 			    print_hdr = 2;
+ #endif /* PICKY_MAILER */
+ 		    }
+ 		}
+ 	    }
+ 	    if (print_hdr)
+ 		/* print_hdr will be 2 for From: header */
+ 		for (i = print_hdr-1; i < size; i++)
+ 		    fputs(buf, files[i]), fputc('\n', files[i]);
+ 	}
+     }
+     /* now do the required (or changed) headers (Date, To, Cc) */
+     wrap_addrs(To, 80);
+     wrap_addrs(Cc, 80);
+     wrap_addrs(Bcc, 80);
+     for (i = 0; i < size; i++) {
+ 	if (!for_editor && !got_date)
+ #ifdef PICKY_MAILER
+ 	    if (i > 0)
+ #endif /* PICKY_MAILER */
+ 	    fprintf(files[i], "%sDate: %s\n",
+ 		ison(flags, FORWARD) ? "Resent-" : "", rfc_date(date_str));
+ 	fprintf(files[i], "X-Mailer: %s\n", VERSION);
+ 	if (!got_from)
+ 	    fputs(From_buf, files[i]);
+ 	fprintf(files[i], "%sTo: %s\n",
+ 	    ison(flags, FORWARD) ? "Resent-" : "", To);
+ 	if (for_editor || isoff(flags, EDIT_HDRS)) {
+ 	    if (*Subject && isoff(flags, FORWARD))
+ 		fprintf(files[i], "Subject: %s\n", Subject);
+ 	} else if (subj && *subj)
+ 	    fputs(subj, files[i]), fputc('\n', files[i]);
+ 	if (*Cc || for_editor && do_set(set_options, "askcc"))
+ 	    fprintf(files[i], "%sCc: %s\n",
+ 		ison(flags, FORWARD) ? "Resent-" : "", Cc);
+ 	if (i > 0 || for_editor)
+ 	    /* Do not send these to mail transfer agent */
+ 	    if (*Bcc)
+ 		fprintf(files[i], "%sBcc: %s\n",
+ 		    ison(flags, FORWARD) ? "Resent-" : "", Bcc);
+ 	if (i > 0)
+ 	    fprintf(files[i], "Status: OR\n");
+     }
+     for (i = 0; i < size; i++)
+ 	fflush(files[i]);
+     if (buf[0]) /* last attempted header read was a line of msg text */
+ 	for (i = 0; i < size; i++)
+ 	    fputs(buf, files[i]), fputc('\n', files[i]), fflush(files[i]);
+     else
+ 	if (isoff(flags, FORWARD))
+ 	    for (i = 0; i < size; i++)
+ 		fputc('\n', files[i]), fflush(files[i]);
+     return fp? ftell(fp) : (long)TRUE;
  }
  
  /* ARGSUSED */
*** mush-6.4/kit.check	Tue Apr 18 17:29:04 1989
--- kit.check	Tue Apr 18 17:29:04 1989
***************
*** 1 ****
!  Part1-check 
--- 1 ----
!  Part2 
-- 
Bart Schaefer       "And if you believe that, you'll believe anything."
							-- DangerMouse
CSNET / Internet                schaefer@cse.ogc.edu
UUCP                            ...{sun,tektronix,verdix}!ogccse!schaefer