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