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

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