Official Patch #4 for Mush 6.5

Barton E. Schaefer schaefer at ogccse.ogc.edu
Wed Jun 14 06:04:02 AEST 1989


This patch covers almost all reported bugs in Mush version 6.5 as of
June 9, 1989.  The "almost" refers to the following problems:

    On some systems, attempting to mail to a remote site via uucp
    will cause mush to hang if autosign and autosign2 are both set.  
    As nearly as we can determine, this is due to compiler problems,
    not logic errors in mush.  If this happens to you, recompile
    addrs.c without any optimization (no -O flag to cc) and relink.
    If that doesn't solve the problem, let us know.

    Mushtool reportedly crashes when attempting to display large
    messages under certain conditions.  A test of the return value
    of realloc has been added (it should have been there all along),
    which hopefully will prevent the tool from crashing, but it may
    still fail to display the entire message.

This patch was made with only 1 line of context around each diff in a
moderately successful attempt to hold its size down a bit.  A brief
summary of the included changes:

README:
    Added mention of the new behavior of -DUUCP from the previous patch.
README-6.5:
    Added short summaries of this patch and the previous one.
addrs.c:
    Miscellaneous minor fixes to address comparison, for problems found
    when searching for the autosign2 hangup.  None of them fix that. :-(
cmd_help:
    Descriptions of new pick and eval options.
commands.c:
    Sorted the commands in question_mark() down the columns.
    Fixed multi-word $visual/$editor for "e" and "v" commands.
    New eval option -h to expand hdr_format strings in arguments.
    Await now beeps when new mail arrives if $bell is set.
curs_io.c:
    M_XENIX uses rdchk() if neither FIONREAD nor SELECT defined.
curses.c:
    Miscelaneous screen-update fixes.
    Finally got [quit] command working right.
dates.c:
    Changed a comment, whoopee.
doproc.c:
    Test events in the right order for Respond toolmode item.
file.c:
    Removed extraneous semicolons.  Wow.
hdrs.c:
    Moved test of $metoo out of take_me_off() and into caller.
init.c:
    Test return of calloc() for SYSV.
    Default $bell to be set for toolmode.
lock.c:
    Corrected MMDF locking calls.
mail.c:
    New mail option -E to edit outgoing headers without $edit_hdrs.
    Edit_hdrs now allows any of the user's "alternates" in From:.
    $autoedit now checks both $visual and $editor before DEF_EDITOR.
    $ask and $asksub do fill-in-the-blank in edit_hdrs, like $askcc.
    Minor PICKY_MAILER fix.
main.c:
    Moved PATCHDATE to the new version.h file, and changed the way
    version strings are printed to match.
makefile.*:
    New makefile for HP/UX (Thanks grlab!scott).
    New flags listed for Xenix-286 compilers.
    Added version.h to HDRS variable in all makefiles.
misc.c:
    Using "flags" sets DO_UPDATE only if READ_ONLY is not set.
    Test returns of realloc and malloc for SUNTOOL internal pager.
msgs.c:
    Removed extraneous #ifdef DOT_LOCK.
mush.1:
    Documented new pick and eval options, $bell, etc.
    Sorted list of curses commands down the columns instead of across.
mush.h:
    Better implementation of bput() [and bitput()] macro.  This caused
    changes in expr.c and folders.c (not mentioned above).
pick.c:
    Big changes to add +<num> and -<num> options (head and tail).
    Smaller changes to fix -x behavior and remove redundant resets of
    various pick flags.
    Fixed parsing for -ago (bet you never knew it was broken ...).
signals.c:
    Don't try to endwin() when HUPped in curses mode.
    Ring tool bell in check_new_mail() only if $bell is set.
version.h:
    New file containing all the version information, patch level and date.
viewopts.c
    Added $bell and its description.
    Fixed toolmode $thisfolder and $name options screen displays.

Prereq: "5/19/89"
*** old/main.c	Thu May 18 21:49:30 1989
--- ./main.c	Mon Jun 12 20:16:25 1989
***************
*** 3,4 ****
--- 3,5 ----
  #include "mush.h"
+ #include "version.h"
  #include "options.h"
***************
*** 5,8 ****
  
- #define PATCHDATE "5/19/89" /* Here because EVERYTHING depends on mush.h */
- 
  #if defined(sun) && defined(M_DEBUG)
--- 6,7 ----
***************
*** 254,256 ****
  	!do_set(set_options, "quiet"))
! 	printf("%s: Type '?' for help.\n", VERSION);
  
--- 253,256 ----
  	!do_set(set_options, "quiet"))
! 	printf("%s (%d.%d.%d %s): Type '?' for help.\n",
! 		MUSHNAME, RELEASE, REVISION, PATCHLEVEL, RELEASE_DATE);
  
