core: New GPGME_DATA_ENCODING_MIME.
[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;
1721   int symmetric = !recp;
1722
1723   err = add_arg (gpg, symmetric ? "--symmetric" : "--encrypt");
1724
1725   if (!err && use_armor)
1726     err = add_arg (gpg, "--armor");
1727
1728   if (!err && (flags & GPGME_ENCRYPT_NO_COMPRESS))
1729     err = add_arg (gpg, "--compress-algo=none");
1730
1731   if (gpgme_data_get_encoding (plain) == GPGME_DATA_ENCODING_MIME
1732       && have_gpg_version (gpg, "2.1.14"))
1733     err = add_arg (gpg, "--mimemode");
1734
1735   if (!symmetric)
1736     {
1737       /* If we know that all recipients are valid (full or ultimate trust)
1738          we can suppress further checks.  */
1739       if (!err && (flags & GPGME_ENCRYPT_ALWAYS_TRUST))
1740         err = add_arg (gpg, "--always-trust");
1741
1742       if (!err && (flags & GPGME_ENCRYPT_NO_ENCRYPT_TO))
1743         err = add_arg (gpg, "--no-encrypt-to");
1744
1745       if (!err)
1746         err = append_args_from_recipients (gpg, recp);
1747     }
1748
1749   /* Tell the gpg object about the data.  */
1750   if (!err)
1751     err = add_arg (gpg, "--output");
1752   if (!err)
1753     err = add_arg (gpg, "-");
1754   if (!err)
1755     err = add_data (gpg, ciph, 1, 1);
1756   if (gpgme_data_get_file_name (plain))
1757     {
1758       if (!err)
1759         err = add_arg (gpg, "--set-filename");
1760       if (!err)
1761         err = add_arg (gpg, gpgme_data_get_file_name (plain));
1762     }
1763   if (!err)
1764     err = add_arg (gpg, "--");
1765   if (!err)
1766     err = add_data (gpg, plain, -1, 0);
1767
1768   if (!err)
1769     err = start (gpg);
1770
1771   return err;
1772 }
1773
1774
1775 static gpgme_error_t
1776 gpg_encrypt_sign (void *engine, gpgme_key_t recp[],
1777                   gpgme_encrypt_flags_t flags, gpgme_data_t plain,
1778                   gpgme_data_t ciph, int use_armor,
1779                   gpgme_ctx_t ctx /* FIXME */)
1780 {
1781   engine_gpg_t gpg = engine;
1782   gpgme_error_t err;
1783   int symmetric = !recp;
1784
1785   err = add_arg (gpg, symmetric ? "--symmetric" : "--encrypt");
1786
1787   if (!err)
1788     err = add_arg (gpg, "--sign");
1789   if (!err && use_armor)
1790     err = add_arg (gpg, "--armor");
1791
1792   if (!err && (flags & GPGME_ENCRYPT_NO_COMPRESS))
1793     err = add_arg (gpg, "--compress-algo=none");
1794
1795   if (gpgme_data_get_encoding (plain) == GPGME_DATA_ENCODING_MIME
1796       && have_gpg_version (gpg, "2.1.14"))
1797     err = add_arg (gpg, "--mimemode");
1798
1799   if (!symmetric)
1800     {
1801       /* If we know that all recipients are valid (full or ultimate trust)
1802          we can suppress further checks.  */
1803       if (!err && (flags & GPGME_ENCRYPT_ALWAYS_TRUST))
1804         err = add_arg (gpg, "--always-trust");
1805
1806       if (!err && (flags & GPGME_ENCRYPT_NO_ENCRYPT_TO))
1807         err = add_arg (gpg, "--no-encrypt-to");
1808
1809       if (!err)
1810         err = append_args_from_recipients (gpg, recp);
1811     }
1812
1813   if (!err)
1814     err = append_args_from_signers (gpg, ctx);
1815
1816   if (!err)
1817     err = append_args_from_sig_notations (gpg, ctx);
1818
1819   /* Tell the gpg object about the data.  */
1820   if (!err)
1821     err = add_arg (gpg, "--output");
1822   if (!err)
1823     err = add_arg (gpg, "-");
1824   if (!err)
1825     err = add_data (gpg, ciph, 1, 1);
1826   if (gpgme_data_get_file_name (plain))
1827     {
1828       if (!err)
1829         err = add_arg (gpg, "--set-filename");
1830       if (!err)
1831         err = add_arg (gpg, gpgme_data_get_file_name (plain));
1832     }
1833   if (!err)
1834     err = add_arg (gpg, "--");
1835   if (!err)
1836     err = add_data (gpg, plain, -1, 0);
1837
1838   if (!err)
1839     err = start (gpg);
1840
1841   return err;
1842 }
1843
1844
1845 static gpgme_error_t
1846 export_common (engine_gpg_t gpg, gpgme_export_mode_t mode,
1847                gpgme_data_t keydata, int use_armor)
1848 {
1849   gpgme_error_t err = 0;
1850
1851   if ((mode & ~(GPGME_EXPORT_MODE_EXTERN
1852                 |GPGME_EXPORT_MODE_MINIMAL
1853                 |GPGME_EXPORT_MODE_SECRET)))
1854     return gpg_error (GPG_ERR_NOT_SUPPORTED);
1855
1856   if ((mode & GPGME_EXPORT_MODE_MINIMAL))
1857     err = add_arg (gpg, "--export-options=export-minimal");
1858
1859   if (err)
1860     ;
1861   else if ((mode & GPGME_EXPORT_MODE_EXTERN))
1862     {
1863       err = add_arg (gpg, "--send-keys");
1864     }
1865   else
1866     {
1867       if ((mode & GPGME_EXPORT_MODE_SECRET))
1868         err = add_arg (gpg, "--export-secret-keys");
1869       else
1870         err = add_arg (gpg, "--export");
1871       if (!err && use_armor)
1872         err = add_arg (gpg, "--armor");
1873       if (!err)
1874         err = add_data (gpg, keydata, 1, 1);
1875     }
1876   if (!err)
1877     err = add_arg (gpg, "--");
1878
1879   return err;
1880 }
1881
1882
1883 static gpgme_error_t
1884 gpg_export (void *engine, const char *pattern, gpgme_export_mode_t mode,
1885             gpgme_data_t keydata, int use_armor)
1886 {
1887   engine_gpg_t gpg = engine;
1888   gpgme_error_t err;
1889
1890   err = export_common (gpg, mode, keydata, use_armor);
1891
1892   if (!err && pattern && *pattern)
1893     err = add_arg (gpg, pattern);
1894
1895   if (!err)
1896     err = start (gpg);
1897
1898   return err;
1899 }
1900
1901
1902 static gpgme_error_t
1903 gpg_export_ext (void *engine, const char *pattern[], gpgme_export_mode_t mode,
1904                 gpgme_data_t keydata, int use_armor)
1905 {
1906   engine_gpg_t gpg = engine;
1907   gpgme_error_t err;
1908
1909   err = export_common (gpg, mode, keydata, use_armor);
1910
1911   if (pattern)
1912     {
1913       while (!err && *pattern && **pattern)
1914         err = add_arg (gpg, *(pattern++));
1915     }
1916
1917   if (!err)
1918     err = start (gpg);
1919
1920   return err;
1921 }
1922
1923
1924 static gpgme_error_t
1925 gpg_genkey (void *engine, gpgme_data_t help_data, int use_armor,
1926             gpgme_data_t pubkey, gpgme_data_t seckey)
1927 {
1928   engine_gpg_t gpg = engine;
1929   gpgme_error_t err;
1930
1931   if (!gpg)
1932     return gpg_error (GPG_ERR_INV_VALUE);
1933
1934   /* We need a special mechanism to get the fd of a pipe here, so that
1935      we can use this for the %pubring and %secring parameters.  We
1936      don't have this yet, so we implement only the adding to the
1937      standard keyrings.  */
1938   if (pubkey || seckey)
1939     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1940
1941   err = add_arg (gpg, "--gen-key");
1942   if (!err && use_armor)
1943     err = add_arg (gpg, "--armor");
1944   if (!err)
1945     err = add_arg (gpg, "--");
1946   if (!err)
1947     err = add_data (gpg, help_data, -1, 0);
1948
1949   if (!err)
1950     err = start (gpg);
1951
1952   return err;
1953 }
1954
1955 /* Return the next DELIM delimited string from DATA as a C-string.
1956    The caller needs to provide the address of a pointer variable which
1957    he has to set to NULL before the first call.  After the last call
1958    to this function, this function needs to be called once more with
1959    DATA set to NULL so that the function can release its internal
1960    state.  After that the pointer variable is free for use again.
1961    Note that we use a delimiter and thus a trailing delimiter is not
1962    required.  DELIM may not be changed after the first call. */
1963 static const char *
1964 string_from_data (gpgme_data_t data, int delim,
1965                   void **helpptr, gpgme_error_t *r_err)
1966 {
1967 #define MYBUFLEN 2000 /* Fixme: We don't support URLs longer than that.  */
1968   struct {
1969     int  eof_seen;
1970     int  nbytes;      /* Length of the last returned string including
1971                          the delimiter. */
1972     int  buflen;      /* Valid length of BUF.  */
1973     char buf[MYBUFLEN+1];  /* Buffer with one byte extra space.  */
1974   } *self;
1975   char *p;
1976   int nread;
1977
1978   *r_err = 0;
1979   if (!data)
1980     {
1981       if (*helpptr)
1982         {
1983           free (*helpptr);
1984           *helpptr = NULL;
1985         }
1986       return NULL;
1987     }
1988
1989   if (*helpptr)
1990     self = *helpptr;
1991   else
1992     {
1993       self = malloc (sizeof *self);
1994       if (!self)
1995         {
1996           *r_err = gpg_error_from_syserror ();
1997           return NULL;
1998         }
1999       *helpptr = self;
2000       self->eof_seen = 0;
2001       self->nbytes = 0;
2002       self->buflen = 0;
2003     }
2004
2005   if (self->eof_seen)
2006     return NULL;
2007
2008   assert (self->nbytes <= self->buflen);
2009   memmove (self->buf, self->buf + self->nbytes, self->buflen - self->nbytes);
2010   self->buflen -= self->nbytes;
2011   self->nbytes = 0;
2012
2013   do
2014     {
2015       /* Fixme: This is fairly infective scanning because we may scan
2016          the buffer several times.  */
2017       p = memchr (self->buf, delim, self->buflen);
2018       if (p)
2019         {
2020           *p = 0;
2021           self->nbytes = p - self->buf + 1;
2022           return self->buf;
2023         }
2024
2025       if ( !(MYBUFLEN - self->buflen) )
2026         {
2027           /* Not enough space - URL too long.  */
2028           *r_err = gpg_error (GPG_ERR_TOO_LARGE);
2029           return NULL;
2030         }
2031
2032       nread = gpgme_data_read (data, self->buf + self->buflen,
2033                                MYBUFLEN - self->buflen);
2034       if (nread < 0)
2035         {
2036           *r_err = gpg_error_from_syserror ();
2037           return NULL;
2038         }
2039       self->buflen += nread;
2040     }
2041   while (nread);
2042
2043   /* EOF reached.  If we have anything in the buffer, append a Nul and
2044      return it. */
2045   self->eof_seen = 1;
2046   if (self->buflen)
2047     {
2048       self->buf[self->buflen] = 0;  /* (we allocated one extra byte)  */
2049       return self->buf;
2050     }
2051   return NULL;
2052 #undef MYBUFLEN
2053 }
2054
2055
2056
2057 static gpgme_error_t
2058 gpg_import (void *engine, gpgme_data_t keydata, gpgme_key_t *keyarray)
2059 {
2060   engine_gpg_t gpg = engine;
2061   gpgme_error_t err;
2062   int idx;
2063   gpgme_data_encoding_t dataenc;
2064
2065   if (keydata && keyarray)
2066     return gpg_error (GPG_ERR_INV_VALUE); /* Only one is allowed.  */
2067
2068   dataenc = gpgme_data_get_encoding (keydata);
2069
2070   if (keyarray)
2071     {
2072       err = add_arg (gpg, "--recv-keys");
2073       if (!err)
2074         err = add_arg (gpg, "--");
2075       for (idx=0; !err && keyarray[idx]; idx++)
2076         {
2077           if (keyarray[idx]->protocol != GPGME_PROTOCOL_OpenPGP)
2078             ;
2079           else if (!keyarray[idx]->subkeys)
2080             ;
2081           else if (keyarray[idx]->subkeys->fpr && *keyarray[idx]->subkeys->fpr)
2082             err = add_arg (gpg, keyarray[idx]->subkeys->fpr);
2083           else if (*keyarray[idx]->subkeys->keyid)
2084             err = add_arg (gpg, keyarray[idx]->subkeys->keyid);
2085         }
2086     }
2087   else if (dataenc == GPGME_DATA_ENCODING_URL
2088            || dataenc == GPGME_DATA_ENCODING_URL0)
2089     {
2090       void *helpptr;
2091       const char *string;
2092       gpgme_error_t xerr;
2093       int delim = (dataenc == GPGME_DATA_ENCODING_URL)? '\n': 0;
2094
2095       /* FIXME: --fetch-keys is probably not correct because it can't
2096          grok all kinds of URLs.  On Unix it should just work but on
2097          Windows we will build the command line and that may fail for
2098          some embedded control characters.  It is anyway limited to
2099          the maximum size of the command line.  We need another
2100          command which can take its input from a file.  Maybe we
2101          should use an option to gpg to modify such commands (ala
2102          --multifile).  */
2103       err = add_arg (gpg, "--fetch-keys");
2104       if (!err)
2105         err = add_arg (gpg, "--");
2106       helpptr = NULL;
2107       while (!err
2108              && (string = string_from_data (keydata, delim, &helpptr, &xerr)))
2109         err = add_arg (gpg, string);
2110       if (!err)
2111         err = xerr;
2112       string_from_data (NULL, delim, &helpptr, &xerr);
2113     }
2114   else if (dataenc == GPGME_DATA_ENCODING_URLESC)
2115     {
2116       /* Already escaped URLs are not yet supported.  */
2117       err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
2118     }
2119   else
2120     {
2121       err = add_arg (gpg, "--import");
2122       if (!err)
2123         err = add_arg (gpg, "--");
2124       if (!err)
2125         err = add_data (gpg, keydata, -1, 0);
2126     }
2127
2128   if (!err)
2129     err = start (gpg);
2130
2131   return err;
2132 }
2133
2134
2135 /* The output for external keylistings in GnuPG is different from all
2136    the other key listings.  We catch this here with a special
2137    preprocessor that reformats the colon handler lines.  */
2138 static gpgme_error_t
2139 gpg_keylist_preprocess (char *line, char **r_line)
2140 {
2141   enum
2142     {
2143       RT_NONE, RT_INFO, RT_PUB, RT_UID
2144     }
2145   rectype = RT_NONE;
2146 #define NR_FIELDS 16
2147   char *field[NR_FIELDS];
2148   int fields = 0;
2149   size_t n;
2150
2151   *r_line = NULL;
2152
2153   while (line && fields < NR_FIELDS)
2154     {
2155       field[fields++] = line;
2156       line = strchr (line, ':');
2157       if (line)
2158         *(line++) = '\0';
2159     }
2160
2161   if (!strcmp (field[0], "info"))
2162     rectype = RT_INFO;
2163   else if (!strcmp (field[0], "pub"))
2164     rectype = RT_PUB;
2165   else if (!strcmp (field[0], "uid"))
2166     rectype = RT_UID;
2167   else
2168     rectype = RT_NONE;
2169
2170   switch (rectype)
2171     {
2172     case RT_INFO:
2173       /* FIXME: Eventually, check the version number at least.  */
2174       return 0;
2175
2176     case RT_PUB:
2177       if (fields < 7)
2178         return 0;
2179
2180       /* The format is:
2181
2182          pub:<keyid>:<algo>:<keylen>:<creationdate>:<expirationdate>:<flags>
2183
2184          as defined in 5.2. Machine Readable Indexes of the OpenPGP
2185          HTTP Keyserver Protocol (draft).  Modern versions of the SKS
2186          keyserver return the fingerprint instead of the keyid.  We
2187          detect this here and use the v4 fingerprint format to convert
2188          it to a key id.
2189
2190          We want:
2191          pub:o<flags>:<keylen>:<algo>:<keyid>:<creatdate>:<expdate>::::::::
2192       */
2193
2194       n = strlen (field[1]);
2195       if (n > 16)
2196         {
2197           if (asprintf (r_line,
2198                         "pub:o%s:%s:%s:%s:%s:%s::::::::\n"
2199                         "fpr:::::::::%s:",
2200                         field[6], field[3], field[2], field[1] + n - 16,
2201                         field[4], field[5], field[1]) < 0)
2202             return gpg_error_from_syserror ();
2203         }
2204       else
2205         {
2206           if (asprintf (r_line,
2207                         "pub:o%s:%s:%s:%s:%s:%s::::::::",
2208                         field[6], field[3], field[2], field[1],
2209                         field[4], field[5]) < 0)
2210             return gpg_error_from_syserror ();
2211         }
2212
2213       return 0;
2214
2215     case RT_UID:
2216       /* The format is:
2217
2218          uid:<escaped uid string>:<creationdate>:<expirationdate>:<flags>
2219
2220          as defined in 5.2. Machine Readable Indexes of the OpenPGP
2221          HTTP Keyserver Protocol (draft).
2222
2223          We want:
2224          uid:o<flags>::::<creatdate>:<expdate>:::<c-coded uid>:
2225       */
2226
2227       {
2228         /* The user ID is percent escaped, but we want c-coded.
2229            Because we have to replace each '%HL' by '\xHL', we need at
2230            most 4/3 th the number of bytes.  But because we also need
2231            to escape the backslashes we allocate twice as much.  */
2232         char *uid = malloc (2 * strlen (field[1]) + 1);
2233         char *src;
2234         char *dst;
2235
2236         if (! uid)
2237           return gpg_error_from_syserror ();
2238         src = field[1];
2239         dst = uid;
2240         while (*src)
2241           {
2242             if (*src == '%')
2243               {
2244                 *(dst++) = '\\';
2245                 *(dst++) = 'x';
2246                 src++;
2247                 /* Copy the next two bytes unconditionally.  */
2248                 if (*src)
2249                   *(dst++) = *(src++);
2250                 if (*src)
2251                   *(dst++) = *(src++);
2252               }
2253             else if (*src == '\\')
2254               {
2255                 *dst++ = '\\';
2256                 *dst++ = '\\';
2257                 src++;
2258               }
2259             else
2260               *(dst++) = *(src++);
2261           }
2262         *dst = '\0';
2263
2264         if (asprintf (r_line, "uid:o%s::::%s:%s:::%s:",
2265                       field[4], field[2], field[3], uid) < 0)
2266           return gpg_error_from_syserror ();
2267       }
2268       return 0;
2269
2270     case RT_NONE:
2271       /* Unknown record.  */
2272       break;
2273     }
2274   return 0;
2275
2276 }
2277
2278
2279 static gpg_error_t
2280 gpg_keylist_build_options (engine_gpg_t gpg, int secret_only,
2281                            gpgme_keylist_mode_t mode)
2282 {
2283   gpg_error_t err;
2284
2285   err = add_arg (gpg, "--with-colons");
2286   if (!err)
2287     err = add_arg (gpg, "--fixed-list-mode");
2288   if (!err)
2289     err = add_arg (gpg, "--with-fingerprint");
2290   if (!err)
2291     err = add_arg (gpg, "--with-fingerprint");
2292   if (!err && (mode & GPGME_KEYLIST_MODE_WITH_SECRET))
2293     err = add_arg (gpg, "--with-secret");
2294   if (!err
2295       && (mode & GPGME_KEYLIST_MODE_SIGS)
2296       && (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS))
2297     {
2298       err = add_arg (gpg, "--list-options");
2299       if (!err)
2300         err = add_arg (gpg, "show-sig-subpackets=\"20,26\"");
2301     }
2302   if (!err)
2303     {
2304       if ( (mode & GPGME_KEYLIST_MODE_EXTERN) )
2305         {
2306           if (secret_only)
2307             err = gpg_error (GPG_ERR_NOT_SUPPORTED);
2308           else if ( (mode & GPGME_KEYLIST_MODE_LOCAL))
2309             {
2310               /* The local+extern mode is special.  It works only with
2311                  gpg >= 2.0.10.  FIXME: We should check that we have
2312                  such a version to that we can return a proper error
2313                  code.  The problem is that we don't know the context
2314                  here and thus can't access the cached version number
2315                  for the engine info structure.  */
2316               err = add_arg (gpg, "--locate-keys");
2317               if ((mode & GPGME_KEYLIST_MODE_SIGS))
2318                 err = add_arg (gpg, "--with-sig-check");
2319             }
2320           else
2321             {
2322               err = add_arg (gpg, "--search-keys");
2323               gpg->colon.preprocess_fnc = gpg_keylist_preprocess;
2324             }
2325         }
2326       else
2327         {
2328           err = add_arg (gpg, secret_only ? "--list-secret-keys"
2329                          : ((mode & GPGME_KEYLIST_MODE_SIGS)
2330                             ? "--check-sigs" : "--list-keys"));
2331         }
2332     }
2333   if (!err)
2334     err = add_arg (gpg, "--");
2335
2336   return err;
2337 }
2338
2339
2340 static gpgme_error_t
2341 gpg_keylist (void *engine, const char *pattern, int secret_only,
2342              gpgme_keylist_mode_t mode, int engine_flags)
2343 {
2344   engine_gpg_t gpg = engine;
2345   gpgme_error_t err;
2346
2347   err = gpg_keylist_build_options (gpg, secret_only, mode);
2348
2349   if (!err && pattern && *pattern)
2350     err = add_arg (gpg, pattern);
2351
2352   if (!err)
2353     err = start (gpg);
2354
2355   return err;
2356 }
2357
2358
2359 static gpgme_error_t
2360 gpg_keylist_ext (void *engine, const char *pattern[], int secret_only,
2361                  int reserved, gpgme_keylist_mode_t mode, int engine_flags)
2362 {
2363   engine_gpg_t gpg = engine;
2364   gpgme_error_t err;
2365
2366   if (reserved)
2367     return gpg_error (GPG_ERR_INV_VALUE);
2368
2369   err = gpg_keylist_build_options (gpg, secret_only, mode);
2370
2371   if (pattern)
2372     {
2373       while (!err && *pattern && **pattern)
2374         err = add_arg (gpg, *(pattern++));
2375     }
2376
2377   if (!err)
2378     err = start (gpg);
2379
2380   return err;
2381 }
2382
2383
2384 static gpgme_error_t
2385 gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
2386           gpgme_sig_mode_t mode, int use_armor, int use_textmode,
2387           int include_certs, gpgme_ctx_t ctx /* FIXME */)
2388 {
2389   engine_gpg_t gpg = engine;
2390   gpgme_error_t err;
2391
2392   if (mode == GPGME_SIG_MODE_CLEAR)
2393     err = add_arg (gpg, "--clearsign");
2394   else
2395     {
2396       err = add_arg (gpg, "--sign");
2397       if (!err && mode == GPGME_SIG_MODE_DETACH)
2398         err = add_arg (gpg, "--detach");
2399       if (!err && use_armor)
2400         err = add_arg (gpg, "--armor");
2401       if (!err)
2402         {
2403           if (gpgme_data_get_encoding (in) == GPGME_DATA_ENCODING_MIME
2404               && have_gpg_version (gpg, "2.1.14"))
2405             err = add_arg (gpg, "--mimemode");
2406           else if (use_textmode)
2407             err = add_arg (gpg, "--textmode");
2408         }
2409     }
2410
2411   if (!err)
2412     err = append_args_from_signers (gpg, ctx);
2413   if (!err)
2414     err = append_args_from_sig_notations (gpg, ctx);
2415
2416   if (gpgme_data_get_file_name (in))
2417     {
2418       if (!err)
2419         err = add_arg (gpg, "--set-filename");
2420       if (!err)
2421         err = add_arg (gpg, gpgme_data_get_file_name (in));
2422     }
2423
2424   /* Tell the gpg object about the data.  */
2425   if (!err)
2426     err = add_arg (gpg, "--");
2427   if (!err)
2428     err = add_data (gpg, in, -1, 0);
2429   if (!err)
2430     err = add_data (gpg, out, 1, 1);
2431
2432   if (!err)
2433     err = start (gpg);
2434
2435   return err;
2436 }
2437
2438 static gpgme_error_t
2439 gpg_trustlist (void *engine, const char *pattern)
2440 {
2441   engine_gpg_t gpg = engine;
2442   gpgme_error_t err;
2443
2444   err = add_arg (gpg, "--with-colons");
2445   if (!err)
2446     err = add_arg (gpg, "--list-trust-path");
2447
2448   /* Tell the gpg object about the data.  */
2449   if (!err)
2450     err = add_arg (gpg, "--");
2451   if (!err)
2452     err = add_arg (gpg, pattern);
2453
2454   if (!err)
2455     err = start (gpg);
2456
2457   return err;
2458 }
2459
2460
2461 static gpgme_error_t
2462 gpg_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text,
2463             gpgme_data_t plaintext)
2464 {
2465   engine_gpg_t gpg = engine;
2466   gpgme_error_t err = 0;
2467
2468   if (plaintext)
2469     {
2470       /* Normal or cleartext signature.  */
2471
2472       err = add_arg (gpg, "--output");
2473       if (!err)
2474         err = add_arg (gpg, "-");
2475       if (!err)
2476         err = add_arg (gpg, "--");
2477       if (!err)
2478         err = add_data (gpg, sig, -1, 0);
2479       if (!err)
2480         err = add_data (gpg, plaintext, 1, 1);
2481     }
2482   else
2483     {
2484       err = add_arg (gpg, "--verify");
2485       if (!err)
2486         err = add_arg (gpg, "--");
2487       if (!err)
2488         err = add_data (gpg, sig, -1, 0);
2489       if (!err && signed_text)
2490         err = add_data (gpg, signed_text, -1, 0);
2491     }
2492
2493   if (!err)
2494     err = start (gpg);
2495
2496   return err;
2497 }
2498
2499
2500 static void
2501 gpg_set_io_cbs (void *engine, gpgme_io_cbs_t io_cbs)
2502 {
2503   engine_gpg_t gpg = engine;
2504
2505   gpg->io_cbs = *io_cbs;
2506 }
2507
2508
2509 static gpgme_error_t
2510 gpg_set_pinentry_mode (void *engine, gpgme_pinentry_mode_t mode)
2511 {
2512   engine_gpg_t gpg = engine;
2513
2514   gpg->pinentry_mode = mode;
2515   return 0;
2516 }
2517
2518
2519 \f
2520 struct engine_ops _gpgme_engine_ops_gpg =
2521   {
2522     /* Static functions.  */
2523     _gpgme_get_default_gpg_name,
2524     NULL,
2525     gpg_get_version,
2526     gpg_get_req_version,
2527     gpg_new,
2528
2529     /* Member functions.  */
2530     gpg_release,
2531     NULL,                               /* reset */
2532     gpg_set_status_cb,
2533     gpg_set_status_handler,
2534     gpg_set_command_handler,
2535     gpg_set_colon_line_handler,
2536     gpg_set_locale,
2537     NULL,                               /* set_protocol */
2538     gpg_decrypt,
2539     gpg_decrypt,                        /* decrypt_verify */
2540     gpg_delete,
2541     gpg_edit,
2542     gpg_encrypt,
2543     gpg_encrypt_sign,
2544     gpg_export,
2545     gpg_export_ext,
2546     gpg_genkey,
2547     gpg_import,
2548     gpg_keylist,
2549     gpg_keylist_ext,
2550     gpg_sign,
2551     gpg_trustlist,
2552     gpg_verify,
2553     NULL,               /* getauditlog */
2554     NULL,               /* opassuan_transact */
2555     NULL,               /* conf_load */
2556     NULL,               /* conf_save */
2557     gpg_set_io_cbs,
2558     gpg_io_event,
2559     gpg_cancel,
2560     NULL,               /* cancel_op */
2561     gpg_passwd,
2562     gpg_set_pinentry_mode,
2563     NULL                /* opspawn */
2564   };