home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume3 / shar2 < prev    next >
Internet Message Format  |  1989-02-03  |  37KB

  1. Path: xanth!mcnc!uvaarpa!umd5!brl-adm!cmcl2!nrl-cmf!ames!necntc!ncoast!allbery
  2. From: davidsen@crdos1.UUCP (Wm E. Davidsen)
  3. Newsgroups: comp.sources.misc
  4. Subject: v03i014: shar2
  5. Message-ID: <8805101146.AA02278@crdos1.UUCP>
  6. Date: 10 May 88 15:46:51 GMT
  7. Sender: allbery@ncoast.UUCP
  8. Reply-To: davidsen@crdos1.UUCP (Wm E. Davidsen)
  9. Lines: 1275
  10. Approved: allbery@ncoast.UUCP
  11.  
  12. comp.sources.misc: Volume 3, Issue 14
  13. Submitted-By: "Wm E. Davidsen" <davidsen@crdos1.UUCP>
  14. Archive-Name: shar2
  15.  
  16. [This is an enhanced "shar" program.  I think I'll stick with mine for
  17.  now, but it's nice to know someone's working on it.  ++bsa]
  18.  
  19. #!/bin/sh
  20. # shar:    Shell Archiver  (v1.22)
  21. #    Packed Tue May 10 11:43:47 EDT 1988 by davidsen
  22. #    from directory /usr2/davidsen/bin/src/shar2
  23. #
  24. #    Run the following text with /bin/sh to create:
  25. #      shar2.readme
  26. #      shar2.1
  27. #      unshar.1
  28. #      shar2.c
  29. #      uushar.c
  30. #      unshar.sh
  31. #      Makefile
  32. #      unshar.c
  33. #
  34. echo "x - extracting shar2.readme (Text)"
  35. sed 's/^X//' << 'SHAR_EOF' > shar2.readme &&
  36. X
  37. X  SHAR2 is a program to create shell archives. I wrote it to solve the
  38. Xproblems inherent in sharing large files, namely:
  39. X
  40. X    breaking up large postings to avoid truncation
  41. X        This is now done by the program
  42. X    concatenating shar parts before unpacking when large files
  43. X    won't fit into one mailable file
  44. X        Each output file may be unpacked separately, and the
  45. X        unpack is sequence checked
  46. X    binary files
  47. X        The shar program will optionally handle binary files, using
  48. X        uuencode to process them. The results are able to be broken
  49. X        into multiple files, as with text.
  50. X    mixed text and binary files
  51. X        The shar program can optionally handle a mixture of file
  52. X        types, using the 'file' command to test them. The mixing of
  53. X        text and binary files may also be done manually, for files
  54. X        which are text files but which contain characters which may
  55. X        be damaged when mailed.
  56. X    losing file permissions
  57. X        file permissions are preserved, allowing shell scripts to
  58. X        retain execute permission and read only files to be
  59. X        protected.
  60. X
  61. X
  62. XThese are the features of shar2 over the many shar versions around:
  63. X
  64. X     1.  It optionally produces multiple output files for mailing.
  65. X     2.  Multiple output files do not have to be concatenated before
  66. X         unpacking. Each may be unpacked independently, input files
  67. X         spanning several output files are joined correctly.
  68. X     3.  Unpacking of multiple-file archives is sequence checked.
  69. X     4.  binary files may be processed, using uuencode and uudecode.
  70. X         this allows large binary files to be easily moved by mail.
  71. X     5.  file permissions are preserved.
  72. X     6.  error checking is available as an option.
  73. X     7.  Fast - written in C.
  74. X     8.  Rejects pipes and directories.
  75. X     9.  Can handle mixed text and binary files, using automatic
  76. X         or manual file typing.
  77. X
  78. X  I wrote this because the version in shell script was too slow, I got a
  79. Xsource for a minimal version which could be enhanced, and to avoid
  80. Xhaving to join parts of binary postings before unpacking.  I hope
  81. Xit will be useful.
  82. X
  83. X                bill davidsen, 4/6/88 (davidsen@sixhub.uucp)
  84. X
  85. X  Latest revision, change checking to use wc instead of sun, since not
  86. Xall versions of sum are compatible.  Thanks to Keith Petersen.  Added
  87. Xthe ability to make the temp filenames DOS compatible to allow use of
  88. X'unshar' on DOS. 
  89. X
  90. SHAR_EOF
  91. chmod 0644 shar2.readme || echo "restore of shar2.readme fails"
  92. set `wc -c shar2.readme`;Sum=$1
  93. if test "$Sum" != "2317"
  94. then echo original size 2317, current size $Sum;fi
  95. echo "x - extracting shar2.1 (Text)"
  96. sed 's/^X//' << 'SHAR_EOF' > shar2.1 &&
  97. X'\" must be run through 'tbl' as well as nroff
  98. X.TH SHAR2 1 local
  99. X.SH NAME
  100. Xshar2 - create shell archives
  101. X.SH SYNOPSIS
  102. Xshar2 [ options ] files
  103. X.SH DESCRIPTION
  104. Xshar2 creates "shell archives" (or shar files) which are in text format
  105. Xand can be mailed. These files may be unpacked later by executing them
  106. Xwith /bin/sh.
  107. X.SS Options
  108. X.TS
  109. Xtab(;);
  110. Xlb lw(50).
  111. X-v;T{
  112. Xverbose. This option causes a running commentary as the archive is
  113. Xcreated, and another as it is unpacked. This option does not control the
  114. Xerror messages, only the informational messages.
  115. XT}
  116. X
  117. X-s;T{
  118. Xsum. The files are tested with the \fIsum\fR command for damage in
  119. Xtransit. Errors are reported.
  120. XT}
  121. X
  122. X-x;T{
  123. Xdon't overwrite existing files. The unpack will check for an existing
  124. Xfile before unpacking a given file from the archive.
  125. XT}
  126. X
  127. X-b;T{
  128. Xbinary. This option causes all files to be treated as binary files, and
  129. Xthe files are changed to text using \fIuuencode\fR. Commands are
  130. Xembedded in the output files to change use uudecode and recreate the
  131. Xbinary files.
  132. XT}
  133. X
  134. X-M;T{
  135. Xmixed text and binary.  This option causes each file to be
  136. Xexamined to determine if it is text or data.  Binary files will be
  137. Xprocessed using uuencode.
  138. XT}
  139. X
  140. X-D;T{
  141. Xgive detail of archive. The date, user, and working directory are added
  142. Xto the archive as comments.
  143. XT}
  144. X
  145. X-c;T{
  146. Xproduce cut line. This option causes a line saying "cut\ here" to be
  147. Xplaced at the start of each output file. This is for sites not offering
  148. Xthe \fIunshar\fR command or shell script.
  149. XT}
  150. X
  151. X-f;T{
  152. Xfilename only. By default the entire path name is used as given on the
  153. Xcommand line. This option causes only the file names to be used, which
  154. Xis useful when building a shar from several directories, or another
  155. Xdirectory.
  156. XT}
  157. X
  158. X-dXXX;T{
  159. Xchange delimiter to XXX. The default delimiter is SHAR_EOF, placed at
  160. Xthe end of each file. This option is left for historical reasons, to
  161. Xamuse those who want their shar files to be personalized.
  162. XT}
  163. X
  164. X-o\fIfile\fR;T{
  165. Xoutput filename. The file \fIfile\fR is used for output instead of the
  166. Xstandard output. This option is required to use the \fB-l\fR (limit
  167. Xfilesize) option.
  168. XT}
  169. X
  170. X-l\fInum\fR;T{
  171. Xfile size limit. The output files created by \fIshar2\fR will be smaller
  172. Xthan \fInum\fRk in length. The \fB-o\fR option must be used to specify
  173. Xan output filename, and the digits 00 through 99 will be appended to
  174. Xform a series of output filenames. Informative messages and sequence
  175. Xchecking are included.
  176. XT}
  177. X.TE
  178. X.SH EXAMPLES
  179. X'\"  examples use spaces, not tabs
  180. X  shar2 *.c > cprog.shar        # all C prog sources
  181. X  shar2 -v *.[ch] > cprog.shar  # verbose, .c and .h files
  182. X  shar2 -b -l28 -oarc.sh *.arc  # all binary .arc files, into
  183. X                                # files arc.sh01 thru arc.shNN
  184. X  shar2 -f /lcl/src/u*.c > u.sh    # use only the filenames
  185. X.SH WARNINGS
  186. XUse of the \fB-s\fR, \fB-b\fR, and \fB-M\fR options will slow the
  187. Xarchive process considerably, depending on the number of files.
  188. X.SH FILES
  189. XTemp files ._temp_ and ._seq_ are created and delted as needed.
  190. X.SH SEE ALSO
  191. Xunshar or unshar.sh.
  192. X.SH DIAGNOSTICS
  193. XError messages for missing or unaccessable files.
  194. X.SH LIMITATIONS
  195. XDoes not chase directory names, limited to the number of names on a
  196. Xcommand line. Uses the \fIfile\fR command to determine file type, may be
  197. Xaffected by its limitations. The -D option calls the \fIdate\fR,
  198. X\fIwho\ am\ i\fR, and \fIpwd\fR commands, and will produce garbage if
  199. Xthey are not present.
  200. X.sp
  201. XRequires the \fIuudecode\fR program to unpack binary files. On some
  202. Xsystems, such as Sun, this program requires world write on the current
  203. Xdirectory.
  204. X.sp
  205. XThe first file archived may not have a name starting with a hyphen, and
  206. Xif the file type is being set manually (-p) no file may be named
  207. X\fB-t\fR or \fB-b\fR. Option parsing should be done with getopt.
  208. X.SH AUTHOR
  209. XBill Davidsen, (davidsen@sixhub.uucp).
  210. X.SH COPYRIGHT
  211. XCopyright 1988 by Bill Davidsen. This program and documentation may be
  212. Xused by any person for any purpose.
  213. SHAR_EOF
  214. chmod 0666 shar2.1 || echo "restore of shar2.1 fails"
  215. set `wc -c shar2.1`;Sum=$1
  216. if test "$Sum" != "3932"
  217. then echo original size 3932, current size $Sum;fi
  218. echo "x - extracting unshar.1 (Text)"
  219. sed 's/^X//' << 'SHAR_EOF' > unshar.1 &&
  220. X'\" xxx
  221. X.TH UNSHAR 1 local
  222. X'\" Heading: name(sect)    center (paren)    name(sect)
  223. X.SH NAME
  224. Xunshar - unpack a shar file
  225. X.SH SYNOPSIS
  226. Xunshar file [ file [ file ] ]
  227. X.SH DESCRIPTION
  228. Xunshar scans mail messages looking for the start of a shell archive. It
  229. Xthen passes the archive through a copy of the shell to unpack it. It
  230. Xwill accept multiple files.
  231. X.SH EXAMPLES
  232. X  unshar msg4
  233. X  unshar msg4.*
  234. X.SH WARNINGS
  235. XIf a line in the introduction starts with a ':' or '#' unshar will
  236. Xbecome confused.
  237. X.SH FILES
  238. X.SH SEE ALSO
  239. Xshar, shar2.
  240. X.SH DIAGNOSTICS
  241. XAny message from the shell may be displayed.
  242. X.SH LIMITATIONS
  243. XProblems will occur if the shar file does not end with an exit command. 
  244. X.SH AUTHOR
  245. XBill Davidsen (davidsen@sixhub)
  246. X.SH COPYRIGHT
  247. XCopyright 1988 by Bill Davidsen. This program may be used by any person
  248. Xfor any purpose.
  249. SHAR_EOF
  250. chmod 0666 unshar.1 || echo "restore of unshar.1 fails"
  251. set `wc -c unshar.1`;Sum=$1
  252. if test "$Sum" != "820"
  253. then echo original size 820, current size $Sum;fi
  254. echo "x - extracting shar2.c (Text)"
  255. sed 's/^X//' << 'SHAR_EOF' > shar2.c &&
  256. X/*
  257. X** cshar.c
  258. X*/
  259. X
  260. X#ifndef lint
  261. X#ifdef RCSIDENT
  262. Xstatic char *rcsid[] =
  263. X{
  264. X    "$Header: shar.c,v 1.3 84/12/09 19:38:53 thompson Exp $",
  265. X    "$Locker:  $"
  266. X};
  267. X#endif RCSIDENT
  268. X#endif lint
  269. X#include <stdio.h>
  270. X#include <sys/types.h>
  271. X#include <sys/stat.h>
  272. X
  273. X/*
  274. X Shar puts readable text files together in a package
  275. Xfrom which they are easy to extract.  The original version
  276. Xwas a shell script posted to the net, shown below:
  277. X    #Date: Mon Oct 18 11:08:34 1982
  278. X    #From: decvax!microsof!uw-beave!jim (James Gosling at CMU)
  279. X    AR=$1
  280. X    shift
  281. X    for i do
  282. X        echo a - $i
  283. X        echo "echo x - $i" >>$AR
  284. X        echo "cat >$i <<'!Funky!Stuff!'" >>$AR
  285. X        cat $i >>$AR
  286. X        echo "!Funky!Stuff!" >>$AR
  287. X    done
  288. XI rewrote this version in C to provide better diagnostics
  289. Xand to run faster.  The main difference is that my version
  290. Xdoes not affect any files because it prints to the standard
  291. Xoutput.  Mine also has a -v (verbose) option.
  292. X*/
  293. X/*
  294. X *    I have made several mods to this program:
  295. X *
  296. X *    1) the -----Cut Here-----... now preceds the script.
  297. X *    2) the cat has been changed to a sed which removes a prefix
  298. X *    character from the beginning of each line of the extracted
  299. X *    file, this prefix character is added to each line of the archived
  300. X *    files and is not the same as the first character of the
  301. X *    file delimeter.
  302. X *    3) added several options:
  303. X *        -c    - add the -----Cut Here-----... line.
  304. X *        -d'del' - change the file delimeter to del.
  305. X *        -s    - cause the resulting script to print the sum of
  306. X *              the orignal file and the sum of the extracted
  307. X *              file.
  308. X *
  309. X *                Michael A. Thompson
  310. X *                Dalhousie University
  311. X *                Halifax, N.S., Canada.
  312. X */
  313. X
  314. X/*
  315. X *    I, too, have been hacking this code. This is the version on sixhub
  316. X *        bill davidsen (davidsen@sixhub.uucp)
  317. X *
  318. X *    - added support for binary files
  319. X *    - automatic creation of limited size multiple file archives,
  320. X *      each of which may be unpacked separately, and with sequence
  321. X *      checking.
  322. X *    - support for mixed text and binary files
  323. X *    - preserve file permissions
  324. X *    - restore to filename rather than pathname
  325. X *
  326. X */
  327. X
  328. Xstatic char *SCCSid =
  329. X             "@(#)cshar, sixhub version 1.22, last change 5/2/88";
  330. X
  331. X#define    DELIM           "SHAR_EOF"/* put after each file */
  332. X#define PREFIX1            'X'    /* goes infront of each line */
  333. X#define PREFIX2        'Y'    /* goes infront of each line if Delim
  334. X                   starts with PREFIX1 */
  335. X#define PREFIX        (Delim[0] == PREFIX1 ? PREFIX2 : PREFIX1)
  336. X#define    SHAR            "shar"    /* the name of this program */
  337. X#define    READ_PERMISSION 4    /* access permission */
  338. X#define SUM            "wc -c"
  339. X
  340. Xint  Verbose = 0;        /* option to provide append/extract
  341. X                   feedback */
  342. Xint  Sum = 0;            /* option to provide sum checking */
  343. Xchar *Delim = DELIM;        /* pointer to delimiter string */
  344. Xint  Cut = 0;            /* option to provide cut mark */
  345. Xint  Binary = 0;        /* flag for binary files */
  346. Xint  Mixed = 0;            /* mixed text and binary files */
  347. Xint  Detail = 0;        /* extra detail in shar header */
  348. Xint  eXists = 0;        /* check if file exists */
  349. Xint  PosParam = 0;        /* allow positional parameters */
  350. Xint  FileStrip;            /* strip directories from filenames */
  351. X#ifdef    DEBUG
  352. Xint de_bug = 0;            /* switch for debugging on */
  353. X#define DeBug(f,v) if (de_bug) printf(f, v)
  354. X#else    /* normal compile */
  355. X#define DeBug(f,v)        /* do nothing */
  356. X#endif
  357. X
  358. XFILE *popen ();
  359. XFILE *outfile = stdout, *fopen ();
  360. Xchar *Rname();            /* file restore name */
  361. Xunsigned  limit = 0;
  362. Xlong  ftell ();
  363. Xlong  TypePos;            /* position for archive type message */
  364. Xchar  outname[50],        /* base for output filename */
  365. X      filename[50];        /* actual output filename */
  366. Xint  filenum = 0;        /* output file # */
  367. Xstruct stat  filestat;        /* check file type, access */
  368. X
  369. Xmain (argc, argv)
  370. X    char **argv;
  371. X{
  372. X    int  status = 0;
  373. X    char *oname;
  374. X
  375. X    while (argv[1][0] == '-')
  376. X    {
  377. X    switch (argv[1][1])
  378. X    {
  379. X    case 'v': 
  380. X        Verbose = 1;
  381. X        break;
  382. X    case 's': 
  383. X        Sum = 1;
  384. X        break;
  385. X    case 'D': /* add detail */
  386. X        Detail = 1;
  387. X        break;
  388. X    case 'd': 
  389. X        if (argv[1][2])
  390. X        Delim = &argv[1][2];
  391. X        break;
  392. X    case 'b': /* binary files */
  393. X        Binary = 1;
  394. X        break;
  395. X    case 't': /* text mode */
  396. X        Binary = 0;
  397. X        break;
  398. X    case 'x': /* does the file exist */
  399. X        eXists = 1;
  400. X        if (limit) exit_incompat();
  401. X        break;
  402. X    case 'c': 
  403. X        Cut = 1;
  404. X        break;
  405. X    case 'f': /* filenames only */
  406. X        FileStrip = 1;
  407. X        break;
  408. X    case 'M': /* mixed text and binary */
  409. X        Mixed = 1;
  410. X        break;
  411. X    case 'p': /* allow positional parameters */
  412. X        PosParam = 1;
  413. X        break;
  414. X    case 'l': /* size limit in k */
  415. X        limit = atoi (argv[1] + 2) - 1;
  416. X        if (eXists) exit_incompat();
  417. X        DeBug("Limit %dk\n", limit);
  418. X        break;
  419. X    case 'o': /* specify output file */
  420. X        if (argv[1][2])
  421. X        oname = &argv[1][2];
  422. X        else
  423. X        { /* use the next arg */
  424. X        if (argc > 1 && argv[2][0] != '-')
  425. X        { /* if the next one isn't an option */
  426. X            oname = argv[2];
  427. X            argc--;
  428. X            argv++;
  429. X        }
  430. X        else
  431. X        { /* format error in the -o option */
  432. X            fprintf (stderr, "Format error in -o option\n");
  433. X            exit (1);
  434. X        }
  435. X        }
  436. X        strcpy (outname, oname);
  437. X        filenum = 1;
  438. X        sprintf (filename, "%s01", outname);
  439. X        outfile = fopen (filename, "w");
  440. X        if (outfile == NULL)
  441. X        { /* creation error */
  442. X        perror ("can't create output file");
  443. X        exit (1);
  444. X        }
  445. X        break;
  446. X#ifdef    DEBUG
  447. X    case '$': /* totally undocumented $ option, debug on */
  448. X        de_bug = 1;
  449. X        break;
  450. X#endif
  451. X    default: /* invalid option */
  452. X        fprintf (stderr, "%s: invalid argument: %s\n", SHAR, argv[1]);
  453. X    case 'h': /* help */
  454. X        helpuser ();
  455. X        break;
  456. X    }
  457. X    argc--;
  458. X    argv++;
  459. X    }
  460. X    if (argc == 1)
  461. X    {
  462. X    fprintf (stderr, "%s: No input files\n", SHAR);
  463. X    helpuser ();
  464. X    exit (1);
  465. X    }
  466. X    if (header (argc, argv))
  467. X    exit (2);
  468. X    while (--argc)
  469. X    { /* process positional parameters and files */
  470. X    argv++;
  471. X    if (PosParam)
  472. X    { /* allow -b and -t inline */
  473. X        if (strcmp (*argv, "-b") == 0)
  474. X        { /* set binary */
  475. X        Binary = 1;
  476. X        continue;
  477. X        }
  478. X        if (strcmp (*argv, "-t") == 0)
  479. X        { /* set mode text */
  480. X        Binary = 0;
  481. X        continue;
  482. X        }
  483. X    }
  484. X    status += shar (*argv);
  485. X    }
  486. X
  487. X /* delete the sequence file, if any */
  488. X    if (limit && filenum > 1)
  489. X    {
  490. X    fputs ("rm -f s2_seq_.tmp\n", outfile);
  491. X    fputs ("echo \"You have unpacked the last part\"\n", outfile);
  492. X    if (!Verbose)
  493. X        fprintf (stderr, "Created %d files\n", filenum);
  494. X    }
  495. X    fputs ("exit 0\n", outfile);
  496. X    exit (status);
  497. X}
  498. X
  499. Xheader (argc, argv)
  500. X    char **argv;
  501. X{
  502. X    int  i;
  503. X    int  status;
  504. X    FILE *ptemp;        /* pipe temp */
  505. X
  506. X /* see if any conflicting options */
  507. X    if (limit && !filenum)
  508. X    { /* can't rename what you don't have */
  509. X    fprintf (stderr, "Can't use -l option without -o\n");
  510. X    helpuser ();
  511. X    }
  512. X
  513. X    for (i = 1; i < argc; i++)
  514. X    { /* skip positional parameters */
  515. X    if (PosParam && (strcmp (argv[i], "-b") == 0 ||
  516. X            strcmp (argv[i], "-t") == 0))
  517. X        continue;
  518. X
  519. X    /* see if access and correct type */
  520. X    if (access (argv[i], READ_PERMISSION))
  521. X    {
  522. X        fprintf (stderr, "%s: Can't access %s\n", SHAR, argv[i]);
  523. X        return 1;
  524. X    }
  525. X
  526. X    /* get file type */
  527. X    stat (argv[i], &filestat);
  528. X    status = filestat.st_mode & S_IFMT;
  529. X
  530. X    /* at this point I check to see that this is a regular file */
  531. X    if (status != S_IFREG)
  532. X    { /* this is not a regular file */
  533. X        fprintf (stderr, "%s: %s is not a file\n", SHAR, argv[i]);
  534. X        return 1;
  535. X    }
  536. X    }
  537. X
  538. X    if (Cut)
  539. X    fputs ("---- Cut Here and unpack ----\n", outfile);
  540. X    fputs ("#!/bin/sh\n", outfile);
  541. X    fprintf (outfile, "# %s:    Shell Archiver  (v1.22)\n", SHAR);
  542. X    if (Detail)
  543. X    {
  544. X    char  dateout[50],    /* pipe output, who */
  545. X          whoout[50];    /* and who am i */
  546. X
  547. X    ptemp = popen ("date; who am i; pwd", "r");
  548. X    fgets (dateout, 50, ptemp);
  549. X    dateout[strlen (dateout) - 1] = 0;
  550. X    fscanf (ptemp, "%s", whoout);
  551. X    fprintf (outfile, "#\tPacked %s by %s\n", dateout, whoout);
  552. X    while (getc (ptemp) != '\n');
  553. X    fgets (dateout, 50, ptemp);
  554. X    fprintf (outfile, "#\tfrom directory %s", dateout);
  555. X
  556. X    pclose (ptemp);
  557. X    }
  558. X
  559. X    if (limit)
  560. X    { /* may be split, explain */
  561. X        fprintf(outfile, "#\n");
  562. X        TypePos = ftell(outfile);
  563. X    fprintf (outfile, "%-75s\n%-75s\n", "#", "#");
  564. X    }
  565. X
  566. X    fputs ("#\n#\tRun the following text with /bin/sh to create:\n", outfile);
  567. X    for (i = 1; i < argc; i++)
  568. X    { /* output names of files but not parameters */
  569. X    if (PosParam && (strcmp (argv[i], "-b") == 0 ||
  570. X            strcmp (argv[i], "-t") == 0))
  571. X        continue;
  572. X    fprintf (outfile, "#\t  %s\n", Rname(argv[i]));
  573. X    }
  574. X    fputs ("#\n", outfile);
  575. X
  576. X    if (limit)
  577. X    { /* now check the sequence */
  578. X    fprintf (outfile, "%s%s%s%s",
  579. X        "if test -r s2_seq_.tmp\n",
  580. X        "then echo \"Must unpack archives in sequence!\"\n",
  581. X        "     next=`cat s2_seq_.tmp`; echo \"Please unpack part $next next\"\n",
  582. X        "     exit 1; fi\n");
  583. X    }
  584. X    return (0);
  585. X}
  586. X
  587. Xshar (file)
  588. X    char *file;
  589. X{
  590. X    char  line[BUFSIZ];
  591. X    FILE *ioptr, *fdopen ();
  592. X    long  cursize, remaining, ftell ();
  593. X    int  split = 0;        /* file split flag */
  594. X    char *filetype;        /* text or binary */
  595. X    char *RstrName;        /* name for restore */
  596. X
  597. X /* if limit set, get the current output length */
  598. X    if (limit)
  599. X    {
  600. X    cursize = ftell (outfile);
  601. X    remaining = (limit * 1024L) - cursize;
  602. X    DeBug("In shar: remaining size %ld\n", remaining);
  603. X    }
  604. X
  605. X /* determine the name to use for restore */
  606. X    RstrName = Rname(file);
  607. X
  608. X /* if mixed, determine the file type */
  609. X    if (Mixed)
  610. X    {
  611. X    int  count;
  612. X    sprintf (line, "file %s | egrep -c \"text|shell\"", file);
  613. X    ioptr = popen (line, "r");
  614. X    fscanf (ioptr, "%d", &count);
  615. X    pclose (ioptr);
  616. X    Binary = (count != 1);
  617. X    }
  618. X
  619. X    if (Binary)
  620. X    { /* fork a uuencode process */
  621. X    static int  pid, pipex[2];
  622. X
  623. X    pipe (pipex);
  624. X    fflush (outfile);
  625. X
  626. X    if (pid = fork ())
  627. X    { /* parent, create a file to read */
  628. X        close (pipex[1]);
  629. X        ioptr = fdopen (pipex[0], "r");
  630. X    }
  631. X    else
  632. X    { /* start writing the pipe with encodes */
  633. X        FILE *outptr;
  634. X
  635. X        ioptr = fopen (file, "rb");
  636. X        outptr = fdopen (pipex[1], "w");
  637. X        fprintf (outptr, "begin 600 %s\n", RstrName);
  638. X        encode (ioptr, outptr);
  639. X        fprintf (outptr, "end\n");
  640. X        exit (0);
  641. X    }
  642. X    filetype = "Binary";
  643. X    }
  644. X    else
  645. X    {
  646. X    ioptr = fopen (file, "r");
  647. X    filetype = "Text";
  648. X    }
  649. X
  650. X    if (ioptr != NULL)
  651. X    {
  652. X    /* protect existing files */
  653. X    if (eXists)
  654. X        fprintf (outfile,
  655. X            "if test -f %s; then echo \"File %s exists\"; else\n",
  656. X            RstrName, RstrName);
  657. X
  658. X    if (Verbose)
  659. X    { /* info on archive and unpack */
  660. X        fprintf (stderr, "%s: saving %s (%s)\n",
  661. X            SHAR, file, filetype);
  662. X        fprintf (outfile, "echo \"x - extracting %s (%s)\"\n",
  663. X            RstrName, filetype);
  664. X    }
  665. X    if (Binary)
  666. X    { /* run sed through uudecode via temp file */
  667. X        fprintf (outfile, "sed 's/^%c//' << '%s' > s2_temp_.tmp &&\n",
  668. X            PREFIX, Delim);
  669. X    }
  670. X    else
  671. X    { /* just run it into the file */
  672. X        fprintf (outfile, "sed 's/^%c//' << '%s' > %s &&\n",
  673. X            PREFIX, Delim, RstrName);
  674. X    }
  675. X    while (fgets (line, BUFSIZ, ioptr))
  676. X    { /* output a line and test the length */
  677. X        fprintf (outfile, "%c%s", PREFIX, line);
  678. X        if (limit && (remaining -= strlen (line) + 2) < 0)
  679. X        { /* change to another file */
  680. X        DeBug("Newfile, remaining %ld, ", remaining);
  681. X        DeBug("limit still %d\n", limit);
  682. X        fprintf (outfile, "%s\n", Delim);
  683. X        if (Verbose)
  684. X        { /* output some reassurance */
  685. X            fprintf (outfile,
  686. X                "echo \"End of part %d\"\n", filenum);
  687. X            fprintf (outfile,
  688. X                "echo \"File %s is continued in part %d\"\n",
  689. X                RstrName, filenum + 1);
  690. X        }
  691. X        else
  692. X            fprintf (outfile,
  693. X                "echo \"End of part %d, continue with part %d\"\n",
  694. X                filenum, filenum + 1);
  695. X        fprintf (outfile, "echo \"%d\" > s2_seq_.tmp\n", filenum + 1);
  696. X        fprintf (outfile, "exit 0\n");
  697. X
  698. X            if (filenum == 1)
  699. X        { /* rewrite the info lines on the firstheader */
  700. X            fseek(outfile, TypePos, 0);
  701. X            fprintf (outfile, "%-75s\n%-75s\n",
  702. X                "# This is part 1 of a multipart archive",
  703. X            "# do not concatenate these parts, unpack them in order with /bin/sh");
  704. X        }
  705. X        fclose (outfile);
  706. X
  707. X        /* form the next filename */
  708. X        sprintf (filename, "%s%02d", outname, ++filenum);
  709. X        outfile = fopen (filename, "w");
  710. X        if (Cut)
  711. X            fputs ("---- Cut Here and unpack ----\n", outfile);
  712. X        fprintf (outfile, "#!/bin/sh\n");
  713. X        fprintf (outfile,
  714. X            "# this is part %d of a multipart archive\n%s%s",
  715. X            filenum, "# do not concatenate these parts, ",
  716. X            "unpack them in order with /bin/sh\n");
  717. X        fprintf (outfile, "# file %s continued\n#\n", RstrName);
  718. X        fprintf (outfile, "CurArch=%d\n", filenum);
  719. X        fprintf (outfile, "%s%s%s%s%s%s%s%s%s",
  720. X            "if test ! -r s2_seq_.tmp\n",
  721. X            "then echo \"Please unpack part 1 first!\"\n",
  722. X            "     exit 1; fi\n",
  723. X            "( read Scheck\n",
  724. X            "  if test \"$Scheck\" != $CurArch\n",
  725. X            "  then echo \"Please unpack part $Scheck next!\"\n",
  726. X            "       exit 1;\n",
  727. X            "  else exit 0; fi\n",
  728. X            ") < s2_seq_.tmp || exit 1\n");
  729. X
  730. X        if (Verbose)
  731. X        { /* keep everybody informed */
  732. X            fprintf (stderr, "Starting file %s\n", filename);
  733. X            fprintf (outfile,
  734. X                "echo \"x - Continuing file %s\"\n", RstrName);
  735. X        }
  736. X        fprintf (outfile,
  737. X            "sed 's/^%c//' << '%s' >> %s\n",
  738. X            PREFIX, Delim, (Binary ? "s2_temp_.tmp" : RstrName));
  739. X        remaining = limit * 1024L;
  740. X        split = 1;
  741. X        }
  742. X    }
  743. X
  744. X    (void) fclose (ioptr);
  745. X    fprintf (outfile, "%s\n", Delim);
  746. X    if (split && Verbose)
  747. X        fprintf (outfile,
  748. X            "echo \"File %s is complete\"\n", RstrName);
  749. X
  750. X    /* if this file was uuencoded, decode it and drop the temp */
  751. X    if (Binary)
  752. X    {
  753. X        if (Verbose)
  754. X        fprintf (outfile, "echo \"uudecoding file %s\"\n", RstrName);
  755. X        fprintf (outfile,
  756. X                "uudecode < s2_temp_.tmp && rm -f s2_temp_.tmp &&\n");
  757. X    }
  758. X
  759. X    /* set the permissions as they were */
  760. X    stat (file, &filestat);
  761. X    fprintf (outfile,
  762. X        "chmod %04o %s || echo \"restore of %s fails\"\n",
  763. X        filestat.st_mode & 07777, RstrName, RstrName);
  764. X
  765. X    if (Sum)
  766. X    { /* validate the transferred file */
  767. X        FILE *pfp;
  768. X        char  command[BUFSIZ];
  769. X
  770. X        sprintf (command, "%s %s", SUM, file);
  771. X        if ((pfp = popen (command, "r")))
  772. X        {
  773. X        char  sum[BUFSIZ];
  774. X
  775. X        fscanf (pfp, "%s", sum);
  776. X        fprintf (outfile, "set `%s %s`;Sum=$1\n",
  777. X            SUM, RstrName);
  778. X        fprintf (outfile,
  779. X            "if test \"$Sum\" != \"%s\"\n", sum);
  780. X        fprintf (outfile,
  781. X            "then echo original size %s, current size $Sum;fi\n",
  782. X            sum);
  783. X        pclose (pfp);
  784. X        }
  785. X    }
  786. X
  787. X    /* if the exists option is in place close the if */
  788. X    if (eXists)
  789. X        fprintf (outfile, "fi\n");
  790. X
  791. X    return (0);
  792. X    }
  793. X    else
  794. X    {
  795. X    fprintf (stderr, "%s: Can't open %s\n", SHAR, file);
  796. X    return (1);
  797. X    }
  798. X}
  799. X
  800. Xchar *Rname(file)
  801. X    register char *file;
  802. X{
  803. X    register char *RstrName;
  804. X
  805. X    if (FileStrip)
  806. X    { /* use just the filename */
  807. X        RstrName = file+strlen(file);
  808. X    while (RstrName > file && *RstrName != '/')
  809. X        RstrName--;
  810. X    if (*RstrName == '/') RstrName++;
  811. X    }
  812. X    else RstrName = file;
  813. X    return (RstrName);
  814. X}
  815. X
  816. X/*****************************************************************
  817. X |  exit_incompat - incompatible options
  818. X ****************************************************************/
  819. X
  820. Xexit_incompat()
  821. X{
  822. X    fprintf(stderr, "%s%s",
  823. X        "The -x and -l options are currently incompatible\n",
  824. X    "Please reenter the command without one option\n");
  825. X    exit(1);
  826. X}
  827. X
  828. Xhelpuser ()
  829. X{                /* output a command format message */
  830. X    register char **ptr;
  831. X    static char *helpinfo[] =
  832. X    {
  833. X    "-v\tverbose messages while executing",
  834. X    "-s\tdo checking with 'sum' after unpack",
  835. X    "-x\tdon't overwrite existing files",
  836. X    "-b\ttreat all files as binary, use uuencode",
  837. X    "-t\ttreat all files as text (default)",
  838. X    "-p\tallow positional parameter options. The options \"-b\"",
  839. X    "\tand \"-t\" may be embedded, and files to the right of the",
  840. X    "\toption will be processed in the specified mode",
  841. X    "-M\tmixed mode. Determine if the files are text or",
  842. X    "\tbinary and archive correctly.",
  843. X    "-D\toutput date, user, and directory comments to the archive",
  844. X    "-c\tstart the shar with 'cut here'",
  845. X    "-f\trestore by filename only, rather than path",
  846. X    "-dXXX\tuse XXX to delimit the files in the shar",
  847. X    "-oXXX\t(or -o XXX) output to file XXX01 thru XXXnn",
  848. X    "-lXX\tlimit output file size to XXk bytes",
  849. X    "\nThe 'o' option is required if the 'l' option is used",
  850. X    NULL
  851. X    };
  852. X    fprintf (stderr,
  853. X        "\nFormat:\n  %s [ options ] file [ file1 ... ] ]\n",
  854. X        SHAR);
  855. X    for (ptr = helpinfo; *ptr; ptr++)
  856. X    fprintf (stderr, "%s\n", *ptr);
  857. X
  858. X    exit (1);
  859. X}
  860. SHAR_EOF
  861. chmod 0444 shar2.c || echo "restore of shar2.c fails"
  862. set `wc -c shar2.c`;Sum=$1
  863. if test "$Sum" != "16149"
  864. then echo original size 16149, current size $Sum;fi
  865. echo "x - extracting uushar.c (Text)"
  866. sed 's/^X//' << 'SHAR_EOF' > uushar.c &&
  867. X#include <stdio.h>
  868. X#include <sys/types.h>
  869. X#include <sys/stat.h>
  870. X
  871. X/* ENC is the basic 1 character encoding function to make a char printing */
  872. X#define ENC(c) ((((c) & 077) + ' ') | ((c & 077) == 0 ? 0100 : 0))
  873. X
  874. Xencode (in, out)
  875. X    FILE *in;
  876. X    FILE *out;
  877. X{
  878. X    char  buf[80];
  879. X    int  i, n;
  880. X
  881. X    for (;;)
  882. X    {
  883. X    /* 1 (up to) 45 character line */
  884. X    n = fr (in, buf, 45);
  885. X    putc (ENC (n), out);
  886. X
  887. X    for (i = 0; i < n; i += 3)
  888. X        outdec (&buf[i], out);
  889. X
  890. X    putc ('\n', out);
  891. X    if (n <= 0)
  892. X        break;
  893. X    }
  894. X}
  895. X
  896. X/*
  897. X * output one group of 3 bytes, pointed at by p, on file f.
  898. X */
  899. Xoutdec (p, f)
  900. X    char *p;
  901. X    FILE *f;
  902. X{
  903. X    int  c1, c2, c3, c4;
  904. X
  905. X    c1 = *p >> 2;
  906. X    c2 = (*p << 4) & 060 | (p[1] >> 4) & 017;
  907. X    c3 = (p[1] << 2) & 074 | (p[2] >> 6) & 03;
  908. X    c4 = p[2] & 077;
  909. X    putc (ENC (c1), f);
  910. X    putc (ENC (c2), f);
  911. X    putc (ENC (c3), f);
  912. X    putc (ENC (c4), f);
  913. X}
  914. X
  915. X/* fr: like read but stdio */
  916. Xint
  917. X     fr (fp, buf, cnt)
  918. X    FILE *fp;
  919. X    char *buf;
  920. X    int  cnt;
  921. X{
  922. X    int  c, i;
  923. X
  924. X    for (i = 0; i < cnt; i++)
  925. X    {
  926. X    c = getc (fp);
  927. X    if (c == EOF)
  928. X        return (i);
  929. X    buf[i] = c;
  930. X    }
  931. X    return (cnt);
  932. X}
  933. SHAR_EOF
  934. chmod 0644 uushar.c || echo "restore of uushar.c fails"
  935. set `wc -c uushar.c`;Sum=$1
  936. if test "$Sum" != "1114"
  937. then echo original size 1114, current size $Sum;fi
  938. echo "x - extracting unshar.sh (Text)"
  939. sed 's/^X//' << 'SHAR_EOF' > unshar.sh &&
  940. X#!/bin/sh
  941. X#
  942. X#  unshar shell - unpack one or more shar files
  943. X#
  944. X#  Copyright 1988 bill davidsen
  945. X#    this program may be used by any person for any purpose.
  946. X
  947. Xfor Name in $*
  948. Xdo    sed -n '/^[:#]/,$p' $Name | sh
  949. Xdone
  950. SHAR_EOF
  951. chmod 0755 unshar.sh || echo "restore of unshar.sh fails"
  952. set `wc -c unshar.sh`;Sum=$1
  953. if test "$Sum" != "207"
  954. then echo original size 207, current size $Sum;fi
  955. echo "x - extracting Makefile (Text)"
  956. sed 's/^X//' << 'SHAR_EOF' > Makefile &&
  957. X#
  958. X#  makefile for shar2
  959. X#
  960. X
  961. XCFLAGS    = -O
  962. X
  963. XSRC    = shar2.c uushar.c unshar.sh
  964. XOBJ    = shar2.o uushar.o
  965. XDOC    = shar2.1 unshar.1 shar2.readme
  966. X
  967. Xall    : xshar unshar
  968. X
  969. Xxshar    : ${OBJ}
  970. X    $(CC) shar2.o uushar.o -o xshar
  971. X
  972. Xunshar    : unshar.c
  973. X    if test -f /vmunix; \
  974. X    then cc -O unshar.c -s -o unshar; \
  975. X    else cc -O -Dindex=strchr unshar.c -s -o unshar; \
  976. X    fi
  977. SHAR_EOF
  978. chmod 0644 Makefile || echo "restore of Makefile fails"
  979. set `wc -c Makefile`;Sum=$1
  980. if test "$Sum" != "336"
  981. then echo original size 336, current size $Sum;fi
  982. echo "x - extracting unshar.c (Text)"
  983. sed 's/^X//' << 'SHAR_EOF' > unshar.c &&
  984. X/****************************************************************
  985. X * unshar.c: Unpackage one or more shell archive files
  986. X *
  987. X * Usage:    unshar [ -d directory ] [ file ] ...
  988. X *
  989. X * Description:    unshar is a filter which removes the front part
  990. X *        of a file and passes the rest to the 'sh' command.
  991. X *        It understands phrases like "cut here", and also
  992. X *        knows about shell comment characters and the Unix
  993. X *        commands "echo", "cat", and "sed".
  994. X *
  995. X * HISTORY
  996. X *  1-Feb-85  Guido van Rossum (guido@mcvax) at CWI, Amsterdam
  997. X *    Added missing 'quit' routine;
  998. X *    added -d flag to change to directory first;
  999. X *    added filter mode (read stdin when no arguments);
  1000. X *    added 'getopt' to get flags (makes it self-contained).
  1001. X * 29-Jan-85  Michael Mauldin (mlm) at Carnegie-Mellon University
  1002. X *    Created.
  1003. X ****************************************************************/
  1004. X
  1005. X# include <stdio.h>
  1006. X# define EOL '\n'
  1007. X
  1008. Xextern char *optarg;
  1009. Xextern int optind;
  1010. X
  1011. Xmain (argc, argv)
  1012. Xint argc;
  1013. Xchar *argv[];
  1014. X{ int i, ch;
  1015. X  FILE *in;
  1016. X
  1017. X  /* Process options */
  1018. X
  1019. X  while ((ch = getopt (argc, argv, "d:")) != EOF) {
  1020. X    switch (ch) {
  1021. X    case 'd':
  1022. X      if (chdir (optarg) == -1) {
  1023. X    fprintf (stderr, "unshar: cannot chdir to '%s'\n", optarg);
  1024. X    exit(2);
  1025. X      }
  1026. X      break;
  1027. X    default:
  1028. X      quit (2, "Usage: unshar [-d directory] [file] ...\n");
  1029. X    }
  1030. X  }
  1031. X
  1032. X  if (optind < argc)
  1033. X  { for (i= optind; i < argc; ++i)
  1034. X    { if ((in = fopen (argv[i], "r")) == NULL)
  1035. X      { fprintf (stderr, "unshar: file '%s' not found\n", argv[i]);
  1036. X        exit (1);
  1037. X      }
  1038. X      process (argv[i], in);
  1039. X      fclose (in);
  1040. X    }
  1041. X  }
  1042. X  else
  1043. X    process ("standard input", stdin);
  1044. X
  1045. X  exit (0);
  1046. X}
  1047. X
  1048. X
  1049. Xprocess (name, in)
  1050. Xchar *name;
  1051. XFILE *in;
  1052. X{ char ch;
  1053. X  FILE *shpr, *popen();
  1054. X
  1055. X   if (position (name, in))
  1056. X    { printf ("%s:\n", name);
  1057. X      if ((shpr = popen ("sh", "w")) == NULL)
  1058. X    quit (1, "unshar: cannot open 'sh' process\n");
  1059. X
  1060. X    while ((ch = fgetc (in)) != EOF)
  1061. X      fputc (ch, shpr);
  1062. X
  1063. X    pclose (shpr);
  1064. X    }
  1065. X}
  1066. X
  1067. X/****************************************************************
  1068. X * position: position 'fil' at the start of the shell command
  1069. X * portion of a shell archive file.
  1070. X ****************************************************************/
  1071. X
  1072. Xposition (fn, fil)
  1073. Xchar *fn;
  1074. XFILE *fil;
  1075. X{ char buf[BUFSIZ];
  1076. X  long pos, ftell ();
  1077. X
  1078. X  /* Results from star matcher */
  1079. X  static char res1[BUFSIZ], res2[BUFSIZ], res3[BUFSIZ], res4[BUFSIZ];
  1080. X  static char *result[] = { res1, res2, res3, res4 };
  1081. X
  1082. X  rewind (fil);
  1083. X
  1084. X  while (1)
  1085. X  { /* Record position of the start of this line */
  1086. X    pos = ftell (fil);
  1087. X
  1088. X    /* Read next line, fail if no more */
  1089. X    if (fgets (buf, BUFSIZ, fil) == NULL)
  1090. X    { fprintf (stderr, "unshar: found no shell commands in %s\n", fn);
  1091. X      return (0);
  1092. X    }
  1093. X
  1094. X    /* Bail out if we see C preprocessor commands or C comments */
  1095. X    if (stlmatch (buf, "#include")    || stlmatch (buf, "# include") ||
  1096. X    stlmatch (buf, "#define")    || stlmatch (buf, "# define") ||
  1097. X    stlmatch (buf, "#ifdef")    || stlmatch (buf, "# ifdef") ||
  1098. X    stlmatch (buf, "#ifndef")    || stlmatch (buf, "# ifndef") ||
  1099. X    stlmatch (buf, "/*"))
  1100. X    { fprintf (stderr,
  1101. X           "unshar: %s looks like raw C code, not a shell archive\n", fn);
  1102. X      return (0);
  1103. X    }
  1104. X
  1105. X    /* Does this line start with a shell command or comment */
  1106. X    if (stlmatch (buf, "#")    || stlmatch (buf, ":") ||
  1107. X    stlmatch (buf, "echo ")    || stlmatch (buf, "sed ") ||
  1108. X    stlmatch (buf, "cat "))
  1109. X    { fseek (fil, pos, 0); return (1); }
  1110. X
  1111. X    /* Does this line say "Cut here" */
  1112. X    if (smatch (buf, "*CUT*HERE*", result) ||
  1113. X    smatch (buf, "*cut*here*", result) ||
  1114. X    smatch (buf, "*TEAR*HERE*", result) ||
  1115. X    smatch (buf, "*tear*here*", result) ||
  1116. X    smatch (buf, "*CUT*CUT*", result) ||
  1117. X    smatch (buf, "*cut*cut*", result))
  1118. X    {
  1119. X      /* Read next line after "cut here", skipping blank lines */
  1120. X      while (1)
  1121. X      { pos = ftell (fil);
  1122. X
  1123. X        if (fgets (buf, BUFSIZ, fil) == NULL)
  1124. X    { fprintf (stderr,
  1125. X        "unshar: found no shell commands after 'cut' in %s\n", fn);
  1126. X      return (0);
  1127. X    }
  1128. X    
  1129. X    if (*buf != '\n') break;
  1130. X      }
  1131. X
  1132. X      /* Win if line starts with a comment character of lower case letter */
  1133. X      if (*buf == '#' || *buf == ':' || (('a' <= *buf) && ('z' >= *buf)))
  1134. X      { fseek (fil, pos, 0);
  1135. X    return (1);
  1136. X      }
  1137. X
  1138. X      /* Cut here message lied to us */      
  1139. X      fprintf (stderr, "unshar: %s is probably not a shell archive,\n", fn);
  1140. X      fprintf (stderr, "        the 'cut' line was followed by: %s", buf);
  1141. X      return (0);
  1142. X    }
  1143. X  }
  1144. X}
  1145. X
  1146. X/*****************************************************************
  1147. X * stlmatch  --  match leftmost part of string
  1148. X *
  1149. X * Usage:  i = stlmatch (big,small)
  1150. X *    int i;
  1151. X *    char *small, *big;
  1152. X *
  1153. X * Returns 1 iff initial characters of big match small exactly;
  1154. X * else 0.
  1155. X *
  1156. X * HISTORY
  1157. X * 18-May-82 Michael Mauldin (mlm) at Carnegie-Mellon University
  1158. X *      Ripped out of CMU lib for Rog-O-Matic portability
  1159. X * 20-Nov-79  Steven Shafer (sas) at Carnegie-Mellon University
  1160. X *    Rewritten for VAX from Ken Greer's routine.
  1161. X *
  1162. X *  Originally from klg (Ken Greer) on IUS/SUS UNIX
  1163. X *****************************************************************/
  1164. X
  1165. Xint   stlmatch (big, small)
  1166. Xchar *small, *big;
  1167. X{ register char *s, *b;
  1168. X  s = small;
  1169. X  b = big;
  1170. X  do
  1171. X  { if (*s == '\0')
  1172. X      return (1);
  1173. X  }
  1174. X  while (*s++ == *b++);
  1175. X  return (0);
  1176. X}
  1177. X
  1178. X/*****************************************************************
  1179. X * smatch: Given a data string and a pattern containing one or
  1180. X * more embedded stars (*) (which match any number of characters)
  1181. X * return true if the match succeeds, and set res[i] to the
  1182. X * characters matched by the 'i'th *.
  1183. X *****************************************************************/
  1184. X
  1185. Xsmatch (dat, pat, res)
  1186. Xregister char *dat, *pat, **res;
  1187. X{ register char *star = 0, *starend, *resp;
  1188. X  int nres = 0;
  1189. X
  1190. X  while (1)
  1191. X  { if (*pat == '*')
  1192. X    { star = ++pat;                  /* Pattern after * */
  1193. X      starend = dat;                  /* Data after * match */
  1194. X      resp = res[nres++];              /* Result string */
  1195. X      *resp = '\0';                  /* Initially null */
  1196. X    }
  1197. X    else if (*dat == *pat)              /* Characters match */
  1198. X    { if (*pat == '\0')              /* Pattern matches */
  1199. X    return (1);
  1200. X      pat++;                      /* Try next position */
  1201. X      dat++;
  1202. X    }
  1203. X    else
  1204. X    { if (*dat == '\0')              /* Pattern fails - no more */
  1205. X    return (0);                  /* data */
  1206. X      if (star == 0)                  /* Pattern fails - no * to */
  1207. X    return (0);                  /* adjust */
  1208. X      pat = star;                  /* Restart pattern after * */
  1209. X      *resp++ = *starend;              /* Copy character to result */
  1210. X      *resp = '\0';                  /* null terminate */
  1211. X      dat = ++starend;                  /* Rescan after copied char */
  1212. X    }
  1213. X  }
  1214. X}
  1215. X
  1216. X/*****************************************************************
  1217. X * Addendum: quit subroutine (print a message and exit)
  1218. X *****************************************************************/
  1219. X
  1220. Xquit (status, message)
  1221. Xint status;
  1222. Xchar *message;
  1223. X{
  1224. X  fprintf(stderr, message);
  1225. X  exit(status);
  1226. X}
  1227. X
  1228. X/*****************************************************************
  1229. X * Public Domain getopt routine
  1230. X *****************************************************************/
  1231. X
  1232. X/*
  1233. X * get option letter from argument vector
  1234. X */
  1235. Xint    opterr = 1,        /* useless, never set or used */
  1236. X    optind = 1,        /* index into parent argv vector */
  1237. X    optopt;            /* character checked for validity */
  1238. Xchar    *optarg;        /* argument associated with option */
  1239. X
  1240. X#define BADCH    (int)'?'
  1241. X#define EMSG    ""
  1242. X#define tell(s)    fputs(*nargv,stderr);fputs(s,stderr); \
  1243. X        fputc(optopt,stderr);fputc('\n',stderr);return(BADCH);
  1244. X
  1245. Xgetopt(nargc,nargv,ostr)
  1246. Xint    nargc;
  1247. Xchar    **nargv,
  1248. X    *ostr;
  1249. X{
  1250. X    static char    *place = EMSG;    /* option letter processing */
  1251. X    register char    *oli;        /* option letter list index */
  1252. X    char    *index();
  1253. X
  1254. X    if(!*place) {            /* update scanning pointer */
  1255. X        if(optind >= nargc || *(place = nargv[optind]) != '-' || !*++place) return(EOF);
  1256. X        if (*place == '-') {    /* found "--" */
  1257. X            ++optind;
  1258. X            return(EOF);
  1259. X        }
  1260. X    }                /* option letter okay? */
  1261. X    if ((optopt = (int)*place++) == (int)':' || !(oli = index(ostr,optopt))) {
  1262. X        if(!*place) ++optind;
  1263. X        tell(": illegal option -- ");
  1264. X    }
  1265. X    if (*++oli != ':') {        /* don't need argument */
  1266. X        optarg = NULL;
  1267. X        if (!*place) ++optind;
  1268. X    }
  1269. X    else {                /* need an argument */
  1270. X        if (*place) optarg = place;    /* no white space */
  1271. X        else if (nargc <= ++optind) {    /* no arg */
  1272. X            place = EMSG;
  1273. X            tell(": option requires an argument -- ");
  1274. X        }
  1275. X         else optarg = nargv[optind];    /* white space */
  1276. X        place = EMSG;
  1277. X        ++optind;
  1278. X    }
  1279. X    return(optopt);            /* dump back option letter */
  1280. X}
  1281. SHAR_EOF
  1282. chmod 0644 unshar.c || echo "restore of unshar.c fails"
  1283. set `wc -c unshar.c`;Sum=$1
  1284. if test "$Sum" != "8429"
  1285. then echo original size 8429, current size $Sum;fi
  1286. exit 0
  1287.