Support DSA2.
[gnupg.git] / tools / gpgsplit.c
1 /* gpgsplit.c - An OpenPGP packet splitting tool
2  * Copyright (C) 2001, 2002, 2003 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 3 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, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <errno.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include <unistd.h>
27 #include <assert.h>
28 #include <sys/types.h>
29 #ifdef HAVE_DOSISH_SYSTEM
30 # include <fcntl.h> /* for setmode() */
31 #endif
32 #include <zlib.h>
33 #ifdef HAVE_BZIP2
34 #include <bzlib.h>
35 #endif /* HAVE_BZIP2 */
36 #if defined(__riscos__) && defined(USE_ZLIBRISCOS)
37 # include "zlib-riscos.h"
38 #endif
39
40 #define INCLUDED_BY_MAIN_MODULE 1
41 #include "util.h"
42 #include "openpgpdefs.h"
43
44 static int opt_verbose;
45 static const char *opt_prefix = "";
46 static int opt_uncompress;
47 static int opt_secret_to_public;
48 static int opt_no_split;
49
50 static void g10_exit( int rc );
51 static void split_packets (const char *fname);
52
53
54 enum cmd_and_opt_values {
55   aNull = 0,
56   oVerbose        = 'v',
57   oPrefix       = 'p',                          
58   oUncompress   = 500,                      
59   oSecretToPublic,                      
60   oNoSplit,
61
62   aTest
63 };
64
65
66 static ARGPARSE_OPTS opts[] = {
67
68     { 301, NULL, 0, "@Options:\n " },
69
70     { oVerbose, "verbose",   0, "verbose" },
71     { oPrefix,  "prefix",    2, "|STRING|Prepend filenames with STRING" },
72     { oUncompress, "uncompress", 0, "uncompress a packet"},
73     { oSecretToPublic, "secret-to-public", 0, "convert secret keys to public keys"},
74     { oNoSplit, "no-split", 0, "write to stdout and don't actually split"},
75 {0} };
76
77
78 static const char *
79 my_strusage (int level)
80 {
81   const char *p;
82   switch (level)
83     {
84     case 11: p = "gpgsplit (GnuPG)";
85       break;
86     case 13: p = VERSION; break;
87     case 17: p = PRINTABLE_OS_NAME; break;
88     case 19: p =
89                "Please report bugs to <bug-gnupg@gnu.org>.\n";
90     break;
91     case 1:
92     case 40:    p =
93                   "Usage: gpgsplit [options] [files] (-h for help)";
94     break;
95     case 41:    p =
96                   "Syntax: gpgsplit [options] [files]\n"
97                   "Split an OpenPGP message into packets\n";
98     break;
99     
100     default:    p = NULL;
101     }
102   return p;
103 }
104
105
106
107 int
108 main (int argc, char **argv)
109 {
110   ARGPARSE_ARGS pargs;
111
112 #ifdef HAVE_DOSISH_SYSTEM
113   setmode( fileno(stdin), O_BINARY );
114   setmode( fileno(stdout), O_BINARY );
115 #endif
116   log_set_prefix ("gpgsplit", JNLIB_LOG_WITH_PREFIX);
117   set_strusage (my_strusage);
118   
119   pargs.argc = &argc;
120   pargs.argv = &argv;
121   pargs.flags=  1;  /* do not remove the args */
122   while (optfile_parse( NULL, NULL, NULL, &pargs, opts))
123     {
124       switch (pargs.r_opt)
125         {
126         case oVerbose: opt_verbose = 1; break;
127         case oPrefix: opt_prefix = pargs.r.ret_str; break;
128         case oUncompress: opt_uncompress = 1; break;
129         case oSecretToPublic: opt_secret_to_public = 1; break;
130         case oNoSplit: opt_no_split = 1; break;
131         default : pargs.err = 2; break;
132         }
133     }
134   
135   if (log_get_errorcount(0))
136     g10_exit (2);
137
138   if (!argc)
139     split_packets (NULL);
140   else
141     {
142       for ( ;argc; argc--, argv++) 
143         split_packets (*argv);
144     }
145   
146   g10_exit (0);
147   return 0; 
148 }
149
150
151 static void
152 g10_exit (int rc)
153 {
154   rc = rc? rc : log_get_errorcount(0)? 2 : 0;
155   exit(rc );
156 }
157
158 static const char *
159 pkttype_to_string (int pkttype)
160 {
161   const char *s;
162
163   switch (pkttype)
164     {
165     case PKT_PUBKEY_ENC    : s = "pk_enc"; break;
166     case PKT_SIGNATURE     : s = "sig"; break;
167     case PKT_SYMKEY_ENC    : s = "sym_enc"; break;
168     case PKT_ONEPASS_SIG   : s = "onepass_sig"; break;
169     case PKT_SECRET_KEY    : s = "secret_key"; break;
170     case PKT_PUBLIC_KEY    : s = "public_key"; break;
171     case PKT_SECRET_SUBKEY : s = "secret_subkey"; break;
172     case PKT_COMPRESSED    : 
173       s = opt_uncompress? "uncompressed":"compressed";
174       break;
175     case PKT_ENCRYPTED     : s = "encrypted"; break;
176     case PKT_MARKER            : s = "marker"; break;
177     case PKT_PLAINTEXT     : s = "plaintext"; break;
178     case PKT_RING_TRUST    : s = "ring_trust"; break;
179     case PKT_USER_ID       : s = "user_id"; break;
180     case PKT_PUBLIC_SUBKEY : s = "public_subkey"; break;
181     case PKT_OLD_COMMENT   : s = "old_comment"; break;
182     case PKT_ATTRIBUTE     : s = "attribute"; break;
183     case PKT_ENCRYPTED_MDC : s = "encrypted_mdc"; break;
184     case PKT_MDC               : s = "mdc"; break;
185     case PKT_COMMENT       : s = "comment"; break;
186     case PKT_GPG_CONTROL   : s = "gpg_control"; break;
187     default: s = "unknown"; break;
188     }
189   return s;
190 }
191
192
193 /*
194  * Create a new filename and a return a pointer to a statically
195  * allocated buffer 
196  */
197 static char *
198 create_filename (int pkttype)
199 {
200   static unsigned int partno = 0;
201   static char *name;
202   
203   if (!name) 
204     name = xmalloc (strlen (opt_prefix) + 100 );
205   
206   assert (pkttype < 1000 && pkttype >= 0 );
207   partno++;
208   sprintf (name, "%s%06u-%03d" EXTSEP_S "%.40s",
209            opt_prefix, partno, pkttype, pkttype_to_string (pkttype));
210   return name;
211 }
212
213 static int
214 read_u16 (FILE *fp, size_t *rn)
215 {
216   int c;
217
218   if ( (c = getc (fp)) == EOF )
219     return -1;
220   *rn = c << 8;
221   if ( (c = getc (fp)) == EOF )
222     return -1;
223   *rn |= c;
224   return 0;
225 }
226
227 static int
228 read_u32 (FILE *fp, unsigned long *rn)
229 {
230   size_t tmp;
231   
232   if (read_u16 (fp, &tmp))
233     return -1;
234   *rn = tmp << 16;
235   if (read_u16 (fp, &tmp))
236     return -1;
237   *rn |= tmp;
238   return 0;
239 }
240
241 static int
242 write_old_header (FILE *fp, int pkttype, unsigned int len)
243 {     
244   int ctb = (0x80 | ((pkttype & 15)<<2));
245   
246   if (len < 256)
247     ;
248   else if (len < 65536)
249     ctb |= 1;
250   else
251     ctb |= 2;
252
253   if ( putc ( ctb, fp) == EOF )
254     return -1;
255
256   if ( (ctb & 2) )
257     {
258       if (putc ((len>>24), fp) == EOF)
259         return -1;
260       if (putc ((len>>16), fp) == EOF)
261         return -1;
262     }
263   if ( (ctb & 3) )
264     {
265       if (putc ((len>>8), fp) == EOF)
266         return -1;
267     }
268   if (putc ((len&0xff), fp) == EOF)
269     return -1;
270   return 0;
271 }
272
273 static int
274 write_new_header (FILE *fp, int pkttype, unsigned int len)
275 {     
276   if ( putc ((0xc0 | (pkttype & 0x3f)), fp) == EOF )
277     return -1;
278
279   if (len < 192)
280     {
281       if (putc (len, fp) == EOF)
282         return -1;
283     }
284   else if (len < 8384)
285     {
286       len -= 192;
287       if (putc ((len/256)+192, fp) == EOF)
288         return -1;
289       if (putc ((len%256), fp) == EOF)
290         return -1;
291     }
292   else
293     {
294       if (putc ( 0xff, fp) == EOF)
295         return -1;
296       if (putc ( (len >> 24), fp) == EOF)
297         return -1;
298       if (putc ( (len >> 16), fp) == EOF)
299         return -1;
300       if (putc ( (len >> 8), fp) == EOF)
301         return -1;
302       if (putc ( (len & 0xff), fp) == EOF)
303         return -1;
304     }
305   return 0;
306 }
307
308 /* Return the length of the public key given BUF of BUFLEN with a
309    secret key. */
310 static int
311 public_key_length (const unsigned char *buf, size_t buflen)
312 {
313   const unsigned char *s;
314   int nmpis;
315
316   /*   byte version number (3 or 4)
317        u32  creation time 
318        [u16  valid days (version 3 only)]
319        byte algorithm 
320        n    MPIs (n and e) */
321   if (!buflen)
322     return 0;
323   if (buf[0] < 2 || buf[0] > 4)
324     return 0; /* wrong version number */
325   if (buflen < (buf[0] == 4? 6:8))
326     return 0;
327   s = buf + (buf[0] == 4? 6:8);
328   buflen -= (buf[0] == 4? 6:8);
329   switch (s[-1])
330     {
331     case 1:
332     case 2:
333     case 3:
334       nmpis = 2;
335       break;
336     case 16:
337     case 20:
338       nmpis = 3;
339       break;
340     case 17:
341       nmpis = 4;
342       break;
343     default:
344       return 0;
345     }
346
347   for (; nmpis; nmpis--)
348     {
349       unsigned int nbits, nbytes;
350
351       if (buflen < 2)
352         return 0;
353       nbits = (s[0] << 8) | s[1];
354       s += 2; buflen -= 2;
355       nbytes = (nbits+7) / 8;
356       if (buflen < nbytes)
357         return 0;
358       s += nbytes; buflen -= nbytes;
359     }
360
361   return s - buf;
362 }
363
364 static int
365 handle_zlib(int algo,FILE *fpin,FILE *fpout)
366 {
367   z_stream zs;
368   byte *inbuf, *outbuf;
369   unsigned int inbufsize, outbufsize;
370   int c,zinit_done, zrc, nread, count;
371   size_t n;
372               
373   memset (&zs, 0, sizeof zs);
374   inbufsize = 2048;
375   inbuf = xmalloc (inbufsize);
376   outbufsize = 8192;
377   outbuf = xmalloc (outbufsize);
378   zs.avail_in = 0;
379   zinit_done = 0;
380               
381   do
382     {
383       if (zs.avail_in < inbufsize)
384         {
385           n = zs.avail_in;
386           if (!n)
387             zs.next_in = (Bytef *) inbuf;
388           count = inbufsize - n;
389           for (nread=0;
390                nread < count && (c=getc (fpin)) != EOF;
391                nread++) 
392             inbuf[n+nread] = c;
393                       
394           n += nread;
395           if (nread < count && algo == 1) 
396             {
397               inbuf[n] = 0xFF; /* chew dummy byte */
398               n++;
399             }
400           zs.avail_in = n;
401         }
402       zs.next_out = (Bytef *) outbuf;
403       zs.avail_out = outbufsize;
404                     
405       if (!zinit_done) 
406         {
407           zrc = (algo == 1? inflateInit2 ( &zs, -13)
408                  : inflateInit ( &zs ));
409           if (zrc != Z_OK) 
410             {
411               log_fatal ("zlib problem: %s\n", zs.msg? zs.msg :
412                          zrc == Z_MEM_ERROR ? "out of core" :
413                          zrc == Z_VERSION_ERROR ?
414                          "invalid lib version" :
415                          "unknown error" );
416             }
417           zinit_done = 1;
418         }
419       else
420         {
421 #ifdef Z_SYNC_FLUSH
422           zrc = inflate (&zs, Z_SYNC_FLUSH);
423 #else
424           zrc = inflate (&zs, Z_PARTIAL_FLUSH);
425 #endif
426           if (zrc == Z_STREAM_END)
427             ; /* eof */
428           else if (zrc != Z_OK && zrc != Z_BUF_ERROR)
429             {
430               if (zs.msg)
431                 log_fatal ("zlib inflate problem: %s\n", zs.msg );
432               else
433                 log_fatal ("zlib inflate problem: rc=%d\n", zrc );
434             }
435           for (n=0; n < outbufsize - zs.avail_out; n++) 
436             {
437               if (putc (outbuf[n], fpout) == EOF )
438                 return 1;
439             }
440         }
441     } 
442   while (zrc != Z_STREAM_END && zrc != Z_BUF_ERROR);
443   {
444     int i;
445     
446     fputs ("Left over bytes:", stderr);
447     for (i=0; i < zs.avail_in; i++)
448       fprintf (stderr, " %02X", zs.next_in[i]);
449     putc ('\n', stderr);
450
451   }
452   inflateEnd (&zs);
453
454   return 0;
455 }
456
457 #ifdef HAVE_BZIP2
458 static int
459 handle_bzip2(int algo,FILE *fpin,FILE *fpout)
460 {
461   bz_stream bzs;
462   byte *inbuf, *outbuf;
463   unsigned int inbufsize, outbufsize;
464   int c,zinit_done, zrc, nread, count;
465   size_t n;
466               
467   memset (&bzs, 0, sizeof bzs);
468   inbufsize = 2048;
469   inbuf = xmalloc (inbufsize);
470   outbufsize = 8192;
471   outbuf = xmalloc (outbufsize);
472   bzs.avail_in = 0;
473   zinit_done = 0;
474               
475   do
476     {
477       if (bzs.avail_in < inbufsize)
478         {
479           n = bzs.avail_in;
480           if (!n)
481             bzs.next_in = inbuf;
482           count = inbufsize - n;
483           for (nread=0;
484                nread < count && (c=getc (fpin)) != EOF;
485                nread++) 
486             inbuf[n+nread] = c;
487                       
488           n += nread;
489           if (nread < count && algo == 1) 
490             {
491               inbuf[n] = 0xFF; /* chew dummy byte */
492               n++;
493             }
494           bzs.avail_in = n;
495         }
496       bzs.next_out = outbuf;
497       bzs.avail_out = outbufsize;
498                     
499       if (!zinit_done) 
500         {
501           zrc = BZ2_bzDecompressInit(&bzs,0,0);
502           if (zrc != BZ_OK) 
503             log_fatal ("bz2lib problem: %d\n",zrc);
504           zinit_done = 1;
505         }
506       else
507         {
508           zrc = BZ2_bzDecompress(&bzs);
509           if (zrc == BZ_STREAM_END)
510             ; /* eof */
511           else if (zrc != BZ_OK && zrc != BZ_PARAM_ERROR)
512             log_fatal ("bz2lib inflate problem: %d\n", zrc );
513           for (n=0; n < outbufsize - bzs.avail_out; n++) 
514             {
515               if (putc (outbuf[n], fpout) == EOF )
516                 return 1;
517             }
518         }
519     } 
520   while (zrc != BZ_STREAM_END && zrc != BZ_PARAM_ERROR);
521   BZ2_bzDecompressEnd(&bzs);
522
523   return 0;
524 }
525 #endif /* HAVE_BZIP2 */
526
527 /* hdr must point to a buffer large enough to hold all header bytes */
528 static int
529 write_part ( const char *fname, FILE *fpin, unsigned long pktlen,
530              int pkttype, int partial, unsigned char *hdr, size_t hdrlen)
531 {
532   FILE *fpout;
533   int c, first;
534   unsigned char *p;
535   const char *outname = create_filename (pkttype);
536   
537 #if defined(__riscos__) && defined(USE_ZLIBRISCOS)
538   static int initialized = 0;
539
540   if (!initialized)
541       initialized = riscos_load_module("ZLib", zlib_path, 1);
542 #endif
543   if (opt_no_split)
544     fpout = stdout;
545   else
546     {
547       if (opt_verbose)
548         log_info ("writing `%s'\n", outname);
549       fpout = fopen (outname, "wb");
550       if (!fpout) 
551         {
552           log_error ("error creating `%s': %s\n", outname, strerror(errno));
553           /* stop right now, otherwise we would mess up the sequence
554              of the part numbers */
555           g10_exit (1);
556         }
557     }
558
559   if (opt_secret_to_public
560       && (pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY))
561     {
562       unsigned char *blob = xmalloc (pktlen);
563       int i, len;
564
565       pkttype = pkttype == PKT_SECRET_KEY? PKT_PUBLIC_KEY:PKT_PUBLIC_SUBKEY;
566
567       for (i=0; i < pktlen; i++) 
568         {
569           c = getc (fpin);
570           if (c == EOF) 
571             goto read_error;
572           blob[i] = c;
573         }
574       len = public_key_length (blob, pktlen);
575       if (!len)
576         {
577           log_error ("error calcualting public key length\n");
578           g10_exit (1);
579         }
580       if ( (hdr[0] & 0x40) )
581         { 
582           if (write_new_header (fpout, pkttype, len))
583             goto write_error;
584         }
585       else
586         { 
587           if (write_old_header (fpout, pkttype, len))
588             goto write_error;
589         }
590
591       for (i=0; i < len; i++) 
592         {
593           if ( putc (blob[i], fpout) == EOF )
594             goto write_error;
595         }
596
597       goto ready;
598     }
599
600
601   if (!opt_uncompress)
602     {
603       for (p=hdr; hdrlen; p++, hdrlen--)
604         {
605           if ( putc (*p, fpout) == EOF )
606             goto write_error;
607         }
608     }
609   
610   first = 1;
611   while (partial)
612     {
613       size_t partlen;
614       
615       if (partial == 1)
616         { /* openpgp */
617           if (first )
618             {
619               c = pktlen;
620               assert( c >= 224 && c < 255 );
621               first = 0;
622             }
623           else if ((c = getc (fpin)) == EOF ) 
624             goto read_error;
625           else
626             hdr[hdrlen++] = c;
627             
628           if (c < 192)
629             {
630               pktlen = c;
631               partial = 0; /* (last segment may follow) */
632             }
633           else if (c < 224 )
634             {
635               pktlen = (c - 192) * 256;
636               if ((c = getc (fpin)) == EOF) 
637                 goto read_error;
638               hdr[hdrlen++] = c;
639               pktlen += c + 192;
640               partial = 0;
641             }
642           else if (c == 255)
643             {
644               if (read_u32 (fpin, &pktlen))
645                 goto read_error;
646               hdr[hdrlen++] = pktlen >> 24;
647               hdr[hdrlen++] = pktlen >> 16;
648               hdr[hdrlen++] = pktlen >> 8;
649               hdr[hdrlen++] = pktlen;
650               partial = 0;
651             }
652           else
653             { /* next partial body length */
654               for (p=hdr; hdrlen; p++, hdrlen--)
655                 {
656                   if ( putc (*p, fpout) == EOF )
657                     goto write_error;
658                 }
659               partlen = 1 << (c & 0x1f);
660               for (; partlen; partlen--) 
661                 {
662                   if ((c = getc (fpin)) == EOF) 
663                     goto read_error;
664                   if ( putc (c, fpout) == EOF )
665                     goto write_error;
666                 }
667             }
668         }
669       else if (partial == 2)
670         { /* old gnupg */
671           assert (!pktlen);
672           if ( read_u16 (fpin, &partlen) )
673             goto read_error;
674           hdr[hdrlen++] = partlen >> 8;
675           hdr[hdrlen++] = partlen;
676           for (p=hdr; hdrlen; p++, hdrlen--) 
677             {
678               if ( putc (*p, fpout) == EOF )
679                 goto write_error;
680             }
681           if (!partlen)
682             partial = 0; /* end of packet */
683           for (; partlen; partlen--) 
684             {
685               c = getc (fpin);
686               if (c == EOF) 
687                 goto read_error;
688               if ( putc (c, fpout) == EOF )
689                 goto write_error;
690             }
691         }
692       else
693         { /* compressed: read to end */
694           pktlen = 0;
695           partial = 0;
696           hdrlen = 0;
697           if (opt_uncompress) 
698             {
699               if ((c = getc (fpin)) == EOF)
700                 goto read_error;
701
702               if(c==1 || c==2)
703                 {
704                   if(handle_zlib(c,fpin,fpout))
705                     goto write_error;
706                 }
707 #ifdef HAVE_BZIP2
708               else if(c==3)
709                 {
710                   if(handle_bzip2(c,fpin,fpout))
711                     goto write_error;
712                 }
713 #endif /* HAVE_BZIP2 */
714               else
715                 {
716                   log_error("invalid compression algorithm (%d)\n",c);
717                   goto read_error;
718                 }
719             }
720           else
721             {
722               while ( (c=getc (fpin)) != EOF ) 
723                 {
724                   if ( putc (c, fpout) == EOF )
725                     goto write_error;
726                 }
727             }
728           if (!feof (fpin))
729             goto read_error;
730         }
731     }
732
733   for (p=hdr; hdrlen; p++, hdrlen--) 
734     {
735       if ( putc (*p, fpout) == EOF )
736         goto write_error;
737     }
738   
739   /* standard packet or last segment of partial length encoded packet */
740   for (; pktlen; pktlen--) 
741     {
742       c = getc (fpin);
743       if (c == EOF) 
744         goto read_error;
745       if ( putc (c, fpout) == EOF )
746         goto write_error;
747     }
748   
749  ready:
750   if ( !opt_no_split && fclose (fpout) )
751     log_error ("error closing `%s': %s\n", outname, strerror (errno));
752   return 0;
753   
754  write_error:    
755   log_error ("error writing `%s': %s\n", outname, strerror (errno));
756   if (!opt_no_split)
757     fclose (fpout);
758   return 2;
759   
760  read_error:
761   if (!opt_no_split)
762     {
763       int save = errno;
764       fclose (fpout);
765       errno = save;
766     }
767   return -1;
768 }
769
770
771
772 static int
773 do_split (const char *fname, FILE *fp)
774 {
775   int c, ctb, pkttype;
776   unsigned long pktlen = 0;
777   int partial = 0;
778   unsigned char header[20];
779   int header_idx = 0;
780   
781   ctb = getc (fp);
782   if (ctb == EOF)
783     return 3; /* ready */
784   header[header_idx++] = ctb;
785   
786   if (!(ctb & 0x80))
787     {
788       log_error("invalid CTB %02x\n", ctb );
789       return 1;
790     }
791   if ( (ctb & 0x40) )
792     { /* new CTB */
793       pkttype =  (ctb & 0x3f);
794       if( (c = getc (fp)) == EOF )
795         return -1;
796       header[header_idx++] = c;
797
798       if ( c < 192 )
799         pktlen = c;
800       else if ( c < 224 )
801         {
802           pktlen = (c - 192) * 256;
803           if( (c = getc (fp)) == EOF ) 
804             return -1;
805           header[header_idx++] = c;
806           pktlen += c + 192;
807         }
808       else if ( c == 255 ) 
809         {
810           if (read_u32 (fp, &pktlen))
811             return -1;
812           header[header_idx++] = pktlen >> 24;
813           header[header_idx++] = pktlen >> 16;
814           header[header_idx++] = pktlen >> 8;
815           header[header_idx++] = pktlen; 
816         }
817       else
818         { /* partial body length */
819           pktlen = c;
820           partial = 1;
821         }
822     }
823   else
824     {
825       int lenbytes;
826       
827       pkttype = (ctb>>2)&0xf;
828       lenbytes = ((ctb&3)==3)? 0 : (1<<(ctb & 3));
829       if (!lenbytes )
830         {
831           pktlen = 0; /* don't know the value */
832           if( pkttype == PKT_COMPRESSED )
833             partial = 3;
834           else
835             partial = 2; /* the old GnuPG partial length encoding */
836         }
837       else
838         {
839           for ( ; lenbytes; lenbytes-- ) 
840             {
841               pktlen <<= 8;
842               if( (c = getc (fp)) == EOF ) 
843                 return -1;
844               header[header_idx++] = c;
845               
846               pktlen |= c;
847             }
848         }
849     }
850
851   return write_part (fname, fp, pktlen, pkttype, partial,
852                      header, header_idx);
853 }
854
855
856 static void
857 split_packets (const char *fname)
858 {
859   FILE *fp;
860   int rc;
861   
862   if (!fname || !strcmp (fname, "-"))
863     {
864       fp = stdin;
865       fname = "-";
866     }
867   else if ( !(fp = fopen (fname,"rb")) ) 
868     {
869       log_error ("can't open `%s': %s\n", fname, strerror (errno));
870       return;
871     }
872   
873   while ( !(rc = do_split (fname, fp)) )
874     ;
875   if ( rc > 0 )
876     ; /* error already handled */
877   else if ( ferror (fp) )
878     log_error ("error reading `%s': %s\n", fname, strerror (errno));
879   else
880     log_error ("premature EOF while reading `%s'\n", fname );
881   
882   if ( fp != stdin )
883     fclose (fp);
884 }