The Connoisseur's Shar, version 2

bd at hpdsb.UUCP bd at hpdsb.UUCP
Fri Dec 21 01:07:34 AEST 1984


# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by john on Thu Dec 20 10:04:09 EST 1984
# Contents:  shar shar.l
 
echo x - shar
sed 's/^@//' > "shar" <<'@//E*O*F shar//'

# UNISRC_ID: @(#)shar.sh	27.1	84/12/17  
: Make a shell archive package

# Usage: $0 [-b] [-c] [-t] [-v] files... > package
# See the manual entry for details.


# Initialize:

diagnostic='eval echo >&2'	# diagnostics to stderr by default.
trap '$diagnostic "$0: quitting early"; exit 1' 1 2 3 15
base_option=FALSE		# use pathnames, not basenames.
check_option=FALSE		# don't generate integrity check.
USAGE='Usage: $0 \[-b] \[-c] \[-t] \[-v] files... \> package'


# Extract and digest options, if any:
#
# Un-comment the "-)" line below to treat single dashes as a no-op.
# Commented means single dashes elicit a usage diagnostic.

while [ -n "$1" ]	# while there are more arguments,
do			# digest them; stop when you find a non-option.
	case "$1" in
	-b)	base_option=TRUE;	shift;;
	-c)	check_option=TRUE;	shift;;
	-v)	verbose=TRUE;		shift;;
	-t)	verbose=TRUE; diagnostic='eval echo >/dev/tty'; shift;;
###	-)	shift;;		# if uncommented, eat single dashes.
	-*)	$diagnostic $USAGE; exit 1;;	 # die at illegal options.
	*)	break;;		# non-option found.
	esac
done


# Check remaining arguments, which should be just a list of files:

if [ $# = 0 ]
then	# no arguments left!
	$diagnostic $USAGE
	exit 1
fi


# Check the cupboard to see if the ingredients are all there:

contents=''	# no files so far.
contdirs=''	# no directories so far.

for arg		# for all files specified,
do		# establish the archive name.
	if [ -f "$arg" ]
	then	# file exists and is not a directory.
		case $base_option in
		TRUE)	unpack_name=`basename "$arg"` ;;
		FALSE)	unpack_name="$arg" ;;
		esac

		contents="$contents $unpack_name"

	elif [ -d "$arg" ]
	then	# file exists and is a directory.
		case $base_option in
		TRUE)   $diagnostic '$0: cannot archive directory "$arg" with -b option.'
			exit 1 ;;
		FALSE)  contdirs="$contdirs $arg/ " ;;
		esac

	else	# not a plain file and not a directory.
		$diagnostic '$0: cannot archive "$arg"'
		exit 1
	fi
done


# Emit the prologue:
# (The leading newline is for those who type csh instead of sh.)

cat <<!!!

# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by `who am i | sed 's/[ 	].*//'` on `date`
!!!


# Emit the list of ingredients:

# Simple version (breaks if you shar lots of files at once):
#	echo "# Contents: $contdirs$contents"
#
# Complex and cosmetic version to pack contents list onto lines that fit on
# one terminal line ("expr string : .*" prints the length of the string):

MAX=80
line='# Contents: '
for item in $contdirs $contents
do
	if [ `expr "$line" : '.*' + 1 + "$item" : '.*'` -lt $MAX ]
	then	# length of old line + new item is short enough,
		line="$line $item"	# so just append it.

	else	# new element makes line too long,
		echo "$line"		# so put it on a new line.
		line="#	$item"		# start a new line.
		MAX=74			# compensate for tab width.
	fi
done

echo "$line"
echo " "


# Emit the files and their separators:

for arg
do
	# Decide which name to archive under.
	case $base_option in
	TRUE)   unpack_name=`basename "$arg"`
		test $verbose && $diagnostic "a - $unpack_name [from $arg]" ;;
	FALSE)  unpack_name="$arg"
		test $verbose && $diagnostic "a - $arg" ;;
	esac

	# Emit either a mkdir or a cat/sed to extract the file.
	if [ -d "$arg" ]
	then
		echo "echo mkdir - $arg"
		echo "mkdir $arg"
	else
		echo "echo x - $unpack_name"
		separator="@//E*O*F $unpack_name//"
		echo "sed 's/^@//' > \"$unpack_name\" <<'$separator'"
		sed  -e 's/^[.~@]/@&/'  -e 's/^From/@&/'  "$arg"
		echo $separator
	fi

	# Emit chmod to set permissions on the extracted file;
	# this keels over if the filename contains "?".
	ls -ld $arg | sed \
		-e 's/^.\(...\)\(...\)\(...\).*/u=\1,g=\2,o=\3/' \
		-e 's/-//g' \
		-e 's?.*?chmod & '"$unpack_name?"
	echo " "
