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