9f3b7ba3fe5ad9d6c746137f1a62506b6a36faab
[miniexpect.git] / miniexpect.c
1 /* miniexpect
2  * Copyright (C) 2014 Red Hat Inc.
3  *
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.
8  *
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.
13  *
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
17  */
18
19 #include <config.h>
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <stdarg.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include <fcntl.h>
27 #include <unistd.h>
28 #include <signal.h>
29 #include <poll.h>
30 #include <errno.h>
31 #include <termios.h>
32 #include <time.h>
33 #include <assert.h>
34 #include <sys/types.h>
35 #include <sys/wait.h>
36 #include <sys/time.h>
37
38 #define PCRE2_CODE_UNIT_WIDTH 8
39 #include <pcre2.h>
40
41 #include "miniexpect.h"
42
43 static void debug_buffer (FILE *, const char *);
44
45 static mexp_h *
46 create_handle (void)
47 {
48   mexp_h *h = malloc (sizeof *h);
49   if (h == NULL)
50     return NULL;
51
52   /* Initialize the fields to default values. */
53   h->fd = -1;
54   h->pid = 0;
55   h->timeout = 60000;
56   h->read_size = 1024;
57   h->pcre_error = 0;
58   h->buffer = NULL;
59   h->len = h->alloc = 0;
60   h->next_match = -1;
61   h->debug_fp = NULL;
62   h->user1 = h->user2 = h->user3 = NULL;
63
64   return h;
65 }
66
67 static void
68 clear_buffer (mexp_h *h)
69 {
70   free (h->buffer);
71   h->buffer = NULL;
72   h->alloc = h->len = 0;
73   h->next_match = -1;
74 }
75
76 int
77 mexp_close (mexp_h *h)
78 {
79   int status = 0;
80
81   free (h->buffer);
82
83   if (h->fd >= 0)
84     close (h->fd);
85   if (h->pid > 0) {
86     if (waitpid (h->pid, &status, 0) == -1)
87       return -1;
88   }
89
90   free (h);
91
92   return status;
93 }
94
95 mexp_h *
96 mexp_spawnlf (unsigned flags, const char *file, const char *arg, ...)
97 {
98   char **argv, **new_argv;
99   size_t i;
100   va_list args;
101   mexp_h *h;
102
103   argv = malloc (sizeof (char *));
104   if (argv == NULL)
105     return NULL;
106   argv[0] = (char *) arg;
107
108   va_start (args, arg);
109   for (i = 1; arg != NULL; ++i) {
110     arg = va_arg (args, const char *);
111     new_argv = realloc (argv, sizeof (char *) * (i+1));
112     if (new_argv == NULL) {
113       free (argv);
114       va_end (args);
115       return NULL;
116     }
117     argv = new_argv;
118     argv[i] = (char *) arg;
119   }
120
121   h = mexp_spawnvf (flags, file, argv);
122   free (argv);
123   va_end (args);
124   return h;
125 }
126
127 mexp_h *
128 mexp_spawnvf (unsigned flags, const char *file, char **argv)
129 {
130   mexp_h *h = NULL;
131   int fd = -1;
132   int err;
133   char slave[1024];
134   pid_t pid = 0;
135
136   fd = posix_openpt (O_RDWR|O_NOCTTY);
137   if (fd == -1)
138     goto error;
139
140   if (grantpt (fd) == -1)
141     goto error;
142
143   if (unlockpt (fd) == -1)
144     goto error;
145
146   /* Get the slave pty name now, but don't open it in the parent. */
147   if (ptsname_r (fd, slave, sizeof slave) != 0)
148     goto error;
149
150   /* Create the handle last before we fork. */
151   h = create_handle ();
152   if (h == NULL)
153     goto error;
154
155   pid = fork ();
156   if (pid == -1)
157     goto error;
158
159   if (pid == 0) {               /* Child. */
160     int slave_fd;
161
162     if (!(flags & MEXP_SPAWN_KEEP_SIGNALS)) {
163       struct sigaction sa;
164       int i;
165
166       /* Remove all signal handlers.  See the justification here:
167        * https://www.redhat.com/archives/libvir-list/2008-August/msg00303.html
168        * We don't mask signal handlers yet, so this isn't completely
169        * race-free, but better than not doing it at all.
170        */
171       memset (&sa, 0, sizeof sa);
172       sa.sa_handler = SIG_DFL;
173       sa.sa_flags = 0;
174       sigemptyset (&sa.sa_mask);
175       for (i = 1; i < NSIG; ++i)
176         sigaction (i, &sa, NULL);
177     }
178
179     setsid ();
180
181     /* Open the slave side of the pty.  We must do this in the child
182      * after setsid so it becomes our controlling tty.
183      */
184     slave_fd = open (slave, O_RDWR);
185     if (slave_fd == -1)
186       goto error;
187
188     if (!(flags & MEXP_SPAWN_COOKED_MODE)) {
189       struct termios termios;
190
191       /* Set raw mode. */
192       tcgetattr (slave_fd, &termios);
193       cfmakeraw (&termios);
194       tcsetattr (slave_fd, TCSANOW, &termios);
195     }
196
197     /* Set up stdin, stdout, stderr to point to the pty. */
198     dup2 (slave_fd, 0);
199     dup2 (slave_fd, 1);
200     dup2 (slave_fd, 2);
201     close (slave_fd);
202
203     /* Close the master side of the pty - do this late to avoid a
204      * kernel bug, see sshpass source code.
205      */
206     close (fd);
207
208     if (!(flags & MEXP_SPAWN_KEEP_FDS)) {
209       int i, max_fd;
210
211       /* Close all other file descriptors.  This ensures that we don't
212        * hold open (eg) pipes from the parent process.
213        */
214       max_fd = sysconf (_SC_OPEN_MAX);
215       if (max_fd == -1)
216         max_fd = 1024;
217       if (max_fd > 65536)
218         max_fd = 65536;      /* bound the amount of work we do here */
219       for (i = 3; i < max_fd; ++i)
220         close (i);
221     }
222
223     /* Run the subprocess. */
224     execvp (file, argv);
225     perror (file);
226     _exit (EXIT_FAILURE);
227   }
228
229   /* Parent. */
230
231   h->fd = fd;
232   h->pid = pid;
233   return h;
234
235  error:
236   err = errno;
237   if (fd >= 0)
238     close (fd);
239   if (pid > 0)
240     waitpid (pid, NULL, 0);
241   if (h != NULL)
242     mexp_close (h);
243   errno = err;
244   return NULL;
245 }
246
247 int
248 mexp_expect (mexp_h *h, const mexp_regexp *regexps,
249              pcre2_match_data *match_data)
250 {
251   time_t start_t, now_t;
252   int timeout;
253   struct pollfd pfds[1];
254   int r;
255   ssize_t rs;
256
257   time (&start_t);
258
259   if (h->next_match == -1) {
260     /* Fully clear the buffer, then read. */
261     clear_buffer (h);
262   } else {
263     /* See the comment in the manual about h->next_match.  We have
264      * some data remaining in the buffer, so begin by matching that.
265      */
266     memmove (&h->buffer[0], &h->buffer[h->next_match], h->len - h->next_match);
267     h->len -= h->next_match;
268     h->buffer[h->len] = '\0';
269     h->next_match = -1;
270     goto try_match;
271   }
272
273   for (;;) {
274     /* If we've got a timeout then work out how many seconds are left.
275      * Timeout == 0 is not particularly well-defined, but it probably
276      * means "return immediately if there's no data to be read".
277      */
278     if (h->timeout >= 0) {
279       time (&now_t);
280       timeout = h->timeout - ((now_t - start_t) * 1000);
281       if (timeout < 0)
282         timeout = 0;
283     }
284     else
285       timeout = 0;
286
287     pfds[0].fd = h->fd;
288     pfds[0].events = POLLIN;
289     pfds[0].revents = 0;
290     r = poll (pfds, 1, timeout);
291     if (h->debug_fp)
292       fprintf (h->debug_fp, "DEBUG: poll returned %d\n", r);
293     if (r == -1)
294       return MEXP_ERROR;
295
296     if (r == 0)
297       return MEXP_TIMEOUT;
298
299     /* Otherwise we expect there is something to read from the file
300      * descriptor.
301      */
302     if (h->alloc - h->len <= h->read_size) {
303       char *new_buffer;
304       /* +1 here allows us to store \0 after the data read */
305       new_buffer = realloc (h->buffer, h->alloc + h->read_size + 1);
306       if (new_buffer == NULL)
307         return MEXP_ERROR;
308       h->buffer = new_buffer;
309       h->alloc += h->read_size;
310     }
311     rs = read (h->fd, h->buffer + h->len, h->read_size);
312     if (h->debug_fp)
313       fprintf (h->debug_fp, "DEBUG: read returned %zd\n", rs);
314     if (rs == -1) {
315       /* Annoyingly on Linux (I'm fairly sure this is a bug) if the
316        * writer closes the connection, the entire pty is destroyed,
317        * and read returns -1 / EIO.  Handle that special case here.
318        */
319       if (errno == EIO)
320         return MEXP_EOF;
321       return MEXP_ERROR;
322     }
323     if (rs == 0)
324       return MEXP_EOF;
325
326     /* We read something. */
327     h->len += rs;
328     h->buffer[h->len] = '\0';
329     if (h->debug_fp) {
330       fprintf (h->debug_fp, "DEBUG: read %zd bytes from pty\n", rs);
331       fprintf (h->debug_fp, "DEBUG: buffer content: ");
332       debug_buffer (h->debug_fp, h->buffer);
333       fprintf (h->debug_fp, "\n");
334     }
335
336   try_match:
337     /* See if there is a full or partial match against any regexp. */
338     if (regexps) {
339       size_t i;
340       int can_clear_buffer = 1;
341
342       assert (h->buffer != NULL);
343
344       for (i = 0; regexps[i].r > 0; ++i) {
345         const int options = regexps[i].options | PCRE2_PARTIAL_SOFT;
346
347         r = pcre2_match (regexps[i].re,
348                          (PCRE2_SPTR) h->buffer, (int)h->len, 0,
349                          options, match_data, NULL);
350         h->pcre_error = r;
351
352         if (r >= 0) {
353           /* A full match. */
354           const PCRE2_SIZE *ovector = NULL;
355
356           if (match_data)
357             ovector = pcre2_get_ovector_pointer (match_data);
358
359           if (ovector != NULL && ovector[1] != ~(PCRE2_SIZE)0)
360             h->next_match = ovector[1];
361           else
362             h->next_match = -1;
363           if (h->debug_fp)
364             fprintf (h->debug_fp, "DEBUG: next_match at buffer offset %zu\n",
365                      h->next_match);
366           return regexps[i].r;
367         }
368
369         else if (r == PCRE2_ERROR_NOMATCH) {
370           /* No match at all. */
371           /* (nothing here) */
372         }
373
374         else if (r == PCRE2_ERROR_PARTIAL) {
375           /* Partial match.  Keep the buffer and keep reading. */
376           can_clear_buffer = 0;
377         }
378
379         else {
380           /* An actual PCRE error. */
381           return MEXP_PCRE_ERROR;
382         }
383       }
384
385       /* If none of the regular expressions matched (not partially)
386        * then we can clear the buffer.  This is an optimization.
387        */
388       if (can_clear_buffer)
389         clear_buffer (h);
390
391     } /* if (regexps) */
392   }
393 }
394
395 static int mexp_vprintf (mexp_h *h, int password, const char *fs, va_list args)
396   __attribute__((format(printf,3,0)));
397
398 static int
399 mexp_vprintf (mexp_h *h, int password, const char *fs, va_list args)
400 {
401   char *msg;
402   int len;
403   size_t n;
404   ssize_t r;
405   char *p;
406
407   len = vasprintf (&msg, fs, args);
408
409   if (len < 0)
410     return -1;
411
412   if (h->debug_fp) {
413     if (!password) {
414       fprintf (h->debug_fp, "DEBUG: writing: ");
415       debug_buffer (h->debug_fp, msg);
416       fprintf (h->debug_fp, "\n");
417     }
418     else
419       fprintf (h->debug_fp, "DEBUG: writing the password\n");
420   }
421
422   n = len;
423   p = msg;
424   while (n > 0) {
425     r = write (h->fd, p, n);
426     if (r == -1) {
427       free (msg);
428       return -1;
429     }
430     n -= r;
431     p += r;
432   }
433
434   free (msg);
435   return len;
436 }
437
438 int
439 mexp_printf (mexp_h *h, const char *fs, ...)
440 {
441   int r;
442   va_list args;
443
444   va_start (args, fs);
445   r = mexp_vprintf (h, 0, fs, args);
446   va_end (args);
447   return r;
448 }
449
450 int
451 mexp_printf_password (mexp_h *h, const char *fs, ...)
452 {
453   int r;
454   va_list args;
455
456   va_start (args, fs);
457   r = mexp_vprintf (h, 1, fs, args);
458   va_end (args);
459   return r;
460 }
461
462 int
463 mexp_send_interrupt (mexp_h *h)
464 {
465   return write (h->fd, "\003", 1);
466 }
467
468 /* Print escaped buffer to fp. */
469 static void
470 debug_buffer (FILE *fp, const char *buf)
471 {
472   while (*buf) {
473     if (isprint (*buf))
474       fputc (*buf, fp);
475     else {
476       switch (*buf) {
477       case '\0': fputs ("\\0", fp); break;
478       case '\a': fputs ("\\a", fp); break;
479       case '\b': fputs ("\\b", fp); break;
480       case '\f': fputs ("\\f", fp); break;
481       case '\n': fputs ("\\n", fp); break;
482       case '\r': fputs ("\\r", fp); break;
483       case '\t': fputs ("\\t", fp); break;
484       case '\v': fputs ("\\v", fp); break;
485       default:
486         fprintf (fp, "\\x%x", (unsigned char) *buf);
487       }
488     }
489     buf++;
490   }
491 }