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