home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk1.iso / altsrc / articles / 1000-1999 / 1153 < prev    next >
Internet Message Format  |  1990-12-27  |  48KB

  1. From: wht@n4hgf.uucp (Warren Tucker)
  2. Newsgroups: alt.sources
  3. Subject: shar 3.11
  4. Message-ID: <657@n4hgf.uucp>
  5. Date: 6 Apr 90 19:25:03 GMT
  6.  
  7. Submitted by: wht@n4hgf
  8. Archive-name: shar311/part01
  9.  
  10. #!/bin/sh
  11. # This is shar311, a shell archive (shar 3.11)
  12. # made 04/06/1990 19:13 UTC by wht@n4hgf
  13. # Source directory /u1/src/shar
  14. #
  15. # existing files WILL be overwritten
  16. #
  17. # This shar contains:
  18. # length  mode       name
  19. # ------ ---------- ------------------------------------------
  20. #   5093 -rw-r--r-- README
  21. #    333 -rw-r--r-- Makefile
  22. #  24654 -rw-r--r-- shar.c
  23. #   8440 -rw-r--r-- unshar.c
  24. #   1169 -rw-r--r-- uushar.c
  25. #   2784 -rw-r--r-- who@where.c
  26. #
  27. touch 2>&1 | fgrep '[-amc]' > /tmp/s3_touch$$
  28. if [ -s /tmp/s3_touch$$ ]
  29. then
  30.     TOUCH=can
  31. else
  32.     TOUCH=cannot
  33. fi
  34. rm -f /tmp/s3_touch$$
  35. # ============= README ==============
  36. echo "x - extracting README (Text)"
  37. sed 's/^X//' << 'SHAR_EOF' > README &&
  38. XSubmitted by: wht%n4hgf@gatech.edu
  39. XArchive-name: shar311/part01
  40. X
  41. XHere is shar311, an updated version of shar 3.10, derived from 'shar2'
  42. X
  43. XI apologize as appropriate to davidsen@sixhub for his not receiving 
  44. Xmy mail of Wed, 28 Mar 90 17:31:25 EST sending him an advance copy
  45. Xof shar310.  The mail header for this transmission to him is:
  46. X
  47. X    From wht  Fri Apr  6 15:14:30 1990 remote from n4hgf
  48. X    Received: by n4hgf.UUCP (smail2.5-UNIX/386 5.3.2)
  49. X        id AA01781; 6 Apr 90 15:14:30 EDT (Fri)
  50. X    Date: Fri, 6 Apr 90 15:14:30 EDT
  51. X    X-Mailer: Mail User's Shell (6.5 4/17/89)
  52. X    From: wht@n4hgf (Warren Tucker)
  53. X    To: davidsen@sixhub
  54. X    Subject: shar 3.11
  55. X    X-Bang-Reply-to: gatech!n4hgf!wht -or- emory!tridom!n4hgf!wht
  56. X    Reply-to: wht%n4hgf@gatech.edu
  57. X    Message-Id: <9004061514.AA01781@n4hgf.UUCP>
  58. X
  59. X  C.gatechN26ac UUCP uux file
  60. X    U wht n4hgf
  61. X    # return status on failure
  62. X    Z
  63. X    # return address for status or input return
  64. X    R wht
  65. X    F D.n4hgf54ef6e7
  66. X    I D.n4hgf54ef6e7
  67. X    C rmail mailrus!uunet!crdgw1!sixhub!davidsen 
  68. #
  69. XChanges from 3.10:
  70. X
  71. X1) A much simplified who_am_i() is used.  The function in 3.10
  72. X   was derived from code where it was important to obtain the user
  73. X   name of the login user despite su'ing, setuid, etc.  This
  74. X   is difficult to do in a portable fashion and not necessary
  75. X   for the 'shar' application.  This version of shar uses the
  76. X   username assosciated with the 'real uid'; use -s to override
  77. X   the automagically determined submitter name if necessary.
  78. X
  79. X2) The -X switch generates shell sequences in the generated shar
  80. X   code necessary to interactively query the disposition of files
  81. X   which would be overwritten if unshared.  NOTE: _PLEASE_ DO NOT,
  82. X   OH PLEASE, DO NOT use this option for shars submitted to public
  83. X   networks. 
  84. X
  85. X   When -X shars are extracted, the first time a file which would be
  86. X   overwritten is encountered, the user is given the option of
  87. X
  88. X     overwrite 'name' -- [No], [Y]es, [A]ll, [Q]uit?
  89. X     N  means no for this file, continue extraction, skipping 'file'
  90. X     Y  means yes for this file, continue extraction, including 'file'
  91. X     A  means yes for this file, continue extraction, automatically
  92. X        overwriting any additional files encountered
  93. X     Q  means quit extraction
  94. X
  95. X   Credit for this idea is given to Bill Silvert <silvert@cs.dal.ca>,
  96. X   Habitat Ecology Division, Bedford Inst. of Oceanography, Dartmouth,
  97. X   Nova Scotia, Canada
  98. X
  99. X   I repeat: NOTE _PLEASE_: DO NOT, OH PLEASE, DO NOT use this option
  100. X   for shars submitted to public networks.  The overhead for -X is high and
  101. X   its use will SCREW UP a lot of automated unshar mechanisms in use
  102. X   throughout the world when the script tries to read from standard
  103. X   input (which may not be open).  Specifically, the unshar program
  104. X   in this distrivbution is not compatible with shars created by the
  105. X   -X option.  it will die horribly with complaints about shell syntax
  106. X   errors.
  107. X
  108. X3) A bug in the sun version which caused a bogus read from standard
  109. X   input when shar was run has been fixed.  It was botched who_am_i()
  110. X   that was doing it.
  111. X
  112. X4) bugs reported and fixed (thanks!) pat@rwing (Pat Myrto):
  113. X>  One was the M option - it was defined as M in the usage
  114. X>  message, and in the switch construct, but as m in the
  115. X>  getopt() call.  I also changed the defaults for wc checking
  116. X>  and verbose extraction to be ON - the cmd line options
  117. X>  turning these OFF (since usually these are desired to be
  118. X>  on).  In who@where, in the utsname structure, looking at
  119. X>  sysname returns 'UNIX' - I think nodename is what you want
  120. X>  to get the [system's] name. ...  Also declared a
  121. X>  function that gave a compiler warning (getpwuid()).
  122. X
  123. XThis version
  124. X1) generates shell code which attempts to create missing directories
  125. X2) handle deviants sun, vax, pyramid, sequent, and SCO XENIX/UNIX
  126. X   automatically; for system V systems I did not catch, add -DSYS5
  127. X   to CFLAGS; for other BSD-like systems, add -DBSD42
  128. X3) if unsharing system's touch is Sys V compatible (allows touch -m),
  129. X   the unshar process restores file dates
  130. X4) An archive name may be specified for includion in the header
  131. X   of the shar files( -n switch)
  132. X5) allows automatic generation of "Submitted-by: who@where" &
  133. X   "Archive-name: <name>/part##" headers
  134. X6) uses getopt; no good system library should be without a copy
  135. X   but it is readily available
  136. X7) other chrome-plated junque
  137. X
  138. X------------------------ usage -----------------------------------
  139. X
  140. Xshar 3.11
  141. Xusage: shar [ options ] file [ file1 ... ] ]
  142. X-v  verbose messages OFF while executing
  143. X-w  don't check with 'wc -c' after unpack
  144. X-n  Name of archive (documentation)
  145. X-a  Generate Submitted-by: & Archive-name: headers
  146. X-s  override automatically determined submitter name
  147. X-x  don't overwrite existing files
  148. X-X  interactively overwrite existing files (NOT FOR NET SHARS)
  149. X-b  treat all files as binary, use uuencode
  150. X-t  treat all files as text (default)
  151. X-p  allow positional parameter options. The options "-b"
  152. X    and "-t" may be embedded, and files to the right of the
  153. X    option will be processed in the specified mode
  154. X-M  mixed mode. Determine if the files are text or
  155. X    binary and archive correctly.
  156. X-D  output date, user, and directory comments to the archive
  157. X-c  start the shar with a cut line
  158. X-f  restore by filename only, rather than path
  159. X-dXXX   use XXX to delimit the files in the shar
  160. X-oXXX   (or -o XXX) output to file XXX.01 thru XXX.nn
  161. X-lXX    limit output file size to XXk bytes
  162. X
  163. XThe 'o' option is required if the 'l' option is used
  164. XThe 'n' option is required if the 'a' option is used
  165. XThe 'x' and 'l' options are incompatible
  166. X
  167. X-a generates sharname/part## headers. If you are producing patches
  168. Xyou'll need to edit -a headers (or please improve shar :-))
  169. XThe automatic submitter name is trivial: essentially `whoami`@`uname`
  170. SHAR_EOF
  171. chmod 0644 README || echo "restore of README fails"
  172. if [ $TOUCH = can ]
  173. then
  174.     touch -am 0406151290 README
  175. fi
  176. # ============= Makefile ==============
  177. echo "x - extracting Makefile (Text)"
  178. sed 's/^X//' << 'SHAR_EOF' > Makefile &&
  179. X#  CHK=0xDDF8
  180. X#
  181. X#  makefile for shar
  182. X#
  183. X#+:EDITS:
  184. X#:03-28-1990-14:54-wht@n4hgf-for 3.10, add who@where.c
  185. X
  186. XCFLAGS    = -O 
  187. X
  188. XSRC    = shar.c uushar.c unshar.sh
  189. XOBJ    = shar.o uushar.o who@where.o
  190. XDOC    = shar.1 unshar.1 shar.readme
  191. X
  192. Xall: shar unshar
  193. X
  194. Xshar: $(OBJ)
  195. X    cc $(CFLAGS) $(OBJ) -o shar
  196. X
  197. Xunshar : unshar.c
  198. X    cc $(CFLAGS) unshar.c -o unshar;
  199. SHAR_EOF
  200. chmod 0644 Makefile || echo "restore of Makefile fails"
  201. if [ $TOUCH = can ]
  202. then
  203.     touch -am 0328165590 Makefile
  204. fi
  205. # ============= shar.c ==============
  206. echo "x - extracting shar.c (Text)"
  207. sed 's/^X//' << 'SHAR_EOF' > shar.c &&
  208. X/* CHK=0xE923 */
  209. Xchar *revision = "3.11";
  210. X/*
  211. X** shar.c
  212. X
  213. X  Defined functions:
  214. X    Rname(file)
  215. X    exit_incompat()
  216. X    gen_mkdir(path)
  217. X    gen_mkdir_script(path)
  218. X    header(argc,argv)
  219. X    helpuser()
  220. X    main(argc,argv)
  221. X    mode_map(mode,mode_str)
  222. X    shar(file)
  223. X
  224. X*/
  225. X/*+:EDITS:*/
  226. X/*:04-03-1990-20:09-wht@n4hgf-3.11 */
  227. X/*:04-01-1990-13:20-pat@rwing-correct case on M option in getopt() call */
  228. X/*:04-01-1990-13:50-pat@rwing-change defaults on -v, -w to be on */
  229. X/*:03-29-1990-18:23-wht@n4hgf-add automatic sequent support */
  230. X/*:03-28-1990-15:56-wht@n4hgf-add mode and length net.bandwidth chrome */
  231. X/*:03-28-1990-14:23-wht@n4hgf-correct some runtime diagnostics */
  232. X/*:11-14-1989-02:21-wht-SHAR_EOF was botched if last file char not newline */
  233. X/*:11-02-1989-14:11-wht-add touch -am */
  234. X
  235. X/*
  236. X Shar puts readable text files together in a package
  237. X from which they are easy to extract.
  238. X earlier attribution wht@n4hgf has:    decvax!microsof!uw-beave!jim
  239. X                                    (James Gosling at CMU)
  240. X*/
  241. X/*
  242. X *    I have made several mods to this program:
  243. X *
  244. X *    1) the -----Cut Here-----... now preceds the script.
  245. X *    2) the cat has been changed to a sed which removes a prefix
  246. X *    character from the beginning of each line of the extracted
  247. X *    file, this prefix character is added to each line of the archived
  248. X *    files and is not the same as the first character of the
  249. X *    file delimeter.
  250. X *    3) added several options:
  251. X *        -c    - add the -----Cut Here-----... line.
  252. X *        -d'del' - change the file delimeter to del.
  253. X *        -s    - cause the resulting script to print the wc of
  254. X *              the orignal file and the wc of the extracted
  255. X *              file.
  256. X *
  257. X *                Michael A. Thompson
  258. X *                Dalhousie University
  259. X *                Halifax, N.S., Canada.
  260. X */
  261. X
  262. X/*
  263. X *    I, too, have been hacking this code. This is the version on sixhub
  264. X *        bill davidsen (davidsen@sixhub.uucp)
  265. X *
  266. X *    - added support for binary files
  267. X *    - automatic creation of limited size multiple file archives,
  268. X *      each of which may be unpacked separately, and with sequence
  269. X *      checking.
  270. X *    - support for mixed text and binary files
  271. X *    - preserve file permissions
  272. X *    - restore to filename rather than pathname
  273. X *
  274. X */
  275. X/*
  276. X *  One good hack deserves another ... this version generates shell
  277. X *  code which attempts to create missing directories
  278. X *  handle deviants sun, vax, pyr (pyramid), SCO XENIX/UNIX automatically
  279. X *  for sequent, add -DBSD42
  280. X *  force Verbose on
  281. X *  if unsharing system's touch Sys V compatible (allows touch -m),
  282. X *  restore file dates
  283. X *  -n switch puts an alpha "name" in header
  284. X *  -a (if also -n) puts "Submitted-by:" & "Archive-name: <name>/part##
  285. X *  use getopt
  286. X *  as well as some other chrome-plated junque
  287. X *  ...!gatech!emory!tridom!wht (wht%n4hgf@gatech.edu) Warren Tucker
  288. X *
  289. X *  3.11 - Fri Apr  6 14:21:51 EDT 1990
  290. X *  With due deference to davidsen@sixhub, more changes..... copies
  291. X *  of this, like 3.10,  were mailed to him:
  292. X *  From wht  Fri Apr  6 15:14:30 1990 remote from n4hgf
  293. X *  Received: by n4hgf.UUCP (smail2.5-UNIX/386 5.3.2)
  294. X *      id AA01781; 6 Apr 90 15:14:30 EDT (Fri)
  295. X *  Date: Fri, 6 Apr 90 15:14:30 EDT
  296. X *  X-Mailer: Mail User's Shell (6.5 4/17/89)
  297. X *  From: wht@n4hgf (Warren Tucker)
  298. X *  To: davidsen@sixhub
  299. X *  Subject: shar 3.11
  300. X *  X-Bang-Reply-to: gatech!n4hgf!wht -or- emory!tridom!n4hgf!wht
  301. X *  Reply-to: wht%n4hgf@gatech.edu
  302. X *  Message-Id: <9004061514.AA01781@n4hgf.UUCP>
  303. X *
  304. X *  1. changes suggested by pat@rwing (Pat Myrto) and silvert@cs.dal.ca
  305. X *  (Bill Silvert)
  306. X *  2. fixes to who_am_i code in who@where.c
  307. X *  ...!gatech!n4hgf!wht (wht%n4hgf@gatech.edu) Warren Tucker
  308. X *
  309. X */
  310. X
  311. X#include <stdio.h>
  312. X#include <sys/types.h>
  313. X#include <time.h>
  314. X#include <sys/stat.h>
  315. X
  316. X/* assume system v unless otherwise fixed */
  317. X#if (defined(pyr) || defined(vax) || defined(sequent)) && !defined(BSD42)
  318. X#define BSD42
  319. X#endif
  320. X#if defined(sun)    /* this miscreant doesn't exactly fit BSD or SYSV */
  321. X#undef BSD42
  322. X#undef SYS5
  323. X#endif
  324. X#if !defined(BSD42) && !defined(sun)
  325. X#define SYS5
  326. X#endif
  327. X
  328. X#if defined(sun) || defined(BSD42)
  329. X#define strchr    index
  330. X#define strrchr    rindex
  331. X#endif
  332. X
  333. Xchar *strchr();
  334. Xchar *strrchr();
  335. X#ifdef __STDC__ /* my concession to ANSI-pansiness */
  336. Xvoid *malloc();
  337. X#else
  338. Xchar *malloc();
  339. X#endif
  340. XFILE *fdopen();
  341. XFILE *popen();
  342. X
  343. X#define    DELIM        "SHAR_EOF"/* put after each file */
  344. X#define PREFIX1        'X'    /* goes in front of each line */
  345. X#define PREFIX2        'Y'    /* goes in front of each line if Delim
  346. X                         * starts with PREFIX1 */
  347. X#define PREFIX        (Delim[0] == PREFIX1 ? PREFIX2 : PREFIX1)
  348. X#define WC            "wc -c"
  349. X
  350. Xint Archive_name = 0;    /* option to generate "Archive-name:" headers */
  351. Xint Verbose = 1;        /* option to provide append/extract feedback */
  352. Xint Wc_c = 1;            /* option to provide wc checking */
  353. Xchar *Delim = DELIM;    /* pointer to delimiter string */
  354. Xint Cut = 0;            /* option to provide cut mark */
  355. Xint Binary = 0;            /* flag for binary files */
  356. Xint Mixed = 0;            /* mixed text and binary files */
  357. Xint eXists = 0;            /* check if file exists */
  358. Xint InterOW = 0;        /* interactive overwrite */
  359. Xint PosParam = 0;        /* allow positional parameters */
  360. Xint FileStrip;            /* strip directories from filenames */
  361. X#ifdef    DEBUG
  362. Xint de_bug = 0;            /* switch for debugging on */
  363. X#define DeBug(f,v) if (de_bug) printf(f, v)
  364. X#else    /* normal compile */
  365. X#define DeBug(f,v)        /* do nothing */
  366. X#endif
  367. X
  368. XFILE *fpout = stdout;
  369. Xchar *Rname();            /* file restore name */
  370. Xunsigned limit = 0;
  371. Xlong ftell();
  372. Xlong TypePos;            /* position for archive type message */
  373. Xchar outname[50];        /* base for output filename */
  374. Xchar filename[50];        /* actual output filename */
  375. Xchar *sharname = (char *)0;
  376. Xchar *submitter = (char *)0;
  377. Xint filenum = 0;        /* output file # */
  378. Xstruct stat fst;        /* check file type, access */
  379. X
  380. Xmain(argc,argv)
  381. Xchar **argv;
  382. X{
  383. Xint status = 0;
  384. Xchar *oname;
  385. Xint c;
  386. Xextern int optind;
  387. Xextern char *optarg;
  388. X
  389. X    while((c = getopt(argc,argv,"vwd:btxXcfmpas:n:l:o:h")) != -1)
  390. X    {
  391. X        switch(c)
  392. X        {
  393. X        case 'v':
  394. X            Verbose = 0;
  395. X            break;
  396. X        case 'w':
  397. X            Wc_c = 0;
  398. X            break;
  399. X        case 'd':
  400. X            Delim = optarg;
  401. X            break;
  402. X        case 'b': /* binary files */
  403. X            Binary = 1;
  404. X            break;
  405. X        case 't': /* text mode */
  406. X            Binary = 0;
  407. X            break;
  408. X        case 'x': /* does the file exist */
  409. X            eXists = 1;
  410. X            if(InterOW || limit)
  411. X                exit_incompat();
  412. X            break;
  413. X        case 'X': /* does the file exist */
  414. X            InterOW = 1;
  415. X            if(limit || eXists)
  416. X                exit_incompat();
  417. X            eXists = 1;
  418. X            break;
  419. X        case 'c':
  420. X            Cut = 1;
  421. X            break;
  422. X        case 'f': /* filenames only */
  423. X            FileStrip = 1;
  424. X            break;
  425. X        case 'M': /* mixed text and binary */
  426. X            Mixed = 1;
  427. X            break;
  428. X        case 'p': /* allow positional parameters */
  429. X            PosParam = 1;
  430. X            break;
  431. X        case 'l': /* size limit in k */
  432. X            if(eXists)
  433. X                exit_incompat();
  434. X            limit = atoi(optarg) - 1;
  435. X            DeBug("Limit %dk\n",limit);
  436. X            break;
  437. X        case 'n': /* name of archive */
  438. X            sharname = optarg;
  439. X            break;
  440. X        case 's': /* submitter */
  441. X            submitter = optarg;
  442. X            break;
  443. X        case 'a': /* generate Archive-name: headers */
  444. X            Archive_name = 1;
  445. X            break;
  446. X        case 'o': /* specify output file */
  447. X            oname = optarg;
  448. X            strcpy(outname,oname);
  449. X            strcat(outname,".");
  450. X            filenum = 1;
  451. X            strcpy(filename,outname);
  452. X            strcat(filename,"01");
  453. X            fpout = fopen(filename,"w");
  454. X            if(!fpout)
  455. X            { /* creation error */
  456. X                perror("can't create output file");
  457. X                exit(1);
  458. X            }
  459. X            break;
  460. X#ifdef    DEBUG
  461. X        case '$': /* totally undocumented $ option, debug on */
  462. X            de_bug = 1;
  463. X            break;
  464. X#endif
  465. X        default: /* invalid option */
  466. X        case 'h': /* help */
  467. X            helpuser();
  468. X            break;
  469. X        }
  470. X    }
  471. X
  472. X    if(optind >= argc)
  473. X    {
  474. X        fprintf(stderr,"shar: No input files\n");
  475. X        helpuser();
  476. X        exit(1);
  477. X    }
  478. X
  479. X    if(Archive_name && !sharname)
  480. X    {
  481. X        fprintf(stderr,"shar: -n must accompany -a\n");
  482. X        helpuser();
  483. X        exit(1);
  484. X    }
  485. X
  486. X    if(!submitter)
  487. X    {
  488. X        submitter = malloc(128);
  489. X        who_where(submitter);
  490. X    }
  491. X
  492. X    if(header(argc-optind,&argv[optind]))
  493. X        exit(2);
  494. X
  495. X    if(InterOW)
  496. X    {
  497. X        Verbose = 1;
  498. X        fprintf(fpout,"wish=\n");
  499. X        if(Archive_name)
  500. X        {
  501. X            printf("PLEASE do not submit -X shars to the usenet or other\n");
  502. X            printf("public networks.  They will cause problems.\n");
  503. X        }
  504. X    }
  505. X
  506. X    while(optind < argc)
  507. X    { /* process positional parameters and files */
  508. X        if(PosParam)
  509. X        {        /* allow -b and -t inline */
  510. X            if(strcmp(argv[optind],"-b") == 0)
  511. X            { /* set binary */
  512. X                Binary = 1;
  513. X                optind++;
  514. X                continue;
  515. X            }
  516. X            if(strcmp(argv[optind],"-t") == 0)
  517. X            { /* set mode text */
  518. X                Binary = 0;
  519. X                optind++;
  520. X                continue;
  521. X            }
  522. X        }
  523. X        status += shar(argv[optind++]);
  524. X    }
  525. X
  526. X    /* delete the sequence file, if any */
  527. X    if(limit && filenum > 1)
  528. X    {
  529. X        fputs("rm -f s3_seq_.tmp\n",fpout);
  530. X        fputs("echo \"You have unpacked the last part\"\n",fpout);
  531. X        if(!Verbose)
  532. X            fprintf(stderr,"Created %d files\n",filenum);
  533. X    }
  534. X    fputs("exit 0\n",fpout);
  535. X    exit(status);
  536. X}
  537. X
  538. X/*+-----------------------------------------------------------------------
  539. X    mode_map(mode,mode_str)    build drwxrwxrwx string
  540. X------------------------------------------------------------------------*/
  541. Xchar *
  542. Xmode_map(mode,mode_str)
  543. Xunsigned short mode;
  544. Xchar *mode_str;
  545. X{
  546. Xregister unsigned ftype = mode & S_IFMT;
  547. Xregister char *rtn;
  548. Xstatic char result[12];
  549. X
  550. X    rtn = (mode_str == (char *)0) ? result : mode_str;
  551. X
  552. X    /*          drwxrwxrwx */
  553. X    /*          0123456789 */
  554. X    strcpy(rtn,"----------");
  555. X
  556. X#ifdef THIS_IS_NOT_NEEDED_FOR_SHAR
  557. X    switch(ftype)
  558. X    {
  559. X        case S_IFIFO:    *rtn = 'p'; break; /* FIFO (named pipe) */
  560. X        case S_IFDIR:    *rtn = 'd'; break; /* directory */
  561. X        case S_IFCHR:    *rtn = 'c'; break; /* character special */
  562. X        case S_IFBLK:    *rtn = 'b'; break; /* block special */
  563. X        case S_IFREG:    *rtn = '-'; break; /* regular */
  564. X
  565. X#if defined(sun) | defined(BSD42)
  566. X        case S_IFLNK:    *rtn = 'l'; break; /* symbolic link */
  567. X        case S_IFSOCK:    *rtn = 's'; break; /* socket */
  568. X#endif
  569. X
  570. X#if defined (SYS5)
  571. X        case S_IFNAM:                        /* name space entry */
  572. X            if(mode & S_INSEM)                /* semaphore */
  573. X            {
  574. X                *rtn = 's';
  575. X                break;
  576. X            }
  577. X            if(mode & S_INSHD)                /* shared memory */
  578. X            {
  579. X                *rtn = 'm';
  580. X                break;
  581. X            }
  582. X#endif
  583. X
  584. X        default:        *rtn = '?'; break;    /* ??? */
  585. X    }
  586. X#endif /* THIS_IS_NOT_NEEDED_FOR_SHAR */
  587. X
  588. X    if(mode & 000400) *(rtn + 1) = 'r';
  589. X    if(mode & 000200) *(rtn + 2) = 'w';
  590. X    if(mode & 000100) *(rtn + 3) = 'x';
  591. X    if(mode & 004000) *(rtn + 3) = 's';
  592. X    if(mode & 000040) *(rtn + 4) = 'r';
  593. X    if(mode & 000020) *(rtn + 5) = 'w';
  594. X    if(mode & 000010) *(rtn + 6) = 'x';
  595. X    if(mode & 002000) *(rtn + 6) = 's';
  596. X    if(mode & 000004) *(rtn + 7) = 'r';
  597. X    if(mode & 000002) *(rtn + 8) = 'w';
  598. X    if(mode & 000001) *(rtn + 9) = 'x';
  599. X    if(mode & 001000) *(rtn + 9) = 't';
  600. X
  601. X    return(rtn);
  602. X
  603. X}    /* end of mode_map */
  604. X
  605. Xheader(argc,argv)
  606. Xchar **argv;
  607. X{
  608. Xint i;
  609. Xint status;
  610. XFILE *fpsource;    /* pipe temp */
  611. Xchar s128[128];
  612. Xlong now;
  613. Xstruct tm *utc;
  614. Xstruct tm *gmtime();
  615. X
  616. X    /* see if any conflicting options */
  617. X    if(limit && !filenum)
  618. X    { /* can't rename what you don't have */
  619. X        fprintf(stderr,"Can't use -l option without -o\n");
  620. X        helpuser();
  621. X    }
  622. X
  623. X    for(i = 0; i < argc; i++)
  624. X    { /* skip positional parameters */
  625. X        if(PosParam && (strcmp(argv[i],"-b") == 0 ||
  626. X            strcmp(argv[i],"-t") == 0))
  627. X            continue;
  628. X
  629. X        /* see if access and correct type */
  630. X        if(access(argv[i],4))
  631. X        {
  632. X            fprintf(stderr,"shar: Can't access %s\n",argv[i]);
  633. X            return(1);
  634. X        }
  635. X
  636. X        /* get file type */
  637. X        stat(argv[i],&fst);
  638. X        status = fst.st_mode & S_IFMT;
  639. X
  640. X        /* at this point I check to see that this is a regular file */
  641. X        if(status != S_IFREG)
  642. X        { /* this is not a regular file */
  643. X            fprintf(stderr,"shar: %s is not a regular file\n",argv[i]);
  644. X            return(1);
  645. X        }
  646. X    }
  647. X
  648. X    if(Archive_name)
  649. X    {
  650. X        fprintf(fpout,"Submitted by: %s\n",submitter);
  651. X        fprintf(fpout,"Archive-name: %s/part%02d\n\n",
  652. X            sharname,(filenum) ? filenum : 1);
  653. X    }
  654. X
  655. X    if(Cut)
  656. X        fputs("---- Cut Here and unpack ----\n",fpout);
  657. X    fputs("#!/bin/sh\n",fpout);
  658. X    if(sharname)
  659. X        fprintf(fpout,"# This is %s, a shell archive (shar %s)\n",
  660. X            sharname,revision);
  661. X    else
  662. X        fprintf(fpout,"# This is a shell archive (shar %s)\n",revision);
  663. X
  664. X    time(&now);
  665. X    utc = gmtime(&now);
  666. X    fprintf(fpout,"# made %02d/%02d/%04d %02d:%02d UTC ",
  667. X        utc->tm_mon + 1,utc->tm_mday,utc->tm_year + 1900,
  668. X        utc->tm_hour,utc->tm_min);
  669. X
  670. X    fputs("by ",fpout);
  671. X    fputs(submitter,fpout);
  672. X    fputs("\n",fpout);
  673. X
  674. X#if defined(SYS5)
  675. X    if(!(fpsource = popen("/bin/pwd","r")))
  676. X        return(-1);
  677. X    fgets(s128,sizeof(s128),fpsource);
  678. X    s128[strlen(s128) - 1] = 0;
  679. X    fclose(fpsource);
  680. X#else
  681. X#if defined(BSD42) || defined(sun)
  682. X    getwd(s128);
  683. X#else
  684. X#include "Need_conditional_compile_fix"
  685. X#endif
  686. X#endif
  687. X    fprintf(fpout,"# Source directory %s\n",s128);
  688. X
  689. X    fprintf(fpout,"#\n# existing files %s be overwritten\n",
  690. X        (eXists) ? "will NOT"
  691. X                 : ((InterOW) ? "MAY" : "WILL"));
  692. X    if(InterOW)
  693. X        fprintf(fpout,"# The unsharer will be INTERACTIVELY queried.\n");
  694. X
  695. X    if(limit)
  696. X    { /* may be split, explain */
  697. X        fputs("#\n",fpout);
  698. X        TypePos = ftell(fpout);
  699. X        fprintf(fpout,"%-75s\n%-75s\n","#","#");
  700. X    }
  701. X
  702. X    fputs("#\n# This shar contains:\n",fpout);
  703. X    fputs("# length  mode       name\n",fpout);
  704. X    fputs("# ------ ---------- ------------------------------------------\n",
  705. X        fpout);
  706. X    for(i = 0; i < argc; i++)
  707. X    { /* output names of files but not parameters */
  708. X        if(PosParam && (strcmp(argv[i],"-b") == 0 ||
  709. X            strcmp(argv[i],"-t") == 0))
  710. X            continue;
  711. X        stat(argv[i],&fst);
  712. X        fst.st_mode &= ~(07000); /* turn off setuid, setgid and sticky bits */
  713. X        fprintf(fpout,"# %6ld %s %s\n",fst.st_size,
  714. X            mode_map(fst.st_mode,(char *)0),Rname(argv[i]));
  715. X    }
  716. X    fputs("#\n",fpout);
  717. X
  718. X    fputs("touch 2>&1 | fgrep '[-amc]' > /tmp/s3_touch$$\n",fpout);
  719. X    fputs("if [ -s /tmp/s3_touch$$ ]\n",fpout);
  720. X    fputs("then\n",fpout);
  721. X    fputs("    TOUCH=can\n",fpout);
  722. X    fputs("else\n",fpout);
  723. X    fputs("    TOUCH=cannot\n",fpout);
  724. X    fputs("fi\n",fpout);
  725. X    fputs("rm -f /tmp/s3_touch$$\n",fpout);
  726. X
  727. X    if(limit)
  728. X    { /* now check the sequence */
  729. X        fprintf(fpout,"%s%s%s%s",
  730. X            "if test -r s3_seq_.tmp\n",
  731. X            "then echo \"Must unpack archives in sequence!\"\n",
  732. X            "     next=`cat s3_seq_.tmp`; echo \"Please unpack part $next next\"\n",
  733. X            "     exit 1; fi\n");
  734. X    }
  735. X    return(0);
  736. X}
  737. X
  738. X#define MAX_MKDIR_ALREADY    128    /* ridiculously enough */
  739. Xchar *mkdir_already[MAX_MKDIR_ALREADY];
  740. Xint mkdir_already_count = 0;
  741. X
  742. Xvoid
  743. Xgen_mkdir(path)
  744. Xchar *path;
  745. X{
  746. Xregister int ialready;
  747. Xchar *cptr;
  748. X
  749. X/* if already generated code for this dir creation, dont do again */
  750. X    for(ialready = 0; ialready < mkdir_already_count; ialready++)
  751. X    {
  752. X        if(!strcmp(path,mkdir_already[ialready]))
  753. X            return;
  754. X    }
  755. X
  756. X/* haven't done this one */
  757. X    if(mkdir_already_count == MAX_MKDIR_ALREADY)
  758. X    {
  759. X        fprintf(stderr,"too many directories for mkdir generation\n");
  760. X        exit(255);
  761. X    }
  762. X    if(!(cptr = mkdir_already[mkdir_already_count++] = malloc(strlen(path)+1)))
  763. X    {
  764. X        fprintf(stderr,"out of memory for mkdir generation\n");
  765. X        exit(255);
  766. X    }
  767. X    strcpy(cptr,path);
  768. X
  769. X/* generate the text */
  770. X    fprintf(fpout,"if test ! -d '%s' ; then\n",path);
  771. X    if(Verbose)
  772. X        fprintf(fpout,"    echo \"x - creating directory %s\"\n",path);
  773. X    fprintf(fpout,"    mkdir '%s'\n",path);
  774. X    fprintf(fpout,"fi\n");
  775. X
  776. X}    /* end of gen_mkdir */
  777. X
  778. Xvoid
  779. Xgen_mkdir_script(path)
  780. Xregister char *path;
  781. X{
  782. Xregister char *cptr;
  783. X
  784. X    for(cptr = strchr(path,'/'); cptr; cptr = strchr(cptr + 1,'/'))
  785. X    {
  786. X        /* avoid empty string if leading or double '/' */
  787. X        if(cptr == path || *(cptr - 1) == '/')
  788. X            continue;
  789. X        /* omit '.' */
  790. X        if((*(cptr - 1) == '.') && ((cptr == path + 1) || (*(cptr - 2) == '/')))
  791. X            continue;
  792. X        *cptr = 0;                /* temporarily terminate string */
  793. X        gen_mkdir(path);
  794. X        *cptr = '/';
  795. X    }
  796. X}    /* end of gen_mkdir_script */
  797. X
  798. Xshar(file)
  799. Xchar *file;
  800. X{
  801. Xchar line[BUFSIZ];
  802. XFILE *fpsource;
  803. Xlong cursize,remaining,ftell();
  804. Xint split = 0;        /* file split flag */
  805. Xchar *filetype;        /* text or binary */
  806. Xchar *RstrName;        /* name for restore */
  807. Xstruct tm *lt;
  808. Xchar *filename_base;
  809. X
  810. X    /* if limit set, get the current output length */
  811. X    if(limit)
  812. X    {
  813. X        cursize = ftell(fpout);
  814. X        remaining = (limit * 1024L) - cursize;
  815. X        DeBug("In shar: remaining size %ld\n",remaining);
  816. X    }
  817. X
  818. X    /* determine the name to use for restore */
  819. X    RstrName = Rname(file);
  820. X
  821. X    fputs("# ============= ",fpout);
  822. X    fputs(RstrName,fpout);
  823. X    fputs(" ==============\n",fpout);
  824. X
  825. X    gen_mkdir_script(RstrName);
  826. X
  827. X    /* if mixed, determine the file type */
  828. X    if(Mixed)
  829. X    {
  830. X        int count;
  831. X        sprintf(line,"file %s | egrep -c \"text|shell\"",file);
  832. X        fpsource = popen(line,"r");
  833. X        fscanf(fpsource,"%d",&count);
  834. X        pclose(fpsource);
  835. X        Binary = (count != 1);
  836. X    }
  837. X
  838. X    if(Binary)
  839. X    { /* fork a uuencode process */
  840. X        static int pid,pipex[2];
  841. X
  842. X        pipe(pipex);
  843. X        fflush(fpout);
  844. X
  845. X        if(pid = fork())
  846. X        { /* parent, create a file to read */
  847. X            close(pipex[1]);
  848. X            fpsource = fdopen(pipex[0],"r");
  849. X        }
  850. X        else
  851. X        { /* start writing the pipe with encodes */
  852. X            FILE *outptr;
  853. X
  854. X            fpsource = fopen(file,"rb");
  855. X            outptr = fdopen(pipex[1],"w");
  856. X            fprintf(outptr,"begin 600 %s\n",RstrName);
  857. X            encode(fpsource,outptr);
  858. X            fprintf(outptr,"end\n");
  859. X            exit(0);
  860. X        }
  861. X        filetype = "Binary";
  862. X    }
  863. X    else
  864. X    {
  865. X        fpsource = fopen(file,"r");
  866. X        filetype = "Text";
  867. X    }
  868. X
  869. X    if(fpsource)
  870. X    {
  871. X        /* protect existing files */
  872. X        if(eXists)
  873. X        {
  874. X            if(InterOW)
  875. X            {
  876. X            fprintf(fpout,"if test -f '%s'\n",RstrName);
  877. X            fprintf(fpout,"then\n");
  878. X            fprintf(fpout,"\tcase $wish in\n");
  879. X            fprintf(fpout,"\tA*|a*) echo x - overwriting '%s';;\n",RstrName);
  880. X            fprintf(fpout,
  881. X    "\t*) echo \"? - overwrite '%s' -- [No], [Y]es, [A]ll, [Q]uit? \"\n",
  882. X                RstrName);
  883. X            fprintf(fpout,"\t\tread wish;;\n");
  884. X            fprintf(fpout,"\tesac\n");
  885. X            fprintf(fpout,"\tcase $wish in\n");
  886. X            fprintf(fpout,"\tQ*|q*) echo aborted; exit 86;;\n");
  887. X            fprintf(fpout,"\tA*|a*|Y*|y*) x=Y;;\n");
  888. X            fprintf(fpout,"\t*) x=N;;\n");
  889. X            fprintf(fpout,"\tesac\n");
  890. X            fprintf(fpout,"else\n");
  891. X            fprintf(fpout,"\tx=Y\n");
  892. X            fprintf(fpout,"fi\n");
  893. X            fprintf(fpout,"if test $x != Y\n");
  894. X            fprintf(fpout,"then\n");
  895. X            fprintf(fpout,"\techo x - skipping '%s'\n",RstrName);
  896. X            fprintf(fpout,"else\n");
  897. X            }
  898. X            else
  899. X            {
  900. X                fprintf(fpout,
  901. X                "if test -f '%s'; then echo \"File %s exists\"; else\n",
  902. X                RstrName,RstrName);
  903. X            }
  904. X        }
  905. X
  906. X        fprintf(stderr,"shar: saving %s (%s)\n",file,filetype);
  907. X        if(Verbose)
  908. X        { /* info on archive and unpack */
  909. X            fprintf(fpout,"echo \"x - extracting %s (%s)\"\n",
  910. X                RstrName,filetype);
  911. X        }
  912. X        if(Binary)
  913. X        { /* run sed through uudecode via temp file */
  914. X            fprintf(fpout,"sed 's/^%c//' << '%s' > s3_temp_.tmp &&\n",
  915. X                PREFIX,Delim);
  916. X        }
  917. X        else
  918. X        { /* just run it into the file */
  919. X            fprintf(fpout,"sed 's/^%c//' << '%s' > %s &&\n",
  920. X                PREFIX,Delim,RstrName);
  921. X        }
  922. X        while(fgets(line,BUFSIZ,fpsource))
  923. X        { /* output a line and test the length */
  924. X            fprintf(fpout,"%c%s",PREFIX,line);
  925. X            if(limit && (remaining -= strlen(line) + 2) < 0)
  926. X            { /* change to another file */
  927. X                DeBug("Newfile, remaining %ld, ",remaining);
  928. X                DeBug("limit still %d\n",limit);
  929. X
  930. X                if(line[strlen(line) - 1] != '\n')
  931. X                    fputc('\n',fpout);
  932. X
  933. X                fprintf(fpout,"%s\n",Delim);
  934. X                if(Verbose)
  935. X                { /* output some reassurance */
  936. X                    fprintf(fpout,
  937. X                        "echo \"End of %s part %d\"\n",
  938. X                            (sharname) ? sharname : "",filenum);
  939. X                    fprintf(fpout,
  940. X                        "echo \"File %s is continued in part %d\"\n",
  941. X                        RstrName,filenum + 1);
  942. X                }
  943. X                else
  944. X                    fprintf(fpout,
  945. X                        "echo \"End of part %d, continue with part %d\"\n",
  946. X                        filenum,filenum + 1);
  947. X                fprintf(fpout,"echo \"%d\" > s3_seq_.tmp\n",filenum + 1);
  948. X                fprintf(fpout,"exit 0\n");
  949. X
  950. X                if(filenum == 1)
  951. X                { /* rewrite the info lines on the firstheader */
  952. X                    fseek(fpout,TypePos,0);
  953. X                    fprintf(fpout,"%-75s\n%-75s\n",
  954. X                        "# This is part 1 of a multipart archive",
  955. X                        "# do not concatenate these parts, unpack them in order with /bin/sh");
  956. X                }
  957. X                fclose(fpout);
  958. X
  959. X                /* form the next filename */
  960. X                sprintf(filename,"%s%02d",outname,++filenum);
  961. X                fpout = fopen(filename,"w");
  962. X
  963. X                if(Archive_name)
  964. X                {
  965. X                    fprintf(fpout,"Submitted by: %s\n",submitter);
  966. X                    fprintf(fpout,"Archive-name: %s/part%2d\n\n",
  967. X                        sharname,(filenum) ? filenum : 1);
  968. X                }
  969. X
  970. X                if(Cut)
  971. X                    fputs("---- Cut Here and unpack ----\n",fpout);
  972. X                if(!(filename_base = strrchr(filename,'/')))
  973. X                    filename_base = filename;
  974. X                else
  975. X                    filename_base++;
  976. X
  977. X                fprintf(fpout,"#!/bin/sh\n");
  978. X                fprintf(fpout,
  979. X                    "# this is %s (part %d of %s)\n",
  980. X                    filename_base,
  981. X                    filenum,
  982. X                    (sharname) ? sharname : "a multipart archive");
  983. X                fputs("# do not concatenate these parts, ",fpout);
  984. X                fputs("unpack them in order with /bin/sh\n",fpout);
  985. X                fprintf(fpout,"# file %s continued\n#\n",RstrName);
  986. X
  987. X                fputs("touch 2>&1 | fgrep '[-amc]' > /tmp/s3_touch$$\n",fpout);
  988. X                fputs("if [ -s /tmp/s3_touch$$ ]\n",fpout);
  989. X                fputs("then\n",fpout);
  990. X                fputs("    TOUCH=can\n",fpout);
  991. X                fputs("else\n",fpout);
  992. X                fputs("    TOUCH=cannot\n",fpout);
  993. X                fputs("fi\n",fpout);
  994. X                fputs("rm -f /tmp/s3_touch$$\n",fpout);
  995. X
  996. X                fprintf(fpout,"CurArch=%d\n",filenum);
  997. X                fprintf(fpout,"%s%s%s%s%s%s%s%s%s",
  998. X                    "if test ! -r s3_seq_.tmp\n",
  999. X                    "then echo \"Please unpack part 1 first!\"\n",
  1000. X                    "     exit 1; fi\n",
  1001. X                    "( read Scheck\n",
  1002. X                    "  if test \"$Scheck\" != $CurArch\n",
  1003. X                    "  then echo \"Please unpack part $Scheck next!\"\n",
  1004. X                    "       exit 1;\n",
  1005. X                    "  else exit 0; fi\n",
  1006. X                    ") < s3_seq_.tmp || exit 1\n");
  1007. X
  1008. X                if(Verbose)
  1009. X                { /* keep everybody informed */
  1010. X                    fprintf(stderr,"Starting file %s\n",filename);
  1011. X                    fprintf(fpout,
  1012. X                        "echo \"x - Continuing file %s\"\n",RstrName);
  1013. X                }
  1014. X                fprintf(fpout,
  1015. X                    "sed 's/^%c//' << '%s' >> %s\n",
  1016. X                    PREFIX,Delim,(Binary ? "s3_temp_.tmp" : RstrName));
  1017. X                remaining = limit * 1024L;
  1018. X                split = 1;
  1019. X            }
  1020. X        }
  1021. X
  1022. X        (void) fclose(fpsource);
  1023. X
  1024. X        if(line[strlen(line) - 1] != '\n')
  1025. X            fputc('\n',fpout);
  1026. X
  1027. X        fprintf(fpout,"%s\n",Delim);
  1028. X        if(split && Verbose)
  1029. X            fprintf(fpout,
  1030. X                "echo \"File %s is complete\"\n",RstrName);
  1031. X
  1032. X        /* if this file was uuencoded, decode it and drop the temp */
  1033. X        if(Binary)
  1034. X        {
  1035. X            if(Verbose)
  1036. X                fprintf(fpout,"echo \"uudecoding file %s\"\n",RstrName);
  1037. X            fprintf(fpout,
  1038. X                "uudecode < s3_temp_.tmp && rm -f s3_temp_.tmp &&\n");
  1039. X        }
  1040. X
  1041. X        /* set the permissions as they were */
  1042. X        stat(file,&fst);
  1043. X        fprintf(fpout,"chmod %04o %s || echo \"restore of %s fails\"\n",
  1044. X            fst.st_mode & 00777,RstrName,RstrName);
  1045. X        lt = localtime(&fst.st_mtime);
  1046. X        fputs("if [ $TOUCH = can ]\nthen\n",fpout);
  1047. X        fprintf(fpout,"    touch -am %02d%02d%02d%02d%02d %s\n",
  1048. X            lt->tm_mon + 1,lt->tm_mday,lt->tm_hour,lt->tm_min,lt->tm_year,
  1049. X            RstrName);
  1050. X        fputs("fi\n",fpout);
  1051. X
  1052. X        if(Wc_c)
  1053. X        { /* validate the transferred file */
  1054. X            FILE *pfp;
  1055. X            char command[BUFSIZ];
  1056. X
  1057. X            sprintf(command,"%s %s",WC,file);
  1058. X            if((pfp = popen(command,"r")))
  1059. X            {
  1060. X                char wc[BUFSIZ];
  1061. X
  1062. X                fscanf(pfp,"%s",wc);
  1063. X                fprintf(fpout,"set `%s %s`;Wc_c=$1\n",
  1064. X                    WC,RstrName);
  1065. X                fprintf(fpout,
  1066. X                    "if test \"$Wc_c\" != \"%s\"\n",wc);
  1067. X                fprintf(fpout,
  1068. X                    "then echo original size %s, current size $Wc_c;fi\n",wc);
  1069. X                pclose(pfp);
  1070. X            }
  1071. X        }
  1072. X
  1073. X        /* if the exists option is in place close the if */
  1074. X        if(eXists)
  1075. X            fprintf(fpout,"fi\n");
  1076. X
  1077. X        return(0);
  1078. X    }
  1079. X    else
  1080. X    {
  1081. X        fprintf(stderr,"shar: Can't open %s (%s): ",file,filetype);
  1082. X        perror("");
  1083. X        return(1);
  1084. X    }
  1085. X}
  1086. X
  1087. Xchar *
  1088. XRname(file)
  1089. Xregister char *file;
  1090. X{
  1091. X    register char *RstrName;
  1092. X
  1093. X    if(FileStrip)
  1094. X    { /* use just the filename */
  1095. X        RstrName = file+strlen(file);
  1096. X        while(RstrName > file && *RstrName != '/')
  1097. X            RstrName--;
  1098. X        if(*RstrName == '/') RstrName++;
  1099. X    }
  1100. X    else
  1101. X        RstrName = file;
  1102. X    if(!strncmp(RstrName,"./",2))
  1103. X        RstrName += 2;
  1104. X    return(RstrName);
  1105. X}
  1106. X
  1107. X/*****************************************************************
  1108. X |  exit_incompat - incompatible options
  1109. X ****************************************************************/
  1110. X
  1111. Xexit_incompat()
  1112. X{
  1113. X       fputs("You may only specify one of -l, -X or -x\n",stderr);
  1114. X    exit(1);
  1115. X}
  1116. X
  1117. Xhelpuser()
  1118. X{                /* output a command format message */
  1119. X    register char **ptr;
  1120. X    static char *helpinfo[] =
  1121. X    {
  1122. X        "-v  verbose messages OFF while executing",
  1123. X        "-w  don't check with 'wc -c' after unpack",
  1124. X        "-n  Name of archive (documentation)",
  1125. X        "-a  Generate Submitted-by: & Archive-name: headers",
  1126. X        "-s  override automatically determined submitter name",
  1127. X        "-x  don't overwrite existing files",
  1128. X        "-X  interactively overwrite existing files (NOT FOR NET SHARS)",
  1129. X        "-b  treat all files as binary, use uuencode",
  1130. X        "-t  treat all files as text (default)",
  1131. X        "-p  allow positional parameter options. The options \"-b\"",
  1132. X        "    and \"-t\" may be embedded, and files to the right of the",
  1133. X        "    option will be processed in the specified mode",
  1134. X        "-M  mixed mode. Determine if the files are text or",
  1135. X        "    binary and archive correctly.",
  1136. X        "-D  output date, user, and directory comments to the archive",
  1137. X        "-c  start the shar with a cut line",
  1138. X        "-f  restore by filename only, rather than path",
  1139. X        "-dXXX   use XXX to delimit the files in the shar",
  1140. X        "-oXXX   (or -o XXX) output to file XXX.01 thru XXX.nn",
  1141. X        "-lXX    limit output file size to XXk bytes",
  1142. X        "\nThe 'o' option is required if the 'l' option is used",
  1143. X        "The 'n' option is required if the 'a' option is used",
  1144. X        "The 'x' and 'l' options are incompatible",
  1145. X        "\n-a generates sharname/part## headers. If you are producing patches",
  1146. X        "you'll need to edit -a headers (or please improve shar :-))",
  1147. X        "The automatic submitter name is trivial: essentially `whoami`@`uname`",
  1148. X        (char *)0
  1149. X    };
  1150. X    fprintf(stderr,
  1151. X        "shar %s\nusage: shar [ options ] file [ file1 ... ] ]\n",revision);
  1152. X    for(ptr = helpinfo; *ptr; ptr++)
  1153. X        fprintf(stderr,"%s\n",*ptr);
  1154. X
  1155. X    exit(1);
  1156. X}
  1157. X/* vi: set tabstop=4 shiftwidth=4: */
  1158. SHAR_EOF
  1159. chmod 0644 shar.c || echo "restore of shar.c fails"
  1160. if [ $TOUCH = can ]
  1161. then
  1162.     touch -am 0406143490 shar.c
  1163. fi
  1164. # ============= unshar.c ==============
  1165. echo "x - extracting unshar.c (Text)"
  1166. sed 's/^X//' << 'SHAR_EOF' > unshar.c &&
  1167. X/* CHK=0x4D8D */
  1168. X/****************************************************************
  1169. X * unshar.c: Unpackage one or more shell archive files
  1170. X *
  1171. X * Usage:    unshar [ -d directory ] [ file ] ...
  1172. X *
  1173. X * Description:    unshar is a filter which removes the front part
  1174. X *        of a file and passes the rest to the 'sh' command.
  1175. X *        It understands phrases like "cut here", and also
  1176. X *        knows about shell comment characters and the Unix
  1177. X *        commands "echo", "cat", and "sed".
  1178. X *
  1179. X * HISTORY
  1180. X *  1-Feb-85  Guido van Rossum (guido@mcvax) at CWI, Amsterdam
  1181. X *    Added missing 'quit' routine;
  1182. X *    added -d flag to change to directory first;
  1183. X *    added filter mode (read stdin when no arguments);
  1184. X *    added 'getopt' to get flags (makes it self-contained).
  1185. X * 29-Jan-85  Michael Mauldin (mlm) at Carnegie-Mellon University
  1186. X *    Created.
  1187. X ****************************************************************/
  1188. X
  1189. X#include <stdio.h>
  1190. X#define EOL '\n'
  1191. X
  1192. X#if defined(pyr) || defined(sun) || defined(BSD42) || \
  1193. X defined(vax) || defined(sequent)
  1194. X#define strchr    index
  1195. X#endif
  1196. X
  1197. Xchar *strchr();
  1198. X
  1199. Xextern char *optarg;
  1200. Xextern int optind;
  1201. X
  1202. Xmain(argc,argv)
  1203. Xint argc;
  1204. Xchar *argv[];
  1205. X{ 
  1206. X    int i,ch;
  1207. X    FILE *in;
  1208. X
  1209. X    setbuf(stdout,NULL);
  1210. X    setbuf(stderr,NULL);
  1211. X
  1212. X    /* Process options */
  1213. X
  1214. X    while((ch = getopt(argc,argv,"d:")) != EOF)
  1215. X    {
  1216. X        switch(ch)
  1217. X        {
  1218. X        case 'd':
  1219. X            if(chdir(optarg) == -1)
  1220. X            {
  1221. X                fprintf(stderr,"unshar: cannot chdir to '%s'\n",optarg);
  1222. X                exit(2);
  1223. X            }
  1224. X            break;
  1225. X        default:
  1226. X            quit(2,"Usage: unshar [-d directory] [file] ...\n");
  1227. X        }
  1228. X    }
  1229. X
  1230. X    if(optind < argc)
  1231. X    { 
  1232. X        for(i= optind; i < argc; ++i)
  1233. X        { 
  1234. X            if(!(in = fopen(argv[i],"r")))
  1235. X            { 
  1236. X                fprintf(stderr,"unshar: file '%s' not found\n",argv[i]);
  1237. X                exit(1);
  1238. X            }
  1239. X            process(argv[i],in);
  1240. X            fclose(in);
  1241. X        }
  1242. X    }
  1243. X    else
  1244. X        process("standard input",stdin);
  1245. X
  1246. X    exit(0);
  1247. X}
  1248. X
  1249. X
  1250. Xprocess(name,in)
  1251. Xchar *name;
  1252. XFILE *in;
  1253. X{ 
  1254. X    char ch;
  1255. X    FILE *shpr,*popen();
  1256. X
  1257. X    if(position(name,in))
  1258. X    { 
  1259. X        printf("%s:\n",name);
  1260. X        if(!(shpr = popen("sh","w")))
  1261. X            quit(1,"unshar: cannot open 'sh' process\n");
  1262. X
  1263. X        while((ch = fgetc(in)) != EOF)
  1264. X            fputc(ch,shpr);
  1265. X
  1266. X        pclose(shpr);
  1267. X    }
  1268. X}
  1269. X
  1270. X/****************************************************************
  1271. X * position: position 'fil' at the start of the shell command
  1272. X * portion of a shell archive file.
  1273. X ****************************************************************/
  1274. X
  1275. Xposition(fn,fil)
  1276. Xchar *fn;
  1277. XFILE *fil;
  1278. X{ 
  1279. X    char buf[BUFSIZ];
  1280. X    long pos,ftell();
  1281. X
  1282. X    /* Results from star matcher */
  1283. X    static char res1[BUFSIZ],res2[BUFSIZ],res3[BUFSIZ],res4[BUFSIZ];
  1284. X    static char *result[] = 
  1285. X    { 
  1286. X        res1,res2,res3,res4     };
  1287. X
  1288. X    rewind(fil);
  1289. X
  1290. X    while(1)
  1291. X    { /* Record position of the start of this line */
  1292. X        pos = ftell(fil);
  1293. X
  1294. X        /* Read next line, fail if no more */
  1295. X        if(!fgets(buf,BUFSIZ,fil))
  1296. X        { 
  1297. X            fprintf(stderr,"unshar: found no shell commands in %s\n",fn);
  1298. X            return(0);
  1299. X        }
  1300. X
  1301. X        /* Bail out if we see C preprocessor commands or C comments */
  1302. X        if(stlmatch(buf,"#include")    || stlmatch(buf,"# include") ||
  1303. X            stlmatch(buf,"#define")    || stlmatch(buf,"# define") ||
  1304. X            stlmatch(buf,"#ifdef")    || stlmatch(buf,"# ifdef") ||
  1305. X            stlmatch(buf,"#ifndef")    || stlmatch(buf,"# ifndef") ||
  1306. X            stlmatch(buf,"/*"))
  1307. X        { 
  1308. X            fprintf(stderr,
  1309. X                "unshar: %s looks like raw C code, not a shell archive\n",fn);
  1310. X            return(0);
  1311. X        }
  1312. X
  1313. X        /* Does this line start with a shell command or comment */
  1314. X        if(stlmatch(buf,"#")    || stlmatch(buf,":") ||
  1315. X            stlmatch(buf,"echo ")    || stlmatch(buf,"sed ") ||
  1316. X            stlmatch(buf,"cat "))
  1317. X        { 
  1318. X            fseek(fil,pos,0); 
  1319. X            return(1); 
  1320. X        }
  1321. X
  1322. X        /* Does this line say "Cut here" */
  1323. X        if(smatch(buf,"*CUT*HERE*",result) ||
  1324. X            smatch(buf,"*cut*here*",result) ||
  1325. X            smatch(buf,"*TEAR*HERE*",result) ||
  1326. X            smatch(buf,"*tear*here*",result) ||
  1327. X            smatch(buf,"*CUT*CUT*",result) ||
  1328. X            smatch(buf,"*cut*cut*",result))
  1329. X        {
  1330. X            /* Read next line after "cut here", skipping blank lines */
  1331. X            while(1)
  1332. X            { 
  1333. X                pos = ftell(fil);
  1334. X
  1335. X                if(!fgets(buf,BUFSIZ,fil))
  1336. X                { 
  1337. X                    fprintf(stderr,
  1338. X                        "unshar: found no shell commands after 'cut' in %s\n",fn);
  1339. X                    return(0);
  1340. X                }
  1341. X
  1342. X                if(*buf != '\n') break;
  1343. X            }
  1344. X
  1345. X            /* Win if line starts with a comment character of lower case letter */
  1346. X            if(*buf == '#' || *buf == ':' || (('a' <= *buf) && ('z' >= *buf)))
  1347. X            { 
  1348. X                fseek(fil,pos,0);
  1349. X                return(1);
  1350. X            }
  1351. X
  1352. X            /* Cut here message lied to us */
  1353. X            fprintf(stderr,"unshar: %s is probably not a shell archive,\n",fn);
  1354. X            fprintf(stderr,"        the 'cut' line was followed by: %s",buf);
  1355. X            return(0);
  1356. X        }
  1357. X    }
  1358. X}
  1359. X
  1360. X/*****************************************************************
  1361. X * stlmatch  --  match leftmost part of string
  1362. X *
  1363. X * Usage:  i = stlmatch (big,small)
  1364. X *    int i;
  1365. X *    char *small, *big;
  1366. X *
  1367. X * Returns 1 iff initial characters of big match small exactly;
  1368. X * else 0.
  1369. X *
  1370. X * HISTORY
  1371. X * 18-May-82 Michael Mauldin (mlm) at Carnegie-Mellon University
  1372. X *      Ripped out of CMU lib for Rog-O-Matic portability
  1373. X * 20-Nov-79  Steven Shafer (sas) at Carnegie-Mellon University
  1374. X *    Rewritten for VAX from Ken Greer's routine.
  1375. X *
  1376. X *  Originally from klg (Ken Greer) on IUS/SUS UNIX
  1377. X *****************************************************************/
  1378. X
  1379. Xint stlmatch(big,small)
  1380. Xchar *small,*big;
  1381. X{ 
  1382. X    register char *s,*b;
  1383. X    s = small;
  1384. X    b = big;
  1385. X    do
  1386. X    { 
  1387. X        if(*s == '\0')
  1388. X            return(1);
  1389. X    }  while(*s++ == *b++);
  1390. X    return(0);
  1391. X}
  1392. X
  1393. X/*****************************************************************
  1394. X * smatch: Given a data string and a pattern containing one or
  1395. X * more embedded stars (*) (which match any number of characters)
  1396. X * return true if the match succeeds, and set res[i] to the
  1397. X * characters matched by the 'i'th *.
  1398. X *****************************************************************/
  1399. X
  1400. Xsmatch(dat,pat,res)
  1401. Xregister char *dat,*pat,**res;
  1402. X{ 
  1403. X    register char *star = 0,*starend,*resp;
  1404. X    int nres = 0;
  1405. X
  1406. X    while(1)
  1407. X    { 
  1408. X        if(*pat == '*')
  1409. X        { 
  1410. X            star = ++pat;                  /* Pattern after * */
  1411. X            starend = dat;                  /* Data after * match */
  1412. X            resp = res[nres++];              /* Result string */
  1413. X            *resp = '\0';                  /* Initially null */
  1414. X        }
  1415. X        else if(*dat == *pat)              /* Characters match */
  1416. X        { 
  1417. X            if(*pat == '\0')              /* Pattern matches */
  1418. X                return(1);
  1419. X            pat++;                      /* Try next position */
  1420. X            dat++;
  1421. X        }
  1422. X        else
  1423. X        { 
  1424. X            if(*dat == '\0')              /* Pattern fails - no more */
  1425. X                return(0);                  /* data */
  1426. X            if(star == 0)                  /* Pattern fails - no * to */
  1427. X                return(0);                  /* adjust */
  1428. X            pat = star;                  /* Restart pattern after * */
  1429. X            *resp++ = *starend;              /* Copy character to result */
  1430. X            *resp = '\0';                  /* null terminate */
  1431. X            dat = ++starend;                  /* Rescan after copied char */
  1432. X        }
  1433. X    }
  1434. X}
  1435. X
  1436. X/*****************************************************************
  1437. X * Addendum: quit subroutine (print a message and exit)
  1438. X *****************************************************************/
  1439. X
  1440. Xquit(status,message)
  1441. Xint status;
  1442. Xchar *message;
  1443. X{
  1444. X    fprintf(stderr,message);
  1445. X    exit(status);
  1446. X}
  1447. X
  1448. X/*****************************************************************
  1449. X * Public Domain getopt routine
  1450. X *****************************************************************/
  1451. X
  1452. X/*
  1453. X * get option letter from argument vector
  1454. X */
  1455. Xint opterr = 1;        /* useless, never set or used */
  1456. Xint optind = 1;        /* index into parent argv vector */
  1457. Xint optopt;            /* character checked for validity */
  1458. Xchar *optarg;        /* argument associated with option */
  1459. X
  1460. X#define BADCH    (int)'?'
  1461. X#define EMSG    ""
  1462. X#define tell(s)    fputs(*nargv,stderr);fputs(s,stderr); \
  1463. X        fputc(optopt,stderr);fputc('\n',stderr);return(BADCH);
  1464. X
  1465. Xgetopt(nargc,nargv,ostr)
  1466. Xint nargc;
  1467. Xchar **nargv,*ostr;
  1468. X{
  1469. X    static char *place = EMSG;    /* option letter processing */
  1470. X    register char *oli;        /* option letter list index */
  1471. X    char *strchr();
  1472. X
  1473. X    if(!*place)
  1474. X    {            /* update scanning pointer */
  1475. X        if(optind >= nargc || *(place = nargv[optind]) != '-' || !*++place)
  1476. X            return(EOF);
  1477. X        if(*place == '-')
  1478. X        {    /* found "--" */
  1479. X            ++optind;
  1480. X            return(EOF);
  1481. X        }
  1482. X    }                /* option letter okay? */
  1483. X    if((optopt = (int)*place++) == (int)':' || !(oli = strchr(ostr,optopt)))
  1484. X    {
  1485. X        if(!*place) ++optind;
  1486. X        tell(": illegal option -- ");
  1487. X    }
  1488. X    if(*++oli != ':')
  1489. X    {        /* don't need argument */
  1490. X        optarg = (char *)0;
  1491. X        if(!*place) ++optind;
  1492. X    }
  1493. X    else 
  1494. X    {                /* need an argument */
  1495. X        if(*place) optarg = place;    /* no white space */
  1496. X        else if(nargc <= ++optind)
  1497. X        {    /* no arg */
  1498. X            place = EMSG;
  1499. X            tell(": option requires an argument -- ");
  1500. X        }
  1501. X        else optarg = nargv[optind];    /* white space */
  1502. X        place = EMSG;
  1503. X        ++optind;
  1504. X    }
  1505. X    return(optopt);            /* dump back option letter */
  1506. X}
  1507. X/* vi: set tabstop=4 shiftwidth=4: */
  1508. SHAR_EOF
  1509. chmod 0644 unshar.c || echo "restore of unshar.c fails"
  1510. if [ $TOUCH = can ]
  1511. then
  1512.     touch -am 0403210990 unshar.c
  1513. fi
  1514. # ============= uushar.c ==============
  1515. echo "x - extracting uushar.c (Text)"
  1516. sed 's/^X//' << 'SHAR_EOF' > uushar.c &&
  1517. X/* CHK=0x46B4 */
  1518. X#include <stdio.h>
  1519. X#include <sys/types.h>
  1520. X#include <sys/stat.h>
  1521. X
  1522. X/* ENC is the basic 1 character encoding function to make a char printing */
  1523. X#define ENC(c) ((((c) & 077) + ' ') | ((c & 077) == 0 ? 0100 : 0))
  1524. X
  1525. Xencode (in, out)
  1526. X    FILE *in;
  1527. X    FILE *out;
  1528. X{
  1529. X    char  buf[80];
  1530. X    int  i, n;
  1531. X
  1532. X    for (;;)
  1533. X    {
  1534. X    /* 1 (up to) 45 character line */
  1535. X    n = fr (in, buf, 45);
  1536. X    putc (ENC (n), out);
  1537. X
  1538. X    for (i = 0; i < n; i += 3)
  1539. X        outdec (&buf[i], out);
  1540. X
  1541. X    putc ('\n', out);
  1542. X    if (n <= 0)
  1543. X        break;
  1544. X    }
  1545. X}
  1546. X
  1547. X/*
  1548. X * output one group of 3 bytes, pointed at by p, on file f.
  1549. X */
  1550. Xoutdec (p, f)
  1551. X    char *p;
  1552. X    FILE *f;
  1553. X{
  1554. X    int  c1, c2, c3, c4;
  1555. X
  1556. X    c1 = *p >> 2;
  1557. X    c2 = (*p << 4) & 060 | (p[1] >> 4) & 017;
  1558. X    c3 = (p[1] << 2) & 074 | (p[2] >> 6) & 03;
  1559. X    c4 = p[2] & 077;
  1560. X    putc (ENC (c1), f);
  1561. X    putc (ENC (c2), f);
  1562. X    putc (ENC (c3), f);
  1563. X    putc (ENC (c4), f);
  1564. X}
  1565. X
  1566. X/* fr: like read but stdio */
  1567. Xint
  1568. X     fr (fp, buf, cnt)
  1569. X    FILE *fp;
  1570. X    char *buf;
  1571. X    int  cnt;
  1572. X{
  1573. X    int  c, i;
  1574. X
  1575. X    for (i = 0; i < cnt; i++)
  1576. X    {
  1577. X    c = getc (fp);
  1578. X    if (c == EOF)
  1579. X        return (i);
  1580. X    buf[i] = c;
  1581. X    }
  1582. X    return (cnt);
  1583. X}
  1584. X/* vi: set tabstop=4 shiftwidth=4: */
  1585. SHAR_EOF
  1586. chmod 0644 uushar.c || echo "restore of uushar.c fails"
  1587. if [ $TOUCH = can ]
  1588. then
  1589.     touch -am 0330002690 uushar.c
  1590. fi
  1591. # ============= who@where.c ==============
  1592. echo "x - extracting who@where.c (Text)"
  1593. sed 's/^X//' << 'SHAR_EOF' > who@where.c &&
  1594. X/* CHK=0xBAD4 */
  1595. X/*+-------------------------------------------------------------------------
  1596. X    who@where.c - find out who i am & where i am
  1597. X    ...!gatech!kd4nc!n4hgf!wht (wht%n4hgf@gatech.edu)
  1598. X--------------------------------------------------------------------------*/
  1599. X/*+:EDITS:*/
  1600. X/*:04-03-1990-19:55-wht@n4hgf-get rid of complicated who_am_i */
  1601. X/*:04-01-1990-13:30-pat@rwing-use utsname.nodename instead of sysname */
  1602. X/*:04-02-1990-12:12-wht@n4hgf-sigh... some pwd.h dont declare functions */
  1603. X/*:03-29-1990-18:23-wht@n4hgf-add automatic sequent support */
  1604. X/*:03-28-1990-15:24-wht@n4hgf-creation */
  1605. X
  1606. X#include <stdio.h>
  1607. X#include <sys/types.h>
  1608. X#include <pwd.h>
  1609. X
  1610. X/* assume system v unless otherwise fixed */
  1611. X#if (defined(pyr) || defined(vax) || defined(sequent)) && !defined(BSD42)
  1612. X#define BSD42
  1613. X#endif
  1614. X#if defined(sun)    /* this miscreant doesn't exactly fit BSD or SYSV */
  1615. X#undef BSD42
  1616. X#undef SYS5
  1617. X#endif
  1618. X#if !defined(BSD42) && !defined(sun)
  1619. X#define SYS5
  1620. X#endif
  1621. X
  1622. X#if defined(sun) || defined(BSD42)
  1623. X#define strchr    index
  1624. X#define strrchr    rindex
  1625. X#endif
  1626. X
  1627. X#if !defined(SYS5) || defined(sun)
  1628. X#include <sys/time.h>
  1629. Xextern int errno;
  1630. X#else
  1631. X#include <sys/utsname.h>
  1632. X#include <time.h>
  1633. X#endif    /* system dependencies */
  1634. X
  1635. X/*+-------------------------------------------------------------------------
  1636. X    who_am_i() - get user name
  1637. X--------------------------------------------------------------------------*/
  1638. Xchar *
  1639. Xwho_am_i()
  1640. X{
  1641. X    struct passwd *getpwuid();
  1642. X    struct passwd *passwd;
  1643. X    passwd = getpwuid(getuid());
  1644. X    (void)endpwent();
  1645. X    if(passwd == (struct passwd *)0)
  1646. X        return("???");
  1647. X    return(passwd->pw_name);
  1648. X
  1649. X}    /* end of who_am_i */
  1650. X
  1651. X/*+-------------------------------------------------------------------------
  1652. X    where_am_i() - do uname, gethostname, or read file (/etc/systemid)
  1653. X--------------------------------------------------------------------------*/
  1654. Xchar *
  1655. Xwhere_am_i()
  1656. X{
  1657. X#if defined(M_SYS5)    /* SCO UNIX or XENIX */
  1658. XFILE *fpsid = fopen("/etc/systemid","r");
  1659. Xstatic char s20[20];
  1660. X    if(!fpsid)
  1661. X        return("???");
  1662. X    fgets(s20,sizeof(s20),fpsid);
  1663. X    fclose(fpsid);
  1664. X    s20[strlen(s20) - 1] = 0;
  1665. X    return(s20);
  1666. X#else /* M_SYS5 */
  1667. X#if defined(SYS5)
  1668. Xstatic struct utsname where_i_am;
  1669. X    uname(&where_i_am);
  1670. X    return(where_i_am.nodename);
  1671. X#else /* SYS5 */
  1672. Xstatic char where_i_am[64];
  1673. X    gethostname(where_i_am,sizeof(where_i_am));
  1674. X    return(where_i_am);
  1675. X#endif /* SYS5 */
  1676. X#endif /* M_SYS5 */
  1677. X}    /* end of where_am_i */
  1678. X
  1679. X/*+-------------------------------------------------------------------------
  1680. X    who_where(buf)
  1681. X--------------------------------------------------------------------------*/
  1682. Xchar *
  1683. Xwho_where(buf)
  1684. Xchar *buf;
  1685. X{
  1686. Xstatic char ww[64];
  1687. X
  1688. X    if(!buf)
  1689. X        buf = ww;
  1690. X    strcpy(buf,who_am_i());
  1691. X    strcat(buf,"@");
  1692. X    strcat(buf,where_am_i());
  1693. X}    /* end of who_where */
  1694. X
  1695. X/* vi: set tabstop=4 shiftwidth=4: */
  1696. X/* end of who@where.c */
  1697. SHAR_EOF
  1698. chmod 0644 who@where.c || echo "restore of who@where.c fails"
  1699. if [ $TOUCH = can ]
  1700. then
  1701.     touch -am 0406145790 who@where.c
  1702. fi
  1703. exit 0
  1704.  
  1705. -------------------------------------------------------------------
  1706. Warren Tucker, TuckerWare  gatech!n4hgf!wht or wht%n4hgf@gatech.edu
  1707. Sforzando (It., sfohr-tsahn'-doh).  A direction to perform the tone
  1708. or chord with special stress, or marked and sudden emphasis.
  1709.