[alt.sources] shar 3.49

rhg@cpsolv.CPS.COM (Richard H. Gumpertz) (09/13/90)

Submitted-by: rhg@cpsolv
Archive-name: shar3.49/part01

Patch 3 to shar 3.43 was relative to the wrong version of Makefile.  Rather
than try to patch a patch and all that, here is the whole thing.

---- Cut Here and feed the following to sh ----
#!/bin/sh
# This is shar3.49, a shell archive (produced by shar 3.49)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
# made 09/12/1990 20:16 UTC by rhg@cpsolv
# Source directory /u/rhg/src/shar
#
# existing files will NOT be overwritten unless -c is specified
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#  10942 -rw-r--r-- README
#   3696 -rw-r--r-- Makefile
#   7946 -rw-r--r-- shar.1
#   1515 -rw-r--r-- unshar.1
#   1365 -rw-r--r-- uushar.c
#   3077 -rw-r--r-- who@where.c
#  11602 -rw-r--r-- unshar.c
#  38151 -rw-r--r-- shar.c
#
# ============= README ==============
if test -f 'README' -a X"$1" != X"-c"; then
	echo 'x - skipping README (File already exists)'
else
echo 'x - extracting README (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'README' &&
XThis file last revised Sat Aug 4 17:15:01 CDT 1990
X
XHere is shar 3.49, an updated version of shar 3.43, derived from 'shar2'.
XThis offering is the work of many people.  Thanks to wht@n4hgf.Mt-Park.GA.US
X(Warren Tucker), rhg@CPS.COM (Richard H. Gumpertz), colas@avahi.inria.fr
X(Colas Nahaboo), bill@netagw.com (Bill Aten), marks@rex.cs.tulane.edu, and
Xmaaaany others.
X
XThis version's shar:
X1) generates shell code which attempts to create missing directories
X2) generates shell code which will force overwriting of files when passed
X   the '-c' option.
X3) allows entire directories to be archived
X4) handle deviants sun, vax, pyramid, sequent, and SCO XENIX/UNIX
X   automatically; for system V systems I did not catch, add -DSYS5
X   to CFLAGS; for other BSD-like systems, add -DBSD42
X5) if unsharing system's touch is Sys V compatible (allows touch -m),
X   the unshar process restores file dates (-m switch)
X6) An archive name may be specified for inclusion in the header
X   of the shar files (-n switch)
X7) allows automatic generation of "Submitted-by: who@where" &
X   "Archive-name: <name>/part##" headers
X8) uses getopt; no good system library should be without a copy
X   but it is readily available (like look in unshar.c)
X9) includes other chrome-plated bells, whistles, and junque
X
XThis version's unshar:
X1) can change directory before unsharing
X2) can unshar from standard in, from a COLLECTION of shars,
X   from a file containing multiple concatenated shars,
X   or a mixture of shar files and concatenated-shar files.
X3) can pass the '-c' option on to the script being extracted.
X4) does not have a Social Security number.
X
X------------------------ shar  usage -----------------------------------
Xshar 3.49
Xusage: shar [ options ] file ...
X       shar -S [ options ]
X-V  produce "vanilla" shars demanding little of the unshar environment
X-v  verbose messages OFF while executing
X-m  restore file modification dates & times with "touch" commands
X-w  don't check with 'wc -c' after unpack
X-a  generate Submitted-by: & Archive-name: headers
X-nXXX   use XXX as the name of the archive (documentation)
X-s  override automatically determined submitter name
X-x  overwrite existing files without checking if they already exist
X-X  interactively overwrite existing files (NOT FOR NET SHARS)
X-B  treat all files as binary, use uuencode
X-T  treat all files as text (default)
X-C  compress and uuencode all files
X-bXX    pass -bXX (default 12) to compress when compressing (implies -C)
X-p  allow positional parameter options. The options "-B" and "-B"
X    and "-C" may be embedded, and files to the right of the
X    option will be processed in the specified mode
X-M  mixed mode. Determine if the files are text or
X    binary and archive correctly.
X-P  use temp files instead of pipes in the shar file
X-F  force the prefix character on every line (even if not required)
X-c  start the shar with a cut line
X-f  restore by filename only, rather than path
X-dXXX   use XXX to delimit the files in the shar
X-oXXX   (or -o XXX) output to file XXX.01 thru XXX.nn
X-lXX    limit output file size to XXk bytes (but don't split files)
X-LXX    limit output file size to XXk bytes (may split files)
X-S      read files to wrap from stdin, ignoring argument line
X
XThe -S option reads filenames one per line from stdin; input
Xformat must be similar to 'find' output, except that if -p
Xis specified, -B, -T or -C may be used (on lines by themselves)
Xe.g., find . -type f -print | sort | shar -C -l50 -o /tmp/big
X
XThe 'o' option is required if the 'l' or 'L' option is used
XThe 'n' option is required if the 'a' option is used
X
X-a generates sharname/part## headers. If the -a argument contains
Xa '/', then /part is not appended
XThe automatic submitter name is trivial: essentially `whoami`@`uname`
X
X------------------------ unshar usage -----------------------------------
XUnshar has no usage built in.  It has default actions when invoked
Xwith no arguments (read from stdin).
X
XUsage:     unshar [ -d directory ] [ -c ] [ -e | -E exit_line ] [ files ... ]
X
X      The -c flag is passed through to the shell as a parameter to the script
X      It can unshar shar files concatenated in one file, with the
X      the "-e" command, which separates files by recognizing the
X      "exit 0" string at the beginning of a line
X
X      (The -E string option allows you to specify this string, thus
X      -e is equivalent to -E "exit 0")
X
X      The -d flag tells unshar to change directory before unsharing
X
X
X--------------------- history -----------------------------------------
XChanges since 3.11: kudos to rhg@CPS.COM (Richard H. Gumpertz)
X
X1.  The -l switch still specifies a maximum size for the generated
X    shar files, but now it prevents files from spanning shar parts.
X    Shars generated using this method may be unpacked in any order.
X
X2.  The old -l switch functionality is precisely emulated by using the
X    the -L switch.  That is, archived files may be split across parts.
X    Shars generated using this method must still be unpacked in order.
X
X3.  The -C switch causes files to be compressed, then uuencoded.
X    Unpacking reverses the process.
X
X4.  The -P causes the shar to use temp files instead of pipes in
X    the unshar process.
X
X5.  The -f causes files to be resotred by name only (i.e., strip
X    directory portion of input filenames before placing the name
X    into the shar.
X
X
XChanges since 3.20: kudos to colas@avahi.inria.fr (Colas Nahaboo)
X
X1.  The Archived-name: header no longer uses "/part" if there is
X    a "/" in the -n name.  Thus
X        -n xyzzy                     procduces:
X                                     xyzzy/part01
X                                     xyzzy/part02
X
X        -n xyzzy/patch               procduces:
X                                     xyzzy/patch01
X                                     xyzzy/patch02
X
X        -n xyzzy/patch01.            procduces:
X                                     xyzzy/patch01.01
X                                     xyzzy/patch01.02
X2.  The Archive-name part number other than part01 had no leading zero
X    in the number.
X
X3.  The "Submitted-by:" header was missing the hyphen (minus for olde
X    UNIX hackres).
X
X4.  The unshar program may now unshar a whole mailbox or concatenation
X    of shar files.
X
X    -C "string" looks for "string" at the beginning of the line to
X       break the file into individual shar files
X    -c is equivalent to -C "exit 0"
X
X    This of course will only work if there is something in the shar
X    file recognizable to terminate the shar.  Some shars dont have
X    "exit 0" at the end.  However, a clue: most/many .signatures have
X    "--" on a line right before them.
X
X5.  Unshar -d (change directory) no longer makes argv files unreachable.
X    I had never used the feature until the other day.  I guess the
X    author has used in only for unsharing from stdin.
X
XChanges since 3.21: thanks to Adri Verhoef, <a3@rivm.UUCP>
X
X1.  Some vaxen do not run BSD.  I guess I knew this, but -er-
X    here is Adri's note:
X> Hi Warren,
X> 
X>   I encountered a problem trying to get 'shar3.21' to compile on System V
X> on a vax.  Yes, can you believe it?  We run System V Release 3.0 on VAXen!
X> The shar3.21 code assumes that you are BSD if you're on a vax.  This is not
X> always true!  What I did to get the code compiled on System V, was:
X> (+) edit the Makefile and add -DSYS5 to CFLAGS.
X> (+) edit all the C-source files to circumcise compiler warnings
X>     ("SYS5 redefined").
X> 
X
XHe made a suggestion about having a localize.sh edit a distribution
XMakefile, but for now, I'll just suggest you add -DSYS5 to CFLAGS 
Xmanually.
X
X2.  jhd@irfu.se (Jan Dj{rv, sorry about the screwed up character
X    translation, Jan) wrote man pages.  Thanks!
X
XChanges since 3.22: thanks to Dennis Boylan <dennis@nanovx>
X
X1.  The new -S option allows the list of files to be packed
X    to be read from the standard input rather than from the
X    command line.
X
X2.  A few purist checks were made to ensure fork() or malloc()
X    doesn't fail and excite the "if 20 hours of your time is
X    free then why isn't 200?" crowd (who probably will never see
X    this revision anyway :-))
X
XChanges since 3.23:
X
X1.  The -V mode was added.
X
X2.  Altos doesn't like the '@' in filenames.  The filename format
X    was changed.  Thanks to rhg@cps.com.
X
XChanges since 3.24:
X
X1.  Man pages were revised by gam@netcom (Gordon Moffet). Thanks.
X
X2.  When -L was specified, the "Starting ..." message was not
Xproduced on standard error (with or without -v).
X
X3.  When using -X, the 'not for net' warning was printed on standard
Xoutput rather thsn standard error.
X
X4.  marks@rex.cs.tulane.edu reccommends adding -F 5000 to the load
X    line of unshar when using on XENIX 286 to avoid stack overflow
X    core dumps.  I added this information to an excellkent remake
X    of the Makefile by bill@netagw.com.
X
XChanges since 3.25:
X
X1.  Fixed one minor bug with -a/-n.  The period supplied when a
X    slash appears in the -n name was omitted.  This is a hatefully
X    small bug to fix and reissue a whole release, but
X    a) several new names are on the sharlist now and they have
X       only 3.24 to work with,
X    b) this will surely sync us all up, and
X    c) I think it will put shar to bed for a while ("no known bugs
X       at this ti ... bus error core dumped").
X
XChanges since 3.27:
X
X1.  The unshar-time test for a touch -m facility now greps for
X    'mmdd', not '[-amc]', making it more universally successful.
X
X2.  NOTE:  there is still a problem with -n arguments using
X    a 'x/y' construct, but I don't know how to properly generalize
X    it so you'll have to edit shars made with some uses of -a
X    with -n x/y.
X
X3.  This is surely my last work on this.  It does everything
X    I needed and more.  Thanks for all the help and suggestions.
X    It seems as though we didn't precipitate 'death of the shar'
X    after all :-) :-) :-).
X
XChanges since 3.32:
X
X1.  Several bug fixes.
X
X2.  Inverted the meaning of '-x'; the new default is to NOT overwrite.
X
X3.  Added '-c' checking when unpacking so the recipient can force overwrites.
X
X4.  Made '-L' work even with files not being overwritten.
X
X5.  Added '-m' and changed the default behavior to not generate TOUCH commands.
X
X6.  Added '-F'; the default is to suppress the extra 'X' at the beginning of
X    each line unless it is needed (i.e., the first character of the line is
X    already 'X' or is a non-graphic).
X
X7.  Renamed '-b' and '-t' to '-B' and '-T', respectively.
X
X8.  Added '-bn' for use with compression (calls compress with -bn).
X
X9.  Renamed the temporary files used in unpacking from shar3_???_.tmp to
X    _shar_???_.tmp.
X
X10. Directories may now be passed to shar; a recursive directory walk is
X    performed.  This feature may be disabled by compiling with -DNO_WALKTREE.
X
XChanges since 3.43:
X
X1.  Several more minor bug fixes.
X
X2.  Added support for BSD-style <sys/dir.h> and -ldir.
X
X3.  Added more usage directions to the shar header.
SHAR_EOF
chmod 0644 README ||
echo 'restore of README failed'
Wc_c="`wc -c < 'README'`"
test 10942 -eq "$Wc_c" ||
	echo 'README: original size 10942, current size' "$Wc_c"
fi
# ============= Makefile ==============
if test -f 'Makefile' -a X"$1" != X"-c"; then
	echo 'x - skipping Makefile (File already exists)'
