home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume26 / pcomm-2.0.2 / part02 / script.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-13  |  5.8 KB  |  287 lines

  1. /*
  2.  * Spawn a shell with file descriptors that look like this:
  3.  *
  4.  *                   + ---> screen (& virtual screen)
  5.  *                   |
  6.  *              +---------+                     +-----------+
  7.  *              |         | <---> cmd IPC <---> | pcomm_cmd |
  8.  *              |  Pcomm  |                     +-----------+
  9.  *   TTYin ---> |         | ---> pipe --> stdin |           |
  10.  *              +---------+                     |   shell   |
  11.  *   TTYout <--------------------------- stdout |           |
  12.  *                                              +-----------+
  13.  *
  14.  * This allows the characters to appear on the screen *and* be interpreted
  15.  * by the shell script.
  16.  */
  17.  
  18. #include <stdio.h>
  19. #include <curses.h>
  20. #include <signal.h>
  21. #include <errno.h>
  22. #include "config.h"
  23. #include "dial_dir.h"
  24. #include "misc.h"
  25. #include "modem.h"
  26. #include "status.h"
  27.  
  28. static int epid, dup_pipe[2];
  29. static char **fixup_env();
  30.  
  31. void
  32. do_script(script)
  33. char *script;
  34. {
  35.     extern int fd;
  36.     char buf[80], *path, *findfile(), **envp, *ipc_key(), *strcpy();
  37.     void _exit(), error_win(), ipc_update();
  38.  
  39.     if (*script == '\0')
  40.         return;
  41.     /*
  42.      * Chaining of scripts, is not allowed.  If a script performs the
  43.      * "pcomm_cmd dial" command and that dialing directory entry has
  44.      * something in the script field, then ignore the second script.
  45.      */
  46.     if (status->dup_fd != -1)
  47.         return;
  48.                     /* find the script file */
  49.     if ((path = findfile(script)) == NULL) {
  50.         /*
  51.          * Fail quietly, if the script is actually a TTY or a
  52.          * modem 
  53.          */
  54.         if (chk_aux(script) != IS_SCRIPT)
  55.             return;
  56.  
  57.         sprintf(buf, "Can't locate script \"%s\"", script);
  58.         error_win(0, buf, "");
  59.         return;
  60.     }
  61.                     /* execute permission ? */
  62.     if (access(path, 1)) {
  63.         sprintf(buf, "\"%s\"", path);
  64.         error_win(0, "No execute permission on script file", buf);
  65.         return;
  66.     }
  67.     /*
  68.      * If a script is invoked prior to dialing, then we need to 
  69.      * pass a valid "fd" to the child process.  If the script
  70.      * then does a "pcomm_cmd dial", it *must* use that fd.
  71.      */
  72.     if (fd == -1) {
  73.         dir->d_cur = 0;
  74.         dir->q_num[0] = 0;
  75.         if (get_port())
  76.             return;
  77.     }
  78.                     /* create a fd for duplicating input */
  79.     if (pipe(dup_pipe) < 0) {
  80.         error_win(0, "Out of pipe resources", "");
  81.         return;
  82.     }
  83.  
  84.     status->dup_fd = dup_pipe[1];
  85.                     /* open an IPC channel */
  86.     if ((status->cmd_ipc = ipc_open()) < 0) {
  87.         close(dup_pipe[0]);
  88.         close(dup_pipe[1]);
  89.         status->dup_fd = -1;
  90.         error_win(0, "Can't open IPC channel", "");
  91.         return;
  92.     }
  93.     ipc_update(fd, status->cmd_ipc);
  94.                     /* pass the "key" in the environment */
  95.     strcpy(buf, ipc_key(status->cmd_ipc));
  96.     envp = fixup_env(buf);
  97.  
  98.     if (!(epid = fork())) {
  99.                     /* create a new process group ID */
  100. #ifdef BSD
  101.         setpgrp(0, getpid());
  102. #else /* BSD */
  103.         setpgrp();
  104. #endif /* BSD */
  105.                     /* swap the stdin and stdout */
  106.         close(0);
  107.         dup(dup_pipe[0]);
  108.         close(1);
  109.         dup(fd);
  110.  
  111.         setgid(getgid());
  112.         setuid(getuid());
  113.  
  114.         execle("/bin/sh", "sh", "-c", path, (char *) 0, envp);
  115.         _exit(1);
  116.     }
  117.     return;
  118. }
  119.  
  120. /*
  121.  * See if the script process is still active
  122.  */
  123.  
  124. void
  125. is_active()
  126. {
  127.     extern int errno, fd;
  128.     int dummy;
  129.     void ipc_update();
  130.  
  131. #ifdef BSD
  132.     if ((kill(epid, 0) == -1) && errno == ESRCH) {
  133. #else /* BSD */
  134.     if ((kill(-epid, 0) == -1) && errno == ESRCH) {
  135. #endif /* BSD */
  136.                     /* shut down the duplication of input */
  137.         close(dup_pipe[0]);
  138.         close(dup_pipe[1]);
  139.         ipc_close(status->cmd_ipc);
  140.  
  141.         status->dup_fd = -1;
  142.         status->cmd_ipc = -1;
  143.         ipc_update(fd, status->cmd_ipc);
  144.  
  145.         wait(&dummy);
  146.         beep();
  147.     }
  148.     return;
  149. }
  150.  
  151. /*
  152.  * Abort the script prematurely.
  153.  */
  154.  
  155. void
  156. stop_script()
  157. {
  158.     extern int fd;
  159.     int dummy;
  160.     unsigned int sleep();
  161.     void ipc_update();
  162.  
  163. #ifdef BSD
  164.     killpg(epid, SIGKILL);
  165. #else /* BSD */
  166.     kill(-epid, SIGKILL);
  167. #endif /* BSD */
  168.  
  169.     sleep(1);
  170.  
  171.     close(dup_pipe[0]);
  172.     close(dup_pipe[1]);
  173.     ipc_close(status->cmd_ipc);
  174.  
  175.     status->dup_fd = -1;
  176.     status->cmd_ipc = -1;
  177.     ipc_update(fd, status->cmd_ipc);
  178.  
  179.     wait(&dummy);
  180.     return;
  181. }
  182.  
  183. /*
  184.  * Prompt the user for a shell script.
  185.  */
  186.  
  187. char *
  188. script_menu()
  189. {
  190.     extern int fd;
  191.     WINDOW *sc_win, *newwin();
  192.     char *ans, *script, *get_str(), *findfile(), *str_dup(), *path;
  193.     char *strchr(), buf[80], *strcpy();
  194.     void free_ptr(), error_win();
  195.  
  196.     if (status->dup_fd != -1) {
  197.         error_win(0, "A script is already running", "Concurrent scripts are not allowed");
  198.         return(NULL);
  199.     }
  200.  
  201.     sc_win = newwin(5, 55, 4, 7);
  202.  
  203.     box(sc_win, VERT, HORZ);
  204.     mvwaddstr(sc_win, 2, 4, "Shell script: ");
  205.     mvwattrstr(sc_win, 0, 3, A_BOLD, " Command Files ");
  206.     wmove(sc_win, 2, 18);
  207.     wrefresh(sc_win);
  208.  
  209.     script = NULL;
  210.     strcpy(buf, "Shell script not found");
  211.                     /* get the answer */
  212.     while ((ans = get_str(sc_win, 80, "", " \t\n")) != NULL) {
  213.                     /* a CR means exit */
  214.         if (*ans == '\0')
  215.             break;
  216.                     /* see if we can find it */
  217.         if ((path = findfile(ans)) != NULL) {
  218.             if (!access(path, 1)) {
  219.                 free_ptr(path);
  220.                 script = str_dup(ans);
  221.                 break;
  222.             }
  223.             else
  224.                 strcpy(buf, "No execute permission");
  225.         }
  226.  
  227.         beep();
  228.         if (strchr(ans, '/'))
  229.             strcpy(buf, "Don't include the path");
  230.  
  231.         mvwattrstr(sc_win, 3, 16, A_BOLD, buf);
  232.         wrefresh(sc_win);
  233.         wait_key(sc_win, 3);
  234.                     /* clean up the mess */
  235.         clear_line(sc_win, 2, 18, TRUE);
  236.         clear_line(sc_win, 3, 16, TRUE);
  237.         wmove(sc_win, 2, 18);
  238.         wrefresh(sc_win);
  239.  
  240.         free_ptr(path);
  241.     }
  242.     if (fd == -1) {
  243.         werase(sc_win);
  244.         wrefresh(sc_win);
  245.     }
  246.     delwin(sc_win);
  247.     return(script);
  248. }
  249.  
  250. /*
  251.  * Put PCOMM_CMD into a new environmental variable array.
  252.  */
  253.  
  254. static char **
  255. fixup_env(key)
  256. char *key;
  257. {
  258.     int n;
  259.     extern char **environ;
  260.     char **envp, buf[80], **old, **new, *malloc(), *str_dup();
  261.  
  262.                     /* how many variables do we have? */
  263.     old = environ;
  264.     n = 0;
  265.     while (*old != NULL) {
  266.         n++;
  267.         old++;
  268.     }
  269.  
  270.     envp = (char **) malloc((n+2) * sizeof(char *));
  271.     new = envp;
  272.     old = environ;
  273.     while (*old != NULL) {
  274.                     /* don't copy an old value */
  275.         if (strncmp(*old, "PCOMM_CMD=", 10)) {
  276.             *new = str_dup(*old);
  277.             new++;
  278.         }
  279.         old++;
  280.     }
  281.     sprintf(buf, "PCOMM_CMD=%s", key);
  282.     *new = str_dup(buf);
  283.     new++;
  284.     *new = NULL;
  285.     return(envp);
  286. }
  287.