[comp.sources.unix] v11i058: Mail user's shell, Part08/12

rsalz@uunet.UU.NET (Rich Salz) (09/21/87)

Submitted-by: island!argv@Sun.COM (Dan Heller)
Posting-number: Volume 11, Issue 58
Archive-name: mush5.7/Part08

#! /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 8 (of 12)."
# Contents:  hdrs.c tool_help
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'hdrs.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'hdrs.c'\"
else
echo shar: Extracting \"'hdrs.c'\" \(23014 characters\)
sed "s/^X//" >'hdrs.c' <<'END_OF_FILE'
X/* hdr_procs.c 	(c) copyright 1986 (Dan Heller) */
X
X/* hdrs.h -- routines that look at message headers */
X#include "mush.h"
X
X/*
X * get which message via the offset and search for the headers which
X * match the string "str". there may be more than one of a field (like Cc:)
X * so get them all and "cat" them together into the static buffer
X * "buf" and return its address.
X */
Xchar *
Xheader_field(n, str)
Xchar *str;
X{
X    static char    buf[BUFSIZ];
X    char 	   tmp[BUFSIZ];
X    register char  *p, *p2, *b = buf;
X    int contd_hdr;  /* true if next line is a continuation of the hdr we want */
X
X    if (fseek(tmpf, msg[n].m_offset, L_SET) != 0) {
X	error("fseek in %s (msg %d, folder=%s)", tempfile, n+1, mailfile);
X	turnon(glob_flags, READ_ONLY);
X	return NULL;
X    }
X    *b = 0;
X    while((p = fgets(tmp, BUFSIZ, tmpf)) && *p != '\n') {
X	if (*p != ' ' && *p != '\t') {
X	    contd_hdr = 0;
X	    /* strcmp ignoring case */
X	    for(p2 = str; *p && *p2 && *p2 == lower(*p); ++p, ++p2);
X	    /* MATCH is true if p2 is at the end of str and *p is ':' */
X	    if (*p2 || *p++ != ':')
X		continue;
X	    else
X		contd_hdr = 1;
X	} else if (!contd_hdr)
X	    continue;
X	skipspaces(0);
X	p2 = no_newln(p);
X	*++p2 = ' ', *++p2 = 0;
X	b += Strcpy(b, p);
X    }
X    if (b > buf) /* now get rid of the trailing blank */
X	*--b = 0;
X    return (*buf)? buf: NULL;
X}
X
Xdo_hdrs(argc, argv, list)
Xregister char **argv, list[];
X{
X    register int   pageful = 0, fnd;
X    int 	   (*oldint)(), (*oldquit)(), show_deleted;
X    static int     cnt;
X    register char  *p;
X    char 	   first_char = (argc) ? **argv: 'h';
X
X    if (!msg_cnt) {
X	if (isoff(glob_flags, DO_PIPE))
X	    return;
X#ifdef CURSES
X	if (iscurses)
X	    clear();
X#endif CURSES
X#ifdef SUNTOOL
X	if (istool)
X	    mail_status(0);
X#endif SUNTOOL
X	return 0;
X    }
X    if (first_char == ':' || (argc > 1 && argv[1][0] == ':')) {
X	if (first_char != ':')
X	    argv++;
X	return specl_hdrs(argv, list);
X    }
X
X    if (argc > 1 && !strcmp(argv[1], "-?"))
X	return help(0, "headers", cmd_help);
X
X    on_intr();
X
X    if (argc && (argv[0][1] == '+' || argc > 1 && !strcmp(argv[1], "+")) ||
X	    first_char == 'z' && !argv[1])
X	if (msg_cnt > screen)
X	    cnt = min(msg_cnt - screen, n_array[0] + screen);
X	else
X	    cnt = 0;
X    else if (argc && (argv[0][1] == '-' || argc > 1 && !strcmp(argv[1], "-")))
X	cnt = max((cnt - 2*screen), 0);
X    else if (argc && *++argv &&
X	(isdigit(**argv) || **argv == '^' || **argv == '$')
X	 || ison(glob_flags, IS_PIPE)) {
X	/* if we're coming from a pipe, start display at the first msg bit
X	 * set in the msg_list
X	 */
X	if (ison(glob_flags, IS_PIPE)) {
X	    if (isoff(glob_flags, DO_PIPE))
X		for (fnd = 0; fnd < msg_cnt; fnd++)
X		    if (msg_bit(list, fnd))
X			wprint("%s\n", compose_hdr(fnd));
X	    off_intr();
X	    return 0;
X	}
X	/* if a number was given, use it */
X	if (!(fnd = chk_msg(*argv))) {
X	    off_intr();
X	    return -1;
X	}
X	for (cnt = fnd - 1; cnt > 0 && cnt + screen > msg_cnt; cnt--);
X    } else if (current_msg < n_array[0] || current_msg > n_array[screen-1])
X	cnt = current_msg; /* adjust if user reads passed screen bounds */
X    else if (cnt >= msg_cnt || !argc || !*argv)
X	cnt = max((cnt - screen), 0); /* adjust window to maintian position */
X
X    show_deleted = !!do_set(set_options, "show_deleted");
X
X    for (;pageful<screen && cnt<msg_cnt && isoff(glob_flags, WAS_INTR); cnt++) {
X	if (!iscurses && !show_deleted && first_char == 'h'
X	    && ison(msg[cnt].m_flags, DELETE))
X	    continue;
X	n_array[pageful++] = cnt;
X	/* this message was displayed -- set the bit */
X	if (list)
X	    set_msg_bit(list, cnt);
X	/* if do_pipe, don't output anything */
X	if (ison(glob_flags, DO_PIPE))
X	    continue;
X	p = compose_hdr(cnt);
X	if (!istool && (!iscurses || ison(glob_flags, IS_GETTING)))
X	    puts(p);
X#ifdef SUNTOOL
X	else if (istool) {
X	    if (cnt == current_msg) /* embolden or reverse_video */
X		highlight(hdr_win, 0,pageful*l_height(DEFAULT), DEFAULT,p);
X	    else
X		pw_text(hdr_win, 0, pageful * l_height(DEFAULT), PIX_SRC,
X							fonts[DEFAULT], p);
X	    Clrtoeol(hdr_win, strlen(p)*l_width(DEFAULT),
X		     pageful*l_height(DEFAULT), DEFAULT);
X	}
X#endif SUNTOOL
X#ifdef CURSES
X        else if (iscurses)
X	    mvprintw(pageful, 0, "%-*s", COLS-2, p);
X#endif CURSES
X    }
X    /* just in case a signal stopped us */
X    off_intr();
X    pageful++;
X#ifdef CURSES
X    if (iscurses && pageful < screen)
X	move(pageful, 0), clrtobot();
X#endif CURSES
X    if (cnt == msg_cnt) {
X	while (pageful <= screen) {
X	    n_array[pageful-1] = msg_cnt+1; /* assign out-of-range values */
X#ifdef SUNTOOL
X	    if (istool)
X		Clrtoeol(hdr_win, 0, pageful * l_height(DEFAULT), DEFAULT);
X#endif SUNTOOL
X	    ++pageful;
X	}
X    }
X#ifdef SUNTOOL
X    if (istool) {
X	if (msg_cnt > screen) {
X	    panel_set(next_scr, PANEL_SHOW_ITEM, TRUE, 0);
X	    panel_set(prev_scr, PANEL_SHOW_ITEM, TRUE, 0);
X	}
X	mail_status(0);
X    }
X#endif SUNTOOL
X    return 0;
X}
X
X#define NEW 1
X#define ALL 2
X
Xspecl_hdrs(argv, list)
Xchar **argv, list[];
X{
X    u_long	special = 0;
X    int 	n = 0;
X
X    while (argv[0][++n])
X	switch(argv[0][n]) {
X	    case 'a': special = ALL;
X	    when 'n': special = NEW;
X	    when 'u': special = UNREAD;
X	    when 'o': special = OLD;
X	    when 'd': special = DELETE;
X	    otherwise: print("choose from n,u,o,d, or a"); return -1;
X	}
X    if (debug)
X	(void) check_flags(special);
X
X    for (n = 0; n < msg_cnt; n++) {
X	/*
X	 * First, see if we're looking for NEW messages.
X	 * If so, then check to see if the msg is unread and not old.
X	 * If special > ALL, then special has a mask of bits describing
X	 * the state of the message.
X	 */
X	if (ison(glob_flags, IS_PIPE)&& !msg_bit(list, n))
X	    continue;
X	if (special == ALL || special == NEW &&
X	       (ison(msg[n].m_flags, UNREAD) && isoff(msg[n].m_flags, OLD))) {
X	    if (isoff(glob_flags, DO_PIPE))
X		print("%s\n", compose_hdr(n));
X	    if (list)
X		set_msg_bit(list, n);
X#ifndef SYSV
X	/*
X	 * XENIX compiler can't handle "special" in ison() macro.
X	 * It only works if the second argument is a constant!
X	 */
X	} else if (special > ALL && ison(msg[n].m_flags, special)) {
X	    if (isoff(glob_flags, DO_PIPE))
X		print("%s\n", compose_hdr(n));
X	    if (list)
X		set_msg_bit(list, n);
X#endif SYSV
X	} else {
X	    if (list)
X		unset_msg_bit(list, n);
X	    Debug("msg[%d].m_flags: %d", n, msg[n].m_flags),
X			 (void) check_flags(msg[n].m_flags);
X	}
X    }
X    return 0;
X}
X
Xchar *
Xcompose_hdr(cnt)
X{
X    static char buf[256];
X    register char *p, *b, *status;
X    char from[256], subject[256], date[17], lines[6], chars[6], line[256];
X    char to[512], addr[256], name[256];
X
X    /* status of the message */
X    if (ison(msg[cnt].m_flags, DELETE))
X	status = "*";
X    else if (ison(msg[cnt].m_flags, OLD) && ison(msg[cnt].m_flags, UNREAD))
X	status = "U";
X    else if (ison(msg[cnt].m_flags, PRESERVE))
X	status = "P";
X    else if (isoff(msg[cnt].m_flags, UNREAD))
X	status = " ";
X    else
X	status = "N";
X
X    to[0] = from[0] = subject[0] = date[0] = lines[0] = chars[0] =
X    addr[0] = name[0] = line[0] = 0;
X
X    /* who's the message to */
X    if (p = header_field(cnt, "to"))
X	(void) strcpy(to, p);
X
X    /* who the messages is from--
X	%f		From field
X	%a		From address
X	%n		From name
X
X	where %a is anything in angle brackets, or if no angle brackets,
X	anything not in parenthesis, and %n is anything in parenthesis, or if
X	nothing in parenthesis, anything not in angle brackets.
X     */
X    if (!(p = header_field(cnt, "from"))) {
X	/* if all else fails, then get the first token in "From" line */
X	register char *p2;
X	p = ""; /* just in case */
X	if (fseek(tmpf, msg[cnt].m_offset, L_SET) == -1 ||
X	    !(p2 = fgets(line, BUFSIZ, tmpf))) {
X	    error("fseek in %s (msg %d, folder=%s)", tempfile, cnt+1, mailfile);
X	    turnon(glob_flags, READ_ONLY);
X	} else if (!(p = index(p2, ' ')))
X	    print("Fudged \"From\" line: %s", p2);
X	else if (p2 = any(++p, " \t"))
X	    *p2 = 0;
X    }
X    skipspaces(0);
X    (void) no_newln(p);
X    /* if the "from" line produced the user's login name, then the message is
X     * from the user -- attempt to give more useful information by telling
X     * to whom the message was sent.  This is not possible if the "to" header
X     * failed to get info (which is probably impossible).
X     */
X    if (!strcmp(p, login) && *to)
X	(void) sprintf(from, "TO: %s", to);
X    else
X	(void) strcpy(from, p);
X    /* look for < or (  If <, then whatever is inside goes in addr, and
X     * whatever isn't inside goes in name.  If it's a (, then whatever is
X     * inside goes in name and whatever isn't, goes in addr.  It the same
X     * type of thing, but exclusive of each other.
X     */
X    if (p = any(from, "<(")) {
X	register char *p2, *out, *in;
X	if (*p == '<')
X	    out = name, in = addr;
X	else
X	    out = addr, in = name;
X
X	(void) strcpy(in, p+1);
X	if (p2 = index(in, (*p == '<')? '>' : ')'))
X	    *p2 = 0;
X	/* whatever isn't in <'s gets put in "name". Put p at end of name */
X	if (p - from > 1)
X	    (void) strncpy(out, from, p - from), p = out+(p-from);
X	else
X	    p = out;
X	if (p2) {
X	    /* p2 will be at >, so there will be at least a blank following */
X	    while (isspace(*++p2));
X	    /* copy remainder of line onto p (end of name) */
X	    (void) strcpy(p, p2);
X	}
X    }
X
X    (void) sprintf(lines, "%d", msg[cnt].m_lines);
X    (void) sprintf(chars, "%d", msg[cnt].m_size);
X
X    /* the date */
X    if (p = msg_date(cnt))
X	(void) strcpy(date, date_to_string(p));
X
X    /* and the subject */
X    if (p = header_field(cnt, "subject"))
X	(void) strcpy(subject, p);
X
X    /* now, construct a header */
X    if (!hdr_format) /* this should NEVER be true, but just in case */
X	hdr_format = DEF_HDR_FMT;
X
X    (void) sprintf(buf, "%3.d ", cnt+1);
X    b = buf+4;
X    *b++ = ((cnt == current_msg && !iscurses)? '>': ' ');
X    cnt = 5;
X    for (p = hdr_format; *p; p++)
X	if (*p == '\\')
X	    switch (*++p) {
X		case 't':
X		    while (cnt % 8)
X			cnt++, *b++ = ' ';
X		when 'n':
X		    cnt = 1, *b++ = '\n';
X		otherwise: cnt++, *b++ = *p;
X	    }
X	else if (*p == '%') {
X	    int buffer_space = 0;
X	    register char *p2;
X
X	    if (isdigit(*++p))
X		p = my_atoi(p, &buffer_space);
X	    switch (*p) {
X		case 'f': p2 = from;
X		when 'a':
X		    if (!*(p2 = addr))
X			p2 = from;
X		when 'n':
X		    if (!*(p2 = name))
X			p2 = from;
X		when '%': p2 = "%";
X		when 't': p2 = to;
X		when 'd': p2 = date;
X		when 's': p2 = subject;
X		when 'l': p2 = lines;
X		when 'c': p2 = chars;
X		when 'S': p2 = status;
X		otherwise: continue; /* unknown formatting char */
X	    }
X	    if (!buffer_space)
X		buffer_space = strlen(p2);
X	    (void) sprintf(b, "%-*.*s", buffer_space, buffer_space, p2);
X	    cnt += buffer_space, b += buffer_space;
X	} else
X	    cnt++, *b++ = *p;
X    for (*b-- = 0; isspace(*b); --b)
X	*b = 0;
X    return buf;
X}
X
X/*
X * Using message "n", build a list of recipients that you would mail to if
X * you were to reply to this message.  If "all" is true, then it will take
X * everyone from the To line in addition to the original sender.
X * fix_address() is caled from mail.c, not from here.  There are too many
X * other uses for reply_to to always require reconstruction of return paths.
X * Note that we do NOT deal with Cc paths here either.
X * Check to make sure that we in fact return a legit address (i.e. not blanks
X * or null). If such a case occurs, return login name.  Always pad blank at end.
X */
Xchar *
Xreply_to(n, all, buf)
Xregister char *buf;
X{
X    register char *p = NULL, *p2, *b = buf, *field;
X    char line[256];
X
X    if (field = do_set(set_options, "reply_to_hdr")) {
X	if (!*field)
X	    goto From; /* special case -- get the colon-less From line */
X	field = lcase_strcpy(line, field);
X	while (*field) {
X	    if (p2 = any(field, " \t,:"))
X		*p2 = 0;
X	    if ((p = header_field(n, field)) || !p2)
X		break;
X	    else {
X		field = p2+1;
X		while (isspace(*field) || *field == ':' || *field == ',')
X		    field++;
X	    }
X	}
X	if (!p)
X	    print("Warning: message contains no `reply_to_hdr' headers.\n");
X    }
X    if (p || (!p && ((p = header_field(n, "reply-to")) ||
X        (p = header_field(n, "return-path")) ||
X        (p = header_field(n, "from"))))) {
X	skipspaces(0);
X	/* correct reply address is in "<correct-address>" */
X	if (p2 = index(p, '<')) {
X	    if (p = index(p2, '>'))
X		*p = 0;
X	    p = ++p2;
X	}
X    } else if (!p) {
XFrom:
X	/* if all else fails, then get the first token in "From" line */
X	if (fseek(tmpf, msg[n].m_offset, L_SET) == -1 ||
X		!(p2 = fgets(line, BUFSIZ, tmpf))) {
X	    error("fseek in %s (msg %d, folder=%s)", tempfile, n+1, mailfile);
X	    turnon(glob_flags, READ_ONLY);
X	    return "";
X	}
X	p = index(p2, ' ') + 1;
X    }
X    /* find the first space and plug a null */
X    if (p2 = any(p, " \t\n"))
X	*p2 = 0;
X    b += Strcpy(buf, p);
X
X    /*
X     * if `all' is true, append everyone on the "To:" line.
X     * cc_to(), called separately, will catch the cc's
X     */
X    if (all && (p = header_field(n, "to")) && *p)
X	(void) sprintf(b, " %s", p);
X    rm_cmts_in_addr(buf);
X    for (p = buf; isspace(*p); p++);
X    if (!*p)
X	(void) strcpy(buf, login);
X    return strcat(buf, " ");
X}
X
Xchar *
Xsubject_to(n, buf)
Xregister char *buf;
X{
X    register char *p;
X    buf[0] = 0; /* make sure it's already null terminated */
X    if (!(p = header_field(n, "subject")))
X	return NULL;
X    if (strncmp(p, "Re:", 3))
X	(void) strcpy(buf, "Re: ");
X    return strcat(buf, p);
X}
X
Xchar *
Xcc_to(n, buf)
Xregister char *buf;
X{
X    register char *p;
X    buf[0] = 0; /* make sure it's already null terminated */
X    if (!(p = header_field(n, "cc")))
X	return NULL;
X    rm_cmts_in_addr(p);
X    return strcpy(buf, p);
X}
X
X/*
X * fix addresses according to the sender's address.  If he's on a remote
X * machine, chances are that the addresses of everyone else he mailed to
X * are addresses from his machine.  Reconstruct those addresses to route
X * thru the senders machine first.
X */
Xfix_addresses(to, cc)
Xchar *to, *cc;
X{
X    int   to_argc, cc_argc, cnt;
X    char  **to_argv, **cc_argv, pre_path[128], *p, c;
X    char  **new_to, **new_cc, **calloc(), buf[256];
X
X    pre_path[0] = 0;
X    if (!(to_argv = mk_argv(to, &to_argc, 0)))
X	return;   /* what can we do?  Just return unchanged To and Cc lists */
X    cc_argv = mk_argv(cc, &cc_argc, 0);  /* the cc list may be empty */
X    if (cc_argc == 0 && to_argc == 1)
X	return;   /* there's only one reciepient, nothing to alter */
X
X    if (p = any(to_argv[0], "!=")) {
X	char *p2;
X	while (p2 = any(++p, "!="))
X	    p = p2;
X	c = *p, *p = 0;
X	(void) strcpy(pre_path, to_argv[0]);
X	*p = c;
X	for (cnt = 0; cnt < MAX_HOST_NAMES && ourname[cnt]; cnt++)
X	    if (!strcmp(pre_path, ourname[cnt])) {
X		*pre_path = 0;
X		break;
X	    }
X    }
X
X    if (!(new_to = calloc((unsigned)(to_argc+1), sizeof (char *))) ||
X	!(new_cc = calloc((unsigned)(cc_argc+1), sizeof (char *)))) {
X	error("malloc in fix_headers");
X	return;
X    }
X    /* this is the original sender */
X    strdup(new_to[0], to_argv[0]);
X
X    /* now modify the addresses to be routed thru the sender's adderess */
X    for (cnt = 1; cnt < to_argc; cnt++) {
X	if (p = index(to_argv[cnt], ','))
X	    *p = 0;
X	Debug("Changing \"%s\" to ", to_argv[cnt]);
X	(void) sprintf(buf, "%s%s", pre_path, to_argv[cnt]);
X	strdup(new_to[cnt], buf);
X	Debug("\"%s\"\n", new_to[cnt]);
X    }
X    for (cnt = 0; cnt < cc_argc; cnt++) {
X	Debug("Changing \"%s\" to ", cc_argv[cnt]);
X	if (p = index(cc_argv[cnt], ','))
X	    *p = 0;
X	(void) sprintf(buf, "%s%s", pre_path, cc_argv[cnt]);
X	strdup(new_cc[cnt], buf);
X	Debug("\"%s\"\n", new_cc[cnt]);
X    }
X    (void) argv_to_string(to, new_to);
X    (void) argv_to_string(cc, new_cc);
X    free_vec(to_argv);
X    free_vec(cc_argv);
X    free_vec(new_to);
X    free_vec(new_cc);
X}
X
X/*
X * pass a string describing header like, "Subject: ", current value, and
X * whether or not to prompt for it or to just post the information.
X * If do_prompt is true, "type in" the current value so user can either
X * modify it, erase it, or add to it.
X */
Xchar *
Xset_header(str, curstr, do_prompt)
Xregister char *str, *curstr;
X{
X    static char	   buf[BUFSIZ];
X    int 	   offset = 0;
X    register char  *p = curstr;
X
X    buf[0] = 0;
X    wprint(str);
X    fflush(stdout);		 /* force str curstr */
X    if (do_prompt) {
X	if (curstr)
X	    for (p = curstr; *p; p++)
X#ifdef SUNTOOL
X		if (istool)
X		    rite(*p); /* mimics typing for the tool */
X		else
X#endif /* SUNTOOL */
X		if (isoff(glob_flags, ECHO_FLAG))
X		    fputc((buf[offset++] = *p), stdout);
X		else
X#ifdef TIOCSTI
X		    if (ioctl(0, TIOCSTI, p) == -1) {
X			error("ioctl: TIOCSTI");
X			wprint("You must retype the entire line.\n%s", str);
X			break;
X		    }
X#else
X                {
X		    wprint("WARNING: -e flag! Type the line over.\n%s", str);
X		    break;
X		}
X#endif TIOCSTI
X
X	if (istool)
X	    return NULL;
X	if (Getstr(buf, BUFSIZ, offset) == -1)
X	    buf[0] = 0;
X    } else
X	puts(strcpy(buf, curstr));
X    if (debug > 1)
X	print("returning (%s) from set_header\n", buf);
X    return buf;
X}
X
X/*
X * rm_cmts_in_addr() removes the comment lines in addresses that result from
X * sendmail or other mailers which append the user's "real name" on the
X * from lines.  Comments are in parens.
X * `take_me_off' takes occurences of login out of a list of recipients
X * if the variable "metoo" is set.  Some say that "metoo" is supposed to
X * pass the -m flag along to sendmail, but not everyone runs sendmail :-)
X *
X * First expand a possible alias. Note that same string returns if not aliased.
X * strip off host from login name (considers user@host, host!user and so on)
X * if (user == ourlogin)
X *    match host with _this_ host, or
X *    match host with alternate hosts (alternate hostname, * matches all cases)
X *    if matched, then remove name from list.
X * ignore parenthesized names (those are comments ignored by "correct" mailers)
X */
Xrm_cmts_in_addr(p)
Xregister char *p;
X{
X    char buf[BUFSIZ], *start = p, *cmnt;
X    register char **argv;
X    int cnt, argc, x = 0, take_me_off = !do_set(set_options, "metoo");
X    int in_cmnt = FALSE, i;
X
X    if (!(argv = mk_argv(p, &argc, 0)))
X	return;
X    for (cnt = 0; cnt < argc; cnt = x+1) {
X	/* comments are in parens, as in: "argv (Dan Heller)" */
X	if ((cmnt = any(argv[cnt], "()")) || in_cmnt) {
X	    x++;
X	    if (cmnt && *cmnt != ')')
X		in_cmnt = TRUE;
X	    else if (cmnt && *cmnt == ')')
X		in_cmnt = FALSE; /* else, unchange cmnt flag */
X	    /* if the previous argument was deleted, then delete this one
X	     * example, we are "user" and our host is "host" take off:
X	     * list ... user@host (firstname lastname) more users...
X	     * "user@host" "(Firstname" "Last name)"
X	     */
X	    xfree(argv[cnt]), argv[cnt] = "";
X	    continue;
X	}
X	(void) strcpy(buf, argv[x = cnt]);
X	/* example: "Dan Heller <argv>" -- real address is in angle brackets
X	 * delete the angle brackets.  Potential bug: the name is still in
X	 * the address.. result might be: "Dan Heller argv"
X	 */
X	if (*buf == '<') {
X	    while (!(p = index(argv[x], '>')))
X		if (++x == argc)
X		    break;
X		else
X		    (void) strcat(buf, argv[x]);
X	    if (!p)  /* this one is in error, but parse the rest anyway */
X		continue;
X	    if (p = index(buf, '>'))
X		*p = 0; /* play with buf, not argv[]! */
X	}
X
X	/* if we're removing ourselves from the list, see if we're on it */
X	if (!take_me_off || !chk_two_lists(login, buf, "!@%="))
X	    continue;
X
X	/* we must be on the list -- see if the hostnames match alternates
X	 * first match our current host if a host was even given.
X	 * Bug: if a login name is a subset (or a complete) hostname, then
X	 * incorrect results may occur.
X	 */
X	if (any(buf, "!@%=")) {
X	    for (i = 0; i < MAX_HOST_NAMES && ourname[i]; i++)
X		if (chk_two_lists(buf, ourname[i], "!@%="))
X		    break;
X	    /* If the hostname in the address is one of our hostnames,
X	     * remove this address.  Else, see if the alternates hostnames
X	     * are in the address.
X	     */
X	    if ((i == MAX_HOST_NAMES || !ourname[i]) &&
X		(!(p = do_set(set_options, "alternates")) || *p != '*' &&
X		 !chk_two_lists(buf, p, "!@%= \t,")))
X		    continue;
X	}
X	/* all's well that ends well -- take us off the list */
X	xfree(argv[cnt]), argv[cnt] = "";
X    }
X    (void) argv_to_string(start, argv);
X    free_vec(argv);
X}
X
X/*
X * improve uucp paths by looking at the name of each host listed in the
X * path given.
X *    sun!island!pixar!island!argv
X * It's a legal address, but redundant. Also, if we know we talk to particular
X * hosts via uucp, then we can just start with that host and disregard the
X * rest of the line.  So, first get the known hosts and save them. Then start
X * at the end of the original path (at the last ! found), and move backwards
X * saving each hostname.  If we get to a host that we know about, stop there
X * and use that address.  If we get to a host we've already seen, then
X * delete it and all the hosts since then until the first occurance of that
X * hostname.  When we get to the beginning, the address will be complete.
X *
X * return all results into the original buffer passed to us.  Since we can
X * at worst not touch the path (shorten it if anything), we know we're not
X * going to overrun the buffer.
X */
X
X#define go_back_to_bang() for (--p; p > start && *p != '!'; p--)
X
Ximprove_uucp_paths(original)
Xregister char *original;
X{
X    char	   hostnames[32][64], buf[BUFSIZ], *knowns, *end;
X    register char *p, *recipient, *start = original, *b = buf, c;
X    int		   saved_hosts, i;
X
X    if (!original || !*original)
X	return;
X
X    knowns = do_set(set_options, "known_hosts");
X
X    while ((end = any(start, " \t,")) || *start) {
X	saved_hosts = 0;
X	if (!end)
X	    p = start + strlen(start);
X	else
X	    p = end; /* set p to the "end" cuz p moves. start will equal end */
X	c = *p, *p = 0; /* save the char we're nulling out (separating addrs) */
X	go_back_to_bang();
X	if (p == start)
X	    b += Strcpy(b, start), recipient = NULL;
X	else {
X	    recipient = p+1;
X	    while (p > start) {
X		/* null remainder of string to save the hostname */
X		*p = 0;
X		go_back_to_bang();
X		/* if p is not at the start, move it forward past the '!' */
X		if (p != start)
X		    ++p;
X#ifndef SYSV
X		/* next host on the list is ourselves, ignore preceding names */
X		for (i = 0; i < MAX_HOST_NAMES && ourname[i]; i++)
X		    if (!strcmp(p, ourname[i]))
X			saved_hosts = 0;
X#endif SYSV
X		for (i = 0; i < saved_hosts; i++)
X		    if (!strcmp(hostnames[i], p))
X		       saved_hosts = i;
X		(void) strcpy(hostnames[saved_hosts++], p);
X		if (saved_hosts == 32) {
X		    print("Too many hosts in uucp path! Address not fixed.\n");
X		    return; /* original buffer is unchanged */
X		}
X		/* If we know that we call this host, break */
X		if (p == start || knowns && chk_two_lists(p, knowns, " ,\t"))
X		    break;
X		--p; /* move p back onto the '!'; it != start */
X	    }
X	}
X	while (saved_hosts-- > 0)
X	    b += strlen(sprintf(b, "%s!", hostnames[saved_hosts]));
X	if (recipient) {
X	    /* if there were no saved_hosts, add a ! */
X	    if (*(b-1) != '!')
X		*b++ = '!';
X	    b += Strcpy(b, recipient);
X	}
X	*b++ = c;
X	if (!end)
X	    break;
X	start = end + 1;
X	if (isspace(*start)) {
X	    *b++ = ' ';
X	    while (isspace(*start))
X		start++;
X	}
X    }
X    *b = 0;
X    (void) strcpy(original, buf);
X}
END_OF_FILE
if test 23014 -ne `wc -c <'hdrs.c'`; then
    echo shar: \"'hdrs.c'\" unpacked with wrong size!
