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