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