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