home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-05-06 | 55.1 KB | 2,050 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 18 (of 19)."
- # Contents: mush/Mushrc mush/expr.c mush/macros.c mush/main.c
- # mush/options.c mush/print.c mush/sort.c
- # Wrapped by argv@turnpike on Wed May 2 13:59:53 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'mush/Mushrc' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'mush/Mushrc'\"
- else
- echo shar: Extracting \"'mush/Mushrc'\" \(5551 characters\)
- sed "s/^X//" >'mush/Mushrc' <<'END_OF_FILE'
- X# Mushrc -- suggested /usr/lib/Mushrc init file for Mush
- X# Copyright (c) 1989 by Bart Schaefer and Dan Heller
- X#
- X# Set these variables as they are set in config.h
- X# (assumes that this file is DEFAULT_RC from config.h)
- Xset \
- X MAILRC = ".mushrc" \
- X ALTERNATE_RC = ".mailrc" \
- X ALT_DEF_RC = "/usr/lib/Mail.rc"
- X
- X# Set up the display early to allow quick exit in headers-only mode.
- X# The hdrs_only flag is true if the command line was: "mush -H".
- X# The variable hdr_format is set to change the format of the header
- X# summaries that are displayed.
- Xif hdrs_only
- X set hdr_format='%22a %M %-2N %5T %.33s'
- X exit # Quits reading this file
- Xelse
- X set hdr_format='%22a %M %-2N %5T (%3.5l li) %.25s'
- Xendif
- X
- X# Set the prompt to show current time, name of the current folder,
- X# current message number, and count of total messages.
- Xset prompt="(%T) %f: #%m of %t> "
- X
- X# Hitting <CR> should do nothing (helps make mush more shell-like). If
- X# newline is not set, hitting <CR> prints the next message (like Mail).
- X# This variable could be set to any mush command.
- Xset newline
- X
- X# When reading messages, don't bother looking at lengthy, boring headers.
- Xignore message-id received via status
- X
- X# Since mush has csh-like history, you might find it annoying to type
- X# things like "mail host\!host1\!host2\!user" from within the mush shell.
- X# Setting nonobang will prevent the "unknown event" and allow the !'s to
- X# be typed without having to be preceded by backslashes.
- Xset nonobang
- X
- X# By default, mush's history is set to the last command only. Set it to
- X# remember the last 100 commands.
- Xset history = 100
- X
- X# If the variable "unix" is set, then any command that isn't a mush command
- X# will execute the command as if you typed it from the shell. Note, such
- X# commands will not go through another shell -- this is it. This may be
- X# considered confusing for new users, so it is commented out by default.
- X# set unix
- X
- X# When you use the -i option to reply, or use the ~i tilde escape in a letter
- X# when in compose mode, the current message will be included in your text.
- X# Put a nice wrapper around those included messages. Here, show the author's
- X# name and the subject of his letter, label the end, and add a trailing blank
- X# to separate each inclusion and make finding the end easier.
- Xset pre_indent_str='On %M %N, %T, %.50n wrote:\n} Subject: %.65s'
- Xset indent_str='} ' # actual message text is preceded by a "}"
- Xset post_indent_str='}-- End of excerpt from %.50n\n'
- X
- X# Label replies with a header showing the who, what, and when of the
- X# message being replied-to.
- Xset in_reply_to='%f\n\t"%s" (%d)'
- X
- X# Mail routing and address-fixing conveniences. If auto_route is set, then
- X# replies to messages take a closer look at the addresses of the recipients.
- X# If any redundant paths are present, they are pruned. Also, the path that
- X# precedes any hosts listed in the "known_hosts" list is truncated. This is
- X# useful for uucp sites only, and is therefore commented out by default.
- X# set auto_route known_hosts="sun ucbcad well unicom"
- X
- X# The curses mode allows the screen to be set up like a full screen editor.
- X# There are basic "curses commands" which are bound to keyboard key-sequences
- X# (usually one character). The user can rebind these keys to suit his tastes.
- X# Note that the binding for R below removes the binding of reply-all.
- X#
- Xset curses_help # Unset this to remove help message in curses.
- Xbind \n display # Hit return to display the next message.
- Xbind e macro "[line-mode]edit\n" # Quick edit from curses.
- Xbind P macro "[line-mode]Print\n" # Show me all the headers.
- X
- X# "cmd" is used to set command line aliases similar to the way "csh"
- X# does it. The only difference is that "alias" is a reserved word in
- X# Mush and Mail, so cmd is used.
- X#
- Xcmd dq 'd \!*; q' # Delete a message list, then quit.
- Xcmd unread 'flags \!* U O' # Mark messages unread.
- Xcmd : curses # Colon now "toggles" curses mode.
- X
- X# Read the alternate system init file in addition to this file
- Xsource $ALT_DEF_RC
- Xunset ALT_DEF_RC
- X
- X# Mush tries to read ~/.mushrc first, then it tries ~/.mailrc. If .mushrc
- X# is found, .mailrc is normally not read. Source the contents of .mailrc
- X# as well in case there are Mail aliases that are set there.
- Xif -e $HOME/$MAILRC
- X if -e $HOME/$ALTERNATE_RC
- X source $HOME/$ALTERNATE_RC
- X endif
- Xendif
- Xunset ALTERNATE_RC
- X
- X# The rest of this file demonstrates how sysadmins with novice users
- X# might want to set things up.
- X
- Xif -e $HOME/.mushexpert
- X set quiet
- X exit
- Xendif
- Xif ! -e $HOME/.mushuser
- X echo "I see you've never used the Mush program before."
- X echo "I'll set some special flags to help you out."
- X echo "After you've used Mush a few times, you can type the command:"
- X echo ""
- X echo " expert"
- X echo ""
- X echo "and the flags will no longer be set unless you put them"
- X echo "in your $HOME/$MAILRC file."
- X echo ""
- X sh touch $HOME/.mushuser # Use sh in case $unix is not set.
- X if $?quiet
- X unset quiet # Show the help message on startup.
- X endif
- Xendif
- X# At this point some helpful variables should be set. See the list above,
- X# marked as "helpful for new users", for suggestions.
- X#
- X# Create the "expert" command mentioned in the message above.
- Xcmd expert 'sh touch $HOME/.mushexpert'
- X
- X# These variables are helpful for new users:
- X# ask -- always prompt for Subject: of mail
- X# ignoreeof -- ignore end-of-file from keyboard
- X# verify -- query that all is well before sending mail
- X# warning -- report miscellaneous possible problems
- Xset ask verify warning
- Xset ignoreeof="echo 'Use "'"'quit'"'" to quit.'"
- END_OF_FILE
- if test 5551 -ne `wc -c <'mush/Mushrc'`; then
- echo shar: \"'mush/Mushrc'\" unpacked with wrong size!
- fi
- # end of 'mush/Mushrc'
- fi
- if test -f 'mush/expr.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'mush/expr.c'\"
- else
- echo shar: Extracting \"'mush/expr.c'\" \(4685 characters\)
- sed "s/^X//" >'mush/expr.c' <<'END_OF_FILE'
- X/* @(#)expr.c 2.3 (c) copyright 10/15/86 (Dan Heller) */
- X
- X#include "mush.h"
- X
- Xchar *eval_expr();
- X
- X/* Parse a string (p) to interpret numbers and ranges of numbers (n-m)
- X * delimited by whitespace or comma's. Set msg_list bitfields using
- X * macros in mush.h.
- X * Return the address of the end of whatever we parsed (in case there's
- X * more that the calling routine cares to deal with).
- X * Finally, remember that user specifies one more than actual message number
- X */
- Xchar *
- Xdo_range(p, list1)
- Xregister char *p, *list1;
- X{
- X register int num1 = -1, num2 = -1, except = 0;
- X register char *p2;
- X char list2[MAXMSGS_BITS];
- X
- X if (!p)
- X return "";
- X while (*p) {
- X if (isdigit(*p) || *p == '$' || *p == '.' || *p == '^') {
- X if (isdigit(*p)) {
- X char c;
- X p2 = p;
- X skipdigits(0); /* find the end of the digits */
- X c = *p, *p = 0; /* temporarily plug a null */
- X if (!(num2 = chk_msg(p2))) {
- X clear_msg_list(list1);
- X return NULL;
- X }
- X *p = c;
- X } else if (*p == '$')
- X p++, num2 = msg_cnt;
- X else if (*p == '.')
- X p++, num2 = current_msg+1;
- X else if (*p == '^')
- X p++, num2 = 1;
- X if (except)
- X unset_msg_bit(list1, num2-1);
- X else
- X set_msg_bit(list1, num2-1);
- X if (num1 >= 0) {
- X if (num1 > num2) {
- X print("syntax error: range sequence order reversed.\n");
- X clear_msg_list(list1);
- X return NULL;
- X }
- X while (++num1 < num2)
- X if (except)
- X unset_msg_bit(list1, num1-1);
- X else
- X set_msg_bit(list1, num1-1);
- X num1 = num2 = -1;
- X }
- X }
- X /* expressions to evaluate start with a `
- X * p2 points to first char passed the last char parsed.
- X */
- X if (*p == '`') {
- X clear_msg_list(list2);
- X if (!(p = eval_expr(p, list2))) {
- X clear_msg_list(list1);
- X return NULL;
- X } else {
- X if (except)
- X bitput(list2, list1, msg_cnt, &=~); /* MACRO */
- X else
- X bitput(list2, list1, msg_cnt, |=); /* MACRO */
- X }
- X }
- X /* NOT operator: `* {5}' (everything except for 5)
- X * `4-16 {8-10}' (4 thru 16 except for 8,9,10)
- X */
- X if (*p == '{' || *p == '}') {
- X if (*p == '{' && (except || num1 >= 0))
- X break;
- X if (*p == '}' && !except) {
- X print("syntax error: missing {\n"); /* } */
- X break;
- X }
- X except = !except;
- X } else if (*p == '-')
- X if (num1 >= 0 || num2 < 0
- X || !index(" \t{},.*`$", *(p+1)) && !isdigit(*(p+1)))
- X break;
- X else
- X num1 = num2;
- X else if (*p == ',' || *p == '*') {
- X if (num1 >= 0)
- X break;
- X else if (*p == '*') {
- X if (except)
- X clear_msg_list(list1);
- X else
- X for (num1 = 0; num1 < msg_cnt; num1++)
- X set_msg_bit(list1, num1);
- X num1 = -1;
- X }
- X } else if (!index(" \t`", *p))
- X break;
- X if (*p)
- X skipspaces(1); /* don't make user type stuff squished together */
- X }
- X if (num1 >= 0 || except) {
- X if (except)
- X /* { */ print("syntax error: unmatched }\n");
- X else
- X print("syntax error: unfinished range\n");
- X clear_msg_list(list1);
- X return NULL;
- X }
- X return p;
- X}
- X
- X/*
- X * convert a message list to an ascii string.
- X */
- Xvoid
- Xlist_to_str(list, str)
- Xchar list[], *str;
- X{
- X int n, m = -1;
- X
- X for (n = 0; n < msg_cnt; n++) {
- X if (msg_bit(list, n)) {
- X if (m == -1)
- X str += strlen(sprintf(str, "%d", (m = n) + 1 ));
- X continue;
- X }
- X if (m == -1)
- X continue;
- X if (n - m > 2)
- X str += strlen(sprintf(str, "-%d", n));
- X else if (n - m == 2)
- X str += strlen(sprintf(str, " %d", n));
- X *str++ = ' ';
- X m = -1;
- X }
- X if (m > -1 && m != n - 1) {
- X if (n - m > 2)
- X *str++ = '-';
- X else
- X *str++ = ' ';
- X str += Strcpy(str, itoa(msg_cnt));
- X }
- X *str = 0;
- X}
- X
- X/* evaluate expressions:
- X * mail> delete `pick -f root` deletes all messages from root.
- X * mail> save * {`pick -s "Re:"`} save all message that don't have "Re:"
- X * in the subject header.
- X * mail> save `pick -x -s "Re:"` same
- X * args as follows:
- X * p should point to the first ` -- check for it.
- X * on tells whether to turn bits on or off if messages match.
- X */
- Xchar *
- Xeval_expr(p, new_list)
- Xregister char *p, new_list[];
- X{
- X register char *p2, **argv;
- X int argc;
- X u_long save_flags = glob_flags;
- X
- X if (!(p2 = index(++p, '`'))) {
- X print("unmatched backquote (`)\n");
- X return NULL;
- X }
- X *p2 = 0;
- X
- X skipspaces(0);
- X if (!*p) {
- X print("Invalid null command\n");
- X return NULL;
- X }
- X turnon(glob_flags, DO_PIPE);
- X /* ignore sigs only because if user interrupts the do_command,
- X * the longjmp will corrupt the stack and the program is hosed.
- X * fix is to have layers of jmp_bufs to return to different levels.
- X */
- X turnon(glob_flags, IGN_SIGS);
- X if (*p && (argv = make_command(p, TRPL_NULL, &argc)))
- X (void) do_command(argc, argv, new_list);
- X glob_flags = save_flags;
- X *p2 = '`';
- X return p2+1;
- X}
- END_OF_FILE
- if test 4685 -ne `wc -c <'mush/expr.c'`; then
- echo shar: \"'mush/expr.c'\" unpacked with wrong size!
- fi
- # end of 'mush/expr.c'
- fi
- if test -f 'mush/macros.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'mush/macros.c'\"
- else
- echo shar: Extracting \"'mush/macros.c'\" \(9279 characters\)
- sed "s/^X//" >'mush/macros.c' <<'END_OF_FILE'
- X/* (@)# macros.c (c) copyright 9/19/88 (Bart Schaefer, Dan Heller) */
- X
- X#include "bindings.h"
- X#include "mush.h"
- X
- Xextern struct cmd_map map_func_names[];
- X
- Xstruct cmd_map *mac_stack, *mac_hide;
- X
- X/*
- X * print current binding to macro mappings if "str" is NULL.
- X * else return the string "x_str" which the str is bound to.
- X */
- Xchar *
- Xc_macro(name, str, opts)
- Xchar *name;
- Xregister char *str;
- Xregister struct cmd_map *opts;
- X{
- X register int incurses = iscurses;
- X char buf[MAX_MACRO_LEN], buf2[sizeof buf * 3];
- X
- X if (!str) {
- X for (; opts; opts = opts->m_next)
- X if (opts->m_cmd == C_MACRO)
- X break;
- X if (!opts) {
- X print("No %s settings.\n", name);
- X return (char *)(-1);
- X }
- X if (incurses)
- X clr_bot_line(), iscurses = FALSE;
- X (void) do_pager(NULL, TRUE);
- X (void) do_pager(sprintf(buf, "\nCurrent %s settings:\n\n",name), FALSE);
- X }
- X
- X if (!opts)
- X return NULL;
- X
- X for (; opts; opts = opts->m_next) {
- X if (opts->m_cmd != C_MACRO)
- X continue;
- X if (!str) {
- X (void) do_pager(sprintf(buf, "%-20.20s ",
- X ctrl_strcpy(buf2, opts->m_str, FALSE)), FALSE);
- X if (do_pager(sprintf(buf, "%s\n",
- X ctrl_strcpy(buf2, opts->x_str, TRUE)), FALSE) == EOF)
- X break;
- X } else {
- X if (strcmp(str, opts->m_str))
- X continue;
- X else
- X return opts->x_str;
- X }
- X }
- X iscurses = incurses;
- X if (str)
- X (void) do_pager(NULL, FALSE);
- X return NULL;
- X}
- X
- Xmac_push(str)
- Xregister char *str;
- X{
- X register struct cmd_map *tmp;
- X
- X /* now make a new macro struct and set fields */
- X if (!(tmp = (struct cmd_map *)calloc((unsigned)1,sizeof(struct cmd_map)))) {
- X error("calloc");
- X return -1;
- X }
- X tmp->m_next = mac_stack;
- X mac_stack = tmp;
- X tmp->x_str = savestr(str); /* x_str is the text of the expansion */
- X tmp->m_str = tmp->x_str; /* m_str is the current read position */
- X
- X /*
- X * Save the current state of the glob_flags so
- X * mac_push() can also serve as unget of stdin
- X */
- X tmp->m_cmd = glob_flags;
- X return 0;
- X}
- X
- Xmac_queue(str)
- Xregister char *str;
- X{
- X register struct cmd_map **tmp; /* NOTE pointer to pointer! */
- X
- X /* Find the bottom of the macro stack */
- X for (tmp = &mac_stack; *tmp; tmp = &((*tmp)->m_next))
- X ;
- X /* now make a new macro struct and set fields */
- X if (!(*tmp =
- X (struct cmd_map *)calloc((unsigned)1,sizeof(struct cmd_map)))) {
- X error("calloc");
- X return -1;
- X }
- X (*tmp)->m_next = (struct cmd_map *)0; /* calloc should do this .... */
- X (*tmp)->x_str = savestr(str); /* x_str is the text of the expansion */
- X (*tmp)->m_str = (*tmp)->x_str; /* m_str is the current read position */
- X
- X /*
- X * Save the current state of the glob_flags
- X */
- X (*tmp)->m_cmd = glob_flags;
- X return 0;
- X}
- X
- Xvoid
- Xmac_pop()
- X{
- X register struct cmd_map *tmp;
- X
- X if (mac_stack) {
- X tmp = mac_stack;
- X mac_stack = tmp->m_next;
- X xfree(tmp->x_str);
- X xfree((char *) tmp);
- X }
- X /*
- X * Restore saved MACRO glob_flags only (see mac_push())
- X */
- X if (mac_stack) {
- X if (ison(mac_stack->m_cmd, IN_MACRO))
- X turnon(glob_flags, IN_MACRO);
- X else
- X turnoff(glob_flags, IN_MACRO);
- X if (ison(mac_stack->m_cmd, LINE_MACRO))
- X turnon(glob_flags, LINE_MACRO);
- X else
- X turnoff(glob_flags, LINE_MACRO);
- X if (ison(mac_stack->m_cmd, QUOTE_MACRO))
- X turnon(glob_flags, QUOTE_MACRO);
- X else
- X turnoff(glob_flags, QUOTE_MACRO);
- X }
- X}
- X
- X/* Abandon macro processing */
- Xvoid
- Xmac_flush()
- X{
- X while (mac_stack)
- X mac_pop();
- X if (mac_hide) {
- X mac_stack = mac_hide;
- X mac_hide = NULL_MAP;
- X while (mac_stack)
- X mac_pop();
- X }
- X turnoff(glob_flags, IN_MACRO);
- X turnoff(glob_flags, LINE_MACRO);
- X turnoff(glob_flags, QUOTE_MACRO);
- X}
- X
- X/* Check for pending input from a macro. */
- Xmac_pending()
- X{
- X register struct cmd_map *msp;
- X
- X for (msp = mac_stack; msp && !*(msp->m_str); msp = msp->m_next)
- X ;
- X
- X return !!msp;
- X}
- X
- X/* Get input and treat it as a macro. */
- Xget_mac_input(newline)
- Xint newline; /* 1 if newline to be appended, 0 otherwise */
- X{
- X register int len;
- X char buf[MAX_MACRO_LEN];
- X
- X /* This call cannot be nested */
- X if (mac_hide)
- X return -1;
- X
- X /* Hide the mac_stack so input comes from stdin */
- X mac_hide = mac_stack; mac_stack = NULL_MAP;
- X
- X if ((len = Getstr(buf, MAX_MACRO_LEN - 1, 0)) < 0)
- X return len;
- X if (newline) {
- X buf[len++] = '\n';
- X buf[len] = 0;
- X }
- X
- X /* Restore the mac_stack */
- X if (mac_stack) {
- X /*
- X * Somehow, a push happened even though mac_hide was
- X * nonzero -- maybe by line wrap? Fix it as best we can.
- X */
- X struct cmd_map *msp;
- X for (msp = mac_stack; msp->m_next; msp = msp->m_next)
- X ;
- X msp->m_next = mac_hide;
- X } else
- X mac_stack = mac_hide;
- X mac_hide = NULL_MAP;
- X
- X /* Restore saved flags */
- X if (mac_stack) {
- X if (ison(mac_stack->m_cmd, IN_MACRO))
- X turnon(glob_flags, IN_MACRO);
- X else
- X turnoff(glob_flags, IN_MACRO);
- X if (ison(mac_stack->m_cmd, LINE_MACRO))
- X turnon(glob_flags, LINE_MACRO);
- X else
- X turnoff(glob_flags, LINE_MACRO);
- X }
- X if (len > 0)
- X Ungetstr(buf);
- X
- X return 1;
- X}
- X
- X/* getchar() substitute -- reads from the current macro if one is active,
- X * otherwise does a getchar().
- X *
- X * NOTE: In the mac_stack, x_str is the saved text of the current macro,
- X * and m_str is the current read position within the macro.
- X */
- Xm_getchar()
- X{
- X int c;
- X
- X while (mac_stack && (! *(mac_stack->m_str)))
- X mac_pop();
- X if (mac_stack) {
- X c = *((mac_stack->m_str)++);
- X return c;
- X } else {
- X turnoff(glob_flags, IN_MACRO);
- X turnoff(glob_flags, LINE_MACRO);
- X turnoff(glob_flags, QUOTE_MACRO);
- X while ((c = getchar()) == 0) /* Ignore NUL chars from stdin */
- X ; /* until better solution found */
- X return c;
- X }
- X}
- X
- Xm_ungetc(c)
- Xchar c;
- X{
- X if (mac_stack && (mac_stack->m_str > mac_stack->x_str))
- X *(--(mac_stack->m_str)) = c;
- X else
- X (void) ungetc(c, stdin);
- X}
- X
- X/*
- X * Try to read a long command; assumes MAC_LONG_CMD already seen.
- X * On immediate failure, return 0.
- X * On failure after reading some input, return less than zero.
- X * On success, return greater than 0.
- X * The absolute value of the return is the number of chars placed in buf.
- X */
- Xread_long_cmd (buf)
- Xchar *buf;
- X{
- X register char c, *p = buf;
- X register int count = 0;
- X
- X /*
- X * Test in_macro() in this loop because the _entire_
- X * long command _must_ be in the macro -- if we run
- X * out of macro in mid-long-command, it is an error.
- X */
- X while (in_macro() && (count < MAX_LONG_CMD - 1)
- X && ((c = m_getchar()) != MAC_LONG_END)) {
- X *p++ = c; ++count;
- X }
- X *p = '\0';
- X if (c != MAC_LONG_END)
- X return (-count);
- X return count;
- X}
- X
- X/*
- X * Identify and possibly execute a reserved long macro command
- X * Executes if do_exec is true. Otherwise, just parse.
- X */
- Xreserved_cmd (buf, do_exec)
- Xchar *buf;
- X{
- X int ret = 1;
- X
- X if (!strcmp(buf, MAC_GET_STR)) {
- X if (do_exec)
- X ret = get_mac_input(0);
- X } else if (!strcmp(buf, MAC_GET_LINE)) {
- X if (do_exec)
- X ret = get_mac_input(1);
- X } else
- X ret = 0;
- X return ret;
- X}
- X
- X#ifdef CURSES
- X
- X/*
- X * Identify (and possibly execute, if reserved) curses mode commands
- X * that appear in macro strings enclosed by MAC_LONG_CMD and
- X * MAC_LONG_END. Return the binding of the command.
- X */
- Xlong_mac_cmd (c, do_exec)
- Xint c;
- X{
- X char buf[MAX_LONG_CMD];
- X register int count, binding;
- X int y, x;
- X
- X if (c != MAC_LONG_CMD)
- X return C_ERROR;
- X
- X if ((count = read_long_cmd(buf)) <= 0) {
- X print("Invalid long macro command");
- X if (ison(glob_flags, CNTD_CMD))
- X putchar('\n');
- X if (do_exec)
- X mac_flush();
- X return C_ERROR;
- X }
- X
- X if (do_exec) {
- X if (ison(glob_flags, CNTD_CMD))
- X clr_bot_line();
- X getyx(stdscr, y, x);
- X move(LINES - 1, 0);
- X }
- X if (reserved_cmd(buf, do_exec)) {
- X if (do_exec) {
- X if (isoff(glob_flags, CNTD_CMD))
- X move(y, x);
- X return getcmd();
- X } else
- X return C_NULL;
- X } else if (do_exec)
- X move(y, x);
- X
- X /* Can start at C_NULL because of "no-op" command */
- X for (count = 0; count <= C_HELP; count++) {
- X if (!strcmp(buf, map_func_names[count].m_str)) {
- X binding = (int)map_func_names[count].m_cmd;
- X break;
- X }
- X }
- X /* Don't allow C_MACRO to be called directly */
- X if (count > C_HELP || binding == C_MACRO) {
- X print("Invalid long macro command");
- X if (ison(glob_flags, CNTD_CMD))
- X putchar('\n');
- X return C_ERROR;
- X } else
- X return binding;
- X}
- X
- X#endif /* CURSES */
- X
- X/*
- X * Check the validity of a macro binding as far as possible
- X */
- Xcheck_mac_bindings(buf)
- Xchar *buf;
- X{
- X int ok = TRUE;
- X
- X while (ok && buf && *buf) {
- X if (*buf == MAC_LONG_CMD) {
- X char *i;
- X#ifdef CURSES
- X int count;
- X#endif /* CURSES */
- X
- X if (ok)
- X ok = ((i = index(++buf, MAC_LONG_END)) != NULL);
- X if (i)
- X *i = '\0'; /* Don't worry, we'll fix it */
- X else
- X return ok;
- X#ifdef CURSES
- X /* OK to start at C_NULL because of "no-op" command */
- X for (count = 0; count <= C_HELP; count++)
- X if (! strcmp(buf, map_func_names[count].m_str))
- X break;
- X /* Don't allow C_MACRO to be called directly */
- X if (count == C_MACRO)
- X ok = FALSE;
- X else if (count > C_HELP)
- X#endif /* CURSES */
- X if (ok && !(ok = reserved_cmd(buf, FALSE)))
- X wprint("Warning: unrecognized curses command: \"%s\"\n", buf);
- X buf = i;
- X *buf++ = MAC_LONG_END;
- X } else if (*buf++ == '\\' && *buf)
- X ++buf;
- X }
- X return ok;
- X}
- END_OF_FILE
- if test 9279 -ne `wc -c <'mush/macros.c'`; then
- echo shar: \"'mush/macros.c'\" unpacked with wrong size!
- fi
- # end of 'mush/macros.c'
- fi
- if test -f 'mush/main.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'mush/main.c'\"
- else
- echo shar: Extracting \"'mush/main.c'\" \(8938 characters\)
- sed "s/^X//" >'mush/main.c' <<'END_OF_FILE'
- X/* @(#)main.c (c) copyright 10/18/86 (Dan Heller) */
- X
- X#include "mush.h"
- X#include "options.h"
- X
- X#if defined(sun) && defined(M_DEBUG)
- Xcpu()
- X{
- X print("CPU time limit exceeded!\n");
- X}
- X#endif /* sun && DEBUG */
- X
- X#ifdef LCKDFLDIR
- Xextern char *lckdfldir;
- X#endif /* LCKDFLDIR */
- X
- X#ifdef DOT_LOCK
- Xint sgid;
- X#ifdef BSD
- Xint rgid;
- X#endif /* BSD */
- X#endif /* DOT_LOCK */
- X
- X/*ARGSUSED*/ /* we ignore envp */
- Xmain(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X int n;
- X char buf[MAXPATHLEN];
- X register char *p;
- X struct mush_flags Flags;
- X
- X#ifndef INTERNAL_MALLOC
- X extern char *stackbottom; /* used by xfree() */
- X
- X stackbottom = (char *) &argc;
- X#endif /* INTERNAL_MALLOC */
- X
- X#ifdef LCKDFLDIR
- X lckdfldir = LCKDFLDIR;
- X#endif /* LCKDFLDIR */
- X if (prog_name = rindex(*argv, '/'))
- X prog_name++;
- X else
- X prog_name = *argv;
- X
- X (void) signal(SIGBUS, bus_n_seg);
- X (void) signal(SIGSEGV, bus_n_seg);
- X (void) signal(SIGPIPE, SIG_IGN); /* if pager is terminated before end */
- X
- X#if defined(sun) && defined(M_DEBUG)
- X (void) signal(SIGXCPU, cpu);
- X
- X if (p = getenv("MALLOC_DEBUG"))
- X malloc_debug(atoi(p));
- X else
- X malloc_debug(0);
- X#endif /* sun && debug */
- X
- X if (!isatty(0))
- X turnon(glob_flags, REDIRECT);
- X else
- X (void) setbuf(stdin, NULL);
- X
- X (void) cmd_line(strcpy(buf, "set cmd_help"), NULL);
- X
- X init(); /* must be done before checking mail since "login" is set here */
- X mailfile = "";
- X#ifdef HOMEMAIL
- X {
- X char *home = do_set(set_options, "home");
- X if (!home)
- X home = ALTERNATE_HOME;
- X strdup(spoolfile, sprintf(buf, "%s/%s", home, MAILFILE));
- X }
- X#else /* HOMEMAIL */
- X strdup(spoolfile, sprintf(buf, "%s/%s", MAILDIR, login));
- X#endif /* HOMEMAIL */
- X
- X n = preparse_opts(&argc,argv);
- X
- X /* check for any mail at all and exit if we're not continuing */
- X if (!n) {
- X struct stat statb;
- X if (stat(spoolfile, &statb) || statb.st_size == 0) {
- X (void) printf("No mail for %s.\n", login);
- X exit(0);
- X }
- X }
- X
- X#ifdef DOT_LOCK
- X sgid = getegid();
- X#ifdef BSD
- X rgid = getgid();
- X setregid(sgid, rgid);
- X#else
- X setgid(getgid());
- X#endif /* BSD */
- X#endif /* DOT_LOCK */
- X
- X parse_options(&argv, &Flags);
- X
- X set_cwd();
- X
- X if (Flags.init_file)
- X (void) cmd_line(sprintf(buf, "source %s", Flags.init_file), msg_list);
- X if (Flags.source_rc > 0) {
- X /* use cmd_line() in case DEFAULT_RC has expandable chars */
- X (void) cmd_line(sprintf(buf, "source %s", DEFAULT_RC), msg_list);
- X }
- X if (Flags.source_rc > -1)
- X (void) source(0, DUBL_NULL);
- X mailfile = Flags.folder;
- X
- X if (*spoolfile != '/') {
- X n = 1;
- X p = getpath(spoolfile, &n);
- X if (n == -1)
- X (void) fputs(p, stderr), exit(1);
- X else if (n)
- X (void) fprintf(stderr, "\"%s\" is a directory.\n", p), exit(1);
- X else if (*p != '/') {
- X /* if it still isn't a full path, make it one */
- X char *wd = do_set(set_options, "cwd");
- X if (*wd) {
- X (void) sprintf(buf, "%s/%s", wd, p);
- X strdup(spoolfile, buf);
- X } else
- X strdup(spoolfile, p);
- X } else
- X strdup(spoolfile, p);
- X }
- X
- X#ifdef SUNTOOL
- X if (istool) {
- X make_tool();
- X turnon(glob_flags, DO_SHELL);
- X turnoff(glob_flags, REDIRECT); /* -- SunOS-4.0 has a problem here */
- X }
- X#endif /* SUNTOOL */
- X
- X /* now we're ready for I/O */
- X if (isoff(glob_flags, REDIRECT)) {
- X /* make sure we can always recover from no echo mode */
- X (void) signal(SIGINT, catch);
- X (void) signal(SIGQUIT, catch);
- X (void) signal(SIGHUP, catch);
- X if (istool)
- X turnon(glob_flags, ECHO_FLAG);
- X tty_settings();
- X#ifdef SIGCONT
- X (void) signal(SIGTSTP, stop_start); /* this will take care of SIGCONT */
- X#endif /* SIGCONT */
- X /* echo_off() checks to see if echo_flg is set, so don't worry */
- X echo_off();
- X }
- X
- X if (!istool && ison(glob_flags, IS_SENDING)) {
- X char recipients[BUFSIZ], *mailv[16];
- X (void) argv_to_string(recipients, argv);
- X fix_up_addr(recipients);
- X mailv[0] = "mail";
- X n = 1;
- X if (ison(Flags.flg, VERBOSE))
- X mailv[n++] = "-v";
- X if (Flags.Subj && *(Flags.Subj)) {
- X mailv[n++] = "-s";
- X mailv[n++] = Flags.Subj;
- X }
- X if (Flags.Cc && *(Flags.Cc)) {
- X fix_up_addr(Flags.Cc);
- X mailv[n++] = "-c";
- X mailv[n++] = Flags.Cc;
- X }
- X if (Flags.Bcc && *(Flags.Bcc)) {
- X fix_up_addr(Flags.Bcc);
- X mailv[n++] = "-b";
- X mailv[n++] = Flags.Bcc;
- X }
- X if (ison(Flags.flg, NO_SIGN))
- X mailv[n++] = "-u";
- X if (ison(Flags.flg, SEND_NOW))
- X mailv[n++] = "-U";
- X if (Flags.draft) {
- X if (isoff(Flags.flg, SEND_NOW))
- X mailv[n++] = "-E";
- X mailv[n++] = "-h";
- X mailv[n++] = Flags.draft;
- X }
- X mailv[n++] = recipients;
- X mailv[n] = NULL;
- X /* set now in case user is not running shell, but is running debug */
- X#ifndef SUNTOOL
- X (void) signal(SIGCHLD, sigchldcatcher);
- X#endif /* SUNTOOL */
- X if (!setjmp(jmpbuf))
- X (void) do_mail(n, mailv, msg_list);
- X /* do shell set from above: "mush -S user" perhaps */
- X if (isoff(glob_flags, DO_SHELL) && !*mailfile) {
- X if (isoff(glob_flags, REDIRECT))
- X echo_on();
- X exit(0);
- X }
- X }
- X turnoff(glob_flags, IS_SENDING); /* no longer sending mail; running shell */
- X
- X if (ison(glob_flags, REDIRECT)
- X && (!Flags.src_file || !Flags.src_n_exit)) {
- X puts("You can't redirect input unless you're sending mail.");
- X puts("If you want to run a shell with redirection, use \"-i\"");
- X cleanup(0);
- X }
- X if (!*mailfile) {
- X strdup(mailfile, spoolfile);
- X if (!mail_size() && isoff(glob_flags, DO_SHELL)) {
- X /* we know it's not the spool file here */
- X (void) printf("No mail in %s.\n", mailfile);
- X echo_on(), exit(0);
- X }
- X }
- X
- X if (!hdrs_only) {
- X /* catch will test DO_SHELL and try to longjmp if set. this is a
- X * transition state from no-shell to do-shell to ignore sigs to
- X * avoid a longjmp botch. Note setjmp isn't called until do_loop().
- X */
- X turnon(glob_flags, IGN_SIGS);
- X#ifdef CURSES
- X if (ison(glob_flags, PRE_CURSES))
- X (void) curses_init(0, DUBL_NULL);
- X turnoff(glob_flags, PRE_CURSES);
- X#endif /* CURSES */
- X }
- X
- X /* find a free tmpfile */
- X if (!(p = getdir(do_set(set_options, "tmpdir"))))
- Xalted:
- X p = ALTERNATE_HOME;
- X {
- X int pid = getpid();
- X while (!Access(sprintf(tempfile, "%s/.%s%d", p, prog_name, pid++), F_OK))
- X ;
- X }
- X /* just create the file, make sure it's empty. It'll close later and
- X * be reopened for reading only.
- X */
- X if (!(tmpf = mask_fopen(tempfile, "w"))) {
- X if (strcmp(p, ALTERNATE_HOME))
- X goto alted;
- X error("Can't create tempfile %s", tempfile);
- X cleanup(0);
- X }
- X
- X /* do pseudo-intelligent stuff with certain signals */
- X (void) signal(SIGINT, catch);
- X (void) signal(SIGQUIT, catch);
- X (void) signal(SIGHUP, catch);
- X
- X if (!hdrs_only && !istool && (!Flags.src_file || !Flags.src_n_exit) &&
- X !glob(do_set(set_options, "quiet"), "{,{,*[ \\,]}startup{,[ \\,]*}}"))
- X (void) printf("%s: Type '?' for help.\n", check_internal("version"));
- X
- X (void) sprintf(buf, "folder %s %s", Flags.f_flags, mailfile);
- X if ((argv = mk_argv(buf, &argc, TRUE)) && argc > 0) {
- X if (folder(argc, argv, NULL) == -1 && isoff(glob_flags, DO_SHELL)) {
- X if (iscurses)
- X putchar('\n');
- X turnoff(glob_flags, IGN_SIGS), cleanup(0);
- X }
- X#ifdef CURSES
- X if (iscurses)
- X (void) curses_help_msg(TRUE);
- X#endif /* CURSES */
- X free_vec(argv);
- X }
- X
- X if (hdrs_only) {
- X (void) sprintf(buf, "headers %s", hdrs_only);
- X if (argv = make_command(buf, TRPL_NULL, &argc))
- X (void) do_hdrs(argc, argv, NULL);
- X cleanup(0);
- X }
- X
- X turnon(glob_flags, DO_SHELL);
- X if (istool && msg_cnt)
- X set_isread(current_msg);
- X
- X /* finally, if the user wanted to source a file to execute, do it now */
- X if (Flags.src_file) {
- X char *s_argv[2];
- X s_argv[1] = Flags.src_file;
- X (void) source(2, s_argv);
- X if (!istool && Flags.src_n_exit)
- X cleanup(0);
- X }
- X
- X#ifdef SUNTOOL
- X if (istool) {
- X char buf[16];
- X n = 0;
- X (void) cmd_line(strcpy(buf, "set tool_help"), NULL);
- X if (time_out < 30)
- X time_out = 30;
- X turnoff(glob_flags, IGN_SIGS);
- X (void) do_hdrs(0, DUBL_NULL, NULL);
- X timerclear(&(mail_timer.it_interval));
- X timerclear(&(mail_timer.it_value));
- X
- X /* Reload time with value of timeout upon timer expiration. */
- X mail_timer.it_interval.tv_sec = time_out;
- X
- X mail_timer.it_value.tv_sec = time_out;
- X (void) notify_set_itimer_func(tool, do_check,
- X ITIMER_REAL, &mail_timer, (struct itimerval *) 0);
- X timeout_cursors(FALSE);
- X turnoff(glob_flags, DO_UPDATE);
- X window_main_loop(tool);
- X cleanup(0);
- X }
- X#endif /* SUNTOOL */
- X do_loop();
- X}
- X
- Xdo_version()
- X{
- X print("%s\n", check_internal("version"));
- X return -1;
- X}
- X
- X/* set the current working directory */
- Xset_cwd()
- X{
- X char cwd[MAXPATHLEN];
- X#ifndef SYSV
- X extern char *getwd();
- X#else /* SYSV */
- X extern char *getcwd();
- X#endif /* SYSV */
- X
- X#ifndef SYSV
- X if (getwd(cwd) == NULL)
- X#else
- X if (getcwd(cwd, MAXPATHLEN) == NULL)
- X#endif /* SYSV */
- X {
- X error("set_cwd: %s", cwd);
- X (void) un_set(&set_options, "cwd");
- X } else {
- X char *argv[4];
- X argv[0] = "cwd";
- X argv[1] = "=";
- X argv[2] = cwd;
- X argv[3] = NULL;
- X (void) add_option(&set_options, argv);
- X }
- X}
- END_OF_FILE
- if test 8938 -ne `wc -c <'mush/main.c'`; then
- echo shar: \"'mush/main.c'\" unpacked with wrong size!
- fi
- # end of 'mush/main.c'
- fi
- if test -f 'mush/options.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'mush/options.c'\"
- else
- echo shar: Extracting \"'mush/options.c'\" \(8816 characters\)
- sed "s/^X//" >'mush/options.c' <<'END_OF_FILE'
- X/* @(#)options.c (c) copyright 10/10/88 (Dan Heller, Bart Schaefer) */
- X
- X#include "mush.h"
- X#include "options.h"
- X
- X/*
- X * NOTE: Any word flag which is a prefix of another word flag must be
- X * listed AFTER the flag it prefixes in the list below
- X */
- X
- Xchar *word_flags[][2] = {
- X { "-bcc", "-b" },
- X { "-blindcarbon", "-b" },
- X { "-blind", "-b" },
- X { "-carbon", "-c" },
- X { "-cc", "-c" },
- X { "-copy", "-c" },
- X { "-curses", "-C" },
- X { "-debug", "-d" },
- X { "-draft", "-h" },
- X { "-echo", "-e" },
- X { "-folder", "-f" }, /* Maybe -file should become -f too? */
- X { "-file", "-F" }, /* Don't really like -file for -F */
- X { "-headerfile", "-h" },
- X { "-headers", "-H" },
- X { "-initialize", "-I" },
- X { "-init", "-I" },
- X { "-interactive", "-i" },
- X { "-interact", "-i" },
- X { "-mailbox", "-m" },
- X { "-message", "-h" },
- X { "-noheaders", "-N" },
- X { "-noinit", "-n" },
- X { "-readonly", "-r" },
- X { "-send", "-U" },
- X { "-shell", "-S" },
- X { "-source", "-F" }, /* This is better for -F */
- X { "-subject", "-s" },
- X { "-timeout", "-T" },
- X { "-toolhelp", "-2" },
- X { "-tool", "-t" },
- X { "-user", "-u" },
- X { "-verbose", "-v" },
- X { "-visual", "-C" },
- X { NULL, NULL } /* This must be the last entry */
- X};
- X
- Xfix_word_flag(argp)
- Xregister char **argp;
- X{
- X int i;
- X
- X Debug("%s --> ", *argp);
- X for (i = 0; word_flags[i][0]; i++) {
- X int len = strlen(word_flags[i][0]);
- X if (! strncmp(*argp, word_flags[i][0], len)) {
- X char buf[BUFSIZ], *p = buf;
- X p += Strcpy(buf, word_flags[i][1]);
- X (void) strcpy(p, *argp + len);
- X (void) strcpy(*argp, buf);
- X }
- X }
- X Debug("%s\n", *argp);
- X}
- X
- X/*
- X * preparse the command line to determine whether or not we're going
- X * to bail out after checking that the user has no mail. Also, check
- X * to see if we're going to run a tool because it must be built first.
- X */
- Xpreparse_opts(argcp, argv)
- Xregister int *argcp; /* Pointer to argument count */
- Xregister char **argv; /* Argument vector */
- X{
- X int n = FALSE;
- X char **args;
- X
- X#ifdef SUNTOOL
- X /* Note: we are assigning a boolean result to n and istool here */
- X if (n = istool = (strlen(prog_name) > 3 &&
- X (!strcmp(prog_name+strlen(prog_name)-4, "tool") ||
- X !strcmp(prog_name+strlen(prog_name)-4, "view")))) {
- X turnon(glob_flags, DO_SHELL);
- X parse_tool_opts(argcp, argv);
- X }
- X#endif /* SUNTOOL */
- X
- X if (!istool && *argcp > 1) {
- X for (args = argv+1; *args && args[0][0] == '-'; args++) {
- X int next = 1;
- X fix_word_flag(&args[0]);
- XDoNext:
- X switch (args[0][next]) {
- X#ifdef SUNTOOL
- X case 'T' :
- X if (args[1])
- X args++;
- X case 't' :
- X /* Note: we won't ever get here if started as
- X * "mushtool" or "mushview" because istool is true.
- X */
- X istool = 1;
- X parse_tool_opts(argcp, argv);
- X turnon(glob_flags, DO_SHELL);
- X return TRUE;
- X /* break; */
- X#endif /* SUNTOOL */
- X case 'S' :
- X turnon(glob_flags, DO_SHELL);
- X n = TRUE;
- X break;
- X case 'f' :
- X case 'F' :
- X case 'h' :
- X case 'm' :
- X case 'u' :
- X n = TRUE;
- X case 'b' :
- X case 'c' :
- X case 'I' :
- X case 's' :
- X if (args[1]) {
- X args++;
- X next = 0;
- X }
- X break;
- X case 'H' :
- X if (args[0][next+1] == ':')
- X next = 0;
- X break;
- X case '\0':
- X next = 0;
- X default : ;
- X }
- X if (next) {
- X ++next;
- X goto DoNext;
- X }
- X }
- X if (*args) { /* unused args indicates sending mail to someone */
- X n = TRUE;
- X if (!istool)
- X turnon(glob_flags, IS_SENDING);
- X }
- X }
- X
- X return n;
- X}
- X
- Xstatic char *usage_str =
- X#ifdef SUNTOOL
- X "usage: %s [-t] [-C] [-i] [-f [folder] ] [-v] [-S] [-s subject] [users]\n";
- X#else
- X#ifdef CURSES
- X "usage: %s [-C] [-i] [-f [folder] ] [-v] [-S] [-s subject] [user list]\n";
- X#else
- X "usage: %s [-i] [-f [folder] ] [-v] [-S] [-s subject] [user list]\n";
- X#endif /* CURSES */
- X#endif /* SUNTOOL */
- X
- Xparse_options(argvp, flags)
- Xregister char ***argvp;
- Xstruct mush_flags *flags;
- X{
- X char buf[256];
- X
- X bzero((char *) flags, sizeof (struct mush_flags));
- X flags->source_rc = TRUE;
- X flags->folder = "";
- X
- X for (++(*argvp); **argvp && ***argvp == '-'; (*argvp)++) {
- X int look_again;
- XDoLookAgain:
- X look_again = TRUE;
- X switch ((*argvp)[0][1]) {
- X case 'e':
- X /*
- X * don't set tty modes -- e.g. echo and cbreak modes aren't
- X * changed.
- X */
- X turnon(glob_flags, ECHO_FLAG);
- X#ifdef CURSES
- X when 'C':
- X /* don't init curses -- don't even set iscurses. */
- X if (istool) {
- X puts("-C: You are already running in tool mode");
- X turnoff(glob_flags, PRE_CURSES);
- X } else if (hdrs_only)
- X puts("headers only: ignoring -C flag");
- X else
- X turnon(glob_flags, PRE_CURSES);
- X#endif /* CURSES */
- X when 'F':
- X flags->src_n_exit = ((*argvp)[0][2] == '!');
- X if (!(flags->src_file = *++(*argvp)))
- X puts("specify filename to source"), exit(1);
- X look_again = FALSE;
- X /* fall thru! */
- X case 'N':
- X (void) strcat(flags->f_flags, "-N ");
- X when 'r':
- X (void) strcat(flags->f_flags, "-r "); /* folder() argument */
- X when 'H':
- X if (istool) {
- X puts("running in tool-mode; -H option ignored.");
- X break;
- X }
- X turnoff(glob_flags, PRE_CURSES);
- X if (*(hdrs_only = (*(*argvp))+2) != ':')
- X hdrs_only = ":a";
- X else
- X look_again = FALSE;
- X /* read only cuz no updates */
- X (void) strcat(flags->f_flags, "-N -r ");
- X when 'i':
- X /* force interactive even if !isatty(0) */
- X turnoff(glob_flags, REDIRECT);
- X when 'u': /* specify a user's mailbox */
- X if (*(flags->folder))
- X puts("You can't specify more than one mailbox"), exit(1);
- X#ifdef HOMEMAIL
- X {
- X char *p;
- X int isdir = 1;
- X (void) sprintf(buf, "%%%s",
- X (*argvp)[1] ? (*argvp)[1] : "root");
- X if ((p = getpath(buf, &isdir)) && !isdir)
- X strdup(flags->folder, p);
- X else if (isdir < 0)
- X puts(p), exit(1);
- X else if (isdir)
- X (void) printf("\"%s\" is a directory\n", p), exit(1);
- X }
- X#else /* HOMEMAIL */
- X strdup(flags->folder, sprintf(buf, "%s/%s",
- X MAILDIR, ((*argvp)[1])? (*argvp)[1] : "root"));
- X#endif /* HOMEMAIL */
- X if ((*argvp)[1])
- X ++(*argvp);
- X look_again = FALSE;
- X when 'h':
- X if (istool)
- X puts("bad option when run as a tool"), exit(1);
- X if ((*argvp)[1])
- X flags->draft = *++(*argvp);
- X else
- X (void) printf("-h: missing file name.\n"), exit(1);
- X look_again = FALSE;
- X turnon(glob_flags, IS_SENDING);
- X when 'U':
- X if (istool)
- X puts("bad option when run as a tool"), exit(1);
- X turnon(flags->flg, SEND_NOW);
- X if ((*argvp)[0][2] == '!') {
- X turnon(flags->flg, NO_SIGN);
- X ++(**argvp);
- X }
- X when 'm':
- X if ((*argvp)[1])
- X strdup(spoolfile, *++(*argvp));
- X else
- X (void) printf("-m: missing mailbox name.\n"), exit(1);
- X look_again = FALSE;
- X when 'f':
- X if (*(flags->folder))
- X puts("You can't specify more than one mailbox"), exit(1);
- X if ((*argvp)[1]) {
- X strdup(flags->folder, *++(*argvp));
- X look_again = FALSE;
- X } else
- X strdup(flags->folder, "&");
- X when 's':
- X if (istool)
- X puts("bad option when run as a tool"), exit(1);
- X else if ((*argvp)[1])
- X flags->Subj = *++(*argvp);
- X else
- X puts("-s \"subject\""), exit(1);
- X look_again = FALSE;
- X when 'b':
- X if (istool)
- X puts("-b: bad option when run as a tool"), exit(1);
- X else if ((*argvp)[1])
- X flags->Bcc = *++(*argvp);
- X else
- X puts("-b \"bcc list\""), exit(1);
- X look_again = FALSE;
- X when 'c':
- X if (istool)
- X puts("-c: bad option when run as a tool"), exit(1);
- X else if ((*argvp)[1])
- X flags->Cc = *++(*argvp);
- X else
- X puts("-c \"cc list\""), exit(1);
- X look_again = FALSE;
- X break;
- X#ifdef VERBOSE_ARG
- X case 'v':
- X if (istool)
- X puts("bad option when run as a tool"), exit(1);
- X turnon(flags->flg, VERBOSE);
- X break;
- X#endif /* VERBOSE_ARG */
- X#ifdef SUNTOOL
- X case 'T':
- X if ((time_out = atoi(*(*argvp))) <= 29)
- X time_out = 30;
- X look_again = FALSE;
- X /* -T implies -t */
- X case 't': istool = 1;
- X#endif /* SUNTOOL */
- X case 'S': turnon(glob_flags, DO_SHELL);
- X when 'n':
- X if ((*argvp)[0][2] == '!') {
- X ++(**argvp);
- X flags->source_rc = -1; /* No init files sourced */
- X } else
- X flags->source_rc = 0; /* Only ~/.mushrc sourced */
- X when 'I':
- X if ((*argvp)[0][2] == '!' && flags->source_rc > 0)
- X flags->source_rc = 0; /* Only ~/.mushrc sourced */
- X if (!(flags->init_file = *++(*argvp)))
- X puts("specify filename for init"), exit(1);
- X look_again = FALSE;
- X when 'd': debug = 1;
- X when '\0' : look_again = FALSE;
- X otherwise:
- X print("%s: unknown option: `%c'\n", prog_name,
- X (*argvp)[0][1]? (*argvp)[0][1] : '-');
- X print(usage_str, prog_name);
- X }
- X if (look_again && ++(**argvp) != '\0')
- X goto DoLookAgain;
- X }
- X
- X if (ison(flags->flg, SEND_NOW) && !flags->draft) {
- X print("You must specify a draft file to autosend\n");
- X exit(1);
- X }
- X}
- END_OF_FILE
- if test 8816 -ne `wc -c <'mush/options.c'`; then
- echo shar: \"'mush/options.c'\" unpacked with wrong size!
- fi
- # end of 'mush/options.c'
- fi
- if test -f 'mush/print.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'mush/print.c'\"
- else
- echo shar: Extracting \"'mush/print.c'\" \(5410 characters\)
- sed "s/^X//" >'mush/print.c' <<'END_OF_FILE'
- X/* @(#)print.c 2.4 (c) copyright 10/15/86 (Dan Heller) */
- X
- X#include "mush.h"
- X#include <varargs.h>
- X
- X/*ARGSUSED*/
- X/*VARARGS1*/
- Xvoid
- Xerror(fmt, arg1, arg2, arg3, arg4)
- Xregister char *fmt;
- Xchar *arg1, *arg2, *arg3, *arg4;
- X{
- X char buf[BUFSIZ];
- X
- X (void) sprintf(buf, fmt, arg1, arg2, arg3, arg4);
- X sprintf(buf+strlen(buf), ": %s\n", sys_errlist[errno]);
- X#ifdef SUNTOOL
- X if (istool > 1)
- X ok_box(buf);
- X else
- X#endif /* SUNTOOL */
- X print(buf);
- X}
- X
- X#if defined(SUNTOOL) || defined(CURSES)
- X/*
- X * print just like printf -- to a window, to curses, or to stdout. Use vprintf
- X * if available. msgbuf is the buffer used to print into if necessary.
- X * If you're running SUN3.2 or higher, the typecast (unsigned char *)msgbuf
- X * (where indicated) otherwise, msgbuf is not typecast at all.
- X */
- X/*VARARGS*/
- Xvoid
- Xprint(va_alist)
- Xva_dcl
- X{
- X static char msgbuf[BUFSIZ];
- X char *fmt;
- X va_list args;
- X#ifndef VPRINTF
- X FILE foo;
- X#endif /* VPRINTF */
- X static int x; /* position on line saved for continued prints */
- X char *p; /* same type as struct file _ptr,_buf in stdio.h */
- X
- X#ifdef CURSES
- X if (iscurses) {
- X if (isoff(glob_flags, CONT_PRNT))
- X move(LINES-1, x = 0), refresh();
- X } else
- X#endif /* CURSES */
- X if (istool < 2) {
- X va_start(args);
- X fmt = va_arg(args, char *);
- X#ifdef VPRINTF
- X (void) vprintf(fmt, args);
- X#else /* VPRINTF */
- X _doprnt(fmt, args, stdout);
- X#endif /* VPRINTF */
- X va_end(args);
- X (void) fflush(stdout);
- X return;
- X }
- X va_start(args);
- X fmt = va_arg(args, char *);
- X if (fmt) {
- X#ifdef VPRINTF
- X (void) vsprintf(msgbuf, fmt, args); /* NULL in fmt reprints last msg */
- X#else /* VPRINTF */
- X foo._cnt = BUFSIZ;
- X foo._base = foo._ptr = msgbuf; /* may have to cast(unsigned char *) */
- X foo._flag = _IOWRT+_IOSTRG;
- X (void) _doprnt(fmt, args, &foo);
- X *foo._ptr = '\0'; /* plant terminating null character */
- X#endif /* VPRINTF */
- X }
- X va_end(args);
- X if (istool) {
- X wprint("%s", msgbuf);
- X return;
- X }
- X p = msgbuf;
- X if (iscurses)
- X while (p = index(p, '\n'))
- X *p = ' ';
- X#ifdef CURSES
- X if (iscurses) {
- X p = msgbuf;
- X for (;;) {
- X int len = COLS-1-x; /* space remaining at till the eol */
- X /* don't wrap the line! Just print it and refresh() */
- X printw("%-.*s", len, p), clrtoeol(), refresh();
- X /* if length(p) (remainder of msgbuf) doesn't wrap, break loop */
- X if ((x += strlen(p)) < COLS-1)
- X break;
- X /* the next print will overwrite bottom line, so \n first */
- X putchar('\n'), move(LINES-1, x = 0); /* reset x */
- X /* move p forward the number of chars we were able to display */
- X p += len;
- X turnon(glob_flags, CNTD_CMD); /* display ...continue... prompt */
- X }
- X turnoff(glob_flags, CONT_PRNT);
- X (void) fflush(stdout); /* some sys-v's aren't fflushing \n's */
- X return;
- X }
- X#endif /* CURSES */
- X}
- X
- X#endif /* SUNTOOL || CURSES */
- X
- X/* for curses mode */
- Xclr_bot_line()
- X{
- X print("");
- X}
- X
- X#ifdef SUNTOOL
- X
- X/*
- X * wprint prints stuff to a scrollable textsw. This is intended for
- X * print statements that need to be recalled since print() overwrites
- X * its last message. Messages are printed to whatever wprint_sw
- X * currently points to. If you set it to null, nothing prints.
- X * For non-suntool mode, wprint() is just like printf(). For curses mode,
- X * wprint() does -not- act like print() -- lines length is not counted
- X * and newlines are not stripped.
- X */
- X/*VARARGS*/
- Xvoid
- Xwprint(va_alist)
- Xva_dcl
- X{
- X#ifndef VPRINTF
- X FILE foo;
- X#endif /* VPRINTF */
- X char msgbuf[BUFSIZ]; /* we're not getting huge strings */
- X char *fmt;
- X va_list args;
- X
- X if (istool < 2) {
- X va_start(args);
- X fmt = va_arg(args, char *);
- X#ifdef VPRINTF
- X (void) vprintf(fmt, args);
- X#else /* VPRINTF */
- X _doprnt(fmt, args, stdout);
- X#endif /* VPRINTF */
- X va_end(args);
- X (void) fflush(stdout);
- X return;
- X }
- X if (!compose_frame || !window_get(compose_frame, WIN_SHOW) || !cprint_sw)
- X wprint_sw = mfprint_sw;
- X else
- X wprint_sw = cprint_sw;
- X
- X if (!wprint_sw)
- X return;
- X va_start(args);
- X fmt = va_arg(args, char *);
- X if (fmt) {
- X#ifdef VPRINTF
- X (void) vsprintf(msgbuf, fmt, args); /* NULL in fmt reprints last msg */
- X#else /* VPRINTF */
- X foo._cnt = BUFSIZ;
- X foo._base = foo._ptr = msgbuf; /* may have to cast (unsigned char *) */
- X foo._flag = _IOWRT+_IOSTRG;
- X _doprnt(fmt, args, &foo); /* format like printf into msgbuf via foo */
- X *foo._ptr = '\0'; /* plant terminating null character */
- X#endif /* VPRINTF */
- X textsw_insert(wprint_sw, msgbuf, strlen(msgbuf));
- X }
- X va_end(args);
- X}
- X
- X#include <sundev/kbio.h>
- X#include <sundev/kbd.h>
- X
- Xbell()
- X{
- X#ifdef KIOCCMD
- X if (istool) {
- X int kbd = open("/dev/kbd", O_WRONLY, 0);
- X struct timeval timer;
- X timer.tv_sec = 0;
- X timer.tv_usec = 100000;
- X if (kbd != -1) {
- X int cmd = KBD_CMD_BELL;
- X (void) ioctl(kbd, KIOCCMD, &cmd);
- X (void) select(32, (fd_set *) 0,(fd_set *) 0,(fd_set *) 0, &timer);
- X cmd = KBD_CMD_NOBELL;
- X (void) ioctl(kbd, KIOCCMD, &cmd);
- X (void) close(kbd);
- X }
- X } else
- X#endif /* KIOCCMD */
- X (void) fputc('\007', stderr), (void) fflush(stderr);
- X return 0;
- X}
- X
- X#endif /* SUNTOOL */
- X
- X#ifdef BSD
- X#undef fputs
- X
- X/*
- X * The standard 4.x BSD fputs() does not return any useful value.
- X * For compatibility with Sun and SysV fputs(), we use this wrapper.
- X */
- X
- XFputs(line, fp)
- Xchar *line;
- XFILE *fp;
- X{
- X clearerr(fp);
- X (void) fputs(line, fp);
- X if (ferror(fp))
- X return EOF;
- X return 0;
- X}
- X
- X#endif /* BSD */
- END_OF_FILE
- if test 5410 -ne `wc -c <'mush/print.c'`; then
- echo shar: \"'mush/print.c'\" unpacked with wrong size!
- fi
- # end of 'mush/print.c'
- fi
- if test -f 'mush/sort.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'mush/sort.c'\"
- else
- echo shar: Extracting \"'mush/sort.c'\" \(8063 characters\)
- sed "s/^X//" >'mush/sort.c' <<'END_OF_FILE'
- X/* sort.c 3.0 (c) copyright 1986,1990 (Dan Heller) */
- X
- X#include "mush.h"
- X/* #define MYQSORT */
- X
- X/* The size of this array should really be bounded by
- X * 2 spaces for each possible different sort criteria
- X * (one space for each key letter and one per for 'r'),
- X * but 16 leaves room to add to the current list.
- X */
- Xstatic char subsort[16];
- X
- Xstatic int depth, order, ignore_case;
- Xstatic jmp_buf sortbuf;
- X
- Xsort(argc, argv, list)
- Xregister int argc;
- Xregister char *argv[], list[];
- X{
- X int msg_cmp();
- X SIGRET (*oldint)(), (*oldquit)();
- X int n, offset = -1, range = 0;
- X long curr_msg_off = msg[current_msg].m_offset;
- X
- X depth = 0, order = 1, ignore_case = FALSE;
- X
- X while (argc && *++argv) {
- X n = (argv[0][0] == '-' && argv[0][1] != 0);
- X while (argv[0][n]) {
- X if (depth > sizeof subsort - 2)
- X break;
- X switch(argv[0][n]) {
- X case '-': /* reverse order of next criteria (obsolete) */
- X argv[0][n] = 'r'; /* fix it and fall through */
- X case 'r': /* reverse order of next criteria */
- X case 'd': /* sort by date */
- X case 'a': /* sort by author (address) */
- X case 's': /* sort by subject (ignore Re:) */
- X case 'R': /* sort by subject including Re: */
- X case 'l': /* sort by length in bytes */
- X case 'S': /* sort by message status */
- X /* skip consecutive repeats of the same flag */
- X if (subsort[depth-1] != argv[0][n])
- X subsort[depth++] = argv[0][n];
- X when 'i': ignore_case = TRUE;
- X otherwise: return help(0, "sort", cmd_help);
- X }
- X n++;
- X }
- X }
- X if (depth == 0 || subsort[depth-1] == 'r')
- X subsort[depth++] = 'S'; /* status sort is the default */
- X subsort[depth] = 0;
- X depth = 0; /* start at the beginning */
- X if (msg_cnt <= 1) {
- X print("Not enough messages to sort.\n");
- X return -1;
- X }
- X turnon(glob_flags, IGN_SIGS);
- X on_intr();
- X
- X if (list && ison(glob_flags, IS_PIPE)) {
- X for (n = 0; n < msg_cnt; n++)
- X if (msg_bit(list, n)) {
- X if (offset < 0)
- X offset = n;
- X range++;
- X } else if (offset >= 0)
- X break;
- X } else
- X offset = 0, range = msg_cnt;
- X
- X if (range < 2)
- X print("Range not broad enough to sort anything\n");
- X else {
- X Debug("Sorting %d messages starting at message %d\n", range, offset+1);
- X
- X if (setjmp(sortbuf) == 0)
- X qsort((char *)&msg[offset], range, sizeof (struct msg), msg_cmp);
- X else
- X print("WARNING: Sorting interrupted: unpredictable order.\n");
- X turnon(glob_flags, DO_UPDATE);
- X }
- X for (n = 0; n < msg_cnt; n++)
- X if (msg[n].m_offset == curr_msg_off)
- X break;
- X current_msg = n;
- X turnoff(glob_flags, IGN_SIGS);
- X off_intr();
- X /* Break pipes because message lists are invalid */
- X return 0 - in_pipe();
- X}
- X
- X#ifdef MYQSORT
- Xqsort(base, len, siz, compar)
- Xregister struct msg *base;
- Xint (*compar)();
- X{
- X register int i, swapping;
- X struct msg temp;
- X
- X do {
- X swapping = 0;
- X for (i = 0; i < len-1; ++i) {
- X if (compar(base+i, base+i+1) > 0) {
- X temp = base[i];
- X base[i] = base[i+1];
- X base[i+1] = temp;
- X swapping = 1;
- X }
- X }
- X } while (swapping);
- X}
- X#endif /* MYSORT */
- X
- Xstatus_cmp(msg1, msg2)
- Xregister struct msg *msg1, *msg2;
- X{
- X if (msg1->m_flags == msg2->m_flags)
- X return msg_cmp(msg1, msg2);
- X if (ison(msg1->m_flags, DELETE) && isoff(msg2->m_flags, DELETE))
- X return order;
- X if (isoff(msg1->m_flags, DELETE) && ison(msg2->m_flags, DELETE))
- X return -order;
- X if (isoff(msg1->m_flags, OLD) && ison(msg2->m_flags, OLD))
- X return -order;
- X if (ison(msg1->m_flags, OLD) && isoff(msg2->m_flags, OLD))
- X return order;
- X if (ison(msg1->m_flags, UNREAD) && isoff(msg2->m_flags, UNREAD))
- X return -order;
- X if (isoff(msg1->m_flags, UNREAD) && ison(msg2->m_flags, UNREAD))
- X return order;
- X if (ison(msg1->m_flags,PRESERVE) && isoff(msg2->m_flags,PRESERVE))
- X return -order;
- X if (isoff(msg1->m_flags,PRESERVE) && ison(msg2->m_flags,PRESERVE))
- X return order;
- X if (ison(msg1->m_flags,REPLIED) && isoff(msg2->m_flags,REPLIED))
- X return -order;
- X if (isoff(msg1->m_flags,REPLIED) && ison(msg2->m_flags,REPLIED))
- X return order;
- X if (ison(msg1->m_flags,SAVED) && isoff(msg2->m_flags,SAVED))
- X return -order;
- X if (isoff(msg1->m_flags,SAVED) && ison(msg2->m_flags,SAVED))
- X return order;
- X if (ison(msg1->m_flags,PRINTED) && isoff(msg2->m_flags,PRINTED))
- X return -order;
- X if (isoff(msg1->m_flags,PRINTED) && ison(msg2->m_flags,PRINTED))
- X return order;
- X if (ison(msg1->m_flags,FORWARD) && isoff(msg2->m_flags,FORWARD))
- X return -order;
- X if (isoff(msg1->m_flags,FORWARD) && ison(msg2->m_flags,FORWARD))
- X return order;
- X
- X return order;
- X}
- X
- Xauthor_cmp(msg1, msg2)
- Xregister struct msg *msg1, *msg2;
- X{
- X char buf1[HDRSIZ], buf2[HDRSIZ];
- X int retval;
- X
- X (void) reply_to(msg1 - msg, 0, buf1); /* "0" for "author only" */
- X (void) reply_to(msg2 - msg, 0, buf2);
- X Debug("author: msg %d: %s, msg %d: %s\n", msg1-msg, buf1, msg2-msg, buf2);
- X if (ignore_case)
- X retval = lcase_strncmp(buf1, buf2, -1) * order;
- X else
- X retval = strcmp(buf1, buf2) * order;
- X return retval ? retval : msg_cmp(msg1, msg2);
- X}
- X
- X/* compare messages according to size (length) */
- Xsize_cmp(msg1, msg2)
- Xregister struct msg *msg1, *msg2;
- X{
- X int retval;
- X
- X Debug("sizes: (%d): %d, (%d): %d\"\n",
- X msg1-msg, msg1->m_size, msg2-msg, msg2->m_size);
- X if (retval = (msg1->m_size - msg2->m_size) * order) /* assign and test */
- X return retval;
- X return msg_cmp(msg1, msg2);
- X}
- X
- X/*
- X * Subject comparison ignoring Re: subject_to() appends an Re: if there is
- X * any subject whatsoever.
- X */
- Xsubject_cmp(msg1, msg2)
- Xregister struct msg *msg1, *msg2;
- X{
- X char buf1[HDRSIZ], buf2[HDRSIZ];
- X register char *p1, *p2;
- X int retval;
- X
- X p1 = subject_to(msg1 - msg, buf1);
- X p2 = subject_to(msg2 - msg, buf2);
- X if (p1) {
- X p1 += 4;
- X while (isspace(*p1))
- X p1++;
- X } else
- X p1 = buf1; /* subject_to() makes it an empty string */
- X if (p2) {
- X p2 += 4;
- X while (isspace(*p2))
- X p2++;
- X } else
- X p2 = buf2; /* subject_to() makes it an empty string */
- X Debug("subjects: (%d): \"%s\" (%d): \"%s\"\n", msg1-msg, p1, msg2-msg, p2);
- X if (ignore_case)
- X retval = lcase_strncmp(p1, p2, -1) * order;
- X else
- X retval = strcmp(p1, p2) * order;
- X return retval ? retval : msg_cmp(msg1, msg2);
- X}
- X
- X/*
- X * compare subject strings from two messages.
- X * If Re is appended, so be it -- if user wants to ignore Re: use 'R' flag.
- X */
- Xsubj_with_re(msg1, msg2)
- Xregister struct msg *msg1, *msg2;
- X{
- X char buf1[HDRSIZ], buf2[HDRSIZ], *p;
- X int retval;
- X
- X if (!(p = header_field(msg1 - msg, "subject")))
- X p = "";
- X (void) strcpy(buf1, p);
- X if (!(p = header_field(msg2 - msg, "subject")))
- X p = "";
- X (void) strcpy(buf2, p);
- X Debug("subjects: (%d): \"%s\" (%d): \"%s\"\n",
- X msg1-msg, buf1, msg2-msg, buf2);
- X if (ignore_case)
- X retval = lcase_strncmp(buf1, buf2, -1) * order;
- X else
- X retval = strcmp(buf1, buf2) * order;
- X return retval ? retval : msg_cmp(msg1, msg2);
- X}
- X
- Xdate_cmp(msg1, msg2)
- Xregister struct msg *msg1, *msg2;
- X{
- X int retval;
- X long tm1, tm2;
- X
- X if (ison(glob_flags, DATE_RECV)) {
- X (void) sscanf(msg1->m_date_recv, "%ld", &tm1);
- X (void) sscanf(msg2->m_date_recv, "%ld", &tm2);
- X } else {
- X (void) sscanf(msg1->m_date_sent, "%ld", &tm1);
- X (void) sscanf(msg2->m_date_sent, "%ld", &tm2);
- X }
- X return tm1 < tm2 ? -order : (tm1 > tm2) ? order : msg_cmp(msg1, msg2);
- X}
- X
- Xstatic
- Xmsg_cmp(msg1, msg2)
- Xregister struct msg *msg1, *msg2;
- X{
- X int sv_order = order, sv_depth = depth, retval = 0;
- X
- X if (ison(glob_flags, WAS_INTR))
- X longjmp(sortbuf, 1);
- X if (msg1 < msg || msg2 < msg) {
- X wprint("sort botch trying to sort %d and %d using %s\n",
- X msg1-msg, msg2-msg, subsort);
- X return 0;
- X }
- X
- X if (subsort[depth] == 'r') {
- X order = -1;
- X depth++;
- X } else
- X order = 1;
- X switch(subsort[depth++]) {
- X case '\0': retval = 0;
- X when 'd': retval = date_cmp(msg1, msg2);
- X when 'a': retval = author_cmp(msg1, msg2);
- X when 's': retval = subject_cmp(msg1, msg2);
- X when 'R': retval = subj_with_re(msg1, msg2);
- X when 'l': retval = size_cmp(msg1, msg2); /* length compare */
- X otherwise: retval = status_cmp(msg1, msg2);
- X }
- X depth = sv_depth;
- X order = sv_order;
- X return retval;
- X}
- END_OF_FILE
- if test 8063 -ne `wc -c <'mush/sort.c'`; then
- echo shar: \"'mush/sort.c'\" unpacked with wrong size!
- fi
- # end of 'mush/sort.c'
- fi
- echo shar: End of archive 18 \(of 19\).
- cp /dev/null ark18isdone
- 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
-
-
-