home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume11 / newsbreak1.08 / newsbreak.c
Encoding:
C/C++ Source or Header  |  1990-03-25  |  10.5 KB  |  396 lines

  1. #define VERSION "newsbreak 1.08 by G. R. Walter"
  2.  
  3. /*
  4.  * newsbreak.c
  5.  *
  6.  * by G. R. Walter (Fred) December 30, 1988
  7.  *
  8.  * TO COMPILE:
  9.  *     Under BSD 4.3
  10.  *         cc newsbreak.c -o newsbreak.c
  11.  *     Under System V (only those variants that allow -lbsd, which is
  12.  *                     required for scandir and alphasort)
  13.  *         cc newsbreak.c -DSYSTEM_V -lbsd -o newsbreak.c
  14.  *
  15.  * DESCRIPTION:
  16.  *     Takes a series of files which are shar files (strips any
  17.  *     garbage at the start of the shar file) that have been posted to
  18.  *     comp.{sources|binaries}.* and feeds them through sh.
  19.  *     After they have been fed through sh the original files are
  20.  *     deleted. Then any uuencoded files are uudecoded, after which
  21.  *     the uuencoded files are also deleted.
  22.  *
  23.  * NOTES:
  24.  *     1) This program assumes that all necessary shar files are in the
  25.  *        current directory. It attempts to not delete stuff if it can't
  26.  *        handle it (like when not all the parts of a multi-part uuencoded
  27.  *        file are available).
  28.  *     2) When there are multiple parts to a uuencoded file, a maximum
  29.  *        of 99 parts are currently handled.
  30.  *
  31.  * HISTORY:
  32.  * 1.00 - original version
  33.  * 1.01 - small enhancements/bug fixes
  34.  * 1.02 - now handle .zu's with > 9 parts correctly
  35.  * 1.03 - now check for ":\tshar\:Shell Archiver" when checking if a file
  36.  *        is a shar archive
  37.  *      - now handles files ending in .uu#
  38.  * 1.04 - now check for ": run sh on this file to unbundle" when checking
  39.  *        if a file is a shar archive
  40.  * 1.05 - now check for "# This is a shell archive." when checking
  41.  *        if a file is a shar archive
  42.  *      - now prints out the version (and author name) when run
  43.  * 1.06 - now check for "Archive-name:" to see what directory the
  44.  *        resulting files should be put in. NOTE: any parts after
  45.  *        a "part*" section in the path are not mkdir'ed
  46.  *      - now handles files ending in .zuu#
  47.  *      - now handles files ending in .uu# properly
  48.  *      - now doesn't attempt to process files starting in "."
  49.  *      - now prints some useful info (so you know what it is doing)
  50.  *      - now check for "# After you unpack everything" when checking
  51.  *        if a file is a shar archive
  52.  *      - make sure I don't try to uudecode directories
  53.  *      - recursively descend directories when uudecoding
  54.  * 1.07 - added ifdef's around code needed so this compiles under System V
  55.  *      - changes by ames!uts.amdahl.com!dwl10@mailrus (Dave Lowrey)
  56.  * 1.08 - now check for ": This is a shar archive." when checking
  57.  *        if a file is a shar archive
  58.  *      - now check for "# This is the first line of a \"shell archive\""
  59.  *        when checking if a file is a shar archive
  60.  *      - build up a list of files in the current directory before unshar'ing
  61.  *      - scan these files to see which ones should be unshar'ed and try
  62.  *        to determine the best ordering for unshar'ing (using the secondary
  63.  *        header "Archive-name:" if it exists, otherwise using file name)
  64.  *      - print what directory is being searched for uuencoded files
  65.  *      - print what is being uudecoded
  66.  */
  67.  
  68. #include <stdio.h>
  69. #include <ctype.h>
  70. #include <sys/types.h>
  71. #include <sys/file.h>
  72. #include <sys/stat.h>
  73. #include <sys/dir.h>
  74. #ifndef SYSTEM_V
  75. char           *getwd();
  76. #else
  77. # include <dirent.h>
  78. char           *getcwd();
  79. #endif
  80.  
  81. char           *malloc();
  82. char           *strcpy();
  83.  
  84. typedef struct {
  85.     char           *filename;
  86.     char           *archivename;
  87. }               Name;
  88.  
  89. char            ArchiveName[200];
  90.  
  91. #define AN_ARCHIVE(BUF) \
  92. ( \
  93.    (!strncmp(BUF, "#!/bin/sh", 9)) \
  94. || (!strncmp(BUF, "#! /bin/sh", 10)) \
  95. || (!strncmp(BUF, "# This is a shell archive.", 26)) \
  96. || (!strncmp(BUF, ": This is a shar archive.", 25)) \
  97. || (!strncmp(BUF, ":\tshar:\tShell Archiver", 22)) \
  98. || (!strncmp(BUF, ": run sh on this file to unbundle", 33)) \
  99. || (!strncmp(BUF, "# After you unpack everything", 29)) \
  100. || (!strncmp(BUF, "# This is the first line of a \"shell archive\"", 45)) \
  101. )
  102.  
  103. main()
  104. {
  105. #ifndef SYSTEM_V
  106.     struct direct **dp;
  107. #else
  108.     struct dirent **dp;
  109. #endif
  110.     struct stat     stat_buf;
  111.     int             size;
  112.     int             i;
  113.     int             j;
  114.     Name           *array;
  115.  
  116.     int             Select();
  117.     extern int      alphasort();
  118.     int             compare();
  119.     void            unshar();
  120.     void            uudecode();
  121.  
  122.     fprintf(stderr, "%s\n", VERSION);
  123.  
  124.     /*
  125.      * Count the sharfiles in the current directory. If there are any, put
  126.      * the filenames and archive-names (if any) into an array and sort it.
  127.      * Then unshar. (This code assumes that the current directory contents
  128.      * don't change underneath you.) 
  129.      */
  130.     size = scandir(".", &dp, Select, alphasort);
  131.     if (size > 0) {
  132.     array = (Name *) malloc((unsigned) (sizeof(Name) * size));
  133.     for (i = 0, j = 0; i < size; i++) {
  134.         if (stat(dp[i]->d_name, &stat_buf))    /* can't stat !?!?!? */
  135.         continue;
  136.  
  137.         if ((stat_buf.st_mode & S_IFDIR))    /* a directory */
  138.         continue;
  139.  
  140.         if (is_a_sharfile(dp[i]->d_name)) {
  141.         array[j].filename =
  142.             malloc((unsigned) (strlen(dp[i]->d_name) + 1));
  143.         strcpy(array[j].filename, dp[i]->d_name);
  144.         array[j].archivename =
  145.             malloc((unsigned) (strlen(ArchiveName) + 1));
  146.         strcpy(array[j].archivename, ArchiveName);
  147.         j++;
  148.         }
  149.     }
  150.     size = j;
  151.     if (size > 0) {
  152.         fprintf(stderr, "\nNow performing the unshar pass.\n");
  153.  
  154.         qsort((char *) array, size, (int) sizeof(Name), compare);
  155.  
  156.         /* now unshar everything */
  157.         for (i = 0; i < size; i++)
  158.         unshar(array[i].filename, array[i].archivename);
  159.     }
  160.     fprintf(stderr, "\nNow performing the uudecode pass.\n");
  161.  
  162.     uudecode(".", 0);
  163.     }
  164.     /*
  165.      * In theory I should free all allocated memory, but it will be free'd
  166.      * upon exitting. 
  167.      */
  168.     exit(0);
  169. }
  170.  
  171. void
  172. unshar(name, archivename)
  173.     char           *name;
  174.     char           *archivename;
  175. {
  176.     FILE           *fin;
  177.     FILE           *fout;
  178.     char            buf[200];
  179.     char            dir[200];
  180.     char            path[200];
  181.     char           *p;
  182.  
  183.     fprintf(stderr, "Attempting to unshar %s\n", name);
  184.     fin = fopen(name, "r");
  185.     if (fin == NULL)        /* file doesn't exist !? */
  186.     return;
  187.  
  188.     strcpy(dir, ".");        /* setup directory to use */
  189.     if (archivename[0] != '\0') {
  190.     strcpy(dir, archivename);
  191.     path[0] = '\0';
  192.     for (p = dir; *p != NULL; p++)
  193.         if (*p == '/') {
  194.         *p = NULL;
  195.         if (strncmp(p + 1, "part", 4) == 0)
  196.             break;
  197.         if (access(dir, F_OK) < 0)
  198.             if (mkdir(dir, 0777) < 0)
  199.             goto ABORT_ATTEMPT;
  200.         strcpy(path, archivename);
  201.         *p = '/';
  202.         }
  203.     if (access(dir, F_OK) < 0) {
  204.         if (mkdir(dir, 0777) < 0) {
  205.     ABORT_ATTEMPT:
  206.         fprintf(stderr, "Couldn't mkdir %s\n", dir);
  207.         fprintf(stderr, "Aborting this attempt\n");
  208.         if (path[0] != '\0')
  209.             (void) unlink(path);
  210.         fclose(fin);
  211.         return;
  212.         }
  213.     }
  214.     }
  215.     fprintf(stderr, "unsharing into directory \"%s\"\n", dir);
  216.  
  217.     for (;;) {
  218.     if (fgets(buf, 200, fin) == NULL) {    /* not a shar file !? */
  219.         fclose(fin);
  220.         return;
  221.     }
  222.     if (AN_ARCHIVE(buf))
  223.         break;
  224.     }
  225.  
  226.     sprintf(path, "%s/.unshar.temp.file", dir);
  227.     fout = fopen(path, "w");
  228.     while (fgets(buf, 200, fin) != NULL)
  229.     fprintf(fout, "%s", buf);
  230.     fclose(fout);
  231.     fclose(fin);
  232.  
  233.     sprintf(buf, "cd %s; sh .unshar.temp.file", dir);
  234.     if (system(buf) == 0) {
  235.     (void) unlink(name);
  236.     } else {
  237.     fprintf(stderr, "exit status non-zero, not deleting %s\n", name);
  238.     }
  239.  
  240.     (void) unlink(path);
  241. }
  242.  
  243. void
  244. uudecode(name, level)
  245.     char           *name;
  246.     int             level;
  247. {
  248. #ifndef SYSTEM_V
  249.     struct direct **dp;
  250. #else
  251.     struct dirent **dp;
  252. #endif
  253.     FILE           *file;
  254.     char            buf[200];
  255.     char            name_buf[200];
  256.     char            path[200];
  257.     char           *p;
  258.     struct stat     stat_buf;
  259.     char            digit;
  260.     int             i;
  261.     int             size;
  262.  
  263.     int             Select();
  264.     extern int      alphasort();
  265.  
  266.     if (stat(name, &stat_buf))    /* can't stat !?!?!?! */
  267.     return;
  268.  
  269.     if ((stat_buf.st_mode & S_IFDIR)) {
  270.     /* uudecode everything in this directory */
  271. #ifndef SYSTEM_V
  272.     if (!getwd(path))
  273.         return;
  274. #else
  275.     if (!getcwd(path, 200))
  276.         return;
  277. #endif
  278.     size = scandir(name, &dp, Select, alphasort);
  279.     if (size <= 0)
  280.         return;
  281.  
  282.     if (chdir(name))
  283.         return;
  284.  
  285.     level++;
  286.     if (level == 1)
  287.         fprintf(stderr, "uudecoding in directory \"%s\"\n", path);
  288.     else
  289.         fprintf(stderr, "uudecoding in directory \"%s/%s\"\n", path, name);
  290.     for (i = 0; i < size; i++)
  291.         uudecode(dp[i]->d_name, level);
  292.     (void) chdir(path);
  293.     if (level > 1)
  294.         fprintf(stderr, "uudecoding in directory \"%s\"\n", path);
  295.     return;
  296.     }
  297.     /*
  298.      * If the file ends in ".uue" or ".zuu" or ".uu" just uudecode it. Handle
  299.      * ".zuu#", ".zu#" and ".uu#" where # is a number. 
  300.      */
  301.     p = name + strlen(name) - 4;
  302.     if (strcmp(p, ".uue") && strcmp(p, ".zuu") && strcmp(p + 1, ".uu")) {
  303.     p += 3;
  304.     while (isdigit(*p))
  305.         p--;
  306.  
  307.     digit = p[1];
  308.     p[1] = '\0';
  309.     p -= 2;
  310.     if (!strcmp(p, ".uu") || !strcmp(p, ".zu")) {
  311.         if (digit == '0') {
  312.         sprintf(buf, "cat %s* | uudecode", name);
  313.         } else {
  314.         sprintf(name_buf, "%s10", name);
  315.         file = fopen(name_buf, "r");
  316.         if (file == NULL) {
  317.             sprintf(buf, "cat %s? | uudecode", name);
  318.         } else {
  319.             fclose(file);
  320.             sprintf(buf, "cat %s? %s?? | uudecode", name, name);
  321.         }
  322.         }
  323.     } else if (strcmp(p - 1, ".zuu")) {
  324.         return;
  325.     }
  326.     }
  327.     sprintf(buf, "cat %s* | uudecode", name);
  328.     fprintf(stderr, "%s\n", buf);
  329.     if (system(buf) == 0) {
  330.     sprintf(buf, "rm %s*", name);
  331.     system(buf);
  332.     } else {
  333.     fprintf(stderr, "exit status non-zero, not deleting file(s)\n");
  334.     }
  335. }
  336.  
  337. int
  338. compare(element1, element2)
  339.     Name           *element1;
  340.     Name           *element2;
  341. {
  342.     int             result;
  343.  
  344.     result = strcmp(element1->archivename, element2->archivename);
  345.     if (result == 0)
  346.     result = strcmp(element1->filename, element2->filename);
  347.  
  348.     return (result);
  349. }
  350.  
  351. /*
  352.  * is_a_sharfile - return -1 if a sharfile, 0 otherwise.
  353.  *               - as well, set the global variable ArchiveName
  354.  */
  355.  
  356. int
  357. is_a_sharfile(name)
  358.     char           *name;
  359. {
  360.     FILE           *fin;
  361.     char            buf[200];
  362.  
  363.     ArchiveName[0] = '\0';
  364.  
  365.     fin = fopen(name, "r");
  366.     if (fin == NULL)        /* file doesn't exist !? */
  367.     return (0);
  368.  
  369.     for (;;) {
  370.     if (fgets(buf, 200, fin) == NULL) {    /* not a shar file !? */
  371.         break;
  372.     } else if (strncmp(buf, "Archive-name:", 13) == 0) {
  373.         sscanf(buf, "Archive-name: %s", ArchiveName);
  374.     } else if (AN_ARCHIVE(buf)) {
  375.         fclose(fin);
  376.         return (-1);
  377.     }
  378.     }
  379.     fclose(fin);
  380.     return (0);
  381. }
  382.  
  383. int
  384. Select(dp)
  385. #ifndef SYSTEM_V
  386.     struct direct  *dp;
  387. #else
  388.     struct dirent  *dp;
  389. #endif
  390. {
  391.     if (dp->d_name[0] != '.')
  392.     return (-1);
  393.     else
  394.     return (0);
  395. }
  396.