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