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