doc: Describe filter expressions.
[gnupg.git] / common / exectool.c
1 /* exectool.c - Utility functions to execute a helper tool
2  * Copyright (C) 2015 Werner Koch
3  *
4  * This file is part of GnuPG.
5  *
6  * This file is free software; you can redistribute it and/or modify
7  * it under the terms of either
8  *
9  *   - the GNU Lesser General Public License as published by the Free
10  *     Software Foundation; either version 3 of the License, or (at
11  *     your option) any later version.
12  *
13  * or
14  *
15  *   - the GNU General Public License as published by the Free
16  *     Software Foundation; either version 2 of the License, or (at
17  *     your option) any later version.
18  *
19  * or both in parallel, as here.
20  *
21  * This file is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, see <http://www.gnu.org/licenses/>.
28  */
29
30 #include <config.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <stdarg.h>
35 #include <errno.h>
36 #include <assert.h>
37 #include <gpg-error.h>
38
39 #include <assuan.h>
40 #include "i18n.h"
41 #include "logging.h"
42 #include "membuf.h"
43 #include "mischelp.h"
44 #include "exechelp.h"
45 #include "sysutils.h"
46 #include "util.h"
47 #include "exectool.h"
48
49 typedef struct
50 {
51   const char *pgmname;
52   exec_tool_status_cb_t status_cb;
53   void *status_cb_value;
54   int cont;
55   size_t used;
56   size_t buffer_size;
57   char *buffer;
58 } read_and_log_buffer_t;
59
60
61 static inline gpg_error_t
62 my_error_from_syserror (void)
63 {
64   return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
65 }
66
67
68 static void
69 read_and_log_stderr (read_and_log_buffer_t *state, es_poll_t *fderr)
70 {
71   gpg_error_t err;
72   int c;
73
74   if (!fderr)
75     {
76       /* Flush internal buffer.  */
77       if (state->used)
78         {
79           const char *pname;
80           int len;
81
82           state->buffer[state->used] = 0;
83           state->used = 0;
84
85           pname = strrchr (state->pgmname, '/');
86           if (pname && pname != state->pgmname && pname[1])
87             pname++;
88           else
89             pname = state->pgmname;
90           len = strlen (pname);
91
92           if (state->status_cb
93               && !strncmp (state->buffer, "[GNUPG:] ", 9)
94               && state->buffer[9] >= 'A' && state->buffer[9] <= 'Z')
95             {
96               char *rest;
97
98               rest = strchr (state->buffer + 9, ' ');
99               if (!rest)
100                 {
101                   /* Set REST to an empty string.  */
102                   rest = state->buffer + strlen (state->buffer);
103                 }
104               else
105                 {
106                   *rest++ = 0;
107                   trim_spaces (rest);
108                 }
109               state->status_cb (state->status_cb_value,
110                                 state->buffer + 9, rest);
111             }
112           else if (!state->cont
113               && !strncmp (state->buffer, pname, len)
114               && strlen (state->buffer) > strlen (pname)
115               && state->buffer[len] == ':' )
116             {
117               /* PGMNAME plus colon is identical to the start of
118                  the output: print only the output.  */
119               log_info ("%s\n", state->buffer);
120             }
121           else
122             log_info ("%s%c %s\n",
123                       pname, state->cont? '+':':', state->buffer);
124         }
125       state->cont = 0;
126       return;
127     }
128   for (;;)
129     {
130       c = es_fgetc (fderr->stream);
131       if (c == EOF)
132         {
133           if (es_feof (fderr->stream))
134             {
135               fderr->ignore = 1; /* Not anymore needed.  */
136             }
137           else if (es_ferror (fderr->stream))
138             {
139               err = my_error_from_syserror ();
140               log_error ("error reading stderr of '%s': %s\n",
141                          state->pgmname, gpg_strerror (err));
142               fderr->ignore = 1; /* Disable.  */
143             }
144
145           break;
146         }
147       else if (c == '\n')
148         {
149           read_and_log_stderr (state, NULL);
150         }
151       else
152         {
153           if (state->used >= state->buffer_size - 1)
154             {
155               if (state->status_cb)
156                 {
157                   /* A status callback requires that we have a full
158                    * line.  Thus we need to enlarget the buffer in
159                    * this case.  */
160                   char *newbuffer;
161                   size_t newsize = state->buffer_size + 256;
162
163                   newbuffer = xtrymalloc (newsize);
164                   if (!newbuffer)
165                     {
166                       log_error ("error allocating memory for status cb: %s\n",
167                                  gpg_strerror (my_error_from_syserror ()));
168                       /* We better disable the status CB in this case.  */
169                       state->status_cb = NULL;
170                       read_and_log_stderr (state, NULL);
171                       state->cont = 1;
172                     }
173                   else
174                     {
175                       memcpy (newbuffer, state->buffer, state->used);
176                       xfree (state->buffer);
177                       state->buffer = newbuffer;
178                       state->buffer_size = newsize;
179                     }
180                 }
181               else
182                 {
183                   read_and_log_stderr (state, NULL);
184                   state->cont = 1;
185                 }
186             }
187           state->buffer[state->used++] = c;
188         }
189     }
190 }
191
192 \f
193
194 /* A buffer to copy from one stream to another.  */
195 struct copy_buffer
196 {
197   char buffer[4096];
198   char *writep;
199   size_t nread;
200 };
201
202
203 /* Initialize a copy buffer.  */
204 static void
205 copy_buffer_init (struct copy_buffer *c)
206 {
207   c->writep = c->buffer;
208   c->nread = 0;
209 }
210
211
212 /* Securely wipe a copy buffer.  */
213 static void
214 copy_buffer_shred (struct copy_buffer *c)
215 {
216   wipememory (c->buffer, sizeof c->buffer);
217   c->writep = NULL;
218   c->nread = ~0U;
219 }
220
221
222 /* Copy data from SOURCE to SINK using copy buffer C.  */
223 static gpg_error_t
224 copy_buffer_do_copy (struct copy_buffer *c, estream_t source, estream_t sink)
225 {
226   gpg_error_t err;
227   size_t nwritten = 0;
228
229   if (c->nread == 0)
230     {
231       c->writep = c->buffer;
232       err = es_read (source, c->buffer, sizeof c->buffer, &c->nread);
233       if (err)
234         {
235           if (errno == EAGAIN)
236             return 0;   /* We will just retry next time.  */
237
238           return my_error_from_syserror ();
239         }
240
241       assert (c->nread <= sizeof c->buffer);
242     }
243
244   if (c->nread == 0)
245     return 0;   /* Done copying.  */
246
247
248   err = sink? es_write (sink, c->writep, c->nread, &nwritten) : 0;
249   if (err)
250     {
251       if (errno == EAGAIN)
252         return 0;       /* We will just retry next time.  */
253
254       return my_error_from_syserror ();
255     }
256
257   assert (nwritten <= c->nread);
258   c->writep += nwritten;
259   c->nread -= nwritten;
260   assert (c->writep - c->buffer <= sizeof c->buffer);
261
262   if (sink && es_fflush (sink) && errno != EAGAIN)
263     err = my_error_from_syserror ();
264
265   return err;
266 }
267
268
269 /* Flush the remaining data to SINK.  */
270 static gpg_error_t
271 copy_buffer_flush (struct copy_buffer *c, estream_t sink)
272 {
273   gpg_error_t err;
274
275   while (c->nread > 0)
276     {
277       err = copy_buffer_do_copy (c, NULL, sink);
278       if (err)
279         return err;
280     }
281
282   return 0;
283 }
284
285 \f
286
287 /* Run the program PGMNAME with the command line arguments given in
288  * the NULL terminates array ARGV.  If INPUT is not NULL it will be
289  * fed to stdin of the process.  stderr is logged using log_info and
290  * the process' stdout is written to OUTPUT.  If OUTPUT is NULL the
291  * output is discarded.  If INEXTRA is given, an additional input
292  * stream will be passed to the child; to tell the child about this
293  * ARGV is scanned and the first occurrence of an argument
294  * "-&@INEXTRA@" is replaced by the concatenation of "-&" and the
295  * child's file descriptor of the pipe created for the INEXTRA stream.
296  *
297  * On error a diagnostic is printed and an error code returned.  */
298 gpg_error_t
299 gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
300                         estream_t input, estream_t inextra,
301                         estream_t output,
302                         exec_tool_status_cb_t status_cb,
303                         void *status_cb_value)
304 {
305   gpg_error_t err;
306   pid_t pid;
307   estream_t infp = NULL;
308   estream_t extrafp = NULL;
309   estream_t outfp, errfp;
310   es_poll_t fds[4];
311   int exceptclose[2];
312   int extrapipe[2] = {-1, -1};
313   char extrafdbuf[20];
314   const char *argsave = NULL;
315   int argsaveidx;
316   int count;
317   read_and_log_buffer_t fderrstate;
318   struct copy_buffer cpbuf_in, cpbuf_out, cpbuf_extra; /* Fixme: malloc them. */
319
320   memset (fds, 0, sizeof fds);
321   memset (&fderrstate, 0, sizeof fderrstate);
322   copy_buffer_init (&cpbuf_in);
323   copy_buffer_init (&cpbuf_out);
324   copy_buffer_init (&cpbuf_extra);
325
326   fderrstate.pgmname = pgmname;
327   fderrstate.status_cb = status_cb;
328   fderrstate.status_cb_value = status_cb_value;
329   fderrstate.buffer_size = 256;
330   fderrstate.buffer = xtrymalloc (fderrstate.buffer_size);
331   if (!fderrstate.buffer)
332     return my_error_from_syserror ();
333
334   if (inextra)
335     {
336       err = gnupg_create_outbound_pipe (extrapipe, &extrafp, 1);
337       if (err)
338         {
339           log_error ("error running outbound pipe for extra fp: %s\n",
340                      gpg_strerror (err));
341           xfree (fderrstate.buffer);
342           return err;
343         }
344       exceptclose[0] = extrapipe[0]; /* Do not close in child. */
345       exceptclose[1] = -1;
346       /* Now find the argument marker and replace by the pipe's fd.
347          Yeah, that is an ugly non-thread safe hack but it safes us to
348          create a copy of the array.  */
349       snprintf (extrafdbuf, sizeof extrafdbuf, "-&%d", extrapipe[0]);
350       for (argsaveidx=0; argv[argsaveidx]; argsaveidx++)
351         if (!strcmp (argv[argsaveidx], "-&@INEXTRA@"))
352           {
353             argsave = argv[argsaveidx];
354             argv[argsaveidx] = extrafdbuf;
355             break;
356           }
357     }
358   else
359     exceptclose[0] = -1;
360
361   err = gnupg_spawn_process (pgmname, argv,
362                              exceptclose, NULL, GNUPG_SPAWN_NONBLOCK,
363                              input? &infp : NULL,
364                              &outfp, &errfp, &pid);
365   if (extrapipe[0] != -1)
366     close (extrapipe[0]);
367   if (argsave)
368     argv[argsaveidx] = argsave;
369   if (err)
370     {
371       log_error ("error running '%s': %s\n", pgmname, gpg_strerror (err));
372       es_fclose (extrafp);
373       xfree (fderrstate.buffer);
374       return err;
375     }
376
377   fds[0].stream = infp;
378   fds[0].want_write = 1;
379   if (!input)
380     fds[0].ignore = 1;
381   fds[1].stream = outfp;
382   fds[1].want_read = 1;
383   fds[2].stream = errfp;
384   fds[2].want_read = 1;
385   fds[3].stream = extrafp;
386   fds[3].want_write = 1;
387   if (!inextra)
388     fds[3].ignore = 1;
389
390   /* Now read as long as we have something to poll.  We continue
391      reading even after EOF or error on stdout so that we get the
392      other error messages or remaining outut.  */
393   while (! (fds[1].ignore && fds[2].ignore))
394     {
395       count = es_poll (fds, DIM(fds), -1);
396       if (count == -1)
397         {
398           err = my_error_from_syserror ();
399           log_error ("error polling '%s': %s\n", pgmname, gpg_strerror (err));
400           goto leave;
401         }
402       if (!count)
403         {
404           log_debug ("unexpected timeout while polling '%s'\n", pgmname);
405           break;
406         }
407
408       if (fds[0].got_write)
409         {
410           err = copy_buffer_do_copy (&cpbuf_in, input, fds[0].stream);
411           if (err)
412             {
413               log_error ("error feeding data to '%s': %s\n",
414                          pgmname, gpg_strerror (err));
415               goto leave;
416             }
417
418           if (es_feof (input))
419             {
420               err = copy_buffer_flush (&cpbuf_in, fds[0].stream);
421               if (err)
422                 {
423                   log_error ("error feeding data to '%s': %s\n",
424                              pgmname, gpg_strerror (err));
425                   goto leave;
426                 }
427
428               fds[0].ignore = 1; /* ready.  */
429               es_fclose (infp); infp = NULL;
430             }
431         }
432
433       if (fds[3].got_write)
434         {
435           log_assert (inextra);
436           err = copy_buffer_do_copy (&cpbuf_extra, inextra, fds[3].stream);
437           if (err)
438             {
439               log_error ("error feeding data to '%s': %s\n",
440                          pgmname, gpg_strerror (err));
441               goto leave;
442             }
443
444           if (es_feof (inextra))
445             {
446               err = copy_buffer_flush (&cpbuf_extra, fds[3].stream);
447               if (err)
448                 {
449                   log_error ("error feeding data to '%s': %s\n",
450                              pgmname, gpg_strerror (err));
451                   goto leave;
452                 }
453
454               fds[3].ignore = 1; /* ready.  */
455               es_fclose (extrafp); extrafp = NULL;
456             }
457         }
458
459       if (fds[1].got_read)
460         {
461           err = copy_buffer_do_copy (&cpbuf_out, fds[1].stream, output);
462           if (err)
463             {
464               log_error ("error reading data from '%s': %s\n",
465                          pgmname, gpg_strerror (err));
466               goto leave;
467             }
468
469           if (es_feof (fds[1].stream))
470             {
471               err = copy_buffer_flush (&cpbuf_out, output);
472               if (err)
473                 {
474                   log_error ("error reading data from '%s': %s\n",
475                              pgmname, gpg_strerror (err));
476                   goto leave;
477                 }
478
479               fds[1].ignore = 1; /* ready.  */
480             }
481         }
482
483       if (fds[2].got_read)
484         read_and_log_stderr (&fderrstate, fds + 2);
485     }
486
487   read_and_log_stderr (&fderrstate, NULL); /* Flush.  */
488   es_fclose (infp); infp = NULL;
489   es_fclose (extrafp); extrafp = NULL;
490   es_fclose (outfp); outfp = NULL;
491   es_fclose (errfp); errfp = NULL;
492
493   err = gnupg_wait_process (pgmname, pid, 1, NULL);
494   pid = (pid_t)(-1);
495
496  leave:
497   if (err)
498     gnupg_kill_process (pid);
499
500   es_fclose (infp);
501   es_fclose (extrafp);
502   es_fclose (outfp);
503   es_fclose (errfp);
504   if (pid != (pid_t)(-1))
505     gnupg_wait_process (pgmname, pid, 1, NULL);
506   gnupg_release_process (pid);
507
508   copy_buffer_shred (&cpbuf_in);
509   copy_buffer_shred (&cpbuf_out);
510   if (inextra)
511     copy_buffer_shred (&cpbuf_extra);
512   xfree (fderrstate.buffer);
513   return err;
514 }
515
516
517 /* A dummy free function to pass to 'es_mopen'.  */
518 static void
519 nop_free (void *ptr)
520 {
521   (void) ptr;
522 }
523
524 /* Run the program PGMNAME with the command line arguments given in
525    the NULL terminates array ARGV.  If INPUT_STRING is not NULL it
526    will be fed to stdin of the process.  stderr is logged using
527    log_info and the process' stdout is returned in a newly malloced
528    buffer RESULT with the length stored at RESULTLEN if not given as
529    NULL.  A hidden Nul is appended to the output.  On error NULL is
530    stored at RESULT, a diagnostic is printed, and an error code
531    returned.  */
532 gpg_error_t
533 gnupg_exec_tool (const char *pgmname, const char *argv[],
534                  const char *input_string,
535                  char **result, size_t *resultlen)
536 {
537   gpg_error_t err;
538   estream_t input = NULL;
539   estream_t output;
540   size_t len;
541   size_t nread;
542
543   *result = NULL;
544   if (resultlen)
545     *resultlen = 0;
546
547   if (input_string)
548     {
549       len = strlen (input_string);
550       input = es_mopen ((char *) input_string, len, len,
551                         0 /* don't grow */, NULL, nop_free, "rb");
552       if (! input)
553         return my_error_from_syserror ();
554     }
555
556   output = es_fopenmem (0, "wb");
557   if (! output)
558     {
559       err = my_error_from_syserror ();
560       goto leave;
561     }
562
563   err = gnupg_exec_tool_stream (pgmname, argv, input, NULL, output, NULL, NULL);
564   if (err)
565     goto leave;
566
567   len = es_ftello (output);
568   err = es_fseek (output, 0, SEEK_SET);
569   if (err)
570     goto leave;
571
572   *result = xtrymalloc (len + 1);
573   if (!*result)
574     {
575       err = my_error_from_syserror ();
576       goto leave;
577     }
578
579   if (len)
580     {
581       err = es_read (output, *result, len, &nread);
582       if (err)
583         goto leave;
584       if (nread != len)
585         log_fatal ("%s: short read from memstream\n", __func__);
586     }
587   (*result)[len] = 0;
588
589   if (resultlen)
590     *resultlen = len;
591
592  leave:
593   es_fclose (input);
594   es_fclose (output);
595   if (err)
596     {
597       xfree (*result);
598       *result = NULL;
599     }
600   return err;
601 }