ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Convert-UUlib/uulib/uuencode.c
Revision: 1.2.2.1
Committed: Sun Mar 31 19:51:29 2002 UTC (22 years, 2 months ago) by root
Content type: text/plain
Branch: UUDEVIEW
CVS Tags: UUDEVIEW-0-5-15
Changes since 1.2: +21 -21 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 /*
2     * This file is part of uudeview, the simple and friendly multi-part multi-
3 root 1.2 * file uudecoder program (c) 1994-2001 by Frank Pilhofer. The author may
4     * be contacted at fp@fpx.de
5 root 1.1 *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     */
16    
17     #ifdef HAVE_CONFIG_H
18     #include "config.h"
19     #endif
20    
21     #ifdef SYSTEM_WINDLL
22     #include <windows.h>
23     #endif
24     #ifdef SYSTEM_OS2
25     #include <os2.h>
26     #endif
27    
28     #include <sys/types.h>
29     #include <sys/stat.h>
30     #include <ctype.h>
31     #include <stdio.h>
32     #include <time.h>
33    
34     #ifdef STDC_HEADERS
35     #include <stdlib.h>
36     #include <string.h>
37     #endif
38     #ifdef HAVE_UNISTD_H
39     #include <unistd.h>
40     #endif
41     #ifdef HAVE_ERRNO_H
42     #include <errno.h>
43     #endif
44    
45 root 1.2 #include <uudeview.h>
46 root 1.1 #include <uuint.h>
47     #include <fptools.h>
48     #include <uustring.h>
49    
50     /* for braindead systems */
51     #ifndef SEEK_SET
52     #ifdef L_BEGIN
53     #define SEEK_SET L_BEGIN
54     #else
55     #define SEEK_SET 0
56     #endif
57     #endif
58    
59 root 1.2.2.1 char * uuencode_id = "$Id: uuencode.c,v 1.18 2001/06/06 18:21:47 fp Exp $";
60 root 1.1
61     #if 0
62     /*
63     * the End-Of-Line string. MIME enforces CRLF, so that's what we use. Some
64     * implementations of uudecode will complain about a missing end line, since
65     * they look for "end^J" but find "end^J^M". We don't care - especially be-
66     * cause they still decode the file properly despite this complaint.
67     */
68    
69     #ifndef EOLSTRING
70     #define EOLSTRING "\015\012"
71     #endif
72    
73     #else
74    
75     /*
76     * Argh. Some delivery software (inews) has problems with the CRLF
77     * line termination. Let's try native EOL and see if we run into
78     * any problems.
79     * This involves opening output files in text mode instead of binary
80     */
81    
82     #ifndef EOLSTRING
83     #define EOLSTRING "\n"
84     #endif
85    
86     #endif
87    
88    
89     /*
90     * =========================================================================
91     * User-configurable settings end here. Don't spy below unless you know what
92     * you're doing.
93     * =========================================================================
94     */
95    
96     /*
97     * Define End-Of-Line sequence
98     */
99    
100     #ifdef EOLSTRING
101     static unsigned char *eolstring = (unsigned char *) EOLSTRING;
102     #else
103     static unsigned char *eolstring = (unsigned char *) "\012";
104     #endif
105    
106     /*
107     * Content-Transfer-Encoding types for non-MIME encodings
108     */
109    
110     #define CTE_UUENC "x-uuencode"
111     #define CTE_XXENC "x-xxencode"
112     #define CTE_BINHEX "x-binhex"
113    
114     #define CTE_TYPE(y) (((y)==B64ENCODED) ? "Base64" : \
115     ((y)==UU_ENCODED) ? CTE_UUENC : \
116     ((y)==XX_ENCODED) ? CTE_XXENC : \
117 root 1.2 ((y)==PT_ENCODED) ? "8bit" : \
118     ((y)==QP_ENCODED) ? "quoted-printable" : \
119 root 1.1 ((y)==BH_ENCODED) ? CTE_BINHEX : "x-oops")
120    
121     /*
122     * encoding tables
123     */
124    
125     unsigned char UUEncodeTable[64] = {
126     '`', '!', '"', '#', '$', '%', '&', '\'',
127     '(', ')', '*', '+', ',', '-', '.', '/',
128     '0', '1', '2', '3', '4', '5', '6', '7',
129     '8', '9', ':', ';', '<', '=', '>', '?',
130     '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
131     'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
132     'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
133     'X', 'Y', 'Z', '[', '\\',']', '^', '_'
134     };
135    
136    
137     unsigned char B64EncodeTable[64] = {
138     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
139     'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
140     'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
141     'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
142     'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
143     'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
144     'w', 'x', 'y', 'z', '0', '1', '2', '3',
145     '4', '5', '6', '7', '8', '9', '+', '/'
146     };
147    
148     unsigned char XXEncodeTable[64] = {
149     '+', '-', '0', '1', '2', '3', '4', '5',
150     '6', '7', '8', '9', 'A', 'B', 'C', 'D',
151     'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
152     'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
153     'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b',
154     'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
155     'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
156     's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
157     };
158    
159     unsigned char BHEncodeTable[64] = {
160     '!', '"', '#', '$', '%', '&', '\'', '(',
161     ')', '*', '+', ',', '-', '0', '1', '2',
162     '3', '4', '5', '6', '8', '9', '@', 'A',
163     'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
164     'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R',
165     'S', 'T', 'U', 'V', 'X', 'Y', 'Z', '[',
166     '`', 'a', 'b', 'c', 'd', 'e', 'f', 'h',
167     'i', 'j', 'k', 'l', 'm', 'p', 'q', 'r'
168 root 1.2 };
169    
170     unsigned char HexEncodeTable[16] = {
171     '0', '1', '2', '3', '4', '5', '6', '7',
172     '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
173     };
174 root 1.1
175     typedef struct {
176     char *extension;
177     char *mimetype;
178     } mimemap;
179    
180     /*
181     * This table maps a file's extension into a Content-Type. The current
182     * official list can be downloaded as
183     * ftp://ftp.isi.edu/in-notes/iana/assignments/media-type
184     * I haven't listed any text types since it doesn't make sense to encode
185     * them. Everything not on the list gets mapped to application/octet-stream
186     */
187    
188     static mimemap mimetable[] = {
189     { "gif", "image/gif" }, /* Grafics Interchange Format */
190     { "jpg", "image/jpeg" }, /* JFIF encoded files */
191     { "jpeg", "image/jpeg" },
192     { "tif", "image/tiff" }, /* Tag Image File Format */
193     { "tiff", "image/tiff" },
194     { "cgm", "image/cgm" }, /* Computer Graphics Metafile */
195     { "au", "audio/basic" }, /* 8kHz ulaw audio data */
196     { "mov", "video/quicktime" }, /* Apple Quicktime */
197     { "qt", "video/quicktime" }, /* Also infrequently used */
198     { "mpeg", "video/mpeg" }, /* Motion Picture Expert Group */
199     { "mpg", "video/mpeg" },
200     { "mp2", "video/mpeg" }, /* dito, MPEG-2 encoded files */
201 root 1.2 { "mp3", "audio/mpeg" }, /* dito, MPEG-3 encoded files */
202 root 1.1 { "ps", "application/postscript" }, /* Postscript Language */
203     { "zip", "application/zip" }, /* ZIP archive */
204     { "doc", "application/msword"},/* assume Microsoft Word */
205     { NULL, NULL }
206     };
207    
208     /*
209     * the order of the following two tables must match the
210     * Encoding Types definition in uudeview.h
211     */
212    
213     /*
214     * encoded bytes per line
215     */
216    
217     static int bpl[5] = { 0, 45, 57, 45, 45 };
218    
219     /*
220     * tables
221     */
222    
223     static unsigned char *etables[5] = {
224     NULL,
225     UUEncodeTable,
226     B64EncodeTable,
227     XXEncodeTable,
228     BHEncodeTable
229     };
230    
231     /*
232     * variables to malloc upon initialization
233     */
234    
235     char *uuestr_itemp;
236     char *uuestr_otemp;
237    
238     /*
239     * Encode one part of the data stream
240     */
241    
242     static int
243     UUEncodeStream (FILE *outfile, FILE *infile, int encoding, long linperfile)
244     {
245 root 1.2.2.1 unsigned char *itemp = (char *) uuestr_itemp;
246     unsigned char *otemp = (char *) uuestr_otemp;
247 root 1.1 unsigned char *optr, *table, *tptr;
248     int index, count;
249     long line=0;
250     size_t llen;
251    
252     if (outfile==NULL || infile==NULL ||
253 root 1.2 (encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED&&
254     encoding!=PT_ENCODED&&encoding!=QP_ENCODED)) {
255 root 1.1 UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
256     uustring (S_PARM_CHECK), "UUEncodeStream()");
257     return UURET_ILLVAL;
258     }
259    
260 root 1.2 /*
261     * Special handling for plain text and quoted printable. Text is
262     * read line oriented.
263     */
264    
265     if (encoding == PT_ENCODED || encoding == QP_ENCODED) {
266     while (!feof (infile) && (linperfile <= 0 || line < linperfile)) {
267 root 1.2.2.1 if (_FP_fgets (itemp, 255, infile) == NULL) {
268 root 1.2 break;
269     }
270    
271     itemp[255] = '\0';
272     count = strlen (itemp);
273    
274     llen = 0;
275     optr = otemp;
276    
277     /*
278     * Busy Callback
279     */
280    
281     if (UUBUSYPOLL(ftell(infile)-progress.foffset,progress.fsize)) {
282     UUMessage (uuencode_id, __LINE__, UUMSG_NOTE,
283     uustring (S_ENCODE_CANCEL));
284     return UURET_CANCEL;
285     }
286    
287     if (encoding == PT_ENCODED) {
288     /*
289     * If there is a line feed, replace by eolstring
290     */
291     if (count > 0 && itemp[count-1] == '\n') {
292     itemp[--count] = '\0';
293     if (fwrite (itemp, 1, count, outfile) != count ||
294     fwrite ((char *) eolstring, 1,
295     strlen(eolstring), outfile) != strlen (eolstring)) {
296     return UURET_IOERR;
297     }
298     }
299     else {
300     if (fwrite (itemp, 1, count, outfile) != llen) {
301     return UURET_IOERR;
302     }
303     }
304     }
305     else if (encoding == QP_ENCODED) {
306     for (index=0; index<count; index++) {
307     if (llen == 0 && itemp[index] == '.') {
308     /*
309     * Special rule: encode '.' at the beginning of a line, so
310     * that some mailers aren't confused.
311     */
312     *optr++ = '=';
313     *optr++ = HexEncodeTable[itemp[index] >> 4];
314     *optr++ = HexEncodeTable[itemp[index] & 0x0f];
315     llen += 3;
316     }
317     else if ((itemp[index] >= 33 && itemp[index] <= 60) ||
318     (itemp[index] >= 62 && itemp[index] <= 126) ||
319     itemp[index] == 9 || itemp[index] == 32) {
320     *optr++ = itemp[index];
321     llen++;
322     }
323     else if (itemp[index] == '\n') {
324     /*
325     * If the last character before EOL was a space or tab,
326     * we must encode it. If llen > 74, there's no space to do
327     * that, so generate a soft line break instead.
328     */
329    
330     if (index>0 && (itemp[index-1] == 9 || itemp[index-1] == 32)) {
331     *(optr-1) = '=';
332     if (llen <= 74) {
333     *optr++ = HexEncodeTable[itemp[index-1] >> 4];
334     *optr++ = HexEncodeTable[itemp[index-1] & 0x0f];
335     llen += 2;
336     }
337     }
338    
339     if (fwrite (otemp, 1, llen, outfile) != llen ||
340     fwrite ((char *) eolstring, 1,
341     strlen(eolstring), outfile) != strlen (eolstring)) {
342     return UURET_IOERR;
343     }
344    
345     /*
346     * Fix the soft line break condition from above
347     */
348    
349     if (index>0 && (itemp[index-1] == 9 || itemp[index-1] == 32) &&
350     *(optr-1) == '=') {
351     otemp[0] = '=';
352     otemp[1] = HexEncodeTable[itemp[index-1] >> 4];
353     otemp[2] = HexEncodeTable[itemp[index-1] & 0x0f];
354    
355     if (fwrite (otemp, 1, 3, outfile) != 3 ||
356     fwrite ((char *) eolstring, 1,
357     strlen(eolstring), outfile) != strlen (eolstring)) {
358     return UURET_IOERR;
359     }
360     }
361    
362     optr = otemp;
363     llen = 0;
364     }
365     else {
366     *optr++ = '=';
367     *optr++ = HexEncodeTable[itemp[index] >> 4];
368     *optr++ = HexEncodeTable[itemp[index] & 0x0f];
369     llen += 3;
370     }
371    
372     /*
373     * Lines must be shorter than 76 characters (not counting CRLF).
374     * If the line grows longer than that, we must include a soft
375     * line break.
376     */
377    
378     if (itemp[index+1] != 0 && itemp[index+1] != '\n' &&
379     (llen >= 75 ||
380     !((itemp[index+1] >= 33 && itemp[index+1] <= 60) ||
381     (itemp[index+1] >= 62 && itemp[index+1] <= 126)) &&
382     llen >= 73)) {
383    
384     *optr++ = '=';
385     llen++;
386    
387     if (fwrite (otemp, 1, llen, outfile) != llen ||
388     fwrite ((char *) eolstring, 1,
389     strlen(eolstring), outfile) != strlen (eolstring)) {
390     return UURET_IOERR;
391     }
392    
393     optr = otemp;
394     llen = 0;
395     }
396     }
397     }
398    
399     line++;
400     }
401    
402     return UURET_OK;
403     }
404    
405     /*
406     * Handling for binary encodings
407     */
408 root 1.1
409     /*
410     * select charset
411     */
412    
413     table = etables[encoding];
414    
415     if (table==NULL || bpl[encoding]==0) {
416     UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
417 root 1.2 uustring (S_PARM_CHECK), "UUEncodeStream()");
418 root 1.1 return UURET_ILLVAL;
419     }
420    
421     while (!feof (infile) && (linperfile <= 0 || line < linperfile)) {
422     if ((count = fread (itemp, 1, bpl[encoding], infile)) != bpl[encoding]) {
423     if (count == 0)
424     break;
425     else if (ferror (infile))
426     return UURET_IOERR;
427     }
428 root 1.2
429 root 1.1 optr = otemp;
430     llen = 0;
431    
432     /*
433     * Busy Callback
434     */
435    
436     if (UUBUSYPOLL(ftell(infile)-progress.foffset,progress.fsize)) {
437     UUMessage (uuencode_id, __LINE__, UUMSG_NOTE,
438     uustring (S_ENCODE_CANCEL));
439     return UURET_CANCEL;
440     }
441    
442     /*
443     * for UU and XX, encode the number of bytes as first character
444     */
445 root 1.2
446 root 1.1 if (encoding == UU_ENCODED || encoding == XX_ENCODED) {
447     *optr++ = table[count];
448     llen++;
449     }
450    
451 root 1.2 /*
452     * Main encoding
453     */
454    
455     if (encoding == UU_ENCODED || encoding == XX_ENCODED ||
456     encoding == B64ENCODED) {
457     for (index=0; index<=count-3; index+=3, llen+=4) {
458     *optr++ = table[itemp[index] >> 2];
459     *optr++ = table[((itemp[index ] & 0x03) << 4)|(itemp[index+1] >> 4)];
460     *optr++ = table[((itemp[index+1] & 0x0f) << 2)|(itemp[index+2] >> 6)];
461     *optr++ = table[ itemp[index+2] & 0x3f];
462     }
463 root 1.1 }
464    
465     /*
466     * Special handling for incomplete lines
467     */
468 root 1.2
469 root 1.1 if (index != count) {
470     if (encoding == B64ENCODED) {
471     if (count - index == 2) {
472     *optr++ = table[itemp[index] >> 2];
473     *optr++ = table[((itemp[index ] & 0x03) << 4) |
474     ((itemp[index+1] & 0xf0) >> 4)];
475     *optr++ = table[((itemp[index+1] & 0x0f) << 2)];
476     *optr++ = '=';
477     }
478     else if (count - index == 1) {
479     *optr++ = table[ itemp[index] >> 2];
480     *optr++ = table[(itemp[index] & 0x03) << 4];
481     *optr++ = '=';
482     *optr++ = '=';
483     }
484     llen += 4;
485     }
486 root 1.2 else if (encoding == UU_ENCODED || encoding == XX_ENCODED) {
487 root 1.1 if (count - index == 2) {
488     *optr++ = table[itemp[index] >> 2];
489     *optr++ = table[((itemp[index ] & 0x03) << 4) |
490     ( itemp[index+1] >> 4)];
491     *optr++ = table[((itemp[index+1] & 0x0f) << 2)];
492     *optr++ = table[0];
493     }
494     else if (count - index == 1) {
495     *optr++ = table[ itemp[index] >> 2];
496     *optr++ = table[(itemp[index] & 0x03) << 4];
497     *optr++ = table[0];
498     *optr++ = table[0];
499     }
500     llen += 4;
501     }
502     }
503 root 1.2
504 root 1.1 /*
505     * end of line
506     */
507 root 1.2
508 root 1.1 tptr = eolstring;
509    
510     while (*tptr)
511     *optr++ = *tptr++;
512    
513     *optr++ = '\0';
514     llen += strlen ((char *) eolstring);
515    
516     if (fwrite (otemp, 1, llen, outfile) != llen)
517     return UURET_IOERR;
518    
519     line++;
520     }
521     return UURET_OK;
522     }
523    
524     /*
525     * Encode as MIME multipart/mixed sub-message.
526     */
527    
528     int UUEXPORT
529     UUEncodeMulti (FILE *outfile, FILE *infile, char *infname, int encoding,
530     char *outfname, char *mimetype, int filemode)
531     {
532     mimemap *miter=mimetable;
533     struct stat finfo;
534     int res, themode;
535     FILE *theifile;
536     char *ptr;
537    
538     if (outfile==NULL ||
539     (infile == NULL && infname==NULL) ||
540     (outfname==NULL && infname==NULL) ||
541 root 1.2 (encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED&&
542     encoding!=PT_ENCODED&&encoding!=QP_ENCODED)) {
543 root 1.1 UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
544     uustring (S_PARM_CHECK), "UUEncodeMulti()");
545     return UURET_ILLVAL;
546     }
547    
548     progress.action = 0;
549    
550     if (infile==NULL) {
551     if (stat (infname, &finfo) == -1) {
552     UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
553     uustring (S_NOT_STAT_FILE),
554     infname, strerror (uu_errno=errno));
555     return UURET_IOERR;
556     }
557     if ((theifile = fopen (infname, "rb")) == NULL) {
558     UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
559     uustring (S_NOT_OPEN_FILE),
560     infname, strerror (uu_errno=errno));
561     return UURET_IOERR;
562     }
563     themode = (filemode) ? filemode : ((int) finfo.st_mode & 0777);
564     progress.fsize = (long) finfo.st_size;
565     }
566     else {
567     if (fstat (fileno (infile), &finfo) != 0) {
568     themode = (filemode)?filemode:0644;
569     progress.fsize = -1;
570     }
571     else {
572     themode = (int) finfo.st_mode & 0777;
573     progress.fsize = (long) finfo.st_size;
574     }
575     theifile = infile;
576     }
577    
578     if (progress.fsize <= 0)
579     progress.fsize = -1;
580    
581 root 1.2.2.1 _FP_strncpy (progress.curfile, (outfname)?outfname:infname, 256);
582 root 1.1
583     progress.partno = 1;
584     progress.numparts = 1;
585     progress.percent = 0;
586     progress.foffset = 0;
587     progress.action = UUACT_ENCODING;
588    
589     /*
590     * If not given from outside, select an appropriate Content-Type by
591     * looking at the file's extension. If it is unknown, default to
592     * Application/Octet-Stream
593     */
594    
595     if (mimetype == NULL) {
596 root 1.2.2.1 if ((ptr = _FP_strrchr ((outfname)?outfname:infname, '.'))) {
597     while (miter->extension && _FP_stricmp (ptr+1, miter->extension) != 0)
598 root 1.1 miter++;
599     mimetype = miter->mimetype;
600     }
601     }
602 root 1.2
603     if (mimetype == NULL && (encoding == PT_ENCODED || encoding == QP_ENCODED)) {
604     mimetype = "text/plain";
605     }
606    
607 root 1.1 /*
608     * print sub-header
609     */
610    
611     fprintf (outfile, "Content-Type: %s%s",
612     (mimetype)?mimetype:"Application/Octet-Stream",
613     eolstring);
614     fprintf (outfile, "Content-Transfer-Encoding: %s%s",
615     CTE_TYPE(encoding), eolstring);
616     fprintf (outfile, "Content-Disposition: attachment; filename=\"%s\"%s",
617     UUFNameFilter ((outfname)?outfname:infname), eolstring);
618     fprintf (outfile, "%s", eolstring);
619    
620     if (encoding == UU_ENCODED || encoding == XX_ENCODED) {
621     fprintf (outfile, "begin %o %s%s",
622     (themode) ? themode : 0644,
623     UUFNameFilter ((outfname)?outfname:infname),
624     eolstring);
625     }
626     if ((res = UUEncodeStream (outfile, theifile, encoding, 0)) != UURET_OK) {
627     if (res != UURET_CANCEL) {
628     UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
629     uustring (S_ERR_ENCODING),
630     UUFNameFilter ((infname)?infname:outfname),
631     (res==UURET_IOERR)?strerror(uu_errno):UUstrerror(res));
632     }
633     progress.action = 0;
634     return res;
635     }
636     if (encoding == UU_ENCODED || encoding == XX_ENCODED) {
637     fprintf (outfile, "%c%s",
638     (encoding==UU_ENCODED) ? UUEncodeTable[0] : XXEncodeTable[0],
639     eolstring);
640     fprintf (outfile, "end%s", eolstring);
641     }
642     /*
643     * empty line at end does no harm
644     */
645     fprintf (outfile, "%s", eolstring);
646    
647     if (infile==NULL)
648     fclose (theifile);
649    
650     progress.action = 0;
651     return UURET_OK;
652     }
653    
654     /*
655     * Encode as MIME message/partial
656     */
657    
658     int UUEXPORT
659     UUEncodePartial (FILE *outfile, FILE *infile,
660     char *infname, int encoding,
661     char *outfname, char *mimetype,
662     int filemode, int partno, long linperfile)
663     {
664     mimemap *miter=mimetable;
665     static FILE *theifile;
666     int themode, numparts;
667     struct stat finfo;
668     long thesize;
669     char *ptr;
670     int res;
671    
672     if ((outfname==NULL&&infname==NULL) || partno<=0 ||
673     (infile == NULL&&infname==NULL) || outfile==NULL ||
674 root 1.2 (encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED&&
675     encoding!=PT_ENCODED&&encoding!=QP_ENCODED)) {
676 root 1.1 UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
677     uustring (S_PARM_CHECK), "UUEncodePartial()");
678     return UURET_ILLVAL;
679     }
680    
681     /*
682     * The first part needs a set of headers
683     */
684    
685     progress.action = 0;
686    
687     if (partno == 1) {
688     if (infile==NULL) {
689     if (stat (infname, &finfo) == -1) {
690     UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
691     uustring (S_NOT_STAT_FILE),
692     infname, strerror (uu_errno=errno));
693     return UURET_IOERR;
694     }
695     if ((theifile = fopen (infname, "rb")) == NULL) {
696     UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
697     uustring (S_NOT_OPEN_FILE),
698     infname, strerror (uu_errno=errno));
699     return UURET_IOERR;
700     }
701     if (linperfile <= 0)
702     numparts = 1;
703     else
704     numparts = (int) (((long)finfo.st_size+(linperfile*bpl[encoding]-1))/
705     (linperfile*bpl[encoding]));
706    
707     themode = (filemode) ? filemode : ((int) finfo.st_mode & 0777);
708     thesize = (long) finfo.st_size;
709     }
710     else {
711     if (fstat (fileno (infile), &finfo) != 0) {
712     UUMessage (uuencode_id, __LINE__, UUMSG_WARNING,
713     uustring (S_STAT_ONE_PART));
714     numparts = 1;
715     themode = (filemode)?filemode:0644;
716     thesize = 0;
717     }
718     else {
719     if (linperfile <= 0)
720     numparts = 1;
721     else
722     numparts = (int) (((long)finfo.st_size+(linperfile*bpl[encoding]-1))/
723     (linperfile*bpl[encoding]));
724    
725     themode = (int) finfo.st_mode & 0777;
726     thesize = (long) finfo.st_size;
727     }
728     theifile = infile;
729     }
730    
731 root 1.2.2.1 _FP_strncpy (progress.curfile, (outfname)?outfname:infname, 256);
732 root 1.1
733     progress.totsize = (thesize>0) ? thesize : -1;
734     progress.partno = 1;
735     progress.numparts = numparts;
736     progress.percent = 0;
737     progress.foffset = 0;
738    
739     /*
740     * If not given from outside, select an appropriate Content-Type by
741     * looking at the file's extension. If it is unknown, default to
742     * Application/Octet-Stream
743     */
744    
745     if (mimetype == NULL) {
746 root 1.2.2.1 if ((ptr = _FP_strrchr ((outfname)?outfname:infname, '.'))) {
747     while (miter->extension && _FP_stricmp (ptr+1, miter->extension) != 0)
748 root 1.1 miter++;
749     mimetype = miter->mimetype;
750     }
751     }
752 root 1.2
753     if (mimetype == NULL && (encoding==PT_ENCODED || encoding==QP_ENCODED)) {
754     mimetype = "text/plain";
755     }
756    
757 root 1.1 /*
758     * print sub-header
759     */
760    
761     fprintf (outfile, "MIME-Version: 1.0%s", eolstring);
762     fprintf (outfile, "Content-Type: %s%s",
763     (mimetype)?mimetype:"Application/Octet-Stream",
764     eolstring);
765     fprintf (outfile, "Content-Transfer-Encoding: %s%s",
766     CTE_TYPE(encoding), eolstring);
767     fprintf (outfile, "Content-Disposition: attachment; filename=\"%s\"%s",
768     UUFNameFilter ((outfname)?outfname:infname), eolstring);
769     fprintf (outfile, "%s", eolstring);
770    
771     /*
772     * for the first part of UU or XX messages, print a begin line
773     */
774     if (encoding == UU_ENCODED || encoding == XX_ENCODED) {
775     fprintf (outfile, "begin %o %s%s",
776     (themode) ? themode : ((filemode)?filemode:0644),
777     UUFNameFilter ((outfname)?outfname:infname), eolstring);
778     }
779     }
780    
781     /*
782     * update progress information
783     */
784    
785     progress.partno = partno;
786     progress.percent = 0;
787     progress.foffset = ftell (theifile);
788    
789     if (progress.totsize <= 0)
790     progress.fsize = -1;
791     else if (linperfile <= 0)
792     progress.fsize = progress.totsize;
793     else if (progress.foffset+linperfile*bpl[encoding] > progress.totsize)
794     progress.fsize = progress.totsize - progress.foffset;
795     else
796     progress.fsize = linperfile*bpl[encoding];
797    
798     progress.action = UUACT_ENCODING;
799    
800     if ((res = UUEncodeStream (outfile, theifile,
801     encoding, linperfile)) != UURET_OK) {
802     if (infile==NULL) fclose (theifile);
803     if (res != UURET_CANCEL) {
804     UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
805     uustring (S_ERR_ENCODING),
806     UUFNameFilter ((outfname)?outfname:infname),
807     (res==UURET_IOERR)?strerror(uu_errno):UUstrerror (res));
808     }
809     progress.action = 0;
810     return res;
811     }
812     /*
813     * print end line
814     */
815     if (feof (theifile) &&
816     (encoding == UU_ENCODED || encoding == XX_ENCODED)) {
817     fprintf (outfile, "%c%s",
818     (encoding==UU_ENCODED) ? UUEncodeTable[0] : XXEncodeTable[0],
819     eolstring);
820     fprintf (outfile, "end%s", eolstring);
821     }
822 root 1.2
823 root 1.1 /*
824     * empty line at end does no harm
825     */
826 root 1.2
827     if (encoding != PT_ENCODED && encoding != QP_ENCODED) {
828     fprintf (outfile, "%s", eolstring);
829     }
830 root 1.1
831     if (infile==NULL) {
832     if (res != UURET_OK) {
833     progress.action = 0;
834     fclose (theifile);
835     return res;
836     }
837     if (feof (theifile)) {
838     progress.action = 0;
839     fclose (theifile);
840     return UURET_OK;
841     }
842     return UURET_CONT;
843     }
844    
845     /*
846     * leave progress.action as-is
847     */
848    
849     return UURET_OK;
850     }
851    
852     /*
853     * send output to a stream, don't do any headers at all
854     */
855    
856     int UUEXPORT
857     UUEncodeToStream (FILE *outfile, FILE *infile,
858     char *infname, int encoding,
859     char *outfname, int filemode)
860     {
861     struct stat finfo;
862     FILE *theifile;
863     int themode;
864     int res;
865    
866     if (outfile==NULL ||
867     (infile == NULL&&infname==NULL) ||
868     (outfname==NULL&&infname==NULL) ||
869 root 1.2 (encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED&&
870     encoding!=PT_ENCODED&&encoding!=QP_ENCODED)) {
871 root 1.1 UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
872     uustring (S_PARM_CHECK), "UUEncodeToStream()");
873     return UURET_ILLVAL;
874     }
875    
876     progress.action = 0;
877    
878     if (infile==NULL) {
879     if (stat (infname, &finfo) == -1) {
880     UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
881     uustring (S_NOT_STAT_FILE),
882     infname, strerror (uu_errno=errno));
883     return UURET_IOERR;
884     }
885     if ((theifile = fopen (infname, "rb")) == NULL) {
886     UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
887     uustring (S_NOT_OPEN_FILE),
888     infname, strerror (uu_errno=errno));
889     return UURET_IOERR;
890     }
891     themode = (filemode) ? filemode : ((int) finfo.st_mode & 0777);
892     progress.fsize = (long) finfo.st_size;
893     }
894     else {
895     if (fstat (fileno (infile), &finfo) == -1) {
896     /* gotta live with it */
897     themode = 0644;
898     progress.fsize = -1;
899     }
900     else {
901     themode = (filemode) ? filemode : ((int) finfo.st_mode & 0777);
902     progress.fsize = (long) finfo.st_size;
903     }
904     theifile = infile;
905     }
906    
907     if (progress.fsize <= 0)
908     progress.fsize = -1;
909    
910 root 1.2.2.1 _FP_strncpy (progress.curfile, (outfname)?outfname:infname, 256);
911 root 1.1
912     progress.partno = 1;
913     progress.numparts = 1;
914     progress.percent = 0;
915     progress.foffset = 0;
916     progress.action = UUACT_ENCODING;
917    
918     if (encoding == UU_ENCODED || encoding == XX_ENCODED) {
919     fprintf (outfile, "begin %o %s%s",
920     (themode) ? themode : 0644,
921     UUFNameFilter ((outfname)?outfname:infname),
922     eolstring);
923     }
924     if ((res = UUEncodeStream (outfile, theifile, encoding, 0)) != UURET_OK) {
925     if (res != UURET_CANCEL) {
926     UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
927     uustring (S_ERR_ENCODING),
928     UUFNameFilter ((infname)?infname:outfname),
929     (res==UURET_IOERR)?strerror(uu_errno):UUstrerror (res));
930     }
931     progress.action = 0;
932     return res;
933     }
934     if (encoding == UU_ENCODED || encoding == XX_ENCODED) {
935     fprintf (outfile, "%c%s",
936     (encoding==UU_ENCODED) ? UUEncodeTable[0] : XXEncodeTable[0],
937     eolstring);
938     fprintf (outfile, "end%s", eolstring);
939     }
940     /*
941     * empty line at end does no harm
942     */
943     fprintf (outfile, "%s", eolstring);
944    
945     if (infile==NULL) fclose (theifile);
946     progress.action = 0;
947    
948     return UURET_OK;
949     }
950    
951     /*
952     * Encode to files on disk, don't generate any headers
953     */
954    
955     int UUEXPORT
956     UUEncodeToFile (FILE *infile, char *infname, int encoding,
957     char *outfname, char *diskname, long linperfile)
958     {
959     int part, numparts, len, filemode, res;
960     char *oname=NULL, *optr, *ptr;
961     FILE *theifile, *outfile;
962     struct stat finfo;
963    
964     if ((diskname==NULL&&infname==NULL) ||
965     (outfname==NULL&&infname==NULL) || (infile==NULL&&infname==NULL) ||
966 root 1.2 (encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED&&
967     encoding!=PT_ENCODED&&encoding!=QP_ENCODED)) {
968 root 1.1 UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
969     uustring (S_PARM_CHECK), "UUEncodeToFile()");
970     return UURET_ILLVAL;
971     }
972    
973     if (diskname) {
974     if ((ptr = strchr (diskname, '/')) == NULL)
975     ptr = strchr (diskname, '\\');
976     if (ptr) {
977     len = strlen (diskname) + ((uuencodeext)?strlen(uuencodeext):3) + 5;
978    
979     if ((oname = malloc (len)) == NULL) {
980     UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
981     uustring (S_OUT_OF_MEMORY), len);
982     return UURET_NOMEM;
983     }
984     sprintf (oname, "%s", diskname);
985     }
986     else {
987     len = ((uusavepath)?strlen(uusavepath):0) + strlen (diskname)
988     + ((uuencodeext)?strlen(uuencodeext):0) + 5;
989    
990     if ((oname = malloc (len)) == NULL) {
991     UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
992     uustring (S_OUT_OF_MEMORY), len);
993     return UURET_NOMEM;
994     }
995     sprintf (oname, "%s%s", (uusavepath)?uusavepath:"", diskname);
996     }
997     }
998     else {
999     len = ((uusavepath) ? strlen (uusavepath) : 0) +
1000     strlen(UUFNameFilter(infname)) +
1001     ((uuencodeext)?strlen(uuencodeext):0) + 5;
1002    
1003     if ((oname = malloc (len)) == NULL) {
1004     UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
1005     uustring (S_OUT_OF_MEMORY), len);
1006     return UURET_NOMEM;
1007     }
1008     optr = UUFNameFilter (infname);
1009     sprintf (oname, "%s%s",
1010     (uusavepath)?uusavepath:"",
1011     (*optr=='.')?optr+1:optr);
1012     }
1013    
1014     /*
1015     * optr points after the last dot, so that we can print the part number
1016     * there.
1017     */
1018    
1019 root 1.2.2.1 optr = _FP_strrchr (oname, '.');
1020 root 1.1 if (optr==NULL || strchr (optr, '/')!=NULL || strchr (optr, '\\')!=NULL) {
1021     optr = oname + strlen (oname);
1022     *optr++ = '.';
1023     }
1024     else if (optr==oname || *(optr-1)=='/' || *(optr-1)=='\\') {
1025     optr = oname + strlen (oname);
1026     *optr++ = '.';
1027     }
1028     else
1029     optr++;
1030    
1031     progress.action = 0;
1032    
1033     if (infile==NULL) {
1034     if (stat (infname, &finfo) == -1) {
1035     UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
1036     uustring (S_NOT_STAT_FILE),
1037     infname, strerror (uu_errno=errno));
1038 root 1.2.2.1 _FP_free (oname);
1039 root 1.1 return UURET_IOERR;
1040     }
1041     if ((theifile = fopen (infname, "rb")) == NULL) {
1042     UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
1043     uustring (S_NOT_OPEN_FILE),
1044     infname, strerror (uu_errno=errno));
1045 root 1.2.2.1 _FP_free (oname);
1046 root 1.1 return UURET_IOERR;
1047     }
1048     if (linperfile <= 0)
1049     numparts = 1;
1050     else
1051     numparts = (int) (((long)finfo.st_size + (linperfile*bpl[encoding]-1)) /
1052     (linperfile*bpl[encoding]));
1053    
1054     filemode = (int) finfo.st_mode & 0777;
1055     progress.totsize = (long) finfo.st_size;
1056     }
1057     else {
1058     if (fstat (fileno (infile), &finfo) == -1) {
1059     /* gotta live with it */
1060     filemode = 0644;
1061     numparts = -1;
1062     progress.totsize = -1;
1063     }
1064     else {
1065     if (linperfile <= 0)
1066     numparts = 1;
1067     else
1068     numparts = (int) (((long)finfo.st_size+(linperfile*bpl[encoding]-1))/
1069     (linperfile*bpl[encoding]));
1070    
1071     filemode = (int) finfo.st_mode & 0777;
1072     progress.totsize = -1;
1073     }
1074     theifile = infile;
1075     }
1076    
1077 root 1.2.2.1 _FP_strncpy (progress.curfile, (outfname)?outfname:infname, 256);
1078 root 1.1
1079     progress.totsize = (progress.totsize<=0) ? -1 : progress.totsize;
1080     progress.numparts = numparts;
1081    
1082     for (part=1; !feof (theifile); part++) {
1083     /*
1084     * Attach extension
1085     */
1086     if (progress.numparts==1 && progress.totsize!=-1 && uuencodeext!=NULL)
1087     strcpy (optr, uuencodeext);
1088     else
1089     sprintf (optr, "%03d", part);
1090    
1091     /*
1092     * check if target file exists
1093     */
1094    
1095     if (!uu_overwrite) {
1096     if (stat (oname, &finfo) == 0) {
1097     UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
1098     uustring (S_TARGET_EXISTS), oname);
1099     if (infile==NULL) fclose (theifile);
1100     progress.action = 0;
1101     free (oname);
1102     return UURET_EXISTS;
1103     }
1104     }
1105    
1106     /*
1107     * update progress information
1108     */
1109    
1110     progress.action = 0;
1111     progress.partno = part;
1112     progress.percent = 0;
1113     progress.foffset = ftell (theifile);
1114    
1115     if (progress.totsize == -1)
1116     progress.fsize = -1;
1117     else if (linperfile <= 0)
1118     progress.fsize = progress.totsize;
1119     else if (progress.foffset+linperfile*bpl[encoding] > progress.totsize)
1120     progress.fsize = progress.totsize - progress.foffset;
1121     else
1122     progress.fsize = linperfile*bpl[encoding];
1123    
1124     progress.action = UUACT_ENCODING;
1125    
1126     if ((outfile = fopen (oname, "w")) == NULL) {
1127     UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
1128     uustring (S_NOT_OPEN_TARGET),
1129     oname, strerror (uu_errno = errno));
1130     if (infile==NULL) fclose (theifile);
1131     progress.action = 0;
1132     free (oname);
1133     return UURET_IOERR;
1134     }
1135     fprintf (outfile, "%s", eolstring);
1136     fprintf (outfile, "_=_ %s", eolstring);
1137     if (numparts == -1)
1138     fprintf (outfile, "_=_ Part %03d of file %s%s",
1139     part, UUFNameFilter ((outfname)?outfname:infname),
1140     eolstring);
1141     else
1142     fprintf (outfile, "_=_ Part %03d of %03d of file %s%s",
1143     part, numparts,
1144     UUFNameFilter ((outfname)?outfname:infname),
1145     eolstring);
1146     fprintf (outfile, "_=_ %s", eolstring);
1147     fprintf (outfile, "%s", eolstring);
1148    
1149     if (part==1 && (encoding == UU_ENCODED || encoding == XX_ENCODED)) {
1150     fprintf (outfile, "begin %o %s%s",
1151     (filemode)?filemode : 0644,
1152     UUFNameFilter ((outfname)?outfname:infname),
1153     eolstring);
1154     }
1155     if ((res = UUEncodeStream (outfile, theifile,
1156     encoding, linperfile)) != UURET_OK) {
1157     if (res != UURET_CANCEL) {
1158     UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
1159     uustring (S_ERR_ENCODING),
1160     UUFNameFilter ((infname)?infname:outfname),
1161     (res==UURET_IOERR)?strerror(uu_errno):UUstrerror (res));
1162     }
1163     if (infile==NULL) fclose (theifile);
1164     progress.action = 0;
1165     fclose (outfile);
1166     unlink (oname);
1167 root 1.2.2.1 _FP_free (oname);
1168 root 1.1 return res;
1169     }
1170     if (feof (theifile) &&
1171     (encoding == UU_ENCODED || encoding == XX_ENCODED)) {
1172     fprintf (outfile, "%c%s",
1173     (encoding==UU_ENCODED) ? UUEncodeTable[0] : XXEncodeTable[0],
1174     eolstring);
1175     fprintf (outfile, "end%s", eolstring);
1176     }
1177     /*
1178     * empty line at end does no harm
1179     */
1180     fprintf (outfile, "%s", eolstring);
1181     fclose (outfile);
1182     }
1183     if (infile==NULL) fclose (theifile);
1184     progress.action = 0;
1185 root 1.2.2.1 _FP_free (oname);
1186 root 1.1 return UURET_OK;
1187     }
1188    
1189     /*
1190     * Encode a MIME Mail message or Newsgroup posting and send to a
1191     * stream. Still needs a somewhat smart MDA, since we only gene-
1192     * rate a minimum set of headers.
1193     */
1194    
1195     int UUEXPORT
1196     UUE_PrepSingle (FILE *outfile, FILE *infile,
1197     char *infname, int encoding,
1198     char *outfname, int filemode,
1199     char *destination, char *from,
1200     char *subject, int isemail)
1201     {
1202 root 1.2 return UUE_PrepSingleExt (outfile, infile,
1203     infname, encoding,
1204     outfname, filemode,
1205     destination, from,
1206     subject, NULL,
1207     isemail);
1208     }
1209    
1210     int UUEXPORT
1211     UUE_PrepSingleExt (FILE *outfile, FILE *infile,
1212     char *infname, int encoding,
1213     char *outfname, int filemode,
1214     char *destination, char *from,
1215     char *subject, char *replyto,
1216     int isemail)
1217     {
1218 root 1.1 mimemap *miter=mimetable;
1219     char *subline, *oname;
1220     char *mimetype, *ptr;
1221     int res, len;
1222    
1223     if ((outfname==NULL&&infname==NULL) || (infile==NULL&&infname==NULL) ||
1224 root 1.2 (encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED&&
1225     encoding!=PT_ENCODED&&encoding!=QP_ENCODED)) {
1226 root 1.1 UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
1227     uustring (S_PARM_CHECK), "UUE_PrepSingle()");
1228     return UURET_ILLVAL;
1229     }
1230    
1231     oname = UUFNameFilter ((outfname)?outfname:infname);
1232     len = ((subject)?strlen(subject):0) + strlen(oname) + 40;
1233    
1234 root 1.2.2.1 if ((ptr = _FP_strrchr (oname, '.'))) {
1235     while (miter->extension && _FP_stricmp (ptr+1, miter->extension) != 0)
1236 root 1.1 miter++;
1237     mimetype = miter->mimetype;
1238     }
1239     else
1240     mimetype = NULL;
1241    
1242 root 1.2 if (mimetype == NULL && (encoding == PT_ENCODED || encoding == QP_ENCODED)) {
1243     mimetype = "text/plain";
1244     }
1245    
1246 root 1.1 if ((subline = (char *) malloc (len)) == NULL) {
1247     UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
1248     uustring (S_OUT_OF_MEMORY), len);
1249     return UURET_NOMEM;
1250     }
1251    
1252     if (subject)
1253     sprintf (subline, "%s (001/001) - [ %s ]", subject, oname);
1254     else
1255     sprintf (subline, "[ %s ] (001/001)", oname);
1256    
1257     if (from) {
1258     fprintf (outfile, "From: %s%s", from, eolstring);
1259     }
1260     if (destination) {
1261     fprintf (outfile, "%s: %s%s",
1262     (isemail)?"To":"Newsgroups",
1263     destination, eolstring);
1264     }
1265 root 1.2
1266     fprintf (outfile, "Subject: %s%s", subline, eolstring);
1267    
1268     if (replyto) {
1269     fprintf (outfile, "Reply-To: %s%s", replyto, eolstring);
1270     }
1271    
1272 root 1.1 fprintf (outfile, "MIME-Version: 1.0%s", eolstring);
1273     fprintf (outfile, "Content-Type: %s; name=\"%s\"%s",
1274     (mimetype)?mimetype:"Application/Octet-Stream",
1275     UUFNameFilter ((outfname)?outfname:infname),
1276     eolstring);
1277     fprintf (outfile, "Content-Transfer-Encoding: %s%s",
1278     CTE_TYPE(encoding), eolstring);
1279     fprintf (outfile, "%s", eolstring);
1280    
1281     res = UUEncodeToStream (outfile, infile, infname, encoding,
1282     outfname, filemode);
1283    
1284 root 1.2.2.1 _FP_free (subline);
1285 root 1.1 return res;
1286     }
1287    
1288     int UUEXPORT
1289     UUE_PrepPartial (FILE *outfile, FILE *infile,
1290     char *infname, int encoding,
1291     char *outfname, int filemode,
1292     int partno, long linperfile, long filesize,
1293     char *destination, char *from, char *subject,
1294     int isemail)
1295     {
1296 root 1.2 return UUE_PrepPartialExt (outfile, infile,
1297     infname, encoding,
1298     outfname, filemode,
1299     partno, linperfile, filesize,
1300     destination,
1301     from, subject, NULL,
1302     isemail);
1303     }
1304    
1305     int UUEXPORT
1306     UUE_PrepPartialExt (FILE *outfile, FILE *infile,
1307     char *infname, int encoding,
1308     char *outfname, int filemode,
1309     int partno, long linperfile, long filesize,
1310     char *destination,
1311     char *from, char *subject, char *replyto,
1312     int isemail)
1313     {
1314 root 1.1 static int numparts, themode;
1315     static char mimeid[64];
1316     static FILE *theifile;
1317     struct stat finfo;
1318     char *subline, *oname;
1319     long thesize;
1320     int res, len;
1321    
1322     if ((outfname==NULL&&infname==NULL) || (infile==NULL&&infname==NULL) ||
1323 root 1.2 (encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED&&
1324     encoding!=PT_ENCODED&&encoding!=QP_ENCODED)) {
1325 root 1.1 UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
1326     uustring (S_PARM_CHECK), "UUE_PrepPartial()");
1327     return UURET_ILLVAL;
1328     }
1329    
1330     oname = UUFNameFilter ((outfname)?outfname:infname);
1331     len = ((subject)?strlen(subject):0) + strlen (oname) + 40;
1332    
1333     /*
1334     * if first part, get information about the file
1335     */
1336     if (partno == 1) {
1337     if (infile==NULL) {
1338     if (stat (infname, &finfo) == -1) {
1339     UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
1340     uustring (S_NOT_STAT_FILE),
1341     infname, strerror (uu_errno=errno));
1342     return UURET_IOERR;
1343     }
1344     if ((theifile = fopen (infname, "rb")) == NULL) {
1345     UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
1346     uustring (S_NOT_OPEN_FILE),
1347     infname, strerror (uu_errno=errno));
1348     return UURET_IOERR;
1349     }
1350     if (linperfile <= 0)
1351     numparts = 1;
1352     else
1353     numparts = (int) (((long)finfo.st_size+(linperfile*bpl[encoding]-1))/
1354     (linperfile*bpl[encoding]));
1355    
1356     themode = (filemode) ? filemode : ((int) finfo.st_mode & 0777);
1357     thesize = (long) finfo.st_size;
1358     }
1359     else {
1360     if (fstat (fileno (infile), &finfo) != 0) {
1361     if (filesize <= 0) {
1362     UUMessage (uuencode_id, __LINE__, UUMSG_WARNING,
1363     uustring (S_STAT_ONE_PART));
1364     numparts = 1;
1365     themode = (filemode)?filemode:0644;
1366     thesize = 0;
1367     }
1368     else {
1369     if (linperfile <= 0)
1370     numparts = 1;
1371     else
1372     numparts = (int) ((filesize+(linperfile*bpl[encoding]-1))/
1373     (linperfile*bpl[encoding]));
1374    
1375     themode = (filemode)?filemode:0644;
1376     thesize = filesize;
1377     }
1378     }
1379     else {
1380     if (linperfile <= 0)
1381     numparts = 1;
1382     else
1383     numparts = (int) (((long)finfo.st_size+(linperfile*bpl[encoding]-1))/
1384     (linperfile*bpl[encoding]));
1385    
1386     filemode = (int) finfo.st_mode & 0777;
1387     thesize = (long) finfo.st_size;
1388     }
1389     theifile = infile;
1390     }
1391     /*
1392     * if there's one part only, don't use Message/Partial
1393     */
1394    
1395     if (numparts == 1) {
1396     if (infile==NULL) fclose (theifile);
1397 root 1.2 return UUE_PrepSingleExt (outfile, infile, infname, encoding,
1398     outfname, filemode, destination,
1399     from, subject, replyto, isemail);
1400 root 1.1 }
1401    
1402     /*
1403     * we also need a unique ID
1404     */
1405     sprintf (mimeid, "UUDV-%ld.%ld.%s",
1406     (long) time(NULL), thesize,
1407     (strlen(oname)>16)?"oops":oname);
1408     }
1409    
1410     if ((subline = (char *) malloc (len)) == NULL) {
1411     UUMessage (uuencode_id, __LINE__, UUMSG_ERROR,
1412     uustring (S_OUT_OF_MEMORY), len);
1413     if (infile==NULL) fclose (theifile);
1414     return UURET_NOMEM;
1415     }
1416    
1417     if (subject)
1418     sprintf (subline, "%s (%03d/%03d) - [ %s ]",
1419     subject, partno, numparts, oname);
1420     else
1421     sprintf (subline, "[ %s ] (%03d/%03d)",
1422     oname, partno, numparts);
1423    
1424     if (from) {
1425     fprintf (outfile, "From: %s%s", from, eolstring);
1426     }
1427 root 1.2
1428 root 1.1 if (destination) {
1429     fprintf (outfile, "%s: %s%s",
1430     (isemail)?"To":"Newsgroups",
1431     destination, eolstring);
1432     }
1433 root 1.2
1434     fprintf (outfile, "Subject: %s%s", subline, eolstring);
1435    
1436     if (replyto) {
1437     fprintf (outfile, "Reply-To: %s%s", replyto, eolstring);
1438     }
1439    
1440 root 1.1 fprintf (outfile, "MIME-Version: 1.0%s", eolstring);
1441     fprintf (outfile, "Content-Type: Message/Partial; number=%d; total=%d;%s",
1442     partno, numparts, eolstring);
1443     fprintf (outfile, "\tid=\"%s\"%s",
1444     mimeid, eolstring);
1445     fprintf (outfile, "%s", eolstring);
1446    
1447     res = UUEncodePartial (outfile, theifile,
1448     infname, encoding,
1449     (outfname)?outfname:infname, NULL,
1450     themode, partno, linperfile);
1451    
1452 root 1.2.2.1 _FP_free (subline);
1453 root 1.1
1454     if (infile==NULL) {
1455     if (res != UURET_OK) {
1456     fclose (theifile);
1457     return res;
1458     }
1459     if (feof (theifile)) {
1460     fclose (theifile);
1461     return UURET_OK;
1462     }
1463     return UURET_CONT;
1464     }
1465    
1466     return res;
1467     }