schaefer@ogicse.cse.ogi.edu (Barton E. Schaefer) (07/12/90)
@OFF This is Official Patch #2 for Mush 7.1. Mush was previously posted to comp.sources.misc at patch level 1. A copy of this message has been sent to the comp.sources.misc moderator for posting and archiving. As usual, complete sources for Mush (already including the changes in this patch) can be obtained via anonymous ftp from either of: ucbvax.berkeley.edu:pub/mailers/mush-7.1.tar.Z cse.ogi.edu:pub/mush/mush-7.1.tar.Z Be aware that a version of mush with RELEASE_DATE (from version.h) of 7/10/90 was incorrectly made available for ftp for approximately 24 hours spanning the night of July 10th and most of the day July 11th. The correct RELEASE_DATE is 7/11/90. If you have the 7/10 version, please pick up the more recent one. The only change was to enable walking menus by default (see below); the functionality is the same. This affects Sun systems only, but for purposes of patching you should obtain the correct version. If you need any earlier patches, they are available for ftp from cse.ogi.edu, or you can send E-mail to me: schaefer@cse.ogi.edu {decwrl,garp,harvard,rutgers,sdsu,ucsd,unmvax}!ogicse!schaefer Include in your message a line of the form @PATCH patch-number path-from-ogicse-to-you where patch-number is the number of the patch you need (digit, 1 or 2) and path-from-ogicse-to-you is either your Internet domain address or a UUCP path from site ogicse to you at your site. There continue to be sendmail configuration problems at ogicse so please do not use mixed UUCP and Internet addresses and do not use domain names (with `.'s) in UUCP paths. Ogicse does do UUCP map lookups now, so user@site.UUCP will often work if your site is registered. If you don't get your patches in 2 or 3 days, try again, but use a different path. You may include one @PATCH line for each patch you need. You can also recieve a complete set of sources by E-mail by including a line of the form @MUSH path-from-ogicse-to-you where path-from-ogicse-to-you is as above. You need not request both source and patches; the source you receive will include all current patches. Sources are shipped as a 9-part compressed tar file, encoded for mailing with the "btoa" utility. You will receive instructions explaining how to unpack the tar file in a separate message. CSNet also operates an E-mail server that accesses anonymous ftp. It may or may not be functional at this time. To find out, and to get instructions for using the server, send a message to info-server@cs.net with the following lines in the text: request: info topic: help-ftp request: end Other information, plus questions and answers, on mush and mush patches is available from the mush-users mailing list, which is gatewayed in both directions with newsgroup comp.mail.mush. The list currently resides at mush-users@garp.mit.edu, but may in the near future be moving to mush-users@apple.com. Requests to be added to or deleted from the list should be sent to mush-users-request@garp.mit.edu, for now. Changes/Fixes in this patch: The "undelete" operation in the Mailrc configuration file for UCB Mail emulation has been adjusted to change the current message to the last message in the undeleted list. This causes one message header summary to be printed whenever "undelete" is used. The "delete" operation in tool mode will now bring the new current message onto the header display if and only if it was changed by the deletion. Failure to truncate and recreate the editor temp file (e.g. by ~E) is now detected and handled properly. Handling of "corrupted" spool mailboxes has been improved. The size of the spool file is now correctly recorded on new mail checks, which should reduce the frequency of corruption reports on systems that rely on DOT_LOCKing. See also the locking corrections for MMDF, noted below. Once possible corruption is detected, new mail is no longer checked, and upon quit or any folder change operation the user is warned of the error. If mush exits with the folder still in a corrupt state, no update is done and the temporary copy is not removed. Further improvements in this error handling are planned for future patches. SYSV systems that support BSD-style directory functions will now correctly #include <dirent.h> if DIRECTORY is defined. Addresses containing UUCP !-paths ending in a domain-style @host suffix will now be shifted to the right in header summaries to show as at least the last two hosts of the UUCP path tail. This assumes that the correct parsing of host2!host3!user@host1 is the same as host1!host2!host3!user. Use of the file locking routines from the MMDF libraries has been fixed. Previous usage assumed that the MMDF routines locked in a blocking manner, waiting until the lock was obtained; this is not correct, and mush now loops until the lock is obtained. The "history" command now includes itself in the listing of the last N history items when invoked with a numeric argument. E.g., "history 5" will now show "history 5" as the most recent of the five commands displayed. This is consistent with "history -r 5" and the csh usage. $verify is now treated as a multivalued variable. In addition to the old usage of verifying send/edit/discard on outgoing mail, it is now necessary to "set verify=save" to enable the toolmode query boxes that confirm save operations. The other valid settings are "mail" and no value, both of which behave as $verify did before. To verify both outgoing mail and tool mode save operations, use "set verify=mail,save". Stray alarm timers could be triggered by use of the "await" command under SysV, resulting in core dumps. This has been corrected. For SunView users, walking menus are now used for the file names displayed under the <Folder> and <Save> items. This neatens up display of nested directory structures and avoids the menu size limits of SunView in most cases. Thanks to J. William Claypool <unify!jwc@Sun.COM> for contributing 99% of this. If you run into any problems with this, compilation with -DNO_WALK_MENUS will revert to the previous menu format. *** /tmp/,RCSt1002753 Wed Jul 11 21:30:33 1990 --- Mailrc Wed Jul 4 15:36:14 1990 *************** *** 52,59 **** cmd se set cmd shell sh cmd so source ! cmd un undelete ! cmd unread 'flags \!* U' # "unread" is undocumented in Mail cmd uns unset cmd vi v cmd z 'z \!* + | from -' # "z" changes current message in Mail --- 52,61 ---- cmd se set cmd shell sh cmd so source ! cmd u 'u \!* | pick -1 | from -' # "u" changes current message in Mail ! cmd un u ! cmd undelete u ! cmd unread 'flags \!* +U' # "unread" is undocumented in Mail cmd uns unset cmd vi v cmd z 'z \!* + | from -' # "z" changes current message in Mail *** /tmp/,RCSt1002753 Wed Jul 11 21:32:30 1990 --- README Wed Jul 11 21:32:23 1990 *************** *** 81,86 **** --- 81,89 ---- SUN_4_0, or SUN_4_1 depending on your SunOS version. If SUNTOOL is the only thing defined, SUN_4_0 will be used. + You may also choose to define NO_WALK_MENUS to disable walking menus + for file names selectable from the "folder" and "save" command items. + If you are on a BSD UNIX machine: You should use the makefile.bsd makefile. *** /tmp/,RCSt1002753 Wed Jul 11 21:32:39 1990 --- commands.c Wed Jul 11 21:26:46 1990 *************** *** 440,447 **** --- 440,451 ---- if (firstchar != 'c' && n > 0) (void) do_hdrs(0, DUBL_NULL, NULL); if (*mode == 'w' && n > 0) { + #ifndef NO_WALK_MENUS + create_folder_menus(); + #else /* NO_WALK_MENUS */ add_folder_to_menu(folder_item, 3); add_folder_to_menu(save_item, 1); + #endif /* NO_WALK_MENUS */ } } #endif /* SUNTOOL */ *************** *** 615,623 **** /* goto next available message if current was just deleted. * If there are no more messages, turnoff prnt_next. */ ! if (!iscurses && !undel && msg_bit(list, current_msg) && ! (ison(msg[current_msg].m_flags, DELETE) || ! ison(msg[current_msg].m_flags, SAVED))) (void) next_msg(); else prnt_next = 0; --- 619,625 ---- /* goto next available message if current was just deleted. * If there are no more messages, turnoff prnt_next. */ ! if (!iscurses && !undel && msg_bit(list, current_msg)) (void) next_msg(); else prnt_next = 0; *************** *** 632,643 **** } #ifdef SUNTOOL if (istool && isoff(glob_flags, IS_PIPE)) { ! char *av[3], buf[8]; ! /* do_hdrs(0, ...) repositions the display, so pass an arg */ ! av[0] = "h"; ! av[1] = sprintf(buf, "%d", n_array[0] + 1); ! av[2] = NULL; ! (void) do_hdrs(2, av, NULL); } #endif /* SUNTOOL */ return 0; --- 634,649 ---- } #ifdef SUNTOOL if (istool && isoff(glob_flags, IS_PIPE)) { ! if (current_msg != old_msg && !do_set(set_options, "show_deleted")) ! (void) do_hdrs(0, DUBL_NULL, NULL); ! else { ! char *av[3], buf[8]; ! /* do_hdrs(0, ...) repositions the display, so pass an arg */ ! av[0] = "h"; ! av[1] = sprintf(buf, "%d", n_array[0] + 1); ! av[2] = NULL; ! (void) do_hdrs(2, av, NULL); ! } } #endif /* SUNTOOL */ return 0; *** /tmp/,RCSt1002753 Wed Jul 11 21:32:40 1990 --- config.h-dist Tue Jul 10 08:34:56 1990 *************** *** 85,93 **** /* If your mailer does not understand commas between addresses, you should * define NO_COMMAS. This includes pre-3.0 smail and default MTAs used on * xenix, and sys-v systems. ! * This does NOT apply to MMDF or sendmail. */ ! /* #define NO_COMMAS /**/ /* * Most RFC822 compliant mailers (sendmail) will add the headers From: --- 85,95 ---- /* If your mailer does not understand commas between addresses, you should * define NO_COMMAS. This includes pre-3.0 smail and default MTAs used on * xenix, and sys-v systems. ! * This does NOT apply to MMDF or sendmail, in most cases. */ ! #ifdef SUN_4_1 /* SunOS 4.1 has warped sendmail.cf */ ! #define NO_COMMAS /**/ ! #endif /* SUN_4_1 /* * Most RFC822 compliant mailers (sendmail) will add the headers From: *** /tmp/,RCSt1002753 Wed Jul 11 21:32:46 1990 --- file.c Thu May 3 12:44:05 1990 *************** *** 217,223 **** (void) fclose(*fp); if (!(*fp = fopen(fname, "w"))) ret = -1; ! ret = 0; (void) umask(omask); return ret; } --- 217,224 ---- (void) fclose(*fp); if (!(*fp = fopen(fname, "w"))) ret = -1; ! else ! ret = 0; (void) umask(omask); return ret; } *** /tmp/,RCSt1002753 Wed Jul 11 21:32:47 1990 --- folders.c Wed Jul 4 16:54:04 1990 *************** *** 125,130 **** --- 125,131 ---- /* an error occured updating the folder */ return -1; } + turnoff(glob_flags, CORRUPTED); /* copyback() was successful */ /* Assure that both oldfolder and mailfile are full paths */ if (strcmp(mailfile, buf) || !*oldfolder) { n = 1; /* force load of new folder */ *** /tmp/,RCSt1002753 Wed Jul 11 21:32:49 1990 --- glob.h Wed May 23 19:58:51 1990 *************** *** 3,10 **** --- 3,14 ---- #endif /* BSD */ #ifdef DIRECTORY + #ifdef SYSV /* Some SysV 3.0 or higher */ + #include <dirent.h> + #else /* SYSV */ #include <sys/dir.h> #define dirent direct + #endif #else /* !DIRECTORY */ /* *** /tmp/,RCSt1002753 Wed Jul 11 21:32:50 1990 --- hdrs.c Thu Jul 5 09:22:07 1990 *************** *** 529,537 **** * "important" part is readable only for ! paths/addresses. */ while (p3 = index(p2, '!')) { ! int tmp = strlen(p3+1); /* xenix has compiler problems */ p2 = p3+1; ! if (tmp + isauthor*4 < pad) { if (isauthor && (p2 -= 4) < old_p2) p2 = old_p2; break; --- 529,537 ---- * "important" part is readable only for ! paths/addresses. */ while (p3 = index(p2, '!')) { ! len = strlen(p3+1); /* xenix has compiler problems */ p2 = p3+1; ! if (len + isauthor*4 < pad) { if (isauthor && (p2 -= 4) < old_p2) p2 = old_p2; break; *************** *** 539,544 **** --- 539,551 ---- } if (isauthor && p2 > old_p2+4 && !p3 && strlen(p2) + 4 > pad) p2 -= 4; + if (p3 && (p3 = rindex(p2, '@'))) { + len = strlen(p3); + while (len-- && --p2 > old_p2) { + if (*(p2 + isauthor*4 - 1) == '!') + break; + } + } if (old_p2 != p2 && isauthor) (void) strncpy(p2, "TO: ", 4); /* doesn't null terminate */ } *** /tmp/,RCSt1002753 Wed Jul 11 21:32:53 1990 --- lock.c Tue Jun 19 13:19:03 1990 *************** *** 123,133 **** char *mode; { FILE *mail_fp = NULL_FILE; - #ifndef LCKDFLDIR int fd, lk; int cnt = 0; SIGRET (*oldint)(), (*oldquit)(); ! #else /* LCKDFLDIR */ extern FILE *lk_fopen(); #endif /* !LCKDFLDIR */ --- 123,132 ---- char *mode; { FILE *mail_fp = NULL_FILE; int fd, lk; int cnt = 0; SIGRET (*oldint)(), (*oldquit)(); ! #ifdef LCKDFLDIR extern FILE *lk_fopen(); #endif /* !LCKDFLDIR */ *************** *** 136,145 **** return NULL_FILE; } - #ifdef LCKDFLDIR - return lk_fopen(filename, mode, NULL, NULL, 0); - #else /* !LCKDFLDIR */ - #ifdef DOT_LOCK if (dot_lock(filename) == 0) #endif /* DOT_LOCK */ --- 135,140 ---- *************** *** 154,161 **** lk = LOCK_SH | LOCK_NB; on_intr(); ! while (isoff(glob_flags, WAS_INTR) && flock(fd, lk)) { ! if (errno == EWOULDBLOCK) { if (isoff(glob_flags, REDIRECT)) if (!cnt++) print("\nwaiting to lock"); --- 149,168 ---- lk = LOCK_SH | LOCK_NB; on_intr(); ! #ifdef LCKDFLDIR ! (void) fclose(mail_fp); ! while (isoff(glob_flags, WAS_INTR) && ! !(mail_fp = lk_fopen(filename, mode, NULL, NULL, 0))) ! #else /* !LCKDFLDIR */ ! while (isoff(glob_flags, WAS_INTR) && flock(fd, lk)) ! #endif /* LCKDFLDIR */ ! { ! #ifdef LCKDFLDIR ! if (Access(filename, any(mode, "aw+") ? W_OK : R_OK) == 0) ! #else /* !LCKDFLDIR */ ! if (errno == EWOULDBLOCK) ! #endif /* LCKDFLDIR */ ! { if (isoff(glob_flags, REDIRECT)) if (!cnt++) print("\nwaiting to lock"); *************** *** 179,185 **** return NULL_FILE; } return mail_fp; - #endif /* LCKDFLDIR */ } /*ARGSUSED*/ --- 186,191 ---- *** /tmp/,RCSt1002753 Wed Jul 11 21:32:54 1990 --- loop.c Wed Jul 4 15:39:39 1990 *************** *** 1280,1287 **** num_of_hists = min(hist_size, hist_no); if (!reverse) ! while (hist_no - hist->histno > num_of_hists) { ! (void) printf("skipping %d\n", hist->histno); hist = hist->next; } --- 1280,1287 ---- num_of_hists = min(hist_size, hist_no); if (!reverse) ! while (hist_no - hist->histno >= num_of_hists) { ! Debug("skipping %d\n", hist->histno); hist = hist->next; } *** /tmp/,RCSt1002753 Wed Jul 11 21:32:57 1990 --- mail.c Wed Jul 4 15:28:00 1990 *************** *** 899,907 **** } if (*p != '!' && !do_set(set_options, "nosave")) dead_letter(0); ! if (emptyfile(&ed_fp, edfile) == -1) error(edfile); ! else print("Message buffer empty\n"); when 'q': /* save in dead.letter if nosave not set -- rm_edfile(-2). */ --- 899,908 ---- } if (*p != '!' && !do_set(set_options, "nosave")) dead_letter(0); ! if (emptyfile(&ed_fp, edfile) == -1) { error(edfile); ! return -1; ! } else print("Message buffer empty\n"); when 'q': /* save in dead.letter if nosave not set -- rm_edfile(-2). */ *************** *** 982,988 **** } /* ~v on the Cc line asks for verification, first initialize p! */ p = NULL; ! if (!strncmp(Cc, "~v", 2) || (p = do_set(set_options, "verify"))) { if (!p) /* so we don't Cc to ~v! */ *Cc = 0; for (;;) { --- 983,992 ---- } /* ~v on the Cc line asks for verification, first initialize p! */ p = NULL; ! if (!strncmp(Cc, "~v", 2) || ! /* Flashy test for $verify either empty or set to "mail" */ ! glob(p = do_set(set_options, "verify"), ! "{,{,*[ \\,]}mail{,[ \\,]*}}")) { if (!p) /* so we don't Cc to ~v! */ *Cc = 0; for (;;) { *************** *** 1504,1510 **** * created a From: header with the my_hdr command (the own_hdrs list). * If his is not legitimate, warn user and use the other header. */ ! if ((for_editor || isoff(glob_flags, EDIT_HDRS)) && own_hdrs && !do_set(set_options, "no_hdrs")) { for (opts = own_hdrs; opts; opts = opts->next) if (!strcmp(opts->option, "From:")) { --- 1508,1514 ---- * created a From: header with the my_hdr command (the own_hdrs list). * If his is not legitimate, warn user and use the other header. */ ! if ((for_editor || isoff(flags, EDIT_HDRS)) && own_hdrs && !do_set(set_options, "no_hdrs")) { for (opts = own_hdrs; opts; opts = opts->next) if (!strcmp(opts->option, "From:")) { *** /tmp/,RCSt1002753 Wed Jul 11 21:33:00 1990 --- main.c Wed Jul 4 07:23:41 1990 *************** *** 40,49 **** #ifdef LCKDFLDIR lckdfldir = LCKDFLDIR; #endif /* LCKDFLDIR */ ! if (prog_name = rindex(*argv, '/')) ! prog_name++; ! else ! prog_name = *argv; (void) signal(SIGBUS, bus_n_seg); (void) signal(SIGSEGV, bus_n_seg); --- 40,46 ---- #ifdef LCKDFLDIR lckdfldir = LCKDFLDIR; #endif /* LCKDFLDIR */ ! prog_name = basename(*argv); (void) signal(SIGBUS, bus_n_seg); (void) signal(SIGSEGV, bus_n_seg); *** /tmp/,RCSt1002753 Wed Jul 11 21:33:06 1990 --- msgs.c Wed Jul 4 17:07:44 1990 *************** *** 270,277 **** */ if (!first && mail_size()) { lost_lock: ! if (get_new_mail(TRUE) && prompt && isoff(glob_flags, REDIRECT) ! && show_new_mail()) { char buf[80]; if (iscurses) putchar('\n'), turnon(glob_flags, CNTD_CMD); --- 270,277 ---- */ if (!first && mail_size()) { lost_lock: ! if ((ison(glob_flags, CORRUPTED) || get_new_mail(TRUE)) && ! prompt && isoff(glob_flags, REDIRECT) && show_new_mail()) { char buf[80]; if (iscurses) putchar('\n'), turnon(glob_flags, CNTD_CMD); *************** *** 280,286 **** buf[0] = 0; #ifdef SUNTOOL if (istool) { ! (void) sprintf(buf, "New mail -- %s", prompt); if (ask(buf) != TRUE) return 0; } else --- 280,288 ---- buf[0] = 0; #ifdef SUNTOOL if (istool) { ! (void) sprintf(buf, "%s -- %s", ! ison(glob_flags, CORRUPTED) ? "Error" : "New mail", ! prompt); if (ask(buf) != TRUE) return 0; } else *************** *** 287,298 **** #endif /* SUNTOOL */ if (!Getstr(buf, sizeof (buf), 0) || lower(*buf) != 'y') return 0; } } first = 0; /* If the user hasn't changed anything, just return true */ ! if (isoff(glob_flags, DO_UPDATE)) return 1; if (ison(glob_flags, READ_ONLY)) { print("Unable to update %s: read only\n", mailfile); --- 289,301 ---- #endif /* SUNTOOL */ if (!Getstr(buf, sizeof (buf), 0) || lower(*buf) != 'y') return 0; + turnoff(glob_flags, CORRUPTED); /* User says go ahead */ } } first = 0; /* If the user hasn't changed anything, just return true */ ! if (isoff(glob_flags, DO_UPDATE) || ison(glob_flags, CORRUPTED)) return 1; if (ison(glob_flags, READ_ONLY)) { print("Unable to update %s: read only\n", mailfile); *************** *** 316,323 **** if (!(mail_fp = lock_fopen(mailfile, "r+"))) { error("WARNING: unable to lock %s -- update aborted", mailfile); #ifdef SUNTOOL ! write_err = 1; /* forces return 0; below */ ! goto resume_timer; /* blecch */ #else /* !SUNTOOL */ return 0; #endif /* SUNTOOL */ --- 319,328 ---- if (!(mail_fp = lock_fopen(mailfile, "r+"))) { error("WARNING: unable to lock %s -- update aborted", mailfile); #ifdef SUNTOOL ! if (istool) { ! write_err = 1; /* forces return 0; below */ ! goto resume_timer; /* blecch */ ! } #else /* !SUNTOOL */ return 0; #endif /* SUNTOOL */ *** /tmp/,RCSt1002753 Wed Jul 11 21:33:10 1990 --- mush.1 Wed Jul 4 07:47:47 1990 *************** *** 2937,2944 **** searches for special mail headers in the author's message that indicate the most efficient mail path for return mail. .I Mush ! will search for the \*QReply-To:\*U, \*QReturn-Path:\*U, ! and \*QFrom:\*U headers, in that order, by default. .sp If none of these fields are found in the message, the first line of the message is parsed if possible; --- 2937,2944 ---- searches for special mail headers in the author's message that indicate the most efficient mail path for return mail. .I Mush ! will search for the \*QReply-To:\*U, ! \*QFrom:\*U, and \*QReturn-Path:\*U headers, in that order, by default. .sp If none of these fields are found in the message, the first line of the message is parsed if possible; *************** *** 4291,4296 **** --- 4291,4297 ---- If set to a string, that string is executed as a command when a carriage return is typed. Otherwise, carriage return prints the next undeleted message. + .TP .B newmail_icon (String) Set to a pathname for an alternate icon pixmap to use *************** *** 4578,4584 **** When replying to mail, .I Mush searches for return paths from the message by searching for ! the message headings \*QReply-to\*U, \*QReturn-path\*U, and \*QFrom:\*U, in that order. If none are found, then the first line of the message created by the delivery system is parsed and the address --- 4579,4585 ---- When replying to mail, .I Mush searches for return paths from the message by searching for ! the message headings \*QReply-to\*U, \*QFrom:\*U, and \*QReturn-path\*U, in that order. If none are found, then the first line of the message created by the delivery system is parsed and the address *************** *** 4778,4788 **** to print additional information about the sending process. .TP .B verify ! (Boolean) ! When through editing messages, just before sending, .B verify ! will ask you if you want to send, continue editing, or abort the ! whole message altogether. .TP .B version (Read-only String) --- 4779,4805 ---- to print additional information about the sending process. .TP .B verify ! (Boolean/Multivalued) ! This variable causes mush to request confirmation of certain actions. ! If set only as a boolean (no string value), .B verify ! will ask just before sending mail whether you want to send, continue ! editing, or abort the message altogether. ! Otherwise, ! .B verify ! can be set to one or more of these words: ! .sp ! .nf ! .ta 1.5i ! .in +4 ! .\" \& escapes are to make obvious the tab after each word ! mail\&\& Confirm sending of mail (as above). ! save\&\& Confirm save-item selections (tool only). ! .in -4 ! .fi ! .sp ! Appending of messages to files that are not folders is verified regardless ! of the setting of this variable. .TP .B version (Read-only String) *** /tmp/,RCSt1002753 Wed Jul 11 21:33:19 1990 --- mush.h Wed Jul 4 16:36:00 1990 *************** *** 379,384 **** --- 379,385 ---- #define QUOTE_MACRO ULBIT(23) /* protect current macro from recursive expan.. */ #define NEW_FRAME ULBIT(24) /* toolmode should build a new frame for pager */ #define HELP_TEXT ULBIT(25) /* create textsw frame for paging help messages */ + #define CORRUPTED ULBIT(26) /* error loading new mail has occurred */ /* flags to control composition */ #define VERBOSE ULBIT(0) /* verbose flag for sendmail */ *** /tmp/,RCSt1002753 Wed Jul 11 21:33:25 1990 --- signals.c Tue Jul 10 08:38:54 1990 *************** *** 74,79 **** --- 74,86 ---- wrapcolumn = atoi(fix); } turnoff(glob_flags, IS_GETTING); + #ifdef SYSV + /* Interrupting "await" leaves an alarm timer running, which + * some SysV systems mishandle. Clean up. + */ + if (!istool) + (void) signal(SIGALRM, SIG_IGN); + #endif /* SYSV */ longjmp(jmpbuf, 1); } else puts("exiting"), cleanup(sig); *************** *** 176,182 **** c = lower(*buf); } if (c != 'n' && *tempfile) { ! if (sig == SIGHUP && do_set(set_options, "hangup") && copyback(NULL)) (void) unlink(tempfile); else if (unlink(tempfile) && !sig && errno != ENOENT) error(tempfile); --- 183,190 ---- c = lower(*buf); } if (c != 'n' && *tempfile) { ! if (sig == SIGHUP && do_set(set_options, "hangup") && ! copyback(NULL) && isoff(glob_flags, CORRUPTED)) (void) unlink(tempfile); else if (unlink(tempfile) && !sig && errno != ENOENT) error(tempfile); *************** *** 229,238 **** if (isoff(glob_flags, READ_ONLY)) (void) emptyfile(&tmpf, tempfile); current_msg = msg_cnt = 0; } if (load_folder(mailfile, 1, NULL) < 1) { print("Can't load new mail: \"%s\" may be corrupted!\n", mailfile); ! turnon(glob_flags, DO_UPDATE); /* Don't reload without rewrite */ return update_size; /* NOTE: The above is used to stop check_new_mail() from calling * show_new_mail(), while still allowing copyback() to detect the --- 237,249 ---- if (isoff(glob_flags, READ_ONLY)) (void) emptyfile(&tmpf, tempfile); current_msg = msg_cnt = 0; + turnoff(glob_flags, CORRUPTED); } + if (ison(glob_flags, CORRUPTED)) + return 0; if (load_folder(mailfile, 1, NULL) < 1) { print("Can't load new mail: \"%s\" may be corrupted!\n", mailfile); ! turnon(glob_flags, CORRUPTED); return update_size; /* NOTE: The above is used to stop check_new_mail() from calling * show_new_mail(), while still allowing copyback() to detect the *************** *** 240,245 **** --- 251,260 ---- * should be a better-defined way to handle this. */ } + /* Prevent both bogus "new mail" messages and missed new mail */ + last_size = msg[msg_cnt].m_offset; + if (!strcmp(mailfile, spoolfile)) + spool_size = last_size; if (last_spool_size != spool_size) { if (update_size) last_spool_size = spool_size; *** /tmp/,RCSt1002753 Wed Jul 11 21:33:27 1990 --- strings.c Wed Jul 4 07:26:33 1990 *************** *** 442,444 **** --- 442,458 ---- *s_out = 0; return start; } + + /* + * This routine returns a pointer to the file portion of a path/file name. + */ + char * + basename(path) + register char *path; + { + char *file; + + if (file = rindex(path, '/')) + return ++file; + return path; + } *** /tmp/,RCSt1002753 Wed Jul 11 21:33:28 1990 --- strings.h Wed Jul 4 15:51:50 1990 *************** *** 21,26 **** --- 21,27 ---- *Sprintf(), /* See comments above function in strings.c */ *argv_to_string(), /* convert a vector of strings into one string */ *any(), /* return first char in str2 that exists in str1 */ + *basename(), /* return the last component of a file path */ *ctrl_strcpy(), /* string copy converting control chars to ascii */ *itoa(), /* return a string representation of a number */ *lcase_strcpy(), /* just like strcpy, but convert all chars to lower */ *** /tmp/,RCSt1002753 Wed Jul 11 21:33:29 1990 --- version.h Wed Jul 11 21:30:09 1990 *************** *** 1,7 **** /* @(#)version.h (c) Copyright 1989 (Dan Heller) */ #define MUSHNAME "Mail User's Shell" ! #define RELEASE_DATE "5/02/90" #define RELEASE 7 #define REVISION "1" ! #define PATCHLEVEL 1 --- 1,7 ---- /* @(#)version.h (c) Copyright 1989 (Dan Heller) */ #define MUSHNAME "Mail User's Shell" ! #define RELEASE_DATE "7/11/90" #define RELEASE 7 #define REVISION "1" ! #define PATCHLEVEL 2 *** /tmp/,RCSt1002753 Wed Jul 11 21:33:29 1990 --- viewopts.c Wed Jul 4 07:39:03 1990 *************** *** 184,190 **** { "unix", NULL, "Non-mush commands are considered to be UNIX commands." }, { "verify", NULL, ! "Verify to send, re-edit, or abort letter after editing." }, { "visual", "Visual editor:", "Visual editor for messages (default = $editor or env VISUAL)."}, { "warning", NULL, --- 184,190 ---- { "unix", NULL, "Non-mush commands are considered to be UNIX commands." }, { "verify", NULL, ! "Verify before acting in various situations, such as sending mail." }, { "visual", "Visual editor:", "Visual editor for messages (default = $editor or env VISUAL)."}, { "warning", NULL, *** /tmp/,RCSt1002926 Wed Jul 11 21:33:32 1990 --- doproc.c Wed Jul 11 21:26:46 1990 *************** *** 139,148 **** if (!(p = panel_get_value(item)) || !*p && (!(p = do_set(set_options, "mbox")) || !*p)) p = DEF_MBOX; ! (void) sprintf(msgstr, "%s in \"%s\"?", buf, trim_filename(p)); ! if (ask(msgstr) != TRUE) { ! wprint("Message not saved\n"); ! return PANEL_NONE; } (void) strcpy(b, p); /* now add to command */ } --- 139,150 ---- if (!(p = panel_get_value(item)) || !*p && (!(p = do_set(set_options, "mbox")) || !*p)) p = DEF_MBOX; ! if (chk_option("verify", "save")) { ! (void) sprintf(msgstr, "%s in \"%s\"?", buf, trim_filename(p)); ! if (ask(msgstr) != TRUE) { ! wprint("Message not saved\n"); ! return PANEL_NONE; ! } } (void) strcpy(b, p); /* now add to command */ } *************** *** 153,163 **** --- 155,231 ---- return PANEL_NONE; } + #ifndef NO_WALK_MENUS + void + xx_file_dir(item, value) + Panel_item item; + char * value; + { + char buf[BUFSIZ]; + u_long bang = ison(glob_flags, IGN_BANG); + + if (item == folder_item) { + (void) sprintf(buf, "folder %s ", + (ison(glob_flags, READ_ONLY) || ison(glob_flags, DO_UPDATE) && + !ask("Folder has been modified. Update changes?"))? "!" : ""); + strcat(buf, value); + } else if (item == save_item) { + char msgstr[BUFSIZ], *p; + register char *p2 = (char *)panel_get_value(msg_num_item); + (void) strcpy(buf, "save "); + + if (p2 && *p2) { + (void) strcat(buf, p2); + (void) strcat(buf, " "); + } + (void) strcat(buf, value); + if (chk_option("verify", "save")) { + (void) sprintf(msgstr, "Save in %s? ", trim_filename(value)); + if (ask(msgstr) != TRUE) { + wprint("Message not saved\n"); + return; + } + } + } + turnon(glob_flags, IGN_BANG); + (void) cmd_line(buf, msg_list); + if (!bang) + turnoff(glob_flags, IGN_BANG); + (void) panel_set(item, PANEL_VALUE, 0, NULL); /* remove last value */ + } + /* * callback routine for the panel items that need filename input. * (folder and save) */ void + do_file_dir(item, event) + Panel_item item; + Event *event; + { + if (item == folder_item) { + char *p = panel_get_value(folder_text_item); + if (!*p) { + ok_box("Enter folder name."); + return; + } + xx_file_dir(item, p); + } else if (item == save_item) { + if (!strcmp("Filename:", panel_get(file_item,PANEL_LABEL_STRING))) { + event_id(event) = '\n'; /* let file_dir think it got a \n */ + file_dir(file_item, event); + return; + } + } + (void) panel_set(item, PANEL_VALUE, 0, NULL); /* remove last value */ + } + #else /* NO_WALK_MENUS */ + + /* + * callback routine for the panel items that need filename input. + * (folder and save) + */ + void do_file_dir(item, value, event) Panel_item item; int value; *************** *** 206,215 **** (void) strcat(buf, p); } else (void) strcat(buf, p = panel_get(item, PANEL_CHOICE_STRING, value)); ! (void) sprintf(msgstr, "Save in %s? ", trim_filename(p)); ! if (ask(msgstr) != TRUE) { ! wprint("Message not saved\n"); ! return; } } turnon(glob_flags, IGN_BANG); --- 274,285 ---- (void) strcat(buf, p); } else (void) strcat(buf, p = panel_get(item, PANEL_CHOICE_STRING, value)); ! if (chk_option("verify", "save")) { ! (void) sprintf(msgstr, "Save in %s? ", trim_filename(p)); ! if (ask(msgstr) != TRUE) { ! wprint("Message not saved\n"); ! return; ! } } } turnon(glob_flags, IGN_BANG); *************** *** 218,223 **** --- 288,294 ---- turnoff(glob_flags, IGN_BANG); (void) panel_set(item, PANEL_VALUE, 0, NULL); /* remove last value */ } + #endif /* NO_WALK_MENUS */ /*ARGSUSED*/ void *** /tmp/,RCSt1002926 Wed Jul 11 21:33:35 1990 --- hdr_sw.c Wed Jul 11 21:26:47 1990 *************** *** 19,26 **** static Notify_value scroll_hdr(); static void msg_menu_func(), do_menu(), msg_menu_notify(); ! static Menu msg_menu; ! static Menu_item cur_msg_item; void make_hdr_sw(parent) --- 19,25 ---- static Notify_value scroll_hdr(); static void msg_menu_func(), do_menu(), msg_menu_notify(); ! Menu msg_menu; void make_hdr_sw(parent) *************** *** 261,267 **** char *data; /* Menu item client data. */ }; ! static void get_msg_menu() { int i; --- 260,266 ---- char *data; /* Menu item client data. */ }; ! void get_msg_menu() { int i; *************** *** 278,284 **** { "Help", HELP_MSG }, }; ! msg_menu = menu_create(MENU_NOTIFY_PROC, msg_menu_notify, NULL); for (i = 0; i < ArraySize(msg_items); i++) { mi = menu_create_item(MENU_STRING, msg_items[i].str, MENU_CLIENT_DATA, msg_items[i].data, --- 277,283 ---- { "Help", HELP_MSG }, }; ! msg_menu = menu_create(MENU_NOTIFY_PROC, menu_return_item, NULL); for (i = 0; i < ArraySize(msg_items); i++) { mi = menu_create_item(MENU_STRING, msg_items[i].str, MENU_CLIENT_DATA, msg_items[i].data, *************** *** 288,301 **** } static void - msg_menu_notify(menu, item) - Menu menu; - Menu_item item; - { - cur_msg_item = item; - } - - static void do_menu(can_sw, event, fd, message) Canvas can_sw; Event *event; --- 287,292 ---- *************** *** 302,307 **** --- 293,300 ---- int fd, message; { char *action; + char * save_place; + Menu_item cur_msg_item; static char buf[16]; if (!msg_cnt) { *************** *** 323,329 **** box(0, 5 + line * l_height(), hdr_rect->r_width, 5 + (line+1) * l_height()); /* show menu */ ! menu_show(msg_menu, can_sw, event, NULL); /* remove feedback */ box(0, 5 + line * l_height(), hdr_rect->r_width, 5 + (line+1) * l_height()); --- 316,322 ---- box(0, 5 + line * l_height(), hdr_rect->r_width, 5 + (line+1) * l_height()); /* show menu */ ! cur_msg_item = menu_show(msg_menu, can_sw, event, NULL); /* remove feedback */ box(0, 5 + line * l_height(), hdr_rect->r_width, 5 + (line+1) * l_height()); *************** *** 330,337 **** /* if user selected something, figure out what was selected. */ if (!cur_msg_item) return; ! action = (char *) menu_get(cur_msg_item, MENU_CLIENT_DATA); ! cur_msg_item = (Menu_item)NULL; } else action = (char *) event; --- 323,338 ---- /* if user selected something, figure out what was selected. */ if (!cur_msg_item) return; ! #ifndef NO_WALK_MENUS ! if ((Menu)menu_get(cur_msg_item, MENU_PARENT) == msg_menu) { ! action = (char *) menu_get(cur_msg_item, MENU_CLIENT_DATA); ! } else { ! save_place = (char *)menu_get(cur_msg_item, MENU_CLIENT_DATA); ! action = SAVE_MSG; ! } /* endif */ ! #else /* NO_WALK_MENUS */ ! action = (char *) menu_get(cur_msg_item, MENU_CLIENT_DATA); ! #endif /* NO_WALK_MENUS */ } else action = (char *) event; *************** *** 341,348 **** extern Panel_item msg_num_item, save_item; (void) panel_set(msg_num_item, PANEL_VALUE, sprintf(buf, "%d", message+1), NULL); ! event_id(event) = MS_LEFT; ! do_file_dir(save_item, 0, event); (void) panel_set(msg_num_item, PANEL_VALUE, NO_STRING, NULL); } when HELP_MSG : --- 342,357 ---- extern Panel_item msg_num_item, save_item; (void) panel_set(msg_num_item, PANEL_VALUE, sprintf(buf, "%d", message+1), NULL); ! #ifndef NO_WALK_MENUS ! if (*save_place == '\0') { /* magic to mean "use Filename:" */ ! do_file_dir(save_item, event); ! } else { ! xx_file_dir(save_item, save_place); ! } /* endif */ ! #else /* NO_WALK_MENUS */ ! event_id(event) = MS_LEFT; ! do_file_dir(save_item, 0, event); ! #endif /* NO_WALK_MENUS */ (void) panel_set(msg_num_item, PANEL_VALUE, NO_STRING, NULL); } when HELP_MSG : *** /tmp/,RCSt1002926 Wed Jul 11 21:33:38 1990 --- panels.c Wed Jul 11 21:26:47 1990 *************** *** 31,36 **** --- 31,47 ---- save_item, /* saves messages */ sub_hdr_item[6]; /* display items that just sit there and give help */ + #ifndef NO_WALK_MENUS + Panel + folder_panel, + save_panel; + Menu folder_menu; /* Menu of folders for folder button */ + Menu save_menu; /* Menu of folders for save button */ + Menu hdr_save_menu;/* Menu of folders for save option in hdr window */ + extern Menu msg_menu; /* header subwindow menu, defined in hdr_sw.c */ + walk_menu_event(); + #endif /* NO_WALK_MENUS */ + /* These global panel items for letter composition should eventually go away */ Panel_item edit_item, /* edit a message */ *************** *** 75,80 **** --- 86,101 ---- PANEL_NOTIFY_PROC, do_help, NULL); + #ifndef NO_WALK_MENUS + folder_panel = panel; + folder_item = panel_create_item(panel, PANEL_BUTTON, + PANEL_ATTRIBUTE_LIST, button_args, + PANEL_LABEL_IMAGE, + panel_button_image(panel, "Folder", 6, mush_font), + PANEL_NOTIFY_PROC, do_file_dir, + PANEL_EVENT_PROC, walk_menu_event, + NULL); + #else /* NO_WALK_MENUS */ folder_item = panel_create_item(panel, PANEL_CHOICE, PANEL_ATTRIBUTE_LIST, choice_args, PANEL_LABEL_IMAGE, *************** *** 85,90 **** --- 106,112 ---- NULL); add_folder_to_menu(folder_item, 3); + #endif /* NO_WALK_MENUS */ folder_text_item = panel_create_item(panel, PANEL_TEXT, PANEL_ATTRIBUTE_LIST, choice_args, *************** *** 214,219 **** --- 236,252 ---- PANEL_NOTIFY_PROC, delete_mail, NULL); + #ifndef NO_WALK_MENUS + save_panel = panel; + save_item = panel_create_item(panel, PANEL_BUTTON, + PANEL_ATTRIBUTE_LIST, button_args, + PANEL_LABEL_IMAGE, panel_button_image(panel, "Save", 4, mush_font), + PANEL_NOTIFY_PROC, do_file_dir, + PANEL_EVENT_PROC, walk_menu_event, + NULL); + + create_folder_menus(); + #else /* NO_WALK_MENUS */ { char *mbox = do_set(set_options, "mbox"); if (!mbox || !*mbox) *************** *** 227,232 **** --- 260,266 ---- } add_folder_to_menu(save_item, 1); + #endif /* NO_WALK_MENUS */ file_item = panel_create_item(panel, PANEL_TEXT, PANEL_ATTRIBUTE_LIST, choice_args, *************** *** 391,445 **** #include "glob.h" ! #ifdef WALK_MENUS ! folder_menu_notify(menu, mi) ! Menu menu; ! Menu_item mi; ! { ! } ! static Menu_item ! add_path_to_menu(menu, path) ! Menu menu; char *path; { - DIR *dirp; - struct dirent *dp; - struct stat s_buf; Menu_item mi; Menu next_menu; char buf[MAXPATHLEN]; /* don't add a folder to the list if user can't read it */ ! if (stat(path, &s_buf) == -1 || !(s_buf.st_mode & S_IREAD)) return NULL; if ((s_buf.st_mode & S_IFMT) == S_IFDIR) { int cnt = 0; ! if (!(dirp = opendir(path))) ! return NULL; /* don't bother adding to list if we can't scan it */ ! next_menu = menu_create(MENU_NOTIFY_PROC, folder_menu_notify, NULL); ! while (dp = readdir(dirp)) ! if (strcmp(dp->d_name, ".") && strcmp(dp->d_name, "..")) ! if (mi = add_path_to_menu(next_menu, ! sprintf(buf, "%s/%s", path, dp->d_name))) { ! menu_set(next_menu, MENU_APPEND_ITEM, mi, NULL); ! cnt++; } ! closedir(dirp); ! mi = menu_create_item(MENU_STRING, trim_filename(path), NULL); ! if (!cnt) { menu_destroy(next_menu); menu_set(mi, MENU_INACTIVE, TRUE, NULL); ! } else menu_set(mi, MENU_PULLRIGHT, next_menu, NULL); ! return mi; } ! /* we should check that this file is actually a folder */ ! return menu_create_item(MENU_STRING, trim_filename(path), NULL); } - #endif /* WALK_MENUS */ static add_path_to_menu(item, path, n) Panel_item item; char *path; --- 425,675 ---- #include "glob.h" ! #ifndef NO_WALK_MENUS ! static ! Menu_item ! make_folder_item(path) char *path; { Menu_item mi; + Menu_item sub_mi; Menu next_menu; + char **names, **np; + struct stat s_buf; char buf[MAXPATHLEN]; + if (glob(path, "*/{.,..}")) { + return NULL; + } + /* don't add a folder to the list if user can't read it */ ! if (stat(path, &s_buf) == -1 || !(s_buf.st_mode & S_IREAD)) { return NULL; + } + mi = menu_create_item( + MENU_STRING, savestr(basename(trim_filename(path))), + MENU_CLIENT_DATA, NULL, + MENU_RELEASE, /* no value */ + NULL); if ((s_buf.st_mode & S_IFMT) == S_IFDIR) { int cnt = 0; ! next_menu = menu_create(MENU_NOTIFY_PROC, menu_return_item, NULL); ! sprintf(buf, "%s/{.*,*}", path); ! if (filexp(buf, &names) > 0) { ! for (np = names; np && *np; np++) { ! if ((sub_mi = make_folder_item(*np)) != NULL) { ! menu_set(next_menu, MENU_APPEND_ITEM, sub_mi, NULL); ! ++cnt; } ! } ! free_vec(names); ! } ! if (! cnt) { menu_destroy(next_menu); menu_set(mi, MENU_INACTIVE, TRUE, NULL); ! } else { menu_set(mi, MENU_PULLRIGHT, next_menu, NULL); ! } ! } else if (test_folder(path, NULL)) { ! menu_set(mi, MENU_CLIENT_DATA, savestr(path), NULL); ! } else { ! menu_destroy(mi); ! mi = NULL; } ! return mi; } static + void + destroy_folder_item(menu_item, menu_type) + Menu_item menu_item; + Menu_attribute menu_type; + { + char *ptr; + + if (menu_type == MENU_ITEM) { + if ((ptr = (char *)menu_get(menu_item, MENU_STRING)) != NULL) { + free(ptr); + } + if ((ptr = (char *)menu_get(menu_item, MENU_CLIENT_DATA)) != NULL) { + free(ptr); + } + } + return; + } + + create_folder_menus() + { + int item_number; + Menu menu; + Menu_item menu_item; + int nitems; + char *mbox; + char *tmp = NULL; + char *p; + static int menus_exist = 0; + + if (menus_exist) { + /* remove duplicated menu items from save_menu */ + for (item_number = (int)menu_get(save_menu, MENU_NITEMS) ; + item_number > 1 ; --item_number) { + menu_set(save_menu, MENU_REMOVE, item_number, NULL); + } + /* remove duplicated menu items from hdr_save_menu */ + for (item_number = (int)menu_get(hdr_save_menu, MENU_NITEMS) ; + item_number > 1 ; --item_number) { + menu_set(save_menu, MENU_REMOVE, item_number, NULL); + } + menu_destroy_with_proc(hdr_save_menu, destroy_folder_item); + menu_destroy_with_proc(save_menu, destroy_folder_item); + menu_destroy_with_proc(folder_menu, destroy_folder_item); + } + + if (!(p = do_set(set_options, "folder")) || !*p) { + p = DEF_FOLDER; + } + if (p) { + int x = 0; + tmp = getpath(p, &x); + if (x == -1) { + if (errno != ENOENT) + print("%s: %s\n", p, tmp); + tmp = NULL; + } + } + menu = NULL; + menu_item = NULL; + if (tmp != NULL) { + if ((menu_item = make_folder_item(tmp)) != NULL) { + if ((menu = menu_get(menu_item, MENU_PULLRIGHT)) != NULL) { + /* $folder was a directory, use the pullright + * instead of the directory menu item. + */ + /* "unhook" the pullright (so it is not released) */ + menu_set(menu_item, MENU_PULLRIGHT, NULL, NULL); + /* destroy the menu item */ + menu_destroy_with_proc(menu_item, destroy_folder_item); + menu_item = NULL; + } + } + } + if (menu == NULL) { + menu = menu_create(MENU_NOTIFY_PROC, menu_return_item, NULL); + if (menu_item != NULL) { + menu_set(menu, MENU_APPEND_ITEM, menu_item, NULL); + } + } + + /* create save_menu */ + save_menu = menu_create(MENU_NOTIFY_PROC, menu_return_item, NULL); + /* add magic first item */ + mbox = do_set(set_options, "mbox"); + if (!mbox || !*mbox) { + mbox = DEF_MBOX; + } + menu_item = menu_create_item( + MENU_STRING, savestr(trim_filename(mbox)), + MENU_CLIENT_DATA, savestr(mbox), + MENU_RELEASE, /* no value */ + NULL); + menu_set(save_menu, MENU_APPEND_ITEM, menu_item, NULL); + /* copy menu for save_menu */ + nitems = (int)menu_get(menu, MENU_NITEMS); + for (item_number = 1 ; item_number <= nitems ; ++item_number) { + menu_set(save_menu, + MENU_APPEND_ITEM, menu_get(menu, MENU_NTH_ITEM, item_number), + NULL); + } + + /* create hdr_save_menu */ + hdr_save_menu = menu_create(MENU_NOTIFY_PROC, menu_return_item, NULL); + /* add magic first item */ + menu_item = menu_create_item( + MENU_STRING, savestr("use Filename:"), + MENU_CLIENT_DATA, savestr(""), /* magic */ + MENU_RELEASE, /* no value */ + NULL); + menu_set(hdr_save_menu, MENU_APPEND_ITEM, menu_item, NULL); + /* copy save_menu for hdr_save_menu */ + nitems = (int)menu_get(save_menu, MENU_NITEMS); + for (item_number = 1 ; item_number <= nitems ; ++item_number) { + menu_set(hdr_save_menu, + MENU_APPEND_ITEM, menu_get(save_menu, MENU_NTH_ITEM, item_number), + NULL); + } + /* Make sure the header subwindow menu exists so we can tack on a + * pullright for Save. + */ + if (! msg_menu) { + get_msg_menu(); + } + if ((menu_item = menu_find(msg_menu, MENU_STRING, "Save", NULL)) + != NULL) { + menu_set(menu_item, MENU_PULLRIGHT, hdr_save_menu, NULL); + } + + /* insert folder-specific initial options to menu */ + folder_menu = menu; + menu_item = menu_create_item( + MENU_STRING, savestr("System Mailbox"), + MENU_CLIENT_DATA, savestr("%"), + MENU_RELEASE, /* no value */ + NULL); + menu_set(folder_menu, MENU_INSERT, 0, menu_item, NULL); + menu_item = menu_create_item( + MENU_STRING, savestr("Main Mailbox"), + MENU_CLIENT_DATA, savestr("&"), + MENU_RELEASE, /* no value */ + NULL); + menu_set(folder_menu, MENU_INSERT, 1, menu_item, NULL); + menu_item = menu_create_item( + MENU_STRING, savestr("Last Accessed Folder"), + MENU_CLIENT_DATA, savestr("#"), + MENU_RELEASE, /* no value */ + NULL); + menu_set(folder_menu, MENU_INSERT, 2, menu_item, NULL); + + menus_exist = 1; + return; + } + + static + walk_menu_event(item, event) + Panel_item item; + Event *event; + { + char *folder_name; + Menu_item selection; + Menu menu; + Panel panel; + void xx_file_dir(); + + if (event_id(event) == MS_RIGHT && event_is_down(event)) { + if (item == folder_item) { + menu = folder_menu; + panel = folder_panel; + } else { + menu = save_menu; + panel = save_panel; + } + selection = (Menu_item)menu_show(menu, panel, event, 0); + if (! selection) { + /* no selection was made */ + return; + } + if ((folder_name = (char *)menu_get(selection, MENU_CLIENT_DATA)) + != NULL) { + xx_file_dir(item, folder_name); + } + } else { + panel_default_handle_event(item, event); + } + } + + #else /* NO_WALK_MENUS */ + + static add_path_to_menu(item, path, n) Panel_item item; char *path; *************** *** 476,484 **** Panel_item item; { char *tmp = NULL, *p; - #ifdef WALK_MENUS - Menu_item mi; - #endif /* WALK_MENUS */ if (!(p = do_set(set_options, "folder")) || !*p) p = DEF_FOLDER; --- 706,711 ---- *************** *** 492,501 **** } } if (tmp) { - #ifdef WALK_MENUS - mi = add_path_to_menu(menu, tmp); - #else /* WALK_MENUS */ add_path_to_menu(item, tmp, &n); - #endif /* WALK_MENUS */ } } --- 719,725 ---- } } if (tmp) { add_path_to_menu(item, tmp, &n); } } + #endif /* NO_WALK_MENUS */
jwc@Unify.Com (J. William Claypool) (07/12/90)
In article <10491@ogicse.ogc.edu> schaefer@ogicse.cse.ogi.edu (Barton E. Schaefer) writes: > For SunView users, walking menus are now used for the file names > displayed under the <Folder> and <Save> items. This neatens up > display of nested directory structures and avoids the menu size > limits of SunView in most cases. Thanks to J. William Claypool > <unify!jwc@Sun.COM> for contributing 99% of this. If you run into > any problems with this, compilation with -DNO_WALK_MENUS will > revert to the previous menu format. I'm flattered. But, Duane R. Gibson <drg@Unify.Com> actually did the work. I just encouraged him to do it and send it in. -- Bill Claypool +1 916 920 1830 x341| I know what I know if you know what I mean jwc@Unify.Com |-------------------------------------------- ...!{csusac,pyramid}!unify!jwc | SCCA SFR Solo II 74 es 1984 CRX 1.5
woods@eci386.uucp (Greg A. Woods) (07/18/90)
In article <10491@ogicse.ogc.edu> schaefer@ogicse.cse.ogi.edu (Barton E. Schaefer) writes: > This is Official Patch #2 for Mush 7.1. >[....] > Handling of "corrupted" spool mailboxes has been improved. The > size of the spool file is now correctly recorded on new mail checks, > which should reduce the frequency of corruption reports on systems > that rely on DOT_LOCKing. Unfortunately the code for DOT_LOCKing is still very closely tied to either BSD, or SysVr3.0+ (i.e SVID vol. 3). It will not work on earlier versions of SysV, i.e. those described by SVID vol. 1. According to the SVID vol. 1, setuid(BA_OS), there is no "saved-set-group-ID" capability in SysV. This means that either mush is made setuid root, or another locking mechanism is found. Our 3b1's (which run a bastardized version of SysVr2.1) also have smail2.5 and lmail2.6 installed, and since lmail2.6 uses a similar (and compatible) scheme to DOT_LOCKing, I've decided to write a pair of helper programmes which can be exec()'ed to lock and unlock the mailbox, instead of changing the locking scheme. I'll post these here, instead of just mailing them off to Bart for inclusion in the next patch. I do so in order to allow other SysVr2 sites to get running safely as soon as possible, as well as to solicit comment on other possible solutions (I think these are far from being the most desirable, or secure, solution). I'm also considering adding a couple of locking enhancements to lmail, specifically also have it lockf() the file if lockf() is available, and perhaps have it set the modes on mailboxes such that mandatory locking (if available) is enforced by lockf() on all read()'s and write()'s. Anyway, here it is. Note that a patch for "Makefile" is also included. Makefile was derived directly from makefile.sys.v, as the patch indicates. #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of shell archive." # Contents: Patch.sVr2 dolock.c undolock.c # Wrapped by woods@gate.UUCP on Tue Jul 17 22:05:04 1990 PATH=/bin:/usr/bin:/usr/lbin ; export PATH if test -f 'Patch.sVr2' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Patch.sVr2'\" else echo shar: Extracting \"'Patch.sVr2'\" \(6913 characters\) sed "s/^X//" >'Patch.sVr2' <<'END_OF_FILE' XIndex: Makefile X*** makefile.sys.v Sat May 12 22:16:31 1990 X--- Makefile Tue Jul 17 20:31:43 1990 X*************** X*** 27,33 X X # IRIX 3.2 systems (SGI Iris workstations) should add -DDIRECTORY to CFLAGS X X! CFLAGS= -O -DSYSV -DUSG -DCURSES -DREGCMP -DSIGRET=void X LDFLAGS= X LIBS= -lcurses -lPW X OTHERLIBS= X X--- 27,33 ----- X X # IRIX 3.2 systems (SGI Iris workstations) should add -DDIRECTORY to CFLAGS X X! CFLAGS= -O -DSYSV -DSYSVR2 -DUSG -DCURSES -DREGCMP -DSIGRET=int -DDIRECTORY -DSMAIL X LDFLAGS= X LIBS= -lcurses -lPW -ldirent -lmalloc X OTHERLIBS= X*************** X*** 29,35 X X CFLAGS= -O -DSYSV -DUSG -DCURSES -DREGCMP -DSIGRET=void X LDFLAGS= X! LIBS= -lcurses -lPW X OTHERLIBS= X # Use some variant of this one if you #define MMDF in config.h X #OTHERLIBS=/usr/src/mmdf/lib/libmmdf.a X X--- 29,35 ----- X X CFLAGS= -O -DSYSV -DSYSVR2 -DUSG -DCURSES -DREGCMP -DSIGRET=int -DDIRECTORY -DSMAIL X LDFLAGS= X! LIBS= -lcurses -lPW -ldirent -lmalloc X OTHERLIBS= X # Use some variant of this one if you #define MMDF in config.h X #OTHERLIBS=/usr/src/mmdf/lib/libmmdf.a X*************** X*** 35,40 X #OTHERLIBS=/usr/src/mmdf/lib/libmmdf.a X PROG= mush X X $(PROG): $(OBJS1) $(OBJS2) X @echo loading... X @$(CC) $(LDFLAGS) $(OBJS1) $(OBJS2) -o $(PROG) $(LIBS) $(OTHERLIBS) X X--- 35,44 ----- X #OTHERLIBS=/usr/src/mmdf/lib/libmmdf.a X PROG= mush X X+ #if SYSVR2 X+ all: $(PROG) dolock undolock X+ #endif SYSVR2 X+ X $(PROG): $(OBJS1) $(OBJS2) X $(CC) $(LDFLAGS) $(OBJS1) $(OBJS2) -o $(PROG) $(LIBS) $(OTHERLIBS) X X*************** X*** 36,43 X PROG= mush X X $(PROG): $(OBJS1) $(OBJS2) X! @echo loading... X! @$(CC) $(LDFLAGS) $(OBJS1) $(OBJS2) -o $(PROG) $(LIBS) $(OTHERLIBS) X X $(OBJS1): $(HDRS1) $(HDRS2) X $(OBJS2): $(HDRS1) $(HDRS2) $(HDRS3) X X--- 40,46 ----- X #endif SYSVR2 X X $(PROG): $(OBJS1) $(OBJS2) X! $(CC) $(LDFLAGS) $(OBJS1) $(OBJS2) -o $(PROG) $(LIBS) $(OTHERLIBS) X X #if SYSVR2 X dolock: dolock.o X*************** X*** 39,44 X @echo loading... X @$(CC) $(LDFLAGS) $(OBJS1) $(OBJS2) -o $(PROG) $(LIBS) $(OTHERLIBS) X X $(OBJS1): $(HDRS1) $(HDRS2) X $(OBJS2): $(HDRS1) $(HDRS2) $(HDRS3) X loop.o: version.h X X--- 42,55 ----- X $(PROG): $(OBJS1) $(OBJS2) X $(CC) $(LDFLAGS) $(OBJS1) $(OBJS2) -o $(PROG) $(LIBS) $(OTHERLIBS) X X+ #if SYSVR2 X+ dolock: dolock.o X+ $(CC) $(LDFLAGS) dolock.o -o dolock X+ X+ undolock: undolock.o X+ $(CC) $(LDFLAGS) undolock.o -o undolock X+ #endif SYSVR2 X+ X $(OBJS1): $(HDRS1) $(HDRS2) X $(OBJS2): $(HDRS1) $(HDRS2) $(HDRS3) X loop.o: version.h X*************** X*** 43,51 X $(OBJS2): $(HDRS1) $(HDRS2) $(HDRS3) X loop.o: version.h X X! BINDIR= /usr/local/bin X! LIBDIR= /usr/local/lib X! MRCDIR= /usr/lib X MANDIR= /usr/local/man/man1 X MANEXT= 1 X X X--- 54,62 ----- X $(OBJS2): $(HDRS1) $(HDRS2) $(HDRS3) X loop.o: version.h X X! BINDIR= /usr/lbin X! LIBDIR= /usr/lib/mush X! MRCDIR= /usr/lib/mush X MANDIR= /usr/local/man/man1 X MANEXT= 1 X X*************** X*** 51,60 X X install: mush X cp mush $(BINDIR) X! strip $(BINDIR)/mush X! chmod 0755 $(BINDIR)/mush X! cp mush.1 $(MANDIR)/mush.$(MANEXT) X! chmod 0644 $(MANDIR)/mush.$(MANEXT) X cp cmd_help $(LIBDIR) X chmod 0644 $(LIBDIR)/cmd_help X cp Mushrc $(MRCDIR)/Mushrc X X--- 62,76 ----- X X install: mush X cp mush $(BINDIR) X! # strip $(BINDIR)/mush X! #if SYSV X! chgrp mail $(BINDIR)/mush X! chmod 2755 $(BINDIR)/mush X! #else X! # chmod 755 $(BINDIR)/mush X! #endif X! # cp mush.1 $(MANDIR)/mush.$(MANEXT) X! # chmod 0644 $(MANDIR)/mush.$(MANEXT) X cp cmd_help $(LIBDIR) X chmod 0644 $(LIBDIR)/cmd_help X # cp Mushrc $(MRCDIR)/Mushrc X*************** X*** 57,61 X chmod 0644 $(MANDIR)/mush.$(MANEXT) X cp cmd_help $(LIBDIR) X chmod 0644 $(LIBDIR)/cmd_help X! cp Mushrc $(MRCDIR)/Mushrc X! chmod 0644 $(MRCDIR)/Mushrc X X--- 73,87 ----- X # chmod 0644 $(MANDIR)/mush.$(MANEXT) X cp cmd_help $(LIBDIR) X chmod 0644 $(LIBDIR)/cmd_help X! # cp Mushrc $(MRCDIR)/Mushrc X! # chmod 0644 $(MRCDIR)/Mushrc X! cp Mail.rc $(MRCDIR) X! chmod 0644 $(MRCDIR)/Mail.rc X! #if SYSVR2 X! cp dolock $(LIBDIR) X! chgrp mail $(LIBDIR)/dolock X! chmod 2755 $(LIBDIR)/dolock X! cp undolock $(LIBDIR) X! chgrp mail $(LIBDIR)/undolock X! chmod 2755 $(LIBDIR)/undolock X! #endif SYSVR2 XIndex: lock.c X*** Standard Input Wed Dec 31 19:00:00 1969 X--- lock.c Tue Jul 17 21:47:06 1990 X*************** X*** 26,31 **** X--- 26,36 ---- X char buf[MAXPATHLEN]; X int lockfd, cnt = 0; X SIGRET (*oldint)(), (*oldquit)(); X+ #ifdef SYSVR2 X+ int status; X+ int lockpid; X+ int waitid; X+ #endif X X #ifdef SYSV X /* Only the spoolfile needs to be dot_locked -- other files are X*************** X*** 35,40 **** X--- 40,70 ---- X if (strcmp(spoolfile, filename) != 0) X return 0; X #endif X+ #ifdef SYSVR2 /* no saved-group id on setgid pgms. */ X+ switch (lockpid = fork()) { X+ case 0: X+ execl(DO_DOT_LOCK, "mush-dolock", spoolfile, filename, (char *) NULL); X+ error("unable to exec(%s, %s)", DO_DOT_LOCK, filename); X+ status = -1; X+ break; X+ case -1: X+ error("unable to fork(dolock) for %s", filename); X+ status = -1; X+ break; X+ default: X+ while ((waitid = wait(&status)) == -1) X+ error("oops, wait() got EINTR"); X+ if (waitid != lockpid) X+ error("oops, wait() got %d, not %d", waitid, lockpid); X+ if (status != 0) { X+ errno = ((status & 0xf) == 0) ? (status >> 8) & 0xf : 0; X+ error("unable to lock %s (status = %d)", filename, status); X+ status = -1; X+ } X+ break; X+ } X+ return(status); X+ #else X #ifdef BSD X setregid(rgid, sgid); X #else /* BSD */ X*************** X*** 73,78 **** X--- 103,109 ---- X setgid(getgid()); X #endif /* BSD */ X return lockfd == -1? -1 : 0; X+ #endif /* SYSVR2 */ X } X #endif /* DOT_LOCK */ X X*************** X*** 200,209 **** X--- 231,270 ---- X { X #ifdef DOT_LOCK X char buf[MAXPATHLEN]; X+ #ifdef SYSVR2 X+ int status; X+ int lockpid; X+ int waitid; X+ #endif X #endif /* DOT_LOCK */ X X fflush(fp); X #ifdef DOT_LOCK X+ #ifdef SYSVR2 /* no saved-group id on setgid pgms. */ X+ X+ switch (lockpid = fork()) { X+ case 0: X+ execl(UNDO_DOT_LOCK, "mush-undolock", spoolfile, filename, (char *) NULL); X+ error("unable to exec(%s, %s)", UNDO_DOT_LOCK, filename); X+ status = -1; X+ break; X+ case -1: X+ error("unable to fork(undolock) for %s", filename); X+ status = -1; X+ break; X+ default: X+ while ((waitid = wait(&status)) == -1) X+ error("oops, wait() got EINTR"); X+ if (waitid != lockpid) X+ error("oops, wait() got %d, not %d", waitid, lockpid); X+ if (status != 0) { X+ errno = ((status & 0xf) == 0) ? (status >> 8) & 0xf : 0; X+ error("unable to unlock %s (status = %d)", filename, status); X+ status = -1; X+ } X+ break; X+ } X+ #else /* !SYSVR2 */ X #ifdef BSD X setregid(rgid, sgid); X #else X*************** X*** 222,227 **** X--- 283,289 ---- X #else X setgid(getgid()); X #endif /* BSD */ X+ #endif /* SYSVR2 */ X #endif /* DOT_LOCK */ X X (void) flock(fileno(fp), LOCK_UN); END_OF_FILE if test 6913 -ne `wc -c <'Patch.sVr2'`; then echo shar: \"'Patch.sVr2'\" unpacked with wrong size! fi # end of 'Patch.sVr2' fi if test -f 'dolock.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'dolock.c'\" else echo shar: Extracting \"'dolock.c'\" \(996 characters\) sed "s/^X//" >'dolock.c' <<'END_OF_FILE' X#include <stdio.h> X#include <errno.h> X#include <fcntl.h> X#include "config.h" X Xint Xmain(argc, argv) X int argc; X char *argv[]; X{ X char *filename; X char *spoolfile; X char buf[BUFSIZ]; X int lockfd; X int cnt = 0; X X if (strcmp(argv[0], "mush-dolock") != 0 || argc != 3) { X fprintf(stderr, "dolock: usage error.\n"); X exit(0); X } X spoolfile = argv[1]; X filename = argv[2]; X /* X * Only the spoolfile needs to be dot_locked X */ X if (strcmp(spoolfile, filename) != 0) X exit(0); X (void) sprintf(buf, "%s.lock", filename); X while ((lockfd = open(buf, O_CREAT|O_WRONLY|O_EXCL, 0444)) == -1) { X if (errno != EEXIST) { X fprintf(stderr, "%s: unable to lock %s", argv[0], filename); X perror(""); X break; X } X if (cnt++ == 0) X printf("%s already locked, waiting", filename); X else { X putchar('.'); X fflush(stdout); X } X sleep(1); X /* SIGINT will terminate the process, with non-zero status */ X } X if (lockfd == -1) X exit(errno); X if (cnt) X puts("done."); X (void) close(lockfd); X exit(0); X} END_OF_FILE if test 996 -ne `wc -c <'dolock.c'`; then echo shar: \"'dolock.c'\" unpacked with wrong size! fi # end of 'dolock.c' fi if test -f 'undolock.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'undolock.c'\" else echo shar: Extracting \"'undolock.c'\" \(579 characters\) sed "s/^X//" >'undolock.c' <<'END_OF_FILE' X#include <stdio.h> X#include <string.h> X#include <errno.h> X#include "config.h" X Xint Xmain(argc, argv) X int argc; X char *argv[]; X{ X char *filename; X char *spoolfile; X char buf[BUFSIZ]; X int cnt = 0; X X if (strcmp(argv[0], "mush-undolock") != 0 || argc != 3) { X fprintf(stderr, "undolock: usage error\n"); X exit(0); X } X spoolfile = argv[1]; X filename = argv[2]; X if (strcmp(spoolfile, filename) == 0) { X (void) sprintf(buf, "%s.lock", filename); X if (unlink(buf) == -1) { X fprintf(stderr, "undolock: can't unlink(%s) - ", buf); X perror(""); X exit(errno); X } X } X exit(0); X} END_OF_FILE if test 579 -ne `wc -c <'undolock.c'`; then echo shar: \"'undolock.c'\" unpacked with wrong size! fi # end of 'undolock.c' fi echo shar: End of shell archive. exit 0 -- Greg A. Woods woods@{eci386,gate,robohack,ontmoh,tmsoft}.UUCP +1-416-443-1734 [h] +1-416-595-5425 [w] VE3-TCP Toronto, Ontario CANADA
davidsen@crdos1.crd.ge.COM (07/20/90)
> looked closely enough to work out all the details. If the lockfile > didn't have to go in /usr/mail, I think the create-and-link solution > would work (in fact, I'm quite surprised that mush isn't doing it > already -- I never really looked at the DOT_LOCK code). Oops, neither did I. I assumed they were doing some arcane thing because of the refs to which system works. I have just put 7.x aside for later, because 6.5 works for me and until X support is in it isn't worth the upgrade pain to me. Sorry if I suggested doing what is already done.
schaefer@ogicse.ogc.edu (Barton E. Schaefer) (07/20/90)
In article <1990Jul18.021543.11830@eci386.uucp> woods@eci386.UUCP (Greg A. Woods) writes: } In article <10491@ogicse.ogc.edu> schaefer@ogicse.cse.ogi.edu (Barton E. Schaefer) writes: } > This is Official Patch #2 for Mush 7.1. } >[....] } > Handling of "corrupted" spool mailboxes has been improved. The } > size of the spool file is now correctly recorded on new mail checks, } > which should reduce the frequency of corruption reports on systems } > that rely on DOT_LOCKing. } } Unfortunately the code for DOT_LOCKing is still very closely tied to } either BSD, or SysVr3.0+ (i.e SVID vol. 3). It will not work on } earlier versions of SysV, i.e. those described by SVID vol. 1. There are two other "unfortunately" comments I want to make about that patch before we start getting a lot of bug reports. First, the patch claims: The "delete" operation in tool mode will now bring the new current message onto the header display if and only if it was changed by the deletion. Due to a reversed logical test, this actually behaves exactly the same way it did before. It really will do this, honest, after Patch #3. Second, the patch also says: Addresses containing UUCP !-paths ending in a domain-style @host suffix will now be shifted to the right in header summaries to show as at least the last two hosts of the UUCP path tail. This assumes that the correct parsing of host2!host3!user@host1 is the same as host1!host2!host3!user. Another botched boolean check also renders this code a no-op. This is what I get for trying to generate a patch and a final draft of a thesis at the same time. (I hope my thesis is doing better.) Fixed in #3. -- Bart Schaefer schaefer@cse.ogi.edu