home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-05-06 | 54.4 KB | 1,900 lines |
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # If this archive is complete, you will see the following message at the end:
- # "End of archive 13 (of 19)."
- # Contents: mush/hdrs.c mush/setopts.c mush/tooledit.c
- # Wrapped by argv@turnpike on Wed May 2 13:59:40 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'mush/hdrs.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'mush/hdrs.c'\"
- else
- echo shar: Extracting \"'mush/hdrs.c'\" \(21753 characters\)
- sed "s/^X//" >'mush/hdrs.c' <<'END_OF_FILE'
- X/* hdrs.c (c) copyright 1986 (Dan Heller) */
- X
- X/*
- X * Routines that deal with message headers inside messages
- X * msg_get(n, from, count) -- get the From_ line in msg n into "from".
- X * header_field(n, str) -- get the header named "str" from msg n.
- X * do_hdrs(argc, argv, list) -- diplay message headers.
- X * specl_hdrs(argv, list) -- display msgs that share common attributes.
- X * compose_hdr(cnt) -- compose a message header from msg n.
- X * reply_to(n, all, buf) -- construct a header based on the To: header of n.
- X * subject_to(n, buf) -- get the subject for replying to msg n.
- X * cc_to(n, buf) -- construct a Cc header based on the Cc of message n.
- X */
- X#include "mush.h"
- X
- X#ifdef SUNTOOL
- X#define highlight(win,x,y,s) \
- X (void) (pw_text(win,x,y, PIX_SRC, mush_font, s), \
- X pw_text(win,x+1,y, \
- X (ison(glob_flags, REV_VIDEO))? PIX_NOT(PIX_SRC): PIX_SRC|PIX_DST, \
- X mush_font, s))
- X#endif /* SUNTOOL */
- X
- X/*
- X * Get a message from the current folder by its offset.
- X * Copy the From_ line to the second argument if the third arg > 0,
- X * and return the second argument, or NULL on an error.
- X */
- Xchar *
- Xmsg_get(n, from, count)
- Xint n, count;
- Xchar *from;
- X{
- X if (fseek(tmpf, msg[n].m_offset, L_SET) == -1) {
- X error("fseek in %s (msg %d, folder=%s)", tempfile, n+1, mailfile);
- X turnon(glob_flags, READ_ONLY);
- X return NULL;
- X }
- X if (count)
- X#ifndef MSG_SEPARATOR
- X return fgets(from, count, tmpf);
- X#else
- X *from = '\0';
- X#endif
- X return from;
- X}
- 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[HDRSIZ];
- X char tmp[HDRSIZ];
- 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 /* use msg_get as a test for fseek() -- don't let it fgets() (pass 0) */
- X if (!msg_get(n, tmp, 0))
- X return NULL;
- X *b = 0;
- X while((p = fgets(tmp, sizeof(tmp), tmpf)) && *p != '\n') {
- X if (*p != ' ' && *p != '\t') {
- X contd_hdr = 0;
- X /* strcmp ignoring case */
- X for(p2 = str; *p && *p2 && lower(*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 if (b > buf && (b - buf) < sizeof buf - 2)
- X *b++ = ',';
- X } else if (!contd_hdr)
- X continue;
- X skipspaces(0);
- X (void) no_newln(p);
- X if (strlen(p) + (b - buf) < sizeof buf - 1) {
- X if (b > buf)
- X *b++ = ' ';
- X b += Strcpy(b, p);
- X }
- X }
- X if (*--b == ',')
- 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;
- X SIGRET (*oldint)(), (*oldquit)();
- X int show_deleted, srch = 1; /* search forward by default */
- X static int cnt, oldscrn = 1;
- X register char *p;
- X char first_char = (argc) ? **argv: 'h';
- X
- X if (argc > 1 && !strcmp(argv[1], "-?"))
- X return help(0, "headers", cmd_help);
- X
- X if (!msg_cnt) {
- X if (ison(glob_flags, DO_PIPE))
- X return 0;
- 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 } else if (argc > 1 && !strncmp(argv[1], "-H:", 3)) {
- X argv[1][0] = ':';
- X argv[1][1] = argv[1][3];
- X argv[1][2] = 0;
- X return specl_hdrs(&argv[1], list);
- X }
- X
- X on_intr();
- X
- X if (argc && (argv[0][1] == '-' || argc > 1 && !strcmp(argv[1], "-"))) {
- X cnt = max(n_array[0], 0);
- X srch = -1; /* search backwards */
- X } else if (argc && (argv[0][1] == '+' ||
- X 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 &&
- X (isdigit(**argv) || **argv == '^' ||
- X **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 int fnd;
- 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 ;
- X } else if (current_msg < n_array[0] || current_msg > n_array[oldscrn-1] ||
- X (iscurses || oldscrn != screen) &&
- X (cnt > current_msg + screen || cnt < current_msg - screen))
- X cnt = current_msg; /* adjust if reads have passed screen bounds */
- X else if (cnt >= msg_cnt || !argc || !*argv)
- X /* adjust window to maintain position */
- X cnt = (n_array[0] > msg_cnt) ? current_msg : n_array[0];
- X
- X oldscrn = screen;
- X show_deleted = !!do_set(set_options, "show_deleted");
- X
- X /* Make sure we have at least $screen headers to print */
- X if (cnt > 0 && !iscurses && first_char == 'h') {
- X int top, bot = cnt;
- X /* first count how many messages we can print without adjusting */
- X for (pageful = 0; pageful<screen && bot<msg_cnt && bot; bot += srch)
- X if (show_deleted || isoff(msg[bot].m_flags, DELETE))
- X pageful++;
- X /* if we can't print a pagefull of hdrs, back up till we can */
- X for (top = cnt-srch; pageful<screen && top && top<msg_cnt; top -= srch)
- X if (show_deleted || isoff(msg[top].m_flags, DELETE))
- X pageful++;
- X if (srch < 0)
- X cnt = bot; /* the search was upside down */
- X else
- X cnt = top + (pageful == screen);
- X pageful = 0; /* Used later as an index, so reset */
- X } else if (cnt > 0 && srch < 0)
- X cnt = max(cnt - screen, 0);
- X else
- X cnt = max(cnt, 0);
- 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(), p);
- X else
- X (void) pw_text(hdr_win, 0, pageful * l_height(), PIX_SRC,
- X mush_font, p);
- X Clrtoeol(hdr_win, strlen(p)*l_width(), pageful*l_height());
- X }
- X#endif /* SUNTOOL */
- X
- X#ifdef CURSES
- X else if (iscurses) {
- X move(pageful, 0);
- X printw("%-.*s", COLS-2, p), clrtoeol();
- X }
- 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());
- X#endif /* SUNTOOL */
- X ++pageful;
- X }
- X }
- X#ifdef SUNTOOL
- X if (istool) {
- X Scrollbar sb = (Scrollbar) window_get(hdr_sw, WIN_VERTICAL_SCROLLBAR);
- X
- X if (show_deleted) {
- X scrollbar_set(sb,
- X SCROLL_OBJECT_LENGTH, msg_cnt,
- X SCROLL_VIEW_START, n_array[0],
- X 0);
- X } else {
- X int i, not_deleted, start;
- X
- X for (i = start = 0; i < n_array[0]; i++)
- X if (!ison(msg[i].m_flags, DELETE))
- X start++;
- X for (not_deleted = start; i < msg_cnt; i++)
- X if (!ison(msg[i].m_flags, DELETE))
- X not_deleted++;
- X scrollbar_set(sb,
- X SCROLL_OBJECT_LENGTH, not_deleted,
- X SCROLL_VIEW_START, start,
- X 0);
- X }
- X
- X scrollbar_paint(sb);
- X mail_status(0);
- X }
- X#endif /* SUNTOOL */
- X
- 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 when 'r': special = REPLIED;
- X when 's': special = SAVED;
- X when 'p': special = PRESERVE;
- X otherwise: print("choose from n,u,o,d,r,s,p 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 } 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 } else {
- X if (list)
- X unset_msg_bit(list, n);
- X if (debug) {
- X (void) printf("msg[%d].m_flags: %d", n, msg[n].m_flags);
- X (void) check_flags(msg[n].m_flags);
- X }
- X }
- X }
- X return 0;
- X}
- X
- X#define Strncpy(buf,p) (void)(strncpy(buf,p,sizeof(buf)),buf[sizeof(buf)-1]=0)
- X
- X/*
- X * format a header from the information about a message (from, to, date,
- X * subject, etc..). The header for message number "cnt" is built and is
- X * returned in the static buffer "buf". There will be *at least* 9 chars
- X * in the buffer which will be something like: " 123 >N " The breakdown
- X * is as follows: 4 chars for the message number, 1 space, 1 char for '>'
- X * (if current message) and two spaces for message status (new, unread, etc)
- X * followed by 1 terminating space.
- X * Read other comments in the routine for more info.
- X */
- Xchar *
- Xformat_hdr(cnt, hdr_fmt, show_to)
- Xint cnt, show_to;
- Xchar *hdr_fmt;
- X{
- X static char buf[256];
- X register char *p, *p2, *b;
- X int len, do_pad = FALSE, val, pad, got_dot, isauthor = 0, n;
- X char from[HDRSIZ], subject[256], date[64], lines[16];
- X char to[256], addr[256], name[256], status[4];
- X char Day[3], Mon[4], Tm[8], Yr[5], Wkday[4], Zone[8], *date_p;
- X
- X /* status of the message */
- X if (ison(msg[cnt].m_flags, DELETE))
- X status[0] = '*';
- X else if (ison(msg[cnt].m_flags, PRESERVE))
- X status[0] = 'P';
- X else if (ison(msg[cnt].m_flags, SAVED))
- X status[0] = 'S';
- X else if (ison(msg[cnt].m_flags, OLD) && ison(msg[cnt].m_flags, UNREAD))
- X status[0] = 'U';
- X else if (ison(msg[cnt].m_flags, PRINTED))
- X status[0] = 'p';
- X else if (ison(msg[cnt].m_flags, FORWARD))
- X status[0] = 'f';
- X else if (isoff(msg[cnt].m_flags, UNREAD))
- X status[0] = ' ';
- X else
- X status[0] = 'N';
- X
- X if (ison(msg[cnt].m_flags, REPLIED))
- X status[1] = 'r';
- X else
- X status[1] = ' ';
- X
- X to[0] = from[0] = subject[0] = date[0] = lines[0] = addr[0] =
- X name[0] = Day[0] = Mon[0] = Tm[0] = Yr[0] = Wkday[0] = 0;
- X
- X /* who's the message to */
- X if ((p = header_field(cnt, "resent-to")) ||
- X (p = header_field(cnt, "to")) ||
- X (p = header_field(cnt, "apparently-to")))
- X Strncpy(to, p);
- X
- X /* who's the message from */
- X if ((p = header_field(cnt, "from")) && strcpy(from, p)
- X || (p = reply_to(cnt, 0, from))) {
- X /* NOTE: this fails if the sender has '<' or '!' in
- X * the RFC822 comment fields -- leading "comment"
- X * or trailing (comment) -- but that isn't critical
- X */
- X if ((p2 = rindex(p, '!')) || (p2 = index(p, '<')))
- X p = p2 + 1;
- X } else
- X p = strcpy(from, "unknown"); /* just in case */
- X /* If the From field contains the user's login name, then the message
- X * could be from the user -- attempt to give more useful information
- X * by telling to whom the message was sent. This is not possible if
- X * the "to" header failed to get info (which is probably impossible).
- X * Use take_me_off() to be sure the message really is from the current
- X * user and not just someone with the same login at another site.
- X */
- X if (show_to && !strncmp(p, login, strlen(login)))
- X (void) take_me_off(from);
- X if (show_to && (isauthor = !*from)) { /* assign and test */
- X (void) get_name_n_addr(to, name+4, addr+4);
- X if (addr[4])
- X (void) strncpy(addr, "TO: ", 4);
- X if (name[4]) { /* check to see if a name got added */
- X (void) strncpy(name, "TO: ", 4);
- X Strncpy(from, name);
- X } else
- X Strncpy(from, addr);
- X } else
- X (void) get_name_n_addr(from, name, addr);
- X
- X if (ison(glob_flags, DATE_RECV))
- X date_p = msg[cnt].m_date_recv;
- X else
- X date_p = msg[cnt].m_date_sent;
- X (void) date_to_string(date_p, Yr, Mon, Day, Wkday, Tm, Zone, date);
- X
- X /* and the subject */
- X if (p = header_field(cnt, "subject"))
- X Strncpy(subject, p);
- X
- X /* now, construct a header out of a format string */
- X if (!hdr_fmt)
- X hdr_fmt = hdr_format;
- X
- X (void) sprintf(buf, "%4.d ", cnt+1);
- X b = buf+5;
- X *b++ = ((cnt == current_msg && !iscurses)? '>': ' ');
- X *b++ = status[0], *b++ = status[1];
- X *b++ = ' ';
- X /* Count chars since beginning of buf. Initialize to 9 (strlen(buf) so far)
- X * This magic number is used in other places in msgs.c and mail.c
- X */
- X n = 9;
- X for (p = hdr_fmt; *p; p++)
- X if (*p == '\\')
- X switch (*++p) {
- X case 't':
- X while (n % 8)
- X n++, *b++ = ' ';
- X when 'n':
- X n = 1, *b++ = '\n';
- X otherwise: n++, *b++ = *p;
- X }
- X else if (*p == '%') {
- X char fmt[64];
- X
- X p2 = fmt;
- X /* first check for string padding: %5n, %.4a, %10.5f, %-.3l etc. */
- X do_pad = pad = val = got_dot = 0;
- X *p2++ = '%';
- X if (p[1] != '-')
- X *p2++ = '-';
- X else
- X ++p;
- X while (isdigit(*++p) || !got_dot && *p == '.') {
- X if (*p == '.')
- X got_dot = TRUE, val = pad, pad = 0;
- X else
- X pad = pad * 10 + *p - '0';
- X *p2++ = *p;
- X }
- X if (!got_dot && isdigit(p[-1])) {
- X *p2 = 0; /* assure null termination */
- X val = atoi(fmt+1);
- X if (val < 0)
- X val = -val;
- X p2 += strlen(sprintf(p2, ".%d", val));
- X }
- X pad = min(pad, val);
- X *p2++ = 's', *p2 = 0;
- X if (!*p)
- X break;
- X switch (*p) {
- X case 'f': p2 = from, do_pad = TRUE;
- X when 'a':
- X if (!*(p2 = addr))
- X p2 = from;
- X do_pad = TRUE;
- X when 'n':
- X if (!*(p2 = name))
- X p2 = from, do_pad = TRUE;
- X when '%': p2 = "%";
- X when 't': p2 = to;
- X when 's': p2 = subject;
- X when 'l': p2 = sprintf(lines, "%d", msg[cnt].m_lines);
- X when 'c': p2 = sprintf(lines, "%ld", msg[cnt].m_size);
- X when 'i': (p2 = header_field(cnt, "message-id")) || (p2 = "");
- X /* date formatting chars */
- X when 'd': p2 = date; /* the full date */
- X when 'T': p2 = Tm;
- X when 'M': p2 = Mon;
- X when 'Y': p2 = Yr;
- X when 'y': p2 = Yr+2;
- X when 'N': p2 = Day;
- X when 'D': case 'W': p2 = Wkday;
- X when 'Z': p2 = Zone;
- X /* Any selected header */
- X when '?': {
- X p2 = p + 1;
- X p = index(p2, '?');
- X if (p) {
- X *p = 0;
- X if (!(p2 = header_field(cnt, p2)))
- X p2 = "";
- X *p = '?';
- X } else {
- X p = p2 + (strlen(p2) - 1);
- X if (!(p2 = header_field(cnt, p2)))
- X p2 = "";
- X }
- X }
- X otherwise: continue; /* unknown formatting char */
- X }
- X if (do_pad && pad && strlen(p2) > pad) {
- X char *old_p2 = p2, *p3;
- X /* if addr is too long, move pointer forward till the
- X * "important" part is readable only for ! paths/addresses.
- X */
- X while (p3 = index(p2, '!')) {
- X int tmp = strlen(p3+1); /* xenix has compiler problems */
- X p2 = p3+1;
- X if (tmp + isauthor*4 < pad) {
- X if (isauthor && (p2 -= 4) < old_p2)
- X p2 = old_p2;
- X break;
- X }
- X }
- X if (isauthor && p2 > old_p2+4 && !p3 && strlen(p2) + 4 > pad)
- X p2 -= 4;
- X if (old_p2 != p2 && isauthor)
- X (void) strncpy(p2, "TO: ", 4); /* doesn't null terminate */
- X }
- X len = strlen(sprintf(b, fmt, p2));
- X n += len, b += len;
- X /* Get around a bug in 5.5 IBM RT which pads with NULs not ' ' */
- X while (n && !*(b-1))
- X b--, n--;
- X } else
- X n++, *b++ = *p;
- X for (*b-- = 0; isspace(*b) && *b != '\n'; --b)
- X *b = 0;
- X return buf;
- X}
- X
- Xchar *
- Xcompose_hdr(cnt)
- Xint cnt;
- X{
- X if (!hdr_format)
- X hdr_format = DEF_HDR_FMT;
- X return format_hdr(cnt, hdr_format, TRUE);
- 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 * route_addresses() is called 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 end w/blank.
- X */
- Xchar *
- Xreply_to(n, all, buf)
- Xchar buf[];
- X{
- X register char *p = NULL, *p2, *b = buf, *field;
- X char line[256], name[256], addr[256], *unscramble_addr();
- X
- X if (field = do_set(set_options, "reply_to_hdr")) {
- X#ifndef MSG_SEPARATOR
- X if (!*field)
- X goto DoFrom; /* special case -- get the colon-less From line */
- X#endif /* MSG_SEPARATOR */
- X field = lcase_strcpy(line, field);
- X while (*field) {
- X if (p2 = any(field, " \t,:"))
- X *p2 = 0;
- X#ifndef MSG_SEPARATOR
- X if (!lcase_strncmp(field, "from_", -1))
- X goto DoFrom;
- X#endif /* MSG_SEPARATOR */
- 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, field = "reply-to")) ||
- X (p = header_field(n, field = "from")) ||
- X (p = header_field(n, field = "return-path")))))
- X skipspaces(0);
- X else if (!p) {
- X#ifndef MSG_SEPARATOR
- XDoFrom:
- X field = "from_";
- X /* if all else fails, then get the first token in "From" line */
- X if (p2 = msg_get(n, line, sizeof line))
- X p = index(p2, ' ');
- X else
- X return "";
- X skipspaces(1);
- X if (p2 = index(p, ' '))
- X *p2 = 0;
- X (void) unscramble_addr(p, line); /* p is safely recopied to line */
- X p = line;
- X#else /* MSG_SEPARATOR */
- X wprint("Warning: unable to find who msg %d is from!\n", n+1);
- X#endif /* MSG_SEPARATOR */
- X }
- X (void) get_name_n_addr(p, name, addr);
- X if (!name[0] && (!lcase_strncmp(field, "return-path", -1) ||
- X !lcase_strncmp(field, "from_", -1))) {
- X /*
- X * Get the name of the author of the message we're replying to from the
- X * From: header since that header contains the author's name. Only do
- X * this if the address was gotten from the return-path or from_ lines
- X * because this is the only way to guarantee that the return address
- X * matches the author's name. Reply-To: may not be the same person!
- X * Check Resent-From: if the address came from the from_ line, else
- X * check From:, and finally Sender: or Name:.
- X */
- X if (!lcase_strncmp(field, "from_", -1) &&
- X (p = header_field(n, "resent-from")) ||
- X (p = header_field(n, "from")) ||
- X (p = header_field(n, "sender")))
- X (void) get_name_n_addr(p, name, NULL);
- X if (!name[0] && (p = header_field(n, "name")))
- X (void) strcpy(name, p);
- X if (name[0]) {
- X if ((p = any(name, "(<,\"")) && (*p == ',' || *p == '<'))
- X *b++ = '"';
- X b += Strcpy(b, name);
- X if (p && (*p == ',' || *p == '<'))
- X *b++ = '"';
- X *b++ = ' ', *b++ = '<';
- X }
- X b += Strcpy(b, addr);
- X if (name[0])
- X *b++ = '>', *b = 0;
- X } else
- X b += Strcpy(buf, p);
- X
- X /*
- X * if `all' is true, append everyone on the "To:" line(s).
- X * cc_to(), called separately, will catch the cc's
- X */
- X if (all) {
- X int lim = HDRSIZ - (b - buf) - 2;
- X /* Check for overflow on each copy.
- X * The assumption that HDRSIZ is correct is unwise, but I know it
- X * to be true for Mush. Be forewarned if you call this routine.
- X */
- X if (lim > 0 && (p = header_field(n, "resent-to")) && *p) {
- X *b++ = ',', *b++ = ' ';
- X p[lim] = '\0'; /* prevent overflow */
- X b += Strcpy(b, p);
- X lim = HDRSIZ - (b - buf) - 2;
- X }
- X if (lim > 0 && (p = header_field(n, "to")) && *p) {
- X *b++ = ',', *b++ = ' ';
- X p[lim] = '\0'; /* prevent overflow */
- X b += Strcpy(b, p);
- X lim = HDRSIZ - (b - buf) - 2;
- X }
- X if (lim > 0 && (p = header_field(n, "apparently-to")) && *p) {
- X *b++ = ',', *b++ = ' ';
- X p[lim] = '\0'; /* prevent overflow */
- X b += Strcpy(b, p);
- X lim = HDRSIZ - (b - buf) - 2;
- X }
- X /* Also append the Resent-From address if there is one. */
- X if (lim > 0 && (p = header_field(n, "resent-from")) && *p) {
- X *b++ = ',', *b++ = ' ';
- X p[lim] = '\0'; /* prevent overflow */
- X (void) strcpy(b, p);
- X }
- X }
- X fix_up_addr(buf);
- X /* p2 used to save boolean value of $metoo */
- X if (!(p2 = do_set(set_options, "metoo"))) {
- X /* Save the original name/addr in case it is the only one */
- X (void) get_name_n_addr(buf, name, addr);
- X take_me_off(buf);
- X }
- X for (p = buf; *p == ',' || isspace(*p); p++)
- X ;
- X if (!*p)
- X if (p2) /* take_me_off() was not done */
- X (void) strcpy(buf, login);
- X else
- X (void) sprintf(buf, "%s <%s>", name, addr);
- X return 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 (lcase_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 fix_up_addr(p);
- X if (!do_set(set_options, "metoo"))
- X take_me_off(p);
- X return strcpy(buf, p);
- X}
- END_OF_FILE
- if test 21753 -ne `wc -c <'mush/hdrs.c'`; then
- echo shar: \"'mush/hdrs.c'\" unpacked with wrong size!
- fi
- # end of 'mush/hdrs.c'
- fi
- if test -f 'mush/setopts.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'mush/setopts.c'\"
- else
- echo shar: Extracting \"'mush/setopts.c'\" \(20739 characters\)
- sed "s/^X//" >'mush/setopts.c' <<'END_OF_FILE'
- X/* setopts.c (c) copyright 1986 (Dan Heller) */
- X
- X#include "mush.h"
- X#include "bindings.h"
- X
- Xstatic void
- Xinsert_option(list, opt, order)
- Xstruct options **list, *opt;
- Xint order; /* Insert in sorted order? */
- X{
- X while (*list && (!order || (strcmp((*list)->option, opt->option) < 1)))
- X list = &((*list)->next);
- X opt->next = *list;
- X *list = opt;
- X}
- X
- X/* add an option indicated by "set option[=value]" or by "alias name alias"
- X * function is recursive, so multilists get appended accordingly
- X */
- Xadd_option(list, argv)
- Xregister struct options **list;
- Xregister char **argv;
- X{
- X register struct options *tmp;
- X register char *option, *value = NULL;
- X
- X if (!(option = *argv))
- X return 1;
- X /* check for one of three forms:
- X * option=value option= value option = value
- X */
- X if (value = index(option, '=')) {
- X if (value == option) {
- X print("No variable specified\n");
- X return 0;
- X }
- X /* "option=value" strip into option="option" value="value" */
- X *value++ = 0; /* option is now a null terminated `option' */
- X if (*value || (value = *++argv)) { /* "option= value" */
- X ++argv;
- X }
- X } else if (*++argv && !strcmp(*argv, "=")) {
- X if (value = *++argv) /* "option = value" */
- X ++argv;
- X }
- X
- X /* check for internal vars that can't be set this way */
- X if (*list == set_options && check_internal(option)) {
- X print("You can't change %s with \"set\".\n", option);
- X return 0;
- X }
- X
- X /* check to see if option is already set by attempting to unset it */
- X if (un_set(list, option) == -1)
- X return 0;
- X
- X /* now make a new option struct and set fields */
- X if (!(tmp = (struct options *)calloc((unsigned)1,sizeof(struct options)))) {
- X error("calloc");
- X return -1;
- X }
- X tmp->option = savestr(option);
- X tmp->value = savestr(value); /* strdup handles the NULL case */
- X
- X insert_option(list, tmp, (list != &own_hdrs));
- X
- X /* check for options which must have values or are used frequently */
- X if (*list == set_options) {
- X#if defined(CURSES) || defined(SUNTOOL)
- X if (!strcmp(tmp->option, "no_reverse"))
- X turnoff(glob_flags, REV_VIDEO);
- X else
- X#endif /* CURSES || SUNTOOL */
- X#ifdef SUNTOOL
- X if (!strcmp(tmp->option, "tool_help"))
- X if (tmp->value && *(tmp->value))
- X strdup(tool_help, tmp->value);
- X else {
- X int n = 0;
- X char *p = getpath(TOOL_HELP, &n);
- X if (n)
- X strdup(tool_help, "tool_help");
- X else
- X strdup(tool_help, p);
- X strdup(tmp->value, tool_help);
- X }
- X else
- X#endif /* SUNTOOL */
- X if (!strcmp(tmp->option, "cmd_help"))
- X if (tmp->value && *(tmp->value))
- X strdup(cmd_help, tmp->value);
- X else {
- X int n = 0; /* don't ignore no such file or directory */
- X char *p = getpath(COMMAND_HELP, &n);
- X if (n)
- X strdup(cmd_help, "cmd_help");
- X else
- X strdup(cmd_help, p);
- X strdup(tmp->value, cmd_help);
- X }
- X else if (!strcmp(tmp->option, "prompt"))
- X prompt = (tmp->value)? tmp->value : DEF_PROMPT;
- X else if (!strcmp(tmp->option, "warning"))
- X turnon(glob_flags, WARNING);
- X else if (!strcmp(tmp->option, "mil_time"))
- X turnon(glob_flags, MIL_TIME);
- X#ifndef MSG_SEPARATOR
- X else if (!strcmp(tmp->option, "date_received"))
- X turnon(glob_flags, DATE_RECV);
- X#endif /* MSG_SEPARATOR */
- X else if (!strcmp(tmp->option, "escape"))
- X escape = (tmp->value)? tmp->value : DEF_ESCAPE;
- X else if (!strcmp(tmp->option, "hdr_format"))
- X hdr_format = (tmp->value)? tmp->value : DEF_HDR_FMT;
- X else if (!strcmp(tmp->option, "crt")) {
- X if (!istool)
- X crt = (tmp->value)? max(atoi(tmp->value), 2): 18;
- X }
- X else if (!strcmp(tmp->option, "screen")) {
- X screen = (tmp->value)? max(atoi(tmp->value), 1): 18;
- X#ifdef CURSES
- X if (iscurses && screen > LINES-2)
- X screen = LINES-2;
- X#endif /* CURSES */
- X } else if (!strcmp(tmp->option, "wrapcolumn")) {
- X char wval[16];
- X wrapcolumn =
- X (tmp->value && *(tmp->value))? max(atoi(tmp->value), 0): 78;
- X#ifdef CURSES
- X /* Use COLS-2 because of silly terminals like vt100 */
- X if (iscurses && wrapcolumn > COLS - 2)
- X wrapcolumn = COLS - 2;
- X#endif /* CURSES */
- X xfree(tmp->value);
- X tmp->value = savestr(sprintf(wval, "%d", wrapcolumn));
- X } else if (!strcmp(tmp->option, "history"))
- X init_history((value && *value)? atoi(value) : 1);
- X else if (!strcmp(tmp->option, "realname")) {
- X char *new[4];
- X new[1] = "NAME";
- X new[2] = tmp->value;
- X new[3] = NULL;
- X (void) Setenv(3, new); /* new[0] is ignored */
- X } else if (!strcmp(tmp->option, "known_hosts")) {
- X register char *p;
- X int n;
- X /* in case user separated with commas */
- X for (p = index(tmp->value, ','); p; p = index(p+1, ','))
- X *p = ' ';
- X free_vec(known_hosts);
- X known_hosts = mk_argv(tmp->value, &n, FALSE);
- X } else if (!strcmp(tmp->option, "hostname")) {
- X register char *p;
- X int n;
- X /* in case user separated with commas */
- X for (p = index(tmp->value, ','); p; p = index(p+1, ','))
- X *p = ' ';
- X free_vec(ourname);
- X ourname = mk_argv(tmp->value, &n, FALSE);
- X } else if (!strcmp(tmp->option, "complete")) {
- X if (value && *value) {
- X m_xlate(value); /* use the original, don't change tmp->value */
- X complete = value[0];
- X complist = value[1];
- X } else {
- X tmp->value = savestr("\\E\\CD");
- X complete = '\033';
- X complist = '\004';
- X }
- X }
- X }
- X
- X if (*argv)
- X return add_option(list, argv);
- X return 1;
- X}
- X
- X/*
- X * If str is NULL, just print options and their values. Note that numerical
- X * values are not converted to int upon return. If str is not NULL
- X * return the string that matched, else return NULL;
- X */
- Xchar *
- Xdo_set(list, str)
- Xregister struct options *list;
- Xregister char *str;
- X{
- X register struct options *opts;
- X
- X if (!str)
- X (void) do_pager(NULL, TRUE); /* page using internal pager */
- X
- X for (opts = list; opts; opts = opts->next)
- X if (!str) {
- X (void) do_pager(opts->option, FALSE);
- X if (opts->value && *opts->value) {
- X (void) do_pager(" \t", FALSE);
- X (void) do_pager(opts->value, FALSE);
- X }
- X if (do_pager("\n", FALSE) == EOF)
- X break;
- X } else {
- X if (strcmp(str, opts->option))
- X continue;
- X if (opts->value)
- X return opts->value;
- X else
- X return "";
- X }
- X
- X if (!str)
- X (void) do_pager(NULL, FALSE); /* terminate internal pager */
- X
- X /* if we still haven't matched, check for environment vars */
- X if (str && list == set_options) {
- X register int N, n;
- X for (N = 0; environ[N]; N++) {
- X char *p = index(environ[N], '=');
- X if (p)
- X *p = 0;
- X n = lcase_strncmp(str, environ[N], -1);
- X if (p)
- X *p = '=';
- X if (!n)
- X return p+1;
- X }
- X }
- X return NULL;
- X}
- X
- X/*
- X * unset the variable described by p in the list "list".
- X * if the variable isn't set, then return 0, else return 1.
- X */
- Xun_set(list, p)
- Xregister struct options **list;
- Xregister char *p;
- X{
- X register struct options *opts = *list, *tmp;
- X
- X if (!list || !*list || !p || !*p)
- X return 0;
- X if (*list == set_options) {
- X#if defined(CURSES) || defined(SUNTOOL)
- X if (!strcmp(p, "no_reverse"))
- X turnon(glob_flags, REV_VIDEO);
- X else
- X#endif /* CURSES || SUNTOOL */
- X if (!strcmp(p, "prompt"))
- X prompt = DEF_PROMPT;
- X else if (!strcmp(p, "warning"))
- X turnoff(glob_flags, WARNING);
- X else if (!strcmp(p, "mil_time"))
- X turnoff(glob_flags, MIL_TIME);
- X#ifndef MSG_SEPARATOR
- X else if (!strcmp(p, "date_received"))
- X turnoff(glob_flags, DATE_RECV);
- X#endif /* MSG_SEPARATOR */
- X else if (!strcmp(p, "escape"))
- X escape = DEF_ESCAPE;
- X else if (!strcmp(p, "hdr_format"))
- X hdr_format = DEF_HDR_FMT;
- X else if (!strcmp(p, "crt"))
- X crt = 18;
- X else if (!strcmp(p, "screen")) {
- X screen = 18;
- X#ifdef CURSES
- X if (iscurses && screen > LINES-2)
- X screen = LINES-2;
- X#endif /* CURSES */
- X } else
- X#ifdef SUNTOOL
- X if (!strcmp(p, "tool_help")) {
- X int n = 0;
- X char *p2 = getpath(TOOL_HELP, &n);
- X if (n)
- X strdup(tool_help, "tool_help");
- X else
- X strdup(tool_help, p2);
- X } else
- X#endif /* SUNTOOL */
- X if (!strcmp(p, "cmd_help")) {
- X int n = 0; /* don't ignore no such file or directory */
- X char *p2 = getpath(COMMAND_HELP, &n);
- X if (n)
- X strdup(cmd_help, "cmd_help");
- X else
- X strdup(cmd_help, p2);
- X } else if (!strcmp(p, "wrapcolumn"))
- X wrapcolumn = 0;
- X else if (!strcmp(p, "history"))
- X init_history(1);
- X else if (!strcmp(p, "known_hosts")) {
- X free_vec(known_hosts);
- X known_hosts = DUBL_NULL;
- X } else if (!strcmp(p, "hostname")) {
- X free_vec(ourname);
- X ourname = DUBL_NULL;
- X } else if (ison(glob_flags, IS_GETTING) && !strcmp(p, "edit_hdrs")) {
- X wprint("You mush finish this letter first.\n");
- X return -1;
- X } else if (!strcmp(p, "complete"))
- X complete = complist = 0;
- X }
- X
- X if (!strcmp(p, opts->option)) {
- X *list = (*list)->next;
- X xfree (opts->option);
- X if (opts->value)
- X xfree(opts->value);
- X xfree((char *)opts);
- X return 1;
- X }
- X for ( ; opts->next; opts = opts->next)
- X if (!strcmp(p, opts->next->option)) {
- X tmp = opts->next;
- X opts->next = opts->next->next;
- X xfree (tmp->option);
- X if (tmp->value)
- X xfree(tmp->value);
- X xfree ((char *)tmp);
- X return 1;
- X }
- X return 0;
- X}
- X
- X/* The functions below return 0 since they don't affect
- X * messages.
- X */
- Xset(n, argv, list)
- Xregister int n;
- Xregister char **argv;
- Xchar *list;
- X{
- X void list_to_str();
- X char firstchar = **argv;
- X register char *cmd = *argv;
- X register struct options **optlist;
- X char buf[BUFSIZ];
- X
- X if (*cmd == 'u')
- X cmd += 2;
- X if (*++argv && !strcmp(*argv, "-?"))
- X return help(0, (*cmd == 'i')? "ignore": "set", cmd_help);
- X
- X if (*argv && **argv == '?') {
- X int incurses;
- X if (!strcmp(*argv, "?all")) {
- X if (incurses = iscurses) /* assign and compare to TRUE */
- X clr_bot_line(), iscurses = FALSE;
- X (void) do_pager(NULL, TRUE); /* start internal pager */
- X for (n = 0; variable_stuff(n, NULL, buf); n++)
- X if (do_pager(strcat(buf, "\n"), FALSE) == EOF)
- X break;
- X (void) do_pager(NULL, FALSE); /* terminate pager */
- X iscurses = incurses;
- X } else {
- X /* May return null if variable not set. */
- X (void) variable_stuff(0, (*argv)+1, buf);
- X print("%s\n", buf);
- X }
- X return 0;
- X }
- X
- X if (firstchar == 'u') {
- X if (!*argv) {
- X print("%s what?\n", cmd);
- X return -1;
- X } else {
- X optlist = (*cmd == 'i')? &ignore_hdr : &set_options;
- X do if (!strcmp(*argv, "*")) {
- X while (*optlist)
- X (void) un_set(optlist, (*optlist)->option);
- X#ifdef SUNTOOL
- X if (*cmd != 'i')
- X opts_panel_item(NULL);
- X#endif /* SUNTOOL */
- X } else if (!un_set(optlist, *argv) &&
- X do_set(set_options, "warning"))
- X print("un%s: %s not set\n",
- X (*cmd == 'i')? "ignore" : "set", *argv);
- X#ifdef SUNTOOL
- X else if (*cmd != 'i')
- X opts_panel_item(*argv);
- X#endif /* SUNTOOL */
- X while (*++argv);
- X#ifdef SUNTOOL
- X if (*cmd == 'i' && istool > 1)
- X update_list_textsw(&ignore_hdr);
- X#endif /* SUNTOOL */
- X }
- X return 0;
- X }
- X
- X if (!*argv) {
- X (void) do_set((*cmd == 'i')? ignore_hdr: set_options, NULL);
- X return 0;
- X }
- X
- X /*
- X * Check for input redirection. If so, set the variable to the ascii
- X * value of the current msg_list.
- X */
- X if (ison(glob_flags, IS_PIPE)) {
- X char *newargv[4];
- X
- X if (*cmd == 'i') {
- X print("You can't pipe to the \"%s\" command.\n", cmd);
- X return -1;
- X }
- X if (newargv[0] = index(argv[0], '='))
- X *newargv[0] = 0;
- X list_to_str(list, buf);
- X if (!buf[0] && !do_set(set_options, argv[0])) {
- X return 0;
- X }
- X newargv[0] = argv[0];
- X newargv[1] = "=";
- X newargv[2] = buf;
- X newargv[3] = NULL;
- X (void) add_option(&set_options, newargv);
- X return 0;
- X }
- X
- X /*
- X * finally, just set the variable the user requested.
- X */
- X (void) add_option((*cmd == 'i')? &ignore_hdr: &set_options, argv);
- X#ifdef SUNTOOL
- X if (istool > 1)
- X if (*cmd == 'i')
- X update_list_textsw(&ignore_hdr);
- X else
- X opts_panel_item(argv[0]);
- X#endif /* SUNTOOL */
- X return 0;
- X}
- X
- X/*
- X * The alts list is a list of hostnames or pathnames where the user
- X * has an account. If he doesn't specify "metoo", then when replying
- X * to mail, if his address is listed, it will be removed. The syntax
- X * is compatible with ucb Mail in that just hostnames can be used.
- X * However, there is an added feature that mush provides which another
- X * login name or path to another login can be specified by preceding the
- X * path or login with a !
- X * "argv" may be a file pointer to write the data into by use of save_opts()
- X */
- Xalts(argc, argv)
- Xregister char **argv;
- X{
- X char buf[BUFSIZ], *p;
- X
- X /* check here first because a 0 argc means to write it to a file */
- X if (argc <= 1) {
- X int n;
- X if (!alternates)
- X return 0;
- X if (argc == 0)
- X (void) fprintf((FILE *)argv, "alts ");
- X for (n = 0; alternates[n]; n++) {
- X p = 0;
- X buf[0] = 0;
- X (void) strcpy(&buf[1], alternates[n]);
- X if (buf[1] != '*')
- X (void) reverse(&buf[1]);
- X if ((p = rindex(&buf[1], '!')) && !lcase_strncmp(p+1, login, -1))
- X *p = 0;
- X else if (buf[1] != '*')
- X buf[0] = '!';
- X if (argc == 0)
- X (void) fprintf((FILE *)argv, "%s ", *buf? buf : &buf[1]);
- X else
- X wprint("%s ", *buf? buf : &buf[1]);
- X if (p)
- X *p = '!';
- X }
- X if (argc == 0)
- X (void) fputc('\n', (FILE *)argv);
- X else
- X wprint("\n");
- X return 0;
- X }
- X
- X if (argc-- && *++argv && !strcmp(*argv, "-?"))
- X return help(0, "alts", cmd_help);
- X
- X free_vec(alternates);
- X if (alternates = (char **)calloc((unsigned)argc+1, sizeof(char *)))
- X while (argc-- > 0) {
- X if (argv[argc][0] == '!')
- X alternates[argc] = savestr(reverse(&argv[argc][1]));
- X else if (argv[argc][0] == '*') {
- X alternates[argc] = savestr(argv[argc]);
- X } else {
- X p = buf + Strcpy(buf, argv[argc]);
- X *p++ = '!', p += Strcpy(p, login);
- X alternates[argc] = savestr(reverse(buf));
- X }
- X }
- X return 0;
- X}
- X
- Xsave_opts(cnt, argv)
- Xchar **argv;
- X{
- X char file[MAXPATHLEN], *tmp;
- X register FILE *fp;
- X
- X if (cnt && *++argv && !strcmp(*argv, "-?"))
- X return help(0, "source", cmd_help);
- X if (cnt && *argv)
- X (void) strcpy(file, *argv);
- X else if ((tmp = getenv("MUSHRC")) || (tmp = getenv("MAILRC")))
- X (void) strcpy(file, tmp);
- X else {
- X char *home = do_set(set_options, "home");
- X if (!home || !*home)
- X home = ALTERNATE_HOME;
- X /* if .mushrc doesn't exist, check .mailrc. If neither, force .mushrc */
- X if (Access(sprintf(file, "%s/%s", home, MAILRC), F_OK) &&
- X Access(sprintf(file, "%s/%s", home, ALTERNATE_RC), F_OK))
- X (void) sprintf(file, "%s/%s", home, MAILRC);
- X }
- X
- X cnt = 1;
- X tmp = getpath(file, &cnt);
- X if (cnt) {
- X if (cnt == -1) {
- X print("%s: %s\n", file, tmp);
- X return -1;
- X } else {
- X print("%s is a directory.\n", tmp);
- X return -2;
- X }
- X }
- X /* See if the file exists and confirm overwrite */
- X if (!Access(tmp, F_OK)) {
- X int overwrite = TRUE;
- X char buf[BUFSIZ];
- X if (!istool) {
- X print("\"%s\" exists. Overwrite? ", trim_filename(tmp));
- X if (Getstr(buf, 3, 0) <= 0 || lower(*buf) != 'y')
- X overwrite = FALSE;
- X }
- X#ifdef SUNTOOL
- X else {
- X sprintf(buf, "\"%s\" exists. Overwrite? ", trim_filename(tmp));
- X overwrite = ask(buf);
- X }
- X#endif /* SUNTOOL */
- X if (!overwrite) {
- X print("\"%s\" unchanged.\n", tmp);
- X return -3;
- X }
- X }
- X if (!(fp = fopen(tmp, "w"))) {
- X error("Can't open %s", file);
- X return -1;
- X }
- X
- X save_list("basic variable settings", set_options, "set", '=', fp);
- X
- X save_list("mail headers for outgoing mail", own_hdrs, "my_hdr", 0, fp);
- X
- X save_list("aliases", aliases, "alias", 0, fp);
- X
- X (void) alts(0, (char **)fp);
- X
- X save_list("headers to ignore", ignore_hdr, "ignore", ' ', fp);
- X
- X save_list("command abbreviations", functions, "cmd", ' ', fp);
- X
- X save_list("command macros for function keys", fkeys, "fkey", ' ', fp);
- X
- X#ifdef CURSES
- X save_cmd("curses mode key bindings", cmd_map, "bind", 1, fp);
- X#endif /* CURSES */
- X
- X save_cmd("line mode mappings", line_map, "map", 0, fp);
- X
- X save_cmd("composition mode mappings", bang_map, "map!", 0, fp);
- X
- X (void) fclose(fp);
- X print("All variables and options saved in %s\n", trim_filename(tmp));
- X return 0;
- X}
- X
- Xsave_list(title, list, command, equals, fp)
- Xstruct options *list;
- Xregister char *command, *title, equals;
- Xregister FILE *fp;
- X{
- X register struct options *opts;
- X register char *p;
- X
- X if (!list)
- X return;
- X (void) fprintf(fp, "#\n# %s\n#\n", title);
- X for (opts = list; opts; opts = opts->next) {
- X if (list == set_options && !strcmp(opts->option, "cwd"))
- X continue; /* don't print $cwd */
- X (void) fprintf(fp, "%s %s", command, opts->option);
- X if (opts->value && *opts->value) {
- X register char *quote;
- X if (!equals)
- X quote = NO_STRING;
- X else if (p = any(opts->value, "\"'"))
- X if (*p == '\'')
- X quote = "\"";
- X else
- X quote = "'";
- X else
- X if (!any(opts->value, " \t;|"))
- X quote = NO_STRING;
- X else
- X quote = "'";
- X (void) fputc(equals? equals: ' ', fp);
- X (void) fprintf(fp, "%s%s%s", quote, opts->value, quote);
- X }
- X (void) fputc('\n', fp);
- X }
- X}
- X
- Xextern struct cmd_map map_func_names[];
- X
- Xsave_cmd(title, list, command, equals, fp)
- Xstruct cmd_map *list;
- Xregister char *command, *title;
- Xregister int equals;
- Xregister FILE *fp;
- X{
- X register struct cmd_map *opts;
- X register char *p;
- X char buf[MAX_MACRO_LEN * 2];
- X
- X if (!list)
- X return;
- X (void) fprintf(fp, "#\n# %s\n#\n", title);
- X for (opts = list; opts; opts = opts->m_next) {
- X register char *quote;
- X if ((p = any(opts->m_str, "\"'")) && *p == '\'')
- X quote = "\"";
- X else
- X quote = "'";
- X (void) fprintf(fp, "%s %s%s%s", command, quote,
- X ctrl_strcpy(buf, opts->m_str, TRUE), quote);
- X if (equals && map_func_names[opts->m_cmd].m_str)
- X (void) fprintf(fp, " %s", map_func_names[opts->m_cmd].m_str);
- X if (opts->x_str && *opts->x_str) {
- X if ((p = any(opts->x_str, "\"'")) && *p == '\'')
- X quote = "\"";
- X else
- X quote = "'";
- X (void) fprintf(fp, " %s%s%s", quote,
- X ctrl_strcpy(buf, opts->x_str, TRUE), quote);
- X }
- X (void) fputc('\n', fp);
- X }
- X}
- X
- X/*
- X * do_alias handles aliases, header settings, functions, and fkeys.
- X * since they're all handled in the same manner, the same routine is
- X * used. argv[0] determines which to use.
- X * alias is given here as an example
- X *
- X * alias identify all aliases
- X * alias name identify alias
- X * alias name arg1 arg2 arg3... -> name="arg1 arg2 arg3"; call add_option
- X * unalias arg1 [arg2 arg3 ... ] unalias args
- X *
- X * same is true for dealing with your own headers.
- X * (also the expand command)
- X */
- Xdo_alias(argc, argv)
- Xregister char **argv;
- X{
- X register char *cmd = *argv, *p;
- X struct options **list;
- X char firstchar = *cmd, buf[BUFSIZ];
- X
- X if (argc == 0)
- X return 0 - in_pipe();
- X if (firstchar == 'u')
- X firstchar = cmd[2];
- X if (*++argv && !strcmp(*argv, "-?")) { /* doesn't apply for fkeys */
- X register char *help_str;
- X if (firstchar == 'a' || firstchar == 'e')
- X help_str = "alias";
- X else if (firstchar == 'c')
- X help_str = "cmd";
- X else if (firstchar == 'f')
- X help_str = "fkey";
- X else
- X help_str = "my_hdr";
- X return help(0, help_str, cmd_help);
- X }
- X
- X if (firstchar == 'a')
- X list = &aliases;
- X else if (firstchar == 'c')
- X list = &functions;
- X else if (firstchar == 'f')
- X list = &fkeys;
- X else
- X list = &own_hdrs;
- X
- X if (*cmd == 'u') {
- X if (!*argv) {
- X print("%s what?\n", cmd);
- X return -1;
- X /* unset a list separated by spaces or ',' */
- X } else while (*argv) {
- X if (!strcmp(*argv, "*")) /* unset everything */
- X while (*list)
- X (void) un_set(list, (*list)->option);
- X else if (!un_set(list, *argv))
- X print("\"%s\" isn't set\n", *argv);
- X argv++;
- X }
- X#ifdef SUNTOOL
- X if (istool > 1)
- X update_list_textsw(list);
- X#endif /* SUNTOOL */
- X return 0;
- X }
- X
- X if (!*argv && *cmd != 'e') {
- X /* just type out all the aliases or own_hdrs */
- X (void) do_set(*list, NULL);
- X return 0;
- X }
- X
- X if (*cmd == 'e') { /* command was "expand" (aliases only) */
- X if (!*argv) {
- X print("expand which alias?\n");
- X return -1;
- X } else
- X do {
- X print("%s: ", *argv);
- X if (p = alias_to_address(*argv))
- X print("%s\n", p);
- X } while (*++argv);
- X return 0;
- X }
- X
- X /* at this point, *argv now points to a variable name ...
- X * check for hdr -- if so, *argv better end with a ':' (check *p)
- X */
- X if (list == &own_hdrs && !(p = index(*argv, ':'))) {
- X print("header labels must end with a ':' (%s)\n", *argv);
- X return -1;
- X }
- X if (!argv[1] && !index(*argv, '='))
- X if (p = do_set(*list, *argv))
- X print("%s\n", p);
- X else
- X print("%s is not set\n", *argv);
- X else {
- X char *tmpargv[2];
- X (void) argv_to_string(buf, argv);
- X if ((p = any(buf, " \t=")) && *p != '=')
- X *p = '=';
- X /* if we're setting an alias, enforce the insertion of commas
- X * between each well-formed address.
- X */
- X if (list == &aliases)
- X fix_up_addr(p+1);
- X tmpargv[0] = buf;
- X tmpargv[1] = NULL;
- X (void) add_option(list, tmpargv);
- X#ifdef SUNTOOL
- X if (istool > 1)
- X update_list_textsw(list);
- X#endif /* SUNTOOL */
- X }
- X return 0;
- X}
- END_OF_FILE
- if test 20739 -ne `wc -c <'mush/setopts.c'`; then
- echo shar: \"'mush/setopts.c'\" unpacked with wrong size!
- fi
- # end of 'mush/setopts.c'
- fi
- if test -f 'mush/tooledit.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'mush/tooledit.c'\"
- else
- echo shar: Extracting \"'mush/tooledit.c'\" \(9136 characters\)
- sed "s/^X//" >'mush/tooledit.c' <<'END_OF_FILE'
- X/* @(#)tooledit.c (c) copyright 2/14/90 (Dan Heller) */
- X
- X/*
- X * intercept events in the compose window for auto-
- X * positioning and tilde command recognition.
- X */
- X#include "mush.h"
- X
- Xstatic short dat_bentarrow[] = {
- X 0x007F, 0x007F, 0x007F, 0x0007, 0x0407, 0x0C07, 0x1C07, 0x3807,
- X 0x7FFF, 0xFFFF, 0x7FFF, 0x3800, 0x1C00, 0x0C00, 0x0400, 0x0000
- X};
- Xmpr_static(bent_arrow, 16, 16, 1, dat_bentarrow);
- XCursor bentarrow;
- X
- Xextern void do_send(), do_edit();
- X
- X/* Return the byte position in the textsw of the header specified */
- XTextsw_index
- Xheader_position(textsw, str)
- XTextsw textsw;
- Xchar *str;
- X{
- X char buf[256];
- X register char *p = buf, *p2;
- X int contd_hdr = 0, add_newline = 0;
- X Textsw_index pos = 0L, ret_pos = 0L;
- X
- X buf[0] = 0;
- X for (;;) {
- X /* get a line at a time from the textsw */
- X (void) window_get(textsw, TEXTSW_CONTENTS, pos, buf, 256);
- X if (p = index(buf, '\n'))
- X *p = 0;
- X else
- X add_newline++;
- X p = buf;
- X skipspaces(0);
- X if (!*p) /* newline alone -- end of headers */
- X break;
- X pos += strlen(buf) + 1; /* advance position to next line */
- X if (*p != ' ' && *p != '\t') {
- X contd_hdr = 0;
- X /* strcmp ignoring case */
- X for (p2 = str; *p && *p2 && lower(*p2) == lower(*p); ++p, ++p2)
- X ;
- X /* MATCH is true if p2 is at the end of str and *p is ':' */
- X if (*p2 || *p != ':') {
- X if (!*p2 && isspace(*any(p, ": \t"))) {
- X /* Not a legal or continued header */
- X pos -= strlen(buf) + 1; /* go back to beginning of line */
- X break;
- X }
- X continue;
- X } else {
- X contd_hdr = 1;
- X ret_pos = pos - 1;
- X }
- X } else if (!contd_hdr)
- X continue;
- X }
- X if (!ret_pos) {
- X /* coudn't find the header -- add it */
- X window_set(textsw, TEXTSW_INSERTION_POINT, pos, NULL);
- X p = buf;
- X if (add_newline)
- X *p++ = '\n', pos--;
- X for (p2 = str; *p2; ++p2) {
- X if (p2 == str || p2[-1] == '-')
- X *p++ = upper(*p2);
- X else
- X *p++ = *p2;
- X }
- X *p++ = ':', *p++ = ' ', *p++ = '\n', *p = 0;
- X textsw_insert(textsw, buf, strlen(buf));
- X ret_pos = pos + strlen(buf) - 1;
- X }
- X return ret_pos;
- X}
- X
- X/* position_flags indicates which header to go to when uses tilde commands */
- Xstatic u_long position_flags;
- Xstatic char *tilde_hdrs[] = {
- X#define POSITION_TO ULBIT(0)
- X "to",
- X#define POSITION_SUBJ ULBIT(1)
- X "subject",
- X#define POSITION_CC ULBIT(2)
- X "cc",
- X#define POSITION_BCC ULBIT(3)
- X "bcc",
- X#define POSITION_FCC ULBIT(4)
- X "fcc"
- X};
- X#define POSITION_ALL \
- X ((POSITION_TO) | (POSITION_SUBJ) | (POSITION_CC) | (POSITION_BCC))
- X#define POSITION_END ULBIT(5)
- X#define TOTAL_POSITIONS 6
- X
- X/*
- X * position_flags identifies which header is requested by the calling func.
- X * use header_position to find the position of the header associated with
- X * with the flags.
- X */
- Xstatic void
- Xgo_to_next_pos(textsw)
- XTextsw textsw;
- X{
- X Textsw_index pos;
- X int i = 0;
- X
- X while (i < TOTAL_POSITIONS && isoff(position_flags, ULBIT(i)))
- X i++;
- X if (i == TOTAL_POSITIONS)
- X return;
- X if (i < ArraySize(tilde_hdrs))
- X pos = header_position(textsw, tilde_hdrs[i]);
- X else
- X pos = (Textsw_index)window_get(textsw, TEXTSW_LENGTH);
- X turnoff(position_flags, ULBIT(i));
- X if (!position_flags)
- X /* restore old cursor */
- X window_set(textsw,WIN_CURSOR, window_get(mfprint_sw, WIN_CURSOR), NULL);
- X else
- X window_set(textsw, WIN_CURSOR, bentarrow, NULL);
- X window_set(textsw, TEXTSW_INSERTION_POINT, pos, NULL);
- X textsw_normalize_view(textsw, (Textsw_index)0);
- X}
- X
- Xtilde_from_menu(item, value, event)
- XPanel_item item;
- Xint value;
- XEvent *event;
- X{
- X Textsw textsw = (Textsw)panel_get(panel_get(item, PANEL_PARENT_PANEL),
- X PANEL_CLIENT_DATA);
- X if (value == 0 || event_id(event) == MS_LEFT)
- X position_flags = POSITION_ALL;
- X else
- X turnon(position_flags, ULBIT(value - 1));
- X panel_set_value(item, 0);
- X go_to_next_pos(textsw);
- X}
- X
- X/*
- X * This interpose function is here to parse for tilde escapes.
- X * Note: this is a (currently) undocumented feature and is intended
- X * as an accelerator for advanced users. Supported tilde escapes
- X * are: t,s,c,b,x,e and v.
- X */
- XNotify_value
- Xedit_msg_textwin(textsw, event, arg, type)
- XTextsw textsw;
- XEvent *event;
- XNotify_arg arg;
- XNotify_event_type type;
- X{
- X char buf[2];
- X static char do_tilde;
- X Textsw_index pos;
- X
- X if (do_tilde == 1 && event_is_ascii(event) &&
- X /* make sure we are going to catch this switch */
- X index("bschetv", event_id(event))) {
- X textsw_erase(textsw,
- X (unsigned)window_get(textsw, TEXTSW_INSERTION_POINT)-1,
- X (unsigned)window_get(textsw, TEXTSW_INSERTION_POINT));
- X switch (event_id(event)) {
- X case 'h':
- X turnon(position_flags, POSITION_ALL);
- X when 't':
- X turnon(position_flags, POSITION_TO);
- X when 's':
- X turnon(position_flags, POSITION_SUBJ);
- X when 'c':
- X turnon(position_flags, POSITION_CC);
- X when 'b':
- X turnon(position_flags, POSITION_BCC);
- X when 'e' : case 'v' : {
- X /* shouldn't use global -- hack for now */
- X extern Panel_item edit_item;
- X do_edit(edit_item);
- X return NOTIFY_DONE;
- X }
- X }
- X do_tilde = 0;
- X go_to_next_pos(textsw);
- X return NOTIFY_DONE;
- X }
- X do_tilde = 0;
- X /* check to see if this is a potential tilde escape */
- X if (event_id(event) == *escape) {
- X /* get previous character entered */
- X pos = (Textsw_index)window_get(textsw, TEXTSW_INSERTION_POINT);
- X if (pos > 0)
- X (void) window_get(textsw, TEXTSW_CONTENTS, pos-1, buf, 1);
- X /* test to see if ~ came at the beginning of a line */
- X if (pos < 1 || buf[0] == '\n')
- X do_tilde = 1;
- X }
- X /* check for auto-next-header .. e.g. when you hit CR on To: go to Subj:
- X * special case backspace keys since textsw_start_of_display_line() has
- X * a bug where it gets the line # wrong when backspacing.
- X */
- X if (position_flags != 0L && ID != CTRL('H') && ID != 127) {
- X Notify_value val;
- X if (ID == '\n' || ID == '\r') {
- X go_to_next_pos(textsw);
- X return NOTIFY_DONE; /* don't process event */
- X }
- X /* we're still processing this header -- continue to do so unless
- X * the event in question changes the line# of the insertion point.
- X * first get current position...
- X */
- X pos = (Textsw_index)window_get(textsw, TEXTSW_INSERTION_POINT);
- X /* now let the event be processed... */
- X val = notify_next_event_func(textsw, event, arg, type);
- X /* see if the line # for the new insertion point has changed. */
- X if (textsw_start_of_display_line(textsw, pos) !=
- X textsw_start_of_display_line(textsw,
- X (Textsw_index)window_get(textsw, TEXTSW_INSERTION_POINT))) {
- X /* the event (mouse button, ACTION_??), changed the line # */
- X position_flags = 0L; /* disable auto-next-header */
- X /* restore cursor */
- X window_set(textsw,
- X WIN_CURSOR, window_get(mfprint_sw, WIN_CURSOR),
- X NULL);
- X }
- X return val;
- X }
- X return notify_next_event_func(textsw, event, arg, type);
- X}
- X
- X/*
- X * start the compose textsw. This is here because we need position_flags
- X * and the tilde-bits to set the insertion point at the To: line if
- X * do_position is true.
- X */
- Xvoid
- Xstart_textsw_edit(textsw, do_position)
- XTextsw textsw;
- X{
- X extern char *hfile;
- X char *file = (char *)window_get(textsw, TEXTSW_CLIENT_DATA);
- X Textsw_index first, last, to_index;
- X int i;
- X
- X strdup(file, hfile);
- X#ifdef SUN_4_0 /* SunOS 4.0+ */
- X window_set(textsw,
- X TEXTSW_CLIENT_DATA, file,
- X TEXTSW_FILE_CONTENTS, hfile,
- X TEXTSW_READ_ONLY, FALSE,
- X TEXTSW_STORE_CHANGES_FILE, FALSE,
- X NULL);
- X#else /* SUN_4_0 */
- X textsw_load_file(textsw, hfile, 1, 0, 0);
- X window_set(textsw,
- X TEXTSW_CLIENT_DATA, file,
- X TEXTSW_READ_ONLY, FALSE,
- X TEXTSW_STORE_CHANGES_FILE, FALSE,
- X NULL);
- X#endif /* SUN_4_0 */
- X position_flags = 0L;
- X if (do_position) {
- X turnon(position_flags, POSITION_TO);
- X if (do_set(set_options, "ask") || do_set(set_options, "asksub"))
- X turnon(position_flags, POSITION_SUBJ);
- X if (do_set(set_options, "askcc"))
- X turnon(position_flags, POSITION_CC);
- X }
- X turnon(position_flags, POSITION_END);
- X go_to_next_pos(textsw);
- X (void) unlink(hfile);
- X xfree(hfile), hfile = NULL;
- X}
- X
- X/*ARGSUSED*/
- Xvoid
- Xdo_edit(item, value, event)
- XPanel_item item;
- Xint value;
- Xregister Event *event;
- X{
- X int argc;
- X char *file, **argv, *edit, cmd[MAXPATHLEN];
- X Panel_item next;
- X Panel panel = (Panel)panel_get(item, PANEL_PARENT_PANEL);
- X Textsw textsw = (Textsw)panel_get(panel, PANEL_CLIENT_DATA);
- X
- X file = (char *)window_get(textsw, TEXTSW_CLIENT_DATA);
- X if (textsw_store_file(textsw, file, 0, 0)) {
- X error("Can't start editor");
- X return;
- X }
- X if ((!(edit = do_set(set_options, "visual")) || !*edit) &&
- X (!(edit = do_set(set_options, "editor")) || !*edit))
- X edit = DEF_EDITOR;
- X (void) sprintf(cmd, "%s %s", edit, file);
- X argc = 0;
- X if (!(argv = mk_argv(cmd, &argc, FALSE))) {
- X unlink(file);
- X return;
- X }
- X if (tool_edit_letter(textsw, argv) > -1) {
- X /* skip first panel item */
- X item = (Panel_item) panel_get(panel, PANEL_FIRST_ITEM);
- X for (item = (Panel_item) panel_get(item, PANEL_NEXT_ITEM);
- X item; item = next) {
- X next = (Panel_item) panel_get(item, PANEL_NEXT_ITEM);
- X (void) panel_set(item, PANEL_SHOW_ITEM, FALSE, NULL);
- X }
- X position_flags = 0L;
- X window_set(textsw,WIN_CURSOR, window_get(mfprint_sw,WIN_CURSOR), NULL);
- X }
- X free_vec(argv);
- X}
- END_OF_FILE
- if test 9136 -ne `wc -c <'mush/tooledit.c'`; then
- echo shar: \"'mush/tooledit.c'\" unpacked with wrong size!
- fi
- # end of 'mush/tooledit.c'
- fi
- echo shar: End of archive 13 \(of 19\).
- cp /dev/null ark13isdone
- 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
-
-
-