done


# If the -c option was given, emit the checking epilogue:
# (The sed script converts files to basenames so it works regardless of -b.)

if [ $check_option = TRUE ]
then
	echo 'echo Inspecting for damage in transit...'
	echo 'temp=/tmp/shar$$; dtemp=/tmp/.shar$$'
	echo 'trap "rm -f $temp $dtemp; exit" 0 1 2 3 15'
	echo 'cat > $temp <<\!!!'
	case $base_option in
	TRUE)   wc $@ | sed 's=[^ ]*/=='	;;
	FALSE)  wc $contents | sed 's=[^ ]*/=='	;;
	esac
	echo '!!!'
	echo "wc $contents | sed 's=[^ ]*/==' | "'diff -b $temp - >$dtemp'
	echo 'if [ -s $dtemp ]'
	echo 'then echo "Ouch [diff of wc output]:" ; cat $dtemp'
	echo 'else echo "No problems found."'
	echo 'fi'
fi


# Finish up:

echo 'exit 0'	# sharchives unpack even if junk follows.
exit 0
@//E*O*F shar//
chmod u=rwx,g=rx,o=rx shar
 
echo x - shar.l
sed 's/^@//' > "shar.l" <<'@//E*O*F shar.l//'
@.TH SHAR LOCAL HEWLETT-PACKARD
@.ad b
@.SH NAME
shar \- make a shell archive package
@.SH SYNOPSIS
\fBshar\fR [\fB-b\fR] [\fB-c\fR] [\fB-t\fR] [\fB-v\fR] file ...
@.SH DESCRIPTION
@.I Shar
bundles the named
@.IR file ( s )
into a single distribution package suitable for mailing or carrying around.
The files should be mailable (not object code, for instance).
@.IR Shar 's
resulting package, written to standard output, is an editable file.
It is actually a shell script using
@.IR sh (1)
"here" documents to extract its contents into the appropriate places.
@.PP
The package is unwrapped by running
@.IR sh
with the package name as an argument.
Its files are written to the pathnames recorded in the archive,
then permissions are set via
@.IR chmod (1)
to match the original files.
@.PP
Except with the
@.B \-b
option, a directory tree
@.I dir
can be archived using the command "shar `find
@.I dir
-print`".
@.PP
Available options are:
@.TP
@.B \-b
Archive files under their basenames, regardless of the original pathnames
specified.
The contents are thus unpacked into the current directory instead of to the
originally-specified pathnames.
This allows you to archive files from many directories but unpack them into a
single directory.
It also allows you to unpack, say,
@.I /etc/termcap
into
@.I ./termcap
instead of overwriting the original one in
@.IR /etc .
@.TP
@.B \-c
Append to the package a simple data-integrity check using
@.IR wc (1)
to insure that the contents were not damaged in transit.
This check will be performed automatically after unpacking.
@.TP
@.B \-t
Write diagnostics and messages directly to your terminal,
instead of to the standard error.  This is useful when invoking
@.I shar
from programs such as
@.IR vi (1)
which normally combine standard error with standard output.
Specifying
@.B \-t
also turns on the
@.B \-v
(verbose) option.
@.TP
@.B \-v
Announce archived file names as they are packed.
The
@.B \-t
option determines the destination for these announcements.
@.br
@.ne 5
@.SH FILES
/dev/tty               	if specified with \fB-t\fR
@.br
/tmp/shar*, /tmp/.shar*	when inspecting for damage
@.br
cat, echo, sed, chmod  	as subprocesses
@.br
basename, wc, mkdir    	as optional subprocesses
@.SH DIAGNOSTICS
@.I Shar
refuses to archive nonexistent files.
When the
@.B \-b
option is used, it refuses to archive directories.
@.I Shar
terminates and does no archiving if it encounters either problem.
@.PP
Exit status 1 is returned upon interrupt or trouble with arguments.
@.SH "SEE ALSO"
ar(1),
cpio(1),
find(1),
tar(1).
@.SH BUGS
Archived directories must appear before the files in them.  Failure to adhere
to this ordering is not detected, but the result will fail to unpack.
@.PP
Ownerships for archived files are not retained.
@.PP
The integrity check is very simple-minded.
In particular, it notices only if the number of characters, words, or lines
is altered; it fails to catch bits flipped during transmission.
@.PP
@.I Shar
should complain about binary files.
It should also complain about filenames with embedded spaces and
question marks, which
@.IR shar 's
subprocesses don't handle.
@.PP
There should be a standard way
to record the system on which the archive was created.
Berkeley hosts return this information via
@.IR "who am i" ,
but Bell-derived hosts often use wildly differing methods.
@//E*O*F shar.l//
chmod u=rw,g=rw,o=r shar.l
 
exit 0



More information about the Mod.sources mailing list