dca@toylnd.UUCP (David C. Albrecht) (10/11/86)
Those who are running SYS V with the Unix utilities on a 7300 with the 20M drive know what a tight fit it is. This utility when used in conjunction with expire allows frequent archiving of the news to floppies while maintaining a Subject line index which remains online. It compresses the files with the news compress utility in an attempt to get maximum density on the floppy (but frequently the inodes run out before the space does). Also, recently someone sent me a request that I mail them my version of shortc which produces a C executable which will filter code to be unique to 7 characters via recapitalization but it was my last day at that job and I accidently deleted the mail message. If he will send the request again to this address I will be happy to mail it to him. ---------- cut here ------------ #!/bin/sh echo 'Start of ../archnews, part 01 of 01:' echo 'x - archnews.1' sed 's/^X//' > archnews.1 << '/' X.TH ARCHNEWS 1 local X.SH NAME Xarchnews \- archive expired news to a floppy X.SH SYNOPSIS X.B archnews Xfloppy directory X.SH DESCRIPTION X.I Archnews Xis a program that takes news which has been expired by the news expire utility Xand archives it to a floppy disk. It should be invoked in the root directory Xof the tree which is desired to be archived. X.I Archnews Xwill print to standard output the subject and summary of the files which Xit archives giving easy index to the floppy archives. The files are Xstored after compression via the news compress utility Xin the same tree structure as the tree being archived. X.pp XWhen the floppy device gets full X.I archnews Xwill fail and may simply be reissued to continue archiving the remaining Xfiles. X.SH AUTHOR XDavid Albrecht / echo 'x - archnews.c' sed 's/^X//' > archnews.c << '/' X#define MAXSTRING 132 X#define MAXDIR 60 X X#include <stdio.h> X X#include "ndir.h" X#include <sys/stat.h> X Xchar newsbuf[512], archdir[MAXDIR], make_dirs[8][MAXDIR], target[MAXDIR]; Xchar in_string[MAXSTRING]; X Xmain(argc,argv) Xint argc; Xchar **argv; X{ char rootdir[MAXDIR], newspath[MAXDIR], newsgroup[MAXDIR]; X X getcwd(rootdir, MAXDIR); X *newspath = '\0'; X *newsgroup = '\0'; X if (argc > 1) { X strcpy(archdir, argv[1]); X } X else { X fprintf(stderr, "archnews archive_directory\n"); X exit(1); X } X procdir(rootdir, newspath, newsgroup, 0); X} X Xprocdir(dirpath, newspath, newsgroup, level) Xchar *dirpath, *newspath, *newsgroup; X{ DIR *directory; X FILE *fp, *fp1, *pin, *pout; X struct direct *dp; X struct stat buf; X int ldirpath, lnewspath, lnewsgroup, i, f_status, child_status, pid; X char entryname[MAXDIR], *str, c; X X if (!(directory = opendir(dirpath))) { X fprintf(stderr, "unable to open directory %s\n", dirpath); X } X else { X while (dp = readdir(directory)) { X X if (*(dp->d_name) == '.') continue; X X *entryname= '\0'; X strncat(entryname, dp->d_name, dp->d_namlen); X fp = fopen(entryname, "r"); X if (!fp) { X fprintf(stderr, "unable to open file %s/%s\n", X dirpath, entryname); X continue; X } X X fstat(fileno(fp), &buf); X if (buf.st_mode & S_IFDIR) { X fclose(fp); X X ldirpath = strlen(dirpath); X strcat(dirpath, "/"); X strcat(dirpath, entryname); X X lnewspath = strlen(newspath); X if (lnewspath) { X strcat(newspath, "/"); X } X strcat(newspath, entryname); X X lnewsgroup = strlen(newsgroup); X if (lnewsgroup) { X strcat(newsgroup, "."); X } X strcat(newsgroup, entryname); X X strcpy(target, archdir); X strcat(target, "/"); X strcat(target, newspath); X fp = fopen(target, "r"); X if (!fp) { X strcpy(&make_dir[level][0], target); X } X else { X fclose(fp); X } X X chdir(entryname); X X procdir(dirpath, newspath, newsgroup, level + 1); X X make_dir[level][0] = '\0'; X dirpath[ldirpath] = '\0'; X chdir(dirpath); X newspath[lnewspath] = '\0'; X newsgroup[lnewsgroup] = '\0'; X } X else { X for (i = 0; i < level; i++) { X if (make_dir[i][0]) { X if (mkdir(&make_dir[i][0], 0777)) { X fprintf(stderr, "cannot create directory %s, archive full\n", X &make_dir[i][0]); X } X else { X make_dir[i][0] = '\0'; X } X } X } X X strcpy(target, archdir); X strcat(target, "/"); X strcat(target, newspath); X strcat(target, "/"); X strcat(target, entryname); X strcat(target, ".Z"); X fp1 = fopen(target, "w"); X if (!fp1) { X fprintf(stderr, "unable to create %s, archive full\n", target); X exit(1); X } X X if (pipe_command("/usr/lib/news/compress", "compress", &pin, &pout)) { X fprintf(stderr, "pipe to /usr/lib/news/compress failed\n"); X } X X if (!(pid = fork())) { X X fclose(fp); X fclose(pin); X X c = getc(pout); X while (!feof(pout)) { X if ((f_status = putc(c, fp1)) == EOF) { X break; X } X c = getc(pout); X } X fclose(fp1); X X if (f_status == EOF) { X while (!feof(pout)) getc(pout); X fclose(pout); X exit(1); X } X else { X fclose(pout); X exit(0); X } X } X else { X X fclose(fp1); X fclose(pout); X X *newsbuf = '\0'; X str = newsbuf; X i = 0; X while (fgets(in_string, MAXSTRING - 1, fp)) { X fputs(in_string, pin); X if (!strncmp(in_string, "Subject", 7)) { X sprintf(str, "%s:%s - %s", newsgroup, entryname, in_string); X str += strlen(str); X } X else if (!strncmp(in_string, "Summary", 7)) { X sprintf(str, "%s:%s - %s", newsgroup, entryname, in_string); X str += strlen(str); X } X else if (!strncmp(in_string, "Keywords", 8)) { X sprintf(str, "%s:%s - %s", newsgroup, entryname, in_string); X str += strlen(str); X } X } X fclose(fp); X fclose(pin); X X while (wait(&child_status) != pid); X if (child_status >> 8) { X fprintf(stderr, "write to %s failed, archive full\n", X target); X unlink(target); X } X else { X fputs(newsbuf, stdout); X unlink(entryname); X } X } X } X } X closedir(directory); X } X} X Xpipe_command(path, command, pin, pout) Xchar *path, *command; XFILE **pin; XFILE **pout; X X{ int fildes1[2], fildes2[2], status = 0; X X if (pipe(fildes1)) { X fprintf(stderr, "cannot create pipes for %s command\n", path); X status = 1; X } X if (pipe(fildes2)) { X fprintf(stderr, "cannot create pipes for %s command\n", path); X status = 1; X } X if (!fork()) { X close(fildes1[1]); X close(fildes2[0]); X close(0); X dup(fildes1[0]); X close(fildes1[0]); X close(1); X dup(fildes2[1]); X close(fildes2[1]); X (void) execlp(path, command, (char *) NULL); X perror(path); X _exit(1); X } X else { X close(fildes1[0]); X close(fildes2[1]); X *pin = fdopen(fildes1[1], "w"); X *pout = fdopen(fildes2[0], "r"); X if (!(*pin) || !(*pout)) status = 1; X } X return(status); X} / echo 'x - funcs.c' sed 's/^X//' > funcs.c << '/' X/* X * This software is Copyright (c) 1986 by Rick Adams. X * X * Permission is hereby granted to copy, reproduce, redistribute or X * otherwise use this software as long as: there is no monetary X * profit gained specifically from the use or reproduction or this X * software, it is not sold, rented, traded or otherwise marketed, and X * this copyright notice is included prominently in any copy X * made. X * X * The author make no claims as to the fitness or correctness of X * this software for any use whatsoever, and it is provided as is. X * Any use of this software is at the user's own risk. X * X * funcs - functions used by many programs X */ X X#ifdef SCCSID Xstatic char *SccsId = "@(#)funcs.c 2.31 1/17/86"; X#endif /* SCCSID */ X X/*LINTLIBRARY*/ X X#include <stdio.h> X#include <errno.h> X#if defined(USG) || defined(BSD4_2) || defined(BSD4_1C) X#include <fcntl.h> X#endif /* !v7 */ X X#if !defined(BSD4_2) && !defined(BSD4_1C) X/* X * make a directory. Also make sure that the directory is owned X * by the right userid X */ Xmkdir(path, perm) Xchar *path; Xint perm; X{ X int pid, status; X X if (pid=fork()) { X while (wait(&status) != pid); X } else { X (void) execlp("mkdir", "mkdir", path, (char *)NULL); X perror(path); X _exit(1); X } X return status; X} X#endif /* !BSD4_2 && ! BSD4_1C */ / echo 'x - ndir.c' sed 's/^X//' > ndir.c << '/' X#include "defs.h" X#if !defined(BSD4_2) && !defined(BSD4_1C) X#include <sys/param.h> X#include "ndir.h" X X#ifdef SCCSID Xstatic char *SccsId = "@(#)ndir.c 1.8 4/26/85"; X#endif /* SCCSID */ X X/* X * support for Berkeley directory reading routine on a V7 file system X */ X Xextern char *malloc(); X X/* X * open a directory. X */ XDIR * Xopendir(name) Xchar *name; X{ X register DIR *dirp; X register int fd; X X if ((fd = open(name, 0)) == -1) X return NULL; X if ((dirp = (DIR *)malloc(sizeof(DIR))) == NULL) { X close (fd); X return NULL; X } X dirp->dd_fd = fd; X dirp->dd_loc = 0; X return dirp; X} X X/* X * read an old style directory entry and present it as a new one X */ X#ifdef pyr X/* Pyramid in the AT&T universe */ X#define ODIRSIZ 248 Xstruct olddirect { X long od_ino; X short od_fill1, od_fill2; X char od_name[ODIRSIZ]; X}; X#else /* V7 file system */ X#define ODIRSIZ 14 X Xstruct olddirect { X ushort od_ino; X char od_name[ODIRSIZ]; X}; X#endif /* V7 */ X X/* X * get next entry in a directory. X */ Xstruct direct * Xreaddir(dirp) Xregister DIR *dirp; X{ X register struct olddirect *dp; X static struct direct dir; X X for (;;) { X if (dirp->dd_loc == 0) { X dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, X DIRBLKSIZ); X if (dirp->dd_size <= 0) X return NULL; X } X if (dirp->dd_loc >= dirp->dd_size) { X dirp->dd_loc = 0; X continue; X } X dp = (struct olddirect *)(dirp->dd_buf + dirp->dd_loc); X dirp->dd_loc += sizeof(struct olddirect); X if (dp->od_ino == 0) X continue; X dir.d_ino = dp->od_ino; X strncpy(dir.d_name, dp->od_name, ODIRSIZ); X dir.d_name[ODIRSIZ] = '\0'; /* insure null termination */ X dir.d_namlen = strlen(dir.d_name); X dir.d_reclen = DIRSIZ(&dir); X return (&dir); X } X} X X/* X * close a directory. X */ Xvoid Xclosedir(dirp) Xregister DIR *dirp; X{ X close(dirp->dd_fd); X dirp->dd_fd = -1; X dirp->dd_loc = 0; X free((char *)dirp); X} X#endif /* !BSD4_2 && !BSD4_1C */ / echo 'x - ndir.h' sed 's/^X//' > ndir.h << '/' X/* @(#)ndir.h 1.4 4/16/85 */ X#ifndef DEV_BSIZE X#define DEV_BSIZE 512 X#endif X#define DIRBLKSIZ DEV_BSIZE X#define MAXNAMLEN 255 X Xstruct direct { X long d_ino; /* inode number of entry */ X short d_reclen; /* length of this record */ X short d_namlen; /* length of string in d_name */ X char d_name[MAXNAMLEN + 1]; /* name must be no longer than this */ X}; X X/* X * The DIRSIZ macro gives the minimum record length which will hold X * the directory entry. This requires the amount of space in struct direct X * without the d_name field, plus enough space for the name with a terminating X * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary. X */ X X#ifdef DIRSIZ X#undef DIRSIZ X#endif /* DIRSIZ */ X#define DIRSIZ(dp) \ X ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3)) X X/* X * Definitions for library routines operating on directories. X */ Xtypedef struct _dirdesc { X int dd_fd; X long dd_loc; X long dd_size; X char dd_buf[DIRBLKSIZ]; X} DIR; X#ifndef NULL X#define NULL 0 X#endif Xextern DIR *opendir(); Xextern struct direct *readdir(); Xextern void closedir(); / echo 'Part 01 of ../archnews complete.' exit
news@toylnd.UUCP (News) (10/20/86)
#!/bin/sh # # The version of archnews which I posted had two very important missing lines: # a fflush without which the summary file gets replicated lines and an exit # when a bounce occurs writing a file to the floppy. Since the diffs were # about 3/4 the size of archnews the following is a new archnews.c and # archnews.1 # # David Albrecht # # echo 'Start of ../archnews.post1, part 01 of 01:' echo 'x - archnews.c' sed 's/^X//' > archnews.c << '/' X#define MAXSTRING 132 X#define MAXDIR 60 X X#include <stdio.h> X X#include "ndir.h" X#include <sys/stat.h> X Xchar newsbuf[512], archdir[MAXDIR], make_dirs[8][MAXDIR], target[MAXDIR]; Xchar in_string[MAXSTRING]; X XFILE *summaries = {stdout}; X Xmain(argc,argv) Xint argc; Xchar **argv; X{ char rootdir[MAXDIR], newspath[MAXDIR], newsgroup[MAXDIR]; X X getcwd(rootdir, MAXDIR); X *newspath = '\0'; X *newsgroup = '\0'; X if (argc > 1) { X strcpy(archdir, argv[1]); X if (argc > 2) { X summaries = fopen(argv[2], "a"); X if (!summaries) { X fprintf(stderr, "unable to open summary file %s\n", argv[2]); X exit(1); X } X } X } X else { X fprintf(stderr, "archnews archive_directory [ summary_file ]\n"); X exit(1); X } X procdir(rootdir, newspath, newsgroup, 0); X} X Xprocdir(dirpath, newspath, newsgroup, level) Xchar *dirpath, *newspath, *newsgroup; X{ DIR *directory; X FILE *fp, *fp1, *pin, *pout; X struct direct *dp; X struct stat buf; X int ldirpath, lnewspath, lnewsgroup, i, f_status, child_status, pid; X char entryname[MAXDIR], *str, c; X X if (!(directory = opendir(dirpath))) { X fprintf(stderr, "unable to open directory %s\n", dirpath); X } X else { X while (dp = readdir(directory)) { X X if (*(dp->d_name) == '.') continue; X X *entryname= '\0'; X strncat(entryname, dp->d_name, dp->d_namlen); X fp = fopen(entryname, "r"); X if (!fp) { X fprintf(stderr, "unable to open file %s/%s\n", X dirpath, entryname); X continue; X } X X fstat(fileno(fp), &buf); X if (buf.st_mode & S_IFDIR) { X fclose(fp); X X ldirpath = strlen(dirpath); X strcat(dirpath, "/"); X strcat(dirpath, entryname); X X lnewspath = strlen(newspath); X if (lnewspath) { X strcat(newspath, "/"); X } X strcat(newspath, entryname); X X lnewsgroup = strlen(newsgroup); X if (lnewsgroup) { X strcat(newsgroup, "."); X } X strcat(newsgroup, entryname); X X strcpy(target, archdir); X strcat(target, "/"); X strcat(target, newspath); X fp = fopen(target, "r"); X if (!fp) { X strcpy(&make_dir[level][0], target); X } X else { X fclose(fp); X } X X chdir(entryname); X X procdir(dirpath, newspath, newsgroup, level + 1); X X make_dir[level][0] = '\0'; X dirpath[ldirpath] = '\0'; X chdir(dirpath); X newspath[lnewspath] = '\0'; X newsgroup[lnewsgroup] = '\0'; X } X else { X for (i = 0; i < level; i++) { X if (make_dir[i][0]) { X if (mkdir(&make_dir[i][0], 0777)) { X fprintf(stderr, "cannot create directory %s, archive full\n", X &make_dir[i][0]); X } X else { X make_dir[i][0] = '\0'; X } X } X } X X strcpy(target, archdir); X strcat(target, "/"); X strcat(target, newspath); X strcat(target, "/"); X strcat(target, entryname); X strcat(target, ".Z"); X fp1 = fopen(target, "w"); X if (!fp1) { X fprintf(stderr, "unable to create %s, archive full\n", target); X exit(1); X } X X fflush(summaries); X if (pipe_command("/usr/lib/news/compress", "compress", &pin, &pout)) { X fprintf(stderr, "pipe to /usr/lib/news/compress failed\n"); X exit(1); X } X X if (!(pid = fork())) { X X fclose(fp); X fclose(pin); X X c = getc(pout); X while (!feof(pout)) { X if ((f_status = putc(c, fp1)) == EOF) { X break; X } X c = getc(pout); X } X fclose(fp1); X X if (f_status == EOF) { X while (!feof(pout)) getc(pout); X fclose(pout); X exit(1); X } X else { X fclose(pout); X exit(0); X } X } X else { X X fclose(fp1); X fclose(pout); X X *newsbuf = '\0'; X str = newsbuf; X i = 0; X while (fgets(in_string, MAXSTRING - 1, fp)) { X fputs(in_string, pin); X if (!strncmp(in_string, "Subject", 7)) { X sprintf(str, "%s:%s - %s", newsgroup, entryname, in_string); X str += strlen(str); X } X else if (!strncmp(in_string, "Summary", 7)) { X sprintf(str, "%s:%s - %s", newsgroup, entryname, in_string); X str += strlen(str); X } X else if (!strncmp(in_string, "Keywords", 8)) { X sprintf(str, "%s:%s - %s", newsgroup, entryname, in_string); X str += strlen(str); X } X } X fclose(fp); X fclose(pin); X X while (wait(&child_status) != pid); X if (child_status >> 8) { X fprintf(stderr, "write to %s failed, archive full\n", X target); X unlink(target); X exit(1); X } X else { X fputs(newsbuf, summaries); X unlink(entryname); X } X } X } X } X closedir(directory); X } X} X Xpipe_command(path, command, pin, pout) Xchar *path, *command; XFILE **pin; XFILE **pout; X X{ int fildes1[2], fildes2[2], status = 0; X X if (pipe(fildes1)) { X fprintf(stderr, "cannot create pipes for %s command\n", path); X status = 1; X } X if (pipe(fildes2)) { X fprintf(stderr, "cannot create pipes for %s command\n", path); X status = 1; X } X if (!fork()) { X close(fildes1[1]); X close(fildes2[0]); X close(0); X dup(fildes1[0]); X close(fildes1[0]); X close(1); X dup(fildes2[1]); X close(fildes2[1]); X (void) execlp(path, command, (char *) NULL); X perror(path); X _exit(1); X } X else { X close(fildes1[0]); X close(fildes2[1]); X *pin = fdopen(fildes1[1], "w"); X *pout = fdopen(fildes2[0], "r"); X if (!(*pin) || !(*pout)) status = 1; X } X return(status); X} / echo 'x - archnews.1' sed 's/^X//' > archnews.1 << '/' X.TH ARCHNEWS 1 local X.SH NAME Xarchnews \- archive expired news to a floppy X.SH SYNOPSIS X.B archnews Xfloppy directory [ summary file ] X.SH DESCRIPTION X.I Archnews Xis a program that takes news which has been expired by the news expire utility Xand archives it to a floppy disk. It should be invoked in the root directory Xof the tree which is desired to be archived. X.I Archnews Xif no summary file is specified will print to standard output the subject Xand summary of the files which Xit archives. The summary file gives an easy index to the floppy archives. XThe files are Xstored after compression via the news compress utility Xin the same tree structure as the tree being archived. X.pp XWhen the floppy device gets full X.I archnews Xwill fail and may simply be reissued to continue archiving the remaining Xfiles. X.SH AUTHOR XDavid Albrecht / echo 'Part 01 of ../archnews.post1 complete.' exit