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