***************
*** 321,327 ****
  {
! #ifdef PATCHDATE
!     print("%s [%s]\n", VERSION, PATCHDATE);
! #else /* !PATCHDATE */
!     print("%s\n", VERSION);
! #endif /* PATCHDATE */
      return -1;
--- 321,324 ----
  {
!     print("%s (%d.%d.%d %s)\n",
! 	    MUSHNAME, RELEASE, REVISION, PATCHLEVEL, RELEASE_DATE);
      return -1;
*** old/README	Thu May 18 21:49:31 1989
--- ./README	Thu May 18 21:30:45 1989
***************
*** 163,164 ****
--- 163,166 ----
      UUCP format (host!user).  Otherwise, arpa-style format is used (user at host)
+     Also, return addresses generated from RFC822 route specs will be put
+     in UUCP format with a complete path.
  
*** old/README-6.5	Fri May 12 12:22:25 1989
--- ./README-6.5	Tue Jun 13 12:05:20 1989
***************
*** 146 ****
--- 146,187 ----
  Added sort-by-length to the curses [sort] and [sort-reverse] interface.
+ 
+ ----------
+ Changes in the 5-19-89 patch:
+ 
+ Bugfixes only, except for change to -DUUCP (see README).
+ 
+ ----------
+ Changes in the 6-09-89 patch:
+ 
+ Numerous bugfixes: address comparisons, toolmode Respond item, MMDF file
+ locking, miscellaneous malloc calls, "e" and "v" commands, curses screen
+ updates and quitting, PICKY_MAILER headers, suntool options display.
+ 
+ Listing of commands generated by "?" now sorted down columns instead of
+ across rows.  Curses commands are similarly sorted in the man page.
+ 
+ New variable:
+ 
+     "bell" is set by default in suntool mode; if unset, the tool will
+     not beep when new mail arrives.  If set in other modes, the "await"
+     command will beep when new mail arrives.
+ 
+ New command options:
+ 
+     "pick +<num>" selects the first <num> messages, and "pick -<num>"
+     selects the last <num> messages (head/tail on message lists).
+     "pick -e ..." specifies that all remaining args are to be used as
+     expression searched for, allowing expressions to begin with +/-.
+ 
+     "eval -h" substitutes hdr_format parameters in its argument list before
+     evaluating the command.
+ 
+     "mail -E" edits outgoing message headers.
+ 
+ When editing outgoing headers, the From: line is now allowed to contain any
+ address in the user's "alternates" list.  No Sender: line is generated --
+ validation is left to the MTA.
+ 
+ Status flags for "forwarded" and "printed" are now set on the appropriate
+ messages.  The "printed" flag is set automatically only on messages printed
+ with the mush "lpr" command.  The "flags" command can set either flag.
*** old/addrs.c	Thu May 18 21:49:32 1989
--- ./addrs.c	Fri Jun  9 09:22:07 1989
***************
*** 68,70 ****
  		    /* "*user" == "user" or "*" == login */
! 		    if (!addrv[a][1] && !lcase_strncmp(listv[l], login) ||
  			!lcase_strncmp(listv[l], addrv[a]+1, -1))
--- 68,70 ----
  		    /* "*user" == "user" or "*" == login */
! 		    if (!addrv[a][1] && !lcase_strncmp(listv[l], login, -1) ||
  			!lcase_strncmp(listv[l], addrv[a]+1, -1))
***************
*** 75,78 ****
  		} else for (h = 0; ourname && ourname[h]; h++)
! 		    if (!lcase_strncmp(addrv[a]+1,
! 			ourname[h], -1)) {
  			ret_val = 1;
--- 75,77 ----
  		} else for (h = 0; ourname && ourname[h]; h++)
! 		    if (!lcase_strncmp(addrv[a]+1, ourname[h], -1)) {
  			ret_val = 1;
***************
*** 90,92 ****
  	    char *start, *user = p + 1;
! 	    while (p-1 >= listv[l] && *--p != '!')
  		;
--- 89,91 ----
  	    char *start, *user = p + 1;
! 	    while (p > listv[l] && *--p != '!')
  		;
***************
*** 105,107 ****
  			if (!addrv[a][1] && !lcase_strncmp(user, login, -1) ||
! 			    addrv[a][1] && !lcase_strncmp(user, addrv[a]+1,-1)){
  			    ret_val = 1;
--- 104,106 ----
  			if (!addrv[a][1] && !lcase_strncmp(user, login, -1) ||
! 			    addrv[a][1] && !lcase_strncmp(user,addrv[a]+1,-1)){
  			    ret_val = 1;
***************
*** 116,118 ****
  		path = addrv[a]+1;
! 		while (addrv[a][1] == '@' && *path == '.')
  		    path++;
--- 115,117 ----
  		path = addrv[a]+1;
! 		while (addrv[a][0] == '@' && *path == '.')
  		    path++;
***************
*** 132,134 ****
  			if (!lcase_strncmp(p, path, len) &&
! 			    (p[len] == '!' || p[len] == 0)) {
  			    ret_val = 1;
--- 131,133 ----
  			if (!lcase_strncmp(p, path, len) &&
! 				(p[len] == '!' || p[len] == 0)) {
  			    ret_val = 1;
***************
*** 667,669 ****
  
!     if (!str || !*str || do_set(set_options, "metoo"))
  	return;
--- 666,668 ----
  
!     if (!str || !*str)
  	return;
***************
*** 696,697 ****
--- 695,697 ----
  	    for (i = 0; !rm_me && ourname && ourname[i]; i++) {
+ 		int len;
  		p2 = tmp + Strcpy(tmp, ourname[i]);
***************
*** 700,702 ****
  		reverse(tmp);
! 		if (!lcase_strncmp(tmp, addr, strlen(tmp))) {
  		    Debug("\t%s\n", reverse(addr));
--- 700,703 ----
  		reverse(tmp);
! 		if (!lcase_strncmp(tmp, addr, (len = strlen(tmp))) &&
! 			(!addr[len] || addr[len] == '!')) {
  		    Debug("\t%s\n", reverse(addr));
***************
*** 772,773 ****
--- 773,778 ----
      list = (char **) calloc(256, sizeof(char *));
+     if (!list) {
+ 	error("out of memory in rm_redundant_addrs");
+ 	return;
+     }
      /* first do the To header */
*** old/cmd_help	Fri May 12 12:22:27 1989
--- ./cmd_help	Mon Jun 12 21:11:11 1989
***************
*** 227,230 ****
  %pick%
!       pick [-x] [-f|s|t] [-h hdr] [-i] [-r msg_list] [<pat>]
!             [-d [-][date]] [-ago [n days] [n weeks] [n months]]
  
--- 227,230 ----
  %pick%
!       pick [+<num>] [-<num>] [-r msg_list] [-x] [-i] [-h hdr] [-f|s|t]
! 	[-d [-][date]] [-ago [n days] [n weeks] [n months]] [[-e] <pat>]
  
***************
*** 233,237 ****
  Only one of -d, -f, -h, -s, -t and -ago can be specified; no
! pattern is used with -d and -ago.
  
!   -x            return those messages which do NOT match
    -f            match pattern in the "From:" field (author) only
--- 233,241 ----
  Only one of -d, -f, -h, -s, -t and -ago can be specified; no
! pattern is used with -d and -ago; and -x may not be used in
! conjunction with +<num> and/or -<num>.
  
!   +<num>        return only the first <num>ber messages matched
!   -<num>        return only the last <num>ber messages matched
!   -x            return all the messages which do NOT match
!   -e		remaining arguments are the <pat> (`e'xpression)
    -f            match pattern in the "From:" field (author) only
***************
*** 254,255 ****
--- 258,271 ----
  	the manual page for details.
+ 
+ Examples:
+     Find the first 5 messages with the subject "Telephone Message":
+ 	pick +5 -s Telephone Message
+     Find the first 2 messages of the last 4 that are to "mush-users":
+ 	pick -4 +2 -t mush-users
+     Find those among messages 1 to 10 that are 2 months or more old:
+ 	pick -r 1-10 -ago -2m
+     Find messages that are 1 week old or newer:
+ 	pick -ago +1w
+     Find messages that contain "-request" in the Resent-From field:
+ 	pick -h resent-from -e -request
  %%
***************
*** 526,528 ****
  %msg_flags%
!       flags [msg_list] [[+|-] [D N O P R S r U]]
  
--- 542,544 ----
  %msg_flags%
!       flags [msg_list] [[+|-] [D f N O P p R S r U]]
  
***************
*** 530,538 ****
  If a list is specified, it will tell which bits of the
! message are set: Delete, New, Old, Preserved, Read, Saved
! replied-to, and Unread.  If any (one or more) of the bits
! are given and no + or - modifier is specified, then the
! status of each message in the list will be set to that
! status absolutely (other status flags are lost).  However,
! if a + or - is specified, then the status is modified for
! that bit to on (+) or off (-).
  
--- 546,554 ----
  If a list is specified, it will tell which bits of the
! message are set: Delete, forwarded, New, Old, Preserved,
! printed, Read, Saved, replied-to, and Unread.  If any (one
! or more) of the bits are given and no + or - modifier is
! specified, then the status of each message in the list will
! be set to that status absolutely (other status flags are
! lost).  However, if a + or - is specified, then the status
! is modified for that bit to on (+) or off (-).
  
***************
*** 674,676 ****
  %eval%
!       eval args ...
  
--- 690,692 ----
  %eval%
!       eval [-h] args ...
  
***************
*** 678,679 ****
--- 694,696 ----
  executed as a mush command.  Example:
+ 
      set initprompt='"$hostname:$cwd "'
***************
*** 680,681 ****
--- 697,706 ----
      eval set prompt=$initprompt
+ 
+ If the -h flag is given, then eval looks for formatting parameters
+ as defined for the variable $hdr_format, and expands the formats
+ for the "current" message before executing the command.  Example:
+ 
+     eval -h pick -f %f
+ 
+ will find all messages from the same author as the current message.
  %%
*** old/commands.c	Thu May 18 21:49:34 1989
--- ./commands.c	Mon Jun 12 21:05:42 1989
***************
*** 269,270 ****
--- 269,271 ----
  	    print_more("(%d lines)\n", copy_msg(n, pp, flags));
+ 	    turnon(msg[n].m_flags, PRINTED);
  	}
***************
*** 733,735 ****
  {
!     int n = 0;
      char *Cmds[sizeof cmds/sizeof(struct cmd)], *p, buf[30];
--- 734,736 ----
  {
!     int n = 0, N = sizeof cmds / sizeof (struct cmd);
      char *Cmds[sizeof cmds/sizeof(struct cmd)], *p, buf[30];
***************
*** 736,742 ****
  
-     qsort((char *)cmds, sizeof(cmds)/sizeof(struct cmd)-1,
- 			sizeof(struct cmd), sorter);
- 
      if (!*++argv) {
! 	for (x = 0; cmds[x].command; x++) {
  	    if (!(x % 5))
--- 737,748 ----
  
      if (!*++argv) {
! 	if (N % 5)
! 	    N = N / 5 + 1;
! 	else
! 	    N = N / 5;
! 
! 	qsort((char *)cmds, sizeof(cmds)/sizeof(struct cmd)-1,
! 			    sizeof(struct cmd), sorter);
! 
! 	for (x = 0; x < N * 5; x++) {
  	    if (!(x % 5))
***************
*** 747,749 ****
  		}
! 	    p += strlen(sprintf(p, "%-14.14s ", cmds[x].command));
  	}
--- 753,756 ----
  		}
! 	    if (x%5*N+n-1 < sizeof cmds / sizeof (struct cmd))
! 		p += strlen(sprintf(p, "%-14.14s ", cmds[x%5*N+n-1].command));
  	}
***************
*** 788,795 ****
      if (i == 3) {
! 	newstr = malloc(strlen(argv[1]) + strlen(argv[2]) + 2);
! 	(void) sprintf(newstr, "%s=%s", argv[1], argv[2]);
      } else {
! 	newstr = malloc(strlen(argv[1]) + 2);
! 	(void) sprintf(newstr, "%s=", argv[1]);
      }
  
--- 795,806 ----
      if (i == 3) {
! 	if (newstr = malloc(strlen(argv[1]) + strlen(argv[2]) + 2))
! 	    (void) sprintf(newstr, "%s=%s", argv[1], argv[2]);
      } else {
! 	if (newstr = malloc(strlen(argv[1]) + 2))
! 	    (void) sprintf(newstr, "%s=", argv[1]);
      }
+     if (!newstr) {
+ 	error("setenv: out of memory");
+ 	return -1;
+     }
  
***************
*** 882,884 ****
      int edited = 0;
!     char buf[MAXPATHLEN], *dir, *edit_cmd[3];
      u_long flags = 0L;
--- 893,895 ----
      int edited = 0;
!     char buf[MAXPATHLEN], *b, *dir, **edit_cmd, *editor;
      u_long flags = 0L;
***************
*** 901,902 ****
--- 912,917 ----
  
+     if (!(editor = do_set(set_options,
+ 	(*cmd == 'v')? "visual" : "editor")) || !*editor)
+ 	editor = DEF_EDITOR;
+ 
      for (i = 0; i < msg_cnt; i++) {
***************
*** 913,914 ****
--- 928,932 ----
  
+ 	b = buf + Strcpy(buf, editor);
+ 	*b++ = ' ';
+ 
  	if (!(dir = do_set(set_options, "tmpdir")) &&
***************
*** 917,920 ****
  	    dir = ALTERNATE_HOME;
! 	(void) mktemp(sprintf(buf, "%s/.msgXXXXXXX", dir));
! 	if (!(fp = mask_fopen(buf, "w+"))) {
  	    if (strcmp(dir, ALTERNATE_HOME))
--- 935,938 ----
  	    dir = ALTERNATE_HOME;
! 	(void) mktemp(sprintf(b, "%s/.msgXXXXXXX", dir));
! 	if (!(fp = mask_fopen(b, "w+"))) {
  	    if (strcmp(dir, ALTERNATE_HOME))
***************
*** 921,923 ****
  		goto alted;
! 	    error("can't create %s", buf);
  	    return -1;
--- 939,941 ----
  		goto alted;
! 	    error("can't create %s", b);
  	    return -1;
***************
*** 932,948 ****
  
! 	if (!(edit_cmd[0] = do_set(set_options,
! 	    (*cmd == 'v')? "visual" : "editor")) || !*edit_cmd[0])
! 	    edit_cmd[0] = DEF_EDITOR;
! 	edit_cmd[1] = buf;
! 	edit_cmd[2] = NULL;
! 	print("Starting \"%s %s\"...\n", edit_cmd[0], buf);
! 	fclose(fp);
! 	turnon(glob_flags, IS_GETTING);
! 	execute(edit_cmd);
! 	turnoff(glob_flags, IS_GETTING);
! 	if (load_folder(buf, FALSE, (char *)i) > 0) {
! 	    (void) unlink(buf);
! 	    edited++;
  	}
- 	set_isread(i); /* if you edit it, you read it, right? */
      }
--- 950,964 ----
  
! 	if (edit_cmd = mk_argv(buf, &edited, FALSE)) {
! 	    print("Starting \"%s\"...\n", buf);
! 	    fclose(fp);
! 	    turnon(glob_flags, IS_GETTING);
! 	    execute(edit_cmd);
! 	    turnoff(glob_flags, IS_GETTING);
! 	    free_vec(edit_cmd);
! 	    if (load_folder(b, FALSE, (char *)i) > 0) {
! 		(void) unlink(b);
! 		edited = 1;
! 	    }
! 	    set_isread(i); /* if you edit it, you read it, right? */
  	}
      }
***************
*** 1036,1038 ****
      if (comp_hdr && as_prompt) {
! 	print("-h and -n cannot be used together.\n");
  	return -1;
--- 1052,1054 ----
      if (comp_hdr && as_prompt) {
! 	print("-h and -p cannot be used together.\n");
  	return -1;
***************
*** 1068,1074 ****
      char **newav, buf[BUFSIZ];
  
!     if (*++argv && !strcmp(*argv, "-?"))
! 	return help(0, "eval", cmd_help);
  
!     (void) argv_to_string(buf,argv);
      /* Can't use cmd_line() because we want DO_PIPE and IS_PIPE
--- 1084,1125 ----
      char **newav, buf[BUFSIZ];
+     int comp_hdr = 0 /* , as_prompt = 0 */;
  
!     while (argv && *++argv && **argv == '-') {
! 	int c, n = 1;
! 	while (c = argv[0][n++])
! 	    switch(c) {
! 		when 'h': comp_hdr++;
! 		/* when 'p': as_prompt++; */
! 		otherwise: return help(0, "eval", cmd_help);
! 	    }
!     }
!     /*
!     if (comp_hdr && as_prompt) {
! 	print("-h and -p cannot be used together.\n");
! 	return -1;
!     }
!     */
  
!     (void) argv_to_string(buf, argv);
!     newav = make_command(buf, TRPL_NULL, &argc);
!     if (comp_hdr) {
! 	char *save_hdr_fmt = hdr_format;
! 	if (!msg_cnt) {
! 	    print("No messages.\n");
! 	    return -1;
! 	}
! 	/* This is inefficient, but the only way to preserve
! 	 * imbedded quotes, tabs, etc. in format expansions.
! 	 */
! 	for (argv = newav; argv && *argv; argv++) {
! 	    /* Don't mess with one-character strings */
! 	    if (argv[0][1]) {
! 		hdr_format = *argv;
! 		*argv = savestr(compose_hdr(current_msg)+9); /* 9 is "magic" */
! 		Debug("expanding (%s) to (%s)\n", hdr_format, *argv);
! 		xfree(hdr_format);
! 	    }
! 	}
! 	hdr_format = save_hdr_fmt;
!     }
      /* Can't use cmd_line() because we want DO_PIPE and IS_PIPE
***************
*** 1076,1078 ****
       */
!     if (newav = make_command(buf, TRPL_NULL, &argc)) {
  	save_is_pipe = ison(glob_flags, IS_PIPE);
--- 1127,1129 ----
       */
!     if (newav) {
  	save_is_pipe = ison(glob_flags, IS_PIPE);
***************
*** 1108,1109 ****
--- 1159,1162 ----
      } while (!done);
+     if (do_set(set_options, "bell"))
+ 	bell();
  
*** old/curs_io.c	Thu Apr 27 12:18:14 1989
--- ./curs_io.c	Thu Jun  8 09:29:04 1989
***************
*** 371,372 ****
--- 371,376 ----
  	    || !ioctl(0, FIONREAD, &n) && n > 0
+ #else
+ #ifdef M_XENIX
+ 	    || rdchk(0) > 0
+ #endif /* M_XENIX */
  #endif /* FIONREAD */
***************
*** 402,403 ****
--- 406,412 ----
  #else
+ #ifdef M_XENIX
+ 	    (void) sleep(1);
+ 	    n = rdchk(0);
+ #else
+ 
  	    /* system has neither select() nor FIONREAD, so just set n
***************
*** 408,409 ****
--- 417,419 ----
  	    n = 1;
+ #endif /* M_XENIX  */
  #endif /* FIONREAD */
*** old/curses.c	Thu May 18 21:49:35 1989
--- ./curses.c	Sun May 21 14:38:37 1989
***************
*** 668,671 ****
  		c = cmd_line(strcpy(buf, "top"), msg_list);
! 	    else
! 		c = cmd_line(strcpy(buf, "next"), msg_list);
  	    if (c > -1)
--- 668,674 ----
  		c = cmd_line(strcpy(buf, "top"), msg_list);
! 	    else {
! 		/* "next" screws up the screen whether it displays or not */
! 		(void) cmd_line(strcpy(buf, "next"), msg_list);
! 		c = 0;
! 	    }
  	    if (c > -1)
***************
*** 762,767 ****
  	}
! 	if (cmd_line(strcpy(buf, *redo? "update" : "quit"), msg_list) != -1
! 		&& ison(glob_flags, CNTD_CMD))
! 	    *redo = 1, turnoff(glob_flags, CNTD_CMD);
!     }
      turnoff(glob_flags, DO_UPDATE);
--- 765,771 ----
  	}
!     } else if (*redo)
! 	return 1;
!     if (cmd_line(strcpy(buf, *redo? "update" : "quit"), msg_list) != -1
! 	    && ison(glob_flags, CNTD_CMD))
! 	*redo = 1, turnoff(glob_flags, CNTD_CMD);
      turnoff(glob_flags, DO_UPDATE);
*** old/dates.c	Thu May 18 21:49:36 1989
--- ./dates.c	Thu May 25 13:00:36 1989
***************
*** 63,65 ****
  /* parse date and return a string that looks like
!  *    "%2d%2d%2d%2d%2d%3c", wkday,yr,mo,date,hrs,mins
   * This function is a bunch of scanfs on known date formats.  Don't
--- 63,65 ----
  /* parse date and return a string that looks like
!  *    "%2d%2d%2d%2d%2d%3c", yr,mo,date,hrs,mins,wkday
   * This function is a bunch of scanfs on known date formats.  Don't
*** old/doproc.c	Thu Apr 27 12:18:32 1989
--- ./doproc.c	Wed May 24 09:17:24 1989
***************
*** 12,13 ****
--- 12,15 ----
  
+     if (event && event->ie_code == MS_LEFT)
+ 	value = 0;
      if (value == 4)
***************
*** 23,26 ****
      print("Responding to message %d", current_msg+1);
-     if (event && event->ie_code == MS_LEFT)
- 	value = 0;
      (void) sprintf(buf, "%s %s %d",
--- 25,26 ----
*** old/expr.c	Thu Apr 27 12:18:10 1989
--- ./expr.c	Thu Jun  8 11:47:06 1989
***************
*** 69,73 ****
  		if (except)
! 		    bitput(list2, list1, msg_cnt, &=~) /* MACRO */
  		else
! 		    bitput(list2, list1, msg_cnt, |=) /* MACRO */
  	    }
--- 69,73 ----
  		if (except)
! 		    bitput(list2, list1, msg_cnt, &=~); /* MACRO */
  		else
! 		    bitput(list2, list1, msg_cnt, |=); /* MACRO */
  	    }
*** old/file.c	Fri May 12 12:22:31 1989
--- ./file.c	Tue May 23 12:45:46 1989
***************
*** 395,397 ****
  	head = buf;
! 	*head++ = '+';;
  	(void) strcpy(head, name + len + 1);
--- 395,397 ----
  	head = buf;
! 	*head++ = '+';
  	(void) strcpy(head, name + len + 1);
***************
*** 401,403 ****
  	head = buf;
! 	*head++ = '~';;
  	(void) strcpy(head, name + len);
--- 401,403 ----
  	head = buf;
! 	*head++ = '~';
  	(void) strcpy(head, name + len);
*** old/folders.c	Thu May 18 21:49:37 1989
--- ./folders.c	Thu Jun  8 11:47:20 1989
***************
*** 205,207 ****
  	clear_msg_list(list);
! 	bitput(list, list, msg_cnt, =~) /* macro */
      }
--- 205,207 ----
  	clear_msg_list(list);
! 	bitput(list, list, msg_cnt, =~); /* macro */
      }
*** old/hdrs.c	Fri May 12 12:22:32 1989
--- ./hdrs.c	Mon Jun 12 20:36:36 1989
***************
*** 337,338 ****
--- 337,342 ----
  	status[0] = 'U';
+     else if (ison(msg[cnt].m_flags, PRINTED))
+ 	status[0] = 'p';
+     else if (ison(msg[cnt].m_flags, FORWARD))
+ 	status[0] = 'f';
      else if (isoff(msg[cnt].m_flags, UNREAD))
***************
*** 630,632 ****
      fix_up_addr(buf);
!     take_me_off(buf);
      for (p = buf; *p == ',' || isspace(*p); p++)
--- 634,637 ----
      fix_up_addr(buf);
!     if (!do_set(set_options, "metoo"))
! 	take_me_off(buf);
      for (p = buf; *p == ',' || isspace(*p); p++)
***************
*** 660,662 ****
      fix_up_addr(p);
!     take_me_off(p);
      return strcpy(buf, p);
--- 665,668 ----
      fix_up_addr(p);
!     if (!do_set(set_options, "metoo"))
! 	take_me_off(p);
      return strcpy(buf, p);
*** old/init.c	Thu Apr 27 12:17:59 1989
--- ./init.c	Fri Jun  9 11:42:11 1989
***************
*** 201,219 ****
  #ifdef SYSV
!     ourname = (char **)calloc((unsigned)2, sizeof (char *));
!     if ((uname (&ourhost) >= 0) && (*ourhost.nodename))
! 	ourname[0] = savestr(ourhost.nodename);
!     else {
!         /* Try to use uuname -l to get host's name if uname didn't work */
!         char buff[50];
!         char *p;
!         FILE *F;
  
!         if (F = popen("exec uuname -l", "r")) {
!     	    if ((fgets(buff, sizeof buff, F) == buff) &&
! 	            (p = strchr(buff, '\n'))) {
! 	        *p = '\0';		/* eliminate newline */
! 		ourname[0] = savestr (buff);
  	    }
! 	(void)pclose(F);
!         }
      }
--- 201,220 ----
  #ifdef SYSV
!     if (ourname = (char **)calloc((unsigned)2, sizeof (char *))) {
! 	if ((uname (&ourhost) >= 0) && (*ourhost.nodename))
! 	    ourname[0] = savestr(ourhost.nodename);
! 	else {
! 	    /* Try to use uuname -l to get host's name if uname didn't work */
! 	    char buff[50];
! 	    char *p;
! 	    FILE *F;
  
! 	    if (F = popen("exec uuname -l", "r")) {
! 		if ((fgets(buff, sizeof buff, F) == buff) &&
! 			(p = strchr(buff, '\n'))) {
! 		    *p = '\0';		/* eliminate newline */
! 		    ourname[0] = savestr (buff);
! 		}
! 	    (void)pclose(F);
  	    }
! 	}
      }
***************
*** 230,231 ****
--- 231,241 ----
      }
+ 
+ #ifdef SUNTOOL
+     if (istool) {
+ 	argv[0] = "bell"; /* defaults on in tool mode */
+ 	argv[1] = NULL;
+ 	(void) add_option(&set_options, argv);
+     }
+ #endif /* SUNTOOL */
+ 
      init_bindings();
*** old/lock.c	Thu May 18 21:49:38 1989
--- ./lock.c	Thu Jun  1 17:49:52 1989
***************
*** 82,85 ****
  {
  #ifdef LCKDFLDIR
!     if (Access(filename, W_OK) || lk_lock(filename, NULL, NULL, 0))
  	return -1;
--- 82,87 ----
  {
+     int fd = fileno(fp);
+ 
  #ifdef LCKDFLDIR
!     if (Access(filename, W_OK) || lk_lock(fd, filename, NULL, NULL, 0))
  	return -1;
***************
*** 86,88 ****
  #else /* LCKDFLDIR */
-     int fd = fileno(fp);
  
--- 88,89 ----
***************
*** 143,145 ****
      fflush(fp);
!     (void) lk_unlock(filename, NULL, NULL);
      fclose(fp);
--- 144,146 ----
      fflush(fp);
!     (void) lk_unlock(fileno(fp), filename, NULL, NULL);
      fclose(fp);
*** old/mail.c	Thu May 18 21:49:39 1989
--- ./mail.c	Mon Jun 12 21:31:54 1989
***************
*** 3,4 ****
--- 3,5 ----
  #include "mush.h"
+ #include "version.h"
  
***************
*** 75,76 ****
--- 76,78 ----
  #endif /* VERBOSE_ARG */
+ 		case 'E': turnon(flgs, EDIT_HDRS); /* Fall through */
  		case 'e': turnon(flgs, EDIT); n++;
***************
*** 147,148 ****
--- 149,151 ----
  #endif /* VERBOSE_ARG */
+ 		    wprint("E      edit outgoing headers (implies -e)\n");
  		    wprint("e      immediately enter editor (autoedit)\n");
***************
*** 389,390 ****
--- 392,394 ----
  		    return -1;
+ 		turnon(msg[i].m_flags, FORWARD);
  		clear_msg_list(fwd);
***************
*** 491,493 ****
  	int argc;
! 	if (!(edit = do_set(set_options, "visual")) || !*edit)
  	    edit = DEF_EDITOR;
--- 495,498 ----
  	int argc;
! 	if ((!(edit = do_set(set_options, "visual")) || !*edit) &&
! 		(!(edit = do_set(set_options, "editor")) || !*edit))
  	    edit = DEF_EDITOR;
***************
*** 1523,1525 ****
  {
!     char buf[256], From_buf[256], *pF = From_buf, date_str[64];
      char *host = NULL, *p, *subj = NULL;
--- 1528,1530 ----
  {
!     char buf[BUFSIZ], From_buf[256], *pF = From_buf, date_str[64];
      char *host = NULL, *p, *subj = NULL;
***************
*** 1606,1610 ****
  			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);
--- 1611,1614 ----
  			skipspaces(0);
! 			/* user can't set his own date: headers */
! 			if (*p && lcase_strncmp(opts->option, "date:", 5))
  			    fprintf(files[i], "%s %s\n", opts->option, p);
***************
*** 1661,1677 ****
  		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 */
- 		    }
  		}
--- 1665,1687 ----
  		else if (!lcase_strncmp(p, "from:", 5)) {
! 		    char not_me[BUFSIZ];
! 		    (void) strcpy(not_me, buf + 5);
! 		    take_me_off(not_me);
! 		    if (*not_me) {
! 			/* Ignore bogus From: if we have a good one */
! 			if (got_from)
! 			    print_hdr = FALSE;
! 			/* otherwise, output a good one */
! 			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 */
  		}
***************
*** 1695,1697 ****
  		ison(flags, FORWARD) ? "Resent-" : "", rfc_date(date_str));
! 	fprintf(files[i], "X-Mailer: %s\n", VERSION);
  	if (!got_from)
--- 1705,1711 ----
  		ison(flags, FORWARD) ? "Resent-" : "", rfc_date(date_str));
! 	fprintf(files[i], "X-Mailer: %s (%d.%d.%d %s)\n",
! 			MUSHNAME, RELEASE, REVISION, PATCHLEVEL, RELEASE_DATE);
! #ifdef PICKY_MAILER
! 	if (i > 0)
! #endif /* PICKY_MAILER */
  	if (!got_from)
***************
*** 1701,1705 ****
  	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]);
--- 1715,1721 ----
  	if (for_editor || isoff(flags, EDIT_HDRS)) {
! 	    if (isoff(flags, FORWARD) && 
! 		    (*Subject || for_editor && (do_set(set_options, "ask") ||
! 					    do_set(set_options, "asksub"))))
  		fprintf(files[i], "Subject: %s\n", Subject);
! 	} else if (subj && *subj && strlen(subj) > 9)
  	    fputs(subj, files[i]), fputc('\n', files[i]);
*** old/makefile.bsd	Thu Apr 27 12:18:29 1989
--- ./makefile.bsd	Mon Jun 12 11:42:37 1989
***************
*** 3,5 ****
  #
! HDRS= mush.h config.h-dist strings.h bindings.h options.h
  
--- 3,5 ----
  #
! HDRS= mush.h config.h-dist strings.h bindings.h options.h version.h
  
*** old/makefile.hpux	Tue Jun 13 12:31:35 1989
--- ./makefile.hpux	Mon Jun 12 11:42:54 1989
***************
*** 0 ****
--- 1,32 ----
+ # Mush makefile for HP/UX.
+ #
+ HDRS1= mush.h config.h
+ HDRS2= strings.h options.h
+ HDRS3= bindings.h version.h
+ SRCS1= commands.c dates.c execute.c expr.c folders.c \
+ 	hdrs.c init.c loop.c mail.c main.c misc.c msgs.c pick.c \
+ 	print.c setopts.c signals.c sort.c viewopts.c options.c lock.c
+ SRCS2= bind.c curs_io.c curses.c file.c strings.c macros.c \
+ 	addrs.c malloc.c
+ 
+ OBJS1= commands.o dates.o execute.o expr.o folders.o \
+ 	hdrs.o init.o loop.o mail.o main.o misc.o msgs.o pick.o \
+ 	print.o setopts.o signals.o sort.o viewopts.o options.o lock.o
+ OBJS2= bind.o curs_io.o curses.o file.o strings.o macros.o \
+ 	addrs.o malloc.o
+ 
+ HELP_FILES= README README-6.0 README-6.1 README-6.2 README-6.3 README-6.4 \
+ 	README-6.5 mush.1 Mailrc Gnurc cmd_help sample.mushrc advanced.mushrc
+ MAKES= makefile.sys.v makefile.xenix makefile.bsd
+ 
+ CFLAGS= 	-O -DSYSV -DHPUX -DCURSES -DREGCMP -DUSG -DSIGRET=void -DSELECT
+ LDFLAGS= 	-s
+ LIBS= 		-lcurses -lPW -lmalloc
+ PROG=		mush
+ 
+ $(PROG): $(OBJS1) $(OBJS2)
+ 	@echo loading...
+ 	@$(CC) $(LDFLAGS) $(OBJS1) $(OBJS2) -o $(PROG) $(LIBS)
+ 
+ $(OBJS1): $(HDRS1) $(HDRS2)
+ $(OBJS2): $(HDRS1) $(HDRS2) $(HDRS3)
*** old/makefile.sun	Thu Apr 27 12:18:30 1989
--- ./makefile.sun	Mon Jun 12 11:42:42 1989
***************
*** 3,5 ****
  #
! HDRS= mush.h config.h-dist strings.h bindings.h options.h
  
--- 3,5 ----
  #
! HDRS= mush.h config.h-dist strings.h bindings.h options.h version.h
  
*** old/makefile.sys.v	Thu Apr 27 12:18:30 1989
--- ./makefile.sys.v	Mon Jun 12 12:23:37 1989
***************
*** 5,7 ****
  HDRS2= strings.h options.h
! HDRS3= bindings.h
  SRCS1= commands.c dates.c execute.c expr.c folders.c \
--- 5,7 ----
  HDRS2= strings.h options.h
! HDRS3= bindings.h version.h
  SRCS1= commands.c dates.c execute.c expr.c folders.c \
*** old/makefile.xenix	Thu Apr 27 12:18:30 1989
--- ./makefile.xenix	Mon Jun 12 11:42:59 1989
***************
*** 8,10 ****
  #
! HDRS= mush.h config.h-dist strings.h bindings.h options.h
  SRCS1= main.c init.c misc.c execute.c
--- 8,10 ----
  #
! HDRS= mush.h config.h-dist strings.h bindings.h options.h version.h
  SRCS1= main.c init.c misc.c execute.c
***************
*** 27,29 ****
  # Memory model.  Use -M3e for 80386 machines.
! # Use -M2le -Mt32 for 80286 machines.
  MODEL= -M3e
--- 27,29 ----
  # Memory model.  Use -M3e for 80386 machines.
! # Use -M2le -Mt32 -LARGE for 80286 machines.
  MODEL= -M3e
***************
*** 32,34 ****
  # 80286 xenix may use this LDFLAGS define:
! #LDFLAGS= -X -lx -M2le -Mt32 -F 8000 -SEG 256
  LDFLAGS= -X -lx -M3
--- 32,34 ----
  # 80286 xenix may use this LDFLAGS define:
! #LDFLAGS= -X -lx -M2le -Mt32 -F 8000 -SEG 256 -LARGE
  LDFLAGS= -X -lx -M3
*** old/misc.c	Sat May  6 16:43:39 1989
--- ./misc.c	Mon Jun 12 21:42:21 1989
***************
*** 332,334 ****
      if (v && *(v += (c-1))) {
! 	turnon(glob_flags, DO_UPDATE);
  	while (*++v)
--- 332,335 ----
      if (v && *(v += (c-1))) {
! 	if (isoff(glob_flags, READ_ONLY))
! 	    turnon(glob_flags, DO_UPDATE);
  	while (*++v)
***************
*** 338,340 ****
  		    when 'd' : turnon(newflag, DELETE);
! 		    when 'p' : turnon(newflag, PRESERVE);
  		    when 's' : turnon(newflag, SAVED);
--- 339,345 ----
  		    when 'd' : turnon(newflag, DELETE);
! 		    when 'p' :
! 			if (v[0][c] == 'P')
! 			    turnon(newflag, PRESERVE);
! 			else
! 			    turnon(newflag, PRINTED);
  		    when 's' : turnon(newflag, SAVED);
***************
*** 347,348 ****
--- 352,354 ----
  			    turnon(newflag, REPLIED);
+ 		    when 'f' : turnon(newflag, FORWARD);
  		    when '+' : modify = 1;
***************
*** 372,373 ****
--- 378,383 ----
  		wprint(" SAVED");
+ 	    if (ison(msg[i].m_flags, PRINTED))
+ 		wprint(" PRINTED");
+ 	    if (ison(msg[i].m_flags, FORWARD))
+ 		wprint(" FORWARD");
  	    if (ison(msg[i].m_flags, UPDATE_STATUS))
***************
*** 427,430 ****
  		if ((cnt % STR_ARRAY) == 0)
! 		    strings = (char **)realloc(strings,
! 			sizeof (char *) * (unsigned)(cnt + STR_ARRAY));
  		do  {
--- 437,444 ----
  		if ((cnt % STR_ARRAY) == 0)
! 		    if (!(strings = (char **)realloc(strings,
! 			    sizeof (char *) * (unsigned)(cnt + STR_ARRAY)))) {
! 			error("out of memory");
! 			free_vec(strings);
! 			return 0;
! 		    }
  		do  {
***************
*** 444,446 ****
  	    cnt = lines = 0;
! 	    strings = (char **)malloc((unsigned)sizeof (char *));
  	    if (tool->tl_flags&TOOL_ICONIC)
--- 458,463 ----
  	    cnt = lines = 0;
! 	    if (!(strings = (char **)malloc((unsigned)sizeof (char *)))) {
! 		error("out of memory");
! 		return 0;
! 	    }
  	    if (tool->tl_flags&TOOL_ICONIC)
***************
*** 455,456 ****
--- 472,478 ----
  				 max(msg_rect.r_height, height), 1);
+ 	    if (!msg_pix) {
+ 		error("can't mem_create msg_pixrect");
+ 		free_vec(strings);
+ 		return 0;
+ 	    }
  	    for (cnt = 0; strings[cnt]; cnt++)
*** old/msgs.c	Fri May 12 12:22:37 1989
--- ./msgs.c	Thu Jun  1 14:10:25 1989
***************
*** 212,214 ****
      register FILE	*mbox = NULL_FILE, *mail_fp = NULL_FILE;
- #ifndef DOT_LOCK
  #ifdef SYSV
--- 212,213 ----
***************
*** 216,218 ****
  #endif /* SYSV */
- #endif /* !DOT_LOCK */
      char		*mbox_file, action = 0;
--- 215,216 ----
*** old/mush.1	Thu May 18 21:49:43 1989
--- ./mush.1	Mon Jun 12 21:13:59 1989
***************
*** 1269,1271 ****
  .sp
! .ta 1.5i 3i 4.5i
  .in +4
--- 1269,1271 ----
  .sp
! .ta 2i 4i
  .in +4
***************
*** 1272,1288 ****
  .nf
! alias	back-msg	bind	bind-macro
! bottom-page	chdir	copy	copy-list
! delete	delete-list	display	display-next
! exit	exit!	first-msg	folder
! goto-msg	ignore	last-msg	line-mode
! lpr	mail	mail-flags	map
! map!	my-hdrs	next-msg	preserve
! quit	quit!	redraw	reply
! reply-all	reverse-video	save	save-list
! saveopts	screen-back	screen-next	search-again
! search-back	search-next	shell-escape	sort
! sort-reverse	source	top	top-page
! unbind	undelete	undelete-list	update
! variable	version	write	write-list
! help
  .fi
--- 1272,1292 ----
  .nf
! alias	last-msg	screen-back	
! back-msg	line-mode	screen-next	
! bind	lpr	search-again	
! bind-macro	mail	search-back	
! bottom-page	mail-flags	search-next	
! chdir	map	shell-escape	
! copy	map!	sort	
! copy-list	my-hdrs	sort-reverse	
! delete	next-msg	source	
! delete-list	preserve	top	
! display	quit	top-page	
! display-next	quit!	unbind	
! exit	redraw	undelete	
! exit!	reply	undelete-list	
! first-msg	reply-all	update	
! folder	reverse-video	variable	
! goto-msg	save	version	
! help	save-list	write	
! ignore	saveopts	write-list	
  .fi
***************
*** 1824,1826 ****
  .TP
! .BR eval " arg ..."
  As in most shells, the list of arguments to
--- 1828,1830 ----
  .TP
! .BR eval " [\-h] arg ..."
  As in most shells, the list of arguments to
***************
*** 1829,1830 ****
--- 1833,1853 ----
  This is useful primarily for causing multiple levels of variable expansion.
+ .sp
+ If the \-h option is given,
+ .B eval
+ will expand header format strings in the argument list before executing the
+ command.
+ Header formats are expanded using the 
+ .I current
+ message.
+ Formats are implicitly quoted, so imbedded quotes, tabs, `!'s, etc. are
+ handled correctly.
+ For example,
+ .sp
+ .ti +2
+ eval \-h pick \-f %a
+ .sp
+ will find all messages from the same author as the current message.
+ See the the entry for
+ .I hdr_format
+ in the VARIABLES section for more details.
  .TP
***************
*** 1860,1862 ****
  .TP
! .BR flags " [msg-list] [ [ + | \- ] [ D N O P R r S U ] ]"
  This command modifies the flag bits set on the listed messages.
--- 1883,1885 ----
  .TP
! .BR flags " [msg-list] [ [ + | \- ] [ D f N O P p R r S U ] ]"
  This command modifies the flag bits set on the listed messages.
***************
*** 1873,1874 ****
--- 1896,1898 ----
  D	deleted
+ f	forwarded
  N	new
***************
*** 1876,1877 ****
--- 1900,1902 ----
  P	preserved
+ p	printed
  R	read
***************
*** 2134,2135 ****
--- 2159,2162 ----
  variable are ignored and the command is simply executed as is.
+ .sp
+ The \*Qprinted\*U status bit is set for each message printed by this command.
  .TP
***************
*** 2181,2182 ****
--- 2208,2210 ----
  \-c addr-list	set list of carbon copy recipients
+ \-E	edit outgoing message headers (implies -e)
  \-e	immediately enter editor (autoedit)
***************
*** 2361,2362 ****
--- 2389,2392 ----
  .in +2
+ \+<num>	keep only the first <num> messages matched (head).
+ \-<num>	keep only the last <num> messages matched (tail).
  \-ago <format>	search for messages relative to today's date.
***************
*** 2363,2364 ****
--- 2393,2395 ----
  \-d [+|\-]date	messages sent on or [+ after] [`\-' before] date.
+ \-e	take all remaining arguments to be the pattern.
  \-f	search for pattern in \*QFrom\*U field only.
***************
*** 2369,2371 ****
  \-t	search for pattern in \*QTo\*U field only.
! \-x	select messages not containing the pattern.
  .in -2
--- 2400,2402 ----
  \-t	search for pattern in \*QTo\*U field only.
! \-x	select all messages \fIexcept\fP those specified.
  .in -2
***************
*** 2382,2383 ****
--- 2413,2419 ----
  No patterns can be specified with the \-a or \-d options.
+ The \-x option may not be used in conjunction with
+ .IR + n
+ (head) and
+ .IR \- n
+ (tail).
  .sp
***************
*** 2439,2441 ****
  .sp
! will find all the messages between the dates February 5, 1986, and
  February 5, 1987, that contain the subject "mail stuff" and send them
--- 2475,2477 ----
  .sp
! Will find all the messages between the dates February 5, 1986, and
  February 5, 1987, that contain the subject "mail stuff" and send them
***************
*** 2446,2448 ****
  .sp
! deletes messages that have \*QRe:\*U in the Subject header.
  .sp
--- 2482,2484 ----
  .sp
! Deletes messages that have \*QRe:\*U in the Subject header.
  .sp
***************
*** 2466,2467 ****
--- 2502,2513 ----
  called \fIcurrent\fR, which is found in the user's \fIfolder\fR variable.
+ .sp
+ .ti +2
+ pick +3 mush-users
+ .sp
+ Finds the first three messages containing the string \*Qmush-users\*U.
+ .sp
+ .ti +2
+ eval -h "pick +2 \-r .-$ \-s %s" | pick -1
+ .sp
+ Finds the next message with the same subject as the current message.
  .TP
***************
*** 3261,3262 ****
--- 3307,3324 ----
  .RE
+ .TP
+ .B bell
+ (Boolean)
+ When this variable is set, the suntool interface and the
+ .B await
+ command will ring a bell when new mail arrives.
+ The bell will not sound in the line or curses modes if
+ .B await
+ is not in use.
+ This variable is set (defaults to \fItrue\fR) in tool mode, but is unset
+ (defaults to \fIfalse\fR) in other modes.
+ Tool mode users must explicitly unset bell to silence it.
+ .sp
+ .IR Note :
+ The tool mode default is for compatibility with previous versions, and may
+ change in future releases.
  .TP
*** old/mush.h	Fri May 12 12:22:41 1989
--- ./mush.h	Mon Jun 12 20:34:16 1989
***************
*** 2,5 ****
  
- #define VERSION "Mail User's Shell (6.5 4/17/89)"
- 
  #include "config.h"
--- 2,3 ----
***************
*** 217,218 ****
--- 215,217 ----
  #endif /* F_OK */
+ #ifndef HPUX
  typedef	unsigned long	u_long;
***************
*** 219,220 ****
--- 218,220 ----
  #define vfork   fork
+ #endif /* HPUX */
  #ifndef SIGCHLD
***************
*** 299,301 ****
  #define bput(S1, S2, Len, op)   				\
! 		{ 						\
  		    register char *s1 = S1, *s2 = S2; 		\
--- 299,301 ----
  #define bput(S1, S2, Len, op)   				\
! 		do { 						\
  		    register char *s1 = S1, *s2 = S2; 		\
***************
*** 304,306 ****
  			*s2++ op *s1++; 			\
! 		}
  #define bitput(m1,m2,len,op)	bput(m1, m2, (((len)+7)/8), op)
--- 304,306 ----
  			*s2++ op *s1++; 			\
! 		} while (0)
  #define bitput(m1,m2,len,op)	bput(m1, m2, (((len)+7)/8), op)
***************
*** 358,359 ****
--- 358,360 ----
  /* msg flags */
+ #define PRINTED		5	/* sent through lpr command */
  #define NO_HEADER	7	/* don't print header of message (top, write) */
*** old/pick.c	Thu Apr 27 12:18:09 1989
--- ./pick.c	Mon Jun 12 13:03:36 1989
***************
*** 22,26 ****
      if (isoff(glob_flags, IS_PIPE))
! 	bitput(list, list, msg_cnt, =~) /* macro, turn on all bits */
      clear_msg_list(ret_list);
!     if (pick(n, argv, list, ret_list, isoff(glob_flags, DO_PIPE)) == -1)
  	return -1;
--- 22,26 ----
      if (isoff(glob_flags, IS_PIPE))
! 	bitput(list, list, msg_cnt, =~); /* macro, turn on all bits */
      clear_msg_list(ret_list);
!     if ((n = pick(argv, list, ret_list, isoff(glob_flags, DO_PIPE))) == -1)
  	return -1;
***************
*** 27,32 ****
      if (istool && isoff(glob_flags, DO_PIPE))
! 	print("Messages: ");
      for (n = 0; n < msg_cnt; n++)
! 	if (msg_bit(ret_list, n) && !xflg ||
! 	    !msg_bit(ret_list, n) && xflg) {
  	    if (isoff(glob_flags, DO_PIPE))
--- 27,31 ----
      if (istool && isoff(glob_flags, DO_PIPE))
! 	print("%d matches:\n", n);
      for (n = 0; n < msg_cnt; n++)
! 	if (msg_bit(ret_list, n)) {
  	    if (isoff(glob_flags, DO_PIPE))
***************
*** 43,46 ****
  /*
!  * search for messages.  Even if no messages match, return 0.  Errors such
   * as internal errors or syntax errors, return -1.
   */
--- 42,51 ----
  /*
!  * search for messages.  Return the number of matches.  Errors such
   * as internal errors or syntax errors, return -1.
+  * "head" and "tail" are specified using +<num> or -<num> as args.
+  * Both can be specified and the order is significant.
+  *    pick +5 -3
+  * returns the last three of the first five matches.
+  *    pick -3 +2
+  * returns the first two of the last three matches.
   */
***************
*** 47,50 ****
  static int
! pick(ret, argv, list, ret_list, verbose)
! register int ret;
  register char **argv, list[], ret_list[];
--- 52,54 ----
  static int
! pick(argv, list, ret_list, verbose)
  register char **argv, list[], ret_list[];
***************
*** 52,61 ****
      register char c;
      char pattern[256];
!     int o_before = before, o_after = after, o_search_from = search_from,
! 	o_search_subj = search_subj, o_search_to = search_to, o_mdy[3], n;
  
-     for (c = 0; c < 3; c++)
- 	o_mdy[c] = mdy[c];
- 
-     ret = -1;
      if (!msg_cnt) {
--- 56,62 ----
      register char c;
+     int matches = 0;
      char pattern[256];
!     short head_first, head_cnt, tail_cnt, search = TRUE;
!     int n;
  
      if (!msg_cnt) {
***************
*** 62,64 ****
  	print("No Messages.\n");
! 	goto bad;
      }
--- 63,65 ----
  	print("No Messages.\n");
! 	return -1;
      }
***************
*** 65,70 ****
  
!     icase = before = after = search_from = search_subj = xflg = 0;
!     mdy[0] = search_hdr[0] = 0;
!     while (*argv && *++argv && **argv == '-')
! 	switch(c = argv[0][1]) {
  	    /* users specifies a range */
--- 66,92 ----
  
!     head_first = TRUE;
!     head_cnt = tail_cnt = -1;
!     icase = before = after = search_from = search_subj = search_to = xflg = 0;
!     mdy[0] = mdy[1] = search_hdr[0] = 0;
!     while (*argv && *++argv && (**argv == '-' || **argv == '+'))
! 	if (**argv == '+' || isdigit(argv[0][1])) {
! 	    if (**argv == '+')
! 		head_cnt = atoi(&argv[0][1]);
! 	    else {
! 		tail_cnt = atoi(&argv[0][1]);
! 		if (head_cnt == -1)
! 		    head_first = FALSE;
! 	    }
! 	    if (head_cnt == 0 || tail_cnt == 0) {
! 		print("pick: invalid head/tail number: %s\n", &argv[0][1]);
! 		clear_msg_list(ret_list);
! 		return -1;
! 	    }
! 	} else if ((c = argv[0][1]) == 'e') {
! 	    if (!*++argv) {
! 		print("use: -e expression...\n");
! 		return -1;
! 	    }
! 	    break;
! 	} else switch (c) {
  	    /* users specifies a range */
***************
*** 88,90 ****
  		if (n == -1)
! 		    goto bad;
  		argv += (n-1); /* we're going to increment another up top */
--- 110,112 ----
  		if (n == -1)
! 		    return -1;
  		argv += (n-1); /* we're going to increment another up top */
***************
*** 93,95 ****
  		if ((n = ago_date(++argv)) == -1)
! 		    goto bad;
  		argv += n;
--- 115,117 ----
  		if ((n = ago_date(++argv)) == -1)
! 		    return -1;
  		argv += n;
***************
*** 98,101 ****
  		if (!*++argv) {
! 		    print("specify a date for -%c\n", c);
! 		    goto bad;
  		}
--- 120,123 ----
  		if (!*++argv) {
! 		    print("Specify a date for -%c\n", c);
! 		    return -1;
  		}
***************
*** 102,104 ****
  		if (!date1(*argv))
! 		    goto bad;
  	    when 's' : case 'f': case 't': case 'h':
--- 124,126 ----
  		if (!date1(*argv))
! 		    return -1;
  	    when 's' : case 'f': case 't': case 'h':
***************
*** 105,108 ****
  		if (search_subj + search_from + search_to + *search_hdr > 1) {
! 		    print("specify one of `s', `f', `t' or `h' only\n");
! 		    goto bad;
  	        }
--- 127,130 ----
  		if (search_subj + search_from + search_to + *search_hdr > 1) {
! 		    print("Specify one of `s', `f', `t' or `h' only\n");
! 		    return -1;
  	        }
***************
*** 126,127 ****
--- 148,153 ----
  	}
+     if (xflg && head_cnt + tail_cnt >= 0) {
+ 	print("Can't specify -x and head/tail options together.\n");
+ 	return -1;
+     }
      pattern[0] = 0;
***************
*** 128,134 ****
      (void) argv_to_string(pattern, argv);
      if (verbose) {
! 	print_more("Searching for messages");
! 	if (mdy[1] == 0) {
! 	    print(" that %scontain \"%s\"", (xflg)? "does not ": "",
! 				(*pattern)? pattern: "<previous expression>");
  	    if (search_subj)
--- 154,188 ----
      (void) argv_to_string(pattern, argv);
+     search = (pattern[0] || head_cnt + tail_cnt < 0);
      if (verbose) {
! 	if (head_cnt + tail_cnt >= 0) {
! 	    print("Finding the ");
! 	    if (head_cnt > 0) {
! 		if (head_first)
! 		    if (tail_cnt == -1)
! 			print_more("first %d message%s",
! 			    head_cnt, head_cnt > 1? "s" : "");
! 		    else
! 			print_more("last %d message%s",
! 			    tail_cnt, tail_cnt > 1? "s" : "");
! 		else /* there must be a tail_cnt and it comes first */
! 		    print_more("first %d message%s",
! 			    head_cnt, head_cnt > 1? "s" : "");
! 	    } else
! 		print_more("last %d message%s",
! 		    tail_cnt, tail_cnt > 1? "s" : "");
! 	    if (tail_cnt > 0 && head_cnt > 0)
! 		if (head_first)
! 		    print_more(" of the first %d", head_cnt);
! 		else
! 		    print_more(" of the last %d", tail_cnt);
! 	} else
! 	    print_more("Searching for messages");
! 	if (!search) {
! 	    if (tail_cnt > 0 && head_cnt > 0)
! 		print_more(" messages");
! 	    if (ison(glob_flags, IS_PIPE))
! 		print_more(" from the input list");
! 	} else if (mdy[1] == 0) {
! 	    print(" that %scontain \"%s\"", (xflg)? "do not ": "",
! 			    (*pattern)? pattern: "<previous expression>");
  	    if (search_subj)
***************
*** 140,142 ****
  	    else if (search_hdr[0])
! 		print_more(" from the message header: \"%s:\"", search_hdr);
  	} else {
--- 194,196 ----
  	    else if (search_hdr[0])
! 		print_more(" from the message header \"%s:\"", search_hdr);
  	} else {
***************
*** 149,151 ****
  		    print_more("on or %s ", (before)? "before": "after");
! 	    print_more("%s. %d, 19%d.",
  		      month_names[mdy[0]], mdy[1], mdy[2]);
--- 203,205 ----
  		    print_more("on or %s ", (before)? "before": "after");
! 	    print_more("%s. %d, 19%d",
  		      month_names[mdy[0]], mdy[1], mdy[2]);
***************
*** 152,154 ****
  	}
! 	print_more("\n");
      }
--- 206,208 ----
  	}
! 	print_more(".\n");
      }
***************
*** 156,165 ****
  	print("using date: -i flag ignored.\n");
!     ret = find_pattern(pattern, list, ret_list);
! bad:
!     before = o_before, after = o_after, search_from = o_search_from;
!     search_subj = o_search_subj, search_to = o_search_to;
!     for (c = 0; c < 3; c++)
! 	mdy[c] = o_mdy[c];
  
!     return ret;
  }
--- 210,252 ----
  	print("using date: -i flag ignored.\n");
!     if (!search) {
! 	for (n = 0; n < msg_cnt && (!head_first || matches < head_cnt); n++)
! 	    if (msg_bit(list, n))
! 		++matches, set_msg_bit(ret_list, n);
!     } else
! 	matches = find_pattern(head_first? head_cnt : msg_cnt,
! 			   pattern, list, ret_list);
!     if (xflg && matches >= 0) {
! 	/* invert items in ret_list that also appear in list */
! 	bitput(list, ret_list, msg_cnt, ^=);
! 	/* there should be a faster way to do this count ... */
! 	for (matches = n = 0; n < msg_cnt; n++)
! 	    if (msg_bit(ret_list, n))
! 		++matches;
!     }
!     Debug("matches = %d\n", matches);
!     if (!matches)
! 	return 0;
  
!     /* ok, the list we've got is a list of matched messages.  If "tailing"
!      * is set, reduce the number of matches to at least tail_cnt.
!      */
!     if (tail_cnt >= 0)
! 	for (n = 0; n < msg_cnt && matches > tail_cnt; n++)
! 	    if (msg_bit(ret_list, n)) {
! 		Debug("tail: dropping %d\n", n+1);
! 		unset_msg_bit(ret_list, n);
! 		matches--;
! 	    }
! 
!     /* if tailing came before heading, we need to do the heading now. */
!     if (!head_first && head_cnt >= 0)
! 	for (n = 0; n < msg_cnt; n++)
! 	    if (msg_bit(ret_list, n))
! 		if (head_cnt > 0)
! 		    head_cnt--;
! 		else {
! 		    unset_msg_bit(ret_list, n);
! 		    matches--;
! 		}
!     return matches;
  }
***************
*** 166,168 ****
  
! find_pattern(p, check_list, ret_list)
  register char *p;
--- 253,262 ----
  
! /*
!  * find_pattern will search thru all the messages set in the check_list
!  * until the list runs out or "cnt" has been exhasted.  ret_list contains
!  * the list of messages which have matched the pattern.
!  * return -1 for internal error or # of pattern matches.
!  */
! find_pattern(cnt, p, check_list, ret_list)
! int cnt;
  register char *p;
***************
*** 171,172 ****
--- 265,267 ----
      register int n, val, i; /* val is return value from regex or re_exec */
+     int matches = 0;
      long bytes = 0;
***************
*** 208,210 ****
      /* start searching: set bytes, and message number: n */
!     for (n = 0; n < msg_cnt; n++)
  	if (msg_bit(check_list, n)) {
--- 303,305 ----
      /* start searching: set bytes, and message number: n */
!     for (n = 0; cnt && n < msg_cnt; n++)
  	if (msg_bit(check_list, n)) {
***************
*** 231,232 ****
--- 326,328 ----
  			    set_msg_bit(ret_list, n);
+ 			    cnt--, matches++;
  			    break;
***************
*** 288,289 ****
--- 384,386 ----
  		    set_msg_bit(ret_list, n);
+ 		    cnt--, matches++;
  		    break;
***************
*** 294,296 ****
  	}
!     return 0;
  }
--- 391,393 ----
  	}
!     return matches;
  }
***************
*** 464,467 ****
      while (*p) {
! 	if (!isdigit(*p))
  	    break; /* really a syntax error, but it could be other pick args */
  	p = my_atoi(p, &value); /* get 1 or more digits */
--- 561,566 ----
      while (*p) {
! 	if (!isdigit(*p)) {
! 	    p -= 2;
  	    break; /* really a syntax error, but it could be other pick args */
+ 	}
  	p = my_atoi(p, &value); /* get 1 or more digits */
***************
*** 478,480 ****
  	while (*p == ',' || isspace(*p))
! 	    ; /* 0 or more whitespaces or commas */
      }
--- 577,579 ----
  	while (*p == ',' || isspace(*p))
! 	    ++p; /* 0 or more whitespaces or commas */
      }
*** old/signals.c	Thu Apr 27 12:18:06 1989
--- ./signals.c	Fri Jun  9 10:58:25 1989
***************
*** 218,220 ****
  #ifdef CURSES
!     if (iscurses)
  	iscurses = FALSE, endwin();
--- 218,220 ----
  #ifdef CURSES
!     if (iscurses && sig != SIGHUP)
  	iscurses = FALSE, endwin();
***************
*** 302,304 ****
  	    (void) do_hdrs(0, DUBL_NULL, NULL);
! 	    bell();
  	}
--- 302,305 ----
  	    (void) do_hdrs(0, DUBL_NULL, NULL);
! 	    if (do_set(set_options, "bell"))
! 		bell();
  	}
*** old/sort.c	Thu May 18 21:49:44 1989
--- ./sort.c	Mon Jun 12 20:36:21 1989
***************
*** 127,128 ****
--- 127,136 ----
  	return order;
+     if (ison(msg1->m_flags,PRINTED) && isoff(msg2->m_flags,PRINTED))
+ 	return -order;
+     if (isoff(msg1->m_flags,PRINTED) && ison(msg2->m_flags,PRINTED))
+ 	return order;
+     if (ison(msg1->m_flags,FORWARD) && isoff(msg2->m_flags,FORWARD))
+ 	return -order;
+     if (isoff(msg1->m_flags,FORWARD) && ison(msg2->m_flags,FORWARD))
+ 	return order;
  
*** old/version.h	Tue Jun 13 12:31:34 1989
--- ./version.h	Tue Jun 13 12:03:26 1989
***************
*** 0 ****
--- 1,8 ----
+ /* @(#)version.h	(c) Copyright 1989 (Dan Heller) */
+ 
+ #define MUSHNAME	"Mail User's Shell"
+ #define RELEASE_DATE	"6/12/89"
+ #define RELEASE		6
+ #define REVISION	5
+ #define PATCHLEVEL	4
+ #define ORIGINAL_DATE	"4/17/89"
*** old/viewopts.c	Thu May 18 21:49:45 1989
--- ./viewopts.c	Tue Jun 13 12:02:52 1989
***************
*** 43,44 ****
--- 43,46 ----
  	"Signature to use for specific addresses. \"addr, ... : <signature>\""},
+     { "bell", NULL, TOOL | TEXT,
+ 	"Ring a bell when new mail arrives (toolmode or \"await\" command)." },
      { "cdpath", "Path", TEXT,
***************
*** 123,125 ****
  	"Don't print the version number of Mush on startup." },
!     { "realname", "Name:", TOOL | TEXT,
  	"Your real name." },
--- 125,127 ----
  	"Don't print the version number of Mush on startup." },
!     { "realname", "Name", TOOL | TEXT,
  	"Your real name." },
***************
*** 145,147 ****
  	"When reading messages, squeeze all blank lines into one." },
