home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 1 / 1795 < prev    next >
Encoding:
Internet Message Format  |  1990-12-28  |  38.3 KB

  1. From: rhg@cpsolv.CPS.COM (Richard H. Gumpertz)
  2. Newsgroups: alt.sources
  3. Subject: shar 3.43 part 2 of 2
  4. Message-ID: <537@cpsolv.CPS.COM>
  5. Date: 8 Sep 90 18:00:38 GMT
  6.  
  7. Submitted-by: rhg@cpsolv.cps.com
  8. Archive-name: shar3.43/part02
  9.  
  10. ---- Cut Here and feed the following to sh ----
  11. #!/bin/sh
  12. # This is part 02 of shar3.43
  13. # ============= shar.c ==============
  14. if test -f 'shar.c' -a X"$1" != X"-c"; then
  15.     echo 'x - skipping shar.c (File already exists)'
  16. else
  17. echo 'x - extracting shar.c (Text)'
  18. sed 's/^X//' << 'SHAR_EOF' > 'shar.c' &&
  19. Xchar *revision = "3.43";
  20. Xchar RCS_ID[] = "$Header: /u/rhg/src/shar/shar.c,v 3.43 90/08/13 07:50:34 rhg Exp $";
  21. X/*
  22. X** shar.c
  23. X
  24. X  Defined functions:
  25. X    gen_mkdir(path)
  26. X    gen_mkdir_script(path)
  27. X    setTOUCH()
  28. X    walktree(rtn,rootname)
  29. X    header(argc,argv)
  30. X    helpuser()
  31. X    main(argc,argv)
  32. X    mode_map(mode,mode_str)
  33. X    shar(file,RstrName)
  34. X
  35. X*/
  36. X/*+:EDITS:*/
  37. X/*:08-06-1990-00:40-rhg@cps.com-revised Cut message to be more explanatory */
  38. X/*:08-05-1990-14:04-rhg@cps.com-merged Rname into walktree */
  39. X/*:08-05-1990-12:11-rhg@cps.com-added walktree & support for sharing dirs */
  40. X/*:08-05-1990-09:05-rhg@cps.com-change -Bn, -t, and -b to -bn, -T, and -B */
  41. X/*:08-04-1990-15:31-rhg@cps.com-added -Bn to set compress -bn (default 12) */
  42. X/*:08-04-1990-15:31-rhg@cps.com-changed shar3_???_.tmp to _shar_???_.tmp */
  43. X/*:08-04-1990-15:22-rhg@cps.com-added check for "exit 0" under OptPREFIX */
  44. X/*:08-04-1990-14:32-rhg@cps.com-added -m to generate TOUCH (default off) */
  45. X/*:08-04-1990-14:18-rhg@cps.com-reversed the meaning of -x and deleted -O */
  46. X/*:06-14-1990-14:48-rhg@cps.com-made Split and eXists compatible.
  47. X/*:06-14-1990-14:18-rhg@cps.com-made -x the default and added -O
  48. X/*:06-14-1990-12:44-rhg@cps.com-always terminate the && and report failures
  49. X/*:06-14-1990-12:28-rhg@cps.com-clear mkdir_already between -l files
  50. X/*:06-14-1990-12:14-rhg@cps.com-change PREFIX from a #define to an int variable.
  51. X/*:04-19-1990-22:49-rhg@cps.com-get rid of "set" so "sh sharfil -c" will work */
  52. X/*:04-19-1990-21:52-rhg@cps.com-add -F to clear OptPREFIX */
  53. X/*:04-18-1990-08:49-rhg@cps.com-add OptPREFIX (for now, always on) */
  54. X/*:07-09-1990-19:24-wht@n4hgf-back to fgrep amc -- fits more -m touches */
  55. X/*:07-01-1990-18:37-wht@n4hgf-wait() needed after fork() */
  56. X/*:05-19-1990-02:47-wht@n4hgf-change fgrep amc to mmdd */
  57. X/*:05-16-1990-01:53-wht@n4hgf-Archive-name had extra period sometimes */
  58. X/*:05-10-1990-20:39-wht@n4hgf-altos does not not like at-sign in filenames */
  59. X/*:05-10-1990-13:38-wht@n4hgf-add -V Vanilla mode */
  60. X/*:05-07-1990-00:06-wht@n4hgf-test all mallocs for Purity Of Essence */
  61. X/*:05-07-1990-00:06-wht@n4hgf-add -S switch */
  62. X/*:05-05-1990-01:37-relay.EU.net!rivm!a3-dont assume vax is running BSD */
  63. X/*:04-18-1990-02:01-wht@n4hgf-3.20 rhg@cps.com did all the NICE work */
  64. X/*:04-17-1990-14:30-rhg@cps.com-pretty up if-then-else-fi in shar file */
  65. X/*:04-17-1990-12:13-rhg@cps.com-add Split and renamed old -l to -L */
  66. X/*:04-17-1990-12:13-rhg@cps.com-add -c option to shar file execution */
  67. X/*:04-17-1990-11:20-rhg@cps.com-simplify TOUCH logic in shar file */
  68. X/*:04-17-1990-10:27-rhg@cps.com-create setTOUCH to avoid duplicate code */
  69. X/*:04-17-1990-04:43-rhg@cps.com-add missing && to commands in shar file(s) */
  70. X/*:04-17-1990-02:03-rhg@cps.com-add Compress */
  71. X/*:04-16-1990-17:08-rhg@cps.com-add AvoidPipes as well as code to use pipes */
  72. X/*:04-03-1990-20:09-wht@n4hgf-3.11 */
  73. X/*:04-01-1990-13:20-pat@rwing-correct case on M option in getopt() call */
  74. X/*:04-01-1990-13:50-pat@rwing-change defaults on -v, -w to be on */
  75. X/*:03-29-1990-18:23-wht@n4hgf-add automatic sequent support */
  76. X/*:03-28-1990-15:56-wht@n4hgf-add mode and length net.bandwidth chrome */
  77. X/*:03-28-1990-14:23-wht@n4hgf-correct some runtime diagnostics */
  78. X/*:11-14-1989-02:21-wht-SHAR_EOF was botched if last file char not newline */
  79. X/*:11-02-1989-14:11-wht-add touch -am */
  80. X
  81. X/*
  82. X Shar puts readable text files together in a package
  83. X from which they are easy to extract.
  84. X earlier attribution wht@n4hgf has:    decvax!microsof!uw-beave!jim
  85. X                                    (James Gosling at CMU)
  86. X*/
  87. X/*
  88. X *    I have made several mods to this program:
  89. X *
  90. X *    1) the -----Cut Here-----... now preceds the script.
  91. X *    2) the cat has been changed to a sed which removes a prefix
  92. X *    character from the beginning of each line of the extracted
  93. X *    file, this prefix character is added to each line of the archived
  94. X *    files and is not the same as the first character of the
  95. X *    file delimeter.
  96. X *    3) added several options:
  97. X *        -c    - add the -----Cut Here-----... line.
  98. X *        -d'del' - change the file delimeter to del.
  99. X *        -s    - cause the resulting script to print the wc of
  100. X *              the orignal file and the wc of the extracted
  101. X *              file.
  102. X *
  103. X *                Michael A. Thompson
  104. X *                Dalhousie University
  105. X *                Halifax, N.S., Canada.
  106. X */
  107. X
  108. X/*
  109. X *    I, too, have been hacking this code. This is the version on sixhub
  110. X *        bill davidsen (davidsen@sixhub.uucp)
  111. X *
  112. X *    - added support for binary files
  113. X *    - automatic creation of limited size multiple file archives,
  114. X *      each of which may be unpacked separately, and with sequence
  115. X *      checking.
  116. X *    - support for mixed text and binary files
  117. X *    - preserve file permissions
  118. X *    - restore to filename rather than pathname
  119. X *
  120. X */
  121. X/*
  122. X *  One good hack deserves another ... this version generates shell
  123. X *  code which attempts to create missing directories
  124. X *  handle deviants sun, vax, pyr (pyramid), SCO XENIX/UNIX automatically
  125. X *  for sequent, add -DBSD42
  126. X *  force Verbose on
  127. X *  if unsharing system's touch Sys V compatible (allows touch -m),
  128. X *  restore file dates
  129. X *  -n switch puts an alpha "name" in header
  130. X *  -a (if also -n) puts "Submitted-by:" & "Archive-name: <name>/part##
  131. X *  use getopt
  132. X *  as well as some other chrome-plated junque
  133. X *  ...!gatech!emory!tridom!wht (wht%n4hgf@gatech.edu) Warren Tucker
  134. X *
  135. X *  3.11 - Fri Apr  6 14:21:51 EDT 1990
  136. X *  With due deference to davidsen@sixhub, more changes..... copies
  137. X *  of this, like 3.10,  were mailed to him:
  138. X *  From wht  Fri Apr  6 15:14:30 1990 remote from n4hgf
  139. X *  Received: by n4hgf.UUCP (smail2.5-UNIX/386 5.3.2)
  140. X *      id AA01781; 6 Apr 90 15:14:30 EDT (Fri)
  141. X *  Date: Fri, 6 Apr 90 15:14:30 EDT
  142. X *  X-Mailer: Mail User's Shell (6.5 4/17/89)
  143. X *  From: wht@n4hgf (Warren Tucker)
  144. X *  To: davidsen@sixhub
  145. X *  Subject: shar 3.11
  146. X *  X-Bang-Reply-to: gatech!n4hgf!wht -or- emory!tridom!n4hgf!wht
  147. X *  Reply-to: wht%n4hgf@gatech.edu
  148. X *  Message-Id: <9004061514.AA01781@n4hgf.UUCP>
  149. X *
  150. X *  1. changes suggested by pat@rwing (Pat Myrto) and silvert@cs.dal.ca
  151. X *  (Bill Silvert)
  152. X *  2. fixes to who_am_i code in who@where.c
  153. X *
  154. X *  3.20 - Wed Apr 18 01:58:32 EDT 1990
  155. X *  changes were made per edit notes by
  156. XFrom: gatech!mailrus!uunet!cpsolv.CPS.COM!rhg (Richard H. Gumpertz)
  157. X *  ...!gatech!n4hgf!wht (wht%n4hgf@gatech.edu) Warren Tucker
  158. X *
  159. X */
  160. X
  161. X#include <stdio.h>
  162. X#include <sys/types.h>
  163. X#include <time.h>
  164. X#include <sys/stat.h>
  165. X#include <ctype.h>
  166. X
  167. X/* assume system v unless otherwise fixed */
  168. X#if (defined(pyr) || defined(vax) || defined(sequent)) && !defined(BSD42) && !defined(SYS5)
  169. X#define BSD42
  170. X#endif
  171. X#if defined(sun)    /* this miscreant doesn't exactly fit BSD or SYSV */
  172. X#undef BSD42
  173. X#undef SYS5
  174. X#endif
  175. X#if !defined(BSD42) && !defined(sun) && !defined(SYS5)
  176. X#define SYS5
  177. X#endif
  178. X
  179. X#if defined(sun) || defined(BSD42)
  180. X#define strchr    index
  181. X#define strrchr    rindex
  182. X#endif
  183. X
  184. Xchar *strchr();
  185. Xchar *strrchr();
  186. X#ifdef __STDC__ /* my concession to ANSI-pansiness */
  187. Xvoid *malloc();
  188. X#else
  189. Xchar *malloc();
  190. X#endif
  191. XFILE *fdopen();
  192. XFILE *popen();
  193. X
  194. X#define    DELIM        "SHAR_EOF"/* put after each file */
  195. X#define PREFIX1        'X'    /* goes in front of each line */
  196. X#define PREFIX2        'Y'    /* goes in front of each line if Delim[0] == PREFIX1 */
  197. X#define WC            "wc -c <"
  198. X
  199. Xint PREFIX = PREFIX1;    /* Character to get at the beginning of each line */
  200. X
  201. Xint Archive_name = 0;    /* option to generate "Archive-name:" headers */
  202. Xint Verbose = 1;        /* option to provide append/extract feedback */
  203. Xint Wc_c = 1;            /* option to provide wc checking */
  204. Xchar *Delim = DELIM;    /* pointer to delimiter string */
  205. Xint OptPREFIX = 1;        /* suppress PREFIX unless 1st char forces it */
  206. Xint Cut = 0;            /* option to provide cut mark */
  207. Xchar *CutMessage = "---- Cut Here and feed the following to sh ----\n";
  208. Xint Binary = 0;            /* flag for binary files */
  209. Xint AvoidPipes = 0;        /* use temp file instead of pipe to feed uudecode, etc.
  210. X                           (better error detection at expense of disk space) */
  211. Xint Vanilla = 0;        /* no Brown-Shirt mode */
  212. Xint Touch = 0;            /* generate $TOUCH commands */
  213. Xint Compress = 0;        /* run input files through compress (requires Binary) */
  214. Xint CompressBits = 12;    /* -b option to compress */
  215. Xint Mixed = 0;            /* mixed text and binary files */
  216. Xint eXists = 1;            /* check if file exists */
  217. Xint InterOW = 0;        /* interactive overwrite */
  218. Xint PosParam = 0;        /* allow positional parameters */
  219. Xint FileStrip;            /* strip directories from filenames */
  220. X#ifdef    DEBUG
  221. Xint de_bug = 0;            /* switch for debugging on */
  222. X#define DeBug(f,v) if (de_bug) printf(f, v)
  223. X#else    /* normal compile */
  224. X#define DeBug(f,v)        /* do nothing */
  225. X#endif
  226. X
  227. XFILE *fpout = stdout;
  228. Xint shar();
  229. Xunsigned limit = 0;
  230. Xint Split = 0;            /* Split files in the middle */
  231. Xlong ftell();
  232. Xlong TypePos;            /* position for archive type message */
  233. Xlong EndHeadPos;        /* position for first file in the shar file */
  234. Xchar outname[50];        /* base for output filename */
  235. Xchar filename[50];        /* actual output filename */
  236. Xchar *sharname = (char *)0;
  237. Xchar *submitter = (char *)0;
  238. Xint filenum = 0;        /* output file # */
  239. Xstruct stat fst;        /* check file type, access */
  240. X
  241. Xmain(argc,argv)
  242. Xchar **argv;
  243. X{
  244. Xint status = 0;
  245. Xint stdin_file_list = 0;
  246. Xchar *oname;
  247. Xint c;
  248. Xextern int optind;
  249. Xextern char *optarg;
  250. X
  251. X    while((c = getopt(argc,argv,"VmSvwd:BTCb:xXcfMpPFas:n:l:L:o:h")) != -1)
  252. X    {
  253. X        switch(c)
  254. X        {
  255. X        case 'V':
  256. X            Vanilla = 1;
  257. X            break;
  258. X        case 'm':
  259. X            Touch = 1;
  260. X            break;
  261. X        case 'S':
  262. X            stdin_file_list = 1;
  263. X            break;
  264. X        case 'v':
  265. X            Verbose = 0;
  266. X            break;
  267. X        case 'w':
  268. X            Wc_c = 0;
  269. X            break;
  270. X        case 'd':
  271. X            Delim = optarg;
  272. X            PREFIX = (Delim[0] == PREFIX1 ? PREFIX2 : PREFIX1);
  273. X            break;
  274. X        case 'B': /* binary files */
  275. X            Binary = 1;
  276. X            Compress = 0;
  277. X            break;
  278. X        case 'T': /* text mode */
  279. X            Binary = 0;
  280. X            Compress = 0;
  281. X            break;
  282. X        case 'b': /* Compress bits */
  283. X            CompressBits = atoi(optarg);
  284. X            /* fall through to -C */
  285. X        case 'C': /* Compress */
  286. X            Binary = 1;
  287. X            Compress = 1;
  288. X            break;
  289. X        case 'x': /* don't worry whether the file exist */
  290. X            eXists = 0;
  291. X            break;
  292. X        case 'X': /* ask the user whether to overwrite existing files */
  293. X            InterOW = 1;
  294. X            eXists = 1;
  295. X            break;
  296. X        case 'c':
  297. X            Cut = 1;
  298. X            break;
  299. X        case 'f': /* filenames only */
  300. X            FileStrip = 1;
  301. X            break;
  302. X        case 'M': /* mixed text and binary */
  303. X            Mixed = 1;
  304. X            break;
  305. X        case 'p': /* allow positional parameters */
  306. X            PosParam = 1;
  307. X            break;
  308. X        case 'P': /* use temp files instead of pipes in the shar file */
  309. X            AvoidPipes = 1;
  310. X            break;
  311. X        case 'F': /* force PREFIX to be put out even if not required */
  312. X            OptPREFIX = 0;
  313. X            break;
  314. X        case 'l': /* soft size limit in k */
  315. X            if((limit = atoi(optarg)) > 1)
  316. X                --limit;
  317. X            Split = 0;
  318. X            DeBug("Soft limit %dk\n",limit);
  319. X            break;
  320. X        case 'L': /* hard size limit in k */
  321. X            if((limit = atoi(optarg)) > 1)
  322. X                --limit;
  323. X            Split = (limit != 0);
  324. X            AvoidPipes = 1;
  325. X            DeBug("Hard limit %dk\n",limit);
  326. X            break;
  327. X        case 'n': /* name of archive */
  328. X            sharname = optarg;
  329. X            break;
  330. X        case 's': /* submitter */
  331. X            submitter = optarg;
  332. X            break;
  333. X        case 'a': /* generate Archive-name: headers */
  334. X            Archive_name = 1;
  335. X            break;
  336. X        case 'o': /* specify output file */
  337. X            oname = optarg;
  338. X            strcpy(outname,oname);
  339. X            strcat(outname,".");
  340. X            filenum = 1;
  341. X            strcpy(filename,outname);
  342. X            strcat(filename,"01");
  343. X            fpout = fopen(filename,"w");
  344. X            if(!fpout)
  345. X            { /* creation error */
  346. X                perror("can't create output file");
  347. X                exit(1);
  348. X            }
  349. X            break;
  350. X#ifdef    DEBUG
  351. X        case '$': /* totally undocumented $ option, debug on */
  352. X            de_bug = 1;
  353. X            break;
  354. X#endif
  355. X        default: /* invalid option */
  356. X        case 'h': /* help */
  357. X            helpuser();
  358. X            break;
  359. X        }
  360. X    }
  361. X
  362. X    if(Vanilla)
  363. X    {
  364. X        fprintf(stderr,"Vanilla mode disabling years of progress :-)\n");
  365. X        Wc_c = 0;
  366. X        OptPREFIX = 0;
  367. X#ifdef V_AVOIDPIPES    /* pipes are benign and only used with uudecode anyway */
  368. X        AvoidPipes = 1;
  369. X#endif /* V_AVOIDPIPES */
  370. X#ifdef V_NOFORCE    /* If the user specifies non-defaults, let him have them */
  371. X#else
  372. X        Touch = 0;
  373. X        InterOW = 0;
  374. X        if(Binary || Mixed || Compress || PosParam)
  375. X            fprintf(stderr,"WARNING: non-Text storage options overridden.\n");
  376. X        Binary = 0;
  377. X        Mixed = 0;
  378. X        Compress = 0;
  379. X        PosParam = 0;
  380. X#endif /* V_NOFORCE */
  381. X    }
  382. X
  383. X    if(stdin_file_list)
  384. X    {
  385. X        char stdin_buf[258];
  386. X        argc = 0;
  387. X        if(!(argv = (char **)malloc(1024 * sizeof(char *))))
  388. X            goto MEMORY_ERROR;
  389. X        stdin_buf[0] = 0;
  390. X        while(fgets(stdin_buf,sizeof(stdin_buf),stdin))
  391. X        {
  392. X            if(argc == 1024)
  393. X            {
  394. X                fprintf(stderr,"max files from stdin is 1024!\n");
  395. X                exit(1);
  396. X            }
  397. X            if(stdin_buf[0])
  398. X                stdin_buf[strlen(stdin_buf) - 1] = 0;
  399. X            if(!(argv[argc] = malloc(strlen(stdin_buf) + 1)))
  400. X            {
  401. XMEMORY_ERROR: /* NOT likely, but free software must pure as snow! */
  402. X                fprintf(stderr,"out of memory handling stdin input at %d\n",
  403. X                    argc);
  404. X                exit(1);
  405. X            }
  406. X            strcpy(argv[argc],stdin_buf);
  407. X            ++argc;
  408. X            stdin_buf[0] = 0;
  409. X        }
  410. X        optind = 0;
  411. X    }
  412. X
  413. X    if(optind >= argc)
  414. X    {
  415. X        fprintf(stderr,"shar: No input files\n");
  416. X        helpuser();
  417. X        exit(1);
  418. X    }
  419. X
  420. X    if(Archive_name && !sharname)
  421. X    {
  422. X        fprintf(stderr,"shar: -n must accompany -a\n");
  423. X        helpuser();
  424. X        exit(1);
  425. X    }
  426. X
  427. X    if(!submitter)
  428. X    {
  429. X        if(!(submitter = malloc(128)))
  430. X        {
  431. X            fprintf(stderr,"memory allocation failed\n"); /* NOT likely */
  432. X            exit(1);
  433. X        }
  434. X        who_where(submitter);
  435. X    }
  436. X
  437. X    if(header(argc-optind,&argv[optind]))
  438. X        exit(2);
  439. X
  440. X    if(InterOW)
  441. X    {
  442. X        Verbose = 1;
  443. X        fputs("wish=\n",fpout);
  444. X        if(Archive_name)
  445. X        {
  446. X            fprintf(stderr,
  447. X                "PLEASE do not submit -X shars to the usenet or other\n");
  448. X            fprintf(stderr,
  449. X                "public networks.  They will cause problems.\n");
  450. X        }
  451. X    }
  452. X
  453. X    EndHeadPos = ftell(fpout);
  454. X
  455. X    for( ; optind < argc; ++optind)
  456. X    { /* process positional parameters and files */
  457. X        if(PosParam)
  458. X        {        /* allow -B and -T and -C inline */
  459. X            if(strcmp(argv[optind],"-B") == 0)
  460. X            { /* set binary */
  461. X                Binary = 1;
  462. X                Compress = 0;
  463. X                continue;
  464. X            }
  465. X            if(strcmp(argv[optind],"-T") == 0)
  466. X            { /* set mode text */
  467. X                Binary = 0;
  468. X                Compress = 0;
  469. X                continue;
  470. X            }
  471. X            if(strcmp(argv[optind],"-C") == 0)
  472. X            { /* set compress */
  473. X                Binary = 1;
  474. X                Compress = 1;
  475. X                continue;
  476. X            }
  477. X        }
  478. X        status += walktree(shar,argv[optind]);
  479. X    }
  480. X
  481. X    /* delete the sequence file, if any */
  482. X    if(Split && filenum > 1)
  483. X    {
  484. X        fputs("rm -f _shar_seq_.tmp\n",fpout);
  485. X        fputs("echo You have unpacked the last part\n",fpout);
  486. X        if(!Verbose)
  487. X            fprintf(stderr,"Created %d files\n",filenum);
  488. X    }
  489. X    fputs("exit 0\n",fpout);
  490. X    exit(status);
  491. X}
  492. X
  493. X/*+-----------------------------------------------------------------------
  494. X    mode_map(mode,mode_str)    build drwxrwxrwx string
  495. X------------------------------------------------------------------------*/
  496. Xchar *
  497. Xmode_map(mode,mode_str)
  498. Xunsigned short mode;
  499. Xchar *mode_str;
  500. X{
  501. Xregister unsigned ftype = mode & S_IFMT;
  502. Xregister char *rtn;
  503. Xstatic char result[12];
  504. X
  505. X    rtn = (mode_str == (char *)0) ? result : mode_str;
  506. X
  507. X    /*          drwxrwxrwx */
  508. X    /*          0123456789 */
  509. X    strcpy(rtn,"----------");
  510. X
  511. X#ifdef THIS_IS_NOT_NEEDED_FOR_SHAR
  512. X    switch(ftype)
  513. X    {
  514. X        case S_IFIFO:    *rtn = 'p'; break; /* FIFO (named pipe) */
  515. X        case S_IFDIR:    *rtn = 'd'; break; /* directory */
  516. X        case S_IFCHR:    *rtn = 'c'; break; /* character special */
  517. X        case S_IFBLK:    *rtn = 'b'; break; /* block special */
  518. X        case S_IFREG:    *rtn = '-'; break; /* regular */
  519. X
  520. X#if defined(sun) | defined(BSD42)
  521. X        case S_IFLNK:    *rtn = 'l'; break; /* symbolic link */
  522. X        case S_IFSOCK:    *rtn = 's'; break; /* socket */
  523. X#endif
  524. X
  525. X#if defined (SYS5)
  526. X        case S_IFNAM:                        /* name space entry */
  527. X            if(mode & S_INSEM)                /* semaphore */
  528. X            {
  529. X                *rtn = 's';
  530. X                break;
  531. X            }
  532. X            if(mode & S_INSHD)                /* shared memory */
  533. X            {
  534. X                *rtn = 'm';
  535. X                break;
  536. X            }
  537. X#endif
  538. X
  539. X        default:        *rtn = '?'; break;    /* ??? */
  540. X    }
  541. X#endif /* THIS_IS_NOT_NEEDED_FOR_SHAR */
  542. X
  543. X    if(mode & 000400) *(rtn + 1) = 'r';
  544. X    if(mode & 000200) *(rtn + 2) = 'w';
  545. X    if(mode & 000100) *(rtn + 3) = 'x';
  546. X    if(mode & 004000) *(rtn + 3) = 's';
  547. X    if(mode & 000040) *(rtn + 4) = 'r';
  548. X    if(mode & 000020) *(rtn + 5) = 'w';
  549. X    if(mode & 000010) *(rtn + 6) = 'x';
  550. X    if(mode & 002000) *(rtn + 6) = 's';
  551. X    if(mode & 000004) *(rtn + 7) = 'r';
  552. X    if(mode & 000002) *(rtn + 8) = 'w';
  553. X    if(mode & 000001) *(rtn + 9) = 'x';
  554. X    if(mode & 001000) *(rtn + 9) = 't';
  555. X
  556. X    return(rtn);
  557. X
  558. X}    /* end of mode_map */
  559. X
  560. Xvoid
  561. XsetTOUCH()
  562. X{
  563. X    if(Touch)
  564. X    {
  565. X        fputs("if touch 2>&1 | fgrep 'amc' > /dev/null\n",fpout);
  566. X        fputs(" then TOUCH=touch\n",fpout);
  567. X        fputs(" else TOUCH=true\n",fpout);
  568. X        fputs("fi\n",fpout);
  569. X    }
  570. X} /* end of setTOUCH */
  571. X
  572. X#ifdef NO_WALKTREE
  573. X
  574. Xint
  575. Xwalktree(rtn,file)                /* dummy walktree */
  576. Xint (*rtn)(/*file,rname*/);    /* may also assume fst is set */
  577. Xchar *file;
  578. X{
  579. X    register char *rname;
  580. X
  581. X    if(stat(file,&fst))
  582. X    {
  583. X        fprintf(stderr,"shar: Can't access %s\n",file);
  584. X        return(1);
  585. X    }
  586. X
  587. X    if(FileStrip)
  588. X    { /* use just the filename */
  589. X        rname = file + strlen(file);
  590. X        while(rname > file && *rname != '/')
  591. X            --rname;
  592. X        if(*rname == '/')
  593. X            ++rname;
  594. X    }
  595. X    else
  596. X        rname = file;
  597. X    if(!strncmp(rname,"./",2) && rname[2])
  598. X        rname += 2;
  599. X
  600. X    return((*rtn)(file,rname));
  601. X}
  602. X
  603. X#else /* NO_WALKTREE*/
  604. X
  605. X#include <dirent.h>            /* Doug Gwyn's dirent routines */
  606. XDIR *opendir();
  607. Xstruct dirent *readdir();
  608. Xint closedir();
  609. X
  610. Xint
  611. Xwalkdown(rtn,file,filelen,rname)
  612. Xint (*rtn)(/*file,rname*/);    /* may also assume fst is set */
  613. Xchar *file, *rname;            /* *rname must be *file + n where n < filelen */
  614. Xint filelen;
  615. X{
  616. X    DIR *dirp;
  617. X    struct dirent *dp;
  618. X
  619. X    if(stat(file,&fst))
  620. X    {
  621. X        fprintf(stderr,"shar: Can't access %s\n",file);
  622. X        return(1);
  623. X    }
  624. X
  625. X    if((fst.st_mode & S_IFMT) != S_IFDIR)
  626. X        return((*rtn)(file,rname));
  627. X
  628. X    if(!(dirp = opendir(file)))
  629. X    {
  630. X        fprintf(stderr,"shar: unable to open directory %s",file);
  631. X        return(1);
  632. X    }
  633. X
  634. X    if(!strcmp(rname,"."))
  635. X        rname += 2;                /* avoid "./xxx" when sharing "." */
  636. X
  637. X    while((dp = readdir(dirp)))
  638. X        if (strcmp(dp->d_name,".") && strcmp(dp->d_name,".."))
  639. X        {
  640. X            int newlen;
  641. X
  642. X            if((newlen = filelen + 1 + strlen(dp->d_name)) >= MAXNAMLEN)
  643. X            {
  644. X                fprintf(stderr,"shar: file name too long: %s/%s\n",
  645. X                        file,dp->d_name);
  646. X                return(1);
  647. X            }
  648. X            sprintf(file + filelen,"/%s",dp->d_name);
  649. X
  650. X            if(walkdown(rtn,file,newlen,rname))
  651. X                return(1);
  652. X
  653. X            file[filelen] = '\0';    /* in case we print any error messages */
  654. X        }
  655. X
  656. X    if(closedir(dirp))
  657. X    {
  658. X        fprintf(stderr,"shar: unable to close directory %s",file);
  659. X        return(1);
  660. X    }
  661. X}
  662. X
  663. Xint
  664. Xwalktree(rtn,rootname)                /* real walktree */
  665. Xint (*rtn)(/*file,rname*/);    /* may also assume fst is set */
  666. Xchar *rootname;
  667. X{
  668. X    char file[MAXNAMLEN];
  669. X    int filelen;
  670. X    register char *rname;
  671. X
  672. X    if((filelen = strlen(rootname)) >= MAXNAMLEN)
  673. X    {
  674. X        fprintf(stderr,"shar: file name too long: %s\n",rootname);
  675. X        return(1);
  676. X    }
  677. X    strcpy(file,rootname);
  678. X
  679. X    if(FileStrip)
  680. X    { /* use just the filename */
  681. X        rname = file + filelen;
  682. X        while(rname > file && *rname != '/')
  683. X            --rname;
  684. X        if(*rname == '/')
  685. X            ++rname;
  686. X    }
  687. X    else
  688. X        rname = file;
  689. X    if(!strncmp(rname,"./",2) && rname[2])
  690. X        rname += 2;
  691. X
  692. X    return(walkdown(rtn,file,filelen,rname));
  693. X}
  694. X
  695. X#endif /* NO_WALKTREE */
  696. X
  697. Xint
  698. Xonecheck(file,rname)
  699. Xchar *file, *rname;
  700. X{
  701. X    if(access(file,04))
  702. X    {
  703. X        fprintf(stderr,"shar: Can't access %s\n",file);
  704. X        return(1);
  705. X    }
  706. X
  707. X    return(0);
  708. X}
  709. X
  710. Xint
  711. Xoneheader(file,rname)
  712. Xchar *file, *rname;
  713. X{
  714. X    fprintf(fpout,"# %6ld %s %s\n",fst.st_size,
  715. X        mode_map(fst.st_mode & ~(S_ISUID|S_ISGID|S_ISVTX),(char *)0),rname);
  716. X    return(0);
  717. X}
  718. X
  719. Xheader(argc,argv)
  720. Xchar **argv;
  721. X{
  722. Xint i;
  723. XFILE *fpsource;    /* pipe temp */
  724. Xchar s128[128];
  725. Xlong now;
  726. Xstruct tm *utc;
  727. Xstruct tm *gmtime();
  728. X
  729. X    /* see if any conflicting options */
  730. X    if(limit && !filenum)
  731. X    { /* can't rename what you don't have */
  732. X        fprintf(stderr,"Can't use -l or -L option without -o\n");
  733. X        helpuser();
  734. X        return(1);
  735. X    }
  736. X
  737. X    for(i = 0; i < argc; i++)
  738. X    { /* skip positional parameters */
  739. X        if(PosParam &&
  740. X            (strcmp(argv[i],"-B") == 0 ||
  741. X             strcmp(argv[i],"-T") == 0 ||
  742. X             strcmp(argv[i],"-C") == 0))
  743. X            continue;
  744. X
  745. X        if(walktree(onecheck,argv[i]))
  746. X            return(1);
  747. X    }
  748. X
  749. X    if(Archive_name)
  750. X    {
  751. X        fprintf(fpout,"Submitted-by: %s\n",submitter);
  752. X        fprintf(fpout,"Archive-name: %s%s%02d\n\n",
  753. X            sharname,(strchr(sharname,'/')) ? "" : "/part",
  754. X            (filenum) ? filenum : 1);
  755. X    }
  756. X
  757. X    if(Cut)
  758. X        fputs(CutMessage,fpout);
  759. X    fputs("#!/bin/sh\n",fpout);
  760. X    if(sharname)
  761. X        fprintf(fpout,"# This is %s, a shell archive (shar %s)\n",
  762. X            sharname,revision);
  763. X    else
  764. X        fprintf(fpout,"# This is a shell archive (shar %s)\n",revision);
  765. X
  766. X    time(&now);
  767. X    utc = gmtime(&now);
  768. X    fprintf(fpout,"# made %02d/%02d/%04d %02d:%02d UTC by %s\n",
  769. X        utc->tm_mon + 1,utc->tm_mday,utc->tm_year + 1900,
  770. X        utc->tm_hour,utc->tm_min,
  771. X        submitter);
  772. X
  773. X#if defined(SYS5)
  774. X    if(!(fpsource = popen("/bin/pwd","r")))
  775. X        return(-1);
  776. X    fgets(s128,sizeof(s128),fpsource);
  777. X    s128[strlen(s128) - 1] = 0;
  778. X    fclose(fpsource);
  779. X#else
  780. X#if defined(BSD42) || defined(sun)
  781. X    getwd(s128);
  782. X#else
  783. X#include "Need_conditional_compile_fix"
  784. X#endif
  785. X#endif
  786. X    fprintf(fpout,"# Source directory %s\n",s128);
  787. X
  788. X    fprintf(fpout,"#\n# existing files %s\n",
  789. X        (eXists) ? "will NOT be overwritten unless -c is specified" 
  790. X            : ((InterOW) ? "MAY be overwritten"
  791. X                : "WILL be overwritten"));
  792. X
  793. X    if(InterOW)
  794. X        fputs("# The unsharer will be INTERACTIVELY queried.\n",fpout);
  795. X
  796. X    if(Vanilla)
  797. X    {
  798. X        fputs("# This format requires very little intelligence at unshar time.\n",fpout);
  799. X        fputs("# ",fpout);
  800. X        if(eXists || Split)
  801. X            fputs("\"if test\", ",fpout);
  802. X        if(Split)
  803. X            fputs("\"cat\", \"rm\", ",fpout);
  804. X        fputs("\"echo\", \"true\", and \"sed\" may be needed.\n",fpout);
  805. X    }
  806. X
  807. X    if(Split)
  808. X    { /* may be split, explain */
  809. X        fputs("#\n",fpout);
  810. X        TypePos = ftell(fpout);
  811. X        fprintf(fpout,"%-75s\n%-75s\n","#","#");
  812. X    }
  813. X
  814. X    fputs("#\n# This shar contains:\n",fpout);
  815. X    fputs("# length  mode       name\n",fpout);
  816. X    fputs("# ------ ---------- ------------------------------------------\n",
  817. X        fpout);
  818. X    for(i = 0; i < argc; i++)
  819. X    { /* output names of files but not parameters */
  820. X        if(PosParam &&
  821. X            (strcmp(argv[i],"-B") == 0 ||
  822. X             strcmp(argv[i],"-T") == 0 ||
  823. X             strcmp(argv[i],"-C") == 0))
  824. X            continue;
  825. X        if(walktree(oneheader,argv[i]))
  826. X            exit(1);
  827. X    }
  828. X    fputs("#\n",fpout);
  829. X
  830. X    setTOUCH();
  831. X
  832. X    if(Split)
  833. X    { /* now check the sequence */
  834. X        fputs("if test -r _shar_seq_.tmp; then\n",fpout);
  835. X        fputs("\techo 'Must unpack archives in sequence!'\n",fpout);
  836. X        fputs("\techo Please unpack part `cat _shar_seq_.tmp` next\n",fpout);
  837. X        fputs("\texit 1\nfi\n",fpout);
  838. X    }
  839. X    return(0);
  840. X}
  841. X
  842. X#define MAX_MKDIR_ALREADY    128    /* ridiculously enough */
  843. Xchar *mkdir_already[MAX_MKDIR_ALREADY];
  844. Xint mkdir_already_count = 0;
  845. X
  846. Xvoid
  847. Xgen_mkdir(path)
  848. Xchar *path;
  849. X{
  850. Xregister int ialready;
  851. Xchar *cptr;
  852. X
  853. X/* if already generated code for this dir creation, don't do again */
  854. X    for(ialready = 0; ialready < mkdir_already_count; ialready++)
  855. X    {
  856. X        if(!strcmp(path,mkdir_already[ialready]))
  857. X            return;
  858. X    }
  859. X
  860. X/* haven't done this one */
  861. X    if(mkdir_already_count == MAX_MKDIR_ALREADY)
  862. X    {
  863. X        fprintf(stderr,"too many directories for mkdir generation\n");
  864. X        exit(255);
  865. X    }
  866. X    if(!(cptr = mkdir_already[mkdir_already_count++] = malloc(strlen(path)+1)))
  867. X    {
  868. X        fprintf(stderr,"out of memory for mkdir generation\n");
  869. X        exit(255);
  870. X    }
  871. X    strcpy(cptr,path);
  872. X
  873. X/* generate the text */
  874. X    fprintf(fpout,"if test ! -d '%s'; then\n",path);
  875. X    if(Verbose)
  876. X        fprintf(fpout,"    echo 'x - creating directory %s'\n",path);
  877. X    fprintf(fpout,"    mkdir '%s'\n",path);
  878. X    fputs("fi\n",fpout);
  879. X
  880. X}    /* end of gen_mkdir */
  881. X
  882. Xvoid
  883. Xgen_mkdir_script(path)
  884. Xregister char *path;
  885. X{
  886. Xregister char *cptr;
  887. X
  888. X    for(cptr = strchr(path,'/'); cptr; cptr = strchr(cptr + 1,'/'))
  889. X    {
  890. X        /* avoid empty string if leading or double '/' */
  891. X        if(cptr == path || *(cptr - 1) == '/')
  892. X            continue;
  893. X        /* omit '.' */
  894. X        if((*(cptr - 1) == '.') && ((cptr == path + 1) || (*(cptr - 2) == '/')))
  895. X            continue;
  896. X        *cptr = 0;                /* temporarily terminate string */
  897. X        gen_mkdir(path);
  898. X        *cptr = '/';
  899. X    }
  900. X}    /* end of gen_mkdir_script */
  901. X
  902. Xint
  903. Xshar(file,RstrName)
  904. Xchar *file, *RstrName;
  905. X{
  906. Xchar line[BUFSIZ];
  907. XFILE *fpsource;
  908. Xlong cursize,remaining,ftell();
  909. Xint split = 0;        /* file split flag */
  910. Xchar *filetype;        /* text or binary */
  911. Xstruct tm *lt;
  912. Xchar *filename_base;
  913. X
  914. X    /* check to see that this is still a regular file  and readable */
  915. X    if((fst.st_mode & S_IFMT) != S_IFREG)
  916. X    { /* this is not a regular file */
  917. X        fprintf(stderr,"shar: %s is not a regular file\n",file);
  918. X        return(1);
  919. X    }
  920. X    if(access(file,04))
  921. X    {
  922. X        fprintf(stderr,"shar: Can't access %s\n",file);
  923. X        return(1);
  924. X    }
  925. X
  926. X    /* if limit set, get the current output length */
  927. X    if(limit)
  928. X    {
  929. X        cursize = ftell(fpout);
  930. X        remaining = (limit * 1024L) - cursize;
  931. X        DeBug("In shar: remaining size %ld\n",remaining);
  932. X        
  933. X        if(!Split && cursize > EndHeadPos &&
  934. X            (Binary ? fst.st_size + fst.st_size/3 : fst.st_size) > remaining)
  935. X        { /* change to another file */
  936. X            DeBug("Newfile, remaining %ld, ",remaining);
  937. X            DeBug("limit still %d\n",limit);
  938. X
  939. X            /* close the "&&" and report an error if any of the above failed */
  940. X            fprintf(fpout,"true || echo 'restore of %s failed'\n",RstrName);
  941. X
  942. X            fprintf(fpout, "echo End of part %d, continue with part %d\n",
  943. X                filenum,filenum + 1);
  944. X            fputs("exit 0\n",fpout);
  945. X
  946. X            fclose(fpout);
  947. X
  948. X            /* Clear mkdir_already in case the user unshars out of order */
  949. X            while (mkdir_already_count > 0)
  950. X                free(mkdir_already[--mkdir_already_count]);
  951. X
  952. X            /* form the next filename */
  953. X            sprintf(filename,"%s%02d",outname,++filenum);
  954. X            fpout = fopen(filename,"w");
  955. X            if(Verbose)
  956. X                fprintf(stderr,"Starting file %s\n",filename);
  957. X
  958. X            if(Archive_name)
  959. X            {
  960. X                fprintf(fpout,"Submitted-by: %s\n",submitter);
  961. X                fprintf(fpout,"Archive-name: %s%s%02d\n\n",
  962. X                    sharname,(strchr(sharname,'/')) ? "" : "/part",
  963. X                    (filenum) ? filenum : 1);
  964. X            }
  965. X
  966. X            if(Cut)
  967. X                fputs(CutMessage,fpout);
  968. X            if(!(filename_base = strrchr(filename,'/')))
  969. X                filename_base = filename;
  970. X            else
  971. X                ++filename_base;
  972. X
  973. X            fputs("#!/bin/sh\n",fpout);
  974. X            fprintf(fpout,"# This is part %02d of %s\n",
  975. X                filenum,(sharname) ? sharname : "a multipart archive");
  976. X
  977. X            setTOUCH();
  978. X
  979. X            EndHeadPos = ftell(fpout);
  980. X        }
  981. X    }
  982. X
  983. X    fprintf(fpout,"# ============= %s ==============\n",RstrName);
  984. X
  985. X    gen_mkdir_script(RstrName);
  986. X
  987. X    /* if mixed, determine the file type */
  988. X    if(Mixed)
  989. X    {
  990. X        int count;
  991. X        sprintf(line,"file %s | egrep -c \"text|shell\"",file);
  992. X        fpsource = popen(line,"r");
  993. X        fscanf(fpsource,"%d",&count);
  994. X        pclose(fpsource);
  995. X        Binary = (count != 1);
  996. X    }
  997. X
  998. X    if(Binary)
  999. X    { /* fork a uuencode process */
  1000. X        static int pid,pipex[2];
  1001. X
  1002. X        pipe(pipex);
  1003. X        fflush(fpout);
  1004. X
  1005. X        if(pid = fork())
  1006. X        { /* parent, create a file to read */
  1007. X            if(pid < 0)
  1008. X            {
  1009. X                fprintf(stderr,"could not fork!\n");
  1010. X                exit(1);
  1011. X            }
  1012. X            close(pipex[1]);
  1013. X            fpsource = fdopen(pipex[0],"r");
  1014. X            filetype = (Compress ? "Compressed" : "Binary");
  1015. X        }
  1016. X        else
  1017. X        { /* start writing the pipe with encodes */
  1018. X            FILE *outptr;
  1019. X
  1020. X            if(Compress)
  1021. X            {
  1022. X                sprintf(line, "compress -b%d < '%s'", CompressBits, file);
  1023. X                fpsource = popen(line, "r");
  1024. X            }
  1025. X            else
  1026. X                fpsource = fopen(file, "rb");
  1027. X            outptr = fdopen(pipex[1],"w");
  1028. X            fprintf(outptr,"begin 600 %s\n",
  1029. X                (Compress ? "_shar_cmp_.tmp" : RstrName));
  1030. X            encode(fpsource,outptr);
  1031. X            fprintf(outptr,"end\n");
  1032. X            if(Compress)
  1033. X                pclose(fpsource);
  1034. X            else
  1035. X            {
  1036. X                fclose(fpsource);
  1037. X            }
  1038. X            exit(0);
  1039. X        }
  1040. X    }
  1041. X    else
  1042. X    {
  1043. X        fpsource = fopen(file,"r");
  1044. X        filetype = "Text";
  1045. X    }
  1046. X
  1047. X    if(fpsource)
  1048. X    {
  1049. X        /* protect existing files */
  1050. X        if(eXists)
  1051. X        {
  1052. X            fprintf(fpout,"if test -f '%s' -a X\"$1\" != X\"-c\"; then\n",
  1053. X                RstrName);
  1054. X            if(InterOW)
  1055. X            {
  1056. X                fputs("\tcase $wish in\n",fpout);
  1057. X                fprintf(fpout,"\tA*|a*) echo 'x - overwriting %s';;\n",
  1058. X                    RstrName);
  1059. X                fprintf(fpout,
  1060. X        "\t*) echo '? - overwrite %s -- [No], [Y]es, [A]ll, [Q]uit? '\n",
  1061. X                    RstrName);
  1062. X                fputs("\t\tread wish;;\n",fpout);
  1063. X                fputs("\tesac\n",fpout);
  1064. X                fputs("\tcase $wish in\n",fpout);
  1065. X                fputs("\tQ*|q*) echo aborted; exit 86;;\n",fpout);
  1066. X                fputs("\tA*|a*|Y*|y*) x=Y;;\n",fpout);
  1067. X                fputs("\t*) x=N;;\n",fpout);
  1068. X                fputs("\tesac\n",fpout);
  1069. X                fputs("else\n",fpout);
  1070. X                fputs("\tx=Y\n",fpout);
  1071. X                fputs("fi\n",fpout);
  1072. X                fputs("if test $x != Y; then\n",fpout);
  1073. X                fprintf(fpout,"\techo 'x - skipping %s'\n",RstrName);
  1074. X            }
  1075. X            else
  1076. X                fprintf(fpout,"\techo 'x - skipping %s (File already exists)'\n",
  1077. X                    RstrName);
  1078. X            if (Split)
  1079. X                fputs("\trm -f _shar_wnt_.tmp\n",fpout);
  1080. X            fputs("else\n",fpout);
  1081. X            if (Split)
  1082. X                fputs("> _shar_wnt_.tmp\n",fpout);    
  1083. X        }
  1084. X
  1085. X        fprintf(stderr,"shar: saving %s (%s)\n",file,filetype);
  1086. X        if(Verbose)
  1087. X        { /* info on archive and unpack */
  1088. X            fprintf(fpout,"echo 'x - extracting %s (%s)'\n",
  1089. X                RstrName,filetype);
  1090. X        }
  1091. X        if(Binary)
  1092. X        { /* run sed through uudecode (via temp file if might get split) */
  1093. X            fprintf(fpout, "sed 's/^%c//' << '%s' %s &&\n",
  1094. X                   PREFIX,Delim,
  1095. X                (AvoidPipes ? "> _shar_tmp_.tmp" : "| uudecode"));
  1096. X        }
  1097. X        else
  1098. X        { /* just run it into the file */
  1099. X            fprintf(fpout,"sed 's/^%c//' << '%s' > '%s' &&\n",
  1100. X                PREFIX,Delim,RstrName);
  1101. X        }
  1102. X        while(fgets(line,BUFSIZ,fpsource))
  1103. X        { /* output a line and test the length */
  1104. X            if(OptPREFIX && isgraph(line[0]) && line[0] != PREFIX
  1105. X#ifdef STRNCMP_IS_FAST
  1106. X               && strncmp(line,"exit 0",6))    /* See "unshar -e" */
  1107. X#else /* STRNCMP_IS_FAST */
  1108. X               && (line[0] != 'e' || strncmp(line,"exit 0",6))) /* unshar -e */
  1109. X#endif /* STRNCMP_IS_FAST */
  1110. X                fputs(line,fpout);
  1111. X            else
  1112. X            {
  1113. X                fprintf(fpout,"%c%s",PREFIX,line);
  1114. X                --remaining;    /* count PREFIX (in case Split is in effect) */
  1115. X            }
  1116. X#ifdef MSDOS    /* This probably doesn't work but accounts for some old code */
  1117. X            if(Split && (remaining -= strlen(line) + 1) < 0)    /* 1 extra for CR */
  1118. X#else /* MSDOS */
  1119. X            if(Split && (remaining -= strlen(line)) < 0)
  1120. X#endif /* MSDOS */
  1121. X            { /* change to another file */
  1122. X                DeBug("Newfile, remaining %ld, ",remaining);
  1123. X                DeBug("limit still %d\n",limit);
  1124. X
  1125. X                if(line[strlen(line) - 1] != '\n')
  1126. X                    fputc('\n',fpout);
  1127. X
  1128. X                fprintf(fpout,"%s\n",Delim);
  1129. X
  1130. X                /* close the "&&" and report an error if any of the above failed */
  1131. X                fprintf(fpout,"true || echo 'restore of %s failed'\n",RstrName);
  1132. X
  1133. X                if (eXists)
  1134. X                    fputs("fi\n",fpout);
  1135. X
  1136. X                if(Verbose)
  1137. X                { /* output some reassurance */
  1138. X                    fprintf(fpout, "echo 'End of %s part %d'\n",
  1139. X                        (sharname) ? sharname : "",filenum);
  1140. X                    fprintf(fpout, "echo 'File %s is continued in part %d'\n",
  1141. X                        RstrName,filenum + 1);
  1142. X                }
  1143. X                else
  1144. X                    fprintf(fpout,
  1145. X                        "echo 'End of part %d, continue with part %d'\n",
  1146. X                        filenum,filenum + 1);
  1147. X                fprintf(fpout,"echo %d > _shar_seq_.tmp\n",filenum + 1);
  1148. X                fputs("exit 0\n",fpout);
  1149. X
  1150. X                if(filenum == 1)
  1151. X                { /* rewrite the info lines on the firstheader */
  1152. X                    fseek(fpout,TypePos,0);
  1153. X                    fprintf(fpout,"%-75s\n%-75s\n",
  1154. X                        "# This is part 1 of a multipart archive",
  1155. X                        "# do not concatenate these parts, unpack them in order with /bin/sh");
  1156. X                }
  1157. X                fclose(fpout);
  1158. X
  1159. X                /* form the next filename */
  1160. X                sprintf(filename,"%s%02d",outname,++filenum);
  1161. X                fpout = fopen(filename,"w");
  1162. X
  1163. X                if(Archive_name)
  1164. X                {
  1165. X                    fprintf(fpout,"Submitted-by: %s\n",submitter);
  1166. X                    fprintf(fpout,"Archive-name: %s%s%02d\n\n",
  1167. X                        sharname,(strchr(sharname,'/')) ? "" : "/part",
  1168. X                        (filenum) ? filenum : 1);
  1169. X                }
  1170. X
  1171. X                if(Cut)
  1172. X                    fputs(CutMessage,fpout);
  1173. X                if(!(filename_base = strrchr(filename,'/')))
  1174. X                    filename_base = filename;
  1175. X                else
  1176. X                    ++filename_base;
  1177. X
  1178. X                fputs("#!/bin/sh\n",fpout);
  1179. X                fprintf(fpout,"# this is %s (part %d of %s)\n",
  1180. X                    filename_base,
  1181. X                    filenum,
  1182. X                    (sharname) ? sharname : "a multipart archive");
  1183. X                fputs(
  1184. X        "# do not concatenate these parts, unpack them in order with /bin/sh\n",
  1185. X                    fpout);
  1186. X                fprintf(fpout,"# file %s continued\n#\n",RstrName);
  1187. X
  1188. X                setTOUCH();
  1189. X                
  1190. X                fputs("if test ! -r _shar_seq_.tmp; then\n",fpout);
  1191. X                fputs("\techo 'Please unpack part 1 first!'\n",fpout);
  1192. X                fputs("\texit 1\nfi\n",fpout);
  1193. X                fputs("(read Scheck\n",fpout);
  1194. X                fprintf(fpout," if test \"$Scheck\" != %d; then\n",filenum);
  1195. X                fputs("\techo Please unpack part \"$Scheck\" next!\n",
  1196. X                    fpout);
  1197. X                fputs("\texit 1\n",fpout);
  1198. X                fputs(" else\n\texit 0\n fi\n",fpout);
  1199. X                fputs(") < _shar_seq_.tmp || exit 1\n",fpout);
  1200. X
  1201. X                if(eXists)
  1202. X                    if(Verbose)
  1203. X                    { /* keep everybody informed */
  1204. X                        fputs("if test ! -f _shar_wnt_.tmp; then\n",fpout);
  1205. X                        fprintf(fpout,"\techo 'x - still skipping %s'\n",
  1206. X                                RstrName);
  1207. X                        fputs("else\n",fpout);
  1208. X                    }
  1209. X                    else
  1210. X                        fputs("if test -f _shar_wnt_.tmp; then\n",fpout);
  1211. X
  1212. X                if(Verbose)
  1213. X                { /* keep everybody informed */
  1214. X                    fprintf(stderr,"Starting file %s\n",filename);
  1215. X                    fprintf(fpout,"echo 'x - continuing file %s'\n",RstrName);
  1216. X                }
  1217. X                fprintf(fpout,"sed 's/^%c//' << '%s' >> '%s' &&\n",
  1218. X                    PREFIX,Delim,
  1219. X                    (Binary ? "_shar_tmp_.tmp" : RstrName));
  1220. X                remaining = limit * 1024L;
  1221. X                split = 1;
  1222. X            }
  1223. X        }
  1224. X
  1225. X        (void) fclose(fpsource);
  1226. X        while(wait((int *)0) >= 0)
  1227. X            ;
  1228. X
  1229. X        if(line[strlen(line) - 1] != '\n')
  1230. X            fputc('\n',fpout);
  1231. X
  1232. X        fprintf(fpout,"%s\n",Delim);
  1233. X        if(split && Verbose)
  1234. X            fprintf(fpout,"echo 'File %s is complete' &&\n",RstrName);
  1235. X
  1236. X        /* if this file was uuencoded w/Split, decode it and drop the temp */
  1237. X        if(Binary && AvoidPipes)
  1238. X        {
  1239. X            if(Verbose)
  1240. X                fprintf(fpout,"echo 'uudecoding file %s' &&\n",RstrName);
  1241. X            fputs("uudecode < _shar_tmp_.tmp && rm -f _shar_tmp_.tmp &&\n",fpout);
  1242. X        }
  1243. X
  1244. X        /* if this file was compressed, uncompress it and drop the temp */
  1245. X        if(Compress)
  1246. X        {
  1247. X            if(Verbose)
  1248. X                fprintf(fpout,"echo 'uncompressing file %s' &&\n",RstrName);
  1249. X            fprintf(fpout,
  1250. X                "compress -d < _shar_cmp_.tmp > '%s' && rm -f _shar_cmp_.tmp &&\n",
  1251. X                RstrName);
  1252. X        }
  1253. X
  1254. X        if(Touch)
  1255. X        {
  1256. X            /* set the dates as they were */
  1257. X            lt = localtime(&fst.st_mtime);
  1258. X            fprintf(fpout,"$TOUCH -am %02d%02d%02d%02d%02d '%s' &&\n",
  1259. X                lt->tm_mon + 1,
  1260. X                lt->tm_mday,
  1261. X                lt->tm_hour,
  1262. X                lt->tm_min,
  1263. X                lt->tm_year,
  1264. X                RstrName);
  1265. X        }
  1266. X
  1267. X        if(Vanilla)
  1268. X        {
  1269. X            /* close the "&&" and report an error if any of the above failed */
  1270. X            fprintf(fpout,"true || echo 'restore of %s failed'\n",RstrName);
  1271. X        }
  1272. X        else
  1273. X        {
  1274. X            /* set the permissions as they were */
  1275. X            fprintf(fpout,"chmod %04o %s ||\n",
  1276. X                fst.st_mode & 00777,RstrName);
  1277. X
  1278. X            /* report an error if any of the above failed */
  1279. X            fprintf(fpout,"echo 'restore of %s failed'\n",RstrName);
  1280. X
  1281. X            if(Wc_c)
  1282. X            { /* validate the transferred file */
  1283. X                FILE *pfp;
  1284. X                char command[BUFSIZ];
  1285. X
  1286. X                sprintf(command,"%s '%s'",WC,file);
  1287. X                if((pfp = popen(command,"r")))
  1288. X                {
  1289. X                    char wc[BUFSIZ];
  1290. X
  1291. X                    fscanf(pfp,"%s",wc);
  1292. X                    fprintf(fpout,"Wc_c=\"`%s '%s'`\"\n",WC,RstrName);
  1293. X                    fprintf(fpout,"test %s -eq \"$Wc_c\" ||\n",wc);
  1294. X                    fprintf(fpout,
  1295. X                        "\techo '%s: original size %s, current size' \"$Wc_c\"\n",
  1296. X                        RstrName, wc);
  1297. X                    pclose(pfp);
  1298. X                }
  1299. X            }
  1300. X        }
  1301. X
  1302. X        /* if the exists option is in place close the if */
  1303. X        if(eXists)
  1304. X        {
  1305. X            if (Split)
  1306. X                fputs("rm -f _shar_wnt_.tmp\n",fpout);
  1307. X
  1308. X            fputs("fi\n",fpout);
  1309. X        }
  1310. X
  1311. X        return(0);
  1312. X    }
  1313. X    else
  1314. X    {
  1315. X        fprintf(stderr,"shar: Can't open %s (%s): ",file,filetype);
  1316. X        perror("");
  1317. X        return(1);
  1318. X    }
  1319. X}
  1320. X
  1321. X
  1322. Xchar *helpinfo[] =
  1323. X{
  1324. X    "-V  produce \"vanilla\" shars demanding little of the unshar environment",
  1325. X    "-v  verbose messages OFF while executing",
  1326. X    "-m  restore file modification dates & times with \"touch\" commands",
  1327. X    "-w  don't check with 'wc -c' after unpack",
  1328. X    "-a  generate Submitted-by: & Archive-name: headers",
  1329. X    "-nXXX   use XXX as the name of the archive (documentation)",
  1330. X    "-s  override automatically determined submitter name",
  1331. X    "-x  overwrite existing files without checking if they already exist",
  1332. X    "-X  interactively overwrite existing files (NOT FOR NET SHARS)",
  1333. X    "-B  treat all files as binary, use uuencode",
  1334. X    "-T  treat all files as text (default)",
  1335. X    "-C  compress and uuencode all files",
  1336. X    "-bXX    pass -bXX (default 12) to compress when compressing (implies -C)",
  1337. X    "-p  allow positional parameter options. The options \"-B\" and \"-T\"",
  1338. X    "    and \"-C\" may be embedded, and files to the right of the",
  1339. X    "    option will be processed in the specified mode",
  1340. X    "-M  mixed mode. Determine if the files are text or",
  1341. X    "    binary and archive correctly.",
  1342. X    "-P  use temp files instead of pipes in the shar file",
  1343. X    "-F  force the prefix character on every line (even if not required)",
  1344. X    "-c  start the shar with a cut line",
  1345. X    "-f  restore by filename only, rather than path",
  1346. X    "-dXXX   use XXX to delimit the files in the shar",
  1347. X    "-oXXX   (or -o XXX) output to file XXX.01 thru XXX.nn",
  1348. X    "-lXX    limit output file size to XXk bytes (but don't split files)",
  1349. X    "-LXX    limit output file size to XXk bytes (may split files)",
  1350. X    "-S      read files to wrap from stdin, ignoring argument line",
  1351. X    "\nThe -S option reads filenames one per line from stdin; input",
  1352. X    "format must be similar to 'find' output, except that if -p",
  1353. X    "is specified, -B, -T or -C may be used (on lines by themselves)",
  1354. X    "e.g., find . -type f -print | sort | shar -C -l50 -o /tmp/big",
  1355. X    "\nThe 'o' option is required if the 'l' or 'L' option is used",
  1356. X    "The 'n' option is required if the 'a' option is used",
  1357. X    "\n-a generates sharname/part## headers. If the -a argument contains",
  1358. X    "a '/', then /part is not appended",
  1359. X    "The automatic submitter name is trivial: essentially `whoami`@`uname`",
  1360. X    (char *)0
  1361. X};
  1362. X
  1363. Xhelpuser()
  1364. X{                /* output a command format message */
  1365. X    register char **ptr;
  1366. X    fprintf(stderr,
  1367. X        "shar %s\nusage: shar [ options ] file ...\n       shar -S [ options ]\n",
  1368. X        revision);
  1369. X    for(ptr = helpinfo; *ptr; ptr++)
  1370. X        fprintf(stderr,"%s\n",*ptr);
  1371. X
  1372. X    exit(1);
  1373. X}
  1374. X/* vi: set tabstop=4 shiftwidth=4: */
  1375. SHAR_EOF
  1376. chmod 0644 shar.c ||
  1377. echo 'restore of shar.c failed'
  1378. Wc_c="`wc -c < 'shar.c'`"
  1379. test 36835 -eq "$Wc_c" ||
  1380.     echo 'shar.c: original size 36835, current size' "$Wc_c"
  1381. fi
  1382. exit 0
  1383. -- 
  1384.   ==========================================================================
  1385.   | Richard H. Gumpertz    rhg@CPS.COM    (913) 642-1777 or (816) 891-3561 |
  1386.   | Computer Problem Solving, 8905 Mohawk Lane, Leawood, Kansas 66206-1749 |
  1387.   ==========================================================================
  1388.