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