From harvard!uucp Mon Nov 18 19:39:25 1985 Received: from harvard.HARVARD.EDU by seismo.CSS.GOV with SMTP; Mon, 18 Nov 85 19:12:32 EST Received: by harvard.HARVARD.EDU; Mon, 18 Nov 85 19:14:11 EST From: harvard!uucp (Black Hole) Return-Path: Received: by panda.LOCAL on Mon, 18 Nov 85 18:38:22 est Date: Mon, 18 Nov 85 18:38:22 est Message-Id: <8511182338.AA22129@panda.LOCAL> To: talcott!seismo!rick Subject: newshar Status: R 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 , 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 < \"$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