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