core: Check for GPG_TTY as well as DISPLAY.
[gpgme.git] / src / engine-gpg.c
1 /* engine-gpg.c - Gpg Engine.
2    Copyright (C) 2000 Werner Koch (dd9jn)
3    Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007,
4                  2009, 2010, 2012, 2013 g10 Code GmbH
5
6    This file is part of GPGME.
7
8    GPGME is free software; you can redistribute it and/or modify it
9    under the terms of the GNU Lesser General Public License as
10    published by the Free Software Foundation; either version 2.1 of
11    the License, or (at your option) any later version.
12
13    GPGME is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    Lesser General Public License for more details.
17
18    You should have received a copy of the GNU Lesser General Public
19    License along with this program; if not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #if HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <assert.h>
29 #include <errno.h>
30 #ifdef HAVE_UNISTD_H
31 # include <unistd.h>
32 #endif
33 #ifdef HAVE_LOCALE_H
34 #include <locale.h>
35 #endif
36
37 #include "gpgme.h"
38 #include "util.h"
39 #include "ops.h"
40 #include "wait.h"
41 #include "context.h"  /*temp hack until we have GpmeData methods to do I/O */
42 #include "priv-io.h"
43 #include "sema.h"
44 #include "debug.h"
45 #include "data.h"
46
47 #include "engine-backend.h"
48
49
50 /* This type is used to build a list of gpg arguments and data
51    sources/sinks.  */
52 struct arg_and_data_s
53 {
54   struct arg_and_data_s *next;
55   gpgme_data_t data;  /* If this is not NULL, use arg below.  */
56   int inbound;     /* True if this is used for reading from gpg.  */
57   int dup_to;
58   int print_fd;    /* Print the fd number and not the special form of it.  */
59   int *arg_locp;   /* Write back the argv idx of this argument when
60                       building command line to this location.  */
61   char arg[1];     /* Used if data above is not used.  */
62 };
63
64
65 struct fd_data_map_s
66 {
67   gpgme_data_t data;
68   int inbound;  /* true if this is used for reading from gpg */
69   int dup_to;
70   int fd;       /* the fd to use */
71   int peer_fd;  /* the other side of the pipe */
72   int arg_loc;  /* The index into the argv for translation purposes.  */
73   void *tag;
74 };
75
76
77 typedef gpgme_error_t (*colon_preprocessor_t) (char *line, char **rline);
78
79 struct engine_gpg
80 {
81   char *file_name;
82   char *version;
83
84   char *lc_messages;
85   char *lc_ctype;
86
87   struct arg_and_data_s *arglist;
88   struct arg_and_data_s **argtail;
89
90   struct
91   {
92     int fd[2];
93     int arg_loc;
94     size_t bufsize;
95     char *buffer;
96     size_t readpos;
97     int eof;
98     engine_status_handler_t fnc;
99     void *fnc_value;
100     gpgme_status_cb_t mon_cb;
101     void *mon_cb_value;
102     void *tag;
103   } status;
104
105   /* This is a kludge - see the comment at colon_line_handler.  */
106   struct
107   {
108     int fd[2];
109     int arg_loc;
110     size_t bufsize;
111     char *buffer;
112     size_t readpos;
113     int eof;
114     engine_colon_line_handler_t fnc;  /* this indicate use of this structrue */
115     void *fnc_value;
116     void *tag;
117     colon_preprocessor_t preprocess_fnc;
118   } colon;
119
120   char **argv;
121   struct fd_data_map_s *fd_data_map;
122
123   /* stuff needed for interactive (command) mode */
124   struct
125   {
126     int used;
127     int fd;
128     void *cb_data;
129     int idx;            /* Index in fd_data_map */
130     gpgme_status_code_t code;  /* last code */
131     char *keyword;       /* what has been requested (malloced) */
132     engine_command_handler_t fnc;
133     void *fnc_value;
134     /* The kludges never end.  This is used to couple command handlers
135        with output data in edit key mode.  */
136     gpgme_data_t linked_data;
137     int linked_idx;
138   } cmd;
139
140   struct gpgme_io_cbs io_cbs;
141   gpgme_pinentry_mode_t pinentry_mode;
142 };
143
144 typedef struct engine_gpg *engine_gpg_t;
145
146 \f
147 static void
148 gpg_io_event (void *engine, gpgme_event_io_t type, void *type_data)
149 {
150   engine_gpg_t gpg = engine;
151
152   TRACE3 (DEBUG_ENGINE, "gpgme:gpg_io_event", gpg,
153           "event %p, type %d, type_data %p",
154           gpg->io_cbs.event, type, type_data);
155   if (gpg->io_cbs.event)
156     (*gpg->io_cbs.event) (gpg->io_cbs.event_priv, type, type_data);
157 }
158
159
160 static void
161 close_notify_handler (int fd, void *opaque)
162 {
163   engine_gpg_t gpg = opaque;
164   assert (fd != -1);
165
166   if (gpg->status.fd[0] == fd)
167     {
168       if (gpg->status.tag)
169         (*gpg->io_cbs.remove) (gpg->status.tag);
170       gpg->status.fd[0] = -1;
171     }
172   else if (gpg->status.fd[1] == fd)
173     gpg->status.fd[1] = -1;
174   else if (gpg->colon.fd[0] == fd)
175     {
176       if (gpg->colon.tag)
177         (*gpg->io_cbs.remove) (gpg->colon.tag);
178       gpg->colon.fd[0] = -1;
179     }
180   else if (gpg->colon.fd[1] == fd)
181     gpg->colon.fd[1] = -1;
182   else if (gpg->cmd.fd == fd)
183     gpg->cmd.fd = -1;
184   else if (gpg->fd_data_map)
185     {
186       int i;
187
188       for (i = 0; gpg->fd_data_map[i].data; i++)
189         {
190           if (gpg->fd_data_map[i].fd == fd)
191             {
192               if (gpg->fd_data_map[i].tag)
193                 (*gpg->io_cbs.remove) (gpg->fd_data_map[i].tag);
194               gpg->fd_data_map[i].fd = -1;
195               break;
196             }
197           if (gpg->fd_data_map[i].peer_fd == fd)
198             {
199               gpg->fd_data_map[i].peer_fd = -1;
200               break;
201             }
202         }
203     }
204 }
205
206 /* If FRONT is true, push at the front of the list.  Use this for
207    options added late in the process.  */
208 static gpgme_error_t
209 _add_arg (engine_gpg_t gpg, const char *prefix, const char *arg, size_t arglen,
210           int front, int *arg_locp)
211 {
212   struct arg_and_data_s *a;
213   size_t prefixlen = prefix? strlen (prefix) : 0;
214
215   assert (gpg);
216   assert (arg);
217
218   a = malloc (sizeof *a + prefixlen + arglen);
219   if (!a)
220     return gpg_error_from_syserror ();
221
222   a->data = NULL;
223   a->dup_to = -1;
224   a->arg_locp = arg_locp;
225
226   if (prefixlen)
227     memcpy (a->arg, prefix, prefixlen);
228   memcpy (a->arg + prefixlen, arg, arglen);
229   a->arg[prefixlen + arglen] = 0;
230   if (front)
231     {
232       a->next = gpg->arglist;
233       if (!gpg->arglist)
234         {
235           /* If this is the first argument, we need to update the tail
236              pointer.  */
237           gpg->argtail = &a->next;
238         }
239       gpg->arglist = a;
240     }
241   else
242     {
243       a->next = NULL;
244       *gpg->argtail = a;
245       gpg->argtail = &a->next;
246     }
247
248   return 0;
249 }
250
251
252 static gpgme_error_t
253 add_arg_ext (engine_gpg_t gpg, const char *arg, int front)
254 {
255   return _add_arg (gpg, NULL, arg, strlen (arg), front, NULL);
256 }
257
258 static gpgme_error_t
259 add_arg_with_locp (engine_gpg_t gpg, const char *arg, int *locp)
260 {
261   return _add_arg (gpg, NULL, arg, strlen (arg), 0, locp);
262 }
263
264 static gpgme_error_t
265 add_arg (engine_gpg_t gpg, const char *arg)
266 {
267   return _add_arg (gpg, NULL, arg, strlen (arg), 0, NULL);
268 }
269
270 static gpgme_error_t
271 add_arg_pfx (engine_gpg_t gpg, const char *prefix, const char *arg)
272 {
273   return _add_arg (gpg, prefix, arg, strlen (arg), 0, NULL);
274 }
275
276 static gpgme_error_t
277 add_arg_len (engine_gpg_t gpg, const char *prefix,
278              const char *arg, size_t arglen)
279 {
280   return _add_arg (gpg, prefix, arg, arglen, 0, NULL);
281 }
282
283
284 static gpgme_error_t
285 add_data (engine_gpg_t gpg, gpgme_data_t data, int dup_to, int inbound)
286 {
287   struct arg_and_data_s *a;
288
289   assert (gpg);
290   assert (data);
291
292   a = malloc (sizeof *a - 1);
293   if (!a)
294     return gpg_error_from_syserror ();
295   a->next = NULL;
296   a->data = data;
297   a->inbound = inbound;
298   a->arg_locp = NULL;
299
300   if (dup_to == -2)
301     {
302       a->print_fd = 1;
303       a->dup_to = -1;
304     }
305   else
306     {
307       a->print_fd = 0;
308       a->dup_to = dup_to;
309     }
310   *gpg->argtail = a;
311   gpg->argtail = &a->next;
312   return 0;
313 }
314
315
316 /* Return true if the engine's version is at least VERSION.  */
317 static int
318 have_gpg_version (engine_gpg_t gpg, const char *version)
319 {
320   return _gpgme_compare_versions (gpg->version, version);
321 }
322
323
324 \f
325 static char *
326 gpg_get_version (const char *file_name)
327 {
328   return _gpgme_get_program_version (file_name ? file_name
329                                      : _gpgme_get_default_gpg_name ());
330 }
331
332
333 static const char *
334 gpg_get_req_version (void)
335 {
336   return "1.4.0";
337 }
338
339
340 static void
341 free_argv (char **argv)
342 {
343   int i;
344
345   for (i = 0; argv[i]; i++)
346     free (argv[i]);
347   free (argv);
348 }
349
350
351 static void
352 free_fd_data_map (struct fd_data_map_s *fd_data_map)
353 {
354   int i;
355
356   if (!fd_data_map)
357     return;
358
359   for (i = 0; fd_data_map[i].data; i++)
360     {
361       if (fd_data_map[i].fd != -1)
362         _gpgme_io_close (fd_data_map[i].fd);
363       if (fd_data_map[i].peer_fd != -1)
364         _gpgme_io_close (fd_data_map[i].peer_fd);
365       /* Don't release data because this is only a reference.  */
366     }
367   free (fd_data_map);
368 }
369
370
371 static gpgme_error_t
372 gpg_cancel (void *engine)
373 {
374   engine_gpg_t gpg = engine;
375
376   if (!gpg)
377     return gpg_error (GPG_ERR_INV_VALUE);
378
379   /* If gpg may be waiting for a cmd, close the cmd fd first.  On
380      Windows, close operations block on the reader/writer thread.  */
381   if (gpg->cmd.used)
382     {
383       if (gpg->cmd.fd != -1)
384         _gpgme_io_close (gpg->cmd.fd);
385       else if (gpg->fd_data_map
386                && gpg->fd_data_map[gpg->cmd.idx].fd != -1)
387         _gpgme_io_close (gpg->fd_data_map[gpg->cmd.idx].fd);
388     }
389
390   if (gpg->status.fd[0] != -1)
391     _gpgme_io_close (gpg->status.fd[0]);
392   if (gpg->status.fd[1] != -1)
393     _gpgme_io_close (gpg->status.fd[1]);
394   if (gpg->colon.fd[0] != -1)
395     _gpgme_io_close (gpg->colon.fd[0]);
396   if (gpg->colon.fd[1] != -1)
397     _gpgme_io_close (gpg->colon.fd[1]);
398   if (gpg->fd_data_map)
399     {
400       free_fd_data_map (gpg->fd_data_map);
401       gpg->fd_data_map = NULL;
402     }
403
404   return 0;
405 }
406
407 static void
408 gpg_release (void *engine)
409 {
410   engine_gpg_t gpg = engine;
411
412   if (!gpg)
413     return;
414
415   gpg_cancel (engine);
416
417   if (gpg->file_name)
418     free (gpg->file_name);
419   if (gpg->version)
420     free (gpg->version);
421
422   if (gpg->lc_messages)
423     free (gpg->lc_messages);
424   if (gpg->lc_ctype)
425     free (gpg->lc_ctype);
426
427   while (gpg->arglist)
428     {
429       struct arg_and_data_s *next = gpg->arglist->next;
430
431       free (gpg->arglist);
432       gpg->arglist = next;
433     }
434
435   if (gpg->status.buffer)
436     free (gpg->status.buffer);
437   if (gpg->colon.buffer)
438     free (gpg->colon.buffer);
439   if (gpg->argv)
440     free_argv (gpg->argv);
441   if (gpg->cmd.keyword)
442     free (gpg->cmd.keyword);
443
444   free (gpg);
445 }
446
447
448 static gpgme_error_t
449 gpg_new (void **engine, const char *file_name, const char *home_dir,
450          const char *version)
451 {
452   engine_gpg_t gpg;
453   gpgme_error_t rc = 0;
454   char *dft_display = NULL;
455   char dft_ttyname[64];
456   char *dft_ttytype = NULL;
457   char *env_tty = NULL;
458
459   gpg = calloc (1, sizeof *gpg);
460   if (!gpg)
461     return gpg_error_from_syserror ();
462
463   if (file_name)
464     {
465       gpg->file_name = strdup (file_name);
466       if (!gpg->file_name)
467         {
468           rc = gpg_error_from_syserror ();
469           goto leave;
470         }
471     }
472
473   if (version)
474     {
475       gpg->version = strdup (version);
476       if (!gpg->version)
477         {
478           rc = gpg_error_from_syserror ();
479           goto leave;
480         }
481     }
482
483   gpg->argtail = &gpg->arglist;
484   gpg->status.fd[0] = -1;
485   gpg->status.fd[1] = -1;
486   gpg->colon.fd[0] = -1;
487   gpg->colon.fd[1] = -1;
488   gpg->cmd.fd = -1;
489   gpg->cmd.idx = -1;
490   gpg->cmd.linked_data = NULL;
491   gpg->cmd.linked_idx = -1;
492
493   /* Allocate the read buffer for the status pipe.  */
494   gpg->status.bufsize = 1024;
495   gpg->status.readpos = 0;
496   gpg->status.buffer = malloc (gpg->status.bufsize);
497   if (!gpg->status.buffer)
498     {
499       rc = gpg_error_from_syserror ();
500       goto leave;
501     }
502   /* In any case we need a status pipe - create it right here and
503      don't handle it with our generic gpgme_data_t mechanism.  */
504   if (_gpgme_io_pipe (gpg->status.fd, 1) == -1)
505     {
506       rc = gpg_error_from_syserror ();
507       goto leave;
508     }
509   if (_gpgme_io_set_close_notify (gpg->status.fd[0],
510                                   close_notify_handler, gpg)
511       || _gpgme_io_set_close_notify (gpg->status.fd[1],
512                                      close_notify_handler, gpg))
513     {
514       rc = gpg_error (GPG_ERR_GENERAL);
515       goto leave;
516     }
517   gpg->status.eof = 0;
518
519   if (home_dir)
520     {
521       rc = add_arg (gpg, "--homedir");
522       if (!rc)
523         rc = add_arg (gpg, home_dir);
524       if (rc)
525         goto leave;
526     }
527
528   rc = add_arg (gpg, "--status-fd");
529   if (rc)
530     goto leave;
531
532   {
533     char buf[25];
534     _gpgme_io_fd2str (buf, sizeof (buf), gpg->status.fd[1]);
535     rc = add_arg_with_locp (gpg, buf, &gpg->status.arg_loc);
536     if (rc)
537       goto leave;
538   }
539
540   rc = add_arg (gpg, "--no-tty");
541   if (!rc)
542     rc = add_arg (gpg, "--charset");
543   if (!rc)
544     rc = add_arg (gpg, "utf8");
545   if (!rc)
546     rc = add_arg (gpg, "--enable-progress-filter");
547   if (rc)
548     goto leave;
549
550   rc = _gpgme_getenv ("DISPLAY", &dft_display);
551   if (rc)
552     goto leave;
553   if (dft_display)
554     {
555       rc = add_arg (gpg, "--display");
556       if (!rc)
557         rc = add_arg (gpg, dft_display);
558
559       free (dft_display);
560       if (rc)
561         goto leave;
562     }
563
564   rc = _gpgme_getenv ("GPG_TTY", &env_tty);
565   if (isatty (1) || env_tty || rc)
566     {
567       int err = 0;
568
569       if (rc)
570         goto leave;
571       else if (env_tty)
572         {
573           snprintf (dft_ttyname, sizeof (dft_ttyname), "%s", env_tty);
574           free (env_tty);
575         }
576       else
577         err = ttyname_r (1, dft_ttyname, sizeof (dft_ttyname));
578
579       /* Even though isatty() returns 1, ttyname_r() may fail in many
580          ways, e.g., when /dev/pts is not accessible under chroot.  */
581       if (!err)
582         {
583           if (*dft_ttyname)
584             {
585               rc = add_arg (gpg, "--ttyname");
586               if (!rc)
587                 rc = add_arg (gpg, dft_ttyname);
588             }
589           else
590             rc = 0;
591           if (!rc)
592             {
593               rc = _gpgme_getenv ("TERM", &dft_ttytype);
594               if (rc)
595                 goto leave;
596
597               if (dft_ttytype)
598                 {
599                   rc = add_arg (gpg, "--ttytype");
600                   if (!rc)
601                     rc = add_arg (gpg, dft_ttytype);
602                 }
603
604               free (dft_ttytype);
605             }
606           if (rc)
607             goto leave;
608         }
609     }
610
611  leave:
612   if (rc)
613     gpg_release (gpg);
614   else
615     *engine = gpg;
616   return rc;
617 }
618
619
620 static gpgme_error_t
621 gpg_set_locale (void *engine, int category, const char *value)
622 {
623   engine_gpg_t gpg = engine;
624
625   if (0)
626     ;
627 #ifdef LC_CTYPE
628   else if (category == LC_CTYPE)
629     {
630       if (gpg->lc_ctype)
631         {
632           free (gpg->lc_ctype);
633           gpg->lc_ctype = NULL;
634         }
635       if (value)
636         {
637           gpg->lc_ctype = strdup (value);
638           if (!gpg->lc_ctype)
639             return gpg_error_from_syserror ();
640         }
641     }
642 #endif
643 #ifdef LC_MESSAGES
644   else if (category == LC_MESSAGES)
645     {
646       if (gpg->lc_messages)
647         {
648           free (gpg->lc_messages);
649           gpg->lc_messages = NULL;
650         }
651       if (value)
652         {
653           gpg->lc_messages = strdup (value);
654           if (!gpg->lc_messages)
655             return gpg_error_from_syserror ();
656         }
657     }
658 #endif /* LC_MESSAGES */
659   else
660     return gpg_error (GPG_ERR_INV_VALUE);
661
662   return 0;
663 }
664
665 /* This sets a status callback for monitoring status lines before they
666  * are passed to a caller set handler.  */
667 static void
668 gpg_set_status_cb (void *engine, gpgme_status_cb_t cb, void *cb_value)
669 {
670   engine_gpg_t gpg = engine;
671
672   gpg->status.mon_cb = cb;
673   gpg->status.mon_cb_value = cb_value;
674 }
675
676
677 /* Note, that the status_handler is allowed to modifiy the args
678    value.  */
679 static void
680 gpg_set_status_handler (void *engine, engine_status_handler_t fnc,
681                         void *fnc_value)
682 {
683   engine_gpg_t gpg = engine;
684
685   gpg->status.fnc = fnc;
686   gpg->status.fnc_value = fnc_value;
687 }
688
689 /* Kludge to process --with-colon output.  */
690 static gpgme_error_t
691 gpg_set_colon_line_handler (void *engine, engine_colon_line_handler_t fnc,
692                             void *fnc_value)
693 {
694   engine_gpg_t gpg = engine;
695
696   gpg->colon.bufsize = 1024;
697   gpg->colon.readpos = 0;
698   gpg->colon.buffer = malloc (gpg->colon.bufsize);
699   if (!gpg->colon.buffer)
700     return gpg_error_from_syserror ();
701
702   if (_gpgme_io_pipe (gpg->colon.fd, 1) == -1)
703     {
704       int saved_err = gpg_error_from_syserror ();
705       free (gpg->colon.buffer);
706       gpg->colon.buffer = NULL;
707       return saved_err;
708     }
709   if (_gpgme_io_set_close_notify (gpg->colon.fd[0], close_notify_handler, gpg)
710       || _gpgme_io_set_close_notify (gpg->colon.fd[1],
711                                      close_notify_handler, gpg))
712     return gpg_error (GPG_ERR_GENERAL);
713   gpg->colon.eof = 0;
714   gpg->colon.fnc = fnc;
715   gpg->colon.fnc_value = fnc_value;
716   return 0;
717 }
718
719
720 static gpgme_error_t
721 command_handler (void *opaque, int fd)
722 {
723   struct io_cb_data *data = (struct io_cb_data *) opaque;
724   engine_gpg_t gpg = (engine_gpg_t) data->handler_value;
725   gpgme_error_t err;
726   int processed = 0;
727   assert (gpg->cmd.used);
728   assert (gpg->cmd.code);
729   assert (gpg->cmd.fnc);
730
731   err = gpg->cmd.fnc (gpg->cmd.fnc_value, gpg->cmd.code, gpg->cmd.keyword, fd,
732                       &processed);
733
734   gpg->cmd.code = 0;
735   /* And sleep again until read_status will wake us up again.  */
736   /* XXX We must check if there are any more fds active after removing
737      this one.  */
738   (*gpg->io_cbs.remove) (gpg->fd_data_map[gpg->cmd.idx].tag);
739   gpg->cmd.fd = gpg->fd_data_map[gpg->cmd.idx].fd;
740   gpg->fd_data_map[gpg->cmd.idx].fd = -1;
741
742   if (err)
743     return err;
744
745   /* We always need to send at least a newline character.  */
746   if (!processed)
747     _gpgme_io_write (fd, "\n", 1);
748
749   return 0;
750 }
751
752
753
754 /* The Fnc will be called to get a value for one of the commands with
755    a key KEY.  If the Code passed to FNC is 0, the function may release
756    resources associated with the returned value from another call.  To
757    match such a second call to a first call, the returned value from
758    the first call is passed as keyword.  */
759 static gpgme_error_t
760 gpg_set_command_handler (void *engine, engine_command_handler_t fnc,
761                          void *fnc_value, gpgme_data_t linked_data)
762 {
763   engine_gpg_t gpg = engine;
764   gpgme_error_t rc;
765
766   rc = add_arg (gpg, "--command-fd");
767   if (rc)
768     return rc;
769
770   /* This is a hack.  We don't have a real data object.  The only
771      thing that matters is that we use something unique, so we use the
772      address of the cmd structure in the gpg object.  */
773   rc = add_data (gpg, (void *) &gpg->cmd, -2, 0);
774   if (rc)
775     return rc;
776
777   gpg->cmd.fnc = fnc;
778   gpg->cmd.cb_data = (void *) &gpg->cmd;
779   gpg->cmd.fnc_value = fnc_value;
780   gpg->cmd.linked_data = linked_data;
781   gpg->cmd.used = 1;
782   return 0;
783 }
784
785
786 static gpgme_error_t
787 build_argv (engine_gpg_t gpg, const char *pgmname)
788 {
789   gpgme_error_t err;
790   struct arg_and_data_s *a;
791   struct fd_data_map_s *fd_data_map;
792   size_t datac=0, argc=0;
793   char **argv;
794   int need_special = 0;
795   int use_agent = 0;
796   char *p;
797
798   if (_gpgme_in_gpg_one_mode ())
799     {
800       /* In GnuPG-1 mode we don't want to use the agent with a
801          malformed environment variable.  This is only a very basic
802          test but sufficient to make our life in the regression tests
803          easier.  With GnuPG-2 the agent is anyway required and on
804          modern installations GPG_AGENT_INFO is optional.  */
805       err = _gpgme_getenv ("GPG_AGENT_INFO", &p);
806       if (err)
807         return err;
808       use_agent = (p && strchr (p, ':'));
809       if (p)
810         free (p);
811     }
812
813   if (gpg->argv)
814     {
815       free_argv (gpg->argv);
816       gpg->argv = NULL;
817     }
818   if (gpg->fd_data_map)
819     {
820       free_fd_data_map (gpg->fd_data_map);
821       gpg->fd_data_map = NULL;
822     }
823
824   argc++;       /* For argv[0].  */
825   for (a = gpg->arglist; a; a = a->next)
826     {
827       argc++;
828       if (a->data)
829         {
830           /*fprintf (stderr, "build_argv: data\n" );*/
831           datac++;
832           if (a->dup_to == -1 && !a->print_fd)
833             need_special = 1;
834         }
835       else
836         {
837           /*   fprintf (stderr, "build_argv: arg=`%s'\n", a->arg );*/
838         }
839     }
840   if (need_special)
841     argc++;
842   if (use_agent)
843     argc++;
844   if (gpg->pinentry_mode)
845     argc++;
846   if (!gpg->cmd.used)
847     argc++;     /* --batch */
848   argc += 1;    /* --no-sk-comments */
849
850   argv = calloc (argc + 1, sizeof *argv);
851   if (!argv)
852     return gpg_error_from_syserror ();
853   fd_data_map = calloc (datac + 1, sizeof *fd_data_map);
854   if (!fd_data_map)
855     {
856       int saved_err = gpg_error_from_syserror ();
857       free_argv (argv);
858       return saved_err;
859     }
860
861   argc = datac = 0;
862   argv[argc] = strdup (_gpgme_get_basename (pgmname)); /* argv[0] */
863   if (!argv[argc])
864     {
865       int saved_err = gpg_error_from_syserror ();
866       free (fd_data_map);
867       free_argv (argv);
868       return saved_err;
869     }
870   argc++;
871   if (need_special)
872     {
873       argv[argc] = strdup ("--enable-special-filenames");
874       if (!argv[argc])
875         {
876           int saved_err = gpg_error_from_syserror ();
877           free (fd_data_map);
878           free_argv (argv);
879           return saved_err;
880         }
881       argc++;
882     }
883   if (use_agent)
884     {
885       argv[argc] = strdup ("--use-agent");
886       if (!argv[argc])
887         {
888           int saved_err = gpg_error_from_syserror ();
889           free (fd_data_map);
890           free_argv (argv);
891           return saved_err;
892         }
893       argc++;
894     }
895
896   if (gpg->pinentry_mode && have_gpg_version (gpg, "2.1.0"))
897     {
898       const char *s = NULL;
899       switch (gpg->pinentry_mode)
900         {
901         case GPGME_PINENTRY_MODE_DEFAULT: break;
902         case GPGME_PINENTRY_MODE_ASK:     s = "--pinentry-mode=ask"; break;
903         case GPGME_PINENTRY_MODE_CANCEL:  s = "--pinentry-mode=cancel"; break;
904         case GPGME_PINENTRY_MODE_ERROR:   s = "--pinentry-mode=error"; break;
905         case GPGME_PINENTRY_MODE_LOOPBACK:s = "--pinentry-mode=loopback"; break;
906         }
907       if (s)
908         {
909           argv[argc] = strdup (s);
910           if (!argv[argc])
911             {
912               int saved_err = gpg_error_from_syserror ();
913               free (fd_data_map);
914               free_argv (argv);
915               return saved_err;
916             }
917           argc++;
918         }
919     }
920
921   if (!gpg->cmd.used)
922     {
923       argv[argc] = strdup ("--batch");
924       if (!argv[argc])
925         {
926           int saved_err = gpg_error_from_syserror ();
927           free (fd_data_map);
928           free_argv (argv);
929           return saved_err;
930         }
931       argc++;
932     }
933   argv[argc] = strdup ("--no-sk-comments");
934   if (!argv[argc])
935     {
936       int saved_err = gpg_error_from_syserror ();
937       free (fd_data_map);
938       free_argv (argv);
939       return saved_err;
940     }
941   argc++;
942   for (a = gpg->arglist; a; a = a->next)
943     {
944       if (a->arg_locp)
945         *(a->arg_locp) = argc;
946
947       if (a->data)
948         {
949           /* Create a pipe to pass it down to gpg.  */
950           fd_data_map[datac].inbound = a->inbound;
951
952           /* Create a pipe.  */
953           {
954             int fds[2];
955
956             if (_gpgme_io_pipe (fds, fd_data_map[datac].inbound ? 1 : 0)
957                 == -1)
958               {
959                 int saved_errno = errno;
960                 free (fd_data_map);
961                 free_argv (argv);
962                 return gpg_error (saved_errno);
963               }
964             if (_gpgme_io_set_close_notify (fds[0],
965                                             close_notify_handler, gpg)
966                 || _gpgme_io_set_close_notify (fds[1],
967                                                close_notify_handler,
968                                                gpg))
969               {
970                 /* We leak fd_data_map and the fds.  This is not easy
971                    to avoid and given that we reach this here only
972                    after a malloc failure for a small object, it is
973                    probably better not to do anything.  */
974                 return gpg_error (GPG_ERR_GENERAL);
975               }
976             /* If the data_type is FD, we have to do a dup2 here.  */
977             if (fd_data_map[datac].inbound)
978               {
979                 fd_data_map[datac].fd       = fds[0];
980                 fd_data_map[datac].peer_fd  = fds[1];
981               }
982             else
983               {
984                 fd_data_map[datac].fd       = fds[1];
985                 fd_data_map[datac].peer_fd  = fds[0];
986               }
987           }
988
989           /* Hack to get hands on the fd later.  */
990           if (gpg->cmd.used)
991             {
992               if (gpg->cmd.cb_data == a->data)
993                 {
994                   assert (gpg->cmd.idx == -1);
995                   gpg->cmd.idx = datac;
996                 }
997               else if (gpg->cmd.linked_data == a->data)
998                 {
999                   assert (gpg->cmd.linked_idx == -1);
1000                   gpg->cmd.linked_idx = datac;
1001                 }
1002             }
1003
1004           fd_data_map[datac].data = a->data;
1005           fd_data_map[datac].dup_to = a->dup_to;
1006
1007           if (a->dup_to == -1)
1008             {
1009               char *ptr;
1010               int buflen = 25;
1011
1012               argv[argc] = malloc (buflen);
1013               if (!argv[argc])
1014                 {
1015                   int saved_err = gpg_error_from_syserror ();
1016                   free (fd_data_map);
1017                   free_argv (argv);
1018                   return saved_err;
1019                 }
1020
1021               ptr = argv[argc];
1022               if (!a->print_fd)
1023                 {
1024                   *(ptr++) = '-';
1025                   *(ptr++) = '&';
1026                   buflen -= 2;
1027                 }
1028
1029               _gpgme_io_fd2str (ptr, buflen, fd_data_map[datac].peer_fd);
1030               fd_data_map[datac].arg_loc = argc;
1031               argc++;
1032             }
1033           datac++;
1034         }
1035       else
1036         {
1037           argv[argc] = strdup (a->arg);
1038           if (!argv[argc])
1039             {
1040               int saved_err = gpg_error_from_syserror ();
1041               free (fd_data_map);
1042               free_argv (argv);
1043               return saved_err;
1044             }
1045             argc++;
1046         }
1047     }
1048
1049   gpg->argv = argv;
1050   gpg->fd_data_map = fd_data_map;
1051   return 0;
1052 }
1053
1054
1055 static gpgme_error_t
1056 add_io_cb (engine_gpg_t gpg, int fd, int dir, gpgme_io_cb_t handler, void *data,
1057            void **tag)
1058 {
1059   gpgme_error_t err;
1060
1061   err = (*gpg->io_cbs.add) (gpg->io_cbs.add_priv, fd, dir, handler, data, tag);
1062   if (err)
1063     return err;
1064   if (!dir)
1065     /* FIXME Kludge around poll() problem.  */
1066     err = _gpgme_io_set_nonblocking (fd);
1067   return err;
1068 }
1069
1070
1071 /* Handle the status output of GnuPG.  This function does read entire
1072    lines and passes them as C strings to the callback function (we can
1073    use C Strings because the status output is always UTF-8 encoded).
1074    Of course we have to buffer the lines to cope with long lines
1075    e.g. with a large user ID.  Note: We can optimize this to only cope
1076    with status line code we know about and skip all other stuff
1077    without buffering (i.e. without extending the buffer).  */
1078 static gpgme_error_t
1079 read_status (engine_gpg_t gpg)
1080 {
1081   char *p;
1082   int nread;
1083   size_t bufsize = gpg->status.bufsize;
1084   char *buffer = gpg->status.buffer;
1085   size_t readpos = gpg->status.readpos;
1086   gpgme_error_t err;
1087
1088   assert (buffer);
1089   if (bufsize - readpos < 256)
1090     {
1091       /* Need more room for the read.  */
1092       bufsize += 1024;
1093       buffer = realloc (buffer, bufsize);
1094       if (!buffer)
1095         return gpg_error_from_syserror ();
1096     }
1097
1098   nread = _gpgme_io_read (gpg->status.fd[0],
1099                           buffer + readpos, bufsize-readpos);
1100   if (nread == -1)
1101     return gpg_error_from_syserror ();
1102
1103   if (!nread)
1104     {
1105       err = 0;
1106       gpg->status.eof = 1;
1107       if (gpg->status.mon_cb)
1108         err = gpg->status.mon_cb (gpg->status.mon_cb_value, "", "");
1109       if (gpg->status.fnc)
1110         {
1111           char emptystring[1] = {0};
1112           err = gpg->status.fnc (gpg->status.fnc_value,
1113                                  GPGME_STATUS_EOF, emptystring);
1114           if (gpg_err_code (err) == GPG_ERR_FALSE)
1115             err = 0; /* Drop special error code.  */
1116         }
1117
1118       return err;
1119     }
1120
1121   while (nread > 0)
1122     {
1123       for (p = buffer + readpos; nread; nread--, p++)
1124         {
1125           if (*p == '\n')
1126             {
1127               /* (we require that the last line is terminated by a LF) */
1128               if (p > buffer && p[-1] == '\r')
1129                 p[-1] = 0;
1130               *p = 0;
1131               if (!strncmp (buffer, "[GNUPG:] ", 9)
1132                   && buffer[9] >= 'A' && buffer[9] <= 'Z')
1133                 {
1134                   char *rest;
1135                   gpgme_status_code_t r;
1136
1137                   rest = strchr (buffer + 9, ' ');
1138                   if (!rest)
1139                     rest = p; /* Set to an empty string.  */
1140                   else
1141                     *rest++ = 0;
1142
1143                   r = _gpgme_parse_status (buffer + 9);
1144                   if (gpg->status.mon_cb && r != GPGME_STATUS_PROGRESS)
1145                     {
1146                       /* Note that we call the monitor even if we do
1147                        * not know the status code (r < 0).  */
1148                       err = gpg->status.mon_cb (gpg->status.mon_cb_value,
1149                                                 buffer + 9, rest);
1150                       if (err)
1151                         return err;
1152                     }
1153                   if (r >= 0)
1154                     {
1155                       if (gpg->cmd.used
1156                           && (r == GPGME_STATUS_GET_BOOL
1157                               || r == GPGME_STATUS_GET_LINE
1158                               || r == GPGME_STATUS_GET_HIDDEN))
1159                         {
1160                           gpg->cmd.code = r;
1161                           if (gpg->cmd.keyword)
1162                             free (gpg->cmd.keyword);
1163                           gpg->cmd.keyword = strdup (rest);
1164                           if (!gpg->cmd.keyword)
1165                             return gpg_error_from_syserror ();
1166                           /* This should be the last thing we have
1167                              received and the next thing will be that
1168                              the command handler does its action.  */
1169                           if (nread > 1)
1170                             TRACE0 (DEBUG_CTX, "gpgme:read_status", 0,
1171                                     "error: unexpected data");
1172
1173                           add_io_cb (gpg, gpg->cmd.fd, 0,
1174                                      command_handler, gpg,
1175                                      &gpg->fd_data_map[gpg->cmd.idx].tag);
1176                           gpg->fd_data_map[gpg->cmd.idx].fd = gpg->cmd.fd;
1177                           gpg->cmd.fd = -1;
1178                         }
1179                       else if (gpg->status.fnc)
1180                         {
1181                           err = gpg->status.fnc (gpg->status.fnc_value,
1182                                                  r, rest);
1183                           if (gpg_err_code (err) == GPG_ERR_FALSE)
1184                             err = 0; /* Drop special error code.  */
1185                           if (err)
1186                             return err;
1187                         }
1188
1189                       if (r == GPGME_STATUS_END_STREAM)
1190                         {
1191                           if (gpg->cmd.used)
1192                             {
1193                               /* Before we can actually add the
1194                                  command fd, we might have to flush
1195                                  the linked output data pipe.  */
1196                               if (gpg->cmd.linked_idx != -1
1197                                   && gpg->fd_data_map[gpg->cmd.linked_idx].fd
1198                                   != -1)
1199                                 {
1200                                   struct io_select_fd_s fds;
1201                                   fds.fd =
1202                                     gpg->fd_data_map[gpg->cmd.linked_idx].fd;
1203                                   fds.for_read = 1;
1204                                   fds.for_write = 0;
1205                                   fds.opaque = NULL;
1206                                   do
1207                                     {
1208                                       fds.signaled = 0;
1209                                       _gpgme_io_select (&fds, 1, 1);
1210                                       if (fds.signaled)
1211                                         _gpgme_data_inbound_handler
1212                                           (gpg->cmd.linked_data, fds.fd);
1213                                     }
1214                                   while (fds.signaled);
1215                                 }
1216
1217                               /* XXX We must check if there are any
1218                                  more fds active after removing this
1219                                  one.  */
1220                               (*gpg->io_cbs.remove)
1221                                 (gpg->fd_data_map[gpg->cmd.idx].tag);
1222                               gpg->cmd.fd = gpg->fd_data_map[gpg->cmd.idx].fd;
1223                               gpg->fd_data_map[gpg->cmd.idx].fd = -1;
1224                             }
1225                         }
1226                     }
1227                 }
1228               /* To reuse the buffer for the next line we have to
1229                  shift the remaining data to the buffer start and
1230                  restart the loop Hmmm: We can optimize this function
1231                  by looking forward in the buffer to see whether a
1232                  second complete line is available and in this case
1233                  avoid the memmove for this line.  */
1234               nread--; p++;
1235               if (nread)
1236                 memmove (buffer, p, nread);
1237               readpos = 0;
1238               break; /* the for loop */
1239             }
1240           else
1241             readpos++;
1242         }
1243     }
1244
1245   /* Update the gpg object.  */
1246   gpg->status.bufsize = bufsize;
1247   gpg->status.buffer = buffer;
1248   gpg->status.readpos = readpos;
1249   return 0;
1250 }
1251
1252
1253 static gpgme_error_t
1254 status_handler (void *opaque, int fd)
1255 {
1256   struct io_cb_data *data = (struct io_cb_data *) opaque;
1257   engine_gpg_t gpg = (engine_gpg_t) data->handler_value;
1258   int err;
1259
1260   assert (fd == gpg->status.fd[0]);
1261   err = read_status (gpg);
1262   if (err)
1263     return err;
1264   if (gpg->status.eof)
1265     _gpgme_io_close (fd);
1266   return 0;
1267 }
1268
1269
1270 static gpgme_error_t
1271 read_colon_line (engine_gpg_t gpg)
1272 {
1273   char *p;
1274   int nread;
1275   size_t bufsize = gpg->colon.bufsize;
1276   char *buffer = gpg->colon.buffer;
1277   size_t readpos = gpg->colon.readpos;
1278
1279   assert (buffer);
1280   if (bufsize - readpos < 256)
1281     {
1282       /* Need more room for the read.  */
1283       bufsize += 1024;
1284       buffer = realloc (buffer, bufsize);
1285       if (!buffer)
1286         return gpg_error_from_syserror ();
1287     }
1288
1289   nread = _gpgme_io_read (gpg->colon.fd[0], buffer+readpos, bufsize-readpos);
1290   if (nread == -1)
1291     return gpg_error_from_syserror ();
1292
1293   if (!nread)
1294     {
1295       gpg->colon.eof = 1;
1296       assert (gpg->colon.fnc);
1297       gpg->colon.fnc (gpg->colon.fnc_value, NULL);
1298       return 0;
1299     }
1300
1301   while (nread > 0)
1302     {
1303       for (p = buffer + readpos; nread; nread--, p++)
1304         {
1305           if ( *p == '\n' )
1306             {
1307               /* (we require that the last line is terminated by a LF)
1308                  and we skip empty lines.  Note: we use UTF8 encoding
1309                  and escaping of special characters.  We require at
1310                  least one colon to cope with some other printed
1311                  information.  */
1312               *p = 0;
1313               if (*buffer && strchr (buffer, ':'))
1314                 {
1315                   char *line = NULL;
1316
1317                   if (gpg->colon.preprocess_fnc)
1318                     {
1319                       gpgme_error_t err;
1320
1321                       err = gpg->colon.preprocess_fnc (buffer, &line);
1322                       if (err)
1323                         return err;
1324                     }
1325
1326                   assert (gpg->colon.fnc);
1327                   if (line)
1328                     {
1329                       char *linep = line;
1330                       char *endp;
1331
1332                       do
1333                         {
1334                           endp = strchr (linep, '\n');
1335                           if (endp)
1336                             *endp++ = 0;
1337                           gpg->colon.fnc (gpg->colon.fnc_value, linep);
1338                           linep = endp;
1339                         }
1340                       while (linep && *linep);
1341
1342                       free (line);
1343                     }
1344                   else
1345                     gpg->colon.fnc (gpg->colon.fnc_value, buffer);
1346                 }
1347
1348               /* To reuse the buffer for the next line we have to
1349                  shift the remaining data to the buffer start and
1350                  restart the loop Hmmm: We can optimize this function
1351                  by looking forward in the buffer to see whether a
1352                  second complete line is available and in this case
1353                  avoid the memmove for this line.  */
1354               nread--; p++;
1355               if (nread)
1356                 memmove (buffer, p, nread);
1357               readpos = 0;
1358               break; /* The for loop.  */
1359             }
1360           else
1361             readpos++;
1362         }
1363     }
1364
1365   /* Update the gpg object.  */
1366   gpg->colon.bufsize = bufsize;
1367   gpg->colon.buffer  = buffer;
1368   gpg->colon.readpos = readpos;
1369   return 0;
1370 }
1371
1372
1373 /* This colonline handler thing is not the clean way to do it.  It
1374    might be better to enhance the gpgme_data_t object to act as a wrapper
1375    for a callback.  Same goes for the status thing.  For now we use
1376    this thing here because it is easier to implement.  */
1377 static gpgme_error_t
1378 colon_line_handler (void *opaque, int fd)
1379 {
1380   struct io_cb_data *data = (struct io_cb_data *) opaque;
1381   engine_gpg_t gpg = (engine_gpg_t) data->handler_value;
1382   gpgme_error_t rc = 0;
1383
1384   assert (fd == gpg->colon.fd[0]);
1385   rc = read_colon_line (gpg);
1386   if (rc)
1387     return rc;
1388   if (gpg->colon.eof)
1389     _gpgme_io_close (fd);
1390   return 0;
1391 }
1392
1393
1394 static gpgme_error_t
1395 start (engine_gpg_t gpg)
1396 {
1397   gpgme_error_t rc;
1398   int i, n;
1399   int status;
1400   struct spawn_fd_item_s *fd_list;
1401   pid_t pid;
1402   const char *pgmname;
1403
1404   if (!gpg)
1405     return gpg_error (GPG_ERR_INV_VALUE);
1406
1407   if (!gpg->file_name && !_gpgme_get_default_gpg_name ())
1408     return trace_gpg_error (GPG_ERR_INV_ENGINE);
1409
1410   if (gpg->lc_ctype)
1411     {
1412       rc = add_arg_ext (gpg, gpg->lc_ctype, 1);
1413       if (!rc)
1414         rc = add_arg_ext (gpg, "--lc-ctype", 1);
1415       if (rc)
1416         return rc;
1417     }
1418
1419   if (gpg->lc_messages)
1420     {
1421       rc = add_arg_ext (gpg, gpg->lc_messages, 1);
1422       if (!rc)
1423         rc = add_arg_ext (gpg, "--lc-messages", 1);
1424       if (rc)
1425         return rc;
1426     }
1427
1428   pgmname = gpg->file_name ? gpg->file_name : _gpgme_get_default_gpg_name ();
1429   rc = build_argv (gpg, pgmname);
1430   if (rc)
1431     return rc;
1432
1433   /* status_fd, colon_fd and end of list.  */
1434   n = 3;
1435   for (i = 0; gpg->fd_data_map[i].data; i++)
1436     n++;
1437   fd_list = calloc (n, sizeof *fd_list);
1438   if (! fd_list)
1439     return gpg_error_from_syserror ();
1440
1441   /* Build the fd list for the child.  */
1442   n = 0;
1443   fd_list[n].fd = gpg->status.fd[1];
1444   fd_list[n].dup_to = -1;
1445   fd_list[n].arg_loc = gpg->status.arg_loc;
1446   n++;
1447   if (gpg->colon.fnc)
1448     {
1449       fd_list[n].fd = gpg->colon.fd[1];
1450       fd_list[n].dup_to = 1;
1451       n++;
1452     }
1453   for (i = 0; gpg->fd_data_map[i].data; i++)
1454     {
1455       fd_list[n].fd = gpg->fd_data_map[i].peer_fd;
1456       fd_list[n].dup_to = gpg->fd_data_map[i].dup_to;
1457       fd_list[n].arg_loc = gpg->fd_data_map[i].arg_loc;
1458       n++;
1459     }
1460   fd_list[n].fd = -1;
1461   fd_list[n].dup_to = -1;
1462
1463   status = _gpgme_io_spawn (pgmname, gpg->argv,
1464                             (IOSPAWN_FLAG_DETACHED |IOSPAWN_FLAG_ALLOW_SET_FG),
1465                             fd_list, NULL, NULL, &pid);
1466   {
1467     int saved_err = gpg_error_from_syserror ();
1468     free (fd_list);
1469     if (status == -1)
1470       return saved_err;
1471   }
1472
1473   /*_gpgme_register_term_handler ( closure, closure_value, pid );*/
1474
1475   rc = add_io_cb (gpg, gpg->status.fd[0], 1, status_handler, gpg,
1476                   &gpg->status.tag);
1477   if (rc)
1478     /* FIXME: kill the child */
1479     return rc;
1480
1481   if (gpg->colon.fnc)
1482     {
1483       assert (gpg->colon.fd[0] != -1);
1484       rc = add_io_cb (gpg, gpg->colon.fd[0], 1, colon_line_handler, gpg,
1485                       &gpg->colon.tag);
1486       if (rc)
1487         /* FIXME: kill the child */
1488         return rc;
1489     }
1490
1491   for (i = 0; gpg->fd_data_map[i].data; i++)
1492     {
1493       if (gpg->cmd.used && i == gpg->cmd.idx)
1494         {
1495           /* Park the cmd fd.  */
1496           gpg->cmd.fd = gpg->fd_data_map[i].fd;
1497           gpg->fd_data_map[i].fd = -1;
1498         }
1499       else
1500         {
1501           rc = add_io_cb (gpg, gpg->fd_data_map[i].fd,
1502                           gpg->fd_data_map[i].inbound,
1503                           gpg->fd_data_map[i].inbound
1504                           ? _gpgme_data_inbound_handler
1505                           : _gpgme_data_outbound_handler,
1506                           gpg->fd_data_map[i].data, &gpg->fd_data_map[i].tag);
1507
1508           if (rc)
1509             /* FIXME: kill the child */
1510             return rc;
1511         }
1512     }
1513
1514   gpg_io_event (gpg, GPGME_EVENT_START, NULL);
1515
1516   /* fixme: check what data we can release here */
1517   return 0;
1518 }
1519
1520
1521 /* Add the --input-size-hint option if requested.  */
1522 static gpgme_error_t
1523 add_input_size_hint (engine_gpg_t gpg, gpgme_data_t data)
1524 {
1525   gpgme_error_t err;
1526   gpgme_off_t value = _gpgme_data_get_size_hint (data);
1527   char numbuf[50];  /* Large enough for even 2^128 in base-10.  */
1528   char *p;
1529
1530   if (!value || !have_gpg_version (gpg, "2.1.15"))
1531     return 0;
1532
1533   err = add_arg (gpg, "--input-size-hint");
1534   if (!err)
1535     {
1536       p = numbuf + sizeof numbuf;
1537       *--p = 0;
1538       do
1539         {
1540           *--p = '0' + (value % 10);
1541           value /= 10;
1542         }
1543       while (value);
1544       err = add_arg (gpg, p);
1545     }
1546   return err;
1547 }
1548
1549
1550 static gpgme_error_t
1551 gpg_decrypt (void *engine, gpgme_data_t ciph, gpgme_data_t plain)
1552 {
1553   engine_gpg_t gpg = engine;
1554   gpgme_error_t err;
1555
1556   err = add_arg (gpg, "--decrypt");
1557
1558   /* Tell the gpg object about the data.  */
1559   if (!err)
1560     err = add_arg (gpg, "--output");
1561   if (!err)
1562     err = add_arg (gpg, "-");
1563   if (!err)
1564     err = add_data (gpg, plain, 1, 1);
1565   if (!err)
1566     err = add_input_size_hint (gpg, ciph);
1567   if (!err)
1568     err = add_arg (gpg, "--");
1569   if (!err)
1570     err = add_data (gpg, ciph, -1, 0);
1571
1572   if (!err)
1573     err = start (gpg);
1574   return err;
1575 }
1576
1577 static gpgme_error_t
1578 gpg_delete (void *engine, gpgme_key_t key, int allow_secret)
1579 {
1580   engine_gpg_t gpg = engine;
1581   gpgme_error_t err;
1582
1583   err = add_arg (gpg, allow_secret ? "--delete-secret-and-public-key"
1584                  : "--delete-key");
1585   if (!err)
1586     err = add_arg (gpg, "--");
1587   if (!err)
1588     {
1589       if (!key->subkeys || !key->subkeys->fpr)
1590         return gpg_error (GPG_ERR_INV_VALUE);
1591       else
1592         err = add_arg (gpg, key->subkeys->fpr);
1593     }
1594
1595   if (!err)
1596     err = start (gpg);
1597   return err;
1598 }
1599
1600
1601 static gpgme_error_t
1602 gpg_passwd (void *engine, gpgme_key_t key, unsigned int flags)
1603 {
1604   engine_gpg_t gpg = engine;
1605   gpgme_error_t err;
1606
1607   (void)flags;
1608
1609   if (!key || !key->subkeys || !key->subkeys->fpr)
1610     return gpg_error (GPG_ERR_INV_CERT_OBJ);
1611
1612   err = add_arg (gpg, "--passwd");
1613   if (!err)
1614     err = add_arg (gpg, key->subkeys->fpr);
1615   if (!err)
1616     err = start (gpg);
1617   return err;
1618 }
1619
1620
1621 static gpgme_error_t
1622 append_args_from_signers (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */)
1623 {
1624   gpgme_error_t err = 0;
1625   int i;
1626   gpgme_key_t key;
1627
1628   for (i = 0; (key = gpgme_signers_enum (ctx, i)); i++)
1629     {
1630       const char *s = key->subkeys ? key->subkeys->keyid : NULL;
1631       if (s)
1632         {
1633           if (!err)
1634             err = add_arg (gpg, "-u");
1635           if (!err)
1636             err = add_arg (gpg, s);
1637         }
1638       gpgme_key_unref (key);
1639       if (err)
1640         break;
1641     }
1642   return err;
1643 }
1644
1645
1646 static gpgme_error_t
1647 append_args_from_sig_notations (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */)
1648 {
1649   gpgme_error_t err = 0;
1650   gpgme_sig_notation_t notation;
1651
1652   notation = gpgme_sig_notation_get (ctx);
1653
1654   while (!err && notation)
1655     {
1656       if (notation->name
1657           && !(notation->flags & GPGME_SIG_NOTATION_HUMAN_READABLE))
1658         err = gpg_error (GPG_ERR_INV_VALUE);
1659       else if (notation->name)
1660         {
1661           char *arg;
1662
1663           /* Maximum space needed is one byte for the "critical" flag,
1664              the name, one byte for '=', the value, and a terminating
1665              '\0'.  */
1666
1667           arg = malloc (1 + notation->name_len + 1 + notation->value_len + 1);
1668           if (!arg)
1669             err = gpg_error_from_syserror ();
1670
1671           if (!err)
1672             {
1673               char *argp = arg;
1674
1675               if (notation->critical)
1676                 *(argp++) = '!';
1677
1678               memcpy (argp, notation->name, notation->name_len);
1679               argp += notation->name_len;
1680
1681               *(argp++) = '=';
1682
1683               /* We know that notation->name is '\0' terminated.  */
1684               strcpy (argp, notation->value);
1685             }
1686
1687           if (!err)
1688             err = add_arg (gpg, "--sig-notation");
1689           if (!err)
1690             err = add_arg (gpg, arg);
1691
1692           if (arg)
1693             free (arg);
1694         }
1695       else
1696         {
1697           /* This is a policy URL.  */
1698
1699           char *value;
1700
1701           if (notation->critical)
1702             {
1703               value = malloc (1 + notation->value_len + 1);
1704               if (!value)
1705                 err = gpg_error_from_syserror ();
1706               else
1707                 {
1708                   value[0] = '!';
1709                   /* We know that notation->value is '\0' terminated.  */
1710                   strcpy (&value[1], notation->value);
1711                 }
1712             }
1713           else
1714             value = notation->value;
1715
1716           if (!err)
1717             err = add_arg (gpg, "--sig-policy-url");
1718           if (!err)
1719             err = add_arg (gpg, value);
1720
1721           if (value != notation->value)
1722             free (value);
1723         }
1724
1725       notation = notation->next;
1726     }
1727   return err;
1728 }
1729
1730
1731 static gpgme_error_t
1732 gpg_edit (void *engine, int type, gpgme_key_t key, gpgme_data_t out,
1733           gpgme_ctx_t ctx /* FIXME */)
1734 {
1735   engine_gpg_t gpg = engine;
1736   gpgme_error_t err;
1737
1738   err = add_arg (gpg, "--with-colons");
1739   if (!err)
1740     err = append_args_from_signers (gpg, ctx);
1741   if (!err)
1742   err = add_arg (gpg, type == 0 ? "--edit-key" : "--card-edit");
1743   if (!err)
1744     err = add_data (gpg, out, 1, 1);
1745   if (!err)
1746     err = add_arg (gpg, "--");
1747   if (!err && type == 0)
1748     {
1749       const char *s = key->subkeys ? key->subkeys->fpr : NULL;
1750       if (!s)
1751         err = gpg_error (GPG_ERR_INV_VALUE);
1752       else
1753         err = add_arg (gpg, s);
1754     }
1755   if (!err)
1756     err = start (gpg);
1757
1758   return err;
1759 }
1760
1761
1762 static gpgme_error_t
1763 append_args_from_recipients (engine_gpg_t gpg, gpgme_key_t recp[])
1764 {
1765   gpgme_error_t err = 0;
1766   int i = 0;
1767
1768   while (recp[i])
1769     {
1770       if (!recp[i]->subkeys || !recp[i]->subkeys->fpr)
1771         err = gpg_error (GPG_ERR_INV_VALUE);
1772       if (!err)
1773         err = add_arg (gpg, "-r");
1774       if (!err)
1775         err = add_arg (gpg, recp[i]->subkeys->fpr);
1776       if (err)
1777         break;
1778       i++;
1779     }
1780   return err;
1781 }
1782
1783
1784 static gpgme_error_t
1785 gpg_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,
1786              gpgme_data_t plain, gpgme_data_t ciph, int use_armor)
1787 {
1788   engine_gpg_t gpg = engine;
1789   gpgme_error_t err = 0;
1790
1791   if (recp)
1792     err = add_arg (gpg, "--encrypt");
1793
1794   if (!err && ((flags & GPGME_ENCRYPT_SYMMETRIC) || !recp))
1795     err = add_arg (gpg, "--symmetric");
1796
1797   if (!err && use_armor)
1798     err = add_arg (gpg, "--armor");
1799
1800   if (!err && (flags & GPGME_ENCRYPT_NO_COMPRESS))
1801     err = add_arg (gpg, "--compress-algo=none");
1802
1803   if (gpgme_data_get_encoding (plain) == GPGME_DATA_ENCODING_MIME
1804       && have_gpg_version (gpg, "2.1.14"))
1805     err = add_arg (gpg, "--mimemode");
1806
1807   if (recp)
1808     {
1809       /* If we know that all recipients are valid (full or ultimate trust)
1810          we can suppress further checks.  */
1811       if (!err && (flags & GPGME_ENCRYPT_ALWAYS_TRUST))
1812         err = add_arg (gpg, "--always-trust");
1813
1814       if (!err && (flags & GPGME_ENCRYPT_NO_ENCRYPT_TO))
1815         err = add_arg (gpg, "--no-encrypt-to");
1816
1817       if (!err)
1818         err = append_args_from_recipients (gpg, recp);
1819     }
1820
1821   /* Tell the gpg object about the data.  */
1822   if (!err)
1823     err = add_arg (gpg, "--output");
1824   if (!err)
1825     err = add_arg (gpg, "-");
1826   if (!err)
1827     err = add_data (gpg, ciph, 1, 1);
1828   if (gpgme_data_get_file_name (plain))
1829     {
1830       if (!err)
1831         err = add_arg (gpg, "--set-filename");
1832       if (!err)
1833         err = add_arg (gpg, gpgme_data_get_file_name (plain));
1834     }
1835   if (!err)
1836     err = add_input_size_hint (gpg, plain);
1837   if (!err)
1838     err = add_arg (gpg, "--");
1839   if (!err)
1840     err = add_data (gpg, plain, -1, 0);
1841
1842   if (!err)
1843     err = start (gpg);
1844
1845   return err;
1846 }
1847
1848
1849 static gpgme_error_t
1850 gpg_encrypt_sign (void *engine, gpgme_key_t recp[],
1851                   gpgme_encrypt_flags_t flags, gpgme_data_t plain,
1852                   gpgme_data_t ciph, int use_armor,
1853                   gpgme_ctx_t ctx /* FIXME */)
1854 {
1855   engine_gpg_t gpg = engine;
1856   gpgme_error_t err = 0;
1857
1858   if (recp)
1859     err = add_arg (gpg, "--encrypt");
1860
1861   if (!err && ((flags & GPGME_ENCRYPT_SYMMETRIC) || !recp))
1862     err = add_arg (gpg, "--symmetric");
1863
1864   if (!err)
1865     err = add_arg (gpg, "--sign");
1866   if (!err && use_armor)
1867     err = add_arg (gpg, "--armor");
1868
1869   if (!err && (flags & GPGME_ENCRYPT_NO_COMPRESS))
1870     err = add_arg (gpg, "--compress-algo=none");
1871
1872   if (gpgme_data_get_encoding (plain) == GPGME_DATA_ENCODING_MIME
1873       && have_gpg_version (gpg, "2.1.14"))
1874     err = add_arg (gpg, "--mimemode");
1875
1876   if (recp)
1877     {
1878       /* If we know that all recipients are valid (full or ultimate trust)
1879          we can suppress further checks.  */
1880       if (!err && (flags & GPGME_ENCRYPT_ALWAYS_TRUST))
1881         err = add_arg (gpg, "--always-trust");
1882
1883       if (!err && (flags & GPGME_ENCRYPT_NO_ENCRYPT_TO))
1884         err = add_arg (gpg, "--no-encrypt-to");
1885
1886       if (!err)
1887         err = append_args_from_recipients (gpg, recp);
1888     }
1889
1890   if (!err)
1891     err = append_args_from_signers (gpg, ctx);
1892
1893   if (!err)
1894     err = append_args_from_sig_notations (gpg, ctx);
1895
1896   /* Tell the gpg object about the data.  */
1897   if (!err)
1898     err = add_arg (gpg, "--output");
1899   if (!err)
1900     err = add_arg (gpg, "-");
1901   if (!err)
1902     err = add_data (gpg, ciph, 1, 1);
1903   if (gpgme_data_get_file_name (plain))
1904     {
1905       if (!err)
1906         err = add_arg (gpg, "--set-filename");
1907       if (!err)
1908         err = add_arg (gpg, gpgme_data_get_file_name (plain));
1909     }
1910   if (!err)
1911     err = add_input_size_hint (gpg, plain);
1912   if (!err)
1913     err = add_arg (gpg, "--");
1914   if (!err)
1915     err = add_data (gpg, plain, -1, 0);
1916
1917   if (!err)
1918     err = start (gpg);
1919
1920   return err;
1921 }
1922
1923
1924 static gpgme_error_t
1925 export_common (engine_gpg_t gpg, gpgme_export_mode_t mode,
1926                gpgme_data_t keydata, int use_armor)
1927 {
1928   gpgme_error_t err = 0;
1929
1930   if ((mode & ~(GPGME_EXPORT_MODE_EXTERN
1931                 |GPGME_EXPORT_MODE_MINIMAL
1932                 |GPGME_EXPORT_MODE_SECRET)))
1933     return gpg_error (GPG_ERR_NOT_SUPPORTED);
1934
1935   if ((mode & GPGME_EXPORT_MODE_MINIMAL))
1936     err = add_arg (gpg, "--export-options=export-minimal");
1937
1938   if (err)
1939     ;
1940   else if ((mode & GPGME_EXPORT_MODE_EXTERN))
1941     {
1942       err = add_arg (gpg, "--send-keys");
1943     }
1944   else
1945     {
1946       if ((mode & GPGME_EXPORT_MODE_SECRET))
1947         err = add_arg (gpg, "--export-secret-keys");
1948       else
1949         err = add_arg (gpg, "--export");
1950       if (!err && use_armor)
1951         err = add_arg (gpg, "--armor");
1952       if (!err)
1953         err = add_data (gpg, keydata, 1, 1);
1954     }
1955   if (!err)
1956     err = add_arg (gpg, "--");
1957
1958   return err;
1959 }
1960
1961
1962 static gpgme_error_t
1963 gpg_export (void *engine, const char *pattern, gpgme_export_mode_t mode,
1964             gpgme_data_t keydata, int use_armor)
1965 {
1966   engine_gpg_t gpg = engine;
1967   gpgme_error_t err;
1968
1969   err = export_common (gpg, mode, keydata, use_armor);
1970
1971   if (!err && pattern && *pattern)
1972     err = add_arg (gpg, pattern);
1973
1974   if (!err)
1975     err = start (gpg);
1976
1977   return err;
1978 }
1979
1980
1981 static gpgme_error_t
1982 gpg_export_ext (void *engine, const char *pattern[], gpgme_export_mode_t mode,
1983                 gpgme_data_t keydata, int use_armor)
1984 {
1985   engine_gpg_t gpg = engine;
1986   gpgme_error_t err;
1987
1988   err = export_common (gpg, mode, keydata, use_armor);
1989
1990   if (pattern)
1991     {
1992       while (!err && *pattern && **pattern)
1993         err = add_arg (gpg, *(pattern++));
1994     }
1995
1996   if (!err)
1997     err = start (gpg);
1998
1999   return err;
2000 }
2001
2002
2003 \f
2004 /* Helper to add algo, usage, and expire to the list of args.  */
2005 static gpgme_error_t
2006 gpg_add_algo_usage_expire (engine_gpg_t gpg,
2007                            const char *algo,
2008                            unsigned long expires,
2009                            unsigned int flags)
2010 {
2011   gpg_error_t err;
2012
2013   /* This condition is only required to allow the use of gpg < 2.1.16 */
2014   if (algo
2015       || (flags & (GPGME_CREATE_SIGN | GPGME_CREATE_ENCR
2016                    | GPGME_CREATE_CERT | GPGME_CREATE_AUTH))
2017       || expires)
2018     {
2019       err = add_arg (gpg, algo? algo : "default");
2020       if (!err)
2021         {
2022           char tmpbuf[5*4+1];
2023           snprintf (tmpbuf, sizeof tmpbuf, "%s%s%s%s",
2024                     (flags & GPGME_CREATE_SIGN)? " sign":"",
2025                     (flags & GPGME_CREATE_ENCR)? " encr":"",
2026                     (flags & GPGME_CREATE_CERT)? " cert":"",
2027                     (flags & GPGME_CREATE_AUTH)? " auth":"");
2028           err = add_arg (gpg, *tmpbuf? tmpbuf : "default");
2029         }
2030       if (!err && expires)
2031         {
2032           char tmpbuf[8+20];
2033           snprintf (tmpbuf, sizeof tmpbuf, "seconds=%lu", expires);
2034           err = add_arg (gpg, tmpbuf);
2035         }
2036     }
2037   else
2038     err = 0;
2039
2040   return err;
2041 }
2042
2043
2044 static gpgme_error_t
2045 gpg_createkey_from_param (engine_gpg_t gpg,
2046                           gpgme_data_t help_data, unsigned int extraflags)
2047 {
2048   gpgme_error_t err;
2049
2050   err = add_arg (gpg, "--gen-key");
2051   if (!err && (extraflags & GENKEY_EXTRAFLAG_ARMOR))
2052     err = add_arg (gpg, "--armor");
2053   if (!err)
2054     err = add_arg (gpg, "--");
2055   if (!err)
2056     err = add_data (gpg, help_data, -1, 0);
2057   if (!err)
2058     err = start (gpg);
2059   return err;
2060 }
2061
2062
2063 static gpgme_error_t
2064 gpg_createkey (engine_gpg_t gpg,
2065                const char *userid, const char *algo,
2066                unsigned long expires,
2067                unsigned int flags,
2068                unsigned int extraflags)
2069 {
2070   gpgme_error_t err;
2071
2072   err = add_arg (gpg, "--quick-gen-key");
2073   if (!err && (extraflags & GENKEY_EXTRAFLAG_ARMOR))
2074     err = add_arg (gpg, "--armor");
2075   if (!err && (flags & GPGME_CREATE_NOPASSWD))
2076     {
2077       err = add_arg (gpg, "--passphrase");
2078       if (!err)
2079         err = add_arg (gpg, "");
2080     }
2081   if (!err && (flags & GPGME_CREATE_FORCE))
2082     err = add_arg (gpg, "--yes");
2083   if (!err)
2084     err = add_arg (gpg, "--");
2085   if (!err)
2086     err = add_arg (gpg, userid);
2087
2088   if (!err)
2089     err = gpg_add_algo_usage_expire (gpg, algo, expires, flags);
2090
2091   if (!err)
2092     err = start (gpg);
2093   return err;
2094 }
2095
2096
2097 static gpgme_error_t
2098 gpg_addkey (engine_gpg_t gpg,
2099             const char *algo,
2100             unsigned long expires,
2101             gpgme_key_t key,
2102             unsigned int flags,
2103             unsigned int extraflags)
2104 {
2105   gpgme_error_t err;
2106
2107   if (!key || !key->fpr)
2108     return gpg_error (GPG_ERR_INV_ARG);
2109
2110   err = add_arg (gpg, "--quick-addkey");
2111   if (!err && (extraflags & GENKEY_EXTRAFLAG_ARMOR))
2112     err = add_arg (gpg, "--armor");
2113   if (!err && (flags & GPGME_CREATE_NOPASSWD))
2114     {
2115       err = add_arg (gpg, "--passphrase");
2116       if (!err)
2117         err = add_arg (gpg, "");
2118     }
2119   if (!err)
2120     err = add_arg (gpg, "--");
2121   if (!err)
2122     err = add_arg (gpg, key->fpr);
2123
2124   if (!err)
2125     err = gpg_add_algo_usage_expire (gpg, algo, expires, flags);
2126
2127   if (!err)
2128     err = start (gpg);
2129   return err;
2130 }
2131
2132
2133 static gpgme_error_t
2134 gpg_adduid (engine_gpg_t gpg,
2135             gpgme_key_t key,
2136             const char *userid,
2137             unsigned int extraflags)
2138 {
2139   gpgme_error_t err;
2140
2141   if (!key || !key->fpr || !userid)
2142     return gpg_error (GPG_ERR_INV_ARG);
2143
2144   if ((extraflags & GENKEY_EXTRAFLAG_REVOKE))
2145     err = add_arg (gpg, "--quick-revuid");
2146   else
2147     err = add_arg (gpg, "--quick-adduid");
2148
2149   if (!err)
2150     err = add_arg (gpg, "--");
2151   if (!err)
2152     err = add_arg (gpg, key->fpr);
2153   if (!err)
2154     err = add_arg (gpg, userid);
2155
2156   if (!err)
2157     err = start (gpg);
2158   return err;
2159 }
2160
2161
2162 static gpgme_error_t
2163 gpg_genkey (void *engine,
2164             const char *userid, const char *algo,
2165             unsigned long reserved, unsigned long expires,
2166             gpgme_key_t key, unsigned int flags,
2167             gpgme_data_t help_data, unsigned int extraflags,
2168             gpgme_data_t pubkey, gpgme_data_t seckey)
2169 {
2170   engine_gpg_t gpg = engine;
2171   gpgme_error_t err;
2172
2173   (void)reserved;
2174
2175   if (!gpg)
2176     return gpg_error (GPG_ERR_INV_VALUE);
2177
2178   /* If HELP_DATA is given the use of the old interface
2179    * (gpgme_op_genkey) has been requested.  The other modes are:
2180    *
2181    *  USERID && !KEY          - Create a new keyblock.
2182    * !USERID &&  KEY          - Add a new subkey to KEY (gpg >= 2.1.14)
2183    *  USERID &&  KEY && !ALGO - Add a new user id to KEY (gpg >= 2.1.14).
2184    *
2185    */
2186   if (help_data)
2187     {
2188       /* We need a special mechanism to get the fd of a pipe here, so
2189          that we can use this for the %pubring and %secring
2190          parameters.  We don't have this yet, so we implement only the
2191          adding to the standard keyrings.  */
2192       if (pubkey || seckey)
2193         err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
2194       else
2195         err = gpg_createkey_from_param (gpg, help_data, extraflags);
2196     }
2197   else if (!have_gpg_version (gpg, "2.1.13"))
2198     err = gpg_error (GPG_ERR_NOT_SUPPORTED);
2199   else if (userid && !key)
2200     err = gpg_createkey (gpg, userid, algo, expires, flags, extraflags);
2201   else if (!userid && key)
2202     err = gpg_addkey (gpg, algo, expires, key, flags, extraflags);
2203   else if (userid && key && !algo)
2204     err = gpg_adduid (gpg, key, userid, extraflags);
2205   else
2206     err = gpg_error (GPG_ERR_INV_VALUE);
2207
2208   return err;
2209 }
2210
2211 /* Return the next DELIM delimited string from DATA as a C-string.
2212    The caller needs to provide the address of a pointer variable which
2213    he has to set to NULL before the first call.  After the last call
2214    to this function, this function needs to be called once more with
2215    DATA set to NULL so that the function can release its internal
2216    state.  After that the pointer variable is free for use again.
2217    Note that we use a delimiter and thus a trailing delimiter is not
2218    required.  DELIM may not be changed after the first call. */
2219 static const char *
2220 string_from_data (gpgme_data_t data, int delim,
2221                   void **helpptr, gpgme_error_t *r_err)
2222 {
2223 #define MYBUFLEN 2000 /* Fixme: We don't support URLs longer than that.  */
2224   struct {
2225     int  eof_seen;
2226     int  nbytes;      /* Length of the last returned string including
2227                          the delimiter. */
2228     int  buflen;      /* Valid length of BUF.  */
2229     char buf[MYBUFLEN+1];  /* Buffer with one byte extra space.  */
2230   } *self;
2231   char *p;
2232   int nread;
2233
2234   *r_err = 0;
2235   if (!data)
2236     {
2237       if (*helpptr)
2238         {
2239           free (*helpptr);
2240           *helpptr = NULL;
2241         }
2242       return NULL;
2243     }
2244
2245   if (*helpptr)
2246     self = *helpptr;
2247   else
2248     {
2249       self = malloc (sizeof *self);
2250       if (!self)
2251         {
2252           *r_err = gpg_error_from_syserror ();
2253           return NULL;
2254         }
2255       *helpptr = self;
2256       self->eof_seen = 0;
2257       self->nbytes = 0;
2258       self->buflen = 0;
2259     }
2260
2261   if (self->eof_seen)
2262     return NULL;
2263
2264   assert (self->nbytes <= self->buflen);
2265   memmove (self->buf, self->buf + self->nbytes, self->buflen - self->nbytes);
2266   self->buflen -= self->nbytes;
2267   self->nbytes = 0;
2268
2269   do
2270     {
2271       /* Fixme: This is fairly infective scanning because we may scan
2272          the buffer several times.  */
2273       p = memchr (self->buf, delim, self->buflen);
2274       if (p)
2275         {
2276           *p = 0;
2277           self->nbytes = p - self->buf + 1;
2278           return self->buf;
2279         }
2280
2281       if ( !(MYBUFLEN - self->buflen) )
2282         {
2283           /* Not enough space - URL too long.  */
2284           *r_err = gpg_error (GPG_ERR_TOO_LARGE);
2285           return NULL;
2286         }
2287
2288       nread = gpgme_data_read (data, self->buf + self->buflen,
2289                                MYBUFLEN - self->buflen);
2290       if (nread < 0)
2291         {
2292           *r_err = gpg_error_from_syserror ();
2293           return NULL;
2294         }
2295       self->buflen += nread;
2296     }
2297   while (nread);
2298
2299   /* EOF reached.  If we have anything in the buffer, append a Nul and
2300      return it. */
2301   self->eof_seen = 1;
2302   if (self->buflen)
2303     {
2304       self->buf[self->buflen] = 0;  /* (we allocated one extra byte)  */
2305       return self->buf;
2306     }
2307   return NULL;
2308 #undef MYBUFLEN
2309 }
2310
2311
2312
2313 static gpgme_error_t
2314 gpg_import (void *engine, gpgme_data_t keydata, gpgme_key_t *keyarray)
2315 {
2316   engine_gpg_t gpg = engine;
2317   gpgme_error_t err;
2318   int idx;
2319   gpgme_data_encoding_t dataenc;
2320
2321   if (keydata && keyarray)
2322     return gpg_error (GPG_ERR_INV_VALUE); /* Only one is allowed.  */
2323
2324   dataenc = gpgme_data_get_encoding (keydata);
2325
2326   if (keyarray)
2327     {
2328       err = add_arg (gpg, "--recv-keys");
2329       if (!err)
2330         err = add_arg (gpg, "--");
2331       for (idx=0; !err && keyarray[idx]; idx++)
2332         {
2333           if (keyarray[idx]->protocol != GPGME_PROTOCOL_OpenPGP)
2334             ;
2335           else if (!keyarray[idx]->subkeys)
2336             ;
2337           else if (keyarray[idx]->subkeys->fpr && *keyarray[idx]->subkeys->fpr)
2338             err = add_arg (gpg, keyarray[idx]->subkeys->fpr);
2339           else if (*keyarray[idx]->subkeys->keyid)
2340             err = add_arg (gpg, keyarray[idx]->subkeys->keyid);
2341         }
2342     }
2343   else if (dataenc == GPGME_DATA_ENCODING_URL
2344            || dataenc == GPGME_DATA_ENCODING_URL0)
2345     {
2346       void *helpptr;
2347       const char *string;
2348       gpgme_error_t xerr;
2349       int delim = (dataenc == GPGME_DATA_ENCODING_URL)? '\n': 0;
2350
2351       /* FIXME: --fetch-keys is probably not correct because it can't
2352          grok all kinds of URLs.  On Unix it should just work but on
2353          Windows we will build the command line and that may fail for
2354          some embedded control characters.  It is anyway limited to
2355          the maximum size of the command line.  We need another
2356          command which can take its input from a file.  Maybe we
2357          should use an option to gpg to modify such commands (ala
2358          --multifile).  */
2359       err = add_arg (gpg, "--fetch-keys");
2360       if (!err)
2361         err = add_arg (gpg, "--");
2362       helpptr = NULL;
2363       while (!err
2364              && (string = string_from_data (keydata, delim, &helpptr, &xerr)))
2365         err = add_arg (gpg, string);
2366       if (!err)
2367         err = xerr;
2368       string_from_data (NULL, delim, &helpptr, &xerr);
2369     }
2370   else if (dataenc == GPGME_DATA_ENCODING_URLESC)
2371     {
2372       /* Already escaped URLs are not yet supported.  */
2373       err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
2374     }
2375   else
2376     {
2377       err = add_arg (gpg, "--import");
2378       if (!err)
2379         err = add_arg (gpg, "--");
2380       if (!err)
2381         err = add_data (gpg, keydata, -1, 0);
2382     }
2383
2384   if (!err)
2385     err = start (gpg);
2386
2387   return err;
2388 }
2389
2390
2391 /* The output for external keylistings in GnuPG is different from all
2392    the other key listings.  We catch this here with a special
2393    preprocessor that reformats the colon handler lines.  */
2394 static gpgme_error_t
2395 gpg_keylist_preprocess (char *line, char **r_line)
2396 {
2397   enum
2398     {
2399       RT_NONE, RT_INFO, RT_PUB, RT_UID
2400     }
2401   rectype = RT_NONE;
2402 #define NR_FIELDS 16
2403   char *field[NR_FIELDS];
2404   int fields = 0;
2405   size_t n;
2406
2407   *r_line = NULL;
2408
2409   while (line && fields < NR_FIELDS)
2410     {
2411       field[fields++] = line;
2412       line = strchr (line, ':');
2413       if (line)
2414         *(line++) = '\0';
2415     }
2416
2417   if (!strcmp (field[0], "info"))
2418     rectype = RT_INFO;
2419   else if (!strcmp (field[0], "pub"))
2420     rectype = RT_PUB;
2421   else if (!strcmp (field[0], "uid"))
2422     rectype = RT_UID;
2423   else
2424     rectype = RT_NONE;
2425
2426   switch (rectype)
2427     {
2428     case RT_INFO:
2429       /* FIXME: Eventually, check the version number at least.  */
2430       return 0;
2431
2432     case RT_PUB:
2433       if (fields < 7)
2434         return 0;
2435
2436       /* The format is:
2437
2438          pub:<keyid>:<algo>:<keylen>:<creationdate>:<expirationdate>:<flags>
2439
2440          as defined in 5.2. Machine Readable Indexes of the OpenPGP
2441          HTTP Keyserver Protocol (draft).  Modern versions of the SKS
2442          keyserver return the fingerprint instead of the keyid.  We
2443          detect this here and use the v4 fingerprint format to convert
2444          it to a key id.
2445
2446          We want:
2447          pub:o<flags>:<keylen>:<algo>:<keyid>:<creatdate>:<expdate>::::::::
2448       */
2449
2450       n = strlen (field[1]);
2451       if (n > 16)
2452         {
2453           if (asprintf (r_line,
2454                         "pub:o%s:%s:%s:%s:%s:%s::::::::\n"
2455                         "fpr:::::::::%s:",
2456                         field[6], field[3], field[2], field[1] + n - 16,
2457                         field[4], field[5], field[1]) < 0)
2458             return gpg_error_from_syserror ();
2459         }
2460       else
2461         {
2462           if (asprintf (r_line,
2463                         "pub:o%s:%s:%s:%s:%s:%s::::::::",
2464                         field[6], field[3], field[2], field[1],
2465                         field[4], field[5]) < 0)
2466             return gpg_error_from_syserror ();
2467         }
2468
2469       return 0;
2470
2471     case RT_UID:
2472       /* The format is:
2473
2474          uid:<escaped uid string>:<creationdate>:<expirationdate>:<flags>
2475
2476          as defined in 5.2. Machine Readable Indexes of the OpenPGP
2477          HTTP Keyserver Protocol (draft).
2478
2479          We want:
2480          uid:o<flags>::::<creatdate>:<expdate>:::<c-coded uid>:
2481       */
2482
2483       {
2484         /* The user ID is percent escaped, but we want c-coded.
2485            Because we have to replace each '%HL' by '\xHL', we need at
2486            most 4/3 th the number of bytes.  But because we also need
2487            to escape the backslashes we allocate twice as much.  */
2488         char *uid = malloc (2 * strlen (field[1]) + 1);
2489         char *src;
2490         char *dst;
2491
2492         if (! uid)
2493           return gpg_error_from_syserror ();
2494         src = field[1];
2495         dst = uid;
2496         while (*src)
2497           {
2498             if (*src == '%')
2499               {
2500                 *(dst++) = '\\';
2501                 *(dst++) = 'x';
2502                 src++;
2503                 /* Copy the next two bytes unconditionally.  */
2504                 if (*src)
2505                   *(dst++) = *(src++);
2506                 if (*src)
2507                   *(dst++) = *(src++);
2508               }
2509             else if (*src == '\\')
2510               {
2511                 *dst++ = '\\';
2512                 *dst++ = '\\';
2513                 src++;
2514               }
2515             else
2516               *(dst++) = *(src++);
2517           }
2518         *dst = '\0';
2519
2520         if (asprintf (r_line, "uid:o%s::::%s:%s:::%s:",
2521                       field[4], field[2], field[3], uid) < 0)
2522           return gpg_error_from_syserror ();
2523       }
2524       return 0;
2525
2526     case RT_NONE:
2527       /* Unknown record.  */
2528       break;
2529     }
2530   return 0;
2531
2532 }
2533
2534
2535 static gpg_error_t
2536 gpg_keylist_build_options (engine_gpg_t gpg, int secret_only,
2537                            gpgme_keylist_mode_t mode)
2538 {
2539   gpg_error_t err;
2540
2541   err = add_arg (gpg, "--with-colons");
2542
2543   /* Since gpg 2.1.15 fingerprints are always printed, thus there is
2544    * no more need to explictly request them.  */
2545   if (!have_gpg_version (gpg, "2.1.15"))
2546     {
2547       if (!err)
2548         err = add_arg (gpg, "--fixed-list-mode");
2549       if (!err)
2550         err = add_arg (gpg, "--with-fingerprint");
2551       if (!err)
2552         err = add_arg (gpg, "--with-fingerprint");
2553     }
2554
2555   if (!err && (mode & GPGME_KEYLIST_MODE_WITH_TOFU)
2556       && have_gpg_version (gpg, "2.1.16"))
2557     err = add_arg (gpg, "--with-tofu-info");
2558
2559   if (!err && (mode & GPGME_KEYLIST_MODE_WITH_SECRET))
2560     err = add_arg (gpg, "--with-secret");
2561
2562   if (!err
2563       && (mode & GPGME_KEYLIST_MODE_SIGS)
2564       && (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS))
2565     {
2566       err = add_arg (gpg, "--list-options");
2567       if (!err)
2568         err = add_arg (gpg, "show-sig-subpackets=\"20,26\"");
2569     }
2570
2571   if (!err)
2572     {
2573       if ( (mode & GPGME_KEYLIST_MODE_EXTERN) )
2574         {
2575           if (secret_only)
2576             err = gpg_error (GPG_ERR_NOT_SUPPORTED);
2577           else if ( (mode & GPGME_KEYLIST_MODE_LOCAL))
2578             {
2579               /* The local+extern mode is special.  It works only with
2580                  gpg >= 2.0.10.  FIXME: We should check that we have
2581                  such a version to that we can return a proper error
2582                  code.  The problem is that we don't know the context
2583                  here and thus can't access the cached version number
2584                  for the engine info structure.  */
2585               err = add_arg (gpg, "--locate-keys");
2586               if ((mode & GPGME_KEYLIST_MODE_SIGS))
2587                 err = add_arg (gpg, "--with-sig-check");
2588             }
2589           else
2590             {
2591               err = add_arg (gpg, "--search-keys");
2592               gpg->colon.preprocess_fnc = gpg_keylist_preprocess;
2593             }
2594         }
2595       else
2596         {
2597           err = add_arg (gpg, secret_only ? "--list-secret-keys"
2598                          : ((mode & GPGME_KEYLIST_MODE_SIGS)
2599                             ? "--check-sigs" : "--list-keys"));
2600         }
2601     }
2602
2603   if (!err)
2604     err = add_arg (gpg, "--");
2605
2606   return err;
2607 }
2608
2609
2610 static gpgme_error_t
2611 gpg_keylist (void *engine, const char *pattern, int secret_only,
2612              gpgme_keylist_mode_t mode, int engine_flags)
2613 {
2614   engine_gpg_t gpg = engine;
2615   gpgme_error_t err;
2616
2617   (void)engine_flags;
2618
2619   err = gpg_keylist_build_options (gpg, secret_only, mode);
2620
2621   if (!err && pattern && *pattern)
2622     err = add_arg (gpg, pattern);
2623
2624   if (!err)
2625     err = start (gpg);
2626
2627   return err;
2628 }
2629
2630
2631 static gpgme_error_t
2632 gpg_keylist_ext (void *engine, const char *pattern[], int secret_only,
2633                  int reserved, gpgme_keylist_mode_t mode, int engine_flags)
2634 {
2635   engine_gpg_t gpg = engine;
2636   gpgme_error_t err;
2637
2638   (void)engine_flags;
2639
2640   if (reserved)
2641     return gpg_error (GPG_ERR_INV_VALUE);
2642
2643   err = gpg_keylist_build_options (gpg, secret_only, mode);
2644
2645   if (pattern)
2646     {
2647       while (!err && *pattern && **pattern)
2648         err = add_arg (gpg, *(pattern++));
2649     }
2650
2651   if (!err)
2652     err = start (gpg);
2653
2654   return err;
2655 }
2656
2657
2658 static gpgme_error_t
2659 gpg_keysign (void *engine, gpgme_key_t key, const char *userid,
2660              unsigned long expire, unsigned int flags,
2661              gpgme_ctx_t ctx)
2662 {
2663   engine_gpg_t gpg = engine;
2664   gpgme_error_t err;
2665   const char *s;
2666
2667   if (!key || !key->fpr)
2668     return gpg_error (GPG_ERR_INV_ARG);
2669
2670   if (!have_gpg_version (gpg, "2.1.12"))
2671     return gpg_error (GPG_ERR_NOT_SUPPORTED);
2672
2673   if ((flags & GPGME_KEYSIGN_LOCAL))
2674     err = add_arg (gpg, "--quick-lsign-key");
2675   else
2676     err = add_arg (gpg, "--quick-sign-key");
2677
2678   if (!err)
2679     err = append_args_from_signers (gpg, ctx);
2680
2681   /* If an expiration time has been given use that.  If none has been
2682    * given the default from gpg.conf is used.  To make sure not to set
2683    * an expiration time at all the flag GPGME_KEYSIGN_NOEXPIRE can be
2684    * used.  */
2685   if (!err && (expire || (flags & GPGME_KEYSIGN_NOEXPIRE)))
2686     {
2687       char tmpbuf[8+20];
2688
2689       if ((flags & GPGME_KEYSIGN_NOEXPIRE))
2690         expire = 0;
2691       snprintf (tmpbuf, sizeof tmpbuf, "seconds=%lu", expire);
2692       err = add_arg (gpg, "--default-cert-expire");
2693       if (!err)
2694         err = add_arg (gpg, tmpbuf);
2695     }
2696
2697   if (!err)
2698     err = add_arg (gpg, "--");
2699
2700   if (!err)
2701     err = add_arg (gpg, key->fpr);
2702   if (!err && userid)
2703     {
2704       if ((flags & GPGME_KEYSIGN_LFSEP))
2705         {
2706           for (; !err && (s = strchr (userid, '\n')); userid = s + 1)
2707             if ((s - userid))
2708               err = add_arg_len (gpg, "=", userid, s - userid);
2709           if (!err && *userid)
2710             err = add_arg_pfx (gpg, "=", userid);
2711         }
2712       else
2713         err = add_arg_pfx (gpg, "=", userid);
2714     }
2715
2716   if (!err)
2717     err = start (gpg);
2718
2719   return err;
2720 }
2721
2722
2723 static gpgme_error_t
2724 gpg_tofu_policy (void *engine, gpgme_key_t key, gpgme_tofu_policy_t policy)
2725 {
2726   engine_gpg_t gpg = engine;
2727   gpgme_error_t err;
2728   const char *policystr = NULL;
2729
2730   if (!key || !key->fpr)
2731     return gpg_error (GPG_ERR_INV_ARG);
2732
2733   switch (policy)
2734     {
2735     case GPGME_TOFU_POLICY_NONE:                           break;
2736     case GPGME_TOFU_POLICY_AUTO:    policystr = "auto";    break;
2737     case GPGME_TOFU_POLICY_GOOD:    policystr = "good";    break;
2738     case GPGME_TOFU_POLICY_BAD:     policystr = "bad";     break;
2739     case GPGME_TOFU_POLICY_ASK:     policystr = "ask";     break;
2740     case GPGME_TOFU_POLICY_UNKNOWN: policystr = "unknown"; break;
2741     }
2742   if (!policystr)
2743     return gpg_error (GPG_ERR_INV_VALUE);
2744
2745   if (!have_gpg_version (gpg, "2.1.10"))
2746     return gpg_error (GPG_ERR_NOT_SUPPORTED);
2747
2748   err = add_arg (gpg, "--tofu-policy");
2749   if (!err)
2750     err = add_arg (gpg, "--");
2751   if (!err)
2752     err = add_arg (gpg, policystr);
2753   if (!err)
2754     err = add_arg (gpg, key->fpr);
2755
2756   if (!err)
2757     err = start (gpg);
2758
2759   return err;
2760 }
2761
2762
2763 static gpgme_error_t
2764 gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
2765           gpgme_sig_mode_t mode, int use_armor, int use_textmode,
2766           int include_certs, gpgme_ctx_t ctx /* FIXME */)
2767 {
2768   engine_gpg_t gpg = engine;
2769   gpgme_error_t err;
2770
2771   (void)include_certs;
2772
2773   if (mode == GPGME_SIG_MODE_CLEAR)
2774     err = add_arg (gpg, "--clearsign");
2775   else
2776     {
2777       err = add_arg (gpg, "--sign");
2778       if (!err && mode == GPGME_SIG_MODE_DETACH)
2779         err = add_arg (gpg, "--detach");
2780       if (!err && use_armor)
2781         err = add_arg (gpg, "--armor");
2782       if (!err)
2783         {
2784           if (gpgme_data_get_encoding (in) == GPGME_DATA_ENCODING_MIME
2785               && have_gpg_version (gpg, "2.1.14"))
2786             err = add_arg (gpg, "--mimemode");
2787           else if (use_textmode)
2788             err = add_arg (gpg, "--textmode");
2789         }
2790     }
2791
2792   if (!err)
2793     err = append_args_from_signers (gpg, ctx);
2794   if (!err)
2795     err = append_args_from_sig_notations (gpg, ctx);
2796
2797   if (gpgme_data_get_file_name (in))
2798     {
2799       if (!err)
2800         err = add_arg (gpg, "--set-filename");
2801       if (!err)
2802         err = add_arg (gpg, gpgme_data_get_file_name (in));
2803     }
2804
2805   /* Tell the gpg object about the data.  */
2806   if (!err)
2807     err = add_input_size_hint (gpg, in);
2808   if (!err)
2809     err = add_arg (gpg, "--");
2810   if (!err)
2811     err = add_data (gpg, in, -1, 0);
2812   if (!err)
2813     err = add_data (gpg, out, 1, 1);
2814
2815   if (!err)
2816     err = start (gpg);
2817
2818   return err;
2819 }
2820
2821 static gpgme_error_t
2822 gpg_trustlist (void *engine, const char *pattern)
2823 {
2824   engine_gpg_t gpg = engine;
2825   gpgme_error_t err;
2826
2827   err = add_arg (gpg, "--with-colons");
2828   if (!err)
2829     err = add_arg (gpg, "--list-trust-path");
2830
2831   /* Tell the gpg object about the data.  */
2832   if (!err)
2833     err = add_arg (gpg, "--");
2834   if (!err)
2835     err = add_arg (gpg, pattern);
2836
2837   if (!err)
2838     err = start (gpg);
2839
2840   return err;
2841 }
2842
2843
2844 static gpgme_error_t
2845 gpg_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text,
2846             gpgme_data_t plaintext)
2847 {
2848   engine_gpg_t gpg = engine;
2849   gpgme_error_t err = 0;
2850
2851   if (plaintext)
2852     {
2853       /* Normal or cleartext signature.  */
2854       err = add_arg (gpg, "--output");
2855       if (!err)
2856         err = add_arg (gpg, "-");
2857       if (!err)
2858         err = add_input_size_hint (gpg, sig);
2859       if (!err)
2860         err = add_arg (gpg, "--");
2861       if (!err)
2862         err = add_data (gpg, sig, -1, 0);
2863       if (!err)
2864         err = add_data (gpg, plaintext, 1, 1);
2865     }
2866   else
2867     {
2868       err = add_arg (gpg, "--verify");
2869       if (!err)
2870         err = add_input_size_hint (gpg, signed_text);
2871       if (!err)
2872         err = add_arg (gpg, "--");
2873       if (!err)
2874         err = add_data (gpg, sig, -1, 0);
2875       if (!err && signed_text)
2876         err = add_data (gpg, signed_text, -1, 0);
2877     }
2878
2879   if (!err)
2880     err = start (gpg);
2881
2882   return err;
2883 }
2884
2885
2886 static void
2887 gpg_set_io_cbs (void *engine, gpgme_io_cbs_t io_cbs)
2888 {
2889   engine_gpg_t gpg = engine;
2890
2891   gpg->io_cbs = *io_cbs;
2892 }
2893
2894
2895 static gpgme_error_t
2896 gpg_set_pinentry_mode (void *engine, gpgme_pinentry_mode_t mode)
2897 {
2898   engine_gpg_t gpg = engine;
2899
2900   gpg->pinentry_mode = mode;
2901   return 0;
2902 }
2903
2904
2905 \f
2906 struct engine_ops _gpgme_engine_ops_gpg =
2907   {
2908     /* Static functions.  */
2909     _gpgme_get_default_gpg_name,
2910     NULL,
2911     gpg_get_version,
2912     gpg_get_req_version,
2913     gpg_new,
2914
2915     /* Member functions.  */
2916     gpg_release,
2917     NULL,                               /* reset */
2918     gpg_set_status_cb,
2919     gpg_set_status_handler,
2920     gpg_set_command_handler,
2921     gpg_set_colon_line_handler,
2922     gpg_set_locale,
2923     NULL,                               /* set_protocol */
2924     gpg_decrypt,
2925     gpg_decrypt,                        /* decrypt_verify */
2926     gpg_delete,
2927     gpg_edit,
2928     gpg_encrypt,
2929     gpg_encrypt_sign,
2930     gpg_export,
2931     gpg_export_ext,
2932     gpg_genkey,
2933     gpg_import,
2934     gpg_keylist,
2935     gpg_keylist_ext,
2936     gpg_keysign,
2937     gpg_tofu_policy,    /* tofu_policy */
2938     gpg_sign,
2939     gpg_trustlist,
2940     gpg_verify,
2941     NULL,               /* getauditlog */
2942     NULL,               /* opassuan_transact */
2943     NULL,               /* conf_load */
2944     NULL,               /* conf_save */
2945     gpg_set_io_cbs,
2946     gpg_io_event,
2947     gpg_cancel,
2948     NULL,               /* cancel_op */
2949     gpg_passwd,
2950     gpg_set_pinentry_mode,
2951     NULL                /* opspawn */
2952   };