home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mush-7.1.1 / commands.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-05-02  |  33.0 KB  |  1,250 lines

  1. /* @(#)commands.c    (c) copyright 10/18/86 (Dan Heller) */
  2.  
  3. #include "mush.h"
  4.  
  5. /*
  6.  * Note that all of the routines in here act upon and return 0 or -1.
  7.  * if -1, then the main loop will clear message lists.
  8.  */
  9.  
  10. struct cmd cmds[] = {
  11. #ifdef SIGSTOP
  12.     { "stop", stop },
  13. #endif /* SIGSTOP */
  14.     { "?",       question_mark },{ "sh", sh },
  15.     { "alias",       do_alias    },  { "unalias",    do_alias   },
  16.     { "expand",      do_alias    },  { "cmd",     do_alias   },
  17.     { "uncmd",       do_alias    },  { "from",    do_from    },
  18.     { "un_hdr",      do_alias    },  { "my_hdr",      do_alias   },
  19.     { "fkey",       do_alias    },  { "unfkey",     do_alias   },
  20.     { "set",       set         },  { "unset",     set        },
  21.     { "ignore",      set         },  { "unignore", set        },
  22.     { "version",  do_version  },  { "help",    print_help },
  23.     { "pick",       do_pick     },  { "sort",     sort        },
  24.     { "next",      readmsg     },  { "previous", readmsg    },
  25.     { "type",     readmsg     },  { "print",    readmsg    },
  26.     { "history",  disp_hist   },  { "top",    readmsg       },
  27.     { "saveopts", save_opts   },  { "source",   source        },
  28.     { "headers",  do_hdrs     },  { "ls",    ls       },
  29.     { "folder",   folder      },  { "update",   folder     },
  30.     { "cd",       cd          },  { "pwd",    cd        },
  31.     { "exit",      mush_quit   },  { "quit",     mush_quit  },
  32.     { "write",       save_msg    },  { "save",     save_msg   },
  33.     { "copy",       save_msg    },  { "folders",  folders    },
  34.     { "merge",      merge_folders },
  35. #ifdef CURSES
  36.     { "curses",   curses_init },  { "bind",    bind_it    },
  37.     { "unbind",   bind_it     },  { "bind-macro", bind_it  },
  38.     { "unbind-macro", bind_it  },
  39. #endif /* CURSES */
  40.     { "map",      bind_it     },  { "unmap",       bind_it    },
  41.     { "map!",     bind_it     },  { "unmap!",      bind_it    },
  42.     { "preserve", preserve    },  { "unpreserve",  preserve   },
  43.     { "replyall", respond     },  { "replysender", respond    },
  44.     { "delete",      delete      },  { "undelete",    delete     },
  45.     { "mail",       do_mail     },  { "echo",       do_echo    },
  46.     { "lpr",      lpr          },  { "alternates",  alts       },
  47.     { "edit",      edit_msg    },  { "flags",       msg_flags  },
  48.     { "pipe",     pipe_msg    },  { "eval",       eval_cmd   },
  49.     { "undigest", do_undigest },  { "await",       await      },
  50.     { NULL, mush_quit }
  51. };
  52.  
  53. struct cmd ucb_cmds[] = {
  54.     { "t",   readmsg   }, { "n",  readmsg  }, { "p", readmsg  },
  55.     { "+",   readmsg   }, { "-",  readmsg  }, { "P", readmsg  },
  56.     { "Print", readmsg }, { "T",  readmsg  }, { "Type", readmsg },
  57.     { "x",   mush_quit }, { "q", mush_quit }, { "xit", mush_quit },
  58.     { ":a",  do_hdrs   }, { ":d", do_hdrs  }, { ":r", do_hdrs },
  59.     { ":o",  do_hdrs   }, { ":u", do_hdrs  }, { ":n", do_hdrs },
  60.     { ":s",  do_hdrs   }, { ":p", do_hdrs  },
  61.     { "z",   do_hdrs   }, { "z-", do_hdrs  }, { "z+", do_hdrs },
  62.     { "h",   do_hdrs   }, { "H",  do_hdrs  },
  63.     { "f",   do_from   }, { "m",  do_mail  }, { "alts", alts  },
  64.     { "d",   delete    }, { "dt", delete   }, { "dp", delete  },
  65.     { "u",   delete    }, { "fo", folder   },
  66.     { "s",   save_msg  }, { "co", save_msg }, { "w", save_msg },
  67.     { "pre", preserve  }, { "unpre", preserve },
  68.     { "R",   respond   }, { "r",   respond },
  69.     { "reply", respond }, { "respond", respond },
  70.     { "v",   edit_msg  }, { "e",   edit_msg },
  71.     { NULL, mush_quit }
  72. };
  73.  
  74. struct cmd hidden_cmds[] = {
  75.     { "debug", toggle_debug }, { "open",     nopenfiles },
  76.     { "stty",    my_stty     },
  77.     { "setenv",    Setenv      }, { "unsetenv",     Unsetenv   },
  78.     { "printenv", Printenv  }, { "Pipe",    pipe_msg   },
  79.     { NULL, mush_quit }
  80. };
  81.  
  82. toggle_debug(argc, argv)
  83. char **argv;
  84. {
  85.     if (argc < 2) /* no value -- toggle "debug" (off/on) */
  86.     debug = !debug;
  87.     else
  88.     debug = atoi(*++argv);
  89.     print("debugging value: %d\n", debug);
  90.     return 0;
  91. }
  92.  
  93. /* if + was specified, then print messages without headers.
  94.  * n or \n (which will be NULL) will print next unread or undeleted message.
  95.  */
  96. readmsg(x, argv, list)
  97. register char **argv, list[];
  98. {
  99.     register char *p = x? *argv : NULL;
  100.     register long flg = 0;
  101.     extern FILE *ed_fp;
  102.  
  103.     if (x && *++argv && !strcmp(*argv, "-?"))
  104.     return help(0, "readmsg", cmd_help);
  105.     /* View a message as long as user isn't in the editor.
  106.      * If ed_fp is not null, then we've got the
  107.      * file open for typing.  If it's NULL, then an editor is going.
  108.      */
  109.     if (ison(glob_flags, IS_GETTING) && !ed_fp) {
  110.     print("Not while you're in the editor, you don't.\n");
  111.     return -1;
  112.     }
  113.     if (!msg_cnt) {
  114.     print("No messages.\n");
  115.     return -1;
  116.     }
  117.     if (x)
  118.     if (!strcmp(p, "top"))
  119.         turnon(flg, M_TOP);
  120.     else if (*p == '+') {
  121.         turnon(flg, NO_PAGE);
  122.         turnon(flg, NO_HEADER);
  123.     } else if (isupper(*p))
  124.         turnon(flg, NO_IGNORE);
  125.  
  126.     if (x && (x = get_msg_list(argv, list)) == -1)
  127.     return -1;
  128.     else if (x == 0) {  /* no arguments were parsed (or given) */
  129.     /* get_msg_list sets current msg on */
  130.     if (isoff(glob_flags, IS_PIPE))
  131.         unset_msg_bit(list, current_msg);
  132.     /* most commands move to the "next" message. type and print don't */
  133.     if ((!p || !*p || *p == 'n' || *p == '+') && current_msg < msg_cnt &&
  134.                     isoff(msg[current_msg].m_flags, UNREAD))
  135.         current_msg++;
  136.     if (p && (*p == '-' || !strcmp(p, "previous"))) {
  137.         while (--current_msg >= 0 &&
  138.         (ison(msg[current_msg].m_flags, DELETE) ||
  139.          ison(msg[current_msg].m_flags, SAVED)))
  140.         ;
  141.         if (current_msg < 0) {
  142.         print("No previous message.\n");
  143.         current_msg = 0;
  144.         return -1;
  145.         }
  146.     } else {
  147.         /*
  148.          * To be compatible with ucb-mail, find the next available unread
  149.          * message.  If at the end, only wrap around if "wrap" is set.
  150.          */
  151.         if (current_msg == msg_cnt && do_set(set_options, "wrap"))
  152.         current_msg = 0;
  153.         /* "type" or "print" prints the current only -- "next" goes on.. */
  154.         if (!p || !*p || *p == 'n')
  155.         while (current_msg < msg_cnt &&
  156.             (ison(msg[current_msg].m_flags, DELETE) ||
  157.              ison(msg[current_msg].m_flags, SAVED)))
  158.             current_msg++;
  159.         if (current_msg >= msg_cnt) {
  160.         print("No more messages.\n");
  161.         current_msg = msg_cnt - 1;
  162.         return -1;
  163.         }
  164.     }
  165.     if (isoff(glob_flags, IS_PIPE))
  166.         set_msg_bit(list, current_msg);
  167.     }
  168.     current_msg = 0;
  169.     for (x = 0; x < msg_cnt; x++)
  170.     if (msg_bit(list, x)) {
  171.         current_msg = x;
  172. #ifdef SUNTOOL
  173.         if (istool > 1) {
  174.         read_mail(NO_ITEM, 0, NO_EVENT);
  175.         return 0;
  176.         }
  177. #endif /* SUNTOOL */
  178.         display_msg(x, flg);
  179.     }
  180.     return 0;
  181. }
  182.  
  183. preserve(n, argv, list)
  184. register int n;        /* no use for argc, so use space for a local variable */
  185. register char **argv, list[];
  186. {
  187.     register int unpre;
  188.  
  189.     unpre = !strncmp(*argv, "un", 2);
  190.     if (*++argv && !strcmp(*argv, "-?"))
  191.     return help(0, "preserve", cmd_help);
  192.     if (get_msg_list(argv, list) == -1)
  193.     return -1;
  194.     for (n = 0; n < msg_cnt; n++)
  195.     if (msg_bit(list, n))
  196.         if (unpre) {
  197.         if (ison(msg[n].m_flags, PRESERVE)) {
  198.             turnoff(msg[n].m_flags, PRESERVE);
  199.             turnon(glob_flags, DO_UPDATE);
  200.         }
  201.         } else {
  202.         if (isoff(msg[n].m_flags, PRESERVE)) {
  203.             /* || ison(msg[n].m_flags, DELETE)) */
  204.             /* turnoff(msg[n].m_flags, DELETE); */
  205.             turnon(msg[n].m_flags, PRESERVE);
  206.             turnon(glob_flags, DO_UPDATE);
  207.         }
  208.         }
  209.     if (istool)
  210.     (void) do_hdrs(0, DUBL_NULL, NULL);
  211.     return 0;
  212. }
  213.  
  214. lpr(n, argv, list)
  215. register int n;  /* no use for argc, so use its address space for a variable */
  216. register char **argv, list[];
  217. {
  218.     register FILE    *pp;
  219.     register long     flags = 0;
  220.     char        print_cmd[128], *printer, c, *cmd;
  221.     int            total = 0;
  222.     SIGRET        (*oldint)(), (*oldquit)();
  223.  
  224.     if (!chk_option("alwaysignore", "printer"))
  225.     turnon(flags, NO_IGNORE);
  226. #ifdef MSG_SEPARATOR
  227.     turnon(flags, NO_SEPARATOR);
  228. #endif /* MMDF */
  229.     if (!(printer = do_set(set_options, "printer")) || !*printer)
  230.     printer = DEF_PRINTER;
  231.     while (argv && *++argv && **argv == '-') {
  232.     n = 1;
  233.     while (c = argv[0][n++])
  234.         switch(c) {
  235.         case 'n': turnon(flags, NO_HEADER);
  236.         when 'h': turnoff(flags, NO_IGNORE);
  237.         when 'P': case 'd':
  238.             if (!argv[0][n]) {
  239.                 print("specify printer!\n");
  240.                 return -1;
  241.             }
  242.             printer = argv[0] + n;
  243.             n += strlen(printer);
  244.         otherwise: return help(0, "lpr", cmd_help);
  245.         }
  246.     }
  247.     if (get_msg_list(argv, list) == -1)
  248.     return -1;
  249.  
  250.     if (cmd = do_set(set_options, "print_cmd"))
  251.     (void) strcpy(print_cmd, cmd);
  252.     else
  253. #ifdef SYSV
  254.     (void) sprintf(print_cmd, "%s -d%s", LPR, printer);
  255. #else
  256.     (void) sprintf(print_cmd, "%s -P%s", LPR, printer);
  257. #endif /* SYSV */
  258.     Debug("print command: %s\n", print_cmd);
  259.     if (!(pp = popen(print_cmd, "w"))) {
  260.     error("cannot print");
  261.     return -1;
  262.     }
  263.     on_intr();
  264.     for (n = 0; isoff(glob_flags, WAS_INTR) && n < msg_cnt; n++) {
  265.     if (msg_bit(list, n)) {
  266.         if (total++)
  267.         (void) fputc('\f', pp); /* send a formfeed for multiple copies */
  268.         print("printing message %d...", n+1);
  269.         print_more("(%d lines)\n", copy_msg(n, pp, (u_long) flags, NULL));
  270.         turnon(msg[n].m_flags, PRINTED), turnon(glob_flags, DO_UPDATE);
  271.     }
  272.     }
  273.     off_intr();
  274.     (void) pclose(pp);
  275.     print_more("%d message%s printed ", total, (total==1)? "": "s");
  276.     if (cmd)
  277.     print_more("through \"%s\".\n", cmd);
  278.     else
  279.     print_more("at \"%s\".\n", printer);
  280.     return 0;
  281. }
  282.  
  283. /* save [msg_list] [file] */
  284. save_msg(n, argv, list)   /* argc isn't used, so use space for variable 'n' */
  285. register char **argv, list[];
  286. {
  287.     register FILE    *mail_fp = NULL_FILE;
  288.     register char     *file = NULL, *mode, firstchar = **argv, *tmp = ".";
  289.     int         msg_number, force = 0, by_subj = 0, by_author = 0;
  290.     char        buf[MAXPATHLEN];
  291.     long         flg = 0;
  292.  
  293.     while (*++argv)
  294.     if (*argv[0] != '-')
  295.         break;
  296.     else
  297.         switch (argv[0][1]) {
  298.         case 'S' :
  299.             by_subj = 2;
  300.         when 's' :
  301.             by_subj = 1;
  302.         when 'A' :
  303.             by_author = 2;
  304.         when 'a' :
  305.             by_author = 1;
  306.         when 'f' :
  307.             force = 1;
  308.         otherwise :
  309.             return help(0, "save", cmd_help);
  310.         }
  311.     if (!force && (force = (*argv && !strcmp(*argv, "!"))))
  312.     argv++;
  313.     if ((n = get_msg_list(argv, list)) == -1)
  314.     return -1;
  315.     argv += n;
  316.     if (*argv && *(file = *argv) == '\\')
  317.     file++;
  318.     else if (!file && !by_subj && !by_author) {
  319.     /* if no filename specified, save in ~/mbox */
  320.     if (firstchar == 'w') {
  321.         /* mbox should have headers. If he really wants it, specify it */
  322.         print("Must specify file name for 'w'\n");
  323.         return -1;
  324.     }
  325.     if (!(file = do_set(set_options, "mbox")) || !*file)
  326.         file = DEF_MBOX;
  327.     }
  328.     n = 1; /* tell getpath to ignore no such file or directory */
  329.     if (file)
  330.     tmp = getpath(file, &n);
  331.     if (n < 0) {
  332.     print("%s: %s\n", file, tmp);
  333.     return -1;
  334.     } else if (n && !by_subj && !by_author) {
  335.     print("%s is a directory\n", file);
  336.     return -1;
  337.     }
  338.     file = tmp;
  339.     if (force || Access(file, F_OK))
  340.     mode = "w", force = 0;
  341.     else
  342.     mode = "a";
  343.     if (firstchar != 'w' && *mode == 'a' && !by_author && !by_subj &&
  344.         !test_folder(file, "not a folder, save anyway?"))
  345.     return 0;
  346.     /*
  347.      * open the file for writing (appending) unless we're saving by subject
  348.      * or author name in which case we'll determine the filename later
  349.      */
  350.     if (!by_author && !by_subj && !(mail_fp = lock_fopen(file, mode))) {
  351.     error("cannot save in \"%s\"", file);
  352.     return -1;
  353.     }
  354.  
  355. #ifdef SUNTOOL
  356.     if (istool)
  357.     timeout_cursors(TRUE);
  358. #endif /* SUNTOOL */
  359.     if (!chk_option("alwaysignore", "save"))
  360.     turnon(flg, NO_IGNORE);    /* presently overridden by UPDATE_STATUS */
  361.     if (firstchar == 'w') {
  362.     turnon(flg, NO_HEADER);
  363. #ifdef MMDF
  364.     turnon(flg, NO_SEPARATOR);
  365. #endif /* MMDF */
  366.     } else
  367.     turnon(flg, UPDATE_STATUS);
  368.  
  369.     for (n = msg_number = 0; msg_number < msg_cnt; msg_number++)
  370.     if (msg_bit(list, msg_number)) {
  371.         if ((by_author || by_subj) && !mail_fp) {
  372.         char buf2[256], addr[256];
  373.         register char *p, *p2;
  374.         if (by_subj) {
  375.             if (p = header_field(msg_number, "subject")) {
  376.             /* convert spaces and non-alpha-numerics to '_' */
  377.             if (!lcase_strncmp(p, "re: ", 4))
  378.                 p += 4;
  379.             for (p2 = p; *p2; p2++)
  380.                 if (!isalnum(*p2) && !index(".,@#$%-+=", *p2))
  381.                 *p2 = '_';
  382.             } else
  383.             p = "mbox";
  384.         } else {
  385.             (void) reply_to(msg_number, FALSE, buf2);
  386.             (void) get_name_n_addr(buf2, NULL, addr);
  387.             if (p = rindex(addr, '!'))
  388.             p++;
  389.             else
  390.             p = addr;
  391.             if (p2 = any(p, "@%"))
  392.             *p2 = 0;
  393.         }
  394.         if (!p || !*p)
  395.             p = "tmp";
  396.         (void) sprintf(buf, "%s/%s", file, p);
  397.         if (force || Access(buf, F_OK))
  398.             mode = "w";
  399.         else
  400.             mode = "a";
  401.         if (firstchar != 'w' && *mode == 'a' &&
  402.             !test_folder(buf, "not a folder, save anyway?")) {
  403.             if (by_author == 2 || by_subj == 2)
  404.             break;
  405.             continue;
  406.         }
  407.         if (!(mail_fp = lock_fopen(buf, mode))) {
  408.             error("cannot save in \"%s\"", buf);
  409.             if (by_author == 2 || by_subj == 2)
  410.             break;
  411.             continue;
  412.         }
  413.         }
  414.         print("%sing msg %d ... ",
  415.         (firstchar == 's')? "Sav" : "Writ", msg_number+1);
  416.         print_more("(%d lines)",
  417.         copy_msg(msg_number, mail_fp, (u_long) flg, NULL));
  418.         if (by_author == 1 || by_subj == 1) {
  419.         print_more(" in \"%s\"", buf);
  420.         (void) close_lock(buf, mail_fp), mail_fp = NULL_FILE;
  421.         }
  422.         print_more("\n");
  423.         n++;
  424.         if (isoff(msg[msg_number].m_flags, SAVED) && firstchar != 'c') {
  425.         turnon(glob_flags, DO_UPDATE);
  426.         turnon(msg[msg_number].m_flags, SAVED);
  427.         }
  428.     }
  429.     if (mail_fp) {
  430.     (void) close_lock(file, mail_fp);
  431.     if (!file)
  432.         file = buf;
  433.     print_more("%s %d msg%s to %s\n",
  434.         (*mode == 'a')? "Appended" : "Saved", n, (n != 1)? "s": "", file);
  435.     }
  436. #ifdef SUNTOOL
  437.     if (istool) {
  438.     extern Panel_item folder_item, save_item;
  439.     timeout_cursors(FALSE);
  440.     if (firstchar != 'c' && n > 0)
  441.         (void) do_hdrs(0, DUBL_NULL, NULL);
  442.     if (*mode == 'w' && n > 0) {
  443.         add_folder_to_menu(folder_item, 3);
  444.         add_folder_to_menu(save_item, 1);
  445.     }
  446.     }
  447. #endif /* SUNTOOL */
  448.     return 0;
  449. }
  450.  
  451. respond(n, argv, list)
  452. register int n;  /* no use for argc, so use its address space for a variable */
  453. register char **argv, *list;
  454. {
  455.     register char *cmd = *argv;
  456.     char list1[MAXMSGS_BITS];
  457.     int cur_msg = current_msg, save_cnt = msg_cnt;
  458.  
  459.     if (*++argv && !strcmp(*argv, "-?"))
  460.     return help(0, "respond", cmd_help);
  461.     if ((n = get_msg_list(argv, list)) == -1)
  462.     return -1;
  463.  
  464.     /* make into our own list so ~: commands don't overwrite this list */
  465.     bitput(list, list1, MAXMSGS, =);
  466.  
  467.     /* back up one arg to replace "cmd" in the new argv[0] */
  468.     argv += (n-1);
  469.     if (!strcmp(cmd, "replyall"))
  470.     Upper(*cmd);
  471.     strdup(argv[0], cmd);
  472.  
  473.     /* make sure the *current* message is the one being replied to */
  474.     for (current_msg = -1, n = 0; n < msg_cnt && current_msg == -1; n++)
  475.     if (msg_bit(list1, n) && current_msg == -1)
  476.         current_msg = n;
  477.     if (current_msg == -1) { /* "reply -" can cause this to happen */
  478.     current_msg = cur_msg;
  479.     return -1;
  480.     }
  481.     if (do_mail(1 /* ignored */, argv, list) == -1)
  482.     return -1;
  483.     /* New mail may have arrived during do_mail(), which will change
  484.      * the msg_cnt.  Use the old count when examining the list of bits
  485.      * to set the replied flag, or the wrong messages can be marked.
  486.      */
  487.     for (n = 0; n < save_cnt; n++)
  488.     if (msg_bit(list1, n)) {
  489.         /* set_isread(n); */
  490.         set_replied(n); /* only if mail got delivered */
  491.     }
  492.     if (istool)
  493.     (void) do_hdrs(0, DUBL_NULL, NULL);
  494.     /* copy the specified list back into msg_list */
  495.     bitput(list1, list, MAXMSGS, =);
  496.     return 0;
  497. }
  498.  
  499. /* cd to a particular directory specified by "p" */
  500. cd(x, argv) /* argc, unused -- use space for a non-register variable */
  501. register char **argv;
  502. {
  503.     char *cwd, buf[MAXPATHLEN];
  504.     register char *path, *p = argv[1], *cdpath = NULL, *p2;
  505.     int err = 0;
  506.  
  507.     if (argv && argv[1] && !strcmp(argv[1], "-?"))
  508.     return help(0, argv[0], cmd_help);
  509.  
  510.     if (!strcmp(*argv, "pwd")) {
  511.     set_cwd(); /* reset in case some dummy changed $cwd */
  512.         if ((p = do_set(set_options, "cwd")) && *p) {
  513.         print("%s\n", p);
  514.         return 0;
  515.     }
  516.     return -1;
  517.     }
  518.     if (!p || !*p) /* if no args, pwd = ".", cd = ~ */
  519.     p = (**argv == 'p')? "." : "~";
  520.     /* if a full path was not specified, loop through cdpath */
  521.     if (**argv != 'p' && *p != '/' && *p != '~' && *p != '+')
  522.     cdpath = do_set(set_options, "cdpath");
  523.     do  {
  524.     if (cdpath) {
  525.         char c;
  526.         if (p2 = any(cdpath, " \t:"))
  527.         c = *p2, *p2 = 0;
  528.         (void) sprintf(buf, "%s/%s", cdpath, p);
  529.         if (cdpath = p2) /* assign and compare to NULL */
  530.         *p2 = c;
  531.         while (cdpath && (isspace(*cdpath) || *cdpath == ':'))
  532.         cdpath++;
  533.     } else
  534.         (void) strcpy(buf, p);
  535.     x = 0;
  536.     path = getpath(buf, &x);
  537.     if (x != 1 || chdir(path) == -1)
  538.         err = errno;
  539.     else
  540.         err = 0;
  541.     } while (err && cdpath && *cdpath);
  542.     if (err)
  543.     error(p);
  544.     set_cwd();
  545.     if ((istool || iscurses || err) && (cwd = do_set(set_options, "cwd"))) {
  546.     if (err)
  547.         turnon(glob_flags, CONT_PRNT);
  548.     if (iscurses || istool || ison(glob_flags, WARNING))
  549.         print("Working dir: %s\n", cwd);
  550.     }
  551.     return 0;
  552. }
  553.  
  554. mush_quit(argc, argv)
  555. char **argv;
  556. {
  557.     u_long updated = ison(glob_flags, DO_UPDATE);
  558.  
  559.     if (argc > 1) {
  560.     if (!strcmp(argv[1], "-?"))
  561.         return help(0, "quit", cmd_help);
  562.     else {
  563.         print("%s: too many arguments\n", argv[0]);
  564.         return -1;
  565.     }
  566.     }
  567.     if ((!argc || (*argv && **argv == 'q')) && !copyback("Really Quit? "))
  568.     return -1;
  569. #ifdef CURSES
  570.     if (iscurses) {
  571.     /* we may already be on the bottom line; some cases won't be */
  572.     move(LINES-1, 0), refresh();
  573.     if (updated)
  574.         putchar('\n');
  575.     }
  576. #endif /* CURSES */
  577.     cleanup(0);
  578. #ifdef lint
  579.     return 0;
  580. #endif /* lint */
  581. }
  582.  
  583. delete(argc, argv, list)
  584. register int argc;
  585. register char **argv, list[];
  586. {
  587.     register int prnt_next, undel = argc && **argv == 'u';
  588.     int old_msg = current_msg;
  589.  
  590.     prnt_next = (argv && (!strcmp(*argv, "dt") || !strcmp(*argv, "dp")));
  591.  
  592.     if (argc && *++argv && !strcmp(*argv, "-?"))
  593.     return help(0, "delete", cmd_help);
  594.  
  595.     if (ison(glob_flags, READ_ONLY)) {
  596.     print("Folder is read-only\n");
  597.     return -1;
  598.     }
  599.  
  600.     if (get_msg_list(argv, list) == -1)
  601.     return -1;
  602.     for (argc = 0; argc < msg_cnt; argc++)
  603.     if (msg_bit(list, argc))
  604.         if (undel)
  605.         turnoff(msg[argc].m_flags, DELETE);
  606.         else
  607.         turnon(msg[argc].m_flags, DELETE);
  608.  
  609.     /* only if current_msg has been affected && not in curses mode */
  610.     if (prnt_next == 0 && !iscurses && msg_bit(list, current_msg))
  611.     prnt_next = !!do_set(set_options, "autoprint"); /* change to boolean */
  612.  
  613.     turnon(glob_flags, DO_UPDATE);
  614.  
  615.     /* goto next available message if current was just deleted.
  616.      * If there are no more messages, turnoff prnt_next.
  617.      */
  618.     if (!iscurses && !undel && msg_bit(list, current_msg) &&
  619.         (ison(msg[current_msg].m_flags, DELETE) ||
  620.         ison(msg[current_msg].m_flags, SAVED)))
  621.     (void) next_msg();
  622.     else
  623.     prnt_next = 0;
  624.  
  625.     if (prnt_next && !undel && !iscurses && isoff(glob_flags, DO_PIPE))
  626.     if (old_msg != current_msg && isoff(msg[current_msg].m_flags, DELETE))
  627.         display_msg(current_msg, (long)0);
  628.     else {
  629.         if (ison(msg[current_msg].m_flags, DELETE))
  630.         print("No more messages.\n");
  631.         current_msg = old_msg;
  632.     }
  633. #ifdef SUNTOOL
  634.     if (istool && isoff(glob_flags, IS_PIPE)) {
  635.     char *av[3], buf[8];
  636.     /* do_hdrs(0, ...) repositions the display, so pass an arg */
  637.     av[0] = "h";
  638.     av[1] = sprintf(buf, "%d", n_array[0] + 1);
  639.     av[2] = NULL;
  640.     (void) do_hdrs(2, av, NULL);
  641.     }
  642. #endif /* SUNTOOL */
  643.     return 0;
  644. }
  645.  
  646. /*
  647.  * historically from the "from" command in ucb-mail, this just prints
  648.  * the composed header of the messages set in list or in pipe.
  649.  */
  650. do_from(n, argv, list)
  651. char **argv, list[];
  652. {
  653.     int inc_cur_msg = 0;
  654.  
  655.     if (argv && *++argv && !strcmp(*argv, "-?"))
  656.     return help(0, "from", cmd_help);
  657.     if (argv && *argv && (!strcmp(*argv, "+") || !strcmp(*argv, "-")))
  658.     if (!strcmp(*argv, "+")) {
  659.         if (!*++argv && current_msg < msg_cnt-1)
  660.         current_msg++;
  661.         inc_cur_msg = 1;
  662.     } else if (!strcmp(*argv, "-")) {
  663.         if (!*++argv && current_msg > 0)
  664.         current_msg--;
  665.         inc_cur_msg = -1;
  666.     }
  667.     if ((n = get_msg_list(argv, list)) == -1)
  668.     return -1;
  669.     else if (argv && argv[n]) {
  670.     u_long save_flags = glob_flags;
  671.     char *newargv[6], buf[BUFSIZ];
  672.     (void) argv_to_string(buf, &argv[n]);
  673.     newargv[0] = "pick";
  674.     if (n == 0) {
  675.         newargv[++n] = "-r";
  676.         newargv[++n] = "*";
  677.         turnoff(glob_flags, IS_PIPE);
  678.     } else {
  679.         n = 0;
  680.         turnon(glob_flags, IS_PIPE);
  681.     }
  682.     newargv[++n] = "-f";
  683.     newargv[++n] = buf;
  684.     newargv[++n] = NULL;
  685.     Debug("calling: "), print_argv(newargv);
  686.     turnon(glob_flags, DO_PIPE);
  687.     (void) do_pick(n, newargv, list);
  688.     glob_flags = save_flags;
  689.     }
  690.     for (n = 0; n < msg_cnt; n++)
  691.     if (msg_bit(list, n)) {
  692.         wprint("%s\n", compose_hdr(n));
  693.         /* if -/+ given, set current message pointer to this message */
  694.         if (inc_cur_msg) {
  695.         current_msg = n;
  696.         /* if - was given, then set to first listed message.
  697.          * otherwise, + means last listed message -- let it go...
  698.          */
  699.         if (inc_cur_msg < 0)
  700.             inc_cur_msg = 0;
  701.         }
  702.     }
  703.     return 0;
  704. }
  705.  
  706. /*
  707.  * Do an ls from the system.
  708.  * Read from a popen and use wprint in case the tool does this command.
  709.  * The folders command uses this command.
  710.  */
  711. ls(x, argv)
  712. char **argv;
  713. {
  714.     register char  *p, *tmp;
  715.     char       buf[128];
  716.     register FILE  *pp;
  717.  
  718.     if (*++argv && !strcmp(*argv, "-?"))
  719.     return help(0, "ls", cmd_help);
  720.     p = buf + strlen(sprintf(buf, "%s -C", LS_COMMAND));
  721.     for ( ; *argv; ++argv) {
  722.     x = 0;
  723.     if (**argv != '-')
  724.         tmp = getpath(*argv, &x);
  725.     else
  726.         tmp = *argv;
  727.     if (x == -1) {
  728.         wprint("%s: %s\n", *argv, tmp);
  729.         return -1;
  730.     }
  731.     *p++ = ' ';
  732.     p += Strcpy(p, tmp);
  733.     }
  734.     if (!(pp = popen(buf, "r"))) {
  735.     error(buf);
  736.     return -1;
  737.     }
  738.     (void) do_pager(NULL, TRUE);
  739.     while (fgets(buf, 127, pp) && do_pager(buf, FALSE) != EOF)
  740.     ;
  741.     (void) pclose(pp);
  742.     (void) do_pager(NULL, FALSE);
  743.     return 0;
  744. }
  745.  
  746. /*ARGSUSED*/
  747. sh(un_used, argv)
  748. char **argv;
  749. {
  750.     register char *p;
  751.     char buf[128];
  752.  
  753.     if (*++argv && !strcmp(*argv, "-?"))
  754.     return help(0, "shell", cmd_help);
  755.     if (!(p = do_set(set_options, "shell")))
  756.     p = DEF_SHELL;
  757.     if (!*argv)
  758.     if (istool) {
  759.         print("You can't run an interactive shell from tool mode (yet).");
  760.         return -1;
  761.     } else
  762.         (void) strcpy(buf, p);
  763.     else
  764.     (void) argv_to_string(buf, argv);
  765.     if (!istool)
  766.     echo_on();
  767.     (void) system(buf);
  768.     if (!istool)
  769.     echo_off();
  770.     return 0;
  771. }
  772.  
  773. static
  774. sorter(cmd1, cmd2)
  775. register struct cmd *cmd1, *cmd2;
  776. {
  777.     return strcmp(cmd1->command, cmd2->command);
  778. }
  779.  
  780. question_mark(x, argv)
  781. char **argv;
  782. {
  783.     int n = 0, N = sizeof cmds / sizeof (struct cmd);
  784.     char *Cmds[sizeof cmds/sizeof(struct cmd)], *p, buf[30];
  785.  
  786.     if (!*++argv) {
  787.     if (N % 5)
  788.         N = N / 5 + 1;
  789.     else
  790.         N = N / 5;
  791.  
  792.     qsort((char *)cmds, sizeof(cmds)/sizeof(struct cmd)-1,
  793.                 sizeof(struct cmd), sorter);
  794.  
  795.     for (x = 0; x < N * 5; x++) {
  796.         if (!(x % 5))
  797.         if (!(p = Cmds[n++] = malloc(80))) {
  798.             error("malloc in question_mark()");
  799.             free_vec(Cmds);
  800.             return -1;
  801.         }
  802.         if (x%5*N+n < sizeof cmds / sizeof (struct cmd))
  803.         p += strlen(sprintf(p, "%-14.14s ", cmds[x%5*N+n-1].command));
  804.     }
  805.     Cmds[n++] = savestr("Type: `command -?' for help with most commands.");
  806.     Cmds[n] = NULL;
  807.     (void) help(0, (char *) Cmds, NULL);
  808.     free_vec(Cmds);
  809.     } else if (!strcmp(*argv, "-?"))
  810.     return help(0, "?", cmd_help);
  811.     else {
  812.     for (x = 0; cmds[x].command; x++)
  813.         if (!strcmp(*argv, cmds[x].command))
  814.         return cmd_line(sprintf(buf, "\\%s -?", *argv), msg_list);
  815.     print("Unknown command: %s\n", *argv);
  816.     }
  817.     return 0 - in_pipe();
  818. }
  819.  
  820. #ifdef SIGSTOP
  821. stop(argc, argv)
  822. char **argv;
  823. {
  824.     if (istool)
  825.     print("Not a tool-based option.");
  826.     if (argc && *++argv && !strcmp(*argv, "-?"))
  827.     return help(0, "stop", cmd_help);
  828.     if (kill(getpid(), SIGTSTP) == -1)
  829.     error("couldn't stop myself");
  830.     return 0;
  831. }
  832. #endif /* SIGSTOP */
  833.  
  834. extern char **environ;
  835. static int spaces = 0;
  836.  
  837. Setenv(i, argv)
  838. char **argv;
  839. {
  840.     char *newstr;
  841.  
  842.     if (i > 3 || !strcmp(argv[1], "-?"))
  843.     return help(0, "setenv", cmd_help);
  844.     else if (i < 2)
  845.     return Printenv(i, argv);
  846.  
  847.     if (i == 3) {
  848.     if (newstr = malloc((unsigned) (strlen(argv[1]) + strlen(argv[2]) + 2)))
  849.         (void) sprintf(newstr, "%s=%s", argv[1], argv[2]);
  850.     } else {
  851.     if (newstr = malloc((unsigned)(strlen(argv[1]) + 2)))
  852.         (void) sprintf(newstr, "%s=", argv[1]);
  853.     }
  854.     if (!newstr) {
  855.     error("setenv: out of memory");
  856.     return -1;
  857.     }
  858.  
  859.     (void) Unsetenv(2, argv);
  860.  
  861.     for (i = 0; environ[i]; i++);
  862.     if (!spaces) {
  863.     char **new_environ =
  864.             (char **)malloc((unsigned) ((i+2) * sizeof(char *)));
  865.     /* add 1 for the new item, and 1 for null-termination */
  866.     if (!new_environ) {
  867.         xfree(newstr);
  868.         return -1;
  869.     }
  870.     spaces = 1;
  871.     for (i = 0; new_environ[i] = environ[i]; i++);
  872.     xfree((char *) environ);
  873.     environ = new_environ;
  874.     }
  875.     environ[i] = newstr;
  876.     environ[i+1] = NULL;
  877.     spaces--;
  878.     return 0;
  879. }
  880.  
  881. Unsetenv(n, argv)
  882. char **argv;
  883. {
  884.     char **envp, **last;
  885.  
  886.     if (n != 2 || !strcmp(argv[1], "-?"))
  887.     return help(0, "unsetenv", cmd_help);
  888.  
  889.     n = strlen(argv[1]);
  890.     for (last = environ; *last; last++);
  891.     last--;
  892.  
  893.     for (envp = environ; envp <= last; envp++) {
  894.     if (strncmp(argv[1], *envp, n) == 0 && (*envp)[n] == '=') {
  895.         xfree(*envp);
  896.         *envp = *last;
  897.         *last-- = NULL;
  898.         spaces++;
  899.     }
  900.     }
  901.     return 0;
  902. }
  903.  
  904. Printenv(argc, argv)
  905. char **argv;
  906. {
  907.     char **e;
  908.  
  909.     if (argv && argv[1] && !strcmp(argv[1], "-?"))
  910.     return help(0, "printenv", cmd_help);
  911.     for (e = environ; *e; e++)
  912.     if (argc < 2 || !strncmp(*e, argv[1], strlen(argv[1])))
  913.         wprint("%s\n", *e);
  914.     return 0;
  915. }
  916.  
  917. /*
  918.  * internal stty call to allow the user to change his tty character
  919.  * settings.  sorry, no way to change cbreak/echo modes.  Save echo_flg
  920.  * so that execute() won't reset it.
  921.  */
  922. /*ARGSUSED*/
  923. my_stty(un_used, argv)
  924. char **argv;
  925. {
  926.     u_long save_echo = ison(glob_flags, ECHO_FLAG);
  927.  
  928.     if (istool)
  929.     return 0;
  930.  
  931.     if (argv && argv[1] && !strcmp(argv[1], "-?"))
  932.     return help(0, "stty", cmd_help);
  933.     turnon(glob_flags, ECHO_FLAG);
  934.     execute(argv);
  935.     if (save_echo)
  936.     turnon(glob_flags, ECHO_FLAG);
  937.     else
  938.     turnoff(glob_flags, ECHO_FLAG);
  939.  
  940.     savetty();
  941. #ifdef TIOCGLTC
  942.     if (ioctl(0, TIOCGLTC, <chars))
  943.     error("TIOCGLTC");
  944. #endif /* TIOCGLTC */
  945.     echo_off();
  946.     return 0;
  947. }
  948.  
  949. /*
  950.  * Edit a message...
  951.  */
  952. edit_msg(i, argv, list)
  953. char *argv[], list[];
  954. {
  955.     int edited = 0;
  956.     char buf[MAXPATHLEN], *b, *dir, **edit_cmd, *editor, *mktemp();
  957.     u_long flags = 0L;
  958.     char *cmd = *argv;
  959.     FILE *fp;
  960.  
  961.     if (istool)
  962.     return 0;
  963.  
  964.     if (*++argv && !strcmp(*argv, "-?"))
  965.     return help(0, "edit_msg", cmd_help);
  966.  
  967.     if (ison(glob_flags, READ_ONLY)) {
  968.     print("\"%s\" is read-only.\n", mailfile);
  969.     return -1;
  970.     }
  971.  
  972.     if (get_msg_list(argv, list) == -1)
  973.     return -1;
  974.  
  975.     if (!(editor = do_set(set_options,
  976.     (*cmd == 'v')? "visual" : "editor")) || !*editor)
  977.     editor = DEF_EDITOR;
  978.  
  979.     for (i = 0; i < msg_cnt; i++) {
  980.     if (!msg_bit(list, i))
  981.         continue;
  982.  
  983.     if (edited) {
  984.         print("Edit message %d [y/n/q]? ", i+1);
  985.         if (Getstr(buf, sizeof (buf), 0) < 0 || lower(buf[0]) == 'q')
  986.         return 0;
  987.         if (buf[0] && buf[0] != 'y')
  988.         continue;
  989.     }
  990.  
  991.     b = buf + Strcpy(buf, editor);
  992.     *b++ = ' ';
  993.  
  994.     /* getdir() uses the home directory if no tmpdir */
  995.     if (!(dir = getdir(do_set(set_options, "tmpdir"))))
  996. alted:
  997.         dir = ALTERNATE_HOME;
  998.     (void) mktemp(sprintf(b, "%s/.msgXXXXXXX", dir));
  999.     if (!(fp = mask_fopen(b, "w+"))) {
  1000.         if (strcmp(dir, ALTERNATE_HOME))
  1001.         goto alted;
  1002.         error("can't create %s", b);
  1003.         return -1;
  1004.     }
  1005.     wprint("editing message %d ...", i+1);
  1006.     /* copy message into file making sure all headers exist. */
  1007.     turnon(flags, UPDATE_STATUS);
  1008. #ifdef MMDF
  1009.     turnon(flags, NO_SEPARATOR);
  1010. #endif /* MMDF */
  1011.     wprint("(%d lines)\n", copy_msg(i, fp, flags, NULL));
  1012.  
  1013.     if (edit_cmd = mk_argv(buf, &edited, FALSE)) {
  1014.         print("Starting \"%s\"...\n", buf);
  1015.         (void) fclose(fp);
  1016.         turnon(glob_flags, IS_GETTING);
  1017.         execute(edit_cmd);
  1018.         turnoff(glob_flags, IS_GETTING);
  1019.         free_vec(edit_cmd);
  1020.         if (load_folder(b, FALSE, (char *)i) > 0) {
  1021.         (void) unlink(b);
  1022.         edited = 1;
  1023.         }
  1024.         set_isread(i); /* if you edit it, you read it, right? */
  1025.     }
  1026.     }
  1027.     return 0;
  1028. }
  1029.  
  1030. /*
  1031.  * Pipe a message list to a unix command.  This function is hacked together
  1032.  * from bits of readmsg, above, and other bits of display_msg (misc.c).
  1033.  */
  1034. pipe_msg(x, argv, list)
  1035. register char **argv, list[];
  1036. {
  1037.     char *p = x ? *argv : NULL;
  1038.     char buf[256], *pattern = NULL;
  1039.     u_long flg = 0L;
  1040.     extern FILE *ed_fp;
  1041.     int show_deleted = !!do_set(set_options, "show_deleted");
  1042.  
  1043.     /* Increment argv only if argv[0] is the mush command "pipe" */
  1044.     if (x && p && (!strcmp(p, "pipe") || !strcmp(p, "Pipe"))) {
  1045.     if (p && *p == 'P')
  1046.         turnon(flg, NO_HEADER);
  1047.     while (x && *++argv && **argv == '-')
  1048.         if (!strcmp(*argv, "-?"))
  1049.         return help(0, "pipe_msg", cmd_help);
  1050.         else if (!strcmp(*argv, "-p") && !(pattern = *++argv)) {
  1051.         print("Specify a pattern with -p\n");
  1052.         return -1;
  1053.         }
  1054.     }
  1055.     if (!msg_cnt) {
  1056.     print("No messages.\n");
  1057.     return -1;
  1058.     }
  1059.  
  1060.     if (x && (x = get_msg_list(argv, list)) == -1)
  1061.     return -1;
  1062.     argv += x;
  1063.     if (!*argv) {
  1064.     turnon(flg, NO_HEADER);
  1065.     /* The constant strings must be constants because user's
  1066.      * $SHELL might not be appropriate since "sh" scripts are
  1067.      * usually sent.  User can always (easily) override.
  1068.      */
  1069.     (void) strcpy(buf, "/bin/sh");
  1070.     if (!pattern)
  1071.         pattern = "#!";
  1072.     } else
  1073.     (void) argv_to_string(buf, argv);
  1074.     if (!buf[0]) {
  1075.     print("Must specify a legitimate command or shell.\n");
  1076.     return -1;
  1077.     }
  1078.     current_msg = 0;
  1079.     if (!chk_option("alwaysignore", "pipe"))
  1080.     turnon(flg, NO_IGNORE);
  1081. #ifdef MMDF
  1082.     turnon(flg, NO_SEPARATOR);
  1083. #endif /* MMDF */
  1084.     (void) do_pager(buf, -1); /* start pager -- see do_pager() about "-1" */
  1085.     turnoff(glob_flags, WAS_INTR); /* if command interrupts, mush gets it */
  1086.  
  1087.     for (x = 0; x < msg_cnt && isoff(glob_flags, WAS_INTR); x++)
  1088.     if (msg_bit(list, x)) {
  1089.         current_msg = x;
  1090.         if (!show_deleted && ison(msg[x].m_flags, DELETE)) {
  1091.         print("Message %d deleted; ", x+1);
  1092.         if (iscurses)
  1093.             print_more("skipping it.");
  1094.         else
  1095.             print("skipping it.\n");
  1096.         continue;
  1097.         }
  1098.         set_isread(x);
  1099.         if (copy_msg(x, NULL_FILE, flg, pattern) == 0)
  1100.         print("No lines sent to %s!\n", buf);
  1101.     }
  1102.     (void) do_pager(NULL, FALSE); /* end pager */
  1103.     return 0;
  1104. }
  1105.  
  1106. /* echo the arguments.  return 0 or -1 if -h given and there are no msgs. */
  1107. do_echo(n, argv)
  1108. register char **argv;
  1109. {
  1110.     char buf[BUFSIZ], c;
  1111.     int no_return = 0, comp_hdr = 0, as_prompt = 0;
  1112.  
  1113.     while (n >= 0 && argv && *++argv && **argv == '-') {
  1114.     n = 1;
  1115.     while (n > 0 && (c = argv[0][n++]))
  1116.         switch(c) {
  1117.         case 'n': no_return++;
  1118.         when 'h': comp_hdr++;
  1119.         when 'p': as_prompt++;
  1120.         when '?': return help(0, "echo", cmd_help);
  1121.         otherwise: n = -1; break; /* Just echo whatever it was */
  1122.         }
  1123.     }
  1124.     if (comp_hdr && as_prompt) {
  1125.     print("-h and -p cannot be used together.\n");
  1126.     return -1;
  1127.     }
  1128.  
  1129.     (void) argv_to_string(buf, argv);
  1130.     if (comp_hdr) {
  1131.     if (!msg_cnt) {
  1132.         print("No messages.\n");
  1133.         return -1;
  1134.     }
  1135.     /* there may be a %-sign, so use %s to print */
  1136.     print("%s", format_hdr(current_msg, buf, FALSE)+9);
  1137.     } else if (as_prompt) {
  1138.     print("%s", format_prompt(current_msg, buf)); /* may be a %-sign */
  1139.     } else
  1140.     print("%s", buf); /* there may be a %-sign in "buf" */
  1141.     if (!no_return)
  1142.     print_more("\n");
  1143.     return 0;
  1144. }
  1145.  
  1146. eval_cmd (argc, argv, list)
  1147. char *argv[], list[];
  1148. {
  1149.     int status = -1;
  1150.     u_long save_is_pipe;
  1151.     char **newav, buf[BUFSIZ];
  1152.     int comp_hdr = 0, as_prompt = 0, as_macro = 0;
  1153.  
  1154.     while (argv && *++argv && **argv == '-') {
  1155.     int c, n = 1;
  1156.     while (c = argv[0][n++])
  1157.         switch(c) {
  1158.         case 'h': comp_hdr++;
  1159.         when 'p': as_prompt++;
  1160.         when 'm': as_macro++;
  1161.         otherwise: return help(0, "eval", cmd_help);
  1162.         }
  1163.     }
  1164.     if (comp_hdr && as_prompt) {
  1165.     print("-h and -p cannot be used together.\n");
  1166.     return -1;
  1167.     }
  1168.  
  1169.     (void) argv_to_string(buf, argv);
  1170.     if (as_macro) {
  1171.     m_xlate(buf);
  1172.     mac_queue(buf);
  1173.     return 0;
  1174.     }
  1175.     newav = make_command(buf, TRPL_NULL, &argc);
  1176.     if (comp_hdr) {
  1177.     if (!msg_cnt) {
  1178.         print("No messages.\n");
  1179.         return -1;
  1180.     }
  1181.     /* This is inefficient, but the only way to preserve
  1182.      * imbedded quotes, tabs, etc. in format expansions.
  1183.      */
  1184.     for (argv = newav; argv && *argv; argv++) {
  1185.         /* Don't mess with one-character strings */
  1186.         if (argv[0][1]) {
  1187.         char *format = *argv;
  1188.         *argv = savestr(format_hdr(current_msg, format, FALSE)+9);
  1189.         Debug("expanding (%s) to (%s)\n", format, *argv);
  1190.         xfree(format);
  1191.         }
  1192.     }
  1193.     } else if (as_prompt) {
  1194.     for (argv = newav; argv && *argv; argv++) {
  1195.         /* Don't mess with one-character strings */
  1196.         if (argv[0][1]) {
  1197.         char *tmp = *argv;
  1198.         *argv = savestr(format_prompt(current_msg, tmp));
  1199.         Debug("expanding (%s) to (%s)\n", tmp, *argv);
  1200.         xfree(tmp);
  1201.         }
  1202.     }
  1203.     }
  1204.     /* Can't use cmd_line() because we want DO_PIPE and IS_PIPE
  1205.      * to remain on -- cmd_line() turns both of them off
  1206.      */
  1207.     if (newav) {
  1208.     save_is_pipe = ison(glob_flags, IS_PIPE);
  1209.     status = do_command(argc, newav, list);
  1210.     if (save_is_pipe)
  1211.         turnon(glob_flags, IS_PIPE);
  1212.     }
  1213.     return status;
  1214. }
  1215.  
  1216. await(argc, argv, list)
  1217. char *argv[], list[];
  1218. {
  1219.     int done = 0, snooze = 30, last_cnt = msg_cnt;
  1220.  
  1221.     if (argc && *++argv) {
  1222.     if (!strcmp(*argv, "-?"))
  1223.         return help(0, "await", cmd_help);
  1224.     else if (!strcmp(*argv, "-T")) {
  1225.         if (*++argv && isdigit(**argv) && **argv > '0') {
  1226.         snooze = atoi(*argv);
  1227.         } else {
  1228.         print("await: integer greater than 0 required for -T\n");
  1229.         return -1;
  1230.         }
  1231.     }
  1232.     }
  1233.     Debug("snoozing %d\n", snooze);
  1234.  
  1235.     do {
  1236.     if (!(done = check_new_mail()))
  1237.         sleep((unsigned) snooze);
  1238.     } while (!done);
  1239.     /* Known to be safe to pass NULL to chk_two_lists() */
  1240.     if (!chk_option("quiet", "await"))
  1241.     bell();
  1242.  
  1243.     while (last_cnt < msg_cnt) {
  1244.     set_msg_bit(list, last_cnt);
  1245.     ++last_cnt;
  1246.     }
  1247.  
  1248.     return 0;
  1249. }
  1250.