home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume15 / cshar / part01 next >
Encoding:
Internet Message Format  |  1988-05-26  |  58.5 KB

  1. Subject:  v15i018:  Tools to create and unpack shell archives, Part01/03
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4.  
  5. Submitted-by: Rich Salz <rsalz@bbn.com>
  6. Posting-number: Volume 15, Issue 18
  7. Archive-name: cshar/part01
  8.  
  9. [  I will soon be posting a variant of this package that handles the
  10.    missing features, for those who want or need them.  --r$  ]
  11.  
  12. This set of tools is designed to make it easier to ship sources around.  I
  13. wrote them because I do a lot of that as moderator of comp.sources.unix,
  14. and nothing else did the job for me.  This set isn't perfect, but's very
  15. close.  Included are a program to find source files, a program to
  16. partition them into reasonable sizes, a program to make shell archives out
  17. of them, a program to strip mail, news, and notes headers from archives
  18. before feeding them to a shell, and a program that simulates enough
  19. /bin/sh syntax so that non-Unix systems can unpack them.
  20.  
  21. I believe this works under MSDOS.  If you have diffs, send them to me.
  22. Owen at Oxford Trading Partners, oxtrap!osm, ported an earlier version to
  23. MSDOS; I hope I didn't break anything when I merged his changes into what
  24. I've got now.  Same for Amiga and other PC's.  I might do a VMS port.  The
  25. dir.msdos shar (which I haven't touched) seems to be solid; I don't know
  26. about the dir.amiga code.
  27.  
  28. I freely stole ideas from a number of people who have been good enough to
  29. put their stuff out on Usenet.  Particular thanks to Gary Perlman and
  30. Larry Wall for giving me something nice to reverse-engineer, and Michael
  31. Mauldin for unshar.  People who sent significant comments and fixes from
  32. earlier versions include Bob Desinger, Darryl Ohahato, Jamie Watson, Joel
  33. Shprentz, Ken Yap, Matt Landau, Paul Vixie, Shane McCarron, Tim Pointing,
  34. Tom Beattie, Vital Dobroey, and Don Libes.  Thanks to all of them,
  35. particularly Paul for an amazing number of comments on earlier versions.
  36.  
  37. On a philosophical note, I've tried to make this all as general as
  38. possible for shipping sources around.  I'm not interested in binaries, so
  39. things like automatically running uuencode don't interest me a great
  40. deal.  I haven't come up with a good portable way to split files into
  41. pieces if they're too large, and doubt I ever will.  There are too many
  42. installation parameters, but I'm not particularly worried about that:  Once
  43. you get things working, consider it incentive to avoid future changes.
  44. It would be nice if I could use Larry's meta-Config, but that only works
  45. on Unix-type systems.
  46.     /rich $alz
  47.  
  48. #! /bin/sh
  49. # This is a shell archive.  Remove anything before this line, then unpack
  50. # it by saving it into a file and typing "sh file".  To overwrite existing
  51. # files, type "sh file -c".  You can also feed this as standard input via
  52. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  53. # will see the following message at the end:
  54. #        "End of archive 1 (of 3)."
  55. # Contents:  MANIFEST Makefile README config.h dir.msdos findsrc.man
  56. #   glue.c lcwd.c lexec.c lfiles.c lhost.c llib.c lmem.c luser.c
  57. #   makekit.man patchlevel.h shar.h shar.man shell.c shell.man
  58. #   unshar.man
  59. # Wrapped by rsalz@fig.bbn.com on Fri May 27 14:15:05 1988
  60. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  61. if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  62.   echo shar: Will not clobber existing file \"'MANIFEST'\"
  63. else
  64. echo shar: Extracting \"'MANIFEST'\" \(1725 characters\)
  65. sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
  66. X   File Name        Archive #    Description
  67. X-----------------------------------------------------------
  68. X MANIFEST                   1    This shipping list
  69. X Makefile                   1    Control file for Unix make program
  70. X README                     1    Acknowledgements, installation notes
  71. X config.h                   1    Default configuration file
  72. X dir.amiga                  2    A partial Amiga readdir package
  73. X dir.msdos                  1    An MS-DOS readdir package
  74. X findsrc.c                  2    Find source files, based on filename
  75. X findsrc.man                1    Manual page for findsrc
  76. X glue.c                     1    Glue that so unshar uses my /bin/sh parser
  77. X lcwd.c                     1    Routines to find current directory
  78. X lexec.c                    1    Fork, exec, system, signal, etc., routines
  79. X lfiles.c                   1    File size and type routines
  80. X lhost.c                    1    Find our machine name
  81. X llib.c                     1    Stuff that should be in your C library
  82. X lmem.c                     1    Memory allocator, uses calloc
  83. X luser.c                    1    Get user's name
  84. X makekit.c                  2    Partition files into reasonable-sized kits
  85. X makekit.man                1    Manual page for makekit
  86. X parser.c                   3    Interpreter for shell archives
  87. X patchlevel.h               1    Mistake recorder
  88. X shar.c                     2    Create script to create files
  89. X shar.h                     1    Header file, used by everyone
  90. X shar.man                   1    Manual page for makekit
  91. X shell.c                    1    Main routine for my shell interpreter
  92. X shell.man                  1    Manual page for shell
  93. X unshar.c                   2    Strip news, notes, mail headers from shar's
  94. X unshar.man                 1    Manual page for unshar
  95. END_OF_FILE
  96. if test 1725 -ne `wc -c <'MANIFEST'`; then
  97.     echo shar: \"'MANIFEST'\" unpacked with wrong size!
  98. fi
  99. # end of 'MANIFEST'
  100. fi
  101. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  102.   echo shar: Will not clobber existing file \"'Makefile'\"
  103. else
  104. echo shar: Extracting \"'Makefile'\" \(3261 characters\)
  105. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  106. X##
  107. X##  SOURCE-SHIPPING TOOLS MAKEFILE
  108. X##  $Header: Makefile,v 2.0 88/05/27 13:29:42 rsalz Exp $
  109. X##  $Log:    Makefile,v $
  110. X# Revision 2.0  88/05/27  13:29:42  rsalz
  111. X# First comp.sources.unix release
  112. X# 
  113. X##
  114. X
  115. X## Grrrr...
  116. SHELL    = /bin/sh
  117. X
  118. X##  Edit appropriately, such as -g if you don't trust me...
  119. CFLAGS    = -O
  120. X
  121. X##  Where the readdir() and friends are, if not in your C library.
  122. X#DIRLIB    = -lndir
  123. X
  124. X##  Use these two lines if you use ranlib...
  125. AR_OBJ    = $(LIB_OBJ)
  126. RANLIB    = ranlib lib.a
  127. X##  ...or use these two if you need tsort instead...
  128. X#AR_OBJ    = `lorder $(LIB_OBJ) | tsort`
  129. X#RANLIB    = @echo
  130. X##  ...or these two if you need neither.
  131. X#AR_OBJ    = $(LIB_OBJ)
  132. X#RANLIB    = @echo
  133. X
  134. X##  Where executables should be put.
  135. DESTDIR    = /usr/local/bin
  136. X
  137. X##  The "foo" manpage will get put in $(MANDIR)/foo.$1
  138. MANDIR    = /usr/man/man1
  139. X1    = 1
  140. X#MANDIR    = /usr/man/u_man/manl
  141. X#1    = 1L
  142. X
  143. X##
  144. X##  END OF CONFIGURATION SECTION
  145. X##
  146. X
  147. X##  Header files.
  148. HDRS    = shar.h config.h
  149. LIB    = lib.a $(DIRLIB)
  150. X
  151. X##  Programs and documentation.
  152. PROGRAMS= findsrc    makekit    shar    unshar    shell
  153. MANPAGES= findsrc.$1 makekit.$1 shar.$1 unshar.$1 shell.$1
  154. X
  155. X##  Our library of utility functions.
  156. LIB_SRC    = glue.c parser.c lcwd.c lexec.c lfiles.c lhost.c llib.c lmem.c luser.c
  157. LIB_OBJ    = glue.o parser.o lcwd.o lexec.o lfiles.o lhost.o llib.o lmem.o luser.o
  158. X
  159. X
  160. all:        $(PROGRAMS) $(MANPAGES)
  161. X    touch all
  162. X
  163. X##  You might want to change these actions...
  164. install:    all
  165. X    cd $(DESTDIR) ; rm -f $(PROGRAMS)
  166. X    cp $(PROGRAMS) $(DESTDIR)
  167. X    cd $(DESTDIR) ; strip $(PROGRAMS) ; chmod 755 $(PROGRAMS)
  168. X#    cd $(DESTDIR) ; /etc/chown root $(PROGRAMS)
  169. X    cd $(MANDIR) ; rm -f $(MANPAGES)
  170. X    cp $(MANPAGES) $(MANDIR)
  171. X    touch install
  172. X
  173. clean:
  174. X    rm -f *.[oa] *.$1 *.BAK $(PROGRAMS) unshar.safe
  175. X    rm -f lint lib.ln tags core foo a.out Part?? all install
  176. X
  177. X
  178. X##  Creating manpages.
  179. X.SUFFIXES:    .$1 .man
  180. X.man.$1:
  181. X    @rm -f $@
  182. X    cp $< $@
  183. X    chmod 444 $@
  184. X
  185. X
  186. X##  Programs.
  187. findsrc:    findsrc.o $(HDRS) $(LIB)
  188. X    @rm -f $@
  189. X    $(CC) $(CFLAGS) -o findsrc findsrc.o $(LIB)
  190. X
  191. makekit:    makekit.o $(HDRS) $(LIB)
  192. X    @rm -f $@
  193. X    $(CC) $(CFLAGS) -o makekit makekit.o $(LIB)
  194. X
  195. shar:        shar.o $(HDRS) $(LIB)
  196. X    @rm -f $@
  197. X    $(CC) $(CFLAGS) -o shar shar.o $(LIB)
  198. X
  199. shell:        shell.o $(HDRS) $(LIB)
  200. X    @rm -f $@
  201. X    $(CC) $(CFLAGS) -o shell shell.o $(LIB)
  202. X
  203. unshar:        unshar.o $(HDRS) $(LIB)
  204. X    @rm -f $@
  205. X    $(CC) $(CFLAGS) -o unshar unshar.c $(LIB)
  206. X
  207. X
  208. X##  Special case, a version of unshar that uses the /bin/sh interpreter.
  209. unshar.safe:    unshar.c $(HDRS) $(LIB)
  210. X    @rm -f $@
  211. X    @rm -f unshar.o
  212. X    $(CC) $(CFLAGS) -DUSE_MY_SHELL -o unshar unshar.c $(LIB)
  213. X    @rm -f unshar.o
  214. X
  215. X
  216. X##  Support your local library.
  217. lib.a:        $(LIB_OBJ)
  218. X    @rm -f $@
  219. X    ar r lib.a $(AR_OBJ)
  220. X    $(RANLIB)
  221. X$(LIB_OBJ):    $(HDRS)
  222. X
  223. X
  224. X##  Lint; this is probably only good for BSD-derived lints.
  225. X##  Ultrix 1.2 lint really hates the !var construct, for some reason.
  226. X#LINTF    = -p -ahb
  227. LINTF    = -ahb
  228. X##  A slight speed hack...
  229. XX    = exec
  230. lint:        $(PROGRAMS) lib.ln
  231. X    @rm -f $@
  232. X    $X lint $(LINTF) -u  >lint $(LIB_SRC)
  233. X    $X lint $(LINTF)    >>lint findsrc.c lib.ln
  234. X    $X lint $(LINTF)    >>lint makekit.c lib.ln
  235. X    $X lint $(LINTF)    >>lint shar.c    lib.ln
  236. X    $X lint $(LINTF)    >>lint shell.c   lib.ln
  237. X    $X lint $(LINTF)    >>lint unshar.c  lib.ln
  238. X#    $X lint $(LINTF) -DUSE_MY_SHELL >>lint unshar.c  lib.ln
  239. X
  240. lib.ln:        $(LIB_SRC)
  241. X    @rm -f $@
  242. X    lint -CX $(LIB_SRC)
  243. X    mv llib-lX.ln lib.ln
  244. END_OF_FILE
  245. if test 3261 -ne `wc -c <'Makefile'`; then
  246.     echo shar: \"'Makefile'\" unpacked with wrong size!
  247. fi
  248. # end of 'Makefile'
  249. fi
  250. if test -f 'README' -a "${1}" != "-c" ; then 
  251.   echo shar: Will not clobber existing file \"'README'\"
  252. else
  253. echo shar: Extracting \"'README'\" \(3392 characters\)
  254. sed "s/^X//" >'README' <<'END_OF_FILE'
  255. This set of tools is designed to make it easier to ship sources around.  I
  256. wrote them because I do a lot of that as moderator of comp.sources.unix,
  257. and nothing else did the job for me.  This set isn't perfect, but's very
  258. close.  Included are a program to find source files, a program to
  259. partition them into reasonable sizes, a program to make shell archives out
  260. of them, a program to strip mail, news, and notes headers from archives
  261. before feeding them to a shell, and a program that simulates enough
  262. X/bin/sh syntax so that non-Unix systems can unpack them.
  263. X
  264. The sources in this distribution are being released into the public
  265. domain; do what you want, but let your conscience be your guide.  If you
  266. somehow enhance this package, please send it on to me so that others can
  267. benefit.
  268. X
  269. I'll try to answer any questions or problems that come up -- send me
  270. electronic mail.
  271. X
  272. To install, edit the Makefile and config.h as necessary then run make;
  273. doing make install will put the manpages and executables where you told
  274. it to.  I don't think "make lint" will be totally reasonable except on
  275. a BSD-derived system, but you can try.  If you write config.h files for
  276. other systems, send them to me.
  277. X
  278. If you aren't running on Unix, then you will have to write replacements
  279. for the functions in the lxxxx.c files; everything else should be OK.  If
  280. you find something in another file that you had to change, please let me
  281. know.  If you don't have a Unix-like make available, you will have to
  282. write a command script or otherwise work out something with your compiler,
  283. linker, etc.
  284. X
  285. I believe this works under MSDOS.  If you have diffs, send them to me.
  286. Owen at Oxford Trading Partners, oxtrap!osm, ported an earlier version to
  287. MSDOS; I hope I didn't break anything when I merged his changes into what
  288. I've got now.  Same for Amiga and other PC's.  I might do a VMS port.  The
  289. dir.msdos shar (which I haven't touched) seems to be solid; I don't know
  290. about the dir.amiga code.
  291. X
  292. I freely stole ideas from a number of people who have been good enough to
  293. put their stuff out on Usenet.  Particular thanks to Gary Perlman and
  294. Larry Wall for giving me something nice to reverse-engineer, and Michael
  295. Mauldin for unshar.  People who sent significant comments and fixes from
  296. earlier versions include Bob Desinger, Darryl Ohahato, Jamie Watson, Joel
  297. Shprentz, Ken Yap, Matt Landau, Paul Vixie, Shane McCarron, Tim Pointing,
  298. Tom Beattie, Vital Dobroey, and Don Libes.  Thanks to all of them,
  299. particularly Paul for an amazing number of comments on earlier versions.
  300. X
  301. On a philosophical note, I've tried to make this all as general as
  302. possible for shipping sources around.  I'm not interested in binaries, so
  303. things like automatically running uuencode don't interest me a great
  304. deal.  I haven't come up with a good portable way to split files into
  305. pieces if they're too large, and doubt I ever will.  There are too many
  306. installation parameters, but I'm not particularly worried about that:  Once
  307. you get things working, consider it incentive to avoid future changes.
  308. It would be nice if I could use Larry's meta-Config, but that only works
  309. on Unix (and Eunice).  Send me your config.h file so that others can benefit.
  310. X
  311. XEnjoy!
  312. X    Rich $alz
  313. X    BBN Laboratories, Inc.
  314. X    10 Moulton Street
  315. X    Cambridge, MA  02238
  316. X    rsalz@bbn.com
  317. X    rsalz@uunet.uu.net
  318. X
  319. My, my, my, aren't we anal:
  320. X    $Header: README,v 2.0 88/05/27 13:29:50 rsalz Exp $
  321. END_OF_FILE
  322. if test 3392 -ne `wc -c <'README'`; then
  323.     echo shar: \"'README'\" unpacked with wrong size!
  324. fi
  325. # end of 'README'
  326. fi
  327. if test -f 'config.h' -a "${1}" != "-c" ; then 
  328.   echo shar: Will not clobber existing file \"'config.h'\"
  329. else
  330. echo shar: Extracting \"'config.h'\" \(4142 characters\)
  331. sed "s/^X//" >'config.h' <<'END_OF_FILE'
  332. X/*
  333. X**  Configuration file for shar and friends.
  334. X**
  335. X**  This is known to work on Ultrix1.2 and Sun3.4 machines; it may work
  336. X**  on other BSD variants, too.
  337. X**
  338. X**  $Header: config.h,v 2.0 88/05/27 13:15:39 rsalz Exp $
  339. X*/
  340. X
  341. X
  342. X/*
  343. X**  Higher-level controls for which operating system we're running on.
  344. X*/
  345. X#define UNIX                /* Works            */
  346. X/*efine MSDOS                /* Should work            */
  347. X/*efine VMS                /* Doesn't work            */
  348. X
  349. X
  350. X/*
  351. X**  A dense section of one-line compilation controls.  If you're confused,
  352. X**  your best bet is to search through the source to see where and how
  353. X**  each one of these is used.
  354. X*/
  355. X#define IDX        index        /* Maybe strchr?        */
  356. X#define RDX        rindex        /* Maybe strrchr?        */
  357. X/*efine NEED_MKDIR            /* Don't have mkdir(2)?        */
  358. X/*efine NEED_QSORT            /* Don't have qsort(3)?        */
  359. X#define NEED_GETOPT            /* Need local getopt object?    */
  360. X#define CAN_POPEN            /* Can invoke file(1) command?    */
  361. X/*efine USE_MY_SHELL            /* Don't popen("/bin/sh")?    */
  362. typedef int         sigret_t;    /* What a signal handler returns */
  363. typedef int        *align_t;    /* Worst-case alignment, for lint */
  364. X/* typedef long        time_t        /* Needed for non-BSD sites?    */
  365. X/* typedef long        off_t        /* Needed for non-BSD sites?    */
  366. X/*efine void        int        /* If you don't have void    */
  367. X#define SYS_WAIT            /* Have <sys/wait.h> and vfork?    */
  368. X/*efine USE_SYSTEM            /* Use system(3), not exec(2)?    */
  369. X#define USE_SYSERRLIST            /* Have sys_errlist[], sys_nerr? */
  370. X#define USE_GETPWUID            /* Use getpwuid(3)?        */
  371. X#define DEF_SAVEIT    1        /* Save headers by default?    */
  372. X/*efine FMT02d                /* Need "%02.2d", not "%2.2d"?    */
  373. X#define MAX_LEVELS    6        /* Levels for findsrc to walk    */
  374. X#define THE_TTY        "/dev/tty"    /* Maybe "con:" for MS-DOS?    */
  375. X#define RCSID                /* Compile in the RCS strings?    */
  376. X#define USERNAME    "USER"        /* Your name, if not in environ    */
  377. X#define PTR_SPRINTF            /* Need extern char *sprinf()?    */
  378. X/*efine ANSI_HDRS            /* Use <stdlib.h>, etc.?    */
  379. X#define REGISTER    register    /* Do you trust your compiler?    */
  380. X
  381. X
  382. X/*
  383. X**  There are several ways to get current machine name.  Enable just one
  384. X**  of one of the following lines.
  385. X*/
  386. X#define GETHOSTNAME            /* Use gethostname(2) call    */
  387. X/*efine UNAME                /* Use uname(2) call        */
  388. X/*efine UUNAME                /* Invoke "uuname -l"        */
  389. X/*efine    WHOAMI                /* Try /etc/whoami & <whoami.h>    */
  390. X/*efine HOST        "SITE"        /* If all else fails        */
  391. X
  392. X
  393. X/*
  394. X**  There are several different ways to get the current working directory.
  395. X**  Enable just one of the following lines.
  396. X*/
  397. X#define GETWD                /* Use getwd(3) routine        */
  398. X/*efine GETCWD                /* Use getcwd(3) routine    */
  399. X/*efine PWDPOPEN            /* Invoke "pwd"            */
  400. X/*efine PWDGETENV    "PWD"        /* Get $PWD from environment    */
  401. X
  402. X
  403. X/*
  404. X**  If you're a notes site, you might have to tweaks these two #define's.
  405. X**  If you don't care, then set them equal to something that doesn't
  406. X**  start with the comment-begin sequence and they'll be effectively no-ops
  407. X**  at the cost of an extra strcmp.  I've also heard of broken MS-DOS
  408. X**  compilers that don't ignore slash-star inside comments!  Anyhow, for
  409. X**  more details see unshar.c
  410. X*/
  411. X/*efine NOTES1        "/* Written "    /* This is what notes 1.7 uses    */
  412. X/*efine NOTES2        "/* ---"    /* This is what notes 1.7 uses    */
  413. X#define NOTES1        "$$"        /* This is a don't care        */
  414. X#define NOTES2        "$$"        /* This is a don't care        */
  415. X
  416. X
  417. X/*
  418. X**  The findsrc program uses the readdir() routines to read directories.
  419. X**  If your system doesn't have this interface, there are public domain
  420. X**  implementations available for Unix from the comp.sources.unix archives,
  421. X**  GNU has a VMS one inside EMACS, and this package comes with kits for
  422. X**  MS-DOS and the Amiga.  Help save the world and use or write a readdir()
  423. X**  package for your system!
  424. X*/
  425. X
  426. X/* Now then, where did I put that header file?   Pick one. */
  427. X#define IN_SYS_DIR            /* <sys/dir.h>            */
  428. X/*efine IN_SYS_NDIR            /* <sys/ndir.h>            */
  429. X/*efine IN_DIR                /* <dir.h>            */
  430. X/*efine IN_DIRECT            /* <direct.h>            */
  431. X/*efine IN_NDIR                /* "ndir.h"            */
  432. X/*efine IN_DIRENT            /* "dirent.h"            */
  433. X
  434. X/*  What readdir() returns.  Must be a #define because of #include order. */
  435. X#ifdef    IN_DIRENT
  436. X#define DIRENTRY    struct dirent
  437. X#else
  438. X#define DIRENTRY    struct direct
  439. X#endif    /* IN_DIRENT */
  440. X
  441. X/*
  442. X**  Congratulations, you're done!
  443. X*/
  444. END_OF_FILE
  445. if test 4142 -ne `wc -c <'config.h'`; then
  446.     echo shar: \"'config.h'\" unpacked with wrong size!
  447. fi
  448. # end of 'config.h'
  449. fi
  450. if test -f 'dir.msdos' -a "${1}" != "-c" ; then 
  451.   echo shar: Will not clobber existing file \"'dir.msdos'\"
  452. else
  453. echo shar: Extracting \"'dir.msdos'\" \(6547 characters\)
  454. sed "s/^X//" >'dir.msdos' <<'END_OF_FILE'
  455. X#! /bin/sh
  456. X# This is a shell archive.  Remove anything before this line, then unpack
  457. X# it by saving it into a file and typing "sh file".  To overwrite existing
  458. X# files, type "sh file -c".  You can also feed this as standard input via
  459. X# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  460. X# will see the following message at the end:
  461. X#        "End of shell archive."
  462. X# Contents:  msd_dir.c msd_dir.h
  463. X# Wrapped by rsalz@fig.bbn.com on Thu May 26 16:06:31 1988
  464. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  465. if test -f 'msd_dir.c' -a "${1}" != "-c" ; then 
  466. X  echo shar: Will not clobber existing file \"'msd_dir.c'\"
  467. else
  468. echo shar: Extracting \"'msd_dir.c'\" \(4114 characters\)
  469. sed "s/^X//" >'msd_dir.c' <<'END_OF_FILE'
  470. XX/*
  471. XX * @(#)msd_dir.c 1.4 87/11/06    Public Domain.
  472. XX *
  473. XX *  A public domain implementation of BSD directory routines for
  474. XX *  MS-DOS.  Written by Michael Rendell ({uunet,utai}michael@garfield),
  475. XX *  August 1897
  476. XX */
  477. XX
  478. XX#include    <sys/types.h>
  479. XX#include    <sys/stat.h>
  480. XX#include    <sys/dir.h>
  481. XX#include    <malloc.h>
  482. XX#include    <string.h>
  483. XX#include    <dos.h>
  484. XX
  485. XX#ifndef    NULL
  486. XX# define    NULL    0
  487. XX#endif    /* NULL */
  488. XX
  489. XX#ifndef    MAXPATHLEN
  490. XX# define    MAXPATHLEN    255
  491. XX#endif    /* MAXPATHLEN */
  492. XX
  493. XX/* attribute stuff */
  494. XX#define    A_RONLY        0x01
  495. XX#define    A_HIDDEN    0x02
  496. XX#define    A_SYSTEM    0x04
  497. XX#define    A_LABEL        0x08
  498. XX#define    A_DIR        0x10
  499. XX#define    A_ARCHIVE    0x20
  500. XX
  501. XX/* dos call values */
  502. XX#define    DOSI_FINDF    0x4e
  503. XX#define    DOSI_FINDN    0x4f
  504. XX#define    DOSI_SDTA    0x1a
  505. XX
  506. XX#define    Newisnull(a, t)        ((a = (t *) malloc(sizeof(t))) == (t *) NULL)
  507. XX#define    ATTRIBUTES        (A_DIR | A_HIDDEN | A_SYSTEM)
  508. XX
  509. XX/* what find first/next calls look use */
  510. typedef struct {
  511. XX    char        d_buf[21];
  512. XX    char        d_attribute;
  513. XX    unsigned short    d_time;
  514. XX    unsigned short    d_date;
  515. XX    long        d_size;
  516. XX    char        d_name[13];
  517. XX} Dta_buf;
  518. XX
  519. static    char    *getdirent();
  520. static    void    setdta();
  521. static    void    free_dircontents();
  522. XX
  523. static    Dta_buf        dtabuf;
  524. static    Dta_buf        *dtapnt = &dtabuf;
  525. static    union REGS    reg, nreg;
  526. XX
  527. XX#if    defined(M_I86LM)
  528. static    struct SREGS    sreg;
  529. XX#endif
  530. XX
  531. DIR    *
  532. opendir(name)
  533. XX    char    *name;
  534. XX{
  535. XX    struct    stat        statb;
  536. XX    DIR            *dirp;
  537. XX    char            c;
  538. XX    char            *s;
  539. XX    struct _dircontents    *dp;
  540. XX    char            nbuf[MAXPATHLEN + 1];
  541. XX    
  542. XX    if (stat(name, &statb) < 0 || (statb.st_mode & S_IFMT) != S_IFDIR)
  543. XX        return (DIR *) NULL;
  544. XX    if (Newisnull(dirp, DIR))
  545. XX        return (DIR *) NULL;
  546. XX    if (*name && (c = name[strlen(name) - 1]) != '\\' && c != '/')
  547. XX        (void) strcat(strcpy(nbuf, name), "\\*.*");
  548. XX    else
  549. XX        (void) strcat(strcpy(nbuf, name), "*.*");
  550. XX    dirp->dd_loc = 0;
  551. XX    setdta();
  552. XX    dirp->dd_contents = dirp->dd_cp = (struct _dircontents *) NULL;
  553. XX    if ((s = getdirent(nbuf)) == (char *) NULL)
  554. XX        return dirp;
  555. XX    do {
  556. XX        if (Newisnull(dp, struct _dircontents) || (dp->_d_entry =
  557. XX            malloc((unsigned) (strlen(s) + 1))) == (char *) NULL)
  558. XX        {
  559. XX            if (dp)
  560. XX                free((char *) dp);
  561. XX            free_dircontents(dirp->dd_contents);
  562. XX            return (DIR *) NULL;
  563. XX        }
  564. XX        if (dirp->dd_contents)
  565. XX            dirp->dd_cp = dirp->dd_cp->_d_next = dp;
  566. XX        else
  567. XX            dirp->dd_contents = dirp->dd_cp = dp;
  568. XX        (void) strcpy(dp->_d_entry, s);
  569. XX        dp->_d_next = (struct _dircontents *) NULL;
  570. XX    } while ((s = getdirent((char *) NULL)) != (char *) NULL);
  571. XX    dirp->dd_cp = dirp->dd_contents;
  572. XX
  573. XX    return dirp;
  574. XX}
  575. XX
  576. void
  577. closedir(dirp)
  578. XX    DIR    *dirp;
  579. XX{
  580. XX    free_dircontents(dirp->dd_contents);
  581. XX    free((char *) dirp);
  582. XX}
  583. XX
  584. struct direct    *
  585. readdir(dirp)
  586. XX    DIR    *dirp;
  587. XX{
  588. XX    static    struct direct    dp;
  589. XX    
  590. XX    if (dirp->dd_cp == (struct _dircontents *) NULL)
  591. XX        return (struct direct *) NULL;
  592. XX    dp.d_namlen = dp.d_reclen =
  593. XX        strlen(strcpy(dp.d_name, dirp->dd_cp->_d_entry));
  594. XX    dp.d_ino = 0;
  595. XX    dirp->dd_cp = dirp->dd_cp->_d_next;
  596. XX    dirp->dd_loc++;
  597. XX
  598. XX    return &dp;
  599. XX}
  600. XX
  601. void
  602. seekdir(dirp, off)
  603. XX    DIR    *dirp;
  604. XX    long    off;
  605. XX{
  606. XX    long            i = off;
  607. XX    struct _dircontents    *dp;
  608. XX
  609. XX    if (off < 0)
  610. XX        return;
  611. XX    for (dp = dirp->dd_contents ; --i >= 0 && dp ; dp = dp->_d_next)
  612. XX        ;
  613. XX    dirp->dd_loc = off - (i + 1);
  614. XX    dirp->dd_cp = dp;
  615. XX}
  616. XX
  617. long
  618. telldir(dirp)
  619. XX    DIR    *dirp;
  620. XX{
  621. XX    return dirp->dd_loc;
  622. XX}
  623. XX
  624. static    void
  625. free_dircontents(dp)
  626. XX    struct    _dircontents    *dp;
  627. XX{
  628. XX    struct _dircontents    *odp;
  629. XX
  630. XX    while (dp) {
  631. XX        if (dp->_d_entry)
  632. XX            free(dp->_d_entry);
  633. XX        dp = (odp = dp)->_d_next;
  634. XX        free((char *) odp);
  635. XX    }
  636. XX}
  637. XX
  638. static    char    *
  639. getdirent(dir)
  640. XX    char    *dir;
  641. XX{
  642. XX    if (dir != (char *) NULL) {        /* get first entry */
  643. XX        reg.h.ah = DOSI_FINDF;
  644. XX        reg.h.cl = ATTRIBUTES;
  645. XX#if    defined(M_I86LM)
  646. XX        reg.x.dx = FP_OFF(dir);
  647. XX        sreg.ds = FP_SEG(dir);
  648. XX#else
  649. XX        reg.x.dx = (unsigned) dir;
  650. XX#endif
  651. XX    } else {                /* get next entry */
  652. XX        reg.h.ah = DOSI_FINDN;
  653. XX#if    defined(M_I86LM)
  654. XX        reg.x.dx = FP_OFF(dtapnt);
  655. XX        sreg.ds = FP_SEG(dtapnt);
  656. XX#else
  657. XX        reg.x.dx = (unsigned) dtapnt;
  658. XX#endif
  659. XX    }
  660. XX#if    defined(M_I86LM)
  661. XX    intdosx(®, &nreg, &sreg);
  662. XX#else
  663. XX    intdos(®, &nreg);
  664. XX#endif
  665. XX    if (nreg.x.cflag)
  666. XX        return (char *) NULL;
  667. XX
  668. XX    return dtabuf.d_name;
  669. XX}
  670. XX
  671. static    void
  672. setdta()
  673. XX{
  674. XX    reg.h.ah = DOSI_SDTA;
  675. XX#if    defined(M_I86LM)
  676. XX    reg.x.dx = FP_OFF(dtapnt);
  677. XX    sreg.ds = FP_SEG(dtapnt);
  678. XX    intdosx(®, &nreg, &sreg);
  679. XX#else
  680. XX    reg.x.dx = (int) dtapnt;
  681. XX    intdos(®, &nreg);
  682. XX#endif
  683. XX}
  684. XEND_OF_FILE
  685. if test 4114 -ne `wc -c <'msd_dir.c'`; then
  686. X    echo shar: \"'msd_dir.c'\" unpacked with wrong size!
  687. fi
  688. X# end of 'msd_dir.c'
  689. fi
  690. if test -f 'msd_dir.h' -a "${1}" != "-c" ; then 
  691. X  echo shar: Will not clobber existing file \"'msd_dir.h'\"
  692. else
  693. echo shar: Extracting \"'msd_dir.h'\" \(954 characters\)
  694. sed "s/^X//" >'msd_dir.h' <<'END_OF_FILE'
  695. XX/*
  696. XX * @(#)msd_dir.h 1.4 87/11/06    Public Domain.
  697. XX *
  698. XX *  A public domain implementation of BSD directory routines for
  699. XX *  MS-DOS.  Written by Michael Rendell ({uunet,utai}michael@garfield),
  700. XX *  August 1897
  701. XX */
  702. XX
  703. XX#define    rewinddir(dirp)    seekdir(dirp, 0L)
  704. XX
  705. XX#define    MAXNAMLEN    12
  706. XX
  707. struct direct {
  708. XX    ino_t    d_ino;            /* a bit of a farce */
  709. XX    int    d_reclen;        /* more farce */
  710. XX    int    d_namlen;        /* length of d_name */
  711. XX    char    d_name[MAXNAMLEN + 1];        /* garentee null termination */
  712. XX};
  713. XX
  714. struct _dircontents {
  715. XX    char    *_d_entry;
  716. XX    struct _dircontents    *_d_next;
  717. XX};
  718. XX
  719. typedef struct _dirdesc {
  720. XX    int        dd_id;    /* uniquely identify each open directory */
  721. XX    long        dd_loc;    /* where we are in directory entry is this */
  722. XX    struct _dircontents    *dd_contents;    /* pointer to contents of dir */
  723. XX    struct _dircontents    *dd_cp;    /* pointer to current position */
  724. XX} DIR;
  725. XX
  726. extern    DIR        *opendir();
  727. extern    struct direct    *readdir();
  728. extern    void        seekdir();
  729. extern    long        telldir();
  730. extern    void        closedir();
  731. XEND_OF_FILE
  732. if test 954 -ne `wc -c <'msd_dir.h'`; then
  733. X    echo shar: \"'msd_dir.h'\" unpacked with wrong size!
  734. fi
  735. X# end of 'msd_dir.h'
  736. fi
  737. echo shar: End of shell archive.
  738. exit 0
  739. END_OF_FILE
  740. if test 6547 -ne `wc -c <'dir.msdos'`; then
  741.     echo shar: \"'dir.msdos'\" unpacked with wrong size!
  742. fi
  743. # end of 'dir.msdos'
  744. fi
  745. if test -f 'findsrc.man' -a "${1}" != "-c" ; then 
  746.   echo shar: Will not clobber existing file \"'findsrc.man'\"
  747. else
  748. echo shar: Extracting \"'findsrc.man'\" \(1859 characters\)
  749. sed "s/^X//" >'findsrc.man' <<'END_OF_FILE'
  750. X.TH FINDSRC 1l
  751. X.\" $Header: findsrc.man,v 2.0 88/05/27 13:28:20 rsalz Exp $
  752. X.SH NAME
  753. findsrc \- walk directories, trying to find source files
  754. X.SH SYNOPSIS
  755. X.B findsrc
  756. X[
  757. X.B \-.
  758. X] [
  759. X.BI \-d\| y_or_n
  760. X] [
  761. X.BI \-o\| output_file
  762. X] [
  763. X.B \-R
  764. X] [
  765. X.B \-S
  766. X] [
  767. X.B \-v
  768. X] [ file... ]
  769. X.SH DESCRIPTION
  770. X.I Findsrc
  771. recursively examines all directories and files specified on the command
  772. line, and determines, based on the file name, whether the file contains
  773. source code or not.
  774. All directories are listed first, followed by all regular files,
  775. with one item per line.
  776. X.PP
  777. If
  778. X.I findsrc
  779. is unable to make a decision, it invokes the
  780. X.IR file (1)
  781. command, and prompts the user for a decision.
  782. In reply to the prompt, type the letter ``y'' or ``n'' (either case);
  783. RETURN means yes.
  784. If the reply starts with an exclamation point, the rest of the line
  785. is passed off to a sub-shell and the question is repeated.
  786. The ``\-d'' option may be used with an argument of ``y'' or ``n''
  787. to by-pass the interaction, and provide a default answer.
  788. X.PP
  789. The ``\-o'' option may be used to specify an output filename.
  790. This is designed to prevent confusion if a command like the following
  791. is executed:
  792. X.RS
  793. findsrc . * >LIST
  794. X.RE
  795. X.PP
  796. By default,
  797. X.I findsrc
  798. ignores files whose names begin with a period, like ``.newsrc'' or
  799. X``.tags''; such files may be included by using the ``\-.'' option.
  800. X.I Findsrc
  801. also normally ignores
  802. RCS and SCCS files and directories; using either the ``\-R'' or ``\-S''
  803. option causes both to be included.
  804. X.PP
  805. X.I Findsrc
  806. normally lists only the names of those files that have been selected.
  807. If the ``\-v'' option is used, rejected files are also listed preceeded
  808. by the word ``PUNTED.''
  809. X.PP
  810. If no files are specified on the command line, the program operates as
  811. a filter, reading a list of files and directories from the standard
  812. input, one per line.
  813. X.SH "SEE ALSO"
  814. makekit(1l).
  815. END_OF_FILE
  816. if test 1859 -ne `wc -c <'findsrc.man'`; then
  817.     echo shar: \"'findsrc.man'\" unpacked with wrong size!
  818. fi
  819. # end of 'findsrc.man'
  820. fi
  821. if test -f 'glue.c' -a "${1}" != "-c" ; then 
  822.   echo shar: Will not clobber existing file \"'glue.c'\"
  823. else
  824. echo shar: Extracting \"'glue.c'\" \(1239 characters\)
  825. sed "s/^X//" >'glue.c' <<'END_OF_FILE'
  826. X/*
  827. X**  Subroutine to call the shell archive parser.  This is "glue"
  828. X**  between unshar and the parser proper.
  829. X*/
  830. X#include "shar.h"
  831. X#ifdef    RCSID
  832. static char RCS[] =
  833. X    "$Header: glue.c,v 2.0 88/05/27 13:26:14 rsalz Exp $";
  834. X#endif    /* RCSID */
  835. X
  836. X
  837. X#ifdef    USE_MY_SHELL
  838. X/*
  839. X**  Cleanup routine after BinSh is done
  840. X*/
  841. void
  842. BSclean()
  843. X{
  844. X    (void)fclose(Input);
  845. X    (void)unlink(File);
  846. X}
  847. X
  848. X
  849. X/*
  850. X**  Copy the input to a temporary file, then call the shell parser.
  851. X*/
  852. BinSh(Name, Stream, Pushback)
  853. X    char        *Name;
  854. X    REGISTER FILE    *Stream;
  855. X    char        *Pushback;
  856. X{
  857. X    REGISTER FILE    *F;
  858. X    char         buff[BUFSIZ];
  859. X    char        *vec[MAX_WORDS];
  860. X
  861. X    Interactive = Name == NULL;
  862. X#ifdef    MSDOS
  863. X    File = "shell.XXX";
  864. X    onexit(BSclean);
  865. X#else
  866. X    File = mktemp("/tmp/shellXXXXXX");
  867. X#endif    /* MSDOS */
  868. X
  869. X    F = fopen(File, "w");
  870. X    (void)fputs(Pushback, F);
  871. X    while (fgets(buff, sizeof buff, Stream))
  872. X    (void)fputs(buff, F);
  873. X    (void)fclose(Stream);
  874. X
  875. X    if ((Input = fopen(TEMP, "r")) == NULL)
  876. X    Fprintf(stderr, "Can't open %s, %s!?\n", TEMP, Ermsg(errno));
  877. X    else
  878. X    while (GetLine(TRUE)) {
  879. X#ifdef    MSDOS
  880. X        if (setjmp(jEnv))
  881. X        break;
  882. X#endif    /* MSDOS */
  883. X        if (Argify(vec) && Exec(vec) == -FALSE)
  884. X            break;
  885. X    }
  886. X
  887. X    BSclean();
  888. X}
  889. X#endif    /* USE_MY_SHELL */
  890. END_OF_FILE
  891. if test 1239 -ne `wc -c <'glue.c'`; then
  892.     echo shar: \"'glue.c'\" unpacked with wrong size!
  893. fi
  894. # end of 'glue.c'
  895. fi
  896. if test -f 'lcwd.c' -a "${1}" != "-c" ; then 
  897.   echo shar: Will not clobber existing file \"'lcwd.c'\"
  898. else
  899. echo shar: Extracting \"'lcwd.c'\" \(1110 characters\)
  900. sed "s/^X//" >'lcwd.c' <<'END_OF_FILE'
  901. X/*
  902. X**  Return current working directory.  Something for everyone.
  903. X*/
  904. X/* LINTLIBRARY */
  905. X#include "shar.h"
  906. X#ifdef    RCSID
  907. static char RCS[] =
  908. X    "$Header: lcwd.c,v 2.0 88/05/27 13:26:24 rsalz Exp $";
  909. X#endif    /* RCSID */
  910. X
  911. X
  912. X#ifdef    PWDGETENV
  913. X/* ARGSUSED */
  914. char *
  915. Cwd(p, i)
  916. X    char    *p;
  917. X    int         i;
  918. X{
  919. X    char    *q;
  920. X
  921. X    return((q = getenv(PWDGETENV)) ? strcpy(p, q) : NULL);
  922. X}
  923. X#endif    /* PWDGETENV */
  924. X
  925. X
  926. X#ifdef    GETWD
  927. X/* ARGSUSED1 */
  928. char *
  929. Cwd(p, size)
  930. X    char    *p;
  931. X    int         size;
  932. X{
  933. X    extern char    *getwd();
  934. X
  935. X    return(getwd(p) ? p : NULL);
  936. X}
  937. X#endif    /* GETWD */
  938. X
  939. X
  940. X#ifdef    GETCWD
  941. char *
  942. Cwd(p, size)
  943. X    char    *p;
  944. X    int         size;
  945. X{
  946. X    extern char    *getcwd();
  947. X
  948. X    return(getcwd(p, size) ? p : NULL);
  949. X}
  950. X#endif    /* GETCWD */
  951. X
  952. X
  953. X#ifdef    PWDPOPEN
  954. char *
  955. Cwd(p, size)
  956. X    char    *p;
  957. X    int         size;
  958. X{
  959. X    extern FILE    *popen();
  960. X    FILE    *F;
  961. X    int         i;
  962. X
  963. X    /* This string could be "exec /bin/pwd" if you want... */
  964. X    if (F = popen("pwd", "r")) {
  965. X    if (fgets(p, size, F) && p[i = strlen(p) - 1] == '\n') {
  966. X        p[i] = '\0';
  967. X        (void)fclose(F);
  968. X        return(p);
  969. X    }
  970. X    (void)fclose(F);
  971. X    }
  972. X    return(NULL);
  973. X}
  974. X#endif    /* PWDPOPEN */
  975. END_OF_FILE
  976. if test 1110 -ne `wc -c <'lcwd.c'`; then
  977.     echo shar: \"'lcwd.c'\" unpacked with wrong size!
  978. fi
  979. # end of 'lcwd.c'
  980. fi
  981. if test -f 'lexec.c' -a "${1}" != "-c" ; then 
  982.   echo shar: Will not clobber existing file \"'lexec.c'\"
  983. else
  984. echo shar: Extracting \"'lexec.c'\" \(2062 characters\)
  985. sed "s/^X//" >'lexec.c' <<'END_OF_FILE'
  986. X/*
  987. X**  Process stuff, like fork exec and wait.  Also signals.
  988. X*/
  989. X/* LINTLIBRARY */
  990. X#include "shar.h"
  991. X#include <signal.h>
  992. X#ifdef    RCSID
  993. static char RCS[] =
  994. X    "$Header: lexec.c,v 2.0 88/05/27 13:26:35 rsalz Exp $";
  995. X#endif    /* RCSID */
  996. X
  997. X
  998. X/* How to fork(), what to wait with. */
  999. X#ifdef    SYS_WAIT
  1000. X#include <sys/wait.h>
  1001. X#define FORK()         vfork()
  1002. X#define W_VAL(w)     ((w).w_retcode)
  1003. typedef union wait     WAITER;
  1004. X#else
  1005. X#define FORK()         fork()
  1006. X#define W_VAL(w)     ((w) >> 8)
  1007. typedef int         WAITER;
  1008. X#endif    /* SYS_WAIT */
  1009. X
  1010. X
  1011. X
  1012. X/*
  1013. X**  Set up a signal handler.
  1014. X*/
  1015. SetSigs(What, Func)
  1016. X    int          What;
  1017. X    sigret_t    (*Func)();
  1018. X{
  1019. X    if (What == S_IGNORE)
  1020. X    Func = SIG_IGN;
  1021. X    else if (What == S_RESET)
  1022. X    Func = SIG_DFL;
  1023. X#ifdef    SIGINT
  1024. X    if (signal(SIGINT, SIG_IGN) != SIG_IGN)
  1025. X    (void)signal(SIGINT, Func);
  1026. X#endif    /* SIGINT */
  1027. X#ifdef    SIGQUIT
  1028. X    if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
  1029. X    (void)signal(SIGQUIT, Func);
  1030. X#endif    /* SIGQUIT */
  1031. X}
  1032. X
  1033. X
  1034. X/*
  1035. X**  Return the process ID.
  1036. X*/
  1037. int
  1038. Pid()
  1039. X{
  1040. X#ifdef    MSDOS
  1041. X    return(1);
  1042. X#else
  1043. X    static int     X;
  1044. X
  1045. X    if (X == 0)
  1046. X    X = getpid();
  1047. X    return(X);
  1048. X#endif    /* MSDOS */
  1049. X}
  1050. X
  1051. X
  1052. X#ifndef    USE_SYSTEM
  1053. X/*
  1054. X**  Fork off a command.
  1055. X*/
  1056. int
  1057. XExecute(av)
  1058. X    char        *av[];
  1059. X{
  1060. X    REGISTER int     i;
  1061. X    REGISTER int     j;
  1062. X    WAITER         W;
  1063. X
  1064. X    if ((i = FORK()) == 0) {
  1065. X    SetSigs(S_RESET, (sigret_t (*)())NULL);
  1066. X    (void)execvp(av[0], av);
  1067. X    perror(av[0]);
  1068. X    _exit(1);
  1069. X    }
  1070. X
  1071. X    SetSigs(S_IGNORE, (sigret_t (*)())NULL);
  1072. X    while ((j = wait(&W)) < 0 && j != i)
  1073. X    ;
  1074. X    SetSigs(S_RESET, (sigret_t (*)())NULL);
  1075. X    return(W_VAL(W));
  1076. X}
  1077. X
  1078. X#else
  1079. X
  1080. X/*
  1081. X**  Cons all the arguments together into a single command line and hand
  1082. X**  it off to the shell to execute.
  1083. X*/
  1084. int
  1085. XExecute(av)
  1086. X    REGISTER char    *av[];
  1087. X{
  1088. X    REGISTER char    **v;
  1089. X    REGISTER char     *p;
  1090. X    REGISTER char     *q;
  1091. X    REGISTER int     i;
  1092. X
  1093. X    /* Get length of command line. */
  1094. X    for (i = 0, v = av; *v; v++)
  1095. X    i += strlen(*v) + 1;
  1096. X
  1097. X    /* Create command line and execute it. */
  1098. X    p = NEW(char, i);
  1099. X    for (q = p, v = av; *v; v++) {
  1100. X    *q++ = ' ';
  1101. X    q += strlen(strcpy(q, *v));
  1102. X    }
  1103. X
  1104. X    return(system(p));
  1105. X}
  1106. X#endif    /* USE_SYSTEM */
  1107. END_OF_FILE
  1108. if test 2062 -ne `wc -c <'lexec.c'`; then
  1109.     echo shar: \"'lexec.c'\" unpacked with wrong size!
  1110. fi
  1111. # end of 'lexec.c'
  1112. fi
  1113. if test -f 'lfiles.c' -a "${1}" != "-c" ; then 
  1114.   echo shar: Will not clobber existing file \"'lfiles.c'\"
  1115. else
  1116. echo shar: Extracting \"'lfiles.c'\" \(1007 characters\)
  1117. sed "s/^X//" >'lfiles.c' <<'END_OF_FILE'
  1118. X/*
  1119. X**  File related routines.
  1120. X*/
  1121. X/* LINTLIBRARY */
  1122. X#include "shar.h"
  1123. X#include <sys/stat.h>
  1124. X#ifdef    RCSID
  1125. static char RCS[] =
  1126. X    "$Header: lfiles.c,v 2.0 88/05/27 13:26:47 rsalz Exp $";
  1127. X#endif    /* RCSID */
  1128. X
  1129. X
  1130. X/* Mask of executable bits. */
  1131. X#define    EXE_MASK    (S_IEXEC | (S_IEXEC >> 3) | (S_IEXEC >> 6))
  1132. X
  1133. X/* Stat buffer for last file. */
  1134. static struct stat     Sb;
  1135. X
  1136. X
  1137. X/*
  1138. X**  Stat the file if it's not the one we did last time.
  1139. X*/
  1140. int
  1141. GetStat(p)
  1142. X    char        *p;
  1143. X{
  1144. X    static char         Name[BUFSIZ];
  1145. X
  1146. X    if (*p == Name[0] && EQ(p, Name))
  1147. X    return(TRUE);
  1148. X    return(stat(strcpy(Name, p), &Sb) < 0 ? FALSE : TRUE);
  1149. X}
  1150. X
  1151. X
  1152. X/*
  1153. X**  Return the file type -- directory or regular file.
  1154. X*/
  1155. int
  1156. XFtype(p)
  1157. X    char    *p;
  1158. X{
  1159. X    return(GetStat(p) && ((Sb.st_mode & S_IFMT) == S_IFDIR) ? F_DIR : F_FILE);
  1160. X}
  1161. X
  1162. X
  1163. X/*
  1164. X**  Return the file size.
  1165. X*/
  1166. off_t
  1167. XFsize(p)
  1168. X    char    *p;
  1169. X{
  1170. X    return(GetStat(p) ? Sb.st_size : 0);
  1171. X}
  1172. X
  1173. X
  1174. X/*
  1175. X**  Is a file executable?
  1176. X*/
  1177. int
  1178. XFexecute(p)
  1179. X    char    *p;
  1180. X{
  1181. X    return(GetStat(p) && (Sb.st_mode & EXE_MASK) ? TRUE : FALSE);
  1182. X}
  1183. END_OF_FILE
  1184. if test 1007 -ne `wc -c <'lfiles.c'`; then
  1185.     echo shar: \"'lfiles.c'\" unpacked with wrong size!
  1186. fi
  1187. # end of 'lfiles.c'
  1188. fi
  1189. if test -f 'lhost.c' -a "${1}" != "-c" ; then 
  1190.   echo shar: Will not clobber existing file \"'lhost.c'\"
  1191. else
  1192. echo shar: Extracting \"'lhost.c'\" \(1714 characters\)
  1193. sed "s/^X//" >'lhost.c' <<'END_OF_FILE'
  1194. X/*
  1195. X**  Return name of this host.  Something for everyone.
  1196. X*/
  1197. X/* LINTLIBRARY */
  1198. X#include "shar.h"
  1199. X#ifdef    RCSID
  1200. static char RCS[] =
  1201. X    "$Header: lhost.c,v 2.0 88/05/27 13:27:01 rsalz Exp $";
  1202. X#endif    /* RCSID */
  1203. X
  1204. X
  1205. X#ifdef    HOST
  1206. char *
  1207. Host()
  1208. X{
  1209. X    return(HOST);
  1210. X}
  1211. X#endif    /* HOST */
  1212. X
  1213. X
  1214. X#ifdef    GETHOSTNAME
  1215. char *
  1216. Host()
  1217. X{
  1218. X    static char         buff[64];
  1219. X
  1220. X    return(gethostname(buff, sizeof buff) < 0 ? "SITE" : buff);
  1221. X}
  1222. X#endif    /* GETHOSTNAME */
  1223. X
  1224. X
  1225. X#ifdef    UNAME
  1226. X#include <sys/utsname.h>
  1227. char *
  1228. Host()
  1229. X{
  1230. X    static struct utsname     U;
  1231. X
  1232. X    return(uname(&U) < 0 ? "SITE" : U.nodename);
  1233. X}
  1234. X#endif    /* UNAME */
  1235. X
  1236. X
  1237. X#ifdef    UUNAME
  1238. extern FILE    *popen();
  1239. char *
  1240. Host()
  1241. X{
  1242. X    static char         buff[50];
  1243. X    FILE        *F;
  1244. X    char        *p;
  1245. X
  1246. X    if (F = popen("exec uuname -l", "r")) {
  1247. X    if (fgets(buff, sizeof buff, F) == buff && (p = IDX(buff, '\n'))) {
  1248. X        (void)pclose(F);
  1249. X        *p = '\0';
  1250. X        return(buff);
  1251. X    }
  1252. X    (void)pclose(F);
  1253. X    }
  1254. X    return("SITE");
  1255. X}
  1256. X#endif    /* UUNAME */
  1257. X
  1258. X
  1259. X#ifdef    WHOAMI
  1260. char *
  1261. Host()
  1262. X{
  1263. X    static char         name[64];
  1264. X    REGISTER FILE    *F;
  1265. X    REGISTER char    *p;
  1266. X    char         buff[100];
  1267. X
  1268. X    /* Try /etc/whoami; look for a single well-formed line. */
  1269. X    if (F = fopen("/etc/whoami", "r")) {
  1270. X    if (fgets(name, sizeof name, F) && (p = IDX(name, '\n'))) {
  1271. X        (void)fclose(F);
  1272. X        *p = '\0';
  1273. X        return(name);
  1274. X    }
  1275. X    (void)fclose(F);
  1276. X    }
  1277. X
  1278. X    /* Try /usr/include/whoami.h; look for #define sysname "foo" somewhere. */
  1279. X    if (F = fopen("/usr/include/whoami.h", "r")) {
  1280. X    while (fgets(buff, sizeof buff, F))
  1281. X        /* I don't like sscanf, nor do I trust it.  Sigh. */
  1282. X        if (sscanf(buff, "#define sysname \"%[^\"]\"", name) == 1) {
  1283. X        (void)fclose(F);
  1284. X        return(name);
  1285. X        }
  1286. X    (void)fclose(F);
  1287. X    }
  1288. X    return("SITE");
  1289. X}
  1290. X#endif /* WHOAMI */
  1291. END_OF_FILE
  1292. if test 1714 -ne `wc -c <'lhost.c'`; then
  1293.     echo shar: \"'lhost.c'\" unpacked with wrong size!
  1294. fi
  1295. # end of 'lhost.c'
  1296. fi
  1297. if test -f 'llib.c' -a "${1}" != "-c" ; then 
  1298.   echo shar: Will not clobber existing file \"'llib.c'\"
  1299. else
  1300. echo shar: Extracting \"'llib.c'\" \(3393 characters\)
  1301. sed "s/^X//" >'llib.c' <<'END_OF_FILE'
  1302. X/*
  1303. X**  Some systems will need these routines because they're missing from
  1304. X**  their C library.  I put Ermsg() here so that everyone will need
  1305. X**  something from this file...
  1306. X*/
  1307. X/* LINTLIBRARY */
  1308. X#include "shar.h"
  1309. X#ifdef    RCSID
  1310. static char RCS[] =
  1311. X    "$Header: llib.c,v 2.0 88/05/27 13:27:09 rsalz Exp $";
  1312. X#endif    /* RCSID */
  1313. X
  1314. X
  1315. X/*
  1316. X**  Return the text string that corresponds to errno.
  1317. X*/
  1318. char *
  1319. XErmsg(e)
  1320. X    int             e;
  1321. X{
  1322. X#ifdef    USE_SYSERRLIST
  1323. X    extern int         sys_nerr;
  1324. X    extern char        *sys_errlist[];
  1325. X#endif    /* USE_SYSERRLIST */
  1326. X    static char         buff[30];
  1327. X
  1328. X#ifdef    USE_SYSERRLIST
  1329. X    if (e > 0 && e < sys_nerr)
  1330. X    return(sys_errlist[e]);
  1331. X#endif    /* USE_SYSERRLIST */
  1332. X    (void)sprintf(buff, "Error code %d", e);
  1333. X    return(buff);
  1334. X}
  1335. X
  1336. X
  1337. X
  1338. X#ifdef    NEED_MKDIR
  1339. X/*
  1340. X**  Quick and dirty mkdir routine for them that's need it.
  1341. X*/
  1342. int
  1343. mkdir(name, mode)
  1344. X    char    *name;
  1345. X    int         mode;
  1346. X{
  1347. X    char    *av[3];
  1348. X    int         i;
  1349. X    int         U;
  1350. X
  1351. X    av[0] = "mkdir";
  1352. X    av[1] = name;
  1353. X    av[2] = NULL;
  1354. X    U = umask(~mode);
  1355. X    i = Execute(av);
  1356. X    (void)umask(U);
  1357. X    return(i ? -1 : 0);
  1358. X}
  1359. X#endif    /* NEED_MKDIR */
  1360. X
  1361. X
  1362. X#ifdef    NEED_QSORT
  1363. X/*
  1364. X**  Bubble sort an array of arbitrarily-sized elements.  This routine
  1365. X**  can be used as an (inefficient) replacement for the Unix qsort
  1366. X**  routine, hence the name.  If I were to put this into my C library,
  1367. X**  I'd do two things:
  1368. X**    -Make it be a quicksort;
  1369. X**    -Have a front routine which called specialized routines for
  1370. X**     cases where Width equals sizeof(int), sizeof(char *), etc.
  1371. X*/
  1372. qsort(Table, Number, Width, Compare)
  1373. X    REGISTER char     *Table;
  1374. X    REGISTER int      Number;
  1375. X    REGISTER int      Width;
  1376. X    REGISTER int    (*Compare)();
  1377. X{
  1378. X    REGISTER char     *i;
  1379. X    REGISTER char     *j;
  1380. X
  1381. X    for (i = &Table[Number * Width]; (i -= Width) >= &Table[Width]; )
  1382. X    for (j = i; (j -= Width) >= &Table[0]; )
  1383. X        if ((*Compare)(i, j) < 0) {
  1384. X        REGISTER char    *p;
  1385. X        REGISTER char    *q;
  1386. X        REGISTER int     t;
  1387. X        REGISTER int     w;
  1388. X
  1389. X        /* Swap elements pointed to by i and j. */
  1390. X        for (w = Width, p = i, q = j; --w >= 0; *p++ = *q, *q++ = t)
  1391. X            t = *p;
  1392. X        }
  1393. X}
  1394. X#endif    /* NEED_QSORT */
  1395. X
  1396. X
  1397. X#ifdef    NEED_GETOPT
  1398. X
  1399. X#define TYPE    int
  1400. X
  1401. X#define ERR(s, c)    if(opterr){\
  1402. X    char errbuf[2];\
  1403. X    errbuf[0] = c; errbuf[1] = '\n';\
  1404. X    (void) write(2, argv[0], (TYPE)strlen(argv[0]));\
  1405. X    (void) write(2, s, (TYPE)strlen(s));\
  1406. X    (void) write(2, errbuf, 2);}
  1407. X
  1408. extern int strcmp();
  1409. X
  1410. int    opterr = 1;
  1411. int    optind = 1;
  1412. int    optopt;
  1413. char    *optarg;
  1414. X
  1415. X/*
  1416. X**  Return options and their values from the command line.
  1417. X**  This comes from the AT&T public-domain getopt published in mod.sources.
  1418. X*/
  1419. int
  1420. getopt(argc, argv, opts)
  1421. int    argc;
  1422. char    **argv, *opts;
  1423. X{
  1424. X    static int sp = 1;
  1425. X    REGISTER int c;
  1426. X    REGISTER char *cp;
  1427. X
  1428. X    if(sp == 1)
  1429. X        if(optind >= argc ||
  1430. X           argv[optind][0] != '-' || argv[optind][1] == '\0')
  1431. X            return(EOF);
  1432. X        else if(strcmp(argv[optind], "--") == NULL) {
  1433. X            optind++;
  1434. X
  1435. X        }
  1436. X    optopt = c = argv[optind][sp];
  1437. X    if(c == ':' || (cp=IDX(opts, c)) == NULL) {
  1438. X        ERR(": illegal option -- ", c);
  1439. X        if(argv[optind][++sp] == '\0') {
  1440. X            optind++;
  1441. X            sp = 1;
  1442. X        }
  1443. X        return('?');
  1444. X    }
  1445. X    if(*++cp == ':') {
  1446. X        if(argv[optind][sp+1] != '\0')
  1447. X            optarg = &argv[optind++][sp+1];
  1448. X        else if(++optind >= argc) {
  1449. X            ERR(": option requires an argument -- ", c);
  1450. X            sp = 1;
  1451. X            return('?');
  1452. X        } else
  1453. X            optarg = argv[optind++];
  1454. X        sp = 1;
  1455. X    } else {
  1456. X        if(argv[optind][++sp] == '\0') {
  1457. X            sp = 1;
  1458. X            optind++;
  1459. X        }
  1460. X        optarg = NULL;
  1461. X    }
  1462. X    return(c);
  1463. X}
  1464. X
  1465. X#endif    /* NEED_GETOPT */
  1466. END_OF_FILE
  1467. if test 3393 -ne `wc -c <'llib.c'`; then
  1468.     echo shar: \"'llib.c'\" unpacked with wrong size!
  1469. fi
  1470. # end of 'llib.c'
  1471. fi
  1472. if test -f 'lmem.c' -a "${1}" != "-c" ; then 
  1473.   echo shar: Will not clobber existing file \"'lmem.c'\"
  1474. else
  1475. echo shar: Extracting \"'lmem.c'\" \(579 characters\)
  1476. sed "s/^X//" >'lmem.c' <<'END_OF_FILE'
  1477. X/*
  1478. X**  Get some memory or die trying.
  1479. X*/
  1480. X/* LINTLIBRARY */
  1481. X#include "shar.h"
  1482. X#ifdef    RCSID
  1483. static char RCS[] =
  1484. X    "$Header: lmem.c,v 2.0 88/05/27 13:27:16 rsalz Exp $";
  1485. X#endif    /* RCSID */
  1486. X
  1487. X
  1488. align_t
  1489. getmem(i, j)
  1490. X    unsigned int     i;
  1491. X    unsigned int     j;
  1492. X{
  1493. X    extern char        *calloc();
  1494. X    align_t         p;
  1495. X
  1496. X    /* Lint fluff:  "possible pointer alignment problem." */
  1497. X    if ((p = (align_t)calloc(i, j)) == NULL) {
  1498. X    /* Print the unsigned values as int's so ridiculous values show up. */
  1499. X    Fprintf(stderr, "Can't Calloc(%d,%d), %s.\n", i, j, Ermsg(errno));
  1500. X    exit(1);
  1501. X    }
  1502. X    return(p);
  1503. X}
  1504. END_OF_FILE
  1505. if test 579 -ne `wc -c <'lmem.c'`; then
  1506.     echo shar: \"'lmem.c'\" unpacked with wrong size!
  1507. fi
  1508. # end of 'lmem.c'
  1509. fi
  1510. if test -f 'luser.c' -a "${1}" != "-c" ; then 
  1511.   echo shar: Will not clobber existing file \"'luser.c'\"
  1512. else
  1513. echo shar: Extracting \"'luser.c'\" \(727 characters\)
  1514. sed "s/^X//" >'luser.c' <<'END_OF_FILE'
  1515. X/*
  1516. X**  Get user name.  Something for everyone.
  1517. X*/
  1518. X/* LINTLIBRARY */
  1519. X#include "shar.h"
  1520. X#ifdef    USE_GETPWUID
  1521. X#include <pwd.h>
  1522. X#endif    /* USE_GETPWUID */
  1523. X#ifdef    RCSID
  1524. static char RCS[] =
  1525. X    "$Header: luser.c,v 2.0 88/05/27 13:27:23 rsalz Exp $";
  1526. X#endif    /* RCSID */
  1527. X
  1528. X
  1529. X/*
  1530. X**  Get user name.  Not secure, but who sends nastygrams as shell archives?
  1531. X*/
  1532. char *
  1533. User()
  1534. X{
  1535. X#ifdef    USE_GETPWUID
  1536. X    extern struct passwd    *getpwuid();
  1537. X    struct passwd        *p;
  1538. X#endif    /* USE_GETPWUID */
  1539. X    char            *g;
  1540. X
  1541. X    if (g = getenv("USER"))
  1542. X    return(g);
  1543. X    if (g = getenv("LOGNAME"))
  1544. X    return(g);
  1545. X    if (g = getenv("NAME"))
  1546. X    return(g);
  1547. X#ifdef    USE_GETPWUID
  1548. X    if (p = getpwuid(getuid()))
  1549. X    return(p->pw_name);
  1550. X#endif    /* USE_GETPWUID */
  1551. X    return(USERNAME);
  1552. X}
  1553. END_OF_FILE
  1554. if test 727 -ne `wc -c <'luser.c'`; then
  1555.     echo shar: \"'luser.c'\" unpacked with wrong size!
  1556. fi
  1557. # end of 'luser.c'
  1558. fi
  1559. if test -f 'makekit.man' -a "${1}" != "-c" ; then 
  1560.   echo shar: Will not clobber existing file \"'makekit.man'\"
  1561. else
  1562. echo shar: Extracting \"'makekit.man'\" \(4320 characters\)
  1563. sed "s/^X//" >'makekit.man' <<'END_OF_FILE'
  1564. X.TH MAKEKIT 1l
  1565. X.\" $Header: makekit.man,v 2.0 88/05/27 13:28:41 rsalz Exp $
  1566. X.SH NAME
  1567. makekit \- split files up into shell archive packages
  1568. X.SH SYNOPSIS
  1569. X.B makekit
  1570. X[
  1571. X.B -1
  1572. X] [
  1573. X[
  1574. X.B -e
  1575. X] [
  1576. X.BI -h\| #
  1577. X] [
  1578. X.BI -i\| name
  1579. X] [
  1580. X.BI -k\| #
  1581. X] [
  1582. X.B -m
  1583. X] [
  1584. X.BI -n\| name
  1585. X] [
  1586. X.BI -o\| name
  1587. X] [
  1588. X.B -p
  1589. X] [
  1590. X.BI -s\| #[k]
  1591. X] [
  1592. X.BI -t\| text
  1593. X] [ file... ]
  1594. X.SH DESCRIPTION
  1595. X.I Makekit
  1596. reads a list of files and directories, determines their sizes,
  1597. and parcels them up into a series of shell archives such that all the
  1598. archives are of reasonable size.
  1599. It then invokes
  1600. X.IR shar (1l)
  1601. to actually create the archives.
  1602. X.PP
  1603. By default, no archive will be larger than about 50,000 bytes; this may be
  1604. changed by using the ``\-s'' option.
  1605. If the number given with the ``\-s'' option ends with the letter ``k''
  1606. then the size is multiplied by 1024, otherwise it is taken to be the
  1607. desired maximum size, in bytes.
  1608. XEach archive will have a name that looks like
  1609. X.IR Part nn,
  1610. where ``nn'' represents the two-digit sequence number (with leading zero
  1611. if needed).
  1612. The leader part of the archive name may be changed with the ``\-n'' option.
  1613. The ``\-n'' is also useful when write permission to the directory being
  1614. archive is denied; e.g., ``\-n/tmp/KERNEL.''
  1615. X.PP
  1616. X.I Makekit
  1617. reads its list of files on the command line, or standard input
  1618. if none are given.
  1619. It is also possible to specify an input filename with the ``\-i'' option.
  1620. The input should contain a list of files, one to a line, to separate.
  1621. In addition, if each input line looks like this:
  1622. X.RS
  1623. filename\ \ \ whitespace\ \ \ optional-digits\ \ \ whitespace\ \ \ text
  1624. X.RE
  1625. then
  1626. X.I makekit
  1627. will ignore the spaces and digits, but remember the text associated with
  1628. each file, and output it with the filename when generating the ``shipping
  1629. manifest.''
  1630. XFurther, the ``\-h'' option may be given to have the program skip the
  1631. indicated number of lines in the input; this option is provided so that
  1632. X.I makekit
  1633. can more easily re-parse the manifests it has generated.
  1634. X.PP
  1635. The generated manifest will be sent to the standard output.
  1636. An alternate output file may be given by using the ``\-o'' option; if
  1637. the output file exists,
  1638. X.I makekit
  1639. will try to rename it with an extension of
  1640. X.IR \&.BAK \&.
  1641. If the ``\-o'' option is used,
  1642. X.I makekit
  1643. will add that name to the list of files to be archived; the ``\-e''
  1644. option may be given to exclude the manifest from the list.
  1645. X.PP
  1646. The ``\-m'' option is the same as giving the options,
  1647. X\&``-iMANIFEST -oMANIFEST -h2.''
  1648. This is a common way to regenerate a set of archives after the first
  1649. use of
  1650. X.I makekit
  1651. in a directory.
  1652. X.PP
  1653. If a large number of kits has to be generated, you may need to give
  1654. the ``\-k'' option to increase the maximum number of kits to be
  1655. generated.
  1656. X.PP
  1657. After partitioning the files and directories,
  1658. X.I makekit
  1659. calls
  1660. X.I shar
  1661. with the proper options to generate archives in a series.
  1662. XEach resultant archive will, when executed, check to see if all the parts
  1663. are present.
  1664. If the ``\-1'' option is used, then
  1665. X.I makekit
  1666. will not instruct
  1667. X.I shar
  1668. to generate the checks (by not passing on the ``\-n'' and ``\-e'' options).
  1669. By using the ``\-t'' option, you can specify a line of starting instructions
  1670. to display to the recipient when all pieces have been unpacked.
  1671. This is useful when resending part of a series that has probably already
  1672. been unpacked by the recipient.
  1673. See
  1674. X.I shar
  1675. for more information on multi-part archives.
  1676. If the ``\-x'' option is used,
  1677. X.I shar
  1678. is not called, but the manifest is still created.
  1679. X.PP
  1680. X.I Makekit
  1681. normally reorders its input so that the archives are as ``dense'' as
  1682. possible, with the exception that directories are given priority over
  1683. files, and a file named
  1684. X.I README
  1685. is the first of all.
  1686. The manifest is also sorted in alphabetical order; this makes it easy
  1687. to locate ``missing'' files when the distribution is a large one.
  1688. The ``\-p'' option may be used to override both sortings, however,
  1689. and preserve the original order of the input list in generating
  1690. both the manifest, and the shell archives.
  1691. X.SH NOTES
  1692. X.I Makekit
  1693. tries to partition the files so that all directories are in the first archive.
  1694. This usually means the first archive must be the first one to be unpacked.
  1695. X.PP
  1696. Saying ``the `\-k' option is to help prevent runaway packaging'' is probably
  1697. X.I "post hoc propter hoc"
  1698. reasoning.
  1699. X.SH "SEE ALSO"
  1700. findsrc(1l), shar(1l)
  1701. END_OF_FILE
  1702. if test 4320 -ne `wc -c <'makekit.man'`; then
  1703.     echo shar: \"'makekit.man'\" unpacked with wrong size!
  1704. fi
  1705. # end of 'makekit.man'
  1706. fi
  1707. if test -f 'patchlevel.h' -a "${1}" != "-c" ; then 
  1708.   echo shar: Will not clobber existing file \"'patchlevel.h'\"
  1709. else
  1710. echo shar: Extracting \"'patchlevel.h'\" \(214 characters\)
  1711. sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE'
  1712. X/*
  1713. X**  This file records official patches.  RCS records the edit log.
  1714. X**
  1715. X**  $Log:    patchlevel.h,v $
  1716. X**  Revision 2.0  88/05/27  13:32:13  rsalz
  1717. X**  First comp.sources.unix release
  1718. X**  
  1719. X**  
  1720. X*/
  1721. X#define PATCHLEVEL 0
  1722. END_OF_FILE
  1723. if test 214 -ne `wc -c <'patchlevel.h'`; then
  1724.     echo shar: \"'patchlevel.h'\" unpacked with wrong size!
  1725. fi
  1726. # end of 'patchlevel.h'
  1727. fi
  1728. if test -f 'shar.h' -a "${1}" != "-c" ; then 
  1729.   echo shar: Will not clobber existing file \"'shar.h'\"
  1730. else
  1731. echo shar: Extracting \"'shar.h'\" \(3038 characters\)
  1732. sed "s/^X//" >'shar.h' <<'END_OF_FILE'
  1733. X/*
  1734. X**  Header file for shar and friends.
  1735. X**  If you have to edit this file, then I messed something up, please
  1736. X**  let me know what.
  1737. X**
  1738. X**  $Header: shar.h,v 2.0 88/05/27 13:28:00 rsalz Exp $
  1739. X*/
  1740. X
  1741. X#include "config.h"
  1742. X
  1743. X#ifdef    ANSI_HDRS
  1744. X#include <stdlib.h>
  1745. X#include <stddef.h>
  1746. X#include <string.h>
  1747. X#include <io.h>
  1748. X#include <time.h>
  1749. X#else
  1750. X#include <stdio.h>
  1751. X#ifdef    VMS
  1752. X#include <types.h>
  1753. X#else
  1754. X#include <sys/types.h>
  1755. X#endif    /* VMS */
  1756. X#include <ctype.h>
  1757. X#include <setjmp.h>
  1758. X#endif    /* ANSI_HDRS */
  1759. X
  1760. X#ifdef    IN_SYS_DIR
  1761. X#include <sys/dir.h>
  1762. X#endif    /* IN_SYS_DIR */
  1763. X#ifdef    IN_DIR
  1764. X#include <dir.h>
  1765. X#endif    /* IN_DIR */
  1766. X#ifdef    IN_DIRECT
  1767. X#include <direct.h>
  1768. X#endif    /* IN_DIRECT */
  1769. X#ifdef    IN_SYS_NDIR
  1770. X#include <sys/ndir.h>
  1771. X#endif    /* IN_SYS_NDIR */
  1772. X#ifdef    IN_NDIR
  1773. X#include "ndir.h"
  1774. X#endif    /* IN_NDIR */
  1775. X#ifdef    IN_DIRENT
  1776. X#include "dirent.h"
  1777. X#endif    /* IN_DIRENT */
  1778. X
  1779. X
  1780. X/*
  1781. X**  Handy shorthands.
  1782. X*/
  1783. X#define TRUE        1
  1784. X#define FALSE        0
  1785. X#define WIDTH        72
  1786. X#define F_DIR        36        /* Something is a directory    */
  1787. X#define F_FILE        65        /* Something is a regular file    */
  1788. X#define S_IGNORE    76        /* Ignore this signal        */
  1789. X#define S_RESET        90        /* Reset signal to default    */
  1790. X
  1791. X/* These are used by the archive parser. */
  1792. X#define LINE_SIZE    200        /* Length of physical input line*/
  1793. X#define MAX_VARS     20        /* Number of shell vars allowed    */
  1794. X#define MAX_WORDS     30        /* Make words in command lnes    */
  1795. X#define VAR_NAME_SIZE     30        /* Length of a variable's name    */
  1796. X#define VAR_VALUE_SIZE    128        /* Length of a variable's value    */
  1797. X
  1798. X
  1799. X/*
  1800. X**  Lint placation.
  1801. X*/
  1802. X#ifdef    lint
  1803. X#undef RCSID
  1804. X#undef putchar
  1805. X#endif    /* lint */
  1806. X#define Fprintf        (void)fprintf
  1807. X#define Printf        (void)printf
  1808. X
  1809. X
  1810. X/*
  1811. X**  Memory hacking.
  1812. X*/
  1813. X#define NEW(T, count)    ((T *)getmem(sizeof (T), (unsigned int)(count)))
  1814. X#define ALLOC(n)    getmem(1, (unsigned int)(n))
  1815. X#define COPY(s)        strcpy(NEW(char, strlen((s)) + 1), (s))
  1816. X
  1817. X
  1818. X/*
  1819. X**  Macros.
  1820. X*/
  1821. X#define BADCHAR(c)    (iscntrl((c)) && !isspace((c)))
  1822. X#define EQ(a, b)    (strcmp((a), (b)) == 0)
  1823. X#define EQn(a, b, n)    (strncmp((a), (b), (n)) == 0)
  1824. X#define PREFIX(a, b)    (EQn((a), (b), sizeof b - 1))
  1825. X#define WHITE(c)    ((c) == ' ' || (c) == '\t')
  1826. X
  1827. X
  1828. X/*
  1829. X**  Linked in later.
  1830. X*/
  1831. extern int     errno;
  1832. extern int     optind;
  1833. extern char    *optarg;
  1834. X
  1835. X/* From your C run-time library. */
  1836. extern FILE    *popen();
  1837. extern time_t     time();
  1838. extern long     atol();
  1839. extern char    *IDX();
  1840. extern char    *RDX();
  1841. extern char    *ctime();
  1842. extern char    *gets();
  1843. extern char    *mktemp();
  1844. extern char    *strcat();
  1845. extern char    *strcpy();
  1846. extern char    *strncpy();
  1847. extern char       *getenv();
  1848. X#ifdef    PTR_SPRINTF
  1849. extern char    *sprintf();
  1850. X#endif    /* PTR_SPRINTF */
  1851. X
  1852. X/* From our local library. */
  1853. extern align_t     getmem();
  1854. extern off_t     Fsize();
  1855. extern char    *Copy();
  1856. extern char    *Cwd();
  1857. extern char    *Ermsg();
  1858. extern char    *Host();
  1859. extern char    *User();
  1860. X
  1861. X/* Exported by the archive parser. */
  1862. extern jmp_buf     jEnv;
  1863. extern FILE    *Input;            /* Current input stream        */
  1864. extern char    *File;            /* Input filename        */
  1865. extern int     Interactive;        /* isatty(fileno(stdin))?    */
  1866. extern void     SetVar();        /* Shell variable assignment    */
  1867. extern void     SynErr();        /* Fatal syntax error        */
  1868. END_OF_FILE
  1869. if test 3038 -ne `wc -c <'shar.h'`; then
  1870.     echo shar: \"'shar.h'\" unpacked with wrong size!
  1871. fi
  1872. # end of 'shar.h'
  1873. fi
  1874. if test -f 'shar.man' -a "${1}" != "-c" ; then 
  1875.   echo shar: Will not clobber existing file \"'shar.man'\"
  1876. else
  1877. echo shar: Extracting \"'shar.man'\" \(2967 characters\)
  1878. sed "s/^X//" >'shar.man' <<'END_OF_FILE'
  1879. X.TH SHAR 1l
  1880. X.\" $Header: shar.man,v 2.0 88/05/27 13:28:49 rsalz Exp $
  1881. X.SH NAME
  1882. shar \- create shell archive file for extraction by /bin/sh
  1883. X.SH SYNOPSIS
  1884. X.B shar
  1885. X[
  1886. X.B \-b
  1887. X] [
  1888. X.BI \-i\| input_file
  1889. X] [
  1890. X.BI \-n\| seq_number
  1891. X] [
  1892. X.BI \-e\| seq_end
  1893. X] [
  1894. X.BI \-o\| output_file
  1895. X] [
  1896. X.BI \-t\| final_text
  1897. X] [file...]
  1898. X.SH DESCRIPTION
  1899. X.I Shar
  1900. takes a list of files, and generates a
  1901. X.IR /bin/sh
  1902. script that, when executed, will re-create those files in a different
  1903. directory or on a different machine.
  1904. The resultant script will use
  1905. X.IR wc (1)
  1906. to do a mild error-check, and will warn about possibly-omitted
  1907. control characters.
  1908. X.PP
  1909. X.I Shar
  1910. generates scripts that will make directories and plain files.
  1911. It will not try to generate intermediate filenames, however, so
  1912. X.RS
  1913. shar foo/bar/file
  1914. X.RE
  1915. will not work.  Do
  1916. X.RS
  1917. shar foo foo/bar foo/bar/file
  1918. X.RE
  1919. instead.
  1920. X.PP
  1921. The script is normally sent to standard output; the ``\-o'' option may be
  1922. used to specify an output filename.
  1923. This is designed to prevent filling up the disk if
  1924. X.RS
  1925. shar * >SHAR
  1926. X.RE
  1927. command is done; do
  1928. X.RS
  1929. shar -o SHAR *
  1930. X.RE
  1931. instead.
  1932. X.PP
  1933. The list of files is normally specified on the command line; the ''\-i''
  1934. option may be used instead, to specify a file that contains the list
  1935. of files to pack up, one per line.
  1936. If the file name is ``-'' the standard input is read.
  1937. X.PP
  1938. The ``\-b'' option says that all leading directory names should be stripped
  1939. from the file when they are packed into the archive.
  1940. XFor example,
  1941. X.RS
  1942. shar -b /etc/termcap
  1943. X.RE
  1944. creates an archive that, when executed, creates a file named
  1945. X``termcap'' in the current directory, rather than overwrite the
  1946. host system file.
  1947. Note, however, that the scripts generated by
  1948. X.I shar
  1949. normally refuse to overwrite pre-existing files.
  1950. X.SS "Multi\-part Archives"
  1951. Most larger software packages are usually sent out in two or more shell
  1952. archives.
  1953. The ``\-n,'' ``\-e,'' and ``\-t'' options are used to make an archive
  1954. that is part of a series.
  1955. The individual archives are often called ``kits'' when this is done.
  1956. The ``\-n'' option specifies the archive number; the ``\-e'' option species
  1957. the highest number in the series.
  1958. When executed, the generated archives will then echo messages like
  1959. X.RS
  1960. shar: End of archive 3 of 9.
  1961. X.RE
  1962. at their end.
  1963. X.PP
  1964. In addition, each shar will generate a file named
  1965. X.IR ark X isdone .
  1966. XEach script will contain a loop to check for the presence of these
  1967. files, and indicate to the recipient which archives still need to be
  1968. executed.
  1969. The ``\-t'' option may be used to give starting instructions to the recipient.
  1970. When the scripts determine that all the archives have been unpacked,
  1971. the text specified with this flag is displayed.
  1972. XFor example,
  1973. X.RS
  1974. shar -n1 -k9 -t "Now do 'sh ./Configure'" *.c >SHAR
  1975. X.RE
  1976. Adds commands to output the following when all the archives have been unpacked:
  1977. X.RS
  1978. X.nf
  1979. You have run all 9 archives.
  1980. Now do 'sh ./Configure'
  1981. X.fi
  1982. X.RE
  1983. X.SH "SEE ALSO"
  1984. echo(1), findsrc(1l), makekit(1l), mkdir(1), sh(1), test(1), unshar(1l),
  1985. wc(1).
  1986. END_OF_FILE
  1987. if test 2967 -ne `wc -c <'shar.man'`; then
  1988.     echo shar: \"'shar.man'\" unpacked with wrong size!
  1989. fi
  1990. # end of 'shar.man'
  1991. fi
  1992. if test -f 'shell.c' -a "${1}" != "-c" ; then 
  1993.   echo shar: Will not clobber existing file \"'shell.c'\"
  1994. else
  1995. echo shar: Extracting \"'shell.c'\" \(808 characters\)
  1996. sed "s/^X//" >'shell.c' <<'END_OF_FILE'
  1997. X/*
  1998. X**  Stand-alone driver for shell.
  1999. X*/
  2000. X#include "shar.h"
  2001. X#ifdef    RCSID
  2002. static char RCS[] =
  2003. X    "$Header: shell.c,v 2.0 88/05/27 13:28:06 rsalz Exp $";
  2004. X#endif    /* RCSID */
  2005. X
  2006. X
  2007. main(ac, av)
  2008. X    REGISTER int     ac;
  2009. X    REGISTER char    *av[];
  2010. X{
  2011. X    char        *vec[MAX_WORDS];
  2012. X    char         buff[VAR_VALUE_SIZE];
  2013. X
  2014. X    if (Interactive = ac == 1) {
  2015. X    Fprintf(stderr, "Testing shell interpreter...\n");
  2016. X    Input = stdin;
  2017. X    File = "stdin";
  2018. X    }
  2019. X    else {
  2020. X    if ((Input = fopen(File = av[1], "r")) == NULL)
  2021. X        SynErr("UNREADABLE INPUT");
  2022. X    /* Build the positional parameters. */
  2023. X    for (ac = 1; av[ac]; ac++) {
  2024. X        (void)sprintf(buff, "%d", ac - 1);
  2025. X        SetVar(buff, av[ac]);
  2026. X    }
  2027. X    }
  2028. X
  2029. X    /* Read, parse, and execute. */
  2030. X    while (GetLine(TRUE))
  2031. X    if (Argify(vec) && Exec(vec) == -FALSE)
  2032. X        break;
  2033. X
  2034. X    /* That's it. */
  2035. X    exit(0);
  2036. X}
  2037. END_OF_FILE
  2038. if test 808 -ne `wc -c <'shell.c'`; then
  2039.     echo shar: \"'shell.c'\" unpacked with wrong size!
  2040. fi
  2041. # end of 'shell.c'
  2042. fi
  2043. if test -f 'shell.man' -a "${1}" != "-c" ; then 
  2044.   echo shar: Will not clobber existing file \"'shell.man'\"
  2045. else
  2046. echo shar: Extracting \"'shell.man'\" \(1090 characters\)
  2047. sed "s/^X//" >'shell.man' <<'END_OF_FILE'
  2048. X.TH SHELL 1l
  2049. X.\" $Header: shell.man,v 2.0 88/05/27 13:28:55 rsalz Exp $
  2050. X.SH NAME
  2051. shell \- Interpreter for shell archives
  2052. X.SH SYNOPSIS
  2053. X.B shell
  2054. X[ file...  ]
  2055. X.SH DESCRIPTION
  2056. This program interprets enough UNIX shell syntax, and command usage,
  2057. to enable it to unpack many different types of UNIX shell archives,
  2058. or ``shar's.''
  2059. It is primarily intended to be used on non-UNIX systems that need to
  2060. unpack such archives.
  2061. X.PP
  2062. X.I Shell
  2063. does
  2064. X.B not
  2065. check for security holes, and will blithely execute commands like
  2066. X.RS
  2067. cp /dev/null /etc/passwd
  2068. X.RE
  2069. which, if executed by the super-user, can be disastrous.
  2070. X.PP
  2071. The
  2072. X.I shell
  2073. parser is line-based, where lines are then split into tokens; it is not a
  2074. true token-based parser.
  2075. In general, it is best if all
  2076. X.I sh
  2077. keywords that can appear alone on a line do so, and that compound
  2078. commands (i.e., using a semi-colon) be avoided.
  2079. XFor more details on the syntax, see the source (sorry...).
  2080. X.SH BUGS
  2081. It is probably easier to write a true portable replacement for /bin/sh
  2082. than it is to write something which understands all shar formats.
  2083. X.SH SEE ALSO
  2084. shar(1l).
  2085. END_OF_FILE
  2086. if test 1090 -ne `wc -c <'shell.man'`; then
  2087.     echo shar: \"'shell.man'\" unpacked with wrong size!
  2088. fi
  2089. # end of 'shell.man'
  2090. fi
  2091. if test -f 'unshar.man' -a "${1}" != "-c" ; then 
  2092.   echo shar: Will not clobber existing file \"'unshar.man'\"
  2093. else
  2094. echo shar: Extracting \"'unshar.man'\" \(2326 characters\)
  2095. sed "s/^X//" >'unshar.man' <<'END_OF_FILE'
  2096. X.TH UNSHAR 1l
  2097. X.\" $Header: unshar.man,v 2.0 88/05/27 13:29:02 rsalz Exp $
  2098. X.SH NAME
  2099. unshar \- unpack shell archives from news, mail, notes, etc.
  2100. X.SH SYNOPSIS
  2101. X.B unshar
  2102. X[
  2103. X.BI \-c\| directory
  2104. X] [
  2105. X.BI \-d\| directory
  2106. X] [
  2107. X.BI \-h\| file
  2108. X] [
  2109. X.B \-f
  2110. X] [
  2111. X.B \-n
  2112. X] [
  2113. X.B \-s
  2114. X] [ file... ]
  2115. X.SH DESCRIPTION
  2116. X.I Unshar
  2117. removes mail and news header lines from its input, and feeds the remainder
  2118. to
  2119. X.IR /bin/sh (1)
  2120. so that a shell archive can be properly unpacked.
  2121. If no files are specified,
  2122. X.I unshar
  2123. reads from standard input.
  2124. The program is designed to be useful when unpacking archives directly
  2125. from the news or mail systems (e.g., s | unshar).
  2126. X.PP
  2127. X.I Unshar
  2128. normally unpacks its files in the current directory.
  2129. Use the ``\-c'' option to have the program change to a new directory
  2130. before invoking the shell.
  2131. If the directory does not exist, it will try to create it.
  2132. If the directory name starts with a question mark, then
  2133. X.I unshar
  2134. will ask for the directory name before doing anything; this is most useful
  2135. with the environment variable UNSHAREDIR.
  2136. If the directory name starts with a tilde, then the value of the HOME
  2137. environment variable is inserted in place of that character.
  2138. XFor convenience, the ``\-d'' option is a synonym for the ``\-c'' option.
  2139. X.PP
  2140. X.I Unshar
  2141. normally complains if the input looks like something other than a shar file.
  2142. X(Among other things, it checks for files that resemble C, and Pascal code).
  2143. It can be fooled, however, by nonstandard versions of news, notes, etc.
  2144. The ``\-f'' option forces
  2145. X.I unshar
  2146. to try unpacking files, even if they look like something else.
  2147. X.PP
  2148. Depending on how the program is installed,
  2149. X.I unshar
  2150. may or may not try to preserve the header part of file ``foo''
  2151. into the name ``foo.hdr'' (if the file is standard input, the name
  2152. will be ``UNSHAR.HDR'').
  2153. Using the ``\-s'' option forces the program to save the headers, while
  2154. using the ``\-n'' option forces it to discard the headers.
  2155. The file is appended to, if it already exists, so all headers can be easily
  2156. saved in one file.
  2157. The name of the file may be given by using the ``\-h'' option; this is
  2158. particularly useful when processing more than one file at a time.
  2159. X.SH ENVIRONMENT
  2160. X.ta \w'UNSHAREDIR  'u
  2161. HOME    Value used if a leading tilde is given in directory name.
  2162. X.br
  2163. UNSHAREDIR    Default value for ``\-c'' option.
  2164. X.SH SEE ALSO
  2165. shar(1).
  2166. END_OF_FILE
  2167. if test 2326 -ne `wc -c <'unshar.man'`; then
  2168.     echo shar: \"'unshar.man'\" unpacked with wrong size!
  2169. fi
  2170. # end of 'unshar.man'
  2171. fi
  2172. echo shar: End of archive 1 \(of 3\).
  2173. cp /dev/null ark1isdone
  2174. MISSING=""
  2175. for I in 1 2 3 ; do
  2176.     if test ! -f ark${I}isdone ; then
  2177.     MISSING="${MISSING} ${I}"
  2178.     fi
  2179. done
  2180. if test "${MISSING}" = "" ; then
  2181.     echo You have unpacked all 3 archives.
  2182.     echo "See the README"
  2183.     rm -f ark[1-9]isdone
  2184. else
  2185.     echo You still need to unpack the following archives:
  2186.     echo "        " ${MISSING}
  2187. fi
  2188. ##  End of shell archive.
  2189. exit 0
  2190.