]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/des/des.c
Warnings and casts.
[thirdparty/openssl.git] / crypto / des / des.c
CommitLineData
d02b48c6 1/* crypto/des/des.c */
58964a49 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
d02b48c6
RE
3 * All rights reserved.
4 *
5 * This package is an SSL implementation written
6 * by Eric Young (eay@cryptsoft.com).
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@cryptsoft.com).
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@cryptsoft.com)"
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@cryptsoft.com)"
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#include <stdio.h>
60#include <stdlib.h>
61#ifndef MSDOS
7d7d2cbc 62#ifndef VMS
d02b48c6 63#include <unistd.h>
7d7d2cbc
UM
64#else /* VMS */
65#ifdef __DECC
66#include <unistd.h>
67#if __CRTL_VER < 70000000
68#define RAND
69#endif
70#else /* not __DECC */
71#include <math.h>
72#define RAND
73#endif /* __DECC */
74#endif /* VMS */
d02b48c6
RE
75#else
76#include <io.h>
77#define RAND
78#endif
79
80#include <time.h>
81#include "des_ver.h"
82
83#ifdef VMS
84#include <types.h>
85#include <stat.h>
86#else
87#ifndef _IRIX
88#include <sys/types.h>
89#endif
90#include <sys/stat.h>
91#endif
ec577822 92#include <openssl/des.h>
d02b48c6
RE
93
94#if defined(__STDC__) || defined(VMS) || defined(M_XENIX) || defined(MSDOS)
95#include <string.h>
96#endif
97
98#ifdef RAND
99#define random rand
100#define srandom(s) srand(s)
101#endif
102
d02b48c6
RE
103void usage(void);
104void doencryption(void);
105int uufwrite(unsigned char *data, int size, unsigned int num, FILE *fp);
106void uufwriteEnd(FILE *fp);
107int uufread(unsigned char *out,int size,unsigned int num,FILE *fp);
108int uuencode(unsigned char *in,int num,unsigned char *out);
109int uudecode(unsigned char *in,int num,unsigned char *out);
58964a49
RE
110void des_3cbc_encrypt(des_cblock *input,des_cblock *output,long length,
111 des_key_schedule sk1,des_key_schedule sk2,
112 des_cblock *ivec1,des_cblock *ivec2,int enc);
d02b48c6 113#ifdef VMS
58964a49 114#define EXIT(a) exit(a&0x10000000L)
d02b48c6
RE
115#else
116#define EXIT(a) exit(a)
117#endif
118
119#define BUFSIZE (8*1024)
120#define VERIFY 1
121#define KEYSIZ 8
122#define KEYSIZB 1024 /* should hit tty line limit first :-) */
123char key[KEYSIZB+1];
124int do_encrypt,longk=0;
125FILE *DES_IN,*DES_OUT,*CKSUM_OUT;
126char uuname[200];
127unsigned char uubuf[50];
128int uubufnum=0;
129#define INUUBUFN (45*100)
130#define OUTUUBUF (65*100)
131unsigned char b[OUTUUBUF];
132unsigned char bb[300];
133des_cblock cksum={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
134char cksumname[200]="";
135
136int vflag,cflag,eflag,dflag,kflag,bflag,fflag,sflag,uflag,flag3,hflag,error;
137
6b691a5c 138int main(int argc, char **argv)
d02b48c6
RE
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
6b691a5c 329void usage(void)
d02b48c6
RE
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",
9151d396 355" encryption. Default is triple cbc, -b makes it triple ecb.",
d02b48c6
RE
356NULL
357};
358 for (u=(char **)Usage; *u; u++)
359 {
360 fputs(*u,stderr);
361 fputc('\n',stderr);
362 }
363
364 EXIT(1);
365 }
366
6b691a5c 367void doencryption(void)
d02b48c6
RE
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;
f947eb31 377 des_cblock iv,iv2;
d02b48c6
RE
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 {
f947eb31
UM
390 if ( (( buf=Malloc(BUFSIZE+8)) == NULL) ||
391 ((obuf=Malloc(BUFSIZE+8)) == NULL))
d02b48c6
RE
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 }
f947eb31 438 des_set_key(&k2,ks2);
d02b48c6
RE
439 memset(k2,0,sizeof(k2));
440 }
441 else if (longk || flag3)
442 {
443 if (flag3)
444 {
f947eb31
UM
445 des_string_to_2keys(key,&kk,&k2);
446 des_set_key(&k2,ks2);
d02b48c6
RE
447 memset(k2,0,sizeof(k2));
448 }
449 else
f947eb31 450 des_string_to_key(key,&kk);
d02b48c6
RE
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
f947eb31 468 des_set_key(&kk,ks);
d02b48c6
RE
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 {
f947eb31
UM
508 des_cbc_cksum(buf,&cksum,
509 (long)len,ks,&cksum);
d02b48c6
RE
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,
f947eb31
UM
537 (long)l,ks,ks2,&iv,
538 &iv2,do_encrypt);
d02b48c6
RE
539 if (rem) memcpy(&(buf[l]),tmpbuf,
540 (unsigned int)rem);
541 }
542 else
543 {
544 des_cbc_encrypt(
f947eb31
UM
545 buf,obuf,
546 (long)l,ks,&iv,do_encrypt);
d02b48c6
RE
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,
f947eb31
UM
612 (long)l,ks,ks2,&iv,
613 &iv2,do_encrypt);
d02b48c6
RE
614 }
615 else
616 {
617 des_cbc_encrypt(
f947eb31
UM
618 buf,obuf,
619 (long)l,ks,&iv,do_encrypt);
d02b48c6
RE
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;
f947eb31
UM
644 if (cflag) des_cbc_cksum(obuf,
645 (des_cblock *)cksum,(long)l/8*8,ks,
646 (des_cblock *)cksum);
d02b48c6
RE
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 }
678problems:
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
6b691a5c
UM
694/* We ignore this parameter but it should be > ~50 I believe */
695int uufwrite(unsigned char *data, int size, unsigned int num, FILE *fp)
d02b48c6
RE
696 {
697 int i,j,left,rem,ret=num;
698 static int start=1;
699
700 if (start)
701 {
702 fprintf(fp,"begin 600 %s\n",
703 (uuname[0] == '\0')?"text.d":uuname);
704 start=0;
705 }
706
707 if (uubufnum)
708 {
709 if (uubufnum+num < 45)
710 {
711 memcpy(&(uubuf[uubufnum]),data,(unsigned int)num);
712 uubufnum+=num;
713 return(num);
714 }
715 else
716 {
717 i=45-uubufnum;
718 memcpy(&(uubuf[uubufnum]),data,(unsigned int)i);
719 j=uuencode((unsigned char *)uubuf,45,b);
720 fwrite(b,1,(unsigned int)j,fp);
721 uubufnum=0;
722 data+=i;
723 num-=i;
724 }
725 }
726
727 for (i=0; i<(((int)num)-INUUBUFN); i+=INUUBUFN)
728 {
729 j=uuencode(&(data[i]),INUUBUFN,b);
730 fwrite(b,1,(unsigned int)j,fp);
731 }
732 rem=(num-i)%45;
733 left=(num-i-rem);
734 if (left)
735 {
736 j=uuencode(&(data[i]),left,b);
737 fwrite(b,1,(unsigned int)j,fp);
738 i+=left;
739 }
740 if (i != num)
741 {
742 memcpy(uubuf,&(data[i]),(unsigned int)rem);
743 uubufnum=rem;
744 }
745 return(ret);
746 }
747
6b691a5c 748void uufwriteEnd(FILE *fp)
d02b48c6
RE
749 {
750 int j;
751 static const char *end=" \nend\n";
752
753 if (uubufnum != 0)
754 {
755 uubuf[uubufnum]='\0';
756 uubuf[uubufnum+1]='\0';
757 uubuf[uubufnum+2]='\0';
758 j=uuencode(uubuf,uubufnum,b);
759 fwrite(b,1,(unsigned int)j,fp);
760 }
761 fwrite(end,1,strlen(end),fp);
762 }
763
6b691a5c
UM
764/* int size: should always be > ~ 60; I actually ignore this parameter :-) */
765int uufread(unsigned char *out, int size, unsigned int num, FILE *fp)
d02b48c6
RE
766 {
767 int i,j,tot;
768 static int done=0;
769 static int valid=0;
770 static int start=1;
771
772 if (start)
773 {
774 for (;;)
775 {
776 b[0]='\0';
777 fgets((char *)b,300,fp);
778 if (b[0] == '\0')
779 {
780 fprintf(stderr,"no 'begin' found in uuencoded input\n");
781 return(-1);
782 }
783 if (strncmp((char *)b,"begin ",6) == 0) break;
784 }
785 start=0;
786 }
787 if (done) return(0);
788 tot=0;
789 if (valid)
790 {
791 memcpy(out,bb,(unsigned int)valid);
792 tot=valid;
793 valid=0;
794 }
795 for (;;)
796 {
797 b[0]='\0';
798 fgets((char *)b,300,fp);
799 if (b[0] == '\0') break;
800 i=strlen((char *)b);
801 if ((b[0] == 'e') && (b[1] == 'n') && (b[2] == 'd'))
802 {
803 done=1;
804 while (!feof(fp))
805 {
806 fgets((char *)b,300,fp);
807 }
808 break;
809 }
810 i=uudecode(b,i,bb);
811 if (i < 0) break;
812 if ((i+tot+8) > num)
813 {
814 /* num to copy to make it a multiple of 8 */
815 j=(num/8*8)-tot-8;
816 memcpy(&(out[tot]),bb,(unsigned int)j);
817 tot+=j;
818 memcpy(bb,&(bb[j]),(unsigned int)i-j);
819 valid=i-j;
820 break;
821 }
822 memcpy(&(out[tot]),bb,(unsigned int)i);
823 tot+=i;
824 }
825 return(tot);
826 }
827
828#define ccc2l(c,l) (l =((DES_LONG)(*((c)++)))<<16, \
829 l|=((DES_LONG)(*((c)++)))<< 8, \
830 l|=((DES_LONG)(*((c)++))))
831
832#define l2ccc(l,c) (*((c)++)=(unsigned char)(((l)>>16)&0xff), \
833 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
834 *((c)++)=(unsigned char)(((l) )&0xff))
835
836
6b691a5c 837int uuencode(unsigned char *in, int num, unsigned char *out)
d02b48c6
RE
838 {
839 int j,i,n,tot=0;
840 DES_LONG l;
841 register unsigned char *p;
842 p=out;
843
844 for (j=0; j<num; j+=45)
845 {
846 if (j+45 > num)
847 i=(num-j);
848 else i=45;
849 *(p++)=i+' ';
850 for (n=0; n<i; n+=3)
851 {
852 ccc2l(in,l);
853 *(p++)=((l>>18)&0x3f)+' ';
854 *(p++)=((l>>12)&0x3f)+' ';
855 *(p++)=((l>> 6)&0x3f)+' ';
856 *(p++)=((l )&0x3f)+' ';
857 tot+=4;
858 }
859 *(p++)='\n';
860 tot+=2;
861 }
862 *p='\0';
863 l=0;
864 return(tot);
865 }
866
6b691a5c 867int uudecode(unsigned char *in, int num, unsigned char *out)
d02b48c6
RE
868 {
869 int j,i,k;
870 unsigned int n=0,space=0;
871 DES_LONG l;
872 DES_LONG w,x,y,z;
873 unsigned int blank=(unsigned int)'\n'-' ';
874
875 for (j=0; j<num; )
876 {
877 n= *(in++)-' ';
878 if (n == blank)
879 {
880 n=0;
881 in--;
882 }
883 if (n > 60)
884 {
885 fprintf(stderr,"uuencoded line length too long\n");
886 return(-1);
887 }
888 j++;
889
890 for (i=0; i<n; j+=4,i+=3)
891 {
892 /* the following is for cases where spaces are
893 * removed from lines.
894 */
895 if (space)
896 {
897 w=x=y=z=0;
898 }
899 else
900 {
901 w= *(in++)-' ';
902 x= *(in++)-' ';
903 y= *(in++)-' ';
904 z= *(in++)-' ';
905 }
906 if ((w > 63) || (x > 63) || (y > 63) || (z > 63))
907 {
908 k=0;
909 if (w == blank) k=1;
910 if (x == blank) k=2;
911 if (y == blank) k=3;
912 if (z == blank) k=4;
913 space=1;
914 switch (k) {
915 case 1: w=0; in--;
916 case 2: x=0; in--;
917 case 3: y=0; in--;
918 case 4: z=0; in--;
919 break;
920 case 0:
921 space=0;
922 fprintf(stderr,"bad uuencoded data values\n");
923 w=x=y=z=0;
924 return(-1);
925 break;
926 }
927 }
928 l=(w<<18)|(x<<12)|(y<< 6)|(z );
929 l2ccc(l,out);
930 }
931 if (*(in++) != '\n')
932 {
933 fprintf(stderr,"missing nl in uuencoded line\n");
934 w=x=y=z=0;
935 return(-1);
936 }
937 j++;
938 }
939 *out='\0';
940 w=x=y=z=0;
941 return(n);
942 }