shar 3.21

Showing 1-1 of 1 messages
shar 3.21 Warren Tucker 4/20/90 1:25 PM
Submitted-by: wht%...@gatech.edu
Archive-name: shar321/part01

Here is shar 3.21, an updated version of shar 3.11, derived from 'shar2'.
This offering is the work of many people. Lately, r...@CPS.COM (Richard H.
Gumpertz) made significant changes to 3.11. co...@avahi.inria.fr (Colas
Nahaboo) and I made enhancements to unshar. The details appear in
the README file.

---- Cut Here and unpack ----
#!/bin/sh
# This is shar321, a shell archive (shar 3.21)
# made 04/19/1990 20:17 UTC by wht%...@gatech.edu
# Source directory /u1/src/shar
#
# existing files WILL be overwritten
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#   5941 -rw-r--r-- README
#    333 -rw-r--r-- Makefile
#  28774 -rw-r--r-- shar.c
#  10737 -rw-r--r-- unshar.c
#   1169 -rw-r--r-- uushar.c
#   2784 -rw-r--r-- who@where.c
#
if touch 2>&1 | fgrep '[-amc]' > /dev/null
 then TOUCH=touch
 else TOUCH=true
fi
# ============= README ==============
echo "x - extracting README (Text)"
sed 's/^X//' << 'SHAR_EOF' > README &&
XSubmitted-by: wht%...@gatech.edu
XArchive-name: shar321/part01
X
XHere is shar 3.21, an updated version of shar 3.11, derived from 'shar2'.
XThis offering is the work of many people. Lately, r...@CPS.COM (Richard H.
XGumpertz) made significant changes to 3.11. co...@avahi.inria.fr (Colas
XNahaboo) and I made enhancements to unshar. The change history appears
Xat the bottom of this file.
X
XThis version's shar:
X1) generates shell code which attempts to create missing directories
X2) 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
X3) if unsharing system's touch is Sys V compatible (allows touch -m),
X   the unshar process restores file dates
X4) An archive name may be specified for includion in the header
X   of the shar files( -n switch)
X5) allows automatic generation of "Submitted-by: who@where" &
X   "Archive-name: <name>/part##" headers
X6) uses getopt; no good system library should be without a copy
X   but it is readily available (like look in unshar.c)
X7) other chrome-plated 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) does not have an Social Security number.
X
X------------------------ shar  usage -----------------------------------
X
Xshar 3.21
Xusage: shar [ options ] file [ file1 ... ] ]
X-v  verbose messages OFF while executing
X-w  don't check with 'wc -c' after unpack
X-n  Name of archive (documentation)
X-a  Generate Submitted-by: & Archive-name: headers
X-s  override automatically determined submitter name
X-x  don't overwrite existing files
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-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-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
XThe 'o' option is required if the 'l' or 'L' option is used
XThe 'n' option is required if the 'a' option is used
XThe 'x' and 'L' options are incompatible
X
X-a generates sharname/part## headers. If you are producing patches
Xyou'll need to edit -a headers (or please improve shar :-))
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 [-c] [-C exit_line] [ -d directory ] [ file ] ...
X
X     The -d flag tells unshar to change directory before unsharing
X
X     It can unshar shar files concatenated in one file, with the
X     the "-c" command, which separates files by recognizing the
X     "exit 0" string at the beginning of a line
X
X     (The -C string option allows you to specify this string, thus
X     -c is equivalent to -C "exit 0")
X
X
X--------------------- history -----------------------------------------
XChanges since 3.11: kudos to r...@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 co...@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
SHAR_EOF
$TOUCH -am 0419161790 README &&
chmod 0644 README ||
echo "restore of README failed"
set `wc -c README`;Wc_c=$1
if test "$Wc_c" != "5941"; then
        echo original size 5941, current size $Wc_c
fi
# ============= Makefile ==============
echo "x - extracting Makefile (Text)"
sed 's/^X//' << 'SHAR_EOF' > Makefile &&
X#  CHK=0xDDF8
X#
X#  makefile for shar
X#
X#+:EDITS:
X#:03-28-1990-14:54-wht@n4hgf-for 3.10, add who@where.c
X
XCFLAGS        = -O
X
XSRC        = shar.c uushar.c unshar.sh
XOBJ        = shar.o uushar.o who@where.o
XDOC        = shar.1 unshar.1 shar.readme
X
Xall: shar unshar
X
Xshar: $(OBJ)
X        cc $(CFLAGS) $(OBJ) -o shar
X
Xunshar : unshar.c
X        cc $(CFLAGS) unshar.c -o unshar;
SHAR_EOF
$TOUCH -am 0328165590 Makefile &&
chmod 0644 Makefile ||
echo "restore of Makefile failed"
set `wc -c Makefile`;Wc_c=$1
if test "$Wc_c" != "333"; then
        echo original size 333, current size $Wc_c
