Initial Commit
[packages] / xemacs-packages / mew / mew / bin / mewencode.c
1 /*
2  * mewencode, mewdecode, and mewcat --- MIME encoding for Mew
3  *
4  * Author:  Kazu Yamamoto <Kazu@Mew.org>
5  * Created: Dec  8, 1994
6  * Revised: Dec 12, 1998
7  *
8  * Code:
9  */
10
11 static char version_message[] = "mewencode version 0.14 981219 Kazu Yamamoto";
12
13 #include "getopt.h"
14 #include <stdio.h>
15 #include <string.h>
16 #if defined(_WIN32) || defined(OS2)
17 #include <fcntl.h>
18 #endif
19
20 #define ENCODE_NAME "mewencode"
21 #define DECODE_NAME "mewdecode"
22 #define CAT_NAME    "mewcat"
23
24 #define ENCODE   1
25 #define DECODE   2
26
27 #define SUCCESS 0
28 #define ERROR 1
29
30 #define FILESEP    '/'
31 #define FILESEPLEN 1
32
33 #define LINELEN 71
34
35 #define BASE64  'b'
36 #define QP      'q'
37 #define GZIP64  'z'
38
39 #define ON  1
40 #define YES 1
41 #define OFF 0
42 #define NO  0
43
44 #define CR 13
45 #define LF 10
46
47 #define OOB -1
48 #define EOP -2
49
50 #define PADDING '='
51
52 /*
53  * "b" is ignored on UNIX.
54  */
55 #define FDREAD  "rb"
56 #define FDWRITE "wb"
57
58 #define STRCMP(str1, str2) strncmp(str1, str2, sizeof(str2) - 1)
59
60 /*
61  * long name convention for option
62  */
63
64 struct option longopts [] = {
65         {"encode",           0, 0, 'e'},
66         {"decode",           0, 0, 'd'},
67         {"base64",           0, 0, 'b'},
68         {"quoted-printable", 0, 0, 'q'},
69         {"gzip64",           0, 0, 'z'},
70         {"length",           1, 0, 'l'},
71         {"text",             0, 0, 't'},
72         {"help",             0, 0, 'h'},
73         {"version",          0, 0, 'v'},    
74         {0, 0, 0, 0}
75 };
76
77 void
78 usage(progname)
79         char* progname;
80 {
81         fprintf(stderr, "usage: %s [-e|-d] [-b|-q|-g] [-l length] [-t] [infile [outfile]]\n", progname);
82 }
83
84 char *help_message[] = {
85         " -e  --encode           Encoding <infile>",
86         " -d  --decode           Decoding <infile> instead of encoding",
87         "                        Decoding is the default when called with decoding", 
88         "                        program name.", 
89         " -b  --base64           MIME base64 en/decoding.",
90         " -q  --quoted-printable MIME quoted-printable en/decoding.",
91         " -g  --gzip64           MIME gzip64 en/decoding(not yet specified in RFC).",
92         " -z                     Same as -g.",
93         " -l  --length           Line length into which base64/quoted-printable/gzip64 ",
94         "                        encoding truncate. The default value is 71.",
95         " -t  --text             On base64/gzip64 encoding, local newline is treated",
96         "                        as CRLF.",
97         "                        On base/gzip64 decoding,any newline is translated",
98         "                        into local newline.",
99         "                        Specify this option only when the input is a line",
100         "                        based object(e.g. Content-Type: is text/plain or",
101         "                        application/postscript).",
102         " -h  --help             Display this help message.",
103         " -v  --version          Display the version.",
104         "",
105         "Default is Encoding, Base64, Length = 71, Binary.",
106         "If <infile> is \"-\", it means the standard input.",
107         "If <outfile> is \"-\", it means the standard output.",
108         0
109 };
110
111 void
112 help(progname)
113         char *progname;
114 {
115         char **p = help_message;
116
117         fprintf(stderr, "help: %s\n\n", progname);
118         fprintf(stderr, " A MIME encoder/decoder.\n\n");
119         usage(progname);
120         while (*p) fprintf(stderr, "%s\n", *p++);
121 }
122
123 void
124 version(progname)
125         char *progname;
126 {
127         fprintf(stderr, "version of %s: %s\n", progname, version_message);
128 }
129
130 /*
131  * utils
132  */
133
134 char *
135 mewbasename(filename)
136         char *filename;
137 {
138         char *p;
139
140         if ((p = strrchr(filename, FILESEP)) != NULL)
141                 filename = p + FILESEPLEN;
142         return filename;
143 }
144
145 /*
146  * basic input/output
147  */
148
149 /*
150  * 8bit input with line canonicalization
151  */
152
153 int
154 Getc(stream, text)
155         FILE *stream;
156         int text;
157 {
158         static int Incr = OFF, Ineof = OFF;
159         int c;
160     
161         if (!text)
162                 return(getc(stream));
163     
164         if (Ineof)
165                 return(EOF);
166         c = getc(stream);
167     
168         if (Incr) {
169                 Incr  = OFF;    
170                 switch (c) {
171                 case EOF:
172                         Ineof = ON;
173                         return(LF);
174                         break;
175                 case LF:
176                         return(LF);
177                         break;
178                 default:
179                         ungetc(c, stream);
180                         return(LF);
181                         break;
182                 }
183         }
184         if (c == CR) {
185                 Incr = ON;
186                 return(CR);
187         }
188         if (c == LF) {
189                 ungetc(c, stream);
190                 Incr = ON;
191                 return(CR);
192         }
193         if (c == EOF)
194                 Ineof = ON;
195         return(c);
196 }
197
198 /*
199  * lineless 'ascii' input
200  */
201
202 static char base256[] = {
203         OOB,OOB,OOB,OOB, OOB,OOB,OOB,OOB, OOB,OOB,OOB,OOB, OOB,OOB,OOB,OOB,
204     
205         OOB,OOB,OOB,OOB, OOB,OOB,OOB,OOB, OOB,OOB,OOB,OOB, OOB,OOB,OOB,OOB,
206       /*                                                -                / */
207         OOB,OOB,OOB,OOB, OOB,OOB,OOB,OOB, OOB,OOB,OOB, 62, OOB,OOB,OOB, 63,
208       /*  0   1   2   3    4   5   6   7    8   9                =        */
209          52, 53, 54, 55,  56, 57, 58, 59,  60, 61,OOB,OOB, OOB,OOB,OOB,OOB,
210       /*      A   B   C    D   E   F   G    H   I   J   K    L   M   N   O*/
211         OOB,  0,  1,  2,   3,  4,  5,  6,   7,  8,  9, 10,  11, 12, 13, 14,
212       /*  P   Q   R   S    T   U   V   W    X   Y   Z                     */
213          15, 16, 17, 18,  19, 20, 21, 22,  23, 24, 25,OOB, OOB,OOB,OOB,OOB,
214       /*      a   b   c    d   e   f   g    h   i   j   k    l   m   n   o*/
215         OOB, 26, 27, 28,  29, 30, 31, 32,  33, 34, 35, 36,  37, 38, 39, 40,
216       /*  p   q   r   s    t   u   v   w    x   y   z                     */
217          41, 42, 43, 44,  45, 46, 47, 48,  49, 50, 51,OOB, OOB,OOB,OOB,OOB, 
218 };
219
220 int
221 GetChar(FILE *stream, int cannot_be_eof)
222 {
223         int c, ret;
224         static int Ineof = OFF;
225
226         if (Ineof == ON)
227                 return EOF;
228     
229         do {
230                 c = getc(stream);
231         } while ( c == CR || c == LF);
232
233         if (c == EOF) {
234                 if (cannot_be_eof == YES) {
235                         fprintf(stderr, "Error: base64 decoder saw premature EOF.");
236                         exit(ERROR);
237                 }
238                 Ineof = ON;
239                 return(EOF);
240         }
241
242         if (c == PADDING)
243                 return(EOP);
244         
245         if ((ret = base256[c]) == OOB) {
246                 fprintf(stderr, "base64 decoder saw an illegal character.");
247                 exit(ERROR);
248         }
249         
250         return(ret);
251 }
252
253 void
254 PutChar(c, stream, text)
255         int c;
256         FILE *stream;
257         int text;
258 {
259         static int Outcr = OFF, Outeof = OFF;
260
261         if (!text) {
262                 if (c != EOF)
263                         putc(c, stream);
264                 return;
265         }
266
267         /* text */
268     
269         if (Outeof) return;
270     
271         if (c == EOF) {
272                 Outeof = ON;
273                 Outcr = OFF; /* xxx */
274                 return;
275         }
276
277         if (Outcr) {
278                 Outcr = OFF;
279                 switch (c) {
280                 case LF : 
281                         break;
282                 case CR : 
283                         putc(LF, stream);
284                         Outcr = ON;
285                         break;
286                 default:
287                         putc(c, stream);
288                         break;
289                 }
290                 return;
291         }
292
293         switch (c) {
294         case CR : 
295                 putc(LF, stream);
296                 Outcr = ON;
297                 break;
298         default:
299                 putc(c, stream);
300                 break;
301         }
302     
303 }
304
305 /*
306  * Base 64
307  */
308
309 static char base64[] =
310         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
311
312 void
313 base256to64 (c1, c2, c3, padding, outfile)
314         int c1, c2, c3, padding;
315         FILE *outfile;
316 {
317         putc(base64[c1>>2], outfile);
318         putc(base64[((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4)], outfile);
319         switch (padding) {
320         case 0:
321                 putc(base64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)], outfile);
322                 putc(base64[c3 & 0x3F], outfile);
323                 break;
324         case 1:
325                 putc(base64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)], outfile);
326                 putc(PADDING, outfile);
327                 break;
328         case 2:
329                 putc(PADDING, outfile);
330                 putc(PADDING, outfile);
331                 break;
332         }
333 }
334
335 void
336 base64_encode(infile, outfile, text, length)
337         FILE *infile, *outfile;
338         int text, length;
339 {
340         int c1, c2, c3, len = 0;
341     
342         while ((c1 = Getc(infile, text)) != EOF) {
343                 if ((c2 = Getc(infile, text)) == EOF)
344                         base256to64(c1, 0, 0, 2, outfile);
345                 else if ((c3 = Getc(infile, text)) == EOF)
346                         base256to64(c1, c2, 0, 1, outfile);
347                 else
348                         base256to64(c1, c2, c3, 0, outfile);
349                 len += 4;
350                 if (len > length) {
351                         putc('\n', outfile);
352                         len = 0;
353                 }
354         }
355         if (len) putc('\n', outfile);
356         fflush(outfile);
357     
358 }
359
360 void
361 base64_decode(infile, outfile, text)
362         FILE *infile, *outfile;
363         int text;
364 {
365         int c1, c2, c3, c4;
366
367         while ((c1 = GetChar(infile, NO)) != EOF) {
368                 if (c1 == EOP)
369                         break;
370                 if ((c2 = GetChar(infile, YES)) == EOP)
371                         break;
372                 PutChar(((c1 << 2) | ((c2 & 0x30) >> 4)), outfile, text);
373
374                 if ((c3 = GetChar(infile, YES)) == EOP)
375                         break;
376                 PutChar((((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2)), outfile, text);
377                 
378                 if ((c4 = GetChar(infile, YES)) == EOP)
379                         break;
380                 PutChar((((c3 & 0x03) << 6) | c4), outfile, text);
381         }
382 }
383
384 /*
385  * Quoted_Printable
386  */
387
388 static char base16[] = "0123456789ABCDEF";
389 static char From[] = "\nFrom ";
390
391 #define EQ   '='
392 #define TAB   9
393 #define SP   32
394 #define DOT  '.'
395 #define DEL 127
396 #define softbreak(stream) {putc(EQ, stream); putc(LF, stream);}
397
398 void
399 quoted_printable_encode(infile, outfile, length)
400         FILE *infile, *outfile;
401         int length;
402 {
403         int c, len = 0, sp = OFF, lfdot = OFF, Fromix = 1;
404
405         while ((c = getc(infile)) != EOF) {
406                 if ((c == TAB) || (c == SP)) {
407                         if (From[Fromix] == c) { /* SP */
408                                 putc(EQ, outfile);
409                                 putc(base16[c >> 4], outfile);
410                                 putc(base16[c & 0x0f], outfile);
411                                 len += 3;
412                                 Fromix = 0;
413                                 continue;
414                         }
415                         Fromix = 0;
416                         sp = ON;
417                         putc(c, outfile);
418                         if ((++len) > length) {
419                                 sp = OFF;
420                                 len = 0;
421                                 lfdot = LF;
422                                 Fromix = 1;
423                                 softbreak(outfile);
424                         }
425                         continue;
426                 }
427                 if (c == LF) {
428                         if (sp || (lfdot == DOT))
429                                 softbreak(outfile);
430                         len = 0;
431                         sp = OFF;
432                         lfdot = LF;
433                         Fromix = 1;
434                         putc(LF, outfile);
435                         continue;
436                 }
437                 if ((c < SP) || (c == EQ) || (c >= DEL)) {
438                         /* exclusive TAB, SP */
439                         sp = OFF;
440                         putc(EQ, outfile);
441                         putc(base16[c >> 4], outfile);
442                         putc(base16[c & 0x0f], outfile);
443                         len += 3;
444                         if (len > length) {
445                                 len = 0;
446                                 lfdot = LF;
447                                 Fromix = 1;
448                                 softbreak(outfile);
449                         } else {
450                                 Fromix = 0;
451                                 lfdot = OFF;
452                         }
453                         continue;
454                 }
455                 sp = OFF;
456
457                 if (From[Fromix] == c)
458                         Fromix++;
459                 else
460                         Fromix = 0;
461         
462                 if (c == DOT && lfdot == LF)
463                         lfdot = DOT; 
464                 else
465                         lfdot = OFF;
466
467                 putc(c, outfile);
468                 if ((++len) > length) {
469                         len = 0;
470                         lfdot = LF;
471                         Fromix = 1;
472                         softbreak(outfile);
473                 }
474         }
475         if (len > 0)
476                 softbreak(outfile); /* ignored by decoder */
477 }
478
479 static char base128[] = {
480         OOB,OOB,OOB,OOB, OOB,OOB,OOB,OOB, OOB,OOB,OOB,OOB, OOB,OOB,OOB,OOB,
481         OOB,OOB,OOB,OOB, OOB,OOB,OOB,OOB, OOB,OOB,OOB,OOB, OOB,OOB,OOB,OOB,
482         OOB,OOB,OOB,OOB, OOB,OOB,OOB,OOB, OOB,OOB,OOB,OOB, OOB,OOB,OOB,OOB,
483           0,  1,  2,  3,   4,  5,  6,  7,   8,  9,OOB,OOB, OOB,OOB,OOB,OOB,
484         OOB, 10, 11, 12,  13, 14, 15,OOB, OOB,OOB,OOB,OOB, OOB,OOB,OOB,OOB,
485         OOB,OOB,OOB,OOB, OOB,OOB,OOB,OOB, OOB,OOB,OOB,OOB, OOB,OOB,OOB,OOB,
486         OOB, 10, 11, 12,  13, 14, 15,OOB, OOB,OOB,OOB,OOB, OOB,OOB,OOB,OOB,
487         OOB,OOB,OOB,OOB, OOB,OOB,OOB,OOB, OOB,OOB,OOB,OOB, OOB,OOB,OOB,OOB,
488 };
489
490 int
491 puthexchar(c1, c2, stream)
492         int c1, c2;
493         FILE *stream;
494 {
495         int a1, a2;
496         static int warned = OFF;
497
498         if (((a1 = base128[c1]) != OOB) && ((a2 = base128[c2]) != OOB)) {
499                 putc(((a1 << 4) | a2), stream);
500                 return (SUCCESS);
501         } else {
502                 if (warned == OFF) { /* warn just once */
503                         fprintf(stderr, "Error: can't translate hex to character: %c%c\n",
504                                 c1, c2);
505                         warned = ON;
506                 }
507                 return (ERROR); 
508         }
509 }
510
511 void
512 quoted_printable_decode(infile, outfile)
513         FILE *infile, *outfile;
514 {
515         int c1, c2, c3;
516
517         /* if an error occurs, print input sequence as it is, anyway, sigh */
518     
519         while((c1 = getc(infile)) != EOF) {
520         skipgetc:
521                 if (c1 == EQ) {
522                         if ((c2 = getc(infile)) == EOF) {
523                                 fprintf(stderr, "Error: end of file after =.\n");
524                                 putc(EQ, outfile);
525                                 exit(ERROR);
526                         }
527                         if (c2 == LF) continue;
528                         if ((c3 = getc(infile)) == EOF) {
529                                 fprintf(stderr, "Error: end of file after =.\n");
530                                 putc(EQ, outfile);
531                                 putc(c2, outfile);
532                                 exit(ERROR);
533                         }
534                         if (puthexchar(c2, c3, outfile) == ERROR) {
535                                 putc(EQ, outfile);
536                                 if ((c1 = c2) == EOF) exit(ERROR);
537                                 ungetc(c3, infile);
538                                 goto skipgetc;
539                         } else
540                                 continue;
541                 }
542                 putc(c1, outfile);
543         }
544 }
545
546 /*
547  * Gzip 64
548  */
549
550 #define READ  0
551 #define WRITE 1
552
553 void
554 gzip64_encode(infile, outfile, text, length)
555         FILE *infile, *outfile;
556         int text, length;
557 {
558         int pipes[2];
559         int childpid;
560     
561         if (pipe(pipes) != 0) {
562                 fprintf(stderr, "Can't open pipe\n");
563                 exit(ERROR);
564         }
565
566         childpid = fork ();
567
568         if (childpid < 0) {
569                 fprintf(stderr, "Can't fork.\n");
570                 exit(ERROR);
571         }
572
573         if (childpid > 0) { /* I'm the parent. */
574                 close(pipes[WRITE]);
575                 if ((infile = fdopen(pipes[READ], FDREAD)) == NULL) {
576                         fprintf(stderr, "Can't open read pipe\n");
577                         exit(ERROR);
578                 }
579
580                 base64_encode(infile, outfile, OFF, length);
581
582                 exit(SUCCESS);
583         }
584
585         /* I'm the child. */
586
587         close(WRITE);
588         dup(pipes[WRITE]);
589         close(pipes[READ]);
590         
591         if (text == OFF) {
592         
593                 if (fileno(infile) != READ) {
594                         close(READ);
595                         dup(fileno(infile));
596                 }
597         
598                 execlp("gzip", "gzip", "-q", "-n", "-c", (char *) 0);
599         
600                 exit(SUCCESS);
601
602         } else {
603
604                 int pipes2[2];
605                 int childpid2;
606         
607                 if (pipe(pipes2) != 0) {
608                         fprintf(stderr, "Can't open pipe\n");
609                         exit(ERROR);
610                 }
611         
612                 childpid2 = fork ();
613         
614                 if (childpid2 < 0) {
615                         fprintf(stderr, "Can't fork.\n");
616                         exit(ERROR);
617                 }
618         
619                 if (childpid2 > 0) { /* I'm the child. */
620                         close(pipes2[WRITE]);
621                         close(READ);
622                         dup(pipes2[READ]);
623
624                         execlp("gzip", "gzip", "-q", "-n", "-c", (char *) 0);
625             
626                         exit(SUCCESS);
627                 }
628
629                 /* I'm the grandchild */
630 #ifdef OS2
631                 _setmode(pipes2[WRITE],  O_BINARY);
632 #endif
633                 close(WRITE);
634                 dup(pipes2[WRITE]);
635                 close(pipes2[READ]);
636         
637                 {
638                         int c;
639                         while ((c = Getc(infile, ON)) != EOF)
640                                 putchar(c);
641                 }
642
643                 exit(SUCCESS);
644         
645         }
646     
647 }
648
649 void
650 gzip64_decode(infile, outfile, text)
651         FILE *infile, *outfile;
652         int text;
653 {
654         int pipes[2];
655         int childpid;
656     
657         if (pipe(pipes) != 0) {
658                 fprintf(stderr, "Can't open pipe\n");
659                 exit(ERROR);
660         }
661
662         childpid = fork ();
663
664         if (childpid < 0) {
665                 fprintf(stderr, "Can't fork.\n");
666                 exit(ERROR);
667         }
668
669         if (childpid > 0) { /* I'm the parent. */
670                 close(READ);
671                 dup(pipes[READ]);
672
673                 close(pipes[WRITE]);
674
675                 if (text == ON) {
676                         int c;
677                         while ((c = getchar()) != EOF) PutChar(c, outfile, ON);
678                 } else {
679                         if (fileno(outfile) != WRITE) {
680                                 close(WRITE);
681                                 dup(fileno(outfile));
682                         }
683                         execlp ("gzip", "gzip", "-q", "-d", "-n", "-c", (char *) 0);
684                 }
685         
686                 exit(SUCCESS);
687
688         }
689
690         /* I'm the child. */
691     
692         close(pipes[READ]);
693
694         if (text == ON) {
695                 int pipes2[2];
696                 int childpid2;
697         
698                 if (pipe(pipes2) != 0) {
699                         fprintf(stderr, "Can't open pipe\n");
700                         exit(ERROR);
701                 }
702
703                 childpid2 = fork ();
704
705                 if (childpid2 < 0) {
706                         fprintf(stderr, "Can't fork.\n");
707                         exit(ERROR);
708                 }
709
710                 if (childpid2 > 0) { /* I'm the child. */
711                         close(pipes2[WRITE]);
712                         close(WRITE);
713                         dup(pipes[WRITE]);
714                         close(READ);
715                         dup(pipes2[READ]);
716
717                         execlp("gzip", "gzip", "-q", "-d", "-n", "-c", (char *) 0);
718         
719                         exit(SUCCESS);      
720                 }
721
722                 /* I'm the grandchild */
723
724                 close(pipes2[READ]);
725
726                 if ((outfile = fdopen(pipes2[WRITE], FDWRITE)) == NULL) {
727                         fprintf(stderr, "Can't open write pipe\n");
728                         exit(ERROR);
729                 }
730         
731                 base64_decode(infile, outfile, OFF);
732
733                 exit(SUCCESS);
734
735         } else {
736
737                 if ((outfile = fdopen(pipes[WRITE], FDWRITE)) == NULL) {
738                         fprintf(stderr, "Can't open write pipe\n");
739                         exit(ERROR);
740                 }
741
742                 base64_decode(infile, outfile, OFF);
743         
744                 exit(SUCCESS);
745         }
746 }
747
748 /*
749  * main
750  */
751
752 int main (argc, argv)
753         int argc;
754         char **argv;
755 {
756         int optc;
757         FILE *infile;
758         FILE *outfile;
759         int file_count = 0;
760         /*
761          * default option values
762          */
763         int  action = ENCODE;
764         char encode = BASE64;   /* -b -q -g */
765         int  length = LINELEN;  /* -l num */
766         int  text   = OFF;      /* -t */
767         char *progname = mewbasename(argv[0]), *p;
768
769         for (p = progname; *p; p++) {
770                 *p = tolower(*p);
771         }
772
773 #ifdef _WIN32
774         _setmode(_fileno(stdin),  O_BINARY);
775         _setmode(_fileno(stdout), O_BINARY);    
776 #endif
777 #ifdef OS2
778         _setmode(fileno(stdin),  O_BINARY);
779         _setmode(fileno(stdout), O_BINARY);     
780 #endif
781         while((optc = getopt_long(argc, argv, "esdbqgzl:thv", longopts,
782                                   (int *)0)) != EOF) {
783                 switch (optc) {
784                 case 'e':
785                         action = ENCODE;
786                         break;
787                 case 'd':
788                         action = DECODE;
789                         break;
790                 case 'b':
791                         encode = BASE64;
792                         break;
793                 case 'q':
794                         encode = QP;
795                         break;
796                 case 'g':
797                 case 'z':
798                         encode = GZIP64;
799                         break;
800                 case 'l':
801                         length = atoi(optarg);
802                         break;
803                 case 't':
804                         text = ON;
805                         break;
806                 case 'h':
807                         help(progname);
808                         exit(SUCCESS);
809                         break;
810                 case 'v':
811                         version(progname);
812                         exit(SUCCESS);
813                         break;
814                 default:
815                         usage(progname);
816                         exit(ERROR);
817                 }
818         }
819
820         file_count = argc - optind;
821
822         switch(file_count) {
823         case 0:
824                 infile  = stdin;
825                 outfile = stdout;
826                 break;
827         case 1:
828                 if (STRCMP(argv[optind], "-") == 0) {
829                         infile = stdin;
830                 } else if ((infile = fopen(argv[optind], FDREAD)) == NULL) {
831                         fprintf(stderr, "Can't open file %s.\n", argv[optind]);
832                         exit(ERROR);
833                 }
834                 outfile = stdout;
835                 break;
836         case 2:
837                 if (STRCMP(argv[optind], "-") == 0) {
838                         infile  = stdin;
839                 } else if ((infile = fopen(argv[optind], FDREAD)) == NULL) {
840                         fprintf(stderr, "Can't open file %s.\n", argv[optind]);
841                         exit(ERROR);
842                 }
843                 optind++;
844                 if (STRCMP(argv[optind], "-") == 0) {
845                         outfile  = stdout;
846                 } else if ((outfile = fopen(argv[optind], FDWRITE)) == NULL) {
847                         fprintf(stderr, "Can't open file %s.\n", argv[optind]);
848                         exit(ERROR);
849                 }
850                 break;
851         default:
852                 usage(progname);
853                 exit(ERROR);
854                 break;
855         }
856
857         /* Override argments by progname. */
858
859         if (STRCMP(progname, DECODE_NAME) == 0)
860                 action = DECODE;
861         if (STRCMP(progname, CAT_NAME) == 0) {
862                 action = DECODE;
863                 outfile = stdout;
864         }
865
866         switch (action) {
867         case ENCODE:
868                 switch (encode) {
869                 case BASE64:
870                         base64_encode(infile, outfile, text, length);
871                         break;
872                 case QP:
873                         quoted_printable_encode(infile, outfile, length);
874                         break;
875                 case GZIP64:
876                         gzip64_encode(infile, outfile, text, length);
877                         break;
878                 }
879                 break;
880         case DECODE:
881                 switch (encode) {
882                 case BASE64:
883                         base64_decode(infile, outfile, text);
884                         break;
885                 case QP:
886                         quoted_printable_decode(infile, outfile);
887                         break;
888                 case GZIP64:
889                         gzip64_decode(infile, outfile, text);
890                         break;
891                 }
892                 break;
893         }
894
895         exit(SUCCESS);
896 }
897
898 /* 
899  * Copyright (C) 1994, 1995, 1996, 1997 Mew developing team.
900  * All rights reserved.
901  * 
902  * Redistribution and use in source and binary forms, with or without
903  * modification, are permitted provided that the following conditions
904  * are met:
905  * 
906  * 1. Redistributions of source code must retain the above copyright
907  *    notice, this list of conditions and the following disclaimer.
908  * 2. Redistributions in binary form must reproduce the above copyright
909  *    notice, this list of conditions and the following disclaimer in the
910  *    documentation and/or other materials provided with the distribution.
911  * 3. Neither the name of the team nor the names of its contributors
912  *    may be used to endorse or promote products derived from this software
913  *    without specific prior written permission.
914  * 
915  * THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND
916  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
917  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
918  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE
919  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
920  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
921  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
922  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
923  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
924  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
925  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
926  */
927
928 /*
929  * mewencode.c ends here
930  */