See ChangeLog: Sat Jun 26 12:15:59 CEST 1999 Werner Koch
[gnupg.git] / util / iobuf.c
1 /* iobuf.c  -  file handling
2  *      Copyright (C) 1998, 1999 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <assert.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <unistd.h>
30
31 #include "memory.h"
32 #include "util.h"
33 #include "iobuf.h"
34
35 typedef struct {
36     FILE *fp;      /* open file handle */
37     int  print_only_name; /* flags indicating that fname is not a real file*/
38     char fname[1]; /* name of the file */
39 } file_filter_ctx_t ;
40
41
42 /* The first partial length header block must be of size 512
43  * to make it easier (and efficienter) we use a min. block size of 512
44  * for all chunks (but the last one) */
45 #define OP_MIN_PARTIAL_CHUNK      512
46 #define OP_MIN_PARTIAL_CHUNK_2POW 9
47
48 typedef struct {
49     int use;
50     size_t size;
51     size_t count;
52     int partial;  /* 1 = partial header, 2 in last partial packet */
53     char *buffer;    /* used for partial header */
54     size_t buflen;   /* used size of buffer */
55     int first_c;     /* of partial header (which is > 0)*/
56     int eof;
57 } block_filter_ctx_t;
58
59
60 static int underflow(IOBUF a);
61
62 /****************
63  * Read data from a file into buf which has an allocated length of *LEN.
64  * return the number of read bytes in *LEN. OPAQUE is the FILE * of
65  * the stream. A is not used.
66  * control may be:
67  * IOBUFCTRL_INIT: called just before the function is linked into the
68  *                 list of function. This can be used to prepare internal
69  *                 data structures of the function.
70  * IOBUFCTRL_FREE: called just before the function is removed from the
71  *                  list of functions and can be used to release internal
72  *                  data structures or close a file etc.
73  * IOBUFCTRL_UNDERFLOW: called by iobuf_underflow to fill the buffer
74  *                  with new stuff. *RET_LEN is the available size of the
75  *                  buffer, and should be set to the number of bytes
76  *                  which were put into the buffer. The function
77  *                  returns 0 to indicate success, -1 on EOF and
78  *                  G10ERR_xxxxx for other errors.
79  *
80  * IOBUFCTRL_FLUSH: called by iobuf_flush() to write out the collected stuff.
81  *                  *RET_LAN is the number of bytes in BUF.
82  *
83  */
84 static int
85 file_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
86 {
87     file_filter_ctx_t *a = opaque;
88     FILE *fp = a->fp;
89     size_t size = *ret_len;
90     size_t nbytes = 0;
91     int rc = 0;
92
93     if( control == IOBUFCTRL_UNDERFLOW ) {
94         assert( size ); /* need a buffer */
95         if ( feof(fp)) {        /* On terminals you could easiely read as many EOFs as you call         */
96             rc = -1;            /* fread() or fgetc() repeatly. Every call will block until you press   */
97             *ret_len = 0;       /* CTRL-D. So we catch this case before we call fread() again.          */
98         }
99         else {
100             clearerr( fp );
101             nbytes = fread( buf, 1, size, fp );
102             if( feof(fp) && !nbytes )
103                 rc = -1; /* okay: we can return EOF now. */
104             else if( ferror(fp) && errno != EPIPE  ) {
105                 log_error("%s: read error: %s\n",
106                           a->fname, strerror(errno));
107                 rc = G10ERR_READ_FILE;
108             }
109             *ret_len = nbytes;
110         }
111     }
112     else if( control == IOBUFCTRL_FLUSH ) {
113         if( size ) {
114             clearerr( fp );
115             nbytes = fwrite( buf, 1, size, fp );
116             if( ferror(fp) ) {
117                 log_error("%s: write error: %s\n", a->fname, strerror(errno));
118                 rc = G10ERR_WRITE_FILE;
119             }
120         }
121         *ret_len = nbytes;
122     }
123     else if( control == IOBUFCTRL_INIT ) {
124     }
125     else if( control == IOBUFCTRL_DESC ) {
126         *(char**)buf = "file_filter";
127     }
128     else if( control == IOBUFCTRL_FREE ) {
129         if( fp != stdin && fp != stdout ) {
130             if( DBG_IOBUF )
131                 log_debug("%s: close fd %d\n", a->fname, fileno(fp) );
132             fclose(fp);
133         }
134         fp = NULL;
135         m_free(a); /* we can free our context now */
136     }
137
138     return rc;
139 }
140
141
142 /****************
143  * This is used to implement the block write mode.
144  * Block reading is done on a byte by byte basis in readbyte(),
145  * without a filter
146  */
147 static int
148 block_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
149 {
150     block_filter_ctx_t *a = opaque;
151     size_t size = *ret_len;
152     int c, needed, rc = 0;
153     char *p;
154
155     if( control == IOBUFCTRL_UNDERFLOW ) {
156         size_t n=0;
157
158         p = buf;
159         assert( size ); /* need a buffer */
160         if( a->eof ) /* don't read any further */
161             rc = -1;
162         while( !rc && size ) {
163             if( !a->size ) { /* get the length bytes */
164                 if( a->partial == 2 ) {
165                     a->eof = 1;
166                     if( !n )
167                         rc = -1;
168                     break;
169                 }
170                 else if( a->partial ) {
171                     /* These OpenPGP introduced huffman encoded length
172                      * bytes are really a mess :-( */
173                     if( a->first_c ) {
174                         c = a->first_c;
175                         a->first_c = 0;
176                         assert( c >= 224 && c < 255 );
177                     }
178                     else if( (c = iobuf_get(chain)) == -1 ) {
179                         log_error("block_filter: 1st length byte missing\n");
180                         rc = G10ERR_READ_FILE;
181                         break;
182                     }
183                     if( c < 192 ) {
184                         a->size = c;
185                         a->partial = 2;
186                         if( !a->size ) {
187                             a->eof = 1;
188                             if( !n )
189                                 rc = -1;
190                             break;
191                         }
192                     }
193                     else if( c < 224 ) {
194                         a->size = (c - 192) * 256;
195                         if( (c = iobuf_get(chain)) == -1 ) {
196                             log_error("block_filter: 2nd length byte missing\n");
197                             rc = G10ERR_READ_FILE;
198                             break;
199                         }
200                         a->size += c + 192;
201                         a->partial = 2;
202                         if( !a->size ) {
203                             a->eof = 1;
204                             if( !n )
205                                 rc = -1;
206                             break;
207                         }
208                     }
209                     else if( c == 255 ) {
210                         a->size  = iobuf_get(chain) << 24;
211                         a->size |= iobuf_get(chain) << 16;
212                         a->size |= iobuf_get(chain) << 8;
213                         if( (c = iobuf_get(chain)) == -1 ) {
214                             log_error("block_filter: invalid 4 byte length\n");
215                             rc = G10ERR_READ_FILE;
216                             break;
217                         }
218                         a->size |= c;
219                     }
220                     else { /* next partial body length */
221                         a->size = 1 << (c & 0x1f);
222                     }
223                 }
224                 else { /* the gnupg partial length scheme - much better :-) */
225                     c = iobuf_get(chain);
226                     a->size = c << 8;
227                     c = iobuf_get(chain);
228                     a->size |= c;
229                     if( c == -1 ) {
230                         log_error("block_filter: error reading length info\n");
231                         rc = G10ERR_READ_FILE;
232                     }
233                     if( !a->size ) {
234                         a->eof = 1;
235                         if( !n )
236                             rc = -1;
237                         break;
238                     }
239                 }
240             }
241
242             while( !rc && size && a->size ) {
243                 needed = size < a->size ? size : a->size;
244                 c = iobuf_read( chain, p, needed );
245                 if( c < needed ) {
246                     if( c == -1 ) c = 0;
247                     log_error("block_filter %p: read error (size=%lu,a->size=%lu)\n",
248                               a,  (ulong)size+c, (ulong)a->size+c);
249                     rc = G10ERR_READ_FILE;
250                 }
251                 else {
252                     size -= c;
253                     a->size -= c;
254                     p += c;
255                     n += c;
256                 }
257             }
258         }
259         *ret_len = n;
260     }
261     else if( control == IOBUFCTRL_FLUSH ) {
262         if( a->partial ) { /* the complicated openpgp scheme */
263             size_t blen, n, nbytes = size + a->buflen;
264
265             assert( a->buflen <= OP_MIN_PARTIAL_CHUNK );
266             if( nbytes < OP_MIN_PARTIAL_CHUNK ) {
267                 /* not enough to write a partial block out; so we store it*/
268                 if( !a->buffer )
269                     a->buffer = m_alloc( OP_MIN_PARTIAL_CHUNK );
270                 memcpy( a->buffer + a->buflen, buf, size );
271                 a->buflen += size;
272             }
273             else { /* okay, we can write out something */
274                 /* do this in a loop to use the most efficient block lengths */
275                 p = buf;
276                 do {
277                     /* find the best matching block length - this is limited
278                      * by the size of the internal buffering */
279                     for( blen=OP_MIN_PARTIAL_CHUNK*2,
280                             c=OP_MIN_PARTIAL_CHUNK_2POW+1; blen <= nbytes;
281                                                             blen *=2, c++ )
282                         ;
283                     blen /= 2; c--;
284                     /* write the partial length header */
285                     assert( c <= 0x1f ); /*;-)*/
286                     c |= 0xe0;
287                     iobuf_put( chain, c );
288                     if( (n=a->buflen) ) { /* write stuff from the buffer */
289                         assert( n == OP_MIN_PARTIAL_CHUNK);
290                         if( iobuf_write(chain, a->buffer, n ) )
291                             rc = G10ERR_WRITE_FILE;
292                         a->buflen = 0;
293                         nbytes -= n;
294                     }
295                     if( (n = nbytes) > blen )
296                         n = blen;
297                     if( n && iobuf_write(chain, p, n ) )
298                         rc = G10ERR_WRITE_FILE;
299                     p += n;
300                     nbytes -= n;
301                 } while( !rc && nbytes >= OP_MIN_PARTIAL_CHUNK );
302                 /* store the rest in the buffer */
303                 if( !rc && nbytes ) {
304                     assert( !a->buflen );
305                     assert( nbytes < OP_MIN_PARTIAL_CHUNK );
306                     if( !a->buffer )
307                         a->buffer = m_alloc( OP_MIN_PARTIAL_CHUNK );
308                     memcpy( a->buffer, p, nbytes );
309                     a->buflen = nbytes;
310                 }
311             }
312         }
313         else { /* the gnupg scheme (which is not openpgp compliant) */
314             size_t avail, n;
315
316             for(p=buf; !rc && size; ) {
317                 n = size;
318                 avail = a->size - a->count;
319                 if( !avail ) {
320                     if( n > a->size ) {
321                         iobuf_put( chain, (a->size >> 8) & 0xff );
322                         iobuf_put( chain, a->size & 0xff );
323                         avail = a->size;
324                         a->count = 0;
325                     }
326                     else {
327                         iobuf_put( chain, (n >> 8) & 0xff );
328                         iobuf_put( chain, n & 0xff );
329                         avail = n;
330                         a->count = a->size - n;
331                     }
332                 }
333                 if( n > avail )
334                     n = avail;
335                 if( iobuf_write(chain, p, n ) )
336                     rc = G10ERR_WRITE_FILE;
337                 a->count += n;
338                 p += n;
339                 size -= n;
340             }
341         }
342     }
343     else if( control == IOBUFCTRL_INIT ) {
344         if( DBG_IOBUF )
345             log_debug("init block_filter %p\n", a );
346         if( a->partial )
347             a->count = 0;
348         else if( a->use == 1 )
349             a->count = a->size = 0;
350         else
351             a->count = a->size; /* force first length bytes */
352         a->eof = 0;
353         a->buffer = NULL;
354         a->buflen = 0;
355     }
356     else if( control == IOBUFCTRL_DESC ) {
357         *(char**)buf = "block_filter";
358     }
359     else if( control == IOBUFCTRL_FREE ) {
360         if( a->use == 2 ) { /* write the end markers */
361             if( a->partial ) {
362                 u32 len;
363                 /* write out the remaining bytes without a partial header
364                  * the length of this header may be 0 - but if it is
365                  * the first block we are not allowed to use a partial header
366                  * and frankly we can't do so, because this length must be
367                  * a power of 2. This is _really_ complicated because we
368                  * have to check the possible length of a packet prior
369                  * to it's creation: a chain of filters becomes complicated
370                  * and we need a lot of code to handle compressed packets etc.
371                  *   :-(((((((
372                  */
373                 /* construct header */
374                 len = a->buflen;
375                 if( len < 192 )
376                     rc = iobuf_put(chain, len );
377                 else if( len < 8384 ) {
378                     if( !(rc=iobuf_put( chain, ((len-192) / 256) + 192)) )
379                         rc = iobuf_put( chain, ((len-192) % 256));
380                 }
381                 else { /* use a 4 byte header */
382                     if( !(rc=iobuf_put( chain, 0xff )) )
383                         if( !(rc=iobuf_put( chain, (len >> 24)&0xff )) )
384                             if( !(rc=iobuf_put( chain, (len >> 16)&0xff )) )
385                                 if( !(rc=iobuf_put( chain, (len >> 8)&0xff )))
386                                     rc=iobuf_put( chain, len & 0xff );
387                 }
388                 if( !rc && len )
389                     rc = iobuf_write(chain, a->buffer, len );
390                 if( rc ) {
391                     log_error("block_filter: write error: %s\n",strerror(errno));
392                     rc = G10ERR_WRITE_FILE;
393                 }
394                 m_free( a->buffer ); a->buffer = NULL; a->buflen = 0;
395             }
396             else {
397                 iobuf_writebyte(chain, 0);
398                 iobuf_writebyte(chain, 0);
399             }
400         }
401         else if( a->size ) {
402             log_error("block_filter: pending bytes!\n");
403         }
404         if( DBG_IOBUF )
405             log_debug("free block_filter %p\n", a );
406         m_free(a); /* we can free our context now */
407     }
408
409     return rc;
410 }
411
412
413 static void
414 print_chain( IOBUF a )
415 {
416     if( !DBG_IOBUF )
417         return;
418     for(; a; a = a->chain ) {
419         size_t dummy_len = 0;
420         const char *desc = "[none]";
421
422         if( a->filter )
423             a->filter( a->filter_ov, IOBUFCTRL_DESC, NULL,
424                                                 (byte*)&desc, &dummy_len );
425
426         log_debug("iobuf chain: %d.%d `%s' filter_eof=%d start=%d len=%d\n",
427                    a->no, a->subno, desc, a->filter_eof,
428                    a->d.start, a->d.len );
429     }
430 }
431
432 int
433 iobuf_print_chain( IOBUF a )
434 {
435     print_chain(a);
436     return 0;
437 }
438
439 /****************
440  * Allocate a new io buffer, with no function assigned.
441  * Use is the desired usage: 1 for input, 2 for output, 3 for temp buffer
442  * BUFSIZE is a suggested buffer size.
443  */
444 IOBUF
445 iobuf_alloc(int use, size_t bufsize)
446 {
447     IOBUF a;
448     static int number=0;
449
450     a = m_alloc_clear(sizeof *a);
451     a->use = use;
452     a->d.buf = m_alloc( bufsize );
453     a->d.size = bufsize;
454     a->no = ++number;
455     a->subno = 0;
456     a->opaque = NULL;
457     a->real_fname = NULL;
458     return a;
459 }
460
461
462 int
463 iobuf_close( IOBUF a )
464 {
465     IOBUF a2;
466     size_t dummy_len;
467     int rc=0;
468
469     if( a && a->directfp ) {
470         fclose( a->directfp );
471         m_free( a->real_fname );
472         if( DBG_IOBUF )
473             log_debug("iobuf_close -> %p\n", a->directfp );
474         return 0;
475     }
476
477     for( ; a && !rc ; a = a2 ) {
478         a2 = a->chain;
479         if( a->use == 2 && (rc=iobuf_flush(a)) )
480             log_error("iobuf_flush failed on close: %s\n", g10_errstr(rc));
481
482         if( DBG_IOBUF )
483             log_debug("iobuf-%d.%d: close `%s'\n", a->no, a->subno, a->desc );
484         if( a->filter && (rc = a->filter(a->filter_ov, IOBUFCTRL_FREE,
485                                          a->chain, NULL, &dummy_len)) )
486             log_error("IOBUFCTRL_FREE failed on close: %s\n", g10_errstr(rc) );
487         m_free(a->real_fname);
488         m_free(a->d.buf);
489         m_free(a);
490     }
491     return rc;
492 }
493
494 int
495 iobuf_cancel( IOBUF a )
496 {
497     const char *s;
498
499     if( a && a->use == 2 ) {
500         s = iobuf_get_real_fname(a);
501         if( s && *s )
502             remove(s);  /* remove the file. Fixme: this will fail for MSDOZE*/
503     }                   /* because the file is still open */
504     return iobuf_close(a);
505 }
506
507
508 /****************
509  * create a temporary iobuf, which can be used to collect stuff
510  * in an iobuf and later be written by iobuf_write_temp() to another
511  * iobuf.
512  */
513 IOBUF
514 iobuf_temp()
515 {
516     IOBUF a;
517
518     a = iobuf_alloc(3, 8192 );
519
520     return a;
521 }
522
523 IOBUF
524 iobuf_temp_with_content( const char *buffer, size_t length )
525 {
526     IOBUF a;
527
528     a = iobuf_alloc(3, length );
529     memcpy( a->d.buf, buffer, length );
530     a->d.len = length;
531
532     return a;
533 }
534
535
536 /****************
537  * Create a head iobuf for reading from a file
538  * returns: NULL if an error occures and sets errno
539  */
540 IOBUF
541 iobuf_open( const char *fname )
542 {
543     IOBUF a;
544     FILE *fp;
545     file_filter_ctx_t *fcx;
546     size_t len;
547     int print_only = 0;
548
549     if( !fname || (*fname=='-' && !fname[1])  ) {
550         fp = stdin; /* fixme: set binary mode for msdoze */
551         fname = "[stdin]";
552         print_only = 1;
553     }
554     else if( !(fp = fopen(fname, "rb")) )
555         return NULL;
556     a = iobuf_alloc(1, 8192 );
557     fcx = m_alloc( sizeof *fcx + strlen(fname) );
558     fcx->fp = fp;
559     fcx->print_only_name = print_only;
560     strcpy(fcx->fname, fname );
561     if( !print_only )
562         a->real_fname = m_strdup( fname );
563     a->filter = file_filter;
564     a->filter_ov = fcx;
565     file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
566     file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
567     if( DBG_IOBUF )
568         log_debug("iobuf-%d.%d: open `%s' fd=%d\n",
569                    a->no, a->subno, fname, fileno(fcx->fp) );
570
571     return a;
572 }
573
574 /****************
575  * Create a head iobuf for reading from a file
576  * returns: NULL if an error occures and sets errno
577  */
578 IOBUF
579 iobuf_fdopen( int fd, const char *mode )
580 {
581     IOBUF a;
582     FILE *fp;
583     file_filter_ctx_t *fcx;
584     size_t len;
585
586     if( !(fp = fdopen(fd, mode)) )
587         return NULL;
588     a = iobuf_alloc( strchr( mode, 'w')? 2:1, 8192 );
589     fcx = m_alloc( sizeof *fcx + 20 );
590     fcx->fp = fp;
591     fcx->print_only_name = 1;
592     sprintf(fcx->fname, "[fd %d]", fd );
593     a->filter = file_filter;
594     a->filter_ov = fcx;
595     file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
596     file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
597     if( DBG_IOBUF )
598         log_debug("iobuf-%d.%d: fdopen `%s'\n", a->no, a->subno, fcx->fname );
599
600     return a;
601 }
602
603 /****************
604  * create an iobuf for writing to a file; the file will be created.
605  */
606 IOBUF
607 iobuf_create( const char *fname )
608 {
609     IOBUF a;
610     FILE *fp;
611     file_filter_ctx_t *fcx;
612     size_t len;
613     int print_only = 0;
614
615     if( !fname || (*fname=='-' && !fname[1]) ) {
616         fp = stdout;
617         fname = "[stdout]";
618         print_only = 1;
619     }
620     else if( !(fp = fopen(fname, "wb")) )
621         return NULL;
622     a = iobuf_alloc(2, 8192 );
623     fcx = m_alloc( sizeof *fcx + strlen(fname) );
624     fcx->fp = fp;
625     fcx->print_only_name = print_only;
626     strcpy(fcx->fname, fname );
627     if( !print_only )
628         a->real_fname = m_strdup( fname );
629     a->filter = file_filter;
630     a->filter_ov = fcx;
631     file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
632     file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
633     if( DBG_IOBUF )
634         log_debug("iobuf-%d.%d: create `%s'\n", a->no, a->subno, a->desc );
635
636     return a;
637 }
638
639 /****************
640  * append to an iobuf; if the file does not exist, create it.
641  * cannot be used for stdout.
642  */
643 IOBUF
644 iobuf_append( const char *fname )
645 {
646     IOBUF a;
647     FILE *fp;
648     file_filter_ctx_t *fcx;
649     size_t len;
650
651     if( !fname )
652         return NULL;
653     else if( !(fp = fopen(fname, "ab")) )
654         return NULL;
655     a = iobuf_alloc(2, 8192 );
656     fcx = m_alloc( sizeof *fcx + strlen(fname) );
657     fcx->fp = fp;
658     strcpy(fcx->fname, fname );
659     a->real_fname = m_strdup( fname );
660     a->filter = file_filter;
661     a->filter_ov = fcx;
662     file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
663     file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
664     if( DBG_IOBUF )
665         log_debug("iobuf-%d.%d: append `%s'\n", a->no, a->subno, a->desc );
666
667     return a;
668 }
669
670 IOBUF
671 iobuf_openrw( const char *fname )
672 {
673     IOBUF a;
674     FILE *fp;
675     file_filter_ctx_t *fcx;
676     size_t len;
677
678     if( !fname )
679         return NULL;
680     else if( !(fp = fopen(fname, "r+b")) )
681         return NULL;
682     a = iobuf_alloc(2, 8192 );
683     fcx = m_alloc( sizeof *fcx + strlen(fname) );
684     fcx->fp = fp;
685     strcpy(fcx->fname, fname );
686     a->real_fname = m_strdup( fname );
687     a->filter = file_filter;
688     a->filter_ov = fcx;
689     file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
690     file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
691     if( DBG_IOBUF )
692         log_debug("iobuf-%d.%d: openrw `%s'\n", a->no, a->subno, a->desc );
693
694     return a;
695 }
696
697
698
699 /****************
700  * You can overwrite the normal iobuf behaviour by using this function.
701  * If used the iobuf is a simple wrapper around stdio.
702  * NULL if an error occures and sets errno
703  */
704 IOBUF
705 iobuf_fopen( const char *fname, const char *mode )
706 {
707     IOBUF a;
708     FILE *fp;
709     int print_only = 0;
710
711     if( !fname || (*fname=='-' && !fname[1])  ) {
712         fp = stdin; /* fixme: set binary mode for msdoze */
713         fname = "[stdin]";
714         print_only = 1;
715     }
716     else if( !(fp = fopen(fname, mode) ) )
717         return NULL;
718     a = iobuf_alloc(1, 8192 );
719     a->directfp = fp;
720     a->real_fname = m_strdup( fname );
721
722     if( DBG_IOBUF )
723         log_debug("iobuf_fopen -> %p\n", a->directfp );
724
725     return a;
726 }
727
728
729
730 /****************
731  * Register an i/o filter.
732  */
733 int
734 iobuf_push_filter( IOBUF a,
735                    int (*f)(void *opaque, int control,
736                    IOBUF chain, byte *buf, size_t *len), void *ov )
737 {
738     return iobuf_push_filter2( a, f, ov, 0 );
739 }
740
741 int
742 iobuf_push_filter2( IOBUF a,
743                     int (*f)(void *opaque, int control,
744                     IOBUF chain, byte *buf, size_t *len),
745                     void *ov, int rel_ov )
746 {
747     IOBUF b;
748     size_t dummy_len=0;
749     int rc=0;
750
751     if( a->directfp )
752         BUG();
753
754     if( a->use == 2 && (rc=iobuf_flush(a)) )
755         return rc;
756     /* make a copy of the current stream, so that
757      * A is the new stream and B the original one.
758      * The contents of the buffers are transferred to the
759      * new stream.
760      */
761     b = m_alloc(sizeof *b);
762     memcpy(b, a, sizeof *b );
763     /* fixme: it is stupid to keep a copy of the name at every level
764      * but we need the name somewhere because the name known by file_filter
765      * may have been released when we need the name of the file */
766     b->real_fname = a->real_fname? m_strdup(a->real_fname):NULL;
767     /* remove the filter stuff from the new stream */
768     a->filter = NULL;
769     a->filter_ov = NULL;
770     a->filter_ov_owner = 0;
771     a->filter_eof = 0;
772     if( a->use == 3 )
773         a->use = 2;  /* make a write stream from a temp stream */
774
775     if( a->use == 2 ) { /* allocate a fresh buffer for the original stream */
776         b->d.buf = m_alloc( a->d.size );
777         b->d.len = 0;
778         b->d.start = 0;
779     }
780     else { /* allocate a fresh buffer for the new stream */
781         a->d.buf = m_alloc( a->d.size );
782         a->d.len = 0;
783         a->d.start = 0;
784     }
785     /* disable nlimit for the new stream */
786     a->ntotal = b->ntotal + b->nbytes;
787     a->nlimit = a->nbytes = 0;
788     a->nofast &= ~1;
789     /* make a link from the new stream to the original stream */
790     a->chain = b;
791     a->opaque = b->opaque;
792
793     /* setup the function on the new stream */
794     a->filter = f;
795     a->filter_ov = ov;
796     a->filter_ov_owner = rel_ov;
797
798     a->subno = b->subno + 1;
799     f( ov, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &dummy_len );
800
801     if( DBG_IOBUF ) {
802         log_debug("iobuf-%d.%d: push `%s'\n", a->no, a->subno, a->desc );
803         print_chain( a );
804     }
805
806     /* now we can initialize the new function if we have one */
807     if( a->filter && (rc = a->filter(a->filter_ov, IOBUFCTRL_INIT, a->chain,
808                        NULL, &dummy_len)) )
809         log_error("IOBUFCTRL_INIT failed: %s\n", g10_errstr(rc) );
810     return rc;
811 }
812
813 /****************
814  * Remove an i/o filter.
815  */
816 int
817 pop_filter( IOBUF a, int (*f)(void *opaque, int control,
818                       IOBUF chain, byte *buf, size_t *len), void *ov )
819 {
820     IOBUF b;
821     size_t dummy_len=0;
822     int rc=0;
823
824     if( a->directfp )
825         BUG();
826
827     if( DBG_IOBUF )
828         log_debug("iobuf-%d.%d: pop `%s'\n", a->no, a->subno, a->desc );
829     if( !a->filter ) { /* this is simple */
830         b = a->chain;
831         assert(b);
832         m_free(a->d.buf);
833         m_free(a->real_fname);
834         memcpy(a,b, sizeof *a);
835         m_free(b);
836         return 0;
837     }
838     for(b=a ; b; b = b->chain )
839         if( b->filter == f && (!ov || b->filter_ov == ov) )
840             break;
841     if( !b )
842         log_bug("pop_filter(): filter function not found\n");
843
844     /* flush this stream if it is an output stream */
845     if( a->use == 2 && (rc=iobuf_flush(b)) ) {
846         log_error("iobuf_flush failed in pop_filter: %s\n", g10_errstr(rc));
847         return rc;
848     }
849     /* and tell the filter to free it self */
850     if( b->filter && (rc = b->filter(b->filter_ov, IOBUFCTRL_FREE, b->chain,
851                        NULL, &dummy_len)) ) {
852         log_error("IOBUFCTRL_FREE failed: %s\n", g10_errstr(rc) );
853         return rc;
854     }
855     if( b->filter_ov && b->filter_ov_owner ) {
856         m_free( b->filter_ov );
857         b->filter_ov = NULL;
858     }
859
860
861     /* and see how to remove it */
862     if( a == b && !b->chain )
863         log_bug("can't remove the last filter from the chain\n");
864     else if( a == b ) { /* remove the first iobuf from the chain */
865         /* everything from b is copied to a. This is save because
866          * a flush has been done on the to be removed entry
867          */
868         b = a->chain;
869         m_free(a->d.buf);
870         m_free(a->real_fname);
871         memcpy(a,b, sizeof *a);
872         m_free(b);
873         if( DBG_IOBUF )
874            log_debug("iobuf-%d.%d: popped filter\n", a->no, a->subno );
875     }
876     else if( !b->chain ) { /* remove the last iobuf from the chain */
877         log_bug("Ohh jeee, trying to remove a head filter\n");
878     }
879     else {  /* remove an intermediate iobuf from the chain */
880         log_bug("Ohh jeee, trying to remove an intermediate filter\n");
881     }
882
883     return rc;
884 }
885
886
887 /****************
888  * read underflow: read more bytes into the buffer and return
889  * the first byte or -1 on EOF.
890  */
891 static int
892 underflow(IOBUF a)
893 {
894     size_t len;
895     int rc;
896
897     assert( a->d.start == a->d.len );
898     if( a->use == 3 )
899         return -1; /* EOF because a temp buffer can't do an underflow */
900
901     if( a->filter_eof ) {
902         if( a->chain && a->filter_eof == 1 ) {
903             IOBUF b = a->chain;
904             if( DBG_IOBUF )
905                 log_debug("iobuf-%d.%d: pop `%s' in underflow\n",
906                                         a->no, a->subno, a->desc );
907             m_free(a->d.buf);
908             m_free(a->real_fname);
909             memcpy(a, b, sizeof *a);
910             m_free(b);
911             print_chain(a);
912         }
913         else
914             a->filter_eof = 0;
915         if( DBG_IOBUF )
916             log_debug("iobuf-%d.%d: underflow: eof (due to filter eof)\n",
917                                                     a->no, a->subno );
918         return -1; /* return one(!) EOF */
919     }
920     if( a->error ) {
921         if( DBG_IOBUF )
922             log_debug("iobuf-%d.%d: error\n", a->no, a->subno );
923         return -1;
924     }
925
926     if( a->directfp ) {
927         FILE *fp = a->directfp;
928
929         len = fread( a->d.buf, 1, a->d.size, fp);
930         if( len < a->d.size ) {
931             if( ferror(fp) )
932                 a->error = 1;
933         }
934         a->d.len = len;
935         a->d.start = 0;
936         return len? a->d.buf[a->d.start++] : -1;
937     }
938
939
940     if( a->filter ) {
941         len = a->d.size;
942         rc = a->filter( a->filter_ov, IOBUFCTRL_UNDERFLOW, a->chain,
943                         a->d.buf, &len );
944         if( DBG_IOBUF ) {
945             log_debug("iobuf-%d.%d: underflow: req=%lu got=%lu rc=%d\n",
946                     a->no, a->subno, (ulong)a->d.size, (ulong)len, rc );
947           #if 0
948             if( a->no == 7 ) {
949                 print_string(stderr, a->d.buf, len, 0 );
950                 putc('\n', stderr );
951             }
952           #endif
953
954         }
955         if( a->use == 1 && rc == -1 ) { /* EOF: we can remove the filter */
956             size_t dummy_len;
957
958             /* and tell the filter to free itself */
959             if( (rc = a->filter(a->filter_ov, IOBUFCTRL_FREE, a->chain,
960                                NULL, &dummy_len)) )
961                 log_error("IOBUFCTRL_FREE failed: %s\n", g10_errstr(rc) );
962             if( a->filter_ov && a->filter_ov_owner ) {
963                 m_free( a->filter_ov );
964                 a->filter_ov = NULL;
965             }
966             a->filter = NULL;
967             a->desc = NULL;
968             a->filter_ov = NULL;
969             a->filter_eof = 1;
970             if( !len && a->chain ) {
971                 IOBUF b = a->chain;
972                 if( DBG_IOBUF )
973                     log_debug("iobuf-%d.%d: pop `%s' in underflow (!len)\n",
974                                                a->no, a->subno, a->desc );
975                 print_chain(a);
976                 m_free(a->d.buf);
977                 m_free(a->real_fname);
978                 memcpy(a,b, sizeof *a);
979                 m_free(b);
980                 print_chain(a);
981             }
982         }
983         else if( rc )
984             a->error = 1;
985
986         if( !len ) {
987             if( DBG_IOBUF )
988                 log_debug("iobuf-%d.%d: underflow: eof\n", a->no, a->subno );
989             return -1;
990         }
991         a->d.len = len;
992         a->d.start = 0;
993         return a->d.buf[a->d.start++];
994     }
995     else {
996         if( DBG_IOBUF )
997             log_debug("iobuf-%d.%d: underflow: eof (no filter)\n",
998                                                     a->no, a->subno );
999         return -1;  /* no filter; return EOF */
1000     }
1001 }
1002
1003
1004 int
1005 iobuf_flush(IOBUF a)
1006 {
1007     size_t len;
1008     int rc;
1009
1010     if( a->directfp )
1011         return 0;
1012
1013     /*log_debug("iobuf-%d.%d: flush\n", a->no, a->subno );*/
1014     if( a->use == 3 ) { /* increase the temp buffer */
1015         char *newbuf;
1016         size_t newsize = a->d.size + 8192;
1017
1018         log_debug("increasing temp iobuf from %lu to %lu\n",
1019                     (ulong)a->d.size, (ulong)newsize );
1020         newbuf = m_alloc( newsize );
1021         memcpy( newbuf, a->d.buf, a->d.len );
1022         m_free(a->d.buf);
1023         a->d.buf = newbuf;
1024         a->d.size = newsize;
1025         return 0;
1026     }
1027     else if( a->use != 2 )
1028         log_bug("flush on non-output iobuf\n");
1029     else if( !a->filter )
1030         log_bug("iobuf_flush: no filter\n");
1031     len = a->d.len;
1032     rc = a->filter( a->filter_ov, IOBUFCTRL_FLUSH, a->chain, a->d.buf, &len );
1033     if( !rc && len != a->d.len ) {
1034         log_info("iobuf_flush did not write all!\n");
1035         rc = G10ERR_WRITE_FILE;
1036     }
1037     else if( rc )
1038         a->error = 1;
1039     a->d.len = 0;
1040
1041     return rc;
1042 }
1043
1044
1045 /****************
1046  * Read a byte from the iobuf; returns -1 on EOF
1047  */
1048 int
1049 iobuf_readbyte(IOBUF a)
1050 {
1051     int c;
1052
1053     /* nlimit does not work together with unget */
1054     /* nbytes is also not valid! */
1055     if( a->unget.buf ) {
1056         if( a->unget.start < a->unget.len )
1057             return a->unget.buf[a->unget.start++];
1058         m_free(a->unget.buf);
1059         a->unget.buf = NULL;
1060         a->nofast &= ~2;
1061     }
1062
1063     if( a->nlimit && a->nbytes >= a->nlimit )
1064         return -1; /* forced EOF */
1065
1066     if( a->d.start < a->d.len ) {
1067         c = a->d.buf[a->d.start++];
1068     }
1069     else if( (c=underflow(a)) == -1 )
1070         return -1; /* EOF */
1071
1072     a->nbytes++;
1073     return c;
1074 }
1075
1076
1077 int
1078 iobuf_read(IOBUF a, byte *buf, unsigned buflen )
1079 {
1080     int c, n;
1081
1082     if( a->unget.buf || a->nlimit ) {
1083         /* handle special cases */
1084         for(n=0 ; n < buflen; n++ ) {
1085             if( (c = iobuf_readbyte(a)) == -1 ) {
1086                 if( !n )
1087                     return -1; /* eof */
1088                 break;
1089             }
1090             else
1091                 if( buf ) *buf = c;
1092             if( buf ) buf++;
1093         }
1094         return n;
1095     }
1096
1097     n = 0;
1098     do {
1099         if( n < buflen && a->d.start < a->d.len ) {
1100             unsigned size = a->d.len - a->d.start;
1101             if( size > buflen - n )
1102                 size = buflen - n;
1103             if( buf )
1104                 memcpy( buf, a->d.buf + a->d.start, size );
1105             n += size;
1106             a->d.start += size;
1107             if( buf )
1108                 buf += size;
1109         }
1110         if( n < buflen ) {
1111             if( (c=underflow(a)) == -1 ) {
1112                 a->nbytes += n;
1113                 return n? n : -1/*EOF*/;
1114             }
1115             if( buf )
1116                 *buf++ = c;
1117             n++;
1118         }
1119     } while( n < buflen );
1120     a->nbytes += n;
1121     return n;
1122 }
1123
1124
1125 /****************
1126  * Have a look at the iobuf.
1127  * NOTE: This only works in special cases.
1128  */
1129 int
1130 iobuf_peek(IOBUF a, byte *buf, unsigned buflen )
1131 {
1132     int n=0;
1133
1134     if( a->filter_eof )
1135         return -1;
1136
1137     if( !(a->d.start < a->d.len) ) {
1138         if( underflow(a) == -1 )
1139             return -1;
1140         /* and unget this character */
1141         assert(a->d.start == 1);
1142         a->d.start = 0;
1143     }
1144
1145     for(n=0 ; n < buflen && (a->d.start+n) < a->d.len ; n++, buf++ )
1146         *buf = a->d.buf[n];
1147     return n;
1148 }
1149
1150
1151
1152
1153 int
1154 iobuf_writebyte(IOBUF a, unsigned c)
1155 {
1156
1157     if( a->directfp )
1158         BUG();
1159
1160     if( a->d.len == a->d.size )
1161         if( iobuf_flush(a) )
1162             return -1;
1163
1164     assert( a->d.len < a->d.size );
1165     a->d.buf[a->d.len++] = c;
1166     return 0;
1167 }
1168
1169
1170 int
1171 iobuf_write(IOBUF a, byte *buf, unsigned buflen )
1172 {
1173
1174     if( a->directfp )
1175         BUG();
1176
1177     do {
1178         if( buflen && a->d.len < a->d.size ) {
1179             unsigned size = a->d.size - a->d.len;
1180             if( size > buflen ) size = buflen;
1181             memcpy( a->d.buf + a->d.len, buf, size );
1182             buflen -= size;
1183             buf += size;
1184             a->d.len += size;
1185         }
1186         if( buflen ) {
1187             if( iobuf_flush(a) )
1188                 return -1;
1189         }
1190     } while( buflen );
1191     return 0;
1192 }
1193
1194
1195 int
1196 iobuf_writestr(IOBUF a, const char *buf )
1197 {
1198     for( ; *buf; buf++ )
1199         if( iobuf_writebyte(a, *buf) )
1200             return -1;
1201     return 0;
1202 }
1203
1204
1205
1206 /****************
1207  * copy the contents of TEMP to A.
1208  */
1209 int
1210 iobuf_write_temp( IOBUF a, IOBUF temp )
1211 {
1212     while( temp->chain )
1213         pop_filter( temp, temp->filter, NULL );
1214     return iobuf_write(a, temp->d.buf, temp->d.len );
1215 }
1216
1217 /****************
1218  * copy the contents of the temp io stream to BUFFER.
1219  */
1220 size_t
1221 iobuf_temp_to_buffer( IOBUF a, byte *buffer, size_t buflen )
1222 {
1223     size_t n = a->d.len;
1224
1225     if( n > buflen )
1226         n = buflen;
1227     memcpy( buffer, a->d.buf, n );
1228     return n;
1229 }
1230
1231
1232 /****************
1233  * Call this function to terminate processing of the temp stream
1234  * without closing it.  This removes all filters from the stream
1235  * makes sure that iobuf_get_temp_{buffer,length}() returns correct
1236  * values.
1237  */
1238 void
1239 iobuf_flush_temp( IOBUF temp )
1240 {
1241     while( temp->chain )
1242         pop_filter( temp, temp->filter, NULL );
1243 }
1244
1245
1246 /****************
1247  * Set a limit on how many bytes may be read from the input stream A.
1248  * Setting the limit to 0 disables this feature.
1249  */
1250 void
1251 iobuf_set_limit( IOBUF a, unsigned long nlimit )
1252 {
1253     if( nlimit )
1254         a->nofast |= 1;
1255     else
1256         a->nofast &= ~1;
1257     a->nlimit = nlimit;
1258     a->ntotal += a->nbytes;
1259     a->nbytes = 0;
1260 }
1261
1262
1263
1264 /****************
1265  * Return the length of an open file
1266  */
1267 u32
1268 iobuf_get_filelength( IOBUF a )
1269 {
1270     struct stat st;
1271
1272     if( a->directfp )  {
1273         FILE *fp = a->directfp;
1274
1275         if( !fstat(fileno(fp), &st) )
1276             return st.st_size;
1277         log_error("fstat() failed: %s\n", strerror(errno) );
1278         return 0;
1279     }
1280
1281     /* Hmmm: file_filter may have already been removed */
1282     for( ; a; a = a->chain )
1283         if( !a->chain && a->filter == file_filter ) {
1284             file_filter_ctx_t *b = a->filter_ov;
1285             FILE *fp = b->fp;
1286
1287             if( !fstat(fileno(fp), &st) )
1288                 return st.st_size;
1289             log_error("fstat() failed: %s\n", strerror(errno) );
1290             break;
1291         }
1292
1293     return 0;
1294 }
1295
1296 /****************
1297  * Tell the file position, where the next read will take place
1298  */
1299 ulong
1300 iobuf_tell( IOBUF a )
1301 {
1302     return a->ntotal + a->nbytes;
1303 }
1304
1305
1306
1307 /****************
1308  * This is a very limited implementation. It simply discards all internal
1309  * buffering and removes all filters but the first one.
1310  */
1311 int
1312 iobuf_seek( IOBUF a, ulong newpos )
1313 {
1314     file_filter_ctx_t *b = NULL;
1315
1316     if( a->directfp ) {
1317         FILE *fp = a->directfp;
1318         if( fseek( fp, newpos, SEEK_SET ) ) {
1319             log_error("can't seek to %lu: %s\n", newpos, strerror(errno) );
1320             return -1;
1321         }
1322         clearerr(fp);
1323     }
1324     else {
1325         for( ; a; a = a->chain ) {
1326             if( !a->chain && a->filter == file_filter ) {
1327                 b = a->filter_ov;
1328                 break;
1329             }
1330         }
1331         if( !a )
1332             return -1;
1333         if( fseek( b->fp, newpos, SEEK_SET ) ) {
1334             log_error("can't seek to %lu: %s\n", newpos, strerror(errno) );
1335             return -1;
1336         }
1337     }
1338     a->d.len = 0;   /* discard buffer */
1339     a->d.start = 0;
1340     a->nbytes = 0;
1341     a->nlimit = 0;
1342     a->nofast &= ~1;
1343     a->ntotal = newpos;
1344     a->error = 0;
1345     /* remove filters, but the last */
1346     if( a->chain )
1347         log_debug("pop_filter called in iobuf_seek - please report\n");
1348     while( a->chain )
1349        pop_filter( a, a->filter, NULL );
1350
1351     return 0;
1352 }
1353
1354
1355
1356
1357
1358
1359 /****************
1360  * Retrieve the real filename
1361  */
1362 const char *
1363 iobuf_get_real_fname( IOBUF a )
1364 {
1365     if( a->real_fname )
1366         return a->real_fname;
1367
1368     /* the old solution */
1369     for( ; a; a = a->chain )
1370         if( !a->chain && a->filter == file_filter ) {
1371             file_filter_ctx_t *b = a->filter_ov;
1372             return b->print_only_name? NULL : b->fname;
1373         }
1374
1375     return NULL;
1376 }
1377
1378
1379 /****************
1380  * Retrieve the filename
1381  */
1382 const char *
1383 iobuf_get_fname( IOBUF a )
1384 {
1385     for( ; a; a = a->chain )
1386         if( !a->chain && a->filter == file_filter ) {
1387             file_filter_ctx_t *b = a->filter_ov;
1388             return b->fname;
1389         }
1390
1391     return NULL;
1392 }
1393
1394 /****************
1395  * Start the block write mode, see rfc1991.new for details.
1396  * A value of 0 for N stops this mode (flushes and writes
1397  * the end marker)
1398  */
1399 void
1400 iobuf_set_block_mode( IOBUF a, size_t n )
1401 {
1402     block_filter_ctx_t *ctx = m_alloc_clear( sizeof *ctx );
1403
1404     assert( a->use == 1 || a->use == 2 );
1405     ctx->use = a->use;
1406     if( !n ) {
1407         if( a->use == 1 )
1408             log_debug("pop_filter called in set_block_mode - please report\n");
1409         pop_filter(a, block_filter, NULL );
1410     }
1411     else {
1412         ctx->size = n; /* only needed for use 2 */
1413         iobuf_push_filter(a, block_filter, ctx );
1414     }
1415 }
1416
1417 /****************
1418  * enable partial block mode as described in the OpenPGP draft.
1419  * LEN is the first length byte on read, but ignored on writes.
1420  */
1421 void
1422 iobuf_set_partial_block_mode( IOBUF a, size_t len )
1423 {
1424     block_filter_ctx_t *ctx = m_alloc_clear( sizeof *ctx );
1425
1426     assert( a->use == 1 || a->use == 2 );
1427     ctx->use = a->use;
1428     if( !len ) {
1429         if( a->use == 1 )
1430             log_debug("pop_filter called in set_partial_block_mode"
1431                                                     " - please report\n");
1432         pop_filter(a, block_filter, NULL );
1433     }
1434     else {
1435         ctx->partial = 1;
1436         ctx->size = 0;
1437         ctx->first_c = len;
1438         iobuf_push_filter(a, block_filter, ctx );
1439     }
1440 }
1441
1442
1443 /****************
1444  * Checks whether the stream is in block mode
1445  * Note: This does not work if other filters are pushed on the stream.
1446  */
1447 int
1448 iobuf_in_block_mode( IOBUF a )
1449 {
1450     if( a && a->filter == block_filter )
1451         return 1; /* yes */
1452     return 0; /* no */
1453 }
1454
1455
1456 /****************
1457  * Same as fgets() but if the buffer is too short a larger one will
1458  * be allocated up to some limit *max_length.
1459  * A line is considered a byte stream ending in a LF.
1460  * Returns the length of the line. EOF is indicated by a line of
1461  * length zero. The last LF may be missing due to an EOF.
1462  * is max_length is zero on return, the line has been truncated.
1463  *
1464  * Note: The buffer is allocated with enough space to append a CR,LF,EOL
1465  */
1466 unsigned
1467 iobuf_read_line( IOBUF a, byte **addr_of_buffer,
1468                           unsigned *length_of_buffer, unsigned *max_length )
1469 {
1470     int c;
1471     char *buffer = *addr_of_buffer;
1472     unsigned length = *length_of_buffer;
1473     unsigned nbytes = 0;
1474     unsigned maxlen = *max_length;
1475     char *p;
1476
1477     if( !buffer ) { /* must allocate a new buffer */
1478         length = 256;
1479         buffer = m_alloc( length );
1480         *addr_of_buffer = buffer;
1481         *length_of_buffer = length;
1482     }
1483
1484     length -= 3; /* reserve 3 bytes (cr,lf,eol) */
1485     p = buffer;
1486     while( (c=iobuf_get(a)) != -1 ) {
1487         if( nbytes == length ) { /* increase the buffer */
1488             if( length > maxlen  ) { /* this is out limit */
1489                 /* skip the rest of the line */
1490                 while( c != '\n' && (c=iobuf_get(a)) != -1 )
1491                     ;
1492                 *p++ = '\n'; /* always append a LF (we have reserved space) */
1493                 nbytes++;
1494                 *max_length = 0; /* indicate truncation */
1495                 break;
1496             }
1497             length += 3; /* correct for the reserved byte */
1498             length += length < 1024? 256 : 1024;
1499             buffer = m_realloc( buffer, length );
1500             *addr_of_buffer = buffer;
1501             *length_of_buffer = length;
1502             length -= 3; /* and reserve again */
1503             p = buffer + nbytes;
1504         }
1505         *p++ = c;
1506         nbytes++;
1507         if( c == '\n' )
1508             break;
1509     }
1510     *p = 0; /* make sure the line is a string */
1511
1512     return nbytes;
1513 }
1514