2 * Copyright (C) 2014 Red Hat Inc.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
33 #include <sys/types.h>
39 /* RHEL 6 pcre did not define PCRE_PARTIAL_SOFT. However PCRE_PARTIAL
40 * is a synonym so use that.
42 #ifndef PCRE_PARTIAL_SOFT
43 #define PCRE_PARTIAL_SOFT PCRE_PARTIAL
46 #include "miniexpect.h"
53 mexp_h *h = malloc (sizeof *h);
57 /* Initialize the fields to default values. */
64 h->len = h->alloc = 0;
66 h->user1 = h->user2 = h->user3 = NULL;
72 clear_buffer (mexp_h *h)
76 h->alloc = h->len = 0;
81 mexp_close (mexp_h *h)
90 if (waitpid (h->pid, &status, 0) == -1)
100 mexp_spawnl (const char *file, const char *arg, ...)
102 char **argv, **new_argv;
107 argv = malloc (sizeof (char *));
110 argv[0] = (char *) arg;
112 va_start (args, arg);
113 for (i = 1; arg != NULL; ++i) {
114 arg = va_arg (args, const char *);
115 new_argv = realloc (argv, sizeof (char *) * (i+1));
116 if (new_argv == NULL) {
122 argv[i] = (char *) arg;
125 h = mexp_spawnv (file, argv);
132 mexp_spawnv (const char *file, char **argv)
140 fd = posix_openpt (O_RDWR|O_NOCTTY);
144 if (grantpt (fd) == -1)
147 if (unlockpt (fd) == -1)
150 /* Get the slave pty name now, but don't open it in the parent. */
151 if (ptsname_r (fd, slave, sizeof slave) != 0)
154 /* Create the handle last before we fork. */
155 h = create_handle ();
163 if (pid == 0) { /* Child. */
164 struct termios terminal_settings;
166 int i, slave_fd, max_fd;
168 /* Remove all signal handlers. See the justification here:
169 * https://www.redhat.com/archives/libvir-list/2008-August/msg00303.html
170 * We don't mask signal handlers yet, so this isn't completely
171 * race-free, but better than not doing it at all.
173 memset (&sa, 0, sizeof sa);
174 sa.sa_handler = SIG_DFL;
176 sigemptyset (&sa.sa_mask);
177 for (i = 1; i < NSIG; ++i)
178 sigaction (i, &sa, NULL);
182 /* Open the slave side of the pty. We must do this in the child
183 * after setsid so it becomes our controlling tty.
185 slave_fd = open (slave, O_RDWR);
190 tcgetattr (slave_fd, &terminal_settings);
191 cfmakeraw (&terminal_settings);
192 tcsetattr (slave_fd, TCSANOW, &terminal_settings);
194 /* Set up stdin, stdout, stderr to point to the pty. */
200 /* Close the master side of the pty - do this late to avoid a
201 * kernel bug, see sshpass source code.
205 /* Close all other file descriptors. This ensures that we don't
206 * hold open (eg) pipes from the parent process.
208 max_fd = sysconf (_SC_OPEN_MAX);
212 max_fd = 65536; /* bound the amount of work we do here */
213 for (fd = 3; fd < max_fd; ++fd)
216 /* Run the subprocess. */
219 _exit (EXIT_FAILURE);
233 waitpid (pid, NULL, 0);
241 mexp_expect (mexp_h *h, const mexp_regexp *regexps, int *ovector, int ovecsize)
243 time_t start_t, now_t;
245 struct pollfd pfds[1];
251 if (h->next_match == -1) {
252 /* Fully clear the buffer, then read. */
255 /* See the comment in the manual about h->next_match. We have
256 * some data remaining in the buffer, so begin by matching that.
258 memmove (&h->buffer[0], &h->buffer[h->next_match], h->len - h->next_match);
259 h->len -= h->next_match;
260 h->buffer[h->len] = '\0';
266 /* If we've got a timeout then work out how many seconds are left.
267 * Timeout == 0 is not particularly well-defined, but it probably
268 * means "return immediately if there's no data to be read".
270 if (h->timeout >= 0) {
272 timeout = h->timeout - ((now_t - start_t) * 1000);
280 pfds[0].events = POLLIN;
282 r = poll (pfds, 1, timeout);
284 fprintf (stderr, "DEBUG: poll returned %d\n", r);
292 /* Otherwise we expect there is something to read from the file
295 if (h->alloc - h->len <= h->read_size) {
297 /* +1 here allows us to store \0 after the data read */
298 new_buffer = realloc (h->buffer, h->alloc + h->read_size + 1);
299 if (new_buffer == NULL)
301 h->buffer = new_buffer;
302 h->alloc += h->read_size;
304 rs = read (h->fd, h->buffer + h->len, h->read_size);
306 fprintf (stderr, "DEBUG: read returned %zd\n", rs);
309 /* Annoyingly on Linux (I'm fairly sure this is a bug) if the
310 * writer closes the connection, the entire pty is destroyed,
311 * and read returns -1 / EIO. Handle that special case here.
320 /* We read something. */
322 h->buffer[h->len] = '\0';
324 fprintf (stderr, "DEBUG: read %zd bytes from pty\n", rs);
325 fprintf (stderr, "DEBUG: buffer content: %s\n", h->buffer);
329 /* See if there is a full or partial match against any regexp. */
332 int can_clear_buffer = 1;
334 assert (h->buffer != NULL);
336 for (i = 0; regexps[i].r > 0; ++i) {
337 int options = regexps[i].options | PCRE_PARTIAL_SOFT;
339 r = pcre_exec (regexps[i].re, regexps[i].extra,
340 h->buffer, (int)h->len, 0,
347 if (ovector != NULL && ovecsize >= 1 && ovector[1] >= 0)
348 h->next_match = ovector[1];
354 else if (r == PCRE_ERROR_NOMATCH) {
355 /* No match at all. */
359 else if (r == PCRE_ERROR_PARTIAL) {
360 /* Partial match. Keep the buffer and keep reading. */
361 can_clear_buffer = 0;
365 /* An actual PCRE error. */
366 return MEXP_PCRE_ERROR;
370 /* If none of the regular expressions matched (not partially)
371 * then we can clear the buffer. This is an optimization.
373 if (can_clear_buffer)
381 mexp_printf (mexp_h *h, const char *fs, ...)
391 len = vasprintf (&msg, fs, args);
398 fprintf (stderr, "DEBUG: writing: %s\n", msg);
404 r = write (h->fd, p, n);