README.unix | 2 +- codes.c | 2 +- decode.c | 34 ++++++++++++++++++++++++++++++---- encode.c | 22 +++++++++++++--------- magic.c | 1 + md5.h | 6 ++++-- mkreadme.pl | 2 +- part.c | 9 ++++----- unixos.c | 29 +++++++++++++++++++++-------- unixpk.c | 25 +++++++++++++++++-------- unixpk.man | 15 ++++++++++++++- unixunpk.c | 10 ++++++---- unixunpk.man | 4 ++-- uudecode.c | 27 ++++++++++++++++++++++----- xmalloc.c | 6 +++--- 15 files changed, 140 insertions(+), 54 deletions(-) diff --git a/README.unix b/README.unix index d7a762c..c26b7c8 100644 --- a/README.unix +++ b/README.unix @@ -188,7 +188,7 @@ The environment variables which control munpack's behavior are: TMPDIR Root of directory to store partial messages awaiting - reassembly. Default is "/usr/tmp". Partial messages + reassembly. Default is "/var/tmp". Partial messages are stored in subdirectories of $TMPDIR/m-prts-$USER/ diff --git a/codes.c b/codes.c index 8e7362f..8d98559 100644 --- a/codes.c +++ b/codes.c @@ -128,7 +128,7 @@ char *md5digest(FILE *infile, long int *len) int nbytes; MD5Init(&context); - while (nbytes = fread(buf, 1, sizeof(buf), infile)) { + while ((nbytes = fread(buf, 1, sizeof(buf), infile))) { length += nbytes; MD5Update(&context, buf, nbytes); } diff --git a/decode.c b/decode.c index c96918f..17ba9a4 100644 --- a/decode.c +++ b/decode.c @@ -26,8 +26,10 @@ * SOFTWARE. */ #include +#include #include #include +#include #include "xmalloc.h" #include "common.h" #include "part.h" @@ -37,6 +39,19 @@ extern char *os_idtodir(char *id); extern FILE *os_newtypedfile(char *fname, char *contentType, int flags, params contentParams); extern FILE *os_createnewfile(char *fname); extern char *md5contextTo64(MD5_CTX *context); +extern void warn(char *s); +extern void os_perror(char *str); +extern void chat(char *s); +extern void os_donewithdir(char *dir); +extern void os_warnMD5mismatch(void); +extern void os_closetypedfile(FILE *outfile); + +extern int part_depth(struct part *part); +extern void part_ungets(char *s, struct part *part); +extern void part_close(struct part *part); +extern int part_fill(struct part *part); +extern void part_addboundary(struct part *part, char *boundary); +extern int part_readboundary(struct part *part); /* The possible content transfer encodings */ enum encoding { enc_none, enc_qp, enc_base64 }; @@ -49,6 +64,17 @@ char *getDispositionFilename(char *disposition); void from64(struct part *inpart, FILE *outfile, char **digestp, int suppressCR); void fromqp(struct part *inpart, FILE *outfile, char **digestp); void fromnone(struct part *inpart, FILE *outfile, char **digestp); +int handlePartial(struct part *inpart, char *headers, params contentParams, + int extractText); +int ignoreMessage(struct part *inpart); +int handleMultipart(struct part *inpart, char *contentType, + params contentParams, int extractText); +int handleUuencode(struct part *inpart, char *subject, int extractText); +int handleText(struct part *inpart, enum encoding contentEncoding); +int saveToFile(struct part *inpart, int inAppleDouble, char *contentType, + params contentParams, enum encoding contentEncoding, + char *contentDisposition, char *contentMD5); + /* * Read and handle an RFC 822 message from the body-part 'inpart'. */ @@ -545,8 +571,8 @@ getDispositionFilename(char *disposition) SkipWhitespace(&disposition); if (!disposition) return 0; - /* If we're looking at a ";", we found what we're looking for */ - if (*disposition++ == ';') break; + /* If we're looking at a "=", we found what we're looking for */ + if (*disposition++ == '=') break; } SkipWhitespace(&disposition); @@ -624,7 +650,7 @@ int handlePartial(struct part *inpart, char *headers, params contentParams, int } thispart = atoi(p); - if (p = getParam(contentParams, "total")) { + if ((p = getParam(contentParams, "total"))) { nparts = atoi(p); if (nparts <= 0) { warn("partial message has invalid number of parts"); @@ -643,7 +669,7 @@ int handlePartial(struct part *inpart, char *headers, params contentParams, int else { /* Try to retrieve number of parts from reassembly directory */ sprintf(buf, "%sCT", dir); - if (partfile = fopen(buf, "r")) { + if ((partfile = fopen(buf, "r"))) { if (fgets(buf, sizeof(buf), partfile)) { nparts = atoi(buf); if (nparts < 0) nparts = 0; diff --git a/encode.c b/encode.c index 0ba3934..f5e552c 100644 --- a/encode.c +++ b/encode.c @@ -23,14 +23,18 @@ * SOFTWARE. */ #include +#include #include extern char *magic_look(FILE *infile); extern char *os_genid(void); extern FILE *os_createnewfile(char *fname); extern char *md5digest(FILE *infile, long int *len); +extern void os_perror(char *str); +extern int to64(FILE *infile, FILE *outfile, long int limit); #define NUMREFERENCES 4 +int attachment; /* * Encode a file into one or more MIME messages, each @@ -43,7 +47,7 @@ int encode(FILE *infile, FILE *applefile, char *fname, FILE *descfile, char *sub char *type; FILE *outfile; char *cleanfname, *p; - char *digest, *appledigest; + char *digest, *appledigest = NULL; long filesize, l, written; int thispart, numparts = 1; int wrotefiletype = 0; @@ -57,12 +61,12 @@ int encode(FILE *infile, FILE *applefile, char *fname, FILE *descfile, char *sub /* This filename-cleaning knowledge will probably * be moved to the os layer in a future version. */ - if (p = strrchr(cleanfname, '.')) cleanfname = p+1; + if ((p = strrchr(cleanfname, '.'))) cleanfname = p+1; #else - if (p = strrchr(cleanfname, '/')) cleanfname = p+1; - if (p = strrchr(cleanfname, '\\')) cleanfname = p+1; + if ((p = strrchr(cleanfname, '/'))) cleanfname = p+1; + if ((p = strrchr(cleanfname, '\\'))) cleanfname = p+1; #endif - if (p = strrchr(cleanfname, ':')) cleanfname = p+1; + if ((p = strrchr(cleanfname, ':'))) cleanfname = p+1; /* Find file type */ if (typeoverride) { @@ -189,8 +193,8 @@ int encode(FILE *infile, FILE *applefile, char *fname, FILE *descfile, char *sub "Content-Type: multipart/appledouble; boundary=\"=\"; name=\"%s\"\n", cleanfname); fprintf(outfile, - "Content-Disposition: inline; filename=\"%s\"\n", - cleanfname); + "Content-Disposition: %s; filename=\"%s\"\n", + attachment ? "attachment" : "inline", cleanfname); fprintf(outfile, "\n\n--=\n"); fprintf(outfile, "Content-Type: application/applefile\n"); fprintf(outfile, "Content-Transfer-Encoding: base64\n"); @@ -219,8 +223,8 @@ int encode(FILE *infile, FILE *applefile, char *fname, FILE *descfile, char *sub fprintf(outfile, "Content-Type: %s; name=\"%s\"\n", type, cleanfname); fprintf(outfile, "Content-Transfer-Encoding: base64\n"); - fprintf(outfile, "Content-Disposition: inline; filename=\"%s\"\n", - cleanfname); + fprintf(outfile, "Content-Disposition: %s; filename=\"%s\"\n", + attachment ? "attachment" : "inline", cleanfname); fprintf(outfile, "Content-MD5: %s\n\n", digest); free(digest); written += 80; diff --git a/magic.c b/magic.c index e08c6f8..a452a43 100644 --- a/magic.c +++ b/magic.c @@ -23,6 +23,7 @@ * SOFTWARE. */ #include +#include /* Description of the various file formats and their magic numbers */ struct magic { diff --git a/md5.h b/md5.h index fcb1a12..060c5fb 100644 --- a/md5.h +++ b/md5.h @@ -34,14 +34,16 @@ The following makes PROTOTYPES default to 0 if it has not already #define PROTOTYPES 0 #endif +#include + /* POINTER defines a generic pointer type */ typedef unsigned char *POINTER; /* UINT2 defines a two byte word */ -typedef unsigned short int UINT2; +typedef uint16_t UINT2; /* UINT4 defines a four byte word */ -typedef unsigned long int UINT4; +typedef uint32_t UINT4; /* PROTO_LIST is defined depending on how PROTOTYPES is defined above. If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it diff --git a/mkreadme.pl b/mkreadme.pl index a45117b..22e4e81 100755 --- a/mkreadme.pl +++ b/mkreadme.pl @@ -413,7 +413,7 @@ The environment variables which control munpack's behavior are: =unix TMPDIR Root of directory to store partial messages awaiting - reassembly. Default is "/usr/tmp". Partial messages + reassembly. Default is "/var/tmp". Partial messages are stored in subdirectories of $TMPDIR/m-prts-$USER/ =pc os2 diff --git a/part.c b/part.c index 1d4efe6..7abd86c 100644 --- a/part.c +++ b/part.c @@ -27,6 +27,7 @@ */ #include +#include #include #include "part.h" @@ -58,7 +59,7 @@ struct part *part_init(FILE *infile) /* * Close and free 'part'. */ -int part_close(struct part *part) +void part_close(struct part *part) { fclose(part->infile); if (part->buf) free(part->buf); @@ -77,8 +78,7 @@ part_depth(struct part *part) /* * Add to 'part' the multipart boundary 'boundary'. */ -int -part_addboundary(struct part *part, char *boundary) +void part_addboundary(struct part *part, char *boundary) { /* Grow boundary array if necessary */ if (part->boundary_num == part->boundary_alloc) { @@ -165,8 +165,7 @@ part_gets(char *s, int n, struct part *part) * Leaves room in the input buffer to push back an additional single * character using the prot_ungetc() macro. */ -int -part_ungets(char *s, struct part *part) +void part_ungets(char *s, struct part *part) { int len = strlen(s); int i; diff --git a/unixos.c b/unixos.c index 243a7be..22a1080 100644 --- a/unixos.c +++ b/unixos.c @@ -23,24 +23,30 @@ * SOFTWARE. */ #include +#include #include #include #include #include +#include #include +#include #include #include +#include #include "xmalloc.h" #include "common.h" #include "part.h" +extern void warn(char *s); + #ifndef MAXHOSTNAMELEN #define MAXHOSTNAMELEN 64 #endif +#ifndef errno extern int errno; -extern char *malloc(); -extern char *getenv(); +#endif int overwrite_files = 0; int didchat; @@ -76,7 +82,7 @@ char *os_genid(void) } result = malloc(25+strlen(hostname)); - sprintf(result, "%d.%d@%s", pid, curtime++, hostname); + sprintf(result, "%d.%lu@%s", pid, (unsigned long) curtime++, hostname); return result; } @@ -90,7 +96,7 @@ char *os_idtodir(char *id) strcpy(buf, getenv("TMPDIR")); } else { - strcpy(buf, "/usr/tmp"); + strcpy(buf, "/var/tmp"); } strcat(buf, "/m-prts-"); p = getenv("USER"); @@ -137,7 +143,14 @@ FILE *os_createnewfile(char *fname) FILE *ret; #ifdef O_EXCL - fd=open(fname, O_RDWR|O_CREAT|O_EXCL, 0644); + struct stat statbuf; + + if ((stat(fname, &statbuf) == 0) && (S_ISCHR(statbuf.st_mode))) { + fd=open(fname, O_RDWR); + } + else { + fd=open(fname, O_RDWR|O_CREAT|O_EXCL, 0644); + } #else fd=open(fname, O_RDWR|O_CREAT|O_TRUNC, 0644); #endif @@ -194,7 +207,7 @@ FILE *os_newtypedfile(char *fname, char *contentType, int flags, params contentP do { if (outfile) fclose(outfile); sprintf(buf, "part%d", ++filesuffix); - } while (outfile = fopen(buf, "r")); + } while ((outfile = fopen(buf, "r"))); fname = buf; } else if (!overwrite_files && (outfile = fopen(fname, "r"))) { @@ -202,7 +215,7 @@ FILE *os_newtypedfile(char *fname, char *contentType, int flags, params contentP fclose(outfile); sprintf(buf, "%s.%d", fname, ++filesuffix); - } while (outfile = fopen(buf, "r")); + } while ((outfile = fopen(buf, "r"))); fname = buf; } @@ -228,7 +241,7 @@ FILE *os_newtypedfile(char *fname, char *contentType, int flags, params contentP p = strchr(descfname, '/'); if (!p) p = descfname; - if (p = strrchr(p, '.')) *p = '\0'; + if ((p = strrchr(p, '.'))) *p = '\0'; strcat(descfname, ".desc"); (void) rename(TEMPFILENAME, descfname); diff --git a/unixpk.c b/unixpk.c index 144e34d..e519b44 100644 --- a/unixpk.c +++ b/unixpk.c @@ -23,23 +23,28 @@ * SOFTWARE. */ #include +#include #include #include +#include +#include +#include +#include #include "common.h" #include "version.h" #include "xmalloc.h" #define MAXADDRESS 100 -extern char *getenv(); - -extern int errno; -extern int optind; -extern char *optarg; +extern int attachment; void usage(void); void sendmail(FILE *infile, char **addr, int start); void inews(FILE *infile); +void os_perror(char *str); +int encode(FILE *infile, FILE *applefile, char *fname, FILE *descfile, + char *subject, char *headers, long int maxsize, + char *typeoverride, char *outfname); int main(int argc, char **argv) { @@ -64,7 +69,7 @@ int main(int argc, char **argv) maxsize = atoi(p); } - while ((opt = getopt(argc, argv, "s:d:m:c:o:n:")) != EOF) { + while ((opt = getopt(argc, argv, "as:d:m:c:o:n:")) != EOF) { switch (opt) { case 's': subject = optarg; @@ -90,6 +95,10 @@ int main(int argc, char **argv) newsgroups = optarg; break; + case 'a': + attachment = 1; + break; + default: usage(); @@ -155,7 +164,7 @@ int main(int argc, char **argv) fprintf(stderr, "A subject is required\n"); usage(); } - if (p = strchr(sbuf, '\n')) *p = '\0'; + if ((p = strchr(sbuf, '\n'))) *p = '\0'; subject = sbuf; } @@ -164,7 +173,7 @@ int main(int argc, char **argv) strcpy(fnamebuf, getenv("TMPDIR")); } else { - strcpy(fnamebuf, "/usr/tmp"); + strcpy(fnamebuf, "/var/tmp"); } strcat(fnamebuf, "/mpackXXXXXX"); mktemp(fnamebuf); diff --git a/unixpk.man b/unixpk.man index de251ee..30b1296 100644 --- a/unixpk.man +++ b/unixpk.man @@ -4,6 +4,9 @@ mpack \- pack a file in MIME format .SH SYNOPSIS .B mpack [ +.B \-a +] +[ .B \-s .I subject ] @@ -24,6 +27,9 @@ mpack \- pack a file in MIME format .br .B mpack [ +.B \-a +] +[ .B \-s .I subject ] @@ -45,6 +51,9 @@ mpack \- pack a file in MIME format .br .B mpack [ +.B \-a +] +[ .B \-s .I subject ] @@ -74,6 +83,10 @@ newsgroups. .PP .SH OPTIONS .TP +.BI \-a +Set the Content-Disposition to attachment. If \-a is not used +the Content-Disposition is inline. +.TP .BI \-s " subject" Set the .B Subject @@ -136,7 +149,7 @@ Mail the generated messages to the specified addresses. .SH ENVIRONMENT .TP .B TMPDIR -Directory to store temporary files. Default is /usr/tmp. +Directory to store temporary files. Default is /var/tmp. .TP .B SPLITSIZE Default value of the -m switch. diff --git a/unixunpk.c b/unixunpk.c index a1f065b..e58882d 100644 --- a/unixunpk.c +++ b/unixunpk.c @@ -23,17 +23,19 @@ * SOFTWARE. */ #include +#include +#include +#include #include "version.h" #include "part.h" -extern int optind; -extern char *optarg; - extern int overwrite_files; extern int didchat; int quiet; void usage(void); +int handleMessage(struct part *inpart, char *defaultContentType, + int inAppleDouble, int extractText); int main(int argc, char **argv) { @@ -100,7 +102,7 @@ int main(int argc, char **argv) void usage(void) { fprintf(stderr, "munpack version %s\n", MPACK_VERSION); - fprintf(stderr, "usage: munpack [-f] [-q] [-C directory] [files...]\n"); + fprintf(stderr, "usage: munpack [-f] [-q] [-t] [-C directory] [files...]\n"); exit(1); } diff --git a/unixunpk.man b/unixunpk.man index da384b1..459fc0c 100644 --- a/unixunpk.man +++ b/unixunpk.man @@ -50,7 +50,7 @@ munpack appends ".1", ".2", etc to find a nonexistent file. .TP .B \-q -Be quiet. Supresses messages about saving partial messages and about +Be quiet. Suppresses messages about saving partial messages and about messages with no interesting information. .TP .B \-t @@ -107,7 +107,7 @@ see the section "OPTIONS" above. .SH ENVIRONMENT .TP .B TMPDIR -Directory to store temporary files. Default is /usr/tmp. +Directory to store temporary files. Default is /var/tmp. .SH FILES .TP .B $TMPDIR/m-prts-$USER/ diff --git a/uudecode.c b/uudecode.c index 295241b..e830a19 100644 --- a/uudecode.c +++ b/uudecode.c @@ -23,8 +23,10 @@ * SOFTWARE. */ #include +#include #include #include +#include #include "xmalloc.h" #include "common.h" #include "part.h" @@ -32,9 +34,25 @@ extern char *os_idtodir(char *id); extern FILE *os_newtypedfile(char *fname, char *contentType, int flags, params contentParams); extern FILE *os_createnewfile(char *fname); +extern int os_binhex(struct part *inpart, int part, int nparts); +extern void os_closetypedfile(FILE *outfile); +extern void os_donewithdir(char *dir); +extern void os_perror(char *str); +extern void chat(char *s); + +extern void part_ungets(char *s, struct part *part); +extern void part_close(struct part *part); +extern int handleMessage(struct part *inpart, char *defaultContentType, + int inAppleDouble, int extractText); static FILE *startDescFile(char *fname); +static void uudecodeline(char *line, FILE *outfile); +int parseSubject(char *subject, char **fnamep, int *partp, int *npartsp); +int saveUuFile(struct part *inpart, char *fname, int part, int nparts, + char *firstline); +int descEnd(char *line); +int uudecodefiles(char *dir, int nparts); /* Length of a normal uuencoded line, including newline */ #define UULENGTH 62 @@ -266,7 +284,7 @@ int handleUuencode(struct part *inpart, char *subject, int extractText) } else if (part == 1 && fname && !descfile && !strncasecmp(buf, "x-file-desc: ", 13)) { - if (descfile = startDescFile(fname)) { + if ((descfile = startDescFile(fname))) { fputs(buf+13, descfile); fclose(descfile); descfile = 0; @@ -454,7 +472,7 @@ saveUuFile(struct part *inpart, char *fname, int part, int nparts, char *firstli /* Retrieve any previously saved number of the last part */ if (nparts == 0) { sprintf(buf, "%sCT", dir); - if (partfile = fopen(buf, "r")) { + if ((partfile = fopen(buf, "r"))) { if (fgets(buf, sizeof(buf), partfile)) { nparts = atoi(buf); if (nparts < 0) nparts = 0; @@ -722,7 +740,7 @@ uudecodefiles(char *dir, int nparts) if (!*fname) return 1; /* Guess the content-type of common filename extensions */ - if (p = strrchr(fname, '.')) { + if ((p = strrchr(fname, '.'))) { if (!strcasecmp(p, ".gif")) contentType = "image/gif"; if (!strcasecmp(p, ".jpg")) contentType = "image/jpeg"; if (!strcasecmp(p, ".jpeg")) contentType = "image/jpeg"; @@ -826,7 +844,7 @@ uudecodefiles(char *dir, int nparts) /* * Decode a uuencoded line to 'outfile' */ -int uudecodeline(char *line, FILE *outfile) +static void uudecodeline(char *line, FILE *outfile) { int c, len; @@ -845,7 +863,6 @@ int uudecodeline(char *line, FILE *outfile) } line += 4; } - return; } diff --git a/xmalloc.c b/xmalloc.c index 7c74360..6e84aba 100644 --- a/xmalloc.c +++ b/xmalloc.c @@ -23,14 +23,14 @@ * SOFTWARE. */ #include +#include #include -extern char *malloc(), *realloc(); char *xmalloc (int size) { char *ret; - if (ret = malloc((unsigned) size)) + if ((ret = malloc((unsigned) size))) return ret; fprintf(stderr, "Memory exhausted\n"); @@ -43,7 +43,7 @@ char *xrealloc (char *ptr, int size) char *ret; /* xrealloc (NULL, size) behaves like xmalloc (size), as in ANSI C */ - if (ret = !ptr ? malloc ((unsigned) size) : realloc (ptr, (unsigned) size)) + if ((ret = !ptr ? malloc ((unsigned) size) : realloc (ptr, (unsigned) size))) return ret; fprintf(stderr, "Memory exhausted\n");