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