[comp.sources.bugs] Official Patch #2 for Mush 6.5

schaefer@ogccse.ogc.edu (Barton E. Schaefer) (05/13/89)

This is Official Patch #2 for the Mail User's Shell (MUSH), version 6.5.
A complete version of Mush including this patch can be obtained by anoymous
ftp from ucbvax.berkeley.edu, directory pub, file mush-6.5.tar.Z.

Overview of changes/bugfixes in this patch:

Added summaries of patches #1 and #2 to README-6.5.
Fixed problem of known_hosts being ignored -- touches addrs.c.
Added "await" command -- touches commands.c, mush.h, mush.1, cmd_help.
Fixed NO_SEPARATOR usage -- commands.c, mail.c, msgs.c.
Improved description of MSG_SEPARATOR in config.h-dist.
Added sort by length to curses [sort] interface -- curses.c.
Fixed redundant waiting for child processes -- execute.c.
Fixed Fcc for edit_hdrs -- file.c and mail.c.
Fixed $record not using full path for file locking -- file.c.
Fixed "folder #" not using full path name for # -- folders.c.
Changed "replyall" to pick up Resent-To, Apparently-To, and To -- hdrs.c.
Fixed strcmp in close_lock for SYSV (mailfile ==> filename) -- lock.c.
Fixed return value of dot_lock() (void ==> 0) -- also lock.c.
Fixed M_XENIX dot-locking -- again lock.c.
Fixed wrong status from msg-number commands (^, $, 3, etc.), so now e.g.
    "35 | print" with < 35 messages will break the pipe -- loop.c.
Changed PATCHDATE -- main.c.
Fixed lack of newline following error messages when mush -C fails to load
    the spool folder -- main.c.
Fixed mail_size() to deal correctly with missing spoolfile -- msgs.c.

---------------------------------------------------------------------------

Prereq: "5/04/89"
*** /tmp/,RCSt1009330	Fri May 12 11:39:42 1989
--- main.c	Fri May 12 11:19:04 1989
***************
*** 3,9 ****
  #include "mush.h"
  #include "options.h"
  
! #define PATCHDATE "5/04/89" /* Here because EVERYTHING depends on mush.h */
  
  #if defined(sun) && defined(M_DEBUG)
  cpu()
--- 3,9 ----
  #include "mush.h"
  #include "options.h"
  
! #define PATCHDATE "5/12/89" /* Here because EVERYTHING depends on mush.h */
  
  #if defined(sun) && defined(M_DEBUG)
  cpu()
