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