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