home *** CD-ROM | disk | FTP | other *** search
- /* @(#)commands.c (c) copyright 10/18/86 (Dan Heller) */
-
- #include "mush.h"
-
- /*
- * Note that all of the routines in here act upon and return 0 or -1.
- * if -1, then the main loop will clear message lists.
- */
-
- struct cmd cmds[] = {
- #ifdef SIGSTOP
- { "stop", stop },
- #endif /* SIGSTOP */
- { "?", question_mark },{ "sh", sh },
- { "alias", do_alias }, { "unalias", do_alias },
- { "expand", do_alias }, { "cmd", do_alias },
- { "uncmd", do_alias }, { "from", do_from },
- { "un_hdr", do_alias }, { "my_hdr", do_alias },
- { "fkey", do_alias }, { "unfkey", do_alias },
- { "set", set }, { "unset", set },
- { "ignore", set }, { "unignore", set },
- { "version", do_version }, { "help", print_help },
- { "pick", do_pick }, { "sort", sort },
- { "next", readmsg }, { "previous", readmsg },
- { "type", readmsg }, { "print", readmsg },
- { "history", disp_hist }, { "top", readmsg },
- { "saveopts", save_opts }, { "source", source },
- { "headers", do_hdrs }, { "ls", ls },
- { "folder", folder }, { "update", folder },
- { "cd", cd }, { "pwd", cd },
- { "exit", mush_quit }, { "quit", mush_quit },
- { "write", save_msg }, { "save", save_msg },
- { "copy", save_msg }, { "folders", folders },
- { "merge", merge_folders },
- #ifdef CURSES
- { "curses", curses_init }, { "bind", bind_it },
- { "unbind", bind_it }, { "bind-macro", bind_it },
- { "unbind-macro", bind_it },
- #endif /* CURSES */
- { "map", bind_it }, { "unmap", bind_it },
- { "map!", bind_it }, { "unmap!", bind_it },
- { "preserve", preserve }, { "unpreserve", preserve },
- { "replyall", respond }, { "replysender", respond },
- { "delete", delete }, { "undelete", delete },
- { "mail", do_mail }, { "echo", do_echo },
- { "lpr", lpr }, { "alternates", alts },
- { "edit", edit_msg }, { "flags", msg_flags },
- { "pipe", pipe_msg }, { "eval", eval_cmd },
- { "undigest", do_undigest }, { "await", await },
- { NULL, mush_quit }
- };
-
- struct cmd ucb_cmds[] = {
- { "t", readmsg }, { "n", readmsg }, { "p", readmsg },
- { "+", readmsg }, { "-", readmsg }, { "P", readmsg },
- { "Print", readmsg }, { "T", readmsg }, { "Type", readmsg },
- { "x", mush_quit }, { "q", mush_quit }, { "xit", mush_quit },
- { ":a", do_hdrs }, { ":d", do_hdrs }, { ":r", do_hdrs },
- { ":o", do_hdrs }, { ":u", do_hdrs }, { ":n", do_hdrs },
- { ":s", do_hdrs }, { ":p", do_hdrs },
- { "z", do_hdrs }, { "z-", do_hdrs }, { "z+", do_hdrs },
- { "h", do_hdrs }, { "H", do_hdrs },
- { "f", do_from }, { "m", do_mail }, { "alts", alts },
- { "d", delete }, { "dt", delete }, { "dp", delete },
- { "u", delete }, { "fo", folder },
- { "s", save_msg }, { "co", save_msg }, { "w", save_msg },
- { "pre", preserve }, { "unpre", preserve },
- { "R", respond }, { "r", respond },
- { "reply", respond }, { "respond", respond },
- { "v", edit_msg }, { "e", edit_msg },
- { NULL, mush_quit }
- };
-
- struct cmd hidden_cmds[] = {
- { "debug", toggle_debug }, { "open", nopenfiles },
- { "stty", my_stty },
- { "setenv", Setenv }, { "unsetenv", Unsetenv },
- { "printenv", Printenv }, { "Pipe", pipe_msg },
- { NULL, mush_quit }
- };
-
- toggle_debug(argc, argv)
- char **argv;
- {
- if (argc < 2) /* no value -- toggle "debug" (off/on) */
- debug = !debug;
- else
- debug = atoi(*++argv);
- print("debugging value: %d\n", debug);
- return 0;
- }
-
- /* if + was specified, then print messages without headers.
- * n or \n (which will be NULL) will print next unread or undeleted message.
- */
- readmsg(x, argv, list)
- register char **argv, list[];
- {
- register char *p = x? *argv : NULL;
- register long flg = 0;
- extern FILE *ed_fp;
-
- if (x && *++argv && !strcmp(*argv, "-?"))
- return help(0, "readmsg", cmd_help);
- /* View a message as long as user isn't in the editor.
- * If ed_fp is not null, then we've got the
- * file open for typing. If it's NULL, then an editor is going.
- */
- if (ison(glob_flags, IS_GETTING) && !ed_fp) {
- print("Not while you're in the editor, you don't.\n");
- return -1;
- }
- if (!msg_cnt) {
- print("No messages.\n");
- return -1;
- }
- if (x)
- if (!strcmp(p, "top"))
- turnon(flg, M_TOP);
- else if (*p == '+') {
- turnon(flg, NO_PAGE);
- turnon(flg, NO_HEADER);
- } else if (isupper(*p))
- turnon(flg, NO_IGNORE);
-
- if (x && (x = get_msg_list(argv, list)) == -1)
- return -1;
- else if (x == 0) { /* no arguments were parsed (or given) */
- /* get_msg_list sets current msg on */
- if (isoff(glob_flags, IS_PIPE))
- unset_msg_bit(list, current_msg);
- /* most commands move to the "next" message. type and print don't */
- if ((!p || !*p || *p == 'n' || *p == '+') && current_msg < msg_cnt &&
- isoff(msg[current_msg].m_flags, UNREAD))
- current_msg++;
- if (p && (*p == '-' || !strcmp(p, "previous"))) {
- while (--current_msg >= 0 &&
- (ison(msg[current_msg].m_flags, DELETE) ||
- ison(msg[current_msg].m_flags, SAVED)))
- ;
- if (current_msg < 0) {
- print("No previous message.\n");
- current_msg = 0;
- return -1;
- }
- } else {
- /*
- * To be compatible with ucb-mail, find the next available unread
- * message. If at the end, only wrap around if "wrap" is set.
- */
- if (current_msg == msg_cnt && do_set(set_options, "wrap"))
- current_msg = 0;
- /* "type" or "print" prints the current only -- "next" goes on.. */
- if (!p || !*p || *p == 'n')
- while (current_msg < msg_cnt &&
- (ison(msg[current_msg].m_flags, DELETE) ||
- ison(msg[current_msg].m_flags, SAVED)))
- current_msg++;
- if (current_msg >= msg_cnt) {
- print("No more messages.\n");
- current_msg = msg_cnt - 1;
- return -1;
- }
- }
- if (isoff(glob_flags, IS_PIPE))
- set_msg_bit(list, current_msg);
- }
- current_msg = 0;
- for (x = 0; x < msg_cnt; x++)
- if (msg_bit(list, x)) {
- current_msg = x;
- #ifdef SUNTOOL
- if (istool > 1) {
- read_mail(NO_ITEM, 0, NO_EVENT);
- return 0;
- }
- #endif /* SUNTOOL */
- display_msg(x, flg);
- }
- return 0;
- }
-
- preserve(n, argv, list)
- register int n; /* no use for argc, so use space for a local variable */
- register char **argv, list[];
- {
- register int unpre;
-
- unpre = !strncmp(*argv, "un", 2);
- if (*++argv && !strcmp(*argv, "-?"))
- return help(0, "preserve", cmd_help);
- if (get_msg_list(argv, list) == -1)
- return -1;
- for (n = 0; n < msg_cnt; n++)
- if (msg_bit(list, n))
- if (unpre) {
- if (ison(msg[n].m_flags, PRESERVE)) {
- turnoff(msg[n].m_flags, PRESERVE);
- turnon(glob_flags, DO_UPDATE);
- }
- } else {
- if (isoff(msg[n].m_flags, PRESERVE)) {
- /* || ison(msg[n].m_flags, DELETE)) */
- /* turnoff(msg[n].m_flags, DELETE); */
- turnon(msg[n].m_flags, PRESERVE);
- turnon(glob_flags, DO_UPDATE);
- }
- }
- if (istool)
- (void) do_hdrs(0, DUBL_NULL, NULL);
- return 0;
- }
-
- lpr(n, argv, list)
- register int n; /* no use for argc, so use its address space for a variable */
- register char **argv, list[];
- {
- register FILE *pp;
- register long flags = 0;
- char print_cmd[128], *printer, c, *cmd;
- int total = 0;
- SIGRET (*oldint)(), (*oldquit)();
-
- if (!chk_option("alwaysignore", "printer"))
- turnon(flags, NO_IGNORE);
- #ifdef MSG_SEPARATOR
- turnon(flags, NO_SEPARATOR);
- #endif /* MMDF */
- if (!(printer = do_set(set_options, "printer")) || !*printer)
- printer = DEF_PRINTER;
- while (argv && *++argv && **argv == '-') {
- n = 1;
- while (c = argv[0][n++])
- switch(c) {
- case 'n': turnon(flags, NO_HEADER);
- when 'h': turnoff(flags, NO_IGNORE);
- when 'P': case 'd':
- if (!argv[0][n]) {
- print("specify printer!\n");
- return -1;
- }
- printer = argv[0] + n;
- n += strlen(printer);
- otherwise: return help(0, "lpr", cmd_help);
- }
- }
- if (get_msg_list(argv, list) == -1)
- return -1;
-
- if (cmd = do_set(set_options, "print_cmd"))
- (void) strcpy(print_cmd, cmd);
- else
- #ifdef SYSV
- (void) sprintf(print_cmd, "%s -d%s", LPR, printer);
- #else
- (void) sprintf(print_cmd, "%s -P%s", LPR, printer);
- #endif /* SYSV */
- Debug("print command: %s\n", print_cmd);
- if (!(pp = popen(print_cmd, "w"))) {
- error("cannot print");
- return -1;
- }
- on_intr();
- for (n = 0; isoff(glob_flags, WAS_INTR) && n < msg_cnt; n++) {
- if (msg_bit(list, n)) {
- if (total++)
- (void) fputc('\f', pp); /* send a formfeed for multiple copies */
- print("printing message %d...", n+1);
- print_more("(%d lines)\n", copy_msg(n, pp, (u_long) flags, NULL));
- turnon(msg[n].m_flags, PRINTED), turnon(glob_flags, DO_UPDATE);
- }
- }
- off_intr();
- (void) pclose(pp);
- print_more("%d message%s printed ", total, (total==1)? "": "s");
- if (cmd)
- print_more("through \"%s\".\n", cmd);
- else
- print_more("at \"%s\".\n", printer);
- return 0;
- }
-
- /* save [msg_list] [file] */
- save_msg(n, argv, list) /* argc isn't used, so use space for variable 'n' */
- register char **argv, list[];
- {
- register FILE *mail_fp = NULL_FILE;
- register char *file = NULL, *mode, firstchar = **argv, *tmp = ".";
- int msg_number, force = 0, by_subj = 0, by_author = 0;
- char buf[MAXPATHLEN];
- long flg = 0;
-
- while (*++argv)
- if (*argv[0] != '-')
- break;
- else
- switch (argv[0][1]) {
- case 'S' :
- by_subj = 2;
- when 's' :
- by_subj = 1;
- when 'A' :
- by_author = 2;
- when 'a' :
- by_author = 1;
- when 'f' :
- force = 1;
- otherwise :
- return help(0, "save", cmd_help);
- }
- if (!force && (force = (*argv && !strcmp(*argv, "!"))))
- argv++;
- if ((n = get_msg_list(argv, list)) == -1)
- return -1;
- argv += n;
- if (*argv && *(file = *argv) == '\\')
- file++;
- else if (!file && !by_subj && !by_author) {
- /* if no filename specified, save in ~/mbox */
- if (firstchar == 'w') {
- /* mbox should have headers. If he really wants it, specify it */
- print("Must specify file name for 'w'\n");
- return -1;
- }
- if (!(file = do_set(set_options, "mbox")) || !*file)
- file = DEF_MBOX;
- }
- n = 1; /* tell getpath to ignore no such file or directory */
- if (file)
- tmp = getpath(file, &n);
- if (n < 0) {
- print("%s: %s\n", file, tmp);
- return -1;
- } else if (n && !by_subj && !by_author) {
- print("%s is a directory\n", file);
- return -1;
- }
- file = tmp;
- if (force || Access(file, F_OK))
- mode = "w", force = 0;
- else
- mode = "a";
- if (firstchar != 'w' && *mode == 'a' && !by_author && !by_subj &&
- !test_folder(file, "not a folder, save anyway?"))
- return 0;
- /*
- * open the file for writing (appending) unless we're saving by subject
- * or author name in which case we'll determine the filename later
- */
- if (!by_author && !by_subj && !(mail_fp = lock_fopen(file, mode))) {
- error("cannot save in \"%s\"", file);
- return -1;
- }
-
- #ifdef SUNTOOL
- if (istool)
- timeout_cursors(TRUE);
- #endif /* SUNTOOL */
- if (!chk_option("alwaysignore", "save"))
- turnon(flg, NO_IGNORE); /* presently overridden by UPDATE_STATUS */
- if (firstchar == 'w') {
- turnon(flg, NO_HEADER);
- #ifdef MMDF
- turnon(flg, NO_SEPARATOR);
- #endif /* MMDF */
- } else
- turnon(flg, UPDATE_STATUS);
-
- for (n = msg_number = 0; msg_number < msg_cnt; msg_number++)
- if (msg_bit(list, msg_number)) {
- if ((by_author || by_subj) && !mail_fp) {
- char buf2[256], addr[256];
- register char *p, *p2;
- if (by_subj) {
- if (p = header_field(msg_number, "subject")) {
- /* convert spaces and non-alpha-numerics to '_' */
- if (!lcase_strncmp(p, "re: ", 4))
- p += 4;
- for (p2 = p; *p2; p2++)
- if (!isalnum(*p2) && !index(".,@#$%-+=", *p2))
- *p2 = '_';
- } else
- p = "mbox";
- } else {
- (void) reply_to(msg_number, FALSE, buf2);
- (void) get_name_n_addr(buf2, NULL, addr);
- if (p = rindex(addr, '!'))
- p++;
- else
- p = addr;
- if (p2 = any(p, "@%"))
- *p2 = 0;
- }
- if (!p || !*p)
- p = "tmp";
- (void) sprintf(buf, "%s/%s", file, p);
- if (force || Access(buf, F_OK))
- mode = "w";
- else
- mode = "a";
- if (firstchar != 'w' && *mode == 'a' &&
- !test_folder(buf, "not a folder, save anyway?")) {
- if (by_author == 2 || by_subj == 2)
- break;
- continue;
- }
- if (!(mail_fp = lock_fopen(buf, mode))) {
- error("cannot save in \"%s\"", buf);
- if (by_author == 2 || by_subj == 2)
- break;
- continue;
- }
- }
- print("%sing msg %d ... ",
- (firstchar == 's')? "Sav" : "Writ", msg_number+1);
- print_more("(%d lines)",
- copy_msg(msg_number, mail_fp, (u_long) flg, NULL));
- if (by_author == 1 || by_subj == 1) {
- print_more(" in \"%s\"", buf);
- (void) close_lock(buf, mail_fp), mail_fp = NULL_FILE;
- }
- print_more("\n");
- n++;
- if (isoff(msg[msg_number].m_flags, SAVED) && firstchar != 'c') {
- turnon(glob_flags, DO_UPDATE);
- turnon(msg[msg_number].m_flags, SAVED);
- }
- }
- if (mail_fp) {
- (void) close_lock(file, mail_fp);
- if (!file)
- file = buf;
- print_more("%s %d msg%s to %s\n",
- (*mode == 'a')? "Appended" : "Saved", n, (n != 1)? "s": "", file);
- }
- #ifdef SUNTOOL
- if (istool) {
- extern Panel_item folder_item, save_item;
- timeout_cursors(FALSE);
- if (firstchar != 'c' && n > 0)
- (void) do_hdrs(0, DUBL_NULL, NULL);
- if (*mode == 'w' && n > 0) {
- add_folder_to_menu(folder_item, 3);
- add_folder_to_menu(save_item, 1);
- }
- }
- #endif /* SUNTOOL */
- return 0;
- }
-
- respond(n, argv, list)
- register int n; /* no use for argc, so use its address space for a variable */
- register char **argv, *list;
- {
- register char *cmd = *argv;
- char list1[MAXMSGS_BITS];
- int cur_msg = current_msg, save_cnt = msg_cnt;
-
- if (*++argv && !strcmp(*argv, "-?"))
- return help(0, "respond", cmd_help);
- if ((n = get_msg_list(argv, list)) == -1)
- return -1;
-
- /* make into our own list so ~: commands don't overwrite this list */
- bitput(list, list1, MAXMSGS, =);
-
- /* back up one arg to replace "cmd" in the new argv[0] */
- argv += (n-1);
- if (!strcmp(cmd, "replyall"))
- Upper(*cmd);
- strdup(argv[0], cmd);
-
- /* make sure the *current* message is the one being replied to */
- for (current_msg = -1, n = 0; n < msg_cnt && current_msg == -1; n++)
- if (msg_bit(list1, n) && current_msg == -1)
- current_msg = n;
- if (current_msg == -1) { /* "reply -" can cause this to happen */
- current_msg = cur_msg;
- return -1;
- }
- if (do_mail(1 /* ignored */, argv, list) == -1)
- return -1;
- /* New mail may have arrived during do_mail(), which will change
- * the msg_cnt. Use the old count when examining the list of bits
- * to set the replied flag, or the wrong messages can be marked.
- */
- for (n = 0; n < save_cnt; n++)
- if (msg_bit(list1, n)) {
- /* set_isread(n); */
- set_replied(n); /* only if mail got delivered */
- }
- if (istool)
- (void) do_hdrs(0, DUBL_NULL, NULL);
- /* copy the specified list back into msg_list */
- bitput(list1, list, MAXMSGS, =);
- return 0;
- }
-
- /* cd to a particular directory specified by "p" */
- cd(x, argv) /* argc, unused -- use space for a non-register variable */
- register char **argv;
- {
- char *cwd, buf[MAXPATHLEN];
- register char *path, *p = argv[1], *cdpath = NULL, *p2;
- int err = 0;
-
- if (argv && argv[1] && !strcmp(argv[1], "-?"))
- return help(0, argv[0], cmd_help);
-
- if (!strcmp(*argv, "pwd")) {
- set_cwd(); /* reset in case some dummy changed $cwd */
- if ((p = do_set(set_options, "cwd")) && *p) {
- print("%s\n", p);
- return 0;
- }
- return -1;
- }
- if (!p || !*p) /* if no args, pwd = ".", cd = ~ */
- p = (**argv == 'p')? "." : "~";
- /* if a full path was not specified, loop through cdpath */
- if (**argv != 'p' && *p != '/' && *p != '~' && *p != '+')
- cdpath = do_set(set_options, "cdpath");
- do {
- if (cdpath) {
- char c;
- if (p2 = any(cdpath, " \t:"))
- c = *p2, *p2 = 0;
- (void) sprintf(buf, "%s/%s", cdpath, p);
- if (cdpath = p2) /* assign and compare to NULL */
- *p2 = c;
- while (cdpath && (isspace(*cdpath) || *cdpath == ':'))
- cdpath++;
- } else
- (void) strcpy(buf, p);
- x = 0;
- path = getpath(buf, &x);
- if (x != 1 || chdir(path) == -1)
- err = errno;
- else
- err = 0;
- } while (err && cdpath && *cdpath);
- if (err)
- error(p);
- set_cwd();
- if ((istool || iscurses || err) && (cwd = do_set(set_options, "cwd"))) {
- if (err)
- turnon(glob_flags, CONT_PRNT);
- if (iscurses || istool || ison(glob_flags, WARNING))
- print("Working dir: %s\n", cwd);
- }
- return 0;
- }
-
- mush_quit(argc, argv)
- char **argv;
- {
- u_long updated = ison(glob_flags, DO_UPDATE);
-
- if (argc > 1) {
- if (!strcmp(argv[1], "-?"))
- return help(0, "quit", cmd_help);
- else {
- print("%s: too many arguments\n", argv[0]);
- return -1;
- }
- }
- if ((!argc || (*argv && **argv == 'q')) && !copyback("Really Quit? "))
- return -1;
- #ifdef CURSES
- if (iscurses) {
- /* we may already be on the bottom line; some cases won't be */
- move(LINES-1, 0), refresh();
- if (updated)
- putchar('\n');
- }
- #endif /* CURSES */
- cleanup(0);
- #ifdef lint
- return 0;
- #endif /* lint */
- }
-
- delete(argc, argv, list)
- register int argc;
- register char **argv, list[];
- {
- register int prnt_next, undel = argc && **argv == 'u';
- int old_msg = current_msg;
-
- prnt_next = (argv && (!strcmp(*argv, "dt") || !strcmp(*argv, "dp")));
-
- if (argc && *++argv && !strcmp(*argv, "-?"))
- return help(0, "delete", cmd_help);
-
- if (ison(glob_flags, READ_ONLY)) {
- print("Folder is read-only\n");
- return -1;
- }
-
- if (get_msg_list(argv, list) == -1)
- return -1;
- for (argc = 0; argc < msg_cnt; argc++)
- if (msg_bit(list, argc))
- if (undel)
- turnoff(msg[argc].m_flags, DELETE);
- else
- turnon(msg[argc].m_flags, DELETE);
-
- /* only if current_msg has been affected && not in curses mode */
- if (prnt_next == 0 && !iscurses && msg_bit(list, current_msg))
- prnt_next = !!do_set(set_options, "autoprint"); /* change to boolean */
-
- turnon(glob_flags, DO_UPDATE);
-
- /* goto next available message if current was just deleted.
- * If there are no more messages, turnoff prnt_next.
- */
- if (!iscurses && !undel && msg_bit(list, current_msg) &&
- (ison(msg[current_msg].m_flags, DELETE) ||
- ison(msg[current_msg].m_flags, SAVED)))
- (void) next_msg();
- else
- prnt_next = 0;
-
- if (prnt_next && !undel && !iscurses && isoff(glob_flags, DO_PIPE))
- if (old_msg != current_msg && isoff(msg[current_msg].m_flags, DELETE))
- display_msg(current_msg, (long)0);
- else {
- if (ison(msg[current_msg].m_flags, DELETE))
- print("No more messages.\n");
- current_msg = old_msg;
- }
- #ifdef SUNTOOL
- if (istool && isoff(glob_flags, IS_PIPE)) {
- char *av[3], buf[8];
- /* do_hdrs(0, ...) repositions the display, so pass an arg */
- av[0] = "h";
- av[1] = sprintf(buf, "%d", n_array[0] + 1);
- av[2] = NULL;
- (void) do_hdrs(2, av, NULL);
- }
- #endif /* SUNTOOL */
- return 0;
- }
-
- /*
- * historically from the "from" command in ucb-mail, this just prints
- * the composed header of the messages set in list or in pipe.
- */
- do_from(n, argv, list)
- char **argv, list[];
- {
- int inc_cur_msg = 0;
-
- if (argv && *++argv && !strcmp(*argv, "-?"))
- return help(0, "from", cmd_help);
- if (argv && *argv && (!strcmp(*argv, "+") || !strcmp(*argv, "-")))
- if (!strcmp(*argv, "+")) {
- if (!*++argv && current_msg < msg_cnt-1)
- current_msg++;
- inc_cur_msg = 1;
- } else if (!strcmp(*argv, "-")) {
- if (!*++argv && current_msg > 0)
- current_msg--;
- inc_cur_msg = -1;
- }
- if ((n = get_msg_list(argv, list)) == -1)
- return -1;
- else if (argv && argv[n]) {
- u_long save_flags = glob_flags;
- char *newargv[6], buf[BUFSIZ];
- (void) argv_to_string(buf, &argv[n]);
- newargv[0] = "pick";
- if (n == 0) {
- newargv[++n] = "-r";
- newargv[++n] = "*";
- turnoff(glob_flags, IS_PIPE);
- } else {
- n = 0;
- turnon(glob_flags, IS_PIPE);
- }
- newargv[++n] = "-f";
- newargv[++n] = buf;
- newargv[++n] = NULL;
- Debug("calling: "), print_argv(newargv);
- turnon(glob_flags, DO_PIPE);
- (void) do_pick(n, newargv, list);
- glob_flags = save_flags;
- }
- for (n = 0; n < msg_cnt; n++)
- if (msg_bit(list, n)) {
- wprint("%s\n", compose_hdr(n));
- /* if -/+ given, set current message pointer to this message */
- if (inc_cur_msg) {
- current_msg = n;
- /* if - was given, then set to first listed message.
- * otherwise, + means last listed message -- let it go...
- */
- if (inc_cur_msg < 0)
- inc_cur_msg = 0;
- }
- }
- return 0;
- }
-
- /*
- * Do an ls from the system.
- * Read from a popen and use wprint in case the tool does this command.
- * The folders command uses this command.
- */
- ls(x, argv)
- char **argv;
- {
- register char *p, *tmp;
- char buf[128];
- register FILE *pp;
-
- if (*++argv && !strcmp(*argv, "-?"))
- return help(0, "ls", cmd_help);
- p = buf + strlen(sprintf(buf, "%s -C", LS_COMMAND));
- for ( ; *argv; ++argv) {
- x = 0;
- if (**argv != '-')
- tmp = getpath(*argv, &x);
- else
- tmp = *argv;
- if (x == -1) {
- wprint("%s: %s\n", *argv, tmp);
- return -1;
- }
- *p++ = ' ';
- p += Strcpy(p, tmp);
- }
- if (!(pp = popen(buf, "r"))) {
- error(buf);
- return -1;
- }
- (void) do_pager(NULL, TRUE);
- while (fgets(buf, 127, pp) && do_pager(buf, FALSE) != EOF)
- ;
- (void) pclose(pp);
- (void) do_pager(NULL, FALSE);
- return 0;
- }
-
- /*ARGSUSED*/
- sh(un_used, argv)
- char **argv;
- {
- register char *p;
- char buf[128];
-
- if (*++argv && !strcmp(*argv, "-?"))
- return help(0, "shell", cmd_help);
- if (!(p = do_set(set_options, "shell")))
- p = DEF_SHELL;
- if (!*argv)
- if (istool) {
- print("You can't run an interactive shell from tool mode (yet).");
- return -1;
- } else
- (void) strcpy(buf, p);
- else
- (void) argv_to_string(buf, argv);
- if (!istool)
- echo_on();
- (void) system(buf);
- if (!istool)
- echo_off();
- return 0;
- }
-
- static
- sorter(cmd1, cmd2)
- register struct cmd *cmd1, *cmd2;
- {
- return strcmp(cmd1->command, cmd2->command);
- }
-
- question_mark(x, argv)
- char **argv;
- {
- int n = 0, N = sizeof cmds / sizeof (struct cmd);
- char *Cmds[sizeof cmds/sizeof(struct cmd)], *p, buf[30];
-
- if (!*++argv) {
- if (N % 5)
- N = N / 5 + 1;
- else
- N = N / 5;
-
- qsort((char *)cmds, sizeof(cmds)/sizeof(struct cmd)-1,
- sizeof(struct cmd), sorter);
-
- for (x = 0; x < N * 5; x++) {
- if (!(x % 5))
- if (!(p = Cmds[n++] = malloc(80))) {
- error("malloc in question_mark()");
- free_vec(Cmds);
- return -1;
- }
- if (x%5*N+n < sizeof cmds / sizeof (struct cmd))
- p += strlen(sprintf(p, "%-14.14s ", cmds[x%5*N+n-1].command));
- }
- Cmds[n++] = savestr("Type: `command -?' for help with most commands.");
- Cmds[n] = NULL;
- (void) help(0, (char *) Cmds, NULL);
- free_vec(Cmds);
- } else if (!strcmp(*argv, "-?"))
- return help(0, "?", cmd_help);
- else {
- for (x = 0; cmds[x].command; x++)
- if (!strcmp(*argv, cmds[x].command))
- return cmd_line(sprintf(buf, "\\%s -?", *argv), msg_list);
- print("Unknown command: %s\n", *argv);
- }
- return 0 - in_pipe();
- }
-
- #ifdef SIGSTOP
- stop(argc, argv)
- char **argv;
- {
- if (istool)
- print("Not a tool-based option.");
- if (argc && *++argv && !strcmp(*argv, "-?"))
- return help(0, "stop", cmd_help);
- if (kill(getpid(), SIGTSTP) == -1)
- error("couldn't stop myself");
- return 0;
- }
- #endif /* SIGSTOP */
-
- extern char **environ;
- static int spaces = 0;
-
- Setenv(i, argv)
- char **argv;
- {
- char *newstr;
-
- if (i > 3 || !strcmp(argv[1], "-?"))
- return help(0, "setenv", cmd_help);
- else if (i < 2)
- return Printenv(i, argv);
-
- if (i == 3) {
- if (newstr = malloc((unsigned) (strlen(argv[1]) + strlen(argv[2]) + 2)))
- (void) sprintf(newstr, "%s=%s", argv[1], argv[2]);
- } else {
- if (newstr = malloc((unsigned)(strlen(argv[1]) + 2)))
- (void) sprintf(newstr, "%s=", argv[1]);
- }
- if (!newstr) {
- error("setenv: out of memory");
- return -1;
- }
-
- (void) Unsetenv(2, argv);
-
- for (i = 0; environ[i]; i++);
- if (!spaces) {
- char **new_environ =
- (char **)malloc((unsigned) ((i+2) * sizeof(char *)));
- /* add 1 for the new item, and 1 for null-termination */
- if (!new_environ) {
- xfree(newstr);
- return -1;
- }
- spaces = 1;
- for (i = 0; new_environ[i] = environ[i]; i++);
- xfree((char *) environ);
- environ = new_environ;
- }
- environ[i] = newstr;
- environ[i+1] = NULL;
- spaces--;
- return 0;
- }
-
- Unsetenv(n, argv)
- char **argv;
- {
- char **envp, **last;
-
- if (n != 2 || !strcmp(argv[1], "-?"))
- return help(0, "unsetenv", cmd_help);
-
- n = strlen(argv[1]);
- for (last = environ; *last; last++);
- last--;
-
- for (envp = environ; envp <= last; envp++) {
- if (strncmp(argv[1], *envp, n) == 0 && (*envp)[n] == '=') {
- xfree(*envp);
- *envp = *last;
- *last-- = NULL;
- spaces++;
- }
- }
- return 0;
- }
-
- Printenv(argc, argv)
- char **argv;
- {
- char **e;
-
- if (argv && argv[1] && !strcmp(argv[1], "-?"))
- return help(0, "printenv", cmd_help);
- for (e = environ; *e; e++)
- if (argc < 2 || !strncmp(*e, argv[1], strlen(argv[1])))
- wprint("%s\n", *e);
- return 0;
- }
-
- /*
- * internal stty call to allow the user to change his tty character
- * settings. sorry, no way to change cbreak/echo modes. Save echo_flg
- * so that execute() won't reset it.
- */
- /*ARGSUSED*/
- my_stty(un_used, argv)
- char **argv;
- {
- u_long save_echo = ison(glob_flags, ECHO_FLAG);
-
- if (istool)
- return 0;
-
- if (argv && argv[1] && !strcmp(argv[1], "-?"))
- return help(0, "stty", cmd_help);
- turnon(glob_flags, ECHO_FLAG);
- execute(argv);
- if (save_echo)
- turnon(glob_flags, ECHO_FLAG);
- else
- turnoff(glob_flags, ECHO_FLAG);
-
- savetty();
- #ifdef TIOCGLTC
- if (ioctl(0, TIOCGLTC, <chars))
- error("TIOCGLTC");
- #endif /* TIOCGLTC */
- echo_off();
- return 0;
- }
-
- /*
- * Edit a message...
- */
- edit_msg(i, argv, list)
- char *argv[], list[];
- {
- int edited = 0;
- char buf[MAXPATHLEN], *b, *dir, **edit_cmd, *editor, *mktemp();
- u_long flags = 0L;
- char *cmd = *argv;
- FILE *fp;
-
- if (istool)
- return 0;
-
- if (*++argv && !strcmp(*argv, "-?"))
- return help(0, "edit_msg", cmd_help);
-
- if (ison(glob_flags, READ_ONLY)) {
- print("\"%s\" is read-only.\n", mailfile);
- return -1;
- }
-
- if (get_msg_list(argv, list) == -1)
- return -1;
-
- if (!(editor = do_set(set_options,
- (*cmd == 'v')? "visual" : "editor")) || !*editor)
- editor = DEF_EDITOR;
-
- for (i = 0; i < msg_cnt; i++) {
- if (!msg_bit(list, i))
- continue;
-
- if (edited) {
- print("Edit message %d [y/n/q]? ", i+1);
- if (Getstr(buf, sizeof (buf), 0) < 0 || lower(buf[0]) == 'q')
- return 0;
- if (buf[0] && buf[0] != 'y')
- continue;
- }
-
- b = buf + Strcpy(buf, editor);
- *b++ = ' ';
-
- /* getdir() uses the home directory if no tmpdir */
- if (!(dir = getdir(do_set(set_options, "tmpdir"))))
- alted:
- dir = ALTERNATE_HOME;
- (void) mktemp(sprintf(b, "%s/.msgXXXXXXX", dir));
- if (!(fp = mask_fopen(b, "w+"))) {
- if (strcmp(dir, ALTERNATE_HOME))
- goto alted;
- error("can't create %s", b);
- return -1;
- }
- wprint("editing message %d ...", i+1);
- /* copy message into file making sure all headers exist. */
- turnon(flags, UPDATE_STATUS);
- #ifdef MMDF
- turnon(flags, NO_SEPARATOR);
- #endif /* MMDF */
- wprint("(%d lines)\n", copy_msg(i, fp, flags, NULL));
-
- if (edit_cmd = mk_argv(buf, &edited, FALSE)) {
- print("Starting \"%s\"...\n", buf);
- (void) fclose(fp);
- turnon(glob_flags, IS_GETTING);
- execute(edit_cmd);
- turnoff(glob_flags, IS_GETTING);
- free_vec(edit_cmd);
- if (load_folder(b, FALSE, (char *)i) > 0) {
- (void) unlink(b);
- edited = 1;
- }
- set_isread(i); /* if you edit it, you read it, right? */
- }
- }
- return 0;
- }
-
- /*
- * Pipe a message list to a unix command. This function is hacked together
- * from bits of readmsg, above, and other bits of display_msg (misc.c).
- */
- pipe_msg(x, argv, list)
- register char **argv, list[];
- {
- char *p = x ? *argv : NULL;
- char buf[256], *pattern = NULL;
- u_long flg = 0L;
- extern FILE *ed_fp;
- int show_deleted = !!do_set(set_options, "show_deleted");
-
- /* Increment argv only if argv[0] is the mush command "pipe" */
- if (x && p && (!strcmp(p, "pipe") || !strcmp(p, "Pipe"))) {
- if (p && *p == 'P')
- turnon(flg, NO_HEADER);
- while (x && *++argv && **argv == '-')
- if (!strcmp(*argv, "-?"))
- return help(0, "pipe_msg", cmd_help);
- else if (!strcmp(*argv, "-p") && !(pattern = *++argv)) {
- print("Specify a pattern with -p\n");
- return -1;
- }
- }
- if (!msg_cnt) {
- print("No messages.\n");
- return -1;
- }
-
- if (x && (x = get_msg_list(argv, list)) == -1)
- return -1;
- argv += x;
- if (!*argv) {
- turnon(flg, NO_HEADER);
- /* The constant strings must be constants because user's
- * $SHELL might not be appropriate since "sh" scripts are
- * usually sent. User can always (easily) override.
- */
- (void) strcpy(buf, "/bin/sh");
- if (!pattern)
- pattern = "#!";
- } else
- (void) argv_to_string(buf, argv);
- if (!buf[0]) {
- print("Must specify a legitimate command or shell.\n");
- return -1;
- }
- current_msg = 0;
- if (!chk_option("alwaysignore", "pipe"))
- turnon(flg, NO_IGNORE);
- #ifdef MMDF
- turnon(flg, NO_SEPARATOR);
- #endif /* MMDF */
- (void) do_pager(buf, -1); /* start pager -- see do_pager() about "-1" */
- turnoff(glob_flags, WAS_INTR); /* if command interrupts, mush gets it */
-
- for (x = 0; x < msg_cnt && isoff(glob_flags, WAS_INTR); x++)
- if (msg_bit(list, x)) {
- current_msg = x;
- if (!show_deleted && ison(msg[x].m_flags, DELETE)) {
- print("Message %d deleted; ", x+1);
- if (iscurses)
- print_more("skipping it.");
- else
- print("skipping it.\n");
- continue;
- }
- set_isread(x);
- if (copy_msg(x, NULL_FILE, flg, pattern) == 0)
- print("No lines sent to %s!\n", buf);
- }
- (void) do_pager(NULL, FALSE); /* end pager */
- return 0;
- }
-
- /* echo the arguments. return 0 or -1 if -h given and there are no msgs. */
- do_echo(n, argv)
- register char **argv;
- {
- char buf[BUFSIZ], c;
- int no_return = 0, comp_hdr = 0, as_prompt = 0;
-
- while (n >= 0 && argv && *++argv && **argv == '-') {
- n = 1;
- while (n > 0 && (c = argv[0][n++]))
- switch(c) {
- case 'n': no_return++;
- when 'h': comp_hdr++;
- when 'p': as_prompt++;
- when '?': return help(0, "echo", cmd_help);
- otherwise: n = -1; break; /* Just echo whatever it was */
- }
- }
- if (comp_hdr && as_prompt) {
- print("-h and -p cannot be used together.\n");
- return -1;
- }
-
- (void) argv_to_string(buf, argv);
- if (comp_hdr) {
- if (!msg_cnt) {
- print("No messages.\n");
- return -1;
- }
- /* there may be a %-sign, so use %s to print */
- print("%s", format_hdr(current_msg, buf, FALSE)+9);
- } else if (as_prompt) {
- print("%s", format_prompt(current_msg, buf)); /* may be a %-sign */
- } else
- print("%s", buf); /* there may be a %-sign in "buf" */
- if (!no_return)
- print_more("\n");
- return 0;
- }
-
- eval_cmd (argc, argv, list)
- char *argv[], list[];
- {
- int status = -1;
- u_long save_is_pipe;
- char **newav, buf[BUFSIZ];
- int comp_hdr = 0, as_prompt = 0, as_macro = 0;
-
- while (argv && *++argv && **argv == '-') {
- int c, n = 1;
- while (c = argv[0][n++])
- switch(c) {
- case 'h': comp_hdr++;
- when 'p': as_prompt++;
- when 'm': as_macro++;
- otherwise: return help(0, "eval", cmd_help);
- }
- }
- if (comp_hdr && as_prompt) {
- print("-h and -p cannot be used together.\n");
- return -1;
- }
-
- (void) argv_to_string(buf, argv);
- if (as_macro) {
- m_xlate(buf);
- mac_queue(buf);
- return 0;
- }
- newav = make_command(buf, TRPL_NULL, &argc);
- if (comp_hdr) {
- if (!msg_cnt) {
- print("No messages.\n");
- return -1;
- }
- /* This is inefficient, but the only way to preserve
- * imbedded quotes, tabs, etc. in format expansions.
- */
- for (argv = newav; argv && *argv; argv++) {
- /* Don't mess with one-character strings */
- if (argv[0][1]) {
- char *format = *argv;
- *argv = savestr(format_hdr(current_msg, format, FALSE)+9);
- Debug("expanding (%s) to (%s)\n", format, *argv);
- xfree(format);
- }
- }
- } else if (as_prompt) {
- for (argv = newav; argv && *argv; argv++) {
- /* Don't mess with one-character strings */
- if (argv[0][1]) {
- char *tmp = *argv;
- *argv = savestr(format_prompt(current_msg, tmp));
- Debug("expanding (%s) to (%s)\n", tmp, *argv);
- xfree(tmp);
- }
- }
- }
- /* Can't use cmd_line() because we want DO_PIPE and IS_PIPE
- * to remain on -- cmd_line() turns both of them off
- */
- if (newav) {
- save_is_pipe = ison(glob_flags, IS_PIPE);
- status = do_command(argc, newav, list);
- if (save_is_pipe)
- turnon(glob_flags, IS_PIPE);
- }
- return status;
- }
-
- await(argc, argv, list)
- char *argv[], list[];
- {
- int done = 0, snooze = 30, last_cnt = msg_cnt;
-
- if (argc && *++argv) {
- if (!strcmp(*argv, "-?"))
- return help(0, "await", cmd_help);
- else if (!strcmp(*argv, "-T")) {
- if (*++argv && isdigit(**argv) && **argv > '0') {
- snooze = atoi(*argv);
- } else {
- print("await: integer greater than 0 required for -T\n");
- return -1;
- }
- }
- }
- Debug("snoozing %d\n", snooze);
-
- do {
- if (!(done = check_new_mail()))
- sleep((unsigned) snooze);
- } while (!done);
- /* Known to be safe to pass NULL to chk_two_lists() */
- if (!chk_option("quiet", "await"))
- bell();
-
- while (last_cnt < msg_cnt) {
- set_msg_bit(list, last_cnt);
- ++last_cnt;
- }
-
- return 0;
- }
-