home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-05-06 | 54.0 KB | 1,973 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 6 (of 19)."
- # Contents: mush/commands.c mush/curs_io.c
- # Wrapped by argv@turnpike on Wed May 2 13:59:24 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'mush/commands.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'mush/commands.c'\"
- else
- echo shar: Extracting \"'mush/commands.c'\" \(33824 characters\)
- sed "s/^X//" >'mush/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", mush_quit }, { "quit", mush_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 }, { "await", await },
- X { NULL, mush_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", mush_quit }, { "q", mush_quit }, { "xit", mush_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, mush_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, mush_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.
- X * 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 if (!chk_option("alwaysignore", "printer"))
- X turnon(flags, NO_IGNORE);
- X#ifdef MSG_SEPARATOR
- 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 (void) 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, (u_long) flags, NULL));
- X turnon(msg[n].m_flags, PRINTED), turnon(glob_flags, DO_UPDATE);
- 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 = 0, 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 when 'f' :
- X force = 1;
- X otherwise :
- X return help(0, "save", cmd_help);
- X }
- X if (!force && (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 if (firstchar != 'w' && *mode == 'a' && !by_author && !by_subj &&
- X !test_folder(file, "not a folder, save anyway?"))
- X return 0;
- 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 = lock_fopen(file, mode))) {
- X error("cannot save in \"%s\"", file);
- X return -1;
- X }
- X
- X#ifdef SUNTOOL
- X if (istool)
- X timeout_cursors(TRUE);
- X#endif /* SUNTOOL */
- X if (!chk_option("alwaysignore", "save"))
- X turnon(flg, NO_IGNORE); /* presently overridden by UPDATE_STATUS */
- 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 (firstchar != 'w' && *mode == 'a' &&
- X !test_folder(buf, "not a folder, save anyway?")) {
- X if (by_author == 2 || by_subj == 2)
- X break;
- X continue;
- X }
- X if (!(mail_fp = lock_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)",
- X copy_msg(msg_number, mail_fp, (u_long) flg, NULL));
- X if (by_author == 1 || by_subj == 1) {
- X print_more(" in \"%s\"", buf);
- X (void) close_lock(buf, 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 (void) close_lock(file, 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 extern Panel_item folder_item, save_item;
- X timeout_cursors(FALSE);
- X if (firstchar != 'c' && n > 0)
- X (void) do_hdrs(0, DUBL_NULL, NULL);
- X if (*mode == 'w' && n > 0) {
- X add_folder_to_menu(folder_item, 3);
- X add_folder_to_menu(save_item, 1);
- X }
- 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, save_cnt = msg_cnt;
- 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 /* New mail may have arrived during do_mail(), which will change
- X * the msg_cnt. Use the old count when examining the list of bits
- X * to set the replied flag, or the wrong messages can be marked.
- X */
- X for (n = 0; n < save_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 (void) 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, buf[MAXPATHLEN];
- X register char *path, *p = argv[1], *cdpath = NULL, *p2;
- X int err = 0;
- X
- X if (argv && argv[1] && !strcmp(argv[1], "-?"))
- X return help(0, argv[0], cmd_help);
- X
- X if (!strcmp(*argv, "pwd")) {
- X set_cwd(); /* reset in case some dummy changed $cwd */
- X if ((p = do_set(set_options, "cwd")) && *p) {
- X print("%s\n", p);
- X return 0;
- X }
- 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) || *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 set_cwd();
- X if ((istool || iscurses || err) && (cwd = do_set(set_options, "cwd"))) {
- 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
- Xmush_quit(argc, argv)
- Xchar **argv;
- X{
- X u_long updated = ison(glob_flags, DO_UPDATE);
- X
- X if (argc > 1) {
- X if (!strcmp(argv[1], "-?"))
- X return help(0, "quit", cmd_help);
- X else {
- X print("%s: too many arguments\n", argv[0]);
- X return -1;
- X }
- X }
- 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 return help(0, "delete", cmd_help);
- 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 (void) next_msg();
- X else
- X prnt_next = 0;
- X
- X if (prnt_next && !undel && !iscurses && isoff(glob_flags, DO_PIPE))
- X if (old_msg != current_msg && isoff(msg[current_msg].m_flags, DELETE))
- X display_msg(current_msg, (long)0);
- X else {
- X if (ison(msg[current_msg].m_flags, DELETE))
- X print("No more messages.\n");
- X current_msg = old_msg;
- X }
- X#ifdef SUNTOOL
- X if (istool && isoff(glob_flags, IS_PIPE)) {
- X char *av[3], buf[8];
- X /* do_hdrs(0, ...) repositions the display, so pass an arg */
- X av[0] = "h";
- X av[1] = sprintf(buf, "%d", n_array[0] + 1);
- X av[2] = NULL;
- X (void) do_hdrs(2, av, NULL);
- X }
- 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 ((n = get_msg_list(argv, list)) == -1)
- X return -1;
- X else if (argv && argv[n]) {
- X u_long save_flags = glob_flags;
- X char *newargv[6], buf[BUFSIZ];
- X (void) argv_to_string(buf, &argv[n]);
- X newargv[0] = "pick";
- X if (n == 0) {
- X newargv[++n] = "-r";
- X newargv[++n] = "*";
- X turnoff(glob_flags, IS_PIPE);
- X } else {
- X n = 0;
- X turnon(glob_flags, IS_PIPE);
- X }
- X newargv[++n] = "-f";
- X newargv[++n] = buf;
- X newargv[++n] = NULL;
- X Debug("calling: "), print_argv(newargv);
- X turnon(glob_flags, DO_PIPE);
- X (void) do_pick(n, newargv, list);
- X glob_flags = save_flags;
- X }
- 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 p = buf + strlen(sprintf(buf, "%s -C", LS_COMMAND));
- 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++ = ' ';
- X p += Strcpy(p, 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
- X/*ARGSUSED*/
- Xsh(un_used, argv)
- Xchar **argv;
- X{
- X register char *p;
- X char buf[128];
- X
- X if (*++argv && !strcmp(*argv, "-?"))
- X return help(0, "shell", cmd_help);
- X if (!(p = do_set(set_options, "shell")))
- X p = DEF_SHELL;
- X if (!*argv)
- X if (istool) {
- X print("You can't run an interactive shell from tool mode (yet).");
- X return -1;
- X } else
- X (void) strcpy(buf, p);
- X else
- X (void) argv_to_string(buf, argv);
- X if (!istool)
- X echo_on();
- X (void) system(buf);
- X if (!istool)
- 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, N = sizeof cmds / sizeof (struct cmd);
- X char *Cmds[sizeof cmds/sizeof(struct cmd)], *p, buf[30];
- X
- X if (!*++argv) {
- X if (N % 5)
- X N = N / 5 + 1;
- X else
- X N = N / 5;
- X
- X qsort((char *)cmds, sizeof(cmds)/sizeof(struct cmd)-1,
- X sizeof(struct cmd), sorter);
- X
- X for (x = 0; x < N * 5; 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 if (x%5*N+n < sizeof cmds / sizeof (struct cmd))
- X p += strlen(sprintf(p, "%-14.14s ", cmds[x%5*N+n-1].command));
- X }
- X Cmds[n++] = savestr("Type: `command -?' for help with most commands.");
- X Cmds[n] = NULL;
- X (void) help(0, (char *) Cmds, NULL);
- X free_vec(Cmds);
- X } else if (!strcmp(*argv, "-?"))
- X return help(0, "?", cmd_help);
- 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 > 3 || !strcmp(argv[1], "-?"))
- X return help(0, "setenv", cmd_help);
- X else if (i < 2)
- X return Printenv(i, argv);
- X
- X if (i == 3) {
- X if (newstr = malloc((unsigned) (strlen(argv[1]) + strlen(argv[2]) + 2)))
- X (void) sprintf(newstr, "%s=%s", argv[1], argv[2]);
- X } else {
- X if (newstr = malloc((unsigned)(strlen(argv[1]) + 2)))
- X (void) sprintf(newstr, "%s=", argv[1]);
- X }
- X if (!newstr) {
- X error("setenv: out of memory");
- X return -1;
- X }
- X
- X (void) Unsetenv(2, argv);
- X
- X for (i = 0; environ[i]; i++);
- X if (!spaces) {
- X char **new_environ =
- X (char **)malloc((unsigned) ((i+2) * sizeof(char *)));
- X /* add 1 for the new item, and 1 for null-termination */
- X if (!new_environ) {
- X xfree(newstr);
- X return -1;
- X }
- X spaces = 1;
- X for (i = 0; new_environ[i] = environ[i]; i++);
- X xfree((char *) 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
- X if (argv && argv[1] && !strcmp(argv[1], "-?"))
- X return help(0, "printenv", cmd_help);
- 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 */
- X/*ARGSUSED*/
- Xmy_stty(un_used, argv)
- Xchar **argv;
- X{
- X u_long save_echo = ison(glob_flags, ECHO_FLAG);
- X
- X if (istool)
- X return 0;
- X
- X if (argv && argv[1] && !strcmp(argv[1], "-?"))
- X return help(0, "stty", cmd_help);
- 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], *b, *dir, **edit_cmd, *editor, *mktemp();
- X u_long flags = 0L;
- X char *cmd = *argv;
- 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 if (!(editor = do_set(set_options,
- X (*cmd == 'v')? "visual" : "editor")) || !*editor)
- X editor = DEF_EDITOR;
- 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 b = buf + Strcpy(buf, editor);
- X *b++ = ' ';
- X
- X /* getdir() uses the home directory if no tmpdir */
- X if (!(dir = getdir(do_set(set_options, "tmpdir"))))
- Xalted:
- X dir = ALTERNATE_HOME;
- X (void) mktemp(sprintf(b, "%s/.msgXXXXXXX", dir));
- X if (!(fp = mask_fopen(b, "w+"))) {
- X if (strcmp(dir, ALTERNATE_HOME))
- X goto alted;
- X error("can't create %s", b);
- 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, NULL));
- X
- X if (edit_cmd = mk_argv(buf, &edited, FALSE)) {
- X print("Starting \"%s\"...\n", buf);
- X (void) fclose(fp);
- X turnon(glob_flags, IS_GETTING);
- X execute(edit_cmd);
- X turnoff(glob_flags, IS_GETTING);
- X free_vec(edit_cmd);
- X if (load_folder(b, FALSE, (char *)i) > 0) {
- X (void) unlink(b);
- X edited = 1;
- X }
- X set_isread(i); /* if you edit it, you read it, right? */
- X }
- 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], *pattern = NULL;
- X u_long flg = 0L;
- X extern FILE *ed_fp;
- X int show_deleted = !!do_set(set_options, "show_deleted");
- 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 (p && *p == 'P')
- X turnon(flg, NO_HEADER);
- X while (x && *++argv && **argv == '-')
- X if (!strcmp(*argv, "-?"))
- X return help(0, "pipe_msg", cmd_help);
- X else if (!strcmp(*argv, "-p") && !(pattern = *++argv)) {
- X print("Specify a pattern with -p\n");
- X return -1;
- X }
- 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 argv += x;
- X if (!*argv) {
- X turnon(flg, NO_HEADER);
- X /* The constant strings must be constants because user's
- X * $SHELL might not be appropriate since "sh" scripts are
- X * usually sent. User can always (easily) override.
- X */
- X (void) strcpy(buf, "/bin/sh");
- X if (!pattern)
- X pattern = "#!";
- X } else
- X (void) argv_to_string(buf, argv);
- X if (!buf[0]) {
- X print("Must specify a legitimate command or shell.\n");
- X return -1;
- X }
- X current_msg = 0;
- X if (!chk_option("alwaysignore", "pipe"))
- X turnon(flg, NO_IGNORE);
- X#ifdef MMDF
- X turnon(flg, NO_SEPARATOR);
- X#endif /* MMDF */
- X (void) do_pager(buf, -1); /* start pager -- see do_pager() about "-1" */
- X turnoff(glob_flags, WAS_INTR); /* if command interrupts, mush gets it */
- X
- X for (x = 0; x < msg_cnt && isoff(glob_flags, WAS_INTR); x++)
- X if (msg_bit(list, x)) {
- X current_msg = x;
- X if (!show_deleted && 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 if (copy_msg(x, NULL_FILE, flg, pattern) == 0)
- X print("No lines sent to %s!\n", buf);
- 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 (n >= 0 && argv && *++argv && **argv == '-') {
- X n = 1;
- X while (n > 0 && (c = argv[0][n++]))
- X switch(c) {
- X case 'n': no_return++;
- X when 'h': comp_hdr++;
- X when 'p': as_prompt++;
- X when '?': return help(0, "echo", cmd_help);
- X otherwise: n = -1; break; /* Just echo whatever it was */
- X }
- X }
- X if (comp_hdr && as_prompt) {
- X print("-h and -p cannot be used together.\n");
- X return -1;
- X }
- X
- X (void) argv_to_string(buf, argv);
- X if (comp_hdr) {
- X if (!msg_cnt) {
- X print("No messages.\n");
- X return -1;
- X }
- X /* there may be a %-sign, so use %s to print */
- X print("%s", format_hdr(current_msg, buf, FALSE)+9);
- X } else if (as_prompt) {
- X print("%s", format_prompt(current_msg, buf)); /* may be a %-sign */
- 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 int comp_hdr = 0, as_prompt = 0, as_macro = 0;
- X
- X while (argv && *++argv && **argv == '-') {
- X int c, n = 1;
- X while (c = argv[0][n++])
- X switch(c) {
- X case 'h': comp_hdr++;
- X when 'p': as_prompt++;
- X when 'm': as_macro++;
- X otherwise: return help(0, "eval", cmd_help);
- X }
- X }
- X if (comp_hdr && as_prompt) {
- X print("-h and -p cannot be used together.\n");
- X return -1;
- X }
- X
- X (void) argv_to_string(buf, argv);
- X if (as_macro) {
- X m_xlate(buf);
- X mac_queue(buf);
- X return 0;
- X }
- X newav = make_command(buf, TRPL_NULL, &argc);
- X if (comp_hdr) {
- X if (!msg_cnt) {
- X print("No messages.\n");
- X return -1;
- X }
- X /* This is inefficient, but the only way to preserve
- X * imbedded quotes, tabs, etc. in format expansions.
- X */
- X for (argv = newav; argv && *argv; argv++) {
- X /* Don't mess with one-character strings */
- X if (argv[0][1]) {
- X char *format = *argv;
- X *argv = savestr(format_hdr(current_msg, format, FALSE)+9);
- X Debug("expanding (%s) to (%s)\n", format, *argv);
- X xfree(format);
- X }
- X }
- X } else if (as_prompt) {
- X for (argv = newav; argv && *argv; argv++) {
- X /* Don't mess with one-character strings */
- X if (argv[0][1]) {
- X char *tmp = *argv;
- X *argv = savestr(format_prompt(current_msg, tmp));
- X Debug("expanding (%s) to (%s)\n", tmp, *argv);
- X xfree(tmp);
- X }
- X }
- X }
- 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) {
- 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}
- X
- Xawait(argc, argv, list)
- Xchar *argv[], list[];
- X{
- X int done = 0, snooze = 30, last_cnt = msg_cnt;
- X
- X if (argc && *++argv) {
- X if (!strcmp(*argv, "-?"))
- X return help(0, "await", cmd_help);
- X else if (!strcmp(*argv, "-T")) {
- X if (*++argv && isdigit(**argv) && **argv > '0') {
- X snooze = atoi(*argv);
- X } else {
- X print("await: integer greater than 0 required for -T\n");
- X return -1;
- X }
- X }
- X }
- X Debug("snoozing %d\n", snooze);
- X
- X do {
- X if (!(done = check_new_mail()))
- X sleep((unsigned) snooze);
- X } while (!done);
- X /* Known to be safe to pass NULL to chk_two_lists() */
- X if (!chk_option("quiet", "await"))
- X bell();
- X
- X while (last_cnt < msg_cnt) {
- X set_msg_bit(list, last_cnt);
- X ++last_cnt;
- X }
- X
- X return 0;
- X}
- END_OF_FILE
- if test 33824 -ne `wc -c <'mush/commands.c'`; then
- echo shar: \"'mush/commands.c'\" unpacked with wrong size!
- fi
- # end of 'mush/commands.c'
- fi
- if test -f 'mush/curs_io.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'mush/curs_io.c'\"
- else
- echo shar: Extracting \"'mush/curs_io.c'\" \(17773 characters\)
- sed "s/^X//" >'mush/curs_io.c' <<'END_OF_FILE'
- X/* @(#)curs_io.c (c) copyright 3/18/87 (Dan Heller) */
- X
- X/* curs_io.c -- curses based I/O */
- X#include "mush.h"
- X#include "bindings.h"
- X#include "glob.h"
- X
- Xstatic backspace();
- X
- X#if !defined(M_XENIX) || (defined(M_XENIX) && !defined(CURSES))
- Xchar *_unctrl[] = {
- X "^@", "^A", "^B", "^C", "^D", "^E", "^F", "^G", "^H", "^I", "^J", "^K",
- X "^L", "^M", "^N", "^O", "^P", "^Q", "^R", "^S", "^T", "^U", "^V", "^W",
- X "^X", "^Y", "^Z", "^[", "^\\", "^]", "^~", "^_",
- X " ", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-",
- X ".", "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";",
- X "<", "=", ">", "?", "@", "A", "B", "C", "D", "E", "F", "G", "H", "I",
- X "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W",
- X "X", "Y", "Z", "[", "\\", "]", "^", "_", "`", "a", "b", "c", "d", "e",
- X "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s",
- X "t", "u", "v", "w", "x", "y", "z", "{", "|", "}", "~", "^?"
- X};
- X#endif /* !M_XENIX || (M_XENIX && !CURSES) */
- X
- Xchar del_line; /* tty delete line character */
- Xchar del_word; /* tty delete word character */
- Xchar del_char; /* backspace */
- Xchar reprint_line; /* usually ^R */
- Xchar eofc; /* usually ^D */
- Xchar lit_next; /* usually ^V */
- Xchar complete; /* word completion, usually ESC */
- Xchar complist; /* completion listing, usually ^D */
- X
- Xtty_settings()
- X{
- X savetty();
- X
- X#ifdef SYSV
- X eofc = _tty.c_cc[VEOF];
- X#else
- X#ifdef BSD
- X if (ioctl(0, TIOCGETC, &tchars) != -1)
- X eofc = tchars.t_eofc;
- X else
- X#endif /* BSD */
- X eofc = CTRL('D');
- X#endif /* SYSV */
- X
- X if (!isatty(0)) {
- X del_line = CTRL('U');
- X del_char = CTRL('H');
- X } else {
- X del_line = _tty.sg_kill;
- X del_char = _tty.sg_erase;
- X }
- X
- X#ifdef TIOCGLTC
- X if (ioctl(0, TIOCGLTC, <chars) != -1) {
- X del_word = ltchars.t_werasc;
- X reprint_line = ltchars.t_rprntc;
- X lit_next = ltchars.t_lnextc;
- X } else
- X#endif /* TIOCGLTC */
- X {
- X del_word = CTRL('W');
- X reprint_line = CTRL('R');
- X lit_next = CTRL('V');
- X }
- X}
- X
- X#ifdef Addch
- X#undef Addch
- X#endif /* Addch */
- X
- X#ifndef CURSES
- X
- X/* Make sure all ifs have matching elses! */
- X
- X#define Addch(c) \
- X if (ison(glob_flags, ECHO_FLAG)) \
- X {;} \
- X else \
- X (void) fputc(c, stdout), (void) fflush(stdout)
- X
- X#else
- X
- X/* see end of Getstr */
- X#define Addch(c) \
- X if (iscurses) \
- X addch(c), refresh(); \
- X else if (ison(glob_flags, ECHO_FLAG)) \
- X {;} \
- X else \
- X (void) fputc(c, stdout), (void) fflush(stdout)
- X#endif /* CURSES */
- X
- X/*
- X * get a string of at most 'length' chars.
- X * allow backspace-space-backspace, kill word and kill line
- X * (options set by user in stty).
- X * length is the max length this string can get. offset is from beginning
- X * of string.
- X * input of ^D returns -1; otherwise, return the number of chars in string.
- X */
- XGetstr(String, length, offset)
- Xchar String[];
- Xregister int length;
- X{
- X register int c, literal_next = FALSE, lit_bs = FALSE;
- X struct cmd_map *curr_map;
- X int count = offset, save_wc = wrapcolumn;
- X
- X (void) fflush(stdout); /* make sure everything is flushed before getting input */
- X
- X if (mac_hide) {
- X curr_map = NULL_MAP;
- X wrapcolumn = 0;
- X } else if (ison(glob_flags, IS_GETTING))
- X curr_map = bang_map;
- X else if (iscurses)
- X curr_map = NULL_MAP;
- X else
- X curr_map = line_map;
- X
- X while ((c = m_getchar()) != '\n' && c != '\r' && c != EOF &&
- X isoff(glob_flags, WAS_INTR)) {
- X /* echo isn't set, so whatever the character, enter it */
- X if (ison(glob_flags, QUOTE_MACRO) || ison(glob_flags, ECHO_FLAG)) {
- X if (count < length) {
- X String[count++] = c;
- X /* Note: Addch includes ECHO_FLAG test */
- X if (iscntrl(c)) {
- X Addch('^');
- X Addch(_unctrl[c][1]);
- X } else
- X Addch(c);
- X } else {
- X print("\nWarning: string too long. Truncated at %d chars.",
- X length);
- X if (ison(glob_flags, QUOTE_MACRO)) {
- X mac_flush();
- X m_ungetc(reprint_line);
- X continue;
- X } else
- X break;
- X }
- X }
- X /* ^D as the first char on a line or two ^D's in a row is EOF */
- X else if (c == eofc && !count)
- X break;
- X else if (c == '\\' && count < length) {
- X literal_next = TRUE, lit_bs = FALSE;
- X Addch(String[count++] = '\\');
- X } else if (c == lit_next && count < length) {
- X literal_next = lit_bs = TRUE;
- X String[count++] = '\\';
- X if (!in_macro()) {
- X /* if (iscntrl(c)) */
- X Addch('^');
- X /* Addch(_unctrl[c][1]); */
- X }
- X } else if (literal_next) {
- X struct cmd_map *list;
- X
- X literal_next = FALSE;
- X if (iscntrl(c) || c == del_line || c == del_char || c == del_word
- X || c == lit_next || lit_bs)
- X if (!in_macro() || !lit_bs)
- X backspace(String, &count);
- X else
- X --count;
- X else if (in_macro() && c == MAC_LONG_CMD)
- X --count;
- X /* check to see if user is escaping a map or map! */
- X else
- X for (list = curr_map; list; list = list->m_next)
- X if (list->m_str[0] == c) {
- X if (!in_macro())
- X backspace(String, &count);
- X else
- X --count;
- X break;
- X }
- X /* A literal-next advances the macro offset */
- X String[count++] = c;
- X if (iscntrl(c) || c == del_char) {
- X if (iscntrl(c)) {
- X /*
- X * Decrement wrapcolumn because two chars added.
- X * It will be restored from save_wc before return.
- X */
- X if (wrapcolumn > 1)
- X wrapcolumn--;
- X Addch('^');
- X }
- X Addch(_unctrl[c][1]);
- X } else
- X Addch(c);
- X } else if (complete && (c == complete || c == complist)) {
- X (void) completion(String, &count, (c == complist));
- X } else if (c == del_line) {
- X if (count) {
- X do
- X backspace(String, &count);
- X while (count);
- X }
- X } else if (c == reprint_line)
- X String[count] = 0, wprint("\n%s", String);
- X else if (c == del_word) /* word erase */
- X while (count) {
- X backspace(String, &count);
- X if (!count ||
- X isspace(String[count-1]) && !isspace(String[count]) ||
- X !isalnum(String[count-1]) && isalnum(String[count]))
- X break;
- X }
- X else if (c == del_char || c == CTRL('H') || c == 127 /* CTRL('?') */) {
- X if (count)
- X backspace(String, &count);
- X /* if iscurses, then backspacing too far cancels a function */
- X else if (!count && iscurses && isoff(glob_flags, LINE_MACRO)) {
- X mac_flush();
- X String[0] = '\0';
- X wrapcolumn = save_wc;
- X return -1;
- X }
- X } else if (count == length)
- X bell();
- X else if (c == '\t')
- X do {
- X /* Yuck -- tabs break map! */
- X Addch(' ');
- X String[count] = ' ';
- X } while (++count % 8 && count < length);
- X else if (in_macro() && c == MAC_LONG_CMD) {
- X char cbuf[MAX_LONG_CMD + 1];
- X
- X if ((c = read_long_cmd(cbuf)) == 0) {
- X c = MAC_LONG_CMD;
- X goto check_expand; /* How could I avoid this? */
- X } else if (c > 0) {
- X int ok;
- X
- X String[count] = '\0';
- X if ((ok = reserved_cmd(cbuf, TRUE)) > 0) {
- X /* Reprint the line */
- X if (iscurses)
- X print(":%s", String);
- X else
- X wprint("\r%s", String);
- X continue; /* Get next char without changing count */
- X } else if (ok < 0) {
- X String[offset] = '\0';
- X wrapcolumn = save_wc;
- X return ok;
- X } else
- X goto push_back;
- X } else {
- X /*
- X * Ooops. We read a bunch of stuff we should not
- X * have read, because this isn't really a long command.
- X * Use a trick to push the whole thing back, ala ungetc.
- X * Wouldn't it be nifty if stdio worked this way? :-)
- X */
- Xpush_back:
- X if (c > 0) {
- X cbuf[c++] = MAC_LONG_END;
- X cbuf[c] = '\0';
- X }
- X c = MAC_LONG_CMD;
- X Ungetstr(cbuf);
- X goto check_expand; /* How could I avoid this goto? */
- X }
- X } else {
- Xcheck_expand:
- X if (!curr_map || !check_map(c, curr_map)) {
- X /* else if (match != MATCH) */
- X if (c != '\t' && iscntrl(c)) {
- X Addch('^');
- X Addch(_unctrl[c][1]);
- X /* Decrement wrapcolumn as above */
- X if (wrapcolumn > 1)
- X wrapcolumn--;
- X } else
- X Addch(c);
- X String[count++] = c;
- X }
- X }
- X /* Null-terminate for macro lookup purposes.
- X * This will be overwritten by the next character.
- X */
- X String[count] = '\0';
- X if (line_wrap(String, &count))
- X break;
- X }
- X (void) fflush(stdout); /* for sys-v folks */
- X
- X if (c == eofc || c == EOF || ison(glob_flags, WAS_INTR)) {
- X if (feof(stdin))
- X clearerr(stdin);
- X wrapcolumn = save_wc;
- X return -1;
- X }
- X if (count && String[count-1] == '\\') {
- X int count2;
- X if (isoff(glob_flags, ECHO_FLAG))
- X putchar('\n');
- X wrapcolumn = save_wc;
- X /*
- X * NOTE: If the offset passed here is ever made greater than 0,
- X * the value of wrapcolumn must again be changed/restored ...
- X */
- X if ((count2 = Getstr(&String[count-1], length - count + 1, 0)) == -1)
- X return -1;
- X return count + count2;
- X }
- X if (!iscurses && isoff(glob_flags, ECHO_FLAG))
- X putchar('\n');
- X /* Should be null-terminated already, but just in case */
- X String[count] = '\0';
- X wrapcolumn = save_wc;
- X return count;
- X}
- X
- Xstatic
- Xbackspace(str, n)
- Xregister char *str;
- Xint *n;
- X{
- X (*n)--;
- X Addch('\b'); Addch(' '); Addch('\b');
- X if (iscntrl(str[*n])) {
- X Addch('\b'); Addch(' '); Addch('\b');
- X /* Re-increment wrapcolumn -- see Getstr */
- X if (wrapcolumn)
- X wrapcolumn++;
- X }
- X}
- X
- X#undef Addch
- X
- X/*
- X * Check to see if what the user is typing is supposed to be expanded
- X * into a longer string. The first char is 'c' and the map list to use
- X * is in map_list. Continue looping (reading chars from stdin or a
- X * currently active mapping) until a match happens or we've determined
- X * that there is no match.
- X */
- Xcheck_map(c, map_list)
- Xchar c;
- Xstruct cmd_map *map_list;
- X{
- X char mbuf[MAX_MACRO_LEN], *p = mbuf;
- X struct cmd_map *list;
- X int m, n, match;
- X
- X *p++ = c;
- X
- X while (isoff(glob_flags, WAS_INTR)) {
- X m = 0;
- X *p = 0; /* make sure it's null terminated */
- X /*
- X * loop thru the list of maps and check to see if the typed
- X * char matches the mapping. If it matches completely, substitute
- X * the stuff in x_str and return. If a partial match occurs, then
- X * read the next char until a timeout or no match.
- X */
- X for (list = map_list; list; list = list->m_next) {
- X if ((match = prefix(mbuf, list->m_str)) == MATCH) {
- X /* Must turn on flags BEFORE pushing */
- X line_macro(list->x_str);
- X return 1;
- X } else if (match != NO_MATCH)
- X m++; /* something matched partially */
- X }
- X if (!m)
- X break;
- X /* see if there's anything on the queue to read... */
- X if (mac_pending()
- X#ifdef FIONREAD
- X || !ioctl(0, FIONREAD, &n) && n > 0
- X#else
- X#ifdef M_XENIX
- X || rdchk(0) > 0
- X#endif /* M_XENIX */
- X#endif /* FIONREAD */
- X )
- X *p++ = m_getchar();
- X else {
- X /* The user has typed the first part of a map or macro. Give him
- X * a chance to finish it.
- X */
- X#if defined(BSD) || defined(SELECT)
- X /* If the system has select(), use it. It's much faster and
- X * more aesthetic since there is no mandatory timeout.
- X */
- X struct timeval timer;
- X#ifdef FD_SET
- X fd_set rmask, wmask, xmask;
- X FD_SET(0, &rmask); /* Test stdin for read */
- X FD_ZERO(&wmask); /* Don't care about write */
- X FD_ZERO(&xmask); /* Don't care about exception */
- X#else
- X int rmask = 1, wmask = 0, xmask = 0;
- X#endif /* FD_SET */
- X timer.tv_sec = 1;
- X timer.tv_usec = 0;
- X n = select(1, &rmask, &wmask, &xmask, &timer);
- X#else /* !SELECT */
- X#ifdef FIONREAD
- X /* system doesn't have select(), so use FIONREAD to see if
- X * there are any chars on the queue to read.
- X */
- X (void) sleep(1);
- X (void) ioctl(0, FIONREAD, &n);
- X#else
- X#ifdef M_XENIX
- X (void) sleep(1);
- X n = rdchk(0);
- X#else
- X
- X /* system has neither select() nor FIONREAD, so just set n
- X * and force the user to either complete the map or fail it
- X * without a timeout. Chars won't echo till he does one or
- X * the other.
- X */
- X n = 1;
- X#endif /* M_XENIX */
- X#endif /* FIONREAD */
- X#endif /* SELECT */
- X if (n > 0)
- X /* don't read all 'n' chars -- there may be a match early */
- X *p++ = m_getchar(); /* To flush macros and reset flags */
- X else /* still nothing to read? User doesn't want to use map */
- X break;
- X }
- X }
- X /* no match or a timeout. This isn't a map, just return. */
- X *p = 0;
- X if (mbuf[1])
- X (void) mac_push(mbuf + 1);
- X return 0;
- X}
- X
- X/*
- X * Check for line wrap. This should happen only in composition mode and
- X * only when the variable wrapcolumn has a value greater than zero. Line
- X * wrap is implemented using Ungetstr [that is, mac_push()].
- X *
- X * Returns 1 if the line was wrapped, 0 if not.
- X */
- Xline_wrap(string, count)
- Xchar *string; /* The string to be wrapped */
- Xint *count; /* Offset of string terminator */
- X{
- X char *tail = NULL;
- X int n = *count;
- X
- X if (wrapcolumn < 1 || *count <= wrapcolumn
- X || isoff(glob_flags, IS_GETTING) /* Wrap only in msg body */
- X || ison(glob_flags, QUOTE_MACRO) /* Don't wrap quoted macros */
- X || ison(glob_flags, ECHO_FLAG)) /* Can't wrap in echo mode */
- X return 0;
- X
- X /* Back up past the wrapcolumn point */
- X for (; n > wrapcolumn; --n)
- X ;
- X /* Look for a space */
- X while (n && !isspace(string[n]))
- X --n;
- X /* If no break found, return no wrap */
- X if (!n)
- X return 0;
- X tail = &string[n+1];
- X /* Skip the break char and any whitespace */
- X while (n && isspace(string[n]))
- X --n;
- X ++n; /* move back into the whitespace */
- X /* Erase the stuff that will wrap */
- X while (*count > n)
- X backspace(string,count);
- X string[*count] = '\0';
- X /* Push the tail, if any */
- X if (*tail)
- X Ungetstr(tail);
- X return 1;
- X}
- X
- X/*
- X * Error bell used by completion()
- X */
- Xerrbell(ret)
- Xint ret;
- X{
- X if (ret < 0 || !chk_option("quiet", "completion"))
- X bell();
- X return ret;
- X}
- X
- X/*
- X * Perform word completion on the input string
- X */
- Xcompletion(string, count, showlist)
- Xchar *string; /* The string to be completed */
- Xint *count; /* Offset of string terminator */
- Xint showlist; /* Display list, don't complete */
- X{
- X char buf[MAXPATHLEN], *b = buf, **exp;
- X int n = *count, f, len, prefix, trim, overstrike, expandall;
- X
- X if (!*string || !*count)
- X return errbell(-1);
- X
- X /* Look for a delimiter */
- X while (n > 0 && !index(DELIM, string[--n]))
- X ;
- X if (n > 0 || index(DELIM, string[n]))
- X n++;
- X b = buf + (len = Strcpy(buf, &string[n]));
- X Debug("\nexpanding (%s) ... ", buf);
- X if (!any(buf, FMETA)) {
- X expandall = 0;
- X overstrike = (*buf == '+' || *buf == '~' || *buf == '%');
- X trim = (overstrike && len > 1);
- X if (!overstrike || len > 1 || (*buf == '+' && showlist))
- X *b++ = '*', *b = 0;
- X /* Previous behavior for '+' completions (trailing '/'):
- X if (len > 1 || *buf != '~' || *buf != '%')
- X *b++ = '*', *b = 0;
- X */
- X f = filexp(buf, &exp);
- X if (*--b == '*')
- X *b = 0; /* We need the original buf below */
- X } else {
- X overstrike = 1;
- X trim = (*buf == '+' || *buf == '~');
- X /*
- X * Check first to see if the base pattern matches.
- X * If not, append a '*' and try again.
- X * Don't expand all matches in the latter case.
- X */
- X if ((f = filexp(buf, &exp)) < 1) {
- X *b++ = '*', *b = 0;
- X f = filexp(buf, &exp);
- X *--b = 0; /* We need the original buf below */
- X expandall = 0;
- X } else
- X expandall = 1;
- X }
- X if (!showlist)
- X f = fignore(f, &exp);
- X if (f < 0) {
- X Debug("globbing error!\n%s", string);
- X free_vec(exp);
- X return errbell(-1);
- X } else if (f > 0) {
- X Debug("result is: "), print_argv(exp);
- X if (!expandall && f > 1)
- X prefix = lcprefix(exp, overstrike ? 0 : len);
- X else
- X prefix = 0;
- X if (showlist) {
- X if (!expandall && f > 1)
- X while (prefix && exp[0][prefix - 1] != '/')
- X --prefix;
- X putchar('\n');
- X if (columnate(f, exp, prefix) < 0)
- X (void) errbell(-1);
- X /* Reprint the line */
- X if (iscurses) {
- X wprint(":%s", string);
- X turnon(glob_flags, CNTD_CMD);
- X } else {
- X if (isoff(glob_flags, IS_GETTING))
- X mail_status(1);
- X wprint("%s", string);
- X }
- X } else if (expandall || strlen(exp[0]) > len) {
- X Debug("%s", string);
- X if (overstrike && (prefix || expandall || f == 1)) {
- X char *tmpv[3];
- X tmpv[0] = buf;
- X if (trim)
- X tmpv[1] = trim_filename(exp[0]);
- X else
- X tmpv[1] = exp[0];
- X tmpv[2] = NULL;
- X /* Back up as far as is necessary */
- X len = lcprefix(tmpv, 0);
- X /* If nothing will be erased, we may need to beep */
- X if (n + len == *count) {
- X if (!expandall && !tmpv[1][len])
- X (void) errbell(0);
- X }
- X /* Erase the stuff that will complete */
- X while (*count > n + len)
- X backspace(string,count);
- X string[*count] = '\0';
- X }
- X if (expandall || f == 1) {
- X /* Unget the names IN REVERSE ORDER! */
- X while (f--) {
- X if (trim)
- X b = trim_filename(exp[f]);
- X else
- X b = exp[f];
- X if (f) {
- X Ungetstr(b);
- X Ungetstr(" ");
- X } else
- X Ungetstr(b + len);
- X }
- X } else {
- X if (prefix > len) {
- X exp[0][prefix] = 0;
- X Debug("\ncompletion is (%s)\n%s", exp[0], string);
- X if (trim)
- X Ungetstr(trim_filename(exp[0]) + len);
- X else
- X Ungetstr(&exp[0][len]);
- X } else
- X Debug("\nno longer prefix\n%s", string);
- X /* Special case because "+" always tries to expand "+*"
- X * to get listings and avoid getpath()'s trailing '/'.
- X * No error bell is needed in those cases.
- X */
- X if (strcmp(buf, "+") != 0)
- X (void) errbell(0);
- X }
- X } else {
- X Debug("no longer prefix\n%s", string);
- X (void) errbell(0);
- X }
- X } else {
- X Debug("no match\n%s", string);
- X (void) errbell(0);
- X }
- X free_vec(exp);
- X return 1;
- X}
- X
- Xfignore(argc, argvp)
- Xint argc;
- Xchar ***argvp;
- X{
- X char *fign = do_set(set_options, "fignore");
- X char **flist, buf[MAXPATHLEN], *b = buf;
- X int fcnt, i;
- X
- X if (argc < 2 || !fign || !*fign)
- X return argc;
- X if (!argvp || !*argvp && !**argvp)
- X return -1;
- X
- X if ((flist = mk_argv(fign, &fcnt, FALSE)) && fcnt > 0) {
- X *b++ = '*';
- X for (i = 0; i < fcnt; i++) {
- X if (flist[i][0] == '.' && !any(flist[i], FMETA)) {
- X (void) strcpy(b, flist[i]);
- X (void) strdup(flist[i], buf);
- X }
- X }
- X Debug("ignoring "), print_argv(flist);
- X fcnt = gdiffv(argc, argvp, fcnt, flist);
- X free_vec(flist);
- X if (fcnt == 0)
- X fcnt = argc;
- X }
- X return fcnt;
- X}
- END_OF_FILE
- if test 17773 -ne `wc -c <'mush/curs_io.c'`; then
- echo shar: \"'mush/curs_io.c'\" unpacked with wrong size!
- fi
- # end of 'mush/curs_io.c'
- fi
- echo shar: End of archive 6 \(of 19\).
- cp /dev/null ark6isdone
- 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
-
-
-