else
echo 'x - extracting Makefile (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'Makefile' &&
X#  makefile for shar
X#
X# $Header: /u/rhg/src/shar/Makefile,v 3.49 90/09/12 15:14:18 rhg Exp $
X#
X#+:EDITS:
X#:09-09-1990-20:12-rhg@cps.com-added CLOSEDIR_VOID
X#:09-09-1990-11:31-bill@netagw.com-add SHELL variable/-ldir for XENIX/UNIX 386
X#:08-07-1990-21:25-rhg@cps.com-compress man pages if MANEXT ends with .Z
X#:08-05-1990-23:50-rhg@cps.com-add post and compressed.
X#:08-05-1990-12:19-rhg@cps.com-add LIBS and -ldirent
X#:08-04-1990-18:51-rhg@cps.com-add CC, LD; move strip; reorder chgrp/chown.
X#:05-14-1990-17:33-wht@n4hgf-add -F 5000 for XENIX 286
X#:05-14-1990-17:32-bill@netagw.com-expanded Makefile
X#:03-28-1990-14:54-wht@n4hgf-for 3.10, add who@where.c
X
XSHELL=/bin/sh
X
XBINDIR	= /usr/local/bin
XOWNER	= bin
XGROUP	= bin
XBINMODE	= 0755
XMANDIR	= /usr/man/man1
XMANEXT	= 1
XMANOWN	= bin
XMANGRP	= bin
XMANMODE	= 0644
X
XCC	= cc
XLD	= ${CC}
X
X# If you don't have Doug Gwyn's dirent routines or equivalent, then remove
X# -ldirent from LIBS and add -DNO_WALKTREE to CFLAGS.  All you will give up
X# is the ability to shar directorys without using "find ... -type f | shar -S".
X# Note that many systems have the equivalent of the dirent library built into
X# the standard C library.  For such systems, just remove -ldirent from LIBS.
X# (note by RHG@CPS.COM: I don't know which systems listed below are like that.)
X# Some systems, such as SCO XENIX/UNIX 386 use -ldir instead.
X# Some systems, such as SunOS 3, use <sys/dir.h> instead of <dirent.h>.  For
X# these systems, add -DNO_DIRENT to CFLAGS.  Many of these same systems, such
X# as BSD, have a closedir that has no return value.  For these systems, add
X# both -DNO_DIRENT and -DCLOSEDIR_VOID to CFLAGS.
X
X# For VAX, PYRAMID, SEQUENT, AT&T 3B1/7300
XCFLAGS	= -O 
XLDFLAGS	=
XLIBS	= -ldirent
X
X# For SUN
X#CFLAGS	= -O -DNO_DIRENT -DCLOSEDIR_VOID
X#LDFLAGS	=
X#LIBS	=
X
X# For SCO XENIX/UNIX 386
X#CFLAGS	= -O -DNO_DIRENT -DCLOSEDIR_VOID
X#LDFLAGS	=
X#LIBS	= -ldir
X
X# For SCO XENIX 286
X#CFLAGS	= -O 
X#LDFLAGS	= -F 5000
X#LIBS	= -ldirent
X
X# For other System V systems I did not catch
X#CFLAGS	= -O -DSYS5
X#LDFLAGS	=
X#LIBS	= -ldirent
X
X# For BSD-like systems
X#CFLAGS	= -O -DBSD42 -DNO_DIRENT -DCLOSEDIR_VOID
X#LDFLAGS	=
X#LIBS	=
X
XSOURCES	= README Makefile shar.1 unshar.1 uushar.c who@where.c unshar.c shar.c
X
XSHAR	= shar.o uushar.o who@where.o
XUNSHAR	= unshar.o
X
Xall: shar unshar
X
Xshar: ${SHAR}
X	${LD} ${LDFLAGS} ${SHAR} ${LIBS} -o shar
X
Xunshar : ${UNSHAR}
X	${LD} ${LDFLAGS} ${UNSHAR} ${LIBS} -o unshar
X
Xshar.o : shar.c
X	${CC} ${CFLAGS} -c shar.c
X
Xunshar.o : unshar.c
X	${CC} ${CFLAGS} -c unshar.c
X
Xuushar.o : uushar.c
X	${CC} ${CFLAGS} -c uushar.c
X
Xwho@where.o : who@where.c
X	${CC} ${CFLAGS} -c who@where.c
X
Xinstall : shar unshar
X	strip shar unshar
X	cp shar unshar ${BINDIR}
X	chmod ${BINMODE} ${BINDIR}/shar ${BINDIR}/unshar
X	chgrp ${GROUP} ${BINDIR}/shar ${BINDIR}/unshar
X	chown ${OWNER} ${BINDIR}/shar ${BINDIR}/unshar
X	if expr "${MANEXT}" : ".*\.Z$$" >/dev/null; then \
X		compress -b14 < shar.1   > ${MANDIR}/shar.${MANEXT}; \
X		compress -b14 < unshar.1 > ${MANDIR}/unshar.${MANEXT}; \
X	else \
X		cp shar.1   ${MANDIR}/shar.${MANEXT}; \
X		cp unshar.1 ${MANDIR}/unshar.${MANEXT}; \
X	fi
X	chmod ${MANMODE} ${MANDIR}/shar.${MANEXT} ${MANDIR}/unshar.${MANEXT}
X	chgrp ${MANGRP}  ${MANDIR}/shar.${MANEXT} ${MANDIR}/unshar.${MANEXT}
X	chown ${MANOWN}  ${MANDIR}/shar.${MANEXT} ${MANDIR}/unshar.${MANEXT}
X
Xclean :
X	rm -f shar unshar *.o core
X
XSETV =	X="`head -1 shar.c`"; \
X	V=`expr "$$X" : 'char \*revision = "\([1-9][0-9]*\.[0-9.a-zA-Z]*\)";$$'`;
X
Xpost : ${SOURCES}
X	${SETV} test -n "$$V" && ( \
X	rm -f shar$$V.[0-9][0-9]; \
X	shar -l50 -acF -n "shar$$V" -o "shar$$V" ${SOURCES} )
X
Xcompressed : ${SOURCES}
X	${SETV} test -n "$$V" && \
X	shar -acFm -b16 -n "shar$$V" > "shar$$V" ${SOURCES}
X
SHAR_EOF
chmod 0644 Makefile ||
echo 'restore of Makefile failed'
Wc_c="`wc -c < 'Makefile'`"
test 3696 -eq "$Wc_c" ||
	echo 'Makefile: original size 3696, current size' "$Wc_c"
fi
# ============= shar.1 ==============
if test -f 'shar.1' -a X"$1" != X"-c"; then
	echo 'x - skipping shar.1 (File already exists)'
