home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume34 / unpackmaps / part01 / unpack.c < prev    next >
C/C++ Source or Header  |  1992-11-29  |  7KB  |  316 lines

  1. /* Copyright 1992, Chris Lewis.  All Rights Reserved
  2.    Please see the README for the terms of the copyright.
  3.    1.3 92/08/14
  4.  */
  5.  
  6. #ifndef lint
  7. static char SCCSid[] = "@(#)unpack.c 1.3 92/08/14 20:48:41";
  8. #endif
  9. #define    UNPACKMAPS
  10. #include "unpack.h"
  11.  
  12. /*
  13.     This code depends on the following map article format:
  14.         <don't cares>
  15.         cat << 'something' > filename
  16.             map body
  17.             something
  18.             <don't cares>
  19.  
  20.         "something" doesn't have to be enclosed in quotes in the
  21.         cat line.
  22.  */
  23.  
  24. int stunpacked = 0;
  25. int stdiscarded = 0;
  26.  
  27. unpack() {
  28.     FILE *work, *artfp, *outfp;
  29.     char article[BUFSIZ],
  30.      buf[BUFSIZ],
  31.      outfile[BUFSIZ],
  32.      endmarker[BUFSIZ];
  33.     int discarding, collecting, foundone, endmlen;
  34.     register char *f, *t;
  35.  
  36.     (void) umask(022);
  37.  
  38.     (void) unlink(tempfile);
  39.  
  40.     fatal(chdir(unpackdir), "Can't change to unpacking directory");
  41.     fatal(access(".", W_OK|R_OK),
  42.      "Incorrect permissions on unpacking directory");
  43.  
  44.     if (initialize) {
  45.     (void) sprintf(tempbuf, "find %s/comp/mail/maps -type f -print >> togo",
  46.         spooldir);
  47.     fatal(system(tempbuf), "Find in spooldir/comp/mail/maps failed");
  48.     }
  49.  
  50.     while(access(togofile, R_OK) == 0 ||
  51.       access(workfile, R_OK) == 0) {
  52.  
  53.     if (access(workfile, F_OK) != 0) {
  54.         setbatch(1);
  55.         fatal(link(togofile, workfile), "link from togo to work");
  56.         fatal(unlink(togofile), "unlink of togo");
  57.         setbatch(0);
  58.     }
  59.  
  60.     fatal(!(work = fopen(workfile, "r")), "open of work file");
  61.  
  62.     while(fgets(buf, sizeof(buf), work)) {
  63.  
  64.         for (f = buf, t = article; *f && !isspace(*f); )
  65.         *t++ = *f++;
  66.         *t = '\0';
  67.  
  68.         if (access(article, R_OK) != 0) {
  69.         (void) sprintf(buf, "%s/%s", spooldir, article);
  70.         if (access(buf, R_OK) != 0) {
  71.             (void) fprintf(stderr, "%s apparently superseded or expired\n",
  72.             article);
  73.             continue;
  74.         }
  75.         (void) strcpy(article, buf);
  76.         }
  77.  
  78.         if (debug)
  79.         (void) fprintf(stderr, "AE: %s\n", article);
  80.  
  81.         if (!(artfp = fopen(article, "r"))) {
  82.         (void) fprintf(stderr, "cannot open %s\n", article);
  83.         continue;
  84.         }
  85.  
  86.         collecting = foundone = 0;
  87.  
  88.  
  89.         while(fgets(buf, sizeof(buf), artfp)) {
  90.  
  91.         if (!collecting && strncmp("cat ", buf, 4) == 0) {
  92.             struct stat stb;
  93.  
  94.             if (!catheader(buf, endmarker, outfile, article))
  95.             break;
  96.  
  97.             endmlen = strlen(endmarker);
  98.  
  99.  
  100.             discarding = unlinkskip && search(lmapfiles.list, outfile);
  101.  
  102.             if (discarding)
  103.             unlink(outfile);
  104.  
  105.             if (!(outfp = fopen(tempfile, "w"))) {
  106.             (void) fprintf(stderr, "Couldn't open %s file - skipping\n",
  107.                 tempfile);
  108.             break;
  109.             } else if (verbose)
  110.             (void) fprintf(stderr, "%s %s from %s\n",
  111.                 discarding ? "Discarding": "Extracting",
  112.                 outfile, article);
  113.  
  114.             foundone = collecting = 1;
  115.             continue;
  116.         }
  117.  
  118.         if (!collecting)
  119.             continue;
  120.  
  121.         if (strncmp(buf, endmarker, endmlen) == 0 &&
  122.             buf[endmlen] == '\n') {
  123.  
  124.             collecting = 0;
  125.             (void) fclose(outfp);
  126.  
  127.             (void) unlink(outfile);
  128.  
  129.             if (!discarding)
  130.             fatal(link(tempfile, outfile), "link temp to output file");
  131.  
  132.             if (discarding)
  133.             stdiscarded++;
  134.             else
  135.             stunpacked++;
  136.  
  137.             fatal(unlink(tempfile), "unlink temp file");
  138.  
  139.             chmod(outfile, 0644);
  140.  
  141.             if (!discarding)
  142.             docompress(outfile);
  143.  
  144.             continue;
  145.         }
  146.  
  147.         (void) fputs(buf, outfp);
  148.  
  149.         }
  150.  
  151.         fclose(artfp);
  152.  
  153.         if (collecting) {
  154.         (void) fprintf(stderr, "Non-terminated map in %s\n", article);
  155.         (void) fclose(outfp);
  156.         (void) unlink(tempfile);
  157.         continue;
  158.         }
  159.  
  160.         if (!foundone) {
  161.         (void) fprintf(stderr, "%s does not contain a properly formed map\n",
  162.             article);
  163.         continue;
  164.         } else
  165.         anyunpacked = 1;
  166.  
  167.         if (unlinkflag)
  168.         (void) unlink(article);
  169.     }
  170.  
  171.     (void) fclose(work);
  172.     (void) unlink(workfile);
  173.     }
  174.  
  175.     if (stdiscarded)
  176.     (void) fprintf(stderr, "%d maps discarded\n", stdiscarded);
  177.     if (stunpacked)
  178.     (void) fprintf(stderr, "%d maps unpacked\n", stunpacked);
  179.  
  180.     if (debug)
  181.     (void) fprintf(stderr, "End of %s file\n", workfile);
  182.     docompress((char *) NULL);
  183. }
  184.  
  185. /*
  186.     Parse the "cat << 'something' > filename" line.
  187.  
  188.     Strip off any quotes, and check the filename for security
  189.     breaches.
  190.  
  191.     Since we know that buf is limited to 512 bytes, we
  192.     don't have to check endmarker and outfile overflow.
  193.  */
  194.  
  195. catheader(buf, endmarker, outfile, article)
  196. char *buf, *endmarker, *outfile, *article; {
  197.     register char *p = buf+4, *p2;
  198.     register int i;
  199.  
  200.     p2 = strchr(buf, '\n');    /* chop(inbuf) ;-) */
  201.     if (p2)
  202.     *p2 = '\0';
  203.  
  204.     while(*p && *p == ' ') p++;    /* skip whitespace after cat */
  205.  
  206.     if (!*p || *p != '<') {
  207.     (void) fprintf(stderr, "%s: malformed cat line: %s\n", article, buf);
  208.     return(0);
  209.     }
  210.  
  211.     while(*p && *p != ' ') p++;        /* skip to begin of white space */
  212.     while(*p && *p == ' ') p++;        /* skip to begin of end marker */
  213.  
  214.     for (p2 = endmarker; *p && *p != ' '; )    /* copy over endmarker */
  215.     *p2++ = *p++;
  216.  
  217.     *p2 = '\0';
  218.     if (endmarker[0] == '\'') {
  219.     *(p2-1) = '\0';
  220.     /* should work ;-) */
  221.     (void) strcpy(endmarker, &endmarker[1]);
  222.     }
  223.  
  224.     while(*p && *p == ' ') p++;
  225.     if (!*p || *p != '>') {
  226.     (void) fprintf(stderr, "%s: malformed cat line: %s\n", article, buf);
  227.     return(0);
  228.     }
  229.     while(*p && *p != ' ') p++;        /* skip over > */
  230.     while(*p && *p == ' ') p++;        /* skip over whitespace */
  231.  
  232.     if (!*p) {
  233.     (void) fprintf(stderr, "%s: malformed cat line: %s\n", article, buf);
  234.     return(0);
  235.     }
  236.  
  237.     for (p2 = outfile; *p && *p != ' '; )
  238.     *p2++ = *p++;
  239.     *p2 = '\0';
  240.  
  241.     if (strlen(outfile) < 1) {
  242.     (void) fprintf(stderr, "%s: missing filename: %s\n",
  243.         article, buf);
  244.     return(0);
  245.     }
  246.  
  247. #if    (FILELENGTH == 0)
  248. # define MAXUNPLEN 12
  249. #else
  250. # if    (FILELENGTH == 1)
  251. #  define MAXUNPLEN 14
  252. # else
  253. #  define MAXUNPLEN (FILELENGTH - 2)
  254. # endif
  255. #endif
  256.     
  257.     if (strlen(outfile) > MAXUNPLEN) {
  258.     (void) fprintf(stderr, "%s: output filename too long (> %d): %s\n",
  259.         article, MAXUNPLEN, outfile);
  260.     return(0);
  261.     }
  262.  
  263.     /* security checks */
  264.     for (p = outfile; *p; p++)
  265.     if (isalpha(*p) ||
  266.         isdigit(*p) ||
  267.         *p == '.')
  268.  
  269.         continue;
  270.     else {
  271.         (void) fprintf(stderr, 
  272.         "%s: Security violation attempt: bad character[s]: %s\n%s%s\n",
  273.         article, outfile, "  in cat line: ", buf);
  274.         return(0);
  275.     }
  276.  
  277.     if (*outfile == '.' ||
  278.     strncmp(outfile, "togo", 4) == 0 ||
  279.     strncmp(outfile, "path.", 5) == 0 ||
  280.     strcmp(outfile, "where.db") == 0 ||
  281.     strcmp(outfile, "_temp_") == 0) {
  282.  
  283.     (void) fprintf(stderr,
  284.         "%s: Security violation attempt: attempts to write on %s\n%s%s\n",
  285.         article, outfile, "  in cat line: ", buf);
  286.     return(0);
  287.     }
  288.     return(1);
  289. }
  290.  
  291. #ifdef    TESTCAT
  292. doone(buf)
  293. char *buf; {
  294.     char endmarker[512];
  295.     char outfile[512];
  296.  
  297.     if (catheader(buf, endmarker, outfile, "/////123"))
  298.     printf("Good: %s -> endmarker: %s, outfile: %s\n",
  299.         buf, endmarker, outfile);
  300.     else
  301.     printf("bad: %s\n", buf);
  302. }
  303.  
  304. main() {
  305.     doone("cat << foo > blat\n");
  306.     doone("cat << foo > 'blat'\n");
  307.     doone("cat << foo > \n");
  308.     doone("cat \n");
  309.     doone("cat << 'foo' > foo\n");
  310.     doone("cat << 'foo' > .foo\n");
  311.     doone("cat << 'foo' > README\n");
  312.     doone("cat << 'foo' > u.can.on.1\n");
  313.     doone("cat << 'foo' > u.can.on.1frammisframmis\n");
  314. }
  315. #endif
  316.