X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=miniexpect.c;h=d5a7c6e5d8e5b8596a1c157dacd631d894c2db93;hb=2c56e0f2171d68ff13c4a510feffd6bbb52d6381;hp=9e9cc0ee3b0cbdc30723ac1ed48fd0287c636abb;hpb=329575032af72a3155bcc2640231e603604cd253;p=miniexpect.git diff --git a/miniexpect.c b/miniexpect.c index 9e9cc0e..d5a7c6e 100644 --- a/miniexpect.c +++ b/miniexpect.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,13 @@ #include +/* RHEL 6 pcre did not define PCRE_PARTIAL_SOFT. However PCRE_PARTIAL + * is a synonym so use that. + */ +#ifndef PCRE_PARTIAL_SOFT +#define PCRE_PARTIAL_SOFT PCRE_PARTIAL +#endif + #include "miniexpect.h" #define DEBUG 0 @@ -89,7 +97,7 @@ mexp_close (mexp_h *h) } mexp_h * -mexp_spawnl (const char *file, const char *arg, ...) +mexp_spawnlf (unsigned flags, const char *file, const char *arg, ...) { char **argv, **new_argv; size_t i; @@ -107,21 +115,23 @@ mexp_spawnl (const char *file, const char *arg, ...) new_argv = realloc (argv, sizeof (char *) * (i+1)); if (new_argv == NULL) { free (argv); + va_end (args); return NULL; } argv = new_argv; argv[i] = (char *) arg; } - h = mexp_spawnv (file, argv); + h = mexp_spawnvf (flags, file, argv); free (argv); + va_end (args); return h; } mexp_h * -mexp_spawnv (const char *file, char **argv) +mexp_spawnvf (unsigned flags, const char *file, char **argv) { - mexp_h *h; + mexp_h *h = NULL; int fd = -1; int err; char slave[1024]; @@ -151,9 +161,25 @@ mexp_spawnv (const char *file, char **argv) goto error; if (pid == 0) { /* Child. */ - struct termios terminal_settings; int slave_fd; + if (!(flags & MEXP_SPAWN_KEEP_SIGNALS)) { + struct sigaction sa; + int i; + + /* Remove all signal handlers. See the justification here: + * https://www.redhat.com/archives/libvir-list/2008-August/msg00303.html + * We don't mask signal handlers yet, so this isn't completely + * race-free, but better than not doing it at all. + */ + memset (&sa, 0, sizeof sa); + sa.sa_handler = SIG_DFL; + sa.sa_flags = 0; + sigemptyset (&sa.sa_mask); + for (i = 1; i < NSIG; ++i) + sigaction (i, &sa, NULL); + } + setsid (); /* Open the slave side of the pty. We must do this in the child @@ -163,10 +189,14 @@ mexp_spawnv (const char *file, char **argv) if (slave_fd == -1) goto error; - /* Set raw mode. */ - tcgetattr (slave_fd, &terminal_settings); - cfmakeraw (&terminal_settings); - tcsetattr (slave_fd, TCSANOW, &terminal_settings); + if (!(flags & MEXP_SPAWN_COOKED_MODE)) { + struct termios termios; + + /* Set raw mode. */ + tcgetattr (slave_fd, &termios); + cfmakeraw (&termios); + tcsetattr (slave_fd, TCSANOW, &termios); + } /* Set up stdin, stdout, stderr to point to the pty. */ dup2 (slave_fd, 0); @@ -179,6 +209,21 @@ mexp_spawnv (const char *file, char **argv) */ close (fd); + if (!(flags & MEXP_SPAWN_KEEP_FDS)) { + int i, max_fd; + + /* Close all other file descriptors. This ensures that we don't + * hold open (eg) pipes from the parent process. + */ + max_fd = sysconf (_SC_OPEN_MAX); + if (max_fd == -1) + max_fd = 1024; + if (max_fd > 65536) + max_fd = 65536; /* bound the amount of work we do here */ + for (i = 3; i < max_fd; ++i) + close (i); + } + /* Run the subprocess. */ execvp (file, argv); perror (file); @@ -197,6 +242,8 @@ mexp_spawnv (const char *file, char **argv) close (fd); if (pid > 0) waitpid (pid, NULL, 0); + if (h != NULL) + mexp_close (h); errno = err; return NULL; } @@ -298,7 +345,7 @@ mexp_expect (mexp_h *h, const mexp_regexp *regexps, int *ovector, int ovecsize) assert (h->buffer != NULL); for (i = 0; regexps[i].r > 0; ++i) { - int options = regexps[i].options | PCRE_PARTIAL_SOFT; + const int options = regexps[i].options | PCRE_PARTIAL_SOFT; r = pcre_exec (regexps[i].re, regexps[i].extra, h->buffer, (int)h->len, 0, @@ -377,3 +424,9 @@ mexp_printf (mexp_h *h, const char *fs, ...) free (msg); return len; } + +int +mexp_send_interrupt (mexp_h *h) +{ + return write (h->fd, "\003", 1); +}