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