Rich $alz's cshar package, new alpha release, Part04/05
Rich Salz
rsalz at bbn.com
Tue Feb 21 09:25:21 AEST 1989
This is what I use to create shell archives of small-to-humongous source
distributions. Hope you find it useful. Hope you find bugs, and send
them to me. This will appear in comp.sources.unix after the bug reports
die down. It runs on all sort of Unix machines, and a raft of other OS's,
too.
For more details, see the README file in the first shar.
Please don't pass this version around, wait for the "REAL" one.
/rich $alz
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 4 (of 5)."
# Contents: makekit.c maniscan.c shar.c unshar.c
# Wrapped by rsalz at fig.bbn.com on Mon Feb 20 18:15:51 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'makekit.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'makekit.c'\"
else
echo shar: Extracting \"'makekit.c'\" \(11847 characters\)
sed "s/^X//" >'makekit.c' <<'END_OF_FILE'
X/*
X** MAKEKIT
X**
X** Split up source files into reasonably-sized shar lists.
X*/
X#include "shar.h"
X#ifdef RCSID
Xstatic char RCS[] =
X "$Header: makekit.c,v 2.2 88/06/06 22:04:45 rsalz Exp $";
X#endif /* RCSID */
X
X
X/*
X** Our block of information about the files we're doing.
X*/
Xtypedef struct _block {
X char *Name; /* Filename */
X char *Text; /* What it is */
X int Where; /* Where it is */
X int Type; /* Directory or file? */
X long Bsize; /* Size in bytes */
X} BLOCK;
X
X
X/*
X** Our block of information about the archives we're making.
X*/
Xtypedef struct _archive {
X int Count; /* Number of files */
X long Asize; /* Bytes used by archive */
X} ARCHIVE;
X
X
X/*
X** Global variables.
X*/
Xstatic char *InName; /* File with list to pack */
Xstatic char *OutName; /* Where our output goes */
Xstatic char *SharName = "Part"; /* Prefix for name of each shar */
Xstatic char *Trailer; /* Text for shar to pack in */
Xstatic char TEMP[TEMPSIZE]; /* Temporary manifest file */
X#ifdef USE_TEMP_MANIFEST
Xstatic char FLST[TEMPSIZE]; /* File with list for shar */
X#endif /* USE_TEMP_MANIFEST */
Xstatic int ArkCount = 20; /* Max number of archives */
Xstatic int ExcludeIt; /* Leave out the output file? */
Xstatic int Header; /* Lines of prolog in input */
Xstatic int Preserve; /* Preserve order for Manifest? */
Xstatic int Working = TRUE; /* Call shar when done? */
Xstatic long Size = 55000; /* Largest legal archive size */
X
X
X/*
X** Sorting predicate to put README first, then MANIFEST, then directories,
X** then larger files, then smaller files, which is how we want to pack
X** stuff in archives.
X*/
Xstatic int
XSizeP(t1, t2)
X BLOCK *t1;
X BLOCK *t2;
X{
X long i;
X
X if (t1->Type == F_DIR)
X return t2->Type == F_DIR ? 0 : -1;
X if (t2->Type == F_DIR)
X return 1;
X if (EQ(t1->Name, "PACKNOTES"))
X return -1;
X if (EQ(t2->Name, "PACKNOTES"))
X return 1;
X if (EQn(t1->Name, "README", 6))
X return -1;
X if (EQn(t2->Name, "README", 6))
X return 1;
X if (OutName && EQ(t1->Name, OutName))
X return -1;
X if (OutName && EQ(t2->Name, OutName))
X return 1;
X return (i = t1->Bsize - t2->Bsize) == 0L ? 0 : (i < 0L ? 1 : -1);
X}
X
X
X/*
X** Sorting predicate to get things in alphabetical order, with the
X** README and MANIFEST files as first and second, respectively.
X*/
Xstatic int
XReadmeP(t1, t2)
X BLOCK *t1;
X BLOCK *t2;
X{
X int i;
X
X if (EQ(t1->Name, "PACKNOTES"))
X return -1;
X if (EQ(t2->Name, "PACKNOTES"))
X return 1;
X if (EQ(t1->Name, "README"))
X return -1;
X if (EQ(t2->Name, "README"))
X return 1;
X if (EQ(t1->Name, "MANIFEST"))
X return -1;
X if (EQ(t2->Name, "MANIFEST"))
X return 1;
X return (i = *t1->Name - *t2->Name) ? i : strcmp(t1->Name, t2->Name);
X}
X
X
X/*
X** Skip whitespace.
X*/
Xstatic char *
XSkip(p)
X REGISTER char *p;
X{
X while (*p && WHITE(*p))
X p++;
X return p;
X}
X
X
X/*
X** Signal handler. Clean up and die.
X*/
Xstatic sigret_t
XCatch(s)
X int s;
X{
X int e;
X
X e = errno;
X if (TEMP[0])
X (void)unlink(TEMP);
X#ifdef USE_TEMP_MANIFEST
X if (FLST[0])
X (void)unlink(FLST);
X#endif /* USE_TEMP_MANIFEST */
X Fprintf(stderr, "Got signal %d, %s.\n", s, Ermsg(e));
X exit(1);
X /* NOTREACHED */
X}
X
X
Xmain(ac, av)
X REGISTER int ac;
X char *av[];
X{
X REGISTER FILE *F;
X REGISTER FILE *In;
X REGISTER BLOCK *t;
X REGISTER ARCHIVE *k;
X REGISTER char *p;
X REGISTER int i;
X REGISTER int lines;
X REGISTER int FoundOutname;
X BLOCK *Table;
X BLOCK *TabEnd;
X ARCHIVE *Ark;
X ARCHIVE *ArkEnd;
X char buff[BUFSIZ];
X long lsize;
X int LastOne;
X int Start;
X int Notkits;
X int Believer;
X int Oops;
X char EndArkNum[20];
X char CurArkNum[20];
X
X /* Collect input. */
X Believer = FALSE;
X Notkits = FALSE;
X for (Oops = FALSE; (i = getopt(ac, av, "1beh:i:k:n:mo:ps:t:x")) != EOF; )
X switch (i) {
X default:
X Oops = TRUE;
X break;
X case '1':
X Notkits = TRUE;
X break;
X case 'b':
X Believer = TRUE;
X break;
X case 'e':
X ExcludeIt = TRUE;
X break;
X case 'h':
X Header = atoi(optarg);
X break;
X case 'i':
X InName = optarg;
X break;
X case 'k':
X ArkCount = atoi(optarg);
X break;
X case 'm':
X InName = OutName = "MANIFEST";
X Header = 2;
X break;
X case 'n':
X SharName = optarg;
X break;
X case 'o':
X OutName = optarg;
X break;
X case 'p':
X Preserve = TRUE;
X break;
X case 's':
X Size = (long)atoi(optarg);
X if (IDX(optarg, 'k') || IDX(optarg, 'K'))
X Size *= 1024;
X break;
X case 't':
X Trailer = optarg;
X break;
X case 'x':
X Working = FALSE;
X break;
X }
X ac -= optind;
X av += optind;
X
X if (Oops == FALSE && InName && av[0]) {
X Fprintf(stderr,
X "Can't list files on command line and use -i option.\n");
X Oops = TRUE;
X }
X
X if (Oops) {
X Fprintf(stderr, "Usage:\n makekit %s\n %s [files...]\n",
X "[-1] [-b] [-e] [-x] [-k #] [-s #[k]] [-n Name] [-t Text]",
X "[-p] [-m | -i MANIFEST -o MANIFEST -h 2]");
X exit(1);
X /* NOTREACHED */
X }
X
X /* Write the file list to a temp file. */
X MakeTempName(TEMP, TEMP_NAME1);
X F = fopen(TEMP, "w");
X SetSigs(Catch);
X if (av[0])
X /* Got the arguments on the command line. */
X while (*av)
X Fprintf(F, "%s\n", *av++);
X else {
X /* Got the name of the file from the command line. */
X if (InName == NULL)
X In = stdin;
X else if ((In = fopen(InName, "r")) == NULL) {
X Fprintf(stderr, "Can't read %s as manifest, %s.\n",
X InName, Ermsg(errno));
X exit(1);
X /* NOTREACHED */
X }
X /* Skip any possible prolog, then output rest of file. */
X while (--Header >= 0 && fgets(buff, sizeof buff, In))
X ;
X if (feof(In)) {
X Fprintf(stderr, "Nothing but header lines in list!?\n");
X exit(1);
X /* NOTREACHED */
X }
X while (fgets(buff, sizeof buff, In))
X fputs(buff, F);
X if (In != stdin)
X (void)fclose(In);
X }
X (void)fclose(F);
X
X /* Count number of files, allow for NULL and our output file. */
X F = fopen(TEMP, "r");
X for (lines = 2; fgets(buff, sizeof buff, F); lines++)
X ;
X rewind(F);
X
X /* Read lines and parse lines, see if we found our OutFile. */
X FoundOutname = FALSE;
X Table = NEW(BLOCK, lines); /* Initialized in loop, below. */
X for (t = Table, lines = 0; fgets(buff, sizeof buff, F); ) {
X /* Read line, skip first word, check for blank line. */
X if (p = IDX(buff, '\n'))
X *p = '\0';
X else
X Fprintf(stderr, "Warning, line too long:\n\t%s\n", buff);
X p = Skip(buff);
X if (*p == '\0')
X continue;
X
X /* Copy the line, snip off the first word. */
X for (p = t->Name = COPY(p); *p && !WHITE(*p); p++)
X ;
X if (*p)
X *p++ = '\0';
X
X /* Skip <spaces><digits><spaces>; remainder is the file description. */
X p = Skip(p);
X t->Where = atoi(p);
X while (*p && CTYPE(*p) && isdigit(*p))
X p++;
X t->Text = Skip(p);
X
X /* Get file type. */
X if (!GetStat(t->Name)) {
X Fprintf(stderr, "Can't stat %s (%s), skipping.\n",
X t->Name, Ermsg(errno));
X continue;
X }
X t->Type = Ftype(t->Name);
X
X /* Guesstimate its size when archived: prolog, plus one char/line. */
X t->Bsize = strlen(t->Name) * 4 + 200;
X if (t->Type == F_FILE) {
X lsize = Fsize(t->Name);
X /* If we had a "wc" we could use it, but this is good enough. */
X if (IsProbablySource(t->Name))
X /* Average chars/line in C, Pascal, Fortran. Sort of. */
X t->Bsize += lsize + lsize / 25;
X else
X t->Bsize += lsize + lsize / 60;
X }
X if (t->Bsize > Size) {
X Fprintf(stderr, "At %ld bytes, %s is too big for any archive!\n",
X t->Bsize, t->Name);
X exit(1);
X /* NOTREACHED */
X }
X
X /* Is our ouput file there? */
X if (!FoundOutname && OutName && EQ(OutName, t->Name))
X FoundOutname = TRUE;
X
X /* All done -- advance to next entry. */
X t++;
X lines++;
X }
X (void)fclose(F);
X (void)unlink(TEMP);
X
X /* Add our output file? */
X if (!ExcludeIt && !FoundOutname && OutName) {
X t->Name = OutName;
X t->Text = "This shipping list";
X t->Type = F_FILE;
X t->Bsize = (lines + 3) * 60;
X t->Where = 0;
X t++;
X }
X
X /* Sort by size. */
X lines = t - Table;
X TabEnd = &Table[lines];
X if (!Preserve)
X qsort((char *)Table, lines, sizeof Table[0], SizeP);
X
X /* Get archive space, allow for initial overhead. */
X Ark = NEW(ARCHIVE, ArkCount);
X ArkEnd = &Ark[ArkCount];
X for (k = Ark; k < ArkEnd; k++) {
X k->Count = 0;
X k->Asize = 500;
X }
X
X /* See if everyone has a place to be. */
X if (Believer)
X for (t = Table; t < TabEnd; t++)
X if (t->Where == 0) {
X Fprintf(stderr, "Can't believe the manifest assignments.\n");
X Believer = FALSE;
X break;
X }
X
X /* Loop through the pieces, and put everyone into an archive. */
X if (!Believer) {
X for (t = Table; t < TabEnd; t++) {
X for (k = Ark; k < ArkEnd; k++)
X if (t->Bsize + k->Asize < Size) {
X k->Asize += t->Bsize;
X t->Where = k - Ark;
X k->Count++;
X break;
X }
X if (k == ArkEnd) {
X Fprintf(stderr,
X "'%s' doesn't fit -- need more then %d archives.\n",
X t->Name, ArkCount);
X exit(1);
X /* NOTREACHED */
X }
X /* Since our share doesn't build sub-directories... */
X if (t->Type == F_DIR && k != Ark)
X Fprintf(stderr, "Warning, directory '%s' is in archive %d.\n",
X t->Name, k - Ark + 1);
X }
X }
X
X /* Open the output file. */
X if (OutName == NULL)
X F = stdout;
X else {
X if (Fexists(OutName))
X SafeRename(OutName);
X if ((F = fopen(OutName, "w")) == NULL) {
X Fprintf(stderr, "Can't open '%s' for output, %s.\n",
X OutName, Ermsg(errno));
X exit(1);
X /* NOTREACHED */
X }
X }
X
X /* Sort the shipping list, then write it. */
X if (!Preserve)
X qsort((char *)Table, lines, sizeof Table[0], ReadmeP);
X Fprintf(F, " File Name\t\tArchive #\tDescription\n");
X Fprintf(F, "----------------------------------------------------------\n");
X for (t = Table; t < TabEnd; t++)
X Fprintf(F, MANI_FORMAT, t->Name, t->Where + 1, t->Text);
X
X /* Close output. Are we done? */
X if (F != stdout)
X (void)fclose(F);
X if (!Working)
X exit(0);
X /* NOTREACHED */
X
X /* Find last archive number. */
X for (i = 0, t = Table; t < TabEnd; t++)
X if (i < t->Where)
X i = t->Where;
X LastOne = i + 1;
X
X /* Find archive with most files in it and build an argv vector. */
X for (i = 0, k = Ark; k < ArkEnd; k++)
X if (i < k->Count)
X i = k->Count;
X av = NEW(char*, i + 10);
X
X /* Build the fixed part of the argument vector. */
X av[0] = "shar";
X i = 1;
X if (Trailer) {
X av[i++] = "-t";
X av[i++] = Trailer;
X }
X if (Notkits == FALSE) {
X (void)sprintf(EndArkNum, "%d", LastOne);
X av[i++] = "-e";
X av[i++] = EndArkNum;
X av[i++] = "-n";
X av[i++] = CurArkNum;
X }
X av[i++] = "-o";
X av[i++] = buff; /* See sprintf call in loop below. */
X
X#ifdef USE_TEMP_MANIFEST
X av[i++] = "-i";
X MakeTempName(FLST, TEMP_NAME2);
X av[i++] = FLST;
X av[i] = NULL;
X#endif /* USE_TEMP_MANIFEST */
X
X /* Call shar to package up each archive. */
X for (Start = i, i = 0; i < LastOne; i++) {
X (void)sprintf(CurArkNum, "%d", i + 1);
X (void)sprintf(buff, NAME_FORMAT, SharName, i + 1);
X#ifndef USE_TEMP_MANIFEST
X for (lines = Start, t = Table; t < TabEnd; t++)
X if (t->Where == i)
X av[lines++] = t->Name;
X av[lines] = NULL;
X#else
X if ((F = fopen(FLST, "w")) == NULL) {
X Fprintf(stderr, "Can't open list file '%s' for output, %s.\n",
X FLST, Ermsg(errno));
X exit(1);
X /* NOTREACHED */
X }
X for (t = Table; t < TabEnd; t++)
X if (t->Where == i)
X Fprintf(F, "%s\n", t->Name);
X (void)fclose(F);
X#endif /* USE_TEMP_MANIFEST */
X Fprintf(stderr, "Packing kit %d...\n", i + 1);
X if (lines = Execute(av))
X Fprintf(stderr, "Warning, shar returned status %d.\n", lines);
X }
X
X#ifdef USE_TEMP_MANIFEST
X (void)unlink(FLST);
X#endif /* USE_TEMP_MANIFEST */
X
X /* That's all she wrote. */
X exit(0);
X /* NOTREACHED */
X}
END_OF_FILE
if test 11847 -ne `wc -c <'makekit.c'`; then
echo shar: \"'makekit.c'\" unpacked with wrong size!
fi
# end of 'makekit.c'
fi
if test -f 'maniscan.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'maniscan.c'\"
else
echo shar: Extracting \"'maniscan.c'\" \(9173 characters\)
sed "s/^X//" >'maniscan.c' <<'END_OF_FILE'
X/*
X** MANISCAN
X**
X** Read a manifest, looking for large files and those with binary data.
X*/
X#include "shar.h"
X#ifdef RCSID
Xstatic char RCS[] =
X "$Header$";
X#endif /* RCSID */
X
X
X/*
X** Global variables.
X*/
Xstatic long Size; /* Bigger than this is bad */
Xstatic FILE *Logfile; /* Where to record problems */
X
X
X/*
X** Safely add an extension to a filename. On non-Unix systems, this
X** might be a pain.
X*/
Xstatic void
XAddExtension(Name, Suffix, Buffer)
X char *Name;
X char *Suffix;
X char *Buffer;
X{
X#ifdef UNIX
X (void)sprintf(Buffer, "%s.%s", Name, Suffix);
X#else
X /* Should fix this... */
X (void)sprintf(Buffer, "%s%s", Name, Suffix);
X#endif /* UNIX */
X}
X
X
X/*
X** Do the grunge work of checking a file. Note that we scan stuff more
X** than once because, e.g., after it's been uuencoded and edited it
X** might be too long.
X*/
Xstatic int
XCheckUp(Name, Commentary)
X char *Name;
X char *Commentary;
X{
X REGISTER FILE *F;
X REGISTER FILE *Sfile;
X REGISTER char *p;
X REGISTER int i;
X REGISTER int n;
X REGISTER long s;
X char buff[READ_CHUNK];
X char Newname[LINE_SIZE];
X char Digits[10];
X int RanUUencode;
X int Smudged;
X
X Smudged = FALSE;
X
X /* Open file, read a chunk. */
X if ((F = fopen(Name, "r")) == NULL) {
X Fprintf(stderr, "Can't open \"%s\" to check it, %s.\n",
X Name, Ermsg(errno));
X return Smudged;
X }
X if ((n = fread(buff, sizeof buff[0], READ_CHUNK, F)) <= 0) {
X Fprintf(stderr, "Can't read \"%s\" to check it, %s.\n",
X Name, Ermsg(errno));
X (void)fclose(F);
X return Smudged;
X }
X
X /* Is it binary? Rough hueristic -- one third of the chunk isn't
X * printable. */
X for (p = buff, i = 0; p < &buff[n]; p++)
X if (!CTYPE(*p) || !isprint(*p))
X i++;
X if (RanUUencode = i > n / 3) {
X AddExtension(Name, "UU", Buffer)
X uuencode(Name, Newname);
X if (Logfile) {
X if (!Smudged) {
X Smudged = TRUE;
X Fprintf(Logfile, "\n");
X }
X Fprintf(Logfile, "Run \"uudecode\" on \"%s\" to create \"%s\".\n",
X Newname, Name);
X }
X (void)strcpy(Name, Newname);
X (void)fclose(F);
X if ((F = fopen(Name, "r")) == NULL) {
X Fprintf(stderr, "Can't open \"%s\" to check it, %s.\n",
X Name, Ermsg(errno));
X return Smudged;
X }
X }
X
X /* See if the input has any long lines, or bad characters. */
X rewind(F);
X for (i = 1; fgets(buff, sizeof buff, F); i++) {
X if (p = IDX(buff, '\n'))
X *p = '\0';
X if (p == NULL || p >= &buff[SAFE_WIDTH])
X if (Logfile) {
X if (!Smudged) {
X Smudged = TRUE;
X Fprintf(Logfile, "\n");
X }
X Fprintf(Logfile, "\"%s\", line %d: line too long\n", Name, i);
X }
X
X for (p = buff; *p; p++)
X if (!CTYPE(*p) || !(isprint(*p) || isspace(*p)))
X if (Logfile) {
X if (!Smudged) {
X Smudged = TRUE;
X Fprintf(Logfile, "\n");
X }
X Fprintf(Logfile,
X "\"%s\", line %d: bad character 0%o (%s)\n",
X Name, i, *p, Seechar(*p));
X }
X
X /* Is last character whitespace? Bitnet will choke. */
X if (p > buff) {
X p--;
X if (!CTYPE(*p) || isspace(*p))
X if (Logfile) {
X if (!Smudged) {
X Smudged = TRUE;
X Fprintf(Logfile, "\n");
X }
X Fprintf(Logfile,
X "\"%s\", line %d: ends with whitespace\n",
X Name, i);
X }
X }
X }
X (void)fclose(F);
X
X /* Small enough to fit? */
X if (Fsize(Name) <= Size) {
X Printf("%s%s\n", Name, Commentary);
X return Smudged;
X }
X
X /* Reduce size by slop so last line doesn't make us too long. */
X Size -= 2 * SAFE_WIDTH;
X
X /* Open input. */
X if ((F = fopen(Name, "r")) == NULL) {
X Fprintf(stderr, "Can't open \"%s\" to split it, %s.\n",
X Name, Ermsg(errno));
X return Smudged;
X }
X
X /* Open first output, write commentary. */
X i = 1;
X AddExtension(Name, "1", Newname);
X if ((Sfile = fopen(Newname, "w")) == NULL) {
X Fprintf(stderr, "Can't open \"%s\" for writing, %s.\n",
X Newname, Ermsg(errno));
X (void)fclose(F);
X return Smudged;
X }
X Printf("%s%s (part %d)\n", Newname, Commentary, i);
X
X /* Read input, when current output gets too big, start a new file. */
X for (s = 0; fgets(buff, sizeof buff, F); ) {
X s += strlen(buff);
X if (s > Size) {
X /* Start a new file. */
X (void)fclose(Sfile);
X (void)sprintf(Newname, "%s.%d", Name, ++i);
X (void)sprintf(Digits, "%d", ++i);
X AddExtension(Name, Digits, Newname);
X if ((Sfile = fopen(Newname, "w")) == NULL) {
X Fprintf(stderr, "Can't open \"%s\" for writing, %s.\n",
X Newname, Ermsg(errno));
X (void)fclose(F);
X return Smudged;
X }
X Printf("%s%s (part %d)\n", Newname, Commentary, i);
X s = strlen(buff);
X }
X (void)fputs(buff, Sfile);
X }
X
X /* Close input and current output, remove temporary if we made one. */
X (void)fclose(F);
X (void)fclose(Sfile);
X if (RanUUencode)
X (void)unlink(Name);
X
X /* Write summary message. */
X if (Logfile) {
X if (!Smudged) {
X Smudged = TRUE;
X Fprintf(Logfile, "\n");
X }
X Fprintf(Logfile,
X "File \"%s\" was split because of its size; to create it, do\n",
X Name);
X if (i < 10)
X Fprintf(Logfile, "\tcat %s.? >%s\n", Name, Name);
X else if (i < 100)
X Fprintf(Logfile, "\tcat %s.? %s.?? >%s\n", Name, Name, Name);
X else
X Fprintf(Logfile, "\tWhatever's appropriate\n");
X }
X return Smudged;
X}
X
X
Xmain(ac, av)
X REGISTER int ac;
X REGISTER char *av[];
X{
X REGISTER FILE *F;
X REGISTER char *p;
X REGISTER int i;
X REGISTER int Header;
X REGISTER int LogDirty;
X char *InName;
X char *OutName;
X char *LogName;
X char buff[BUFSIZ];
X char Rest[LINE_SIZE];
X char Name[LINE_SIZE];
X char TempName[TEMPSIZE];
X int ExcludeIt;
X int Oops;
X
X /* Parse JCL. */
X ExcludeIt = FALSE;
X InName = NULL;
X OutName = NULL;
X LogName = NULL;
X Header = 0;
X Size = 50000;
X for (Oops = FALSE; (i = getopt(ac, av, "eh:i:l:mo:s:")) != EOF; )
X switch (i) {
X default:
X Oops = TRUE;
X break;
X case 'e':
X ExcludeIt = TRUE;
X break;
X case 'h':
X Header = atoi(optarg);
X break;
X case 'i':
X InName = optarg;
X break;
X case 'l':
X LogName = optarg;
X break;
X case 'm':
X LogName = "PACKNOTES";
X InName = OutName = "MANIFEST";
X Header = 2;
X break;
X case 'o':
X OutName = optarg;
X break;
X case 's':
X Size = (long)atoi(optarg);
X if (IDX(optarg, 'k') || IDX(optarg, 'K'))
X Size *= 1024;
X break;
X }
X ac -= optind;
X av += optind;
X
X if (ac != 0 || Oops) {
X Fprintf(stderr, "Usage:\n maniscan %s\n",
X "[-e] [-s #[k]] [-m | -i MANIFEST -o MANIFEST -h 2 -l PACKNOTES]");
X exit(1);
X /* NOTREACHED */
X }
X
X /* Open the input file. */
X if (InName && freopen(InName, "r", stdin) == NULL) {
X Fprintf(stderr, "Can't read %s as manifest, %s.\n",
X InName, Ermsg(errno));
X exit(1);
X /* NOTREACHED */
X }
X
X /* Open the output file. */
X if (OutName == NULL)
X F = stdout;
X else {
X MakeTempName(TempName, TEMP_NAME1);
X if ((F = fopen(TempName, "w")) == NULL) {
X Fprintf(stderr, "Can't open '%s' for output, %s.\n",
X TempName, Ermsg(errno));
X exit(1);
X /* NOTREACHED */
X }
X }
X
X /* Open the log file. */
X LogDirty = FALSE;
X if (LogName) {
X if (EQ(LogName, "-")) {
X Logfile = stderr;
X ExcludeIt = TRUE;
X }
X else if ((Logfile = fopen(LogName, "w")) == NULL) {
X Fprintf(stderr, "Can't open \"%s\" for output, %s.\n",
X LogName, Ermsg(errno));
X exit(1);
X /* NOTREACHED */
X }
X }
X
X /* Skip any possible prolog, then output rest of file. */
X while (--Header >= 0 && fgets(buff, sizeof buff, stdin))
X (void)fputs(buff, F);
X if (feof(stdin)) {
X Fprintf(stderr, "Nothing but header lines in the manifest.\n");
X exit(1);
X /* NOTREACHED */
X }
X
X /* Scan rest of file. */
X while (fgets(buff, sizeof buff, stdin)) {
X if (p = IDX(buff, '\n'))
X *p = '\0';
X else
X Fprintf(stderr, "Warning, line too long:\n\t%s\n", buff);
X
X /* Skip leading whitespace and ignore all-blank lines. */
X for (p = buff; *p && CTYPE(*p) && isspace(*p); )
X p++;
X if (*p == '\0')
X continue;
X /* Save name, find end of it, stuff rest of line away. */
X while (*++p && CTYPE(*p) && !isspace(*p))
X ;
X i = *p;
X *p = '\0';
X (void)strcpy(Name, buff);
X *p = i;
X (void)strcpy(Rest, p);
X
X if (CheckUp(Name, Rest))
X LogDirty = TRUE;
X }
X
X /* Close logfile, possibly add it to the manifest. */
X if (Logfile) {
X if (Logfile != stderr)
X (void)fclose(Logfile);
X if (LogDirty && !ExcludeIt)
X Printf(MANI_FORMAT,
X LogName, 1, "1 Warnings about long lines, etc");
X }
X
X /* Move temp file to new file? */
X if (OutName) {
X /* Open new file. */
X (void)fclose(F);
X if ((F = fopen(TempName, "r")) == NULL) {
X Fprintf(stderr, "Can't open \"%s\" for reading, %s.\n",
X Name, Ermsg(errno));
X exit(1);
X /* NOTREACHED */
X }
X
X /* Save old manifest. */
X if (Fexists(OutName))
X SafeRename(OutName);
X if (freopen(OutName, "w", stdout) == NULL) {
X Fprintf(stderr, "Can't open \"%s\" for writing, %s.\n",
X OutName, Ermsg(errno));
X exit(1);
X /* NOTREACHED */
X }
X
X /* Copy. */
X while (fgets(buff, sizeof buff, F))
X (void)fputs(buff, stdout);
X }
X
X /* That's all she wrote. */
X exit(0);
X /* NOTREACHED */
X}
END_OF_FILE
if test 9173 -ne `wc -c <'maniscan.c'`; then
echo shar: \"'maniscan.c'\" unpacked with wrong size!
fi
# end of 'maniscan.c'
fi
if test -f 'shar.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'shar.c'\"
else
echo shar: Extracting \"'shar.c'\" \(8463 characters\)
sed "s/^X//" >'shar.c' <<'END_OF_FILE'
X/*
X** SHAR
X**
X** Make a shell archive of a list of files.
X*/
X#include "shar.h"
X#ifdef RCSID
Xstatic char RCS[] =
X "$Header: shar.c,v 2.1 88/06/03 11:51:12 rsalz Locked $";
X#endif /* RCSID */
X
X/*
X** Minimum allocation of file name pointers used in "-i" option processing.
X*/
X#define MIN_FILES 50
X
X
X/*
X** This prolog is output before the archive.
X*/
Xstatic char *Prolog[] = {
X "! /bin/sh",
X " This is a shell archive. Remove anything before this line, then feed it",
X " into a shell via \"sh file\" or similar. To overwrite existing files,",
X " type \"sh file -c\".",
X#ifdef PEDAGOGY
X " The tool that generated this appeared in the comp.sources.unix newsgroup;",
X " send mail to comp-sources-unix at uunet.uu.net if you want that tool.",
X#endif /* PEDAGOGY */
X " If this archive is complete, you will see the following message at the end:",
X NULL
X};
X
X
X/*
X** Package up one file or directory.
X*/
Xstatic void
Xshar(file, Basename)
X char *file;
X int Basename;
X{
X REGISTER char *s;
X REGISTER char *Name;
X REGISTER int Bads;
X REGISTER off_t Size;
X REGISTER long l;
X char buff[BUFSIZ];
X
X /* Just in case. */
X if (EQ(file, ".") || EQ(file, ".."))
X return;
X
X Size = Fsize(file);
X Name = Basename && (Name = RDX(file, '/')) ? Name + 1 : file;
X
X /* Making a directory? */
X if (Ftype(file) == F_DIR) {
X Printf("if test ! -d '%s' ; then\n", Name);
X Printf(" echo shar: Creating directory \\\"'%s'\\\"\n", Name);
X Printf(" mkdir '%s'\n", Name);
X Printf("fi\n");
X }
X else {
X if (freopen(file, "r", stdin) == NULL) {
X Fprintf(stderr, "Can't open \"%s\" %s\n", file, Ermsg(errno));
X exit(1);
X /* NOTREACHED */
X }
X
X /* Emit the per-file prolog. */
X Printf("if test -f '%s' -a \"${1}\" != \"-c\" ; then \n", Name);
X Printf(" echo shar: Will not clobber existing file \\\"'%s'\\\"\n",
X Name);
X Printf("else\n");
X Printf("echo shar: Extracting \\\"'%s'\\\" \\(%ld character%s\\)\n",
X Name, (long)Size, Size == 1 ? "" : "s");
X Printf("sed \"s/^X//\" >'%s' <<'END_OF_FILE'\n", Name, Name);
X
X /* Output the file contents. */
X for (l = 0, Bads = 0; fgets(buff, sizeof buff, stdin); l++) {
X if (s = IDX(buff, '\n'))
X *s = '\0';
X else
X Fprintf(stderr, "Warning, line too long:\n\t%s\n", buff);
X
X (void)putchar('X');
X for (s = buff; *s; s++) {
X if (BADCHAR(*s)) {
X Fprintf(stderr,
X "Bad character 0%o in line %ld of \"%s\".\n",
X *s, l, Name);
X Bads++;
X }
X (void)putchar(*s);
X }
X (void)putchar('\n');
X }
X
X /* Check for missing \n at end of file. */
X if (*--s != '\n')
X (void)putchar('\n');
X Printf("END_OF_FILE\n",Name);
X if (*s != '\n') {
X Printf("echo shar: NEWLINE appended to \\\"'%s'\\\"\n", Name);
X Fprintf(stderr, "NEWLINE appended to \"%s\"\n", Name);
X Size++;
X }
X
X /* Tell about any control characters. */
X if (Bads) {
X Printf(
X "echo shar: %d control character%s may be missing from \\\"'%s'\\\"\n",
X Bads, Bads == 1 ? "" : "s", Name);
X Fprintf(stderr, "Found %d control char%s in \"%s\"\n",
X Bads, Bads == 1 ? "" : "s", Name);
X }
X
X /* Output size check. */
X Printf("if test %ld -ne `wc -c <'%s'`; then\n", (long)Size, Name);
X Printf(" echo shar: \\\"'%s'\\\" unpacked with wrong size!\n", Name);
X Printf("fi\n");
X
X /* Executable? */
X if (Fexecute(file))
X Printf("chmod +x '%s'\n", Name);
X
X Printf("# end of '%s'\nfi\n", Name);
X }
X}
X
X
X/*
X** Read list of files from file.
X*/
Xstatic char **
XGetFiles(Name)
X char *Name;
X{
X REGISTER FILE *F;
X REGISTER int i;
X REGISTER int count;
X REGISTER char **files;
X REGISTER char **temp;
X REGISTER int j;
X char buff[BUFSIZ];
X char *p;
X
X /* Open the file. */
X if (EQ(Name, "-"))
X F = stdin;
X else if ((F = fopen(Name, "r")) == NULL) {
X Fprintf(stderr, "Can't open \"%s\" for input.\n", Name);
X return NULL;
X }
X
X /* Get space. */
X count = MIN_FILES;
X files = NEW(char*, count);
X
X /* Read lines. */
X for (i = 0; fgets(buff, sizeof buff, F); ) {
X if (p = IDX(buff, '\n'))
X *p = '\0';
X files[i] = COPY(buff);
X if (++i == count - 2) {
X /* Get more space; some systems don't have realloc()... */
X count += MIN_FILES;
X for (temp = NEW(char*, count), j = 0; j < i; j++)
X temp[j] = files[j];
X files = temp;
X }
X }
X
X /* Clean up, close up, return. */
X files[i] = NULL;
X (void)fclose(F);
X return files;
X}
X
X
Xmain(ac, av)
X int ac;
X REGISTER char *av[];
X{
X REGISTER char *Trailer;
X REGISTER char *p;
X REGISTER char *q;
X REGISTER int i;
X REGISTER int length;
X REGISTER int Oops;
X REGISTER int Knum;
X REGISTER int Kmax;
X REGISTER int Basename;
X REGISTER int j;
X time_t clock;
X char **Flist;
X
X /* Parse JCL. */
X Basename = 0;
X Knum = 0;
X Kmax = 0;
X Trailer = NULL;
X Flist = NULL;
X for (Oops = FALSE; (i = getopt(ac, av, "be:i:n:o:t:")) != EOF; )
X switch (i) {
X default:
X Oops = TRUE;
X break;
X case 'b':
X Basename = TRUE;
X break;
X case 'e':
X Kmax = atoi(optarg);
X break;
X case 'i':
X Flist = GetFiles(optarg);
X break;
X case 'n':
X Knum = atoi(optarg);
X break;
X case 'o':
X if (freopen(optarg, "w", stdout) == NULL) {
X Fprintf(stderr, "Can't open \"%s\" for output, %s.\n",
X optarg, Ermsg(errno));
X exit(1);
X /* NOTREACHED */
X }
X break;
X case 't':
X Trailer = optarg;
X break;
X }
X ac -= optind;
X av += optind;
X
X /* If user hasn't screwed up yet, make sure we exactly one of
X * the -i flag or files named on the command line. */
X if (!Oops
X && ((Flist == NULL && ac == 0) || (Flist != NULL && ac != 0))) {
X Fprintf(stderr,
X "What files to shar? Use -i or command line, not both.\n");
X Oops = TRUE;
X }
X
X if (Oops) {
X Fprintf(stderr,
X "Usage:\n shar %s files...\n",
X "[-b] [-o outfile] [-i infile] [-n# -e# -t'text']");
X exit(1);
X /* NOTREACHED */
X }
X
X /* If we didn't get the list from -i, rest of argv is the file list. */
X if (Flist == NULL)
X /* Rest of arguments are files. */
X Flist = av;
X
X /* Everything readable and reasonably-named? */
X for (Oops = FALSE, i = 0; p = Flist[i]; i++)
X if (freopen(p, "r", stdin) == NULL) {
X Fprintf(stderr, "Can't read \"%s\", %s.\n", p, Ermsg(errno));
X Oops = TRUE;
X }
X else
X for (; *p; p++)
X if (!CTYPE(*p)) {
X Fprintf(stderr, "Bad character '%c' in \"%s\".\n",
X *p, Flist[i]);
X Oops = TRUE;
X }
X if (Oops)
X exit(1);
X /* NOTREACHED */
X
X /* Prolog. */
X for (i = 0; p = Prolog[i]; i++)
X Printf("#%s\n", p);
X if (Knum && Kmax)
X Printf("#\t\t\"End of archive %d (of %d).\"\n", Knum, Kmax);
X else
X Printf("#\t\t\"End of shell archive.\"\n");
X Printf("# Contents: ");
X for (length = 12, i = 0; p = Flist[i++]; length += j) {
X if (Basename && (q = RDX(p, '/')))
X p = q + 1;
X j = strlen(p) + 1;
X if (length + j < WIDTH)
X Printf(" %s", p);
X else {
X Printf("\n# %s", p);
X length = 4;
X }
X }
X Printf("\n");
X clock = time((time_t *)NULL);
X Printf("# Wrapped by %s@%s on %s", User(), Host(), ctime(&clock));
X Printf("PATH=/bin:/usr/bin:/usr/ucb ; export PATH\n");
X
X /* Do it. */
X while (*Flist)
X shar(*Flist++, Basename);
X
X /* Epilog. */
X if (Knum && Kmax) {
X Printf("echo shar: End of archive %d \\(of %d\\).\n", Knum, Kmax);
X Printf("cp /dev/null ark%disdone\n", Knum);
X Printf("MISSING=\"\"\n");
X Printf("for I in");
X for (i = 0; i < Kmax; i++)
X Printf(" %d", i + 1);
X Printf(" ; do\n");
X Printf(" if test ! -f ark${I}isdone ; then\n");
X Printf("\tMISSING=\"${MISSING} ${I}\"\n");
X Printf(" fi\n");
X Printf("done\n");
X Printf("if test \"${MISSING}\" = \"\" ; then\n");
X if (Kmax == 1)
X Printf(" echo You have the archive.\n");
X else if (Kmax == 2)
X Printf(" echo You have unpacked both archives.\n");
X else
X Printf(" echo You have unpacked all %d archives.\n", Kmax);
X if (Trailer && *Trailer)
X Printf(" echo \"%s\"\n", Trailer);
X Printf(" rm -f ark[1-9]isdone%s\n",
X Kmax >= 9 ? " ark[1-9][0-9]isdone" : "");
X Printf("else\n");
X Printf(" echo You still need to unpack the following archives:\n");
X Printf(" echo \" \" ${MISSING}\n");
X Printf("fi\n");
X Printf("## End of shell archive.\n");
X }
X else {
X Printf("echo shar: End of shell archive.\n");
X if (Trailer && *Trailer)
X Printf("echo \"%s\"\n", Trailer);
X }
X
X Printf("exit 0\n");
X
X exit(0);
X /* NOTREACHED */
X}
END_OF_FILE
if test 8463 -ne `wc -c <'shar.c'`; then
echo shar: \"'shar.c'\" unpacked with wrong size!
fi
# end of 'shar.c'
fi
if test -f 'unshar.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'unshar.c'\"
else
echo shar: Extracting \"'unshar.c'\" \(8836 characters\)
sed "s/^X//" >'unshar.c' <<'END_OF_FILE'
X/*
X** UNSHAR
X**
X** Unpack shell archives that might have gone through mail, notes, news, etc.
X** This is Michael Mauldin's code which I have usurped and heavily modified.
X*/
X#include "shar.h"
X#ifdef RCSID
Xstatic char RCS[] =
X "$Header: unshar.c,v 2.2 88/06/03 16:08:14 rsalz Locked $";
X#endif /* RCSID */
X
X
X/*
X** Print error message and die.
X*/
Xstatic void
XQuit(text)
X char *text;
X{
X Fprintf(stderr, "unshar: %s, %s.\n", text, Ermsg(errno));
X exit(1);
X /* NOTREACHED */
X}
X
X
X/*
X** Does this look like a mail header line?
X*/
Xstatic int
XIsHeader(p)
X REGISTER char *p;
X{
X REGISTER int i;
X
X if (*p == '\0' || *p == '\n')
X return FALSE;
X if (WHITE(*p))
X return TRUE;
X for (i = 0; (CTYPE(*p) && isalnum(*p)) || HDRCHAR(*p); i++)
X p++;
X return i && *p == ':';
X}
X
X
X/*
X** Is this a /bin/sh comment line? We check that because some shars
X** output comments before the CUT line.
X*/
Xstatic int
XIsSHcomment(p)
X REGISTER char *p;
X{
X while (CTYPE(*p) &&
X (isalpha(*p) || WHITE(*p) || *p == '\n' || *p == ',' || *p == '.'))
X p++;
X return *p == '\0';
X}
X
X
X/*
X** Return TRUE if p has wd1 and wd2 as words (i.e., no preceeding or
X** following letters). Clever code, Michael.
X*/
Xstatic int
XHas(p, wd1, wd2)
X REGISTER char *p;
X REGISTER char *wd1;
X REGISTER char *wd2;
X{
X REGISTER char *wd;
X REGISTER int first;
X
X wd = wd1;
X first = TRUE;
Xagain:
X while (*p) {
X if (!CTYPE(*p) || !isalpha(*p)) {
X p++;
X continue;
X }
X while (*p++ == *wd++) {
X if (*wd == '\0') {
X if (!CTYPE(*p) || !isalpha(*p)) {
X if (!first)
X return TRUE;
X first = FALSE;
X wd = wd2;
X goto again;
X }
X break;
X }
X }
X while (CTYPE(*p) && isalpha(*p))
X p++;
X wd = first ? wd1 : wd2;
X }
X return FALSE;
X}
X
X
X/*
X** Here's where the work gets done. Skip headers and try to intuit
X** if the file is, e.g., C code, etc.
X*/
Xstatic int
XFound(Name, buff, Forced, Stream, Header)
X REGISTER char *Name;
X REGISTER char *buff;
X REGISTER int Forced;
X REGISTER FILE *Stream;
X REGISTER FILE *Header;
X{
X REGISTER char *p;
X REGISTER int InHeader;
X char lower[BUFSIZ];
X
X if (Header)
X InHeader = TRUE;
X
X while (TRUE) {
X /* Read next line, fail if no more */
X if (fgets(buff, BUFSIZ, Stream) == NULL) {
X Fprintf(stderr, "unshar: No shell commands in %s.\n", Name);
X return FALSE;
X }
X
X /* See if it looks like another language. */
X if (!Forced) {
X if (PREFIX(buff, "#include") || PREFIX(buff, "# include")
X || PREFIX(buff, "#define") || PREFIX(buff, "# define")
X || PREFIX(buff, "#ifdef") || PREFIX(buff, "# ifdef")
X || PREFIX(buff, "#ifndef") || PREFIX(buff, "# ifndef")
X || (PREFIX(buff, "/*")
X && !PREFIX(buff, NOTES1) && !PREFIX(buff, NOTES2)))
X p = "C code";
X else if (PREFIX(buff, "(*")) /* For vi :-) */
X p = "PASCAL code";
X else if (buff[0] == '.'
X && CTYPE(buff[1]) && isalpha(buff[1])
X && CTYPE(buff[2]) && isalpha(buff[2])
X && CTYPE(buff[3]) && !isalpha(buff[3]))
X p = "TROFF source";
X else
X p = NULL;
X if (p) {
X Fprintf(stderr,
X "unshar: %s is apparently %s, not a shell archive.\n",
X Name, p);
X return FALSE;
X }
X }
X
X /* Does this line start with a shell command or comment? */
X if ((buff[0] == '#' && !IsSHcomment(buff + 1))
X || buff[0] == ':' || PREFIX(buff, "echo ")
X || PREFIX(buff, "sed ") || PREFIX(buff, "cat ")) {
X return TRUE;
X }
X
X /* Does this line say "Cut here"? */
X for (p = strcpy(lower, buff); *p; p++)
X if (CTYPE(*p) && islower(*p))
X *p = toupper(*p);
X if (PREFIX(buff, "-----") || Has(lower, "cut", "here")
X || Has(lower, "cut", "cut") || Has(lower, "tear", "here")) {
X /* Get next non-blank line. */
X do {
X if (fgets(buff, BUFSIZ, Stream) == NULL) {
X Fprintf(stderr, "unshar: cut line is last line of %s\n",
X Name);
X return FALSE;
X }
X } while (*buff == '\n');
X
X /* If it starts with a comment or lower-case letter we win. */
X if (*buff == '#' || *buff == ':'
X || (CTYPE(*buff) && islower(*buff)))
X return TRUE;
X
X /* The cut message lied. */
X Fprintf(stderr, "unshar: %s is not a shell archive,\n", Name);
X Fprintf(stderr, " the 'cut' line was followed by: %s", buff);
X return FALSE;
X }
X
X if (Header) {
X (void)fputs(buff, Header);
X if (InHeader && !IsHeader(buff))
X InHeader = FALSE;
X }
X }
X}
X
X
X/*
X** Create file for the header, find true start of the archive,
X** and send it off to the shell.
X*/
Xstatic void
XUnshar(Name, HdrFile, Stream, Saveit, Forced)
X char *Name;
X char *HdrFile;
X REGISTER FILE *Stream;
X int Saveit;
X int Forced;
X{
X REGISTER FILE *Header;
X#ifndef USE_MY_SHELL
X REGISTER FILE *Pipe;
X#endif /* USE_MY_SHELL */
X char *p;
X char buff[BUFSIZ];
X
X if (Saveit) {
X /* Create a name for the saved header. */
X if (HdrFile)
X (void)strcpy(buff, HdrFile);
X else if (Name) {
X p = RDX(Name, '/');
X (void)strncpy(buff, p ? p + 1 : Name, 14);
X buff[10] = 0;
X (void)strcat(buff, ".hdr");
X }
X else
X (void)strcpy(buff, "UNSHAR.HDR");
X
X /* Tell user, and open the file. */
X Fprintf(stderr, "unshar: Sending header to %s.\n", buff);
X if ((Header = fopen(buff, "a")) == NULL)
X Quit("Can't open file for header");
X }
X else
X Header = NULL;
X
X /* If name is NULL, we're being piped into... */
X p = Name ? Name : "the standard input";
X Printf("unshar: Doing %s:\n", p);
X
X if (Found(p, buff, Forced, Stream, Header)) {
X#ifdef USE_MY_SHELL
X BinSh(Name, Stream, buff);
X#else
X if ((Pipe = popen("/bin/sh", "w")) == NULL)
X Quit("Can't open pipe to /bin/sh process");
X
X (void)fputs(buff, Pipe);
X while (fgets(buff, sizeof buff, Stream))
X (void)fputs(buff, Pipe);
X
X (void)pclose(Pipe);
X#endif /* USE_MY_SHELL */
X }
X
X /* Close the headers. */
X if (Saveit)
X (void)fclose(Header);
X}
X
X
Xmain(ac, av)
X REGISTER int ac;
X REGISTER char *av[];
X{
X REGISTER FILE *Stream;
X REGISTER int i;
X char *p;
X char *Home;
X char *HdrFile;
X char cwd[BUFSIZ];
X char dir[BUFSIZ];
X char buff[BUFSIZ];
X int Saveit;
X int Forced;
X int Oops;
X
X /* Parse JCL. */
X p = getenv("UNSHARDIR");
X Saveit = DEF_SAVEIT;
X#ifdef UNIX
X HdrFile = NULL;
X#else
X HdrFile = "UNSHAR.HDR";
X#endif /* UNIX */
X Forced = FALSE;
X for (Oops = FALSE; (i = getopt(ac, av, "c:d:fh:ns")) != EOF; )
X switch (i) {
X default:
X Oops = TRUE;
X break;
X case 'c':
X case 'd':
X p = optarg;
X break;
X case 'f':
X Forced = TRUE;
X break;
X case 'h':
X HdrFile = optarg;
X /* FALLTHROUGH */
X case 's':
X Saveit = TRUE;
X break;
X case 'n':
X Saveit = FALSE;
X break;
X }
X ac -= optind;
X av += optind;
X
X if (Oops) {
X Fprintf(stderr, "Usage:\n unshar %s [files...]\n",
X "[-f] [-s] [-n] [-c dir] [-d dir] [-h file]");
X exit(1);
X /* NOTREACHED */
X }
X
X /* Going somewhere? */
X if (p) {
X if (*p == '?') {
X /* Ask for name. */
X Stream = isatty(fileno(stdin))
X ? stdin : fopen(ctermid((char *)NULL), "r");
X if (Stream == NULL)
X Quit("Can't open tty to ask for directory");
X Printf("unshar: what directory? ");
X (void)fflush(stdout);
X if (fgets(buff, sizeof buff, Stream) == NULL
X || buff[0] == '\n'
X || (p = IDX(buff, '\n')) == NULL)
X Quit("Okay, cancelled");
X *p = '\0';
X p = buff;
X if (Stream != stdin)
X (void)fclose(Stream);
X }
X
X /* If name is ~/blah, he means $HOME/blah. */
X if (*p == '~') {
X#ifdef VMS
X (void)sprintf(dir, "sys$login:[%s]", p + 1);
X#else
X Home = getenv("HOME");
X if (Home == NULL) {
X Home = "/tmp";
X Fprintf(stderr, "Unshar warning, no $HOME; using \"%s\".\n",
X Home);
X }
X (void)sprintf(dir, "%s/%s", Home, p + 1);
X#endif /* VMS */
X p = dir;
X }
X
X /* If we're gonna move, first remember where we were. */
X if (GetDir(cwd, sizeof cwd) == NULL) {
X Fprintf(stderr, "Unshar warning, Can't get current directory.\n");
X cwd[0] = '\0';
X }
X
X /* Got directory; try to go there. Only make last component. */
X if (chdir(p) < 0 && (mkdir(p, 0777) < 0 || chdir(p) < 0))
X Quit("Cannot chdir nor mkdir desired directory");
X }
X else
X cwd[0] = '\0';
X
X /* No buffering. */
X (void)setbuf(stdout, (char *)NULL);
X (void)setbuf(stderr, (char *)NULL);
X
X if (*av)
X /* Process filenames from command line. */
X for (; *av; av++) {
X if (cwd[0] && av[0][0] != '/') {
X (void)sprintf(buff, "%s/%s", cwd, *av);
X *av = buff;
X }
X if ((Stream = fopen(*av, "r")) == NULL)
X Fprintf(stderr, "unshar: Can't open file '%s'.\n", *av);
X else {
X Unshar(*av, HdrFile, Stream, Saveit, Forced);
X (void)fclose(Stream);
X }
X }
X else
X /* Do standard input. */
X Unshar((char *)NULL, HdrFile, stdin, Saveit, Forced);
X
X /* That's all she wrote. */
X exit(0);
X /* NOTREACHED */
X}
END_OF_FILE
if test 8836 -ne `wc -c <'unshar.c'`; then
echo shar: \"'unshar.c'\" unpacked with wrong size!
fi
# end of 'unshar.c'
fi
echo shar: End of archive 4 \(of 5\).
cp /dev/null ark4isdone
MISSING=""
for I in 1 2 3 4 5 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 5 archives.
echo "Now go find those bugs, and report them to rsalz at uunet.uu.net"
rm -f ark[1-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
--
Please send comp.sources.unix-related mail to rsalz at uunet.uu.net.
More information about the Alt.sources
mailing list