fi
# ============= shar.c ==============
echo "x - extracting shar.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > shar.c &&
X/* CHK=0x688E */
Xchar *revision = "3.21";
X/*
X** shar.c
X
X  Defined functions:
X        Rname(file)
X        exit_incompat()
X        gen_mkdir(path)
X        gen_mkdir_script(path)
X        setTOUCH()
X        header(argc,argv)
X        helpuser()
X        main(argc,argv)
X        mode_map(mode,mode_str)
X        shar(file)
X
X*/
X/*+:EDITS:*/
X/*:04-18-1990-02:01-wht@n4hgf-3.20 r...@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%...@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%...@gatech.edu
X *  Message-Id: <9004061514.AA01781@n4hgf.UUCP>
X *
X *  1. changes suggested by pat@rwing (Pat Myrto) and sil...@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%...@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
X/* assume system v unless otherwise fixed */
X#if (defined(pyr) || defined(vax) || defined(sequent)) && !defined(BSD42)
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)
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
X                                                 * starts with PREFIX1 */
X#define PREFIX                (Delim[0] == PREFIX1 ? PREFIX2 : PREFIX1)
X#define WC                "wc -c"
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 Cut = 0;                        /* option to provide cut mark */
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 Compress = 0;                /* run input files through compress (requires Binary) */
Xint Mixed = 0;                        /* mixed text and binary files */
Xint eXists = 0;                        /* 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;
Xchar *Rname();                        /* file restore name */
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;
Xchar *oname;
Xint c;
Xextern int optind;
Xextern char *optarg;
X
X        while((c = getopt(argc,argv,"vwd:btCxXcfMpPas:n:l:L:o:h")) != -1)
X        {
X                switch(c)
X                {
X                case 'v':
X                        Verbose = 0;
X                        break;
X                case 'w':
X                        Wc_c = 0;
X                        break;
X                case 'd':
X                        Delim = optarg;
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 'C': /* Compress */
X                        Binary = 1;
X                        Compress = 1;
X                        break;
X                case 'x': /* does the file exist */
X                        eXists = 1;
X                        if(InterOW || Split)
X                                exit_incompat();
X                        break;
X                case 'X': /* does the file exist */
X                        InterOW = 1;
X                        if(eXists || Split)
X                                exit_incompat();
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 '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(eXists)
X                                exit_incompat();
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(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                submitter = malloc(128);
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                fprintf(fpout,"wish=\n");
X                if(Archive_name)
X                {
X                        printf("PLEASE do not submit -X shars to the usenet or other\n");
X                        printf("public networks.  They will cause problems.\n");
X                }
X        }
X
X        EndHeadPos = ftell(fpout);
X
X        while(optind < argc)
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                                optind++;
X                                continue;
X                        }
X                        if(strcmp(argv[optind],"-t") == 0)
X                        { /* set mode text */
X                                Binary = 0;
X                                Compress = 0;
X                                optind++;
X                                continue;
X                        }
X                        if(strcmp(argv[optind],"-C") == 0)
X                        { /* set compress */
X                                Binary = 1;
X                                Compress = 1;
X                                optind++;
X                                continue;
X                        }
X                }
X                status += 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{
Xregister unsigned ftype = mode & S_IFMT;
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        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} /* end of setTOUCH */
X
Xheader(argc,argv)
Xchar **argv;
X{
Xint i;
Xint status;
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        }
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                /* see if access and correct type */
X                if(access(argv[i],4))
X                {
X                        fprintf(stderr,"shar: Can't access %s\n",argv[i]);
X                        return(1);
X                }
X
X                /* get file type */
X                stat(argv[i],&fst);
X                status = fst.st_mode & S_IFMT;
X
X                /* at this point I check to see that this is a regular file */
X                if(status != S_IFREG)
X                { /* this is not a regular file */
X                        fprintf(stderr,"shar: %s is not a regular file\n",argv[i]);
X                        return(1);
X                }
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("---- Cut Here and unpack ----\n",fpout);
X        fputs("#!/bin/sh\n",fpout);
X        if(sharname)
X                fprintf(fpout,"# This is %s, a shell archive (shar %s)\n",
X                        sharname,revision);
X        else
X                fprintf(fpout,"# This is a shell archive (shar %s)\n",revision);
X
X        time(&now);
X        utc = gmtime(&now);
X        fprintf(fpout,"# made %02d/%02d/%04d %02d:%02d UTC ",
X                utc->tm_mon + 1,utc->tm_mday,utc->tm_year + 1900,
X                utc->tm_hour,utc->tm_min);
X
X        fputs("by ",fpout);
X        fputs(submitter,fpout);
X        fputs("\n",fpout);
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 be overwritten\n",
X        (eXists) ? "will NOT"
X                 : ((InterOW) ? "MAY" : "WILL"));
X        if(InterOW)
X                fprintf(fpout,"# The unsharer will be INTERACTIVELY queried.\n");
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                stat(argv[i],&fst);
X                fst.st_mode &= ~(07000); /* turn off setuid, setgid and sticky bits */
X                fprintf(fpout,"# %6ld %s %s\n",fst.st_size,
X                        mode_map(fst.st_mode,(char *)0),Rname(argv[i]));
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("\tnext=`cat @shar_seq_.tmp`; ",fpout);
X                fputs("echo \"Please unpack part $next next\"\n\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, dont 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        fprintf(fpout,"fi\n");
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
Xshar(file)
Xchar *file;
X{
Xchar line[BUFSIZ];
XFILE *fpsource;
Xlong cursize,remaining,ftell();
Xint split = 0;                /* file split flag */
Xchar *filetype;                /* text or binary */
Xchar *RstrName;                /* name for restore */
Xstruct tm *lt;
Xchar *filename_base;
X
X        /* get file size, dates, and mode for later */
X        stat(file,&fst);
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                        fprintf(fpout,
X                                "echo \"End of part %d, continue with part %d\"\n",
X                                filenum,filenum + 1);
X                        fprintf(fpout,"exit 0\n");
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("---- Cut Here and unpack ----\n",fpout);
X                        if(!(filename_base = strrchr(filename,'/')))
X                                filename_base = filename;
X                        else
X                                filename_base++;
X
X                        fprintf(fpout,"#!/bin/sh\n");
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        /* determine the name to use for restore */
X        RstrName = Rname(file);
X
X        fputs("# ============= ",fpout);
X        fputs(RstrName,fpout);
X        fputs(" ==============\n",fpout);
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                        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 < %s", 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                                fclose(fpsource);
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 X\"$1\" != X\"-c\" -a -f '%s'; then\n",
X                                RstrName);
X                        if(InterOW)
X                        {
X                                fprintf(fpout,"\tcase $wish in\n");
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                                fprintf(fpout,"\t\tread wish;;\n");
X                                fprintf(fpout,"\tesac\n");
X                                fprintf(fpout,"\tcase $wish in\n");
X                                fprintf(fpout,"\tQ*|q*) echo aborted; exit 86;;\n");
X                                fprintf(fpout,"\tA*|a*|Y*|y*) x=Y;;\n");
X                                fprintf(fpout,"\t*) x=N;;\n");
X                                fprintf(fpout,"\tesac\n");
X                                fprintf(fpout,"else\n");
X                                fprintf(fpout,"\tx=Y\n");
X                                fprintf(fpout,"fi\n");
X                                fprintf(fpout,"if test $x != Y; then\n");
X                                fprintf(fpout,"\techo x - skipping '%s'\n",RstrName);
X                        }
X                        else
X                                fprintf(fpout,"\techo \"File already exists: skipping '%s'\"\n",
X                                        RstrName);
X                        fprintf(fpout,"else\n");
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                        fprintf(fpout,"%c%s",PREFIX,line);
X                        if(Split && (remaining -= strlen(line) + 2) < 0)
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                                if(Verbose)
X                                { /* output some reassurance */
X                                        fprintf(fpout,
X                                            "echo \"End of %s part %d\"\n",
X                                                        (sharname) ? sharname : "",filenum);
X                                        fprintf(fpout,
X                                            "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                                fprintf(fpout,"exit 0\n");
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("---- Cut Here and unpack ----\n",fpout);
X                                if(!(filename_base = strrchr(filename,'/')))
X                                        filename_base = filename;
X                                else
X                                        filename_base++;
X
X                                fprintf(fpout,"#!/bin/sh\n");
X                                fprintf(fpout,
X                                    "# this is %s (part %d of %s)\n",
X                                        filename_base,
X                                    filenum,
X                                    (sharname) ? sharname : "a multipart archive");
X                                fputs("# do not concatenate these parts, ",fpout);
X                                fputs("unpack them in order with /bin/sh\n",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,
X                                          " 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(Verbose)
X                                { /* keep everybody informed */
X                                        fprintf(stderr,"Starting file %s\n",filename);
X                                        fprintf(fpout,
X                                            "echo \"x - Continuing file %s\"\n",RstrName);
X                                }
X                                fprintf(fpout,
X                                    "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
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,
X                            "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                        fprintf(fpout,
X                            "uudecode < @shar_tmp_.tmp && rm -f @shar_tmp_.tmp &&\n");
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                /* 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,lt->tm_mday,lt->tm_hour,lt->tm_min,lt->tm_year,
X                        RstrName);
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,"set `%s %s`;Wc_c=$1\n",
X                                    WC,RstrName);
X                                fprintf(fpout,
X                                    "if test \"$Wc_c\" != \"%s\"; then\n",wc);
X                                fprintf(fpout,
X                                    "\techo original size %s, current size $Wc_c\nfi\n",
X                                        wc);
X                                pclose(pfp);
X                        }
X                }
X
X                /* if the exists option is in place close the if */
X                if(eXists)
X                        fprintf(fpout,"fi\n");
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
Xchar *
XRname(file)
Xregister char *file;
X{
X        register char *RstrName;
X
X        if(FileStrip)
X        { /* use just the filename */
X                RstrName = file+strlen(file);
X                while(RstrName > file && *RstrName != '/')
X                        RstrName--;
X                if(*RstrName == '/') RstrName++;
X        }
X        else
X                RstrName = file;
X        if(!strncmp(RstrName,"./",2))
X                RstrName += 2;
X        return(RstrName);
X}
X
X/*****************************************************************
X |  exit_incompat - incompatible options
X ****************************************************************/
X
Xexit_incompat()
X{
X           fputs("You may only specify one of -L, -X or -x\n",stderr);
X        exit(1);
X}
X
Xhelpuser()
X{                                /* output a command format message */
X        register char **ptr;
X        static char *helpinfo[] =
X        {
X                "-v  verbose messages OFF while executing",
X                "-w  don't check with 'wc -c' after unpack",
X        "-n  Name of archive (documentation)",
X        "-a  Generate Submitted-by: & Archive-name: headers",
X        "-s  override automatically determined submitter name",
X                "-x  don't overwrite existing files",
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                "-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#ifdef THIS_APPEARS_TO_BE_OBSOLETE
X                "-D  output date, user, and directory comments to the archive",
X#endif /* THIS_APPEARS_TO_BE_OBSOLETE */
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                "\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            "The 'x' and 'L' options are incompatible",
X                "\n-a generates sharname/part## headers. If you are producing patches",
X                "you'll need to edit -a headers (or please improve shar :-))",
X                "The automatic submitter name is trivial: essentially `whoami`@`uname`",
X                (char *)0
X        };
X        fprintf(stderr,
X            "shar %s\nusage: shar [ options ] file [ file1 ... ] ]\n",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
$TOUCH -am 0419135590 shar.c &&
chmod 0644 shar.c ||
echo "restore of shar.c failed"
set `wc -c shar.c`;Wc_c=$1
if test "$Wc_c" != "28774"; then
        echo original size 28774, current size $Wc_c
fi
# ============= unshar.c ==============
echo "x - extracting unshar.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > unshar.c &&
X/* CHK=0x2B39 */
Xchar *revision = "3.22";
X/****************************************************************
X * unshar.c: Unpackage one or more shell archive files
X *
X * Usage:     unshar [-c] [-C 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 *      It can unshar shar files concatenated in one file, with the
X *      the "-c" command, which separates files by recognizing the
X *      "exit 0" string at the beginning of a line
X *
X *      (The -C string option allows you to specify this string, thus
X *      -c is equivalent to -C "exit 0")
X *
X *      The -d flag tells unshar to change directory before unsharing
X *
X * HISTORY
X * 19-Apr-90  Colas Nahaboo (co...@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/*: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#inclu...