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