9a8cce047ccce5cf46b61131d9adb682535b0b51
[gpgme.git] / gpgme / data.c
1 /* data.c
2  *      Copyright (C) 2000 Werner Koch (dd9jn)
3  *      Copyright (C) 2001, 2002 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 <sys/types.h>
29 #include <sys/stat.h>
30 #include "syshdr.h"
31
32 #include "util.h"
33 #include "context.h"
34 #include "ops.h"
35 #include "io.h"
36
37 /* When expanding an internal buffer, always extend it by ALLOC_CHUNK
38    bytes at a time.  */
39 #define ALLOC_CHUNK 1024
40
41
42 /**
43  * gpgme_data_new:
44  * @r_dh: returns the new data object 
45  * 
46  * Create a new data object without any content. 
47  * 
48  * Return value: An error value or 0 on success
49  **/
50 GpgmeError
51 gpgme_data_new (GpgmeData *r_dh)
52 {
53   GpgmeData dh;
54
55   if (!r_dh)
56     return mk_error (Invalid_Value);
57   *r_dh = NULL;
58
59   dh = xtrycalloc (1, sizeof *dh);
60   if (!dh)
61     return mk_error (Out_Of_Core);
62
63   dh->mode = GPGME_DATA_MODE_INOUT; 
64
65   *r_dh = dh;
66   return 0;
67 }
68
69
70 /**
71  * gpgme_data_new_from_mem:
72  * @r_dh:   Returns a new data object.
73  * @buffer: Initialize with this.
74  * @size: Size of the buffer
75  * @copy: Flag wether a copy of the buffer should be used.
76  * 
77  * Create a new data object and initialize with data from the memory.
78  * A @copy with value %TRUE creates a copy of the memory, a value of
79  * %FALSE uses the original memory of @buffer and the caller has to
80  * make sure that this buffer is valid until gpgme_data_release() is
81  * called.
82  * 
83  * Return value: An error value or 0 for success.
84  **/
85 GpgmeError
86 gpgme_data_new_from_mem (GpgmeData *r_dh, const char *buffer, size_t size,
87                          int copy)
88 {
89   GpgmeData dh;
90   GpgmeError err;
91
92   if (!r_dh)
93     return mk_error (Invalid_Value);
94   *r_dh = NULL;
95   if (!buffer)
96     return mk_error (Invalid_Value);
97
98   err = gpgme_data_new (&dh);
99   if (err)
100     return err;
101
102   dh->type = GPGME_DATA_TYPE_MEM;
103   dh->len = size;
104   if (!copy)
105     dh->data = buffer;
106   else
107     {
108       dh->private_buffer = xtrymalloc (size);
109       if (!dh->private_buffer)
110         {
111           gpgme_data_release (dh);
112           return mk_error (Out_Of_Core);
113         }
114       dh->private_len = size;
115       memcpy (dh->private_buffer, buffer, size);
116       dh->data = dh->private_buffer;
117       dh->writepos = size;
118     }
119
120   *r_dh = dh;
121   return 0;
122 }
123
124
125 /**
126  * gpgme_data_new_with_read_cb:
127  * @r_dh: returns the new data object
128  * @read_cb: callback function
129  * @read_cb_value: value passed to the callback function
130  * 
131  * Create a new data object which is a wrapper around the callback function.
132  * The callback function is defined as:
133  * <literal>
134  * typedef int (*read_cb) (void *cb_value,
135  *                         char *buffer,
136  *                         size_t count,
137  *                         size_t *nread);
138  * </literal>
139  *
140  * The callback should return a maximium of @count bytes in @buffer
141  * and the number actually read in @nread.  It may return 0 in @nread
142  * if there are no bytes currently available.  To indicate EOF the
143  * function should return with an error code of %-1 and set @nread to
144  * 0.  The callback may support passing %NULL for @buffer and @nread
145  * and %0 for count as an indication to reset its internal read
146  * pointer.
147  *
148  * Return value: An error value or 0 for success.
149  **/
150 GpgmeError
151 gpgme_data_new_with_read_cb (GpgmeData *r_dh,
152                              int (*read_cb) (void *,char *, size_t ,size_t *),
153                              void *read_cb_value)
154 {
155   GpgmeData dh;
156   GpgmeError err;
157
158   if (!r_dh)
159     return mk_error (Invalid_Value);
160   *r_dh = NULL;
161
162   if (!read_cb)
163     return mk_error (Invalid_Value);
164
165   err = gpgme_data_new (&dh);
166   if (err)
167     return err;
168
169   dh->type = GPGME_DATA_TYPE_CB;
170   dh->mode = GPGME_DATA_MODE_OUT;
171   dh->read_cb = read_cb;
172   dh->read_cb_value = read_cb_value;
173     
174   *r_dh = dh;
175   return 0;
176 }
177
178
179 /**
180  * gpgme_data_new_from_file:
181  * @r_dh: returns the new data object
182  * @fname: filename
183  * @copy: Flag, whether the file should be copied.
184  * 
185  * Create a new data object and initialize it with the content of 
186  * the file @file.  If @copy is %True the file is immediately read in
187  * and closed.  @copy of %False is not yet supportted.
188  * 
189  * Return value: An error code or 0 on success. If the error code is
190  * %GPGME_File_Error, the OS error code is held in %errno.
191  **/
192 GpgmeError
193 gpgme_data_new_from_file (GpgmeData *r_dh, const char *fname, int copy)
194 {
195   GpgmeData dh;
196   GpgmeError err;
197   struct stat st;
198   FILE *fp;
199
200   if (!r_dh)
201     return mk_error (Invalid_Value);
202   *r_dh = NULL;
203   if (!fname)
204     return mk_error (Invalid_Value);
205
206   /* We only support copy for now.  In future we might want to honor
207      the copy flag and just store a file pointer.  */
208   if (!copy)
209     return mk_error (Not_Implemented);
210
211   err = gpgme_data_new (&dh);
212   if (err)
213     return err;
214
215   fp = fopen (fname, "rb");
216   if (!fp)
217     {
218       int save_errno = errno;
219       gpgme_data_release (dh);
220       errno = save_errno;
221       return mk_error (File_Error);
222     }
223
224   if (fstat(fileno(fp), &st))
225     {
226       int save_errno = errno;
227       fclose (fp);
228       gpgme_data_release (dh);
229       errno = save_errno;
230       return mk_error (File_Error);
231     }
232
233   /* We should check the length of the file and don't allow for too
234      large files.  */
235   dh->private_buffer = xtrymalloc (st.st_size);
236   if (!dh->private_buffer)
237     {
238       fclose (fp);
239       gpgme_data_release (dh);
240       return mk_error (Out_Of_Core);
241     }
242   dh->private_len = st.st_size;
243
244   while (fread (dh->private_buffer, dh->private_len, 1, fp) < 1
245          && ferror (fp) && errno == EINTR);
246
247   if (ferror (fp))
248     {
249       int save_errno = errno;
250       fclose (fp);
251       gpgme_data_release (dh);
252       errno = save_errno;
253       return mk_error (File_Error);
254     }
255
256   fclose (fp);
257
258   dh->type = GPGME_DATA_TYPE_MEM;
259   dh->len = dh->private_len;
260   dh->data = dh->private_buffer;
261   dh->writepos = dh->len;
262     
263   *r_dh = dh;
264   return 0;
265 }
266
267
268 /**
269  * gpgme_data_new_from_filepart:
270  * @r_dh: returns the new data object
271  * @fname: filename
272  * @fp: filepointer
273  * @offset: Start reading at this offset
274  * @length: Read this many bytes 
275  * 
276  * Create a new data object and initialize it with @length bytes
277  * starting at @offset of @file or @fp.  Either a filename or an open
278  * filepointer may be given.
279  *
280  *
281  * Return value: An error code or 0 on success. If the error code is
282  * %GPGME_File_Error, the OS error code is held in %errno.
283  **/
284 GpgmeError
285 gpgme_data_new_from_filepart (GpgmeData *r_dh, const char *fname, FILE *fp,
286                               off_t offset, off_t length)
287 {
288   GpgmeData dh;
289   GpgmeError err;
290   int save_errno = 0;
291
292   if (!r_dh)
293     return mk_error (Invalid_Value);
294   *r_dh = NULL;
295
296   if ((fname && fp) || (!fname && !fp))
297     return mk_error (Invalid_Value);
298
299   err = gpgme_data_new (&dh);
300   if (err)
301     return err;
302
303   if (!length)
304     goto out;
305
306   if (fname)
307     {
308       fp = fopen (fname, "rb");
309       if (!fp)
310         {
311           err = mk_error (File_Error);
312           goto out;
313         }
314     }
315
316   if (fseek (fp, (long) offset, SEEK_SET))
317     {
318       err = mk_error (File_Error);
319       goto out;
320     }
321
322   dh->private_buffer = xtrymalloc (length);
323   if (!dh->private_buffer)
324     {
325       err = mk_error (Out_Of_Core);
326       goto out;
327     }
328   dh->private_len = length;
329   
330   while (fread (dh->private_buffer, dh->private_len, 1, fp) < 1
331          && ferror (fp) && errno == EINTR);
332
333   if (ferror (fp))
334     {
335       err = mk_error (File_Error);
336       goto out;
337     }
338       
339   dh->type = GPGME_DATA_TYPE_MEM;
340   dh->len = dh->private_len;
341   dh->data = dh->private_buffer;
342   dh->writepos = dh->len;
343
344  out:
345   if (err)
346     save_errno = errno;
347
348   if (fname && fp)
349     fclose (fp);
350
351   if (err)
352     {
353       gpgme_data_release (dh);
354       errno = save_errno;
355     }
356   else
357     *r_dh = dh;
358   return err;
359 }
360
361
362 /**
363  * gpgme_data_release:
364  * @dh: Data object 
365  * 
366  * Release the data object @dh.  @dh may be NULL in which case nothing
367  * happens.
368  **/
369 void
370 gpgme_data_release (GpgmeData dh)
371 {
372   if (dh)
373     {
374       xfree (dh->private_buffer); 
375       xfree (dh);
376     }
377 }
378
379
380 /*
381  * Release the data object @dh.  @dh may be NULL in which case nothing
382  * happens.
383  * 
384  * Return value: An allocated memory object with the content of the
385  * data object.  The function makes sure that the returned string can
386  * safely be accessed using the string fucntions.
387  **/
388 char *
389 _gpgme_data_release_and_return_string (GpgmeData dh)
390 {
391   char *val = NULL;
392
393   if (dh)
394     {
395       if (_gpgme_data_append (dh, "", 1)) /* append EOS */
396         xfree (dh->private_buffer );
397       else
398         {
399           val = dh->private_buffer;
400           if (!val && dh->data)
401             {
402               val = xtrymalloc (dh->len);
403               if (val)
404                 memcpy (val, dh->data, dh->len);
405             }
406         }
407       xfree (dh);
408     }
409   return val;
410 }
411
412
413 /**
414  * gpgme_data_release_and_get_mem:
415  * @dh: the data object
416  * @r_len: returns the length of the memory
417  * 
418  * Release the data object @dh and return its content and the length
419  * of that content.  The caller has to free this data.  @dh maybe NULL
420  * in which case NULL is returned.  If there is not enough memory for
421  * allocating the return value, NULL is returned and the object is
422  * released.
423  * 
424  * Return value: a pointer to an allocated buffer of length @r_len.
425  **/
426 char *
427 gpgme_data_release_and_get_mem (GpgmeData dh, size_t *r_len)
428 {
429   char *val = NULL;
430
431   if (r_len)
432     *r_len = 0;
433   if (dh)
434     {
435       size_t len = dh->len;
436       val = dh->private_buffer;
437       if (!val && dh->data)
438         {
439           val = xtrymalloc (len);
440           if (val)
441             memcpy (val, dh->data, len);
442         }
443       xfree (dh);
444       if (val && r_len)
445         *r_len = len;
446     }
447   return val;
448 }
449
450
451 /**
452  * gpgme_data_get_type:
453  * @dh: the data object
454  * 
455  * Get the type of the data object.
456  * Data types are prefixed with %GPGME_DATA_TYPE_
457  * 
458  * Return value: the data type
459  **/
460 GpgmeDataType
461 gpgme_data_get_type (GpgmeData dh)
462 {
463   if (!dh || (!dh->data && !dh->read_cb))
464     return GPGME_DATA_TYPE_NONE;
465
466   return dh->type;
467 }
468
469
470 void 
471 _gpgme_data_set_mode (GpgmeData dh, GpgmeDataMode mode)
472 {
473   assert (dh);
474   dh->mode = mode;
475 }
476
477
478 GpgmeDataMode
479 _gpgme_data_get_mode (GpgmeData dh)
480 {
481   assert (dh);
482   return dh->mode;
483 }
484
485
486 /**
487  * gpgme_data_rewind:
488  * @dh: the data object 
489  * 
490  * Prepare the data object in a way, that a gpgme_data_read() does start
491  * at the beginning of the data.  This has to be done for all types
492  * of data objects.
493  * 
494  * Return value: An error code or 0 on success
495  **/
496 GpgmeError
497 gpgme_data_rewind (GpgmeData dh)
498 {
499   if (!dh)
500     return mk_error (Invalid_Value);
501
502   switch (dh->type)
503     {
504     case GPGME_DATA_TYPE_NONE:
505     case GPGME_DATA_TYPE_MEM:
506       dh->readpos = 0;
507       return 0;
508
509     case GPGME_DATA_TYPE_CB:
510       dh->len = dh->readpos = 0;
511       dh->read_cb_eof = 0;
512       if (dh->read_cb (dh->read_cb_value, NULL, 0, NULL))
513         return mk_error (Not_Implemented);
514       return 0;
515
516     default:
517       return mk_error (General_Error);
518     }
519 }
520
521 /**
522  * gpgme_data_read:
523  * @dh: the data object
524  * @buffer: A buffer 
525  * @length: The length of that bufer
526  * @nread: Returns the number of bytes actually read.
527  * 
528  * Copy data from the current read position (which may be set by
529  * gpgme_data_rewind()) to the supplied @buffer, max. @length bytes
530  * are copied and the actual number of bytes are returned in @nread.
531  * If there are no more bytes available %GPGME_EOF is returned and @nread
532  * is set to 0.
533  *
534  * With a @buffer of NULL, the function does only return the number of
535  * bytes available and does not move the read pointer.  This does only
536  * work for certain data types, all other will respond with an
537  * %GPGME_Invalid_Type.
538  * 
539  * Return value: An error code or 0 on success, EOF is indcated by the
540  * error code GPGME_EOF.
541  **/
542 GpgmeError
543 gpgme_data_read (GpgmeData dh, char *buffer, size_t length, size_t *nread)
544 {
545   size_t nbytes;
546
547   if (!dh)
548     return mk_error (Invalid_Value);
549   
550   switch (dh->type)
551     {
552     case GPGME_DATA_TYPE_MEM:
553       nbytes = dh->len - dh->readpos;
554       if (!nbytes)
555         {
556           *nread = 0;
557           return mk_error(EOF);
558         }
559
560       if (!buffer)
561         *nread = nbytes;
562       else
563         {
564           if (nbytes > length)
565             nbytes = length;
566           memcpy (buffer, dh->data + dh->readpos, nbytes);
567           *nread = nbytes;
568           dh->readpos += nbytes;
569         }
570       return 0;
571     
572     case GPGME_DATA_TYPE_CB:
573       if (!buffer)
574         {
575           *nread = 0;
576           return mk_error (Invalid_Type);
577         }
578       nbytes = dh->len - dh->readpos;
579       if (nbytes)
580         {
581           /* We have unread data - return this.  */
582           if (nbytes > length)
583             nbytes = length;
584           memcpy (buffer, dh->data + dh->readpos, nbytes);
585           *nread = nbytes;
586           dh->readpos += nbytes;
587         }
588       else
589         {
590           /* Get the data from the callback.  */
591           if (!dh->read_cb || dh->read_cb_eof)
592             { 
593               *nread = 0;
594               return mk_error (EOF);
595             }
596           if (dh->read_cb (dh->read_cb_value, buffer, length, nread))
597             {
598               *nread = 0;
599               dh->read_cb_eof = 1;
600               return mk_error (EOF);
601             }
602         }
603       return 0;
604       
605     default:
606       return mk_error (General_Error);
607     }
608
609
610
611 GpgmeError
612 _gpgme_data_unread (GpgmeData dh, const char *buffer, size_t length)
613 {
614    if (!dh)
615      return mk_error (Invalid_Value);
616
617    if (dh->type == GPGME_DATA_TYPE_MEM)
618      {
619        /* Check that we don't unread more than we have yet read.  */
620        if (dh->readpos < length)
621          return mk_error (Invalid_Value);
622        /* No need to use the buffer for this data type.  */
623        dh->readpos -= length;
624      }
625    else
626      return mk_error (General_Error);
627
628    return 0;
629 }
630
631
632 /* 
633  * This function does make sense when we know that it contains no nil chars.
634  */
635 char *
636 _gpgme_data_get_as_string (GpgmeData dh)
637 {
638   char *val = NULL;
639
640   if (dh)
641     {
642       val = xtrymalloc (dh->len+1);
643       if (val)
644         {
645           memcpy (val, dh->data, dh->len);
646           val[dh->len] = 0;
647         }
648     }
649   return val;
650 }
651
652
653 /**
654  * gpgme_data_write:
655  * @dh: the context
656  * @buffer: data to be written to the data object
657  * @length: length of this data
658  * 
659  * Write the content of @buffer to the data object @dh at the current write
660  * position. 
661  * 
662  * Return value: 0 on success or an error code
663  **/
664 GpgmeError
665 gpgme_data_write (GpgmeData dh, const char *buffer, size_t length)
666 {
667   if (!dh || !buffer)
668     return mk_error (Invalid_Value);
669       
670   return _gpgme_data_append (dh, buffer, length );
671 }
672
673
674 GpgmeError
675 _gpgme_data_append (GpgmeData dh, const char *buffer, size_t length)
676 {
677   assert (dh);
678
679   if (dh->type == GPGME_DATA_TYPE_NONE)
680     {
681       /* Convert it to a mem data type.  */
682       assert (!dh->private_buffer);
683       dh->type = GPGME_DATA_TYPE_MEM;
684       dh->private_len = length < ALLOC_CHUNK? ALLOC_CHUNK : length;
685       dh->private_buffer = xtrymalloc (dh->private_len);
686       if (!dh->private_buffer)
687         {
688           dh->private_len = 0;
689           return mk_error (Out_Of_Core);
690         }
691       dh->writepos = 0;
692       dh->data = dh->private_buffer;
693     }
694   else if (dh->type != GPGME_DATA_TYPE_MEM)
695     return mk_error (Invalid_Type);
696     
697   if (dh->mode != GPGME_DATA_MODE_INOUT 
698       && dh->mode != GPGME_DATA_MODE_IN)
699     return mk_error (Invalid_Mode);
700
701   if (!dh->private_buffer)
702     {
703       /* We have to copy it now.  */
704       assert (dh->data);
705       dh->private_len = dh->len+length;
706       if (dh->private_len < ALLOC_CHUNK)
707         dh->private_len = ALLOC_CHUNK;
708       dh->private_buffer = xtrymalloc (dh->private_len);
709       if (!dh->private_buffer)
710         {
711           dh->private_len = 0;
712           return mk_error (Out_Of_Core);
713         }
714       memcpy (dh->private_buffer, dh->data, dh->len);
715       dh->writepos = dh->len;
716       dh->data = dh->private_buffer;
717     }
718
719     /* Allocate more memory if needed.  */
720   if (dh->writepos + length > dh->private_len)
721     {
722       char *p;
723       size_t newlen = dh->private_len
724         + (length < ALLOC_CHUNK? ALLOC_CHUNK : length);
725       p = xtryrealloc (dh->private_buffer, newlen);
726       if (!p) 
727         return mk_error (Out_Of_Core);
728       dh->private_buffer = p;
729       dh->private_len = newlen;
730       dh->data = dh->private_buffer;
731       assert (!(dh->writepos + length > dh->private_len));
732     }
733
734   memcpy (dh->private_buffer + dh->writepos, buffer, length);
735   dh->writepos += length;
736   dh->len += length;
737
738   return 0;
739 }
740
741
742 GpgmeError
743 _gpgme_data_append_string (GpgmeData dh, const char *s)
744 {
745   return _gpgme_data_append (dh, s, s ? strlen(s) : 0);
746 }
747
748
749 GpgmeError
750 _gpgme_data_append_for_xml (GpgmeData dh,
751                             const char *buffer, size_t len)
752 {
753   const char *text, *s;
754   size_t n;
755   int rc = 0; 
756        
757   if (!dh || !buffer)
758     return mk_error (Invalid_Value);
759
760   do
761     {
762       for (text=NULL, s = buffer, n = len; n && !text; s++, n--)
763         {
764           if (*s == '<') 
765             text = "&lt;";
766           else if (*s == '>')
767             text = "&gt;";  /* Not sure whether this is really needed.  */
768           else if (*s == '&')
769             text = "&amp;";
770           else if (!*s)
771             text = "&#00;";
772         }
773       if (text)
774         {
775           s--;
776           n++;
777         }
778       if (s != buffer) 
779         rc = _gpgme_data_append (dh, buffer, s-buffer);
780       if (!rc && text)
781         {
782           rc = _gpgme_data_append_string (dh, text);
783           s++;
784           n--;
785         }
786       buffer = s;
787       len = n;
788     }
789   while (!rc && len);
790   return rc;
791 }
792
793
794 /*
795  * Append a string to DATA and convert it so that the result will be 
796  * valid XML. 
797  */
798 GpgmeError
799 _gpgme_data_append_string_for_xml (GpgmeData dh, const char *string)
800 {
801   return _gpgme_data_append_for_xml (dh, string, strlen (string));
802 }
803
804
805 static int
806 hextobyte(const byte *s)
807 {
808   int c;
809
810   if (*s >= '0' && *s <= '9')
811     c = 16 * (*s - '0');
812   else if (*s >= 'A' && *s <= 'F')
813     c = 16 * (10 + *s - 'A');
814   else if (*s >= 'a' && *s <= 'f')
815     c = 16 * (10 + *s - 'a');
816   else
817     return -1;
818   s++;
819   if (*s >= '0' && *s <= '9')
820     c += *s - '0';
821   else if (*s >= 'A' && *s <= 'F')
822     c += 10 + *s - 'A';
823   else if (*s >= 'a' && *s <= 'f')
824     c += 10 + *s - 'a';
825   else
826     return -1;
827   return c;
828 }
829
830 /* 
831  * Append a string with percent style (%XX) escape characters as XML.
832  */
833 GpgmeError
834 _gpgme_data_append_percentstring_for_xml (GpgmeData dh, const char *string)
835 {
836   const byte *s;
837   byte *buf, *d;
838   int val;
839   GpgmeError err;
840
841   d = buf = xtrymalloc (strlen (string));
842   for (s = string; *s; s++)
843     {
844       if (*s == '%' && (val = hextobyte (s+1)) != -1)
845         {
846           *d++ = val;
847           s += 2;
848         }
849       else
850         *d++ = *s;
851     }
852
853   err = _gpgme_data_append_for_xml (dh, buf, d - buf);
854   xfree (buf);
855   return err;
856 }
857
858 /* Functions to support the wait interface.  */
859
860 int
861 _gpgme_data_inbound_handler (void *opaque, int pid, int fd)
862 {
863   GpgmeData dh = opaque;
864   GpgmeError err;
865   int nread;
866   char buf[200];
867
868   assert (_gpgme_data_get_mode (dh) == GPGME_DATA_MODE_IN);
869
870   nread = _gpgme_io_read (fd, buf, 200);
871   if (nread < 0)
872     {
873       DEBUG3 ("read_mem_data: read failed on fd %d (n=%d): %s",
874               fd, nread, strerror (errno) );
875       return 1;
876     }
877   else if (!nread)
878     return 1; /* eof */
879
880   /* We could improve this with a GpgmeData function which takes
881    * the read function or provides a memory area for writing to it.
882    */
883     
884   err = _gpgme_data_append (dh, buf, nread);
885   if (err)
886     {
887       DEBUG1 ("_gpgme_append_data failed: %s\n",
888               gpgme_strerror(err));
889       /* Fixme: we should close the pipe or read it to /dev/null in
890        * this case. Returnin EOF is not sufficient */
891       return 1;
892     }
893
894   return 0;
895 }
896
897 static int
898 write_mem_data (GpgmeData dh, int fd)
899 {
900   size_t nbytes;
901   int nwritten; 
902
903   nbytes = dh->len - dh->readpos;
904   if (!nbytes)
905     {
906       _gpgme_io_close (fd);
907       return 1;
908     }
909     
910   /* FIXME: Arggg, the pipe blocks on large write request, although
911    * select told us that it is okay to write - need to figure out
912    * why this happens?  Stevens says nothing about this problem (or
913    * is it my Linux kernel 2.4.0test1)
914    * To avoid that we have set the pipe to nonblocking.
915    */
916
917   nwritten = _gpgme_io_write (fd, dh->data+dh->readpos, nbytes);
918   if (nwritten == -1 && errno == EAGAIN)
919     return 0;
920   if (nwritten < 1)
921     {
922       DEBUG3 ("write_mem_data(%d): write failed (n=%d): %s",
923               fd, nwritten, strerror (errno));
924       _gpgme_io_close (fd);
925       return 1;
926     }
927
928   dh->readpos += nwritten;
929   return 0;
930 }
931
932 static int
933 write_cb_data (GpgmeData dh, int fd)
934 {
935   size_t nbytes;
936   int  err, nwritten; 
937   char buffer[512];
938
939   err = gpgme_data_read (dh, buffer, DIM(buffer), &nbytes);
940   if (err == GPGME_EOF)
941     {
942       _gpgme_io_close (fd);
943       return 1;
944     }
945     
946   nwritten = _gpgme_io_write (fd, buffer, nbytes);
947   if (nwritten == -1 && errno == EAGAIN )
948     return 0;
949   if (nwritten < 1)
950     {
951       DEBUG3 ("write_cb_data(%d): write failed (n=%d): %s",
952               fd, nwritten, strerror (errno));
953       _gpgme_io_close (fd);
954       return 1;
955     }
956
957   if (nwritten < nbytes)
958     {
959       /* ugly, ugly: It does currently only for for MEM type data */
960       if (_gpgme_data_unread (dh, buffer + nwritten, nbytes - nwritten))
961         DEBUG1 ("wite_cb_data: unread of %d bytes failed\n",
962                 nbytes - nwritten);
963       _gpgme_io_close (fd);
964       return 1;
965     }
966   
967   return 0;
968 }
969
970 int
971 _gpgme_data_outbound_handler (void *opaque, int pid, int fd)
972 {
973   GpgmeData dh = opaque;
974
975   assert (_gpgme_data_get_mode (dh) == GPGME_DATA_MODE_OUT);
976   switch (gpgme_data_get_type (dh))
977     {
978     case GPGME_DATA_TYPE_MEM:
979       if (write_mem_data (dh, fd))
980         return 1; /* ready */
981       break;
982     case GPGME_DATA_TYPE_CB:
983       if (write_cb_data (dh, fd))
984         return 1; /* ready */
985       break;
986     default:
987       assert (0);
988     }
989   
990   return 0;
991 }