v18i035: Mail user's shell version 6.4, Part13/19
Rich Salz
rsalz at bbn.com
Sat Mar 18 04:37:07 AEST 1989
Submitted-by: Dan Heller <island!argv at sun.com>
Posting-number: Volume 18, Issue 35
Archive-name: mush6.4/part13
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 13 (of 19)."
# Contents: commands.c
# Wrapped by rsalz at papaya.bbn.com on Mon Mar 13 19:25:19 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'commands.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'commands.c'\"
else
echo shar: Extracting \"'commands.c'\" \(29012 characters\)
sed "s/^X//" >'commands.c' <<'END_OF_FILE'
X/* @(#)commands.c (c) copyright 10/18/86 (Dan Heller) */
X
X#include "mush.h"
X
X/*
X * Note that all of the routines in here act upon and return 0 or -1.
X * if -1, then the main loop will clear message lists.
X */
X
Xstruct cmd cmds[] = {
X#ifdef SIGSTOP
X { "stop", stop },
X#endif /* SIGSTOP */
X { "?", question_mark },{ "sh", sh },
X { "alias", do_alias }, { "unalias", do_alias },
X { "expand", do_alias }, { "cmd", do_alias },
X { "uncmd", do_alias }, { "from", do_from },
X { "un_hdr", do_alias }, { "my_hdr", do_alias },
X { "fkey", do_alias }, { "unfkey", do_alias },
X { "set", set }, { "unset", set },
X { "ignore", set }, { "unignore", set },
X { "version", do_version }, { "help", print_help },
X { "pick", do_pick }, { "sort", sort },
X { "next", readmsg }, { "previous", readmsg },
X { "type", readmsg }, { "print", readmsg },
X { "history", disp_hist }, { "top", readmsg },
X { "saveopts", save_opts }, { "source", source },
X { "headers", do_hdrs }, { "ls", ls },
X { "folder", folder }, { "update", folder },
X { "cd", cd }, { "pwd", cd },
X { "exit", quit }, { "quit", quit },
X { "write", save_msg }, { "save", save_msg },
X { "copy", save_msg }, { "folders", folders },
X { "merge", merge_folders },
X#ifdef CURSES
X { "curses", curses_init }, { "bind", bind_it },
X { "unbind", bind_it }, { "bind-macro", bind_it },
X { "unbind-macro", bind_it },
X#endif /* CURSES */
X { "map", bind_it }, { "unmap", bind_it },
X { "map!", bind_it }, { "unmap!", bind_it },
X { "preserve", preserve }, { "unpreserve", preserve },
X { "replyall", respond }, { "replysender", respond },
X { "delete", delete }, { "undelete", delete },
X { "mail", do_mail }, { "echo", do_echo },
X { "lpr", lpr }, { "alternates", alts },
X { "edit", edit_msg }, { "flags", msg_flags },
X { "pipe", pipe_msg }, { "eval", eval_cmd },
X { "undigest", do_undigest },
X { NULL, quit }
X};
X
Xstruct cmd ucb_cmds[] = {
X { "t", readmsg }, { "n", readmsg }, { "p", readmsg },
X { "+", readmsg }, { "-", readmsg }, { "P", readmsg },
X { "Print", readmsg }, { "T", readmsg }, { "Type", readmsg },
X { "x", quit }, { "xit", quit }, { "q", quit },
X { ":a", do_hdrs }, { ":d", do_hdrs }, { ":r", do_hdrs },
X { ":o", do_hdrs }, { ":u", do_hdrs }, { ":n", do_hdrs },
X { ":s", do_hdrs }, { ":p", do_hdrs },
X { "z", do_hdrs }, { "z-", do_hdrs }, { "z+", do_hdrs },
X { "h", do_hdrs }, { "H", do_hdrs },
X { "f", do_from }, { "m", do_mail }, { "alts", alts },
X { "d", delete }, { "dt", delete }, { "dp", delete },
X { "u", delete }, { "fo", folder },
X { "s", save_msg }, { "co", save_msg }, { "w", save_msg },
X { "pre", preserve }, { "unpre", preserve },
X { "R", respond }, { "r", respond },
X { "reply", respond }, { "respond", respond },
X { "v", edit_msg }, { "e", edit_msg },
X { NULL, quit }
X};
X
Xstruct cmd hidden_cmds[] = {
X { "debug", toggle_debug }, { "open", nopenfiles },
X { "stty", my_stty },
X { "setenv", Setenv }, { "unsetenv", Unsetenv },
X { "printenv", Printenv }, { "Pipe", pipe_msg },
X { NULL, quit }
X};
X
Xtoggle_debug(argc, argv)
Xchar **argv;
X{
X if (argc < 2) /* no value -- toggle "debug" (off/on) */
X debug = !debug;
X else
X debug = atoi(*++argv);
X print("debugging value: %d\n", debug);
X return 0;
X}
X
X/* if + was specified, then print messages without headers.
X * n or \n (which will be NULL) will print next unread or undeleted message.
X */
Xreadmsg(x, argv, list)
Xregister char **argv, list[];
X{
X register char *p = x? *argv : NULL;
X register long flg = 0;
X extern FILE *ed_fp;
X
X if (x && *++argv && !strcmp(*argv, "-?"))
X return help(0, "readmsg", cmd_help);
X /* View a message as long as user isn't in the editor. If is_getting
X * is set, then the user is typing in a letter (or something else not
X * threatening in tool mode). If ed_fp is not null, then we've got the
X * file open for typing. If it's NULL, then an editor is going.
X */
X if (ison(glob_flags, IS_GETTING) && !ed_fp) {
X print("Not while you're in the editor, you don't.\n");
X return -1;
X }
X if (!msg_cnt) {
X print("No messages.\n");
X return -1;
X }
X if (x)
X if (!strcmp(p, "top"))
X turnon(flg, M_TOP);
X else if (*p == '+') {
X turnon(flg, NO_PAGE);
X turnon(flg, NO_HEADER);
X } else if (isupper(*p))
X turnon(flg, NO_IGNORE);
X
X if (x && (x = get_msg_list(argv, list)) == -1)
X return -1;
X else if (x == 0) { /* no arguments were parsed (or given) */
X /* get_msg_list sets current msg on */
X if (isoff(glob_flags, IS_PIPE))
X unset_msg_bit(list, current_msg);
X /* most commands move to the "next" message. type and print don't */
X if ((!p || !*p || *p == 'n' || *p == '+') && current_msg < msg_cnt &&
X isoff(msg[current_msg].m_flags, UNREAD))
X current_msg++;
X if (p && (*p == '-' || !strcmp(p, "previous"))) {
X while (--current_msg >= 0 &&
X (ison(msg[current_msg].m_flags, DELETE) ||
X ison(msg[current_msg].m_flags, SAVED)))
X ;
X if (current_msg < 0) {
X print("No previous message.\n");
X current_msg = 0;
X return -1;
X }
X } else {
X /*
X * To be compatible with ucb-mail, find the next available unread
X * message. If at the end, only wrap around if "wrap" is set.
X */
X if (current_msg == msg_cnt && do_set(set_options, "wrap"))
X current_msg = 0;
X /* "type" or "print" prints the current only -- "next" goes on.. */
X if (!p || !*p || *p == 'n')
X while (current_msg < msg_cnt &&
X (ison(msg[current_msg].m_flags, DELETE) ||
X ison(msg[current_msg].m_flags, SAVED)))
X current_msg++;
X if (current_msg >= msg_cnt) {
X print("No more messages.\n");
X current_msg = msg_cnt - 1;
X return -1;
X }
X }
X if (isoff(glob_flags, IS_PIPE))
X set_msg_bit(list, current_msg);
X }
X current_msg = 0;
X for (x = 0; x < msg_cnt; x++)
X if (msg_bit(list, x)) {
X current_msg = x;
X#ifdef SUNTOOL
X if (istool > 1) {
X read_mail(NO_ITEM, 0, NO_EVENT);
X return 0;
X }
X#endif /* SUNTOOL */
X display_msg(x, flg);
X }
X return 0;
X}
X
Xpreserve(n, argv, list)
Xregister int n; /* no use for argc, so use space for a local variable */
Xregister char **argv, list[];
X{
X register int unpre;
X
X unpre = !strncmp(*argv, "un", 2);
X if (*++argv && !strcmp(*argv, "-?"))
X return help(0, "preserve", cmd_help);
X if (get_msg_list(argv, list) == -1)
X return -1;
X for (n = 0; n < msg_cnt; n++)
X if (msg_bit(list, n))
X if (unpre) {
X if (ison(msg[n].m_flags, PRESERVE)) {
X turnoff(msg[n].m_flags, PRESERVE);
X turnon(glob_flags, DO_UPDATE);
X }
X } else {
X if (isoff(msg[n].m_flags, PRESERVE)) {
X /* || ison(msg[n].m_flags, DELETE)) */
X /* turnoff(msg[n].m_flags, DELETE); */
X turnon(msg[n].m_flags, PRESERVE);
X turnon(glob_flags, DO_UPDATE);
X }
X }
X if (istool)
X (void) do_hdrs(0, DUBL_NULL, NULL);
X return 0;
X}
X
Xlpr(n, argv, list)
Xregister int n; /* no use for argc, so use its address space for a variable */
Xregister char **argv, list[];
X{
X register FILE *pp;
X register long flags = 0;
X char print_cmd[128], *printer, c, *cmd;
X int total = 0;
X SIGRET (*oldint)(), (*oldquit)();
X
X turnon(flags, NO_IGNORE);
X#ifdef MMDF
X turnon(flags, NO_SEPARATOR);
X#endif /* MMDF */
X if (!(printer = do_set(set_options, "printer")) || !*printer)
X printer = DEF_PRINTER;
X while (argv && *++argv && **argv == '-') {
X n = 1;
X while (c = argv[0][n++])
X switch(c) {
X case 'n': turnon(flags, NO_HEADER);
X when 'h': turnoff(flags, NO_IGNORE);
X when 'P': case 'd':
X if (!argv[0][n]) {
X print("specify printer!\n");
X return -1;
X }
X printer = argv[0] + n;
X n += strlen(printer);
X otherwise: return help(0, "lpr", cmd_help);
X }
X }
X if (get_msg_list(argv, list) == -1)
X return -1;
X
X if (cmd = do_set(set_options, "print_cmd"))
X (void) strcpy(print_cmd, cmd);
X else
X#ifdef SYSV
X (void) sprintf(print_cmd, "%s -d%s", LPR, printer);
X#else
X (void) sprintf(print_cmd, "%s -P%s", LPR, printer);
X#endif /* SYSV */
X Debug("print command: %s\n", print_cmd);
X if (!(pp = popen(print_cmd, "w"))) {
X error("cannot print");
X return -1;
X }
X on_intr();
X for (n = 0; isoff(glob_flags, WAS_INTR) && n < msg_cnt; n++) {
X if (msg_bit(list, n)) {
X if (total++)
X fputc('\f', pp); /* send a formfeed for multiple copies */
X print("printing message %d...", n+1);
X print_more("(%d lines)\n", copy_msg(n, pp, flags));
X }
X }
X off_intr();
X (void) pclose(pp);
X print_more("%d message%s printed ", total, (total==1)? "": "s");
X if (cmd)
X print_more("through \"%s\".\n", cmd);
X else
X print_more("at \"%s\".\n", printer);
X return 0;
X}
X
X/* save [msg_list] [file] */
Xsave_msg(n, argv, list) /* argc isn't used, so use space for variable 'n' */
Xregister char **argv, list[];
X{
X register FILE *mail_fp = NULL_FILE;
X register char *file = NULL, *mode, firstchar = **argv, *tmp = ".";
X int msg_number, force, by_subj = 0, by_author = 0;
X char buf[MAXPATHLEN];
X long flg = 0;
X
X while (*++argv)
X if (*argv[0] != '-')
X break;
X else
X switch (argv[0][1]) {
X case 'S' :
X by_subj = 2;
X when 's' :
X by_subj = 1;
X when 'A' :
X by_author = 2;
X when 'a' :
X by_author = 1;
X otherwise :
X return help(0, "save", cmd_help);
X }
X if (force = (*argv && !strcmp(*argv, "!")))
X argv++;
X if ((n = get_msg_list(argv, list)) == -1)
X return -1;
X argv += n;
X if (*argv && *(file = *argv) == '\\')
X file++;
X else if (!file && !by_subj && !by_author) {
X /* if no filename specified, save in ~/mbox */
X if (firstchar == 'w') {
X /* mbox should have headers. If he really wants it, specify it */
X print("Must specify file name for 'w'\n");
X return -1;
X }
X if (!(file = do_set(set_options, "mbox")) || !*file)
X file = DEF_MBOX;
X }
X n = 1; /* tell getpath to ignore no such file or directory */
X if (file)
X tmp = getpath(file, &n);
X if (n < 0) {
X print("%s: %s\n", file, tmp);
X return -1;
X } else if (n && !by_subj && !by_author) {
X print("%s is a directory\n", file);
X return -1;
X }
X file = tmp;
X if (force || Access(file, F_OK))
X mode = "w", force = 0;
X else
X mode = "a";
X /*
X * open the file for writing (appending) unless we're saving by subject
X * or author name in which case we'll determine the filename later
X */
X if (!by_author && !by_subj && !(mail_fp = mask_fopen(file, mode))) {
X error("cannot save in \"%s\"", file);
X return -1;
X }
X
X#ifdef SUNTOOL
X if (istool)
X lock_cursors();
X#endif /* SUNTOOL */
X turnon(flg, NO_IGNORE);
X if (firstchar == 'w') {
X turnon(flg, NO_HEADER);
X#ifdef MMDF
X turnon(flg, NO_SEPARATOR);
X#endif /* MMDF */
X } else
X turnon(flg, UPDATE_STATUS);
X
X for (n = msg_number = 0; msg_number < msg_cnt; msg_number++)
X if (msg_bit(list, msg_number)) {
X if ((by_author || by_subj) && !mail_fp) {
X char buf2[256], addr[256];
X register char *p, *p2;
X if (by_subj) {
X if (p = header_field(msg_number, "subject")) {
X /* convert spaces and non-alpha-numerics to '_' */
X if (!lcase_strncmp(p, "re: ", 4))
X p += 4;
X for (p2 = p; *p2; p2++)
X if (!isalnum(*p2) && !index(".,@#$%-+=", *p2))
X *p2 = '_';
X } else
X p = "mbox";
X } else {
X (void) reply_to(msg_number, FALSE, buf2);
X (void) get_name_n_addr(buf2, NULL, addr);
X if (p = rindex(addr, '!'))
X p++;
X else
X p = addr;
X if (p2 = any(p, "@%"))
X *p2 = 0;
X }
X if (!p || !*p)
X p = "tmp";
X (void) sprintf(buf, "%s/%s", file, p);
X if (force || Access(buf, F_OK))
X mode = "w";
X else
X mode = "a";
X if (!(mail_fp = fopen(buf, mode))) {
X error("cannot save in \"%s\"", buf);
X if (by_author == 2 || by_subj == 2)
X break;
X continue;
X }
X }
X print("%sing msg %d ... ",
X (firstchar == 's')? "Sav" : "Writ", msg_number+1);
X print_more("(%d lines)", copy_msg(msg_number, mail_fp, flg));
X if (by_author == 1 || by_subj == 1) {
X print_more(" in \"%s\"", buf);
X fclose(mail_fp), mail_fp = NULL_FILE;
X }
X print_more("\n");
X n++;
X if (isoff(msg[msg_number].m_flags, SAVED) && firstchar != 'c') {
X turnon(glob_flags, DO_UPDATE);
X turnon(msg[msg_number].m_flags, SAVED);
X }
X }
X if (mail_fp) {
X fclose(mail_fp);
X if (!file)
X file = buf;
X print_more("%s %d msg%s to %s\n",
X (*mode == 'a')? "Appended" : "Saved", n, (n != 1)? "s": "", file);
X }
X#ifdef SUNTOOL
X if (istool) {
X unlock_cursors();
X (void) do_hdrs(0, DUBL_NULL, NULL);
X add_folder_to_menu(folder_item, 3);
X add_folder_to_menu(save_item, 1);
X }
X#endif /* SUNTOOL */
X return 0;
X}
X
Xrespond(n, argv, list)
Xregister int n; /* no use for argc, so use its address space for a variable */
Xregister char **argv, *list;
X{
X register char *cmd = *argv;
X char list1[MAXMSGS_BITS];
X int cur_msg = current_msg;
X
X if (*++argv && !strcmp(*argv, "-?"))
X return help(0, "respond", cmd_help);
X if ((n = get_msg_list(argv, list)) == -1)
X return -1;
X
X /* make into our own list so ~: commands don't overwrite this list */
X bitput(list, list1, MAXMSGS, =);
X
X /* back up one arg to replace "cmd" in the new argv[0] */
X argv += (n-1);
X if (!strcmp(cmd, "replyall"))
X Upper(*cmd);
X strdup(argv[0], cmd);
X
X /* make sure the *current* message is the one being replied to */
X for (current_msg = -1, n = 0; n < msg_cnt && current_msg == -1; n++)
X if (msg_bit(list1, n) && current_msg == -1)
X current_msg = n;
X if (current_msg == -1) { /* "reply -" can cause this to happen */
X current_msg = cur_msg;
X return -1;
X }
X if (do_mail(1 /* ignored */, argv, list) == -1)
X return -1;
X for (n = 0; n < msg_cnt; n++)
X if (msg_bit(list1, n)) {
X /* set_isread(n); */
X set_replied(n); /* only if mail got delivered */
X }
X if (istool)
X do_hdrs(0, DUBL_NULL, NULL);
X /* copy the specified list back into msg_list */
X bitput(list1, list, MAXMSGS, =);
X return 0;
X}
X
X/* cd to a particular directory specified by "p" */
Xcd(x, argv) /* argc, unused -- use space for a non-register variable */
Xregister char **argv;
X{
X char cwd[MAXPATHLEN], buf[MAXPATHLEN];
X register char *path, *p = argv[1], *cdpath = NULL, *p2;
X#ifdef SYSV
X char *getcwd();
X#else
X char *getwd();
X#endif /* SYSV */
X int err = 0;
X
X if (!strcmp(*argv, "pwd") && (p = do_set(set_options, "cwd")) && *p) {
X print("%s\n", p);
X return -1;
X }
X if (!p || !*p) /* if no args, pwd = ".", cd = ~ */
X p = (**argv == 'p')? "." : "~";
X /* if a full path was not specified, loop through cdpath */
X if (**argv != 'p' && *p != '/' && *p != '~' && *p != '+')
X cdpath = do_set(set_options, "cdpath");
X do {
X if (cdpath) {
X char c;
X if (p2 = any(cdpath, " \t:"))
X c = *p2, *p2 = 0;
X (void) sprintf(buf, "%s/%s", cdpath, p);
X if (cdpath = p2) /* assign and compare to NULL */
X *p2 = c;
X while (cdpath && isspace(*cdpath))
X cdpath++;
X } else
X (void) strcpy(buf, p);
X x = 0;
X path = getpath(buf, &x);
X if (x != 1 || chdir(path) == -1)
X err = errno;
X else
X err = 0;
X } while (err && cdpath && *cdpath);
X if (err)
X error(p);
X#ifdef SYSV
X if (getcwd(cwd, sizeof cwd) == NULL)
X#else
X if (getwd(cwd) == NULL)
X#endif /* SYSV */
X print("can't get cwd: %s.\n", cwd), err++;
X else {
X char *new_argv[4];
X new_argv[0] = "cwd";
X new_argv[1] = "=";
X new_argv[2] = cwd;
X new_argv[3] = NULL;
X (void) add_option(&set_options, new_argv);
X }
X if (istool || iscurses || err) {
X if (err)
X turnon(glob_flags, CONT_PRNT);
X if (iscurses || istool || ison(glob_flags, WARNING))
X print("Working dir: %s\n", cwd);
X }
X return 0;
X}
X
Xquit(argc, argv)
Xchar **argv;
X{
X u_long updated = ison(glob_flags, DO_UPDATE);
X
X if (argc > 1 && !strcmp(argv[1], "-?"))
X return help(0, "quit", cmd_help);
X if ((!argc || (*argv && **argv == 'q')) && !copyback("Really Quit? "))
X return -1;
X#ifdef CURSES
X if (iscurses) {
X /* we may already be on the bottom line; some cases won't be */
X move(LINES-1, 0), refresh();
X if (updated)
X putchar('\n');
X }
X#endif /* CURSES */
X cleanup(0);
X#ifdef lint
X return 0;
X#endif /* lint */
X}
X
Xdelete(argc, argv, list)
Xregister int argc;
Xregister char **argv, list[];
X{
X register int prnt_next, undel = argc && **argv == 'u';
X int old_msg = current_msg;
X
X prnt_next = (argv && (!strcmp(*argv, "dt") || !strcmp(*argv, "dp")));
X
X if (argc && *++argv && !strcmp(*argv, "-?")) {
X print("usage: delete/undelete [msg_list]\n");
X return -1;
X }
X
X if (ison(glob_flags, READ_ONLY)) {
X print("Folder is read-only\n");
X return -1;
X }
X
X if (get_msg_list(argv, list) == -1)
X return -1;
X for (argc = 0; argc < msg_cnt; argc++)
X if (msg_bit(list, argc))
X if (undel)
X turnoff(msg[argc].m_flags, DELETE);
X else
X turnon(msg[argc].m_flags, DELETE);
X
X /* only if current_msg has been affected && not in curses mode */
X if (prnt_next == 0 && !iscurses && msg_bit(list, current_msg))
X prnt_next = !!do_set(set_options, "autoprint"); /* change to boolean */
X
X turnon(glob_flags, DO_UPDATE);
X
X /* goto next available message if current was just deleted.
X * If there are no more messages, turnoff prnt_next.
X */
X if (!iscurses && !undel && msg_bit(list, current_msg) &&
X (ison(msg[current_msg].m_flags, DELETE) ||
X ison(msg[current_msg].m_flags, SAVED)))
X next_msg();
X
X if (prnt_next && !undel && !iscurses)
X if (old_msg != current_msg && isoff(msg[current_msg].m_flags, DELETE))
X display_msg(current_msg, (long)0);
X else
X print("No more messages.\n"), current_msg = old_msg;
X#ifdef SUNTOOL
X if (istool)
X (void) do_hdrs(0, DUBL_NULL, NULL);
X#endif /* SUNTOOL */
X return 0;
X}
X
X/*
X * historically from the "from" command in ucb-mail, this just prints
X * the composed header of the messages set in list or in pipe.
X */
Xdo_from(n, argv, list)
Xchar **argv, list[];
X{
X int inc_cur_msg = 0;
X
X if (argv && *++argv && !strcmp(*argv, "-?"))
X return help(0, "from", cmd_help);
X if (argv && *argv && (!strcmp(*argv, "+") || !strcmp(*argv, "-")))
X if (!strcmp(*argv, "+")) {
X if (!*++argv && current_msg < msg_cnt-1)
X current_msg++;
X inc_cur_msg = 1;
X } else if (!strcmp(*argv, "-")) {
X if (!*++argv && current_msg > 0)
X current_msg--;
X inc_cur_msg = -1;
X }
X if (get_msg_list(argv, list) == -1)
X return -1;
X for (n = 0; n < msg_cnt; n++)
X if (msg_bit(list, n)) {
X wprint("%s\n", compose_hdr(n));
X /* if -/+ given, set current message pointer to this message */
X if (inc_cur_msg) {
X current_msg = n;
X /* if - was given, then set to first listed message.
X * otherwise, + means last listed message -- let it go...
X */
X if (inc_cur_msg < 0)
X inc_cur_msg = 0;
X }
X }
X return 0;
X}
X
X/*
X * Do an ls from the system.
X * Read from a popen and use wprint in case the tool does this command.
X * The folders command uses this command.
X */
Xls(x, argv)
Xchar **argv;
X{
X register char *p, *tmp;
X char buf[128];
X register FILE *pp;
X
X if (*++argv && !strcmp(*argv, "-?"))
X return help(0, "ls", cmd_help);
X if (!(p = do_set(set_options, "lister")))
X p = "";
X (void) sprintf(buf, "%s -C%s ", LS_COMMAND, p);
X p = buf+strlen(buf);
X for ( ; *argv; ++argv) {
X x = 0;
X if (**argv != '-')
X tmp = getpath(*argv, &x);
X else
X tmp = *argv;
X if (x == -1) {
X wprint("%s: %s\n", *argv, tmp);
X return -1;
X }
X p += strlen(sprintf(p, " %s", tmp));
X }
X if (!(pp = popen(buf, "r"))) {
X error(buf);
X return -1;
X }
X (void) do_pager(NULL, TRUE);
X while (fgets(buf, 127, pp) && do_pager(buf, FALSE) != EOF)
X ;
X (void) pclose(pp);
X (void) do_pager(NULL, FALSE);
X return 0;
X}
X
Xsh(un_used, argv)
Xchar **argv;
X{
X register char *p;
X char buf[128];
X
X if (istool > 1 || *++argv && !strcmp(*argv, "-?"))
X return help(0, "shell", cmd_help);
X if (!(p = do_set(set_options, "shell"))
X && !(p = do_set(set_options, "SHELL")))
X p = DEF_SHELL;
X if (!*argv)
X (void) strcpy(buf, p);
X else
X (void) argv_to_string(buf, argv);
X echo_on();
X (void) system(buf);
X echo_off();
X return 0;
X}
X
Xstatic
Xsorter(cmd1, cmd2)
Xregister struct cmd *cmd1, *cmd2;
X{
X return strcmp(cmd1->command, cmd2->command);
X}
X
Xquestion_mark(x, argv)
Xchar **argv;
X{
X int n = 0;
X char *Cmds[sizeof cmds/sizeof(struct cmd)], *p, *malloc(), buf[30];
X
X qsort((char *)cmds, sizeof(cmds)/sizeof(struct cmd)-1,
X sizeof(struct cmd), sorter);
X
X if (!*++argv) {
X for (x = 0; cmds[x].command; x++) {
X if (!(x % 5))
X if (!(p = Cmds[n++] = malloc(80))) {
X error("malloc in question_mark()");
X free_vec(Cmds);
X return -1;
X }
X p += strlen(sprintf(p, "%-14.14s ", cmds[x].command));
X }
X Cmds[n++] = savestr("Type: `command -?' for help with most commands.");
X Cmds[n] = NULL;
X (void) help(0, Cmds, NULL);
X free_vec(Cmds);
X } else {
X for (x = 0; cmds[x].command; x++)
X if (!strcmp(*argv, cmds[x].command))
X return cmd_line(sprintf(buf, "\\%s -?", *argv), msg_list);
X print("Unknown command: %s\n", *argv);
X }
X return 0 - in_pipe();
X}
X
X#ifdef SIGSTOP
Xstop(argc, argv)
Xchar **argv;
X{
X if (istool)
X print("Not a tool-based option.");
X if (argc && *++argv && !strcmp(*argv, "-?"))
X return help(0, "stop", cmd_help);
X if (kill(getpid(), SIGTSTP) == -1)
X error("couldn't stop myself");
X return 0;
X}
X#endif /* SIGSTOP */
X
Xextern char **environ;
Xstatic int spaces = 0;
X
XSetenv(i, argv)
Xchar **argv;
X{
X char *newstr;
X
X if (i < 2 || i > 3 || !strcmp(argv[1], "-?"))
X return help(0, "setenv", cmd_help);
X
X if (i == 3) {
X newstr = malloc(strlen(argv[1]) + strlen(argv[2]) + 2);
X (void) sprintf(newstr, "%s=%s", argv[1], argv[2]);
X } else {
X newstr = malloc(strlen(argv[1]) + 2);
X (void) sprintf(newstr, "%s=", argv[1]);
X }
X
X (void) Unsetenv(2, argv);
X
X for (i = 0; environ[i]; i++);
X if (!spaces) {
X char **new_environ = (char **)malloc((i+2) * sizeof(char *));
X /* add 1 for the new item, and 1 for null-termination */
X if (!new_environ) {
X free(newstr);
X return -1;
X }
X spaces = 1;
X for (i = 0; new_environ[i] = environ[i]; i++);
X xfree(environ);
X environ = new_environ;
X }
X environ[i] = newstr;
X environ[i+1] = NULL;
X spaces--;
X return 0;
X}
X
XUnsetenv(n, argv)
Xchar **argv;
X{
X char **envp, **last;
X
X if (n != 2 || !strcmp(argv[1], "-?"))
X return help(0, "unsetenv", cmd_help);
X
X n = strlen(argv[1]);
X for (last = environ; *last; last++);
X last--;
X
X for (envp = environ; envp <= last; envp++) {
X if (strncmp(argv[1], *envp, n) == 0 && (*envp)[n] == '=') {
X xfree(*envp);
X *envp = *last;
X *last-- = NULL;
X spaces++;
X }
X }
X return 0;
X}
X
XPrintenv(argc, argv)
Xchar **argv;
X{
X char **e;
X for (e = environ; *e; e++)
X if (argc < 2 || !strncmp(*e, argv[1], strlen(argv[1])))
X wprint("%s\n", *e);
X return 0;
X}
X
X/*
X * internal stty call to allow the user to change his tty character
X * settings. sorry, no way to change cbreak/echo modes. Save echo_flg
X * so that execute() won't reset it.
X */
Xmy_stty(un_used, argv)
Xchar **argv;
X{
X u_long save_echo = ison(glob_flags, ECHO_FLAG);
X
X turnon(glob_flags, ECHO_FLAG);
X execute(argv);
X if (save_echo)
X turnon(glob_flags, ECHO_FLAG);
X else
X turnoff(glob_flags, ECHO_FLAG);
X
X savetty();
X#ifdef TIOCGLTC
X if (ioctl(0, TIOCGLTC, <chars))
X error("TIOCGLTC");
X#endif /* TIOCGLTC */
X echo_off();
X return 0;
X}
X
X/*
X * Edit a message...
X */
Xedit_msg(i, argv, list)
Xchar *argv[], list[];
X{
X int edited = 0;
X char buf[MAXPATHLEN], *dir, *edit_cmd[3];
X u_long flags = 0L;
X FILE *fp;
X
X if (istool)
X return 0;
X
X if (*++argv && !strcmp(*argv, "-?"))
X return help(0, "edit_msg", cmd_help);
X
X if (ison(glob_flags, READ_ONLY)) {
X print("\"%s\" is read-only.\n", mailfile);
X return -1;
X }
X
X if (get_msg_list(argv, list) == -1)
X return -1;
X
X for (i = 0; i < msg_cnt; i++) {
X if (!msg_bit(list, i))
X continue;
X
X if (edited) {
X print("Edit message %d [y/n/q]? ", i+1);
X if (Getstr(buf, sizeof (buf), 0) < 0 || lower(buf[0]) == 'q')
X return 0;
X if (buf[0] && buf[0] != 'y')
X continue;
X }
X
X if (!(dir = do_set(set_options, "tmpdir")) &&
X !(dir = do_set(set_options, "home")))
Xalted:
X dir = ALTERNATE_HOME;
X (void) mktemp(sprintf(buf, "%s/.msgXXXXXXX", dir));
X if (!(fp = mask_fopen(buf, "w+"))) {
X if (strcmp(dir, ALTERNATE_HOME))
X goto alted;
X error("can't create %s", buf);
X return -1;
X }
X wprint("editing message %d ...", i+1);
X /* copy message into file making sure all headers exist. */
X turnon(flags, UPDATE_STATUS);
X#ifdef MMDF
X turnon(flags, NO_SEPARATOR);
X#endif /* MMDF */
X wprint("(%d lines)\n", copy_msg(i, fp, flags));
X
X if (!(edit_cmd[0] = do_set(set_options, "visual")) || !*edit_cmd[0])
X edit_cmd[0] = DEF_EDITOR;
X edit_cmd[1] = buf;
X edit_cmd[2] = NULL;
X print("Starting \"%s %s\"...\n", edit_cmd[0], buf);
X fclose(fp);
X turnon(glob_flags, IS_GETTING);
X execute(edit_cmd);
X turnoff(glob_flags, IS_GETTING);
X if (load_folder(buf, FALSE, (char *)i) > 0) {
X (void) unlink(buf);
X edited++;
X }
X set_isread(i); /* if you edit it, you read it, right? */
X }
X return 0;
X}
X
X/*
X * Pipe a message list to a unix command. This function is hacked together
X * from bits of readmsg, above, and other bits of display_msg (misc.c).
X */
Xpipe_msg(x, argv, list)
Xregister char **argv, list[];
X{
X char *p = x ? *argv : NULL;
X char buf[256];
X u_long flg = 0L;
X extern FILE *ed_fp;
X
X /* Increment argv only if argv[0] is the mush command "pipe" */
X if (x && p && (!strcmp(p, "pipe") || !strcmp(p, "Pipe"))) {
X if (*++argv && !strcmp(*argv, "-?"))
X return help(0, "pipe_msg", cmd_help);
X else if (p && *p == 'P')
X turnon(flg, NO_HEADER);
X }
X /* Pipe a message as long as user isn't in the editor. If is_getting
X * is set, then the user is typing in a letter (or something else not
X * threatening in tool mode). If ed_fp is not null, then we've got the
X * file open for typing. If it's NULL, then an editor is going.
X */
X if (ison(glob_flags, IS_GETTING) && !ed_fp) {
X print("Not while you're in the editor, you don't.\n");
X return -1;
X }
X if (!msg_cnt) {
X print("No messages.\n");
X return -1;
X }
X
X if (x && (x = get_msg_list(argv, list)) == -1)
X return -1;
X else {
X argv += x;
X if (!*argv) {
X print("No unix command for pipe!\n");
X return -1;
X }
X (void) argv_to_string(buf, argv);
X }
X current_msg = 0;
X#ifdef MMDF
X turnon(flg, NO_SEPARATOR);
X#endif /* MMDF */
X (void) do_pager(buf, TRUE); /* start pager */
X for (x = 0; x < msg_cnt; x++)
X if (msg_bit(list, x)) {
X current_msg = x;
X if (ison(msg[x].m_flags, DELETE)) {
X print("Message %d deleted; ", x+1);
X if (iscurses)
X print_more("skipping it.");
X else
X print("skipping it.\n");
X continue;
X }
X set_isread(x);
X (void) copy_msg(x, NULL_FILE, flg);
X }
X (void) do_pager(NULL, FALSE); /* end pager */
X return 0;
X}
X
X/* echo the arguments. return 0 or -1 if -h given and there are no msgs. */
Xdo_echo(n, argv)
Xregister char **argv;
X{
X char buf[BUFSIZ], c;
X int no_return = 0, comp_hdr = 0, as_prompt = 0;
X
X while (argv && *++argv && **argv == '-') {
X n = 1;
X while (c = argv[0][n++])
X switch(c) {
X case 'n': no_return++;
X when 'h': comp_hdr++;
X when 'p': as_prompt++;
X otherwise: return help(0, "echo", cmd_help);
X }
X }
X if (comp_hdr && as_prompt) {
X print("-h and -n cannot be used together.\n");
X return -1;
X }
X
X (void) argv_to_string(buf, argv);
X if (comp_hdr) {
X char *save_hdr_fmt = hdr_format;
X if (!msg_cnt) {
X print("No messages.\n");
X return -1;
X }
X hdr_format = buf;
X print("%s", compose_hdr(current_msg)+9); /* there may be a %-sign */
X hdr_format = save_hdr_fmt;
X } else if (as_prompt) {
X char *save_prompt = prompt;
X prompt = buf;
X mail_status(1);
X prompt = save_prompt;
X } else
X print("%s", buf); /* there may be a %-sign in "buf" */
X if (!no_return)
X print_more("\n");
X return 0;
X}
X
Xeval_cmd (argc, argv, list)
Xchar *argv[], list[];
X{
X int status = -1;
X u_long save_is_pipe;
X char **newav, buf[BUFSIZ];
X
X if (*++argv && !strcmp(*argv, "-?"))
X return help(0, "eval", cmd_help);
X
X (void) argv_to_string(buf,argv);
X /* Can't use cmd_line() because we want DO_PIPE and IS_PIPE
X * to remain on -- cmd_line() turns both of them off
X */
X if (newav = make_command(buf, TRPL_NULL, &argc)) {
X save_is_pipe = ison(glob_flags, IS_PIPE);
X status = do_command(argc, newav, list);
X if (save_is_pipe)
X turnon(glob_flags, IS_PIPE);
X }
X return status;
X}
END_OF_FILE
if test 29012 -ne `wc -c <'commands.c'`; then
echo shar: \"'commands.c'\" unpacked with wrong size!
fi
# end of 'commands.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
--
Please send comp.sources.unix-related mail to rsalz at uunet.uu.net.
More information about the Comp.sources.unix
mailing list