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