Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.2 9/3/84; site genrad.UUCP Path: utzoo!decvax!genrad!bd@hpdsb.UUCP From: bd@hpdsb.UUCP Newsgroups: mod.sources Subject: Re: The Connoisseur's Shar, version 2 Message-ID: <542@genrad.UUCP> Date: Thu, 20-Dec-84 10:07:34 EST Article-I.D.: genrad.542 Posted: Thu Dec 20 10:07:34 1984 Date-Received: Fri, 21-Dec-84 06:38:26 EST Sender: john@genrad.UUCP Lines: 314 Approved: john@genrad.UUCP # 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 < \"$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