v18i025: Mail user's shell version 6.4, Part03/19
Rich Salz
rsalz at bbn.com
Thu Mar 16 06:26:55 AEST 1989
Submitted-by: Dan Heller <island!argv at sun.com>
Posting-number: Volume 18, Issue 25
Archive-name: mush6.4/part03
#! /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 archive 3 (of 19)."
# Contents: advanced.mushrc execute.c expr.c hdr_procs.c print.c
# rite.c sample.mushrc sort.c tool.c
# Wrapped by rsalz at papaya.bbn.com on Mon Mar 13 19:25:08 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'advanced.mushrc' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'advanced.mushrc'\"
else
echo shar: Extracting \"'advanced.mushrc'\" \(4980 characters\)
sed "s/^X//" >'advanced.mushrc' <<'END_OF_FILE'
X# advanced.mushrc
X# by Bart Schaefer
X# with special thanks to Phil Lapsley <phil at east.Berkeley.EDU>, who
X# provided the original files on which this example is based. Most of
X# Phil's stuff is still here -- just reorganized and updated to use
X# mush 6.4 features that were unavailable when Phil did the originals.
X#
X# This file is intended to demonstrate helpful ways to use the
X# .mushrc, not advanced mush commands.
X
X# The variable $thisfolder is always set EXCEPT when the .mushrc file
X# is read the first time. A test for non-existance of $thisfolder
X# allows the same .mushrc file to be sourced repeatedly without
X# redundant execution of the initialization commands.
X#
Xif ! $?thisfolder
X # Ignore the usual stuff
X ignore received message-id status
X # Hide folders in ~/.mail and save read mail in spool
X set folder=~/.mail hold
X # Remember a few commands, set up editors, act like a shell
X set history=20 editor=ex visual=vi unix
X # Prompt has folder name, message number, history number
X set prompt="%f %m (!) & "
X # Header summaries show name, date, and subject
X set hdr_format="%25n %-15d %27s"
X # Initialize the cmds below (see later comments)
X set first_time=1
X
X # These two commands are used for automated "bursting" of the spool
X # mailbox. This means that the messages are reorganized into new
X # folders to be read in a prearranged order. See comments below.
X #
X # n brings up the next folder, not the next message
X cmd n 'source ~/.mushrc'
X # N gets the next folder without "bursting"
X cmd N 'set first_time=0; source ~/.mushrc'
X
X # Delete messages by pattern-matching. Examples:
X # del f mailer-daemon Delete mail from mailer-daemon
X # del t mush-users Delete mail to mush-users
X cmd del 'pick -i -\!* | delete'
X # Forwarding
X cmd for 'mail -f'
X # Quick folder change
X cmd F 'folder'
X
X # Some useful aliases
X alias dheller 'The Mush God <island\!argv at cad.berkeley.edu>'
X alias barts 'Archangel Mushael <schaefer at cse.ogc.edu>'
X
X # On init, don't source beyond this point
X exit
Xendif # End of init section -- read on startup only
X
X# This part of the file handles "bursting". A burst is done when the
X# n cmd is used the first time. This is most useful if you habitually
X# have lots of mail when you first log in each morning; unwanted mail
X# can be deleted, and other mail organized for you.
X#
X# The folders in this example bursting scheme are:
X# mush-users anything to or cc'ed to mush-users
X# stats daily stats
X# root root mail other than daily stats
X# Mail not falling into one of these categories is left in the system
X# mailbox to be dealt with first.
X#
Xif $first_time
X # Kill off some uucp garbage
X pick -i -s "file c.* delete" | delete
X pick -i -s "file .* can.t access" | delete
X pick -i -s "remote access to path/file denied" | delete
X # Nuke the boring usenet stuff
X pick -i -f usenet | pick -i -s "uucp map for" | delete
X pick -i -t usenet | pick -i -s "returned mail" | delete
X pick -i -t usenet | pick -i -s "automatic test echo" | delete
X pick -i -t "owner-post" | pick -i -s "unknown mailer" | delete
X pick -i -s "usenet disk space report" | delete
X pick -i -s "very old news articles" | delete
X pick -i -s "uucp map for" | delete
X # Wipe out some uninteresting daily stats
X pick -i -s "the maid was here." | delete
X pick -i -s "daily accounting" | delete
X pick -i -t netsurvey | delete
X # Get rid of these things for good. This isn't essential, but
X # avoids complexity in the later "pick" commands.
X update
X # Save anything "to" or "cc" to mush-users in that folder.
X pick -i -t mush-users | save +mush-users
X pick -i -h cc mush-users | save +mush-users
X # Also save interesting daily stat mail and generic root mail
X pick -i -f root | pick -i -s stats | save +stats
X pick -i -f root | pick -i -s report | save +stats
X pick -i -f uucp | pick -i -s report | save +stats
X pick -i -f root | pick -i -s summary | save +stats
X pick -i -f root | pick -i -s munge | save +stats
X pick -i -t root | save +root
X # Again, make the changes permanent. Saved mail gets deleted.
X # This won't work if you have $keepsave set.
X update
X
X # Make sure we don't burst again needlessly.
X set first_time=0
X
X # Stop sourcing here. Otherwise, we'd change folders without
X # handling the mail left in the system mailbox.
X exit
Xendif
X
X# Finally, handle stepping through the folders one by one. This has been
X# set up for sendmail, where the system mailbox is /usr/spool/mail/$USER,
X# but could easily be modified for other mailers.
X#
X# $thisfolder:t returns the tail only of the folder name.
X
Xif $thisfolder:t == $USER
X folder +stats
X exit
Xendif
X
Xif $thisfolder:t == stats
X folder +mush-users
X exit
Xendif
X
Xif $thisfolder:t == mush-users
X folder +root
X exit
Xendif
X
X# Default back to the system mailbox
Xfolder %
X
X# End of advanced.mushrc
END_OF_FILE
if test 4980 -ne `wc -c <'advanced.mushrc'`; then
echo shar: \"'advanced.mushrc'\" unpacked with wrong size!
fi
# end of 'advanced.mushrc'
fi
if test -f 'execute.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'execute.c'\"
else
echo shar: Extracting \"'execute.c'\" \(5802 characters\)
sed "s/^X//" >'execute.c' <<'END_OF_FILE'
X/* execute.c (c) copyright 10/28/86 (Dan Heller) */
X
X#include "mush.h"
X#ifdef BSD
X#include <sys/wait.h>
X#else
X#ifndef SYSV
X#include <wait.h>
X#endif /* SYSV */
X#endif /* BSD */
X
X#ifdef lint
X#include <sys/resource.h>
X#endif /* lint */
X
Xexecute(argv)
Xchar **argv;
X{
X#ifdef SYSV
X int status;
X#else
X union wait status;
X#endif /* SYSV */
X#ifdef SIGCONT
X SIGRET (*oldstop)(), (*oldcont)();
X#endif /* SIGCONT */
X int pid;
X SIGRET (*oldint)(), (*oldquit)();
X
X#ifdef SUNTOOL
X if (istool) {
X print("Editing letter...");
X
X panel_set(abort_item, PANEL_SHOW_ITEM, FALSE, 0);
X panel_set(send_item, PANEL_SHOW_ITEM, FALSE, 0);
X panel_set(edit_item, PANEL_SHOW_ITEM, FALSE, 0);
X win_setrect(tty_sw->ts_windowfd, &msg_rect);
X msg_rect.r_height = 0;
X win_setrect(msg_sw->ts_windowfd, &msg_rect);
X if ((exec_pid = ttysw_fork(tty_sw->ts_data, argv,
X &tty_sw->ts_io.tio_inputmask,
X &tty_sw->ts_io.tio_outputmask,
X &tty_sw->ts_io.tio_exceptmask)) == -1)
X error("%s failed", *argv), sigchldcatcher();
X Debug("tty pid = %d\n", exec_pid);
X return;
X }
X#endif /* SUNTOOL */
X oldint = signal(SIGINT, SIG_IGN);
X oldquit = signal(SIGQUIT, SIG_IGN);
X#ifdef SIGCONT
X oldstop = signal(SIGTSTP, SIG_DFL);
X oldcont = signal(SIGCONT, SIG_DFL);
X#endif /* SIGCONT */
X turnon(glob_flags, IGN_SIGS);
X
X echo_on();
X if ((exec_pid = vfork()) == 0) {
X (void) signal(SIGINT, SIG_DFL);
X (void) signal(SIGQUIT, SIG_DFL);
X (void) signal(SIGPIPE, SIG_DFL);
X (void) closefileds(3); /* close all descriptors above 2 */
X execvp(*argv, argv);
X if (errno == ENOENT)
X print("%s: command not found.\n", *argv);
X else
X error(*argv);
X _exit(-1);
X }
X /* parent's got to do something; sigchldcatcher will do waiting
X * if other forks die (sendmail), then this wait will catch them,
X * This loop will really get -1, cuz sigchldcatcher will catch all else.
X */
X while ((pid = wait(&status)) != -1 && pid != exec_pid)
X Debug("The exec loop caught a signal? (pid = %d)\n", pid);
X /* reset our ttymodes */
X echo_off();
X (void) signal(SIGINT, oldint);
X (void) signal(SIGQUIT, oldquit);
X#ifdef SIGCONT
X (void) signal(SIGTSTP, oldstop);
X (void) signal(SIGCONT, oldcont);
X#endif /* SIGCONT */
X turnoff(glob_flags, IGN_SIGS);
X}
X
XSIGRET
Xsigchldcatcher()
X{
X#ifdef SUNTOOL
X struct rect rect;
X extern FILE *ed_fp;
X#endif /* SUNTOOL */
X#ifdef SYSV
X int status;
X#else
X union wait status;
X#endif /* SYSV */
X int pid;
X
X#ifdef BSD
X /* The following SHOULDN'T be necessary, but it is!!! ttysw_fork()
X * returns the pid of the thing that it executes, but that's not the
X * pid that dies! There are many procs that might die from ttysw_fork
X * one of them is the process, another is the tty, etc... other
X * procs that might die are sendmail, fortune, etc... tool_sigchld()
X * handles these, but we can't let it have control unless we KNOW the
X * editor is done.
X * so if what we catch is not the exec_pid from ttysw_fork(), then
X * send ourselves a sigchld to go thru this routine again. mush -d
X */
X while ((pid = wait3(&status, WNOHANG, (struct rusage *)0)) > 0) {
X Debug("%d died...\n", pid);
X if (pid == exec_pid)
X break;
X }
X#else
X#ifndef SYSV
X while ((pid = wait2(&status, WNOHANG)) > 0 && pid != exec_pid)
X Debug("%d died...\n", pid);
X#else /* SYSV */
X while ((pid = wait((int *)0)) > 0 && pid != exec_pid)
X Debug("%d died...\n", pid);
X#endif /* SYSV */
X#endif /* BSD */
X#ifndef SUNTOOL
X }
X#else /* SUNTOOL */
X if (pid != exec_pid || exec_pid <= 0) /* if the editor didn't die, return */
X return;
X /* editor died -- reset exec_pid so no one thinks we're running */
X exec_pid = 0;
X /* only the tool needs to continue from here. Reset the win */
X if (istool < 1)
X return;
X tool_sigchld(tool);
X print("Editor done.");
X win_getrect(tty_sw->ts_windowfd, &msg_rect);
X if (msg_rect.r_height < 2 * l_height(curfont)) {
X print_more(" (well, something just happened)");
X return;
X }
X {
X extern char *edfile;
X if (!(ed_fp = fopen(edfile, "r+")))
X error("can't reopen %s", edfile);
X (void) fseek(ed_fp, 0L, 2);
X }
X /* I'd like to be able to just pw_rop the tty window onto the window
X * we're going to use now, but I can't access the data structure!
X *
X * pw_rop(msg_win, 0, 0, msg_rect.r_width, msg_rect.r_height, PIX_SRC,
X * ((struct ??? *)(tty_sw->ts_data))->pr_pixrect, 0, 0);
X * So, instead, just clear the window and write the last N lines from the
X * end of the file into the window.
X */
X rect.r_top = rect.r_left = rect.r_height = 0;
X rect.r_width = msg_rect.r_width;
X win_setrect(tty_sw->ts_windowfd, &rect);
X win_setrect(msg_sw->ts_windowfd, &msg_rect);
X do_clear();
X /* read the last 2K bytes in the file -- search backwards for enough
X * carriage returns that will fill the window with the end of the letter
X * written so far and display the text.
X */
X {
X register long where = ftell(ed_fp);
X register int cr = 0, lines = msg_rect.r_height * l_height(curfont) - 3;
X char buf[2*BUFSIZ], *p;
X where = max(0, where-2*BUFSIZ);
X (void) fseek(ed_fp, where, L_SET);
X p = buf + read(fileno(ed_fp), buf, 2*BUFSIZ);
X *p = 0;
X while (cr < lines && p > buf)
X if (*--p == '\n')
X cr++;
X if (p > buf)
X while (*p != '\n')
X p++;
X Addstr(p);
X }
X panel_set(comp_item, PANEL_SHOW_ITEM, FALSE, 0);
X panel_set(send_item, PANEL_SHOW_ITEM, TRUE, 0);
X panel_set(edit_item, PANEL_SHOW_ITEM, TRUE, 0);
X panel_set(abort_item, PANEL_SHOW_ITEM, TRUE, 0);
X wprint("(continue editing letter.)\n");
X type_cursor(PIX_SRC);
X}
X
XSIGRET
Xsigtermcatcher()
X{
X ttysw_done(tty_sw->ts_data);
X if (ison(glob_flags, IS_GETTING))
X rm_edfile(-1);
X cleanup(SIGTERM);
X}
X#endif /* SUNTOOL */
END_OF_FILE
if test 5802 -ne `wc -c <'execute.c'`; then
echo shar: \"'execute.c'\" unpacked with wrong size!
fi
# end of 'execute.c'
fi
if test -f 'expr.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'expr.c'\"
else
echo shar: Extracting \"'expr.c'\" \(4682 characters\)
sed "s/^X//" >'expr.c' <<'END_OF_FILE'
X/* @(#)expr.c 2.3 (c) copyright 10/15/86 (Dan Heller) */
X
X#include "mush.h"
X
Xchar *eval_expr();
X
X/* Parse a string (p) to interpret numbers and ranges of numbers (n-m)
X * delimited by whitespace or comma's. Set msg_list bitfields using
X * macros in mush.h.
X * Return the address of the end of whatever we parsed (in case there's
X * more that the calling routine cares to deal with).
X * Finally, remember that user specifies one more than actual message number
X */
Xchar *
Xdo_range(p, list1)
Xregister char *p, *list1;
X{
X register int num1 = -1, num2 = -1, except = 0;
X register char *p2;
X char list2[MAXMSGS_BITS];
X
X if (!p)
X return "";
X while (*p) {
X if (isdigit(*p) || *p == '$' || *p == '.' || *p == '^') {
X if (isdigit(*p)) {
X char c;
X p2 = p;
X skipdigits(0); /* find the end of the digits */
X c = *p, *p = 0; /* temporarily plug a null */
X if (!(num2 = chk_msg(p2))) {
X clear_msg_list(list1);
X return NULL;
X }
X *p = c;
X } else if (*p == '$')
X p++, num2 = msg_cnt;
X else if (*p == '.')
X p++, num2 = current_msg+1;
X else if (*p == '^')
X p++, num2 = 1;
X if (except)
X unset_msg_bit(list1, num2-1);
X else
X set_msg_bit(list1, num2-1);
X if (num1 >= 0) {
X if (num1 > num2) {
X print("syntax error: range sequence order reversed.\n");
X clear_msg_list(list1);
X return NULL;
X }
X while (++num1 < num2)
X if (except)
X unset_msg_bit(list1, num1-1);
X else
X set_msg_bit(list1, num1-1);
X num1 = num2 = -1;
X }
X }
X /* expressions to evaluate start with a `
X * p2 points to first char passed the last char parsed.
X */
X if (*p == '`') {
X clear_msg_list(list2);
X if (!(p = eval_expr(p, list2))) {
X clear_msg_list(list1);
X return NULL;
X } else {
X if (except)
X bitput(list2, list1, msg_cnt, &=~) /* MACRO */
X else
X bitput(list2, list1, msg_cnt, |=) /* MACRO */
X }
X }
X /* NOT operator: `* {5}' (everything except for 5)
X * `4-16 {8-10}' (4 thru 16 except for 8,9,10)
X */
X if (*p == '{' || *p == '}') {
X if (*p == '{' && (except || num1 >= 0))
X break;
X if (*p == '}' && !except) {
X print("syntax error: missing {\n"); /* } */
X break;
X }
X except = !except;
X } else if (*p == '-')
X if (num1 >= 0 || num2 < 0
X || !index(" \t{},.*`$", *(p+1)) && !isdigit(*(p+1)))
X break;
X else
X num1 = num2;
X else if (*p == ',' || *p == '*') {
X if (num1 >= 0)
X break;
X else if (*p == '*') {
X if (except)
X clear_msg_list(list1);
X else
X for (num1 = 0; num1 < msg_cnt; num1++)
X set_msg_bit(list1, num1);
X num1 = -1;
X }
X } else if (!index(" \t`", *p))
X break;
X if (*p)
X skipspaces(1); /* don't make user type stuff squished together */
X }
X if (num1 >= 0 || except) {
X if (except)
X /* { */ print("syntax error: unmatched }\n");
X else
X print("syntax error: unfinished range\n");
X clear_msg_list(list1);
X return NULL;
X }
X return p;
X}
X
X/*
X * convert a message list to an ascii string.
X */
Xvoid
Xlist_to_str(list, str)
Xchar list[], *str;
X{
X int n, m = -1;
X
X for (n = 0; n < msg_cnt; n++) {
X if (msg_bit(list, n)) {
X if (m == -1)
X str += strlen(sprintf(str, "%d", (m = n) + 1 ));
X continue;
X }
X if (m == -1)
X continue;
X if (n - m > 2)
X str += strlen(sprintf(str, "-%d", n));
X else if (n - m == 2)
X str += strlen(sprintf(str, " %d", n));
X *str++ = ' ';
X m = -1;
X }
X if (m > -1 && m != n - 1) {
X if (n - m > 2)
X *str++ = '-';
X else
X *str++ = ' ';
X str += Strcpy(str, itoa(msg_cnt));
X }
X *str = 0;
X}
X
X/* evaluate expressions:
X * mail> delete `pick -f root` deletes all messages from root.
X * mail> save * {`pick -s "Re:"`} save all message that don't have "Re:"
X * in the subject header.
X * mail> save `pick -x -s "Re:"` same
X * args as follows:
X * p should point to the first ` -- check for it.
X * on tells whether to turn bits on or off if messages match.
X */
Xchar *
Xeval_expr(p, new_list)
Xregister char *p, new_list[];
X{
X register char *p2, **argv;
X int argc;
X u_long save_flags = glob_flags;
X
X if (!(p2 = index(++p, '`'))) {
X print("unmatched backquote (`)\n");
X return NULL;
X }
X *p2 = 0;
X
X skipspaces(0);
X if (!*p) {
X print("Invalid null command\n");
X return NULL;
X }
X turnon(glob_flags, DO_PIPE);
X /* ignore sigs only because if user interrupts the do_command,
X * the longjmp will corrupt the stack and the program is hosed.
X * fix is to have layers of jmp_bufs to return to different levels.
X */
X turnon(glob_flags, IGN_SIGS);
X if (*p && (argv = make_command(p, TRPL_NULL, &argc)))
X (void) do_command(argc, argv, new_list);
X glob_flags = save_flags;
X *p2 = '`';
X return p2+1;
X}
END_OF_FILE
if test 4682 -ne `wc -c <'expr.c'`; then
echo shar: \"'expr.c'\" unpacked with wrong size!
fi
# end of 'expr.c'
fi
if test -f 'hdr_procs.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'hdr_procs.c'\"
else
echo shar: Extracting \"'hdr_procs.c'\" \(4239 characters\)
sed "s/^X//" >'hdr_procs.c' <<'END_OF_FILE'
X/* @(#)hdr_procs.c (c) copyright 10/18/86 (Dan Heller) */
X
X/* hdr_procs.c -- panel item procedures for the message hdrs */
X#include "mush.h"
X
X/* which message headers are to be displayed */
Xdo_hdr(foo, value, event)
XPanel_item foo;
Xint value;
Xstruct inputevent *event;
X{
X register char *argv[3];
X argv[2] = NULL;
X argv[0] = "headers";
X
X if (!msg_cnt) {
X print("No Mail.");
X return;
X }
X if (!value || event->ie_code == MS_LEFT)
X argv[1] = (foo == next_scr)? "+": "-";
X else
X argv[1] = (foo == next_scr)? "-": "+";
X
X panel_set(foo, PANEL_VALUE, 0, 0);
X (void) do_hdrs(2, argv, NULL);
X}
X
X/* alters display of the message headers */
Xdisplay_hdrs(foo, value, event)
XPanel_item foo;
Xint value;
Xstruct inputevent *event;
X{
X int show_deleted = !!do_set(set_options, "show_deleted");
X
X if (event->ie_code != MS_LEFT) {
X switch(value) {
X case 0 : case 1: {
X char buf[25];
X show_deleted = !value;
X (void) cmd_line(sprintf(buf, "%sset show_deleted",
X (value == 0)? "" : "un"), msg_list);
X }
X when 2 :
X turnoff(glob_flags, REV_VIDEO);
X when 3 :
X turnon(glob_flags, REV_VIDEO);
X when 4:
X return help(hdr_panel_sw->ts_windowfd, "headers", tool_help);
X }
X (void) do_hdrs(0, DUBL_NULL, NULL);
X }
X print("%sShow Deleted headers, \"Current Message\" header in %s",
X (show_deleted)? NO_STRING: "Don't ",
X (ison(glob_flags, REV_VIDEO))? "reverse": "boldface");
X}
X
Xp_set_opts(item, value, event)
XPanel_item item;
Xint value;
Xstruct inputevent *event;
X{
X static char *p, *oldp;
X static char buf[8];
X u_long bang = ison(glob_flags, IGN_BANG);
X
X if (event->ie_code == MS_LEFT)
X value = 0;
X if (value && (value != 3 || value != 2)
X && panel_get(input_item, PANEL_SHOW_ITEM)) {
X print("Need value for %s first!", oldp);
X return;
X } else if (!value && ison(glob_flags, IS_GETTING)) {
X print("Finish editing letter first");
X return;
X } else if (item == option_item) {
X if (!value) /* first menu item */
X view_options();
X else if (value == 1)
X set_fkeys();
X else
X (void) help(panel_sw->ts_windowfd, "opts", tool_help);
X return;
X } else if (item == ignore_item)
X if (value == 3)
X return help(hdr_panel_sw->ts_windowfd, "ignore", tool_help);
X else
X oldp = p = strcpy(buf, "ignore");
X else if (item == alias_item)
X if (value == 3)
X return help(panel_sw->ts_windowfd, "aliases", tool_help);
X else
X oldp = p = strcpy(buf, "alias");
X if (value) {
X char tmp[30];
X (void) sprintf(tmp, "%set %s:", (value == 1)? "S": "Uns", p);
X panel_set(input_item,
X PANEL_LABEL_STRING, tmp,
X PANEL_MENU_CHOICE_STRINGS, "Abort", 0,
X PANEL_SHOW_ITEM, TRUE,
X 0);
X oldp = p;
X return;
X }
X panel_set(item, PANEL_VALUE, 0, 0);
X do_clear();
X pw_text(msg_win, l_width(DEFAULT), 15, PIX_SRC, fonts[LARGE], p);
X if (item != ignore_item)
X pw_text(msg_win, 30*l_width(DEFAULT),15,PIX_SRC,fonts[LARGE],"Values");
X turnon(glob_flags, IGN_BANG);
X (void) cmd_line(p, msg_list);
X if (!bang)
X turnoff(glob_flags, IGN_BANG);
X}
X
Xmsg_num_done(item, event)
XPanel_item item;
Xstruct inputevent *event;
X{
X char buf[82];
X u_long bang = ison(glob_flags, IGN_BANG);
X register char *p;
X int n;
X
X if (event->ie_code != '\n' && event->ie_code != '\r')
X return help(hdr_panel_sw->ts_windowfd, "message range", tool_help);
X (void) sprintf(buf, "headers %s", (p = (char *)panel_get_value(item)));
X panel_set(item, PANEL_VALUE, NO_STRING, 0);
X if (!(n = chk_msg(p)))
X return;
X current_msg = --n;
X turnon(glob_flags, IGN_BANG);
X (void) cmd_line(buf, msg_list);
X if (!bang)
X turnoff(glob_flags, IGN_BANG);
X display_msg(n, (long)0);
X}
X
Xdo_sort(item, value, event)
XPanel_item item;
Xint value;
Xstruct inputevent *event;
X{
X register char *argv[3];
X argv[0] = "sort";
X argv[2] = NULL;
X if (event->ie_code == MS_LEFT)
X argv[1] = do_set(set_options, "sort");
X else switch(value) {
X case 0: argv[1] = "d";
X when 1: argv[1] = "a";
X when 2: argv[1] = "s";
X when 3: argv[1] = "S";
X when 4: argv[1] = "R";
X when 5: help(hdr_panel_sw->ts_windowfd, "sort", tool_help);
X }
X if (value != 5) {
X (void) sort(2, argv, NULL);
X (void) do_hdrs(0, DUBL_NULL, NULL);
X }
X panel_set(item, PANEL_VALUE, 0, 0);
X}
END_OF_FILE
if test 4239 -ne `wc -c <'hdr_procs.c'`; then
echo shar: \"'hdr_procs.c'\" unpacked with wrong size!
fi
# end of 'hdr_procs.c'
fi
if test -f 'print.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'print.c'\"
else
echo shar: Extracting \"'print.c'\" \(5250 characters\)
sed "s/^X//" >'print.c' <<'END_OF_FILE'
X/* @(#)print.c 2.4 (c) copyright 10/15/86 (Dan Heller) */
X
X#include "mush.h"
X#include <varargs.h>
X
X/*ARGSUSED*/
X/*VARARGS1*/
Xvoid
Xerror(fmt, arg1, arg2, arg3, arg4)
Xregister char *fmt;
Xchar *arg1, *arg2, *arg3, *arg4;
X{
X print(fmt, arg1, arg2, arg3, arg4);
X print_more(": %s\n", sys_errlist[errno]);
X}
X
X#if defined(SUNTOOL) || defined(CURSES)
X/*
X * print just like printf -- to a window, to curses, or to stdout. Use vprintf
X * if available. msgbuf is the buffer used to print into if necessary.
X * If you're running SUN3.2 or higher, the typecast (unsigned char *)msgbuf
X * (where indicated) otherwise, msgbuf is not typecast at all.
X * Also note same casting in wprint().
X */
X/*VARARGS*/
Xvoid
Xprint(va_alist)
Xva_dcl
X{
X static char msgbuf[BUFSIZ];
X char *fmt;
X va_list args;
X#ifndef VPRINTF
X FILE foo;
X#endif /* VPRINTF */
X static int x; /* position on line saved for continued prints */
X char *p; /* same type as struct file _ptr,_buf in stdio.h */
X
X#ifdef CURSES
X if (iscurses) {
X if (isoff(glob_flags, CONT_PRNT))
X move(LINES-1, x = 0), refresh();
X } else
X#endif /* CURSES */
X if (istool < 2) {
X va_start(args);
X fmt = va_arg(args, char *);
X#ifdef VPRINTF
X vprintf(fmt, args);
X#else /* VPRINTF */
X _doprnt(fmt, args, stdout);
X#endif /* VPRINTF */
X va_end(args);
X fflush(stdout);
X return;
X }
X va_start(args);
X fmt = va_arg(args, char *);
X if (fmt) {
X#ifdef VPRINTF
X vsprintf(msgbuf, fmt, args); /* NULL in fmt reprints last msg */
X#else /* VPRINTF */
X foo._cnt = BUFSIZ;
X foo._base = foo._ptr = msgbuf; /* may have to cast(unsigned char *) */
X foo._flag = _IOWRT+_IOSTRG;
X (void) _doprnt(fmt, args, &foo);
X *foo._ptr = '\0'; /* plant terminating null character */
X#endif /* VPRINTF */
X }
X va_end(args);
X p = msgbuf;
X if (iscurses || istool)
X while (p = index(p, '\n'))
X *p = ' ';
X#ifdef CURSES
X if (iscurses) {
X p = msgbuf;
X for (;;) {
X int len = COLS-1-x; /* space remaining at till the eol */
X /* don't wrap the line! Just print it and refresh() */
X printw("%-.*s", len, p), clrtoeol(), refresh();
X /* if length(p) (remainder of msgbuf) doesn't wrap, break loop */
X if ((x += strlen(p)) < COLS-1)
X break;
X /* the next print will overwrite bottom line, so \n first */
X putchar('\n'), move(LINES-1, x = 0); /* reset x */
X /* move p forward the number of chars we were able to display */
X p += len;
X turnon(glob_flags, CNTD_CMD); /* display ...continue... prompt */
X }
X turnoff(glob_flags, CONT_PRNT);
X fflush(stdout); /* some sys-v's aren't fflushing \n's */
X return;
X }
X#endif /* CURSES */
X#ifdef SUNTOOL
X if (isoff(glob_flags, CONT_PRNT))
X x = 5;
X turnoff(glob_flags, CONT_PRNT);
X pw_text(print_win, x, l_height(LARGE), PIX_SRC, fonts[LARGE], msgbuf);
X pw_text(print_win, x+1, l_height(LARGE), PIX_SRC|PIX_DST,
X fonts[LARGE], msgbuf);
X x += strlen(msgbuf) * l_width(LARGE);
X Clrtoeol(print_win, x, l_height(LARGE), LARGE);
X#endif /* SUNTOOL */
X}
X#endif /* SUNTOOL || CURSES */
X
X#ifdef SUNTOOL
X/*VARARGS*/
Xvoid
Xwprint(va_alist)
Xva_dcl
X{
X#ifndef VPRINTF
X FILE foo;
X#endif /* VPRINTF */
X char msgbuf[BUFSIZ]; /* we're not getting huge strings */
X char *fmt;
X va_list args;
X
X if (istool < 2) {
X va_start(args);
X fmt = va_arg(args, char *);
X#ifdef VPRINTF
X vprintf(fmt, args);
X#else /* VPRINTF */
X _doprnt(fmt, args, stdout);
X#endif /* VPRINTF */
X va_end(args);
X fflush(stdout);
X return;
X }
X va_start(args);
X fmt = va_arg(args, char *);
X if (fmt) {
X#ifdef VPRINTF
X vsprintf(msgbuf, fmt, args); /* NULL in fmt reprints last msg */
X#else /* VPRINTF */
X foo._cnt = BUFSIZ;
X foo._base = foo._ptr = msgbuf; /* may have to cast (unsigned char *) */
X foo._flag = _IOWRT+_IOSTRG;
X _doprnt(fmt, args, &foo); /* format like printf into msgbuf via foo */
X *foo._ptr = '\0'; /* plant terminating null character */
X#endif /* VPRINTF */
X Addstr(msgbuf); /* addstr() will scroll if necessary */
X }
X va_end(args);
X}
X
X/*
X * scroll the msg_win "lines"
X * if `lines' is negative (backwards scroll) msg_pix can't be NULL
X */
Xvoid
Xscroll_win(lines)
Xregister int lines;
X{
X register int y = lines * l_height(curfont);
X /* if the user attempts to scroll back to before the beginning of the
X * message [either with the middle mouse button or the keyboard command
X * keys ('k', 'K', '-')], scroll back only to the beginning of the message.
X */
X if (txt.y + y < msg_rect.r_height)
X y = - (txt.y - msg_rect.r_height);
X txt.x = 5;
X
X if (msg_pix) {
X if (txt.y + y >= msg_pix->pr_size.y - 5)
X y = msg_pix->pr_size.y - txt.y;
X still_more += y; /* let scrolling know where we are */
X txt.y += y;
X pw_rop(msg_win, 0, 5,
X msg_rect.r_width, crt * l_height(curfont),
X PIX_SRC, msg_pix, 0, txt.y - msg_rect.r_height + 3);
X tool_more(NULL);
X return;
X }
X /* y must be positive (forward scrolling) so we're scrolling typed
X * text or something like that (~p, ~?, etc...)
X */
X pw_copy(msg_win, 0, 0,
X msg_rect.r_width, msg_rect.r_height - y,
X PIX_SRC, msg_win, 0, y);
X pw_writebackground(msg_win, 0, msg_rect.r_height - y,
X msg_rect.r_width, y, PIX_CLR);
X txt.y -= y;
X}
X#endif /* SUNTOOL */
X
Xclr_bot_line()
X{
X print("");
X}
END_OF_FILE
if test 5250 -ne `wc -c <'print.c'`; then
echo shar: \"'print.c'\" unpacked with wrong size!
fi
# end of 'print.c'
fi
if test -f 'rite.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'rite.c'\"
else
echo shar: Extracting \"'rite.c'\" \(4181 characters\)
sed "s/^X//" >'rite.c' <<'END_OF_FILE'
X/* rite.c (c) copyright 1986 (Dan Heller) */
X
X#include "mush.h"
X
X#define LASTLINE (msg_rect.r_height - l_height(LARGE)-5)
X
Xstatic char String[BUFSIZ];
Xstatic int count, overflow, save_orig_x;
X
Xchar *
Xrite(c)
Xregister char c;
X{
X static int literal_next;
X
X if (c == ltchars.t_lnextc || literal_next) {
X if (literal_next)
X Addch(c);
X else /* don't call Addch to prevent cursor from advancing */
X pw_char(msg_win, txt.x, txt.y, PIX_SRC, fonts[curfont], '^');
X literal_next = !literal_next;
X return NULL;
X }
X literal_next = 0;
X if (c == _tty.sg_erase || c == CTRL(127) || c == CTRL(H)) {
X if (count)
X backspace();
X } else if (c == _tty.sg_kill) {
X if (count) {
X Clrtoeol(msg_win, txt.x = save_orig_x, txt.y,curfont);
X overflow = count = String[0] = 0;
X }
X } else if (c == ltchars.t_werasc)
X while (count) {
X char c = String[count-1];
X backspace();
X if (!count ||
X isspace(String[count-1]) && !isspace(c) ||
X !isalnum(String[count-1]) && isalnum(c))
X break;
X }
X else if (c == '\n' || c == '\r' || c == 13) {
X String[count] = 0;
X if ((txt.y += l_height(curfont)) >= LASTLINE && !getting_opts)
X scroll_win(1);
X /* else Clrtoeol(msg_win, txt.x, txt.y, curfont); */
X overflow = count = 0, txt.x = 5;
X return String;
X } else if (c == 12)
X if (ison(glob_flags, IS_GETTING))
X Addch(c);
X else
X do_clear();
X else if (count == BUFSIZ-1)
X print("Text too long for String!"), count--;
X else if (c == '\t')
X do Addch(' ');
X while (count % 8 && count < BUFSIZ);
X else
X Addch(c);
X return NULL;
X}
X
Xstatic
Xbackspace()
X{
X if (overflow) {
X pw_text(msg_win, save_orig_x, txt.y, PIX_SRC, fonts[curfont],
X &String[--overflow]);
X Clrtoeol(msg_win, msg_rect.r_width-10-l_width(curfont), txt.y, curfont);
X String[--count] = 0;
X } else if ((txt.x -= l_width(curfont)) >= 5) {
X if (iscntrl(String[count-1])) {
X pw_char(msg_win, txt.x, txt.y, PIX_SRC, fonts[curfont], ' ');
X txt.x -= l_width(curfont);
X }
X pw_char(msg_win, txt.x, txt.y, PIX_SRC, fonts[curfont], ' ');
X String[--count] = 0;
X } else
X txt.x = 5;
X}
X
Xstatic
XAddch(c)
Xregister char c;
X{
X extern char *_unctrl[];
X
X if (!count)
X save_orig_x = txt.x, bzero(String, BUFSIZ);
X if (c > 31 && c != 127)
X String[count++] = c;
X else {
X Addch('^'), count--;
X Addch(_unctrl[c][1]);
X String[count-1] = c;
X return;
X }
X pw_char(msg_win, txt.x, txt.y, PIX_SRC, fonts[curfont], c);
X if ((txt.x += l_width(curfont)) <= msg_rect.r_width-5-l_width(curfont))
X return;
X if (getting_opts) {
X pw_text(msg_win, save_orig_x, txt.y, PIX_SRC, fonts[curfont],
X &String[++overflow]);
X txt.x -= l_width(curfont);
X pw_char(msg_win, txt.x, txt.y, PIX_SRC, fonts[curfont], ' ');
X } else {
X txt.x = 5;
X if ((txt.y += l_height(curfont)) >= LASTLINE)
X scroll_win(1);
X }
X}
X
XAddstr(s)
Xregister char *s;
X{
X char buf[BUFSIZ];
X register int cnt = 0, max_len;
X register char *p = buf, newline = 0;
X
X max_len = (msg_rect.r_width - 10) / l_width(curfont) + 1;
X
X while ((*p = *s++) && *p != '\n' && cnt < max_len)
X if (*p == '\t')
X do *p++ = ' ';
X while (++cnt % 8);
X else p++, cnt++;
X *p = 0;
X
X if (*--s)
X newline = *s, *s = 0; /* newline may or may not be a '\n' */
X else
X s = 0;
X
X if (*buf) {
X if (msg_pix) {
X struct pr_prpos pixr;
X pixr.pr = msg_pix;
X pixr.pos = txt;
X pf_text(pixr, PIX_SRC, fonts[curfont], buf);
X } else
X pw_text(msg_win, txt.x, txt.y, PIX_SRC, fonts[curfont], buf);
X txt.x += cnt * l_width(curfont);
X }
X if (newline) {
X if (newline != '\n')
X *s = newline;
X if ((txt.y += l_height(curfont)) >= LASTLINE && !msg_pix)
X scroll_win(1);
X txt.x = 5;
X if (newline == '\n' && !*++s)
X return;
X Addstr(s);
X }
X}
X
Xtool_more(p)
Xregister char *p;
X{
X int percent;
X /* we are typing -- scrool the window */
X if (!msg_pix) {
X scroll_win(1);
X return;
X }
X if (p)
X print(p);
X else {
X if ((percent = (still_more * 100) / msg_pix->pr_size.y) >= 100)
X print( "--End of Message %d--", current_msg+1);
X else
X print("--Message %d--(%d%%)", current_msg+1, percent);
X if (ison(glob_flags, IS_GETTING))
X print_more(" ('q' returns to type-in mode)");
X }
X}
END_OF_FILE
if test 4181 -ne `wc -c <'rite.c'`; then
echo shar: \"'rite.c'\" unpacked with wrong size!
fi
# end of 'rite.c'
fi
if test -f 'sample.mushrc' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'sample.mushrc'\"
else
echo shar: Extracting \"'sample.mushrc'\" \(7468 characters\)
sed "s/^X//" >'sample.mushrc' <<'END_OF_FILE'
X# sample.mushrc
X# By Bart Schaefer and Dan Heller
X#
X# Change mush's temp file directory, to avoid quota collisions.
X# /usr/tmp so tmpfiles won't be rm'd before they can be recovered.
Xset tmpdir=/usr/tmp
X
X# Set the folder and mbox locations; the + expands to value of "folder".
Xset folder=$HOME/Mail mbox=+mbox
X
X# Set up the display early to allow quick exit in headers-only mode.
X# The hdrs_only flag is true if the command line was: "mush -H".
X# The variable hdr_format is set to change the format of the header
X# summaries that are displayed.
Xif hdrs_only
X set hdr_format='%28a %M %-2N %.33s'
X exit # Quits reading this file
Xelse
X set hdr_format='%28a %M %-2N (%3.5l li) %.25s'
Xendif
X
X# Set the prompt to show current time, name of the current folder,
X# current message number, and count of total messages.
Xset prompt="(%T) %f: #%m of %t> "
X
X# Hitting <CR> should do nothing (helps make mush more shell-like). If
X# newline is not set, hitting <CR> prints the next message (like Mail).
X# This variable could be set to any mush command.
Xset newline
X
X# These variables are helpful for new users:
X# ask -- always prompt for Subject: of mail
X# ignoreeof -- ignore end-of-file from keyboard
X# verify -- query that all is well before sending mail
X# warning -- report miscellaneous possible problems
Xset ask verify warning
Xset ignoreeof="echo 'Use "'"'quit'"'" to quit.'"
X
X# When reading messages, don't bother looking at lengthy, boring headers.
Xignore message-id received
X
X# Since mush has csh-like history, you might find it annoying to type
X# things like "mail host\!host1\!host2\!user" from within the mush shell.
X# Setting nonobang will prevent the "unknown event" and allow the !'s to
X# be typed without having to be preceded by backslashes.
Xset nonobang
X
X# By default, mush's history is set to the last command only. Set it to
X# remember the last 100 commands.
Xset history = 100
X
X# If the variable "unix" is set, then any command that isn't a mush command
X# will execute the command as if you typed it from the shell. Note, such
X# commands will not go through another shell -- this is it.
Xset unix
X
X# Mush tries to read ~/.mushrc first, then it tries ~/.mailrc. Assuming
X# you use *this* file as your .mushrc, source the contents of .mailrc as
X# well in case there are Mail aliases that are set there.
Xsource $HOME/.mailrc
X
X# Use a real pager.
Xset pager=less
X
X# When typing in a letter, it is sometimes convenient to have lines wrap
X# automatically similar to editors like vi and emacs. In this example, if
X# the user types past column 74, a newline will automatically be inserted.
Xset wrapcolumn=74
X
X# If "autosign" is set, then a file can be read in automatically whenever
X# mail is sent. This file is normally your "signature," that is, your
X# name and other information you want included in every message.
Xset autosign = ~/.signature
X
X# When you use the -i option to reply, or use the ~i tilde escape in a letter
X# when in compose mode, the current message will be included in your text.
X# Put a nice wrapper around those included messages. Here, show the author's
X# name and the subject of his letter, label the end, and add a trailing blank
X# to separate each inclusion and make finding the end easier.
Xset pre_indent_str='On %M %N, %T, %.50n wrote:\n} Subject: %.65s'
Xset indent_str='} ' # actual message text is preceded by a "}"
Xset post_indent_str='}-- End of excerpt from %.50n\n'
X
X# Label replies with a header showing the who, what, and when of the
X# message being replied-to.
Xset in_reply_to='%f\n\t"%s" (%d)'
X
X# Mail routing and address-fixing conveniences. If auto_route is set, then
X# replies to messages take a closer look at the addresses of the recipients.
X# If any redundant paths are present, they are pruned. Also, the path that
X# precedes any hosts listed in the "known_hosts" list is truncated. This is
X# useful for uucp sites only, and is therefore commented out in this sample.
X# set auto_route known_hosts="sun ucbcad well unicom"
X
X# The "alts" command specifies alternate addresses that I have. Here,
X# "*" expands to any "path" whose recipient ends with the user's current
X# login name. If another login name is desired, the login and/or path
X# to that login must be preceded by a !. Otherwise, standard paths are used.
Xalts "*"
X
X# The "map" command can rebind certain key sequences in tty-mode only.
X# Here, if the user types two R's in a row at the prompt, then the string
X# "reply -ei " will be echoed as if the user typed it.
Xmap RR "reply -ei "
X# "rr" will do a reply and do the newline for you so you don't have to.
Xmap rr "reply\n"
X
X# The "map!" command is similar to "map" in that you can do keyboard
X# acceleration, but map! occurs during letter composition mode only.
Xmap! '\CT' ' ' # ^T generates 4 spaces in composition mode.
X# Here, hitting * twice will append a pre-signature.
Xmap! ** "\n Later,\n"
X
X# Be careful with map and map! -- you can cause an infinite loop.
X# Your interrupt key (usually ^C) will stop such loops.
X
X# The curses mode allows the screen to be set up like a full screen editor.
X# There are basic "curses commands" which are bound to keyboard key-sequences
X# (usually one character). The user can rebind these keys to suit his tastes.
X# Note that the binding for R below removes the binding of reply-all.
X#
Xset curses_help # Unset this to remove help message in curses.
Xbind \n display # Hit return to display the next message.
Xbind t top # Make it easier to see the top few lines.
Xbind e macro "[line-mode]edit\n" # Quick edit from curses.
Xbind P macro "[line-mode]Print\n" # Show me all the headers.
Xbind R macro "[line-mode]reply -ei " # Reply with inclusion and edit.
Xbind A macro "R[getline]~t\n\CUargv\n" # R to Dan w/auto address fix.
X
X# "cmd" is used to set command line aliases similar to the way "csh"
X# does it. The only difference is that "alias" is a reserved word in
X# Mush and Mail, so cmd is used.
X#
Xcmd dq 'd \!*; q' # Delete a message list, then quit.
Xcmd unread 'flags \!* U O' # Mark messages unread.
Xcmd : curses # Colon now "toggles" curses mode.
X
X# Find messages from mailer-daemon (ignore upper/lower case).
Xcmd md 'pick -i -f mailer-daemon'
X# Because mush can pipe commands to one another, including "cmd"'s, this
X# example will delete all messages from mailer-daemon
Xcmd dmd 'md | delete'
X
X# aliases -- just like Mail's, but you can specify "names"
Xalias argv Dan Heller <island!argv at sun.com>
Xalias bart Bart Schaefer <schaefer at ogccse.ogc.edu>
Xalias mush-users Mush Users <mush-users-request at garp.mit.edu>
X
X# The rest of this file demonstrates how sysadmins with novice users
X# might want to set things up. The following "exit" should be removed.
Xexit
X
Xif -e $HOME/.mushexpert
X set quiet
X exit
Xendif
Xif ! -e $HOME/.mushuser
X echo "I see you've never used the Mush program before."
X echo "I'll set some special flags to help you out."
X echo "After you've used Mush a few times, you can type the command:"
X echo -p "${prompt} expert\n"
X echo "and the flags will no longer be set unless you put them"
X echo "in your $HOME/.mushrc file."
X sh touch $HOME/.mushuser # Use sh in case $unix is not set.
X if $?quiet
X unset quiet # Show the help message on startup.
X endif
Xendif
X# At this point some helpful variables should be set. See the list above,
X# marked as "helpful for new users", for suggestions.
X#
X# Create the "expert" command mentioned in the message above.
Xcmd expert 'sh touch $HOME/.mushexpert'
END_OF_FILE
if test 7468 -ne `wc -c <'sample.mushrc'`; then
echo shar: \"'sample.mushrc'\" unpacked with wrong size!
fi
# end of 'sample.mushrc'
fi
if test -f 'sort.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'sort.c'\"
else
echo shar: Extracting \"'sort.c'\" \(5803 characters\)
sed "s/^X//" >'sort.c' <<'END_OF_FILE'
X/* sort.c 2.0 (c) copyright 1986 (Dan Heller) */
X
X#include "mush.h"
X/* #define MYQSORT */
X
Xstatic int order, ignore_case;
Xstatic jmp_buf sortbuf;
X
Xsort(argc, argv, list)
Xregister int argc;
Xregister char *argv[], list[];
X{
X int status_cmp(), author_cmp(), date_cmp(), subject_cmp(), subj_with_re();
X SIGRET (*oldint)(), (*oldquit)();
X int (*how)() = status_cmp;
X int n, offset = -1, range = 0;
X
X order = 1, ignore_case = FALSE;
X
X while (argc && *++argv) {
X n = 0;
X while (argv[0][n])
X switch(argv[0][n++]) {
X case '-': order = -1;
X when 'd': how = date_cmp;
X when 'a': how = author_cmp;
X when 's': how = subject_cmp;
X when 'R': how = subj_with_re;
X when 'S': how = status_cmp;
X when 'i': ignore_case = TRUE;
X otherwise: return help(0, "sort", cmd_help);
X }
X }
X if (msg_cnt <= 1) {
X print("Not enough messages to sort.\n");
X return -1;
X }
X turnon(glob_flags, IGN_SIGS);
X on_intr();
X
X if (list && ison(glob_flags, IS_PIPE)) {
X for (n = 0; n < msg_cnt; n++)
X if (msg_bit(list, n)) {
X if (offset < 0)
X offset = n;
X range++;
X } else if (offset >= 0)
X break;
X } else
X offset = 0, range = msg_cnt;
X
X if (range < 2)
X print("Range not broad enough to sort anything\n");
X else {
X Debug("Sorting %d messages starting at message %d\n", range, offset+1);
X
X if (setjmp(sortbuf) == 0)
X qsort((char *)&msg[offset], range, sizeof (struct msg), how);
X else
X print("WARNING: Sorting interrupted: unpredictable order.\n");
X turnon(glob_flags, DO_UPDATE);
X }
X turnoff(glob_flags, IGN_SIGS);
X off_intr();
X /* Break pipes because message lists are invalid */
X return 0 - in_pipe();
X}
X
X#ifdef MYQSORT
Xqsort(base, len, siz, compar)
Xregister struct msg *base;
Xint (*compar)();
X{
X register int i, swapping;
X struct msg temp;
X
X do {
X swapping = 0;
X for (i = 0; i < len-1; ++i) {
X if (compar(base+i, base+i+1) > 0) {
X temp = base[i];
X base[i] = base[i+1];
X base[i+1] = temp;
X swapping = 1;
X }
X }
X } while (swapping);
X}
X#endif /* MYSORT */
X
Xstatus_cmp(msg1, msg2)
Xregister struct msg *msg1, *msg2;
X{
X if (ison(glob_flags, WAS_INTR))
X longjmp(sortbuf, 1);
X if (msg1 < msg || msg2 < msg) {
X wprint("sort botch trying to sort %d and %d\n", msg1-msg, msg2-msg);
X return 0;
X }
X if (msg1->m_flags == msg2->m_flags)
X return 0;
X if (ison(msg1->m_flags, DELETE) && isoff(msg2->m_flags, DELETE))
X return order;
X if (isoff(msg1->m_flags, DELETE) && ison(msg2->m_flags, DELETE))
X return -order;
X if (isoff(msg1->m_flags, OLD) && ison(msg2->m_flags, OLD))
X return -order;
X if (ison(msg1->m_flags, OLD) && isoff(msg2->m_flags, OLD))
X return order;
X if (ison(msg1->m_flags, UNREAD) && isoff(msg2->m_flags, UNREAD))
X return -order;
X if (isoff(msg1->m_flags, UNREAD) && ison(msg2->m_flags, UNREAD))
X return order;
X if (ison(msg1->m_flags,PRESERVE) && isoff(msg2->m_flags,PRESERVE))
X return -order;
X if (isoff(msg1->m_flags,PRESERVE) && ison(msg2->m_flags,PRESERVE))
X return order;
X if (ison(msg1->m_flags,REPLIED) && isoff(msg2->m_flags,REPLIED))
X return -order;
X if (isoff(msg1->m_flags,REPLIED) && ison(msg2->m_flags,REPLIED))
X return order;
X if (ison(msg1->m_flags,SAVED) && isoff(msg2->m_flags,SAVED))
X return -order;
X if (isoff(msg1->m_flags,SAVED) && ison(msg2->m_flags,SAVED))
X return order;
X
X return order;
X}
X
Xauthor_cmp(msg1, msg2)
Xregister struct msg *msg1, *msg2;
X{
X char buf1[HDRSIZ], buf2[HDRSIZ];
X
X if (ison(glob_flags, WAS_INTR))
X longjmp(sortbuf, 1);
X if (msg1 < msg || msg2 < msg) {
X wprint("sort botch trying to sort %d and %d\n", msg1-msg, msg2-msg);
X return 0;
X }
X (void) reply_to(msg1 - msg, 0, buf1); /* "0" for "author only" */
X (void) reply_to(msg2 - msg, 0, buf2);
X Debug("author: msg %d: %s, msg %d: %s\n", msg1-msg, buf1, msg2-msg, buf2);
X if (ignore_case)
X return lcase_strncmp(buf1, buf2, -1) * order;
X return strcmp(buf1, buf2) * order;
X}
X
X/*
X * Subject comparison ignoring Re: subject_to() appends an Re: if there is
X * any subject whatsoever.
X */
Xsubject_cmp(msg1, msg2)
Xregister struct msg *msg1, *msg2;
X{
X char buf1[HDRSIZ], buf2[HDRSIZ];
X
X if (ison(glob_flags, WAS_INTR))
X longjmp(sortbuf, 1);
X if (msg1 < msg || msg2 < msg) {
X wprint("sort botch trying to sort %d and %d\n", msg1-msg, msg2-msg);
X return 0;
X }
X (void) subject_to(msg1 - msg, buf1);
X (void) subject_to(msg2 - msg, buf2);
X Debug("subjects: (%d): \"%s\" (%d): \"%s\"\n", msg1-msg,buf1,msg2-msg,buf2);
X if (ignore_case)
X return lcase_strncmp(buf1, buf2, -1) * order;
X return strcmp(buf1, buf2) * order;
X}
X
X/*
X * compare subject strings from two messages.
X * If Re is appended, so be it -- if user wants to ignore Re: use 'R' flag.
X */
Xsubj_with_re(msg1, msg2)
Xregister struct msg *msg1, *msg2;
X{
X char buf1[HDRSIZ], buf2[HDRSIZ], *p;
X
X if (ison(glob_flags, WAS_INTR))
X longjmp(sortbuf, 1);
X if (msg1 < msg || msg2 < msg) {
X wprint("sort botch trying to sort %d and %d\n", msg1-msg, msg2-msg);
X return 0;
X }
X if (!(p = header_field(msg1 - msg, "subject")))
X p = "";
X (void) strcpy(buf1, p);
X if (!(p = header_field(msg2 - msg, "subject")))
X p = "";
X (void) strcpy(buf2, p);
X Debug("subjects: (%d): \"%s\" (%d): \"%s\"\n",
X msg1-msg, buf1, msg2-msg, buf2);
X if (ignore_case)
X return lcase_strncmp(buf1, buf2, -1) * order;
X return strcmp(buf1, buf2) * order;
X}
X
Xdate_cmp(msg1, msg2)
Xregister struct msg *msg1, *msg2;
X{
X if (ison(glob_flags, WAS_INTR))
X longjmp(sortbuf, 1);
X if (msg1 < msg || msg2 < msg) {
X wprint("sort botch trying to sort %d and %d\n", msg1-msg, msg2-msg);
X return 0;
X }
X if (ison(glob_flags, DATE_RECV))
X return strcmp(msg1->m_date_recv, msg2->m_date_recv) * order;
X else
X return strcmp(msg1->m_date_sent, msg2->m_date_sent) * order;
X}
END_OF_FILE
if test 5803 -ne `wc -c <'sort.c'`; then
echo shar: \"'sort.c'\" unpacked with wrong size!
fi
# end of 'sort.c'
fi
if test -f 'tool.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'tool.c'\"
else
echo shar: Extracting \"'tool.c'\" \(4177 characters\)
sed "s/^X//" >'tool.c' <<'END_OF_FILE'
X/* @(#)tool.c (c) copyright 10/15/86 (Dan Heller) */
X
X/* tool.c --make the mailtool windows, panels, etc... */
X#include "mush.h"
X
Xmake_tool(args)
Xchar **args;
X{
X struct stat rootbuf, tmpbuf;
X struct inputmask im;
X register unsigned i;
X char **choice_args, **button_args, *p;
X char buf1[WIN_NAMESIZE], buf2[WIN_NAMESIZE];
X
X getfonts();
X mail_icon.ic_font = fonts[DEFAULT];
X
X if (p = do_set(set_options, "screen_win"))
X screen = atoi(p);
X else
X screen = 6;
X
X /* where to place text on mail icon -- how many messages there are */
X rect_construct(&mail_icon.ic_textrect,
X l_width(DEFAULT), 58-l_height(DEFAULT),
X 3*l_width(DEFAULT), l_height(DEFAULT));
X
X if (!(tool = tool_make(
X WIN_ICON, &mail_icon,
X WIN_HEIGHT, 700,
X WIN_WIDTH, 650,
X WIN_BOUNDARY_MGR, 1,
X WIN_ATTR_LIST, args,
X NULL)))
X perror(prog_name), cleanup(0);
X tool_free_attribute_list(args);
X
X choice_args = panel_make_list(
X PANEL_MENU_TITLE_FONT, fonts[LARGE],
X PANEL_DISPLAY_LEVEL, PANEL_NONE,
X PANEL_SHOW_MENU, TRUE,
X PANEL_SHOW_MENU_MARK, FALSE,
X 0);
X
X button_args = panel_make_list(
X PANEL_FEEDBACK, PANEL_INVERTED,
X PANEL_SHOW_MENU, FALSE,
X 0);
X
X make_hdr_panel(choice_args, button_args);
X
X if (!(hdr_sw = gfxsw_createtoolsubwindow(tool, "hdr_sw",
X TOOL_SWEXTENDTOEDGE, 10+ screen*l_height(DEFAULT), (char **)0)))
X perror("hdr_sw"), cleanup(0);
X gfxsw_getretained((struct gfxsubwindow *)hdr_sw->ts_data);
X hdr_win = ((struct gfxsubwindow *)(hdr_sw->ts_data))->gfx_pixwin;
X
X input_imnull(&im);
X win_setinputcodebit(&im, LOC_STILL);
X win_setinputcodebit(&im, LOC_MOVE);
X win_setinputcodebit(&im, LOC_WINENTER);
X for (i = VKEY_FIRSTFUNC; i <= VKEY_LASTFUNC; i++)
X win_setinputcodebit(&im, i);
X win_setinputmask(hdr_sw->ts_windowfd, &im, &im,
X win_fdtonumber(hdr_panel_sw->ts_windowfd));
X hdr_sw->ts_io.tio_selected = hdr_io;
X hdr_sw->ts_io.tio_handlesigwinch = hdrwin_handlesigwinch;
X
X make_main_panel(choice_args, button_args);
X xfree(choice_args), xfree(button_args);
X
X if (!(print_sw = gfxsw_createtoolsubwindow(tool, "print_sw",
X TOOL_SWEXTENDTOEDGE, l_height(LARGE) + 10, (char **)0)))
X perror("print_sw"), cleanup(0);
X print_win = ((struct gfxsubwindow *)(print_sw->ts_data))->gfx_pixwin;
X print_sw->ts_io.tio_handlesigwinch = print_sigwinch;
X
X /* text subwindow */
X if (!(msg_sw = gfxsw_createtoolsubwindow(tool, "msg_sw",
X TOOL_SWEXTENDTOEDGE, TOOL_SWEXTENDTOEDGE, (char **)0)))
X perror("msg_sw"), cleanup(0);
X gfxsw_getretained((struct gfxsubwindow *)msg_sw->ts_data);
X msg_win = ((struct gfxsubwindow *)(msg_sw->ts_data))->gfx_pixwin;
X
X /* everything we want the text window to pay attention to */
X input_imnull(&im);
X im.im_flags = IM_ASCII;
X im.im_flags &= ~IM_ANSI;
X for (i = VKEY_FIRSTFUNC; i <= VKEY_LASTFUNC; i++)
X win_setinputcodebit(&im, i);
X win_setinputmask(msg_sw->ts_windowfd, &im, &im, WIN_NULLLINK);
X msg_sw->ts_io.tio_selected = msg_io;
X msg_sw->ts_io.tio_handlesigwinch = msgwin_handlesigwinch;
X
X /* tty subwindow */
X if (!(tty_sw = ttytlsw_createtoolsubwindow(tool, "tty_sw",
X TOOL_SWEXTENDTOEDGE, 0, (char **)0)))
X perror("tty_sw"), cleanup(0);
X ttysw_handlesigwinch(tty_sw);
X win_setcursor(tty_sw->ts_windowfd, &write_cursor);
X
X (void) sprintf(blank, "%128c", ' ');
X (void) signal(SIGWINCH, sigwinchcatcher);
X (void) signal(SIGTERM, sigtermcatcher);
X (void) signal(SIGCHLD, sigchldcatcher);
X pw_writebackground(hdr_win, 0,0, hdr_rect.r_width, hdr_rect.r_height,
X PIX_CLR);
X if (ioctl(0, TIOCGETC, &tchars))
X perror("gtty failed"), cleanup(0);
X win_numbertoname (0, buf1);
X if ((rootfd = open(buf1, 0)) == -1)
X error("can't open %s", buf1), cleanup(0);
X if (fstat(rootfd, &rootbuf))
X error("can't stat %s", buf1), cleanup(0);
X for (parentfd = 3; parentfd < rootfd; parentfd++)
X if (fstat(parentfd, &tmpbuf))
X error("Can't stat fd-%d", parentfd);
X else if (tmpbuf.st_ino == rootbuf.st_ino) {
X (void) close(rootfd);
X rootfd = parentfd;
X break;
X }
X istool = 2;
X (void) do_version();
X lock_cursors();
X tool_install(tool);
X tool_display(tool);
X do_clear();
X}
END_OF_FILE
if test 4177 -ne `wc -c <'tool.c'`; then
echo shar: \"'tool.c'\" unpacked with wrong size!
fi
# end of 'tool.c'
fi
echo shar: End of archive 3 \(of 19\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 19 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
--
Please send comp.sources.unix-related mail to rsalz at uunet.uu.net.
More information about the Comp.sources.unix
mailing list