home *** CD-ROM | disk | FTP | other *** search
- From: decvax!ucbvax!hpda!hpdsb!bd (Bob Desinger)
- Subject: The Connoisseur's Shar, version 2
- Status: RO
-
- Here is the shell archiver often referred to as "The Connoisseur's Shar."
- Actually, it's an upgrade to the Conn. Shar originally posted to net.sources
- a few months ago. It runs on Berkeley and Bell Unixes.
-
- Bob Desinger
- ucbvax!hpda!bd hpda!bd@BERKELEY ihnp4!hpfcla!hpda!bd
- Hewlett-Packard Co. 11000 Wolfe Road Cupertino, CA 95014
-
-
- # 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 hpdsb!bd on Tue Dec 18 14:08:21 PST 1984
- # Contents: shar.announcement shar.l shar
-
- echo x - shar.announcement
- sed 's/^@//' > "shar.announcement" <<'@//E*O*F shar.announcement//'
- Here's the latest "Connoisseur's shar" and documentation. It has a few
- advantages over the previously-posted version:
-
- 1. You can archive a whole directory subtree via: shar `find dir -print`
- 2. The original file's permissions/modes are duplicated upon unpacking.
- 3. The EOF marker is guaranteed to be unique from what's in the archive files.
- 4. A timestamp and personstamp is recorded in the archive.
- 5. Lines beginning with characters that mailers don't like (tildes, dots,
- ampersands) are no longer dangerous.
- 6. The table-of-contents line no longer overflows your mailer's maximum line.
-
- These features also make this a candidate for being dubbed "The Glutton's Shar"
- since it takes longer to start up. The way to fix that would be to rewrite it
- in C, but that seems to take away some of its novelty. Still, a C version may
- be forthcoming (especially if someone volunteers!)....
-
- Kudos to Dan Hoey <hoey@NRL-AIC.ARPA>, who contributed immensely to shar's
- current feature set, especially the directory-recursing code. A tip of the
- Hatlo hat also to Alan Silverstein, who set shar's clear coding style and fixed
- bugs in earlier versions.
-
- Bob Desinger
- ucbvax!hpda!bd hpda!bd@BERKELEY ihnp4!hpfcla!hpda!bd
- Hewlett-Packard Co. 11000 Wolfe Road Cupertino, CA 95014
- @//E*O*F shar.announcement//
- chmod u=rw,g=rw,o=r shar.announcement
-
- 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
-
- 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 Inspecting for damage in transit...
- temp=/tmp/shar$$; dtemp=/tmp/.shar$$
- trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
- cat > $temp <<\!!!
- 24 195 1278 shar.announcement
- 121 539 3292 shar.l
- 176 771 4548 shar
- 321 1505 9118 total
- !!!
- wc shar.announcement shar.l shar | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
- if [ -s $dtemp ]
- then echo "Ouch [diff of wc output]:" ; cat $dtemp
- else echo "No problems found."
- fi
- exit 0
-
-