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