[alt.sources] Rich $alz's cshar package, new alpha release, Part02/05

rsalz@bbn.com (Rich Salz) (02/21/89)

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@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(&reg, &nreg, &sreg);
X#else
X    intdos(&reg, &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(&reg, &nreg, &sreg);
X#else
X    reg.x.dx = (int)dtapnt;
X    intdos(&reg, &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@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@uunet.uu.net.