home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume34
/
unpackmaps
/
part01
/
unpack.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-11-29
|
7KB
|
316 lines
/* Copyright 1992, Chris Lewis. All Rights Reserved
Please see the README for the terms of the copyright.
1.3 92/08/14
*/
#ifndef lint
static char SCCSid[] = "@(#)unpack.c 1.3 92/08/14 20:48:41";
#endif
#define UNPACKMAPS
#include "unpack.h"
/*
This code depends on the following map article format:
<don't cares>
cat << 'something' > filename
map body
something
<don't cares>
"something" doesn't have to be enclosed in quotes in the
cat line.
*/
int stunpacked = 0;
int stdiscarded = 0;
unpack() {
FILE *work, *artfp, *outfp;
char article[BUFSIZ],
buf[BUFSIZ],
outfile[BUFSIZ],
endmarker[BUFSIZ];
int discarding, collecting, foundone, endmlen;
register char *f, *t;
(void) umask(022);
(void) unlink(tempfile);
fatal(chdir(unpackdir), "Can't change to unpacking directory");
fatal(access(".", W_OK|R_OK),
"Incorrect permissions on unpacking directory");
if (initialize) {
(void) sprintf(tempbuf, "find %s/comp/mail/maps -type f -print >> togo",
spooldir);
fatal(system(tempbuf), "Find in spooldir/comp/mail/maps failed");
}
while(access(togofile, R_OK) == 0 ||
access(workfile, R_OK) == 0) {
if (access(workfile, F_OK) != 0) {
setbatch(1);
fatal(link(togofile, workfile), "link from togo to work");
fatal(unlink(togofile), "unlink of togo");
setbatch(0);
}
fatal(!(work = fopen(workfile, "r")), "open of work file");
while(fgets(buf, sizeof(buf), work)) {
for (f = buf, t = article; *f && !isspace(*f); )
*t++ = *f++;
*t = '\0';
if (access(article, R_OK) != 0) {
(void) sprintf(buf, "%s/%s", spooldir, article);
if (access(buf, R_OK) != 0) {
(void) fprintf(stderr, "%s apparently superseded or expired\n",
article);
continue;
}
(void) strcpy(article, buf);
}
if (debug)
(void) fprintf(stderr, "AE: %s\n", article);
if (!(artfp = fopen(article, "r"))) {
(void) fprintf(stderr, "cannot open %s\n", article);
continue;
}
collecting = foundone = 0;
while(fgets(buf, sizeof(buf), artfp)) {
if (!collecting && strncmp("cat ", buf, 4) == 0) {
struct stat stb;
if (!catheader(buf, endmarker, outfile, article))
break;
endmlen = strlen(endmarker);
discarding = unlinkskip && search(lmapfiles.list, outfile);
if (discarding)
unlink(outfile);
if (!(outfp = fopen(tempfile, "w"))) {
(void) fprintf(stderr, "Couldn't open %s file - skipping\n",
tempfile);
break;
} else if (verbose)
(void) fprintf(stderr, "%s %s from %s\n",
discarding ? "Discarding": "Extracting",
outfile, article);
foundone = collecting = 1;
continue;
}
if (!collecting)
continue;
if (strncmp(buf, endmarker, endmlen) == 0 &&
buf[endmlen] == '\n') {
collecting = 0;
(void) fclose(outfp);
(void) unlink(outfile);
if (!discarding)
fatal(link(tempfile, outfile), "link temp to output file");
if (discarding)
stdiscarded++;
else
stunpacked++;
fatal(unlink(tempfile), "unlink temp file");
chmod(outfile, 0644);
if (!discarding)
docompress(outfile);
continue;
}
(void) fputs(buf, outfp);
}
fclose(artfp);
if (collecting) {
(void) fprintf(stderr, "Non-terminated map in %s\n", article);
(void) fclose(outfp);
(void) unlink(tempfile);
continue;
}
if (!foundone) {
(void) fprintf(stderr, "%s does not contain a properly formed map\n",
article);
continue;
} else
anyunpacked = 1;
if (unlinkflag)
(void) unlink(article);
}
(void) fclose(work);
(void) unlink(workfile);
}
if (stdiscarded)
(void) fprintf(stderr, "%d maps discarded\n", stdiscarded);
if (stunpacked)
(void) fprintf(stderr, "%d maps unpacked\n", stunpacked);
if (debug)
(void) fprintf(stderr, "End of %s file\n", workfile);
docompress((char *) NULL);
}
/*
Parse the "cat << 'something' > filename" line.
Strip off any quotes, and check the filename for security
breaches.
Since we know that buf is limited to 512 bytes, we
don't have to check endmarker and outfile overflow.
*/
catheader(buf, endmarker, outfile, article)
char *buf, *endmarker, *outfile, *article; {
register char *p = buf+4, *p2;
register int i;
p2 = strchr(buf, '\n'); /* chop(inbuf) ;-) */
if (p2)
*p2 = '\0';
while(*p && *p == ' ') p++; /* skip whitespace after cat */
if (!*p || *p != '<') {
(void) fprintf(stderr, "%s: malformed cat line: %s\n", article, buf);
return(0);
}
while(*p && *p != ' ') p++; /* skip to begin of white space */
while(*p && *p == ' ') p++; /* skip to begin of end marker */
for (p2 = endmarker; *p && *p != ' '; ) /* copy over endmarker */
*p2++ = *p++;
*p2 = '\0';
if (endmarker[0] == '\'') {
*(p2-1) = '\0';
/* should work ;-) */
(void) strcpy(endmarker, &endmarker[1]);
}
while(*p && *p == ' ') p++;
if (!*p || *p != '>') {
(void) fprintf(stderr, "%s: malformed cat line: %s\n", article, buf);
return(0);
}
while(*p && *p != ' ') p++; /* skip over > */
while(*p && *p == ' ') p++; /* skip over whitespace */
if (!*p) {
(void) fprintf(stderr, "%s: malformed cat line: %s\n", article, buf);
return(0);
}
for (p2 = outfile; *p && *p != ' '; )
*p2++ = *p++;
*p2 = '\0';
if (strlen(outfile) < 1) {
(void) fprintf(stderr, "%s: missing filename: %s\n",
article, buf);
return(0);
}
#if (FILELENGTH == 0)
# define MAXUNPLEN 12
#else
# if (FILELENGTH == 1)
# define MAXUNPLEN 14
# else
# define MAXUNPLEN (FILELENGTH - 2)
# endif
#endif
if (strlen(outfile) > MAXUNPLEN) {
(void) fprintf(stderr, "%s: output filename too long (> %d): %s\n",
article, MAXUNPLEN, outfile);
return(0);
}
/* security checks */
for (p = outfile; *p; p++)
if (isalpha(*p) ||
isdigit(*p) ||
*p == '.')
continue;
else {
(void) fprintf(stderr,
"%s: Security violation attempt: bad character[s]: %s\n%s%s\n",
article, outfile, " in cat line: ", buf);
return(0);
}
if (*outfile == '.' ||
strncmp(outfile, "togo", 4) == 0 ||
strncmp(outfile, "path.", 5) == 0 ||
strcmp(outfile, "where.db") == 0 ||
strcmp(outfile, "_temp_") == 0) {
(void) fprintf(stderr,
"%s: Security violation attempt: attempts to write on %s\n%s%s\n",
article, outfile, " in cat line: ", buf);
return(0);
}
return(1);
}
#ifdef TESTCAT
doone(buf)
char *buf; {
char endmarker[512];
char outfile[512];
if (catheader(buf, endmarker, outfile, "/////123"))
printf("Good: %s -> endmarker: %s, outfile: %s\n",
buf, endmarker, outfile);
else
printf("bad: %s\n", buf);
}
main() {
doone("cat << foo > blat\n");
doone("cat << foo > 'blat'\n");
doone("cat << foo > \n");
doone("cat \n");
doone("cat << 'foo' > foo\n");
doone("cat << 'foo' > .foo\n");
doone("cat << 'foo' > README\n");
doone("cat << 'foo' > u.can.on.1\n");
doone("cat << 'foo' > u.can.on.1frammisframmis\n");
}
#endif