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