home *** CD-ROM | disk | FTP | other *** search
- #define VERSION "newsbreak 1.08 by G. R. Walter"
-
- /*
- * newsbreak.c
- *
- * by G. R. Walter (Fred) December 30, 1988
- *
- * TO COMPILE:
- * Under BSD 4.3
- * cc newsbreak.c -o newsbreak.c
- * Under System V (only those variants that allow -lbsd, which is
- * required for scandir and alphasort)
- * cc newsbreak.c -DSYSTEM_V -lbsd -o newsbreak.c
- *
- * DESCRIPTION:
- * Takes a series of files which are shar files (strips any
- * garbage at the start of the shar file) that have been posted to
- * comp.{sources|binaries}.* and feeds them through sh.
- * After they have been fed through sh the original files are
- * deleted. Then any uuencoded files are uudecoded, after which
- * the uuencoded files are also deleted.
- *
- * NOTES:
- * 1) This program assumes that all necessary shar files are in the
- * current directory. It attempts to not delete stuff if it can't
- * handle it (like when not all the parts of a multi-part uuencoded
- * file are available).
- * 2) When there are multiple parts to a uuencoded file, a maximum
- * of 99 parts are currently handled.
- *
- * HISTORY:
- * 1.00 - original version
- * 1.01 - small enhancements/bug fixes
- * 1.02 - now handle .zu's with > 9 parts correctly
- * 1.03 - now check for ":\tshar\:Shell Archiver" when checking if a file
- * is a shar archive
- * - now handles files ending in .uu#
- * 1.04 - now check for ": run sh on this file to unbundle" when checking
- * if a file is a shar archive
- * 1.05 - now check for "# This is a shell archive." when checking
- * if a file is a shar archive
- * - now prints out the version (and author name) when run
- * 1.06 - now check for "Archive-name:" to see what directory the
- * resulting files should be put in. NOTE: any parts after
- * a "part*" section in the path are not mkdir'ed
- * - now handles files ending in .zuu#
- * - now handles files ending in .uu# properly
- * - now doesn't attempt to process files starting in "."
- * - now prints some useful info (so you know what it is doing)
- * - now check for "# After you unpack everything" when checking
- * if a file is a shar archive
- * - make sure I don't try to uudecode directories
- * - recursively descend directories when uudecoding
- * 1.07 - added ifdef's around code needed so this compiles under System V
- * - changes by ames!uts.amdahl.com!dwl10@mailrus (Dave Lowrey)
- * 1.08 - now check for ": This is a shar archive." when checking
- * if a file is a shar archive
- * - now check for "# This is the first line of a \"shell archive\""
- * when checking if a file is a shar archive
- * - build up a list of files in the current directory before unshar'ing
- * - scan these files to see which ones should be unshar'ed and try
- * to determine the best ordering for unshar'ing (using the secondary
- * header "Archive-name:" if it exists, otherwise using file name)
- * - print what directory is being searched for uuencoded files
- * - print what is being uudecoded
- */
-
- #include <stdio.h>
- #include <ctype.h>
- #include <sys/types.h>
- #include <sys/file.h>
- #include <sys/stat.h>
- #include <sys/dir.h>
- #ifndef SYSTEM_V
- char *getwd();
- #else
- # include <dirent.h>
- char *getcwd();
- #endif
-
- char *malloc();
- char *strcpy();
-
- typedef struct {
- char *filename;
- char *archivename;
- } Name;
-
- char ArchiveName[200];
-
- #define AN_ARCHIVE(BUF) \
- ( \
- (!strncmp(BUF, "#!/bin/sh", 9)) \
- || (!strncmp(BUF, "#! /bin/sh", 10)) \
- || (!strncmp(BUF, "# This is a shell archive.", 26)) \
- || (!strncmp(BUF, ": This is a shar archive.", 25)) \
- || (!strncmp(BUF, ":\tshar:\tShell Archiver", 22)) \
- || (!strncmp(BUF, ": run sh on this file to unbundle", 33)) \
- || (!strncmp(BUF, "# After you unpack everything", 29)) \
- || (!strncmp(BUF, "# This is the first line of a \"shell archive\"", 45)) \
- )
-
- main()
- {
- #ifndef SYSTEM_V
- struct direct **dp;
- #else
- struct dirent **dp;
- #endif
- struct stat stat_buf;
- int size;
- int i;
- int j;
- Name *array;
-
- int Select();
- extern int alphasort();
- int compare();
- void unshar();
- void uudecode();
-
- fprintf(stderr, "%s\n", VERSION);
-
- /*
- * Count the sharfiles in the current directory. If there are any, put
- * the filenames and archive-names (if any) into an array and sort it.
- * Then unshar. (This code assumes that the current directory contents
- * don't change underneath you.)
- */
- size = scandir(".", &dp, Select, alphasort);
- if (size > 0) {
- array = (Name *) malloc((unsigned) (sizeof(Name) * size));
- for (i = 0, j = 0; i < size; i++) {
- if (stat(dp[i]->d_name, &stat_buf)) /* can't stat !?!?!? */
- continue;
-
- if ((stat_buf.st_mode & S_IFDIR)) /* a directory */
- continue;
-
- if (is_a_sharfile(dp[i]->d_name)) {
- array[j].filename =
- malloc((unsigned) (strlen(dp[i]->d_name) + 1));
- strcpy(array[j].filename, dp[i]->d_name);
- array[j].archivename =
- malloc((unsigned) (strlen(ArchiveName) + 1));
- strcpy(array[j].archivename, ArchiveName);
- j++;
- }
- }
- size = j;
- if (size > 0) {
- fprintf(stderr, "\nNow performing the unshar pass.\n");
-
- qsort((char *) array, size, (int) sizeof(Name), compare);
-
- /* now unshar everything */
- for (i = 0; i < size; i++)
- unshar(array[i].filename, array[i].archivename);
- }
- fprintf(stderr, "\nNow performing the uudecode pass.\n");
-
- uudecode(".", 0);
- }
- /*
- * In theory I should free all allocated memory, but it will be free'd
- * upon exitting.
- */
- exit(0);
- }
-
- void
- unshar(name, archivename)
- char *name;
- char *archivename;
- {
- FILE *fin;
- FILE *fout;
- char buf[200];
- char dir[200];
- char path[200];
- char *p;
-
- fprintf(stderr, "Attempting to unshar %s\n", name);
- fin = fopen(name, "r");
- if (fin == NULL) /* file doesn't exist !? */
- return;
-
- strcpy(dir, "."); /* setup directory to use */
- if (archivename[0] != '\0') {
- strcpy(dir, archivename);
- path[0] = '\0';
- for (p = dir; *p != NULL; p++)
- if (*p == '/') {
- *p = NULL;
- if (strncmp(p + 1, "part", 4) == 0)
- break;
- if (access(dir, F_OK) < 0)
- if (mkdir(dir, 0777) < 0)
- goto ABORT_ATTEMPT;
- strcpy(path, archivename);
- *p = '/';
- }
- if (access(dir, F_OK) < 0) {
- if (mkdir(dir, 0777) < 0) {
- ABORT_ATTEMPT:
- fprintf(stderr, "Couldn't mkdir %s\n", dir);
- fprintf(stderr, "Aborting this attempt\n");
- if (path[0] != '\0')
- (void) unlink(path);
- fclose(fin);
- return;
- }
- }
- }
- fprintf(stderr, "unsharing into directory \"%s\"\n", dir);
-
- for (;;) {
- if (fgets(buf, 200, fin) == NULL) { /* not a shar file !? */
- fclose(fin);
- return;
- }
- if (AN_ARCHIVE(buf))
- break;
- }
-
- sprintf(path, "%s/.unshar.temp.file", dir);
- fout = fopen(path, "w");
- while (fgets(buf, 200, fin) != NULL)
- fprintf(fout, "%s", buf);
- fclose(fout);
- fclose(fin);
-
- sprintf(buf, "cd %s; sh .unshar.temp.file", dir);
- if (system(buf) == 0) {
- (void) unlink(name);
- } else {
- fprintf(stderr, "exit status non-zero, not deleting %s\n", name);
- }
-
- (void) unlink(path);
- }
-
- void
- uudecode(name, level)
- char *name;
- int level;
- {
- #ifndef SYSTEM_V
- struct direct **dp;
- #else
- struct dirent **dp;
- #endif
- FILE *file;
- char buf[200];
- char name_buf[200];
- char path[200];
- char *p;
- struct stat stat_buf;
- char digit;
- int i;
- int size;
-
- int Select();
- extern int alphasort();
-
- if (stat(name, &stat_buf)) /* can't stat !?!?!?! */
- return;
-
- if ((stat_buf.st_mode & S_IFDIR)) {
- /* uudecode everything in this directory */
- #ifndef SYSTEM_V
- if (!getwd(path))
- return;
- #else
- if (!getcwd(path, 200))
- return;
- #endif
- size = scandir(name, &dp, Select, alphasort);
- if (size <= 0)
- return;
-
- if (chdir(name))
- return;
-
- level++;
- if (level == 1)
- fprintf(stderr, "uudecoding in directory \"%s\"\n", path);
- else
- fprintf(stderr, "uudecoding in directory \"%s/%s\"\n", path, name);
- for (i = 0; i < size; i++)
- uudecode(dp[i]->d_name, level);
- (void) chdir(path);
- if (level > 1)
- fprintf(stderr, "uudecoding in directory \"%s\"\n", path);
- return;
- }
- /*
- * If the file ends in ".uue" or ".zuu" or ".uu" just uudecode it. Handle
- * ".zuu#", ".zu#" and ".uu#" where # is a number.
- */
- p = name + strlen(name) - 4;
- if (strcmp(p, ".uue") && strcmp(p, ".zuu") && strcmp(p + 1, ".uu")) {
- p += 3;
- while (isdigit(*p))
- p--;
-
- digit = p[1];
- p[1] = '\0';
- p -= 2;
- if (!strcmp(p, ".uu") || !strcmp(p, ".zu")) {
- if (digit == '0') {
- sprintf(buf, "cat %s* | uudecode", name);
- } else {
- sprintf(name_buf, "%s10", name);
- file = fopen(name_buf, "r");
- if (file == NULL) {
- sprintf(buf, "cat %s? | uudecode", name);
- } else {
- fclose(file);
- sprintf(buf, "cat %s? %s?? | uudecode", name, name);
- }
- }
- } else if (strcmp(p - 1, ".zuu")) {
- return;
- }
- }
- sprintf(buf, "cat %s* | uudecode", name);
- fprintf(stderr, "%s\n", buf);
- if (system(buf) == 0) {
- sprintf(buf, "rm %s*", name);
- system(buf);
- } else {
- fprintf(stderr, "exit status non-zero, not deleting file(s)\n");
- }
- }
-
- int
- compare(element1, element2)
- Name *element1;
- Name *element2;
- {
- int result;
-
- result = strcmp(element1->archivename, element2->archivename);
- if (result == 0)
- result = strcmp(element1->filename, element2->filename);
-
- return (result);
- }
-
- /*
- * is_a_sharfile - return -1 if a sharfile, 0 otherwise.
- * - as well, set the global variable ArchiveName
- */
-
- int
- is_a_sharfile(name)
- char *name;
- {
- FILE *fin;
- char buf[200];
-
- ArchiveName[0] = '\0';
-
- fin = fopen(name, "r");
- if (fin == NULL) /* file doesn't exist !? */
- return (0);
-
- for (;;) {
- if (fgets(buf, 200, fin) == NULL) { /* not a shar file !? */
- break;
- } else if (strncmp(buf, "Archive-name:", 13) == 0) {
- sscanf(buf, "Archive-name: %s", ArchiveName);
- } else if (AN_ARCHIVE(buf)) {
- fclose(fin);
- return (-1);
- }
- }
- fclose(fin);
- return (0);
- }
-
- int
- Select(dp)
- #ifndef SYSTEM_V
- struct direct *dp;
- #else
- struct dirent *dp;
- #endif
- {
- if (dp->d_name[0] != '.')
- return (-1);
- else
- return (0);
- }
-