A couple of minor changes and a short README for Gpgcom
[gpgme.git] / gpgme / rungpg.c
1 /* rungpg.c 
2  *      Copyright (C) 2000 Werner Koch (dd9jn)
3  *      Copyright (C) 2001 g10 Code GmbH
4  *
5  * This file is part of GPGME.
6  *
7  * GPGME is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * GPGME is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20  */
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <assert.h>
27 #include <errno.h>
28 #include <time.h>
29 #include <sys/time.h>
30 #include <sys/types.h>
31 #include <signal.h>
32 #include <fcntl.h>
33 #include "unistd.h"
34
35 #include "gpgme.h"
36 #include "util.h"
37 #include "ops.h"
38 #include "wait.h"
39 #include "rungpg.h"
40 #include "context.h"  /*temp hack until we have GpmeData methods to do I/O */
41 #include "io.h"
42 #include "sema.h"
43
44 #include "status-table.h"
45
46
47 /* This type is used to build a list of gpg arguments and
48  * data sources/sinks */
49 struct arg_and_data_s {
50     struct arg_and_data_s *next;
51     GpgmeData data;  /* If this is not NULL .. */
52     int dup_to;
53     int print_fd;    /* print the fd number and not the special form of it */
54     char arg[1];     /* .. this is used */
55 };
56
57 struct fd_data_map_s {
58     GpgmeData data;
59     int inbound;  /* true if this is used for reading from gpg */
60     int dup_to;
61     int fd;       /* the fd to use */
62     int peer_fd;  /* the outher side of the pipe */
63 };
64
65
66 struct gpg_object_s {
67     struct arg_and_data_s *arglist;
68     struct arg_and_data_s **argtail;
69     int arg_error;  
70
71     struct {
72         int fd[2];  
73         size_t bufsize;
74         char *buffer;
75         size_t readpos;
76         int eof;
77         GpgStatusHandler fnc;
78         void *fnc_value;
79     } status;
80
81     /* This is a kludge - see the comment at gpg_colon_line_handler */
82     struct {
83         int fd[2];  
84         size_t bufsize;
85         char *buffer;
86         size_t readpos;
87         int eof;
88         GpgColonLineHandler fnc;  /* this indicate use of this structrue */
89         void *fnc_value;
90         int simple;
91     } colon;
92
93     char **argv;  
94     struct fd_data_map_s *fd_data_map;
95
96     int pid; /* we can't use pid_t because we don't use it in Windoze */
97
98     int running;
99     
100     /* stuff needed for pipemode */
101     struct {
102         int used;
103         int active;
104         GpgmeData sig;
105         GpgmeData text;
106         int stream_started;
107     } pm;
108
109     /* stuff needed for interactive (command) mode */
110     struct {
111         int used;
112         int fd;
113         GpgmeData cb_data;   /* hack to get init the above fd later */
114         GpgStatusCode code;  /* last code */
115         char *keyword;       /* what has been requested (malloced) */
116         GpgCommandHandler fnc; 
117         void *fnc_value;
118     } cmd;
119 };
120
121 struct reap_s {
122     struct reap_s *next;
123     int pid;
124     time_t entered;
125     int term_send;
126 };
127
128 static struct reap_s *reap_list;
129 DEFINE_STATIC_LOCK (reap_list_lock);
130
131
132 static void free_argv ( char **argv );
133 static void free_fd_data_map ( struct fd_data_map_s *fd_data_map );
134
135 static int gpg_inbound_handler ( void *opaque, int pid, int fd );
136 static int gpg_outbound_handler ( void *opaque, int pid, int fd );
137
138 static int gpg_status_handler ( void *opaque, int pid, int fd );
139 static GpgmeError read_status ( GpgObject gpg );
140
141 static int gpg_colon_line_handler ( void *opaque, int pid, int fd );
142 static GpgmeError read_colon_line ( GpgObject gpg );
143
144 static int pipemode_cb ( void *opaque,
145                          char *buffer, size_t length, size_t *nread );
146 static int command_cb ( void *opaque,
147                         char *buffer, size_t length, size_t *nread );
148
149
150 static void
151 close_notify_handler ( int fd, void *opaque )
152 {
153     GpgObject gpg = opaque;
154
155     assert (fd != -1);
156     if (gpg->status.fd[0] == fd )
157         gpg->status.fd[0] = -1;
158     else if (gpg->status.fd[1] == fd )
159         gpg->status.fd[1] = -1;
160     else if (gpg->colon.fd[0] == fd )
161         gpg->colon.fd[0] = -1;
162     else if (gpg->colon.fd[1] == fd )
163         gpg->colon.fd[1] = -1;
164     else if (gpg->fd_data_map) {
165         int i;
166
167         for (i=0; gpg->fd_data_map[i].data; i++ ) {
168             if ( gpg->fd_data_map[i].fd == fd ) {
169                 gpg->fd_data_map[i].fd = -1;
170                 break;
171             }
172             if ( gpg->fd_data_map[i].peer_fd == fd ) {
173                 gpg->fd_data_map[i].peer_fd = -1;
174                 break;
175             }
176         }
177     }
178 }
179
180
181
182
183 GpgmeError
184 _gpgme_gpg_new ( GpgObject *r_gpg )
185 {
186     GpgObject gpg;
187     int rc = 0;
188
189     gpg = xtrycalloc ( 1, sizeof *gpg );
190     if ( !gpg ) {
191         rc = mk_error (Out_Of_Core);
192         goto leave;
193     }
194     gpg->argtail = &gpg->arglist;
195
196     gpg->status.fd[0] = -1;
197     gpg->status.fd[1] = -1;
198     gpg->colon.fd[0] = -1;
199     gpg->colon.fd[1] = -1;
200     gpg->cmd.fd = -1;
201
202     gpg->pid = -1;
203
204     /* allocate the read buffer for the status pipe */
205     gpg->status.bufsize = 1024;
206     gpg->status.readpos = 0;
207     gpg->status.buffer = xtrymalloc (gpg->status.bufsize);
208     if (!gpg->status.buffer) {
209         rc = mk_error (Out_Of_Core);
210         goto leave;
211     }
212     /* In any case we need a status pipe - create it right here  and
213      * don't handle it with our generic GpgmeData mechanism */
214     if (_gpgme_io_pipe (gpg->status.fd, 1) == -1) {
215         rc = mk_error (Pipe_Error);
216         goto leave;
217     }
218     if ( _gpgme_io_set_close_notify (gpg->status.fd[0],
219                                      close_notify_handler, gpg)
220          || _gpgme_io_set_close_notify (gpg->status.fd[1],
221                                         close_notify_handler, gpg) ) {
222         rc = mk_error (General_Error);
223         goto leave;
224     }
225     gpg->status.eof = 0;
226     _gpgme_gpg_add_arg ( gpg, "--status-fd" );
227     {
228         char buf[25];
229         sprintf ( buf, "%d", gpg->status.fd[1]);
230         _gpgme_gpg_add_arg ( gpg, buf );
231     }
232     _gpgme_gpg_add_arg ( gpg, "--no-tty" );
233
234
235  leave:
236     if (rc) {
237         _gpgme_gpg_release (gpg);
238         *r_gpg = NULL;
239     }
240     else
241         *r_gpg = gpg;
242     return rc;
243 }
244
245
246 void
247 _gpgme_gpg_release ( GpgObject gpg )
248 {
249     if ( !gpg )
250         return;
251     xfree (gpg->status.buffer);
252     xfree (gpg->colon.buffer);
253     if ( gpg->argv )
254         free_argv (gpg->argv);
255     xfree (gpg->cmd.keyword);
256
257     if (gpg->pid != -1) 
258         _gpgme_remove_proc_from_wait_queue ( gpg->pid );
259     if (gpg->status.fd[0] != -1 )
260         _gpgme_io_close (gpg->status.fd[0]);
261     if (gpg->status.fd[1] != -1 )
262         _gpgme_io_close (gpg->status.fd[1]);
263     if (gpg->colon.fd[0] != -1 )
264         _gpgme_io_close (gpg->colon.fd[0]);
265     if (gpg->colon.fd[1] != -1 )
266         _gpgme_io_close (gpg->colon.fd[1]);
267     free_fd_data_map (gpg->fd_data_map);
268     if (gpg->running) {
269         int pid = gpg->pid;
270         struct reap_s *r;
271
272         /* resuse the memory, so that we don't need to allocate another
273          * mem block and have to handle errors */
274         assert (sizeof *r < sizeof *gpg );
275         r = (void*)gpg;
276         memset (r, 0, sizeof *r);
277         r->pid = pid;
278         r->entered = time (NULL);
279         LOCK(reap_list_lock);
280         r->next = reap_list;
281         reap_list = r;
282         UNLOCK(reap_list_lock);
283     }
284     else
285         xfree (gpg);
286 }
287
288
289 static void
290 do_reaping (void)
291 {
292     struct reap_s *r, *rlast;
293     static time_t last_check;
294     time_t cur_time = time (NULL);
295
296     /* a race does not matter here */
297     if (!last_check)
298         last_check = time(NULL);
299
300     if (last_check >= cur_time)
301         return;  /* we check only every second */
302
303     /* fixme: it would be nice if to have a TRYLOCK here */
304     LOCK (reap_list_lock);  
305     for (r=reap_list,rlast=NULL; r ; rlast=r, r=r?r->next:NULL) {
306         int dummy1, dummy2;
307
308         if ( _gpgme_io_waitpid (r->pid, 0, &dummy1, &dummy2) ) {
309             /* process has terminated - remove it from the queue */
310             void *p = r;
311             if (!rlast) {
312                 reap_list = r->next;
313                 r = reap_list;
314             }
315             else {
316                 rlast->next = r->next;
317                 r = rlast;
318             }
319             xfree (p);
320         }
321         else if ( !r->term_send ) {
322             if( r->entered+1 >= cur_time ) {
323                 _gpgme_io_kill ( r->pid, 0);
324                 r->term_send = 1;
325                 r->entered = cur_time;
326             }
327         }
328         else {
329             /* give it 5 second before we are going to send the killer */
330             if ( r->entered+5 >= cur_time ) {
331                 _gpgme_io_kill (r->pid, 1);
332                 r->entered = cur_time; /* just in case we have to repat it */
333             }
334         }
335     }
336     UNLOCK (reap_list_lock);  
337 }
338
339 void
340 _gpgme_gpg_housecleaning ()
341 {
342     do_reaping ();
343 }
344
345 void
346 _gpgme_gpg_enable_pipemode ( GpgObject gpg )
347 {
348     gpg->pm.used = 1;
349     assert ( !gpg->pm.sig );
350     assert ( !gpg->pm.text );
351 }
352     
353 GpgmeError
354 _gpgme_gpg_add_arg ( GpgObject gpg, const char *arg )
355 {
356     struct arg_and_data_s *a;
357
358     assert (gpg);
359     assert (arg);
360
361     if (gpg->pm.active)
362         return 0;
363
364     a = xtrymalloc ( sizeof *a + strlen (arg) );
365     if ( !a ) {
366         gpg->arg_error = 1;
367         return mk_error(Out_Of_Core);
368     }
369     a->next = NULL;
370     a->data = NULL;
371     a->dup_to = -1;
372     strcpy ( a->arg, arg );
373     *gpg->argtail = a;
374     gpg->argtail = &a->next;
375     return 0;
376 }
377
378 GpgmeError
379 _gpgme_gpg_add_data ( GpgObject gpg, GpgmeData data, int dup_to )
380 {
381     struct arg_and_data_s *a;
382
383     assert (gpg);
384     assert (data);
385     if (gpg->pm.active)
386         return 0;
387
388     a = xtrymalloc ( sizeof *a - 1 );
389     if ( !a ) {
390         gpg->arg_error = 1;
391         return mk_error(Out_Of_Core);
392     }
393     a->next = NULL;
394     a->data = data;
395     if ( dup_to == -2 ) {
396         a->print_fd = 1;
397         a->dup_to = -1;
398     }
399     else {
400         a->print_fd = 0;
401         a->dup_to = dup_to;
402     }
403     *gpg->argtail = a;
404     gpg->argtail = &a->next;
405     return 0;
406 }
407
408 GpgmeError
409 _gpgme_gpg_add_pm_data ( GpgObject gpg, GpgmeData data, int what )
410 {
411     GpgmeError rc=0;
412
413     assert ( gpg->pm.used );
414     
415     if ( !what ) {
416         /* the signature */
417         assert ( !gpg->pm.sig );
418         gpg->pm.sig = data;
419     }
420     else if (what == 1) {
421         /* the signed data */
422         assert ( !gpg->pm.text );
423         gpg->pm.text = data;
424     }
425     else {
426         assert (0);
427     }
428
429     if ( gpg->pm.sig && gpg->pm.text ) {
430         if ( !gpg->pm.active ) {
431             /* create the callback handler and connect it to stdin */
432             GpgmeData tmp;
433             
434             rc = gpgme_data_new_with_read_cb ( &tmp, pipemode_cb, gpg );
435             if (!rc )
436                 rc = _gpgme_gpg_add_data (gpg, tmp, 0);
437         }
438         if ( !rc ) {
439             /* here we can reset the handler stuff */
440             gpg->pm.stream_started = 0;
441         }
442     }
443
444     return rc;
445 }
446
447 /*
448  * Note, that the status_handler is allowed to modifiy the args value
449  */
450 void
451 _gpgme_gpg_set_status_handler ( GpgObject gpg,
452                                 GpgStatusHandler fnc, void *fnc_value ) 
453 {
454     assert (gpg);
455     if (gpg->pm.active)
456         return;
457
458     gpg->status.fnc = fnc;
459     gpg->status.fnc_value = fnc_value;
460 }
461
462 /* Kludge to process --with-colon output */
463 GpgmeError
464 _gpgme_gpg_set_colon_line_handler ( GpgObject gpg,
465                                     GpgColonLineHandler fnc, void *fnc_value ) 
466 {
467     assert (gpg);
468     if (gpg->pm.active)
469         return 0;
470
471     gpg->colon.bufsize = 1024;
472     gpg->colon.readpos = 0;
473     gpg->colon.buffer = xtrymalloc (gpg->colon.bufsize);
474     if (!gpg->colon.buffer) {
475         return mk_error (Out_Of_Core);
476     }
477     if (_gpgme_io_pipe (gpg->colon.fd, 1) == -1) {
478         xfree (gpg->colon.buffer); gpg->colon.buffer = NULL;
479         return mk_error (Pipe_Error);
480     }
481     if ( _gpgme_io_set_close_notify (gpg->colon.fd[0],
482                                      close_notify_handler, gpg)
483          ||  _gpgme_io_set_close_notify (gpg->colon.fd[1],
484                                          close_notify_handler, gpg) ) {
485         return mk_error (General_Error);
486     }
487     gpg->colon.eof = 0;
488     gpg->colon.fnc = fnc;
489     gpg->colon.fnc_value = fnc_value;
490     gpg->colon.simple = 0;
491     return 0;
492 }
493
494
495 GpgmeError
496 _gpgme_gpg_set_simple_line_handler ( GpgObject gpg,
497                                      GpgColonLineHandler fnc,
498                                      void *fnc_value ) 
499 {
500     GpgmeError err;
501
502     err = _gpgme_gpg_set_colon_line_handler (gpg, fnc, fnc_value);
503     if (!err)
504         gpg->colon.simple = 1;
505     return err;
506 }
507
508
509 /* 
510  * The Fnc will be called to get a value for one of the commands with
511  * a key KEY.  If the Code pssed to FNC is 0, the function may release
512  * resources associated with the returned value from another call.  To
513  * match such a second call to a first call, the returned value from
514  * the first call is passed as keyword.
515  */
516
517 GpgmeError
518 _gpgme_gpg_set_command_handler ( GpgObject gpg,
519                                  GpgCommandHandler fnc, void *fnc_value ) 
520 {
521     GpgmeData tmp;
522     GpgmeError err;
523
524     assert (gpg);
525     if (gpg->pm.active)
526         return 0;
527
528     err = gpgme_data_new_with_read_cb ( &tmp, command_cb, gpg );
529     if (err)
530         return err;
531         
532     _gpgme_gpg_add_arg ( gpg, "--command-fd" );
533     _gpgme_gpg_add_data (gpg, tmp, -2);
534     gpg->cmd.cb_data = tmp;
535     gpg->cmd.fnc = fnc;
536     gpg->cmd.fnc_value = fnc_value;
537     gpg->cmd.used = 1;
538     return 0;
539 }
540
541
542 static void
543 free_argv ( char **argv )
544 {
545     int i;
546
547     for (i=0; argv[i]; i++ )
548         xfree (argv[i]);
549     xfree (argv);
550 }
551
552 static void
553 free_fd_data_map ( struct fd_data_map_s *fd_data_map )
554 {
555     int i;
556
557     if ( !fd_data_map )
558         return;
559
560     for (i=0; fd_data_map[i].data; i++ ) {
561         if ( fd_data_map[i].fd != -1 )
562             _gpgme_io_close (fd_data_map[i].fd);
563         if ( fd_data_map[i].peer_fd != -1 )
564             _gpgme_io_close (fd_data_map[i].peer_fd);
565         /* don't release data because this is only a reference */
566     }
567     xfree (fd_data_map);
568 }
569
570
571 static GpgmeError
572 build_argv ( GpgObject gpg )
573 {
574     struct arg_and_data_s *a;
575     struct fd_data_map_s *fd_data_map;
576     size_t datac=0, argc=0;  
577     char **argv;
578     int need_special = 0;
579     int use_agent = !!getenv ("GPG_AGENT_INFO");
580        
581     if ( gpg->argv ) {
582         free_argv ( gpg->argv );
583         gpg->argv = NULL;
584     }
585     if (gpg->fd_data_map) {
586         free_fd_data_map (gpg->fd_data_map);
587         gpg->fd_data_map = NULL;
588     }
589
590     argc++; /* for argv[0] */
591     for ( a=gpg->arglist; a; a = a->next ) {
592         argc++;
593         if (a->data) {
594             /*fprintf (stderr, "build_argv: data\n" );*/
595             datac++;
596             if ( a->dup_to == -1 && !a->print_fd )
597                 need_special = 1;
598         }
599         else {
600             /*   fprintf (stderr, "build_argv: arg=`%s'\n", a->arg );*/
601         }
602     }
603     if ( need_special )
604         argc++;
605     if (use_agent)
606         argc++;
607     if (!gpg->cmd.used)
608         argc++;
609     argc += 2; /* --comment */
610
611     argv = xtrycalloc ( argc+1, sizeof *argv );
612     if (!argv)
613         return mk_error (Out_Of_Core);
614     fd_data_map = xtrycalloc ( datac+1, sizeof *fd_data_map );
615     if (!fd_data_map) {
616         free_argv (argv);
617         return mk_error (Out_Of_Core);
618     }
619
620     argc = datac = 0;
621     argv[argc] = xtrystrdup ( "gpg" ); /* argv[0] */
622     if (!argv[argc]) {
623         xfree (fd_data_map);
624         free_argv (argv);
625         return mk_error (Out_Of_Core);
626     }
627     argc++;
628     if ( need_special ) {
629         argv[argc] = xtrystrdup ( "--enable-special-filenames" );
630         if (!argv[argc]) {
631             xfree (fd_data_map);
632             free_argv (argv);
633             return mk_error (Out_Of_Core);
634         }
635         argc++;
636     }
637     if ( use_agent ) {
638         argv[argc] = xtrystrdup ( "--use-agent" );
639         if (!argv[argc]) {
640             xfree (fd_data_map);
641             free_argv (argv);
642             return mk_error (Out_Of_Core);
643         }
644         argc++;
645     }
646     if ( !gpg->cmd.used ) {
647         argv[argc] = xtrystrdup ( "--batch" );
648         if (!argv[argc]) {
649             xfree (fd_data_map);
650             free_argv (argv);
651             return mk_error (Out_Of_Core);
652         }
653         argc++;
654     }
655     argv[argc] = xtrystrdup ( "--comment" );
656     if (!argv[argc]) {
657         xfree (fd_data_map);
658         free_argv (argv);
659         return mk_error (Out_Of_Core);
660     }
661     argc++;
662     argv[argc] = xtrystrdup ( "" );
663     if (!argv[argc]) {
664         xfree (fd_data_map);
665         free_argv (argv);
666         return mk_error (Out_Of_Core);
667     }
668     argc++;
669     for ( a=gpg->arglist; a; a = a->next ) {
670         if ( a->data ) {
671             switch ( _gpgme_data_get_mode (a->data) ) {
672               case GPGME_DATA_MODE_NONE:
673               case GPGME_DATA_MODE_INOUT:
674                 xfree (fd_data_map);
675                 free_argv (argv);
676                 return mk_error (Invalid_Mode);
677               case GPGME_DATA_MODE_IN:
678                 /* create a pipe to read from gpg */
679                 fd_data_map[datac].inbound = 1;
680                 break;
681               case GPGME_DATA_MODE_OUT:
682                 /* create a pipe to pass it down to gpg */
683                 fd_data_map[datac].inbound = 0;
684                 break;
685             }
686
687             switch ( gpgme_data_get_type (a->data) ) {
688               case GPGME_DATA_TYPE_NONE:
689                 if ( fd_data_map[datac].inbound )
690                     break;  /* allowed */
691                 xfree (fd_data_map);
692                 free_argv (argv);
693                 return mk_error (Invalid_Type);
694               case GPGME_DATA_TYPE_MEM:
695               case GPGME_DATA_TYPE_CB:
696                 break;
697               case GPGME_DATA_TYPE_FD:
698               case GPGME_DATA_TYPE_FILE:
699                 xfree (fd_data_map);
700                 free_argv (argv);
701                 return mk_error (Not_Implemented);
702             }
703   
704             /* create a pipe */
705             {   
706                 int fds[2];
707                 
708                 if (_gpgme_io_pipe (fds, fd_data_map[datac].inbound?1:0 )
709                     == -1) {
710                     xfree (fd_data_map);
711                     free_argv (argv);
712                     return mk_error (Pipe_Error);
713                 }
714                 if ( _gpgme_io_set_close_notify (fds[0],
715                                                  close_notify_handler, gpg)
716                      || _gpgme_io_set_close_notify (fds[1],
717                                                     close_notify_handler,
718                                                     gpg)) {
719                     return mk_error (General_Error);
720                 }
721                 /* if the data_type is FD, we have to do a dup2 here */
722                 if (fd_data_map[datac].inbound) {
723                     fd_data_map[datac].fd       = fds[0];
724                     fd_data_map[datac].peer_fd  = fds[1];
725                 }
726                 else {
727                     fd_data_map[datac].fd       = fds[1];
728                     fd_data_map[datac].peer_fd  = fds[0];
729                 }
730             }
731
732             /* Hack to get hands on the fd later */
733             if ( gpg->cmd.used && gpg->cmd.cb_data == a->data ) {
734                 assert (gpg->cmd.fd == -1);
735                 gpg->cmd.fd = fd_data_map[datac].fd;
736             }
737
738             fd_data_map[datac].data = a->data;
739             fd_data_map[datac].dup_to = a->dup_to;
740             if ( a->dup_to == -1 ) {
741                 argv[argc] = xtrymalloc ( 25 );
742                 if (!argv[argc]) {
743                     xfree (fd_data_map);
744                     free_argv (argv);
745                     return mk_error (Out_Of_Core);
746                 }
747                 sprintf ( argv[argc], 
748                           a->print_fd? "%d" : "-&%d",
749                           fd_data_map[datac].peer_fd );
750                 argc++;
751             }
752             datac++;
753         }
754         else {
755             argv[argc] = xtrystrdup ( a->arg );
756             if (!argv[argc]) {
757                 xfree (fd_data_map);
758                 free_argv (argv);
759                 return mk_error (Out_Of_Core);
760             }
761             argc++;
762         }
763     }
764
765     gpg->argv = argv;
766     gpg->fd_data_map = fd_data_map;
767     return 0;
768 }
769
770 GpgmeError
771 _gpgme_gpg_spawn( GpgObject gpg, void *opaque )
772 {
773     int rc;
774     int i, n;
775     int pid;
776     struct spawn_fd_item_s *fd_child_list, *fd_parent_list;
777
778     if ( !gpg )
779         return mk_error (Invalid_Value);
780
781     /* Kludge, so that we don't need to check the return code of
782      * all the gpgme_gpg_add_arg().  we bail out here instead */
783     if ( gpg->arg_error )
784         return mk_error (Out_Of_Core);
785
786     if (gpg->pm.active)
787         return 0;
788
789     rc = build_argv ( gpg );
790     if ( rc )
791         return rc;
792
793     n = 4; /* status fd, 2*colon_fd and end of list */
794     for (i=0; gpg->fd_data_map[i].data; i++ ) 
795         n += 2;
796     fd_child_list = xtrycalloc ( n+n, sizeof *fd_child_list );
797     if (!fd_child_list)
798         return mk_error (Out_Of_Core);
799     fd_parent_list = fd_child_list + n;
800
801     /* build the fd list for the child */
802     n=0;
803     fd_child_list[n].fd = gpg->status.fd[0]; 
804     fd_child_list[n].dup_to = -1;
805     n++;
806     if ( gpg->colon.fnc ) {
807         fd_child_list[n].fd = gpg->colon.fd[0];
808         fd_child_list[n].dup_to = -1;
809         n++;
810         fd_child_list[n].fd = gpg->colon.fd[1]; 
811         fd_child_list[n].dup_to = 1; /* dup to stdout */
812         n++;
813     }
814     for (i=0; gpg->fd_data_map[i].data; i++ ) {
815         fd_child_list[n].fd = gpg->fd_data_map[i].fd;
816         fd_child_list[n].dup_to = -1;
817         n++;
818         if (gpg->fd_data_map[i].dup_to != -1) {
819             fd_child_list[n].fd = gpg->fd_data_map[i].peer_fd;
820             fd_child_list[n].dup_to = gpg->fd_data_map[i].dup_to;
821             n++;
822         }
823     }
824     fd_child_list[n].fd = -1;
825     fd_child_list[n].dup_to = -1;
826
827     /* build the fd list for the parent */
828     n=0;
829     if ( gpg->status.fd[1] != -1 ) {
830         fd_parent_list[n].fd = gpg->status.fd[1];
831         fd_parent_list[n].dup_to = -1;
832         n++;
833         gpg->status.fd[1] = -1;
834     }
835     if ( gpg->colon.fd[1] != -1 ) {
836         fd_parent_list[n].fd = gpg->colon.fd[1];
837         fd_parent_list[n].dup_to = -1;
838         n++;
839         gpg->colon.fd[1] = -1;
840     }
841     for (i=0; gpg->fd_data_map[i].data; i++ ) {
842         fd_parent_list[n].fd = gpg->fd_data_map[i].peer_fd;
843         fd_parent_list[n].dup_to = -1;
844         n++;
845         gpg->fd_data_map[i].peer_fd = -1;
846     }        
847     fd_parent_list[n].fd = -1;
848     fd_parent_list[n].dup_to = -1;
849
850
851     pid = _gpgme_io_spawn (_gpgme_get_gpg_path (),
852                            gpg->argv, fd_child_list, fd_parent_list);
853     xfree (fd_child_list);
854     if (pid == -1) {
855         return mk_error (Exec_Error);
856     }
857
858     gpg->pid = pid;
859     if (gpg->pm.used)
860         gpg->pm.active = 1;
861
862     /*_gpgme_register_term_handler ( closure, closure_value, pid );*/
863
864     if ( _gpgme_register_pipe_handler ( opaque, gpg_status_handler,
865                                         gpg, pid, gpg->status.fd[0], 1 ) ) {
866         /* FIXME: kill the child */
867         return mk_error (General_Error);
868
869     }
870
871     if ( gpg->colon.fnc ) {
872         assert ( gpg->colon.fd[0] != -1 );
873         if ( _gpgme_register_pipe_handler ( opaque, gpg_colon_line_handler,
874                                             gpg, pid, gpg->colon.fd[0], 1 ) ) {
875             /* FIXME: kill the child */
876             return mk_error (General_Error);
877             
878         }
879     }
880
881     for (i=0; gpg->fd_data_map[i].data; i++ ) {
882         /* Due to problems with select and write we set outbound pipes
883          * to non-blocking */
884         if (!gpg->fd_data_map[i].inbound) {
885             _gpgme_io_set_nonblocking (gpg->fd_data_map[i].fd);
886         }
887
888         if ( _gpgme_register_pipe_handler (
889                  opaque, 
890                  gpg->fd_data_map[i].inbound?
891                        gpg_inbound_handler:gpg_outbound_handler,
892                  gpg->fd_data_map[i].data,
893                  pid, gpg->fd_data_map[i].fd,
894                  gpg->fd_data_map[i].inbound )
895            ) {
896             /* FIXME: kill the child */
897             return mk_error (General_Error);
898         }
899     }
900
901     if ( gpg->cmd.used )
902         _gpgme_freeze_fd ( gpg->cmd.fd );
903
904     /* fixme: check what data we can release here */
905     
906     gpg->running = 1;
907     return 0;
908 }
909
910
911 static int
912 gpg_inbound_handler ( void *opaque, int pid, int fd )
913 {
914     GpgmeData dh = opaque;
915     GpgmeError err;
916     int nread;
917     char buf[200];
918
919     assert ( _gpgme_data_get_mode (dh) == GPGME_DATA_MODE_IN );
920
921     nread = _gpgme_io_read (fd, buf, 200 );
922     if ( nread < 0 ) {
923         DEBUG3 ("read_mem_data: read failed on fd %d (n=%d): %s",
924                  fd, nread, strerror (errno) );
925         return 1;
926     }
927     else if (!nread)
928         return 1; /* eof */
929
930     /* We could improve this with a GpgmeData function which takes
931      * the read function or provides a memory area for writing to it.
932      */
933     
934     err = _gpgme_data_append ( dh, buf, nread );
935     if ( err ) {
936         DEBUG1 ("_gpgme_append_data failed: %s\n",
937                  gpgme_strerror(err));
938         /* Fixme: we should close the pipe or read it to /dev/null in
939          * this case. Returnin EOF is not sufficient */
940         return 1;
941     }
942
943     return 0;
944 }
945
946
947 static int
948 write_mem_data ( GpgmeData dh, int fd )
949 {
950     size_t nbytes;
951     int  nwritten; 
952
953     nbytes = dh->len - dh->readpos;
954     if ( !nbytes ) {
955         _gpgme_io_close (fd);
956         return 1;
957     }
958     
959     /* FIXME: Arggg, the pipe blocks on large write request, although
960      * select told us that it is okay to write - need to figure out
961      * why this happens?  Stevens says nothing about this problem (or
962      * is it my Linux kernel 2.4.0test1)
963      * To avoid that we have set the pipe to nonblocking.
964      */
965
966     nwritten = _gpgme_io_write ( fd, dh->data+dh->readpos, nbytes );
967     if (nwritten == -1 && errno == EAGAIN )
968         return 0;
969     if ( nwritten < 1 ) {
970         DEBUG3 ("write_mem_data(%d): write failed (n=%d): %s",
971                 fd, nwritten, strerror (errno) );
972         _gpgme_io_close (fd);
973         return 1;
974     }
975
976     dh->readpos += nwritten;
977     return 0;
978 }
979
980 static int
981 write_cb_data ( GpgmeData dh, int fd )
982 {
983     size_t nbytes;
984     int  err, nwritten; 
985     char buffer[512];
986
987     err = gpgme_data_read ( dh, buffer, DIM(buffer), &nbytes );
988     if (err == GPGME_EOF) {
989         _gpgme_io_close (fd);
990         return 1;
991     }
992     
993     nwritten = _gpgme_io_write ( fd, buffer, nbytes );
994     if (nwritten == -1 && errno == EAGAIN )
995         return 0;
996     if ( nwritten < 1 ) {
997         DEBUG3 ("write_cb_data(%d): write failed (n=%d): %s",
998                 fd, nwritten, strerror (errno) );
999         _gpgme_io_close (fd);
1000         return 1;
1001     }
1002
1003     if ( nwritten < nbytes ) {
1004         /* ugly, ugly: It does currently only for for MEM type data */
1005         if ( _gpgme_data_unread (dh, buffer + nwritten, nbytes - nwritten ) )
1006             DEBUG1 ("wite_cb_data: unread of %d bytes failed\n",
1007                      nbytes - nwritten );
1008         _gpgme_io_close (fd);
1009         return 1;
1010     }
1011
1012     return 0;
1013 }
1014
1015
1016 static int
1017 gpg_outbound_handler ( void *opaque, int pid, int fd )
1018 {
1019     GpgmeData dh = opaque;
1020
1021     assert ( _gpgme_data_get_mode (dh) == GPGME_DATA_MODE_OUT );
1022     switch ( gpgme_data_get_type (dh) ) {
1023       case GPGME_DATA_TYPE_MEM:
1024         if ( write_mem_data ( dh, fd ) )
1025             return 1; /* ready */
1026         break;
1027       case GPGME_DATA_TYPE_CB:
1028         if (write_cb_data (dh, fd))
1029             return 1; /* ready */
1030         break;
1031       default:
1032         assert (0);
1033     }
1034
1035     return 0;
1036 }
1037
1038
1039
1040 static int
1041 gpg_status_handler ( void *opaque, int pid, int fd )
1042 {
1043     GpgObject gpg = opaque;
1044     int rc = 0;
1045
1046     assert ( fd == gpg->status.fd[0] );
1047     rc = read_status ( gpg );
1048     if ( rc ) {
1049         DEBUG1 ("gpg_handler: read_status problem %d\n - stop", rc);
1050         return 1;
1051     }
1052
1053     return gpg->status.eof;
1054 }
1055
1056
1057 static int
1058 status_cmp (const void *ap, const void *bp)
1059 {
1060     const struct status_table_s *a = ap;
1061     const struct status_table_s *b = bp;
1062
1063     return strcmp (a->name, b->name);
1064 }
1065
1066
1067
1068 /*
1069  * Handle the status output of GnuPG.  This function does read entire
1070  * lines and passes them as C strings to the callback function (we can
1071  * use C Strings because the status output is always UTF-8 encoded).
1072  * Of course we have to buffer the lines to cope with long lines
1073  * e.g. with a large user ID.  Note: We can optimize this to only cope
1074  * with status line code we know about and skip all other stuff
1075  * without buffering (i.e. without extending the buffer).  */
1076 static GpgmeError
1077 read_status ( GpgObject gpg )
1078 {
1079     char *p;
1080     int nread;
1081     size_t bufsize = gpg->status.bufsize; 
1082     char *buffer = gpg->status.buffer;
1083     size_t readpos = gpg->status.readpos; 
1084
1085     assert (buffer);
1086     if (bufsize - readpos < 256) { 
1087         /* need more room for the read */
1088         bufsize += 1024;
1089         buffer = xtryrealloc (buffer, bufsize);
1090         if ( !buffer ) 
1091             return mk_error (Out_Of_Core);
1092     }
1093     
1094
1095     nread = _gpgme_io_read ( gpg->status.fd[0],
1096                              buffer+readpos, bufsize-readpos );
1097     if (nread == -1)
1098         return mk_error(Read_Error);
1099
1100     if (!nread) {
1101         gpg->status.eof = 1;
1102         if (gpg->status.fnc)
1103             gpg->status.fnc ( gpg->status.fnc_value, STATUS_EOF, "" );
1104         return 0;
1105     }
1106
1107     while (nread > 0) {
1108         for (p = buffer + readpos; nread; nread--, p++) {
1109             if ( *p == '\n' ) {
1110                 /* (we require that the last line is terminated by a LF) */
1111                 *p = 0;
1112                 if (!strncmp (buffer, "[GNUPG:] ", 9 )
1113                     && buffer[9] >= 'A' && buffer[9] <= 'Z' ) {
1114                     struct status_table_s t, *r;
1115                     char *rest;
1116
1117                     rest = strchr (buffer+9, ' ');
1118                     if ( !rest )
1119                         rest = p; /* set to an empty string */
1120                     else
1121                         *rest++ = 0;
1122                     
1123                     t.name = buffer+9;
1124                     /* (the status table as one extra element) */
1125                     r = bsearch ( &t, status_table, DIM(status_table)-1,
1126                                   sizeof t, status_cmp );
1127                     if ( r ) {
1128                         if ( gpg->cmd.used
1129                              && ( r->code == STATUS_GET_BOOL
1130                                   || r->code == STATUS_GET_LINE
1131                                   || r->code == STATUS_GET_HIDDEN )) {
1132                             gpg->cmd.code = r->code;
1133                             xfree (gpg->cmd.keyword);
1134                             gpg->cmd.keyword = xtrystrdup (rest);
1135                             if ( !gpg->cmd.keyword )
1136                                 return mk_error (Out_Of_Core);
1137                             /* this should be the last thing we have received
1138                              * and the next thing will be that the command
1139                              * handler does its action */
1140                             if ( nread > 1 )
1141                                 DEBUG0 ("ERROR, unexpected data in read_status");
1142                             _gpgme_thaw_fd (gpg->cmd.fd);
1143                         }
1144                         else if ( gpg->status.fnc ) {
1145                             gpg->status.fnc ( gpg->status.fnc_value, 
1146                                               r->code, rest);
1147                         }
1148                     
1149                         if ( r->code == STATUS_END_STREAM ) {
1150                             if ( gpg->cmd.used )
1151                                 _gpgme_freeze_fd ( gpg->cmd.fd );
1152                         }
1153                     }
1154                 }
1155                 /* To reuse the buffer for the next line we have to
1156                  * shift the remaining data to the buffer start and
1157                  * restart the loop Hmmm: We can optimize this
1158                  * function by looking forward in the buffer to see
1159                  * whether a second complete line is available and in
1160                  * this case avoid the memmove for this line.  */
1161                 nread--; p++;
1162                 if (nread)
1163                     memmove (buffer, p, nread);
1164                 readpos = 0;
1165                 break; /* the for loop */
1166             }
1167             else
1168                 readpos++;
1169         }
1170     } 
1171
1172     /* Update the gpg object.  */
1173     gpg->status.bufsize = bufsize;
1174     gpg->status.buffer = buffer;
1175     gpg->status.readpos = readpos;
1176     return 0;
1177 }
1178
1179
1180 /*
1181  * This colonline handler thing is not the clean way to do it.
1182  * It might be better to enhance the GpgmeData object to act as
1183  * a wrapper for a callback.  Same goes for the status thing.
1184  * For now we use this thing here becuase it is easier to implement.
1185  */
1186 static int
1187 gpg_colon_line_handler ( void *opaque, int pid, int fd )
1188 {
1189     GpgObject gpg = opaque;
1190     GpgmeError rc = 0;
1191
1192     assert ( fd == gpg->colon.fd[0] );
1193     rc = read_colon_line ( gpg );
1194     if ( rc ) {
1195         DEBUG1 ("gpg_colon_line_handler: "
1196                  "read problem %d\n - stop", rc);
1197         return 1;
1198     }
1199
1200     return gpg->colon.eof;
1201 }
1202
1203 static GpgmeError
1204 read_colon_line ( GpgObject gpg )
1205 {
1206     char *p;
1207     int nread;
1208     size_t bufsize = gpg->colon.bufsize; 
1209     char *buffer = gpg->colon.buffer;
1210     size_t readpos = gpg->colon.readpos; 
1211
1212     assert (buffer);
1213     if (bufsize - readpos < 256) { 
1214         /* need more room for the read */
1215         bufsize += 1024;
1216         buffer = xtryrealloc (buffer, bufsize);
1217         if ( !buffer ) 
1218             return mk_error (Out_Of_Core);
1219     }
1220     
1221
1222     nread = _gpgme_io_read ( gpg->colon.fd[0],
1223                              buffer+readpos, bufsize-readpos );
1224     if (nread == -1)
1225         return mk_error(Read_Error);
1226
1227     if (!nread) {
1228         gpg->colon.eof = 1;
1229         assert (gpg->colon.fnc);
1230         gpg->colon.fnc ( gpg->colon.fnc_value, NULL );
1231         return 0;
1232     }
1233
1234     while (nread > 0) {
1235         for (p = buffer + readpos; nread; nread--, p++) {
1236             if ( *p == '\n' ) {
1237                 /* (we require that the last line is terminated by a
1238                  * LF) and we skip empty lines.  Note: we use UTF8
1239                  * encoding and escaping of special characters
1240                  * We require at least one colon to cope with
1241                  * some other printed information.
1242                  */
1243                 *p = 0;
1244                 if ( gpg->colon.simple
1245                      || (*buffer && strchr (buffer, ':')) ) {
1246                     assert (gpg->colon.fnc);
1247                     gpg->colon.fnc ( gpg->colon.fnc_value, buffer );
1248                 }
1249             
1250                 /* To reuse the buffer for the next line we have to
1251                  * shift the remaining data to the buffer start and
1252                  * restart the loop Hmmm: We can optimize this
1253                  * function by looking forward in the buffer to see
1254                  * whether a second complete line is available and in
1255                  * this case avoid the memmove for this line.  */
1256                 nread--; p++;
1257                 if (nread)
1258                     memmove (buffer, p, nread);
1259                 readpos = 0;
1260                 break; /* the for loop */
1261             }
1262             else
1263                 readpos++;
1264         }
1265     } 
1266     
1267     /* Update the gpg object.  */
1268     gpg->colon.bufsize = bufsize;
1269     gpg->colon.buffer  = buffer;
1270     gpg->colon.readpos = readpos;
1271     return 0;
1272 }
1273
1274 static GpgmeError
1275 pipemode_copy (char *buffer, size_t length, size_t *nread, GpgmeData data )
1276 {
1277     GpgmeError err;
1278     int nbytes;
1279     char tmp[1000], *s, *d;
1280
1281     /* we can optimize this whole thing but for now we just
1282      * return after each escape character */
1283     if (length > 990)
1284         length = 990;
1285
1286     err = gpgme_data_read ( data, tmp, length, &nbytes );
1287     if (err)
1288         return err;
1289     for (s=tmp, d=buffer; nbytes; s++, nbytes--) {
1290         *d++ = *s;
1291         if (*s == '@' ) {
1292             *d++ = '@';
1293             break;
1294         }
1295     }
1296     *nread = d - buffer;
1297     return 0;
1298 }
1299
1300
1301 static int
1302 pipemode_cb ( void *opaque, char *buffer, size_t length, size_t *nread )
1303 {
1304     GpgObject gpg = opaque;
1305     GpgmeError err;
1306
1307     if ( !buffer || !length || !nread )
1308         return 0; /* those values are reserved for extensions */
1309     *nread =0;
1310     if ( !gpg->pm.stream_started ) {
1311         assert (length > 4 );
1312         strcpy (buffer, "@<@B" );
1313         *nread = 4;
1314         gpg->pm.stream_started = 1;
1315     }
1316     else if ( gpg->pm.sig ) {
1317         err = pipemode_copy ( buffer, length, nread, gpg->pm.sig );
1318         if ( err == GPGME_EOF ) {
1319             gpg->pm.sig = NULL;
1320             assert (length > 4 );
1321             strcpy (buffer, "@t" );
1322             *nread = 2;
1323         }
1324         else if (err) {
1325             DEBUG1 ("pipemode_cb: copy sig failed: %s\n",
1326                      gpgme_strerror (err) );
1327             return -1;
1328         }
1329     }
1330     else if ( gpg->pm.text ) {
1331         err = pipemode_copy ( buffer, length, nread, gpg->pm.text );
1332         if ( err == GPGME_EOF ) {
1333             gpg->pm.text = NULL;
1334             assert (length > 4 );
1335             strcpy (buffer, "@.@>" );
1336             *nread = 4;
1337         }
1338         else if (err) {
1339             DEBUG1 ("pipemode_cb: copy data failed: %s\n",
1340                      gpgme_strerror (err) );
1341             return -1;
1342         }
1343     }
1344     else {
1345         return 0; /* eof */
1346     }
1347
1348     return 0;
1349 }
1350
1351
1352 /* 
1353  * Here we handle --command-fd.  This works closely together with
1354  * the status handler.  
1355  */
1356
1357 static int
1358 command_cb ( void *opaque, char *buffer, size_t length, size_t *nread )
1359 {
1360     GpgObject gpg = opaque;
1361     const char *value;
1362     int value_len;
1363
1364     DEBUG0 ("command_cb: enter\n");
1365     assert (gpg->cmd.used);
1366     if ( !buffer || !length || !nread )
1367         return 0; /* those values are reserved for extensions */
1368     *nread =0;
1369     if ( !gpg->cmd.code ) {
1370         DEBUG0 ("command_cb: no code\n");
1371         return -1;
1372     }
1373     
1374     if ( !gpg->cmd.fnc ) {
1375         DEBUG0 ("command_cb: no user cb\n");
1376         return -1;
1377     }
1378
1379     value = gpg->cmd.fnc ( gpg->cmd.fnc_value, 
1380                            gpg->cmd.code, gpg->cmd.keyword );
1381     if ( !value ) {
1382         DEBUG0 ("command_cb: no data from user cb\n");
1383         gpg->cmd.fnc ( gpg->cmd.fnc_value, 0, value);
1384         return -1;
1385     }
1386
1387     value_len = strlen (value);
1388     if ( value_len+1 > length ) {
1389         DEBUG0 ("command_cb: too much data from user cb\n");
1390         gpg->cmd.fnc ( gpg->cmd.fnc_value, 0, value);
1391         return -1;
1392     }
1393
1394     memcpy ( buffer, value, value_len );
1395     if ( !value_len || (value_len && value[value_len-1] != '\n') ) 
1396         buffer[value_len++] = '\n';
1397     *nread = value_len;
1398     
1399     gpg->cmd.fnc ( gpg->cmd.fnc_value, 0, value);
1400     gpg->cmd.code = 0;
1401     /* and sleep again until read_status will wake us up again */
1402     _gpgme_freeze_fd ( gpg->cmd.fd );
1403     return 0;
1404 }
1405
1406
1407
1408