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