else
echo 'x - extracting shar.1 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'shar.1' &&
X.TH SHAR 1 "August 12, 1990"
X.SH NAME
Xshar \- create shell archives
X.SH SYNOPSIS
X.nf
Xshar [ options ] file ...
Xshar \-S [ options ]
X.fi
X.SH DESCRIPTION
XShar
Xcreates "shell archives" (or shar files) which are in text format
Xand can be mailed. These files may be unpacked later by executing them
Xwith /bin/sh. The resulting archive is sent to standard out unless the
X\f2\-o\f1 option is given.  A wide range of features provide extensive
Xflexibility in manufacturing shars and in specifying shar "smartness."
XArchives may be "vanilla" or comprehensive.
XThis manual page reflects shar version 3.49.
X.SS OPTIONS
X.PP
XOptions can be given in any order. Some options depend on each other:
X.nf
X	The \f2\-o\f1 option is required if the \f2\-l\f1 or \f2\-L\f1 option is used.
X	The \f2\-n\f1 option is required if the \f2\-a\f1 option is used.
X	See \f2\-V\f1 below.
X.fi
X.IP "\f2\-V\f1"
XProduce "vanilla" shars which rely only upon the existence of sed and
Xecho in the unsharing environment.  In addition, "if test" must also be
Xsupported if the \f2\-X\f1 option is used.  The \f2\-V\f1 silently
Xdisables options offensive to the "network cop" (or "brown shirt"), but
Xdoes warn you if it is specified with \f2\-B\f1, \f2\-C\f1, \f2\-p\f1
Xor \f2\-M\f1 (any of which does or might require uudecode or compress in
Xthe unsharing environment).
X.IP "\f2\-v\f1"
XVerbose OFF. Disables the inclusion of comments to be output when the archive
Xis unpacked.
X.IP "\f2\-w\f1"
XDo NOT check with 'wc \-c' after unpack. The default is to check.
X.IP "\f2\-n\f1 name"
XName of archive to be included in the header of the shar files.
XSee the \f2\-a\f1 switch.
X.IP "\f2\-a\f1"
XAllows automatic generation of headers:
X.nf
X	Submitted-by: who@where
X	Archive-name: <name>/part##
X.fi
XThe <name> must be given with the \f2\-n\f1 switch.
XIf name includes a '/' "/part" isn't used. Thus:
X.RS 10m
X.nf
X.ta 30m
X\-n xyzzy	produces:
X	xyzzy/part01
X	xyzzy/part02
X
X\-n xyzzy/patch	produces:
X	xyzzy/patch01
X	xyzzy/patch02
X
X\-n xyzzy/patch01.	produces:
X	xyzzy/patch01.01
X	xyzzy/patch01.02
X.RE
X.fi
X.IP ""
XThe who@where can be
Xexplicitly stated with the \f2\-s\f1 switch if the default isn't apropriate.
XWho@where is essentially built as `whoami`@`uname`.
X.IP "\f2\-s\f1 who@where"
XOverride automatically determined submitter name.
X.IP "\f2\-x\f1"
XOverwrite existing files without checking.
XIf neither \f2\-x\f1 nor \f2\-X\f1 is specified, the unpack will
Xcheck for and
Xnot overwrite existing files when unpacking the archive
X(unless '\-c' is passed as a parameter to the script when unpacking).
X.IP "\f2\-X\f1"
XInteractively overwrite existing files
X(DO NOT USE FOR SHARS SUBMITTED TO THE NET).
X.IP "\f2\-B\f1"
XTreat all files as binary, use uuencode prior to packing. This increases the
Xsize of the archive. The recipient must have uudecode in order to unpack.
X(USE OF UUENCODE IS NOT APPRECIATED BY MANY ON THE NET).
X.IP "\f2\-T\f1"
XTreat all files as text (default).
X.IP "\f2\-C\f1"
XCompress and uuencode all files prior to packing. The recipient must have
Xuudecode and uncompress in order to unpack
X(USE OF UUENCODE AND COMPRESS IS NOT APPRECIATED BY MANY ON THE NET).
X.IP "\f2\-m\f1"
XGenerate 'touch' commands to restore the file modification dates when
Xunpacking files from the archive.
X.IP "\f2\-p\f1"
XAllow positional parameter options. The options "\f2\-B\f1" and "\f2\-T\f1"
Xand "\f2\-C\f1" may be embedded, and files to the right of the
Xoption will be processed in the specified mode.
X.IP "\f2\-b\f1 X"
XWhen doing compression, use '\-bX' as a parameter to compress.
XThe \f2\-B\f1 options turns on the \f2\-C\f1 option by default.
X.IP "\f2\-M\f1"
XMixed mode. Determine if the files are text or binary and archive correctly.
XFiles found to be binary are uudecoded prior to packing
X(USE OF UUENCODE IS NOT APPRECIATED BY MANY ON THE NET).
X.IP "\f2\-P\f1"
XUse temporary files instead of pipes in the shar file.
X.IP "\f2\-c\f1"
XStart the shar with a cut line. A line saying 'Cut here' is placed at the
Xstart of each output file.
X.IP "\f2\-f\f1"
XRestore by filename only, rather than path. This option causes only file
Xnames to be used, which is useful when building a shar from several
Xdirectories, or another directory.  Note that if a directory name is passed
Xto shar, the substructure of that directory will be restored whether \f2\-f\f1
Xis specified or not.
X.IP "\f2\-d\f1 XXX"
XUse XXX to delimit the files in the shar instead of SHAR_EOF.
XThis is for those who want to personalize their shar files.
X.IP "\f2\-F\f1"
XForces the prefix character (normally 'X' unless the parameter to the \f2\-d\f1
Xoption starts with 'X') to be prepended to every line even if
Xnot required.  This option may slightly increase the size of the archive,
Xespecially if \f2\-B\f1 or \f2\-C\f1 is used.
X.IP "\f2\-o\f1 XXX"
XSave the archive to files XXX.01 thru XXX.nn instead of standard out.
XMust be used when the \f2\-l\f1 or the \f2\-L\f1 switches are used
X.IP "\f2\-l\f1 XX"
XLimit the output file size to XXk bytes but don't split input files.
X.IP "\f2\-L\f1 XX"
XLimit output file size to XXk bytes and split files if necessary. The archives
Xcreated with this option must be unpacked in correct order.
X.IP "\f2\-S\f1"
XRead list of files to be packed from the standard input rather than
Xfrom the command line.  Input must be in a form similar to
Xthat generated by the find command, one filename per line.  This
Xswitch is especially useful when the command line will not hold
Xthe list of files to be packed. For example:
X.nf
X
Xfind . \-type f \-print | sort | shar \-S \-C \-L50 \-o /tmp/big
X
X.fi
XIf \f2\-p\f1 is specified on the command line, then the 
Xoptions "\f2\-B\f1" and "\f2\-T\f1" and "\f2\-C\f1" may be included
Xin the standard input (on a line separate from filenames).
XThe maximum number of lines of standard input, file names
Xand options, may not exceed 1024.
X.SH EXAMPLES
X.nf
X.ta 37m
Xshar *.c > cprog.shar	# all C prog sources
Xshar \-v *.[ch] > cprog.shar	# non-verbose, .c and .h files
Xshar \-B \-l28 \-oarc.sh *.arc	# all binary .arc files, into
X	# files arc.sh.01 thru arc.sh.NN
Xshar \-f /lcl/src/u*.c > u.sh	# use only the filenames
X.ta
X.fi
X.SH WARNINGS
X.PP
XNo chmod or touch is ever generated for directories created when unpacking.
XThus, if a directory is given to shar, the protection and
Xmodification dates of corresponding unpacked directory
Xmay not match those of the original.
X.PP
XIf a directory is passed to shar, it may be scanned more than once.  Therefore,
Xone should be careful not change the directory while shar is running.
X.PP
XBe careful that the output file(s) are not included in the inputs or shar
Xmay loop until the disk fills up.  Be particularly careful when a directory
Xis passed to shar that the output files are not in that directory
X(or a subdirectory of that directory).
X.PP
XUse of the \f2\-B\f1, \f2\-M\f1 or \f2\-C\f1 may slow the archive process
Xconsiderably, depending on the number of files.
X.PP
XUse of \f2\-X\f1 produces shars which \f2WILL\f1 cause problems
Xwith many unshar procedures.  Use this feature only for archives
Xto be passed among agreeable parties.  Certainly, \f2\-X\f1 is NOT
Xfor shell archives which are to be submitted to Usenet.
XUsage of \f2\-B\f1 or \f2\-C\f1 in net shars will cause you to
Xbe flamed off the earth.
XUsing \f2\-m\f1 or not using \f2\-F\f1 may also get you occasional complaints.
X.SH SEE ALSO
X.PP 
Xunshar(1)
X.SH DIAGNOSTICS
X.PP
XError messages for illegal or incompatible options,
Xfor non-regular, missing or inaccessible files or for (unlikely)
Xmemory allocation failure.
X.SH AUTHORS
X.nf
Xshar3 is a derived work based on the efforts of:
Xdecvax!microsof!uw-beave!jim (James Gosling at CMU)
XMichael A. Thompson, Dalhousie University, Halifax, N.S., Canada
Xdavidsen@sixhub (Bill Davidsen)
Xrhg@CPS.COM (Richard H. Gumpertz)
Xcolas@avahi.inria.fr (Colas Nahaboo)
Xbill@netagw.com (Bill Aten)
Xdennis%nanovx@gatech.edu (Dennis Boylan)
Xwht%n4hgf@gatech.edu (Warren Tucker)
X(other anonymous persons)
X
Xman pages:
Xjhd@irfu.se (Jan Dj{rv)
X.fi
SHAR_EOF
chmod 0644 shar.1 ||
echo 'restore of shar.1 failed'
Wc_c="`wc -c < 'shar.1'`"
test 7946 -eq "$Wc_c" ||
	echo 'shar.1: original size 7946, current size' "$Wc_c"
fi
# ============= unshar.1 ==============
if test -f 'unshar.1' -a X"$1" != X"-c"; then
	echo 'x - skipping unshar.1 (File already exists)'
else
echo 'x - extracting unshar.1 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'unshar.1' &&
X.TH UNSHAR 1 "August 12, 1990"
X.SH NAME
Xunshar \- unpack a shar file
X.SH SYNOPSIS
Xunshar [ \f2\-d\f1 directory ] [ \f2\-c\f1 ] [ \f2\-e\f1 | \f2\-E\f1 exit_line ] [ file ... ]
X.SH DESCRIPTION
X.PP
XUnshar scans mail messages looking for the start of a shell archive. It
Xthen passes the archive through a copy of the shell to unpack it. It
Xwill accept multiple files. If no files are given, standard input is used.
X.PP
XThe \f2\-d\f1 option tells unshar to change directory before unpacking
Xany files.
X.PP
XThe \f2\-c\f1 option is passed through to 'sh' as a parameter to the unpacked
Xscript.  Many archive shar scripts (including those produced by
Xshar 3.40 and newer)
Xuse this to indicate that existing files should be overwritten.
X.PP
XUnshar can unpack shar files that are concatenated in one file with the
X\f2\-e\f1 option, which separates files by recognizing the "exit 0" string
Xat the beginning of a line. 
XThe \f2\-E\f1 option allows you to specify the string that separates archives
Xif "exit 0" isn't appropriate. (Hint: most .signatures have a "\-\-" on a line
Xright before them). \f2\-e\f1 is equivalent to \f2\-E "exit 0"\f1.
X.SH SEE ALSO
Xshar(1)
X.SH DIAGNOSTICS
XAny message from the shell may be displayed.
X.SH AUTHORS
X.nf
XMichael Mauldin at Carnegie-Mellon University
Xguido@mcvax (Guido van Rossum at CWI, Amsterdam)
Xdavidsen@sixhub.uuxp (Bill Davidsen)
Xwht%n4hgf@gatech.edu (Warren Tucker)
Xrhg@CPS.COM (Richard H. Gumpertz)
Xcolas@avahi.inria.fr (Colas Nahaboo)
X
Xman pages:
Xjhd@irfu.se (Jan Dj{rv)
X.fi
X.PP
SHAR_EOF
chmod 0644 unshar.1 ||
echo 'restore of unshar.1 failed'
Wc_c="`wc -c < 'unshar.1'`"
test 1515 -eq "$Wc_c" ||
	echo 'unshar.1: original size 1515, current size' "$Wc_c"
fi
# ============= uushar.c ==============
if test -f 'uushar.c' -a X"$1" != X"-c"; then
	echo 'x - skipping uushar.c (File already exists)'
else
echo 'x - extracting uushar.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'uushar.c' &&
X/* $Header: /u/rhg/src/shar/uushar.c,v 3.49 90/09/12 15:15:26 rhg Exp $ */
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X
X/* ENC is the basic 1 character encoding function to make a char printing */
X#if 1 /* Richard H. Gumpertz (RHG@CPS.COM), 24 April 1990 */
X#define ENC(c) ((((c) + 077) & 077) + 041)
X#else /* RHG */
X#define ENC(c) ((((c) & 077) + ' ') | ((c & 077) == 0 ? 0100 : 0))
X#endif /* RHG */
X
Xencode (in, out)
X    FILE *in;
X    FILE *out;
X{
X    char  buf[80];
X    int  i, n;
X
X    for (;;)
X    {
X    /* 1 (up to) 45 character line */
X	n = fr (in, buf, 45);
X	putc (ENC (n), out);
X
X	for (i = 0; i < n; i += 3)
X	    outdec (&buf[i], out);
X
X	putc ('\n', out);
X	if (n <= 0)
X	    break;
X    }
X}
X
X/*
X * output one group of 3 bytes, pointed at by p, on file f.
X */
Xoutdec (p, f)
X    char *p;
X    FILE *f;
X{
X    int  c1, c2, c3, c4;
X
X    c1 = *p >> 2;
X    c2 = (*p << 4) & 060 | (p[1] >> 4) & 017;
X    c3 = (p[1] << 2) & 074 | (p[2] >> 6) & 03;
X    c4 = p[2] & 077;
X    putc (ENC (c1), f);
X    putc (ENC (c2), f);
X    putc (ENC (c3), f);
X    putc (ENC (c4), f);
X}
X
X/* fr: like read but stdio */
Xint
X     fr (fp, buf, cnt)
X    FILE *fp;
X    char *buf;
X    int  cnt;
X{
X    int  c, i;
X
X    for (i = 0; i < cnt; i++)
X    {
X	c = getc (fp);
X	if (c == EOF)
X	    return (i);
X	buf[i] = c;
X    }
X    return (cnt);
X}
X/* vi: set tabstop=4 shiftwidth=4: */
SHAR_EOF
chmod 0644 uushar.c ||
echo 'restore of uushar.c failed'
Wc_c="`wc -c < 'uushar.c'`"
test 1365 -eq "$Wc_c" ||
	echo 'uushar.c: original size 1365, current size' "$Wc_c"
fi
# ============= who@where.c ==============
if test -f 'who@where.c' -a X"$1" != X"-c"; then
	echo 'x - skipping who@where.c (File already exists)'
else
echo 'x - extracting who@where.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'who@where.c' &&
X/* $Header: /u/rhg/src/shar/who@where.c,v 3.49 90/09/12 15:15:33 rhg Exp $ */
X
X/*+-------------------------------------------------------------------------
X	who@where.c - find out who i am & where i am
X	...!gatech!kd4nc!n4hgf!wht (wht%n4hgf@gatech.edu)
X--------------------------------------------------------------------------*/
X/*+:EDITS:*/
X/*:09-12-1990-01:04-rhg@cps.com-added declarations of strcpy and strcat */
X/*:09-09-1990-19:49-rhg@cps.com-added explicit return statement to who_where */
X/*:04-03-1990-19:55-wht@n4hgf-get rid of complicated who_am_i */
X/*:04-01-1990-13:30-pat@rwing-use utsname.nodename instead of sysname */
X/*:04-02-1990-12:12-wht@n4hgf-sigh... some pwd.h dont declare functions */
X/*:03-29-1990-18:23-wht@n4hgf-add automatic sequent support */
X/*:03-28-1990-15:24-wht@n4hgf-creation */
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <pwd.h>
X
X/* assume system v unless otherwise fixed */
X#if (defined(pyr) || defined(vax) || defined(sequent)) && !defined(BSD42) && !defined(SYS5)
X#define BSD42
X#endif
X#if defined(sun)	/* this miscreant doesn't exactly fit BSD or SYSV */
X#undef BSD42
X#undef SYS5
X#endif
X#if !defined(BSD42) && !defined(sun) && !defined(SYS5)
X#define SYS5
X#endif
X
X#if defined(sun) || defined(BSD42)
X#define strchr	index
X#define strrchr	rindex
X#endif
X
X#if !defined(SYS5) || defined(sun)
X#include <sys/time.h>
Xextern int errno;
X#else
X#include <sys/utsname.h>
X#include <time.h>
X#endif	/* system dependencies */
X
Xchar *strcpy();
Xchar *strcat();
Xstruct passwd *getpwuid();
X
X/*+-------------------------------------------------------------------------
X	who_am_i() - get user name
X--------------------------------------------------------------------------*/
Xchar *
Xwho_am_i()
X{
X	struct passwd *passwd;
X	passwd = getpwuid(getuid());
X	(void)endpwent();
X	if(passwd == (struct passwd *)0)
X		return("???");
X	return(passwd->pw_name);
X
X}	/* end of who_am_i */
X
X/*+-------------------------------------------------------------------------
X	where_am_i() - do uname, gethostname, or read file (/etc/systemid)
X--------------------------------------------------------------------------*/
Xchar *
Xwhere_am_i()
X{
X#if defined(M_SYS5)	/* SCO UNIX or XENIX */
XFILE *fpsid = fopen("/etc/systemid","r");
Xstatic char s20[20];
X	if(!fpsid)
X		return("???");
X	fgets(s20,sizeof(s20),fpsid);
X	fclose(fpsid);
X	s20[strlen(s20) - 1] = 0;
X	return(s20);
X#else /* M_SYS5 */
X#if defined(SYS5)
Xstatic struct utsname where_i_am;
X	uname(&where_i_am);
X	return(where_i_am.nodename);
X#else /* SYS5 */
Xstatic char where_i_am[64];
X	gethostname(where_i_am,sizeof(where_i_am));
X	return(where_i_am);
X#endif /* SYS5 */
X#endif /* M_SYS5 */
X}	/* end of where_am_i */
X
X/*+-------------------------------------------------------------------------
X	who_where(buf)
X--------------------------------------------------------------------------*/
Xchar *
Xwho_where(buf)
Xchar *buf;
X{
Xstatic char ww[64];
X
X	if(!buf)
X		buf = ww;
X	strcpy(buf,who_am_i());
X	strcat(buf,"@");
X	return(strcat(buf,where_am_i()));
X}	/* end of who_where */
X
X/* vi: set tabstop=4 shiftwidth=4: */
X/* end of who@where.c */
SHAR_EOF
chmod 0644 who@where.c ||
echo 'restore of who@where.c failed'
Wc_c="`wc -c < 'who@where.c'`"
test 3077 -eq "$Wc_c" ||
	echo 'who@where.c: original size 3077, current size' "$Wc_c"
fi
# ============= unshar.c ==============
if test -f 'unshar.c' -a X"$1" != X"-c"; then
	echo 'x - skipping unshar.c (File already exists)'
else
echo 'x - extracting unshar.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'unshar.c' &&
Xchar *revision = "3.49";
Xchar RCS_ID[] = "$Header: /u/rhg/src/shar/unshar.c,v 3.49 90/09/12 15:15:17 rhg Exp $";
X/****************************************************************
X * unshar.c: Unpackage one or more shell archive files
X *
X * Usage:     unshar [ -c ] [ -e | -E exit_line ] [ -d directory ] [ file ... ]
X *
X * Description:	unshar is a filter which removes the front part
X *		of  a file and passes the rest to the 'sh' command.
X *		It understands phrases like "cut here", and also
X *		knows about shell comment characters and the Unix
X *		commands "echo", "cat", and "sed".
X *
X *		The -c flag is passed through to the shell as a parameter to the script
X *
X *		It can unshar shar files concatenated in one file, with the
X *		the "-e" command, which separates files by recognizing the
X *		"exit 0" string at the beginning of a line
X *
X *		(The -E string option allows you to specify this string, thus
X *		-e is equivalent to -E "exit 0")
X *
X *		The -d flag tells unshar to change directory before unsharing
X *
X * HISTORY
X * 12-Sep-90  Richard H. Gumpertz (rhg@cps.com)
X *		use fprintf instead of printf when printing error return from getwd.
X *		deleted unused initialization of more_to_read in process.
X *		changed ch from char to int in process so the EOF check would work.
X *  4-Aug-90  Richard H. Gumpertz (rhg@cps.com)
X *		renamed -c and -C to -e and -E and added -c flag (passed through to sh)
X * 19-Apr-90  Colas Nahaboo (colas@mirsa.inria.fr)
X *		added -c and -C flags to read from concatenated archives
X *  1-Feb-85  Guido van Rossum (guido@mcvax) at CWI, Amsterdam
X *		Added missing 'quit' routine;
X *		added -d flag to change to directory first;
X *		added filter mode (read stdin when no arguments);
X *		added 'getopt' to get flags (makes it self-contained).
X * 29-Jan-85  Michael Mauldin (mlm) at Carnegie-Mellon University
X *		Created.
X ****************************************************************/
X/*+:EDITS:*/
X/*:08-04-1990-15:54-rhg@cps.com-changes listed above (-c/-C => -e/-E, new -c) */
X/*:05-05-1990-01:37-relay.EU.net!rivm!a3-dont assume vax is running BSD */
X/*:04-19-1990-15:20-wht@n4hgf-fix so -d doesnt make argv files unreachable */
X/*:04-19-1990-15:06-wht@n4hgf-colas@mirsa patches had expanded tabs */
X/*:04-10-1990-22:02-wht@n4hgf-stdin failed sometimes-can not seek on pipe */
X
X#include <stdio.h>
X#define EOL '\n'
X
X#if (defined(pyr) || defined(sun) || defined(BSD42) || \
X defined(vax) || defined(sequent)) && !defined(SYS5)
X#define strchr	index
X#undef USE_GETCWD
Xchar *getwd();
X#else
X#define USE_GETCWD
Xchar *getcwd();
X#endif
X
Xchar *strchr();
X
Xextern char *optarg;
Xextern int optind;
X
Xint c_flag = 0;
Xint continue_reading = 0;
Xchar *exit_string = "exit 0";
Xint exit_string_length;
Xchar argvdir[1024];
X
Xmain(argc,argv)
Xint argc;
Xchar *argv[];
X{
X	int i,ch;
X	FILE *in;
X	char s1024[1024];
X
X	setbuf(stdout,NULL);
X	setbuf(stderr,NULL);
X
X#ifdef USE_GETCWD
X	if(!getcwd(argvdir,sizeof(argvdir)))
X	{
X		perror("cannot get current directory name");
X		exit(1);
X	}
X#else
X	argvdir[0] = 0;
X	if(!getwd(argvdir))
X	{
X		if(argvdir[0])
X			fprintf(stderr,"%s\n",argvdir);
X		else
X			fprintf(stderr,"cannot get current directory name\n");
X		exit(1);
X	}
X#endif
X
X
X	/* Process options */
X
X	while((ch = getopt(argc,argv,"cd:eE:")) != EOF)
X	{
X		switch(ch)
X		{
X		case 'c':
X			c_flag = 1;
X			break;
X		case 'd':
X			if(chdir(optarg) == -1)
X			{
X				fprintf(stderr,"unshar: cannot chdir to '%s'\n",optarg);
X				exit(2);
X			}
X			break;
X		case 'E':
X			exit_string = optarg;
X		case 'e':
X			continue_reading = 1;
X			exit_string_length = strlen(exit_string);
X			break;
X		default:
X			quit(2,"Usage: unshar [-c] [-e | -E exit_line] [-d directory] [file ...]\n");
X		}
X	}
X
X	if(optind < argc)
X	{
X		for(i= optind; i < argc; ++i)
X		{
X			if(argv[i][0] == '/') {
X				strcpy(s1024,argv[i]);
X			} else {
X				strcpy(s1024,argvdir);
X				strcat(s1024,"/");
X				strcat(s1024,argv[i]);
X			}
X			if(!(in = fopen(s1024,"r")))
X			{
X				perror(s1024);
X				exit(1);
X			}
X			process(s1024,in);
X			fclose(in);
X		}
X	}
X	else
X	{
X		sprintf(s1024,"/tmp/unsh.%05d",getpid());
X		unlink(s1024);
X		if(!(in = fopen(s1024,"w+")))
X		{
X			fprintf(stderr,"cannot open temp file '%s'\n",s1024);
X			exit(1);
X		}
X		unlink(s1024);	/* don't try this with MSDOS, sports fans */
X		while(i = fread(s1024,1,sizeof(s1024),stdin))
X			fwrite(s1024,i,1,in);
X		rewind(in);
X		process("standard input",in);
X		fclose(in);
X	}
X
X	exit(0);
X}
X
X
Xprocess(name,in)
Xchar *name;
XFILE *in;
X{
X	char buffer[8196];
X	int ch;
X	FILE *shpr,*popen();
X	long current_position = 0;
X	char *more_to_read;
X
X	while(position(name,in,current_position))
X	{
X		printf("%s:\n",name);
X		if(!(shpr = popen((c_flag ? "sh -s -c" : "sh"),"w")))
X			quit(1,"unshar: cannot open 'sh' process\n");
X
X		if (!continue_reading) {
X			while((ch = fgetc(in)) != EOF)
X				fputc(ch,shpr);
X			pclose(shpr);
X			break;
X		} else {
X			while (more_to_read = fgets(buffer, 8196, in)) {
X				fputs(buffer, shpr);
X				if (!strncmp(exit_string, buffer, exit_string_length)) {
X					break;
X				}
X			}
X			pclose(shpr);
X			if (more_to_read)
X				current_position = ftell(in);
X			else {
X				break;
X			}
X		}
X	}
X}
X
X/****************************************************************
X * position: position 'fil' at the start of the shell command
X * portion of a shell archive file.
X ****************************************************************/
X
Xposition(fn,fil,start)
Xchar *fn;
XFILE *fil;
Xlong start;                   /* scan file from position */
X{
X	char buf[BUFSIZ];
X	long pos,ftell();
X
X	/* Results from star matcher */
X	static char res1[BUFSIZ],res2[BUFSIZ],res3[BUFSIZ],res4[BUFSIZ];
X	static char *result[] = 
X	{
X		res1,res2,res3,res4 		};
X
X	fseek(fil, start, 0);
X
X	while(1)
X	{ /* Record position of the start of this line */
X		pos = ftell(fil);
X
X		/* Read next line, fail if no more and no previous process */
X		if(!fgets(buf,BUFSIZ,fil))
X		{
X			if(!start)
X				fprintf(stderr,"unshar: found no shell commands in %s\n",fn);
X			return(0);
X		}
X
X		/* Bail out if we see C preprocessor commands or C comments */
X		if(stlmatch(buf,"#include")	|| stlmatch(buf,"# include") ||
X		    stlmatch(buf,"#define")	|| stlmatch(buf,"# define") ||
X		    stlmatch(buf,"#ifdef")	|| stlmatch(buf,"# ifdef") ||
X		    stlmatch(buf,"#ifndef")	|| stlmatch(buf,"# ifndef") ||
X		    stlmatch(buf,"/*"))
X		{
X			fprintf(stderr,
X			    "unshar: %s looks like raw C code, not a shell archive\n",fn);
X			return(0);
X		}
X
X		/* Does this line start with a shell command or comment */
X		if(stlmatch(buf,"#")	|| stlmatch(buf,":") ||
X		    stlmatch(buf,"echo ")	|| stlmatch(buf,"sed ") ||
X		    stlmatch(buf,"cat ") || stlmatch(buf,"if "))
X		{
X			fseek(fil,pos,0);
X			return(1);
X		}
X
X		/* Does this line say "Cut here" */
X		if(smatch(buf,"*CUT*HERE*",result) ||
X		    smatch(buf,"*cut*here*",result) ||
X		    smatch(buf,"*TEAR*HERE*",result) ||
X		    smatch(buf,"*tear*here*",result) ||
X		    smatch(buf,"*CUT*CUT*",result) ||
X		    smatch(buf,"*cut*cut*",result))
X		{
X			/* Read next line after "cut here", skipping blank lines */
X			while(1)
X			{
X				pos = ftell(fil);
X
X				if(!fgets(buf,BUFSIZ,fil))
X				{
X					fprintf(stderr,
X					    "unshar: found no shell commands after 'cut' in %s\n",fn);
X					return(0);
X				}
X
X				if(*buf != '\n') break;
X			}
X
X			/* Win if line starts with a comment character of lower case letter */
X			if(*buf == '#' || *buf == ':' || (('a' <= *buf) && ('z' >= *buf)))
X			{
X				fseek(fil,pos,0);
X				return(1);
X			}
X
X			/* Cut here message lied to us */
X			fprintf(stderr,"unshar: %s is probably not a shell archive,\n",fn);
X			fprintf(stderr,"        the 'cut' line was followed by: %s",buf);
X			return(0);
X		}
X	}
X}
X
X/*****************************************************************
X * stlmatch  --  match leftmost part of string
X *
X * Usage:  i = stlmatch (big,small)
X *	int i;
X *	char *small, *big;
X *
X * Returns 1 iff initial characters of big match small exactly;
X * else 0.
X *
X * HISTORY
X * 18-May-82 Michael Mauldin (mlm) at Carnegie-Mellon University
X *      Ripped out of CMU lib for Rog-O-Matic portability
X * 20-Nov-79  Steven Shafer (sas) at Carnegie-Mellon University
X *	Rewritten for VAX from Ken Greer's routine.
X *
X *  Originally from klg (Ken Greer) on IUS/SUS UNIX
X *****************************************************************/
X
Xint stlmatch(big,small)
Xchar *small,*big;
X{
X	register char *s,*b;
X	s = small;
X	b = big;
X	do
X	{
X		if(*s == '\0')
X			return(1);
X	}  while(*s++ == *b++);
X	return(0);
X}
X
X/*****************************************************************
X * smatch: Given a data string and a pattern containing one or
X * more embedded stars (*) (which match any number of characters)
X * return true if the match succeeds, and set res[i] to the
X * characters matched by the 'i'th *.
X *****************************************************************/
X
Xsmatch(dat,pat,res)
Xregister char *dat,*pat,**res;
X{
X	register char *star = 0,*starend,*resp;
X	int nres = 0;
X
X	while(1)
X	{
X		if(*pat == '*')
X		{
X			star = ++pat; 			     /* Pattern after * */
X			starend = dat; 			     /* Data after * match */
X			resp = res[nres++]; 		     /* Result string */
X			*resp = '\0'; 			     /* Initially null */
X		}
X		else if(*dat == *pat) 		     /* Characters match */
X		{
X			if(*pat == '\0') 		     /* Pattern matches */
X				return(1);
X			pat++; 				     /* Try next position */
X			dat++;
X		}
X		else
X		{
X			if(*dat == '\0') 		     /* Pattern fails - no more */
X				return(0); 			     /* data */
X			if(star == 0) 			     /* Pattern fails - no * to */
X				return(0); 			     /* adjust */
X			pat = star; 			     /* Restart pattern after * */
X			*resp++ = *starend; 		     /* Copy character to result */
X			*resp = '\0'; 			     /* null terminate */
X			dat = ++starend; 			     /* Rescan after copied char */
X		}
X	}
X}
X
X/*****************************************************************
X * Addendum: quit subroutine (print a message and exit)
X *****************************************************************/
X
Xquit(status,message)
Xint status;
Xchar *message;
X{
X	fprintf(stderr,message);
X	exit(status);
X}
X
X/*****************************************************************
X * Public Domain getopt routine
X *****************************************************************/
X
X/*
X * get option letter from argument vector
X */
Xint opterr = 1;		/* useless, never set or used */
Xint optind = 1;		/* index into parent argv vector */
Xint optopt;			/* character checked for validity */
Xchar *optarg;		/* argument associated with option */
X
X#define BADCH	(int)'?'
X#define EMSG	""
X#define tell(s)	fputs(*nargv,stderr);fputs(s,stderr); \
X		fputc(optopt,stderr);fputc('\n',stderr);return(BADCH);
X
Xgetopt(nargc,nargv,ostr)
Xint nargc;
Xchar **nargv,*ostr;
X{
X	static char *place = EMSG;	/* option letter processing */
X	register char *oli;		/* option letter list index */
X	char *strchr();
X
X	if(!*place)
X	{			/* update scanning pointer */
X		if(optind >= nargc || *(place = nargv[optind]) != '-' || !*++place)
X			return(EOF);
X		if(*place == '-')
X		{	/* found "--" */
X			++optind;
X			return(EOF);
X		}
X	}				/* option letter okay? */
X	if((optopt = (int)*place++) == (int)':' || !(oli = strchr(ostr,optopt)))
X	{
X		if(!*place) ++optind;
X		tell(": illegal option -- ");
X	}
X	if(*++oli != ':')
X	{		/* don't need argument */
X		optarg = (char *)0;
X		if(!*place) ++optind;
X	}
X	else 
X	{				/* need an argument */
X		if(*place) optarg = place;	/* no white space */
X		else if(nargc <= ++optind)
X		{	/* no arg */
X			place = EMSG;
X			tell(": option requires an argument -- ");
X		}
X		else optarg = nargv[optind];	/* white space */
X		place = EMSG;
X		++optind;
X	}
X	return(optopt);			/* dump back option letter */
X}
X/* vi: set tabstop=4 shiftwidth=4: */
SHAR_EOF
chmod 0644 unshar.c ||
echo 'restore of unshar.c failed'
Wc_c="`wc -c < 'unshar.c'`"
test 11602 -eq "$Wc_c" ||
	echo 'unshar.c: original size 11602, current size' "$Wc_c"
