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