home *** CD-ROM | disk | FTP | other *** search
- /*
- * Spawn a shell with file descriptors that look like this:
- *
- * + ---> screen (& virtual screen)
- * |
- * +---------+ +-----------+
- * | | <---> cmd IPC <---> | pcomm_cmd |
- * | Pcomm | +-----------+
- * TTYin ---> | | ---> pipe --> stdin | |
- * +---------+ | shell |
- * TTYout <--------------------------- stdout | |
- * +-----------+
- *
- * This allows the characters to appear on the screen *and* be interpreted
- * by the shell script.
- */
-
- #include <stdio.h>
- #include <curses.h>
- #include <signal.h>
- #include <errno.h>
- #include "config.h"
- #include "dial_dir.h"
- #include "misc.h"
- #include "modem.h"
- #include "status.h"
-
- static int epid, dup_pipe[2];
- static char **fixup_env();
-
- void
- do_script(script)
- char *script;
- {
- extern int fd;
- char buf[80], *path, *findfile(), **envp, *ipc_key(), *strcpy();
- void _exit(), error_win(), ipc_update();
-
- if (*script == '\0')
- return;
- /*
- * Chaining of scripts, is not allowed. If a script performs the
- * "pcomm_cmd dial" command and that dialing directory entry has
- * something in the script field, then ignore the second script.
- */
- if (status->dup_fd != -1)
- return;
- /* find the script file */
- if ((path = findfile(script)) == NULL) {
- /*
- * Fail quietly, if the script is actually a TTY or a
- * modem
- */
- if (chk_aux(script) != IS_SCRIPT)
- return;
-
- sprintf(buf, "Can't locate script \"%s\"", script);
- error_win(0, buf, "");
- return;
- }
- /* execute permission ? */
- if (access(path, 1)) {
- sprintf(buf, "\"%s\"", path);
- error_win(0, "No execute permission on script file", buf);
- return;
- }
- /*
- * If a script is invoked prior to dialing, then we need to
- * pass a valid "fd" to the child process. If the script
- * then does a "pcomm_cmd dial", it *must* use that fd.
- */
- if (fd == -1) {
- dir->d_cur = 0;
- dir->q_num[0] = 0;
- if (get_port())
- return;
- }
- /* create a fd for duplicating input */
- if (pipe(dup_pipe) < 0) {
- error_win(0, "Out of pipe resources", "");
- return;
- }
-
- status->dup_fd = dup_pipe[1];
- /* open an IPC channel */
- if ((status->cmd_ipc = ipc_open()) < 0) {
- close(dup_pipe[0]);
- close(dup_pipe[1]);
- status->dup_fd = -1;
- error_win(0, "Can't open IPC channel", "");
- return;
- }
- ipc_update(fd, status->cmd_ipc);
- /* pass the "key" in the environment */
- strcpy(buf, ipc_key(status->cmd_ipc));
- envp = fixup_env(buf);
-
- if (!(epid = fork())) {
- /* create a new process group ID */
- #ifdef BSD
- setpgrp(0, getpid());
- #else /* BSD */
- setpgrp();
- #endif /* BSD */
- /* swap the stdin and stdout */
- close(0);
- dup(dup_pipe[0]);
- close(1);
- dup(fd);
-
- setgid(getgid());
- setuid(getuid());
-
- execle("/bin/sh", "sh", "-c", path, (char *) 0, envp);
- _exit(1);
- }
- return;
- }
-
- /*
- * See if the script process is still active
- */
-
- void
- is_active()
- {
- extern int errno, fd;
- int dummy;
- void ipc_update();
-
- #ifdef BSD
- if ((kill(epid, 0) == -1) && errno == ESRCH) {
- #else /* BSD */
- if ((kill(-epid, 0) == -1) && errno == ESRCH) {
- #endif /* BSD */
- /* shut down the duplication of input */
- close(dup_pipe[0]);
- close(dup_pipe[1]);
- ipc_close(status->cmd_ipc);
-
- status->dup_fd = -1;
- status->cmd_ipc = -1;
- ipc_update(fd, status->cmd_ipc);
-
- wait(&dummy);
- beep();
- }
- return;
- }
-
- /*
- * Abort the script prematurely.
- */
-
- void
- stop_script()
- {
- extern int fd;
- int dummy;
- unsigned int sleep();
- void ipc_update();
-
- #ifdef BSD
- killpg(epid, SIGKILL);
- #else /* BSD */
- kill(-epid, SIGKILL);
- #endif /* BSD */
-
- sleep(1);
-
- close(dup_pipe[0]);
- close(dup_pipe[1]);
- ipc_close(status->cmd_ipc);
-
- status->dup_fd = -1;
- status->cmd_ipc = -1;
- ipc_update(fd, status->cmd_ipc);
-
- wait(&dummy);
- return;
- }
-
- /*
- * Prompt the user for a shell script.
- */
-
- char *
- script_menu()
- {
- extern int fd;
- WINDOW *sc_win, *newwin();
- char *ans, *script, *get_str(), *findfile(), *str_dup(), *path;
- char *strchr(), buf[80], *strcpy();
- void free_ptr(), error_win();
-
- if (status->dup_fd != -1) {
- error_win(0, "A script is already running", "Concurrent scripts are not allowed");
- return(NULL);
- }
-
- sc_win = newwin(5, 55, 4, 7);
-
- box(sc_win, VERT, HORZ);
- mvwaddstr(sc_win, 2, 4, "Shell script: ");
- mvwattrstr(sc_win, 0, 3, A_BOLD, " Command Files ");
- wmove(sc_win, 2, 18);
- wrefresh(sc_win);
-
- script = NULL;
- strcpy(buf, "Shell script not found");
- /* get the answer */
- while ((ans = get_str(sc_win, 80, "", " \t\n")) != NULL) {
- /* a CR means exit */
- if (*ans == '\0')
- break;
- /* see if we can find it */
- if ((path = findfile(ans)) != NULL) {
- if (!access(path, 1)) {
- free_ptr(path);
- script = str_dup(ans);
- break;
- }
- else
- strcpy(buf, "No execute permission");
- }
-
- beep();
- if (strchr(ans, '/'))
- strcpy(buf, "Don't include the path");
-
- mvwattrstr(sc_win, 3, 16, A_BOLD, buf);
- wrefresh(sc_win);
- wait_key(sc_win, 3);
- /* clean up the mess */
- clear_line(sc_win, 2, 18, TRUE);
- clear_line(sc_win, 3, 16, TRUE);
- wmove(sc_win, 2, 18);
- wrefresh(sc_win);
-
- free_ptr(path);
- }
- if (fd == -1) {
- werase(sc_win);
- wrefresh(sc_win);
- }
- delwin(sc_win);
- return(script);
- }
-
- /*
- * Put PCOMM_CMD into a new environmental variable array.
- */
-
- static char **
- fixup_env(key)
- char *key;
- {
- int n;
- extern char **environ;
- char **envp, buf[80], **old, **new, *malloc(), *str_dup();
-
- /* how many variables do we have? */
- old = environ;
- n = 0;
- while (*old != NULL) {
- n++;
- old++;
- }
-
- envp = (char **) malloc((n+2) * sizeof(char *));
- new = envp;
- old = environ;
- while (*old != NULL) {
- /* don't copy an old value */
- if (strncmp(*old, "PCOMM_CMD=", 10)) {
- *new = str_dup(*old);
- new++;
- }
- old++;
- }
- sprintf(buf, "PCOMM_CMD=%s", key);
- *new = str_dup(buf);
- new++;
- *new = NULL;
- return(envp);
- }
-