!     { "thisfolder", NULL, TEXT,
  	"This read-only variable gives the current folder name." },
--- 147,149 ----
  	"When reading messages, squeeze all blank lines into one." },
!     { "thisfolder", "Folder", TEXT,
  	"This read-only variable gives the current folder name." },
***************
*** 246,248 ****
  	un_set(&set_options, viewopts[start_cnt+line].v_opt);
!     else {
  	if (p) {
--- 248,250 ----
  	un_set(&set_options, viewopts[start_cnt+line].v_opt);
!     else if (!check_internal(viewopts[start_cnt+line].v_opt)) {
  	if (p) {
***************
*** 317,319 ****
  	pf_text(win, PIX_SRC, fonts[DEFAULT], ":");
! 	if (v) {
  	    win.pos.x += (2 * l_width(DEFAULT));
--- 319,321 ----
  	pf_text(win, PIX_SRC, fonts[DEFAULT], ":");
! 	if (v || (v = check_internal(viewopts[start_cnt+count].v_opt))) {
  	    win.pos.x += (2 * l_width(DEFAULT));
-- 
Bart Schaefer           "And if you believe that, you'll believe anything."
                                                            -- DangerMouse
CSNET / Internet                schaefer at cse.ogc.edu
UUCP                            ...{sequent,tektronix,verdix}!ogccse!schaefer



More information about the Comp.sources.bugs mailing list