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