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