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