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