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

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

Part 3 of the Mush 6.5 Upgrade Kit.  Read the instructions in part 1.
---------------------------------------------------------------------------
Prereq: Part2
*** mush-6.4/kit.check	Tue Apr 18 17:29:04 1989
--- kit.check	Tue Apr 18 17:29:04 1989
***************
*** 1 ****
!  Part2 
--- 1 ----
!  Part2-check 
*** mush-6.4/hdrs.c	Fri Mar 24 10:06:14 1989
--- hdrs.c	Wed Apr 12 10:18:43 1989
***************
*** 52,58 ****
      register char  *p, *p2, *b = buf;
      int contd_hdr;  /* true if next line is a continuation of the hdr we want */
  
!     if (!msg_get(n, tmp, sizeof tmp))
  	return NULL;
      *b = 0;
      while((p = fgets(tmp, sizeof(tmp), tmpf)) && *p != '\n') {
--- 52,59 ----
      register char  *p, *p2, *b = buf;
      int contd_hdr;  /* true if next line is a continuation of the hdr we want */
  
!     /* use msg_get as a test for fseek() -- don't let it fgets() (pass 0) */
!     if (!msg_get(n, tmp, 0))
  	return NULL;
      *b = 0;
      while((p = fgets(tmp, sizeof(tmp), tmpf)) && *p != '\n') {
***************
*** 108,125 ****
  	if (first_char != ':')
  	    argv++;
  	return specl_hdrs(argv, list);
      }
  
      on_intr();
  
!     if (argc && (argv[0][1] == '+' || argc > 1 && !strcmp(argv[1], "+")) ||
  	    first_char == 'z' && !argv[1])
  	if (msg_cnt > screen)
  	    cnt = min(msg_cnt - screen, n_array[0] + screen);
  	else
  	    cnt = 0;
-     else if (argc && (argv[0][1] == '-' || argc > 1 && !strcmp(argv[1], "-")))
- 	cnt = max((cnt - 2*screen), 0);
      else if (argc && *++argv &&
  	(isdigit(**argv) || **argv == '^' || **argv == '$' || **argv == '.')
  	 || ison(glob_flags, IS_PIPE)) {
--- 109,131 ----
  	if (first_char != ':')
  	    argv++;
  	return specl_hdrs(argv, list);
+     } else if (argc > 1 && !strncmp(argv[1], "-H:", 3)) {
+ 	argv[1][0] = ':';
+ 	argv[1][1] = argv[1][3];
+ 	argv[1][2] = 0;
+ 	return specl_hdrs(&argv[1], list);
      }
  
      on_intr();
  
!     if (argc && (argv[0][1] == '-' || argc > 1 && !strcmp(argv[1], "-")))
! 	cnt = max((cnt - 2*screen), 0);
!     else if (argc && (argv[0][1] == '+' || argc > 1 && !strcmp(argv[1], "+")) ||
  	    first_char == 'z' && !argv[1])
  	if (msg_cnt > screen)
  	    cnt = min(msg_cnt - screen, n_array[0] + screen);
  	else
  	    cnt = 0;
      else if (argc && *++argv &&
  	(isdigit(**argv) || **argv == '^' || **argv == '$' || **argv == '.')
  	 || ison(glob_flags, IS_PIPE)) {
***************
*** 150,156 ****
      show_deleted = !!do_set(set_options, "show_deleted");
  
      /* Make sure we have at least $screen headers to print */
!     if (cnt > 0 && !iscurses && !show_deleted && first_char != 'h') {
  	int tmp = cnt;
  	/* first count how many messages we can print without adjusting */
  	for (pageful = 0; pageful < screen && cnt < msg_cnt; cnt++)
--- 156,162 ----
      show_deleted = !!do_set(set_options, "show_deleted");
  
      /* Make sure we have at least $screen headers to print */
!     if (cnt > 0 && !iscurses && !show_deleted && first_char == 'h') {
  	int tmp = cnt;
  	/* first count how many messages we can print without adjusting */
  	for (pageful = 0; pageful < screen && cnt < msg_cnt; cnt++)
*** mush-6.4/hdr_procs.c	Fri Mar 24 10:01:23 1989
--- hdr_procs.c	Wed Apr 12 10:31:23 1989
***************
*** 9,15 ****
  int value;
  struct inputevent *event;
  {
!     register char *argv[3];
      argv[2] = NULL;
      argv[0] = "headers";
  
--- 9,15 ----
  int value;
  struct inputevent *event;
  {
!     char *argv[3];
      argv[2] = NULL;
      argv[0] = "headers";
  
***************
*** 142,148 ****
  int value;
  struct inputevent *event;
  {
!     register char *argv[3];
      argv[0] = "sort";
      argv[2] = NULL;
      if (event->ie_code == MS_LEFT)
--- 142,148 ----
  int value;
  struct inputevent *event;
  {
!     char *argv[3];
      argv[0] = "sort";
      argv[2] = NULL;
      if (event->ie_code == MS_LEFT)
*** mush-6.4/folders.c	Fri Mar 24 10:05:11 1989
--- folders.c	Thu Apr 13 16:52:25 1989
***************
*** 18,24 ****
   * RETURN -1 on error -- else return 0. All bits in msg_list are set to true.
   */
  folder(argc, argv, list)
! register char **argv, list[];
  {
      int n, updating = !strcmp(*argv, "update"), do_read_only = 0, no_hdrs = 0;
      char *tmp, *newfolder = NULL, buf[MAXPATHLEN];
--- 18,25 ----
   * RETURN -1 on error -- else return 0. All bits in msg_list are set to true.
   */
  folder(argc, argv, list)
! register char **argv;
! char list[];
  {
      int n, updating = !strcmp(*argv, "update"), do_read_only = 0, no_hdrs = 0;
      char *tmp, *newfolder = NULL, buf[MAXPATHLEN];
***************
*** 72,80 ****
  	    return -1;
  	}
  	/* strcpy so copyback() below (which calls getpath) doesn't change
! 	 * the data that tmp intended to point to.
  	 */
! 	(void) strcpy(buf, tmp);
      }
      if (stat(buf, &statbuf) == -1 || !(statbuf.st_mode & 0400)) {
  	error("Unable to read %s", buf);
--- 73,97 ----
  	    return -1;
  	}
  	/* strcpy so copyback() below (which calls getpath) doesn't change
! 	 * the data that tmp intended to point to.  Get the cwd if necessary.
  	 */
! 	n = 0;
! 	if (*tmp != '/') {
! #ifdef SYSV
! 	    extern char *getcwd();
! 	    if (!getcwd(buf, MAXPATHLEN))
! #else /* SYSV */
! 	    extern char *getwd();
! 	    if (!getwd(buf))
! #endif /* SYSV */
! 	    {
! 		error("getcwd: %s",buf);
! 		return -1;
! 	    }
! 	    n = strlen(buf);
! 	    buf[n++] = '/';
! 	}
! 	(void) strcpy(&buf[n], tmp);
      }
      if (stat(buf, &statbuf) == -1 || !(statbuf.st_mode & 0400)) {
  	error("Unable to read %s", buf);
***************
*** 355,364 ****
  	}
      }
  
!     if (!Access(buf, W_OK)) {
! 	fp = mask_fopen(buf, "a");
! 	appending = (fp > 0);
!     } else
  	fp = mask_fopen(buf, "w");
      if (!fp) {
  	if (!*argv && strcmp(dir, ALTERNATE_HOME))
--- 372,380 ----
  	}
      }
  
!     if (!Access(buf, W_OK))
! 	appending = ((fp = mask_fopen(buf, "a")) != NULL_FILE);
!     else
  	fp = mask_fopen(buf, "w");
      if (!fp) {
  	if (!*argv && strcmp(dir, ALTERNATE_HOME))
*** mush-6.4/file.c	Fri Mar 24 10:04:08 1989
--- file.c	Tue Apr 18 09:37:56 1989
***************
*** 59,67 ****
  	    (void) sprintf(buf, "%s/%s", MAILDIR, p);
  #else /* HOMEMAIL */
  	{
! 	    char *p2 = do_set(set_options, "home");
! 	    (void) sprintf(buf, "%s/%s", p2 ? p2 : ALTERNATE_HOME, MAILFILE);
! 	} else {
  	    int t_isdir = *isdir;
  	    char *t, tmp[256];
  	    (void) sprintf(tmp, "~%s/%s", p, MAILFILE);
--- 59,65 ----
  	    (void) sprintf(buf, "%s/%s", MAILDIR, p);
  #else /* HOMEMAIL */
  	{
! 	    /* If it's NOT us, recur to get the path for ~user/MAILFILE */
  	    int t_isdir = *isdir;
  	    char *t, tmp[256];
  	    (void) sprintf(tmp, "~%s/%s", p, MAILFILE);
***************
*** 288,296 ****
   * 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, size)
  register char *s;
  FILE *files[];
  {
      register int     total = 0, prog;
      char 	     file[MAXPATHLEN], buf[HDRSIZ], *start = s, c;
--- 286,295 ----
   * 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[];
  {
      register int     total = 0, prog;
      char 	     file[MAXPATHLEN], buf[HDRSIZ], *start = s, c;
***************
*** 307,314 ****
  	    prog = (*file == '|');
  	    if (size && total < size) {
  		/* either open "file" or &file[1] */
! 		if (files[total] = open_file(&file[prog], prog))
! 		    total++;
  	    } else
  		print("No open space for %s\n", file);
  	} else {
--- 306,319 ----
  	    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);
  	} else {
***************
*** 355,358 ****
--- 360,398 ----
      FILE *fp = fopen(file, mode);
      (void) umask(omask);
      return fp;
+ }
+ 
+ /*
+  * Shorten a file name, replacing its full path name with one using an
+  *  accepted mush abbreviation:
+  *	~	home directory
+  *	+	folder directory
+  *  For files in the current directory, the path is simply skipped.
+  * Returns a pointer into a static buffer holding the trimmed path.
+  */
+ char *
+ trim_filename(name)
+ char *name;
+ {
+     static char buf[MAXPATHLEN];
+     char *head;
+     int len;
+ 
+     if ((head = do_set(set_options, "cwd")) &&
+ 	    (len = strlen(head)) && !strncmp(head, name, len))
+ 	return strcpy(buf, name + len + 1);
+     else if ((head = do_set(set_options, "folder")) &&
+ 	    (len = strlen(head)) && !strncmp(head, name, len)) {
+ 	head = buf;
+ 	*head++ = '+';;
+ 	(void) strcpy(head, name + len + 1);
+ 	return buf;
+     } else if ((head = do_set(set_options, "home")) &&
+ 	    (len = strlen(head)) && !strncmp(head, name, len)) {
+ 	head = buf;
+ 	*head++ = '~';;
+ 	(void) strcpy(head, name + len);
+ 	return buf;
+     }
+     return strcpy(buf, name);
  }
*** mush-6.4/init.c	Fri Mar 24 10:05:14 1989
--- init.c	Wed Apr 12 10:15:38 1989
***************
*** 109,115 ****
  init()
  {
      char 		*home, *realname, *argv[4];
!     extern char		*getlogin(), **calloc();
      char		buf[MAXPATHLEN];
  #ifdef SYSV
      extern struct passwd *getpwuid();  /* sys-v forgot this in pwd.h! */
--- 109,115 ----
  init()
  {
      char 		*home, *realname, *argv[4];
!     extern char		*getlogin();
      char		buf[MAXPATHLEN];
  #ifdef SYSV
      extern struct passwd *getpwuid();  /* sys-v forgot this in pwd.h! */
***************
*** 180,186 ****
      (void) gethostname(ourhost, sizeof ourhost);
      if (!(hp = gethostbyname(ourhost))) {
  	error("gethostbyname: %s", ourhost);
! 	if (ourname = calloc((unsigned)2, sizeof (char *)))
  	    strdup(ourname[0], ourhost);
      } else {
  	int n = 0;
--- 180,186 ----
      (void) gethostname(ourhost, sizeof ourhost);
      if (!(hp = gethostbyname(ourhost))) {
  	error("gethostbyname: %s", ourhost);
! 	if (ourname = (char **)calloc((unsigned)2, sizeof (char *)))
  	    strdup(ourname[0], ourhost);
      } else {
  	int n = 0;
***************
*** 188,194 ****
  	for (p = hp->h_name; p && *p; p = hp->h_aliases[n++])
  	    if (strcmp(ourhost, p)) /* if host name is different */
  		cnt++;
! 	if (ourname = calloc((unsigned)cnt, sizeof (char *))) {
  	    ourname[--cnt] = NULL;
  	    for (p = hp->h_name; p && *p && n >= 0; p = hp->h_aliases[--n])
  		if (strcmp(ourhost, p)) /* if host name is different */
--- 188,194 ----
  	for (p = hp->h_name; p && *p; p = hp->h_aliases[n++])
  	    if (strcmp(ourhost, p)) /* if host name is different */
  		cnt++;
! 	if (ourname = (char **)calloc((unsigned)cnt, sizeof (char *))) {
  	    ourname[--cnt] = NULL;
  	    for (p = hp->h_name; p && *p && n >= 0; p = hp->h_aliases[--n])
  		if (strcmp(ourhost, p)) /* if host name is different */
***************
*** 199,205 ****
      endhostent();
  #endif /* BSD */
  #ifdef SYSV
!     ourname = calloc((unsigned)2, sizeof (char *));
      if ((uname (&ourhost) >= 0) && (*ourhost.nodename))
  	ourname[0] = savestr(ourhost.nodename);
      else {
--- 199,205 ----
      endhostent();
  #endif /* BSD */
  #ifdef SYSV
!     ourname = (char **)calloc((unsigned)2, sizeof (char *));
      if ((uname (&ourhost) >= 0) && (*ourhost.nodename))
  	ourname[0] = savestr(ourhost.nodename);
      else {
*** mush-6.4/lock.c	Fri Mar 24 09:58:38 1989
--- lock.c	Wed Apr 12 10:44:42 1989
***************
*** 32,39 ****
  #else
      setgid(sgid);
  #endif /* BSD */
  #ifdef M_XENIX
!     if (strcmp(spoolfile, mailfile) == 0)
  	(void) sprintf(buf, "/tmp/%.10s.mlk", login);
      else
  #endif /* M_XENIX */
--- 32,47 ----
  #else
      setgid(sgid);
  #endif /* BSD */
+ #ifdef SYSV
+     /* Only the spoolfile needs to be dot_locked -- other files are
+      * handled by lock_file, below.  To avoid collisions with 14-char
+      * 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 */
***************
*** 73,82 ****
  char *filename;
  FILE *fp;
  {
! #ifdef MMDF
      if (Access(filename, W_OK) || lk_lock(filename, NULL, NULL, 0))
  	return -1;
! #else /* MMDF */
      int fd = fileno(fp);
  
      if (debug && do_set(set_options, "deadlock")) {
--- 81,90 ----
  char *filename;
  FILE *fp;
  {
! #ifdef LCKDFLDIR
      if (Access(filename, W_OK) || lk_lock(filename, NULL, NULL, 0))
  	return -1;
! #else /* LCKDFLDIR */
      int fd = fileno(fp);
  
      if (debug && do_set(set_options, "deadlock")) {
***************
*** 99,119 ****
  	on_intr();
  	while (isoff(glob_flags, WAS_INTR) && flock(fd, LOCK_EX | LOCK_NB)) {
  	    if (errno == EWOULDBLOCK)
! 		if (!cnt)
! 		    print("waiting to lock \"%s\"", filename);
  		else
! 		    cnt++, print(".");
  	    else {
! 		error("Unable to lock %s", filename);
  		off_intr();
  		return -1;
  	    }
  	    sleep(1);
  	}
  	if (cnt)
  	    print("\n");
  	off_intr();
! 	if (ison(glob_flags, WAS_INTR))
  	    return -1;
      }
  #else /* BSD */
--- 107,129 ----
  	on_intr();
  	while (isoff(glob_flags, WAS_INTR) && flock(fd, LOCK_EX | LOCK_NB)) {
  	    if (errno == EWOULDBLOCK)
! 		if (!cnt++)
! 		    print("\nwaiting to lock");
  		else
! 		    print(".");
  	    else {
! 		error("Unable to lock \"%s\"", filename);
  		off_intr();
  		return -1;
  	    }
+ 	    fflush(stdout);
  	    sleep(1);
  	}
  	if (cnt)
  	    print("\n");
+ 	cnt = (ison(glob_flags, WAS_INTR) != 0);
  	off_intr();
! 	if (cnt)
  	    return -1;
      }
  #else /* BSD */
***************
*** 121,127 ****
  	print("There is no supported file locking function!\n");
  #endif /* BSD */
  #endif /* SYSV */
! #endif /* MMDF */
      return 0;
  }
  
--- 131,137 ----
  	print("There is no supported file locking function!\n");
  #endif /* BSD */
  #endif /* SYSV */
! #endif /* LCKDFLDIR */
      return 0;
  }
  
***************
*** 129,140 ****
  close_lock(filename, fp)
  char *filename;
  FILE *fp;
! #ifdef MMDF
  {
      (void) lk_unlock(filename, NULL, NULL);
      fclose(fp);
  }
! #endif /* MMDF */
  {
  #ifdef DOT_LOCK
      char buf[MAXPATHLEN];
--- 139,150 ----
  close_lock(filename, fp)
  char *filename;
  FILE *fp;
! #ifdef LCKDFLDIR
  {
      (void) lk_unlock(filename, NULL, NULL);
      fclose(fp);
  }
! #else /* LCKDFLDIR */
  {
  #ifdef DOT_LOCK
      char buf[MAXPATHLEN];
***************
*** 168,170 ****
--- 178,181 ----
  #endif /* SYSV */
      fclose(fp);
  }
+ #endif /* LCKDFLDIR */
*** mush-6.4/loop.c	Fri Mar 24 10:14:49 1989
--- loop.c	Wed Apr 12 10:39:06 1989
***************
*** 21,27 ****
  #define isdelimeter(c)	(index(" \t;|", c))
  
  char *alias_expand(), *hist_expand(), *reference_hist(), *hist_from_str();
! char **calloc();
  
  struct history {
      int histno;
--- 21,27 ----
  #define isdelimeter(c)	(index(" \t;|", c))
  
  char *alias_expand(), *hist_expand(), *reference_hist(), *hist_from_str();
! char *calloc();
  
  struct history {
      int histno;
***************
*** 419,425 ****
  	    continue;
  
  	/* create a new argv containing this (possible subset) of argv */
! 	if (!(argv = calloc((unsigned)(i+1), sizeof (char *))))
  	    continue;
  	sep = n + i;
  	while (i--)
--- 419,425 ----
  	    continue;
  
  	/* create a new argv containing this (possible subset) of argv */
! 	if (!(argv = (char **)calloc((unsigned)(i+1), sizeof (char *))))
  	    continue;
  	sep = n + i;
  	while (i--)
***************
*** 850,856 ****
      if (!*argc)
  	return DUBL_NULL;
      /* newargv[*argc] = NULL; */
!     if (!(argv = calloc((unsigned)((*argc)+1), sizeof(char *)))) {
  	perror("mk_argv: calloc");
  	return DUBL_NULL;
      }
--- 850,856 ----
      if (!*argc)
  	return DUBL_NULL;
      /* newargv[*argc] = NULL; */
!     if (!(argv = (char **)calloc((unsigned)((*argc)+1), sizeof(char *)))) {
  	perror("mk_argv: calloc");
  	return DUBL_NULL;
      }
*** mush-6.4/macros.c	Fri Mar 24 10:02:53 1989
--- macros.c	Wed Apr 12 10:45:06 1989
***************
*** 7,14 ****
  
  struct cmd_map	*mac_stack, *mac_hide;
  
- extern char *calloc();
- 
  /*
   * print current binding to macro mappings if "str" is NULL.
   * else return the string "x_str" which the str is bound to.
--- 7,12 ----
*** mush-6.4/makefile.bsd	Fri Mar 24 09:58:40 1989
--- makefile.bsd	Tue Apr 18 09:42:59 1989
***************
*** 6,19 ****
  SRCS= main.c init.c misc.c mail.c hdrs.c execute.c commands.c print.c dates.c \
        signals.c setopts.c msgs.c pick.c sort.c expr.c folders.c \
        loop.c help.c viewopts.c curses.c curs_io.c bind.c file.c strings.c \
!       lock.c macros.c options.c addrs.c
  OBJS= main.o init.o misc.o mail.o hdrs.o execute.o commands.o print.o file.o \
        signals.o setopts.o msgs.o pick.o sort.o expr.o strings.o \
        folders.o dates.o loop.o help.o viewopts.o curses.o curs_io.o bind.o \
!       lock.o macros.o options.o addrs.o
  
  HELP_FILES= README README-6.0 README-6.1 README-6.2 README-6.3 README-6.4 \
! 	mush.1 Mailrc Gnurc cmd_help sample.mushrc advanced.mushrc
  
  MAKES= makefile.bsd makefile.xenix makefile.sys.v
  
--- 6,19 ----
  SRCS= main.c init.c misc.c mail.c hdrs.c execute.c commands.c print.c dates.c \
        signals.c setopts.c msgs.c pick.c sort.c expr.c folders.c \
        loop.c help.c viewopts.c curses.c curs_io.c bind.c file.c strings.c \
!       lock.c macros.c options.c addrs.c malloc.c
  OBJS= main.o init.o misc.o mail.o hdrs.o execute.o commands.o print.o file.o \
        signals.o setopts.o msgs.o pick.o sort.o expr.o strings.o \
        folders.o dates.o loop.o help.o viewopts.o curses.o curs_io.o bind.o \
!       lock.o macros.o options.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.bsd makefile.xenix makefile.sys.v
  
*** mush-6.4/makefile.sun	Fri Mar 24 09:58:41 1989
--- makefile.sun	Tue Apr 18 09:45:04 1989
***************
*** 6,18 ****
  SRCS= main.c init.c misc.c mail.c hdrs.c execute.c commands.c rite.c \
        select.c doproc.c print.c signals.c addrs.c setopts.c msgs.c \
        hdr_procs.c tool.c hdr_panel.c main_panel.c help.c viewopts.c sort.c \
!       pick.c fkeys.c expr.c folders.c dates.c loop.c edit_menu.c \
        curses.c curs_io.c bind.c file.c strings.c lock.c macros.c options.c
  
  OBJS= main.o init.o misc.o mail.o hdrs.o execute.o commands.o rite.o \
        select.o doproc.o print.o signals.o addrs.o setopts.o msgs.o \
        hdr_procs.o tool.o hdr_panel.o main_panel.o help.o viewopts.o sort.o \
!       pick.o fkeys.o expr.o folders.o dates.o loop.o edit_menu.o \
        curses.o curs_io.o bind.o file.o strings.o lock.o macros.o options.o
  
  IMAGES= mail.icon.1 mail.icon.2 check.pr cycle.pr envelope.pr glasses.pr \
--- 6,18 ----
  SRCS= main.c init.c misc.c mail.c hdrs.c execute.c commands.c rite.c \
        select.c doproc.c print.c signals.c addrs.c setopts.c msgs.c \
        hdr_procs.c tool.c hdr_panel.c main_panel.c help.c viewopts.c sort.c \
!       pick.c fkeys.c expr.c folders.c dates.c loop.c edit_menu.c malloc.c\
        curses.c curs_io.c bind.c file.c strings.c lock.c macros.c options.c
  
  OBJS= main.o init.o misc.o mail.o hdrs.o execute.o commands.o rite.o \
        select.o doproc.o print.o signals.o addrs.o setopts.o msgs.o \
        hdr_procs.o tool.o hdr_panel.o main_panel.o help.o viewopts.o sort.o \
!       pick.o fkeys.o expr.o folders.o dates.o loop.o edit_menu.o malloc.o\
        curses.o curs_io.o bind.o file.o strings.o lock.o macros.o options.o
  
  IMAGES= mail.icon.1 mail.icon.2 check.pr cycle.pr envelope.pr glasses.pr \
***************
*** 19,25 ****
  	write.pr up.arrow.pr dn.arrow.pr coffee.cup.pr
  
  HELP_FILES= README README-6.0 README-6.1 README-6.2 README-6.3 README-6.4 \
! 	mush.1 Mailrc Gnurc sample.mushrc advanced.mushrc cmd_help tool_help
  
  MAKES= makefile.sun makefile.bsd makefile.sys.v makefile.xenix
  
--- 19,26 ----
  	write.pr up.arrow.pr dn.arrow.pr coffee.cup.pr
  
  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 sample.mushrc advanced.mushrc \
! 	cmd_help tool_help
  
  MAKES= makefile.sun makefile.bsd makefile.sys.v makefile.xenix
  
*** mush-6.4/makefile.sys.v	Fri Mar 24 09:58:41 1989
--- makefile.sys.v	Tue Apr 18 09:43:31 1989
***************
*** 7,21 ****
  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 help.c file.c strings.c macros.c addrs.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 help.o file.o strings.o macros.o addrs.o
  
  HELP_FILES= README README-6.0 README-6.1 README-6.2 README-6.3 README-6.4 \
! 	mush.1 Mailrc Gnurc cmd_help sample.mushrc advanced.mushrc
  MAKES= makefile.sys.v makefile.xenix makefile.bsd
  
  # Sun OS systems who wish to compile with sys-v options:
--- 7,23 ----
  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 help.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 help.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
  
  # Sun OS systems who wish to compile with sys-v options:
*** mush-6.4/makefile.xenix	Fri Mar 24 09:58:42 1989
--- makefile.xenix	Tue Apr 18 09:43:41 1989
***************
*** 14,36 ****
  SRCS5= commands.c setopts.c hdrs.c
  SRCS6= mail.c print.c
  SRCS7= curses.c curs_io.c
! SRCS8= file.c strings.c
  SRCS9= lock.c macros.c addrs.c
  OBJS= main.o init.o misc.o mail.o hdrs.o execute.o commands.o print.o file.o \
        signals.o setopts.o msgs.o pick.o sort.o expr.o strings.o \
        folders.o dates.o loop.o help.o viewopts.o bind.o curses.o curs_io.o \
!       lock.o macros.o options.o addrs.o
  HELP_FILES= README README-6.0 README-6.1 README-6.2 README-6.3 README-6.4 \
! 	mush.1 Mailrc Gnurc cmd_help sample.mushrc advanced.mushrc
  MAKES= makefile.sys.v makefile.xenix makefile.bsd
  
  # Memory model.  Use -M3e for 80386 machines.
! # Use -Mle for 80286 machines.
  MODEL= -M3e
  
  #
  # 80286 xenix may use this LDFLAGS define:
! #LDFLAGS= -X -lx -Mle -F 4000
  LDFLAGS= -X -lx -M3
  
  CFLAGS= $(MODEL) -O -DSYSV -DCURSES -DREGCMP -DUSG 
--- 14,36 ----
  SRCS5= commands.c setopts.c hdrs.c
  SRCS6= mail.c print.c
  SRCS7= curses.c curs_io.c
! SRCS8= file.c strings.c malloc.c
  SRCS9= lock.c macros.c addrs.c
  OBJS= main.o init.o misc.o mail.o hdrs.o execute.o commands.o print.o file.o \
        signals.o setopts.o msgs.o pick.o sort.o expr.o strings.o \
        folders.o dates.o loop.o help.o viewopts.o bind.o curses.o curs_io.o \
!       lock.o macros.o options.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
  
  # Memory model.  Use -M3e for 80386 machines.
! # Use -M2le -Mt32 for 80286 machines.
  MODEL= -M3e
  
  #
  # 80286 xenix may use this LDFLAGS define:
! #LDFLAGS= -X -lx -M2le -Mt32 -F 8000 -SEG 256
  LDFLAGS= -X -lx -M3
  
  CFLAGS= $(MODEL) -O -DSYSV -DCURSES -DREGCMP -DUSG 
*** mush-6.4/malloc.c	Tue Apr 18 10:13:15 1989
--- malloc.c	Wed Apr 12 10:40:40 1989
***************
*** 0 ****
--- 1,433 ----
+ /*
+  * This is a slightly modified version of the malloc.c distributed with
+  * Larry Wall's perl 2.0 sources.  RCS and sccs information has been
+  * retained, but modified so that it will not actually affect checkin
+  * or checkout of this file if revision control is used for Mush.
+  *
+  * Other changes include:
+  *	Removal of the ASSERT macro and other code related to the
+  *	preprocessor definition "debug"
+  *
+  *	Replaced #include "perl.h" with #include "mush.h" (guess why)
+  *
+  *	Warning messages are now printed with the mush Debug macro,
+  *	that is, they are normally suppressed
+  *
+  *	Added a calloc() function, using mush's bzero()
+  *
+  * Also, the mush xfree() and free_vec() functions have been moved here.
+  */
+ 
+ #include "mush.h"
+ 
+ /*
+  * Compile this portion only if configured for INTERNAL_MALLOC
+  */
+ #ifdef INTERNAL_MALLOC
+ #ifdef SYSV
+ #include <memory.h>
+ #define bcopy(src,dst,len)	memcpy(dst,src,len)
+ #endif /* SYSV */
+ #define free xfree	/* rename free for mush purposes */
+ 
+ /* Begin modified perl malloc.c */
+ 
+ /* Header: malloc.c,v 2.0 88/06/05 00:09:16 root Exp
+  *
+  * Log:	malloc.c,v
+  * Revision 2.0  88/06/05  00:09:16  root
+  * Baseline version 2.0.
+  * 
+  */
+ 
+ #ifndef lint
+ static char sccsid[] = "malloc.c	4.3 (Berkeley) 9/16/83";
+ #endif /* !lint */
+ 
+ #define RCHECK
+ /*
+  * malloc.c (Caltech) 2/21/82
+  * Chris Kingsley, kingsley@cit-20.
+  *
+  * This is a very fast storage allocator.  It allocates blocks of a small 
+  * number of different sizes, and keeps free lists of each size.  Blocks that
+  * don't exactly fit are passed up to the next larger size.  In this 
+  * implementation, the available sizes are 2^n-4 (or 2^n-12) bytes long.
+  * This is designed for use in a program that uses vast quantities of memory,
+  * but bombs when it runs out. 
+  */
+ 
+ /* I don't much care whether these are defined in sys/types.h--LAW */
+ 
+ #undef u_char
+ #define u_char unsigned char
+ #undef u_int
+ #define u_int unsigned int
+ #undef u_short
+ #define u_short unsigned short
+ 
+ /*
+  * The overhead on a block is at least 4 bytes.  When free, this space
+  * contains a pointer to the next free block, and the bottom two bits must
+  * be zero.  When in use, the first byte is set to MAGIC, and the second
+  * byte is the size index.  The remaining bytes are for alignment.
+  * If range checking is enabled and the size of the block fits
+  * in two bytes, then the top two bytes hold the size of the requested block
+  * plus the range checking words, and the header word MINUS ONE.
+  */
+ union	overhead {
+ 	union	overhead *ov_next;	/* when free */
+ 	struct {
+ 		u_char	ovu_magic;	/* magic number */
+ 		u_char	ovu_index;	/* bucket # */
+ #ifdef RCHECK
+ 		u_short	ovu_size;	/* actual block size */
+ 		u_int	ovu_rmagic;	/* range magic number */
+ #endif /* RCHECK */
+ 	} ovu;
+ #define	ov_magic	ovu.ovu_magic
+ #define	ov_index	ovu.ovu_index
+ #define	ov_size		ovu.ovu_size
+ #define	ov_rmagic	ovu.ovu_rmagic
+ };
+ 
+ #define	MAGIC		0xff		/* magic # on accounting info */
+ #define OLDMAGIC	0x7f		/* same after a free() */
+ #define RMAGIC		0x55555555	/* magic # on range info */
+ #ifdef RCHECK
+ #define	RSLOP		sizeof (u_int)
+ #else /* !RCHECK */
+ #define	RSLOP		0
+ #endif /* RCHECK */
+ 
+ /*
+  * nextf[i] is the pointer to the next free block of size 2^(i+3).  The
+  * smallest allocatable block is 8 bytes.  The overhead information
+  * precedes the data area returned to the user.
+  */
+ #define	NBUCKETS 30
+ static	union overhead *nextf[NBUCKETS];
+ extern	char *sbrk();
+ 
+ #ifdef MSTATS
+ /*
+  * nmalloc[i] is the difference between the number of mallocs and frees
+  * for a given block size.
+  */
+ static	u_int nmalloc[NBUCKETS];
+ #endif /* MSTATS */
+ 
+ char *
+ malloc(nbytes)
+ 	register unsigned nbytes;
+ {
+   	register union overhead *p;
+   	register int bucket = 0;
+   	register unsigned shiftr;
+ 
+ 	/*
+ 	 * Convert amount of memory requested into
+ 	 * closest block size stored in hash buckets
+ 	 * which satisfies request.  Account for
+ 	 * space used per block for accounting.
+ 	 */
+   	nbytes += sizeof (union overhead) + RSLOP;
+   	nbytes = (nbytes + 3) &~ 3; 
+   	shiftr = (nbytes - 1) >> 2;
+ 	/* apart from this loop, this is O(1) */
+   	while (shiftr >>= 1)
+   		bucket++;
+ 	/*
+ 	 * If nothing in hash bucket right now,
+ 	 * request more memory from the system.
+ 	 */
+   	if (nextf[bucket] == (union overhead *)0)    
+   		morecore(bucket);
+   	if ((p = (union overhead *)nextf[bucket]) == (union overhead *)0)
+   		return (NULL);
+ 	/* remove from linked list */
+ 	if (*((int*)p) > 0x10000000)
+ 	    Debug("Corrupt malloc ptr 0x%x at 0x%x\n",*((int*)p),p);
+   	nextf[bucket] = nextf[bucket]->ov_next;
+ 	p->ov_magic = MAGIC;
+ 	p->ov_index= bucket;
+ #ifdef MSTATS
+   	nmalloc[bucket]++;
+ #endif /* MSTATS */
+ #ifdef RCHECK
+ 	/*
+ 	 * Record allocated size of block and
+ 	 * bound space with magic numbers.
+ 	 */
+   	if (nbytes <= 0x10000)
+ 		p->ov_size = nbytes - 1;
+ 	p->ov_rmagic = RMAGIC;
+   	*((u_int *)((caddr_t)p + nbytes - RSLOP)) = RMAGIC;
+ #endif /* RCHECK */
+   	return ((char *)(p + 1));
+ }
+ 
+ /*
+  * Allocate more memory to the indicated bucket.
+  */
+ static
+ morecore(bucket)
+ 	register bucket;
+ {
+   	register union overhead *op;
+   	register int rnu;       /* 2^rnu bytes will be requested */
+   	register int nblks;     /* become nblks blocks of the desired size */
+ 	register int siz;
+ 
+   	if (nextf[bucket])
+   		return;
+ 	/*
+ 	 * Insure memory is allocated
+ 	 * on a page boundary.  Should
+ 	 * make getpageize call?
+ 	 */
+   	op = (union overhead *)sbrk(0);
+   	if ((int)op & 0x3ff)
+   		sbrk(1024 - ((int)op & 0x3ff));
+ 	/* take 2k unless the block is bigger than that */
+   	rnu = (bucket <= 8) ? 11 : bucket + 3;
+   	nblks = 1 << (rnu - (bucket + 3));  /* how many blocks to get */
+   	if (rnu < bucket)
+ 		rnu = bucket;
+ 	op = (union overhead *)sbrk(1 << rnu);
+ 	/* no more room! */
+   	if ((int)op == -1)
+   		return;
+ 	/*
+ 	 * Round up to minimum allocation size boundary
+ 	 * and deduct from block count to reflect.
+ 	 */
+   	if ((int)op & 7) {
+   		op = (union overhead *)(((int)op + 8) &~ 7);
+   		nblks--;
+   	}
+ 	/*
+ 	 * Add new memory allocated to that on
+ 	 * free list for this hash bucket.
+ 	 */
+   	nextf[bucket] = op;
+   	siz = 1 << (bucket + 3);
+   	while (--nblks > 0) {
+ 		op->ov_next = (union overhead *)((caddr_t)op + siz);
+ 		op = (union overhead *)((caddr_t)op + siz);
+   	}
+ }
+ 
+ void
+ free(cp)
+ 	char *cp;
+ {   
+   	register int size;
+ 	register union overhead *op;
+ 
+   	if (cp == NULL || debug < 5)
+   		return;
+ 	op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
+ 	if (op->ov_magic != MAGIC) {
+ 		Debug("%s free() ignored\n",
+ 		    op->ov_magic == OLDMAGIC ? "Duplicate" : "Bad");
+ 		return;				/* sanity */
+ 	}
+ 	op->ov_magic = OLDMAGIC;
+ #ifdef RCHECK
+   	if (op->ov_rmagic != RMAGIC) {
+ 		Debug("Range check failed, free() ignored\n");
+ 		return;
+ 	}
+ 	if (op->ov_index <= 13 &&
+ 	    *(u_int *)((caddr_t)op + op->ov_size + 1 - RSLOP) != RMAGIC) {
+ 		Debug("Range check failed, free() ignored\n");
+ 		return;
+ 	}
+ #endif /* RCHECK */
+   	if (op->ov_index >= NBUCKETS)
+ 	    return;
+   	size = op->ov_index;
+ 	op->ov_next = nextf[size];
+   	nextf[size] = op;
+ #ifdef MSTATS
+   	nmalloc[size]--;
+ #endif /* MSTATS */
+ }
+ 
+ /*
+  * When a program attempts "storage compaction" as mentioned in the
+  * old malloc man page, it realloc's an already freed block.  Usually
+  * this is the last block it freed; occasionally it might be farther
+  * back.  We have to search all the free lists for the block in order
+  * to determine its bucket: 1st we make one pass thru the lists
+  * checking only the first block in each; if that fails we search
+  * ``reall_srchlen'' blocks in each list for a match (the variable
+  * is extern so the caller can modify it).  If that fails we just copy
+  * however many bytes was given to realloc() and hope it's not huge.
+  */
+ int reall_srchlen = 4;	/* 4 should be plenty, -1 =>'s whole list */
+ 
+ char *
+ realloc(cp, nbytes)
+ 	char *cp; 
+ 	unsigned nbytes;
+ {   
+   	register u_int onb;
+ 	union overhead *op;
+   	char *res;
+ 	register int i;
+ 	int was_alloced = 0;
+ 
+   	if (cp == NULL)
+   		return (malloc(nbytes));
+ 	op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
+ 	if (op->ov_magic == MAGIC) {
+ 		was_alloced++;
+ 		i = op->ov_index;
+ 	} else {
+ 		/*
+ 		 * Already free, doing "compaction".
+ 		 *
+ 		 * Search for the old block of memory on the
+ 		 * free list.  First, check the most common
+ 		 * case (last element free'd), then (this failing)
+ 		 * the last ``reall_srchlen'' items free'd.
+ 		 * If all lookups fail, then assume the size of
+ 		 * the memory block being realloc'd is the
+ 		 * smallest possible.
+ 		 */
+ 		if ((i = findbucket(op, 1)) < 0 &&
+ 		    (i = findbucket(op, reall_srchlen)) < 0)
+ 			i = 0;
+ 	}
+ 	onb = (1 << (i + 3)) - sizeof (*op) - RSLOP;
+ 	/* avoid the copy if same size block */
+ 	if (was_alloced &&
+ 	    nbytes <= onb && nbytes > (onb >> 1) - sizeof(*op) - RSLOP)
+ 		return(cp);
+   	if ((res = malloc(nbytes)) == NULL)
+   		return (NULL);
+   	if (cp != res)			/* common optimization */
+ 		bcopy(cp, res, (nbytes < onb) ? nbytes : onb);
+   	if (was_alloced)
+ 		free(cp);
+   	return (res);
+ }
+ 
+ /*
+  * Search ``srchlen'' elements of each free list for a block whose
+  * header starts at ``freep''.  If srchlen is -1 search the whole list.
+  * Return bucket number, or -1 if not found.
+  */
+ static
+ findbucket(freep, srchlen)
+ 	union overhead *freep;
+ 	int srchlen;
+ {
+ 	register union overhead *p;
+ 	register int i, j;
+ 
+ 	for (i = 0; i < NBUCKETS; i++) {
+ 		j = 0;
+ 		for (p = nextf[i]; p && j != srchlen; p = p->ov_next) {
+ 			if (p == freep)
+ 				return (i);
+ 			j++;
+ 		}
+ 	}
+ 	return (-1);
+ }
+ 
+ #ifdef MSTATS
+ /*
+  * mstats - print out statistics about malloc
+  * 
+  * Prints two lines of numbers, one showing the length of the free list
+  * for each size category, the second showing the number of mallocs -
+  * frees for each size category.
+  */
+ mstats(s)
+ 	char *s;
+ {
+   	register int i, j;
+   	register union overhead *p;
+   	int totfree = 0,
+   	totused = 0;
+ 
+   	Debug("Memory allocation statistics %s\nfree:\t", s);
+   	for (i = 0; i < NBUCKETS; i++) {
+   		for (j = 0, p = nextf[i]; p; p = p->ov_next, j++)
+   			;
+   		Debug(" %d", j);
+   		totfree += j * (1 << (i + 3));
+   	}
+   	Debug("\nused:\t");
+   	for (i = 0; i < NBUCKETS; i++) {
+   		Debug( " %d", nmalloc[i]);
+   		totused += nmalloc[i] * (1 << (i + 3));
+   	}
+   	Debug("\n\tTotal in use: %d, total free: %d\n",
+ 	    totused, totfree);
+ }
+ #endif /* MSTATS */
+ 
+ /* End of modified perl malloc.c */
+ 
+ char *
+ calloc(nitems, itemsz)
+ u_int nitems, itemsz;
+ {
+     char *cp;
+ 
+     cp = malloc(nitems * itemsz);
+     bzero(cp, nitems * itemsz);
+     return cp;
+ }
+ 
+ /* These are needed for curses and other external linkage */
+ 
+ #undef free
+ 
+ char *
+ cfree(p, n, s)
+ char *p;
+ u_int n, s;
+ {
+     xfree(p);
+ }
+ 
+ char *
+ free(p)
+ char *p;
+ {
+     xfree(p);
+ }
+ 
+ #else /* INTERNAL_MALLOC */
+ 
+ char *stackbottom;	/* set first thing in main() */
+ 
+ void
+ xfree(cp)
+ char *cp;
+ {
+     extern char end[];
+ 
+     if (cp >= end && cp < stackbottom && cp < (char *) &cp && debug < 5)
+ 	free(cp);
+ }
+ 
+ #endif /* INTERNAL_MALLOC */
+ 
+ void
+ free_vec(argv)
+ char **argv;
+ {
+     register int n;
+     if (!argv)
+ 	return;
+     for (n = 0; argv[n]; n++)
+ 	xfree(argv[n]);
+     xfree((char *)argv);
+ }
*** mush-6.4/misc.c	Fri Mar 24 10:05:44 1989
--- misc.c	Thu Apr 13 16:52:51 1989
***************
*** 282,291 ****
  }
  
  /*
!  * change the status flags for messages.
   *    flags * P		preserves all messages.
   *    flags 4-7 -S	remove the "saved" status on msgs 4-7
   *    flags +r		add the replied-to bit on the current message.
   */
  msg_flags(c, v, list)
  register char **v, *list;
--- 282,293 ----
  }
  
  /*
!  * Change the status flags for messages.
   *    flags * P		preserves all messages.
   *    flags 4-7 -S	remove the "saved" status on msgs 4-7
   *    flags +r		add the replied-to bit on the current message.
+  * The `-' argument for removing flags can be escaped as "\-" to
+  * prevent its interpretation as part of a message list.
   */
  msg_flags(c, v, list)
  register char **v, *list;
***************
*** 316,321 ****
--- 318,324 ----
  			    turnon(newflag, REPLIED);
  		    when '+' : modify = 1;
  		    when '-' : modify = 2;
+ 		    when '\\' : ; /* skip to the next flag */
  		    otherwise: return help(0, "msg_flags", cmd_help);
  		}
      }
***************
*** 380,386 ****
  #ifdef SUNTOOL
      if (istool) {
  	if (buf && !start_pager)
! 	    Addstr(buf);
  	return 0;
      }
  #endif /* SUNTOOL */
--- 383,392 ----
  #ifdef SUNTOOL
      if (istool) {
  	if (buf && !start_pager)
! 	    if (istool < 2)
! 		printf(buf), fflush(stdout);
! 	    else
! 		Addstr(buf);
  	return 0;
      }
  #endif /* SUNTOOL */
***************
*** 546,551 ****
--- 552,558 ----
  	    wprint("Signing letter... ");
  	} else
  	    wprint("Using alternate signature... ");
+ 	(void) fseek(fp, 0L, 2); /* guarantee position at end of file */
  	/* precede _file_ signatures ONLY with "\n-- \n" */
  	if (buf[0] != '\\' && buf[0] != '$')
  	    fputs("\n-- \n", fp);
***************
*** 552,558 ****
  	else
  	    fputc('\n', fp);
  	fflush(fp);
- 	(void) fseek(fp, 0L, 2); /* guarantee position at end of file */
  	if (*buf == '$')
  	    if (!(p = do_set(set_options, buf)))
  		wprint("(%s isn't set -- letter not signed)\n", buf);
--- 559,564 ----
*** mush-6.4/kit.check	Tue Apr 18 17:29:04 1989
--- kit.check	Tue Apr 18 17:29:04 1989
***************
*** 1 ****
!  Part2-check 
--- 1 ----
!  Part3 
-- 
Bart Schaefer       "And if you believe that, you'll believe anything."
							-- DangerMouse
CSNET / Internet                schaefer@cse.ogc.edu
UUCP                            ...{sun,tektronix,verdix}!ogccse!schaefer