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