***************
*** 28,34 ****
  char **argv;
  {
      int		      n;
!     char 	      buf[256];
      register char    *p;
      char	    **args;
      struct mush_flags Flags;
--- 28,34 ----
  char **argv;
  {
      int		      n;
!     char 	      buf[MAXPATHLEN];
      register char    *p;
      char	    **args;
      struct mush_flags Flags;
***************
*** 112,117 ****
--- 112,120 ----
  	(void) cmd_line(sprintf(buf, "source %s", DEFAULT_RC), msg_list);
  	(void) source(0, DUBL_NULL);
      }
+ 
+     set_cwd();  /* call _after_ sourcing files */
+ 
      if (*spoolfile != '/') {
  	n = 1;
  	p = getpath(spoolfile, &n);
***************
*** 119,130 ****
  	    fputs(p, stderr), exit(1);
  	else if (n)
  	    fprintf(stderr, "\"%s\" is a directory.\n", p), exit(1);
! 	else
  	    strdup(spoolfile, p);
      }
  
-     set_cwd();  /* call _after_ sourcing files */
- 
  #ifdef SUNTOOL
      if (istool) {
  	make_tool(args);
--- 122,139 ----
  	    fputs(p, stderr), exit(1);
  	else if (n)
  	    fprintf(stderr, "\"%s\" is a directory.\n", p), exit(1);
! 	else if (*spoolfile != '/') {
! 	    /* if it still isn't a full path, make it one */
! 	    char *wd = do_set(set_options, "cwd");
! 	    if (*wd) {
! 		(void) sprintf(buf, "%s/%s", wd, p);
! 		strdup(spoolfile, buf);
! 	    } else
! 		strdup(spoolfile, p);
! 	} else
  	    strdup(spoolfile, p);
      }
  
  #ifdef SUNTOOL
      if (istool) {
  	make_tool(args);
***************
*** 247,254 ****
  
      (void) sprintf(buf, "folder %s %s", Flags.f_flags, mailfile);
      if (argv = make_command(buf, TRPL_NULL, &argc)) {
! 	if (folder(argc, argv, NULL) == -1 && isoff(glob_flags, DO_SHELL))
  	    turnoff(glob_flags, IGN_SIGS), cleanup(0);
  #ifdef CURSES
  	if (iscurses)
  	    (void) curses_help_msg(TRUE);
--- 256,266 ----
  
      (void) sprintf(buf, "folder %s %s", Flags.f_flags, mailfile);
      if (argv = make_command(buf, TRPL_NULL, &argc)) {
! 	if (folder(argc, argv, NULL) == -1 && isoff(glob_flags, DO_SHELL)) {
! 	    if (iscurses)
! 		putchar('\n');
  	    turnoff(glob_flags, IGN_SIGS), cleanup(0);
+ 	}
  #ifdef CURSES
  	if (iscurses)
  	    (void) curses_help_msg(TRUE);
*** /tmp/,RCSt1010410	Fri May 12 11:55:02 1989
--- README-6.5	Fri May 12 11:54:38 1989
***************
*** 115,117 ****
--- 115,146 ----
  Ringing the terminal bell is now done by opening the kbd device directly,
  rather than by printing ctrl-G on stderr.  This corrects the problem of
  flashing the wrong window when run under SunOS-4.0.
+ 
+ ----------
+ Changes in 5-04-89 patch:
+ 
+ Some repairs to the way headers are displayed, to avoid both coredumps
+ and a propensity for things to vanish from the toolmode display.  Some
+ minor, related fixes to the curses interface.
+ 
+ Added sort-by-length capability, as a -l option to the sort command and
+ a new menu item in tool mode.
+ 
+ ----------
+ Changes in the 5-12-89 patch:
+ 
+ Clearer documentation of MSG_SEPARATOR in config.h-dist.  MSG_SEPARATOR
+ should not contain a newline, except for MMDF.
+ 
+ Numerous minor repairs to address and file handling when sending mail.
+ 
+ Repairs to locking for SYSV with DOT_LOCK, and to signal handling for folder
+ updating in general (but especially for DOT_LOCK).
+ 
+ Minor corrections to error reporting in various situations.
+ 
+ Added a command "await" to wait for new mail.  This allows customizable
+ "asynchronous" notification of new mail in line and curses modes, similar
+ to what is done automatically for the tool mode.
+ 
+ Added sort-by-length to the curses [sort] and [sort-reverse] interface.
*** /tmp/,RCSt1009330	Fri May 12 11:39:08 1989
--- addrs.c	Sun May  7 18:37:15 1989
***************
*** 567,572 ****
--- 567,574 ----
  		for (i = 0; known_hosts && known_hosts[i]; i++)
  		    if (!lcase_strncmp(p, known_hosts[i], -1))
  			break;
+ 		if (known_hosts && known_hosts[i])
+ 		    break;
  	    }
  	    /* temporary holder for where we are in buffer (save address) */
  	    p2 = b;
*** /tmp/,RCSt1009330	Fri May 12 11:39:13 1989
--- cmd_help	Tue May  9 13:18:07 1989
***************
*** 752,754 ****
--- 752,771 ----
  filename (if given).  If no filename is given and the user did not request
  a merge, then a folder is created based on the subject of the digest.
  %%
+ 
+ %await%
+     await [-T delay]
+ 
+ Intructs the shell to wait for new mail to arrive.  New mail is checked
+ every 30 seconds by default; a different delay can be specified by using
+ the -T option.
+ 
+ If this command is used in a pipe, its output is its input plus the list
+ of new messages that have arrived.  For example, to show the headers of
+ all new messages, and set the current message to the first new message:
+ 
+     await | from -
+ 
+ The await command terminates only when new mail arrives or a keyboard
+ interrupt is generated.
+ %%
*** /tmp/,RCSt1009330	Fri May 12 11:39:16 1989
--- commands.c	Fri May 12 10:33:39 1989
***************
*** 73,79 ****
  
  struct cmd hidden_cmds[] = {
      { "debug", toggle_debug }, { "open", 	nopenfiles },
!     { "stty",	my_stty     },
      { "setenv",	Setenv      }, { "unsetenv", 	Unsetenv   },
      { "printenv", Printenv  }, { "Pipe",	pipe_msg   },
      { NULL, quit }
--- 73,79 ----
  
  struct cmd hidden_cmds[] = {
      { "debug", toggle_debug }, { "open", 	nopenfiles },
!     { "stty",	my_stty     }, { "await",	await      },
      { "setenv",	Setenv      }, { "unsetenv", 	Unsetenv   },
      { "printenv", Printenv  }, { "Pipe",	pipe_msg   },
      { NULL, quit }
***************
*** 223,229 ****
      SIGRET		(*oldint)(), (*oldquit)();
  
      turnon(flags, NO_IGNORE);
! #ifdef MMDF
      turnon(flags, NO_SEPARATOR);
  #endif /* MMDF */
      if (!(printer = do_set(set_options, "printer")) || !*printer)
--- 223,229 ----
      SIGRET		(*oldint)(), (*oldquit)();
  
      turnon(flags, NO_IGNORE);
! #ifdef MSG_SEPARATOR
      turnon(flags, NO_SEPARATOR);
  #endif /* MMDF */
      if (!(printer = do_set(set_options, "printer")) || !*printer)
***************
*** 1081,1084 ****
--- 1081,1116 ----
  	    turnon(glob_flags, IS_PIPE);
      }
      return status;
+ }
+ 
+ await(argc, argv, list)
+ char *argv[], list[];
+ {
+     int done = 0, snooze = 30, last_cnt = msg_cnt;
+ 
+     if (argc && *++argv) {
+ 	if (!strcmp(*argv, "-?"))
+ 	    return help(0, "await", cmd_help);
+ 	else if (!strcmp(*argv, "-T")) {
+ 	    if (*++argv && isdigit(**argv) && **argv > '0') {
+ 		snooze = atoi(*argv);
+ 	    } else {
+ 		print("await: integer greater than 0 required for -T\n");
+ 		return -1;
+ 	    }
+ 	}
+     }
+     Debug("snoozing %d\n", snooze);
+ 
+     do {
+ 	if (!(done = check_new_mail()))
+ 	    sleep(snooze);
+     } while (!done);
+ 
+     while (last_cnt < msg_cnt) {
+ 	set_msg_bit(list, last_cnt);
+ 	++last_cnt;
+     }
+ 
+     return 0;
  }
*** /tmp/,RCSt1009330	Fri May 12 11:39:19 1989
--- config.h-dist	Fri May 12 11:00:57 1989
***************
*** 53,60 ****
  
  /* If your mail transfer agent uses something *besides* "From " to separate
   * adjacent messages in a folder, define MSG_SEPARATOR to be this string.
!  * If that string is 4 ^A's, then the string would be "\001\001\001\001"
!  * If you don't know what this means, leave it alone.
   */
  /* #define MSG_SEPARATOR "From " */
  #ifdef MMDF
--- 53,62 ----
  
  /* If your mail transfer agent uses something *besides* "From " to separate
   * adjacent messages in a folder, define MSG_SEPARATOR to be this string.
!  * If that string is 4 ^A's, then the string would be "\001\001\001\001".
!  * With the exception of MMDF, below, you should OMIT a trailing newline
!  * from the setting of MSG_SEPARATOR.
!  * If you don't know what any of this means, leave it alone.
   */
  /* #define MSG_SEPARATOR "From " */
  #ifdef MMDF
*** /tmp/,RCSt1009330	Fri May 12 11:39:21 1989
--- curses.c	Mon May  8 13:45:24 1989
***************
*** 472,479 ****
  		print("Reverse "), turnon(glob_flags, CONT_PRNT);
  		(void) strcat(file, " -");
  	    }
! 	    print("Order messages by [Status, date, subject, author]: ");
! 	    if ((c = m_getchar()) == 's' || c == 'S' || c == 'd' || c == 'a') {
  		print("reordering messages...");
  		(void) cmd_line(sprintf(buf, "%s %c", file, c), msg_list);
  		print_more("done.");
--- 472,482 ----
  		print("Reverse "), turnon(glob_flags, CONT_PRNT);
  		(void) strcat(file, " -");
  	    }
! 	    print(
! 		"Order messages by [author, date, length, Status, subject]: "
! 		);
! 	    if ((c = m_getchar()) == 'a' || c == 'd' || c == 'l' ||
! 		    c == 'S' || c == 's' || c == 'R') {
  		print("reordering messages...");
  		(void) cmd_line(sprintf(buf, "%s %c", file, c), msg_list);
  		print_more("done.");
*** /tmp/,RCSt1009330	Fri May 12 11:39:24 1989
--- execute.c	Thu May 11 14:21:47 1989
***************
*** 13,18 ****
--- 13,20 ----
  #include <sys/resource.h>
  #endif /* lint */
  
+ static jmp_buf execjbuf;
+ 
  execute(argv)
  char **argv;
  {
***************
*** 67,78 ****
  	    error(*argv);
  	_exit(-1);
      }
!     /* parent's got to do something; sigchldcatcher will do waiting
!      * if other forks die (sendmail), then this wait will catch them,
!      * This loop will really get -1, cuz sigchldcatcher will catch all else.
       */
!     while ((pid = wait(&status)) != -1 && pid != exec_pid)
! 	Debug("The exec loop caught a signal? (pid = %d)\n", pid);
      /* reset our ttymodes */
      echo_off();
      (void) signal(SIGINT, oldint);
--- 69,81 ----
  	    error(*argv);
  	_exit(-1);
      }
!     /* Parent's got to do something; sigchldcatcher may also be waiting.
!      * This loop will usually get broken by the longjmp() (except tool),
!      * but in certain circumstances signchldcatcher isn't yet active.
       */
!     if (!setjmp(execjbuf))
! 	while ((pid = wait(&status)) != -1 && pid != exec_pid)
! 	    Debug("The exec loop caught a signal? (pid = %d)\n", pid);
      /* reset our ttymodes */
      echo_off();
      (void) signal(SIGINT, oldint);
***************
*** 114,120 ****
  #endif /* SYSV */
  #endif /* BSD */
  #ifndef SUNTOOL
!     }
  #else /* SUNTOOL */
      /* The following SHOULDN'T be necessary, but it is!!! ttysw_fork()
       * returns the pid of the thing that it executes, but that's not the
--- 117,125 ----
  #endif /* SYSV */
  #endif /* BSD */
  #ifndef SUNTOOL
!     if (pid == exec_pid)
! 	longjmp(execjbuf, 1);
! } /* { */
  #else /* SUNTOOL */
      /* The following SHOULDN'T be necessary, but it is!!! ttysw_fork()
       * returns the pid of the thing that it executes, but that's not the
*** /tmp/,RCSt1009330	Fri May 12 11:39:26 1989
--- file.c	Thu May 11 14:03:17 1989
***************
*** 286,292 ****
   * The string "s" is modified to be a list of address -- all names AND
   * files are stripped out of the list.
   */
