home *** CD-ROM | disk | FTP | other *** search
/ ftp.freefriends.org / ftp.freefriends.org.tar / ftp.freefriends.org / arnold / Source / mush.rstevens.tar.gz / mush.tar / command2.c < prev    next >
C/C++ Source or Header  |  1992-10-30  |  14KB  |  596 lines

  1. /* @(#)command2.c    (c) copyright 1991 (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. /* This is the bottom half of commands.c */
  11.  
  12. /*
  13.  * Do an ls from the system.
  14.  * Read from a popen and use wprint in case the tool does this command.
  15.  * The folders command uses this command.
  16.  */
  17. ls(x, argv)
  18. int x;
  19. char **argv;
  20. {
  21.     register char  *p, *tmp;
  22.     char       buf[128];
  23.     register FILE  *pp;
  24.  
  25.     if (*++argv && !strcmp(*argv, "-?"))
  26.     return help(0, "ls", cmd_help);
  27.     p = buf + strlen(sprintf(buf, "%s -C", LS_COMMAND));
  28.     for ( ; *argv; ++argv) {
  29.     x = 0;
  30.     if (**argv != '-')
  31.         tmp = getpath(*argv, &x);
  32.     else
  33.         tmp = *argv;
  34.     if (x == -1) {
  35.         wprint("%s: %s\n", *argv, tmp);
  36.         return -1;
  37.     }
  38.     *p++ = ' ';
  39.     p += Strcpy(p, tmp);
  40.     }
  41.     if (!(pp = popen(buf, "r"))) {
  42.     error(buf);
  43.     return -1;
  44.     }
  45.     (void) do_pager(NULL, TRUE);
  46.     while (fgets(buf, 127, pp) && do_pager(buf, FALSE) != EOF)
  47.     ;
  48.     (void) pclose(pp);
  49.     (void) do_pager(NULL, FALSE);
  50.     return 0;
  51. }
  52.  
  53. /*ARGSUSED*/
  54. sh(un_used, argv)
  55. int un_used;
  56. char **argv;
  57. {
  58.     register char *p;
  59.     char buf[BUFSIZ];
  60.  
  61.     if (*++argv && !strcmp(*argv, "-?"))
  62.     return help(0, "shell", cmd_help);
  63.     if (!(p = do_set(set_options, "shell")))
  64.     p = DEF_SHELL;
  65.     if (!*argv)
  66.     if (istool) {
  67.         print("You can't run an interactive shell from tool mode (yet).");
  68.         return -1;
  69.     } else
  70.         (void) strcpy(buf, p);
  71.     else
  72.     (void) argv_to_string(buf, argv);
  73.     if (!istool)
  74.     echo_on();
  75.     (void) system(buf);
  76.     if (!istool)
  77.     echo_off();
  78.     return 0;
  79. }
  80.  
  81. #ifdef SIGSTOP
  82. stop(argc, argv)
  83. int argc;
  84. char **argv;
  85. {
  86.     if (istool)
  87.     print("Not a tool-based option.");
  88.     if (argc && *++argv && !strcmp(*argv, "-?"))
  89.     return help(0, "stop", cmd_help);
  90.     if (kill(getpid(), SIGTSTP) == -1)
  91.     error("couldn't stop myself");
  92.     return 0;
  93. }
  94. #endif /* SIGSTOP */
  95.  
  96. extern char **environ;
  97. static int spaces = 0;
  98.  
  99. Setenv(i, argv)
  100. int i;
  101. char **argv;
  102. {
  103.     char *newstr;
  104.  
  105.     if (i < 2)
  106.     return Printenv(i, argv);
  107.     else if (i > 3 || !strcmp(argv[1], "-?"))
  108.     return help(0, "setenv", cmd_help);
  109.  
  110.     if (i == 3) {
  111.     if (newstr = malloc((unsigned) (strlen(argv[1]) + strlen(argv[2]) + 2)))
  112.         (void) sprintf(newstr, "%s=%s", argv[1], argv[2]);
  113.     } else {
  114.     if (newstr = malloc((unsigned)(strlen(argv[1]) + 2)))
  115.         (void) sprintf(newstr, "%s=", argv[1]);
  116.     }
  117.     if (!newstr) {
  118.     error("setenv: out of memory");
  119.     return -1;
  120.     }
  121.  
  122.     (void) Unsetenv(2, argv);
  123.  
  124.     for (i = 0; environ[i]; i++);
  125.     if (!spaces) {
  126.     char **new_environ =
  127.             (char **)malloc((unsigned) ((i+2) * sizeof(char *)));
  128.     /* add 1 for the new item, and 1 for null-termination */
  129.     if (!new_environ) {
  130.         xfree(newstr);
  131.         return -1;
  132.     }
  133.     spaces = 1;
  134.     for (i = 0; new_environ[i] = environ[i]; i++);
  135.     xfree((char *) environ);
  136.     environ = new_environ;
  137.     }
  138.     environ[i] = newstr;
  139.     environ[i+1] = NULL;
  140.     spaces--;
  141.     return 0;
  142. }
  143.  
  144. Unsetenv(n, argv)
  145. int n;
  146. char **argv;
  147. {
  148.     static int new;
  149.     char **envp, **last;
  150.  
  151.     if (n != 2 || !strcmp(argv[1], "-?"))
  152.     return help(0, "unsetenv", cmd_help);
  153.  
  154.     n = strlen(argv[1]);
  155.     for (last = environ; *last; last++);
  156.  
  157.     /* Allocate a copy of the environment so we can free() strings we unset */
  158.     if (new == 0) {
  159.     if (!(envp = (char **)calloc((last - environ) + 1, sizeof(char *)))) {
  160.         error("Unsetenv: out of memory");
  161.         return -1;
  162.     }
  163.     while (environ[new]) {
  164.         envp[new] = savestr(environ[new]);
  165.         if (!envp[new++]) {
  166.         error("Unsetenv: out of memory");
  167.         free_vec(envp);
  168.         new = 0;
  169.         return -1;
  170.         }
  171.     }
  172.     environ = envp;
  173.     last = &envp[new];
  174.     new = 1;
  175.     }
  176.  
  177.     if (last == environ) /* Empty environment? */
  178.     return 0;
  179.  
  180.     last--;
  181.  
  182.     for (envp = environ; envp <= last; envp++) {
  183.     if (strncmp(argv[1], *envp, n) == 0 && (*envp)[n] == '=') {
  184.         xfree(*envp);
  185.         *envp = *last;
  186.         *last-- = NULL;
  187.         spaces++;
  188.     }
  189.     }
  190.     return 0;
  191. }
  192.  
  193. Printenv(argc, argv)
  194. int argc;
  195. char **argv;
  196. {
  197.     char **e;
  198.  
  199.     if (argv && argv[1] && !strcmp(argv[1], "-?"))
  200.     return help(0, "printenv", cmd_help);
  201.     for (e = environ; *e; e++)
  202.     if (argc < 2 || !strncmp(*e, argv[1], strlen(argv[1])))
  203.         wprint("%s\n", *e);
  204.     return 0;
  205. }
  206.  
  207. /*
  208.  * internal stty call to allow the user to change his tty character
  209.  * settings.  sorry, no way to change cbreak/echo modes.  Save echo_flg
  210.  * so that execute() won't reset it.
  211.  */
  212. /*ARGSUSED*/
  213. my_stty(un_used, argv)
  214. int un_used;
  215. char **argv;
  216. {
  217.     u_long save_echo = ison(glob_flags, ECHO_FLAG);
  218.  
  219.     if (istool)
  220.     return 0;
  221.  
  222.     if (argv && argv[1] && !strcmp(argv[1], "-?"))
  223.     return help(0, "stty", cmd_help);
  224.     echo_on();
  225.     turnon(glob_flags, ECHO_FLAG);
  226.     execute(argv);
  227.     if (save_echo)
  228.     turnon(glob_flags, ECHO_FLAG);
  229.     else
  230.     turnoff(glob_flags, ECHO_FLAG);
  231.  
  232.     savetty();
  233. #ifdef TIOCGLTC
  234.     if (ioctl(0, TIOCGLTC, <chars))
  235.     error("TIOCGLTC");
  236. #endif /* TIOCGLTC */
  237.     echo_off();
  238.     return 0;
  239. }
  240.  
  241. /*
  242.  * Edit a message...
  243.  */
  244. edit_msg(i, argv, list)
  245. int i;
  246. char *argv[], list[];
  247. {
  248.     int edited = 0;
  249.     char buf[MAXPATHLEN], *b, *dir, **edit_cmd, *editor, *mktemp();
  250.     u_long flags = 0L;
  251.     char *cmd = *argv;
  252.     FILE *fp;
  253.  
  254.     if (istool)
  255.     return 0;
  256.  
  257.     if (*++argv && !strcmp(*argv, "-?"))
  258.     return help(0, "edit_msg", cmd_help);
  259.  
  260.     if (ison(glob_flags, READ_ONLY)) {
  261.     print("\"%s\" is read-only.\n", mailfile);
  262.     return -1;
  263.     }
  264.  
  265.     if (get_msg_list(argv, list) == -1)
  266.     return -1;
  267.  
  268.     if (!(editor = do_set(set_options,
  269.     (*cmd == 'v')? "visual" : "editor")) || !*editor)
  270.     editor = DEF_EDITOR;
  271.  
  272.     for (i = 0; i < msg_cnt; i++) {
  273.     if (!msg_bit(list, i))
  274.         continue;
  275.  
  276.     if (edited) {
  277.         print("Edit message %d [y/n/q]? ", i+1);
  278.         if (Getstr(buf, sizeof (buf), 0) < 0 || lower(buf[0]) == 'q')
  279.         return 0;
  280.         if (buf[0] && buf[0] != 'y')
  281.         continue;
  282.     }
  283.  
  284.     b = buf + Strcpy(buf, editor);
  285.     *b++ = ' ';
  286.  
  287.     /* getdir() uses the home directory if no tmpdir */
  288.     if (!(dir = getdir(do_set(set_options, "tmpdir"))))
  289. alted:
  290.         dir = ALTERNATE_HOME;
  291.     (void) mktemp(sprintf(b, "%s/.msgXXXXXXX", dir));
  292.     if (!(fp = mask_fopen(b, "w+"))) {
  293.         if (strcmp(dir, ALTERNATE_HOME))
  294.         goto alted;
  295.         error("can't create %s", b);
  296.         return -1;
  297.     }
  298.     wprint("editing message %d ...", i+1);
  299.     /* copy message into file making sure all headers exist. */
  300.     turnon(flags, UPDATE_STATUS);
  301. #ifdef MMDF
  302.     turnon(flags, NO_SEPARATOR);
  303. #endif /* MMDF */
  304.     wprint("(%d lines)\n", copy_msg(i, fp, flags, NULL));
  305.  
  306.     if (edit_cmd = mk_argv(buf, &edited, FALSE)) {
  307.         print("Starting \"%s\"...\n", buf);
  308.         (void) fclose(fp);
  309.         turnon(glob_flags, IS_GETTING);
  310.         execute(edit_cmd);
  311.         turnoff(glob_flags, IS_GETTING);
  312.         free_vec(edit_cmd);
  313.         if (load_folder(b, FALSE, (char *)i) > 0) {
  314.         (void) unlink(b);
  315.         edited = 1;
  316.         }
  317.         set_isread(i); /* if you edit it, you read it, right? */
  318.     }
  319.     }
  320.     return 0;
  321. }
  322.  
  323. /*
  324.  * Pipe a message list to a unix command.  This function is hacked together
  325.  * from bits of readmsg, above, and other bits of display_msg (misc.c).
  326.  */
  327. pipe_msg(x, argv, list)
  328. int x;
  329. char **argv, list[];
  330. {
  331.     char *p = x ? *argv : NULL;
  332.     char buf[256], *pattern = NULL;
  333.     u_long flg = 0L;
  334.     extern FILE *ed_fp;
  335.     int show_deleted = !!do_set(set_options, "show_deleted");
  336.  
  337.     /* Increment argv only if argv[0] is the mush command "pipe" */
  338.     if (x && p && (!strcmp(p, "pipe") || !strcmp(p, "Pipe"))) {
  339.     if (p && *p == 'P')
  340.         turnon(flg, NO_HEADER);
  341.     while (x && *++argv && **argv == '-')
  342.         if (!strcmp(*argv, "-?"))
  343.         return help(0, "pipe_msg", cmd_help);
  344.         else if (!strcmp(*argv, "-p") && !(pattern = *++argv)) {
  345.         print("Specify a pattern with -p\n");
  346.         return -1;
  347.         }
  348.     }
  349.     if (!msg_cnt) {
  350.     print("No messages.\n");
  351.     return -1;
  352.     }
  353.  
  354.     if (x && (x = get_msg_list(argv, list)) == -1)
  355.     return -1;
  356.     argv += x;
  357.     if (!*argv) {
  358.     turnon(flg, NO_HEADER);
  359.     /* The constant strings must be constants because user's
  360.      * $SHELL might not be appropriate since "sh" scripts are
  361.      * usually sent.  User can always (easily) override.
  362.      */
  363.     (void) strcpy(buf, "/bin/sh");
  364.     if (!pattern)
  365.         pattern = "#!";
  366.     } else
  367.     (void) argv_to_string(buf, argv);
  368.     if (!buf[0]) {
  369.     print("Must specify a legitimate command or shell.\n");
  370.     return -1;
  371.     }
  372.     current_msg = 0;
  373.     if (!chk_option("alwaysignore", "pipe"))
  374.     turnon(flg, NO_IGNORE);
  375. #ifdef MMDF
  376.     turnon(flg, NO_SEPARATOR);
  377. #endif /* MMDF */
  378.     (void) do_pager(buf, -1); /* start pager -- see do_pager() about "-1" */
  379.     turnoff(glob_flags, WAS_INTR); /* if command interrupts, mush gets it */
  380.  
  381.     for (x = 0; x < msg_cnt && isoff(glob_flags, WAS_INTR); x++)
  382.     if (msg_bit(list, x)) {
  383.         current_msg = x;
  384.         if (!show_deleted && ison(msg[x].m_flags, DELETE)) {
  385.         print("Message %d deleted; ", x+1);
  386.         if (iscurses)
  387.             print_more("skipping it.");
  388.         else
  389.             print("skipping it.\n");
  390.         continue;
  391.         }
  392.         set_isread(x);
  393.         if (copy_msg(x, NULL_FILE, flg, pattern) == 0)
  394.         print("No lines sent to %s!\n", buf);
  395.     }
  396.     (void) do_pager(NULL, FALSE); /* end pager */
  397.     return 0;
  398. }
  399.  
  400. /* echo the arguments.  return 0 or -1 if -h given and there are no msgs. */
  401. do_echo(n, argv)
  402. int n;
  403. char **argv;
  404. {
  405.     char buf[BUFSIZ], c;
  406.     int no_return = 0, comp_hdr = 0, as_prompt = 0;
  407.  
  408.     while (n >= 0 && argv && *++argv && **argv == '-') {
  409.     n = 1;
  410.     while (n > 0 && (c = argv[0][n++]))
  411.         switch(c) {
  412.         case 'n': no_return++;
  413.         when 'h': comp_hdr++;
  414.         when 'p': as_prompt++;
  415.         when '?': return help(0, "echo", cmd_help);
  416.         otherwise: n = -1; break; /* Just echo whatever it was */
  417.         }
  418.     }
  419.     if (comp_hdr && as_prompt) {
  420.     print("-h and -p cannot be used together.\n");
  421.     return -1;
  422.     }
  423.  
  424.     (void) argv_to_string(buf, argv);
  425.     if (comp_hdr) {
  426.     if (!msg_cnt) {
  427.         print("No messages.\n");
  428.         return -1;
  429.     }
  430.     /* there may be a %-sign, so use %s to print */
  431.     print("%s", format_hdr(current_msg, buf, FALSE)+9);
  432.     } else if (as_prompt) {
  433.     print("%s", format_prompt(current_msg, buf)); /* may be a %-sign */
  434.     } else
  435.     print("%s", buf); /* there may be a %-sign in "buf" */
  436.     if (!no_return)
  437.     print_more("\n");
  438.     return 0;
  439. }
  440.  
  441. eval_cmd (argc, argv, list)
  442. int argc;
  443. char *argv[], list[];
  444. {
  445.     int status = -1;
  446.     u_long save_is_pipe;
  447.     char **newav, buf[BUFSIZ];
  448.     int comp_hdr = 0, as_prompt = 0, as_macro = 0;
  449.  
  450.     while (argv && *++argv && **argv == '-') {
  451.     int c, n = 1;
  452.     while (c = argv[0][n++])
  453.         switch(c) {
  454.         case 'h': comp_hdr++;
  455.         when 'p': as_prompt++;
  456.         when 'm': as_macro++;
  457.         otherwise: return help(0, "eval", cmd_help);
  458.         }
  459.     }
  460.     if (comp_hdr && as_prompt) {
  461.     print("-h and -p cannot be used together.\n");
  462.     return -1;
  463.     }
  464.  
  465.     (void) argv_to_string(buf, argv);
  466.     if (as_macro) {
  467.     m_xlate(buf);
  468.     mac_queue(buf);
  469.     return 0;
  470.     }
  471.     newav = make_command(buf, TRPL_NULL, &argc);
  472.     if (comp_hdr) {
  473.     if (!msg_cnt) {
  474.         print("No messages.\n");
  475.         return -1;
  476.     }
  477.     /* This is inefficient, but the only way to preserve
  478.      * imbedded quotes, tabs, etc. in format expansions.
  479.      */
  480.     for (argv = newav; argv && *argv; argv++) {
  481.         /* Don't mess with one-character strings */
  482.         if (argv[0][1]) {
  483.         char *format = *argv;
  484.         *argv = savestr(format_hdr(current_msg, format, FALSE)+9);
  485.         Debug("expanding (%s) to (%s)\n", format, *argv);
  486.         xfree(format);
  487.         }
  488.     }
  489.     } else if (as_prompt) {
  490.     for (argv = newav; argv && *argv; argv++) {
  491.         /* Don't mess with one-character strings */
  492.         if (argv[0][1]) {
  493.         char *tmp = *argv;
  494.         *argv = savestr(format_prompt(current_msg, tmp));
  495.         Debug("expanding (%s) to (%s)\n", tmp, *argv);
  496.         xfree(tmp);
  497.         }
  498.     }
  499.     }
  500.     /* Can't use cmd_line() because we want DO_PIPE and IS_PIPE
  501.      * to remain on -- cmd_line() turns both of them off
  502.      */
  503.     if (newav) {
  504.     save_is_pipe = ison(glob_flags, IS_PIPE);
  505.     status = do_command(argc, newav, list);
  506.     if (save_is_pipe)
  507.         turnon(glob_flags, IS_PIPE);
  508.     }
  509.     return status;
  510. }
  511.  
  512. await(argc, argv, list)
  513. int argc;
  514. char *argv[], list[];
  515. {
  516.     int done = 0, snooze = 30, last_cnt = msg_cnt;
  517.  
  518.     if (argc && *++argv) {
  519.     if (!strcmp(*argv, "-?"))
  520.         return help(0, "await", cmd_help);
  521.     else if (!strcmp(*argv, "-T")) {
  522.         if (*++argv && isdigit(**argv) && **argv > '0') {
  523.         snooze = atoi(*argv);
  524.         } else {
  525.         print("await: integer greater than 0 required for -T\n");
  526.         return -1;
  527.         }
  528.     }
  529.     }
  530.     Debug("snoozing %d\n", snooze);
  531.  
  532.     do {
  533.     if (!(done = check_new_mail()))
  534.         sleep((unsigned) snooze);
  535.     } while (!done);
  536.     /* Known to be safe to pass NULL to chk_two_lists() */
  537.     if (!chk_option("quiet", "await"))
  538.     bell();
  539.  
  540.     while (last_cnt < msg_cnt) {
  541.     set_msg_bit(list, last_cnt);
  542.     ++last_cnt;
  543.     }
  544.  
  545.     return 0;
  546. }
  547.  
  548. mark_msg(x, argv, list)
  549. int x;
  550. char **argv, list[];
  551. {
  552.     int i, set_priority = 0;
  553.     int unmark = argv && argv[0] && argv[0][0] == 'u';
  554.  
  555.     if (argv && *++argv && !strcmp(*argv, "-?"))
  556.     return help(0, "mark", cmd_help);
  557.  
  558.     /* command must be "mark [ -[A|B|C|D|E] ] [msg_list]" */
  559.     if (!unmark && argv && *argv && **argv == '-') {
  560.     if (!argv[0][1])
  561.         set_priority = -1; /* special case for clearing priority */
  562.     else if ((set_priority = (upper(argv[0][1]) - 'A' + 1)) < 1 ||
  563.           set_priority > MAX_PRIORITY) {
  564.         print("mark: priority -A through -%c required (- to clear)\n",
  565.         MAX_PRIORITY + 'A');
  566.         return -1;
  567.     }
  568.     ++argv;
  569.     }
  570.     if (x && (x = get_msg_list(argv, list)) == -1)
  571.     return -1;
  572.     argv += x;
  573.     /* if extraneous args exist or the priority was misspecified... */
  574.     if (argv[0]) {
  575.     print("Unknown arg: %s.  mark -? for help.\n", *argv);
  576.     return -1;
  577.     }
  578.     for (x = 0; x < msg_cnt; x++)
  579.     if (msg_bit(list, x)) {
  580.         if (set_priority)
  581.         /* could be setting priority or clearing all priorities */
  582.         for (i = 1; i <= MAX_PRIORITY; i++)
  583.             turnoff(msg[x].m_flags, M_PRIORITY(i));
  584.         if (unmark)
  585.         turnoff(msg[x].m_flags, M_PRIORITY(0));
  586.         else if (set_priority > 0) {
  587.         turnon(msg[x].m_flags, M_PRIORITY(set_priority)|DO_UPDATE);
  588.         turnon(glob_flags, DO_UPDATE);
  589.         } else if (set_priority == 0)
  590.         turnon(msg[x].m_flags, M_PRIORITY(0));
  591.     }
  592.     if (istool > 1)
  593.     (void) do_hdrs(0, DUBL_NULL, NULL);
  594.     return 0;
  595. }
  596.