home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume14 / mush / patch01 next >
Encoding:
Text File  |  1990-07-15  |  47.7 KB  |  1,608 lines

  1. Newsgroups: comp.sources.misc
  2. subject: v14i005: Submission: Patch #2 for Mush 7.1
  3. from: schaefer@cse.ogi.edu (Barton E. Schaefer)
  4. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  5.  
  6. Posting-number: Volume 14, Issue 5
  7. Submitted-by: schaefer@cse.ogi.edu (Barton E. Schaefer)
  8. Archive-name: mush/patch01
  9.  
  10. Mush was posted to comp.sources.misc at patchlevel 1.  You can omit
  11. everything up through the @OFF line when posting this; that line is
  12. a directive to my mail server to prevent it from recognizing the
  13. later @-directives should this bounce back to me.
  14.  
  15. @OFF
  16.  
  17. This is Official Patch #2 for Mush 7.1.  Mush was previously posted
  18. to comp.sources.misc at patch level 1.  A copy of this message has
  19. been sent to the comp.sources.misc moderator for posting and archiving.
  20.  
  21. As usual, complete sources for Mush (already including the changes in
  22. this patch) can be obtained via anonymous ftp from either of:
  23.  
  24.             ucbvax.berkeley.edu:pub/mailers/mush-7.1.tar.Z
  25.  
  26.                   cse.ogi.edu:pub/mush/mush-7.1.tar.Z
  27.  
  28. Be aware that a version of mush with RELEASE_DATE (from version.h) of
  29. 7/10/90 was incorrectly made available for ftp for approximately 24
  30. hours spanning the night of July 10th and most of the day July 11th.
  31. The correct RELEASE_DATE is 7/11/90.  If you have the 7/10 version,
  32. please pick up the more recent one.  The only change was to enable
  33. walking menus by default (see below); the functionality is the same.
  34. This affects Sun systems only, but for purposes of patching you should
  35. obtain the correct version.
  36.  
  37. If you need any earlier patches, they are available for ftp from
  38. cse.ogi.edu, or you can send E-mail to me:
  39.  
  40.                          schaefer@cse.ogi.edu
  41.      {decwrl,garp,harvard,rutgers,sdsu,ucsd,unmvax}!ogicse!schaefer
  42.  
  43. Include in your message a line of the form
  44.  
  45. @PATCH patch-number path-from-ogicse-to-you
  46.  
  47. where patch-number is the number of the patch you need (digit, 1 or 2)
  48. and path-from-ogicse-to-you is either your Internet domain address or
  49. a UUCP path from site ogicse to you at your site.  There continue to
  50. be sendmail configuration problems at ogicse so please do not use mixed
  51. UUCP and Internet addresses and do not use domain names (with `.'s) in
  52. UUCP paths.  Ogicse does do UUCP map lookups now, so user@site.UUCP will
  53. often work if your site is registered.  If you don't get your patches
  54. in 2 or 3 days, try again, but use a different path.
  55.  
  56. You may include one @PATCH line for each patch you need.
  57.  
  58. You can also recieve a complete set of sources by E-mail by including
  59. a line of the form
  60.  
  61. @MUSH path-from-ogicse-to-you
  62.  
  63. where path-from-ogicse-to-you is as above.  You need not request both
  64. source and patches; the source you receive will include all current
  65. patches.  Sources are shipped as a 9-part compressed tar file, encoded
  66. for mailing with the "btoa" utility.  You will receive instructions
  67. explaining how to unpack the tar file in a separate message.
  68.  
  69. CSNet also operates an E-mail server that accesses anonymous ftp.  It
  70. may or may not be functional at this time.  To find out, and to get
  71. instructions for using the server, send a message to info-server@cs.net
  72. with the following lines in the text:
  73.  
  74. request: info
  75. topic: help-ftp
  76. request: end
  77.  
  78. Other information, plus questions and answers, on mush and mush patches
  79. is available from the mush-users mailing list, which is gatewayed in
  80. both directions with newsgroup comp.mail.mush.  The list currently
  81. resides at mush-users@garp.mit.edu, but may in the near future be moving
  82. to mush-users@apple.com.  Requests to be added to or deleted from the
  83. list should be sent to mush-users-request@garp.mit.edu, for now.
  84.  
  85. Changes/Fixes in this patch:
  86.  
  87.     The "undelete" operation in the Mailrc configuration file for UCB
  88.     Mail emulation has been adjusted to change the current message to
  89.     the last message in the undeleted list.  This causes one message
  90.     header summary to be printed whenever "undelete" is used.
  91.  
  92.     The "delete" operation in tool mode will now bring the new current
  93.     message onto the header display if and only if it was changed by
  94.     the deletion.
  95.  
  96.     Failure to truncate and recreate the editor temp file (e.g. by ~E)
  97.     is now detected and handled properly.
  98.  
  99.     Handling of "corrupted" spool mailboxes has been improved.  The
  100.     size of the spool file is now correctly recorded on new mail checks,
  101.     which should reduce the frequency of corruption reports on systems
  102.     that rely on DOT_LOCKing.  See also the locking corrections for MMDF,
  103.     noted below.  Once possible corruption is detected, new mail is no
  104.     longer checked, and upon quit or any folder change operation the
  105.     user is warned of the error.  If mush exits with the folder still
  106.     in a corrupt state, no update is done and the temporary copy is not
  107.     removed.  Further improvements in this error handling are planned
  108.     for future patches.
  109.  
  110.     SYSV systems that support BSD-style directory functions will now
  111.     correctly #include <dirent.h> if DIRECTORY is defined.
  112.  
  113.     Addresses containing UUCP !-paths ending in a domain-style @host
  114.     suffix will now be shifted to the right in header summaries to show 
  115.     as at least the last two hosts of the UUCP path tail.  This assumes
  116.     that the correct parsing of host2!host3!user@host1 is the same as
  117.     host1!host2!host3!user.
  118.  
  119.     Use of the file locking routines from the MMDF libraries has been
  120.     fixed.  Previous usage assumed that the MMDF routines locked in a
  121.     blocking manner, waiting until the lock was obtained; this is not
  122.     correct, and mush now loops until the lock is obtained.
  123.  
  124.     The "history" command now includes itself in the listing of the
  125.     last N history items when invoked with a numeric argument.  E.g.,
  126.     "history 5" will now show "history 5" as the most recent of the
  127.     five commands displayed.  This is consistent with "history -r 5"
  128.     and the csh usage.
  129.  
  130.     $verify is now treated as a multivalued variable.  In addition to
  131.     the old usage of verifying send/edit/discard on outgoing mail, it
  132.     is now necessary to "set verify=save" to enable the toolmode query
  133.     boxes that confirm save operations.  The other valid settings are
  134.     "mail" and no value, both of which behave as $verify did before.
  135.     To verify both outgoing mail and tool mode save operations, use
  136.     "set verify=mail,save".
  137.  
  138.     Stray alarm timers could be triggered by use of the "await" command
  139.     under SysV, resulting in core dumps.  This has been corrected.
  140.  
  141.     For SunView users, walking menus are now used for the file names
  142.     displayed under the <Folder> and <Save> items.  This neatens up
  143.     display of nested directory structures and avoids the menu size
  144.     limits of SunView in most cases.  Thanks to J. William Claypool
  145.     <unify!jwc@Sun.COM> for contributing 99% of this.  If you run into
  146.     any problems with this, compilation with -DNO_WALK_MENUS will
  147.     revert to the previous menu format.
  148.  
  149. *** /tmp/,RCSt1002753    Wed Jul 11 21:30:33 1990
  150. --- Mailrc    Wed Jul  4 15:36:14 1990
  151. ***************
  152. *** 52,59 ****
  153.   cmd se set
  154.   cmd shell sh
  155.   cmd so source
  156. ! cmd un undelete
  157. ! cmd unread 'flags \!* U'    # "unread" is undocumented in Mail
  158.   cmd uns unset
  159.   cmd vi v
  160.   cmd z 'z \!* + | from -'    # "z" changes current message in Mail
  161. --- 52,61 ----
  162.   cmd se set
  163.   cmd shell sh
  164.   cmd so source
  165. ! cmd u 'u \!* | pick -1 | from -' # "u" changes current message in Mail
  166. ! cmd un u
  167. ! cmd undelete u
  168. ! cmd unread 'flags \!* +U'    # "unread" is undocumented in Mail
  169.   cmd uns unset
  170.   cmd vi v
  171.   cmd z 'z \!* + | from -'    # "z" changes current message in Mail
  172. *** /tmp/,RCSt1002753    Wed Jul 11 21:32:30 1990
  173. --- README    Wed Jul 11 21:32:23 1990
  174. ***************
  175. *** 81,86 ****
  176. --- 81,89 ----
  177.       SUN_4_0, or SUN_4_1 depending on your SunOS version.  If SUNTOOL is
  178.       the only thing defined, SUN_4_0 will be used.
  179.   
  180. +     You may also choose to define NO_WALK_MENUS to disable walking menus
  181. +     for file names selectable from the "folder" and "save" command items.
  182.   If you are on a BSD UNIX machine:
  183.   
  184.       You should use the makefile.bsd makefile.
  185. *** /tmp/,RCSt1002753    Wed Jul 11 21:32:39 1990
  186. --- commands.c    Wed Jul 11 21:26:46 1990
  187. ***************
  188. *** 440,447 ****
  189. --- 440,451 ----
  190.       if (firstchar != 'c' && n > 0)
  191.           (void) do_hdrs(0, DUBL_NULL, NULL);
  192.       if (*mode == 'w' && n > 0) {
  193. + #ifndef NO_WALK_MENUS
  194. +         create_folder_menus();
  195. + #else /* NO_WALK_MENUS */
  196.           add_folder_to_menu(folder_item, 3);
  197.           add_folder_to_menu(save_item, 1);
  198. + #endif /* NO_WALK_MENUS */
  199.       }
  200.       }
  201.   #endif /* SUNTOOL */
  202. ***************
  203. *** 615,623 ****
  204.       /* goto next available message if current was just deleted.
  205.        * If there are no more messages, turnoff prnt_next.
  206.        */
  207. !     if (!iscurses && !undel && msg_bit(list, current_msg) &&
  208. !         (ison(msg[current_msg].m_flags, DELETE) ||
  209. !         ison(msg[current_msg].m_flags, SAVED)))
  210.       (void) next_msg();
  211.       else
  212.       prnt_next = 0;
  213. --- 619,625 ----
  214.       /* goto next available message if current was just deleted.
  215.        * If there are no more messages, turnoff prnt_next.
  216.        */
  217. !     if (!iscurses && !undel && msg_bit(list, current_msg))
  218.       (void) next_msg();
  219.       else
  220.       prnt_next = 0;
  221. ***************
  222. *** 632,643 ****
  223.       }
  224.   #ifdef SUNTOOL
  225.       if (istool && isoff(glob_flags, IS_PIPE)) {
  226. !     char *av[3], buf[8];
  227. !     /* do_hdrs(0, ...) repositions the display, so pass an arg */
  228. !     av[0] = "h";
  229. !     av[1] = sprintf(buf, "%d", n_array[0] + 1);
  230. !     av[2] = NULL;
  231. !     (void) do_hdrs(2, av, NULL);
  232.       }
  233.   #endif /* SUNTOOL */
  234.       return 0;
  235. --- 634,649 ----
  236.       }
  237.   #ifdef SUNTOOL
  238.       if (istool && isoff(glob_flags, IS_PIPE)) {
  239. !     if (current_msg != old_msg && !do_set(set_options, "show_deleted"))
  240. !         (void) do_hdrs(0, DUBL_NULL, NULL);
  241. !     else {
  242. !         char *av[3], buf[8];
  243. !         /* do_hdrs(0, ...) repositions the display, so pass an arg */
  244. !         av[0] = "h";
  245. !         av[1] = sprintf(buf, "%d", n_array[0] + 1);
  246. !         av[2] = NULL;
  247. !         (void) do_hdrs(2, av, NULL);
  248. !     }
  249.       }
  250.   #endif /* SUNTOOL */
  251.       return 0;
  252. *** /tmp/,RCSt1002753    Wed Jul 11 21:32:40 1990
  253. --- config.h-dist    Tue Jul 10 08:34:56 1990
  254. ***************
  255. *** 85,93 ****
  256.   /* If your mailer does not understand commas between addresses, you should
  257.    * define NO_COMMAS.  This includes pre-3.0 smail and default MTAs used on
  258.    * xenix, and sys-v systems.
  259. !  * This does NOT apply to MMDF or sendmail.
  260.    */
  261. ! /* #define NO_COMMAS /**/
  262.   
  263.   /*
  264.    * Most RFC822 compliant mailers (sendmail) will add the headers From:
  265. --- 85,95 ----
  266.   /* If your mailer does not understand commas between addresses, you should
  267.    * define NO_COMMAS.  This includes pre-3.0 smail and default MTAs used on
  268.    * xenix, and sys-v systems.
  269. !  * This does NOT apply to MMDF or sendmail, in most cases.
  270.    */
  271. ! #ifdef SUN_4_1        /* SunOS 4.1 has warped sendmail.cf */
  272. ! #define NO_COMMAS /**/
  273. ! #endif /* SUN_4_1
  274.   
  275.   /*
  276.    * Most RFC822 compliant mailers (sendmail) will add the headers From:
  277. *** /tmp/,RCSt1002753    Wed Jul 11 21:32:46 1990
  278. --- file.c    Thu May  3 12:44:05 1990
  279. ***************
  280. *** 217,223 ****
  281.       (void) fclose(*fp);
  282.       if (!(*fp = fopen(fname, "w")))
  283.           ret = -1;
  284. !     ret = 0;
  285.       (void) umask(omask);
  286.       return ret;
  287.       }
  288. --- 217,224 ----
  289.       (void) fclose(*fp);
  290.       if (!(*fp = fopen(fname, "w")))
  291.           ret = -1;
  292. !     else
  293. !         ret = 0;
  294.       (void) umask(omask);
  295.       return ret;
  296.       }
  297. *** /tmp/,RCSt1002753    Wed Jul 11 21:32:47 1990
  298. --- folders.c    Wed Jul  4 16:54:04 1990
  299. ***************
  300. *** 125,130 ****
  301. --- 125,131 ----
  302.       /* an error occured updating the folder */
  303.       return -1;
  304.       }
  305. +     turnoff(glob_flags, CORRUPTED);    /* copyback() was successful */
  306.       /* Assure that both oldfolder and mailfile are full paths */
  307.       if (strcmp(mailfile, buf) || !*oldfolder) {
  308.       n = 1; /* force load of new folder */
  309. *** /tmp/,RCSt1002753    Wed Jul 11 21:32:49 1990
  310. --- glob.h    Wed May 23 19:58:51 1990
  311. ***************
  312. *** 3,10 ****
  313. --- 3,14 ----
  314.   #endif /* BSD */
  315.   
  316.   #ifdef DIRECTORY
  317. + #ifdef SYSV /* Some SysV 3.0 or higher */
  318. + #include <dirent.h>
  319. + #else /* SYSV */
  320.   #include <sys/dir.h>
  321.   #define dirent direct
  322. + #endif
  323.   #else /* !DIRECTORY */
  324.   
  325.   /*
  326. *** /tmp/,RCSt1002753    Wed Jul 11 21:32:50 1990
  327. --- hdrs.c    Thu Jul  5 09:22:07 1990
  328. ***************
  329. *** 529,537 ****
  330.            * "important" part is readable only for ! paths/addresses.
  331.            */
  332.           while (p3 = index(p2, '!')) {
  333. !             int tmp = strlen(p3+1); /* xenix has compiler problems */
  334.               p2 = p3+1;
  335. !             if (tmp + isauthor*4 < pad) {
  336.               if (isauthor && (p2 -= 4) < old_p2)
  337.                   p2 = old_p2;
  338.               break;
  339. --- 529,537 ----
  340.            * "important" part is readable only for ! paths/addresses.
  341.            */
  342.           while (p3 = index(p2, '!')) {
  343. !             len = strlen(p3+1); /* xenix has compiler problems */
  344.               p2 = p3+1;
  345. !             if (len + isauthor*4 < pad) {
  346.               if (isauthor && (p2 -= 4) < old_p2)
  347.                   p2 = old_p2;
  348.               break;
  349. ***************
  350. *** 539,544 ****
  351. --- 539,551 ----
  352.           }
  353.           if (isauthor && p2 > old_p2+4 && !p3 && strlen(p2) + 4 > pad)
  354.               p2 -= 4;
  355. +         if (p3 && (p3 = rindex(p2, '@'))) {
  356. +             len = strlen(p3);
  357. +             while (len-- && --p2 > old_p2) {
  358. +             if (*(p2 + isauthor*4 - 1) == '!')
  359. +                 break;
  360. +             }
  361. +         }
  362.           if (old_p2 != p2 && isauthor)
  363.               (void) strncpy(p2, "TO: ", 4); /* doesn't null terminate */
  364.           }
  365. *** /tmp/,RCSt1002753    Wed Jul 11 21:32:53 1990
  366. --- lock.c    Tue Jun 19 13:19:03 1990
  367. ***************
  368. *** 123,133 ****
  369.   char *mode;
  370.   {
  371.       FILE *mail_fp = NULL_FILE;
  372. - #ifndef LCKDFLDIR
  373.       int fd, lk;
  374.       int cnt = 0;
  375.       SIGRET (*oldint)(), (*oldquit)();
  376. ! #else /* LCKDFLDIR */
  377.       extern FILE *lk_fopen();
  378.   #endif /* !LCKDFLDIR */
  379.   
  380. --- 123,132 ----
  381.   char *mode;
  382.   {
  383.       FILE *mail_fp = NULL_FILE;
  384.       int fd, lk;
  385.       int cnt = 0;
  386.       SIGRET (*oldint)(), (*oldquit)();
  387. ! #ifdef LCKDFLDIR
  388.       extern FILE *lk_fopen();
  389.   #endif /* !LCKDFLDIR */
  390.   
  391. ***************
  392. *** 136,145 ****
  393.       return NULL_FILE;
  394.       }
  395.   
  396. - #ifdef LCKDFLDIR
  397. -     return lk_fopen(filename, mode, NULL, NULL, 0);
  398. - #else /* !LCKDFLDIR */
  399.   #ifdef DOT_LOCK
  400.       if (dot_lock(filename) == 0)
  401.   #endif /* DOT_LOCK */
  402. --- 135,140 ----
  403. ***************
  404. *** 154,161 ****
  405.       lk = LOCK_SH | LOCK_NB;
  406.   
  407.       on_intr();
  408. !     while (isoff(glob_flags, WAS_INTR) && flock(fd, lk)) {
  409. !     if (errno == EWOULDBLOCK) {
  410.           if (isoff(glob_flags, REDIRECT))
  411.           if (!cnt++)
  412.               print("\nwaiting to lock");
  413. --- 149,168 ----
  414.       lk = LOCK_SH | LOCK_NB;
  415.   
  416.       on_intr();
  417. ! #ifdef LCKDFLDIR
  418. !     (void) fclose(mail_fp);
  419. !     while (isoff(glob_flags, WAS_INTR) &&
  420. !         !(mail_fp = lk_fopen(filename, mode, NULL, NULL, 0)))
  421. ! #else /* !LCKDFLDIR */
  422. !     while (isoff(glob_flags, WAS_INTR) && flock(fd, lk))
  423. ! #endif /* LCKDFLDIR */
  424. !     {
  425. ! #ifdef LCKDFLDIR
  426. !     if (Access(filename, any(mode, "aw+") ? W_OK : R_OK) == 0)
  427. ! #else /* !LCKDFLDIR */
  428. !     if (errno == EWOULDBLOCK)
  429. ! #endif /* LCKDFLDIR */
  430. !     {
  431.           if (isoff(glob_flags, REDIRECT))
  432.           if (!cnt++)
  433.               print("\nwaiting to lock");
  434. ***************
  435. *** 179,185 ****
  436.       return NULL_FILE;
  437.       }
  438.       return mail_fp;
  439. - #endif /* LCKDFLDIR */
  440.   }
  441.   
  442.   /*ARGSUSED*/
  443. --- 186,191 ----
  444. *** /tmp/,RCSt1002753    Wed Jul 11 21:32:54 1990
  445. --- loop.c    Wed Jul  4 15:39:39 1990
  446. ***************
  447. *** 1280,1287 ****
  448.       num_of_hists = min(hist_size, hist_no);
  449.   
  450.       if (!reverse)
  451. !     while (hist_no - hist->histno > num_of_hists) {
  452. !         (void) printf("skipping %d\n", hist->histno);
  453.           hist = hist->next;
  454.       }
  455.   
  456. --- 1280,1287 ----
  457.       num_of_hists = min(hist_size, hist_no);
  458.   
  459.       if (!reverse)
  460. !     while (hist_no - hist->histno >= num_of_hists) {
  461. !         Debug("skipping %d\n", hist->histno);
  462.           hist = hist->next;
  463.       }
  464.   
  465. *** /tmp/,RCSt1002753    Wed Jul 11 21:32:57 1990
  466. --- mail.c    Wed Jul  4 15:28:00 1990
  467. ***************
  468. *** 899,907 ****
  469.           }
  470.           if (*p != '!' && !do_set(set_options, "nosave"))
  471.           dead_letter(0);
  472. !         if (emptyfile(&ed_fp, edfile) == -1)
  473.           error(edfile);
  474. !         else
  475.           print("Message buffer empty\n");
  476.       when 'q':
  477.           /* save in dead.letter if nosave not set -- rm_edfile(-2). */
  478. --- 899,908 ----
  479.           }
  480.           if (*p != '!' && !do_set(set_options, "nosave"))
  481.           dead_letter(0);
  482. !         if (emptyfile(&ed_fp, edfile) == -1) {
  483.           error(edfile);
  484. !         return -1;
  485. !         } else
  486.           print("Message buffer empty\n");
  487.       when 'q':
  488.           /* save in dead.letter if nosave not set -- rm_edfile(-2). */
  489. ***************
  490. *** 982,988 ****
  491.       }
  492.       /* ~v on the Cc line asks for verification, first initialize p! */
  493.       p = NULL;
  494. !     if (!strncmp(Cc, "~v", 2) || (p = do_set(set_options, "verify"))) {
  495.           if (!p) /* so we don't Cc to ~v! */
  496.           *Cc = 0;
  497.           for (;;) {
  498. --- 983,992 ----
  499.       }
  500.       /* ~v on the Cc line asks for verification, first initialize p! */
  501.       p = NULL;
  502. !     if (!strncmp(Cc, "~v", 2) ||
  503. !         /* Flashy test for $verify either empty or set to "mail" */
  504. !         glob(p = do_set(set_options, "verify"),
  505. !                         "{,{,*[ \\,]}mail{,[ \\,]*}}")) {
  506.           if (!p) /* so we don't Cc to ~v! */
  507.           *Cc = 0;
  508.           for (;;) {
  509. ***************
  510. *** 1504,1510 ****
  511.        * created a From: header with the my_hdr command (the own_hdrs list).
  512.        * If his is not legitimate, warn user and use the other header.
  513.        */
  514. !     if ((for_editor || isoff(glob_flags, EDIT_HDRS)) &&
  515.           own_hdrs && !do_set(set_options, "no_hdrs")) {
  516.       for (opts = own_hdrs; opts; opts = opts->next)
  517.           if (!strcmp(opts->option, "From:")) {
  518. --- 1508,1514 ----
  519.        * created a From: header with the my_hdr command (the own_hdrs list).
  520.        * If his is not legitimate, warn user and use the other header.
  521.        */
  522. !     if ((for_editor || isoff(flags, EDIT_HDRS)) &&
  523.           own_hdrs && !do_set(set_options, "no_hdrs")) {
  524.       for (opts = own_hdrs; opts; opts = opts->next)
  525.           if (!strcmp(opts->option, "From:")) {
  526. *** /tmp/,RCSt1002753    Wed Jul 11 21:33:00 1990
  527. --- main.c    Wed Jul  4 07:23:41 1990
  528. ***************
  529. *** 40,49 ****
  530.   #ifdef LCKDFLDIR
  531.       lckdfldir = LCKDFLDIR;
  532.   #endif /* LCKDFLDIR */
  533. !     if (prog_name = rindex(*argv, '/'))
  534. !     prog_name++;
  535. !     else
  536. !     prog_name = *argv;
  537.   
  538.       (void) signal(SIGBUS,  bus_n_seg);
  539.       (void) signal(SIGSEGV, bus_n_seg);
  540. --- 40,46 ----
  541.   #ifdef LCKDFLDIR
  542.       lckdfldir = LCKDFLDIR;
  543.   #endif /* LCKDFLDIR */
  544. !     prog_name = basename(*argv);
  545.   
  546.       (void) signal(SIGBUS,  bus_n_seg);
  547.       (void) signal(SIGSEGV, bus_n_seg);
  548. *** /tmp/,RCSt1002753    Wed Jul 11 21:33:06 1990
  549. --- msgs.c    Wed Jul  4 17:07:44 1990
  550. ***************
  551. *** 270,277 ****
  552.        */
  553.       if (!first && mail_size()) {
  554.   lost_lock:
  555. !     if (get_new_mail(TRUE) && prompt && isoff(glob_flags, REDIRECT)
  556. !         && show_new_mail()) {
  557.           char buf[80];
  558.           if (iscurses)
  559.           putchar('\n'), turnon(glob_flags, CNTD_CMD);
  560. --- 270,277 ----
  561.        */
  562.       if (!first && mail_size()) {
  563.   lost_lock:
  564. !     if ((ison(glob_flags, CORRUPTED) || get_new_mail(TRUE)) &&
  565. !         prompt && isoff(glob_flags, REDIRECT) && show_new_mail()) {
  566.           char buf[80];
  567.           if (iscurses)
  568.           putchar('\n'), turnon(glob_flags, CNTD_CMD);
  569. ***************
  570. *** 280,286 ****
  571.           buf[0] = 0;
  572.   #ifdef SUNTOOL
  573.           if (istool) {
  574. !         (void) sprintf(buf, "New mail -- %s", prompt);
  575.           if (ask(buf) != TRUE)
  576.               return 0;
  577.           } else
  578. --- 280,288 ----
  579.           buf[0] = 0;
  580.   #ifdef SUNTOOL
  581.           if (istool) {
  582. !         (void) sprintf(buf, "%s -- %s",
  583. !             ison(glob_flags, CORRUPTED) ? "Error" : "New mail",
  584. !             prompt);
  585.           if (ask(buf) != TRUE)
  586.               return 0;
  587.           } else
  588. ***************
  589. *** 287,298 ****
  590.   #endif /* SUNTOOL */
  591.           if (!Getstr(buf, sizeof (buf), 0) || lower(*buf) != 'y')
  592.               return 0;
  593.       }
  594.       }
  595.       first = 0;
  596.   
  597.       /* If the user hasn't changed anything, just return true */
  598. !     if (isoff(glob_flags, DO_UPDATE))
  599.       return 1;
  600.       if (ison(glob_flags, READ_ONLY)) {
  601.       print("Unable to update %s: read only\n", mailfile);
  602. --- 289,301 ----
  603.   #endif /* SUNTOOL */
  604.           if (!Getstr(buf, sizeof (buf), 0) || lower(*buf) != 'y')
  605.               return 0;
  606. +         turnoff(glob_flags, CORRUPTED); /* User says go ahead */
  607.       }
  608.       }
  609.       first = 0;
  610.   
  611.       /* If the user hasn't changed anything, just return true */
  612. !     if (isoff(glob_flags, DO_UPDATE) || ison(glob_flags, CORRUPTED))
  613.       return 1;
  614.       if (ison(glob_flags, READ_ONLY)) {
  615.       print("Unable to update %s: read only\n", mailfile);
  616. ***************
  617. *** 316,323 ****
  618.       if (!(mail_fp = lock_fopen(mailfile, "r+"))) {
  619.       error("WARNING: unable to lock %s -- update aborted", mailfile);
  620.   #ifdef SUNTOOL
  621. !     write_err = 1;    /* forces return 0; below */
  622. !     goto resume_timer;    /* blecch */
  623.   #else /* !SUNTOOL */
  624.       return 0;
  625.   #endif /* SUNTOOL */
  626. --- 319,328 ----
  627.       if (!(mail_fp = lock_fopen(mailfile, "r+"))) {
  628.       error("WARNING: unable to lock %s -- update aborted", mailfile);
  629.   #ifdef SUNTOOL
  630. !     if (istool) {
  631. !         write_err = 1;    /* forces return 0; below */
  632. !         goto resume_timer;    /* blecch */
  633. !     }
  634.   #else /* !SUNTOOL */
  635.       return 0;
  636.   #endif /* SUNTOOL */
  637. *** /tmp/,RCSt1002753    Wed Jul 11 21:33:10 1990
  638. --- mush.1    Wed Jul  4 07:47:47 1990
  639. ***************
  640. *** 2937,2944 ****
  641.   searches for special mail headers in the author's message that
  642.   indicate the most efficient mail path for return mail.
  643.   .I Mush
  644. ! will search for the \*QReply-To:\*U, \*QReturn-Path:\*U,
  645. ! and \*QFrom:\*U headers, in that order, by default.
  646.   .sp
  647.   If none of these fields are found in the message, the first line of the
  648.   message is parsed if possible;
  649. --- 2937,2944 ----
  650.   searches for special mail headers in the author's message that
  651.   indicate the most efficient mail path for return mail.
  652.   .I Mush
  653. ! will search for the \*QReply-To:\*U,
  654. ! \*QFrom:\*U, and \*QReturn-Path:\*U headers, in that order, by default.
  655.   .sp
  656.   If none of these fields are found in the message, the first line of the
  657.   message is parsed if possible;
  658. ***************
  659. *** 4291,4296 ****
  660. --- 4291,4297 ----
  661.   If set to a string, that string is executed as a command when a
  662.   carriage return is typed.
  663.   Otherwise, carriage return prints the next undeleted message.
  664. + .TP
  665.   .B newmail_icon
  666.   (String)
  667.   Set to a pathname for an alternate icon pixmap to use
  668. ***************
  669. *** 4578,4584 ****
  670.   When replying to mail,
  671.   .I Mush
  672.   searches for return paths from the message by searching for
  673. ! the message headings \*QReply-to\*U, \*QReturn-path\*U, and \*QFrom:\*U,
  674.   in that order.
  675.   If none are found, then the first line of the
  676.   message created by the delivery system is parsed and the address
  677. --- 4579,4585 ----
  678.   When replying to mail,
  679.   .I Mush
  680.   searches for return paths from the message by searching for
  681. ! the message headings \*QReply-to\*U, \*QFrom:\*U, and \*QReturn-path\*U,
  682.   in that order.
  683.   If none are found, then the first line of the
  684.   message created by the delivery system is parsed and the address
  685. ***************
  686. *** 4778,4788 ****
  687.   to print additional information about the sending process.
  688.   .TP
  689.   .B verify
  690. ! (Boolean)
  691. ! When through editing messages, just before sending,
  692.   .B verify
  693. ! will ask you if you want to send, continue editing, or abort the
  694. ! whole message altogether.
  695.   .TP
  696.   .B version
  697.   (Read-only String)
  698. --- 4779,4805 ----
  699.   to print additional information about the sending process.
  700.   .TP
  701.   .B verify
  702. ! (Boolean/Multivalued)
  703. ! This variable causes mush to request confirmation of certain actions.
  704. ! If set only as a boolean (no string value), 
  705.   .B verify
  706. ! will ask just before sending mail whether you want to send, continue
  707. ! editing, or abort the message altogether.
  708. ! Otherwise,
  709. ! .B verify
  710. ! can be set to one or more of these words:
  711. ! .sp
  712. ! .nf
  713. ! .ta 1.5i
  714. ! .in +4
  715. ! .\" \& escapes are to make obvious the tab after each word
  716. ! mail\&\&    Confirm sending of mail (as above).
  717. ! save\&\&    Confirm save-item selections (tool only).
  718. ! .in -4
  719. ! .fi
  720. ! .sp
  721. ! Appending of messages to files that are not folders is verified regardless
  722. ! of the setting of this variable.
  723.   .TP
  724.   .B version
  725.   (Read-only String)
  726. *** /tmp/,RCSt1002753    Wed Jul 11 21:33:19 1990
  727. --- mush.h    Wed Jul  4 16:36:00 1990
  728. ***************
  729. *** 379,384 ****
  730. --- 379,385 ----
  731.   #define QUOTE_MACRO ULBIT(23) /* protect current macro from recursive expan.. */
  732.   #define NEW_FRAME   ULBIT(24) /* toolmode should build a new frame for pager */
  733.   #define HELP_TEXT   ULBIT(25) /* create textsw frame for paging help messages */
  734. + #define CORRUPTED   ULBIT(26) /* error loading new mail has occurred */
  735.   
  736.   /* flags to control composition */
  737.   #define VERBOSE        ULBIT(0)  /* verbose flag for sendmail */
  738. *** /tmp/,RCSt1002753    Wed Jul 11 21:33:25 1990
  739. --- signals.c    Tue Jul 10 08:38:54 1990
  740. ***************
  741. *** 74,79 ****
  742. --- 74,86 ----
  743.           wrapcolumn = atoi(fix);
  744.       }
  745.       turnoff(glob_flags, IS_GETTING);
  746. + #ifdef SYSV
  747. +     /* Interrupting "await" leaves an alarm timer running, which
  748. +      * some SysV systems mishandle.  Clean up.
  749. +      */
  750. +     if (!istool)
  751. +         (void) signal(SIGALRM, SIG_IGN);
  752. + #endif /* SYSV */
  753.       longjmp(jmpbuf, 1);
  754.       } else
  755.       puts("exiting"), cleanup(sig);
  756. ***************
  757. *** 176,182 ****
  758.           c = lower(*buf);
  759.       }
  760.       if (c != 'n' && *tempfile) {
  761. !     if (sig == SIGHUP && do_set(set_options, "hangup") && copyback(NULL))
  762.           (void) unlink(tempfile);
  763.       else if (unlink(tempfile) && !sig && errno != ENOENT)
  764.           error(tempfile);
  765. --- 183,190 ----
  766.           c = lower(*buf);
  767.       }
  768.       if (c != 'n' && *tempfile) {
  769. !     if (sig == SIGHUP && do_set(set_options, "hangup") &&
  770. !         copyback(NULL) && isoff(glob_flags, CORRUPTED))
  771.           (void) unlink(tempfile);
  772.       else if (unlink(tempfile) && !sig && errno != ENOENT)
  773.           error(tempfile);
  774. ***************
  775. *** 229,238 ****
  776.       if (isoff(glob_flags, READ_ONLY))
  777.           (void) emptyfile(&tmpf, tempfile);
  778.       current_msg = msg_cnt = 0;
  779.       }
  780.       if (load_folder(mailfile, 1, NULL) < 1) {
  781.       print("Can't load new mail: \"%s\" may be corrupted!\n", mailfile);
  782. !     turnon(glob_flags, DO_UPDATE);    /* Don't reload without rewrite */
  783.       return update_size;
  784.       /* NOTE: The above is used to stop check_new_mail() from calling
  785.        * show_new_mail(), while still allowing copyback() to detect the
  786. --- 237,249 ----
  787.       if (isoff(glob_flags, READ_ONLY))
  788.           (void) emptyfile(&tmpf, tempfile);
  789.       current_msg = msg_cnt = 0;
  790. +     turnoff(glob_flags, CORRUPTED);
  791.       }
  792. +     if (ison(glob_flags, CORRUPTED))
  793. +     return 0;
  794.       if (load_folder(mailfile, 1, NULL) < 1) {
  795.       print("Can't load new mail: \"%s\" may be corrupted!\n", mailfile);
  796. !     turnon(glob_flags, CORRUPTED);
  797.       return update_size;
  798.       /* NOTE: The above is used to stop check_new_mail() from calling
  799.        * show_new_mail(), while still allowing copyback() to detect the
  800. ***************
  801. *** 240,245 ****
  802. --- 251,260 ----
  803.        * should be a better-defined way to handle this.
  804.        */
  805.       }
  806. +     /* Prevent both bogus "new mail" messages and missed new mail */
  807. +     last_size = msg[msg_cnt].m_offset;
  808. +     if (!strcmp(mailfile, spoolfile))
  809. +     spool_size = last_size;
  810.       if (last_spool_size != spool_size) {
  811.       if (update_size)
  812.           last_spool_size = spool_size;
  813. *** /tmp/,RCSt1002753    Wed Jul 11 21:33:27 1990
  814. --- strings.c    Wed Jul  4 07:26:33 1990
  815. ***************
  816. *** 442,444 ****
  817. --- 442,458 ----
  818.       *s_out = 0;
  819.       return start;
  820.   }
  821. + /*
  822. +  * This routine returns a pointer to the file portion of a path/file name.
  823. +  */
  824. + char *
  825. + basename(path)
  826. + register char *path;
  827. + {
  828. +     char *file;
  829. +     if (file = rindex(path, '/'))
  830. +     return ++file;
  831. +     return path;
  832. + }
  833. *** /tmp/,RCSt1002753    Wed Jul 11 21:33:28 1990
  834. --- strings.h    Wed Jul  4 15:51:50 1990
  835. ***************
  836. *** 21,26 ****
  837. --- 21,27 ----
  838.       *Sprintf(),        /* See comments above function in strings.c */
  839.       *argv_to_string(),    /* convert a vector of strings into one string */
  840.       *any(),         /* return first char in str2 that exists in str1 */
  841. +     *basename(),    /* return the last component of a file path */
  842.       *ctrl_strcpy(),    /* string copy converting control chars to ascii */
  843.       *itoa(),        /* return a string representation of a number */
  844.       *lcase_strcpy(),    /* just like strcpy, but convert all chars to lower */
  845. *** /tmp/,RCSt1002753    Wed Jul 11 21:33:29 1990
  846. --- version.h    Wed Jul 11 21:30:09 1990
  847. ***************
  848. *** 1,7 ****
  849.   /* @(#)version.h    (c) Copyright 1989 (Dan Heller) */
  850.   
  851.   #define MUSHNAME    "Mail User's Shell"
  852. ! #define RELEASE_DATE    "5/02/90"
  853.   #define RELEASE        7
  854.   #define REVISION    "1"
  855. ! #define PATCHLEVEL    1
  856. --- 1,7 ----
  857.   /* @(#)version.h    (c) Copyright 1989 (Dan Heller) */
  858.   
  859.   #define MUSHNAME    "Mail User's Shell"
  860. ! #define RELEASE_DATE    "7/11/90"
  861.   #define RELEASE        7
  862.   #define REVISION    "1"
  863. ! #define PATCHLEVEL    2
  864. *** /tmp/,RCSt1002753    Wed Jul 11 21:33:29 1990
  865. --- viewopts.c    Wed Jul  4 07:39:03 1990
  866. ***************
  867. *** 184,190 ****
  868.       { "unix", NULL,
  869.       "Non-mush commands are considered to be UNIX commands." },
  870.       { "verify", NULL,
  871. !     "Verify to send, re-edit, or abort letter after editing." },
  872.       { "visual", "Visual editor:",
  873.       "Visual editor for messages (default = $editor or env VISUAL)."},
  874.       { "warning", NULL,
  875. --- 184,190 ----
  876.       { "unix", NULL,
  877.       "Non-mush commands are considered to be UNIX commands." },
  878.       { "verify", NULL,
  879. !     "Verify before acting in various situations, such as sending mail." },
  880.       { "visual", "Visual editor:",
  881.       "Visual editor for messages (default = $editor or env VISUAL)."},
  882.       { "warning", NULL,
  883. *** /tmp/,RCSt1002926    Wed Jul 11 21:33:32 1990
  884. --- doproc.c    Wed Jul 11 21:26:46 1990
  885. ***************
  886. *** 139,148 ****
  887.       if (!(p = panel_get_value(item)) || !*p &&
  888.           (!(p = do_set(set_options, "mbox")) || !*p))
  889.           p = DEF_MBOX;
  890. !     (void) sprintf(msgstr, "%s in \"%s\"?", buf, trim_filename(p));
  891. !     if (ask(msgstr) != TRUE) {
  892. !         wprint("Message not saved\n");
  893. !         return PANEL_NONE;
  894.       }
  895.       (void) strcpy(b, p); /* now add to command */
  896.       }
  897. --- 139,150 ----
  898.       if (!(p = panel_get_value(item)) || !*p &&
  899.           (!(p = do_set(set_options, "mbox")) || !*p))
  900.           p = DEF_MBOX;
  901. !     if (chk_option("verify", "save")) {
  902. !         (void) sprintf(msgstr, "%s in \"%s\"?", buf, trim_filename(p));
  903. !         if (ask(msgstr) != TRUE) {
  904. !         wprint("Message not saved\n");
  905. !         return PANEL_NONE;
  906. !         }
  907.       }
  908.       (void) strcpy(b, p); /* now add to command */
  909.       }
  910. ***************
  911. *** 153,163 ****
  912. --- 155,231 ----
  913.       return PANEL_NONE;
  914.   }
  915.   
  916. + #ifndef NO_WALK_MENUS
  917. + void
  918. + xx_file_dir(item, value)
  919. + Panel_item item;
  920. + char * value;
  921. + {
  922. +     char buf[BUFSIZ];
  923. +     u_long bang = ison(glob_flags, IGN_BANG);
  924. +     if (item == folder_item) {
  925. +     (void) sprintf(buf, "folder %s ",
  926. +         (ison(glob_flags, READ_ONLY) || ison(glob_flags, DO_UPDATE) &&
  927. +         !ask("Folder has been modified.  Update changes?"))? "!" : "");
  928. +     strcat(buf, value);
  929. +     } else if (item == save_item) {
  930. +     char msgstr[BUFSIZ], *p;
  931. +     register char *p2 = (char *)panel_get_value(msg_num_item);
  932. +     (void) strcpy(buf, "save ");
  933. +     if (p2 && *p2) {
  934. +         (void) strcat(buf, p2);
  935. +         (void) strcat(buf, " ");
  936. +     }
  937. +     (void) strcat(buf, value);
  938. +     if (chk_option("verify", "save")) {
  939. +         (void) sprintf(msgstr, "Save in %s? ", trim_filename(value));
  940. +         if (ask(msgstr) != TRUE) {
  941. +         wprint("Message not saved\n");
  942. +         return;
  943. +         }
  944. +     }
  945. +     }
  946. +     turnon(glob_flags, IGN_BANG);
  947. +     (void) cmd_line(buf, msg_list);
  948. +     if (!bang)
  949. +     turnoff(glob_flags, IGN_BANG);
  950. +     (void) panel_set(item, PANEL_VALUE, 0, NULL); /* remove last value */
  951. + }
  952.   /*
  953.    * callback routine for the panel items that need filename input.
  954.    * (folder and save)
  955.    */
  956.   void
  957. + do_file_dir(item, event)
  958. + Panel_item item;
  959. + Event *event;
  960. + {
  961. +     if (item == folder_item) {
  962. +     char *p = panel_get_value(folder_text_item);
  963. +     if (!*p) {
  964. +         ok_box("Enter folder name.");
  965. +         return;
  966. +     }
  967. +     xx_file_dir(item, p);
  968. +     } else if (item == save_item) {
  969. +     if (!strcmp("Filename:", panel_get(file_item,PANEL_LABEL_STRING))) {
  970. +         event_id(event) = '\n';  /* let file_dir think it got a \n */
  971. +         file_dir(file_item, event);
  972. +         return;
  973. +     }
  974. +     }
  975. +     (void) panel_set(item, PANEL_VALUE, 0, NULL); /* remove last value */
  976. + }
  977. + #else /* NO_WALK_MENUS */
  978. + /*
  979. +  * callback routine for the panel items that need filename input.
  980. +  * (folder and save)
  981. +  */
  982. + void
  983.   do_file_dir(item, value, event)
  984.   Panel_item item;
  985.   int value;
  986. ***************
  987. *** 206,215 ****
  988.           (void) strcat(buf, p);
  989.       } else
  990.           (void) strcat(buf, p = panel_get(item, PANEL_CHOICE_STRING, value));
  991. !     (void) sprintf(msgstr, "Save in %s? ", trim_filename(p));
  992. !     if (ask(msgstr) != TRUE) {
  993. !         wprint("Message not saved\n");
  994. !         return;
  995.       }
  996.       }
  997.       turnon(glob_flags, IGN_BANG);
  998. --- 274,285 ----
  999.           (void) strcat(buf, p);
  1000.       } else
  1001.           (void) strcat(buf, p = panel_get(item, PANEL_CHOICE_STRING, value));
  1002. !     if (chk_option("verify", "save")) {
  1003. !         (void) sprintf(msgstr, "Save in %s? ", trim_filename(p));
  1004. !         if (ask(msgstr) != TRUE) {
  1005. !         wprint("Message not saved\n");
  1006. !         return;
  1007. !         }
  1008.       }
  1009.       }
  1010.       turnon(glob_flags, IGN_BANG);
  1011. ***************
  1012. *** 218,223 ****
  1013. --- 288,294 ----
  1014.       turnoff(glob_flags, IGN_BANG);
  1015.       (void) panel_set(item, PANEL_VALUE, 0, NULL); /* remove last value */
  1016.   }
  1017. + #endif /* NO_WALK_MENUS */
  1018.   
  1019.   /*ARGSUSED*/
  1020.   void
  1021. *** /tmp/,RCSt1002926    Wed Jul 11 21:33:35 1990
  1022. --- hdr_sw.c    Wed Jul 11 21:26:47 1990
  1023. ***************
  1024. *** 19,26 ****
  1025.   
  1026.   static Notify_value scroll_hdr();
  1027.   static void msg_menu_func(), do_menu(), msg_menu_notify();
  1028. ! static Menu msg_menu;
  1029. ! static Menu_item cur_msg_item;
  1030.   
  1031.   void
  1032.   make_hdr_sw(parent)
  1033. --- 19,25 ----
  1034.   
  1035.   static Notify_value scroll_hdr();
  1036.   static void msg_menu_func(), do_menu(), msg_menu_notify();
  1037. ! Menu msg_menu;
  1038.   
  1039.   void
  1040.   make_hdr_sw(parent)
  1041. ***************
  1042. *** 261,267 ****
  1043.       char *data;    /* Menu item client data. */
  1044.   };
  1045.   
  1046. ! static void
  1047.   get_msg_menu()
  1048.   {
  1049.       int i;
  1050. --- 260,266 ----
  1051.       char *data;    /* Menu item client data. */
  1052.   };
  1053.   
  1054. ! void
  1055.   get_msg_menu()
  1056.   {
  1057.       int i;
  1058. ***************
  1059. *** 278,284 ****
  1060.       { "Help",            HELP_MSG  },
  1061.       };
  1062.   
  1063. !     msg_menu = menu_create(MENU_NOTIFY_PROC, msg_menu_notify, NULL);
  1064.       for (i = 0; i < ArraySize(msg_items); i++) {
  1065.       mi = menu_create_item(MENU_STRING,    msg_items[i].str,
  1066.                     MENU_CLIENT_DATA,    msg_items[i].data,
  1067. --- 277,283 ----
  1068.       { "Help",            HELP_MSG  },
  1069.       };
  1070.   
  1071. !     msg_menu = menu_create(MENU_NOTIFY_PROC, menu_return_item, NULL);
  1072.       for (i = 0; i < ArraySize(msg_items); i++) {
  1073.       mi = menu_create_item(MENU_STRING,    msg_items[i].str,
  1074.                     MENU_CLIENT_DATA,    msg_items[i].data,
  1075. ***************
  1076. *** 288,301 ****
  1077.   }
  1078.   
  1079.   static void
  1080. - msg_menu_notify(menu, item)
  1081. - Menu menu;
  1082. - Menu_item item;
  1083. - {
  1084. -     cur_msg_item = item;
  1085. - }
  1086. - static void
  1087.   do_menu(can_sw, event, fd, message)
  1088.   Canvas can_sw;
  1089.   Event *event;
  1090. --- 287,292 ----
  1091. ***************
  1092. *** 302,307 ****
  1093. --- 293,300 ----
  1094.   int fd, message;
  1095.   {
  1096.       char *action;
  1097. +     char * save_place;
  1098. +     Menu_item cur_msg_item;
  1099.       static char buf[16];
  1100.   
  1101.       if (!msg_cnt) {
  1102. ***************
  1103. *** 323,329 ****
  1104.       box(0, 5 + line * l_height(),
  1105.           hdr_rect->r_width, 5 + (line+1) * l_height());
  1106.       /* show menu */
  1107. !     menu_show(msg_menu, can_sw, event, NULL);
  1108.       /* remove feedback */
  1109.       box(0, 5 + line * l_height(),
  1110.           hdr_rect->r_width, 5 + (line+1) * l_height());
  1111. --- 316,322 ----
  1112.       box(0, 5 + line * l_height(),
  1113.           hdr_rect->r_width, 5 + (line+1) * l_height());
  1114.       /* show menu */
  1115. !     cur_msg_item = menu_show(msg_menu, can_sw, event, NULL);
  1116.       /* remove feedback */
  1117.       box(0, 5 + line * l_height(),
  1118.           hdr_rect->r_width, 5 + (line+1) * l_height());
  1119. ***************
  1120. *** 330,337 ****
  1121.       /* if user selected something, figure out what was selected. */
  1122.       if (!cur_msg_item)
  1123.           return;
  1124. !     action = (char *) menu_get(cur_msg_item, MENU_CLIENT_DATA);
  1125. !     cur_msg_item = (Menu_item)NULL;
  1126.       } else
  1127.       action = (char *) event;
  1128.   
  1129. --- 323,338 ----
  1130.       /* if user selected something, figure out what was selected. */
  1131.       if (!cur_msg_item)
  1132.           return;
  1133. ! #ifndef NO_WALK_MENUS
  1134. !         if ((Menu)menu_get(cur_msg_item, MENU_PARENT) == msg_menu) {
  1135. !         action = (char *) menu_get(cur_msg_item, MENU_CLIENT_DATA);
  1136. !         } else {
  1137. !         save_place = (char *)menu_get(cur_msg_item, MENU_CLIENT_DATA);
  1138. !         action = SAVE_MSG;
  1139. !         }   /* endif */
  1140. ! #else /* NO_WALK_MENUS */
  1141. !         action = (char *) menu_get(cur_msg_item, MENU_CLIENT_DATA);
  1142. ! #endif /* NO_WALK_MENUS */
  1143.       } else
  1144.       action = (char *) event;
  1145.   
  1146. ***************
  1147. *** 341,348 ****
  1148.           extern Panel_item msg_num_item, save_item;
  1149.           (void) panel_set(msg_num_item, PANEL_VALUE,
  1150.                       sprintf(buf, "%d", message+1), NULL);
  1151. !         event_id(event) = MS_LEFT;
  1152. !         do_file_dir(save_item, 0, event);
  1153.           (void) panel_set(msg_num_item, PANEL_VALUE, NO_STRING, NULL);
  1154.       }
  1155.       when HELP_MSG :
  1156. --- 342,357 ----
  1157.           extern Panel_item msg_num_item, save_item;
  1158.           (void) panel_set(msg_num_item, PANEL_VALUE,
  1159.                       sprintf(buf, "%d", message+1), NULL);
  1160. ! #ifndef NO_WALK_MENUS
  1161. !         if (*save_place == '\0') { /* magic to mean "use Filename:" */
  1162. !             do_file_dir(save_item, event);
  1163. !         } else {
  1164. !             xx_file_dir(save_item, save_place);
  1165. !         }   /* endif */
  1166. ! #else /* NO_WALK_MENUS */
  1167. !         event_id(event) = MS_LEFT;
  1168. !         do_file_dir(save_item, 0, event);
  1169. ! #endif /* NO_WALK_MENUS */
  1170.           (void) panel_set(msg_num_item, PANEL_VALUE, NO_STRING, NULL);
  1171.       }
  1172.       when HELP_MSG :
  1173. *** /tmp/,RCSt1002926    Wed Jul 11 21:33:38 1990
  1174. --- panels.c    Wed Jul 11 21:26:47 1990
  1175. ***************
  1176. *** 31,36 ****
  1177. --- 31,47 ----
  1178.       save_item,        /* saves messages */
  1179.       sub_hdr_item[6];    /* display items that just sit there and give help */
  1180.   
  1181. + #ifndef NO_WALK_MENUS
  1182. + Panel
  1183. +     folder_panel,
  1184. +     save_panel;
  1185. + Menu      folder_menu;    /* Menu of folders for folder button */
  1186. + Menu      save_menu;    /* Menu of folders for save button */
  1187. + Menu      hdr_save_menu;/* Menu of folders for save option in hdr window */
  1188. + extern Menu msg_menu;    /* header subwindow menu, defined in hdr_sw.c */
  1189. + walk_menu_event();
  1190. + #endif /* NO_WALK_MENUS */
  1191.   /* These global panel items for letter composition should eventually go away */
  1192.   Panel_item
  1193.       edit_item,        /* edit a message */
  1194. ***************
  1195. *** 75,80 ****
  1196. --- 86,101 ----
  1197.       PANEL_NOTIFY_PROC,         do_help,
  1198.       NULL);
  1199.   
  1200. + #ifndef NO_WALK_MENUS
  1201. +     folder_panel = panel;
  1202. +     folder_item = panel_create_item(panel, PANEL_BUTTON,
  1203. +     PANEL_ATTRIBUTE_LIST,         button_args,
  1204. +     PANEL_LABEL_IMAGE,
  1205. +         panel_button_image(panel, "Folder", 6, mush_font),
  1206. +     PANEL_NOTIFY_PROC,         do_file_dir,
  1207. +     PANEL_EVENT_PROC,        walk_menu_event,
  1208. +     NULL);
  1209. + #else /* NO_WALK_MENUS */
  1210.       folder_item = panel_create_item(panel, PANEL_CHOICE,
  1211.       PANEL_ATTRIBUTE_LIST,         choice_args,
  1212.       PANEL_LABEL_IMAGE,
  1213. ***************
  1214. *** 85,90 ****
  1215. --- 106,112 ----
  1216.       NULL);
  1217.   
  1218.       add_folder_to_menu(folder_item, 3);
  1219. + #endif /* NO_WALK_MENUS */
  1220.   
  1221.       folder_text_item = panel_create_item(panel, PANEL_TEXT,
  1222.       PANEL_ATTRIBUTE_LIST,         choice_args,
  1223. ***************
  1224. *** 214,219 ****
  1225. --- 236,252 ----
  1226.       PANEL_NOTIFY_PROC,         delete_mail,
  1227.       NULL);
  1228.   
  1229. + #ifndef NO_WALK_MENUS
  1230. +     save_panel = panel;
  1231. +     save_item = panel_create_item(panel, PANEL_BUTTON,
  1232. +     PANEL_ATTRIBUTE_LIST,         button_args,
  1233. +     PANEL_LABEL_IMAGE, panel_button_image(panel, "Save", 4, mush_font),
  1234. +     PANEL_NOTIFY_PROC,         do_file_dir,
  1235. +     PANEL_EVENT_PROC,        walk_menu_event,
  1236. +     NULL);
  1237. +     create_folder_menus();
  1238. + #else /* NO_WALK_MENUS */
  1239.       {
  1240.       char *mbox = do_set(set_options, "mbox");
  1241.       if (!mbox || !*mbox)
  1242. ***************
  1243. *** 227,232 ****
  1244. --- 260,266 ----
  1245.       }
  1246.   
  1247.       add_folder_to_menu(save_item, 1);
  1248. + #endif /* NO_WALK_MENUS */
  1249.   
  1250.       file_item = panel_create_item(panel, PANEL_TEXT,
  1251.       PANEL_ATTRIBUTE_LIST,         choice_args,
  1252. ***************
  1253. *** 391,445 ****
  1254.   
  1255.   #include "glob.h"
  1256.   
  1257. ! #ifdef WALK_MENUS
  1258. ! folder_menu_notify(menu, mi)
  1259. ! Menu menu;
  1260. ! Menu_item mi;
  1261. ! {
  1262. ! }
  1263.   
  1264. ! static Menu_item
  1265. ! add_path_to_menu(menu, path)
  1266. ! Menu menu;
  1267.   char *path;
  1268.   {
  1269. -     DIR            *dirp;
  1270. -     struct dirent    *dp;
  1271. -     struct stat     s_buf;
  1272.       Menu_item        mi;
  1273.       Menu        next_menu;
  1274.       char        buf[MAXPATHLEN];
  1275.   
  1276.       /* don't add a folder to the list if user can't read it */
  1277. !     if (stat(path, &s_buf) == -1 || !(s_buf.st_mode & S_IREAD))
  1278.       return NULL;
  1279.       if ((s_buf.st_mode & S_IFMT) == S_IFDIR) {
  1280.       int cnt = 0;
  1281. !     if (!(dirp = opendir(path)))
  1282. !         return NULL; /* don't bother adding to list if we can't scan it */
  1283. !     next_menu = menu_create(MENU_NOTIFY_PROC, folder_menu_notify, NULL);
  1284. !     while (dp = readdir(dirp))
  1285. !         if (strcmp(dp->d_name, ".") && strcmp(dp->d_name, ".."))
  1286. !         if (mi = add_path_to_menu(next_menu,
  1287. !             sprintf(buf, "%s/%s", path, dp->d_name))) {
  1288. !             menu_set(next_menu, MENU_APPEND_ITEM, mi, NULL);
  1289. !             cnt++;
  1290.           }
  1291. !     closedir(dirp);
  1292. !     mi = menu_create_item(MENU_STRING, trim_filename(path), NULL);
  1293. !     if (!cnt) {
  1294.           menu_destroy(next_menu);
  1295.           menu_set(mi, MENU_INACTIVE, TRUE, NULL);
  1296. !     } else
  1297.           menu_set(mi, MENU_PULLRIGHT, next_menu, NULL);
  1298. !     return mi;
  1299.       }
  1300. !     /* we should check that this file is actually a folder */
  1301. !     return menu_create_item(MENU_STRING, trim_filename(path), NULL);
  1302.   }
  1303. - #endif /* WALK_MENUS */
  1304.   
  1305.   static
  1306.   add_path_to_menu(item, path, n)
  1307.   Panel_item item;
  1308.   char *path;
  1309. --- 425,675 ----
  1310.   
  1311.   #include "glob.h"
  1312.   
  1313. ! #ifndef NO_WALK_MENUS
  1314.   
  1315. ! static
  1316. ! Menu_item
  1317. ! make_folder_item(path)
  1318.   char *path;
  1319.   {
  1320.       Menu_item        mi;
  1321. +     Menu_item        sub_mi;
  1322.       Menu        next_menu;
  1323. +     char        **names, **np;
  1324. +     struct stat     s_buf;
  1325.       char        buf[MAXPATHLEN];
  1326.   
  1327. +     if (glob(path, "*/{.,..}")) {
  1328. +     return NULL;
  1329. +     }
  1330.       /* don't add a folder to the list if user can't read it */
  1331. !     if (stat(path, &s_buf) == -1 || !(s_buf.st_mode & S_IREAD)) {
  1332.       return NULL;
  1333. +     }
  1334. +     mi = menu_create_item(
  1335. +     MENU_STRING,        savestr(basename(trim_filename(path))),
  1336. +     MENU_CLIENT_DATA,    NULL,
  1337. +     MENU_RELEASE,        /* no value */
  1338. +     NULL);
  1339.       if ((s_buf.st_mode & S_IFMT) == S_IFDIR) {
  1340.       int cnt = 0;
  1341. !     next_menu = menu_create(MENU_NOTIFY_PROC, menu_return_item, NULL);
  1342. !     sprintf(buf, "%s/{.*,*}", path);
  1343. !     if (filexp(buf, &names) > 0) {
  1344. !         for (np = names; np && *np; np++) {
  1345. !         if ((sub_mi = make_folder_item(*np)) != NULL) {
  1346. !             menu_set(next_menu, MENU_APPEND_ITEM, sub_mi, NULL);
  1347. !             ++cnt;
  1348.           }
  1349. !         }
  1350. !         free_vec(names);
  1351. !     }
  1352. !     if (! cnt) {
  1353.           menu_destroy(next_menu);
  1354.           menu_set(mi, MENU_INACTIVE, TRUE, NULL);
  1355. !     } else {
  1356.           menu_set(mi, MENU_PULLRIGHT, next_menu, NULL);
  1357. !     }
  1358. !     } else if (test_folder(path, NULL)) {
  1359. !     menu_set(mi, MENU_CLIENT_DATA, savestr(path), NULL);
  1360. !     } else {
  1361. !     menu_destroy(mi);
  1362. !     mi = NULL;
  1363.       }
  1364. !     return mi;
  1365.   }
  1366.   
  1367.   static
  1368. + void
  1369. + destroy_folder_item(menu_item, menu_type)
  1370. + Menu_item menu_item;
  1371. + Menu_attribute menu_type;
  1372. + {
  1373. +     char    *ptr;
  1374. +     if (menu_type == MENU_ITEM) {
  1375. +     if ((ptr = (char *)menu_get(menu_item, MENU_STRING)) != NULL) {
  1376. +         free(ptr);
  1377. +     }
  1378. +     if ((ptr = (char *)menu_get(menu_item, MENU_CLIENT_DATA)) != NULL) {
  1379. +         free(ptr);
  1380. +     }
  1381. +     }
  1382. +     return;
  1383. + }
  1384. + create_folder_menus()
  1385. + {
  1386. +     int       item_number;
  1387. +     Menu      menu;
  1388. +     Menu_item      menu_item;
  1389. +     int       nitems;
  1390. +     char     *mbox;
  1391. +     char     *tmp = NULL;
  1392. +     char     *p;
  1393. +     static int      menus_exist = 0;
  1394. +     if (menus_exist) {
  1395. +     /* remove duplicated menu items from save_menu */
  1396. +     for (item_number = (int)menu_get(save_menu, MENU_NITEMS) ;
  1397. +           item_number > 1 ; --item_number) {
  1398. +         menu_set(save_menu, MENU_REMOVE, item_number, NULL);
  1399. +     }
  1400. +     /* remove duplicated menu items from hdr_save_menu */
  1401. +     for (item_number = (int)menu_get(hdr_save_menu, MENU_NITEMS) ;
  1402. +           item_number > 1 ; --item_number) {
  1403. +         menu_set(save_menu, MENU_REMOVE, item_number, NULL);
  1404. +     }
  1405. +     menu_destroy_with_proc(hdr_save_menu, destroy_folder_item);
  1406. +     menu_destroy_with_proc(save_menu, destroy_folder_item);
  1407. +     menu_destroy_with_proc(folder_menu, destroy_folder_item);
  1408. +     }
  1409. +     if (!(p = do_set(set_options, "folder")) || !*p) {
  1410. +     p = DEF_FOLDER;
  1411. +     }
  1412. +     if (p) {
  1413. +     int x = 0;
  1414. +     tmp = getpath(p, &x);
  1415. +     if (x == -1) {
  1416. +         if (errno != ENOENT)
  1417. +         print("%s: %s\n", p, tmp);
  1418. +         tmp = NULL;
  1419. +     }
  1420. +     }
  1421. +     menu = NULL;
  1422. +     menu_item = NULL;
  1423. +     if (tmp != NULL) {
  1424. +     if ((menu_item = make_folder_item(tmp)) != NULL) {
  1425. +         if ((menu = menu_get(menu_item, MENU_PULLRIGHT)) != NULL) {
  1426. +             /* $folder was a directory, use the pullright
  1427. +          * instead of the directory menu item.
  1428. +          */
  1429. +         /* "unhook" the pullright (so it is not released) */
  1430. +         menu_set(menu_item, MENU_PULLRIGHT, NULL, NULL);
  1431. +         /* destroy the menu item */
  1432. +         menu_destroy_with_proc(menu_item, destroy_folder_item);
  1433. +         menu_item = NULL;
  1434. +         }
  1435. +     }
  1436. +     }
  1437. +     if (menu == NULL) {
  1438. +     menu = menu_create(MENU_NOTIFY_PROC, menu_return_item, NULL);
  1439. +     if (menu_item != NULL) {
  1440. +         menu_set(menu, MENU_APPEND_ITEM, menu_item, NULL);
  1441. +     }
  1442. +     }
  1443. +     /* create save_menu */
  1444. +     save_menu = menu_create(MENU_NOTIFY_PROC, menu_return_item, NULL);
  1445. +     /* add magic first item */
  1446. +     mbox = do_set(set_options, "mbox");
  1447. +     if (!mbox || !*mbox) {
  1448. +     mbox = DEF_MBOX;
  1449. +     }
  1450. +     menu_item = menu_create_item(
  1451. +     MENU_STRING,        savestr(trim_filename(mbox)),
  1452. +     MENU_CLIENT_DATA,    savestr(mbox),
  1453. +     MENU_RELEASE,        /* no value */
  1454. +     NULL);
  1455. +     menu_set(save_menu, MENU_APPEND_ITEM, menu_item, NULL);
  1456. +     /* copy menu for save_menu */
  1457. +     nitems = (int)menu_get(menu, MENU_NITEMS);
  1458. +     for (item_number = 1 ; item_number <= nitems ; ++item_number) {
  1459. +     menu_set(save_menu,
  1460. +         MENU_APPEND_ITEM, menu_get(menu, MENU_NTH_ITEM, item_number),
  1461. +         NULL);
  1462. +     }
  1463. +     /* create hdr_save_menu */
  1464. +     hdr_save_menu = menu_create(MENU_NOTIFY_PROC, menu_return_item, NULL);
  1465. +     /* add magic first item */
  1466. +     menu_item = menu_create_item(
  1467. +     MENU_STRING,        savestr("use Filename:"),
  1468. +     MENU_CLIENT_DATA,    savestr(""),    /* magic */
  1469. +     MENU_RELEASE,        /* no value */
  1470. +     NULL);
  1471. +     menu_set(hdr_save_menu, MENU_APPEND_ITEM, menu_item, NULL);
  1472. +     /* copy save_menu for hdr_save_menu */
  1473. +     nitems = (int)menu_get(save_menu, MENU_NITEMS);
  1474. +     for (item_number = 1 ; item_number <= nitems ; ++item_number) {
  1475. +     menu_set(hdr_save_menu,
  1476. +         MENU_APPEND_ITEM, menu_get(save_menu, MENU_NTH_ITEM, item_number),
  1477. +         NULL);
  1478. +     }
  1479. +     /* Make sure the header subwindow menu exists so we can tack on a
  1480. +      * pullright for Save.
  1481. +      */
  1482. +     if (! msg_menu) {
  1483. +     get_msg_menu();
  1484. +     }
  1485. +     if ((menu_item = menu_find(msg_menu, MENU_STRING, "Save", NULL))
  1486. +         != NULL) {
  1487. +     menu_set(menu_item, MENU_PULLRIGHT, hdr_save_menu, NULL);
  1488. +     }
  1489. +     /* insert folder-specific initial options to menu */
  1490. +     folder_menu = menu;
  1491. +     menu_item = menu_create_item(
  1492. +     MENU_STRING,        savestr("System Mailbox"),
  1493. +     MENU_CLIENT_DATA,    savestr("%"),
  1494. +     MENU_RELEASE,        /* no value */
  1495. +     NULL);
  1496. +     menu_set(folder_menu, MENU_INSERT, 0, menu_item, NULL);
  1497. +     menu_item = menu_create_item(
  1498. +     MENU_STRING,        savestr("Main Mailbox"),
  1499. +     MENU_CLIENT_DATA,    savestr("&"),
  1500. +     MENU_RELEASE,        /* no value */
  1501. +     NULL);
  1502. +     menu_set(folder_menu, MENU_INSERT, 1, menu_item, NULL);
  1503. +     menu_item = menu_create_item(
  1504. +     MENU_STRING,        savestr("Last Accessed Folder"),
  1505. +     MENU_CLIENT_DATA,    savestr("#"),
  1506. +     MENU_RELEASE,        /* no value */
  1507. +     NULL);
  1508. +     menu_set(folder_menu, MENU_INSERT, 2, menu_item, NULL);
  1509. +     menus_exist = 1;
  1510. +     return;
  1511. + }
  1512. + static
  1513. + walk_menu_event(item, event)
  1514. + Panel_item item;
  1515. + Event *event;
  1516. + {
  1517. +     char     *folder_name;
  1518. +     Menu_item       selection;
  1519. +     Menu      menu;
  1520. +     Panel      panel;
  1521. +     void xx_file_dir();
  1522. +     if (event_id(event) == MS_RIGHT && event_is_down(event)) {
  1523. +     if (item == folder_item) {
  1524. +         menu = folder_menu;
  1525. +         panel = folder_panel;
  1526. +     } else {
  1527. +         menu = save_menu;
  1528. +         panel = save_panel;
  1529. +     }
  1530. +     selection = (Menu_item)menu_show(menu, panel, event, 0);
  1531. +     if (! selection) {
  1532. +         /* no selection was made */
  1533. +         return;
  1534. +     }
  1535. +     if ((folder_name = (char *)menu_get(selection, MENU_CLIENT_DATA))
  1536. +         != NULL) {
  1537. +         xx_file_dir(item, folder_name);
  1538. +     }
  1539. +     } else {
  1540. +     panel_default_handle_event(item, event);
  1541. +     }
  1542. + }
  1543. + #else /* NO_WALK_MENUS */
  1544. + static
  1545.   add_path_to_menu(item, path, n)
  1546.   Panel_item item;
  1547.   char *path;
  1548. ***************
  1549. *** 476,484 ****
  1550.   Panel_item item;
  1551.   {
  1552.       char    *tmp = NULL, *p;
  1553. - #ifdef WALK_MENUS
  1554. -     Menu_item    mi;
  1555. - #endif /* WALK_MENUS */
  1556.   
  1557.       if (!(p = do_set(set_options, "folder")) || !*p)
  1558.       p = DEF_FOLDER;
  1559. --- 706,711 ----
  1560. ***************
  1561. *** 492,501 ****
  1562.       }
  1563.       }
  1564.       if (tmp) {
  1565. - #ifdef WALK_MENUS
  1566. -     mi = add_path_to_menu(menu, tmp);
  1567. - #else /* WALK_MENUS */
  1568.       add_path_to_menu(item, tmp, &n);
  1569. - #endif /* WALK_MENUS */
  1570.       }
  1571.   }
  1572. --- 719,725 ----
  1573.       }
  1574.       }
  1575.       if (tmp) {
  1576.       add_path_to_menu(item, tmp, &n);
  1577.       }
  1578.   }
  1579. + #endif /* NO_WALK_MENUS */
  1580.  
  1581. -- 
  1582. Bart Schaefer                        schaefer@cse.ogi.edu
  1583.  
  1584.