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