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