usage()1 /* crypto/des/des.c */
2 /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au)
3 * All rights reserved.
4 *
5 * This package is an SSL implementation written
6 * by Eric Young (eay@mincom.oz.au).
7 * The implementation was written so as to conform with Netscapes SSL.
8 *
9 * This library is free for commercial and non-commercial use as long as
10 * the following conditions are aheared to. The following conditions
11 * apply to all code found in this distribution, be it the RC4, RSA,
12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
13 * included with this distribution is covered by the same copyright terms
14 * except that the holder is Tim Hudson (tjh@mincom.oz.au).
15 *
16 * Copyright remains Eric Young's, and as such any Copyright notices in
17 * the code are not to be removed.
18 * If this package is used in a product, Eric Young should be given attribution
19 * as the author of the parts of the library used.
20 * This can be in the form of a textual message at program startup or
21 * in documentation (online or textual) provided with the package.
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 * 1. Redistributions of source code must retain the copyright
27 * notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 * notice, this list of conditions and the following disclaimer in the
30 * documentation and/or other materials provided with the distribution.
31 * 3. All advertising materials mentioning features or use of this software
32 * must display the following acknowledgement:
33 * "This product includes cryptographic software written by
34 * Eric Young (eay@mincom.oz.au)"
35 * The word 'cryptographic' can be left out if the rouines from the library
36 * being used are not cryptographic related :-).
37 * 4. If you include any Windows specific code (or a derivative thereof) from
38 * the apps directory (application code) you must include an acknowledgement:
39 * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)"
40 *
41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * SUCH DAMAGE.
52 *
53 * The licence and distribution terms for any publically available version or
54 * derivative of this code cannot be changed. i.e. this code cannot simply be
55 * copied and put under another distribution licence
56 * [including the GNU Public Licence.]
57 */
58
59 #ifdef HAVE_CONFIG_H
60 #include <config.h>
61 #endif
62
63 #include <stdio.h>
64 #include <stdlib.h>
65 #include <string.h>
66 #ifdef HAVE_UNISTD_H
67 #include <unistd.h>
68 #endif
69 #ifdef HAVE_IO_H
70 #include <io.h>
71 #endif
72
73 #include <time.h>
74 #include "des_ver.h"
75
76 #ifdef VMS
77 #include <types.h>
78 #include <stat.h>
79 #endif
80 #ifdef HAVE_SYS_TYPES_H
81 #include <sys/types.h>
82 #endif
83 #ifdef HAVE_SYS_STAT_H
84 #include <sys/stat.h>
85 #endif
86 #include "des.h"
87
88 #ifndef HAVE_RANDOM
89 #define random rand
90 #define srandom(s) srand(s)
91 #endif
92
93 #ifndef NOPROTO
94 void usage(void);
95 void doencryption(void);
96 int uufwrite(unsigned char *data, int size, unsigned int num, FILE *fp);
97 void uufwriteEnd(FILE *fp);
98 int uufread(unsigned char *out,int size,unsigned int num,FILE *fp);
99 int uuencode(unsigned char *in,int num,unsigned char *out);
100 int uudecode(unsigned char *in,int num,unsigned char *out);
101 #else
102 void usage();
103 void doencryption();
104 int uufwrite();
105 void uufwriteEnd();
106 int uufread();
107 int uuencode();
108 int uudecode();
109 #endif
110
111 #ifdef VMS
112 #define EXIT(a) exit(a&0x10000000)
113 #else
114 #define EXIT(a) exit(a)
115 #endif
116
117 #define BUFSIZE (8*1024)
118 #define VERIFY 1
119 #define KEYSIZ 8
120 #define KEYSIZB 1024 /* should hit tty line limit first :-) */
121 char key[KEYSIZB+1];
122 int do_encrypt,longk=0;
123 FILE *DES_IN,*DES_OUT,*CKSUM_OUT;
124 char uuname[200];
125 unsigned char uubuf[50];
126 int uubufnum=0;
127 #define INUUBUFN (45*100)
128 #define OUTUUBUF (65*100)
129 unsigned char b[OUTUUBUF];
130 unsigned char bb[300];
131 des_cblock cksum={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
132 char cksumname[200]="";
133
134 int vflag,cflag,eflag,dflag,kflag,bflag,fflag,sflag,uflag,flag3,hflag,error;
135
136 int main(argc, argv)
137 int argc;
138 char **argv;
139 {
140 int i;
141 struct stat ins,outs;
142 char *p;
143 char *in=NULL,*out=NULL;
144
145 vflag=cflag=eflag=dflag=kflag=hflag=bflag=fflag=sflag=uflag=flag3=0;
146 error=0;
147 memset(key,0,sizeof(key));
148
149 for (i=1; i<argc; i++)
150 {
151 p=argv[i];
152 if ((p[0] == '-') && (p[1] != '\0'))
153 {
154 p++;
155 while (*p)
156 {
157 switch (*(p++))
158 {
159 case '3':
160 flag3=1;
161 longk=1;
162 break;
163 case 'c':
164 cflag=1;
165 strncpy(cksumname,p,200);
166 p+=strlen(cksumname);
167 break;
168 case 'C':
169 cflag=1;
170 longk=1;
171 strncpy(cksumname,p,200);
172 p+=strlen(cksumname);
173 break;
174 case 'e':
175 eflag=1;
176 break;
177 case 'v':
178 vflag=1;
179 break;
180 case 'E':
181 eflag=1;
182 longk=1;
183 break;
184 case 'd':
185 dflag=1;
186 break;
187 case 'D':
188 dflag=1;
189 longk=1;
190 break;
191 case 'b':
192 bflag=1;
193 break;
194 case 'f':
195 fflag=1;
196 break;
197 case 's':
198 sflag=1;
199 break;
200 case 'u':
201 uflag=1;
202 strncpy(uuname,p,200);
203 p+=strlen(uuname);
204 break;
205 case 'h':
206 hflag=1;
207 break;
208 case 'k':
209 kflag=1;
210 if ((i+1) == argc)
211 {
212 fputs("must have a key with the -k option\n",stderr);
213 error=1;
214 }
215 else
216 {
217 int j;
218
219 i++;
220 strncpy(key,argv[i],KEYSIZB);
221 for (j=strlen(argv[i])-1; j>=0; j--)
222 argv[i][j]='\0';
223 }
224 break;
225 default:
226 fprintf(stderr,"'%c' unknown flag\n",p[-1]);
227 error=1;
228 break;
229 }
230 }
231 }
232 else
233 {
234 if (in == NULL)
235 in=argv[i];
236 else if (out == NULL)
237 out=argv[i];
238 else
239 error=1;
240 }
241 }
242 if (error) usage();
243 /* We either
244 * do checksum or
245 * do encrypt or
246 * do decrypt or
247 * do decrypt then ckecksum or
248 * do checksum then encrypt
249 */
250 if (((eflag+dflag) == 1) || cflag)
251 {
252 if (eflag) do_encrypt=DES_ENCRYPT;
253 if (dflag) do_encrypt=DES_DECRYPT;
254 }
255 else
256 {
257 if (vflag)
258 {
259 #ifndef _Windows
260 fprintf(stderr,"des(1) built with %s\n",libdes_version);
261 #endif
262 EXIT(1);
263 }
264 else usage();
265 }
266
267 #ifndef _Windows
268 if (vflag) fprintf(stderr,"des(1) built with %s\n",libdes_version);
269 #endif
270 if ( (in != NULL) &&
271 (out != NULL) &&
272 #ifndef MSDOS
273 (stat(in,&ins) != -1) &&
274 (stat(out,&outs) != -1) &&
275 (ins.st_dev == outs.st_dev) &&
276 (ins.st_ino == outs.st_ino))
277 #else /* MSDOS */
278 (strcmp(in,out) == 0))
279 #endif
280 {
281 fputs("input and output file are the same\n",stderr);
282 EXIT(3);
283 }
284
285 if (!kflag)
286 if (des_read_pw_string(key,KEYSIZB+1,"Enter key:",eflag?VERIFY:0))
287 {
288 fputs("password error\n",stderr);
289 EXIT(2);
290 }
291
292 if (in == NULL)
293 DES_IN=stdin;
294 else if ((DES_IN=fopen(in,"r")) == NULL)
295 {
296 perror("opening input file");
297 EXIT(4);
298 }
299
300 CKSUM_OUT=stdout;
301 if (out == NULL)
302 {
303 DES_OUT=stdout;
304 CKSUM_OUT=stderr;
305 }
306 else if ((DES_OUT=fopen(out,"w")) == NULL)
307 {
308 perror("opening output file");
309 EXIT(5);
310 }
311
312 #ifdef MSDOS
313 /* This should set the file to binary mode. */
314 {
315 #include <fcntl.h>
316 if (!(uflag && dflag))
317 setmode(fileno(DES_IN),O_BINARY);
318 if (!(uflag && eflag))
319 setmode(fileno(DES_OUT),O_BINARY);
320 }
321 #endif
322
323 doencryption();
324 fclose(DES_IN);
325 fclose(DES_OUT);
326 EXIT(0);
327 }
328
329 void usage()
330 {
331 char **u;
332 static const char *Usage[]={
333 "des <options> [input-file [output-file]]",
334 "options:",
335 "-v : des(1) version number",
336 "-e : encrypt using sunOS compatible user key to DES key conversion.",
337 "-E : encrypt ",
338 "-d : decrypt using sunOS compatible user key to DES key conversion.",
339 "-D : decrypt ",
340 "-c[ckname] : generate a cbc_cksum using sunOS compatible user key to",
341 " DES key conversion and output to ckname (stdout default,",
342 " stderr if data being output on stdout). The checksum is",
343 " generated before encryption and after decryption if used",
344 " in conjunction with -[eEdD].",
345 "-C[ckname] : generate a cbc_cksum as for -c but compatible with -[ED].",
346 "-k key : use key 'key'",
347 "-h : the key that is entered will be a hexidecimal number",
348 " that is used directly as the des key",
349 "-u[uuname] : input file is uudecoded if -[dD] or output uuencoded data if -[eE]",
350 " (uuname is the filename to put in the uuencode header).",
351 "-b : encrypt using DES in ecb encryption mode, the defaut is cbc mode.",
352 "-3 : encrypt using tripple DES encryption. This uses 2 keys",
353 " generated from the input key. If the input key is less",
354 " than 8 characters long, this is equivelent to normal",
355 " encryption. Default is tripple cbc, -b makes it tripple ecb.",
356 NULL
357 };
358 for (u=(char **)Usage; *u; u++)
359 {
360 fputs(*u,stderr);
361 fputc('\n',stderr);
362 }
363
364 EXIT(1);
365 }
366
367 void doencryption()
368 {
369 #ifdef _LIBC
370 extern int srandom();
371 extern int random();
372 extern unsigned long time();
373 #endif
374
375 register int i;
376 des_key_schedule ks,ks2;
377 unsigned char iv[8],iv2[8];
378 char *p;
379 int num=0,j,k,l,rem,ll,len,last,ex=0;
380 des_cblock kk,k2;
381 FILE *O;
382 int Exit=0;
383 #ifndef MSDOS
384 static unsigned char buf[BUFSIZE+8],obuf[BUFSIZE+8];
385 #else
386 static unsigned char *buf=NULL,*obuf=NULL;
387
388 if (buf == NULL)
389 {
390 if ( (( buf=(unsigned char *)Malloc(BUFSIZE+8)) == NULL) ||
391 ((obuf=(unsigned char *)Malloc(BUFSIZE+8)) == NULL))
392 {
393 fputs("Not enough memory\n",stderr);
394 Exit=10;
395 goto problems;
396 }
397 }
398 #endif
399
400 if (hflag)
401 {
402 j=(flag3?16:8);
403 p=key;
404 for (i=0; i<j; i++)
405 {
406 k=0;
407 if ((*p <= '9') && (*p >= '0'))
408 k=(*p-'0')<<4;
409 else if ((*p <= 'f') && (*p >= 'a'))
410 k=(*p-'a'+10)<<4;
411 else if ((*p <= 'F') && (*p >= 'A'))
412 k=(*p-'A'+10)<<4;
413 else
414 {
415 fputs("Bad hex key\n",stderr);
416 Exit=9;
417 goto problems;
418 }
419 p++;
420 if ((*p <= '9') && (*p >= '0'))
421 k|=(*p-'0');
422 else if ((*p <= 'f') && (*p >= 'a'))
423 k|=(*p-'a'+10);
424 else if ((*p <= 'F') && (*p >= 'A'))
425 k|=(*p-'A'+10);
426 else
427 {
428 fputs("Bad hex key\n",stderr);
429 Exit=9;
430 goto problems;
431 }
432 p++;
433 if (i < 8)
434 kk[i]=k;
435 else
436 k2[i-8]=k;
437 }
438 des_set_key((C_Block *)k2,ks2);
439 memset(k2,0,sizeof(k2));
440 }
441 else if (longk || flag3)
442 {
443 if (flag3)
444 {
445 des_string_to_2keys(key,(C_Block *)kk,(C_Block *)k2);
446 des_set_key((C_Block *)k2,ks2);
447 memset(k2,0,sizeof(k2));
448 }
449 else
450 des_string_to_key(key,(C_Block *)kk);
451 }
452 else
453 for (i=0; i<KEYSIZ; i++)
454 {
455 l=0;
456 k=key[i];
457 for (j=0; j<8; j++)
458 {
459 if (k&1) l++;
460 k>>=1;
461 }
462 if (l & 1)
463 kk[i]=key[i]&0x7f;
464 else
465 kk[i]=key[i]|0x80;
466 }
467
468 des_set_key((C_Block *)kk,ks);
469 memset(key,0,sizeof(key));
470 memset(kk,0,sizeof(kk));
471 /* woops - A bug that does not showup under unix :-( */
472 memset(iv,0,sizeof(iv));
473 memset(iv2,0,sizeof(iv2));
474
475 l=1;
476 rem=0;
477 /* first read */
478 if (eflag || (!dflag && cflag))
479 {
480 for (;;)
481 {
482 num=l=fread(&(buf[rem]),1,BUFSIZE,DES_IN);
483 l+=rem;
484 num+=rem;
485 if (l < 0)
486 {
487 perror("read error");
488 Exit=6;
489 goto problems;
490 }
491
492 rem=l%8;
493 len=l-rem;
494 if (feof(DES_IN))
495 {
496 srandom((unsigned int)time(NULL));
497 for (i=7-rem; i>0; i--)
498 buf[l++]=random()&0xff;
499 buf[l++]=rem;
500 ex=1;
501 len+=rem;
502 }
503 else
504 l-=rem;
505
506 if (cflag)
507 {
508 des_cbc_cksum((C_Block *)buf,(C_Block *)cksum,
509 (long)len,ks,(C_Block *)cksum);
510 if (!eflag)
511 {
512 if (feof(DES_IN)) break;
513 else continue;
514 }
515 }
516
517 if (bflag && !flag3)
518 for (i=0; i<l; i+=8)
519 des_ecb_encrypt(
520 (des_cblock *)&(buf[i]),
521 (des_cblock *)&(obuf[i]),
522 ks,do_encrypt);
523 else if (flag3 && bflag)
524 for (i=0; i<l; i+=8)
525 des_ecb2_encrypt(
526 (des_cblock *)&(buf[i]),
527 (des_cblock *)&(obuf[i]),
528 ks,ks2,do_encrypt);
529 else if (flag3 && !bflag)
530 {
531 char tmpbuf[8];
532
533 if (rem) memcpy(tmpbuf,&(buf[l]),
534 (unsigned int)rem);
535 des_3cbc_encrypt(
536 (des_cblock *)buf,(des_cblock *)obuf,
537 (long)l,ks,ks2,(des_cblock *)iv,
538 (des_cblock *)iv2,do_encrypt);
539 if (rem) memcpy(&(buf[l]),tmpbuf,
540 (unsigned int)rem);
541 }
542 else
543 {
544 des_cbc_encrypt(
545 (des_cblock *)buf,(des_cblock *)obuf,
546 (long)l,ks,(des_cblock *)iv,do_encrypt);
547 if (l >= 8) memcpy(iv,&(obuf[l-8]),8);
548 }
549 if (rem) memcpy(buf,&(buf[l]),(unsigned int)rem);
550
551 i=0;
552 while (i < l)
553 {
554 if (uflag)
555 j=uufwrite(obuf,1,(unsigned int)l-i,
556 DES_OUT);
557 else
558 j=fwrite(obuf,1,(unsigned int)l-i,
559 DES_OUT);
560 if (j == -1)
561 {
562 perror("Write error");
563 Exit=7;
564 goto problems;
565 }
566 i+=j;
567 }
568 if (feof(DES_IN))
569 {
570 if (uflag) uufwriteEnd(DES_OUT);
571 break;
572 }
573 }
574 }
575 else /* decrypt */
576 {
577 ex=1;
578 for (;;)
579 {
580 if (ex) {
581 if (uflag)
582 l=uufread(buf,1,BUFSIZE,DES_IN);
583 else
584 l=fread(buf,1,BUFSIZE,DES_IN);
585 ex=0;
586 rem=l%8;
587 l-=rem;
588 }
589 if (l < 0)
590 {
591 perror("read error");
592 Exit=6;
593 goto problems;
594 }
595
596 if (bflag && !flag3)
597 for (i=0; i<l; i+=8)
598 des_ecb_encrypt(
599 (des_cblock *)&(buf[i]),
600 (des_cblock *)&(obuf[i]),
601 ks,do_encrypt);
602 else if (flag3 && bflag)
603 for (i=0; i<l; i+=8)
604 des_ecb2_encrypt(
605 (des_cblock *)&(buf[i]),
606 (des_cblock *)&(obuf[i]),
607 ks,ks2,do_encrypt);
608 else if (flag3 && !bflag)
609 {
610 des_3cbc_encrypt(
611 (des_cblock *)buf,(des_cblock *)obuf,
612 (long)l,ks,ks2,(des_cblock *)iv,
613 (des_cblock *)iv2,do_encrypt);
614 }
615 else
616 {
617 des_cbc_encrypt(
618 (des_cblock *)buf,(des_cblock *)obuf,
619 (long)l,ks,(des_cblock *)iv,do_encrypt);
620 if (l >= 8) memcpy(iv,&(buf[l-8]),8);
621 }
622
623 if (uflag)
624 ll=uufread(&(buf[rem]),1,BUFSIZE,DES_IN);
625 else
626 ll=fread(&(buf[rem]),1,BUFSIZE,DES_IN);
627 ll+=rem;
628 rem=ll%8;
629 ll-=rem;
630 if (feof(DES_IN) && (ll == 0))
631 {
632 last=obuf[l-1];
633
634 if ((last > 7) || (last < 0))
635 {
636 fputs("The file was not decrypted correctly.\n",
637 stderr);
638 Exit=8;
639 last=0;
640 }
641 l=l-8+last;
642 }
643 i=0;
644 if (cflag) des_cbc_cksum((C_Block *)obuf,
645 (C_Block *)cksum,(long)l/8*8,ks,
646 (C_Block *)cksum);
647 while (i != l)
648 {
649 j=fwrite(obuf,1,(unsigned int)l-i,DES_OUT);
650 if (j == -1)
651 {
652 perror("Write error");
653 Exit=7;
654 goto problems;
655 }
656 i+=j;
657 }
658 l=ll;
659 if ((l == 0) && feof(DES_IN)) break;
660 }
661 }
662 if (cflag)
663 {
664 l=0;
665 if (cksumname[0] != '\0')
666 {
667 if ((O=fopen(cksumname,"w")) != NULL)
668 {
669 CKSUM_OUT=O;
670 l=1;
671 }
672 }
673 for (i=0; i<8; i++)
674 fprintf(CKSUM_OUT,"%02X",cksum[i]);
675 fprintf(CKSUM_OUT,"\n");
676 if (l) fclose(CKSUM_OUT);
677 }
678 problems:
679 memset(buf,0,sizeof(buf));
680 memset(obuf,0,sizeof(obuf));
681 memset(ks,0,sizeof(ks));
682 memset(ks2,0,sizeof(ks2));
683 memset(iv,0,sizeof(iv));
684 memset(iv2,0,sizeof(iv2));
685 memset(kk,0,sizeof(kk));
686 memset(k2,0,sizeof(k2));
687 memset(uubuf,0,sizeof(uubuf));
688 memset(b,0,sizeof(b));
689 memset(bb,0,sizeof(bb));
690 memset(cksum,0,sizeof(cksum));
691 if (Exit) EXIT(Exit);
692 }
693
694 int uufwrite(data, size, num, fp)
695 unsigned char *data;
696 int size;
697 unsigned int num;
698 FILE *fp;
699
700 /* We ignore this parameter but it should be > ~50 I believe */
701
702
703 {
704 int i,j,left,rem,ret=num;
705 static int start=1;
706
707 if (start)
708 {
709 fprintf(fp,"begin 600 %s\n",
710 (uuname[0] == '\0')?"text.d":uuname);
711 start=0;
712 }
713
714 if (uubufnum)
715 {
716 if (uubufnum+num < 45)
717 {
718 memcpy(&(uubuf[uubufnum]),data,(unsigned int)num);
719 uubufnum+=num;
720 return(num);
721 }
722 else
723 {
724 i=45-uubufnum;
725 memcpy(&(uubuf[uubufnum]),data,(unsigned int)i);
726 j=uuencode((unsigned char *)uubuf,45,b);
727 fwrite(b,1,(unsigned int)j,fp);
728 uubufnum=0;
729 data+=i;
730 num-=i;
731 }
732 }
733
734 for (i=0; i<(((int)num)-INUUBUFN); i+=INUUBUFN)
735 {
736 j=uuencode(&(data[i]),INUUBUFN,b);
737 fwrite(b,1,(unsigned int)j,fp);
738 }
739 rem=(num-i)%45;
740 left=(num-i-rem);
741 if (left)
742 {
743 j=uuencode(&(data[i]),left,b);
744 fwrite(b,1,(unsigned int)j,fp);
745 i+=left;
746 }
747 if (i != num)
748 {
749 memcpy(uubuf,&(data[i]),(unsigned int)rem);
750 uubufnum=rem;
751 }
752 return(ret);
753 }
754
755 void uufwriteEnd(fp)
756 FILE *fp;
757 {
758 int j;
759 static const char *end=" \nend\n";
760
761 if (uubufnum != 0)
762 {
763 uubuf[uubufnum]='\0';
764 uubuf[uubufnum+1]='\0';
765 uubuf[uubufnum+2]='\0';
766 j=uuencode(uubuf,uubufnum,b);
767 fwrite(b,1,(unsigned int)j,fp);
768 }
769 fwrite(end,1,strlen(end),fp);
770 }
771
772 int uufread(out, size, num, fp)
773 unsigned char *out;
774 int size; /* should always be > ~ 60; I actually ignore this parameter :-) */
775 unsigned int num;
776 FILE *fp;
777 {
778 int i,j,tot;
779 static int done=0;
780 static int valid=0;
781 static int start=1;
782
783 if (start)
784 {
785 for (;;)
786 {
787 b[0]='\0';
788 fgets((char *)b,300,fp);
789 if (b[0] == '\0')
790 {
791 fprintf(stderr,"no 'begin' found in uuencoded input\n");
792 return(-1);
793 }
794 if (strncmp((char *)b,"begin ",6) == 0) break;
795 }
796 start=0;
797 }
798 if (done) return(0);
799 tot=0;
800 if (valid)
801 {
802 memcpy(out,bb,(unsigned int)valid);
803 tot=valid;
804 valid=0;
805 }
806 for (;;)
807 {
808 b[0]='\0';
809 fgets((char *)b,300,fp);
810 if (b[0] == '\0') break;
811 i=strlen((char *)b);
812 if ((b[0] == 'e') && (b[1] == 'n') && (b[2] == 'd'))
813 {
814 done=1;
815 while (!feof(fp))
816 {
817 fgets((char *)b,300,fp);
818 }
819 break;
820 }
821 i=uudecode(b,i,bb);
822 if (i < 0) break;
823 if ((i+tot+8) > num)
824 {
825 /* num to copy to make it a multiple of 8 */
826 j=(num/8*8)-tot-8;
827 memcpy(&(out[tot]),bb,(unsigned int)j);
828 tot+=j;
829 memcpy(bb,&(bb[j]),(unsigned int)i-j);
830 valid=i-j;
831 break;
832 }
833 memcpy(&(out[tot]),bb,(unsigned int)i);
834 tot+=i;
835 }
836 return(tot);
837 }
838
839 #define ccc2l(c,l) (l =((DES_LONG)(*((c)++)))<<16, \
840 l|=((DES_LONG)(*((c)++)))<< 8, \
841 l|=((DES_LONG)(*((c)++))))
842
843 #define l2ccc(l,c) (*((c)++)=(unsigned char)(((l)>>16)&0xff), \
844 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
845 *((c)++)=(unsigned char)(((l) )&0xff))
846
847
848 int uuencode(in, num, out)
849 unsigned char *in;
850 int num;
851 unsigned char *out;
852 {
853 int j,i,n,tot=0;
854 DES_LONG l;
855 register unsigned char *p;
856 p=out;
857
858 for (j=0; j<num; j+=45)
859 {
860 if (j+45 > num)
861 i=(num-j);
862 else i=45;
863 *(p++)=i+' ';
864 for (n=0; n<i; n+=3)
865 {
866 ccc2l(in,l);
867 *(p++)=((l>>18)&0x3f)+' ';
868 *(p++)=((l>>12)&0x3f)+' ';
869 *(p++)=((l>> 6)&0x3f)+' ';
870 *(p++)=((l )&0x3f)+' ';
871 tot+=4;
872 }
873 *(p++)='\n';
874 tot+=2;
875 }
876 *p='\0';
877 l=0;
878 return(tot);
879 }
880
881 int uudecode(in, num, out)
882 unsigned char *in;
883 int num;
884 unsigned char *out;
885 {
886 int j,i,k;
887 unsigned int n=0,space=0;
888 DES_LONG l;
889 DES_LONG w,x,y,z;
890 unsigned int blank=(unsigned int)'\n'-' ';
891
892 for (j=0; j<num; )
893 {
894 n= *(in++)-' ';
895 if (n == blank)
896 {
897 n=0;
898 in--;
899 }
900 if (n > 60)
901 {
902 fprintf(stderr,"uuencoded line length too long\n");
903 return(-1);
904 }
905 j++;
906
907 for (i=0; i<n; j+=4,i+=3)
908 {
909 /* the following is for cases where spaces are
910 * removed from lines.
911 */
912 if (space)
913 {
914 w=x=y=z=0;
915 }
916 else
917 {
918 w= *(in++)-' ';
919 x= *(in++)-' ';
920 y= *(in++)-' ';
921 z= *(in++)-' ';
922 }
923 if ((w > 63) || (x > 63) || (y > 63) || (z > 63))
924 {
925 k=0;
926 if (w == blank) k=1;
927 if (x == blank) k=2;
928 if (y == blank) k=3;
929 if (z == blank) k=4;
930 space=1;
931 switch (k) {
932 case 1: w=0; in--;
933 case 2: x=0; in--;
934 case 3: y=0; in--;
935 case 4: z=0; in--;
936 break;
937 case 0:
938 space=0;
939 fprintf(stderr,"bad uuencoded data values\n");
940 w=x=y=z=0;
941 return(-1);
942 break;
943 }
944 }
945 l=(w<<18)|(x<<12)|(y<< 6)|(z );
946 l2ccc(l,out);
947 }
948 if (*(in++) != '\n')
949 {
950 fprintf(stderr,"missing nl in uuencoded line\n");
951 w=x=y=z=0;
952 return(-1);
953 }
954 j++;
955 }
956 *out='\0';
957 w=x=y=z=0;
958 return(n);
959 }
960