! find_files(s, files, names, size)
  register char *s;
  FILE *files[];
  char *names[];
--- 286,292 ----
   * The string "s" is modified to be a list of address -- all names AND
   * files are stripped out of the list.
   */
! find_files(s, files, names, size, force)
  register char *s;
  FILE *files[];
  char *names[];
***************
*** 293,299 ****
  {
      register int     total = 0, prog;
      char 	     file[MAXPATHLEN], buf[HDRSIZ], *start = s, c;
!     register char    *p, *b = buf;
  
      do  {
  	if (!(p = get_name_n_addr(s, NULL, file)))
--- 293,299 ----
  {
      register int     total = 0, prog;
      char 	     file[MAXPATHLEN], buf[HDRSIZ], *start = s, c;
!     register char    *p, *b = buf, *fpath;
  
      do  {
  	if (!(p = get_name_n_addr(s, NULL, file)))
***************
*** 302,318 ****
  	/* It's a file -- try to open it.  This doesn't get written back
  	 * onto "buf" since it is supposed to be extracted anyway.
  	 */
! 	if (*file == '+' || *file == '~' || *file == '|' || *file == '/') {
! 	    prog = (*file == '|');
  	    if (size && total < size) {
! 		/* either open "file" or &file[1] */
! 		if (files[total] = open_file(&file[prog], prog)) {
  		    if (prog)
  			names[total++] = NULL;
! 		    else if (lock_file(&file[prog],files[total]) < 0) {
  			(void) fclose(files[total]);
! 		    } else
! 			names[total++] = savestr(file);
  		}
  	    } else
  		print("No open space for %s\n", file);
--- 302,327 ----
  	/* It's a file -- try to open it.  This doesn't get written back
  	 * onto "buf" since it is supposed to be extracted anyway.
  	 */
! 	if (force || *file == '+' || *file == '~' ||
! 		*file == '|' || *file == '/') {
! 	    int isdir;
! 	    /* open either "file" or &file[1] */
! 	    if (prog = (*file == '|')) {
! 		isdir = 0;
! 		fpath = &file[1];
! 	    } else {
! 		isdir = 1;
! 		/* if successful, getpath will reset isdir to 0 */
! 		fpath = getpath(file, &isdir);
! 	    }
  	    if (size && total < size) {
! 		if (!isdir && (files[total] = open_file(fpath, prog))) {
  		    if (prog)
  			names[total++] = NULL;
! 		    else if (lock_file(fpath, files[total]) < 0)
  			(void) fclose(files[total]);
! 		    else
! 			names[total++] = savestr(fpath);
  		}
  	    } else
  		print("No open space for %s\n", file);
*** /tmp/,RCSt1009330	Fri May 12 11:39:29 1989
--- folders.c	Mon May  8 07:55:59 1989
***************
*** 113,119 ****
      }
      if (strcmp(mailfile, buf)) {
  	if (!updating)
! 	    (void) strcpy(oldfolder, mailfile);
  	strdup(mailfile, buf);
      }
      do_read_only? turnon(glob_flags,READ_ONLY) : turnoff(glob_flags,READ_ONLY);
--- 113,119 ----
      }
      if (strcmp(mailfile, buf)) {
  	if (!updating)
! 	    (void) strcpy(oldfolder, *oldfolder? mailfile : buf);
  	strdup(mailfile, buf);
      }
      do_read_only? turnon(glob_flags,READ_ONLY) : turnoff(glob_flags,READ_ONLY);
*** /tmp/,RCSt1009330	Fri May 12 11:39:30 1989
--- hdrs.c	Thu May 11 17:58:02 1989
***************
*** 593,617 ****
  	b += Strcpy(buf, p);
  
      /*
!      * if `all' is true, append everyone on the "To:" line.
       * cc_to(), called separately, will catch the cc's
       */
!     if (all &&
! 	((p = header_field(n, "resent-to")) || (p = header_field(n, "to")) ||
! 	 (p = header_field(n, "apparently-to"))) && *p) {
! 	*b++ = ',', *b++ = ' ';
! 	/* The assumption that HDRSIZ is correct is unwise, but I know it
  	 * to be true for Mush.  Be forewarned if you call this routine.
  	 */
! 	p[HDRSIZ - (b - buf) - 2] = '\0'; /* prevent overflow */
! 	b += Strcpy(b, p);
!     }
!     /* Also append the Resent-From address if there is one. */
!     if (all && (p = header_field(n, "resent-from")) && *p) {
! 	*b++ = ',', *b++ = ' ';
! 	/* Another trick to prevent overflow.   See warning above. */
! 	(void) strncpy(b, p, HDRSIZ - (b - buf) - 2);
! 	buf[HDRSIZ - 3] = 0;
      }
      fix_up_addr(buf);
      take_me_off(buf);
--- 593,631 ----
  	b += Strcpy(buf, p);
  
      /*
!      * if `all' is true, append everyone on the "To:" line(s).
       * cc_to(), called separately, will catch the cc's
       */
!     if (all) {
! 	int lim = HDRSIZ - (b - buf) - 2;
! 	/* Check for overflow on each copy.
! 	 * The assumption that HDRSIZ is correct is unwise, but I know it
  	 * to be true for Mush.  Be forewarned if you call this routine.
  	 */
! 	if (lim > 0 && (p = header_field(n, "resent-to")) && *p) {
! 	    *b++ = ',', *b++ = ' ';
! 	    p[lim] = '\0'; /* prevent overflow */
! 	    b += Strcpy(b, p);
! 	    lim = HDRSIZ - (b - buf) - 2;
! 	}
! 	if (lim > 0 && (p = header_field(n, "to")) && *p) {
! 	    *b++ = ',', *b++ = ' ';
! 	    p[lim] = '\0'; /* prevent overflow */
! 	    b += Strcpy(b, p);
! 	    lim = HDRSIZ - (b - buf) - 2;
! 	}
! 	if (lim > 0 && (p = header_field(n, "apparently-to")) && *p) {
! 	    *b++ = ',', *b++ = ' ';
! 	    p[lim] = '\0'; /* prevent overflow */
! 	    b += Strcpy(b, p);
! 	    lim = HDRSIZ - (b - buf) - 2;
! 	}
! 	/* Also append the Resent-From address if there is one. */
! 	if (lim > 0 && (p = header_field(n, "resent-from")) && *p) {
! 	    *b++ = ',', *b++ = ' ';
! 	    p[lim] = '\0'; /* prevent overflow */
! 	    (void) strcpy(b, p);
! 	}
      }
      fix_up_addr(buf);
      take_me_off(buf);
*** /tmp/,RCSt1009330	Fri May 12 11:39:33 1989
--- lock.c	Thu May 11 11:49:36 1989
***************
*** 29,35 ****
  
  #ifdef BSD
      setregid(rgid, sgid);
! #else
      setgid(sgid);
  #endif /* BSD */
  #ifdef SYSV
--- 29,35 ----
  
  #ifdef BSD
      setregid(rgid, sgid);
! #else /* BSD */
      setgid(sgid);
  #endif /* BSD */
  #ifdef SYSV
***************
*** 38,51 ****
       * file name limits, we allow dot_locking ONLY of the spoolfile.
       */
      if (strcmp(spoolfile, filename) != 0)
! 	return;
  #endif
  #ifdef M_XENIX
!     if (strcmp(spoolfile, filename) == 0)
! 	(void) sprintf(buf, "/tmp/%.10s.mlk", login);
!     else
! #endif /* M_XENIX */
      (void) sprintf(buf, "%s.lock", filename);
      on_intr();
      while ((lockfd = open(buf, O_CREAT|O_WRONLY|O_EXCL, 0600)) == -1) {
  	if (errno != EEXIST) {
--- 38,50 ----
       * file name limits, we allow dot_locking ONLY of the spoolfile.
       */
      if (strcmp(spoolfile, filename) != 0)
! 	return 0;
  #endif
  #ifdef M_XENIX
!     (void) sprintf(buf, "/tmp/%.10s.mlk", login);
! #else /* M_XENIX */
      (void) sprintf(buf, "%s.lock", filename);
+ #endif /* M_XENIX */
      on_intr();
      while ((lockfd = open(buf, O_CREAT|O_WRONLY|O_EXCL, 0600)) == -1) {
  	if (errno != EEXIST) {
***************
*** 141,146 ****
--- 140,146 ----
  FILE *fp;
  #ifdef LCKDFLDIR
  {
+     fflush(fp);
      (void) lk_unlock(filename, NULL, NULL);
      fclose(fp);
  }
***************
*** 148,164 ****
  {
  #ifdef DOT_LOCK
      char buf[MAXPATHLEN];
  #ifdef BSD
      setregid(rgid, sgid);
  #else
      setgid(sgid);
  #endif /* BSD */
  #ifdef M_XENIX
!     if (strcmp(spoolfile, mailfile) == 0)
! 	(void) unlink(sprintf(buf, "/tmp/%.10s.mlk", login));
!     else
! #endif /* M_XENIX */
      (void) unlink(sprintf(buf, "%s.lock", filename));
  #ifdef BSD
      setregid(sgid, rgid);
  #else
--- 148,170 ----
  {
  #ifdef DOT_LOCK
      char buf[MAXPATHLEN];
+ #endif /* DOT_LOCK */
+ 
+     fflush(fp);
+ #ifdef DOT_LOCK
  #ifdef BSD
      setregid(rgid, sgid);
  #else
      setgid(sgid);
  #endif /* BSD */
+ #ifdef SYSV
+     if (strcmp(spoolfile, filename) == 0)
+ #endif /* SYSV */
  #ifdef M_XENIX
!     (void) unlink(sprintf(buf, "/tmp/%.10s.mlk", login));
! #else /* M_XENIX */
      (void) unlink(sprintf(buf, "%s.lock", filename));
+ #endif /* M_XENIX */
  #ifdef BSD
      setregid(sgid, rgid);
  #else
*** /tmp/,RCSt1009330	Fri May 12 11:39:35 1989
--- loop.c	Mon May  8 15:32:44 1989
***************
*** 356,362 ****
      n = -1; /* default to failure */
      if ((isdigit(**argv) || index("^.*$-`{}", **argv))
  			&& (n = get_msg_list(argv, list)) != 0) {
! 	if (n > 0 && isoff(glob_flags, DO_PIPE))
  	    for (n = 0; n < msg_cnt; n++)
  		if (msg_bit(list, n)) {
  		    display_msg((current_msg = n), (long)0);
--- 356,364 ----
      n = -1; /* default to failure */
      if ((isdigit(**argv) || index("^.*$-`{}", **argv))
  			&& (n = get_msg_list(argv, list)) != 0) {
! 	if (n < 0)
! 	    return -1;
! 	else if (isoff(glob_flags, DO_PIPE))
  	    for (n = 0; n < msg_cnt; n++)
  		if (msg_bit(list, n)) {
  		    display_msg((current_msg = n), (long)0);
***************
*** 368,376 ****
  	if (n == 0)
  	    unset_msg_bit(list, current_msg);
  	if (strlen(*argv) == 1 && index("$^.", **argv)) {
! 	    if (!msg_cnt)
  		print("No messages.");
! 	    else {
  		if (**argv != '.')
  		    current_msg = (**argv == '$') ? msg_cnt-1 : 0;
  		set_msg_bit(list, current_msg);
--- 370,379 ----
  	if (n == 0)
  	    unset_msg_bit(list, current_msg);
  	if (strlen(*argv) == 1 && index("$^.", **argv)) {
! 	    if (!msg_cnt) {
  		print("No messages.");
! 		return -1;
! 	    } else {
  		if (**argv != '.')
  		    current_msg = (**argv == '$') ? msg_cnt-1 : 0;
  		set_msg_bit(list, current_msg);
*** /tmp/,RCSt1011304	Fri May 12 12:19:20 1989
--- mail.c	Fri May 12 12:18:52 1989
***************
*** 445,451 ****
  	    turnon(copy_flgs, NO_HEADER);
  	if (ison(flags, INCLUDE) || is_forw)
  	    turnon(copy_flgs, NO_IGNORE);
! #ifdef MMDF
  	turnon(copy_flgs, NO_SEPARATOR);
  #endif /* MMDF */
  #ifdef SUNTOOL
--- 445,451 ----
  	    turnon(copy_flgs, NO_HEADER);
  	if (ison(flags, INCLUDE) || is_forw)
  	    turnon(copy_flgs, NO_IGNORE);
! #ifdef MSG_SEPARATOR
  	turnon(copy_flgs, NO_SEPARATOR);
  #endif /* MMDF */
  #ifdef SUNTOOL
***************
*** 743,749 ****
  		turnon(copy_flgs, INDENT);
  	    if (line[1] == 'i')
  		turnon(copy_flgs, NO_HEADER);
! #ifdef MMDF
  	    turnon(copy_flgs, NO_SEPARATOR);
  #endif /* MMDF */
  	    if (!*p)
--- 743,749 ----
  		turnon(copy_flgs, INDENT);
  	    if (line[1] == 'i')
  		turnon(copy_flgs, NO_HEADER);
! #ifdef MSG_SEPARATOR
  	    turnon(copy_flgs, NO_SEPARATOR);
  #endif /* MMDF */
  	    if (!*p)
***************
*** 948,954 ****
  		/* add the \n, flush the file, truncate to the current pos */
  		fputc('\n', ed_fp), fflush(ed_fp);
  		(void) ftruncate(fileno(ed_fp), (int)ftell(ed_fp));
! #else
  		/* pad with blanks to the length of the old line. add \n */
  		while (pos++ < 0)
  		    fputc(' ', ed_fp);
--- 948,954 ----
  		/* add the \n, flush the file, truncate to the current pos */
  		fputc('\n', ed_fp), fflush(ed_fp);
  		(void) ftruncate(fileno(ed_fp), (int)ftell(ed_fp));
! #else /* SYSV */
  		/* pad with blanks to the length of the old line. add \n */
  		while (pos++ < 0)
  		    fputc(' ', ed_fp);
***************
*** 1156,1162 ****
  	    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;
--- 1156,1163 ----
  	    if (p = header_field(msg_cnt, "bcc"))
  		(void) strcpy(Bcc, p);
  	    if (p = header_field(msg_cnt, "fcc"))
! 		next_file +=
! 		find_files(p,files+next_file,names+next_file,size-next_file,1);
  	}
  	msg[msg_cnt].m_offset = old_offset;
  	tmpf = save_tmpf;
***************
*** 1208,1214 ****
  	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);
--- 1209,1215 ----
  	rm_edfile(-1);
      } else {
  	next_file +=
! 	    find_files(p, files+next_file, names+next_file, size-next_file, 0);
  	if (expand)
  	    (void) strcpy(To, p);
  	rm_cmts_in_addr(p);
***************
*** 1238,1244 ****
  	    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);
--- 1239,1245 ----
  	    rm_edfile(-1);
  	} else {
  	    next_file +=
! 	      find_files(p,files+next_file,names+next_file,size-next_file,0);
  	    if (expand)
  		(void) strcpy(Cc, p);
  	    rm_cmts_in_addr(p);
***************
*** 1269,1275 ****
  	    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);
--- 1270,1276 ----
  	    rm_edfile(-1);
  	} else {
  	    next_file +=
! 	      find_files(p,files+next_file,names+next_file,size-next_file,0);
  	    (void) strcpy(Bcc, p);
  	    rm_cmts_in_addr(p);
  	    skipspaces(0);
***************
*** 1376,1382 ****
  	    (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;
      }
--- 1377,1383 ----
  	    (void) strcpy(buf, p);
  	log_file = next_file;
  	next_file +=
! 	    find_files(buf,files+next_file,names+next_file,size-next_file,0);
  	if (log_file == next_file)
  	    log_file = -1;
      }
***************
*** 1393,1399 ****
  	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... */
--- 1394,1400 ----
  	else
  	    (void) strcpy(buf, p);
  	next_file +=
! 	    find_files(buf,files+next_file,names+next_file,size-next_file,0);
      }
  
      /* First, put the message separator in... */
***************
*** 1827,1837 ****
      fflush(ed_fp);
      rewind(ed_fp);
  #ifdef MSG_SEPARATOR
! 	fputs(MSG_SEPARATOR, dead);
  #else /* MSG_SEPARATOR */
      fprintf(dead, "From %s %s", login, ctime(&t));
  #endif /* MSG_SEPARATOR */
!     fprintf(dead, "To: %s\nSubject: %s\n", To, Subject);
      fprintf(dead, "Date: %s\n", rfc_date(buf));
      if (*Cc)
  	fprintf(dead, "Cc: %s\n", Cc);
--- 1828,1841 ----
      fflush(ed_fp);
      rewind(ed_fp);
  #ifdef MSG_SEPARATOR
!     fputs(MSG_SEPARATOR, dead);
! #ifndef MMDF
!     fputc('\n', dead);
! #endif /* MMDF */
  #else /* MSG_SEPARATOR */
      fprintf(dead, "From %s %s", login, ctime(&t));
  #endif /* MSG_SEPARATOR */
!     fprintf(dead, "From: %s\nTo: %s\nSubject: %s\n", login, To, Subject);
      fprintf(dead, "Date: %s\n", rfc_date(buf));
      if (*Cc)
  	fprintf(dead, "Cc: %s\n", Cc);
*** /tmp/,RCSt1009330	Fri May 12 11:39:48 1989
--- msgs.c	Fri May 12 10:59:28 1989
***************
*** 28,34 ****
  	print("Top of "), turnon(glob_flags, CONT_PRNT);
      }
  
! #ifdef MMDF
      turnon(flg, NO_SEPARATOR);
  #endif /* MMDF */
      if (!istool && isoff(flg, NO_PAGE) &&
--- 28,34 ----
  	print("Top of "), turnon(glob_flags, CONT_PRNT);
      }
  
! #ifdef MSG_SEPARATOR
      turnon(flg, NO_SEPARATOR);
  #endif /* MMDF */
      if (!istool && isoff(flg, NO_PAGE) &&
***************
*** 98,106 ****
      }
      while (still_more < msg[n].m_size && fgets(line, sizeof (line), tmpf)) {
  	still_more += strlen(line);
! #ifdef MMDF
  	if (ison(flags, NO_SEPARATOR)) {
  	    if (!strncmp(line, MSG_SEPARATOR, 4))
  		continue;
  	}
  #endif /* MMDF */
--- 98,110 ----
      }
      while (still_more < msg[n].m_size && fgets(line, sizeof (line), tmpf)) {
  	still_more += strlen(line);
! #ifdef MSG_SEPARATOR
  	if (ison(flags, NO_SEPARATOR)) {
+ #ifdef MMDF
  	    if (!strncmp(line, MSG_SEPARATOR, 4))
+ #else /* !MMDF */
+ 	    if (!strncmp(line, MSG_SEPARATOR, strlen(MSG_SEPARATOR)))
+ #endif /* MMDF */
  		continue;
  	}
  #endif /* MMDF */
***************
*** 276,292 ****
  		error("Unable to write to %s", mbox_file);
  	}
      }
! #ifdef DOT_LOCK
!     if ((i = dot_lock(mailfile)) == 0)
! 	mail_fp = mask_fopen(mailfile, "w+");
! #else /* !DOT_LOCK */
      /* We can't lock a file unless we have an fd, but "w+" will zero
       * the file.  If the lock later failed for any reason (possible
       * race condition with an MTA), we would lose all current mail.
       * So, open read/write (if possible) and truncate later.
       */
!     mail_fp = mask_fopen(mailfile, "r+");
  #endif /* DOT_LOCK */
      if (!mail_fp) {
  	error("Unable to rewrite %s", mailfile);
  	if (mbox)
--- 280,295 ----
  		error("Unable to write to %s", mbox_file);
  	}
      }
! 
      /* We can't lock a file unless we have an fd, but "w+" will zero
       * the file.  If the lock later failed for any reason (possible
       * race condition with an MTA), we would lose all current mail.
       * So, open read/write (if possible) and truncate later.
       */
! #ifdef DOT_LOCK
!     if ((i = dot_lock(mailfile)) == 0)
  #endif /* DOT_LOCK */
+     mail_fp = mask_fopen(mailfile, "r+");
      if (!mail_fp) {
  	error("Unable to rewrite %s", mailfile);
  	if (mbox)
***************
*** 303,309 ****
  	    fclose(mbox);
  	return 0;
      }
! #if !defined(DOT_LOCK) && defined(SYSV)
      /* SysV can't truncate a file in the middle, so we can't just
       * write to mail_fp and close.  Instead, we save the mail_fp
       * and reopen for writing, ignoring our own lock.  After updating,
--- 306,314 ----
  	    fclose(mbox);
  	return 0;
      }
!     /* ignore signals before truncating */
!     turnon(glob_flags, IGN_SIGS);
! #ifdef SYSV
      /* SysV can't truncate a file in the middle, so we can't just
       * write to mail_fp and close.  Instead, we save the mail_fp
       * and reopen for writing, ignoring our own lock.  After updating,
***************
*** 317,330 ****
  	    close_lock(mailfile, save_mail_fp);
  	if (mbox)
  	    fclose(mbox);
  	return 0;
      }
! #endif /* SYSV && !DOT_LOCK */
  
      print("Updating \"%s\"", mailfile);
  
      turnon(flg, UPDATE_STATUS);
-     turnon(glob_flags, IGN_SIGS);
  
      keepsave = !!do_set(set_options, "keepsave");
      isspool = !strcmp(mailfile, spoolfile);
--- 322,335 ----
  	    close_lock(mailfile, save_mail_fp);
  	if (mbox)
  	    fclose(mbox);
+ 	turnoff(glob_flags, IGN_SIGS);
  	return 0;
      }
! #endif /* SYSV */
  
      print("Updating \"%s\"", mailfile);
  
      turnon(flg, UPDATE_STATUS);
  
      keepsave = !!do_set(set_options, "keepsave");
      isspool = !strcmp(mailfile, spoolfile);
***************
*** 367,373 ****
  	}
      Debug("\n%s", mailfile);
  
- #ifndef DOT_LOCK
  #ifdef SYSV
      /* Close the write file pointer first */
      fclose(mail_fp);
--- 372,377 ----
***************
*** 379,385 ****
       */
      (void) ftruncate(fileno(mail_fp), ftell(mail_fp));
  #endif /* SYSV */
- #endif /* !DOT_LOCK */
  
      /* some users like to have zero length folders for frequent usage */
      if (mbox)
--- 383,388 ----
***************
*** 436,441 ****
--- 439,446 ----
  
      if (!stat(spoolfile, &buf))
  	spool_size = buf.st_size;
+     else if (!strcmp(mailfile, spoolfile))
+ 	return 0;
      if (!*mailfile || ison(glob_flags, IS_SENDING))
  	return 0;
      if (strcmp(mailfile, spoolfile) && stat(mailfile, &buf)) {
*** /tmp/,RCSt1009330	Fri May 12 11:39:53 1989
--- mush.1	Tue May  9 15:31:25 1989
***************
*** 1660,1665 ****
--- 1660,1673 ----
  command is given with no arguments, the current set of alternate
  names is displayed.
  .TP
+ .BR await " [\-T timeout]"
+ Directs the shell to wait for the arrival of new mail.
+ New mail is checked approximately every 30 seconds, or every
+ .I timeout
+ seconds as specified by the \-T option.
+ This command does not return until new mail arrives
+ or until a keyboard interrupt (^C) is typed.
+ .TP
  .BR bind " [string [command [parameters]]]"
  .ns
  .TP
*** /tmp/,RCSt1009330	Fri May 12 11:40:01 1989
--- mush.h	Thu May 11 13:03:05 1989
***************
*** 490,496 ****
      save_msg(), delete(), do_mail(), lpr(), alts(), set(), do_hdrs(),
      save_opts(), preserve(), sort(), readmsg(), edit_msg(), eval_cmd(),
      do_pick(), print_help(), question_mark(), do_from(), my_stty(),
!     do_version(), disp_hist(), source(), do_echo(), ls(), pipe_msg(),
      nopenfiles(), Setenv(), Unsetenv(), Printenv(), msg_flags(), toggle_debug();
  
  #ifndef SIGRET
--- 490,496 ----
      save_msg(), delete(), do_mail(), lpr(), alts(), set(), do_hdrs(),
      save_opts(), preserve(), sort(), readmsg(), edit_msg(), eval_cmd(),
      do_pick(), print_help(), question_mark(), do_from(), my_stty(),
!     do_version(), disp_hist(), source(), do_echo(), ls(), pipe_msg(), await(),
      nopenfiles(), Setenv(), Unsetenv(), Printenv(), msg_flags(), toggle_debug();
  
  #ifndef SIGRET
-- 
Bart Schaefer       "And if you believe that, you'll believe anything."
							-- DangerMouse
CSNET / Internet                schaefer@cse.ogc.edu
UUCP                            ...{sequent,tektronix,verdix}!ogccse!schaefer