home *** CD-ROM | disk | FTP | other *** search
- From: argv@zipcode.com (Dan Heller)
- Newsgroups: comp.sources.misc
- Subject: v18i071: mush - Mail User's Shell, Part14/22
- Message-ID: <1991Apr22.000446.18972@sparky.IMD.Sterling.COM>
- Date: 22 Apr 91 00:04:46 GMT
- Approved: kent@sparky.imd.sterling.com
- X-Checksum-Snefru: d6fbf485 37198fd0 8aa00f78 e9891882
-
- Submitted-by: Dan Heller <argv@zipcode.com>
- Posting-number: Volume 18, Issue 71
- Archive-name: mush/part14
- Supersedes: mush: Volume 12, Issue 28-47
-
- #!/bin/sh
- # do not concatenate these parts, unpack them in order with /bin/sh
- # file misc_frame.c continued
- #
- if test ! -r _shar_seq_.tmp; then
- echo 'Please unpack part 1 first!'
- exit 1
- fi
- (read Scheck
- if test "$Scheck" != 14; then
- echo Please unpack part "$Scheck" next!
- exit 1
- else
- exit 0
- fi
- ) < _shar_seq_.tmp || exit 1
- if test ! -f _shar_wnt_.tmp; then
- echo 'x - still skipping misc_frame.c'
- else
- echo 'x - continuing file misc_frame.c'
- sed 's/^X//' << 'SHAR_EOF' >> 'misc_frame.c' &&
- X PANEL_LABEL_STRING, "",
- X NULL);
- X free_vec(argv);
- X panel_set_value(ignore_name, "");
- X return PANEL_NONE;
- }
- X
- static void
- ignore_done()
- {
- X window_destroy(ignore_frame);
- X ignore_frame = (Frame) 0;
- }
- X
- void
- do_ignore()
- {
- X Panel panel;
- X
- X if (ignore_frame) {
- X window_set(ignore_frame, WIN_SHOW, TRUE, NULL);
- X return;
- X }
- #ifdef SUN_3_5
- X if (nopenfiles(0) < 5) {
- X print("Too many frames; close one first!\n");
- X return;
- X }
- #endif /* SUN_3_5 */
- X
- X ignore_frame = window_create(tool, FRAME,
- X FRAME_SHOW_LABEL, TRUE,
- X FRAME_LABEL, "Ignored Headers",
- X FRAME_NO_CONFIRM, TRUE,
- X FRAME_DONE_PROC, ignore_done,
- X WIN_SHOW, TRUE,
- X WIN_WIDTH, MY_FRAME_WIDTH,
- X NULL);
- X
- X panel = window_create(ignore_frame, PANEL,
- X PANEL_WIDTH, MY_FRAME_WIDTH,
- X NULL);
- X (void) notify_interpose_event_func(panel, fkey_interposer, NOTIFY_SAFE);
- X (void) panel_create_item(panel, PANEL_BUTTON,
- X PANEL_LABEL_IMAGE,
- X panel_button_image(panel, "Help", 4, mush_font),
- X PANEL_NOTIFY_PROC, frame_help,
- X PANEL_CLIENT_DATA, "ignore",
- X NULL);
- X (void) panel_create_item(panel, PANEL_BUTTON,
- X PANEL_LABEL_IMAGE,
- X panel_button_image(panel, "Set", 3, mush_font),
- X PANEL_NOTIFY_PROC, set_ignore,
- X PANEL_CLIENT_DATA, TRUE,
- X NULL);
- X panel_create_item(panel, PANEL_BUTTON,
- X PANEL_LABEL_IMAGE,
- X panel_button_image(panel, "Unset", 5, mush_font),
- X PANEL_NOTIFY_PROC, set_ignore,
- X PANEL_CLIENT_DATA, FALSE,
- X NULL);
- X
- X ignore_msg = panel_create_item(panel, PANEL_MESSAGE,
- X PANEL_LABEL_STRING,
- X "Type name of header to ignore and then <set> or <unset>",
- X NULL);
- X
- X ignore_name = panel_create_item(panel, PANEL_TEXT,
- X PANEL_LABEL_STRING, "Ignored Header:",
- X PANEL_NOTIFY_PROC, set_ignore,
- X PANEL_CLIENT_DATA, 1,
- X PANEL_VALUE_DISPLAY_LENGTH, 60,
- X NULL);
- X window_fit_height(panel);
- X
- X ignore_list_textsw = window_create(ignore_frame, TEXTSW,
- X WIN_BELOW, panel,
- X WIN_WIDTH, MY_FRAME_WIDTH,
- X WIN_HEIGHT, 15 * l_height(),
- #ifdef SUN_4_0 /* SunOS 4.0+ */
- X TEXTSW_LINE_BREAK_ACTION, TEXTSW_WRAP_AT_WORD,
- #else /* SUN_4_0 */
- X TEXTSW_LINE_BREAK_ACTION, TEXTSW_WRAP_AT_CHAR,
- #endif /* SUN_4_0 */
- X NULL);
- X (void) notify_interpose_event_func(ignore_list_textsw,
- X fkey_interposer, NOTIFY_SAFE);
- X
- X window_fit_height(ignore_frame);
- X update_list_textsw(&ignore_hdr);
- }
- SHAR_EOF
- echo 'File misc_frame.c is complete' &&
- chmod 0644 misc_frame.c ||
- echo 'restore of misc_frame.c failed'
- Wc_c="`wc -c < 'misc_frame.c'`"
- test 7659 -eq "$Wc_c" ||
- echo 'misc_frame.c: original size 7659, current size' "$Wc_c"
- rm -f _shar_wnt_.tmp
- fi
- # ============= msgs.c ==============
- if test -f 'msgs.c' -a X"$1" != X"-c"; then
- echo 'x - skipping msgs.c (File already exists)'
- rm -f _shar_wnt_.tmp
- else
- > _shar_wnt_.tmp
- echo 'x - extracting msgs.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'msgs.c' &&
- /* @(#)msgs.c (c) copyright 10/18/86 (Dan Heller) */
- X
- #include "mush.h"
- X
- void
- display_msg(n, flg)
- register int n;
- u_long flg;
- {
- X char buf[32], *pager = NULL;
- X
- X if (ison(msg[n].m_flags, DELETE) && !do_set(set_options, "show_deleted")) {
- X print("Message %d deleted; ", n+1);
- #ifdef SUNTOOL
- X if (istool)
- X wprint("Select UNDELETE to read.\n");
- X else
- #endif /* SUNTOOL */
- X if (iscurses)
- X print_more("Type 'u' to undelete.");
- X else
- X wprint("Type 'undelete %d' to undelete\n", n+1);
- X return;
- X }
- X set_isread(n);
- X if (ison(flg, M_TOP)) {
- X turnon(flg, NO_HEADER);
- X print("Top of "), turnon(glob_flags, CONT_PRNT);
- X }
- X
- #ifdef MSG_SEPARATOR
- X turnon(flg, NO_SEPARATOR);
- #endif /* MMDF */
- X if (!istool && isoff(flg, NO_PAGE) &&
- X crt < msg[n].m_lines && isoff(flg, M_TOP)) {
- X if (!(pager = do_set(set_options, "pager")))
- X pager = DEF_PAGER;
- X if (!*pager || !strcmp(pager, "internal"))
- X pager = NULL; /* default to internal pager if pager set to "" */
- X }
- X (void) do_pager(pager, TRUE); /* start pager */
- X (void) do_pager(sprintf(buf, "Message #%d (%d lines)\n",
- X n+1, msg[n].m_lines), FALSE);
- X (void) copy_msg(n, NULL_FILE, flg, NULL);
- X (void) do_pager(NULL, FALSE); /* end pager */
- }
- X
- /*
- X * copy message 'n' to file "fp" according to various flag arguments
- X * return number of lines copied or -1 if system error on fputs.
- X * If "fp" is null, send to internal pager. This can only happen from
- X * display_msg above.
- X */
- copy_msg(n, fp, flags, pattern)
- register int n;
- register FILE *fp;
- u_long flags;
- char *pattern;
- {
- X register int ignoring = 0, lines = 0;
- X register char *indent_str, *p, *end_pat = NULL;
- X int on_hdr = 1, top, squeeze = 0;
- X long still_more = 0;
- X int pat_len, pat_seek;
- X char line[BUFSIZ], *show_hdrs = NULL;
- X
- X if (ison(flags, M_TOP)) {
- X p = do_set(set_options, "toplines");
- X top = (p)? atoi(p) : crt;
- X }
- X /* When updating to a folder, always write all headers! */
- X if (ison(flags, UPDATE_STATUS))
- X turnon(flags, NO_IGNORE);
- X else if (ison(flags, NO_IGNORE) &&
- X (p = do_set(set_options, "alwaysignore")) && !*p)
- X turnoff(flags, NO_IGNORE); /* preserve historic behavior */
- X if (isoff(flags, NO_IGNORE)) {
- X if (do_set(set_options, "squeeze"))
- X squeeze = 1;
- X show_hdrs = do_set(set_options, "show_hdrs");
- X }
- X if (pattern && *pattern == '/' && (end_pat = index(pattern+1, '/'))) {
- X if (end_pat[1] == ',') {
- X pattern++;
- X *end_pat++ = 0;
- X } else
- X end_pat = NULL;
- X }
- X pat_len = pattern? strlen(pattern) : 0;
- X pat_seek = !!pat_len;
- X
- #ifdef SUNTOOL
- X xfree(more_prompt), more_prompt = NULL;
- #endif /* SUNTOOL */
- X
- X if (ison(flags, INDENT)) {
- X if ((indent_str = do_set(set_options, "pre_indent_str"))) {
- X fputs(format_hdr(n, indent_str, FALSE) + 9, fp); /* magic 9 !! */
- X fputc('\n', fp);
- X }
- X if (!(indent_str = do_set(set_options, "indent_str")))
- X indent_str = DEF_INDENT_STR;
- X indent_str = format_hdr(n, indent_str, FALSE) + 9; /* magic 9 !! */
- X }
- X /* "line" used as dummy here, since 0 bytes read */
- X if (!msg_get(n, line, 0)) {
- X error("Unable to find msg %d", n+1);
- X return -1;
- X }
- X while (still_more < msg[n].m_size && fgets(line, sizeof (line), tmpf)) {
- X still_more += strlen(line);
- #ifdef MSG_SEPARATOR
- X if (ison(flags, NO_SEPARATOR)) {
- #ifdef MMDF
- X if (!strncmp(line, MSG_SEPARATOR, 4))
- #else /* !MMDF */
- X if (!strncmp(line, MSG_SEPARATOR, strlen(MSG_SEPARATOR)))
- #endif /* MMDF */
- X continue;
- X }
- #endif /* MMDF */
- X /*
- X * If squeeze is one, all blanks lines squeeze down to one blank line.
- X * If squeeze is two, squeezing is in progress so wait for the next \n.
- X */
- X if (*line == '\n') {
- X if (on_hdr) { /* blank line -- end of header */
- X on_hdr = 0;
- X if (ison(flags, NO_HEADER))
- X continue;
- X }
- X if (squeeze > 1 || pat_len && pat_seek)
- X continue;
- X else if (squeeze)
- X squeeze = 2;
- X } else {
- X if (squeeze > 1)
- X squeeze = 1;
- X if (pat_len && (!on_hdr || isoff(flags, NO_HEADER))) {
- X /* If we're looking for a pattern for mush-pipe, then
- X * continue if this line doesn't match the pattern.
- X */
- X if (pat_len == 0)
- X continue;
- X Debug("Seeking (%s) in (%s)", pattern, line);
- X if (strncmp(line, pattern, pat_len)) {
- X if (pat_seek)
- X continue;
- X } else if (end_pat && *end_pat++ == ',') {
- X pattern = end_pat;
- X if (*pattern == '/') {
- X pattern++;
- X if (end_pat = index(pattern, '/'))
- X *end_pat++ = 0;
- X }
- X pat_len = pattern? strlen(pattern) : 0;
- X pat_seek = !pat_seek;
- X } else {
- X pat_len = 0;
- X pat_seek = !pat_seek;
- X }
- X }
- X }
- X
- X if (ison(flags, UPDATE_STATUS))
- X if (!strncmp(line, "Status:", 7) || !strncmp(line, "Priority:", 9))
- X continue; /* ignore "Status" and "Priority" lines */
- X else if (!on_hdr) {
- X int i, write_priority = 0;
- X p = line;
- X p += Strcpy(p, "Priority:");
- X for (i = 0; i < MAX_PRIORITY; i++)
- X if (ison(msg[n].m_flags, M_PRIORITY(i + 1))) {
- X write_priority = 1;
- X *p++ = ' ';
- X *p++ = i + 'A';
- X }
- X if (write_priority) {
- X *p++ = '\n', *p = 0;
- X (void) fputs(line, fp);
- X }
- X /* PRESERVE here avoids changing new message status */
- X if (isoff(flags, PRESERVE) || /* NOT msg[n].m_flags */
- X ison(msg[n].m_flags, OLD) ||
- X isoff(msg[n].m_flags, UNREAD)) {
- X p = line;
- X p += Strcpy(p, "Status: O");
- X if (isoff(msg[n].m_flags, UNREAD))
- X *p++ = 'R';
- X if (ison(msg[n].m_flags, SAVED))
- X *p++ = 'S';
- X if (ison(msg[n].m_flags, REPLIED))
- X *p++ = 'r';
- X if (ison(msg[n].m_flags, PRINTED))
- X *p++ = 'p';
- X if (ison(msg[n].m_flags, FORWARD))
- X *p++ = 'f';
- X *p++ = '\n', *p = 0;
- X (void) fputs(line, fp);
- X }
- X turnoff(flags, UPDATE_STATUS);
- X line[0] = '\n', line[1] = '\0';
- X }
- X if (on_hdr && (isoff(flags, NO_IGNORE) || ison(flags, FORWARD))) {
- X p = any(line, " \t:");
- X if (!p)
- X ignoring = 0, on_hdr = 0;
- X else if (ignoring)
- X if (*p != ':') {
- X Debug("Ignoring: %s", line);
- X continue;
- X } else
- X ignoring = 0;
- X if (p && *p == ':') {
- X *p = 0;
- X ignoring = 0;
- X if (ison(flags, FORWARD)) {
- X if (chk_two_lists(line, IGNORE_ON_FWD, ":, \t"))
- X ignoring = 1;
- X } else if (show_hdrs) {
- X if (!chk_two_lists(line, show_hdrs, ":, \t"))
- X ignoring = 1;
- X } else {
- X register struct options *opts;
- X for (opts = ignore_hdr; opts; opts = opts->next)
- X if (!lcase_strncmp(opts->option, line, -1)) {
- X ignoring = 1;
- X break;
- X }
- X }
- X *p = ':';
- X if (ignoring) {
- X Debug("Ignoring: %s", line);
- X continue;
- X }
- X }
- X }
- X if (!on_hdr && ison(flags, M_TOP) && !--top)
- X break;
- X if (!on_hdr && (still_more < msg[n].m_size || line[0] != '\n') ||
- X isoff(flags, NO_HEADER)) {
- X /* note that function returns the number of lines */
- X lines++;
- X if (ison(flags, INDENT))
- X (void) fputs(indent_str, fp);
- X if (!fp) {
- X if (do_pager(line, FALSE) == EOF)
- X return -1;
- X } else if (fputs(line, fp) == EOF)
- X /* Pipe broken, out of file space, etc */
- X return -1;
- X }
- X if (pat_seek && !pat_len)
- X break; /* Skip the rest */
- X }
- X if (ison(flags, INDENT) &&
- X (indent_str = do_set(set_options, "post_indent_str")) && *indent_str) {
- X (void) fprintf(fp, "%s\n", format_hdr(n, indent_str, FALSE)+9);
- X }
- X if (fp && fflush(fp) == EOF)
- X return -1; /* Write failure? */
- X return lines;
- }
- X
- /*
- X * copy tempfile back to folder.
- X * Return 1 on success, 0 on failure.
- X */
- copyback(prompt, final)
- char *prompt;
- int final; /* Are we exiting or updating? */
- {
- X register int i = 0, held = 0, saved = 0;
- X register u_long flg = 0;
- X register FILE *mbox = NULL_FILE, *mail_fp = NULL_FILE;
- #ifdef SYSV
- X FILE *save_mail_fp = NULL_FILE;
- #endif /* SYSV */
- X char *mbox_file, action = 0;
- X int hold = 0, delete_it = 0, dont_unlink = !final;
- X int isspool, keepsave, write_err = FALSE;
- X static int first = 1;
- X
- X /*
- X * if there is new mail in this folder, the user is notified and
- X * prompted if he really wants to update the folder. He's either
- X * quitting or changing folders, so let him read the new mail first.
- X */
- X if (!first && mail_size()) {
- lost_lock:
- X if ((ison(glob_flags, CORRUPTED) || get_new_mail(TRUE)) &&
- X prompt && isoff(glob_flags, REDIRECT) && show_new_mail()) {
- X char buf[80];
- X if (iscurses)
- X putchar('\n'), turnon(glob_flags, CNTD_CMD);
- X if (!istool)
- X print("%s [n] ", prompt);
- X buf[0] = 0;
- #ifdef SUNTOOL
- X if (istool) {
- X (void) sprintf(buf, "%s -- %s",
- X ison(glob_flags, CORRUPTED) ? "Error" : "New mail",
- X prompt);
- X if (ask(buf) != TRUE)
- X return 0;
- X } else
- #endif /* SUNTOOL */
- X if (!Getstr(buf, sizeof (buf), 0) || lower(*buf) != 'y')
- X return 0;
- X turnoff(glob_flags, CORRUPTED); /* User says go ahead */
- X }
- X }
- X first = 0;
- X
- X /* If the user hasn't changed anything, just return true */
- X if (isoff(glob_flags, DO_UPDATE) || ison(glob_flags, CORRUPTED))
- X return 1;
- X if (ison(glob_flags, READ_ONLY)) {
- X print("Unable to update %s: read only\n", mailfile);
- X return 0; /* user should use "exit" instead of "quit". */
- X }
- X if (!msg_cnt) /* prevent unnecessary overwrite */
- X return 1;
- X
- #ifdef SUNTOOL
- X if (istool) {
- X (void) notify_set_itimer_func(tool, do_check,
- X ITIMER_REAL, (struct itimerval *) 0, (struct itimerval *) 0);
- X }
- #endif /* SUNTOOL */
- X
- X /* We can't lock a file unless we have an fd, but "w+" will zero
- X * the file. If the lock later failed for any reason (possible
- X * race condition with an MTA), we would lose all current mail.
- X * So, open read/write (if possible) and truncate later.
- X */
- X if (!(mail_fp = lock_fopen(mailfile, "r+"))) {
- X error("WARNING: unable to lock %s -- update aborted", mailfile);
- #ifdef SUNTOOL
- X if (istool) {
- X write_err = 1; /* forces return 0; below */
- X goto resume_timer; /* blecch */
- X }
- #else /* !SUNTOOL */
- X return 0;
- #endif /* SUNTOOL */
- X }
- X /* Make sure no mail arrived between the last check and when we
- X * got the lock. If it did, release the lock and try again.
- X */
- X if (mail_size()) {
- X (void) close_lock(mailfile, mail_fp);
- X goto lost_lock;
- X }
- X
- X /* open mbox if: "autodelete" AND "hold" are NOT set. */
- X if (!strcmp(mailfile, spoolfile)
- X && !(delete_it = !!do_set(set_options, "autodelete"))
- X && !(hold = !!do_set(set_options, "hold"))) {
- X register char *p;
- X int x = 1; /* tell getpath to ignore "ENOENT" if file not found */
- X
- X if (!(p = do_set(set_options, "mbox")))
- X p = DEF_MBOX;
- X mbox_file = getpath(p, &x); /* static data -- copy? */
- X if (x) {
- X if (x > 0)
- X print("%s is a directory.\n", mbox_file);
- X else
- X print("Unable to open %s: %s\n", p, mbox_file);
- X mbox = NULL_FILE;
- X } else {
- X if (Access(mbox_file, F_OK) == -1) /* does it exist? */
- X mbox = lock_fopen(mbox_file, "w");
- X else
- X mbox = lock_fopen(mbox_file, "a");
- X if (!mbox)
- X error("Unable to write to %s", mbox_file);
- X }
- X }
- X
- X /* ignore signals before truncating */
- X turnon(glob_flags, IGN_SIGS);
- #ifdef SYSV
- X /* SysV can't truncate a file in the middle, so we can't just
- X * write to mail_fp and close. Instead, we save the mail_fp
- X * and reopen for writing, ignoring our own lock. After updating,
- X * we can safely fclose both file pointers.
- X */
- X save_mail_fp = mail_fp;
- X /* This could fail if we run out of file descriptors */
- X if (!(mail_fp = fopen(mailfile, "w"))) {
- X error("WARNING: unable to reopen %s for update", mailfile);
- X if (save_mail_fp)
- X (void) close_lock(mailfile, save_mail_fp);
- X if (mbox)
- X (void) close_lock(mbox_file, mbox);
- X turnoff(glob_flags, IGN_SIGS);
- X return 0;
- X }
- #endif /* SYSV */
- X
- X print("Updating \"%s\"", mailfile);
- X
- X turnon(flg, UPDATE_STATUS);
- X /* Don't set OLD for new messages on update. */
- X if (!final)
- X turnon(flg, PRESERVE);
- X
- X keepsave = !!do_set(set_options, "keepsave");
- X isspool = !strcmp(mailfile, spoolfile);
- X
- X for (i = 0; i < msg_cnt; i++) {
- X /* Maintain the current message across update; if this turns out
- X * to be unnecessary (changing folders), folder() will reset it.
- X */
- X if (current_msg == i)
- X current_msg = held;
- X /* Check to see if message is marked for deletion or, if read and not
- X * preserved, delete it if autodelete is set. Otherwise, if hold is
- X * set save the message in the spool file. If all fails, save in mbox.
- X */
- X if (ison(msg[i].m_flags, DELETE)
- X || ison(msg[i].m_flags, SAVED) && !keepsave &&
- X isoff(msg[i].m_flags, PRESERVE) && isspool
- X || isoff(msg[i].m_flags, UNREAD) && isoff(msg[i].m_flags, PRESERVE)
- X && delete_it) {
- X Debug("%s %d",
- X (action!='d')? "\ndeleting message:" : "", i+1), action = 'd';
- X continue;
- X } else if (isoff(msg[i].m_flags, DO_UPDATE) || hold || !mbox ||
- X ison(msg[i].m_flags, UNREAD) ||
- X ison(msg[i].m_flags, PRESERVE)) {
- X Debug("%s %d",
- X (action!='s')? "\nsaving in spool:" : "", i+1), action = 's';
- X if (copy_msg(i, mail_fp, flg, NULL) == -1) {
- X error("WARNING: unable to write back to spool");
- X print_more("ALL mail left in %s\n", tempfile);
- X print_more("Spool mailbox may be corrupted.\n");
- X dont_unlink = TRUE;
- X write_err = TRUE;
- X break;
- X }
- X held++;
- X } else if (isspool) { /* copy back to mbox */
- X if (copy_msg(i, mbox, flg, NULL) == -1) {
- X error("WARNING: unable to write to mbox");
- X print_more("Unresolved mail left in %s\n", tempfile);
- X dont_unlink = TRUE;
- X write_err = TRUE;
- X break;
- X }
- X saved++;
- X Debug("%s %d",
- X (action!='m')? "\nsaving in mbox:" : "", i+1), action = 'm';
- X }
- X }
- X if (write_err)
- X current_msg = 0;
- X else if (current_msg == held)
- X current_msg--; /* Don't point to a message that got deleted */
- X Debug("\n%s", mailfile);
- X
- #ifdef SYSV
- X /* Close the write file pointer first */
- X (void) fclose(mail_fp);
- X mail_fp = save_mail_fp;
- #else /* !SYSV */
- X /* Truncate the file at the end of what we just wrote.
- X * If you aren't SYSV and you still can't ftruncate(),
- X * you're out of luck?
- X */
- X (void) ftruncate(fileno(mail_fp), ftell(mail_fp));
- #endif /* SYSV */
- X
- X /* some users like to have zero length folders for frequent usage */
- X if (mbox && close_lock(mbox_file, mbox) == EOF) {
- X error("WARNING: unable to close mbox");
- X print_more("Unresolved mail left in %s\n", tempfile);
- X dont_unlink = TRUE;
- X write_err = TRUE;
- X }
- X if (held) {
- X print_more(": saved %d message%s\n", held, (held==1)? NO_STRING: "s");
- X } else
- #ifdef HOMEMAIL
- X if (!dont_unlink && !do_set(set_options, "save_empty"))
- #else /* HOMEMAIL */
- X if (strcmp(mailfile, spoolfile) && !dont_unlink &&
- X !do_set(set_options, "save_empty"))
- #endif /* HOMEMAIL */
- X if (unlink(mailfile))
- X turnon(glob_flags, CONT_PRNT), error(": cannot remove");
- X else {
- X print_more(": removed\n");
- X held = -1;
- X }
- X else
- X print_more(": empty\n");
- X if (saved)
- X print("saved %d message%s in %s\n",
- X saved,(saved==1)? NO_STRING:"s", mbox_file);
- X
- X if (held > 0) {
- X /* Reset the access time of the spool file to prevent
- X * bogus "new mail" messages from the shell.
- X */
- X long times[2];
- X (void) fflush(mail_fp); /* just in case */
- X times[1] = time(×[0]) - (long)2;
- X if (!strcmp(mailfile, spoolfile) && utime(mailfile, times))
- X error("utime");
- X }
- X
- X if (close_lock(mailfile, mail_fp) == EOF) {
- X error("WARNING: unable to close spool");
- X print_more("ALL mail left in %s\n", tempfile);
- X print_more("Spool mailbox may be corrupted.\n");
- X write_err = TRUE;
- X }
- X
- #ifdef SUNTOOL
- X if (istool) {
- resume_timer:
- X mail_timer.it_value.tv_sec = time_out;
- X mail_timer.it_interval.tv_sec = time_out;
- X (void) notify_set_itimer_func(tool, do_check,
- X ITIMER_REAL, &mail_timer, (struct itimerval *) 0);
- X }
- #endif /* SUNTOOL */
- X
- X turnoff(glob_flags, IGN_SIGS);
- X
- X /* Return nonzero for success, -1 if file removed */
- X if (write_err)
- X return 0;
- X else if (held < 0)
- X return -1;
- X else
- X return 1;
- }
- X
- /*
- X * check the sizes of the current folder (file) and the spool file.
- X * spool_size is the size in bytes of the user's main mailbox.
- X * last_size is the size of the _current_ folder the last time we checked.
- X * return true if the current folder has new mail. check_new_mail() checks
- X * for new mail in the system mailbox since it checks against last_spool_size.
- X */
- mail_size()
- {
- X struct stat buf;
- X
- X if (!stat(spoolfile, &buf))
- X spool_size = buf.st_size;
- X else if (!strcmp(mailfile, spoolfile))
- X return 0;
- X if (!is_shell || ison(glob_flags, IS_SENDING))
- X return 0;
- X if (strcmp(mailfile, spoolfile) && stat(mailfile, &buf)) {
- X if (errno != ENOENT)
- X error("Unable to stat %s", mailfile);
- X return 0;
- X }
- X if (buf.st_size != last_size) {
- X last_size = buf.st_size;
- X return 1;
- X }
- X return 0;
- }
- X
- static
- struct mailstat {
- X int new, unread, deleted;
- } mail_stat;
- X
- void
- mail_status(as_prompt)
- {
- X char buf[MAXPATHLEN];
- X register int cnt;
- X
- X mail_stat.new = mail_stat.unread = mail_stat.deleted = 0;
- X
- X for (cnt = 0; cnt < msg_cnt; cnt++) {
- X if (ison(msg[cnt].m_flags, UNREAD))
- X mail_stat.unread++;
- X if (ison(msg[cnt].m_flags, DELETE))
- X mail_stat.deleted++;
- X if (isoff(msg[cnt].m_flags, OLD))
- X mail_stat.new++;
- X }
- X if (as_prompt) {
- X /* use %s in case prompt has any %'s in it */
- X print("%s", format_prompt(current_msg, prompt));
- X return;
- X }
- X (void) sprintf(buf,"\"%s\"%s: %d message%s, %d new, %d unread",
- X trim_filename(mailfile),
- X ison(glob_flags, READ_ONLY)? " [read only]" : "",
- X msg_cnt, (msg_cnt != 1)? "s": NO_STRING,
- X mail_stat.new, mail_stat.unread);
- X if (istool || iscurses)
- X (void) sprintf(buf+strlen(buf), ", %d deleted", mail_stat.deleted);
- #ifdef SUNTOOL
- X if (istool) {
- X static char ic_text[4];
- X char *lbl;
- X Icon icon;
- X extern struct pixrect mail_icon_image1, mail_icon_image2;
- X (void) sprintf(ic_text, "%3d", msg_cnt);
- X if (!(lbl = (char *)window_get(tool, FRAME_LABEL)) || strcmp(lbl, buf))
- X (void) window_set(tool, FRAME_LABEL, buf, NULL);
- X icon = (Icon) window_get(tool, FRAME_ICON);
- X (void) icon_set(icon,
- X ICON_IMAGE, ison(glob_flags, NEW_MAIL)?
- X &mail_icon_image2 : &mail_icon_image1,
- X NULL);
- X if (!chk_option("quiet", "iconlabel"))
- X (void) icon_set(icon, ICON_LABEL, ic_text, NULL);
- X else
- X (void) icon_set(icon, ICON_LABEL, NO_STRING, NULL);
- X (void) window_set(tool, FRAME_ICON, icon, NULL);
- X } else
- #endif /* SUNTOOL */
- X
- #ifdef CURSES
- X if (iscurses) {
- X move (0, 0);
- X printw("%-3d %-.*s",
- X ((msg_cnt)? current_msg+1 : 0), COLS-5, buf), clrtoeol();
- X } else
- #endif /* CURSES */
- X puts(buf);
- X return;
- }
- X
- /*
- X * Construct a prompt for the given message number using the given format
- X */
- char *
- format_prompt(num, fmt)
- int num;
- char *fmt;
- {
- X static char buf[MAXPATHLEN];
- X register char *p, *b = buf, *mf;
- X
- X if (is_shell)
- X mf = mailfile;
- X else
- X mf = "[no folder]";
- X
- X for (p = fmt; *p; p++)
- X if (*p == '\\')
- X switch (*++p) {
- X case 'n': case 'r': *b++ = '\n';
- X when 't': *b++ = '\t';
- X otherwise: *b++ = *p;
- X }
- X else if (*p == '%')
- X switch (*++p) {
- X case 'm':
- X b += strlen(sprintf(b,"%d",(msg_cnt)? num + 1 : 0));
- X when 't':
- X b += strlen(sprintf(b, "%d", msg_cnt));
- X when 'd':
- X b += strlen(sprintf(b, "%d", mail_stat.deleted));
- X when 'u':
- X b += strlen(sprintf(b, "%d", mail_stat.unread));
- X when 'n':
- X b += strlen(sprintf(b, "%d", mail_stat.new));
- X when 'f':
- X {
- X char *tail = rindex(mf, '/');
- X if (tail && tail[1])
- X b += Strcpy(b, tail+1);
- X else {
- X /* Fall through */
- X case 'F':
- X b += Strcpy(b, mf);
- X }
- X if (ison(glob_flags, READ_ONLY))
- X b += Strcpy(b, " [read-only]");
- X }
- X when 'T': case 'D': case 'Y': case 'y':
- X case 'M': case 'N': case 'W':
- X b += Strcpy(b, Time(p, (long)0));
- X when '$':
- X {
- X struct expand var;
- X var.orig = p;
- X if (varexp(&var)) {
- X b += Strcpy(b, var.exp);
- X xfree(var.exp);
- X p = var.rest - 1;
- X }
- X }
- X otherwise: *b++ = *p;
- X }
- X else if (*p == '!')
- X b += strlen(sprintf(b, "%d", hist_no+1));
- X else
- X *b++ = *p;
- X *b = 0;
- X return buf;
- }
- X
- /*
- X * For uucp mailers that use >From lines with "remote from <path>":
- X * (where "path" is a hostname or pathnames)
- X *
- X * a. Set the return_path to the empty string.
- X * b. For each From_ or >From_ line:
- X * c. Save the username (second token).
- X * d. Save the date (3-7 tokens).
- X * e. If it has a "remote from" then append the remote host
- X * (last token) followed by a "!" to the return_path.
- X * f. If the saved username has a '@' but no '!' then convert it
- X * to UUCP path form.
- X * g. Append the saved username to return_path.
- X */
- parse_from(fp, path)
- FILE *fp;
- char path[];
- {
- X char user[256], buf[256]; /* max size for each line in a mail file */
- X register char *p;
- X long save_offset = ftell(fp);
- X
- X path[0] = '\0';
- X while (fgets(buf, sizeof buf, fp)) {
- X if (strncmp(buf, ">From ", 6))
- X break;
- X p = buf + 6;
- X
- X (void) sscanf(p, "%s", user);
- X
- X while (p = index(p+1, 'r')) {
- X if (!strncmp(p, "remote from ", 12)) {
- X char *p2 = path+strlen(path);
- X skipspaces(12);
- X (void) sscanf(p, "%s", p2); /* add the new machine to current path */
- X (void) strcat(p2, "!");
- X break;
- X }
- X }
- X
- X if (p)
- X (void) bang_form(path + strlen(path), user);
- X save_offset = ftell(fp);
- X }
- X (void) fseek(fp, save_offset, L_SET);
- }
- X
- /*
- X * Scan a file and select messages from it and append them to the current folder
- X *
- X * If "append" is 1, start where we left off (held in msg[cnt].m_offset)
- X * and scan for messages. Append all messages found until EOF.
- X *
- X * If "append" is 2, we're merging in a new file, so start at the end of
- X * the present folder and append all messages found until EOF.
- X *
- X * If "append" is 0, then the message separator must exist once and
- X * only once. All extra occurrences of the separator is preceded by a '>'.
- X * The list argument will be the message number to replace in the current
- X * folder with the message read in from other filename.
- X */
- load_folder(file, append, list)
- char *file, *list;
- int append;
- {
- X char buf[BUFSIZ];
- X int lines = 0, msg_found = 0, had_error = 1;
- X int get_status = 1, cnt;
- X long bytes, ftell();
- X struct msg old;
- X char *p, date[64];
- X FILE *fp;
- X int warn = ison(glob_flags, WARNING);
- #ifdef MMDF
- X int begin_sep = 0; /* track beginning vs ending separators */
- #endif /* MMDF */
- X
- X if (!(fp = lock_fopen(file, "r"))) {
- X error("Unable to open %s", file);
- X return -1;
- X }
- X
- X if (append) {
- X cnt = msg_cnt;
- X (void) fseek(fp, append == 1 ? msg[cnt].m_offset : 0L, L_SET);
- X } else {
- X cnt = (int)list;
- X old = msg[cnt];
- X }
- X
- X if (isoff(glob_flags, READ_ONLY)) {
- X if (tmpf)
- X (void) fclose(tmpf);
- X if (!(tmpf = mask_fopen(tempfile, "a"))) {
- X error("Unable to open %s for appending", tempfile);
- X close_lock(file, fp);
- X return -1;
- X }
- X (void) fseek(tmpf, 0L, 2); /* assure we're at the end of the file */
- X } else if (append == 2) {
- X /* you can't merge in a folder to a read-only folder */
- X close_lock(file, fp);
- X return -1;
- X }
- X
- #ifdef MMDF
- X if (!append) {
- X (void) strcpy(buf, MSG_SEPARATOR);
- X goto do_headers;
- X }
- #endif /* MMDF */
- X buf[0] = 0;
- X while (fgets(buf, sizeof (buf), fp)) {
- #ifndef MSG_SEPARATOR
- X turnoff(glob_flags, WARNING);
- X if (!strncmp(buf, "From ", 5)) {
- X p = buf + 5; /* skip "From " */
- X skipspaces(0);
- X p = any(p, " \t"); /* skip the address */
- X } else
- X p = buf;
- X if (p > buf && (p = parse_date(p + 1)) && strcpy(date, p))
- #else /* MSG_SEPARATOR */
- X if (!strncmp(buf, MSG_SEPARATOR, strlen(MSG_SEPARATOR)))
- #endif /* MSG_SEPARATOR */
- X {
- #ifdef MMDF
- X if (!append)
- X (void) fputc('>', tmpf);
- X else if (begin_sep = !begin_sep)
- do_headers:
- #else /* MMDF */
- X if (!append && msg_found)
- X (void) fputc('>', tmpf);
- X else
- #endif /* MMDF */
- X {
- X msg_found++;
- X had_error = 0;
- X if (append && cnt == MAXMSGS-append) {
- X wprint("WARNING: exceeded %d messages.\n", MAXMSGS-append);
- X wprint("Not all messages have been loaded.\n");
- X msg_cnt--;
- X had_error++;
- X break;
- X }
- X if (ison(glob_flags, READ_ONLY))
- X bytes = ftell(fp) - strlen(buf);
- X else {
- X char path[256];
- X parse_from(fp, path);
- X if (path[0])
- X (void)sprintf(buf,"From %s %s", path,
- X date_to_ctime(date));
- X bytes = ftell(tmpf);
- X }
- X /* finish up message structure from previous message.
- X * if this is incorporating new mail, check "lines" to
- X * see if previous message has already been set!
- X */
- X if (cnt && lines) {
- X msg[cnt-1].m_size = bytes - msg[cnt-1].m_offset;
- X msg[cnt-1].m_lines = lines;
- X }
- X if (isoff(glob_flags, READ_ONLY) && fputs(buf, tmpf) == -1) {
- X error(tempfile);
- X had_error++;
- X break;
- X }
- X msg[cnt].m_offset = bytes;
- X msg[cnt].m_flags = 0L;
- #ifdef MSG_SEPARATOR
- X lines = 0;
- #else /* MSG_SEPARATOR */
- X lines = 1; /* count the From_ line */
- X if (warn)
- X turnon(glob_flags, WARNING);
- X strdup(msg[cnt].m_date_recv, date);
- #endif /* MSG_SEPARATOR */
- X turnon(msg[cnt].m_flags, UNREAD); /* initialize */
- X /* we've read the "From " line(s), now read the rest of
- X * the message headers till we get to a blank line.
- X */
- X while (fgets(buf, sizeof (buf), fp) && (*buf != '\n')) {
- X p = buf;
- X if (!strncmp(buf, "Date:", 5))
- X strdup(msg[cnt].m_date_sent, parse_date(p+5));
- X if (!strncmp(buf, "Priority:", 9)) {
- X for (p += 9 ; *p != '\n'; p++) {
- X if (!isalpha(*p) || upper(*p) > 'A' + MAX_PRIORITY)
- X continue;
- X turnon(msg[cnt].m_flags,
- X M_PRIORITY(upper(*p) - 'A' + 1));
- X }
- X }
- X if (get_status &&
- X !(get_status = strncmp(p, "Status:", 7))) {
- X /* new mail should not have a Status: field! */
- X turnon(msg[cnt].m_flags, OLD);
- X for (p += 7 ; *p != '\n'; p++) {
- X if (isspace(*p))
- X continue;
- X switch(*p) {
- X case 'R': turnoff(msg[cnt].m_flags, UNREAD);
- X when 'P': turnon(msg[cnt].m_flags, UNREAD);
- X when 'N': turnon(msg[cnt].m_flags, UNREAD);
- X turnoff(msg[cnt].m_flags, OLD);
- X when 'S': turnon(msg[cnt].m_flags, SAVED);
- X when 'r': turnon(msg[cnt].m_flags, REPLIED);
- X when 'O': ; /* do nothing */
- X when 'f': turnon(msg[cnt].m_flags, FORWARD);
- X when 'p': turnon(msg[cnt].m_flags, PRINTED);
- X otherwise :
- X if (ison(glob_flags, WARNING))
- X print("unknown msg status flag: %c\n",
- X *p);
- X }
- X }
- X }
- X if (isoff(glob_flags,READ_ONLY) && fputs(buf, tmpf) == -1) {
- X error(tempfile);
- X had_error++;
- X break;
- X }
- X lines++;
- X }
- X if (!msg[cnt].m_date_sent || !*msg[cnt].m_date_sent)
- X if (!msg[cnt].m_date_recv || !*msg[cnt].m_date_recv) {
- X wprint("Message %d has *no* date!?\n", cnt+1);
- X msg[cnt].m_date_sent = msg[cnt].m_date_recv =
- X "0000000000XXX";
- X } else
- X strdup(msg[cnt].m_date_sent, msg[cnt].m_date_recv);
- X else if (!msg[cnt].m_date_recv || !*msg[cnt].m_date_recv)
- X strdup(msg[cnt].m_date_recv, msg[cnt].m_date_sent);
- X if (had_error)
- X break;
- X if (append && list)
- X set_msg_bit(list, cnt);
- X if (append)
- X cnt = ++msg_cnt;
- X get_status = 1;
- X }
- X } else if (!msg_found && buf[0] != '\n') {
- X /* Allow leading blank lines, but anything else is wrong */
- X lines++;
- X had_error++;
- X break;
- X }
- X if (msg_found) {
- X lines++;
- X if (isoff(glob_flags, READ_ONLY) && fputs(buf, tmpf) == -1) {
- X error(tempfile);
- X had_error++;
- X break;
- X }
- X }
- X }
- #ifndef MSG_SEPARATOR
- X if (warn)
- X turnon(glob_flags, WARNING);
- #endif /* !MSG_SEPARATOR */
- X if (msg_found && append != 1)
- X turnon(glob_flags, DO_UPDATE);
- #ifdef MMDF
- X if (!append)
- X (void) fputs(END_MSG_SEP, tmpf);
- #endif /* MMDF */
- X if (had_error) {
- X if (!append)
- X msg[cnt] = old;
- X else if (msg_found && append == 1 && cnt == MAXMSGS-append) {
- X /* reset fp to the beginning of the not-loaded message */
- X bytes = ftell(fp) - strlen(buf);
- X (void) fseek(fp, bytes, L_SET);
- X }
- X if (!msg_found) {
- X if (!append)
- X print("File not left in correct message format.\n");
- X else if (cnt == 0) {
- X if (buf[0])
- X print("\"%s\" does not seem to be a folder\n", file);
- X else
- X had_error = 0; /* empty files are OK */
- X }
- X }
- X } else {
- X if (append)
- X cnt--;
- X if (isoff(glob_flags, READ_ONLY))
- X msg[cnt].m_size = ftell(tmpf) - msg[cnt].m_offset;
- X else
- X msg[cnt].m_size = ftell(fp) - msg[cnt].m_offset;
- X msg[cnt].m_lines = lines;
- X /* remember where we were to seek to for when we append new mail */
- X if (append)
- X cnt++;
- X }
- X if (append == 1) /* merge_folders takes care of this for append == 2 */
- X msg[cnt].m_offset = ftell(fp);
- X close_lock(file, fp);
- X if (isoff(glob_flags, READ_ONLY)) {
- X if (had_error && msg_found && append == 1 && cnt == MAXMSGS-append) {
- X wprint("Using read-only mode.\n");
- X turnon(glob_flags, READ_ONLY);
- X had_error = 0; /* return successfully anyway */
- X }
- X (void) fclose(tmpf);
- X if (!(tmpf = fopen(tempfile, "r"))) {
- X error("Unable to open %s for reading", tempfile);
- X return -1;
- X }
- X }
- X return !had_error;
- }
- SHAR_EOF
- chmod 0644 msgs.c ||
- echo 'restore of msgs.c failed'
- Wc_c="`wc -c < 'msgs.c'`"
- test 28895 -eq "$Wc_c" ||
- echo 'msgs.c: original size 28895, current size' "$Wc_c"
- rm -f _shar_wnt_.tmp
- fi
- # ============= mush.1 ==============
- if test -f 'mush.1' -a X"$1" != X"-c"; then
- echo 'x - skipping mush.1 (File already exists)'
- rm -f _shar_wnt_.tmp
- else
- > _shar_wnt_.tmp
- echo 'x - extracting mush.1 (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'mush.1' &&
- .\" Mush Man Page: Copyright (c) 1987, 1989, 1990 Dan Heller
- .\" Cleaned up January 1988 by Bart Schaefer <schaefer@cse.ogc.edu>
- .\" Patched again December 1989 by Bart Schaefer <schaefer@cse.ogi.edu>
- .\" 1990 updates by Bart Schaefer and Bill Randle <billr@saab.cna.tek.com>
- .\"
- .if n .ds Q \&"
- .if n .ds U \&"
- .if t .ds Q \&``
- .if t .ds U \&''
- .if n .ds - --
- .if t .ds - \(em
- .nh
- .TH MUSH 1 "March 17, 1991" "Version 7.2.2"
- .SH NAME
- The Mail User's Shell \- Shell for electronic mail.
- .SH SYNOPSIS
- .B mush
- [
- .B \-n
- ]
- [
- .B \-v
- ]
- [
- .B \-s
- subject
- ]
- [
- .B \-c
- cc-list
- ]
- [
- .B \-b
- bcc-list
- ]
- [
- address-list
- ]
- .br
- .B mush
- [
- .B \-n
- ]
- [
- .B \-v
- ]
- [
- .BR \-U [ ! ]
- ]
- .B \-h
- draft-file
- .br
- .B mush
- [
- mode-options
- ]
- [
- file-options
- ]
- .SH INTRODUCTION
- The Mail User's Shell (Mush) is an interface for sending and manipulating
- a database of electronic mail messages under the
- .IR UNIX (TM)
- environment.
- There are three user interfaces that allow the user to interact with
- .I Mush.
- The default interface is the conventional tty-based line mode
- similar to command line interpreters such as
- .I csh
- as well as other mailers, such as University of California, Berkeley's
- .I Mail
- and Bell Lab's System V
- .I mailx
- interface.
- This mode requires nothing from the terminal in terms of screen
- capability and may be run on many different versions of the
- .IR UNIX (TM)
- operating system.
- .PP
- The text-graphics
- .RI ( curses )
- interface is reminiscent of the
- .I vi
- visual editor, but is user-configurable to simulate other editors.
- This interface does not require graphics capabilities of
- the computer or the terminal on which it is run, but the terminal must
- have the minimum capabilities required by any visual screen editor.
- .PP
- The
- .I window
- interface for the Sun Workstation utilizes the icon and
- menu based (mouse selectable) windowing system.
- This
- .I tool
- (graphics) mode is highly subject to the version of operating system
- your Sun may be running.
- It is intended to be run on Sun versions 3.5 and higher (those that have the
- SunView window system).
- .PP
- See the corresponding sections for more information on the user
- interface desired.
- Most of this manual deals with commands, variables
- and actions that are common to all three interfaces although
- some attention is paid to individual characteristics of each interface.
- .PP
- The following command line arguments are understood by
- .I Mush
- (full word forms in parentheses):
- .TP
- \-b bcc-list
- (\-blindcarbon, \-blind)
- The list of Blind Carbon Copy recipients is set on the command line.
- If more than one address or an address containing spaces is specified, the
- entire list should be enclosed in quotes.
- This option applies when sending mail only.
- If you are entering the shell, curses mode, or the tool mode, this option is
- ignored.
- .TP
- \-C
- (\-curses)
- Enter the mailer in curses mode upon startup.
- .TP
- \-c cc-list
- (\-carbon, \-copy)
- The list of Carbon Copy recipients is set on the command line.
- If more than one address or an address containing spaces is specified, the
- entire list should be enclosed in quotes.
- This option applies when sending mail only.
- If you are entering the shell, curses mode, or the tool mode, this option is
- ignored.
- .TP
- \-d
- (\-debug)
- Turns on the debugging level to 1.
- You can change debugging levels from within the shell using the
- .B debug
- command.
- .TP
- \-e
- (\-echo)
- Normally, the program runs with the local echo off and each character
- typed is processed individually so as to process certain macros and
- keyboard mappings.
- This option suppresses this from taking place
- and the program only processes input after a carriage return has
- been hit.
- Under normal circumstances, this action is transparent to
- the user and the use of this option is discouraged except when using
- a debugger with the program.
- Note that if this option is specified,
- any key sequences set by map or map! do not substitute their expansions.
- This option is ignored for curses mode.
- .TP
- \-F[!] filename
- (\-source)
- This file is the same type as the initialization file read on startup
- (see INITIALIZATION) with the exception that commands that manipulate
- or search messages may be given.
- Normally, such commands may not appear in the initialization file since
- that file is read before the folder is scanned.
- The file specified by \-F is read after the folder is scanned, so
- commands that affect messages are allowed.
- The optional `!' argument prevents the shell from running after the
- file has been sourced.
- Otherwise,
- .I Mush
- continues into whatever interface has been specified.
- .TP
- \-f [ filename ]
- (\-folder)
- The optional filename argument specifies a folder containing mail messages.
- With no argument,
- .B mbox
- in the current directory (or the variable
- .BR mbox )
- is used.
- If no filename is given, this option must be last on the command line.
- .TP
- \-H[:c]
- (\-headers)
- Have
- .I Mush
- display mail headers without entering the shell.
- See the
- .B headers
- command for information on the
- .B :c
- argument.
- No colon modifier is equivalent to \*Q\-H:a\*U.
- This option prevents the shell from running, so this option turns off the
- \-S and \-C flags.
- This option is ignored if the tool mode is in effect.
- .TP
- \-h draft-file
- (-draft)
- This option specifies a previously prepared message file (called a draft)
- which is read in as a new message to be sent.
- The current implementation requires that the draft file must contain all the
- message headers;
- .I Mush
- adds only a new \*QDate:\*U and a \*QFrom:\*U header if there is none.
- If there is no \*QTo:\*U header, the draft is not sent.
- See the
- .B mail
- command and the section on \*QSending mail\*U for more information.
- .TP
- \-I[!] filename
- (\-init)
- This option specifies an initialization file to be read
- .I before
- any of the other
- .I Mush
- initialization is done.
- The file specified by \-I is read before the default system initialization
- file is read (see the INITIALIZATION section for details).
- The optional `!' argument prevents
- .I Mush
- from reading the default system file, so \-I! can be used to specify a
- substitute default file.
- The user's personal initialization file is read normally.
- .TP
- \-i
- (\-interact)
- Forces interactive mode even if input has been redirected to the program.
- This is intended for remote host mail sessions (with -e) but also allows
- the user to redirect input from a \*Qscript\*U of
- .I Mush
- commands.
- See the INITIALIZATION and MUSH SCRIPTS sections for information on how to
- write scripts that deal with mail.
- Note that this flag is different from the \*Qignore\*U flag of UCB Mail.
- .TP
- \-m mailbox-path
- (\-mailbox)
- The mailbox specified is interpreted as if it is the user's main
- (system) mailbox in place of /usr/spool/mail/$USER (or whatever path is
- applicable for your system and Mail Transport Agent).
- .TP
- \-N
- (\-noheaders)
- Enter
- .I Mush
- without displaying any message headers.
- This argument is passed to the
- .B folder
- command.
- .TP
- \-n[!]
- (\-noinit)
- No initialization is done on start up.
- That is, do not source the default system initialization files.
- If the `!' argument is given, reading of the user's personal
- .I .mushrc
- or
- .I .mailrc
- files is also suppressed.
- See the INITIALIZATION section for more information on
- startup and the significance of these files.
- .TP
- \-r
- (\-readonly)
- Initialize the folder in Read-Only mode; no modification of the folder is
- permitted.
- This argument is passed on to the
- .B folder
- command.
- .TP
- \-S
- (\-shell)
- This flag allows the user to enter the shell even if the system
- mailbox or specified folder is empty or doesn't exist.
- .TP
- \-s subject
- (\-subject)
- The subject is set on the command line using this flag.
- If the subject has
- any spaces or tabs, the entire subject should be enclosed in quotes.
- This applies when sending mail only.
- If you are entering the shell,
- curses mode, or the tool mode, this option is ignored.
- .TP
- \-T timeout
- (\-timeout)
- In the tool mode (Sun only),
- .I timeout
- specifies the length of time (seconds) to wait between each check for new mail.
- 30 seconds is the smallest time allowed for performance reasons;
- 60 seconds is the default value.
- This option should be used either in place of \-t or immediately after it.
- .TP
- \-t
- (\-tool)
- Use the graphics tool mode (Sun only).
- This option must be the first one on the command line, before any Sun window
- system flags or other \fIMush\fR options.
- .sp
- .I
- NOTE: The \-t option is obsolete and may be eliminated in future revisions.
- The preferred way to run the tool mode of \fIMush\fR is to use the command
- .BR mushtool ,
- which is a link to
- .BR mush .
- .TP
- \-u [ user ]
- (\-user)
- The mailbox to use is /usr/spool/mail/\fBuser\fR.
- If the login name for user is not specified, then root is used.
- .TP
- \-U[!]
- (-send)
- This option may be used only with \-h (\-draft).
- It causes the draft file to be sent immediately without further editing
- (\*Qunedited\*U, hence \-U).
- If the optional `!' is appended, signatures and fortunes are suppressed.
- See the
- .B mail
- command and the section on \*QSending mail\*U for more information.
- .TP
- \-v
- (\-verbose)
- Verbose mode is turned on.
- This option is passed to the actual mail delivery
- subsystem internal to your version of
- .IR UNIX (TM).
- Some mailers do not have a verbose option, so this flag may not apply
- to your system (System V, for example).
- This applies when sending mail only.
- If you are entering the shell,
- curses mode, or the tool mode, this option is ignored.
- .SH "GENERAL USAGE"
- Because there are three different interfaces available to the user,
- the tty characteristics (backspace, kill-word, kill-line, redraw line)
- are simulated identically in all interfaces.
- When the user has to type something, the 4.2BSD style of tty driver interface
- is simulated whether you're in the window system, the curses mode, or
- the tty-line mode, and even on System-V machines.
- This means that backspacing causes a
- backspace-space-backspace effect (erasing the character backspaced over).
- The user may reset his tty characteristics using the
- .B stty
- command.
- .PP
- .IR "New mail" .
- .PP
- If during a
- .I Mush
- session, new mail arrives for you, it is automatically incorporated into
- your system mailbox and you are told that new mail has arrived.
- .PP
- In the default line mode, new mail is checked between each command
- issued.
- In the curses mode, new mail is checked on each
- command and is displayed in the bottom line of the screen.
- In the tool based graphics mode, new mail is checked approximately
- every minute or the number of seconds specified by the
- .B -T
- option on the command line.
- .PP
- If you are using your system mailbox as your \*Qcurrent folder,\*U then the
- new mail is added immediately to your current
- list of messages and information similar to the following example is
- displayed, to tell you whom the mail is from:
- .sp
- .ti +2
- New mail: (#15) argv@zipcode.com (Dan Heller)
- .sp
- If you are not in your system mailbox, then the new mail is not added
- to your list of messages, but you are instead informed of the new arrival.
- .sp
- If you are using the tool based mode and
- .I Mush
- is closed to an iconic state, then the number of messages in the current
- folder is displayed on the mailbox icon and the flag on the mailbox goes up.
- .PP
- .IR "Displaying messages" .
- .PP
- Depending on the interface you use, you can display any message in your
- list of messages as long as the message is not marked for deletion.
- If the message is marked as deleted, then use the
- .B undelete
- command supplied by the interface you are using.
- To display a message in line mode, specify the message using
- .BR print ,
- .BR type ,
- .BR p ,
- .BR t ,
- or type a message number to display that message on the screen.
- .PP
- In curses mode, move the cursor over the message you want and type
- a `t' or `p' to read the message.
- You may \*Qbind\*U other keys to call
- the function that displays messages if `t' and `p' are uncomfortable.
- .PP
- In the tool mode, move the cursor over the header summary of the
- message you wish to be displayed and select the LEFT mouse button.
- The MIDDLE mouse button deletes the message, and the RIGHT button
- brings up a menu of additional options, including help.
- If the message you want is not visible (in the header subwindow), you may type
- the number of the message in the \*QRange:\*U item, and press return.
- That message number is displayed.
- Finally, the \*QNext\*U item in the panel below the header display
- can be used to step through the folder, one message at a time.
- .PP
- In the line or curses mode, if the message has more lines than the variable
- .BR crt ,
- then a
- .I pager
- is invoked to allow the user to page through the message without
- having it scroll off the screen.
- The pager used is determined by the variable
- .BR pager .
- If that variable is unset, then a default pager is used.
- Note that if pager is set, but not to a value, or is set to the value
- of \*Qinternal\*U, then the internal pager is used.
- The internal pager
- is very simple; the spacebar displays the next
- .B crt
- lines, carriage return prints the next line, and \*Qq\*U quits the pager.
- .PP
- In the tool mode, if a message is larger than the size of the message
- subwindow, the scrollbar at the left side of the window may be used to
- page the message forwards and backwards.
- The variable
- .B crt_win
- may be set in an initialization file to preset the size of the
- message display subwindow.
- .PP
- An alternative to displaying messages is the
- .B top
- command.
- This command prints just the top few lines of a message.
- The number of lines is determined by the variable
- .BR toplines .
- If this variable isn't set,
- .B top
- prints a number of lines equal to the value of the variable
- .BR crt .
- .PP
- .IR "Sorting mail" .
- .PP
- .I Mush
- allows you to sort your mail according to various constraints such
- as time, size, status (new, unread, deleted, etc.), author and subject.
- See the
- .B sort
- command in the COMMANDS section for more information on sorting.
- Sorting has a panel item in the tool mode, and is bound by default
- to the `o' (sort) and `O' (sort reverse) keys in curses mode.
- .PP
- .IR "Picking specific messages" .
- .PP
- You can select messages that contain unique information, or from
- messages that have special attributes.
- You have the option of restricting your search to messages between dates,
- message numbers, author names and other constraints.
- See the
- .B pick
- command in the COMMANDS section for complete details.
- This feature is not directly accessible from the tool mode, and is
- available only as a search action in curses mode (see, however, the
- CURSES INTERFACE section for temporary escapes to line mode).
- .PP
- .IR "Sending mail" .
- .PP
- You can send mail by listing addresses on the command line when
- .I Mush
- is started, by using the
- .B mail
- command from within
- .IR Mush ,
- or by responding to other mail.
- In curses mode, the `m' key invokes mail, and the `r' key begins a response.
- In the tool mode, selecting the \*QCompose\*U or \*QReply\*U items on the main
- panel opens a separate frame for message composition.
- The message replied-to is either the current message or one specified in
- the \*QRange:\*U item.
- .PP
- When you are sending mail, you are in a mode where everything
- you type is added to the contents of the message.
- When you are done typing your message in line or curses modes,
- you can type `^D' (control-D) to signify the end of the message.
- If you have the variable
- .B dot
- set, then you can end a message with a `.' on a line by itself.
- In the tool mode, select the \*QSend\*U item in the composition frame
- to finish and send the message.
- .PP
- While you are composing a message,
- .I Mush
- treats lines beginning with the character `~' specially.
- This is called a
- .BR "tilde escape" .
- For instance, typing \*Q~i\*U (alone on a line) places a copy
- of the \*Qcurrent message\*U into your message body.
- It does not include the message headers of the message, just the body of
- text that comprises the message.
- A subset of these escapes are available in the tool mode, and others are
- provided as panel items or as menu selections from the \*QInclude\*U item.
- Tilde escapes which alter message headers are not usable when the variable
- .B edit_hdrs
- is set or when the \-E option was passed to the
- .B mail
- command.
- .PP
- The tool mode composition window uses header editing at all times, but
- provides some of these escapes anyway; see the descriptions below, and the
- description of the
- .B edit_hdrs
- variable, for complete details.
- .PP
- Available
- .BR "tilde escapes" :
- [OPTIONAL arguments in square brackets]
- .TP
- ~a file
- Append message buffer to file name.
- Accessed via the \*QExport\*U panel item in tool mode.
- .TP
- ~b [bcc-list]
- Modify blind carbon recipients; otherwise identical to ~t.
- In tool mode, moves the cursor to the Bcc: header, adding one if necessary.
- .TP
- ~c [cc-list]
- Modify carbon copy recipients; otherwise identical to ~t.
- In tool mode, moves the cursor to the Cc: header, adding one if necessary.
- .TP
- ~E[!]
- Erase message buffer; not available in tool mode.
- SHAR_EOF
- true || echo 'restore of mush.1 failed'
- fi
- echo 'End of part 14'
- echo 'File mush.1 is continued in part 15'
- echo 15 > _shar_seq_.tmp
- exit 0
- exit 0 # Just in case...
- --
- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM
- Sterling Software, IMD UUCP: uunet!sparky!kent
- Phone: (402) 291-8300 FAX: (402) 291-4362
- Please send comp.sources.misc-related mail to kent@uunet.uu.net.
-