fi
# end of 'hdrs.c'
fi
if test -f 'tool_help' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'tool_help'\"
else
echo shar: Extracting \"'tool_help'\" \(23232 characters\)
sed "s/^X//" >'tool_help' <<'END_OF_FILE'
X@(#)tool_help	(c) copyright 10/18/86 (Dan Heller)
X
X%general%
X
X      IF ALL ELSE FAILS, READ THE DIRECTIONS!
X
XThis famous  quote applies here more  than ever. If
Xyou are unfamiliar with this mailtool, get yourself
Xacquainted with it by choosing  HELP options in all
Xmenu items. If you get frustrated or confused about
Xhow to use or run a command, or if you want to know
Xhow something  works or get to know quick shortcuts
Xin achieving tasks, it is  advisable to look at the
XHelp option available with the item.
X
XSince there  are many different  options to some of
Xthe commands in  mailtool, explanation  of  options
Xfor the commands can be found by choosing the RIGHT
Xmouse button over an item. This will display a menu
Xof options for the command. One of the menu options
Xwill almost always be a Help option.
X
XGive yourself a head start, try selecting this same
Xitem with the RIGHT mouse button.  When you do, you
Xwill given some more help topics to choose from.
X%%
X
X%help%
XHelp was designed for users to get  help from anywhere on  the mailtool
Xwindow.  The RIGHT mouse button may be selected on virtually every -
X on any of the windows on the entire tool and  a menu will appear.
XThe last item in almost  every menu  is a "help" item.  You will get an
Xappropriate help message describing what you can do at the position you
Xare in on the mailtool window.
X
XIf a help  message isn't much help, it may be more helpful to reference
Xa different help item which  describes in more detail  what you want to
Xknow.  For example, reading the help for  "folder" will help you better
Xunderstand  the method in  which mail messages are stored than it would
Xif you had read the help message for "save" first.
X%%
X
X%mouse%
XThe mouse is an image (cursor) which moves across the screen. Its
Xposition indicates which window is to receive input when you type
Xor click a mouse button.
X
XThe mouse may take upon  different images which  indicate various
Xthings. When the image looks like a "coffee cup",  Mushtool is in
Xthe process of doing something,  like sending mail, or reading in
Xnew mail.  In this event, you should wait till the cursor returns
Xto its normal state before attempting to do anything else. Go get
Xsome coffee.
X
XWhen the mouse looks like a pair of glasses, you are reading mail
Xand when it looks like a pencil, you  are editing a letter.  When
Xin the  Header Window, the cursor will look like the mouse device
Xthat you hold  with the buttons  flashing on and off.  This is to
Xremind  you that you  can use each button  to do different tasks.
X
XIn one window, the Main Panel Window, the cursor image looks like
Xan envelope.  Placing the cursor over "Panel Items" and selecting
Xthe LEFT button will do that command.  Selecting the RIGHT  mouse
Xbutton will give a menu of options to choose from. In most cases,
XHelp is  available and the end of each menu list to help you with
Xthe proper use of Panel Items.
X
XWhen you are asked a yes or no question, choosing either the LEFT
Xor RIGHT mouse buttons is the same as typing "y" or "n".
X%%
X
X%respond%
XThis item responds to mail in 4 ways.
XIn all cases, at least one recipient of your message will be the
Xsender of the message you are responding to. If a subject was in
Xthe author's letter, then it will be used as your subject.
X
XThe first and most used method of response is to the author of the
Xmessage only.  Selecting this item with the LEFT mouse button will
Xuse this method for responding to mail.
X
XIf you want to include a copy of the author's message, then choose
Xthe menu item which  says to include the message.  If you wish for
Xall the recipients of the message to receive a copy of your reply,
Xthen choosing the third item will include them.
X
XThe fourth menu item will mail to the author and everyone listed on
Xthe To and Cc lines of the message, and include the message you are
Xresponding to in your text.
X
XIn such cases where you include the message you are responding to,
Xthe included message will be indented by "> " to identify it from
Xyour message. If you would like to have a string other than the
Xdefault used, then set the appropriate option to whatever you would
Xprefer by selecting the "Opts" item, moving the mouse on top of the
Xstring, "indent-str", selecting the LEFT mouse button and typing the
Xdesired string.
X%%
X
X%menu_respond%
XWhen you respond to a message using the menu item, you respond to the author
Xof the message only. Since there are  more ways to respond to a message, you
Xmay want to choose the  Main Panel Window's Reply item. This item also gives
Xfar more extensive help than described here.
X%%
X
X%menu_delete%
XThis menu may delete or undelete
Xwhichever  message you happen to
Xhave the cursor sitting on.  For
Xdeleting messages  only, you can
Xsimply  select the  MIDDLE mouse
Xbutton  over the message  header
Xyou would like deleted.
X
XFor extensive information on -
X or undeletion of messages
Xtry the the  Main Panel Window's
Xitem for Delete.
X%%
X
X%delete%
XYou may  delete or undelete  messages with this item.
XWhen using the LEFT mouse button, you will delete the
Xcurrent message (HIGHLIGHTED in the headers' window).
XOtherwise, you may delete or undelete all messages by
Xselecting the appropriate menu item.
X
XYou may  delete or undelete a  "range" of messages by
Xtyping the range in the  Header Window  and selecting
Xthe appropriate menu item (delete/undelete range).
X
XFor help on valid  message ranges, select the menu in
Xthe area  marked "range" in the  Header Panel Window.
X%%
X
X%folder%
XThis item changes your "folder" -- which is  a place to keep all your
Xindividual messages. Usually, if you are a heavy mail user, you would
Xorganize your mail in such a way in which related mail would be saved
Xtogether in one folder.   You create folders simply by saving mail to
Xa filename.  Additional mail can  be saved to those files in the same
Xway.  To manipulate messages in folders,  you "change folders" to the
Xfolder you wish to access using the folder item.   Since it may occur
Xthat you switch  back and forth  between two folders, you may use the
Xprevious  folder menu item which updates changes  made to the current
Xfolder and  changes your  folder to the one previous to  the current.
X
XYou may also select  the exact name of the  folder you wish to access
Xby selecting  the left  mouse button on the "folder"  item and TYPING
Xthe exact  name of the folder  you wish to access.  The "pathname" to
Xthe folder may start with a tilde (~) indicating your home directory.
XOr, it may  contain a plus sign before the  name indicating your Mail
Xdirectory (+reports, for example).  Alternatively, you  can type  '%'
Xto access your system Mailbox, the place where all your mail is first
Xdelivered.  And finally, you can type '#' to indicate  the previously
Xaccessed folder.  See the help for "chdir" for more information.
X%%
X
X%chdir%
XThis is used to just change working directories.
XYour  working directory contains files and other
Xdirectories.  Files can be "mail folders"  which
Xcontain mail  messages.  You can change to other
Xdirectories using some of the following methods:
X
XYou can select from the menu, HOME or Mail, which
Xare your home and default mail directories. Or,
Xselect the left mouse button and TYPE in the name
Xof the directory you would like to change to.
X
XTyped names may have the following syntax:
X
X~[/subpath]   will change to your home directory and
X              a path below that, if specified. Also,
X              you can specify other users: ~username
X+[subpath]    This is your default Mail directory.
X%%
X
X%save%
XYou may save messages in  two ways. The most commonly used method is to
Xsave messages to  your mailbox folder  ("mbox") in your home directory.
XIf you use mail very frequently and save large amounts of mail, you can
Xsave messages to other folders for better organization.
X
XUsually, when messages are saved, mailtool  marks them for deletion for
Xthe next update.  If you don't want to have saved messages deleted, you
Xmust undelete them.
X
XThere is a text item  in the Main Panel Window which allows you to type
Xthe  name of the file to save a message.  Select the  LEFT mouse button
Xover the "Save" item, and type the filename and hit return. If there is
Xno filename specified, then messages are saved to your mbox file.
X
XYou can specify a range, or group of messages to save by typing a range
Xin the  Header Panel Window.
X
XFor additional information, see the help option for Folders.
X%%
X
X%quit%
XThere are various ways in which you may be finished with mailtool.
XThe most commonly used method  is to simply "close" the tool to an
Xiconic form. This means that you haven't really quit, but you have
Xmerely put it on "hold" till later.  It will become an icon on the
Xside or corner of the screen and appear to sit and do nothing.  To
Xclose the tool to icon form, there are two methods which have will
Xhave two different effects.
X
XThe first method is to select  this panel item with the left mouse
Xbutton.  This  will update your current  folder (deleting messages
Xmarked for deletion) and close the tool.  The second method  is to
Xuse the tool manager around the perimeter of the window and select
X"close".  This will close the tool without updating your mailfile.
X
XWhenever the mailtool is  in the "closed"  state, it  periodically
Xchecks your mail and updates your folder with the  new mail. While
Xmailtool is in iconic form, it will display the number of messages
Xyou have in the current folder.
X
XThere are two equally similar methods of exiting  mailtool, rather
Xthan just closing to an icon:  you may select the second menu item
Xin the menu given by this panel item or you may use the tool mana-
X "quit" item.
X
XUsing the tool manager's quit will exit the tool without updating
Xyour folder whereas the panel item's menu selection will have the
Xmailtool prompt you whether to update the current folder or not.
X%%
X
X%help_menu_help_msg%
XSelecting an item within this menu will
Xgive you help on that item. If you want
Xto execute the action, choose the other
Xmenu by placing the mouse over the menu
XBEHIND this menu, continue to keep your
XRIGHT mouse button depressed and select
Xthe LEFT mouse button  over the menu on
Xthe bottom and select that action.
X%%
X
X%msg_menu%
XWhen given menu in the Header Window, you will have a choice
Xof actions to take.  The message may not be the current one,
Xit may be  any message that  appears in  the Headers Window.
XThe "title" of the menu  will indicate which message you are
Xreferring to.
X
XAt this point, you can select actions to take. You can Read,
XDelete, Undelete, Save, Reply to, or Print messages. Most of
Xthese are self explanatory, but if you need help with one of
Xthese, place the  mouse over the menu BEHIND the given menu,
Xcontinue to have the RIGHT mouse button depressed and select
Xthe LEFT mouse button over the Help Menu.
X
XThis action toggles the menus such  that you can change back
Xand forth between these menus. The menu you are on will tell
Xwhich action to take on that message.  In  either case,  you
Xplace the mouse over the action to take, and,  if you are on
Xthe help menu, help will be given regarding that  particular
Xaction. If not in  the help menu,  then that specific action
Xwill actually be taken.
X%%
X
X%edit%
XChoosing this item with the LEFT mouse button in
Xthe Main Panel Window or in the Menu item will
Xallow you to access a full-screen editor. The
Xeditor which you will use is indicated when you
Xselect the "opts" item in the Main Panel Window.
X
XWhile you are typing a letter, you can specify
Xexplicitly which editor to use by typing (on a
Xline by itself) "~v editor". Type "~?" on a line
Xby itself while typing to see a list of valid
X"~commands".
X
XUpon exiting the editor, you can continue typing
Xand even reenter the editor if you like in the
Xsame manner.
X%%
X
X%update%
XThis item will update the current folder you are using.
XChanges are updated to the folder; that is, deleted mail
Xis removed and all other mail is copied back to the folder
Xunless otherwise specified. See the help in "folder" for
Xmore information on folders.
X
XIf new mail has arrived, it will incorporate it. Otherwise,
Xnew mail is incorporated every two minutes or so, if some
Xcomes in.
X%%
X
X%headers%
XThe message headers are displayed in their own separate window.
XThe "current" message is usually displayed in either BOLD or
XREVERSE text. This "highlighted" message is the one which is
Xdisplayed at the bottom, larger window. In the message window,
Xeach message is displayed in the following format:
Xthe message number is displayed first; if it is the "current"
Xmessage, then there is a '>' sign.
XThe next character is the 'status' character:
X    'N' -- New (and unread)
X    'U' -- not new, but still Unread
X    '*' -- delete messages (set show_deleted)
X    'P' -- preserve in spoolfile.
X    'O' -- Old message which has also been Read.
XIf there is just a space (no character), the message is new, but
Xyou've already read it. You should explicitly save or delete these.
X
XFollowing that is the Author of the message and/or all or part of
Xhis network address and login name.  Following that is the number
Xof lines the message is. In quotes is all or part of the "Subject"
X(if one was specified).
X
XTo read a message, select either the READ item in the main panel
Xsubwindow or move the mouse over the message header you want to read
Xand press the LEFT mouse button. Or, the MIDDLE mouse button will
Xdelete that message. Choosing the RIGHT mouse button will give you
Xa menu of things to do then. Included in the menu, is a help item
Xwhich describes the selections in the menu.
X%%
X
X%preserve%
XUsually, after you read mail and you "update" or quit  mailtool, unread
Xmessages are copied back into your system mailbox, deleted messages are
Xremoved, and messages which have been read but not deleted are saved in
Xyour "mbox" file.  Specifying "hold" prevents this from ever happening,
Xbut you can mark specific messages to be held in your system mailbox by
Xpreserving them.
X%%
X
X%compose%
XWhen you start to compose a letter for mailing,
Xyou will be prompted  for the login name(s), of
Xwhom  you want to mail, the (optional)  subject
Xof the message, and an  optional list of carbon
Xcopy recipients.  This is an additional list of
Xlogin names  who will be  mailed copies of your
Xmessage.
X
XAfter that, anything you type will be added to
Xyour  message.  If you select the  RIGHT mouse
Xbutton in the window in  which you are type to
Xget a menu of  things to do.  You may enter an
Xeditor if your message needs to be modified in
Xmore detail.
X
XWhen you're through with your message, you can
Xsend it by typing (on a line by itself) "." or
X^D.  Or, you can select  the Send item  in the
XMain Panel Window  and your mail will be sent.
XYou cannot send mail while still in an editor;
Xyou must exit the editor first.
X
XIf you have the option "autoedit" set, you are
Xautomatically put into an editor when you want
Xto compose or  whenever you reply to a letter.
XIn this case, whenever  you're through editing
Xthe letter, you will be put back into the main
Xediting mode  where you terminate and send the
Xletter using any of the above methods.
X%%
X
X%next%
XYou can page through all your messages by selecting  "Next" after reading
Xeach message. The same effect is gotten when you select the "Delete" item
Xwhen the option,  "autoprint" is set to be true  (see "opts") except that
Xthe current message is deleted before the next one is displayed. Deleting
Xmail which is  not important  helps the  efficiency of mailtool and reduces
Xunnecessary use of system resources.
X
XIn the Header Window, you will notice the cursor looks like the mouse you
Xuse.  The blinking buttons on the mouse image remind you that you can use
Xany of the  three buttons  at any  time.  When you  move the mouse over a
Xmessage and choose a button, the message under the  mouse is going to be
Xthe one affected.  Choosing left button will read the message, the middle
Xbutton will delete it, and the right button will give you a menu.
X%%
X
X%aliases%
XAliases are used as a method of mailing to users with long addresses using
Xshort names. For example, if you wanted to mail to
X    argv@spam.istc.sri.com
Xbut didn't want to type that all the time, then you could make an alias by
Xselecting the alias menu item that specifies "adding alias" and then TYPE:
X    Dan argv@spam.istc.sri.com
XIf you want to mail to a list of people and do so frequently enough to want
Xan alias name for the whole list, then  you would type something like this:
X    project-group fred mary bob@foo-bar herb sly@baz.bitnet
X
XTo mail to an "alias" you would compose a letter and address the letter:
X
XTo: Dan
XSubject: Alias example
XCc: project-group
X(rest of letter)
X%%
X
X%alts%
X"Alternates" are alternate names for YOU.  In messages you
Xreceive, your account will appear on the "To" or "Cc" list.
XWhen you REPLY to those messages, mailtool will construct
Xa message header for your letter which will contain the To
Xand Cc lists of recipients from the original message. You
Xwould probably want your name taken off the list so you do
Xnot mail yourself a copy of your own message. If you have
Xother account names or accounts on other machines, you can
Xlet mailtool know what those mail addresses are so they can
Xbe removed from the lists as well.
X
XNote, that if YOU add your name MANUALLY (type it yourself)
Xto either of the lists, it will not be removed.
X
XYou can set such a list in your .mailrc file in your home
Xdirectory by adding the line:
X
Xalts hostname1 hostname2 ...
X
XIf you prefer to not have your name removed from lists when
Xresponding to mail, set the option "metoo" and this prevents
Xthe need for alternates and your name will never be removed.
X%%
X
X%opts%
XTo set or unset options and their values, move the mouse over
Xthe option of your choice and select the LEFT button to toggle
Xtrue/false values. If an option requires a string value, you
Xmust type the value, so select the LEFT button to reference
Xthe option, and then type away.  Use a Carriage Return to enter
Xthe final value for the option.
X
XYou may select the RIGHT mouse button anywhere in the window
Xto give a menu which consists of saving options permanently,
Xreading in previous settings (from ~/.mailrc), and other things.
X%%
X
X%ignore%
XWhen reading mail, the message "headers" may clutter up the
Xwindow with information you are not interested in.  For
Xexample, you may not be interested in the "Received" or
X"Message-Id" field of the mail message. You would find that
Xin time, it will become annoying to see these uninteresting
Xmessage headers.
X
XYou can specify which message headers should not be shown,
Xthus shortening the appearance of the length of the message.
X
XTypical settings:
X    Received
X    Message-Id
X    Status
X%%
X
X%printer%
XThis item will send the current message, or the message specified on the
Xmenu header, to the printer. The printer used is given by the "printer"
Xoption (see opts in Main Panel Window). To specify a different printer,
Xchange the printer option by selecting the item "Opts" in the Main Panel
XWindow, moving the mouse over the Printer option, selecting the LEFT
Xmouse button and typing the name of the printer which you'd like to use.
X
XBe sure to set this option before printing because the DEFAULT option may
Xnot be what you want.
X
XYou can print messages that are NOT the current message by moving the
Xmouse into the Header Window and selecting the RIGHT mouse button on top
Xof the message you want to print and selecting the PRINT menu option.
X%%
X
X%windows%
X"Windows" are the boxes which contain items, text, or graphic
Ximages.  There are two "panel" windows. A panel window is one
Xwhich contains items,  which are the little boxes  with words
Xthat you can place the mouse over and click the left or mouse
Xbutton.
X
XEach  window has a separate  function for different purposes.
XStarting at the top of the main "tool" (contains all windows)
Xwe have the "header panel." Everything in this panel pertains
Xto the message headers, only.  The panel in the middle of the
Xtool is the "mail panel" which is more general and applies to
Xjust about everything. For a description of each of the items
Xwithin any panel, select the  "Help"  option  from  the  menu
Xyou get by selecting the RIGHT mouse button.
X%%
X
X%options%
XMove the cursor over the option you wish to change.
XThe LEFT mouse button turns toggles values off and on.
XThe MIDDLE mouse button displays the meaning of a
Xvariable. If the option needs typed input, use the LEFT
Xmouse button.  Sometimes value can be both toggle and
Xstring values so you may have to click the left button
Xmore than once to type.  When entering text values, you
Xmust use RETURN, so the value you typed will be associated
Xwith the option specified. Unsetting the option will -
Xassociate the a string value with that option.
X
XOnce values are disassociated with options, they can
Xonly be retrieved by either reentering their values or
Xby selecting the "restore options" item in the menu.
XDoing so will read in the last copy of the saved options
Xfrom your .mailrc file.
X
XSelecting the Save option in the menu will save the
Xcurrent settings in ~/.mailrc.  Selecting the quit
Xoption in the menu does NOT imply that values are
Xsaved permanently; changed values will remain through-
Xout the rest of the mail session.  To save options more
Xpermanently, select the save menu item.
X%%
X
X%function keys%
XSelecting the panel item "Opts" with the MENU button will give you
Xa choice of the type of options you can set. If you choose the one
Xthat says "function keys", then you can edit the commands that the
Xfunction keys on the keyboard may execute.  Once in this mode, you
Xwill find more extensive help.
X%%
X
X%fkeys%
XUsually the LAST function key in each set (top, left,
Xand right set of keys) will display the current settings
Xof all they keys.  The command which does this is 
X`key_settings X' where X is L, R, or T (left right top)
Xreferencing the associated function keys.  To set a function
Xkey to a specific command or set of commands, place the mouse
Xover the icon image of the key on the screen and click the
Xleft mouse button.  Type a command from the list of commands
Xat the bottom of the window and enter RETURN.
X
XMany commands take arguments or flags, so be sure to enter
Xthem here if you want those options. Clicking the middle button
Xwill display the current value for that key.  If you want to
Xset a key for multiple commands, separate the commands with
Xsemicolons:
X
XL9:  update ; close
X
XThis example would update your mailbox (committing changes)
Xand close the tool to an icon.
X%%
X
X%message range%
XYou can specify a large group of messages using a combination of special
Xsymbols in addition to numbers.  For example, if you wish to save all of
Xthe messages, then you can use `*' to represent them all. If you were to
Xtype the  "star" and select the Save  menu option for "save range", then
Xyou would save ALL the messages you have (including deleted ones).
X
XIf you would like to save messages 4 through 9, then you would specify:
X4-9
XIf you want to specify the messages between 2 and 32 except for messages
X6, 8 and message 12-14, you would type:
X2-32 {6,8,12-14}
XCommas or spaces can be used to separate numbers.
X
XNote that you cannot specify negated messages without first specifying
Xnormal messages; e.g. {2-5} 1-11   doesn't make sense.
X%%
END_OF_FILE
if test 23232 -ne `wc -c <'tool_help'`; then
    echo shar: \"'tool_help'\" unpacked with wrong size!
fi
# end of 'tool_help'
fi
echo shar: End of archive 8 \(of 12\).
cp /dev/null ark8isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 12 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