home *** CD-ROM | disk | FTP | other *** search
- /* 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
-