home *** CD-ROM | disk | FTP | other *** search
- Path: xanth!mcnc!uvaarpa!umd5!brl-adm!cmcl2!nrl-cmf!ames!necntc!ncoast!allbery
- From: davidsen@crdos1.UUCP (Wm E. Davidsen)
- Newsgroups: comp.sources.misc
- Subject: v03i014: shar2
- Message-ID: <8805101146.AA02278@crdos1.UUCP>
- Date: 10 May 88 15:46:51 GMT
- Sender: allbery@ncoast.UUCP
- Reply-To: davidsen@crdos1.UUCP (Wm E. Davidsen)
- Lines: 1275
- Approved: allbery@ncoast.UUCP
-
- comp.sources.misc: Volume 3, Issue 14
- Submitted-By: "Wm E. Davidsen" <davidsen@crdos1.UUCP>
- Archive-Name: shar2
-
- [This is an enhanced "shar" program. I think I'll stick with mine for
- now, but it's nice to know someone's working on it. ++bsa]
-
- #!/bin/sh
- # shar: Shell Archiver (v1.22)
- # Packed Tue May 10 11:43:47 EDT 1988 by davidsen
- # from directory /usr2/davidsen/bin/src/shar2
- #
- # Run the following text with /bin/sh to create:
- # shar2.readme
- # shar2.1
- # unshar.1
- # shar2.c
- # uushar.c
- # unshar.sh
- # Makefile
- # unshar.c
- #
- echo "x - extracting shar2.readme (Text)"
- sed 's/^X//' << 'SHAR_EOF' > shar2.readme &&
- X
- X SHAR2 is a program to create shell archives. I wrote it to solve the
- Xproblems inherent in sharing large files, namely:
- X
- X breaking up large postings to avoid truncation
- X This is now done by the program
- X concatenating shar parts before unpacking when large files
- X won't fit into one mailable file
- X Each output file may be unpacked separately, and the
- X unpack is sequence checked
- X binary files
- X The shar program will optionally handle binary files, using
- X uuencode to process them. The results are able to be broken
- X into multiple files, as with text.
- X mixed text and binary files
- X The shar program can optionally handle a mixture of file
- X types, using the 'file' command to test them. The mixing of
- X text and binary files may also be done manually, for files
- X which are text files but which contain characters which may
- X be damaged when mailed.
- X losing file permissions
- X file permissions are preserved, allowing shell scripts to
- X retain execute permission and read only files to be
- X protected.
- X
- X
- XThese are the features of shar2 over the many shar versions around:
- X
- X 1. It optionally produces multiple output files for mailing.
- X 2. Multiple output files do not have to be concatenated before
- X unpacking. Each may be unpacked independently, input files
- X spanning several output files are joined correctly.
- X 3. Unpacking of multiple-file archives is sequence checked.
- X 4. binary files may be processed, using uuencode and uudecode.
- X this allows large binary files to be easily moved by mail.
- X 5. file permissions are preserved.
- X 6. error checking is available as an option.
- X 7. Fast - written in C.
- X 8. Rejects pipes and directories.
- X 9. Can handle mixed text and binary files, using automatic
- X or manual file typing.
- X
- X I wrote this because the version in shell script was too slow, I got a
- Xsource for a minimal version which could be enhanced, and to avoid
- Xhaving to join parts of binary postings before unpacking. I hope
- Xit will be useful.
- X
- X bill davidsen, 4/6/88 (davidsen@sixhub.uucp)
- X
- X Latest revision, change checking to use wc instead of sun, since not
- Xall versions of sum are compatible. Thanks to Keith Petersen. Added
- Xthe ability to make the temp filenames DOS compatible to allow use of
- X'unshar' on DOS.
- X
- SHAR_EOF
- chmod 0644 shar2.readme || echo "restore of shar2.readme fails"
- set `wc -c shar2.readme`;Sum=$1
- if test "$Sum" != "2317"
- then echo original size 2317, current size $Sum;fi
- echo "x - extracting shar2.1 (Text)"
- sed 's/^X//' << 'SHAR_EOF' > shar2.1 &&
- X'\" must be run through 'tbl' as well as nroff
- X.TH SHAR2 1 local
- X.SH NAME
- Xshar2 - create shell archives
- X.SH SYNOPSIS
- Xshar2 [ options ] files
- X.SH DESCRIPTION
- Xshar2 creates "shell archives" (or shar files) which are in text format
- Xand can be mailed. These files may be unpacked later by executing them
- Xwith /bin/sh.
- X.SS Options
- X.TS
- Xtab(;);
- Xlb lw(50).
- X-v;T{
- Xverbose. This option causes a running commentary as the archive is
- Xcreated, and another as it is unpacked. This option does not control the
- Xerror messages, only the informational messages.
- XT}
- X
- X-s;T{
- Xsum. The files are tested with the \fIsum\fR command for damage in
- Xtransit. Errors are reported.
- XT}
- X
- X-x;T{
- Xdon't overwrite existing files. The unpack will check for an existing
- Xfile before unpacking a given file from the archive.
- XT}
- X
- X-b;T{
- Xbinary. This option causes all files to be treated as binary files, and
- Xthe files are changed to text using \fIuuencode\fR. Commands are
- Xembedded in the output files to change use uudecode and recreate the
- Xbinary files.
- XT}
- X
- X-M;T{
- Xmixed text and binary. This option causes each file to be
- Xexamined to determine if it is text or data. Binary files will be
- Xprocessed using uuencode.
- XT}
- X
- X-D;T{
- Xgive detail of archive. The date, user, and working directory are added
- Xto the archive as comments.
- XT}
- X
- X-c;T{
- Xproduce cut line. This option causes a line saying "cut\ here" to be
- Xplaced at the start of each output file. This is for sites not offering
- Xthe \fIunshar\fR command or shell script.
- XT}
- X
- X-f;T{
- Xfilename only. By default the entire path name is used as given on the
- Xcommand line. This option causes only the file names to be used, which
- Xis useful when building a shar from several directories, or another
- Xdirectory.
- XT}
- X
- X-dXXX;T{
- Xchange delimiter to XXX. The default delimiter is SHAR_EOF, placed at
- Xthe end of each file. This option is left for historical reasons, to
- Xamuse those who want their shar files to be personalized.
- XT}
- X
- X-o\fIfile\fR;T{
- Xoutput filename. The file \fIfile\fR is used for output instead of the
- Xstandard output. This option is required to use the \fB-l\fR (limit
- Xfilesize) option.
- XT}
- X
- X-l\fInum\fR;T{
- Xfile size limit. The output files created by \fIshar2\fR will be smaller
- Xthan \fInum\fRk in length. The \fB-o\fR option must be used to specify
- Xan output filename, and the digits 00 through 99 will be appended to
- Xform a series of output filenames. Informative messages and sequence
- Xchecking are included.
- XT}
- X.TE
- X.SH EXAMPLES
- X'\" examples use spaces, not tabs
- X shar2 *.c > cprog.shar # all C prog sources
- X shar2 -v *.[ch] > cprog.shar # verbose, .c and .h files
- X shar2 -b -l28 -oarc.sh *.arc # all binary .arc files, into
- X # files arc.sh01 thru arc.shNN
- X shar2 -f /lcl/src/u*.c > u.sh # use only the filenames
- X.SH WARNINGS
- XUse of the \fB-s\fR, \fB-b\fR, and \fB-M\fR options will slow the
- Xarchive process considerably, depending on the number of files.
- X.SH FILES
- XTemp files ._temp_ and ._seq_ are created and delted as needed.
- X.SH SEE ALSO
- Xunshar or unshar.sh.
- X.SH DIAGNOSTICS
- XError messages for missing or unaccessable files.
- X.SH LIMITATIONS
- XDoes not chase directory names, limited to the number of names on a
- Xcommand line. Uses the \fIfile\fR command to determine file type, may be
- Xaffected by its limitations. The -D option calls the \fIdate\fR,
- X\fIwho\ am\ i\fR, and \fIpwd\fR commands, and will produce garbage if
- Xthey are not present.
- X.sp
- XRequires the \fIuudecode\fR program to unpack binary files. On some
- Xsystems, such as Sun, this program requires world write on the current
- Xdirectory.
- X.sp
- XThe first file archived may not have a name starting with a hyphen, and
- Xif the file type is being set manually (-p) no file may be named
- X\fB-t\fR or \fB-b\fR. Option parsing should be done with getopt.
- X.SH AUTHOR
- XBill Davidsen, (davidsen@sixhub.uucp).
- X.SH COPYRIGHT
- XCopyright 1988 by Bill Davidsen. This program and documentation may be
- Xused by any person for any purpose.
- SHAR_EOF
- chmod 0666 shar2.1 || echo "restore of shar2.1 fails"
- set `wc -c shar2.1`;Sum=$1
- if test "$Sum" != "3932"
- then echo original size 3932, current size $Sum;fi
- echo "x - extracting unshar.1 (Text)"
- sed 's/^X//' << 'SHAR_EOF' > unshar.1 &&
- X'\" xxx
- X.TH UNSHAR 1 local
- X'\" Heading: name(sect) center (paren) name(sect)
- X.SH NAME
- Xunshar - unpack a shar file
- X.SH SYNOPSIS
- Xunshar file [ file [ file ] ]
- X.SH DESCRIPTION
- Xunshar scans mail messages looking for the start of a shell archive. It
- Xthen passes the archive through a copy of the shell to unpack it. It
- Xwill accept multiple files.
- X.SH EXAMPLES
- X unshar msg4
- X unshar msg4.*
- X.SH WARNINGS
- XIf a line in the introduction starts with a ':' or '#' unshar will
- Xbecome confused.
- X.SH FILES
- X.SH SEE ALSO
- Xshar, shar2.
- X.SH DIAGNOSTICS
- XAny message from the shell may be displayed.
- X.SH LIMITATIONS
- XProblems will occur if the shar file does not end with an exit command.
- X.SH AUTHOR
- XBill Davidsen (davidsen@sixhub)
- X.SH COPYRIGHT
- XCopyright 1988 by Bill Davidsen. This program may be used by any person
- Xfor any purpose.
- SHAR_EOF
- chmod 0666 unshar.1 || echo "restore of unshar.1 fails"
- set `wc -c unshar.1`;Sum=$1
- if test "$Sum" != "820"
- then echo original size 820, current size $Sum;fi
- echo "x - extracting shar2.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > shar2.c &&
- X/*
- X** cshar.c
- X*/
- X
- X#ifndef lint
- X#ifdef RCSIDENT
- Xstatic char *rcsid[] =
- X{
- X "$Header: shar.c,v 1.3 84/12/09 19:38:53 thompson Exp $",
- X "$Locker: $"
- X};
- X#endif RCSIDENT
- X#endif lint
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X
- X/*
- X Shar puts readable text files together in a package
- Xfrom which they are easy to extract. The original version
- Xwas a shell script posted to the net, shown below:
- X #Date: Mon Oct 18 11:08:34 1982
- X #From: decvax!microsof!uw-beave!jim (James Gosling at CMU)
- X AR=$1
- X shift
- X for i do
- X echo a - $i
- X echo "echo x - $i" >>$AR
- X echo "cat >$i <<'!Funky!Stuff!'" >>$AR
- X cat $i >>$AR
- X echo "!Funky!Stuff!" >>$AR
- X done
- XI rewrote this version in C to provide better diagnostics
- Xand to run faster. The main difference is that my version
- Xdoes not affect any files because it prints to the standard
- Xoutput. Mine also has a -v (verbose) option.
- 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 sum of
- X * the orignal file and the sum 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
- Xstatic char *SCCSid =
- X "@(#)cshar, sixhub version 1.22, last change 5/2/88";
- X
- X#define DELIM "SHAR_EOF"/* put after each file */
- X#define PREFIX1 'X' /* goes infront of each line */
- X#define PREFIX2 'Y' /* goes infront of each line if Delim
- X starts with PREFIX1 */
- X#define PREFIX (Delim[0] == PREFIX1 ? PREFIX2 : PREFIX1)
- X#define SHAR "shar" /* the name of this program */
- X#define READ_PERMISSION 4 /* access permission */
- X#define SUM "wc -c"
- X
- Xint Verbose = 0; /* option to provide append/extract
- X feedback */
- Xint Sum = 0; /* option to provide sum checking */
- Xchar *Delim = DELIM; /* pointer to delimiter string */
- Xint Cut = 0; /* option to provide cut mark */
- Xint Binary = 0; /* flag for binary files */
- Xint Mixed = 0; /* mixed text and binary files */
- Xint Detail = 0; /* extra detail in shar header */
- Xint eXists = 0; /* check if file exists */
- 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 *popen ();
- XFILE *outfile = stdout, *fopen ();
- Xchar *Rname(); /* file restore name */
- Xunsigned limit = 0;
- Xlong ftell ();
- Xlong TypePos; /* position for archive type message */
- Xchar outname[50], /* base for output filename */
- X filename[50]; /* actual output filename */
- Xint filenum = 0; /* output file # */
- Xstruct stat filestat; /* check file type, access */
- X
- Xmain (argc, argv)
- X char **argv;
- X{
- X int status = 0;
- X char *oname;
- X
- X while (argv[1][0] == '-')
- X {
- X switch (argv[1][1])
- X {
- X case 'v':
- X Verbose = 1;
- X break;
- X case 's':
- X Sum = 1;
- X break;
- X case 'D': /* add detail */
- X Detail = 1;
- X break;
- X case 'd':
- X if (argv[1][2])
- X Delim = &argv[1][2];
- X break;
- X case 'b': /* binary files */
- X Binary = 1;
- X break;
- X case 't': /* text mode */
- X Binary = 0;
- X break;
- X case 'x': /* does the file exist */
- X eXists = 1;
- X if (limit) exit_incompat();
- 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 'l': /* size limit in k */
- X limit = atoi (argv[1] + 2) - 1;
- X if (eXists) exit_incompat();
- X DeBug("Limit %dk\n", limit);
- X break;
- X case 'o': /* specify output file */
- X if (argv[1][2])
- X oname = &argv[1][2];
- X else
- X { /* use the next arg */
- X if (argc > 1 && argv[2][0] != '-')
- X { /* if the next one isn't an option */
- X oname = argv[2];
- X argc--;
- X argv++;
- X }
- X else
- X { /* format error in the -o option */
- X fprintf (stderr, "Format error in -o option\n");
- X exit (1);
- X }
- X }
- X strcpy (outname, oname);
- X filenum = 1;
- X sprintf (filename, "%s01", outname);
- X outfile = fopen (filename, "w");
- X if (outfile == NULL)
- 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 fprintf (stderr, "%s: invalid argument: %s\n", SHAR, argv[1]);
- X case 'h': /* help */
- X helpuser ();
- X break;
- X }
- X argc--;
- X argv++;
- X }
- X if (argc == 1)
- X {
- X fprintf (stderr, "%s: No input files\n", SHAR);
- X helpuser ();
- X exit (1);
- X }
- X if (header (argc, argv))
- X exit (2);
- X while (--argc)
- X { /* process positional parameters and files */
- X argv++;
- X if (PosParam)
- X { /* allow -b and -t inline */
- X if (strcmp (*argv, "-b") == 0)
- X { /* set binary */
- X Binary = 1;
- X continue;
- X }
- X if (strcmp (*argv, "-t") == 0)
- X { /* set mode text */
- X Binary = 0;
- X continue;
- X }
- X }
- X status += shar (*argv);
- X }
- X
- X /* delete the sequence file, if any */
- X if (limit && filenum > 1)
- X {
- X fputs ("rm -f s2_seq_.tmp\n", outfile);
- X fputs ("echo \"You have unpacked the last part\"\n", outfile);
- X if (!Verbose)
- X fprintf (stderr, "Created %d files\n", filenum);
- X }
- X fputs ("exit 0\n", outfile);
- X exit (status);
- X}
- X
- Xheader (argc, argv)
- X char **argv;
- X{
- X int i;
- X int status;
- X FILE *ptemp; /* pipe temp */
- 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 option without -o\n");
- X helpuser ();
- X }
- X
- X for (i = 1; i < argc; i++)
- X { /* skip positional parameters */
- X if (PosParam && (strcmp (argv[i], "-b") == 0 ||
- X strcmp (argv[i], "-t") == 0))
- X continue;
- X
- X /* see if access and correct type */
- X if (access (argv[i], READ_PERMISSION))
- X {
- X fprintf (stderr, "%s: Can't access %s\n", SHAR, argv[i]);
- X return 1;
- X }
- X
- X /* get file type */
- X stat (argv[i], &filestat);
- X status = filestat.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, "%s: %s is not a file\n", SHAR, argv[i]);
- X return 1;
- X }
- X }
- X
- X if (Cut)
- X fputs ("---- Cut Here and unpack ----\n", outfile);
- X fputs ("#!/bin/sh\n", outfile);
- X fprintf (outfile, "# %s: Shell Archiver (v1.22)\n", SHAR);
- X if (Detail)
- X {
- X char dateout[50], /* pipe output, who */
- X whoout[50]; /* and who am i */
- X
- X ptemp = popen ("date; who am i; pwd", "r");
- X fgets (dateout, 50, ptemp);
- X dateout[strlen (dateout) - 1] = 0;
- X fscanf (ptemp, "%s", whoout);
- X fprintf (outfile, "#\tPacked %s by %s\n", dateout, whoout);
- X while (getc (ptemp) != '\n');
- X fgets (dateout, 50, ptemp);
- X fprintf (outfile, "#\tfrom directory %s", dateout);
- X
- X pclose (ptemp);
- X }
- X
- X if (limit)
- X { /* may be split, explain */
- X fprintf(outfile, "#\n");
- X TypePos = ftell(outfile);
- X fprintf (outfile, "%-75s\n%-75s\n", "#", "#");
- X }
- X
- X fputs ("#\n#\tRun the following text with /bin/sh to create:\n", outfile);
- X for (i = 1; i < argc; i++)
- X { /* output names of files but not parameters */
- X if (PosParam && (strcmp (argv[i], "-b") == 0 ||
- X strcmp (argv[i], "-t") == 0))
- X continue;
- X fprintf (outfile, "#\t %s\n", Rname(argv[i]));
- X }
- X fputs ("#\n", outfile);
- X
- X if (limit)
- X { /* now check the sequence */
- X fprintf (outfile, "%s%s%s%s",
- X "if test -r s2_seq_.tmp\n",
- X "then echo \"Must unpack archives in sequence!\"\n",
- X " next=`cat s2_seq_.tmp`; echo \"Please unpack part $next next\"\n",
- X " exit 1; fi\n");
- X }
- X return (0);
- X}
- X
- Xshar (file)
- X char *file;
- X{
- X char line[BUFSIZ];
- X FILE *ioptr, *fdopen ();
- X long cursize, remaining, ftell ();
- X int split = 0; /* file split flag */
- X char *filetype; /* text or binary */
- X char *RstrName; /* name for restore */
- X
- X /* if limit set, get the current output length */
- X if (limit)
- X {
- X cursize = ftell (outfile);
- X remaining = (limit * 1024L) - cursize;
- X DeBug("In shar: remaining size %ld\n", remaining);
- X }
- X
- X /* determine the name to use for restore */
- X RstrName = Rname(file);
- 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 ioptr = popen (line, "r");
- X fscanf (ioptr, "%d", &count);
- X pclose (ioptr);
- 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 (outfile);
- X
- X if (pid = fork ())
- X { /* parent, create a file to read */
- X close (pipex[1]);
- X ioptr = fdopen (pipex[0], "r");
- X }
- X else
- X { /* start writing the pipe with encodes */
- X FILE *outptr;
- X
- X ioptr = fopen (file, "rb");
- X outptr = fdopen (pipex[1], "w");
- X fprintf (outptr, "begin 600 %s\n", RstrName);
- X encode (ioptr, outptr);
- X fprintf (outptr, "end\n");
- X exit (0);
- X }
- X filetype = "Binary";
- X }
- X else
- X {
- X ioptr = fopen (file, "r");
- X filetype = "Text";
- X }
- X
- X if (ioptr != NULL)
- X {
- X /* protect existing files */
- X if (eXists)
- X fprintf (outfile,
- X "if test -f %s; then echo \"File %s exists\"; else\n",
- X RstrName, RstrName);
- X
- X if (Verbose)
- X { /* info on archive and unpack */
- X fprintf (stderr, "%s: saving %s (%s)\n",
- X SHAR, file, filetype);
- X fprintf (outfile, "echo \"x - extracting %s (%s)\"\n",
- X RstrName, filetype);
- X }
- X if (Binary)
- X { /* run sed through uudecode via temp file */
- X fprintf (outfile, "sed 's/^%c//' << '%s' > s2_temp_.tmp &&\n",
- X PREFIX, Delim);
- X }
- X else
- X { /* just run it into the file */
- X fprintf (outfile, "sed 's/^%c//' << '%s' > %s &&\n",
- X PREFIX, Delim, RstrName);
- X }
- X while (fgets (line, BUFSIZ, ioptr))
- X { /* output a line and test the length */
- X fprintf (outfile, "%c%s", PREFIX, line);
- X if (limit && (remaining -= strlen (line) + 2) < 0)
- X { /* change to another file */
- X DeBug("Newfile, remaining %ld, ", remaining);
- X DeBug("limit still %d\n", limit);
- X fprintf (outfile, "%s\n", Delim);
- X if (Verbose)
- X { /* output some reassurance */
- X fprintf (outfile,
- X "echo \"End of part %d\"\n", filenum);
- X fprintf (outfile,
- X "echo \"File %s is continued in part %d\"\n",
- X RstrName, filenum + 1);
- X }
- X else
- X fprintf (outfile,
- X "echo \"End of part %d, continue with part %d\"\n",
- X filenum, filenum + 1);
- X fprintf (outfile, "echo \"%d\" > s2_seq_.tmp\n", filenum + 1);
- X fprintf (outfile, "exit 0\n");
- X
- X if (filenum == 1)
- X { /* rewrite the info lines on the firstheader */
- X fseek(outfile, TypePos, 0);
- X fprintf (outfile, "%-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 (outfile);
- X
- X /* form the next filename */
- X sprintf (filename, "%s%02d", outname, ++filenum);
- X outfile = fopen (filename, "w");
- X if (Cut)
- X fputs ("---- Cut Here and unpack ----\n", outfile);
- X fprintf (outfile, "#!/bin/sh\n");
- X fprintf (outfile,
- X "# this is part %d of a multipart archive\n%s%s",
- X filenum, "# do not concatenate these parts, ",
- X "unpack them in order with /bin/sh\n");
- X fprintf (outfile, "# file %s continued\n#\n", RstrName);
- X fprintf (outfile, "CurArch=%d\n", filenum);
- X fprintf (outfile, "%s%s%s%s%s%s%s%s%s",
- X "if test ! -r s2_seq_.tmp\n",
- X "then echo \"Please unpack part 1 first!\"\n",
- X " exit 1; fi\n",
- X "( read Scheck\n",
- X " if test \"$Scheck\" != $CurArch\n",
- X " then echo \"Please unpack part $Scheck next!\"\n",
- X " exit 1;\n",
- X " else exit 0; fi\n",
- X ") < s2_seq_.tmp || exit 1\n");
- X
- X if (Verbose)
- X { /* keep everybody informed */
- X fprintf (stderr, "Starting file %s\n", filename);
- X fprintf (outfile,
- X "echo \"x - Continuing file %s\"\n", RstrName);
- X }
- X fprintf (outfile,
- X "sed 's/^%c//' << '%s' >> %s\n",
- X PREFIX, Delim, (Binary ? "s2_temp_.tmp" : RstrName));
- X remaining = limit * 1024L;
- X split = 1;
- X }
- X }
- X
- X (void) fclose (ioptr);
- X fprintf (outfile, "%s\n", Delim);
- X if (split && Verbose)
- X fprintf (outfile,
- X "echo \"File %s is complete\"\n", RstrName);
- X
- X /* if this file was uuencoded, decode it and drop the temp */
- X if (Binary)
- X {
- X if (Verbose)
- X fprintf (outfile, "echo \"uudecoding file %s\"\n", RstrName);
- X fprintf (outfile,
- X "uudecode < s2_temp_.tmp && rm -f s2_temp_.tmp &&\n");
- X }
- X
- X /* set the permissions as they were */
- X stat (file, &filestat);
- X fprintf (outfile,
- X "chmod %04o %s || echo \"restore of %s fails\"\n",
- X filestat.st_mode & 07777, RstrName, RstrName);
- X
- X if (Sum)
- X { /* validate the transferred file */
- X FILE *pfp;
- X char command[BUFSIZ];
- X
- X sprintf (command, "%s %s", SUM, file);
- X if ((pfp = popen (command, "r")))
- X {
- X char sum[BUFSIZ];
- X
- X fscanf (pfp, "%s", sum);
- X fprintf (outfile, "set `%s %s`;Sum=$1\n",
- X SUM, RstrName);
- X fprintf (outfile,
- X "if test \"$Sum\" != \"%s\"\n", sum);
- X fprintf (outfile,
- X "then echo original size %s, current size $Sum;fi\n",
- X sum);
- X pclose (pfp);
- X }
- X }
- X
- X /* if the exists option is in place close the if */
- X if (eXists)
- X fprintf (outfile, "fi\n");
- X
- X return (0);
- X }
- X else
- X {
- X fprintf (stderr, "%s: Can't open %s\n", SHAR, file);
- X return (1);
- X }
- X}
- X
- Xchar *Rname(file)
- X register 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 RstrName = file;
- X return (RstrName);
- X}
- X
- X/*****************************************************************
- X | exit_incompat - incompatible options
- X ****************************************************************/
- X
- Xexit_incompat()
- X{
- X fprintf(stderr, "%s%s",
- X "The -x and -l options are currently incompatible\n",
- X "Please reenter the command without one option\n");
- X exit(1);
- X}
- X
- Xhelpuser ()
- X{ /* output a command format message */
- X register char **ptr;
- X static char *helpinfo[] =
- X {
- X "-v\tverbose messages while executing",
- X "-s\tdo checking with 'sum' after unpack",
- X "-x\tdon't overwrite existing files",
- X "-b\ttreat all files as binary, use uuencode",
- X "-t\ttreat all files as text (default)",
- X "-p\tallow positional parameter options. The options \"-b\"",
- X "\tand \"-t\" may be embedded, and files to the right of the",
- X "\toption will be processed in the specified mode",
- X "-M\tmixed mode. Determine if the files are text or",
- X "\tbinary and archive correctly.",
- X "-D\toutput date, user, and directory comments to the archive",
- X "-c\tstart the shar with 'cut here'",
- X "-f\trestore by filename only, rather than path",
- X "-dXXX\tuse XXX to delimit the files in the shar",
- X "-oXXX\t(or -o XXX) output to file XXX01 thru XXXnn",
- X "-lXX\tlimit output file size to XXk bytes",
- X "\nThe 'o' option is required if the 'l' option is used",
- X NULL
- X };
- X fprintf (stderr,
- X "\nFormat:\n %s [ options ] file [ file1 ... ] ]\n",
- X SHAR);
- X for (ptr = helpinfo; *ptr; ptr++)
- X fprintf (stderr, "%s\n", *ptr);
- X
- X exit (1);
- X}
- SHAR_EOF
- chmod 0444 shar2.c || echo "restore of shar2.c fails"
- set `wc -c shar2.c`;Sum=$1
- if test "$Sum" != "16149"
- then echo original size 16149, current size $Sum;fi
- echo "x - extracting uushar.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > uushar.c &&
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X
- X/* ENC is the basic 1 character encoding function to make a char printing */
- X#define ENC(c) ((((c) & 077) + ' ') | ((c & 077) == 0 ? 0100 : 0))
- X
- Xencode (in, out)
- X FILE *in;
- X FILE *out;
- X{
- X char buf[80];
- X int i, n;
- X
- X for (;;)
- X {
- X /* 1 (up to) 45 character line */
- X n = fr (in, buf, 45);
- X putc (ENC (n), out);
- X
- X for (i = 0; i < n; i += 3)
- X outdec (&buf[i], out);
- X
- X putc ('\n', out);
- X if (n <= 0)
- X break;
- X }
- X}
- X
- X/*
- X * output one group of 3 bytes, pointed at by p, on file f.
- X */
- Xoutdec (p, f)
- X char *p;
- X FILE *f;
- X{
- X int c1, c2, c3, c4;
- X
- X c1 = *p >> 2;
- X c2 = (*p << 4) & 060 | (p[1] >> 4) & 017;
- X c3 = (p[1] << 2) & 074 | (p[2] >> 6) & 03;
- X c4 = p[2] & 077;
- X putc (ENC (c1), f);
- X putc (ENC (c2), f);
- X putc (ENC (c3), f);
- X putc (ENC (c4), f);
- X}
- X
- X/* fr: like read but stdio */
- Xint
- X fr (fp, buf, cnt)
- X FILE *fp;
- X char *buf;
- X int cnt;
- X{
- X int c, i;
- X
- X for (i = 0; i < cnt; i++)
- X {
- X c = getc (fp);
- X if (c == EOF)
- X return (i);
- X buf[i] = c;
- X }
- X return (cnt);
- X}
- SHAR_EOF
- chmod 0644 uushar.c || echo "restore of uushar.c fails"
- set `wc -c uushar.c`;Sum=$1
- if test "$Sum" != "1114"
- then echo original size 1114, current size $Sum;fi
- echo "x - extracting unshar.sh (Text)"
- sed 's/^X//' << 'SHAR_EOF' > unshar.sh &&
- X#!/bin/sh
- X#
- X# unshar shell - unpack one or more shar files
- X#
- X# Copyright 1988 bill davidsen
- X# this program may be used by any person for any purpose.
- X
- Xfor Name in $*
- Xdo sed -n '/^[:#]/,$p' $Name | sh
- Xdone
- SHAR_EOF
- chmod 0755 unshar.sh || echo "restore of unshar.sh fails"
- set `wc -c unshar.sh`;Sum=$1
- if test "$Sum" != "207"
- then echo original size 207, current size $Sum;fi
- echo "x - extracting Makefile (Text)"
- sed 's/^X//' << 'SHAR_EOF' > Makefile &&
- X#
- X# makefile for shar2
- X#
- X
- XCFLAGS = -O
- X
- XSRC = shar2.c uushar.c unshar.sh
- XOBJ = shar2.o uushar.o
- XDOC = shar2.1 unshar.1 shar2.readme
- X
- Xall : xshar unshar
- X
- Xxshar : ${OBJ}
- X $(CC) shar2.o uushar.o -o xshar
- X
- Xunshar : unshar.c
- X if test -f /vmunix; \
- X then cc -O unshar.c -s -o unshar; \
- X else cc -O -Dindex=strchr unshar.c -s -o unshar; \
- X fi
- SHAR_EOF
- chmod 0644 Makefile || echo "restore of Makefile fails"
- set `wc -c Makefile`;Sum=$1
- if test "$Sum" != "336"
- then echo original size 336, current size $Sum;fi
- echo "x - extracting unshar.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > unshar.c &&
- X/****************************************************************
- X * unshar.c: Unpackage one or more shell archive files
- X *
- X * Usage: unshar [ -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 * HISTORY
- 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
- X# include <stdio.h>
- X# define EOL '\n'
- X
- Xextern char *optarg;
- Xextern int optind;
- X
- Xmain (argc, argv)
- Xint argc;
- Xchar *argv[];
- X{ int i, ch;
- X FILE *in;
- X
- X /* Process options */
- X
- X while ((ch = getopt (argc, argv, "d:")) != EOF) {
- X switch (ch) {
- X case 'd':
- X if (chdir (optarg) == -1) {
- X fprintf (stderr, "unshar: cannot chdir to '%s'\n", optarg);
- X exit(2);
- X }
- X break;
- X default:
- X quit (2, "Usage: unshar [-d directory] [file] ...\n");
- X }
- X }
- X
- X if (optind < argc)
- X { for (i= optind; i < argc; ++i)
- X { if ((in = fopen (argv[i], "r")) == NULL)
- X { fprintf (stderr, "unshar: file '%s' not found\n", argv[i]);
- X exit (1);
- X }
- X process (argv[i], in);
- X fclose (in);
- X }
- X }
- X else
- X process ("standard input", stdin);
- X
- X exit (0);
- X}
- X
- X
- Xprocess (name, in)
- Xchar *name;
- XFILE *in;
- X{ char ch;
- X FILE *shpr, *popen();
- X
- X if (position (name, in))
- X { printf ("%s:\n", name);
- X if ((shpr = popen ("sh", "w")) == NULL)
- X quit (1, "unshar: cannot open 'sh' process\n");
- X
- X while ((ch = fgetc (in)) != EOF)
- X fputc (ch, shpr);
- X
- X pclose (shpr);
- X }
- X}
- X
- X/****************************************************************
- X * position: position 'fil' at the start of the shell command
- X * portion of a shell archive file.
- X ****************************************************************/
- X
- Xposition (fn, fil)
- Xchar *fn;
- XFILE *fil;
- X{ char buf[BUFSIZ];
- X long pos, ftell ();
- X
- X /* Results from star matcher */
- X static char res1[BUFSIZ], res2[BUFSIZ], res3[BUFSIZ], res4[BUFSIZ];
- X static char *result[] = { res1, res2, res3, res4 };
- X
- X rewind (fil);
- X
- X while (1)
- X { /* Record position of the start of this line */
- X pos = ftell (fil);
- X
- X /* Read next line, fail if no more */
- X if (fgets (buf, BUFSIZ, fil) == NULL)
- X { fprintf (stderr, "unshar: found no shell commands in %s\n", fn);
- X return (0);
- X }
- X
- X /* Bail out if we see C preprocessor commands or C comments */
- X if (stlmatch (buf, "#include") || stlmatch (buf, "# include") ||
- X stlmatch (buf, "#define") || stlmatch (buf, "# define") ||
- X stlmatch (buf, "#ifdef") || stlmatch (buf, "# ifdef") ||
- X stlmatch (buf, "#ifndef") || stlmatch (buf, "# ifndef") ||
- X stlmatch (buf, "/*"))
- X { fprintf (stderr,
- X "unshar: %s looks like raw C code, not a shell archive\n", fn);
- X return (0);
- X }
- X
- X /* Does this line start with a shell command or comment */
- X if (stlmatch (buf, "#") || stlmatch (buf, ":") ||
- X stlmatch (buf, "echo ") || stlmatch (buf, "sed ") ||
- X stlmatch (buf, "cat "))
- X { fseek (fil, pos, 0); return (1); }
- X
- X /* Does this line say "Cut here" */
- X if (smatch (buf, "*CUT*HERE*", result) ||
- X smatch (buf, "*cut*here*", result) ||
- X smatch (buf, "*TEAR*HERE*", result) ||
- X smatch (buf, "*tear*here*", result) ||
- X smatch (buf, "*CUT*CUT*", result) ||
- X smatch (buf, "*cut*cut*", result))
- X {
- X /* Read next line after "cut here", skipping blank lines */
- X while (1)
- X { pos = ftell (fil);
- X
- X if (fgets (buf, BUFSIZ, fil) == NULL)
- X { fprintf (stderr,
- X "unshar: found no shell commands after 'cut' in %s\n", fn);
- X return (0);
- X }
- X
- X if (*buf != '\n') break;
- X }
- X
- X /* Win if line starts with a comment character of lower case letter */
- X if (*buf == '#' || *buf == ':' || (('a' <= *buf) && ('z' >= *buf)))
- X { fseek (fil, pos, 0);
- X return (1);
- X }
- X
- X /* Cut here message lied to us */
- X fprintf (stderr, "unshar: %s is probably not a shell archive,\n", fn);
- X fprintf (stderr, " the 'cut' line was followed by: %s", buf);
- X return (0);
- X }
- X }
- X}
- X
- X/*****************************************************************
- X * stlmatch -- match leftmost part of string
- X *
- X * Usage: i = stlmatch (big,small)
- X * int i;
- X * char *small, *big;
- X *
- X * Returns 1 iff initial characters of big match small exactly;
- X * else 0.
- X *
- X * HISTORY
- X * 18-May-82 Michael Mauldin (mlm) at Carnegie-Mellon University
- X * Ripped out of CMU lib for Rog-O-Matic portability
- X * 20-Nov-79 Steven Shafer (sas) at Carnegie-Mellon University
- X * Rewritten for VAX from Ken Greer's routine.
- X *
- X * Originally from klg (Ken Greer) on IUS/SUS UNIX
- X *****************************************************************/
- X
- Xint stlmatch (big, small)
- Xchar *small, *big;
- X{ register char *s, *b;
- X s = small;
- X b = big;
- X do
- X { if (*s == '\0')
- X return (1);
- X }
- X while (*s++ == *b++);
- X return (0);
- X}
- X
- X/*****************************************************************
- X * smatch: Given a data string and a pattern containing one or
- X * more embedded stars (*) (which match any number of characters)
- X * return true if the match succeeds, and set res[i] to the
- X * characters matched by the 'i'th *.
- X *****************************************************************/
- X
- Xsmatch (dat, pat, res)
- Xregister char *dat, *pat, **res;
- X{ register char *star = 0, *starend, *resp;
- X int nres = 0;
- X
- X while (1)
- X { if (*pat == '*')
- X { star = ++pat; /* Pattern after * */
- X starend = dat; /* Data after * match */
- X resp = res[nres++]; /* Result string */
- X *resp = '\0'; /* Initially null */
- X }
- X else if (*dat == *pat) /* Characters match */
- X { if (*pat == '\0') /* Pattern matches */
- X return (1);
- X pat++; /* Try next position */
- X dat++;
- X }
- X else
- X { if (*dat == '\0') /* Pattern fails - no more */
- X return (0); /* data */
- X if (star == 0) /* Pattern fails - no * to */
- X return (0); /* adjust */
- X pat = star; /* Restart pattern after * */
- X *resp++ = *starend; /* Copy character to result */
- X *resp = '\0'; /* null terminate */
- X dat = ++starend; /* Rescan after copied char */
- X }
- X }
- X}
- X
- X/*****************************************************************
- X * Addendum: quit subroutine (print a message and exit)
- X *****************************************************************/
- X
- Xquit (status, message)
- Xint status;
- Xchar *message;
- X{
- X fprintf(stderr, message);
- X exit(status);
- X}
- X
- X/*****************************************************************
- X * Public Domain getopt routine
- X *****************************************************************/
- X
- X/*
- X * get option letter from argument vector
- X */
- Xint opterr = 1, /* useless, never set or used */
- X optind = 1, /* index into parent argv vector */
- X optopt; /* character checked for validity */
- Xchar *optarg; /* argument associated with option */
- X
- X#define BADCH (int)'?'
- X#define EMSG ""
- X#define tell(s) fputs(*nargv,stderr);fputs(s,stderr); \
- X fputc(optopt,stderr);fputc('\n',stderr);return(BADCH);
- X
- Xgetopt(nargc,nargv,ostr)
- Xint nargc;
- Xchar **nargv,
- X *ostr;
- X{
- X static char *place = EMSG; /* option letter processing */
- X register char *oli; /* option letter list index */
- X char *index();
- X
- X if(!*place) { /* update scanning pointer */
- X if(optind >= nargc || *(place = nargv[optind]) != '-' || !*++place) return(EOF);
- X if (*place == '-') { /* found "--" */
- X ++optind;
- X return(EOF);
- X }
- X } /* option letter okay? */
- X if ((optopt = (int)*place++) == (int)':' || !(oli = index(ostr,optopt))) {
- X if(!*place) ++optind;
- X tell(": illegal option -- ");
- X }
- X if (*++oli != ':') { /* don't need argument */
- X optarg = NULL;
- X if (!*place) ++optind;
- X }
- X else { /* need an argument */
- X if (*place) optarg = place; /* no white space */
- X else if (nargc <= ++optind) { /* no arg */
- X place = EMSG;
- X tell(": option requires an argument -- ");
- X }
- X else optarg = nargv[optind]; /* white space */
- X place = EMSG;
- X ++optind;
- X }
- X return(optopt); /* dump back option letter */
- X}
- SHAR_EOF
- chmod 0644 unshar.c || echo "restore of unshar.c fails"
- set `wc -c unshar.c`;Sum=$1
- if test "$Sum" != "8429"
- then echo original size 8429, current size $Sum;fi
- exit 0
-