home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume29 / unzip / part01 < prev    next >
Encoding:
Text File  |  1992-04-02  |  54.8 KB  |  1,655 lines

  1. Newsgroups: comp.sources.misc
  2. From: info-zip@cs.ucla.edu
  3. Subject:  v29i031:  unzip - Info-ZIP's portable UnZip v4.2, Part01/12
  4. Message-ID: <csm-v29i031=unzip.224424@sparky.IMD.Sterling.COM>
  5. X-Md4-Signature: 053cf105e87df231018565806bef5456
  6. Date: Fri, 3 Apr 1992 04:47:44 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: info-zip@cs.ucla.edu (Info-Zip)
  10. Posting-number: Volume 29, Issue 31
  11. Archive-name: unzip/part01
  12. Environment: Unix, VMS, OS/2, MS-DOS, Amiga, Macintosh
  13. Supersedes: unzip, Volume 19, Issues 96-101
  14.  
  15. This is unzip v4.2, a public distribution version of the Info-ZIP project's
  16. portable generic Unix unzip utility.  This version of unzip has been ported 
  17. to a wide array of Unix and other mainframes, minis, and micros (to include 
  18. MSDOS, Atari ST (kinda), and Macintosh).  Although highly compatible with 
  19. Phil Katz's PKZIP and PKUNZIP utilities of MSDOS fame, our objective has been 
  20. one of portability and other-than-MSDOS functionality.
  21.  
  22. BEFORE YOU ASK:  UnZip and its companion Zip utility can be found on many
  23. archive sites around the world.  The "archie" ftp database utility can be
  24. used to find a site near you (if you don't know how to use it, DON'T ASK
  25. US--check the Usenet groups news.newusers.questions or news.answers or some
  26. such).  The "official" Info-ZIP ftp site is valeria.cs.ucla.edu in /pub.
  27. The most heavily used US site is wuarchive.wustl.edu; Zip 1.0 can be found
  28. in /packages/compression/zip-1.0-export.tar.Z, and UnZip will probably be
  29. found in the same place.  Zip 1.0 is also at any comp.sources.misc archive
  30. site (volume 23) and, due to an oversight, in comp.sources.unix archives,
  31. too (most recent volume--24?).  Machine-specific archives and executables
  32. for both Zip and UnZip may be stored at wuarchive in /mirrors/misc/unix,
  33. /mirrors/misc/vaxvms, /mirrors/msdos/zip, etc.  See the bottom of Contents
  34. for locations of the decryption routines for Zip and UnZip.  The interna-
  35. tional sites listed there (and US mirrors thereof) will most likely have
  36. the rest of the Zip and UnZip packages, as well.
  37.  
  38. See unzip.1 or unzip.man for usage.  (No, there isn't a manual, per se.
  39. Dave Heiland is working on one, but it's a big job and he isn't done
  40. yet.)  See the Makefile (or the system-specific archives) for details 
  41. on how to compile for your system.  
  42.  
  43. If any changes are made to source, we'd appreciate them (context diff
  44. files only, please), with explanation as appropriate.
  45.  
  46. All bug reports and patches should go to zip-bugs@cs.ucla.edu, and sug-
  47. gestions for new features can be sent to info-zip@cs.ucla.edu (although
  48. we don't promise to use all suggestions).  If it's something which is
  49. manifestly useful, sending the required patches to zip-bugs directly is 
  50. likely to produce a quicker response than asking us to do it.  Those 
  51. directly responsible for updating the code are somewhat short on time 
  52. these days.  If you're considering a port, however, please check in with 
  53. Info-ZIP FIRST, since the code is constantly being updated behind the 
  54. scenes.  We'll arrange to send you the latest source.  The alternative 
  55. is the possibility that your hard work will be tucked away in a sub-
  56. archive and pretty much ignored.
  57.  
  58. If you'd like to keep up to date with our UnZip (and companion Zip
  59. utility) development, join the ranks of BETA testers, add your own
  60. thoughts and contributions, etc., send your request to
  61.  
  62.     Info-ZIP-Request@cs.ucla.edu
  63.  
  64. and Rich Wales'll add you to the Info-ZIP newsletter mailing list.
  65. --------------
  66. #! /bin/sh
  67. # This is a shell archive.  Remove anything before this line, then feed it
  68. # into a shell via "sh file" or similar.  To overwrite existing files,
  69. # type "sh file -c".
  70. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  71. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  72. # Contents:  README AMIGA ATARI ATARI/README.src MAC MSDOS MSDOS/bcc
  73. #   MSDOS/tcc OS2 VMS VMS/bilf VMS/crypt ship.c
  74. # Wrapped by kent@sparky on Mon Mar 30 01:45:50 1992
  75. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  76. echo If this archive is complete, you will see the following message:
  77. echo '          "shar: End of archive 1 (of 12)."'
  78. if test -f 'README' -a "${1}" != "-c" ; then 
  79.   echo shar: Will not clobber existing file \"'README'\"
  80. else
  81.   echo shar: Extracting \"'README'\" \(6487 characters\)
  82.   sed "s/^X//" >'README' <<'END_OF_FILE'
  83. XFile README for:
  84. X
  85. Xunzip42.zip    generic Unix/VMS/OS2/MSDOS/Mac/Amiga/Atari UnZip v4.2
  86. Xunzip42.zoo    same as above, but ZOO format
  87. Xunzip42.arc    same as above, but ARC format
  88. Xunzip42.tar.Z    same as above, but compressed tar format
  89. X
  90. XA public distribution version of the Info-ZIP project's generic UnZip
  91. Xutility; 20 March 1992.
  92. X__________________________________________________________________________
  93. X
  94. XBEFORE YOU ASK:  UnZip and its companion Zip utility can be found on many
  95. Xarchive sites around the world.  The "archie" ftp database utility can be
  96. Xused to find a site near you (if you don't know how to use it, DON'T ASK
  97. XUS--check the Usenet groups news.newusers.questions or news.answers or some
  98. Xsuch).  The "official" Info-ZIP ftp site is valeria.cs.ucla.edu in /pub.
  99. XThe most heavily used US site is wuarchive.wustl.edu; Zip 1.0 can be found
  100. Xin /packages/compression/zip-1.0-export.tar.Z, and UnZip will probably be
  101. Xfound in the same place.  Zip 1.0 is also at any comp.sources.misc archive
  102. Xsite (volume 23) and, due to an oversight, in comp.sources.unix archives,
  103. Xtoo (most recent volume--24?).  Machine-specific archives and executables
  104. Xfor both Zip and UnZip may be stored at wuarchive in /mirrors/misc/unix,
  105. X/mirrors/misc/vaxvms, /mirrors/msdos/zip, etc.  See the bottom of Contents
  106. Xfor locations of the decryption routines for Zip and UnZip.  The interna-
  107. Xtional sites listed there (and US mirrors thereof) will most likely have
  108. Xthe rest of the Zip and UnZip packages, as well.
  109. X__________________________________________________________________________
  110. X
  111. X
  112. XThis version of UnZip has been ported to a wide array of Unix and other
  113. Xmainframes, minis, and micros (including VMS, OS/2, Minix, MSDOS, Amiga,
  114. XAtari ST (kinda), and Macintosh).  Although highly compatible with Phil
  115. XKatz's PKZIP and PKUNZIP utilities of MSDOS fame, our objective has been
  116. Xone of portability and other-than-MSDOS functionality.  Features not found
  117. Xin the PKWare version include default extraction of directory trees (with
  118. Xa switch to defeat this, rather than the other way around); HPFS awareness
  119. Xfor the OS/2 version; and, of course, the ability to run on most of your
  120. Xfavorite operating systems.
  121. X
  122. XNew features in this version are detailed in the History file, but a
  123. Xcouple of them are worth comment.  Decryption (to accompany Zip 1.0's 
  124. Xencryption) is now supported (you still have to ftp the crypt.c source
  125. Xseparately, but that's explained in the Contents file).  It is a recent
  126. Xaddition, however, and there may be some rough edges in the compilation.
  127. XIf it fails, try adding (or removing) -DTERMIO to the compiler command.
  128. X(This is especially likely on System V machines--the error messages will
  129. Xsay things about sgtty being undefined in file_io.c.)  Once you get it
  130. Xto compile, everything should work well; it's only the compilation itself
  131. Xwhich may be a problem.  (The one known exception is for Crays; there is
  132. Xa bug in crypt.c 1.0.  A small patch [cray.dif] is included with UnZip
  133. X4.2.  The patch is unnecessary for later versions of crypt.c.)  Decryption
  134. Xis optional, of course, and there should be virtually no problems compil-
  135. Xing the export (non-decryption) version of UnZip.
  136. X
  137. XShip is also now included with the UnZip distribution.  It first appeared
  138. Xwith Zip 1.0 and is the preferred method for mailing binaries to and from
  139. XInfo-ZIP.  As it was added at the last minute, however, there are only
  140. Xmakefile targets in the main Makefile (for regular Unix, SysV, OS/2 and
  141. XMS-DOS).  Most people will already have Ship compiled with the Zip dis-
  142. Xtribution, so this shouldn't be a big problem.  Ship is likely to disap-
  143. Xpear again in the next release (it should be separately distributed by
  144. Xthen).
  145. X
  146. XThe new compression method in PKZIP 1.93a (deflation) is NOT supported
  147. Xyet and won't be until PKZIP 2.0 (or whatever) is officially released.
  148. XPKZ193A.EXE is a beta version of the software, and its compression format
  149. Xmay change before the official release.  We'll be ready when it does come 
  150. Xout, however.... :-)
  151. X
  152. XSee unzip.1 or unzip.man for usage.  (No, there isn't a manual, per se.
  153. XDave Heiland is working on one, but it's a big job and he isn't done
  154. Xyet.)  See Contents for an explanation of everything in the distribution,
  155. Xand BUGS for a list of what still doesn't work.  The History file lists
  156. Xwhat *did* get fixed and added this time; CONTRIBS lists who did it (not
  157. Xcomplete, but we're trying); and COPYING contains information on commer-
  158. Xcial usage, licensing, etc.  Basically such usage is prohibited at present,
  159. Xbut we're working on lifting that restriction.  So don't bug us unless you
  160. Xhave (legally) rewritten some or all of the code in question (check with
  161. Xus first, however, since we're also working on that as time permits).
  162. X
  163. XSee the Makefile (or the system-specific archives) for details on how to
  164. Xcompile for your system.  If you confirm a clean compile and execution
  165. Xon a unique system (i.e., one different from those in the makefiles), 
  166. Xplease provide Info-ZIP via e-mail with details as to your system type, 
  167. Xany changes required, what Makefile system was used, etc.
  168. X
  169. XIf any changes are made to source, we'd appreciate them (context diff
  170. Xfiles only, please), with explanation as appropriate.
  171. X
  172. XAll bug reports and patches should go to zip-bugs@cs.ucla.edu, and sug-
  173. Xgestions for new features can be sent to info-zip@cs.ucla.edu (although
  174. Xwe don't promise to use all suggestions).  If it's something which is
  175. Xmanifestly useful, sending the required patches to zip-bugs directly is 
  176. Xlikely to produce a quicker response than asking us to do it.  Those 
  177. Xdirectly responsible for updating the code are somewhat short on time 
  178. Xthese days.  If you're considering a port, however, please check in with 
  179. XInfo-ZIP FIRST, since the code is constantly being updated behind the 
  180. Xscenes.  We'll arrange to send you the latest source.  The alternative 
  181. Xis the possibility that your hard work will be tucked away in a sub-
  182. Xarchive and pretty much ignored.
  183. X
  184. XPlease don't send e-mail to me (I'm only the Coordinator), unless
  185. Xyou're requesting something special (e.g., a copy of the "No Feelthy ..."
  186. Xrules for source and change submission).
  187. X
  188. XIf you'd like to keep up to date with our UnZip (and companion Zip
  189. Xutility) development, join the ranks of BETA testers, add your own
  190. Xthoughts and contributions, etc., send your request to
  191. X
  192. X    Info-ZIP-Request@cs.ucla.edu
  193. X
  194. Xand Rich Wales'll add you to the Info-ZIP newsletter mailing list.
  195. X
  196. XDavid Kirschbaum
  197. XInfo-ZIP Coordinator
  198. X
  199. X(with some additions by Cavum Newtus)
  200. END_OF_FILE
  201.   if test 6487 -ne `wc -c <'README'`; then
  202.     echo shar: \"'README'\" unpacked with wrong size!
  203.   fi
  204.   # end of 'README'
  205. fi
  206. if test ! -d 'AMIGA' ; then
  207.     echo shar: Creating directory \"'AMIGA'\"
  208.     mkdir 'AMIGA'
  209. fi
  210. if test ! -d 'ATARI' ; then
  211.     echo shar: Creating directory \"'ATARI'\"
  212.     mkdir 'ATARI'
  213. fi
  214. if test -f 'ATARI/README.src' -a "${1}" != "-c" ; then 
  215.   echo shar: Will not clobber existing file \"'ATARI/README.src'\"
  216. else
  217.   echo shar: Extracting \"'ATARI/README.src'\" \(2944 characters\)
  218.   sed "s/^X//" >'ATARI/README.src' <<'END_OF_FILE'
  219. XUNZIP 4.1 source code for the Atari ST
  220. X======================================
  221. X
  222. XThe source code for UNZIP 4.1 (or later) is available through
  223. Xanonymous ftp from:
  224. X
  225. X    simtel20.army.mil    misc/unix/unzip41.*
  226. Xor    wuarchive.wustl.edu    mirrors/misc/unix/unzip41.*
  227. X
  228. XI have compiled unzip.prg with TURBO C 2.0 for the ATARI ST, probably
  229. Xthe best C compiler available for the Atari ST.
  230. X
  231. XMy modifications to unzip:
  232. X
  233. X1) ATARIST.PAT
  234. X    - an alignment problem in the data (unzip.c)
  235. X
  236. X    - set '\' as the path character for the Atari ST (mapname.c)
  237. X
  238. X    - additions to unzip.h so that Turbo C for the Atari ST is  happy.
  239. X      I think I didn't break anythig else, at least the Sun's version
  240. X      compiles just as before.
  241. X      I commented massively in unzip.h because the configuration
  242. X          is not well thought out.  The last time I generated the ST
  243. X          version I threw out all the mess, the result of which was that
  244. X          my version wasn't distributed.  I hope that will fit in better
  245. X          this time.  If anybody cares about the comments, just clean up
  246. X          the code (together with comments).
  247. X
  248. X2) OPTIMIZE.PAT
  249. X    This patch is general and not related to the Atari ST.
  250. X    It speeds up the processing by as much as 30% by
  251. X    eliminating many function calls, optimizing some
  252. X    macros and using a ULONG bitbuffer.  The claimed
  253. X    performance gain is on a Sun, using unzip -t some-file.
  254. X    I didn't measure the speed on the Atari ST.
  255. X
  256. X3) SYMLINK.PAT
  257. X    This applies to unix systems only.  Unzip does extract
  258. X    symbolic links correctly now.
  259. X
  260. X4) UNIXBLAN.PAT
  261. X    On Unix systems, file names may contain blanks.
  262. X    If they do, why not allow them to be restored exactly?
  263. X    For all other systems still change the blanks to '_'.
  264. X
  265. XDue to historic reasons the order these patches were applied is
  266. X 3 - 4 - 1 - 2.  However they do not overlap and can therefore be
  267. Xapplied independently.
  268. X
  269. XI am providing UNZIP.PRG for the Atari ST as UNZIP41.ARC
  270. Xfor those who don't have any unzipper yet.
  271. X
  272. XSpecial features:
  273. X=================
  274. X
  275. X Unzip.prg uses a special version of the startup file which is capable
  276. X of recognizing extended parameters a la Beckemeyer/Mark Williams shell,
  277. X using the "ARGV=" Environment variable.
  278. X
  279. X Although the Turbo C compiler is quite good, the libs are buggy!
  280. X Therefore I cannot garantee that any unzip.prg compiled with Turbo C
  281. X will ever run successfully. Mine seems to be ok., but I have fixed
  282. X various problems for my lib. Especially the stat() was making trouble.
  283. X
  284. XHowever, if someone wants to compile it the same way I did,
  285. Xthere are essentially 3 ways:
  286. X- using a shell, and the command line compiler TCC,
  287. X  as indicated by the script 'MAKEIT',
  288. X
  289. X- using some sort of make and 'MAKEFILE.ST'
  290. X  This and the previous case both require also 'TLINK.OPT'
  291. X
  292. X- using the interactive version 'TC' of Turbo C and
  293. X  the supplied 'UNZIP.PRJ'.
  294. X
  295. XPlease read the note above about problems which might arise
  296. Xwhen you recompile unzip on your Atari.
  297. X
  298. X                    martin@atlantic.cs.unb.ca
  299. X
  300. END_OF_FILE
  301.   if test 2944 -ne `wc -c <'ATARI/README.src'`; then
  302.     echo shar: \"'ATARI/README.src'\" unpacked with wrong size!
  303.   fi
  304.   # end of 'ATARI/README.src'
  305. fi
  306. if test ! -d 'MAC' ; then
  307.     echo shar: Creating directory \"'MAC'\"
  308.     mkdir 'MAC'
  309. fi
  310. if test ! -d 'MSDOS' ; then
  311.     echo shar: Creating directory \"'MSDOS'\"
  312.     mkdir 'MSDOS'
  313. fi
  314. if test ! -d 'MSDOS/bcc' ; then
  315.     echo shar: Creating directory \"'MSDOS/bcc'\"
  316.     mkdir 'MSDOS/bcc'
  317. fi
  318. if test ! -d 'MSDOS/tcc' ; then
  319.     echo shar: Creating directory \"'MSDOS/tcc'\"
  320.     mkdir 'MSDOS/tcc'
  321. fi
  322. if test ! -d 'OS2' ; then
  323.     echo shar: Creating directory \"'OS2'\"
  324.     mkdir 'OS2'
  325. fi
  326. if test ! -d 'VMS' ; then
  327.     echo shar: Creating directory \"'VMS'\"
  328.     mkdir 'VMS'
  329. fi
  330. if test ! -d 'VMS/bilf' ; then
  331.     echo shar: Creating directory \"'VMS/bilf'\"
  332.     mkdir 'VMS/bilf'
  333. fi
  334. if test ! -d 'VMS/crypt' ; then
  335.     echo shar: Creating directory \"'VMS/crypt'\"
  336.     mkdir 'VMS/crypt'
  337. fi
  338. if test -f 'ship.c' -a "${1}" != "-c" ; then 
  339.   echo shar: Will not clobber existing file \"'ship.c'\"
  340. else
  341.   echo shar: Extracting \"'ship.c'\" \(38513 characters\)
  342.   sed "s/^X//" >'ship.c' <<'END_OF_FILE'
  343. X/* ship.c -- Not copyrighted 1991 Mark Adler */
  344. X
  345. X#define SHIPVER "ship version 1.1  November 4, 1991  Mark Adler"
  346. X
  347. X/* Command for mailing (-m): the %s's are, in order, the subject prefix,
  348. X   the part number (always of the form "partnnnn"), the subject suffix
  349. X   (empty or " (last)" if the last part), the mailing address, and the
  350. X   name of the temporary file begin mailed.  The command "Mail" is for BSD
  351. X   systems.  You may need to change it to "mailx" for System V Unix, using
  352. X   the compile option "-DMAILX".  Also, on Sperry (Unisys?) SysV.3 systems,
  353. X   you might try the command name "v6mail". */
  354. X
  355. X#ifdef DIRENT           /* If compiled with zip, DIRENT implies System V */
  356. X#  define MAILX
  357. X#endif /* DIRENT */
  358. X
  359. X#ifdef sun              /* Except Sun's use DIRENT, but have Mail */
  360. X#  ifdef MAILX
  361. X#    undef MAILX
  362. X#  endif /* MAILX */
  363. X#endif /* sun */
  364. X
  365. X#ifdef sgi              /* Silicon Graphics that way too */
  366. X#  ifdef MAILX
  367. X#    undef MAILX
  368. X#  endif /* MAILX */
  369. X#endif /* sgi */
  370. X
  371. X#ifdef VMS
  372. X#  define TMPNAME "_SXXXXXX."
  373. X#  define MAILCMD "mail %s /subj=\"%s %s%s\" \"%s\""
  374. X#  define PATHCUT ']'
  375. X#else /* !VMS */
  376. X#  define TMPNAME "_SXXXXXX"
  377. X#  ifdef MAILX
  378. X#    define MAILCMD "mailx -s \"%s %s%s\" \"%s\" < %s"
  379. X#  else /* !MAILX */
  380. X#    ifdef M_XENIX
  381. X#      define MAILCMD "mail -s \"%s %s%s\" \"%s\" < %s"
  382. X#    else /* !M_XENIX */
  383. X#      define MAILCMD "Mail -s \"%s %s%s\" \"%s\" < %s"
  384. X#    endif /* ?M_XENIX */
  385. X#  endif /* ?MAILX */
  386. X#  ifdef MSDOS
  387. X#    define PATHCUT '\\'
  388. X#  else /* !MSDOS */
  389. X#    define PATHCUT '/'
  390. X#  endif /* ?MSDOS */
  391. X#endif /* ?VMS */
  392. X
  393. X/*
  394. X
  395. XSHIP -
  396. X
  397. X  Ship is a program for sending binary files through email.  It is designed
  398. X  to supplant uuencode and uudecode.  Ship encodes approximately 6.32 bits
  399. X  per character mailed, compared to uuencode's 5.81 bits per character.
  400. X
  401. X  Ship also has these features: a 32-bit CRC check on each file; automatic
  402. X  splitting of the ship output into multiple, smaller files for speedier
  403. X  mailing; automatic mailing of ship's output, with subject lines for
  404. X  multiple parts; and a check on the sequence of parts when unshipping.
  405. X
  406. X  Usage:
  407. X
  408. X       ship [-nnn] [-m address] [-s subject] file ...
  409. X
  410. X  where nnn is the maximum number of K bytes for each output file, address
  411. X  is the address to send mail to, subject is a Subject" line prefix, and
  412. X  file ... is a list of files to ship.  If no options are given, ship
  413. X  outputs to stdout.  The simplest use is:
  414. X
  415. X       ship foo > x
  416. X
  417. X  where foo is converted into the mailable file, x.
  418. X
  419. X  When -nnn is specified, but -m is not, ship writes to the files
  420. X  part0001, part0002, etc., where each file has nnn or less K bytes.  For
  421. X  example:
  422. X
  423. X       ship -25 bigfoo
  424. X
  425. X  will write however many 25K byte or less ship files is needed to contain
  426. X  bigfoo.  If, say, six files are needed, then the files part0001 to part0006
  427. X  will be written.
  428. X
  429. X  When using -m, nothing is written, either to files or to stdout; rather,
  430. X  the output is mailed to the specified address.  If -nnn is also specified,
  431. X  then the parts are mailed separately with the subject lines part0001, etc.
  432. X  If -nnn is not specified, then only one part (the whole thing) is mailed
  433. X  with the subject line "part0001".  For example:
  434. X
  435. X       ship -25 -m fred bigfoo
  436. X
  437. X  will mail the six parts of bigfoo to fred.
  438. X
  439. X  Any number of files can be shipped at once.  They become part of one long
  440. X  ship stream, so if, for example -25 is specified, all but the last part
  441. X  will have about 25K bytes.  For example:
  442. X
  443. X       ship -25 -m fred fee fi fo fum
  444. X
  445. X  will send the files fee, fi, fo, and fum to fred.
  446. X
  447. X  Fred will get several mail messages with the subject lines part0001, etc.
  448. X  He can then save those messages as the files, say, p1, p2, p3, ...
  449. X  Then he can use the command:
  450. X
  451. X       ship -u p?
  452. X
  453. X  to recreate bigfoo, or fee fi fo and fum, depending on what he was sent.
  454. X  If Fred saved the wrong numbers, ship will detect this and report a
  455. X  sequence error.
  456. X
  457. X  Note: there is enough information in the shipped parts to determine the
  458. X  correct sequence.  A future version of ship will prescan the files to
  459. X  determine the sequence, and then process them in the correct order.
  460. X
  461. X  If a file being received already exists, ship -u will report an error
  462. X  and exit.  The -o option avoids this and allows ship to overwrite existing
  463. X  files.  The -o option must follow the -u option:
  464. X
  465. X       ship -u -o p?
  466. X
  467. X  In addition to the -u option, ship will unship if it sees that its name is
  468. X  unship.  On Unix systems, this can be done simply by linking the executable
  469. X  to unship:
  470. X
  471. X       ln ship unship 
  472. X
  473. X  Ship can also be used as a filter.  The special file name "-" means stdin.
  474. X  For example:
  475. X
  476. X       tar covf - foodir | compress | ship -25 -m fred -
  477. X
  478. X  will tar the directory foodir, compress it, and ship it to fred in 25K byte
  479. X  pieces.  Then, after Fred saves the files as p01, etc. at the other, end,
  480. X  he can:
  481. X
  482. X       ship -u p? | zcat | tar xovf -
  483. X
  484. X  which will recreate the directory foobar and its contents.  ship -u knows
  485. X  to write to stdout, since the original ship put the special file name "-"
  486. X  in the first part.
  487. X
  488. X  Ship uses a base 85 coding that needs 32-bit multiplication and division.
  489. X  This can be slow on 16-bit machines, so ship provides a fast encoding
  490. X  method by specifying the -f option.  This method is somewhat faster even
  491. X  on 32-bit machines, and has approximately a 1% penalty in the size of the
  492. X  encoded result (-f gives 6.26 bits per character, on the average).  The -f
  493. X  option need only be used when shipping--unshipping (ship -u) automatically
  494. X  detects the encoding used.  For example:
  495. X
  496. X       ship -f -25 -m fred foo
  497. X
  498. X  will send foo to fred in 25K byte pieces using the fast encoding method.
  499. X  You don't need to tell Fred, since ship -u will figure that out for him.
  500. X
  501. X  The fast encoding method is probabilistic, so it's possible for the size
  502. X  penalty to be worse than 1%, and it's also possible for the fast encoding
  503. X  to produce a smaller result than base 85 encoding would, all depending on
  504. X  the data.
  505. X
  506. X  The -q option can be used with either ship or unship (ship -u) for quiet
  507. X  operation--informational messages are inhibited.
  508. X
  509. X  You can find out the version of ship and get the command usage by using
  510. X  "ship -h" or "ship -?".  The version number and date and help will be
  511. X  printed, and ship will exit (the rest of the command line is ignored).
  512. X
  513. X  Acknowledgements:
  514. X
  515. X  The hard-arithmetic coding algorithm was blatantly stolen from Peter
  516. X  Gutmann's pgencode/pgdecode programs posted on comp.compression, with
  517. X  modifications to use 86 instead of 94 characters, and to make zeros encode
  518. X  better than, rather than worse than other bytes.  (As Stravinsky once said:
  519. X  "Mediocre composers plagiarize.  Great composers steal.")
  520. X
  521. X*/
  522. X
  523. X/* tailor.h -- Not copyrighted 1991 Mark Adler */
  524. X
  525. X/* const's are inconsistently used across ANSI libraries--kill for all
  526. X   header files. */
  527. X#define const
  528. X
  529. X
  530. X/* Use prototypes and ANSI libraries if __STDC__ */
  531. X#ifdef __STDC__
  532. X#  ifndef PROTO
  533. X#    define PROTO
  534. X#  endif /* !PROTO */
  535. X#  define MODERN
  536. X#endif /* __STDC__ */
  537. X
  538. X
  539. X/* Use prototypes and ANSI libraries if Silicon Graphics */
  540. X#ifdef sgi
  541. X#  ifndef PROTO
  542. X#    define PROTO
  543. X#  endif /* !PROTO */
  544. X#  define MODERN
  545. X#endif /* sgi */
  546. X
  547. X
  548. X/* Define MSDOS for Turbo C as well as Microsoft C */
  549. X#ifdef __POWERC                 /* For Power C too */
  550. X#  define __TURBOC__
  551. X#endif /* __POWERC */
  552. X#ifdef __TURBOC__
  553. X#  ifndef MSDOS
  554. X#    define MSDOS
  555. X#  endif /* !MSDOS */
  556. X#endif /* __TURBOC__ */
  557. X
  558. X
  559. X/* Use prototypes and ANSI libraries if Microsoft or Borland C */
  560. X#ifdef MSDOS
  561. X#  ifndef PROTO
  562. X#    define PROTO
  563. X#  endif /* !PROTO */
  564. X#  define MODERN
  565. X#endif /* MSDOS */
  566. X
  567. X
  568. X/* Turn off prototypes if requested */
  569. X#ifdef NOPROTO
  570. X#  ifdef PROTO
  571. X#    undef PROTO
  572. X#  endif /* PROTO */
  573. X#endif /* NOPROT */
  574. X
  575. X
  576. X/* Used to remove arguments in function prototypes for non-ANSI C */
  577. X#ifdef PROTO
  578. X#  define OF(a) a
  579. X#else /* !PROTO */
  580. X#  define OF(a) ()
  581. X#endif /* ?PROTO */
  582. X
  583. X
  584. X/* Allow far and huge allocation for small model (Microsoft C or Turbo C) */
  585. X#ifdef MSDOS
  586. X#  ifdef __TURBOC__
  587. X#    include <alloc.h>
  588. X#  else /* !__TURBOC__ */
  589. X#    include <malloc.h>
  590. X#    define farmalloc _fmalloc
  591. X#    define farfree   _ffree
  592. X#  endif /* ?__TURBOC__ */
  593. X#else /* !MSDOS */
  594. X#  define huge
  595. X#  define far
  596. X#  define near
  597. X#  define farmalloc malloc
  598. X#  define farfree   free
  599. X#endif /* ?MSDOS */
  600. X
  601. X
  602. X/* Define MSVMS if either MSDOS or VMS defined */
  603. X#ifdef MSDOS
  604. X#  define MSVMS
  605. X#else /* !MSDOS */
  606. X#  ifdef VMS
  607. X#    define MSVMS
  608. X#  endif /* VMS */
  609. X#endif /* ?MSDOS */
  610. X
  611. X
  612. X/* Define void, voidp, and extent (size_t) */
  613. X#include <stdio.h>
  614. X#ifdef MODERN
  615. X#  if !defined(M_XENIX) && !(defined(__GNUC__) && defined(sun))
  616. X#    include <stddef.h>
  617. X#  endif
  618. X#  include <stdlib.h>
  619. X   typedef size_t extent;
  620. X   typedef void voidp;
  621. X#else /* !MODERN */
  622. X   typedef unsigned int extent;
  623. X#  define void int
  624. X   typedef char voidp;
  625. X#endif /* ?MODERN */
  626. X
  627. X/* Get types and stat */
  628. X#ifdef VMS
  629. X#  include <types.h>
  630. X#  include <stat.h>
  631. X#else /* !VMS */
  632. X#  include <sys/types.h>
  633. X#  include <sys/stat.h>
  634. X#endif /* ?VMS */
  635. X
  636. X
  637. X/* Cheap fix for unlink on VMS */
  638. X#ifdef VMS
  639. X#  define unlink delete
  640. X#endif /* VMS */
  641. X
  642. X
  643. X/* For Pyramid */
  644. X#ifdef pyr
  645. X#  define strrchr rindex
  646. X#  define ZMEM
  647. X#endif /* pyr */
  648. X
  649. X
  650. X/* File operations--use "b" for binary if allowed */
  651. X#ifdef MODERN
  652. X#  define FOPR "rb"
  653. X#  define FOPM "r+b"
  654. X#  define FOPW "w+b"
  655. X#else /* !MODERN */
  656. X#  define FOPR "r"
  657. X#  define FOPM "r+"
  658. X#  define FOPW "w+"
  659. X#endif /* ?MODERN */
  660. X
  661. X
  662. X/* Fine tuning */
  663. X#ifndef MSDOS
  664. X#   define BSZ 8192   /* Buffer size for files */
  665. X#else /* !MSDOS */
  666. X#   define BSZ 4096   /* Keep precious NEAR space */
  667. X    /* BSZ can't be 8192 even for compact model because of 64K limitation
  668. X     * in im_lmat.c. If you run out of memory when processing a large number
  669. X     * files, use the compact model and reduce BSZ to 2048 here and in
  670. X     * im_lm.asm.
  671. X     */
  672. X#endif /* ?MSDOS */
  673. X
  674. X/* end of tailor.h */
  675. X
  676. X#ifdef MODERN
  677. X#  include <string.h>
  678. X#else /* !MODERN */
  679. X   voidp *malloc();
  680. X   long atol();
  681. X   char *strcpy();
  682. X   char *strrchr();
  683. X#endif /* ?MODERN */
  684. X
  685. X/* Library functions not in (most) header files */
  686. Xchar *mktemp OF((char *));
  687. Xint unlink OF((char *));
  688. X
  689. X#ifdef MSDOS            /* Use binary mode for binary files */
  690. X#  include <io.h>
  691. X#  include <fcntl.h>
  692. X#endif /* MSDOS */
  693. X
  694. X
  695. X#define LNSZ 1025       /* size of line buffer */
  696. X
  697. Xtypedef unsigned long ulg;      /* 32-bit unsigned integer */
  698. X
  699. Xtypedef struct {        /* associates a CRC with a file */
  700. X  FILE *f;              /* pointer to associated file stream */
  701. X  ulg c;                /* CRC register */
  702. X  ulg b;                /* four byte buffer */
  703. X  int n;                /* buffer count */
  704. X} cfile;
  705. X
  706. X
  707. X/* Function prototypes */
  708. X#ifdef MODERN
  709. X   void err(int, char *);
  710. X   cfile *chook(FILE *);
  711. X   char *nopath(char *);
  712. X   void newship(void);
  713. X   void endship(int);
  714. X   void newline(char *);
  715. X   void ship(char *, FILE *);
  716. X   void mkinv(void);
  717. X   void decode(unsigned char *, cfile *);
  718. X   void unship(char **, int, int);
  719. X   void help(void);
  720. X   void main(int, char **);
  721. X#endif /* MODERN */
  722. X
  723. X
  724. X
  725. X/* Globals for ship() */
  726. Xchar sname[9];          /* current ship file name */
  727. XFILE *sfile;            /* current ship file */
  728. Xulg slns;               /* number of lines written to ship file */
  729. Xulg slmax;              /* maximum number of lines per ship file */
  730. Xint fast;               /* true for arithmetic coding, else base 85 */
  731. Xint mail;               /* true if mailing */
  732. Xchar mpspc[9];          /* prealloced space for prefix */
  733. Xchar *mprefix = mpspc;  /* identification for this mailing */
  734. Xchar *mdest;            /* mail destination */
  735. Xchar mname[10];         /* temporary file name if mailing */
  736. Xulg ccnt;               /* count of bytes read or written */
  737. Xint noisy = 1;          /* false to inhibit informational messages */
  738. X
  739. X
  740. X
  741. X/* Errors */
  742. X#define SE_ARG 1
  743. X#define SE_FIND 2
  744. X#define SE_NONE 3
  745. X#define SE_PART 4
  746. X#define SE_FORM 5
  747. X#define SE_CONT 6
  748. X#define SE_CRC 7
  749. X#define SE_MAIL 8
  750. X#define SE_OVER 9
  751. X#define SE_FULL 10
  752. X#define SE_MANY 11
  753. X#define SE_MEM 12
  754. Xchar *errors[] = {
  755. X  /* 1 */ "invalid argument ",
  756. X  /* 2 */ "could not find ",
  757. X  /* 3 */ "no files received",
  758. X  /* 4 */ "unfinished file ",
  759. X  /* 5 */ "invalid ship format in ",
  760. X  /* 6 */ "wrong sequence for ",
  761. X  /* 7 */ "CRC check failed on ",
  762. X  /* 8 */ "mail command failed: ",
  763. X  /* 9 */ "attempted to overwrite ",
  764. X  /* 10 */ "could not write to ",
  765. X  /* 11 */ "too many output files!",
  766. X  /* 12 */ "out of memory"
  767. X};
  768. X
  769. X
  770. X/* Set of 86 characters used for the base 85 digits (last one not used), and
  771. X   the 86 character arithmetic coding.  Selected to be part of both the ASCII
  772. X   printable characters, and the common EBCDIC printable characters whose
  773. X   ASCII translations are universal. */
  774. Xunsigned char safe[] = {
  775. X        '{','"','#','$','%','&','\'','(',')','*','+',',','-','.','/',
  776. X        '0','1','2','3','4','5','6','7','8','9',':',';','<','=','>','?','@',
  777. X        'A','B','C','D','E','F','G','H','I','J','K','L','M',
  778. X        'N','O','P','Q','R','S','T','U','V','W','X','Y','Z','_',
  779. X        'a','b','c','d','e','f','g','h','i','j','k','l','m',
  780. X        'n','o','p','q','r','s','t','u','v','w','x','y','z','}'};
  781. X
  782. X#define LOWSZ (sizeof(safe)-64)         /* low set size for fast coding */
  783. X
  784. X/* Special replacement pairs--if first of each pair is received, it is
  785. X   treated like the second member of the pair.  You're probably
  786. X   wondering why.  The first pair is for compatibility with an
  787. X   earlier version of ship that used ! for the base 85 zero digit.
  788. X   However, there exist ASCII-EBCDIC translation tables that don't
  789. X   know about exclamation marks.  The second set has mysterious
  790. X   historical origins that are best left unspoken ... */
  791. Xunsigned char aliases[] = {'!','{','|','+',0};
  792. X
  793. X/* Inverse of safe[], filled in by mkinv() */
  794. Xunsigned char invsafe[256];
  795. X
  796. X/* Table of CRC-32's of all single byte values (made by makecrc.c) */
  797. Xulg crctab[] = {
  798. X  0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
  799. X  0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
  800. X  0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
  801. X  0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
  802. X  0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
  803. X  0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
  804. X  0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
  805. X  0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
  806. X  0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
  807. X  0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
  808. X  0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
  809. X  0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
  810. X  0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
  811. X  0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
  812. X  0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
  813. X  0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
  814. X  0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
  815. X  0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
  816. X  0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
  817. X  0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
  818. X  0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
  819. X  0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
  820. X  0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
  821. X  0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
  822. X  0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
  823. X  0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
  824. X  0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
  825. X  0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
  826. X  0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
  827. X  0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
  828. X  0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
  829. X  0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
  830. X  0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
  831. X  0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
  832. X  0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
  833. X  0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
  834. X  0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
  835. X  0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
  836. X  0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
  837. X  0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
  838. X  0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
  839. X  0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
  840. X  0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
  841. X  0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
  842. X  0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
  843. X  0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
  844. X  0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
  845. X  0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
  846. X  0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
  847. X  0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
  848. X  0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
  849. X  0x2d02ef8dL
  850. X};
  851. X
  852. X/* Macro to update the CRC shift register one byte at a time */
  853. X#define CRC(c,b) (crctab[((int)(c)^(int)(b))&0xff]^((c)>>8))
  854. X
  855. X
  856. Xchar *errname = "ship error";
  857. Xchar *warname = "ship warning";
  858. X
  859. Xvoid err(n, m)
  860. Xint n;                  /* error number */
  861. Xchar *m;                /* additional error information */
  862. X{
  863. X  if (n == SE_FIND || n == SE_FULL)
  864. X    perror(errname);
  865. X  fputs(errname, stderr);
  866. X  fputs(": ", stderr);
  867. X  fputs(errors[n - 1], stderr);
  868. X  fputs(m, stderr);
  869. X  putc('\n', stderr);
  870. X  if (*mname)
  871. X    unlink(mname);
  872. X#ifdef VMS
  873. X  exit(0);
  874. X#else /* !VMS */
  875. X  exit(n);
  876. X#endif /* ?VMS */
  877. X}
  878. X
  879. X
  880. Xcfile *chook(f)
  881. XFILE *f;                /* file stream */
  882. X/* Inherit the file stream structure and add a CRC and buffer for appending
  883. X   a CRC on reads and checking the CRC on writes.  Return a pointer to the
  884. X   cfile structure, or NULL if the malloc() failed.  Also, if MSDOS, set the
  885. X   file mode to binary to avoid LF<->CRLF conversions. */
  886. X{
  887. X  cfile *c;             /* allocated cfile structure */
  888. X
  889. X#ifdef MSDOS
  890. X  /* Set file mode to binary for MSDOS systems */
  891. X  setmode(fileno(f), O_BINARY);
  892. X#endif /* MSDOS */
  893. X
  894. X  /* Allocate and fill structure */
  895. X  if ((c = (cfile *)malloc(sizeof(cfile))) != NULL)
  896. X  {
  897. X    c->f = f;                           /* file stream */
  898. X    c->b = 0;                           /* empty fifo (for output) */
  899. X    c->c = 0xffffffffL;                 /* preload CRC register */
  900. X    c->n = 0;                           /* fifo is empty (output) or */
  901. X  }                                     /*  no CRC bytes given (input) */
  902. X  return c;
  903. X}
  904. X
  905. X
  906. X
  907. X/* cgetc(x)--like getc(f), but appends a 32-bit CRC to the end of the stream.
  908. X   Return the byte read (the last four of which will be the CRC) or EOF. */
  909. X#define cgete(x) (x->n==4?EOF:(x->c=x->n++?x->c>>8:~x->c,(int)x->c&0xff))
  910. X#define cgetc(x) (x->n==0&&(b=getc(x->f))!=EOF?(ccnt++,x->c=CRC(x->c,b),b):cgete(c))
  911. X
  912. X
  913. X/* cputc(d,x)--like putc(d,f), but delays four bytes and computes a CRC.
  914. X   x is a cfile *, and d is expected to be an ulg. */
  915. X#define cputf(x) (int)(x->c=CRC(x->c,x->b),putc((int)x->b&0xff,x->f),ccnt++)
  916. X#define cputc(d,x) (x->n!=4?x->n++:cputf(x),x->b=(x->b>>8)+((ulg)(d)<<24))
  917. X
  918. X
  919. Xchar *nopath(p)
  920. Xchar *p;                /* full file name */
  921. X/* Extract just the name of file--remove and subdirectories or devices */
  922. X{
  923. X#ifdef MSDOS
  924. X  char *q = "/\\:";     /* MSDOS delimiters */
  925. X#else /* !MSDOS */
  926. X#ifdef VMS
  927. X  char *q = "]:";       /* VMS delimiters */
  928. X#else /* !VMS */
  929. X  char *q = "/";        /* Unix delimiter */
  930. X#endif /* ?VMS */
  931. X#endif /* ?MSDOS */
  932. X  char *r;              /* result of strrchr() */
  933. X
  934. X  while (*q)
  935. X    if ((r = strrchr(p, *q++)) != NULL)
  936. X      p = r + 1;
  937. X  return p;
  938. X}
  939. X
  940. X
  941. Xvoid newship()
  942. X/* Open up a new ship file to write to */
  943. X{
  944. X  int i;                /* scans down name to increment */
  945. X
  946. X  for (i = 7; i > 3; i--)
  947. X    if (++sname[i] > '9')
  948. X      sname[i] = '0';
  949. X    else
  950. X      break;
  951. X  if (i == 3)
  952. X    err(SE_MANY, "");
  953. X  if ((sfile = fopen(mail ? mktemp(strcpy(mname, TMPNAME)) : sname,
  954. X                     "w")) == NULL)
  955. X    err(SE_FULL, mail ? mname : sname);
  956. X  slns = 0;
  957. X}
  958. X
  959. X
  960. Xvoid endship(e)
  961. Xint e;          /* true if ending the last ship file */
  962. X/* Finish off current ship file */
  963. X{
  964. X  char *s;              /* malloc'd space for mail command */
  965. X
  966. X  if (ferror(sfile) || fclose(sfile))
  967. X    err(SE_FULL, mail ? mname : sname);
  968. X  if (mail)
  969. X  {
  970. X    if ((s = malloc(strlen(MAILCMD)- 5*2 + strlen(mprefix) + strlen(sname) +
  971. X                    (e ? 7 : 0) + strlen(mdest) + strlen(mname) + 1)) == NULL)
  972. X      err(SE_MEM, "");
  973. X#ifdef VMS
  974. X    sprintf(s, MAILCMD, mname, mprefix, sname, e ? " (last)" : "", mdest);
  975. X    if (!system(s))             /* this string fits on one line */
  976. X      err(SE_MAIL, "system() call is not supported on this machine");
  977. X#else /* !VMS */
  978. X    sprintf(s, MAILCMD, mprefix, sname, e ? " (last)" : "", mdest, mname);
  979. X    if (system(s))
  980. X      err(SE_MAIL, s);
  981. X#endif /* ?VMS */
  982. X    free((voidp *)s);
  983. X    unlink(mname);
  984. X    *mname = 0;
  985. X  }
  986. X}
  987. X
  988. X
  989. Xvoid newline(p)
  990. Xchar *p;                /* name of the input file */
  991. X/* Add a new line inside a ship file, possibly cut the file */
  992. X{
  993. X  putc('\n', sfile);
  994. X  slns++;
  995. X  if (slmax && slns >= slmax - 2)
  996. X  {
  997. X    putc('$', sfile);
  998. X    if (fast)
  999. X      fputs(" f", sfile);
  1000. X    fputs("\nmore\n", sfile);
  1001. X    endship(0);
  1002. X    newship();
  1003. X    fprintf(sfile, "$%s\ncont %lu %s\n", fast ? " f" : "", ccnt, nopath(p));
  1004. X    slns += 2;
  1005. X  }
  1006. X}
  1007. X
  1008. X
  1009. X/* Macro to avoid leading dots.  It assumes i==0 at the beginning of a line
  1010. X   and that b is an available int.  c is only evaluated once. */
  1011. X#define sputc(c,f) (i==0?((b=(c))=='.'?putc(' ',f):0,putc(b,f)):putc(c,f))
  1012. X
  1013. X
  1014. Xvoid ship(p, f)
  1015. Xchar *p;                /* name of the input file */
  1016. XFILE *f;                /* input file */
  1017. X/* Encode the binary file f. */
  1018. X{
  1019. X  int b;                /* character just read */
  1020. X  cfile *c;             /* checked file stream */
  1021. X  int i;                /* how much is written on line so far */
  1022. X  int j;                /* how much is in bit buffer */
  1023. X
  1024. X  /* Set up output file if needed */
  1025. X  if ((mail || slmax) && sfile == stdout)
  1026. X  {
  1027. X    strcpy(sname, "part0000");
  1028. X    newship();
  1029. X  }
  1030. X
  1031. X  /* Write header */
  1032. X  if ((c = chook(f)) == NULL)
  1033. X    err(SE_MEM, "");
  1034. X  ccnt = 0;
  1035. X  if (slmax && slns >= slmax - 5) 
  1036. X  {
  1037. X    endship(0);
  1038. X    newship();
  1039. X  }
  1040. X  fprintf(sfile, "$%s\nship %s\n", fast ? " f" : "", nopath(p));
  1041. X  slns += 2;
  1042. X
  1043. X  /* Encode the file, writing to sfile */
  1044. X  if (fast)
  1045. X  {
  1046. X    int d;              /* accumulates bits (never more than 14) */
  1047. X
  1048. X    d = j = i = 0;
  1049. X    while ((b = cgetc(c)) != EOF)
  1050. X    {
  1051. X      d |= b << j;
  1052. X      j += 8;
  1053. X      if ((d & 0x3f) >= LOWSZ)
  1054. X      {
  1055. X        sputc((int)(safe[(d & 0x3f) + LOWSZ]), sfile);
  1056. X        d >>= 6;
  1057. X        j -= 6;
  1058. X      }
  1059. X      else
  1060. X      {
  1061. X        sputc((int)(safe[(d & 0x3f) + (d & 0x40 ? LOWSZ : 0)]), sfile);
  1062. X        d >>= 7;
  1063. X        j -= 7;
  1064. X      }
  1065. X      if (++i == 79)
  1066. X      {
  1067. X        newline(p);
  1068. X        i = 0;
  1069. X      }
  1070. X      if (j >= 6 && (d & 0x3f) >= LOWSZ)
  1071. X      {
  1072. X        sputc((int)(safe[(d & 0x3f) + LOWSZ]), sfile);
  1073. X        d >>= 6;
  1074. X        j -= 6;
  1075. X        if (++i == 79)
  1076. X        {
  1077. X          newline(p);
  1078. X          i = 0;
  1079. X        }
  1080. X      }
  1081. X      else if (j >= 7)
  1082. X      {
  1083. X        sputc((int)(safe[(d & 0x3f) + (d & 0x40 ? LOWSZ : 0)]), sfile);
  1084. X        d >>= 7;
  1085. X        j -= 7;
  1086. X        if (++i == 79)
  1087. X        {
  1088. X          newline(p);
  1089. X          i = 0;
  1090. X        }
  1091. X      }
  1092. X    }
  1093. X    free((voidp *)c);
  1094. X
  1095. X    /* Write leftover bits */
  1096. X    if (j)
  1097. X    {
  1098. X      sputc((int)(safe[d + (d < LOWSZ ? 0 : LOWSZ)]), sfile);
  1099. X      putc('\n', sfile);
  1100. X      slns++;
  1101. X    }
  1102. X    else if (i)
  1103. X    {
  1104. X      putc('\n', sfile);
  1105. X      slns++;
  1106. X    }
  1107. X  }
  1108. X  else
  1109. X  {
  1110. X    ulg d;              /* accumulates bytes */
  1111. X
  1112. X    d = j = i = 0;
  1113. X    while ((b = cgetc(c)) != EOF)
  1114. X    {
  1115. X      d += ((ulg)b) << j;
  1116. X      if ((j += 8) == 32)
  1117. X      {
  1118. X        sputc((int)(safe[(int)(d % 85)]), sfile);  d /= 85;
  1119. X        putc((int)(safe[(int)(d % 85)]), sfile);  d /= 85;
  1120. X        putc((int)(safe[(int)(d % 85)]), sfile);  d /= 85;
  1121. X        putc((int)(safe[(int)(d % 85)]), sfile);  d /= 85;
  1122. X        putc((int)(safe[(int)d]), sfile);
  1123. X        if (++i == 15)                  /* each line is <= 75 characters */
  1124. X        {
  1125. X          newline(p);
  1126. X          i = 0;
  1127. X        }
  1128. X        d = j = 0;
  1129. X      }
  1130. X    }
  1131. X    free((voidp *)c);
  1132. X  
  1133. X    /* Write leftover data */
  1134. X    if (j)
  1135. X    {
  1136. X      j >>= 3;
  1137. X      sputc((int)(safe[(int)(d % 85)]), sfile);
  1138. X      while (j--)
  1139. X      {
  1140. X        d /= 85;
  1141. X        putc((int)(safe[(int)(d % 85)]), sfile);
  1142. X      }
  1143. X      putc('\n', sfile);
  1144. X      slns++;
  1145. X    }
  1146. X    else if (i)
  1147. X    {
  1148. X      putc('\n', sfile);
  1149. X      slns++;
  1150. X    }
  1151. X  }
  1152. X  putc('$', sfile);
  1153. X  if (fast)
  1154. X    fputs(" f", sfile);
  1155. X  fputs("\nend\n", sfile);
  1156. X  slns += 2;
  1157. X  if (ferror(sfile) || fflush(sfile))
  1158. X    err(SE_FULL, mail ? mname : sname);
  1159. X  if (noisy)
  1160. X    fprintf(stderr, "%s shipped\n", p);
  1161. X}
  1162. X
  1163. X
  1164. Xvoid mkinv()
  1165. X/* Build invsafe[], the inverse of safe[]. */
  1166. X{
  1167. X  int i;
  1168. X
  1169. X  for (i = 0; i < 256; i++)
  1170. X    invsafe[i] = 127;
  1171. X  for (i = 0; i < sizeof(safe); i++)
  1172. X    invsafe[safe[i]] = (char)i;
  1173. X  for (i = 0; aliases[i]; i += 2)
  1174. X    invsafe[aliases[i]] = invsafe[aliases[i + 1]];
  1175. X}
  1176. X
  1177. X
  1178. Xunsigned int decb;      /* bit buffer for decode */
  1179. Xunsigned int decn;      /* number of bits in decb */
  1180. X
  1181. Xvoid decode(s, c)
  1182. Xunsigned char *s;       /* data to decode */
  1183. Xcfile *c;               /* binary output file */
  1184. X/* Decode s, a string of base 85 digits or, if fast is true, a string of safe
  1185. X   characters generated arithmetically, into its binary equivalent, writing
  1186. X   the result to c, using cputc(). */
  1187. X{
  1188. X  int b;                /* state of line loop, next character */
  1189. X  int k;                /* counts bits or digits read */
  1190. X  /* powers of 85 table for decoding */
  1191. X  static ulg m[] = {1L,85L,85L*85L,85L*85L*85L,85L*85L*85L*85L};
  1192. X
  1193. X  if (fast)
  1194. X  {
  1195. X    unsigned int d;     /* disperses bits */
  1196. X
  1197. X    d = decb;
  1198. X    k = decn;
  1199. X    while ((b = *s++) != 0)
  1200. X      if ((b = invsafe[b]) < sizeof(safe))
  1201. X      {
  1202. X        if (b < LOWSZ)
  1203. X        {
  1204. X          d |= b << k;
  1205. X          k += 7;
  1206. X        }
  1207. X        else if ((b -= LOWSZ) < LOWSZ)
  1208. X        {
  1209. X          d |= (b + 0x40) << k;
  1210. X          k += 7;
  1211. X        }
  1212. X        else
  1213. X        {
  1214. X          d |= b << k;
  1215. X          k += 6;
  1216. X        }
  1217. X        if (k >= 8)
  1218. X        {
  1219. X          cputc(d, c);
  1220. X          d >>= 8;
  1221. X          k -= 8;
  1222. X        }
  1223. X      }
  1224. X    decb = d;
  1225. X    decn = k;
  1226. X  }
  1227. X  else
  1228. X  {
  1229. X    ulg d;              /* disperses bytes */
  1230. X
  1231. X    d = k = 0;
  1232. X    while ((b = *s++) != 0)
  1233. X      if ((b = invsafe[b]) < 85)
  1234. X      {
  1235. X        d += m[k] * b;
  1236. X        if (++k == 5)
  1237. X        {
  1238. X          cputc(d, c);  d >>= 8;
  1239. X          cputc(d, c);  d >>= 8;
  1240. X          cputc(d, c);  d >>= 8;
  1241. X          cputc(d, c);
  1242. X          d = k = 0;
  1243. X        }
  1244. X      }
  1245. X    if (--k > 0)
  1246. X    {
  1247. X      while (--k)
  1248. X      {
  1249. X        cputc(d, c);
  1250. X        d >>= 8;
  1251. X      }
  1252. X      cputc(d, c);
  1253. X    }
  1254. X  }
  1255. X}
  1256. X
  1257. X
  1258. Xvoid unship(v, g, o)
  1259. Xchar **v;               /* arguments */
  1260. Xint g;                  /* number of arguments */
  1261. Xint o;                  /* overwrite flag */
  1262. X/* Extract from the files named in the arguments the files that were
  1263. X   encoded by ship.  If an argument is "-", then stdin is read. */
  1264. X{
  1265. X  int b;                /* state of line loop */
  1266. X  cfile *c;             /* output binary file */
  1267. X  FILE *f;              /* output file */
  1268. X  char *h;              /* name of current ship file */
  1269. X  char l[LNSZ];         /* line buffer on input */
  1270. X  int n;                /* next argument to use for input */
  1271. X  char *p;              /* modifies line buffer */
  1272. X  char *q;              /* scans continuation line */
  1273. X  char *r;              /* name of output binary file */
  1274. X  FILE *s;              /* current ship file */
  1275. X  int z;                /* true if zero files received */
  1276. X
  1277. X  /* Build inverse table */
  1278. X  mkinv();
  1279. X
  1280. X  /* No input or output files initially */
  1281. X  s = NULL;
  1282. X  c = NULL;
  1283. X  h = r = NULL;
  1284. X
  1285. X  /* Loop on input files' lines */
  1286. X  z = 1;                                /* none received yet */
  1287. X  n = 0;                                /* start with file zero */
  1288. X  b = 2;                                /* not in body yet */
  1289. X  while (1)                             /* return on end of last file */
  1290. X  {
  1291. X    /* Get next line from list of files */
  1292. X    while (s == NULL || fgets(l, LNSZ, s) == NULL)
  1293. X    {
  1294. X      if (s != NULL)
  1295. X        fclose(s);
  1296. X      if (n >= g)
  1297. X      {
  1298. X        if (c != NULL)
  1299. X          err(SE_PART, r);
  1300. X        else if (z)
  1301. X          err(SE_NONE, "");
  1302. X        return;
  1303. X      }
  1304. X      if (v[n][0] == '-')
  1305. X        if (v[n][1])
  1306. X          err(SE_ARG, v[n]);
  1307. X        else
  1308. X        {
  1309. X          h = "stream stdin";
  1310. X          s = stdin;
  1311. X        }
  1312. X      else
  1313. X      {
  1314. X        h = v[n];
  1315. X        if ((s = fopen(h, "r")) == NULL)
  1316. X          err(SE_FIND, h);
  1317. X      }
  1318. X      n++;
  1319. X      b &= ~1;                          /* not in middle of line */
  1320. X    }
  1321. X
  1322. X    /* Strip control characters and leading blank space, if any */
  1323. X    for (q = l; *q && *q <= ' ' && *q != '\n'; q++)
  1324. X      ;
  1325. X    for (p = l; *q; q++)
  1326. X      if (*q >= ' ' || *q == '\n')
  1327. X        *p++ = *q;
  1328. X    *p = 0;
  1329. X
  1330. X    /* Based on current state, end or start on terminator.  States are:
  1331. X         b == 0:  at start of body or body terminator line
  1332. X         b == 1:  in middle of body line
  1333. X         b == 2:  at start of non-body line
  1334. X         b == 3:  in middle of non-body line
  1335. X         b == 4:  at information line
  1336. X    */
  1337. X    switch (b)
  1338. X    {
  1339. X    case 0:
  1340. X      if ((!fast && strcmp(l, "$\n") == 0) ||
  1341. X          (fast && strcmp(l, "$ f\n") == 0))
  1342. X      {
  1343. X        b = 4;
  1344. X        break;
  1345. X      }
  1346. X      /* fall through to case 1 */
  1347. X    case 1:
  1348. X      decode((unsigned char *)l, c);
  1349. X      b = l[strlen(l) - 1] != '\n';
  1350. X      break;
  1351. X    case 2:
  1352. X      if (strcmp(l, "$\n") == 0 || strcmp(l, "$ f\n") == 0)
  1353. X      {
  1354. X        fast = l[1] == ' ';
  1355. X        b = 4;
  1356. X        break;
  1357. X      }
  1358. X      /* fall through to case 3 */
  1359. X    case 3:
  1360. X      b = l[strlen(l)-1] == '\n' ? 2 : 3;
  1361. X      break;
  1362. X    case 4:
  1363. X      /* Possible information lines are ship, more, cont, and end */
  1364. X      if (l[b = strlen(l) - 1] != '\n')
  1365. X        err(SE_FORM, h);
  1366. X      l[b] = 0;
  1367. X      if (strncmp(l, "ship ", 5) == 0)
  1368. X      {
  1369. X        /* get name, open new output file */
  1370. X        if (c != NULL)
  1371. X          err(SE_FORM, h);
  1372. X        if ((r = malloc(b - 4)) == NULL)
  1373. X          err(SE_MEM, "");
  1374. X        strcpy(r, l + 5);
  1375. X        if (strcmp(r, "-") == 0)
  1376. X          f = stdout;
  1377. X#ifndef VMS     /* shouldn't have explicit version #, so VMS won't overwrite */
  1378. X        else if (!o && (f = fopen(r, "r")) != NULL)
  1379. X        {
  1380. X          fclose(f);
  1381. X          err(SE_OVER, r);
  1382. X        }
  1383. X#endif /* !VMS */
  1384. X        else if ((f = fopen(r, "w")) == NULL)
  1385. X          err(SE_FULL, r);
  1386. X        if ((c = chook(f)) == NULL)
  1387. X          err(SE_MEM, "");
  1388. X        b = decb = decn = 0;
  1389. X        ccnt = 0;
  1390. X      }
  1391. X      else if (strcmp(l, "more") == 0)
  1392. X      {
  1393. X        /* check if currently writing */
  1394. X        if (c == NULL)
  1395. X          err(SE_FORM, h);
  1396. X        b = 2;
  1397. X      }
  1398. X      else if (strncmp(l, "cont ", 5) == 0)
  1399. X      {
  1400. X        /* check name and file offset */
  1401. X        if (c == NULL)
  1402. X          err(SE_FORM, h);
  1403. X        for (q = l + 5; *q && *q != ' '; q++)
  1404. X          ;
  1405. X        if (*q == 0 || atol(l + 5) != ccnt + 4 + (decn != 0) ||
  1406. X            strcmp(q + 1, r))
  1407. X          err(SE_CONT, r);
  1408. X        b = 0;
  1409. X      }
  1410. X      else if (strcmp(l, "end") == 0)
  1411. X      {
  1412. X        /* check crc, close output file */
  1413. X        if (c == NULL)
  1414. X          err(SE_FORM, h);
  1415. X        if (c->n != 4 || c->b != ~c->c)
  1416. X          err(SE_CRC, r);
  1417. X        if (ferror(c->f) || fclose(c->f))
  1418. X          err(SE_FULL, r);
  1419. X        if (noisy)
  1420. X          fprintf(stderr, "%s received\n", r);
  1421. X        z = 0;
  1422. X        free((voidp *)c);
  1423. X        c = NULL;
  1424. X        b = 2;
  1425. X      }
  1426. X      else
  1427. X      {
  1428. X        for (q = l; *q && *q != ' '; q++)
  1429. X          ;
  1430. X        *q = 0;
  1431. X        fprintf(stderr, "%s: unsupported keyword '%s' ignored\n", warname, l);
  1432. X        b = 4;
  1433. X      }
  1434. X      break;
  1435. X    }
  1436. X  }
  1437. X}
  1438. X
  1439. X
  1440. Xvoid help()
  1441. X{
  1442. X  int i;
  1443. X  static char *text[] = {
  1444. X"Usage:",
  1445. X"   ship [-f] [-q] [-nnn] [-m address] [-s subject] files...",
  1446. X"",
  1447. X"   ships the files to stdout.  -m sends the output via the mailer to",
  1448. X"   address.  -nnn splits the output into pieces of nnnK bytes or less.",
  1449. X"   if -nnn is used without -m, the output goes to the files partxxxx,",
  1450. X"   where xxxx is 0001, 0002, etc.  If -0 is specified, the output goes",
  1451. X"   entirely to the file part0001.  -f uses a fast method with slightly",
  1452. X"   less performance.  If no files are given, stdin is used.  The special",
  1453. X"   filename '-' also takes input from stdin.  Files shipped from stdin",
  1454. X"   are unshipped to stdout.  This can be used to document a shipment.",
  1455. X"   When mailing, -s gives a subject line prefix.  -q inhibits messages.",
  1456. X"",
  1457. X"   ship -u [-o] [-q] files...",
  1458. X"   unship  [-o] [-q] files...",
  1459. X"",
  1460. X"   extracts the contents of the mail messages in files...  -o allows",
  1461. X"   existing files to be overwritten.  -u is implied if the name of the",
  1462. X"   executable is unship.  If no files are given, the input is from",
  1463. X"   stdin.  If any of the files were shipped from stdin, then they are",
  1464. X"   extracted to stdout."
  1465. X  };
  1466. X
  1467. X  puts(SHIPVER);
  1468. X  for (i = 0; i < sizeof(text)/sizeof(char *); i++)
  1469. X  {
  1470. X    printf(text[i]);
  1471. X    putchar('\n');
  1472. X  }
  1473. X  exit(0);
  1474. X}
  1475. X
  1476. X
  1477. Xvoid main(argc, argv)
  1478. Xint argc;               /* number of arguments */
  1479. Xchar **argv;            /* table of argument strings */
  1480. X{
  1481. X  FILE *f;              /* input file */
  1482. X  ulg k;                /* number of k requested per part */
  1483. X  char *p;              /* temporary variable */
  1484. X  int o;                /* overwrite flag */
  1485. X  int r;                /* temporary variable */
  1486. X  int s;                /* true if no names given */
  1487. X
  1488. X  /* No temporary file yet (for err()) */
  1489. X  *mname = 0;
  1490. X
  1491. X  /* No subject prefix yet */
  1492. X  *mprefix = 0;
  1493. X
  1494. X  /* See if help requested */
  1495. X  if (argc > 1 && (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "-?") == 0))
  1496. X    help();
  1497. X
  1498. X  /* Unship */
  1499. X  if ((p = strrchr(argv[0], PATHCUT)) == NULL)
  1500. X    p = argv[0];
  1501. X  else
  1502. X    p++;
  1503. X  r = 0;                                /* (make some compilers happier) */
  1504. X  if ((r = strncmp(p, "unship", 6)) == 0 ||
  1505. X      (r = strncmp(p, "UNSHIP", 6)) == 0 ||
  1506. X      (argc > 1 && strcmp(argv[1], "-u") == 0))
  1507. X  {
  1508. X    errname = "unship error";
  1509. X    warname = "unship warning";
  1510. X    r = r ? 2 : 1;                      /* next arg */
  1511. X    o = 0;                              /* disallow overwriting */
  1512. X    if (r < argc && strcmp(argv[r], "-o") == 0)
  1513. X    {
  1514. X      r++;
  1515. X      o = 1;                            /* allow overwriting */
  1516. X    }
  1517. X    if (r < argc && strcmp(argv[r], "-q") == 0)
  1518. X    {
  1519. X      r++;
  1520. X      noisy = 0;                        /* inhibit messages */
  1521. X    }
  1522. X    if (r < argc)
  1523. X      unship(argv + r, argc - r, o);    /* unship files in args */
  1524. X    else
  1525. X    {
  1526. X      char *a[1];       /* short list of names (one) */
  1527. X
  1528. X      a[0] = "-";
  1529. X      unship(a, 1, o);                  /* no args--do stdin */
  1530. X    }
  1531. X  }
  1532. X
  1533. X  /* Ship */
  1534. X  else
  1535. X  {
  1536. X    mail = 0;                           /* not mailing */
  1537. X    fast = 0;                           /* use base 85 encoding */
  1538. X    s = 1;                              /* no names given yet */
  1539. X    strcpy(sname, "-");                 /* output to stdout */
  1540. X    sfile = stdout;
  1541. X    slns = slmax = k = 0;
  1542. X    for (r = 1; r < argc; r++)          /* go through args */
  1543. X      if (argv[r][0] == '-')            /* option or stdin */
  1544. X        if (argv[r][1])                 /* option */
  1545. X        {
  1546. X          if (argv[r][1] == 'm')        /* mail output */
  1547. X          {
  1548. X            mail = 1;
  1549. X            mdest = NULL;               /* next arg is mail address */
  1550. X          }
  1551. X          else if (argv[r][1] == 's')   /* next arg is subject prefix */
  1552. X            mprefix = NULL;
  1553. X          else if (argv[r][1] == 'f')   /* fast arithmetic encoding */
  1554. X          {
  1555. X            fast = 1;
  1556. X            if (k)                      /* recompute slmax if needed */
  1557. X              slmax = 4 + (k * 1024L) / 81;
  1558. X          }
  1559. X          else if (argv[r][1] == 'q')   /* quiet operation */
  1560. X            noisy = 0;
  1561. X          else                          /* option is number of lines */
  1562. X          {
  1563. X            /* Check numeric option */
  1564. X            for (p = argv[r] + 1; *p; p++)
  1565. X              if (*p < '0' || *p > '9')
  1566. X                break;
  1567. X            if (*p || slmax)
  1568. X              err(SE_ARG, argv[r]);
  1569. X  
  1570. X            /* Zero means infinity, else convert */
  1571. X            if ((k = atol(argv[r] + 1)) == 0)
  1572. X              slmax = -1L;
  1573. X            else
  1574. X              slmax = 4 + (k * 1024L) / (fast ? 81 : 77);
  1575. X          }
  1576. X        }
  1577. X        else                            /* input file is stdin */
  1578. X        {
  1579. X          if (mail && mdest == NULL)
  1580. X            err(SE_ARG, "- (no mail destination given)");
  1581. X          s = 0;
  1582. X          if (mail && !*mprefix)
  1583. X            strcpy(mprefix, "(stdin)");
  1584. X          ship("-", stdin);
  1585. X        }
  1586. X      else                              /* not option or stdin */
  1587. X        if (mail && mdest == NULL)      /* arg is mail address */
  1588. X          mdest = argv[r];
  1589. X        else if (mprefix == NULL)       /* arg is subject prefix */
  1590. X          mprefix = argv[r];
  1591. X        else                            /* arg is file to ship */
  1592. X        {
  1593. X          s = 0;
  1594. X          if ((f = fopen(argv[r], "r")) == NULL)
  1595. X            err(SE_FIND, argv[r]);
  1596. X          if (mail && !*mprefix)
  1597. X          {
  1598. X            int i;
  1599. X
  1600. X            for (i = 0, p = nopath(argv[r]); i < 8 && *p; p++)
  1601. X              if ((*p >= '0' && *p <= '9') || (*p >= 'A' && *p <= 'Z') ||
  1602. X                  (*p >= 'a' && *p <= 'z') || *p == '.' || *p == '_')
  1603. X                mprefix[i++] = *p;
  1604. X            mprefix[i] = 0;
  1605. X          }
  1606. X          ship(argv[r], f);
  1607. X          fclose(f);
  1608. X        }
  1609. X    if (s)                              /* no names--act as filter */
  1610. X      if (mail && mdest == NULL)
  1611. X        err(SE_ARG, "-m (no mail destination given)");
  1612. X      else if (mprefix == NULL)
  1613. X        err(SE_ARG, "-s (no subject prefix given)");
  1614. X      else
  1615. X      {
  1616. X        if (mail && !*mprefix)
  1617. X          strcpy(mprefix, "(stdin)");
  1618. X        ship("-", stdin);
  1619. X      }
  1620. X    endship(1);                         /* clean up */
  1621. X    if (noisy && (mail || slmax))
  1622. X      fprintf(stderr, "file%s%s %s\n",
  1623. X              strcmp("part0001", sname) ? "s part0001.." : " ", sname,
  1624. X              mail ? "mailed" : "written");
  1625. X  }
  1626. X
  1627. X  /* Done */
  1628. X  exit(0);
  1629. X}
  1630. END_OF_FILE
  1631.   if test 38513 -ne `wc -c <'ship.c'`; then
  1632.     echo shar: \"'ship.c'\" unpacked with wrong size!
  1633.   fi
  1634.   # end of 'ship.c'
  1635. fi
  1636. echo shar: End of archive 1 \(of 12\).
  1637. cp /dev/null ark1isdone
  1638. MISSING=""
  1639. for I in 1 2 3 4 5 6 7 8 9 10 11 12 ; do
  1640.     if test ! -f ark${I}isdone ; then
  1641.     MISSING="${MISSING} ${I}"
  1642.     fi
  1643. done
  1644. if test "${MISSING}" = "" ; then
  1645.     echo You have unpacked all 12 archives.
  1646.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1647. else
  1648.     echo You still must unpack the following archives:
  1649.     echo "        " ${MISSING}
  1650. fi
  1651. exit 0
  1652.  
  1653.  
  1654. exit 0 # Just in case...
  1655.