fi
true || echo 'restore of shar.c failed'
echo End of part 1, continue with part 2
exit 0

-- 
  ==========================================================================
  | Richard H. Gumpertz    rhg@CPS.COM    (913) 642-1777 or (816) 891-3561 |
  | Computer Problem Solving, 8905 Mohawk Lane, Leawood, Kansas 66206-1749 |
  ==========================================================================

rhg@cpsolv.CPS.COM (Richard H. Gumpertz) (09/13/90)

Submitted-by: rhg@cpsolv
Archive-name: shar3.49/part02

---- Cut Here and feed the following to sh ----
#!/bin/sh
# This is part 02 of shar3.49
# ============= shar.c ==============
if test -f 'shar.c' -a X"$1" != X"-c"; then
	echo 'x - skipping shar.c (File already exists)'
else
echo 'x - extracting shar.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'shar.c' &&
Xchar *revision = "3.49";
Xchar RCS_ID[] = "$Header: /u/rhg/src/shar/shar.c,v 3.49 90/09/12 15:14:41 rhg Exp $";
X/*
X** shar.c
X
X  Defined functions:
X	gen_mkdir(path)
X	gen_mkdir_script(path)
X	setTOUCH()
X	walktree(rtn,rootname)
X	header(argc,argv)
X	helpuser()
X	main(argc,argv)
X	mode_map(mode,mode_str)
X	shar(file,RstrName)
X
X*/
X/*+:EDITS:*/
X/*:09-12-1990-14:24-rhg@cps.com-added missing return(0) to walkdown */
X/*:09-12-1990-14:13-rhg@cps.com-deleted some redundant, unused, code */
X/*:09-12-1990-00:28-rhg@cps.com-added more directions to the shar header */
X/*:09-09-1990-20:12-rhg@cps.com-added CLOSEDIR_VOID */
X/*:09-09-1990-18:42-rhg@cps.com-added check for "From" under OptPREFIX */
X/*:09-09-1990-11:55-rhg@cps.com-modified code under NOT STR(N)CMP_IS_FAST */
X/*:09-08-1990-21:20-rhg@cps.com-added NO_DIRENT for SunOS 3 sys/dir.h */
X/*:09-08-1990-21:04-rhg@cps.com-fixed bug in PREFIX check: strcmp(line,Delim) */
X/*:08-06-1990-00:40-rhg@cps.com-revised Cut message to be more explanatory */
X/*:08-05-1990-14:04-rhg@cps.com-merged Rname into walktree */
X/*:08-05-1990-12:11-rhg@cps.com-added walktree & support for sharing dirs */
X/*:08-05-1990-09:05-rhg@cps.com-change -Bn, -t, and -b to -bn, -T, and -B */
X/*:08-04-1990-15:31-rhg@cps.com-added -Bn to set compress -bn (default 12) */
X/*:08-04-1990-15:31-rhg@cps.com-changed shar3_???_.tmp to _shar_???_.tmp */
X/*:08-04-1990-15:22-rhg@cps.com-added check for "exit 0" under OptPREFIX */
X/*:08-04-1990-14:32-rhg@cps.com-added -m to generate TOUCH (default off) */
X/*:08-04-1990-14:18-rhg@cps.com-reversed the meaning of -x and deleted -O */
X/*:06-14-1990-14:48-rhg@cps.com-made Split and eXists compatible.
X/*:06-14-1990-14:18-rhg@cps.com-made -x the default and added -O
X/*:06-14-1990-12:44-rhg@cps.com-always terminate the && and report failures
X/*:06-14-1990-12:28-rhg@cps.com-clear mkdir_already between -l files
X/*:06-14-1990-12:14-rhg@cps.com-change PREFIX from a #define to an int variable.
X/*:04-19-1990-22:49-rhg@cps.com-get rid of "set" so "sh sharfil -c" will work */
X/*:04-19-1990-21:52-rhg@cps.com-add -F to clear OptPREFIX */
X/*:04-18-1990-08:49-rhg@cps.com-add OptPREFIX (for now, always on) */
X/*:07-09-1990-19:24-wht@n4hgf-back to fgrep amc -- fits more -m touches */
X/*:07-01-1990-18:37-wht@n4hgf-wait() needed after fork() */
X/*:05-19-1990-02:47-wht@n4hgf-change fgrep amc to mmdd */
X/*:05-16-1990-01:53-wht@n4hgf-Archive-name had extra period sometimes */
X/*:05-10-1990-20:39-wht@n4hgf-altos does not not like at-sign in filenames */
X/*:05-10-1990-13:38-wht@n4hgf-add -V Vanilla mode */
X/*:05-07-1990-00:06-wht@n4hgf-test all mallocs for Purity Of Essence */
X/*:05-07-1990-00:06-wht@n4hgf-add -S switch */
X/*:05-05-1990-01:37-relay.EU.net!rivm!a3-dont assume vax is running BSD */
X/*:04-18-1990-02:01-wht@n4hgf-3.20 rhg@cps.com did all the NICE work */
X/*:04-17-1990-14:30-rhg@cps.com-pretty up if-then-else-fi in shar file */
X/*:04-17-1990-12:13-rhg@cps.com-add Split and renamed old -l to -L */
X/*:04-17-1990-12:13-rhg@cps.com-add -c option to shar file execution */
X/*:04-17-1990-11:20-rhg@cps.com-simplify TOUCH logic in shar file */
X/*:04-17-1990-10:27-rhg@cps.com-create setTOUCH to avoid duplicate code */
X/*:04-17-1990-04:43-rhg@cps.com-add missing && to commands in shar file(s) */
X/*:04-17-1990-02:03-rhg@cps.com-add Compress */
X/*:04-16-1990-17:08-rhg@cps.com-add AvoidPipes as well as code to use pipes */
X/*:04-03-1990-20:09-wht@n4hgf-3.11 */
X/*:04-01-1990-13:20-pat@rwing-correct case on M option in getopt() call */
X/*:04-01-1990-13:50-pat@rwing-change defaults on -v, -w to be on */
X/*:03-29-1990-18:23-wht@n4hgf-add automatic sequent support */
X/*:03-28-1990-15:56-wht@n4hgf-add mode and length net.bandwidth chrome */
X/*:03-28-1990-14:23-wht@n4hgf-correct some runtime diagnostics */
X/*:11-14-1989-02:21-wht-SHAR_EOF was botched if last file char not newline */
X/*:11-02-1989-14:11-wht-add touch -am */
X
X/*
X Shar puts readable text files together in a package
X from which they are easy to extract.
X earlier attribution wht@n4hgf has:	decvax!microsof!uw-beave!jim
X                                    (James Gosling at CMU)
X*/
X/*
X *	I have made several mods to this program:
X *
X *	1) the -----Cut Here-----... now preceds the script.
X *	2) the cat has been changed to a sed which removes a prefix
X *	character from the beginning of each line of the extracted
X *	file, this prefix character is added to each line of the archived
X *	files and is not the same as the first character of the
X *	file delimeter.
X *	3) added several options:
X *		-c	- add the -----Cut Here-----... line.
X *		-d'del' - change the file delimeter to del.
X *		-s	- cause the resulting script to print the wc of
X *			  the orignal file and the wc of the extracted
X *			  file.
X *
X *				Michael A. Thompson
X *				Dalhousie University
X *				Halifax, N.S., Canada.
X */
X
X/*
X *	I, too, have been hacking this code. This is the version on sixhub
X *		bill davidsen (davidsen@sixhub.uucp)
X *
X *	- added support for binary files
X *	- automatic creation of limited size multiple file archives,
X *	  each of which may be unpacked separately, and with sequence
X *	  checking.
X *	- support for mixed text and binary files
X *	- preserve file permissions
X *	- restore to filename rather than pathname
X *
X */
X/*
X *  One good hack deserves another ... this version generates shell
X *  code which attempts to create missing directories
X *  handle deviants sun, vax, pyr (pyramid), SCO XENIX/UNIX automatically
X *  for sequent, add -DBSD42
X *  force Verbose on
X *  if unsharing system's touch Sys V compatible (allows touch -m),
X *  restore file dates
X *  -n switch puts an alpha "name" in header
X *  -a (if also -n) puts "Submitted-by:" & "Archive-name: <name>/part##
X *  use getopt
X *  as well as some other chrome-plated junque
X *  ...!gatech!emory!tridom!wht (wht%n4hgf@gatech.edu) Warren Tucker
X *
X *  3.11 - Fri Apr  6 14:21:51 EDT 1990
X *  With due deference to davidsen@sixhub, more changes..... copies
X *  of this, like 3.10,  were mailed to him:
X *  From wht  Fri Apr  6 15:14:30 1990 remote from n4hgf
X *  Received: by n4hgf.UUCP (smail2.5-UNIX/386 5.3.2)
X *  	id AA01781; 6 Apr 90 15:14:30 EDT (Fri)
X *  Date: Fri, 6 Apr 90 15:14:30 EDT
X *  X-Mailer: Mail User's Shell (6.5 4/17/89)
X *  From: wht@n4hgf (Warren Tucker)
X *  To: davidsen@sixhub
X *  Subject: shar 3.11
X *  X-Bang-Reply-to: gatech!n4hgf!wht -or- emory!tridom!n4hgf!wht
X *  Reply-to: wht%n4hgf@gatech.edu
X *  Message-Id: <9004061514.AA01781@n4hgf.UUCP>
X *
X *  1. changes suggested by pat@rwing (Pat Myrto) and silvert@cs.dal.ca
X *  (Bill Silvert)
X *  2. fixes to who_am_i code in who@where.c
X *
X *  3.20 - Wed Apr 18 01:58:32 EDT 1990
X *  changes were made per edit notes by
XFrom: gatech!mailrus!uunet!cpsolv.CPS.COM!rhg (Richard H. Gumpertz)
X *  ...!gatech!n4hgf!wht (wht%n4hgf@gatech.edu) Warren Tucker
X *
X */
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <time.h>
X#include <sys/stat.h>
X#include <ctype.h>
X
X/* assume system v unless otherwise fixed */
X#if (defined(pyr) || defined(vax) || defined(sequent)) && !defined(BSD42) && !defined(SYS5)
X#define BSD42
X#endif
X#if defined(sun)	/* this miscreant doesn't exactly fit BSD or SYSV */
X#undef BSD42
X#undef SYS5
X#endif
X#if !defined(BSD42) && !defined(sun) && !defined(SYS5)
X#define SYS5
X#endif
X
X#if defined(sun) || defined(BSD42)
X#define strchr	index
X#define strrchr	rindex
X#endif
X
Xchar *strchr();
Xchar *strrchr();
X#ifdef __STDC__ /* my concession to ANSI-pansiness */
Xvoid *malloc();
X#else
Xchar *malloc();
X#endif
XFILE *fdopen();
XFILE *popen();
X
X#define	DELIM		"SHAR_EOF"/* put after each file */
X#define PREFIX1		'X'	/* goes in front of each line */
X#define PREFIX2		'Y'	/* goes in front of each line if Delim[0] == PREFIX1 */
X#define WC	        "wc -c <"
X
Xint PREFIX = PREFIX1;	/* Character to get at the beginning of each line */
X
Xint Archive_name = 0;	/* option to generate "Archive-name:" headers */
Xint Verbose = 1;		/* option to provide append/extract feedback */
Xint Wc_c = 1;			/* option to provide wc checking */
Xchar *Delim = DELIM;	/* pointer to delimiter string */
Xint OptPREFIX = 1;		/* suppress PREFIX unless 1st char forces it */
Xint Cut = 0;			/* option to provide cut mark */
Xchar *CutMessage = "---- Cut Here and feed the following to sh ----\n";
Xint Binary = 0;			/* flag for binary files */
Xint AvoidPipes = 0;		/* use temp file instead of pipe to feed uudecode, etc.
X						   (better error detection at expense of disk space) */
Xint Vanilla = 0;		/* no Brown-Shirt mode */
Xint Touch = 0;			/* generate $TOUCH commands */
Xint Compress = 0;		/* run input files through compress (requires Binary) */
Xint CompressBits = 12;	/* -b option to compress */
Xint Mixed = 0;			/* mixed text and binary files */
Xint eXists = 1;			/* check if file exists */
Xint InterOW = 0;		/* interactive overwrite */
Xint PosParam = 0;		/* allow positional parameters */
Xint FileStrip;			/* strip directories from filenames */
X#ifdef	DEBUG
Xint de_bug = 0;			/* switch for debugging on */
X#define DeBug(f,v) if (de_bug) printf(f, v)
X#else	/* normal compile */
X#define DeBug(f,v)		/* do nothing */
X#endif
X
XFILE *fpout = stdout;
Xint shar();
Xunsigned limit = 0;
Xint Split = 0;			/* Split files in the middle */
Xlong ftell();
Xlong TypePos;			/* position for archive type message */
Xlong EndHeadPos;		/* position for first file in the shar file */
Xchar outname[50];		/* base for output filename */
Xchar filename[50];		/* actual output filename */
Xchar *sharname = (char *)0;
Xchar *submitter = (char *)0;
Xint filenum = 0;		/* output file # */
Xstruct stat fst;		/* check file type, access */
X
Xmain(argc,argv)
Xchar **argv;
X{
Xint status = 0;
Xint stdin_file_list = 0;
Xchar *oname;
Xint c;
Xextern int optind;
Xextern char *optarg;
X
X	while((c = getopt(argc,argv,"VmSvwd:BTCb:xXcfMpPFas:n:l:L:o:h")) != -1)
X	{
X		switch(c)
X		{
X		case 'V':
X			Vanilla = 1;
X			break;
X		case 'm':
X			Touch = 1;
X			break;
X		case 'S':
X			stdin_file_list = 1;
X			break;
X		case 'v':
X			Verbose = 0;
X			break;
X		case 'w':
X			Wc_c = 0;
X			break;
X		case 'd':
X			Delim = optarg;
X			PREFIX = (Delim[0] == PREFIX1 ? PREFIX2 : PREFIX1);
X			break;
X		case 'B': /* binary files */
X			Binary = 1;
X			Compress = 0;
X			break;
X		case 'T': /* text mode */
X			Binary = 0;
X			Compress = 0;
X			break;
X		case 'b': /* Compress bits */
X			CompressBits = atoi(optarg);
X			/* fall through to -C */
X		case 'C': /* Compress */
X			Binary = 1;
X			Compress = 1;
X			break;
X		case 'x': /* don't worry whether the file exist */
X			eXists = 0;
X			break;
X		case 'X': /* ask the user whether to overwrite existing files */
X			InterOW = 1;
X			eXists = 1;
X			break;
X		case 'c':
X			Cut = 1;
X			break;
X		case 'f': /* filenames only */
X			FileStrip = 1;
X			break;
X		case 'M': /* mixed text and binary */
X			Mixed = 1;
X			break;
X		case 'p': /* allow positional parameters */
X			PosParam = 1;
X			break;
X		case 'P': /* use temp files instead of pipes in the shar file */
X			AvoidPipes = 1;
X			break;
X		case 'F': /* force PREFIX to be put out even if not required */
X			OptPREFIX = 0;
X			break;
X		case 'l': /* soft size limit in k */
X			if((limit = atoi(optarg)) > 1)
X				--limit;
X			Split = 0;
X			DeBug("Soft limit %dk\n",limit);
X			break;
X		case 'L': /* hard size limit in k */
X			if((limit = atoi(optarg)) > 1)
X				--limit;
X			Split = (limit != 0);
X			AvoidPipes = 1;
X			DeBug("Hard limit %dk\n",limit);
X			break;
X		case 'n': /* name of archive */
X			sharname = optarg;
X			break;
X		case 's': /* submitter */
X			submitter = optarg;
X			break;
X		case 'a': /* generate Archive-name: headers */
X			Archive_name = 1;
X			break;
X		case 'o': /* specify output file */
X			oname = optarg;
X			strcpy(outname,oname);
X			strcat(outname,".");
X			filenum = 1;
X			strcpy(filename,outname);
X			strcat(filename,"01");
X			fpout = fopen(filename,"w");
X			if(!fpout)
X			{ /* creation error */
X				perror("can't create output file");
X				exit(1);
X			}
X			break;
X#ifdef	DEBUG
X		case '$': /* totally undocumented $ option, debug on */
X			de_bug = 1;
X			break;
X#endif
X		default: /* invalid option */
X		case 'h': /* help */
X			helpuser();
X			break;
X		}
X	}
X
X	if(Vanilla)
X	{
X		fprintf(stderr,"Vanilla mode disabling years of progress :-)\n");
X		Wc_c = 0;
X		OptPREFIX = 0;
X#ifdef V_AVOIDPIPES	/* pipes are benign and only used with uudecode anyway */
X		AvoidPipes = 1;
X#endif /* V_AVOIDPIPES */
X#ifdef V_NOFORCE	/* If the user specifies non-defaults, let him have them */
X#else
X		Touch = 0;
X		InterOW = 0;
X		if(Binary || Mixed || Compress || PosParam)
X			fprintf(stderr,"WARNING: non-Text storage options overridden.\n");
X		Binary = 0;
X		Mixed = 0;
X		Compress = 0;
X		PosParam = 0;
X#endif /* V_NOFORCE */
X	}
X
X	if(stdin_file_list)
X	{
X		char stdin_buf[258];
X		argc = 0;
X		if(!(argv = (char **)malloc(1024 * sizeof(char *))))
X			goto MEMORY_ERROR;
X		stdin_buf[0] = 0;
X		while(fgets(stdin_buf,sizeof(stdin_buf),stdin))
X		{
X			if(argc == 1024)
X			{
X				fprintf(stderr,"max files from stdin is 1024!\n");
X				exit(1);
X			}
X			if(stdin_buf[0])
X				stdin_buf[strlen(stdin_buf) - 1] = 0;
X			if(!(argv[argc] = malloc(strlen(stdin_buf) + 1)))
X			{
XMEMORY_ERROR: /* NOT likely, but free software must pure as snow! */
X				fprintf(stderr,"out of memory handling stdin input at %d\n",
X					argc);
X				exit(1);
X			}
X			strcpy(argv[argc],stdin_buf);
X			++argc;
X			stdin_buf[0] = 0;
X		}
X		optind = 0;
X	}
X
X	if(optind >= argc)
X	{
X		fprintf(stderr,"shar: No input files\n");
X		helpuser();
X		exit(1);
X	}
X
X	if(Archive_name && !sharname)
X	{
X		fprintf(stderr,"shar: -n must accompany -a\n");
X		helpuser();
X		exit(1);
X	}
X
X	if(!submitter)
X	{
X		if(!(submitter = malloc(128)))
X		{
X			fprintf(stderr,"memory allocation failed\n"); /* NOT likely */
X			exit(1);
X		}
X		who_where(submitter);
X	}
X
X	if(header(argc-optind,&argv[optind]))
X		exit(2);
X
X	if(InterOW)
X	{
X		Verbose = 1;
X		fputs("wish=\n",fpout);
X		if(Archive_name)
X		{
X			fprintf(stderr,
X				"PLEASE do not submit -X shars to the usenet or other\n");
X			fprintf(stderr,
X				"public networks.  They will cause problems.\n");
X		}
X	}
X
X	EndHeadPos = ftell(fpout);
X
X	for( ; optind < argc; ++optind)
X	{ /* process positional parameters and files */
X		if(PosParam)
X		{		/* allow -B and -T and -C inline */
X			if(strcmp(argv[optind],"-B") == 0)
X			{ /* set binary */
X				Binary = 1;
X				Compress = 0;
X				continue;
X			}
X			if(strcmp(argv[optind],"-T") == 0)
X			{ /* set mode text */
X				Binary = 0;
X				Compress = 0;
X				continue;
X			}
X			if(strcmp(argv[optind],"-C") == 0)
X			{ /* set compress */
X				Binary = 1;
X				Compress = 1;
X				continue;
X			}
X		}
X		status += walktree(shar,argv[optind]);
X	}
X
X	/* delete the sequence file, if any */
X	if(Split && filenum > 1)
X	{
X		fputs("rm -f _shar_seq_.tmp\n",fpout);
X		fputs("echo You have unpacked the last part\n",fpout);
X		if(!Verbose)
X			fprintf(stderr,"Created %d files\n",filenum);
X	}
X	fputs("exit 0\n",fpout);
X	exit(status);
X}
X
X/*+-----------------------------------------------------------------------
X	mode_map(mode,mode_str)	build drwxrwxrwx string
X------------------------------------------------------------------------*/
Xchar *
Xmode_map(mode,mode_str)
Xunsigned short mode;
Xchar *mode_str;
X{
X#ifdef THIS_IS_NOT_NEEDED_FOR_SHAR
Xregister unsigned ftype = mode & S_IFMT;
X#endif
Xregister char *rtn;
Xstatic char result[12];
X
X	rtn = (mode_str == (char *)0) ? result : mode_str;
X
X	/*          drwxrwxrwx */
X	/*          0123456789 */
X	strcpy(rtn,"----------");
X
X#ifdef THIS_IS_NOT_NEEDED_FOR_SHAR
X	switch(ftype)
X	{
X		case S_IFIFO:	*rtn = 'p'; break; /* FIFO (named pipe) */
X		case S_IFDIR:	*rtn = 'd'; break; /* directory */
X		case S_IFCHR:	*rtn = 'c'; break; /* character special */
X		case S_IFBLK:	*rtn = 'b'; break; /* block special */
X		case S_IFREG:	*rtn = '-'; break; /* regular */
X
X#if defined(sun) | defined(BSD42)
X		case S_IFLNK:	*rtn = 'l'; break; /* symbolic link */
X		case S_IFSOCK:	*rtn = 's'; break; /* socket */
X#endif
X
X#if defined (SYS5)
X		case S_IFNAM:						/* name space entry */
X			if(mode & S_INSEM)				/* semaphore */
X			{
X				*rtn = 's';
X				break;
X			}
X			if(mode & S_INSHD)				/* shared memory */
X			{
X				*rtn = 'm';
X				break;
X			}
X#endif
X
X		default:		*rtn = '?'; break;	/* ??? */
X	}
X#endif /* THIS_IS_NOT_NEEDED_FOR_SHAR */
X
X	if(mode & 000400) *(rtn + 1) = 'r';
X	if(mode & 000200) *(rtn + 2) = 'w';
X	if(mode & 000100) *(rtn + 3) = 'x';
X	if(mode & 004000) *(rtn + 3) = 's';
X	if(mode & 000040) *(rtn + 4) = 'r';
X	if(mode & 000020) *(rtn + 5) = 'w';
X	if(mode & 000010) *(rtn + 6) = 'x';
X	if(mode & 002000) *(rtn + 6) = 's';
X	if(mode & 000004) *(rtn + 7) = 'r';
X	if(mode & 000002) *(rtn + 8) = 'w';
X	if(mode & 000001) *(rtn + 9) = 'x';
X	if(mode & 001000) *(rtn + 9) = 't';
X
X	return(rtn);
X
X}	/* end of mode_map */
X
Xvoid
XsetTOUCH()
X{
X	if(Touch)
X	{
X		fputs("if touch 2>&1 | fgrep 'amc' > /dev/null\n",fpout);
X		fputs(" then TOUCH=touch\n",fpout);
X		fputs(" else TOUCH=true\n",fpout);
X		fputs("fi\n",fpout);
X	}
X} /* end of setTOUCH */
X
X#ifdef NO_WALKTREE
X
Xint
Xwalktree(rtn,file)				/* dummy walktree */
Xint (*rtn)(/*file,rname*/);	/* may also assume fst is set */
Xchar *file;
X{
X	register char *rname;
X
X	if(stat(file,&fst))
X	{
X		fprintf(stderr,"shar: Can't access %s\n",file);
X		return(1);
X	}
X
X	if(FileStrip)
X	{ /* use just the filename */
X		rname = file + strlen(file);
X		while(rname > file && *rname != '/')
X			--rname;
X		if(*rname == '/')
X			++rname;
X	}
X	else
X		rname = file;
X	if(!strncmp(rname,"./",2) && rname[2])
X		rname += 2;
X
X	return((*rtn)(file,rname));
X}
X
X#else /* NO_WALKTREE*/
X
X#ifdef NO_DIRENT
X
X#include <sys/dir.h>			/* SunOS 3, etc. */
X#define DIRENTRY struct direct
X
X#else /* NO_DIRENT */
X
X#include <dirent.h>			/* Doug Gwyn's dirent routines */
X#define DIRENTRY struct dirent
X
X#endif /* NO_DIRENT */
X
XDIR *opendir();
XDIRENTRY *readdir();
X
Xint
Xwalkdown(rtn,file,filelen,rname)
Xint (*rtn)(/*file,rname*/);	/* may also assume fst is set */
Xchar *file, *rname;			/* *rname must be *file + n where n < filelen */
Xint filelen;
X{
X	DIR *dirp;
X	DIRENTRY *dp;
X
X	if(stat(file,&fst))
X	{
X		fprintf(stderr,"shar: Can't access %s\n",file);
X		return(1);
X	}
X
X	if((fst.st_mode & S_IFMT) != S_IFDIR)
X		return((*rtn)(file,rname));
X
X	if(!(dirp = opendir(file)))
X	{
X		fprintf(stderr,"shar: unable to open directory %s",file);
X		return(1);
X	}
X
X	if(!strcmp(rname,"."))
X		rname += 2;				/* avoid "./xxx" when sharing "." */
X
X	while((dp = readdir(dirp)))
X		if (strcmp(dp->d_name,".") && strcmp(dp->d_name,".."))
X		{
X			int newlen;
X
X			if((newlen = filelen + 1 + strlen(dp->d_name)) >= MAXNAMLEN)
X			{
X				fprintf(stderr,"shar: file name too long: %s/%s\n",
X						file,dp->d_name);
X				return(1);
X			}
X			sprintf(file + filelen,"/%s",dp->d_name);
X
X			if(walkdown(rtn,file,newlen,rname))
X				return(1);
X
X			file[filelen] = '\0';	/* in case we print any error messages */
X		}
X
X#ifdef CLOSEDIR_VOID
X	closedir(dirp);
X#else /* CLOSEDIR_VOID */
X	if(closedir(dirp))
X	{
X		fprintf(stderr,"shar: unable to close directory %s",file);
X		return(1);
X	}
X#endif /* CLOSEDIR_VOID */
X    return(0);
X}
X
Xint
Xwalktree(rtn,rootname)				/* real walktree */
Xint (*rtn)(/*file,rname*/);	/* may also assume fst is set */
Xchar *rootname;
X{
X	char file[MAXNAMLEN];
X	int filelen;
X	register char *rname;
X
X	if((filelen = strlen(rootname)) >= MAXNAMLEN)
X	{
X		fprintf(stderr,"shar: file name too long: %s\n",rootname);
X		return(1);
X	}
X	strcpy(file,rootname);
X
X	if(FileStrip)
X	{ /* use just the filename */
X		rname = file + filelen;
X		while(rname > file && *rname != '/')
X			--rname;
X		if(*rname == '/')
X			++rname;
X	}
X	else
X		rname = file;
X	if(!strncmp(rname,"./",2) && rname[2])
X		rname += 2;
X
X	return(walkdown(rtn,file,filelen,rname));
X}
X
X#endif /* NO_WALKTREE */
X
Xint
Xonecheck(file,rname)
Xchar *file, *rname;
X{
X	if(access(file,04))
X	{
X		fprintf(stderr,"shar: Can't access %s\n",file);
X		return(1);
X	}
X
X	return(0);
X}
X
Xint
Xoneheader(file,rname)
Xchar *file, *rname;
X{
X	fprintf(fpout,"# %6ld %s %s\n",fst.st_size,
X		mode_map(fst.st_mode & ~(S_ISUID|S_ISGID|S_ISVTX),(char *)0),rname);
X	return(0);
X}
X
Xheader(argc,argv)
Xchar **argv;
X{
Xint i;
XFILE *fpsource;	/* pipe temp */
Xchar s128[128];
Xlong now;
Xstruct tm *utc;
Xstruct tm *gmtime();
X
X	/* see if any conflicting options */
X	if(limit && !filenum)
X	{ /* can't rename what you don't have */
X		fprintf(stderr,"Can't use -l or -L option without -o\n");
X		helpuser();
X		return(1);
X	}
X
X	for(i = 0; i < argc; i++)
X	{ /* skip positional parameters */
X		if(PosParam &&
X			(strcmp(argv[i],"-B") == 0 ||
X		     strcmp(argv[i],"-T") == 0 ||
X		     strcmp(argv[i],"-C") == 0))
X			continue;
X
X		if(walktree(onecheck,argv[i]))
X			return(1);
X	}
X
X	if(Archive_name)
X	{
X		fprintf(fpout,"Submitted-by: %s\n",submitter);
X		fprintf(fpout,"Archive-name: %s%s%02d\n\n",
X			sharname,(strchr(sharname,'/')) ? "" : "/part",
X			(filenum) ? filenum : 1);
X	}
X
X	if(Cut)
X		fputs(CutMessage,fpout);
X	fputs("#!/bin/sh\n",fpout);
X	if(sharname)
X		fprintf(fpout,"# This is %s, a shell archive (produced by shar %s)\n",
X			sharname,revision);
X	else
X		fprintf(fpout,"# This is a shell archive (produced by shar %s)\n",
X			revision);
X	fputs("# To extract the files from this archive, save it to a file, remove\n",
X		fpout);
X	fputs("# everything above the \"!/bin/sh\" line above, and type \"sh file_name\".\n#\n",
X		fpout);
X
X	time(&now);
X	utc = gmtime(&now);
X	fprintf(fpout,"# made %02d/%02d/%04d %02d:%02d UTC by %s\n",
X		utc->tm_mon + 1,utc->tm_mday,utc->tm_year + 1900,
X		utc->tm_hour,utc->tm_min,
X		submitter);
X
X#if defined(SYS5)
X	if(!(fpsource = popen("/bin/pwd","r")))
X		return(-1);
X	fgets(s128,sizeof(s128),fpsource);
X	s128[strlen(s128) - 1] = 0;
X	fclose(fpsource);
X#else
X#if defined(BSD42) || defined(sun)
X	getwd(s128);
X#else
X#include "Need_conditional_compile_fix"
X#endif
X#endif
X	fprintf(fpout,"# Source directory %s\n",s128);
X
X	fprintf(fpout,"#\n# existing files %s\n",
X		(eXists) ? "will NOT be overwritten unless -c is specified" 
X			: ((InterOW) ? "MAY be overwritten"
X				: "WILL be overwritten"));
X
X	if(InterOW)
X		fputs("# The unsharer will be INTERACTIVELY queried.\n",fpout);
X
X	if(Vanilla)
X	{
X		fputs("# This format requires very little intelligence at unshar time.\n",fpout);
X		fputs("# ",fpout);
X		if(eXists || Split)
X			fputs("\"if test\", ",fpout);
X		if(Split)
X			fputs("\"cat\", \"rm\", ",fpout);
X		fputs("\"echo\", \"true\", and \"sed\" may be needed.\n",fpout);
X	}
X
X	if(Split)
X	{ /* may be split, explain */
X		fputs("#\n",fpout);
X		TypePos = ftell(fpout);
X		fprintf(fpout,"%-75s\n%-75s\n","#","#");
X	}
X
X	fputs("#\n# This shar contains:\n",fpout);
X	fputs("# length  mode       name\n",fpout);
X	fputs("# ------ ---------- ------------------------------------------\n",
X		fpout);
X	for(i = 0; i < argc; i++)
X	{ /* output names of files but not parameters */
X		if(PosParam &&
X			(strcmp(argv[i],"-B") == 0 ||
X		     strcmp(argv[i],"-T") == 0 ||
X		     strcmp(argv[i],"-C") == 0))
X			continue;
X		if(walktree(oneheader,argv[i]))
X			exit(1);
X	}
X	fputs("#\n",fpout);
X
X	setTOUCH();
X
X	if(Split)
X	{ /* now check the sequence */
X		fputs("if test -r _shar_seq_.tmp; then\n",fpout);
X		fputs("\techo 'Must unpack archives in sequence!'\n",fpout);
X		fputs("\techo Please unpack part `cat _shar_seq_.tmp` next\n",fpout);
X		fputs("\texit 1\nfi\n",fpout);
X	}
X	return(0);
X}
X
X#define MAX_MKDIR_ALREADY	128	/* ridiculously enough */
Xchar *mkdir_already[MAX_MKDIR_ALREADY];
Xint mkdir_already_count = 0;
X
Xvoid
Xgen_mkdir(path)
Xchar *path;
X{
Xregister int ialready;
Xchar *cptr;
X
X/* if already generated code for this dir creation, don't do again */
X	for(ialready = 0; ialready < mkdir_already_count; ialready++)
X	{
X		if(!strcmp(path,mkdir_already[ialready]))
X			return;
X	}
X
X/* haven't done this one */
X	if(mkdir_already_count == MAX_MKDIR_ALREADY)
X	{
X		fprintf(stderr,"too many directories for mkdir generation\n");
X		exit(255);
X	}
X	if(!(cptr = mkdir_already[mkdir_already_count++] = malloc(strlen(path)+1)))
X	{
X		fprintf(stderr,"out of memory for mkdir generation\n");
X		exit(255);
X	}
X	strcpy(cptr,path);
X
X/* generate the text */
X	fprintf(fpout,"if test ! -d '%s'; then\n",path);
X	if(Verbose)
X		fprintf(fpout,"    echo 'x - creating directory %s'\n",path);
X	fprintf(fpout,"    mkdir '%s'\n",path);
X	fputs("fi\n",fpout);
X
X}	/* end of gen_mkdir */
X
Xvoid
Xgen_mkdir_script(path)
Xregister char *path;
X{
Xregister char *cptr;
X
X	for(cptr = strchr(path,'/'); cptr; cptr = strchr(cptr + 1,'/'))
X	{
X		/* avoid empty string if leading or double '/' */
X		if(cptr == path || *(cptr - 1) == '/')
X			continue;
X		/* omit '.' */
X		if((*(cptr - 1) == '.') && ((cptr == path + 1) || (*(cptr - 2) == '/')))
X			continue;
X		*cptr = 0;				/* temporarily terminate string */
X		gen_mkdir(path);
X		*cptr = '/';
X	}
X}	/* end of gen_mkdir_script */
X
Xint
Xshar(file,RstrName)
Xchar *file, *RstrName;
X{
Xchar line[BUFSIZ];
XFILE *fpsource;
Xlong cursize,remaining,ftell();
Xint split = 0;		/* file split flag */
Xchar *filetype;		/* text or binary */
Xstruct tm *lt;
Xchar *filename_base;
X
X	/* check to see that this is still a regular file  and readable */
X	if((fst.st_mode & S_IFMT) != S_IFREG)
X	{ /* this is not a regular file */
X		fprintf(stderr,"shar: %s is not a regular file\n",file);
X		return(1);
X	}
X	if(access(file,04))
X	{
X		fprintf(stderr,"shar: Can't access %s\n",file);
X		return(1);
X	}
X
X	/* if limit set, get the current output length */
X	if(limit)
X	{
X		cursize = ftell(fpout);
X		remaining = (limit * 1024L) - cursize;
X		DeBug("In shar: remaining size %ld\n",remaining);
X		
X		if(!Split && cursize > EndHeadPos &&
X			(Binary ? fst.st_size + fst.st_size/3 : fst.st_size) > remaining)
X		{ /* change to another file */
X			DeBug("Newfile, remaining %ld, ",remaining);
X			DeBug("limit still %d\n",limit);
X
X			/* close the "&&" and report an error if any of the above failed */
X			fprintf(fpout,"true || echo 'restore of %s failed'\n",RstrName);
X
X			fprintf(fpout, "echo End of part %d, continue with part %d\n",
X				filenum,filenum + 1);
X			fputs("exit 0\n",fpout);
X
X			fclose(fpout);
X
X			/* Clear mkdir_already in case the user unshars out of order */
X			while (mkdir_already_count > 0)
X				free(mkdir_already[--mkdir_already_count]);
X
X			/* form the next filename */
X			sprintf(filename,"%s%02d",outname,++filenum);
X			fpout = fopen(filename,"w");
X			if(Verbose)
X				fprintf(stderr,"Starting file %s\n",filename);
X
X			if(Archive_name)
X			{
X				fprintf(fpout,"Submitted-by: %s\n",submitter);
X				fprintf(fpout,"Archive-name: %s%s%02d\n\n",
X					sharname,(strchr(sharname,'/')) ? "" : "/part",
X					(filenum) ? filenum : 1);
X			}
X
X			if(Cut)
X				fputs(CutMessage,fpout);
X
X			fputs("#!/bin/sh\n",fpout);
X			fprintf(fpout,"# This is part %02d of %s\n",
X			    filenum,(sharname) ? sharname : "a multipart archive");
X
X			setTOUCH();
X
X			EndHeadPos = ftell(fpout);
X		}
X	}
X
X	fprintf(fpout,"# ============= %s ==============\n",RstrName);
X
X	gen_mkdir_script(RstrName);
X
X	/* if mixed, determine the file type */
X	if(Mixed)
X	{
X		int count;
X		sprintf(line,"file %s | egrep -c \"text|shell\"",file);
X		fpsource = popen(line,"r");
X		fscanf(fpsource,"%d",&count);
X		pclose(fpsource);
X		Binary = (count != 1);
X	}
X
X	if(Binary)
X	{ /* fork a uuencode process */
X		static int pid,pipex[2];
X
X		pipe(pipex);
X		fflush(fpout);
X
X		if(pid = fork())
X		{ /* parent, create a file to read */
X			if(pid < 0)
X			{
X				fprintf(stderr,"could not fork!\n");
X				exit(1);
X			}
X			close(pipex[1]);
X			fpsource = fdopen(pipex[0],"r");
X			filetype = (Compress ? "Compressed" : "Binary");
X		}
X		else
X		{ /* start writing the pipe with encodes */
X			FILE *outptr;
X
X			if(Compress)
X			{
X				sprintf(line, "compress -b%d < '%s'", CompressBits, file);
X				fpsource = popen(line, "r");
X			}
X			else
X				fpsource = fopen(file, "rb");
X			outptr = fdopen(pipex[1],"w");
X			fprintf(outptr,"begin 600 %s\n",
X				(Compress ? "_shar_cmp_.tmp" : RstrName));
X			encode(fpsource,outptr);
X			fprintf(outptr,"end\n");
X			if(Compress)
X				pclose(fpsource);
X			else
X			{
X				fclose(fpsource);
X			}
X			exit(0);
X		}
X	}
X	else
X	{
X		fpsource = fopen(file,"r");
X		filetype = "Text";
X	}
X
X	if(fpsource)
X	{
X		/* protect existing files */
X		if(eXists)
X		{
X			fprintf(fpout,"if test -f '%s' -a X\"$1\" != X\"-c\"; then\n",
X				RstrName);
X			if(InterOW)
X			{
X				fputs("\tcase $wish in\n",fpout);
X				fprintf(fpout,"\tA*|a*) echo 'x - overwriting %s';;\n",
X					RstrName);
X				fprintf(fpout,
X		"\t*) echo '? - overwrite %s -- [No], [Y]es, [A]ll, [Q]uit? '\n",
X					RstrName);
X				fputs("\t\tread wish;;\n",fpout);
X				fputs("\tesac\n",fpout);
X				fputs("\tcase $wish in\n",fpout);
X				fputs("\tQ*|q*) echo aborted; exit 86;;\n",fpout);
X				fputs("\tA*|a*|Y*|y*) x=Y;;\n",fpout);
X				fputs("\t*) x=N;;\n",fpout);
X				fputs("\tesac\n",fpout);
X				fputs("else\n",fpout);
X				fputs("\tx=Y\n",fpout);
X				fputs("fi\n",fpout);
X				fputs("if test $x != Y; then\n",fpout);
X				fprintf(fpout,"\techo 'x - skipping %s'\n",RstrName);
X			}
X			else
X				fprintf(fpout,"\techo 'x - skipping %s (File already exists)'\n",
X					RstrName);
X			if (Split)
X				fputs("\trm -f _shar_wnt_.tmp\n",fpout);
X			fputs("else\n",fpout);
X			if (Split)
X				fputs("> _shar_wnt_.tmp\n",fpout);	
X		}
X
X		fprintf(stderr,"shar: saving %s (%s)\n",file,filetype);
X		if(Verbose)
X		{ /* info on archive and unpack */
X			fprintf(fpout,"echo 'x - extracting %s (%s)'\n",
X			    RstrName,filetype);
X		}
X		if(Binary)
X		{ /* run sed through uudecode (via temp file if might get split) */
X			fprintf(fpout, "sed 's/^%c//' << '%s' %s &&\n",
X			   	PREFIX,Delim,
X				(AvoidPipes ? "> _shar_tmp_.tmp" : "| uudecode"));
X		}
X		else
X		{ /* just run it into the file */
X			fprintf(fpout,"sed 's/^%c//' << '%s' > '%s' &&\n",
X			    PREFIX,Delim,RstrName);
X		}
X		while(fgets(line,BUFSIZ,fpsource))
X		{ /* output a line and test the length */
X			if(OptPREFIX && isgraph(line[0]) && line[0] != PREFIX
X#ifdef STRCMP_IS_FAST
X			   && strcmp(line,Delim)
X#else /* STRCMP_IS_FAST */
X			   && (line[0] != Delim[0] || strcmp(line,Delim))
X#endif /* STRCMP_IS_FAST */
X#ifdef STRNCMP_IS_FAST
X			   && strncmp(line,"exit 0",6)	/* See unshar -e: avoid "exit 0" */
X			   && strncmp(line,"From",4)	/* Don't let mail prepend a ">" */
X#else /* STRNCMP_IS_FAST */
X			   && (line[0] != 'e'			/* See unshar -e: avoid "exit 0" */
X				   || strncmp(line,"exit 0",6))
X			   && (line[0] != 'F'			/* Don't let mail prepend a ">" */
X			   	   || strncmp(line,"From",4))
X#endif /* STRNCMP_IS_FAST */
X			  )
X				fputs(line,fpout);
X			else
X			{
X				fprintf(fpout,"%c%s",PREFIX,line);
X				--remaining;	/* count PREFIX (in case Split is in effect) */
X			}
X#ifdef MSDOS	/* This probably doesn't work but accounts for some old code */
X			if(Split && (remaining -= strlen(line) + 1) < 0)	/* 1 extra for CR */
X#else /* MSDOS */
X			if(Split && (remaining -= strlen(line)) < 0)
X#endif /* MSDOS */
X			{ /* change to another file */
X				DeBug("Newfile, remaining %ld, ",remaining);
X				DeBug("limit still %d\n",limit);
X
X				if(line[strlen(line) - 1] != '\n')
X					fputc('\n',fpout);
X
X				fprintf(fpout,"%s\n",Delim);
X
X				/* close the "&&" and report an error if any of the above failed */
X				fprintf(fpout,"true || echo 'restore of %s failed'\n",RstrName);
X
X				if (eXists)
X					fputs("fi\n",fpout);
X
X				if(Verbose)
X				{ /* output some reassurance */
X					fprintf(fpout, "echo 'End of %s part %d'\n",
X						(sharname) ? sharname : "",filenum);
X					fprintf(fpout, "echo 'File %s is continued in part %d'\n",
X					    RstrName,filenum + 1);
X				}
X				else
X					fprintf(fpout,
X					    "echo 'End of part %d, continue with part %d'\n",
X					    filenum,filenum + 1);
X				fprintf(fpout,"echo %d > _shar_seq_.tmp\n",filenum + 1);
X				fputs("exit 0\n",fpout);
X
X				if(filenum == 1)
X				{ /* rewrite the info lines on the firstheader */
X					fseek(fpout,TypePos,0);
X					fprintf(fpout,"%-75s\n%-75s\n",
X					    "# This is part 1 of a multipart archive",
X					    "# do not concatenate these parts, unpack them in order with /bin/sh");
X				}
X				fclose(fpout);
X
X				/* form the next filename */
X				sprintf(filename,"%s%02d",outname,++filenum);
X				fpout = fopen(filename,"w");
X
X				if(Archive_name)
X				{
X					fprintf(fpout,"Submitted-by: %s\n",submitter);
X					fprintf(fpout,"Archive-name: %s%s%02d\n\n",
X						sharname,(strchr(sharname,'/')) ? "" : "/part",
X						(filenum) ? filenum : 1);
X				}
X
X				if(Cut)
X					fputs(CutMessage,fpout);
X				fputs("#!/bin/sh\n",fpout);
X
X				fprintf(fpout,"# this is %s (part %d of %s)\n",
X					((filename_base = strrchr(filename,'/'))
X						? filename_base + 1
X						: filename),
X				    filenum,
X				    (sharname) ? sharname : "a multipart archive");
X				fputs(
X		"# do not concatenate these parts, unpack them in order with /bin/sh\n",
X					fpout);
X				fprintf(fpout,"# file %s continued\n#\n",RstrName);
X
X				setTOUCH();
X				
X				fputs("if test ! -r _shar_seq_.tmp; then\n",fpout);
X				fputs("\techo 'Please unpack part 1 first!'\n",fpout);
X				fputs("\texit 1\nfi\n",fpout);
X				fputs("(read Scheck\n",fpout);
X				fprintf(fpout," if test \"$Scheck\" != %d; then\n",filenum);
X				fputs("\techo Please unpack part \"$Scheck\" next!\n",
X					fpout);
X				fputs("\texit 1\n",fpout);
X				fputs(" else\n\texit 0\n fi\n",fpout);
X				fputs(") < _shar_seq_.tmp || exit 1\n",fpout);
X
X				if(eXists)
X					if(Verbose)
X					{ /* keep everybody informed */
X						fputs("if test ! -f _shar_wnt_.tmp; then\n",fpout);
X						fprintf(fpout,"\techo 'x - still skipping %s'\n",
X								RstrName);
X						fputs("else\n",fpout);
X					}
X					else
X						fputs("if test -f _shar_wnt_.tmp; then\n",fpout);
X
X				if(Verbose)
X				{ /* keep everybody informed */
X					fprintf(stderr,"Starting file %s\n",filename);
X					fprintf(fpout,"echo 'x - continuing file %s'\n",RstrName);
X				}
X				fprintf(fpout,"sed 's/^%c//' << '%s' >> '%s' &&\n",
X				    PREFIX,Delim,
X					(Binary ? "_shar_tmp_.tmp" : RstrName));
X				remaining = limit * 1024L;
X				split = 1;
X			}
X		}
X
X		(void) fclose(fpsource);
X		while(wait((int *)0) >= 0)
X			;
X
X		if(line[strlen(line) - 1] != '\n')
X			fputc('\n',fpout);
X
X		fprintf(fpout,"%s\n",Delim);
X		if(split && Verbose)
X			fprintf(fpout,"echo 'File %s is complete' &&\n",RstrName);
X
X		/* if this file was uuencoded w/Split, decode it and drop the temp */
X		if(Binary && AvoidPipes)
X		{
X			if(Verbose)
X				fprintf(fpout,"echo 'uudecoding file %s' &&\n",RstrName);
X			fputs("uudecode < _shar_tmp_.tmp && rm -f _shar_tmp_.tmp &&\n",fpout);
X		}
X
X		/* if this file was compressed, uncompress it and drop the temp */
X		if(Compress)
X		{
X			if(Verbose)
X				fprintf(fpout,"echo 'uncompressing file %s' &&\n",RstrName);
X			fprintf(fpout,
X			    "compress -d < _shar_cmp_.tmp > '%s' && rm -f _shar_cmp_.tmp &&\n",
X				RstrName);
X		}
X
X		if(Touch)
X		{
X			/* set the dates as they were */
X			lt = localtime(&fst.st_mtime);
X			fprintf(fpout,"$TOUCH -am %02d%02d%02d%02d%02d '%s' &&\n",
X				lt->tm_mon + 1,
X				lt->tm_mday,
X				lt->tm_hour,
X				lt->tm_min,
X				lt->tm_year,
X				RstrName);
X		}
X
X		if(Vanilla)
X		{
X			/* close the "&&" and report an error if any of the above failed */
X			fprintf(fpout,"true || echo 'restore of %s failed'\n",RstrName);
X		}
X		else
X		{
X			/* set the permissions as they were */
X			fprintf(fpout,"chmod %04o %s ||\n",
X				fst.st_mode & 00777,RstrName);
X
X			/* report an error if any of the above failed */
X			fprintf(fpout,"echo 'restore of %s failed'\n",RstrName);
X
X			if(Wc_c)
X			{ /* validate the transferred file */
X				FILE *pfp;
X				char command[BUFSIZ];
X
X				sprintf(command,"%s '%s'",WC,file);
X				if((pfp = popen(command,"r")))
X				{
X					char wc[BUFSIZ];
X
X					fscanf(pfp,"%s",wc);
X					fprintf(fpout,"Wc_c=\"`%s '%s'`\"\n",WC,RstrName);
X					fprintf(fpout,"test %s -eq \"$Wc_c\" ||\n",wc);
X					fprintf(fpout,
X					    "\techo '%s: original size %s, current size' \"$Wc_c\"\n",
X						RstrName, wc);
X					pclose(pfp);
X				}
X			}
X		}
X
X		/* if the exists option is in place close the if */
X		if(eXists)
X		{
X			if (Split)
X				fputs("rm -f _shar_wnt_.tmp\n",fpout);
X
X			fputs("fi\n",fpout);
X		}
X
X		return(0);
X	}
X	else
X	{
X		fprintf(stderr,"shar: Can't open %s (%s): ",file,filetype);
X		perror("");
X		return(1);
X	}
X}
X
X
Xchar *helpinfo[] =
X{
X	"-V  produce \"vanilla\" shars demanding little of the unshar environment",
X	"-v  verbose messages OFF while executing",
X	"-m  restore file modification dates & times with \"touch\" commands",
X	"-w  don't check with 'wc -c' after unpack",
X	"-a  generate Submitted-by: & Archive-name: headers",
X	"-nXXX   use XXX as the name of the archive (documentation)",
X	"-s  override automatically determined submitter name",
X	"-x  overwrite existing files without checking if they already exist",
X	"-X  interactively overwrite existing files (NOT FOR NET SHARS)",
X	"-B  treat all files as binary, use uuencode",
X	"-T  treat all files as text (default)",
X	"-C  compress and uuencode all files",
X	"-bXX    pass -bXX (default 12) to compress when compressing (implies -C)",
X	"-p  allow positional parameter options. The options \"-B\" and \"-T\"",
X	"    and \"-C\" may be embedded, and files to the right of the",
X	"    option will be processed in the specified mode",
X	"-M  mixed mode. Determine if the files are text or",
X	"    binary and archive correctly.",
X	"-P  use temp files instead of pipes in the shar file",
X	"-F  force the prefix character on every line (even if not required)",
X	"-c  start the shar with a cut line",
X	"-f  restore by filename only, rather than path",
X	"-dXXX   use XXX to delimit the files in the shar",
X	"-oXXX   (or -o XXX) output to file XXX.01 thru XXX.nn",
X	"-lXX    limit output file size to XXk bytes (but don't split files)",
X	"-LXX    limit output file size to XXk bytes (may split files)",
X	"-S      read files to wrap from stdin, ignoring argument line",
X	"\nThe -S option reads filenames one per line from stdin; input",
X	"format must be similar to 'find' output, except that if -p",
X	"is specified, -B, -T or -C may be used (on lines by themselves)",
X	"e.g., find . -type f -print | sort | shar -C -l50 -o /tmp/big",
X	"\nThe 'o' option is required if the 'l' or 'L' option is used",
X	"The 'n' option is required if the 'a' option is used",
X	"\n-a generates sharname/part## headers. If the -a argument contains",
X	"a '/', then /part is not appended",
X	"The automatic submitter name is trivial: essentially `whoami`@`uname`",
X	(char *)0
X};
X
Xhelpuser()
X{				/* output a command format message */
X	register char **ptr;
X	fprintf(stderr,
X	    "shar %s\nusage: shar [ options ] file ...\n       shar -S [ options ]\n",
X		revision);
X	for(ptr = helpinfo; *ptr; ptr++)
X		fprintf(stderr,"%s\n",*ptr);
X
X	exit(1);
X}
X/* vi: set tabstop=4 shiftwidth=4: */
SHAR_EOF
chmod 0644 shar.c ||
echo 'restore of shar.c failed'
Wc_c="`wc -c < 'shar.c'`"
test 38151 -eq "$Wc_c" ||
	echo 'shar.c: original size 38151, current size' "$Wc_c"
fi
exit 0
-- 
  ==========================================================================
  | Richard H. Gumpertz    rhg@CPS.COM    (913) 642-1777 or (816) 891-3561 |
  | Computer Problem Solving, 8905 Mohawk Lane, Leawood, Kansas 66206-1749 |
  ==========================================================================

tjc@ecs.soton.ac.uk (Tim Chown) (09/14/90)

In <541@cpsolv.CPS.COM> rhg@cpsolv.CPS.COM (Richard H. Gumpertz) writes:

>Submitted-by: rhg@cpsolv
>Archive-name: shar3.49/part01

>Patch 3 to shar 3.43 was relative to the wrong version of Makefile.  Rather
>than try to patch a patch and all that, here is the whole thing.

Is a static version of shar near?  I'm greatful for any bug-fixes
and enhancements, but patches seem to be rather prolific at present!!

Cheers,
	Tim.