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