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