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