Rich $alz's cshar package, new alpha release, Part02/05
Rich Salz
rsalz at bbn.com
Tue Feb 21 09:24:49 AEST 1989
This is what I use to create shell archives of small-to-humongous source
distributions. Hope you find it useful. Hope you find bugs, and send
them to me. This will appear in comp.sources.unix after the bug reports
die down. It runs on all sort of Unix machines, and a raft of other OS's,
too.
For more details, see the README file in the first shar.
Please don't pass this version around, wait for the "REAL" one.
/rich $alz
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 2 (of 5)."
# Contents: config.5r3 config.vms dirmsd.c lfiles.c llib.c makekit.man
# manipull.c maniscan.man shar.h uudecode.c
# Wrapped by rsalz at fig.bbn.com on Mon Feb 20 18:15:38 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'config.5r3' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'config.5r3'\"
else
echo shar: Extracting \"'config.5r3'\" \(6555 characters\)
sed "s/^X//" >'config.5r3' <<'END_OF_FILE'
X/*
X** Configuration file for shar and friends.
X**
X** This is for System V release 3.1 and 3.2.
X**
X** $Header: config.sVr3,v 2.1 88/06/06 22:05:40 rsalz Exp $
X*/
X
X
X/*
X** Higher-level controls for which operating system we're running on.
X*/
X#define UNIX /* Works */
X/*efine MSDOS /* Should work */
X/*efine VMS /* Doesn't work */
X
X
X/*
X** A dense section of one-line compilation controls. If you're confused,
X** your best bet is to search through the source to see where and how
X** each one of these is used.
X*/
X#define IDX strchr /* Maybe strchr? */
X#define RDX strrchr /* Maybe strrchr? */
X/*efine NEED_CTERMID /* Don't make ctermid(3)? */
X/*efine NEED_MKDIR /* Don't have mkdir(2)? */
X/*efine UNOS_MKDIR /* Use makedir, not mkdir? */
X/*efine NEED_QSORT /* Don't have qsort(3)? */
X/*efine NEED_GETOPT /* Need local getopt object? */
X#define CAN_POPEN /* Can invoke file(1) command? */
X/*efine USE_MY_SHELL /* Don't popen("/bin/sh")? */
X/*efine void int /* If you don't have void */
Xtypedef void sigret_t; /* What a signal handler returns */
X/*pedef int sigret_t; /* What a signal handler returns */
Xtypedef int *align_t; /* Worst-case alignment, for lint */
Xtypedef long time_t; /* Needed for non-BSD sites? */
Xtypedef long off_t; /* Needed for non-BSD sites? */
X/*efine SYS_WAIT /* Have <sys/wait.h> and vfork? */
X/*efine HAS_VFORK /* Have vfork but no <sys/wait.h> */
X/*efine USE_SYSTEM /* Use system(3), not exec(2)? */
X/*efine USE_LONGJMP /* Don't exit() within parser? */
X#define USE_SYSERRLIST /* Have sys_errlist[], sys_nerr? */
X#define USE_GETPWUID /* Use getpwuid(3)? */
X#define DEF_SAVEIT TRUE /* Save headers by default? */
X#define UNIX_FILES /* stat(file) gives true size? */
X#define NAME_FORMAT "%s%2.2d" /* To get things like Part02 */
X/*efine NAME_FORMAT "%s%02.2d" /* To get things like Part02 */
X#define MANI_FORMAT " %-25s %2d\t%s\n" /* This should be safe */
X#define MAX_LEVELS 6 /* Levels for findsrc to walk */
X#define THE_TTY "/dev/tty" /* Maybe "con:" for MS-DOS? */
X#define RCSID /* Compile in the RCS strings? */
X#define USERNAME "Somebody" /* Your name, if not in environ */
X/*efine PTR_SPRINTF /* Need extern char *sprinf()? */
X/*efine DECLARE_PROTOTYPES /* Use prototypes in our decls? */
X/*efine ANSI_HDRS /* Use <stdlib.h>, etc.? */
X#define REGISTER register /* Do you trust your compiler? */
X#define PEDAGOGY /* Advertise tools? */
X
X
X/*
X** How do we test to see if a character is okay to pass to one of
X** the macros in <ctype.h>? Note that we never give it EOF.
X*/
X#define CTYPE(c) (isascii((c))) /* Common */
X/*efine CTYPE(c) ((c) > 0) /* Less common */
X/*efine CTYPE(c) (TRUE) /* Uncommon */
X
X
X/*
X** We often want to make a backup copy of a file (usually a manifest).
X** The following sets of #define's control how the copying is done.
X*/
X#define BU_VIA_RENAME /* Use rename call? */
X/*efine BU_VIA_LINK /* Use link/unlink calls? */
X/*efine BU_VIA_COPY /* Use fopen() and such? */
X/*efine BU_NONE /* System has generations? */
X/*efine BU_PREFIX "B-" /* Instead of ".BAK" suffix? */
X#define BU_SUFFIX ".BAK" /* Instead of "B-" prefix? */
X#define BU_NAME_LEN 14 /* For non-BSD filesystems */
X
X
X/*
X** The programs create up to two temporary files at one time, using
X** mktemp(3). Decide where you want the files to go, and if you wanna
X** use a special directory for them (see MakeTempName).
X*/
X#define TEMP_NAME1 "/tmp/csharXXXXXX" /* Unix */
X#define TEMP_NAME2 "/tmp/csharXXXXXX" /* Unix */
X/*efine TEMP_NAME1 "csharXXXXXX" /* MS-DOS */
X/*efine TEMP_NAME2 "csharXXXXXX" /* MS-DOS */
X/*efine TEMP_NAME1 "sys$login:csharXXXXXX" /* VMS */
X/*efine TEMP_NAME2 "sys$login:csharXXXXXX" /* VMS */
X#define TEMPSIZE 40 /* Size of temp file name */
X/*efine TEMPVAR "TMPDIR" /* Place for temp files */
X
X
X/*
X** There are several ways to get current machine name. Enable just one
X** of one of the following lines.
X*/
X/*efine GETHOSTNAME /* Use gethostname(2) call */
X#define UNAME /* Use uname(2) call */
X/*efine UUNAME /* Invoke "uuname -l" */
X/*efine WHOAMI "/etc/whoami" /* Try /etc/whoami & <whoami.h> */
X/*efine HOST_STRING /* Just use DEF_HOST */
X#define DEF_HOST "SITE" /* If all else fails */
X
X
X/*
X** There are several different ways to get the current working directory.
X** Enable just one of the following lines.
X*/
X/*efine GETWD /* Use getwd(3) routine */
X#define GETCWD /* Use getcwd(3) routine */
X/*efine PWDPOPEN /* Invoke "pwd" */
X/*efine PWDGETENV "PWD" /* Get $PWD from environment */
X
X
X/*
X** If you're a notes site, you might have to tweaks these two #define's.
X** If you don't care, then set them equal to something that doesn't
X** start with the comment-begin sequence and they'll be effectively no-ops
X** at the cost of an extra strcmp. I've also heard of broken MS-DOS
X** compilers that don't ignore slash-star inside comments! Anyhow, for
X** more details see unshar.c
X*/
X/*efine NOTES1 "/* Written " /* This is what notes 1.7 uses */
X/*efine NOTES2 "/* ---" /* This is what notes 1.7 uses */
X#define NOTES1 "$$" /* This is a don't care */
X#define NOTES2 "$$" /* This is a don't care */
X
X
X/*
X** The findsrc program uses the readdir() routines to read directories.
X** If your system doesn't have this interface, there are public domain
X** implementations available for Unix from the comp.sources.unix archives,
X** GNU has a VMS one inside EMACS, and this package comes with kits for
X** MS-DOS and the Amiga. Help save the world and use or write a readdir()
X** package for your system!
X*/
X
X/* Now then, where did I put that header file? Pick one. */
X/*efine IN_SYS_DIR /* <sys/dir.h> */
X/*efine IN_SYS_NDIR /* <sys/ndir.h> */
X/*efine IN_DIR /* <dir.h> */
X/*efine IN_DIRECT /* <direct.h> */
X/*efine IN_NDIR /* "ndir.h" */
X#define IN_DIRENT /* <dirent.h> */
X
X/* What readdir() returns. Must be a #define because of #include order. */
X#ifdef IN_DIRENT
X#define DIRENTRY struct dirent
X#else
X#define DIRENTRY struct direct
X#endif /* IN_DIRENT */
X
X
X/*
X** Limits. The shell parser can be compiled with some safety-checks.
X** This includes creating too many files, or writing long ones, creating
X** too many directories, overwriting existing files, etc.
X*/
X/*efine PATH_CHECK /* Check filenames in shars? */
X/*efine MAX_FOPENS 40 /* Max # of files/archive */
X/*efine MAX_LINES 1200 /* Max # of lines in a file */
X/*efine MAX_MKDIRS 10 /* Max directory depth */
X
X/*
X** Congratulations, you're done!
X*/
END_OF_FILE
if test 6555 -ne `wc -c <'config.5r3'`; then
echo shar: \"'config.5r3'\" unpacked with wrong size!
fi
# end of 'config.5r3'
fi
if test -f 'config.vms' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'config.vms'\"
else
echo shar: Extracting \"'config.vms'\" \(6491 characters\)
sed "s/^X//" >'config.vms' <<'END_OF_FILE'
X/*
X** Configuration file for shar and friends.
X**
X** This is believed to work on VMS.
X**
X** $Header$
X*/
X
X
X/*
X** Higher-level controls for which operating system we're running on.
X*/
X/*efine UNIX /* Works */
X/*efine MSDOS /* Should work */
X#define VMS /* Doesn't work */
X
X
X/*
X** A dense section of one-line compilation controls. If you're confused,
X** your best bet is to search through the source to see where and how
X** each one of these is used.
X*/
X#define IDX index /* Maybe strchr? */
X#define RDX rindex /* Maybe strrchr? */
X#define NEED_CTERMID /* Don't make ctermid(3)? */
X/*efine NEED_MKDIR /* Don't have mkdir(2)? */
X/*efine UNOS_MKDIR /* Use makedir, not mkdir? */
X#define NEED_QSORT /* Don't have qsort(3)? */
X#define NEED_GETOPT /* Need local getopt object? */
X/*efine CAN_POPEN /* Can invoke file(1) command? */
X#define USE_MY_SHELL /* Don't popen("/bin/sh")? */
X/*efine void int /* If you don't have void */
X/*pedef void sigret_t; /* What a signal handler returns */
Xtypedef int sigret_t; /* What a signal handler returns */
Xtypedef int *align_t; /* Worst-case alignment, for lint */
X/*pedef long time_t /* Needed for non-BSD sites? */
X/*pedef long off_t /* Needed for non-BSD sites? */
X/*efine SYS_WAIT /* Have <sys/wait.h> and vfork? */
X/*efine HAS_VFORK /* Have vfork but no <sys/wait.h> */
X#define USE_SYSTEM /* Use system(3), not exec(2)? */
X#define USE_LONGJMP /* Don't exit() within parser? */
X#define USE_SYSERRLIST /* Have sys_errlist[], sys_nerr? */
X/*efine USE_GETPWUID /* Use getpwuid(3)? */
X#define DEF_SAVEIT TRUE /* Save headers by default? */
X/*efine UNIX_FILES /* stat(file) gives true size? */
X#define NAME_FORMAT "%s%2.2d" /* To get things like Part02 */
X/*efine NAME_FORMAT "%s%02.2d" /* To get things like Part02 */
X#define MANI_FORMAT " %-25s %2d\t%s\n" /* This should be safe */
X#define MAX_LEVELS 6 /* Levels for findsrc to walk */
X#define THE_TTY "sys$input" /* Maybe "con:" for MS-DOS? */
X#define RCSID /* Compile in the RCS strings? */
X#define USERNAME "Sombody" /* Your name, if not in environ */
X#define PTR_SPRINTF /* Need extern char *sprinf()? */
X/*efine DECLARE_PROTOTYPES /* Use prototypes in our decls? */
X/*efine ANSI_HDRS /* Use <stdlib.h>, etc.? */
X#define REGISTER register /* Do you trust your compiler? */
X#define PEDAGOGY /* Advertise tools? */
X
X
X/*
X** How do we test to see if a character is okay to pass to one of
X** the macros in <ctype.h>? Note that we never give it EOF.
X*/
X#define CTYPE(c) (isascii((c))) /* Common */
X/*efine CTYPE(c) ((c) > 0) /* Less common */
X/*efine CTYPE(c) (TRUE) /* Uncommon */
X
X
X/*
X** We often want to make a backup copy of a file (usually a manifest).
X** The following sets of #define's control how the copying is done.
X*/
X/*efine BU_VIA_RENAME /* Use rename call? */
X/*efine BU_VIA_LINK /* Use link/unlink calls? */
X/*efine BU_VIA_COPY /* Use fopen() and such? */
X#define BU_NONE /* System has generations? */
X/*efine BU_PREFIX "B-" /* Instead of ".BAK" suffix? */
X/*efine BU_SUFFIX ".BAK" /* Instead of "B-" prefix? */
X/*efine BU_NAME_LEN 50 /* For non-BSD filesystems */
X
X
X/*
X** The programs create up to two temporary files at one time, using
X** mktemp(3). Decide where you want the files to go, and if you wanna
X** use a special directory for them (see MakeTempName).
X*/
X#define TEMP_NAME1 "/tmp/csharXXXXXX" /* Unix */
X#define TEMP_NAME2 "/tmp/csharXXXXXX" /* Unix */
X/*efine TEMP_NAME1 "csharXXXXXX" /* MS-DOS */
X/*efine TEMP_NAME2 "csharXXXXXX" /* MS-DOS */
X/*efine TEMP_NAME1 "sys$login:csharXXXXXX" /* VMS */
X/*efine TEMP_NAME2 "sys$login:csharXXXXXX" /* VMS */
X#define TEMPSIZE 40 /* Size of temp file name */
X/*efine TEMPVAR "TMPDIR" /* Place for temp files */
X
X
X/*
X** There are several ways to get current machine name. Enable just one
X** of one of the following lines.
X*/
X/*efine GETHOSTNAME /* Use gethostname(2) call */
X/*efine UNAME /* Use uname(2) call */
X/*efine UUNAME /* Invoke "uuname -l" */
X#define WHOAMI "sys$manager:host.txt" /* Try /etc/whoami */
X/*efine HOST_STRING /* Just use DEF_HOST */
X#define DEF_HOST "SITE" /* If all else fails */
X
X
X/*
X** There are several different ways to get the current working directory.
X** Enable just one of the following lines.
X*/
X#define GETWD /* Use getwd(3) routine */
X/*efine GETCWD /* Use getcwd(3) routine */
X/*efine PWDPOPEN /* Invoke "pwd" */
X/*efine PWDGETENV "PWD" /* Get $PWD from environment */
X
X
X/*
X** If you're a notes site, you might have to tweaks these two #define's.
X** If you don't care, then set them equal to something that doesn't
X** start with the comment-begin sequence and they'll be effectively no-ops
X** at the cost of an extra strcmp. I've also heard of broken MS-DOS
X** compilers that don't ignore slash-star inside comments! Anyhow, for
X** more details see unshar.c
X*/
X/*efine NOTES1 "/* Written " /* This is what notes 1.7 uses */
X/*efine NOTES2 "/* ---" /* This is what notes 1.7 uses */
X#define NOTES1 "$$" /* This is a don't care */
X#define NOTES2 "$$" /* This is a don't care */
X
X
X/*
X** The findsrc program uses the readdir() routines to read directories.
X** If your system doesn't have this interface, there are public domain
X** implementations available for Unix from the comp.sources.unix archives,
X** GNU has a VMS one inside EMACS, and this package comes with kits for
X** MS-DOS and the Amiga. Help save the world and use or write a readdir()
X** package for your system!
X*/
X
X/* Now then, where did I put that header file? Pick one. */
X#define IN_SYS_DIR /* <sys/dir.h> */
X/*efine IN_SYS_NDIR /* <sys/ndir.h> */
X/*efine IN_DIR /* <dir.h> */
X/*efine IN_DIRECT /* <direct.h> */
X/*efine IN_NDIR /* "ndir.h" */
X/*efine IN_DIRENT /* <dirent.h> */
X
X/* What readdir() returns. Must be a #define because of #include order. */
X#ifdef IN_DIRENT
X#define DIRENTRY struct dirent
X#else
X#define DIRENTRY struct direct
X#endif /* IN_DIRENT */
X
X
X/*
X** Limits. The shell parser can be compiled with some safety-checks.
X** This includes creating too many files, or writing long ones, creating
X** too many directories, overwriting existing files, etc.
X*/
X/*efine PATH_CHECK /* Check filenames in shars? */
X/*efine MAX_FOPENS 40 /* Max # of files/archive */
X/*efine MAX_LINES 1200 /* Max # of lines in a file */
X/*efine MAX_MKDIRS 10 /* Max directory depth */
X
X
X/*
X** Congratulations, you're done!
X*/
END_OF_FILE
if test 6491 -ne `wc -c <'config.vms'`; then
echo shar: \"'config.vms'\" unpacked with wrong size!
fi
# end of 'config.vms'
fi
if test -f 'dirmsd.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'dirmsd.c'\"
else
echo shar: Extracting \"'dirmsd.c'\" \(4054 characters\)
sed "s/^X//" >'dirmsd.c' <<'END_OF_FILE'
X/*
X** Readdir package for MS-DOS.
X**
X** [ I have not tried this at all except to reformat it. --r$ ]
X**
X** Public domain implementation Michael Rendell <garfield!michael>
X** August 1897.
X**
X** $Header$
X*/
X#include <sys/stat.h>
X#include "ndir.h"
X#include <malloc.h>
X#include <string.h>
X#include <dos.h>
X
X#ifndef NULL
X#define NULL 0
X#endif /* NULL */
X
X#ifndef MAXPATHLEN
X#define MAXPATHLEN 255
X#endif /* MAXPATHLEN */
X
X/*
X** Attribute stuff.
X*/
X#define A_RONLY 0x01
X#define A_HIDDEN 0x02
X#define A_SYSTEM 0x04
X#define A_LABEL 0x08
X#define A_DIR 0x10
X#define A_ARCHIVE 0x20
X
X/*
X** DOS call values.
X*/
X#define DOSI_FINDF 0x4e
X#define DOSI_FINDN 0x4f
X#define DOSI_SDTA 0x1a
X
X#define ATTRIBUTES (A_DIR | A_HIDDEN | A_SYSTEM)
X
X/*
X** What find first/next calls look use.
X*/
Xtypedef struct _dtabuf {
X char d_buf[21];
X char d_attribute;
X unsigned short d_time;
X unsigned short d_date;
X long d_size;
X char d_name[13];
X} DTABUF;
X
X
Xstatic DTABUF dtabuf;
Xstatic DTABUF *dtapnt = &dtabuf;
Xstatic union REGS reg;
Xstatic union REGS nreg;
X
X#ifdef M_I86LM
Xstatic struct SREGS sreg;
X#endif /* M_I86LM */
X
X
Xstatic char *
Xgetdirent(dir)
X char *dir;
X{
X if (dir) {
X /* get first entry */
X reg.h.ah = DOSI_FINDF;
X reg.h.cl = ATTRIBUTES;
X#ifdef M_I86LM
X reg.x.dx = FP_OFF(dir);
X sreg.ds = FP_SEG(dir);
X#else
X reg.x.dx = (unsigned int)dir;
X#endif /* M_I86LM */
X }
X else {
X /* get next entry */
X reg.h.ah = DOSI_FINDN;
X#ifdef M_I86LM
X reg.x.dx = FP_OFF(dtapnt);
X sreg.ds = FP_SEG(dtapnt);
X#else
X reg.x.dx = (unsigned int)dtapnt;
X#endif /* M_I86LM */
X }
X#ifdef M_I86LM
X intdosx(®, &nreg, &sreg);
X#else
X intdos(®, &nreg);
X#endif /* M_I86LM */
X
X return nreg.x.cflag ? NULL : dtabuf.d_name;
X}
X
X
Xstatic void
Xfree_dircontents(dp)
X _DIRCONTENTS *dp;
X{
X _DIRCONTENTS *new;
X
X for (; dp; dp = new) {
X if (dp->_d_entry)
X free(dp->_d_entry);
X new = dp->_d_next;
X free((char *)dp);
X }
X}
X
Xstatic void
Xsetdta()
X{
X reg.h.ah = DOSI_SDTA;
X#ifdef M_I86LM
X reg.x.dx = FP_OFF(dtapnt);
X sreg.ds = FP_SEG(dtapnt);
X intdosx(®, &nreg, &sreg);
X#else
X reg.x.dx = (int)dtapnt;
X intdos(®, &nreg);
X#endif /* M_I86LM */
X}
X
X
XDIR *
Xopendir(name)
X char *name;
X{
X DIR *dirp;
X _DIRCONTENTS *dp;
X struct stat statb;
X char *s;
X char c;
X char nbuf[MAXPATHLEN + 1];
X
X if (stat(name, &statb) < 0 || (statb.st_mode & S_IFMT) != S_IFDIR)
X return NULL;
X if ((dirp = (DIR *)malloc(sizeof (DIR))) == NULL)
X return NULL;
X
X if (*name && (c = name[strlen(name) - 1]) != '\\' && c != '/')
X (void)strcat(strcpy(nbuf, name), "\\*.*");
X else
X (void)strcat(strcpy(nbuf, name), "*.*");
X
X dirp->dd_loc = 0;
X setdta();
X dirp->dd_contents = dirp->dd_cp = NULL;
X if ((s = getdirent(nbuf)) == NULL)
X return dirp;
X
X do {
X if ((dp = (_DIRCONTENTS *)malloc(sizeof (_DIRCONTENTS))) == NULL
X || (dp->_d_entry = malloc((unsigned int)(strlen(s) + 1))) == NULL) {
X if (dp)
X free((char *)dp);
X free_dircontents(dirp->dd_contents);
X return NULL;
X }
X if (dirp->dd_contents)
X dirp->dd_cp = dirp->dd_cp->_d_next = dp;
X else
X dirp->dd_cp = dirp->dd_contents = dp;
X (void) strcpy(dp->_d_entry, s);
X dp->_d_next = NULL;
X } while (s = getdirent((char *)NULL));
X dirp->dd_cp = dirp->dd_contents;
X
X return dirp;
X}
X
X
Xvoid
Xclosedir(dirp)
X DIR *dirp;
X{
X free_dircontents(dirp->dd_contents);
X free((char *)dirp);
X}
X
Xstruct direct *
Xreaddir(dirp)
X DIR *dirp;
X{
X static struct direct dp;
X
X if (dirp->dd_cp == NULL)
X return NULL;
X dp.d_namlen = dp.d_reclen = strlen(strcpy(dp.d_name, dirp->dd_cp->_d_entry));
X dp.d_ino = 0;
X dirp->dd_cp = dirp->dd_cp->_d_next;
X dirp->dd_loc++;
X return &dp;
X}
X
X
Xvoid
Xseekdir(dirp, off)
X DIR *dirp;
X long off;
X{
X long i;
X _DIRCONTENTS *dp;
X
X if (off < 0)
X return;
X for (i = off, dp = dirp->dd_contents; --i >= 0 && dp; dp = dp->_d_next)
X ;
X dirp->dd_loc = off - (i + 1);
X dirp->dd_cp = dp;
X}
X
X
Xlong
Xtelldir(dirp)
X DIR *dirp;
X{
X return dirp->dd_loc;
X}
END_OF_FILE
if test 4054 -ne `wc -c <'dirmsd.c'`; then
echo shar: \"'dirmsd.c'\" unpacked with wrong size!
fi
# end of 'dirmsd.c'
fi
if test -f 'lfiles.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'lfiles.c'\"
else
echo shar: Extracting \"'lfiles.c'\" \(4239 characters\)
sed "s/^X//" >'lfiles.c' <<'END_OF_FILE'
X/*
X** File-related routines.
X*/
X/* LINTLIBRARY */
X#include "shar.h"
X#ifndef VMS
X#include <sys/stat.h>
X#else
X#include <stat.h>
X#endif /* VMS */
X#ifdef RCSID
Xstatic char RCS[] =
X "$Header: lfiles.c,v 2.0 88/05/27 13:26:47 rsalz Locked $";
X#endif /* RCSID */
X
X
X#ifndef F_OK
X#define F_OK 0
X#endif /* F_OK */
X
X/* Mask of executable bits. */
X#define EXE_MASK (S_IEXEC | (S_IEXEC >> 3) | (S_IEXEC >> 6))
X
X/* Stat buffer for last file. */
Xstatic struct stat Sb;
X
X
X/*
X** Stat the file. We used to save the old name and only do the stat(2)
X** if the name changed, but that's wrong -- we could open and write to
X** the file between stat() calls.
X*/
Xint
XGetStat(p)
X char *p;
X{
X return stat(p, &Sb) < 0 ? FALSE : TRUE;
X}
X
X
X/*
X** See if the file exists. Dumb test, not suitable for use everywhere.
X*/
Xint
XFexists(p)
X char *p;
X{
X return access(p, F_OK) >= 0 || GetStat(p);
X}
X
X
X/*
X** Return the file type -- directory or regular file.
X*/
Xint
XFtype(p)
X char *p;
X{
X return GetStat(p) && ((Sb.st_mode & S_IFMT) == S_IFDIR) ? F_DIR : F_FILE;
X}
X
X
X/*
X** Return the file size.
X*/
Xoff_t
XFsize(p)
X char *p;
X{
X#ifdef UNIX_FILES
X return GetStat(p) ? Sb.st_size : 0;
X#else
X REGISTER FILE *F;
X REGISTER off_t i;
X
X if ((F = fopen(p, "r")) == NULL)
X return 0;
X for (i = 0; getc(F) != EOF; i++)
X ;
X (void)fclose(F);
X return i;
X#endif /* UNIX_FILES */
X}
X
X
X/*
X** Is a file executable?
X*/
Xint
XFexecute(p)
X char *p;
X{
X return GetStat(p) && (Sb.st_mode & EXE_MASK) ? TRUE : FALSE;
X}
X
X
X/*
X** Does it look like a source file (ends with *.[cFflpy])?
X*/
Xint
XIsProbablySource(p)
X register char *p;
X{
X if ((p = RDX(p, '.')) && p[1] != '\0' && p[2] == '\0')
X switch (p[1]) {
X case 'c':
X case 'F':
X case 'f':
X case 'l':
X case 'p':
X case 'y':
X return TRUE;
X }
X
X return FALSE;
X}
X
X
X/*
X** Rename a file so that we don't overwrite it.
X*/
X#ifdef BU_NONE
XSafeRename(Name)
X char *Name;
X{
X Name = Name;
X}
X
X#else
X
XSafeRename(Name)
X char *Name;
X{
X#ifdef BU_VIA_COPY
X REGISTER FILE *In;
X REGISTER FILE *Out;
X#endif /* BU_VIA_COPY */
X#ifdef BU_NAME_LEN
X REGISTER char *p;
X#endif /* BU_NAME_LEN */
X char buff[BUFSIZ];
X
X#ifdef BU_PREFIX
X /* Turn /foo/bar/baz into /foo/bar/B-baz. */
X if (p = RDX(buff, '/')) {
X *p = '\0';
X (void)sprintf(buff, "%s/%s%s", buff, BU_PREFIX, p + 1);
X *p = '/';
X }
X else
X (void)sprintf(buff, "%s%s", BU_PREFIX, Name);
X#endif /* BU_PREFIX */
X
X#ifdef BU_SUFFIX
X /* Turn /foo/bar/baz into /foo/bar/baz.BAK */
X (void)sprintf(buff, "%s%s", Name, BU_SUFFIX);
X#ifdef BU_NAME_LEN
X /* If on a shortname system, turn longfilename.BAK into longfilena.BAK */
X p = (p = RDX(buff, '/')) ? p + 1 : buff;
X if (strlen(p) > BU_NAME_LEN)
X (void)strcpy(&p[BU_NAME_LEN - strlen(BU_SUFFIX)], BU_SUFFIX);
X#endif /* BU_NAME_LEN */
X#endif /* BU_SUFFIX */
X
X#ifdef BU_VIA_RENAME
X (void)rename(Name, buff);
X#endif /* BU_VIA_RENAME */
X
X#ifdef BU_VIA_LINK
X (void)unlink(to);
X (void)link(from, to);
X unlink(from);
X#endif /* BU_VIA_LINK */
X
X#ifdef BU_VIA_COPY
X /* Open the old and new files. */
X if ((In = fopen(Name, "r")) == NULL) {
X Fprintf(stderr, "Can't open \"%s\" for reading to copy, %s.\n",
X Name, Ermsg(errno));
X exit(1);
X /* NOTREACHED */
X }
X if ((Out = fopen(buff, "w")) == NULL) {
X Fprintf(stderr, "Can't open \"%s\" for writing to copy, %s.\n",
X Name, Ermsg(errno));
X (void)fclose(In);
X exit(1);
X /* NOTREACHED */
X }
X
X /* Slurp and spew. */
X while (fgets(buff, sizeof buff, In))
X (void)fputs(buff, Out);
X
X /* Close. */
X (void)fclose(In);
X (void)fclose(Out);
X#endif /* BU_VIA_COPY */
X}
X#endif /* BU_NONE */
X
X
X/*
X** Make a complete pathname to a temporary file.
X*/
XMakeTempName(buff, Name)
X char *buff;
X char *Name;
X{
X#ifdef TEMPVAR
X register char *p;
X register int i;
X
X /* find the temporary directory */
X if ((p = getenv(TEMPVAR)) == NULL)
X (void)strcpy(buff, Name);
X else {
X /* Guarantee a directory separator. */
X i = strlen(p);
X if (p[i - 1] != '/' && p[i - 1] != '\\' && *Name != '/' && *Name != '\\')
X (void)sprintf(buff, "%s/%s", p, Name);
X else
X (void)sprintf(buff, "%s%s", p, Name);
X }
X (void)mktemp(buff);
X#else
X (void)mktemp(strcpy(buff, Name));
X#endif /* TEMPVAR */
X}
END_OF_FILE
if test 4239 -ne `wc -c <'lfiles.c'`; then
echo shar: \"'lfiles.c'\" unpacked with wrong size!
fi
# end of 'lfiles.c'
fi
if test -f 'llib.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'llib.c'\"
else
echo shar: Extracting \"'llib.c'\" \(4834 characters\)
sed "s/^X//" >'llib.c' <<'END_OF_FILE'
X/*
X** Some systems will need these routines because they're missing from
X** their C library. This is also a catch-all for miscellaneous routines.
X*/
X/* LINTLIBRARY */
X#include "shar.h"
X#ifdef RCSID
Xstatic char RCS[] =
X "$Header: llib.c,v 2.1 88/06/06 22:05:14 rsalz Locked $";
X#endif /* RCSID */
X
X
X/*
X** Return the printable representation of a character. Assumes ASCII,
X** but that's ok, it's all we use for portability.
X*/
Xchar *
XSeechar(c)
X register int c;
X{
X static char buff1[20];
X static char buff2[20];
X register char *p;
X int meta;
X
X meta = c & 0200;
X c &= 0177;
X if (c >= 001 && c <= 032) {
X (void)sprintf(buff1, "CTRL-%c", c - 1 + 'A');
X p = buff1;
X }
X else if (c >= 040 && c <= 0176) {
X buff1[0] = c;
X buff1[1] = '\0';
X p = buff1;
X }
X else
X switch (c) {
X default: p = "<BAD>"; break;
X case 000: p = "NUL"; break;
X case 033: p = "ESCAPE"; break;
X case 034: p = "CTRL-\\"; break;
X case 035: p = "CTRL-]"; break;
X case 036: p = "CTRL-^"; break;
X case 037: p = "CTRL-_"; break;
X case 0177: p = "DELETE"; break;
X }
X if (!meta)
X return p;
X (void)sprintf(buff2, "META-%s", p);
X return buff2;
X}
X
X
X/*
X** Return the text string that corresponds to errno.
X*/
Xchar *
XErmsg(e)
X int e;
X{
X static char buff[30];
X
X#ifdef USE_SYSERRLIST
X if (e > 0 && e < sys_nerr)
X return sys_errlist[e];
X#endif /* USE_SYSERRLIST */
X (void)sprintf(buff, "Error code %d", e);
X return buff;
X}
X
X
X#ifdef NEED_CTERMID
X/*
X** Return a pointer to a device that can be fopen'd to query the user,
X** regardless of whether or not stdin is redirected.
X*/
Xchar *
Xctermid(p)
X char *p;
X{
X static char buff[L_ctermid];
X
X return strcpy(p ? p : buff, THE_TTY);
X}
X#endif /* NEED_CTERMID */
X
X
X#ifdef NEED_MKDIR
X/*
X** Quick and dirty mkdir routine for them that's need it.
X*/
Xint
Xmkdir(name, mode)
X char *name;
X int mode;
X{
X char *av[3];
X int i;
X int U;
X
X av[0] = "mkdir";
X av[1] = name;
X av[2] = NULL;
X U = umask(~mode);
X i = Execute(av);
X (void)umask(U);
X return i ? -1 : 0;
X}
X#endif /* NEED_MKDIR */
X
X
X#ifdef UNOS_MAKEDIR
X/*
X** UNOS has makedir(), but not mkdir...
X*/
X#include <sys/stat.h>
X#include <errno.h>
X
X
Xint
Xmkdir(path, mode)
X char *path;
X int mode;
X{
X struct stat Sb;
X
X /* See if it exists, or fails for other than non-existance. */
X if (stat(path, &Sb) == 0) {
X errno = EEXIST;
X return -1;
X }
X if (errno != ENOENT)
X return -1;
X
X /* UNOS makedir doesn't set the mode, so we have to do it. */
X return makedir(path) == -1 ? -1 : chmod(path, mode);
X}
X#endif /* UNOS_MAKEDIR */
X
X
X#ifdef NEED_QSORT
X/*
X** Bubble sort an array of arbitrarily-sized elements. This routine
X** can be used as an (inefficient) replacement for the Unix qsort
X** routine.
X*/
Xqsort(Table, Number, Width, Compare)
X REGISTER char *Table;
X REGISTER int Number;
X REGISTER int Width;
X REGISTER int (*Compare)();
X{
X REGISTER char *i;
X REGISTER char *j;
X
X for (i = &Table[Number * Width]; (i -= Width) >= &Table[Width]; )
X for (j = i; (j -= Width) >= &Table[0]; )
X if ((*Compare)(i, j) < 0) {
X REGISTER char *p;
X REGISTER char *q;
X REGISTER int t;
X REGISTER int w;
X
X /* Swap elements pointed to by i and j. */
X for (w = Width, p = i, q = j; --w >= 0; *p++ = *q, *q++ = t)
X t = *p;
X }
X}
X#endif /* NEED_QSORT */
X
X
X#ifdef NEED_GETOPT
X
X#define TYPE int
X
X#define ERR(s, c) \
X if (opterr) { \
X char buff[2]; \
X buff[0] = c; buff[1] = '\n'; \
X (void)write(2, av[0], (TYPE)strlen(av[0])); \
X (void)write(2, s, (TYPE)strlen(s)); \
X (void)write(2, buff, 2); \
X }
X
Xint opterr = 1;
Xint optind = 1;
Xint optopt;
Xchar *optarg;
X
X/*
X** Return options and their values from the command line.
X** This comes from the AT&T public-domain getopt published in mod.sources.
X*/
Xint
Xgetopt(ac, av, opts)
X int ac;
X char *av[];
X char *opts;
X{
X static int i = 1;
X REGISTER char *p;
X
X /* Move to next value from argv? */
X if (i == 1) {
X if (optind >= ac || av[optind][0] != '-' || av[optind][1] == '\0')
X return EOF;
X if (strcmp(av[optind], "--") == 0) {
X optind++;
X return EOF;
X }
X }
X
X /* Get next option character. */
X if ((optopt = av[optind][i]) == ':' || (p = IDX(opts, optopt)) == NULL) {
X ERR(": illegal option -- ", optopt);
X if (av[optind][++i] == '\0') {
X optind++;
X i = 1;
X }
X return '?';
X }
X
X /* Snarf argument? */
X if (*++p == ':') {
X if (av[optind][i + 1] != '\0')
X optarg = &av[optind++][i + 1];
X else {
X if (++optind >= ac) {
X ERR(": option requires an argument -- ", optopt);
X i = 1;
X return '?';
X }
X optarg = av[optind++];
X }
X i = 1;
X }
X else {
X if (av[optind][++i] == '\0') {
X i = 1;
X optind++;
X }
X optarg = NULL;
X }
X
X return optopt;
X}
X#endif /* NEED_GETOPT */
END_OF_FILE
if test 4834 -ne `wc -c <'llib.c'`; then
echo shar: \"'llib.c'\" unpacked with wrong size!
fi
# end of 'llib.c'
fi
if test -f 'makekit.man' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'makekit.man'\"
else
echo shar: Extracting \"'makekit.man'\" \(4800 characters\)
sed "s/^X//" >'makekit.man' <<'END_OF_FILE'
X.TH MAKEKIT 1L
X.\" $Header: makekit.man,v 2.2 88/06/06 22:05:01 rsalz Exp $
X.SH NAME
Xmakekit \- split files up into shell archive packages
X.SH SYNOPSIS
X.RS
X.na
X.ti -.5i
X.B makekit
X[
X.B \-1
X] [
X.B \-b
X] [
X.B \-e
X] [
X.B \-x
X] [
X.BI \-h\| #
X] [
X.BI \-i\| name
X] [
X.BI \-k\| #
X] [
X.B \-m
X] [
X.BI \-n\| name
X] [
X.BI \-o\| name
X] [
X.B \-p
X] [
X.BI \-s\| #[k]
X] [
X.BI \-t\| text
X] [ file... ]
X.ad
X.RE
X.SH DESCRIPTION
X.I Makekit
Xreads a list of files and directories, determines their sizes,
Xand parcels them up into a series of shell archives such that all the
Xarchives are of reasonable size.
XIt then invokes
X.IR shar (1L)
Xto actually create the archives.
X.PP
XBy default, no archive will be larger than 50,000 bytes; this may be
Xchanged by using the ``\-s'' option.
XIf the number given with the ``\-s'' option ends with the letter ``k''
Xthen the size is multiplied by 1024, otherwise it is taken to be the
Xdesired maximum size, in bytes.
XEach archive will have a name that looks like
X.IR Part nn,
Xwhere ``nn'' represents the two-digit sequence number (with leading zero
Xif needed).
XThe leader part of the archive name may be changed with the ``\-n'' option.
XThe ``\-n'' is also useful when write permission to the directory being
Xarchive is denied; e.g., ``\-n/tmp/KERNEL.''
X.PP
X.I Makekit
Xreads its list of files on the command line, or standard input
Xif none are given.
XIt is also possible to specify an input filename with the ``\-i'' option.
XIt is not possible to specify files on the command line and read an
Xinput file.
XThe input should contain a list of files, one to a line, to separate.
XIn addition, if each input line looks like this:
X.RS
Xfilename\ \ \ spaces\ \ \ optional-digits\ \ \ spaces\ \ \ text
X.RE
Xthen
X.I makekit
Xwill ignore the spaces and digits, but remember the text associated with
Xeach file, and output it with the filename when generating the ``shipping
Xmanifest.''
XFurther, the ``\-h'' option may be given to have the program skip the
Xindicated number of lines in the input; this option is provided so that
X.I makekit
Xcan more easily re-parse the manifests it has generated.
X.PP
XThe generated manifest will be sent to the standard output.
XAn alternate output file may be given by using the ``\-o'' option; if
Xthe output file exists,
X.I makekit
Xwill try to rename it with an extension of
X.IR \&.BAK \&.
XIf the ``\-o'' option is used,
X.I makekit
Xwill add that name to the list of files to be archived; the ``\-e''
Xoption may be given to exclude the manifest from the list.
X.PP
XThe ``\-m'' option is the same as giving the options,
X\&``-iMANIFEST -oMANIFEST -h2.''
XThis is a common way to regenerate a set of archives after the first
Xuse of
X.I makekit
Xin a directory.
X.PP
XTo recreate the archives from an existing manifest, use the ``\-b''
Xflag; this instructs
X.I makekit
Xto believe the part assignments in the manifest.
XSome extra work will be done to rewrite the manifest, but the assignment
Xof files into their kits will be as specified.
XThis option is also useful in tweaking a distribution to get a tighter fit.
X.PP
XIf a large number of kits has to be generated, you may need to give
Xthe ``\-k'' option to increase the maximum number of kits to be
Xgenerated.
XThe existance of this option can be taken as evidence that the program's
Xauthor is lazy.
X.PP
XAfter partitioning the files and directories,
X.I makekit
Xcalls
X.I shar
Xwith the proper options to generate archives in a series.
XEach resultant archive will, when executed, check to see if all the parts
Xare present.
XIf the ``\-1'' option is used, then
X.I makekit
Xwill not instruct
X.I shar
Xto generate the checks (by not passing on the ``\-n'' and ``\-e'' options).
XBy using the ``\-t'' option, you can specify a line of starting instructions
Xto display to the recipient when all pieces have been unpacked.
XThis is useful when resending part of a series that has probably already
Xbeen unpacked by the recipient.
XSee
X.I shar
Xfor more information on multi-part archives.
XIf the ``\-x'' option is used,
X.I shar
Xis not called, but the manifest is still created.
X.PP
X.I Makekit
Xnormally reorders its input so that the archives are as ``dense'' as
Xpossible, with the exception that directories are given priority over
Xfiles, and the files named
X.IR PACKNOTES ,
X.IR README ,
Xand then
X.I MANIFEST
Xappear first.
XThe manifest is also sorted in alphabetical order; this makes it easy
Xto locate ``missing'' files when the distribution is a large one.
XThe ``\-p'' option may be used to override both sortings, however,
Xand preserve the original order of the input list in generating
Xboth the manifest, and the shell archives.
XIt also tries to partition the files so that all directories are in the
Xfirst archive.
XThis usually means the first archive must be the first one to be unpacked.
X.SH "SEE ALSO"
Xfindsrc(1L), maniscan(1L), shar(1L).
END_OF_FILE
if test 4800 -ne `wc -c <'makekit.man'`; then
echo shar: \"'makekit.man'\" unpacked with wrong size!
fi
# end of 'makekit.man'
fi
if test -f 'manipull.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'manipull.c'\"
else
echo shar: Extracting \"'manipull.c'\" \(4140 characters\)
sed "s/^X//" >'manipull.c' <<'END_OF_FILE'
X/*
X** MANIPULL
X**
X** Extract entries out of an existing manifest.
X** This is Phil Budne's code which I have usurped and heavily modified.
X*/
X#include "shar.h"
X#ifdef RCSID
Xstatic char RCS[] =
X "$Header$";
X#endif /* RCSID */
X
X
X/*
X** Our block of information about the files we're doing.
X*/
Xtypedef struct _entry {
X char *Name; /* Filename */
X char *Text; /* What it is */
X int Wanted; /* Does the user want this one? */
X} ENTRY;
X
X
X#define DEF_FILECOUNT 500 /* Seems like plenty */
X
X
Xmain(ac, av)
X int ac;
X register char *av[];
X{
X REGISTER ENTRY *E;
X REGISTER char *p;
X REGISTER int i;
X REGISTER int Count;
X REGISTER int Silent;
X REGISTER int Header;
X ENTRY *Entries;
X int FileCount;
X int Oops;
X char line[BUFSIZ];
X char *Infile;
X char *Outfile;
X
X /* Parse JCL. */
X Header = 0;
X Silent = FALSE;
X Infile = NULL;
X Outfile = NULL;
X FileCount = DEF_FILECOUNT;
X for (Oops = FALSE; (i = getopt(ac, av, "fh:i:mo:s")) != EOF; )
X switch (i) {
X default:
X Oops = TRUE;
X break;
X case 'f':
X FileCount = atoi(optarg);
X break;
X case 'h':
X Header = atoi(optarg);
X break;
X case 'i':
X Infile = optarg;
X break;
X case 'm':
X Header = 2;
X Infile = "MANIFEST";
X Outfile = "MANIFEST.NEW";
X break;
X case 'o':
X Outfile = optarg;
X break;
X case 's':
X Silent = TRUE;
X break;
X }
X ac -= optind;
X av += optind;
X
X if (ac == 0 || Oops) {
X Fprintf(stderr, "Usage:\n manipull %s files...\n",
X "[-m | -h2 -i MANIFEST -o MANIFEST.NEW] -f# -s");
X exit(1);
X /* NOTREACHED */
X }
X
X /* Open input and output streams as necessary. */
X if (Infile && freopen(Infile, "r", stdin) == NULL) {
X Fprintf(stderr, "Can't open \"%s\" for input, %s.\n",
X Infile, Ermsg(errno));
X exit(1);
X /* NOTREACHED */
X }
X if (Outfile && freopen(Outfile, "r", stdout) == NULL) {
X Fprintf(stderr, "Can't open \"%s\" for output, %s.\n",
X Outfile, Ermsg(errno));
X exit(1);
X /* NOTREACHED */
X }
X
X /* Read and store the manifest. */
X Entries = NEW(ENTRY, FileCount); /* Initialized in loop, below. */
X for (E = Entries, Count = 0; fgets(line, sizeof line, stdin); ) {
X if (Header > 0) {
X Header--;
X continue;
X }
X if (p = IDX(line, '\n'))
X *p = '\0';
X else
X Fprintf(stderr, "Line truncated!\n");
X
X /* Skip leading whitespace; check for totally blank line. */
X for (p = line; *p && CTYPE(*p) && isspace(*p); )
X p++;
X if (*p == '\0')
X continue;
X
X /* Got enough room? */
X if (++Count == FileCount - 1) {
X Fprintf(stderr, "Need more than %d files; use -f flag.\n",
X FileCount);
X exit(1);
X /* NOTREACHED */
X }
X
X /* Copy the name, skip whitespace after it. */
X E->Name = COPY(line);
X for (p = E->Name; *p && CTYPE(*p) && !isspace(*p); )
X p++;
X for (*p++ = '\0'; *p && CTYPE(*p) && isspace(*p); )
X p++;
X
X /* Skip past the archive number. */
X while (*p && CTYPE(*p) && isdigit(*p))
X p++;
X
X /* Skip whitespace. */
X while (*p && CTYPE(*p) && isspace(*p))
X p++;
X
X /* Save description. */
X E->Text = p;
X E->Wanted = FALSE;
X E++;
X }
X
X /* Rest of command line is files to pull out of the manifest. */
X for (; *av; av++) {
X /* Awful linear search. */
X for (E = Entries, i = 0; i < Count; E++, i++)
X if (EQ(E->Name, *av)) {
X E->Wanted = TRUE;
X break;
X }
X if (i == Count) {
X /* Not in MANIFEST; add it by hand. */
X if (!Silent)
X Fprintf(stderr, "ADDING %s\n", *av);
X
X /* Got enough room? */
X if (++Count == FileCount - 1) {
X Fprintf(stderr, "Need more than %d files; use -f flag.\n",
X FileCount);
X exit(1);
X /* NOTREACHED */
X }
X E->Name = COPY(*av);
X E->Text = "";
X E->Wanted = TRUE;
X }
X }
X
X /* Write header, then the entries. */
X Printf("FEED THIS BACK INTO MAKEKIT FOR REAL PACKING...\n");
X Printf(" File Name Archive # Description\n");
X for (E = Entries, i = 0; i < Count; E++, i++)
X if (E->Wanted)
X Printf(" %s\t%d\t%s\n", E->Name, 0, E->Text);
X else if (!Silent)
X Fprintf(stderr, "SKIPPING %s\n", E->Name);
X
X /* That's all she wrote. */
X exit(0);
X /* NOTREACHED */
X}
END_OF_FILE
if test 4140 -ne `wc -c <'manipull.c'`; then
echo shar: \"'manipull.c'\" unpacked with wrong size!
fi
# end of 'manipull.c'
fi
if test -f 'maniscan.man' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'maniscan.man'\"
else
echo shar: Extracting \"'maniscan.man'\" \(3608 characters\)
sed "s/^X//" >'maniscan.man' <<'END_OF_FILE'
X.TH MANISCAN 1L
X.\" $Header$
X.SH NAME
Xmaniscan \- scan a manifest for large or binary files
X.SH SYNOPSIS
X.RS
X.na
X.ti -.5i
X.B maniscan
X[
X.B \-e
X] [
X.BI \-h\| #
X] [
X.BI \-i\| name
X] [
X.BI \-l\| name
X] [
X.B \-m
X] [
X.BI \-o\| name
X] [
X.BI \-s\| #[k]
X]
X.ad
X.RE
X.SH DESCRIPTION
X.I Maniscan
Xreads an existing ``manifest'' (usually created and maintained by
X.IR makekit (1L))
Xand scans it for binary files, large files, and files with long
Xlines or that contain non-printing characters.
XLarge files are automatically split and binary files are run through
X.IR uuencode (1).
XAll problems can be recorded in a log file that should be shipped with
Xthe other sources being prepared.
X.PP
XA manifest consist of some header lines, followed by a series of lines
Xthat describe the files contained in the shell archives.
XEach line looks like this;
X.RS
Xfilename\ \ \ spaces\ \ \ optional-digits\ \ \ spaces\ \ \ text
X.RE
XFor more information on the interpretation of the file, see the
X.I makekit
Xdocumentation.
X.PP
XThe original manifest is read from the standard input.
XAn alternate input file may be given by using the ``\-i'' option.
XThe generated manifest will be sent to the standard output.
XAn alternate output file may be given by using the ``\-o'' option; if
Xthe output file exists,
X.I maniscan
Xwill try to rename it with an extension of
X.IR \&.BAK \&.
X.PP
XAs it scans the manifest,
X.I maniscan
Xcan generate a log of the problems it has found so that the recipient
Xwill know to run
X.IR uudecode (1),
Xuse
X.IR cat (1)
Xto re-create a large file, and so on.
XTo create the log file, use the ``\-l'' option to specify the name
Xof the file; if the name is ``\-'' the log will go to standard error.
XIf any problems are found, the log file will be added to the new
Xmanifest; use the ``\-e'' option to exclude it.
X.PP
XThe ``\-m'' option is the same as giving the options
X\&``\-iMANIFEST \-oMANIFEST \-h2 \-lPACKNOTES'' and is commonly used when
Xreading existing manifests.
X.PP
XAfter copying any header to the output,
X.I maniscan
Xscans each file specified in the manifest.
XIf a named file appears to be a binary file (more than a third
Xof the first 100 bytes are not printable characters),
X.I maniscan
Xwill create a
X.IR uuencode (1)'d
Xversion, update the manifest, and print a log message.
XIf the original file is named
X.IR foo.bar ,
Xthen the new file will be named
X.IR foo.bar.UU .
X.I Maniscan
Xnext scans for long lines or lines that have non-printable characters in
Xthem (most commonly ASCII control characters).
XIt also checks for lines that end with a space or tab.
XEach time it finds on of these problems,
X.I maniscan
Xwill write a log entry.
X.PP
XIf a file named in the manifest is too large,
X.I maniscan
Xwill split it up into pieces.
XThe default limit is 50,000 bytes; this may be changed by using
Xthe ``\-s'' option.
XIf the number given with the ``\-s'' option ends with the letter ``k''
Xthen the size is multiplied by 1024, otherwise it is taken to be the
Xdesired maximum size in bytes.
XThe manifest will be updated to refer to the split pieces, and a log
Xentry will be written with instructions to merge the pieces.
XIf the original file is named
X.IR foo.bar ,
Xthen the pieces will be named
X.IR foo.bar.1 ,
X.IR foo.bar.2 ,
Xand so on.
X.PP
XThe scanning is done in the ``right'' way so that a single large executable
Xnamed
X.I a.out
Xwould end up being shipped as
X.IR a.out.UU.1 ,
X.I a.out.UU.2
X\&...
X.IR a.out.UU.n .
XNote that the generated file names are not portable to all systems.
X.PP
XIn no case does
X.I maniscan
Xedit or remove any files mentioned in a manifest (except for the manifest
Xitself).
X.SH "SEE ALSO"
Xmakekit(1L).
END_OF_FILE
if test 3608 -ne `wc -c <'maniscan.man'`; then
echo shar: \"'maniscan.man'\" unpacked with wrong size!
fi
# end of 'maniscan.man'
fi
if test -f 'shar.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'shar.h'\"
else
echo shar: Extracting \"'shar.h'\" \(5115 characters\)
sed "s/^X//" >'shar.h' <<'END_OF_FILE'
X/*
X** Header file for shar and friends.
X**
X** If you have to edit this file, then I messed something up -- please
X** let me know what.
X**
X** $Header: shar.h,v 2.1 88/06/03 11:39:28 rsalz Locked $
X**
X** THIS IS AN ALPHA-TEST RELEASE.
X** If you are not going to port this to new systems, or try to fix bugs, then
X** please wait a month or two until the real "bug-free" release happens in
X** comp.sources.unix; it'd be a shame to go to all sorts of trouble to
X** install buggy software.
X**
X** PLEASE DO NOT RE-DISTRIBUTE THIS PACKAGE.
X** This code is in the public domain, and you can do what you want with it,
X** but I guarantee that the real release will have bugs fixed. I would hate
X** for this to end up on fifty-skadillion BBS systems when the "real" version
X** will be better, and available soon.
X*/
X
X#include "config.h"
X
X#ifdef ANSI_HDRS
X#include <stdlib.h>
X#include <stddef.h>
X#include <string.h>
X#include <io.h>
X#include <time.h>
X#endif /* ANSI_HDRS */
X
X#include <stdio.h>
X#include <ctype.h>
X#include <setjmp.h>
X
X#ifdef VMS
X#include <types.h>
X#else
X#include <sys/types.h>
X#endif /* VMS */
X
X/*
X** Let's play "find the header file."
X*/
X#ifdef IN_SYS_DIR
X#include <sys/dir.h>
X#endif /* IN_SYS_DIR */
X#ifdef IN_DIR
X#include <dir.h>
X#endif /* IN_DIR */
X#ifdef IN_DIRECT
X#include <direct.h>
X#endif /* IN_DIRECT */
X#ifdef IN_SYS_NDIR
X#include <sys/ndir.h>
X#endif /* IN_SYS_NDIR */
X#ifdef IN_NDIR
X#include "ndir.h"
X#endif /* IN_NDIR */
X#ifdef IN_DIRENT
X#include <dirent.h>
X#endif /* IN_DIRENT */
X
X
X/*
X** Handy shorthands.
X*/
X#define TRUE 1 /* What I tell you three times */
X#define FALSE 0 /* ... is false */
X#define OOB_FALSE 3 /* "Emergency" exit from unshar */
X#define WIDTH 72 /* Contents lines in shar.c */
X#define F_DIR 36 /* Something is a directory */
X#define F_FILE 65 /* Something is a regular file */
X#define SAFE_WIDTH 78 /* Warn if longer than this */
X#define READ_CHUNK 100 /* Size of binary-test chunk */
X#define UULINE_SIZE 45 /* Size of uuencode chunk */
X#define UUTABLE_SIZE 127 /* Character mapping table */
X#define UUCHAR_DATA 64 /* Characters used in map */
X
X
X/*
X** These are used by the archive parser.
X*/
X#define LINE_SIZE 200 /* Length of physical input line*/
X#define MAX_VARS 20 /* Number of shell vars allowed */
X#define MAX_WORDS 30 /* Make words in command lnes */
X#define VAR_NAME_SIZE 30 /* Length of a variable's name */
X#define VAR_VALUE_SIZE 128 /* Length of a variable's value */
X
X
X#ifndef L_ctermid
X#define L_ctermid 50
X#endif /* L_ctermid */
X
X/*
X** Lint placation.
X*/
X#ifdef lint
X#undef RCSID
X#undef putc
X#undef putchar
X#endif /* lint */
X#define Printf (void)printf
X#define Fprintf (void)fprintf
X
X
X/*
X** Memory hacking.
X*/
X#define NEW(T, count) ((T *)getmem(sizeof (T), (unsigned int)(count)))
X#define COPY(s) strcpy(NEW(char, strlen((s)) + 1), (s))
X
X
X/*
X** Macros.
X*/
X#define BADCHAR(c) (!isascii((c)) || (iscntrl((c)) && !isspace((c))))
X#define HDRCHAR(c) ((c) == '-' || (c) == '_' || (c) == '.')
X#define EQ(a, b) (strcmp((a), (b)) == 0)
X#define EQn(a, b, n) (strncmp((a), (b), (n)) == 0)
X#define PREFIX(a, b) (EQn((a), (b), sizeof b - 1))
X#define WHITE(c) ((c) == ' ' || (c) == '\t')
X
X
X/*
X** Linked in later.
X*/
Xextern int optind;
Xextern char *optarg;
X
X#ifndef ANSI_HDRS
Xextern int errno;
X
X/* From your C run-time library. */
Xextern FILE *popen();
Xextern time_t time();
Xextern long atol();
Xextern char *IDX();
Xextern char *RDX();
Xextern char *ctime();
Xextern char *gets();
Xextern char *mktemp();
Xextern char *strcat();
Xextern char *strcpy();
Xextern char *strncpy();
Xextern char *getenv();
X#ifdef PTR_SPRINTF
Xextern char *sprintf();
X#endif /* PTR_SPRINTF */
X#ifdef USE_SYSERRLIST
Xextern int sys_nerr;
Xextern char *sys_errlist[];
X#endif /* USE_SYSERRLIST */
X
X#endif /* ANSI_HDRS */
X
X
X/* From our local library. */
X
X#ifdef DECLARE_PROTOTYPES
X
Xextern char *Ermsg(int);
Xextern char *GetDir(char *, int);
Xextern char *Host();
Xextern char *Seechar(int);
Xextern char *User();
Xextern align_t getmem(unsigned int, unsigned int);
Xextern off_t Fsize(char *);
Xextern int Argify(char **);
Xextern int Exec(char **);
Xextern int Execute(char **);
Xextern int Fexecute(char *);
Xextern int Fexists(char *);
Xextern int Ftype(char *);
Xextern int GetLine(int);
Xextern int GetStat(char *);
Xextern int IsProbablySource(char *);
Xextern int MakeTempName(char *, char *);
Xextern int Pid();
Xextern int SafeRename(char *);
Xextern int SetSigs(sigret_t (*)());
Xextern int getopt(int, char **, char *);
Xextern void SetVar(char *, char *);
Xextern void SynErr(char *);
X
X#else
X
Xextern char *Ermsg();
Xextern char *GetDir();
Xextern char *Host();
Xextern char *Seechar();
Xextern char *User();
Xextern align_t getmem();
Xextern off_t Fsize();
Xextern int Argify();
Xextern int Exec();
Xextern int Execute();
Xextern int Fexecute();
Xextern int Fexists();
Xextern int Ftype();
Xextern int GetLine();
Xextern int GetStat();
Xextern int IsProbablySource();
Xextern int MakeTempName();
Xextern int Pid();
Xextern int SafeRename();
Xextern int SetSigs();
Xextern int getopt();
Xextern void SetVar();
Xextern void SynErr();
X
X#endif /* DECLARE_PROTOTYPES */
END_OF_FILE
if test 5115 -ne `wc -c <'shar.h'`; then
echo shar: \"'shar.h'\" unpacked with wrong size!
fi
# end of 'shar.h'
fi
if test -f 'uudecode.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'uudecode.c'\"
else
echo shar: Extracting \"'uudecode.c'\" \(4417 characters\)
sed "s/^X//" >'uudecode.c' <<'END_OF_FILE'
X/*
X** UUDECODE
X**
X** Decode printable representation of binary data. This is based on the
X** public-domain implementation that Mark Horton released to mod.sources
X** with the translation table written by Jean-Pierre H. Dumas.
X*/
X#include "shar.h"
X#ifdef RCSID
Xstatic char RCS[] =
X "$Header$";
X#endif /* RCSID */
X
X/* single character decode */
X#define DEC(c) (((c) - ' ') & 077)
X
X#undef DEC
X#define DEC(c) (Table[(c)])
X
Xstatic char Table[UUTABLE_SIZE];
X
X
X/*
X** Read in the translation table.
X*/
Xstatic void
XGetTable()
X{
X REGISTER char *p;
X REGISTER int c;
X REGISTER int n;
X char buff[BUFSIZ];
X
X /* Clear it out; kinda messy, but one less config parameter... */
X for (p = Table, n = sizeof Table; --n >= 0; p++)
X *p = '\0';
X
X /* Read lines until we hit the all the data elements. */
X for (n = 0; ; ) {
X
X /* Get a line. */
X if (fgets(buff, sizeof buff, stdin) == NULL) {
X Fprintf(stderr, "EOF in translation table, %s\n", Ermsg(errno));
X exit(1);
X }
X if (EQn(buff, "begin", 5)) {
X Fprintf(stderr, "Incomplete translation table.\n");
X exit(1);
X }
X
X /* Strip trailing spaces. */
X for (p = &buff[strlen(buff)]; p > buff && (*--p == '\n' || WHITE(*p)); )
X *p = '\0';
X if (Table[c]) {
X
X /* Rest of the line is part of our table. */
X for (p = buff; c = *p; p++) {
X Fprintf(stderr,
X "Duplicate character 0%0 (%s) in translation table.\n",
X Table[c], Seechar(Table[c]));
X exit(1);
X }
X Table[c] = n;
X if (++n >= UUCHAR_DATA)
X return;
X }
X }
X}
X
Xmain(ac, av)
X int ac;
X char *av[];
X{
X REGISTER FILE *Out;
X REGISTER char *p;
X REGISTER int n;
X REGISTER int c;
X char Name[128];
X char buff[80];
X int mode;
X int Oops;
X
X /* Parse JCL. */
X for (Oops = FALSE; (n = getopt(ac, av, "")) != EOF; )
X switch (n) {
X default:
X Oops = TRUE;
X break;
X }
X ac -= optind;
X av += optind;
X
X if (!Oops)
X switch (ac) {
X default:
X Oops = TRUE;
X break;
X case 0:
X break;
X case 1:
X if ((freopen(*av, "r", stdin)) == NULL) {
X Fprintf(stderr, "Can't open \"%s\" for input, %s.\n",
X *av, Ermsg(errno));
X exit(1);
X /* NOTREACHED */
X }
X break;
X }
X
X if (Oops) {
X Fprintf(stderr, "Usage:\n uudecode %s\n", "[infile]");
X exit(1);
X /* NOTREACHED */
X }
X
X /* Set up default translation table. */
X for (n = 0, p = &Table[n]; n < ' '; n++)
X *p++ = '\0';
X for (c = 0; n < ' ' + UUCHAR_DATA; n++)
X *p++ = c++;
X for (; n < UUTABLE_SIZE; n++)
X *p++ = '\0';
X /* Space and backquote are same; 4.3 started using backquote to avoid
X * BITNET lossage of removing trailing spaces. Uparrow and tilde are
X * another common BITNET munge, which also luckily map to the same thing. */
X Table['`'] = Table[' '];
X Table['~'] = Table['^'];
X
X /* Get header line. */
X do {
X if (fgets(buff, sizeof buff, stdin) == NULL) {
X Fprintf(stderr, "Can't find \"begin\" line, %s.\n", Ermsg(errno));
X exit(1);
X /* NOTREACHED */
X }
X if (EQn(buff, "table", 5))
X GetTable();
X } while (!EQn(buff, "begin ", 6));
X if (sscanf(buff, "begin %o %s", &mode, Name) != 2) {
X Fprintf(stderr, "Malformed \"begin\" line.\n");
X exit(1);
X /* NOTREACHED */
X }
X
X /* Create output file. */
X if ((Out = fopen(Name, "w")) == NULL) {
X Fprintf(stderr, "Can't open \"%s\" for output, %s.\n",
X Name, Ermsg(errno));
X perror(Name);
X exit(1);
X /* NOTREACHED */
X }
X
X if (chmod(Name, mode) < 0)
X Fprintf(stderr, "Warning, can't chmod(\"%s\", 0%o), %s.\n",
X Name, mode, Ermsg(errno));
X
X /* Read and munch. */
X for ( ; ; ) {
X /* Read a line; zero datacount means end of data. */
X if (fgets(buff, sizeof buff, stdin) == NULL) {
X Fprintf(stderr, "Short file, %s.\n", Ermsg(errno));
X exit(1);
X /* NOTREACHED */
X }
X if ((n = DEC(buff[0])) <= 0)
X break;
X
X /* Decode it. */
X for (p = &buff[1]; n > 0; p += 4, n -= 3) {
X c = DEC(p[0]) << 2 | DEC(p[1]) >> 4;
X (void)putc(c, Out);
X if (n >= 2) {
X c = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
X (void)putc(c, Out);
X if (n >= 3) {
X c = DEC(p[2]) << 6 | DEC(p[3]);
X (void)putc(c, Out);
X }
X }
X }
X }
X
X /* Check for good ending. */
X if (fgets(buff, sizeof buff, stdin) == NULL || !EQ(buff, "end\n")) {
X Fprintf(stderr, "No end line\n");
X exit(1);
X /* NOTREACHED */
X }
X
X /* That's all she wrote. */
X (void)fclose(Out);
X (void)fclose(stdin);
X exit(0);
X /* NOTREACHED */
X}
END_OF_FILE
if test 4417 -ne `wc -c <'uudecode.c'`; then
echo shar: \"'uudecode.c'\" unpacked with wrong size!
fi
# end of 'uudecode.c'
fi
echo shar: End of archive 2 \(of 5\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 4 5 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 5 archives.
echo "Now go find those bugs, and report them to rsalz at uunet.uu.net"
rm -f ark[1-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
--
Please send comp.sources.unix-related mail to rsalz at uunet.uu.net.
More information about the Alt.sources
mailing list