doc/
[gpgme.git] / gpgme / rungpg.c
1 /* rungpg.c - Gpg Engine.
2    Copyright (C) 2000 Werner Koch (dd9jn)
3    Copyright (C) 2001, 2002, 2003 g10 Code GmbH
4  
5    This file is part of GPGME.
6  
7    GPGME is free software; you can redistribute it and/or modify it
8    under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11  
12    GPGME is distributed in the hope that it will be useful, but
13    WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    General Public License for more details.
16  
17    You should have received a copy of the GNU General Public License
18    along with GPGME; if not, write to the Free Software Foundation,
19    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21 #if HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <assert.h>
28 #include <errno.h>
29 #include <time.h>
30 #include <sys/time.h>
31 #include <sys/types.h>
32 #include <signal.h>
33 #include <fcntl.h>
34 #include "unistd.h"
35
36 #include "gpgme.h"
37 #include "util.h"
38 #include "ops.h"
39 #include "wait.h"
40 #include "context.h"  /*temp hack until we have GpmeData methods to do I/O */
41 #include "io.h"
42 #include "sema.h"
43 #include "debug.h"
44
45 #include "status-table.h"
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   char arg[1];     /* Used if data above is not used.  */
59 };
60
61
62 struct fd_data_map_s
63 {
64   gpgme_data_t data;
65   int inbound;  /* true if this is used for reading from gpg */
66   int dup_to;
67   int fd;       /* the fd to use */
68   int peer_fd;  /* the outher side of the pipe */
69   void *tag;
70 };
71
72
73 struct engine_gpg
74 {
75   struct arg_and_data_s *arglist;
76   struct arg_and_data_s **argtail;
77   int arg_error;
78
79   struct
80   {
81     int fd[2];  
82     size_t bufsize;
83     char *buffer;
84     size_t readpos;
85     int eof;
86     engine_status_handler_t fnc;
87     void *fnc_value;
88     void *tag;
89   } status;
90
91   /* This is a kludge - see the comment at colon_line_handler.  */
92   struct
93   {
94     int fd[2];  
95     size_t bufsize;
96     char *buffer;
97     size_t readpos;
98     int eof;
99     engine_colon_line_handler_t fnc;  /* this indicate use of this structrue */
100     void *fnc_value;
101     void *tag;
102   } colon;
103
104   char **argv;  
105   struct fd_data_map_s *fd_data_map;
106
107   /* stuff needed for interactive (command) mode */
108   struct
109   {
110     int used;
111     int fd;
112     void *cb_data;
113     int idx;            /* Index in fd_data_map */
114     gpgme_status_code_t code;  /* last code */
115     char *keyword;       /* what has been requested (malloced) */
116     engine_command_handler_t fnc; 
117     void *fnc_value;
118     /* The kludges never end.  This is used to couple command handlers
119        with output data in edit key mode.  */
120     gpgme_data_t linked_data;
121     int linked_idx;
122   } cmd;
123
124   struct gpgme_io_cbs io_cbs;
125 };
126
127 typedef struct engine_gpg *engine_gpg_t;
128
129 \f
130 static void
131 gpg_io_event (void *engine, gpgme_event_io_t type, void *type_data)
132 {
133   engine_gpg_t gpg = engine;
134
135   if (gpg->io_cbs.event)
136     (*gpg->io_cbs.event) (gpg->io_cbs.event_priv, type, type_data);
137 }
138
139
140 static void
141 close_notify_handler (int fd, void *opaque)
142 {
143   engine_gpg_t gpg = opaque;
144   assert (fd != -1);
145
146   if (gpg->status.fd[0] == fd)
147     {
148       if (gpg->status.tag)
149         (*gpg->io_cbs.remove) (gpg->status.tag);
150       gpg->status.fd[0] = -1;
151     }
152   else if (gpg->status.fd[1] == fd)
153     gpg->status.fd[1] = -1;
154   else if (gpg->colon.fd[0] == fd)
155     {
156       if (gpg->colon.tag)
157         (*gpg->io_cbs.remove) (gpg->colon.tag);
158       gpg->colon.fd[0] = -1;
159     }
160   else if (gpg->colon.fd[1] == fd)
161     gpg->colon.fd[1] = -1;
162   else if (gpg->fd_data_map)
163     {
164       int i;
165
166       for (i = 0; gpg->fd_data_map[i].data; i++)
167         {
168           if (gpg->fd_data_map[i].fd == fd)
169             {
170               if (gpg->fd_data_map[i].tag)
171                 (*gpg->io_cbs.remove) (gpg->fd_data_map[i].tag);
172               gpg->fd_data_map[i].fd = -1;
173               break;
174             }
175           if (gpg->fd_data_map[i].peer_fd == fd)
176             {
177               gpg->fd_data_map[i].peer_fd = -1;
178               break;
179             }
180         }
181     }
182 }
183
184 static gpgme_error_t
185 add_arg (engine_gpg_t gpg, const char *arg)
186 {
187   struct arg_and_data_s *a;
188
189   assert (gpg);
190   assert (arg);
191
192   a = malloc (sizeof *a + strlen (arg));
193   if (!a)
194     {
195       gpg->arg_error = 1;
196       return gpg_error_from_errno (errno);
197     }
198   a->next = NULL;
199   a->data = NULL;
200   a->dup_to = -1;
201   strcpy (a->arg, arg);
202   *gpg->argtail = a;
203   gpg->argtail = &a->next;
204   return 0;
205 }
206
207 static gpgme_error_t
208 add_data (engine_gpg_t gpg, gpgme_data_t data, int dup_to, int inbound)
209 {
210   struct arg_and_data_s *a;
211
212   assert (gpg);
213   assert (data);
214
215   a = malloc (sizeof *a - 1);
216   if (!a)
217     {
218       gpg->arg_error = 1;
219       return gpg_error_from_errno (errno);
220     }
221   a->next = NULL;
222   a->data = data;
223   a->inbound = inbound;
224   if (dup_to == -2)
225     {
226       a->print_fd = 1;
227       a->dup_to = -1;
228     }
229   else
230     {
231       a->print_fd = 0;
232       a->dup_to = dup_to;
233     }
234   *gpg->argtail = a;
235   gpg->argtail = &a->next;
236   return 0;
237 }
238
239 \f
240 static const char *
241 gpg_get_version (void)
242 {
243   static const char *gpg_version;
244   DEFINE_STATIC_LOCK (gpg_version_lock);
245
246   LOCK (gpg_version_lock);
247   if (!gpg_version)
248     gpg_version = _gpgme_get_program_version (_gpgme_get_gpg_path ());
249   UNLOCK (gpg_version_lock);
250   return gpg_version;
251 }
252
253
254 static const char *
255 gpg_get_req_version (void)
256 {
257   return NEED_GPG_VERSION;
258 }
259
260
261 static void
262 free_argv (char **argv)
263 {
264   int i;
265
266   for (i = 0; argv[i]; i++)
267     free (argv[i]);
268   free (argv);
269 }
270
271
272 static void
273 free_fd_data_map (struct fd_data_map_s *fd_data_map)
274 {
275   int i;
276
277   if (!fd_data_map)
278     return;
279
280   for (i = 0; fd_data_map[i].data; i++)
281     {
282       if (fd_data_map[i].fd != -1)
283         _gpgme_io_close (fd_data_map[i].fd);
284       if (fd_data_map[i].peer_fd != -1)
285         _gpgme_io_close (fd_data_map[i].peer_fd);
286       /* Don't release data because this is only a reference.  */
287     }
288   free (fd_data_map);
289 }
290
291
292 static void
293 gpg_release (void *engine)
294 {
295   engine_gpg_t gpg = engine;
296
297   if (!gpg)
298     return;
299
300   while (gpg->arglist)
301     {
302       struct arg_and_data_s *next = gpg->arglist->next;
303
304       if (gpg->arglist)
305         free (gpg->arglist);
306       gpg->arglist = next;
307     }
308
309   if (gpg->status.buffer)
310     free (gpg->status.buffer);
311   if (gpg->colon.buffer)
312     free (gpg->colon.buffer);
313   if (gpg->argv)
314     free_argv (gpg->argv);
315   if (gpg->cmd.keyword)
316     free (gpg->cmd.keyword);
317
318   if (gpg->status.fd[0] != -1)
319     _gpgme_io_close (gpg->status.fd[0]);
320   if (gpg->status.fd[1] != -1)
321     _gpgme_io_close (gpg->status.fd[1]);
322   if (gpg->colon.fd[0] != -1)
323     _gpgme_io_close (gpg->colon.fd[0]);
324   if (gpg->colon.fd[1] != -1)
325     _gpgme_io_close (gpg->colon.fd[1]);
326   if (gpg->fd_data_map)
327     free_fd_data_map (gpg->fd_data_map);
328   if (gpg->cmd.fd != -1)
329     _gpgme_io_close (gpg->cmd.fd);
330   free (gpg);
331 }
332
333
334 static gpgme_error_t
335 gpg_new (void **engine)
336 {
337   engine_gpg_t gpg;
338   gpgme_error_t rc = 0;
339
340   gpg = calloc (1, sizeof *gpg);
341   if (!gpg)
342     return gpg_error_from_errno (errno);
343
344   gpg->argtail = &gpg->arglist;
345   gpg->status.fd[0] = -1;
346   gpg->status.fd[1] = -1;
347   gpg->colon.fd[0] = -1;
348   gpg->colon.fd[1] = -1;
349   gpg->cmd.fd = -1;
350   gpg->cmd.idx = -1;
351   gpg->cmd.linked_data = NULL;
352   gpg->cmd.linked_idx = -1;
353
354   /* Allocate the read buffer for the status pipe.  */
355   gpg->status.bufsize = 1024;
356   gpg->status.readpos = 0;
357   gpg->status.buffer = malloc (gpg->status.bufsize);
358   if (!gpg->status.buffer)
359     {
360       rc = gpg_error_from_errno (errno);
361       goto leave;
362     }
363   /* In any case we need a status pipe - create it right here and
364      don't handle it with our generic gpgme_data_t mechanism.  */
365   if (_gpgme_io_pipe (gpg->status.fd, 1) == -1)
366     {
367       rc = gpg_error_from_errno (errno);
368       goto leave;
369     }
370   if (_gpgme_io_set_close_notify (gpg->status.fd[0],
371                                   close_notify_handler, gpg)
372       || _gpgme_io_set_close_notify (gpg->status.fd[1],
373                                      close_notify_handler, gpg))
374     {
375       rc = gpg_error (GPG_ERR_GENERAL);
376       goto leave;
377     }
378   gpg->status.eof = 0;
379   add_arg (gpg, "--status-fd");
380   {
381     char buf[25];
382     sprintf (buf, "%d", gpg->status.fd[1]);
383     add_arg (gpg, buf);
384   }
385   add_arg (gpg, "--no-tty");
386   add_arg (gpg, "--charset");
387   add_arg (gpg, "utf8");
388   add_arg (gpg, "--enable-progress-filter");
389
390  leave:
391   if (rc)
392     gpg_release (gpg);
393   else
394     *engine = gpg;
395   return rc;
396 }
397
398
399 /* Note, that the status_handler is allowed to modifiy the args
400    value.  */
401 static void
402 gpg_set_status_handler (void *engine, engine_status_handler_t fnc,
403                         void *fnc_value)
404 {
405   engine_gpg_t gpg = engine;
406
407   gpg->status.fnc = fnc;
408   gpg->status.fnc_value = fnc_value;
409 }
410
411 /* Kludge to process --with-colon output.  */
412 static gpgme_error_t
413 gpg_set_colon_line_handler (void *engine, engine_colon_line_handler_t fnc,
414                             void *fnc_value)
415 {
416   engine_gpg_t gpg = engine;
417
418   gpg->colon.bufsize = 1024;
419   gpg->colon.readpos = 0;
420   gpg->colon.buffer = malloc (gpg->colon.bufsize);
421   if (!gpg->colon.buffer)
422     return gpg_error_from_errno (errno);
423
424   if (_gpgme_io_pipe (gpg->colon.fd, 1) == -1) 
425     {
426       int saved_errno = errno;
427       free (gpg->colon.buffer);
428       gpg->colon.buffer = NULL;
429       return gpg_error_from_errno (saved_errno);
430     }
431   if (_gpgme_io_set_close_notify (gpg->colon.fd[0], close_notify_handler, gpg)
432       || _gpgme_io_set_close_notify (gpg->colon.fd[1],
433                                      close_notify_handler, gpg))
434     return gpg_error (GPG_ERR_GENERAL);
435   gpg->colon.eof = 0;
436   gpg->colon.fnc = fnc;
437   gpg->colon.fnc_value = fnc_value;
438   return 0;
439 }
440
441
442 static gpgme_error_t
443 command_handler (void *opaque, int fd)
444 {
445   gpgme_error_t err;
446   engine_gpg_t gpg = (engine_gpg_t) opaque;
447
448   assert (gpg->cmd.used);
449   assert (gpg->cmd.code);
450   assert (gpg->cmd.fnc);
451
452   err = gpg->cmd.fnc (gpg->cmd.fnc_value, gpg->cmd.code, gpg->cmd.keyword, fd);
453   if (err)
454     return err;
455
456   gpg->cmd.code = 0;
457   /* And sleep again until read_status will wake us up again.  */
458   /* XXX We must check if there are any more fds active after removing
459      this one.  */
460   (*gpg->io_cbs.remove) (gpg->fd_data_map[gpg->cmd.idx].tag);
461   gpg->cmd.fd = gpg->fd_data_map[gpg->cmd.idx].fd;
462   gpg->fd_data_map[gpg->cmd.idx].fd = -1;
463
464   return 0;
465 }
466
467
468
469 /* The Fnc will be called to get a value for one of the commands with
470    a key KEY.  If the Code pssed to FNC is 0, the function may release
471    resources associated with the returned value from another call.  To
472    match such a second call to a first call, the returned value from
473    the first call is passed as keyword.  */
474 static gpgme_error_t
475 gpg_set_command_handler (void *engine, engine_command_handler_t fnc,
476                          void *fnc_value, gpgme_data_t linked_data)
477 {
478   engine_gpg_t gpg = engine;
479
480   add_arg (gpg, "--command-fd");
481   /* This is a hack.  We don't have a real data object.  The only
482      thing that matters is that we use something unique, so we use the
483      address of the cmd structure in the gpg object.  */
484   add_data (gpg, (void *) &gpg->cmd, -2, 0);
485   gpg->cmd.fnc = fnc;
486   gpg->cmd.cb_data = (void *) &gpg->cmd;
487   gpg->cmd.fnc_value = fnc_value;
488   gpg->cmd.linked_data = linked_data;
489   gpg->cmd.used = 1;
490   return 0;
491 }
492
493
494 static gpgme_error_t
495 build_argv (engine_gpg_t gpg)
496 {
497   struct arg_and_data_s *a;
498   struct fd_data_map_s *fd_data_map;
499   size_t datac=0, argc=0;  
500   char **argv;
501   int need_special = 0;
502   int use_agent = 0;
503   char *p;
504
505   /* We don't want to use the agent with a malformed environment
506      variable.  This is only a very basic test but sufficient to make
507      our life in the regression tests easier. */
508   p = getenv ("GPG_AGENT_INFO");
509   use_agent = (p && strchr (p, ':'));
510        
511   if (gpg->argv)
512     {
513       free_argv (gpg->argv);
514       gpg->argv = NULL;
515     }
516   if (gpg->fd_data_map)
517     {
518       free_fd_data_map (gpg->fd_data_map);
519       gpg->fd_data_map = NULL;
520     }
521
522   argc++;       /* For argv[0].  */
523   for (a = gpg->arglist; a; a = a->next)
524     {
525       argc++;
526       if (a->data)
527         {
528           /*fprintf (stderr, "build_argv: data\n" );*/
529           datac++;
530           if (a->dup_to == -1 && !a->print_fd)
531             need_special = 1;
532         }
533       else
534         {
535           /*   fprintf (stderr, "build_argv: arg=`%s'\n", a->arg );*/
536         }
537     }
538   if (need_special)
539     argc++;
540   if (use_agent)
541     argc++;
542   if (!gpg->cmd.used)
543     argc++;     /* --batch */
544   argc += 2; /* --comment */
545
546   argv = calloc (argc + 1, sizeof *argv);
547   if (!argv)
548     return gpg_error_from_errno (errno);
549   fd_data_map = calloc (datac + 1, sizeof *fd_data_map);
550   if (!fd_data_map)
551     {
552       int saved_errno = errno;
553       free_argv (argv);
554       return gpg_error_from_errno (saved_errno);
555     }
556
557   argc = datac = 0;
558   argv[argc] = strdup ("gpg"); /* argv[0] */
559   if (!argv[argc])
560     {
561       int saved_errno = errno;
562       free (fd_data_map);
563       free_argv (argv);
564       return gpg_error_from_errno (saved_errno);
565     }
566   argc++;
567   if (need_special)
568     {
569       argv[argc] = strdup ("--enable-special-filenames");
570       if (!argv[argc])
571         {
572           int saved_errno = errno;
573           free (fd_data_map);
574           free_argv (argv);
575           return gpg_error_from_errno (saved_errno);
576         }
577       argc++;
578     }
579   if (use_agent)
580     {
581       argv[argc] = strdup ("--use-agent");
582       if (!argv[argc])
583         {
584           int saved_errno = errno;
585           free (fd_data_map);
586           free_argv (argv);
587           return gpg_error_from_errno (saved_errno);
588         }
589       argc++;
590     }
591   if (!gpg->cmd.used)
592     {
593       argv[argc] = strdup ("--batch");
594       if (!argv[argc])
595         {
596           int saved_errno = errno;
597           free (fd_data_map);
598           free_argv (argv);
599           return gpg_error_from_errno (saved_errno);
600         }
601       argc++;
602     }
603   argv[argc] = strdup ("--comment");
604   if (!argv[argc])
605     {
606       int saved_errno = errno;
607       free (fd_data_map);
608       free_argv (argv);
609       return gpg_error_from_errno (saved_errno);
610     }
611   argc++;
612   argv[argc] = strdup ("");
613   if (!argv[argc])
614     {
615       int saved_errno = errno;
616       free (fd_data_map);
617       free_argv (argv);
618       return gpg_error_from_errno (saved_errno);
619     }
620   argc++;
621   for (a = gpg->arglist; a; a = a->next)
622     {
623       if (a->data)
624         {
625           /* Create a pipe to pass it down to gpg.  */
626           fd_data_map[datac].inbound = a->inbound;
627
628           /* Create a pipe.  */
629           {   
630             int fds[2];
631             
632             if (_gpgme_io_pipe (fds, fd_data_map[datac].inbound ? 1 : 0)
633                 == -1)
634               {
635                 int saved_errno = errno;
636                 free (fd_data_map);
637                 free_argv (argv);
638                 return gpg_error (saved_errno);
639               }
640             if (_gpgme_io_set_close_notify (fds[0],
641                                             close_notify_handler, gpg)
642                 || _gpgme_io_set_close_notify (fds[1],
643                                                close_notify_handler,
644                                                gpg))
645               {
646                 return gpg_error (GPG_ERR_GENERAL);
647               }
648             /* If the data_type is FD, we have to do a dup2 here.  */
649             if (fd_data_map[datac].inbound)
650               {
651                 fd_data_map[datac].fd       = fds[0];
652                 fd_data_map[datac].peer_fd  = fds[1];
653               }
654             else
655               {
656                 fd_data_map[datac].fd       = fds[1];
657                 fd_data_map[datac].peer_fd  = fds[0];
658               }
659           }
660
661           /* Hack to get hands on the fd later.  */
662           if (gpg->cmd.used)
663             {
664               if (gpg->cmd.cb_data == a->data)
665                 {
666                   assert (gpg->cmd.idx == -1);
667                   gpg->cmd.idx = datac;
668                 }
669               else if (gpg->cmd.linked_data == a->data)
670                 {
671                   assert (gpg->cmd.linked_idx == -1);
672                   gpg->cmd.linked_idx = datac;
673                 }
674             }
675
676           fd_data_map[datac].data = a->data;
677           fd_data_map[datac].dup_to = a->dup_to;
678           if (a->dup_to == -1)
679             {
680               argv[argc] = malloc (25);
681               if (!argv[argc])
682                 {
683                   int saved_errno = errno;
684                   free (fd_data_map);
685                   free_argv (argv);
686                   return gpg_error_from_errno (saved_errno);
687                 }
688               sprintf (argv[argc], 
689                        a->print_fd ? "%d" : "-&%d",
690                        fd_data_map[datac].peer_fd);
691               argc++;
692             }
693           datac++;
694         }
695       else
696         {
697           argv[argc] = strdup (a->arg);
698           if (!argv[argc])
699             {
700               int saved_errno = errno;
701               free (fd_data_map);
702               free_argv (argv);
703               return gpg_error_from_errno (saved_errno);
704             }
705             argc++;
706         }
707     }
708
709   gpg->argv = argv;
710   gpg->fd_data_map = fd_data_map;
711   return 0;
712 }
713
714
715 static gpgme_error_t
716 add_io_cb (engine_gpg_t gpg, int fd, int dir, gpgme_io_cb_t handler, void *data,
717            void **tag)
718 {
719   gpgme_error_t err;
720
721   err = (*gpg->io_cbs.add) (gpg->io_cbs.add_priv, fd, dir, handler, data, tag);
722   if (err)
723     return err;
724   if (!dir)
725     /* FIXME Kludge around poll() problem.  */
726     err = _gpgme_io_set_nonblocking (fd);
727   return err;
728 }
729
730
731 static int
732 status_cmp (const void *ap, const void *bp)
733 {
734   const struct status_table_s *a = ap;
735   const struct status_table_s *b = bp;
736
737   return strcmp (a->name, b->name);
738 }
739
740
741 /* Handle the status output of GnuPG.  This function does read entire
742    lines and passes them as C strings to the callback function (we can
743    use C Strings because the status output is always UTF-8 encoded).
744    Of course we have to buffer the lines to cope with long lines
745    e.g. with a large user ID.  Note: We can optimize this to only cope
746    with status line code we know about and skip all other stuff
747    without buffering (i.e. without extending the buffer).  */
748 static gpgme_error_t
749 read_status (engine_gpg_t gpg)
750 {
751   char *p;
752   int nread;
753   size_t bufsize = gpg->status.bufsize; 
754   char *buffer = gpg->status.buffer;
755   size_t readpos = gpg->status.readpos; 
756
757   assert (buffer);
758   if (bufsize - readpos < 256)
759     { 
760       /* Need more room for the read.  */
761       bufsize += 1024;
762       buffer = realloc (buffer, bufsize);
763       if (!buffer)
764         return gpg_error_from_errno (errno);
765     }
766
767   nread = _gpgme_io_read (gpg->status.fd[0],
768                           buffer + readpos, bufsize-readpos);
769   if (nread == -1)
770     return gpg_error_from_errno (errno);
771
772   if (!nread)
773     {
774       gpg->status.eof = 1;
775       if (gpg->status.fnc)
776         {
777           gpgme_error_t err;
778           err = gpg->status.fnc (gpg->status.fnc_value, GPGME_STATUS_EOF, "");
779           if (err)
780             return err;
781         }
782       return 0;
783     }
784
785   while (nread > 0)
786     {
787       for (p = buffer + readpos; nread; nread--, p++)
788         {
789           if (*p == '\n')
790             {
791               /* (we require that the last line is terminated by a LF) */
792               *p = 0;
793               if (!strncmp (buffer, "[GNUPG:] ", 9)
794                   && buffer[9] >= 'A' && buffer[9] <= 'Z')
795                 {
796                   struct status_table_s t, *r;
797                   char *rest;
798
799                   rest = strchr (buffer + 9, ' ');
800                   if (!rest)
801                     rest = p; /* Set to an empty string.  */
802                   else
803                     *rest++ = 0;
804                     
805                   t.name = buffer+9;
806                   /* (the status table has one extra element) */
807                   r = bsearch (&t, status_table, DIM(status_table) - 1,
808                                sizeof t, status_cmp);
809                   if (r)
810                     {
811                       if (gpg->cmd.used
812                           && (r->code == GPGME_STATUS_GET_BOOL
813                               || r->code == GPGME_STATUS_GET_LINE
814                               || r->code == GPGME_STATUS_GET_HIDDEN))
815                         {
816                           gpg->cmd.code = r->code;
817                           if (gpg->cmd.keyword)
818                             free (gpg->cmd.keyword);
819                           gpg->cmd.keyword = strdup (rest);
820                           if (!gpg->cmd.keyword)
821                             return gpg_error_from_errno (errno);
822                           /* This should be the last thing we have
823                              received and the next thing will be that
824                              the command handler does its action.  */
825                           if (nread > 1)
826                             DEBUG0 ("ERROR, unexpected data in read_status");
827
828                           /* Before we can actually add the command
829                              fd, we might have to flush the linked
830                              output data pipe.  */
831                           if (gpg->cmd.linked_idx != -1
832                               && gpg->fd_data_map[gpg->cmd.linked_idx].fd != -1)
833                             {
834                               struct io_select_fd_s fds;
835                               fds.fd = gpg->fd_data_map[gpg->cmd.linked_idx].fd;
836                               fds.for_read = 1;
837                               fds.for_write = 0;
838                               fds.frozen = 0;
839                               fds.opaque = NULL;
840                               do
841                                 {
842                                   fds.signaled = 0;
843                                   _gpgme_io_select (&fds, 1, 1);
844                                   if (fds.signaled)
845                                     _gpgme_data_inbound_handler
846                                       (gpg->cmd.linked_data, fds.fd);
847                                 }
848                               while (fds.signaled);
849                             }
850
851                           add_io_cb (gpg, gpg->cmd.fd, 0,
852                                      command_handler, gpg,
853                                      &gpg->fd_data_map[gpg->cmd.idx].tag);
854                           gpg->fd_data_map[gpg->cmd.idx].fd = gpg->cmd.fd;
855                           gpg->cmd.fd = -1;
856                         }
857                       else if (gpg->status.fnc)
858                         {
859                           gpgme_error_t err;
860                           err = gpg->status.fnc (gpg->status.fnc_value, 
861                                                  r->code, rest);
862                           if (err)
863                             return err;
864                         }
865                     
866                       if (r->code == GPGME_STATUS_END_STREAM)
867                         {
868                           if (gpg->cmd.used)
869                             {
870                               /* XXX We must check if there are any
871                                  more fds active after removing this
872                                  one.  */
873                               (*gpg->io_cbs.remove)
874                                 (gpg->fd_data_map[gpg->cmd.idx].tag);
875                               gpg->cmd.fd = gpg->fd_data_map[gpg->cmd.idx].fd;
876                               gpg->fd_data_map[gpg->cmd.idx].fd = -1;
877                             }
878                         }
879                     }
880                 }
881               /* To reuse the buffer for the next line we have to
882                  shift the remaining data to the buffer start and
883                  restart the loop Hmmm: We can optimize this function
884                  by looking forward in the buffer to see whether a
885                  second complete line is available and in this case
886                  avoid the memmove for this line.  */
887               nread--; p++;
888               if (nread)
889                 memmove (buffer, p, nread);
890               readpos = 0;
891               break; /* the for loop */
892             }
893           else
894             readpos++;
895         }
896     } 
897
898   /* Update the gpg object.  */
899   gpg->status.bufsize = bufsize;
900   gpg->status.buffer = buffer;
901   gpg->status.readpos = readpos;
902   return 0;
903 }
904
905
906 static gpgme_error_t
907 status_handler (void *opaque, int fd)
908 {
909   engine_gpg_t gpg = opaque;
910   int err;
911
912   assert (fd == gpg->status.fd[0]);
913   err = read_status (gpg);
914   if (err)
915     return err;
916   if (gpg->status.eof)
917     _gpgme_io_close (fd);
918   return 0;
919 }
920
921
922 static gpgme_error_t
923 read_colon_line (engine_gpg_t gpg)
924 {
925   char *p;
926   int nread;
927   size_t bufsize = gpg->colon.bufsize; 
928   char *buffer = gpg->colon.buffer;
929   size_t readpos = gpg->colon.readpos; 
930
931   assert (buffer);
932   if (bufsize - readpos < 256)
933     { 
934       /* Need more room for the read.  */
935       bufsize += 1024;
936       buffer = realloc (buffer, bufsize);
937       if (!buffer) 
938         return gpg_error_from_errno (errno);
939     }
940
941   nread = _gpgme_io_read (gpg->colon.fd[0], buffer+readpos, bufsize-readpos);
942   if (nread == -1)
943     return gpg_error_from_errno (errno);
944
945   if (!nread)
946     {
947       gpg->colon.eof = 1;
948       assert (gpg->colon.fnc);
949       gpg->colon.fnc (gpg->colon.fnc_value, NULL);
950       return 0;
951     }
952
953   while (nread > 0)
954     {
955       for (p = buffer + readpos; nread; nread--, p++)
956         {
957           if ( *p == '\n' )
958             {
959               /* (we require that the last line is terminated by a LF)
960                  and we skip empty lines.  Note: we use UTF8 encoding
961                  and escaping of special characters We require at
962                  least one colon to cope with some other printed
963                  information.  */
964               *p = 0;
965               if (*buffer && strchr (buffer, ':'))
966                 {
967                   assert (gpg->colon.fnc);
968                   gpg->colon.fnc (gpg->colon.fnc_value, buffer);
969                 }
970             
971               /* To reuse the buffer for the next line we have to
972                  shift the remaining data to the buffer start and
973                  restart the loop Hmmm: We can optimize this function
974                  by looking forward in the buffer to see whether a
975                  second complete line is available and in this case
976                  avoid the memmove for this line.  */
977               nread--; p++;
978               if (nread)
979                 memmove (buffer, p, nread);
980               readpos = 0;
981               break; /* The for loop.  */
982             }
983           else
984             readpos++;
985         }
986     } 
987
988   /* Update the gpg object.  */
989   gpg->colon.bufsize = bufsize;
990   gpg->colon.buffer  = buffer;
991   gpg->colon.readpos = readpos;
992   return 0;
993 }
994
995
996 /* This colonline handler thing is not the clean way to do it.  It
997    might be better to enhance the gpgme_data_t object to act as a wrapper
998    for a callback.  Same goes for the status thing.  For now we use
999    this thing here because it is easier to implement.  */
1000 static gpgme_error_t
1001 colon_line_handler (void *opaque, int fd)
1002 {
1003   engine_gpg_t gpg = opaque;
1004   gpgme_error_t rc = 0;
1005
1006   assert (fd == gpg->colon.fd[0]);
1007   rc = read_colon_line (gpg);
1008   if (rc)
1009     return rc;
1010   if (gpg->colon.eof)
1011     _gpgme_io_close (fd);
1012   return 0;
1013 }
1014
1015
1016 static gpgme_error_t
1017 start (engine_gpg_t gpg)
1018 {
1019   gpgme_error_t rc;
1020   int saved_errno;
1021   int i, n;
1022   int status;
1023   struct spawn_fd_item_s *fd_child_list, *fd_parent_list;
1024
1025   if (!gpg)
1026     return gpg_error (GPG_ERR_INV_VALUE);
1027
1028   if (! _gpgme_get_gpg_path ())
1029     return gpg_error (GPG_ERR_INV_ENGINE);
1030
1031   /* Kludge, so that we don't need to check the return code of all the
1032      add_arg ().  We bail out here instead.  */
1033   if (gpg->arg_error)
1034     return gpg_error (GPG_ERR_ENOMEM);
1035
1036   rc = build_argv (gpg);
1037   if (rc)
1038     return rc;
1039
1040   n = 3; /* status_fd, colon_fd and end of list */
1041   for (i = 0; gpg->fd_data_map[i].data; i++) 
1042     n++;
1043   fd_child_list = calloc (n + n, sizeof *fd_child_list);
1044   if (!fd_child_list)
1045     return gpg_error_from_errno (errno);
1046   fd_parent_list = fd_child_list + n;
1047
1048   /* build the fd list for the child */
1049   n = 0;
1050   if (gpg->colon.fnc)
1051     {
1052       fd_child_list[n].fd = gpg->colon.fd[1]; 
1053       fd_child_list[n].dup_to = 1; /* dup to stdout */
1054       n++;
1055     }
1056   for (i = 0; gpg->fd_data_map[i].data; i++)
1057     {
1058       if (gpg->fd_data_map[i].dup_to != -1)
1059         {
1060           fd_child_list[n].fd = gpg->fd_data_map[i].peer_fd;
1061           fd_child_list[n].dup_to = gpg->fd_data_map[i].dup_to;
1062           n++;
1063         }
1064     }
1065   fd_child_list[n].fd = -1;
1066   fd_child_list[n].dup_to = -1;
1067
1068   /* Build the fd list for the parent.  */
1069   n = 0;
1070   if (gpg->status.fd[1] != -1)
1071     {
1072       fd_parent_list[n].fd = gpg->status.fd[1];
1073       fd_parent_list[n].dup_to = -1;
1074       n++;
1075     }
1076   if (gpg->colon.fd[1] != -1)
1077     {
1078       fd_parent_list[n].fd = gpg->colon.fd[1];
1079       fd_parent_list[n].dup_to = -1;
1080       n++;
1081     }
1082   for (i = 0; gpg->fd_data_map[i].data; i++)
1083     {
1084       fd_parent_list[n].fd = gpg->fd_data_map[i].peer_fd;
1085       fd_parent_list[n].dup_to = -1;
1086       n++;
1087     }        
1088   fd_parent_list[n].fd = -1;
1089   fd_parent_list[n].dup_to = -1;
1090
1091   status = _gpgme_io_spawn (_gpgme_get_gpg_path (),
1092                             gpg->argv, fd_child_list, fd_parent_list);
1093   saved_errno = errno;
1094   free (fd_child_list);
1095   if (status == -1)
1096     return gpg_error_from_errno (errno);
1097
1098   /*_gpgme_register_term_handler ( closure, closure_value, pid );*/
1099
1100   rc = add_io_cb (gpg, gpg->status.fd[0], 1, status_handler, gpg,
1101                   &gpg->status.tag);
1102   if (rc)
1103     /* FIXME: kill the child */
1104     return rc;
1105
1106   if (gpg->colon.fnc)
1107     {
1108       assert (gpg->colon.fd[0] != -1);
1109       rc = add_io_cb (gpg, gpg->colon.fd[0], 1, colon_line_handler, gpg,
1110                       &gpg->colon.tag);
1111       if (rc)
1112         /* FIXME: kill the child */
1113         return rc;
1114     }
1115
1116   for (i = 0; gpg->fd_data_map[i].data; i++)
1117     {
1118       if (gpg->cmd.used && i == gpg->cmd.idx)
1119         {
1120           /* Park the cmd fd.  */
1121           gpg->cmd.fd = gpg->fd_data_map[i].fd;
1122           gpg->fd_data_map[i].fd = -1;
1123         }
1124       else
1125         {
1126           rc = add_io_cb (gpg, gpg->fd_data_map[i].fd,
1127                           gpg->fd_data_map[i].inbound,
1128                           gpg->fd_data_map[i].inbound
1129                           ? _gpgme_data_inbound_handler
1130                           : _gpgme_data_outbound_handler,
1131                           gpg->fd_data_map[i].data, &gpg->fd_data_map[i].tag);
1132           
1133           if (rc)
1134             /* FIXME: kill the child */
1135             return rc;
1136         }
1137     }
1138
1139   (*gpg->io_cbs.event) (gpg->io_cbs.event_priv, GPGME_EVENT_START, NULL);
1140   
1141   /* fixme: check what data we can release here */
1142   return 0;
1143 }
1144
1145
1146 static gpgme_error_t
1147 gpg_decrypt (void *engine, gpgme_data_t ciph, gpgme_data_t plain)
1148 {
1149   engine_gpg_t gpg = engine;
1150   gpgme_error_t err;
1151
1152   err = add_arg (gpg, "--decrypt");
1153
1154   /* Tell the gpg object about the data.  */
1155   if (!err)
1156     err = add_arg (gpg, "--output");
1157   if (!err)
1158     err = add_arg (gpg, "-");
1159   if (!err)
1160     err = add_data (gpg, plain, 1, 1);
1161   if (!err)
1162     err = add_data (gpg, ciph, 0, 0);
1163
1164   if (!err)
1165     start (gpg);
1166   return err;
1167 }
1168
1169 static gpgme_error_t
1170 gpg_delete (void *engine, gpgme_key_t key, int allow_secret)
1171 {
1172   engine_gpg_t gpg = engine;
1173   gpgme_error_t err;
1174
1175   err = add_arg (gpg, allow_secret ? "--delete-secret-and-public-key"
1176                  : "--delete-key");
1177   if (!err)
1178     err = add_arg (gpg, "--");
1179   if (!err)
1180     {
1181       if (!key->subkeys || !key->subkeys->fpr)
1182         return gpg_error (GPG_ERR_INV_VALUE);
1183       else
1184         err = add_arg (gpg, key->subkeys->fpr);
1185     }
1186
1187   if (!err)
1188     start (gpg);
1189   return err;
1190 }
1191
1192
1193 static gpgme_error_t
1194 append_args_from_signers (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */)
1195 {
1196   gpgme_error_t err = 0;
1197   int i;
1198   gpgme_key_t key;
1199
1200   for (i = 0; (key = gpgme_signers_enum (ctx, i)); i++)
1201     {
1202       const char *s = key->subkeys ? key->subkeys->keyid : NULL;
1203       if (s)
1204         {
1205           if (!err)
1206             err = add_arg (gpg, "-u");
1207           if (!err)
1208             err = add_arg (gpg, s);
1209         }
1210       gpgme_key_unref (key);
1211       if (err) break;
1212     }
1213   return err;
1214 }
1215
1216
1217 static gpgme_error_t
1218 gpg_edit (void *engine, gpgme_key_t key, gpgme_data_t out,
1219           gpgme_ctx_t ctx /* FIXME */)
1220 {
1221   engine_gpg_t gpg = engine;
1222   gpgme_error_t err;
1223
1224   err = add_arg (gpg, "--with-colons");
1225   if (!err)
1226     err = append_args_from_signers (gpg, ctx);
1227   if (!err)
1228   err = add_arg (gpg, "--edit-key");
1229   if (!err)
1230     err = add_data (gpg, out, 1, 1);
1231   if (!err)
1232     err = add_arg (gpg, "--");
1233   if (!err)
1234     {
1235       const char *s = key->subkeys ? key->subkeys->fpr : NULL;
1236       if (!s)
1237         err = gpg_error (GPG_ERR_INV_VALUE);
1238       else
1239         err = add_arg (gpg, s);
1240     }
1241   if (!err)
1242     err = start (gpg);
1243
1244   return err;
1245 }
1246
1247
1248 static gpgme_error_t
1249 append_args_from_recipients (engine_gpg_t gpg, gpgme_key_t recp[])
1250 {
1251   gpgme_error_t err = 0;
1252   int i = 0;
1253
1254   while (recp[i])
1255     {
1256       if (!recp[i]->subkeys || !recp[i]->subkeys->fpr)
1257         err = gpg_error (GPG_ERR_INV_VALUE);
1258       if (!err)
1259         err = add_arg (gpg, "-r");
1260       if (!err)
1261         err = add_arg (gpg, recp[i]->subkeys->fpr);
1262       if (err)
1263         break;
1264       i++;
1265     }    
1266   return err;
1267 }
1268
1269
1270 static gpgme_error_t
1271 gpg_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,
1272              gpgme_data_t plain, gpgme_data_t ciph, int use_armor)
1273 {
1274   engine_gpg_t gpg = engine;
1275   gpgme_error_t err;
1276   int symmetric = !recp;
1277
1278   err = add_arg (gpg, symmetric ? "--symmetric" : "--encrypt");
1279
1280   if (!err && use_armor)
1281     err = add_arg (gpg, "--armor");
1282
1283   if (!symmetric)
1284     {
1285       /* If we know that all recipients are valid (full or ultimate trust)
1286          we can suppress further checks.  */
1287       if (!err && !symmetric && (flags & GPGME_ENCRYPT_ALWAYS_TRUST))
1288         err = add_arg (gpg, "--always-trust");
1289
1290       if (!err)
1291         err = append_args_from_recipients (gpg, recp);
1292     }
1293
1294   /* Tell the gpg object about the data.  */
1295   if (!err)
1296     err = add_arg (gpg, "--output");
1297   if (!err)
1298     err = add_arg (gpg, "-");
1299   if (!err)
1300     err = add_data (gpg, ciph, 1, 1);
1301   if (!err)
1302     err = add_arg (gpg, "--");
1303   if (!err)
1304     err = add_data (gpg, plain, 0, 0);
1305
1306   if (!err)
1307     err = start (gpg);
1308
1309   return err;
1310 }
1311
1312
1313 static gpgme_error_t
1314 gpg_encrypt_sign (void *engine, gpgme_key_t recp[],
1315                   gpgme_encrypt_flags_t flags, gpgme_data_t plain,
1316                   gpgme_data_t ciph, int use_armor,
1317                   gpgme_ctx_t ctx /* FIXME */)
1318 {
1319   engine_gpg_t gpg = engine;
1320   gpgme_error_t err;
1321
1322   err = add_arg (gpg, "--encrypt");
1323   if (!err)
1324     err = add_arg (gpg, "--sign");
1325   if (!err && use_armor)
1326     err = add_arg (gpg, "--armor");
1327
1328   /* If we know that all recipients are valid (full or ultimate trust)
1329      we can suppress further checks.  */
1330   if (!err && (flags & GPGME_ENCRYPT_ALWAYS_TRUST))
1331     err = add_arg (gpg, "--always-trust");
1332
1333   if (!err)
1334     err = append_args_from_recipients (gpg, recp);
1335
1336   if (!err)
1337     err = append_args_from_signers (gpg, ctx);
1338
1339   /* Tell the gpg object about the data.  */
1340   if (!err)
1341     err = add_arg (gpg, "--output");
1342   if (!err)
1343     err = add_arg (gpg, "-");
1344   if (!err)
1345     err = add_data (gpg, ciph, 1, 1);
1346   if (!err)
1347     err = add_arg (gpg, "--");
1348   if (!err)
1349     err = add_data (gpg, plain, 0, 0);
1350
1351   if (!err)
1352     err = start (gpg);
1353
1354   return err;
1355 }
1356
1357
1358 static gpgme_error_t
1359 gpg_export (void *engine, const char *pattern, unsigned int reserved,
1360             gpgme_data_t keydata, int use_armor)
1361 {
1362   engine_gpg_t gpg = engine;
1363   gpgme_error_t err;
1364
1365   if (reserved)
1366     return gpg_error (GPG_ERR_INV_VALUE);
1367
1368   err = add_arg (gpg, "--export");
1369   if (!err && use_armor)
1370     err = add_arg (gpg, "--armor");
1371   if (!err)
1372     err = add_data (gpg, keydata, 1, 1);
1373   if (!err)
1374     err = add_arg (gpg, "--");
1375
1376   if (!err && pattern && *pattern)
1377     err = add_arg (gpg, pattern);
1378
1379   if (!err)
1380     err = start (gpg);
1381
1382   return err;
1383 }
1384
1385
1386 static gpgme_error_t
1387 gpg_export_ext (void *engine, const char *pattern[], unsigned int reserved,
1388                 gpgme_data_t keydata, int use_armor)
1389 {
1390   engine_gpg_t gpg = engine;
1391   gpgme_error_t err;
1392
1393   if (reserved)
1394     return gpg_error (GPG_ERR_INV_VALUE);
1395
1396   err = add_arg (gpg, "--export");
1397   if (!err && use_armor)
1398     err = add_arg (gpg, "--armor");
1399   if (!err)
1400     err = add_data (gpg, keydata, 1, 1);
1401   if (!err)
1402     err = add_arg (gpg, "--");
1403
1404   if (pattern)
1405     {
1406       while (!err && *pattern && **pattern)
1407         err = add_arg (gpg, *(pattern++));
1408     }
1409
1410   if (!err)
1411     err = start (gpg);
1412
1413   return err;
1414 }
1415
1416
1417 static gpgme_error_t
1418 gpg_genkey (void *engine, gpgme_data_t help_data, int use_armor,
1419             gpgme_data_t pubkey, gpgme_data_t seckey)
1420 {
1421   engine_gpg_t gpg = engine;
1422   gpgme_error_t err;
1423
1424   if (!gpg)
1425     return gpg_error (GPG_ERR_INV_VALUE);
1426
1427   /* We need a special mechanism to get the fd of a pipe here, so that
1428      we can use this for the %pubring and %secring parameters.  We
1429      don't have this yet, so we implement only the adding to the
1430      standard keyrings.  */
1431   if (pubkey || seckey)
1432     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1433
1434   err = add_arg (gpg, "--gen-key");
1435   if (!err && use_armor)
1436     err = add_arg (gpg, "--armor");
1437   if (!err)
1438     err = add_data (gpg, help_data, 0, 0);
1439
1440   if (!err)
1441     err = start (gpg);
1442
1443   return err;
1444 }
1445
1446
1447 static gpgme_error_t
1448 gpg_import (void *engine, gpgme_data_t keydata)
1449 {
1450   engine_gpg_t gpg = engine;
1451   gpgme_error_t err;
1452
1453   err = add_arg (gpg, "--import");
1454   if (!err)
1455     err = add_data (gpg, keydata, 0, 0);
1456
1457   if (!err)
1458     err = start (gpg);
1459
1460   return err;
1461 }
1462
1463
1464 static gpgme_error_t
1465 gpg_keylist (void *engine, const char *pattern, int secret_only,
1466              gpgme_keylist_mode_t mode)
1467 {
1468   engine_gpg_t gpg = engine;
1469   gpgme_error_t err;
1470
1471   err = add_arg (gpg, "--with-colons");
1472   if (!err)
1473     err = add_arg (gpg, "--fixed-list-mode");
1474   if (!err)
1475     err = add_arg (gpg, "--with-fingerprint");
1476   if (!err)
1477     err = add_arg (gpg, "--with-fingerprint");
1478   if (!err)
1479     err = add_arg (gpg, secret_only ? "--list-secret-keys"
1480                    : ((mode & GPGME_KEYLIST_MODE_SIGS)
1481                       ? "--check-sigs" : "--list-keys"));
1482   
1483   /* Tell the gpg object about the data.  */
1484   if (!err)
1485     err = add_arg (gpg, "--");
1486   if (!err && pattern && *pattern)
1487     err = add_arg (gpg, pattern);
1488
1489   if (!err)
1490     err = start (gpg);
1491
1492   return err;
1493 }
1494
1495
1496 static gpgme_error_t
1497 gpg_keylist_ext (void *engine, const char *pattern[], int secret_only,
1498                  int reserved, gpgme_keylist_mode_t mode)
1499 {
1500   engine_gpg_t gpg = engine;
1501   gpgme_error_t err;
1502
1503   if (reserved)
1504     return gpg_error (GPG_ERR_INV_VALUE);
1505
1506   err = add_arg (gpg, "--with-colons");
1507   if (!err)
1508     err = add_arg (gpg, "--fixed-list-mode");
1509   if (!err)
1510     err = add_arg (gpg, "--with-fingerprint");
1511   if (!err)
1512     err = add_arg (gpg, "--with-fingerprint");
1513   if (!err)
1514     err = add_arg (gpg, secret_only ? "--list-secret-keys"
1515                    : ((mode & GPGME_KEYLIST_MODE_SIGS)
1516                       ? "--check-sigs" : "--list-keys"));
1517   if (!err)
1518     err = add_arg (gpg, "--");
1519
1520   if (pattern)
1521     {
1522       while (!err && *pattern && **pattern)
1523         err = add_arg (gpg, *(pattern++));
1524     }
1525
1526   if (!err)
1527     err = start (gpg);
1528
1529   return err;
1530 }
1531
1532
1533 static gpgme_error_t
1534 gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
1535           gpgme_sig_mode_t mode, int use_armor, int use_textmode,
1536           int include_certs, gpgme_ctx_t ctx /* FIXME */)
1537 {
1538   engine_gpg_t gpg = engine;
1539   gpgme_error_t err;
1540
1541   if (mode == GPGME_SIG_MODE_CLEAR)
1542     err = add_arg (gpg, "--clearsign");
1543   else
1544     {
1545       err = add_arg (gpg, "--sign");
1546       if (!err && mode == GPGME_SIG_MODE_DETACH)
1547         err = add_arg (gpg, "--detach");
1548       if (!err && use_armor)
1549         err = add_arg (gpg, "--armor");
1550       if (!err && use_textmode)
1551         add_arg (gpg, "--textmode");
1552     }
1553
1554   if (!err)
1555     err = append_args_from_signers (gpg, ctx);
1556
1557   /* Tell the gpg object about the data.  */
1558   if (!err)
1559     err = add_data (gpg, in, 0, 0);
1560   if (!err)
1561     err = add_data (gpg, out, 1, 1);
1562
1563   if (!err)
1564     start (gpg);
1565
1566   return err;
1567 }
1568
1569 static gpgme_error_t
1570 gpg_trustlist (void *engine, const char *pattern)
1571 {
1572   engine_gpg_t gpg = engine;
1573   gpgme_error_t err;
1574
1575   err = add_arg (gpg, "--with-colons");
1576   if (!err)
1577     err = add_arg (gpg, "--list-trust-path");
1578   
1579   /* Tell the gpg object about the data.  */
1580   if (!err)
1581     err = add_arg (gpg, "--");
1582   if (!err)
1583     err = add_arg (gpg, pattern);
1584
1585   if (!err)
1586     err = start (gpg);
1587
1588   return err;
1589 }
1590
1591
1592 static gpgme_error_t
1593 gpg_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text,
1594             gpgme_data_t plaintext)
1595 {
1596   engine_gpg_t gpg = engine;
1597   gpgme_error_t err = 0;
1598
1599   if (plaintext)
1600     {
1601       /* Normal or cleartext signature.  */
1602
1603       err = add_arg (gpg, "--output");
1604       if (!err)
1605         err = add_arg (gpg, "-");
1606       if (!err)
1607         err = add_arg (gpg, "--");
1608       if (!err)
1609         err = add_data (gpg, sig, 0, 0);
1610       if (!err)
1611         err = add_data (gpg, plaintext, 1, 1);
1612     }
1613   else
1614     {
1615       err = add_arg (gpg, "--verify");
1616       if (!err)
1617         err = add_arg (gpg, "--");
1618       if (!err)
1619         err = add_data (gpg, sig, -1, 0);
1620       if (signed_text)
1621         {
1622           if (!err)
1623             err = add_arg (gpg, "-");
1624           if (!err)
1625             err = add_data (gpg, signed_text, 0, 0);
1626         }
1627     }
1628
1629   if (!err)
1630     err = start (gpg);
1631
1632   return err;
1633 }
1634
1635
1636 static void
1637 gpg_set_io_cbs (void *engine, gpgme_io_cbs_t io_cbs)
1638 {
1639   engine_gpg_t gpg = engine;
1640
1641   gpg->io_cbs = *io_cbs;
1642 }
1643
1644 \f
1645 struct engine_ops _gpgme_engine_ops_gpg =
1646   {
1647     /* Static functions.  */
1648     _gpgme_get_gpg_path,
1649     gpg_get_version,
1650     gpg_get_req_version,
1651     gpg_new,
1652
1653     /* Member functions.  */
1654     gpg_release,
1655     gpg_set_status_handler,
1656     gpg_set_command_handler,
1657     gpg_set_colon_line_handler,
1658     gpg_decrypt,
1659     gpg_delete,
1660     gpg_edit,
1661     gpg_encrypt,
1662     gpg_encrypt_sign,
1663     gpg_export,
1664     gpg_export_ext,
1665     gpg_genkey,
1666     gpg_import,
1667     gpg_keylist,
1668     gpg_keylist_ext,
1669     gpg_sign,
1670     gpg_trustlist,
1671     gpg_verify,
1672     gpg_set_io_cbs,
1673     gpg_io_event
1674   };