home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / unix / volume26 / xinetd21 / part09 < prev    next >
Encoding:
Text File  |  1993-06-26  |  30.0 KB  |  1,279 lines

  1. Newsgroups: comp.sources.unix
  2. From: panos@cs.colorado.edu (Panos Tsirigotis)
  3. Subject: v26i253: xinetd-2.1.1 - inetd replacement with access control and logging, Part09/31
  4. Sender: unix-sources-moderator@gw.home.vix.com
  5. Approved: vixie@gw.home.vix.com
  6.  
  7. Submitted-By: panos@cs.colorado.edu (Panos Tsirigotis)
  8. Posting-Number: Volume 26, Issue 253
  9. Archive-Name: xinetd-2.1.1/part09
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 9 (of 31)."
  18. # Contents:  libs/src/sio/Makefile libs/src/sio/suite/copytest.c
  19. #   libs/src/str/strparse.3 libs/src/str/strs.3 xinetd/itox.c
  20. #   xinetd/parsesup.c
  21. # Wrapped by panos@mystique on Mon Jun 21 14:51:22 1993
  22. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  23. if test -f 'libs/src/sio/Makefile' -a "${1}" != "-c" ; then 
  24.   echo shar: Will not clobber existing file \"'libs/src/sio/Makefile'\"
  25. else
  26. echo shar: Extracting \"'libs/src/sio/Makefile'\" \(4227 characters\)
  27. sed "s/^X//" >'libs/src/sio/Makefile' <<'END_OF_FILE'
  28. X# (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
  29. X# All rights reserved.  The file named COPYRIGHT specifies the terms 
  30. X# and conditions for redistribution.
  31. X
  32. X#
  33. X# $Id: Makefile,v 8.6 1993/03/30 21:34:09 panos Exp $
  34. X#
  35. X# Based on Library makefile template: *Revision: 1.15 *
  36. X#
  37. X
  38. X# 
  39. X# Available entries:
  40. X#         lib             --> creates the library
  41. X#        install        --> installs the library (archive, man page(s), header(s))
  42. X#        uninstall    --> uninstall the library
  43. X#        clean            --> removes all .o and .a files
  44. X#        spotless        --> clean + uninstall
  45. X#         lint            --> lints a file (usage: make lint MODULE=foo.c)
  46. X#        tags            --> creates a tags file (from the SOURCES and HEADERS)
  47. X#        checkout     --> checkout all files
  48. X#        dist            --> distribution support
  49. X#
  50. X
  51. XNAME                = sio
  52. XVERSION            = 1.6.2
  53. X
  54. XHEADERS            = sio.h impl.h events.h sioconf.h
  55. XSOURCES            = sprint.c sio.c siosup.c
  56. XOBJECTS            = sprint.o sio.o siosup.o
  57. X
  58. XMANFILES            = sio.3 Sprint.3
  59. XINCLUDEFILES    = sio.h
  60. X
  61. X# The following variables are used by the 'install' entry and
  62. X# should be customized:
  63. X#     LIBDIR:     where the library will be placed
  64. X#     INCUDEDIR:  where the include files will be placed
  65. X#     MANDIR:     where the man pages will be placed
  66. X#
  67. XLIBDIR            = $(HOME)/.links/libraries/$(ARCH)
  68. XMANDIR            = $(HOME)/.links/includes
  69. XINCLUDEDIR        = $(HOME)/.links/manpages/man3
  70. X
  71. X#
  72. X# Available flags:
  73. X#  -DDEBUG           :  enables assertions in the code. A failed assertion
  74. X#                       terminates the program
  75. X#  -DEVENTS          :  enables code that records events (currently limited
  76. X#                       to which functions have been called on a given fd)
  77. X#                       and code that accesses the event buffers.
  78. X#  -DLITTLE_ENDIAN   :  says that the machine is a little endian. This is
  79. X#                       needed if you enable EVENTS and your machine is a
  80. X#                       little endian (big endian is the default).
  81. X#
  82. X
  83. X#
  84. X# DEFS should be set from the command line; the current group of defs
  85. X# is for SunOS 4.x
  86. X#
  87. XDEFS                = -DHAS_MMAP -DHAS_ONEXIT -DHAS_MEMOPS -DHAS_ISATTY
  88. X
  89. XDEBUG                = -g            # -g or -O
  90. XVERSION_DEF        = -DVERSION=\"SIO\ Version\ $(VERSION)\"
  91. X
  92. XCPP_DEFS            = $(VERSION_DEF) $(DEFS)
  93. X
  94. X#
  95. X# The following variables shouldn't need to be changed
  96. X#
  97. XLINT_FLAGS        = -hbux
  98. XCPP_FLAGS        = $(CPP_DEFS)
  99. XCC_FLAGS            = $(DEBUG)
  100. XCFLAGS            = $(CPP_FLAGS) $(CC_FLAGS)
  101. X
  102. XINSTALL            = install -c
  103. XFMODE                = -m 640            # used by install
  104. XRANLIB            = ranlib
  105. X
  106. XPAGER                = less
  107. X
  108. X
  109. XLIBNAME            = lib$(NAME).a
  110. X
  111. Xlib: $(LIBNAME)
  112. X
  113. Xlibopt: clean
  114. X    make DEBUG=-O lib
  115. X    $(INSTALL) $(FMODE) $(LIBNAME) $(LIBDIR)/optimized
  116. X
  117. X$(LIBNAME): $(OBJECTS)
  118. X    ar r $@ $?
  119. X    $(RANLIB) $@
  120. X
  121. Xlint:
  122. X    lint $(CPP_FLAGS) $(LINT_FLAGS) $(MODULE) 2>&1 | $(PAGER)
  123. X
  124. Xinstall: $(LIBNAME)
  125. X    @if test "$(LIBDIR)" -a "$(INCLUDEDIR)" -a "$(MANDIR)" ;\
  126. X    then \
  127. X        $(INSTALL) $(FMODE) $(LIBNAME) $(LIBDIR) ;\
  128. X        echo "Installed $(LIBNAME) to $(LIBDIR)" ;\
  129. X        for i in $(INCLUDEFILES); do $(INSTALL) $(FMODE) $$i $(INCLUDEDIR) ; done ;\
  130. X        echo Installed $(INCLUDEFILES) to $(INCLUDEDIR) ;\
  131. X        for i in $(MANFILES) ; do $(INSTALL) $(FMODE) $$i $(MANDIR) ; done ;\
  132. X        echo Installed $(MANFILES) to $(MANDIR) ;\
  133. X    else \
  134. X        echo "You forgot to set one of the following variables: LIBDIR,INCLUDEDIR,MANDIR" ;\
  135. X    fi
  136. X
  137. Xuninstall:
  138. X    a=`pwd` ; cd $(INCLUDEDIR) ;\
  139. X    if test $$a != `pwd` ; then rm -f $(INCLUDEFILES) ; fi
  140. X    a=`pwd` ; cd $(LIBDIR) ;\
  141. X    if test $$a != `pwd` ; then rm -f $(LIBNAME) ; fi
  142. X    a=`pwd` ; cd $(MANDIR) ;\
  143. X    if test $$a != `pwd` ; then rm -f $(MANFILES) ; fi
  144. X
  145. Xclean:
  146. X    rm -f $(OBJECTS) $(LIBNAME) core
  147. X
  148. Xspotless: clean uninstall
  149. X
  150. Xtags: $(SOURCES) $(HEADERS)
  151. X    ctags -w $(SOURCES) $(HEADERS)
  152. X
  153. Xcheckout:
  154. X    co $(SOURCES) $(HEADERS) $(MANFILES)
  155. X
  156. X#
  157. X# Distribution section
  158. X# This section contains the 2 targets for distribution support: dist, dirs
  159. X# "dist" checks out all files to be distributed
  160. X# "dirs" prints a list of directories to be included in the distribution.
  161. X# These directories should have a Makefile with a "dist" target
  162. X#
  163. XDISTRIBUTION_FILES    = $(HEADERS) $(SOURCES) $(MANFILES) README COPYRIGHT
  164. XDIRS                        = suite
  165. X
  166. Xdist:
  167. X    -co -q $(DISTRIBUTION_FILES)
  168. X
  169. Xdirs:
  170. X    @echo $(DIRS)
  171. X
  172. X#
  173. X# PUT HERE THE RULES TO MAKE THE OBJECT FILES
  174. X#
  175. Xsprint.o:   sio.h impl.h sioconf.h
  176. Xsio.o:      sio.h impl.h sioconf.h events.h
  177. Xsiosup.o:   sio.h impl.h sioconf.h events.h
  178. X
  179. END_OF_FILE
  180. if test 4227 -ne `wc -c <'libs/src/sio/Makefile'`; then
  181.     echo shar: \"'libs/src/sio/Makefile'\" unpacked with wrong size!
  182. fi
  183. # end of 'libs/src/sio/Makefile'
  184. fi
  185. if test -f 'libs/src/sio/suite/copytest.c' -a "${1}" != "-c" ; then 
  186.   echo shar: Will not clobber existing file \"'libs/src/sio/suite/copytest.c'\"
  187. else
  188. echo shar: Extracting \"'libs/src/sio/suite/copytest.c'\" \(4262 characters\)
  189. sed "s/^X//" >'libs/src/sio/suite/copytest.c' <<'END_OF_FILE'
  190. X/*
  191. X * (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
  192. X * All rights reserved.  The file named COPYRIGHT specifies the terms 
  193. X * and conditions for redistribution.
  194. X */
  195. X
  196. Xstatic char RCSid[] = "$Id: copytest.c,v 8.1 1993/03/13 01:21:48 panos Exp $" ;
  197. X
  198. X#include "sio.h"
  199. X#include <stdio.h>
  200. X#include <syscall.h>
  201. X
  202. X
  203. X/*************************************************************/
  204. X
  205. X#ifdef TEST_Sread
  206. X
  207. X#define BUFFER_SIZE  4096
  208. X
  209. Xmain()
  210. X{
  211. X    char buf[ BUFFER_SIZE ] ;
  212. X    int cc ;
  213. X    int nbytes ;
  214. X
  215. X    for ( ;; )
  216. X    {
  217. X        nbytes = random() & ( BUFFER_SIZE - 1 ) ;
  218. X        if ( nbytes == 0 )
  219. X            nbytes = 1 ;
  220. X        cc = Sread( 0, buf, nbytes ) ;
  221. X        if ( cc == 0 )
  222. X            break ;
  223. X        if ( cc == SIO_ERR )
  224. X            exit( 1 ) ;
  225. X        write( 1, buf, cc ) ;
  226. X    }
  227. X    exit( 0 ) ;
  228. X}
  229. X#endif /* TEST_Sread */
  230. X
  231. X/*************************************************************/
  232. X
  233. X#ifdef TEST_Swrite
  234. X
  235. X#define BUFFER_SIZE  4096
  236. X
  237. Xmain()
  238. X{
  239. X    char buf[ BUFFER_SIZE ] ;
  240. X    int cc ;
  241. X    int nbytes ;
  242. X
  243. X    for ( ;; )
  244. X    {
  245. X        nbytes = random() & ( BUFFER_SIZE - 1 ) ;
  246. X        if ( nbytes == 0 )
  247. X            nbytes = 1 ;
  248. X        cc = read( 0, buf, nbytes ) ;
  249. X        if ( cc == 0 )
  250. X            break ;
  251. X        if ( Swrite( 1, buf, cc ) != cc )
  252. X            exit( 1 ) ;
  253. X    }
  254. X    exit( 0 ) ;
  255. X}
  256. X#endif /* TEST_Swrite */
  257. X
  258. X/*************************************************************/
  259. X
  260. X#ifdef TEST_Srdline
  261. X
  262. Xmain()
  263. X{
  264. X    char *s ;
  265. X    int count=0 ;
  266. X
  267. X    while ( s = Srdline( 0 ) )
  268. X    {
  269. X        puts( s ) ;
  270. X        count++ ;
  271. X    }
  272. X    Sdone( 0 ) ;
  273. X    exit( 0 ) ;
  274. X}
  275. X
  276. X#endif  /* TEST_Srdline */
  277. X
  278. X/*************************************************************/
  279. X
  280. X#ifdef TEST_Sputchar
  281. X
  282. Xmain()
  283. X{
  284. X    int c ;
  285. X
  286. X    while ( ( c = getchar() ) != EOF )
  287. X        if ( Sputchar( 1, c ) != c )
  288. X            exit( 1 ) ;
  289. X    exit( 0 ) ;
  290. X}
  291. X
  292. X#endif /* TEST_Sputchar */
  293. X
  294. X/*************************************************************/
  295. X
  296. X#ifdef TEST_Sgetchar
  297. X
  298. Xmain()
  299. X{
  300. X    int c ;
  301. X
  302. X    while ( ( c = Sgetchar( 0 ) ) != SIO_EOF )
  303. X        putchar( c ) ;
  304. X    exit( 0 ) ;
  305. X}
  306. X
  307. X#endif    /* TEST_Sgetchar */
  308. X
  309. X/*************************************************************/
  310. X
  311. X#ifdef TEST_Sputc
  312. X
  313. Xmain()
  314. X{
  315. X   int c ;
  316. X   while ( ( c = getchar() ) != EOF )
  317. X      if ( Sputc( 1, c ) != c )
  318. X         exit( 1 ) ;
  319. X   exit( 0 ) ;
  320. X}
  321. X
  322. X#endif /* TEST_Sputc */
  323. X
  324. X/*************************************************************/
  325. X
  326. X#ifdef TEST_Sgetc
  327. X
  328. Xmain()
  329. X{
  330. X   int c ;
  331. X
  332. X   while ( ( c = Sgetc( 0 ) ) != SIO_EOF )
  333. X      putchar( c ) ;
  334. X   exit( 0 ) ;
  335. X}
  336. X
  337. X#endif /* TEST_Sgetc */
  338. X
  339. X/*************************************************************/
  340. X
  341. X#ifdef TEST_Sfetch
  342. X
  343. Xmain()
  344. X{
  345. X    char *s ;
  346. X    int len ;
  347. X
  348. X    while ( s = Sfetch( 0, &len ) )
  349. X        fwrite( s, 1, len, stdout ) ;
  350. X    exit( 0 ) ;
  351. X}
  352. X
  353. X#endif /* TEST_Sfetch */
  354. X
  355. X/*************************************************************/
  356. X
  357. X#ifdef TEST_Sflush
  358. X
  359. X#define MAX_COUNT        100
  360. X
  361. Xmain()
  362. X{
  363. X    int c ;
  364. X    int errval ;
  365. X    int count = 0 ;
  366. X    int max_count = random() % MAX_COUNT + 1 ;
  367. X
  368. X    while ( ( c = getchar() ) != EOF )
  369. X        if ( Sputchar( 1, c ) != c )
  370. X            exit( errval ) ;
  371. X        else
  372. X        {
  373. X            count++ ;
  374. X            if ( count >= max_count )
  375. X            {
  376. X                errval = Sflush( 1 ) ;
  377. X                if ( errval != 0 )
  378. X                    exit( 1 ) ;
  379. X                max_count = random() % MAX_COUNT + 1 ;
  380. X                count = 0 ;
  381. X            }
  382. X        }
  383. X    exit( 0 ) ;
  384. X}
  385. X
  386. X#endif /* TEST_Sflush */
  387. X
  388. X/*************************************************************/
  389. X
  390. X#ifdef TEST_Sundo
  391. X
  392. Xmain()
  393. X{
  394. X    int c ;
  395. X    char *s ;
  396. X    int errval ;
  397. X
  398. X    for ( ;; )
  399. X    {
  400. X        if ( random() % 1 )
  401. X        {
  402. X            s = Srdline( 0 ) ;
  403. X            if ( s == NULL )
  404. X                break ;
  405. X            if ( random() % 16 < 5 )
  406. X            {
  407. X                errval = Sundo( 0, SIO_UNDO_LINE ) ;
  408. X                if ( errval == SIO_ERR )
  409. X                    exit( 1 ) ;
  410. X            }
  411. X            else
  412. X                puts( s ) ;
  413. X        }
  414. X        else
  415. X        {
  416. X            c = Sgetchar( 0 ) ;
  417. X            if ( c == SIO_EOF )
  418. X                break ;
  419. X            if ( random() % 16 < 5 )
  420. X            {
  421. X                errval = Sundo( 0, SIO_UNDO_CHAR ) ;
  422. X                if ( errval == SIO_ERR )
  423. X                    exit( 2 ) ;
  424. X            }
  425. X            else
  426. X                putchar( c ) ;
  427. X        }
  428. X    }
  429. X    exit( 0 ) ;
  430. X}
  431. X
  432. X#endif /* TEST_Sundo */
  433. X
  434. X
  435. X#if defined( TEST_switch ) || defined( TEST_switch2 )
  436. X
  437. Xmain()
  438. X{
  439. X    int c ;
  440. X    char *s ;
  441. X    int lines = 4000 ;
  442. X
  443. X    for ( ;; )
  444. X    {
  445. X        c = Sgetchar( 0 ) ;
  446. X        if ( c == SIO_EOF )
  447. X            exit( 0 ) ;
  448. X        if ( c == SIO_ERR )
  449. X            exit( 1 ) ;
  450. X        putchar( c ) ;
  451. X        if ( c == '\n' )
  452. X        {
  453. X            lines-- ;
  454. X            if ( lines == 0 )
  455. X                break ;
  456. X        }
  457. X    }
  458. X    while ( s = Srdline( 0 ) )
  459. X        puts( s ) ;
  460. X    exit( 0 ) ;
  461. X}
  462. X
  463. X#ifdef TEST_switch2
  464. X
  465. Xchar *mmap( addr, len, prot, type, fd, off )
  466. X    char *addr ;
  467. X    int len, prot, type, fd, off ;
  468. X{
  469. X    return( (char *)-1 ) ;
  470. X}
  471. X
  472. X#endif    /* TEST_switch2 */
  473. X
  474. X#endif     /* TEST_switch */
  475. X
  476. X
  477. X
  478. END_OF_FILE
  479. if test 4262 -ne `wc -c <'libs/src/sio/suite/copytest.c'`; then
  480.     echo shar: \"'libs/src/sio/suite/copytest.c'\" unpacked with wrong size!
  481. fi
  482. # end of 'libs/src/sio/suite/copytest.c'
  483. fi
  484. if test -f 'libs/src/str/strparse.3' -a "${1}" != "-c" ; then 
  485.   echo shar: Will not clobber existing file \"'libs/src/str/strparse.3'\"
  486. else
  487. echo shar: Extracting \"'libs/src/str/strparse.3'\" \(4130 characters\)
  488. sed "s/^X//" >'libs/src/str/strparse.3' <<'END_OF_FILE'
  489. X.\"(c) Copyright 1992, 1993 by Panagiotis Tsirigotis
  490. X.\"All rights reserved.  The file named COPYRIGHT specifies the terms 
  491. X.\"and conditions for redistribution.
  492. X.\"
  493. X.\" $Id: strparse.3,v 3.1 1993/06/13 02:48:02 panos Exp $
  494. X.TH STRPARSE 3X "30 September 1992"
  495. X.SH NAME
  496. Xstr_parse, str_endparse, str_component, str_separator, str_nextpos
  497. X.SH SYNOPSIS
  498. X.LP
  499. X.nf
  500. X.ft B
  501. X#include "str.h"
  502. X.LP
  503. X.ft B
  504. Xstr_h str_parse( str, separ, flags, errnop )
  505. Xchar *str ;
  506. Xchar *separ ;
  507. Xint flags ;
  508. Xint *errnop ;
  509. X.LP
  510. X.ft B
  511. Xvoid str_endparse( handle )
  512. Xstr_h handle ;
  513. X.LP
  514. X.ft B
  515. Xchar *str_component( handle )
  516. Xstr_h handle ;
  517. X.LP
  518. X.ft B
  519. Xint str_setstr( handle, newstr )
  520. Xstr_h handle ;
  521. Xchar *newstr ;
  522. X.LP
  523. X.ft B
  524. Xint str_separator( handle, separ )
  525. Xstr_h handle ;
  526. Xchar *separ ;
  527. X.LP
  528. X.ft B
  529. Xchar *str_nextpos( handle )
  530. Xstr_h handle ;
  531. X.LP
  532. Xextern int str_errno ;
  533. X.SH DESCRIPTION
  534. X.LP
  535. XThese functions are useful for parsing strings.  In this context
  536. Xparsing means breaking the string into substrings. The substrings are
  537. Xseparated by a list of possible separator characters.
  538. X.LP
  539. X.B str_component()
  540. Xreturns successive substrings of the string.
  541. X.B str_parse()
  542. Xcreates and initializes a string parser with the string
  543. Xthat will be processed, \fIstr\fR, the list of possible separator
  544. Xcharacters, \fIsepar\fR, and flags that control how the parser
  545. Xworks. The \fIflags\fR argument is formed by ORing one or more of
  546. Xthe following constants:
  547. X.TP 20
  548. X.SB STR_RETURN_ERROR
  549. XIf something goes wrong return a value that indicates that an error occured
  550. X(e.g. out of memory). The default is for the program to be terminated
  551. Xwith an appropriate error message.
  552. X.TP
  553. X.SB STR_NULL_START
  554. XIf \fIstr\fR starts with a separator then a zero-length string will be returned
  555. Xthe first time \fBstr_component()\fR is called.
  556. X.TP
  557. X.SB STR_NULL_END
  558. XIf \fIstr\fR ends with a separator then a zero-length string will be returned
  559. Xby \fBstr_component()\fR when the substrings of \fIstr\fR are exhausted.
  560. X.TP
  561. X.SB STR_MALLOC
  562. XThe strings returned by \fBstr_component()\fR will be in malloc'ed memory.
  563. XBy default the substrings are part of \fIstr\fR.
  564. XIf this option is not used \fIstr\fR will be modified
  565. Xby \fBstr_component()\fR.
  566. X.LP
  567. XFinally, \fBSTR_NOFLAGS\fR may be used to specify no flags.
  568. XThe \fIerrnop\fR argument points to an integer where the string processing
  569. Xfunctions will deposit an error code if an error occurs.
  570. XIf \fIerrnop\fR
  571. Xis
  572. X.SM NULL
  573. Xthe error codes will be placed in \fIstr_errno\fR.
  574. XThis is useful only if \fBSTR_RETURN_ERROR\fR is used in \fIflags\fR.
  575. XIt is possible that \fIstr\fP is 
  576. X.SM NULL.
  577. XIn this case, a subsequent
  578. X.B str_setstr()
  579. Xshould be used to specify the string to be processed.
  580. X.LP
  581. X.B str_component()
  582. Xreturns successive substrings from the string associated with the
  583. Xparser specified by \fIhandle\fR.
  584. X.LP
  585. X.B str_endparse()
  586. Xdestroys the parser specified by \fIhandle\fR.
  587. X.LP
  588. X.B str_setstr()
  589. Xchanges the processed string to \fInewstr\fP.
  590. X.LP
  591. X.B str_separator()
  592. Xreplaces the list of separator characters with \fIsepar\fR.
  593. XProcessing continues from the current position.
  594. X.LP
  595. X.B str_nextpos()
  596. Xreturns a pointer to the rest of the string. The previous character
  597. Xis a separator character (if \fBSTR_MALLOC\fR is not set, then the
  598. Xprevious character is
  599. X.SM NUL
  600. X).
  601. X.SH "RETURN VALUES"
  602. X.LP
  603. X.B str_parse()
  604. Xreturns a parser handle or
  605. X.SM NULL
  606. Xif something goes wrong and \fIflags\fR & \fBSTR_RETURN_ERROR\fR is true.
  607. XPossible \fIstr_errno\fR values:
  608. X.RS
  609. X.TP 20
  610. X.SB STR_ENULLSEPAR
  611. X\fIsepar\fR is
  612. X.SM NULL
  613. X.TP
  614. X.SB STR_ENOMEM
  615. Xthe program ran out of memory
  616. X.RE
  617. X.LP
  618. X.B str_component()
  619. Xreturns a pointer to the next substring or
  620. X.SM NULL
  621. Xif something goes wrong and \fIflags\fR & \fBSTR_RETURN_ERROR\fR is true.
  622. X.LP
  623. X.B str_setstr()
  624. Xreturns 
  625. X.SB STR_OK
  626. Xon success or
  627. X.SB STR_ERR
  628. Xon failure.
  629. X.LP
  630. X.B str_separator()
  631. Xreturns 
  632. X.SB STR_OK
  633. Xon success or
  634. X.SB STR_ERR
  635. Xon failure.
  636. X.LP
  637. X.B str_nextpos()
  638. Xreturns a pointer or
  639. X.SM NULL
  640. Xif the end of string has been reached.
  641. X.SH BUGS
  642. X.B str_component()
  643. Xmodifies the string unless \fBSTR_MALLOC\fR is
  644. Xset in the parser.
  645. X.LP
  646. XThere should be only one parser active on a specific string. If there
  647. Xis more than
  648. Xone, they all must use the \fBSTR_MALLOC\fR option.
  649. X
  650. END_OF_FILE
  651. if test 4130 -ne `wc -c <'libs/src/str/strparse.3'`; then
  652.     echo shar: \"'libs/src/str/strparse.3'\" unpacked with wrong size!
  653. fi
  654. # end of 'libs/src/str/strparse.3'
  655. fi
  656. if test -f 'libs/src/str/strs.3' -a "${1}" != "-c" ; then 
  657.   echo shar: Will not clobber existing file \"'libs/src/str/strs.3'\"
  658. else
  659. echo shar: Extracting \"'libs/src/str/strs.3'\" \(4394 characters\)
  660. sed "s/^X//" >'libs/src/str/strs.3' <<'END_OF_FILE'
  661. X.\"(c) Copyright 1992, 1993 by Panagiotis Tsirigotis
  662. X.\"All rights reserved.  The file named COPYRIGHT specifies the terms 
  663. X.\"and conditions for redistribution.
  664. X.\"
  665. X.\" $Id: strs.3,v 3.1 1993/06/13 02:49:50 panos Exp $
  666. X.TH STRS 3X "12 June 1993"
  667. X.SH NAME
  668. Xstrs_setup, strs_match, strs_done, strs_search - string matching functions
  669. X.SH SYNOPSIS
  670. X.LP
  671. X.nf
  672. X.ft B
  673. X#include "str.h"
  674. X.LP
  675. X.ft B
  676. Xstrs_h strs_setup( flags, pattern [, patlen] )
  677. Xint flags ;
  678. Xchar *pattern ;
  679. X.LP
  680. X.ft B
  681. Xchar *strs_match( handle, str, len )
  682. Xstrs_h handle ;
  683. Xchar *str ;
  684. Xint len ;
  685. X.LP
  686. X.ft B
  687. Xvoid strs_done( handle )
  688. Xstrs_h handle ;
  689. X.LP
  690. X.ft B
  691. Xchar *strs_search( flags, str, len, pattern [, patlen] )
  692. Xint flags ;
  693. Xchar *str ;
  694. Xint len ;
  695. Xchar *pattern ;
  696. X.SH DESCRIPTION
  697. X.LP
  698. XThese functions perform string matching. They have been designed with
  699. Xthe assumption that one needs to find a certain pattern in a set of
  700. Xstrings. It is also possible to use them to find if a pattern occurs
  701. Xin a specific string.
  702. X.LP
  703. X.B strs_setup()
  704. Xis used to specify the pattern to look for. It returns a
  705. X.I handle
  706. Xwhich is used in subsequent string matching operations against
  707. Xthe specified
  708. X.I pattern.
  709. XThe
  710. X.I flags
  711. Xargument has two parts: a search method and generic flags.
  712. XThe available search methods include the following algorithms:
  713. X.RS
  714. X.TP 15
  715. X.SB STRS_BF
  716. Xbrute force algorithm (also called naive in the literature). 
  717. X.TP
  718. X.SB STRS_RK
  719. XRabin-Karp algorithm (probabilistic).
  720. X.TP
  721. X.SB STRS_KMP
  722. XKnuth-Morris-Pratt algorithm.
  723. X.TP
  724. X.SB STRS_SBM
  725. XSimple Boyer-Moore (uses only the last occurrence heuristic).
  726. X.TP
  727. X.SB STRS_BMH
  728. XThis is the Boyer-Moore algorithm using the last occurrence heuristic
  729. Xas modified by Horspool (this is faster than the simple Boyer-Moore).
  730. X.TP
  731. X.SB STRS_SO
  732. XShift-Or algorithm (this algorithm works only for patterns whose length
  733. Xdoes not exceed the number of bits in a word).
  734. X.RE
  735. X.LP
  736. XThe default algorithm is the brute force method.
  737. XIn practice, the fastest algorithm is the
  738. XBoyer-Moore-Horspool one.
  739. X.LP
  740. XThe flags that can be specified include:
  741. X.RS
  742. X.TP 15
  743. X.SB STRS_NOMALLOC
  744. Xdo not allocate space for the pattern. This can be specified if
  745. Xthe pattern space will be available during the matching phase
  746. X(i.e. do not use this flag if the pattern space was malloc'ed and
  747. Xyou free it before doing any matching).
  748. X.TP
  749. X.SB STRS_IGNCASE
  750. Xperform case-insensitive string matching
  751. X(the default is case-sensitive matching).
  752. X.TP
  753. X.SB STRS_NOSWITCH
  754. Xdisallows switching to another search method; a switch to the brute
  755. Xforce algorithm happens if the length of the pattern is less than 4
  756. Xor if the initialization of the specified search algorithm fails (for
  757. Xexample, when using the shift-or algorithm with a very long pattern).
  758. XWhen this flag is used, no switch happens.
  759. X.TP
  760. X.SB STRS_PATLEN
  761. Xis used to explicitly specify the length of the pattern
  762. X(with the
  763. X.I patlen
  764. Xargument); normally the pattern is assumed to be NUL-terminated.
  765. X.RE
  766. X.LP
  767. X.B strs_match()
  768. Xtries to match the string specified by
  769. X.I str
  770. Xagainst the pattern identified by
  771. X.I handle.
  772. XSince the length of the string is given by the
  773. X.I len
  774. Xargument the string does not need to be NUL-terminated.
  775. X.B strs_done()
  776. Xshould be invoked after all matching against the pattern identified by
  777. X.I handle
  778. Xis done.
  779. X.LP
  780. X.B strs_search()
  781. Xis equivalent to:
  782. X.LP
  783. X.PD .1v
  784. X.nf
  785. X.RS
  786. Xh = strs_setup( flags, pattern ) ;
  787. Xp = strs_match( h, str, len ) ;
  788. Xstrs_done( h ) ;
  789. Xreturn( p ) ;
  790. X.RE
  791. X.PD
  792. X.SH "RETURN VALUES"
  793. X.LP
  794. X.B strs_setup()
  795. Xreturns a search handle on success or
  796. X.SM NULL
  797. Xon failure.
  798. X.LP
  799. X.B strs_match()
  800. Xand
  801. X.B strs_search()
  802. Xreturn a pointer to the first occurrence of the pattern in the string or
  803. X.SM NULL
  804. Xif the pattern does not occur in the string.
  805. X.SH "SEE ALSO"
  806. XDonald E. Knuth, James H. Morris, Vaughan R. Pratt.
  807. XFast pattern matching in strings.
  808. XSIAM Journal on Computing, 6(2):323-350, 1977.
  809. X.LP
  810. XRichard M. Karp, Michael O. Rabin.
  811. XEfficient randomized pattern-matching algorithms.
  812. XTechnical Report TR-31-81,
  813. XAiken Computation Laboratory, Harvard University, 1981.
  814. X.LP
  815. XRobert S. Boyer, J. Strother Moore.
  816. XA fast string-searching algorithm.
  817. XCommunications of the ACM, 20(10):762-772, 1977.
  818. X.LP
  819. XN. Horspool.
  820. XPractical fast searching in strings.
  821. XSoftware - Practice and Experience, 10:501-506, 1980.
  822. X.LP
  823. XR. Baeza-Yates, G.H. Gonnet.
  824. XA new approach to text searching.
  825. XProceedings of 12th SIGIR, June 1989.
  826. X.LP
  827. XThomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest.
  828. XIntroduction to Algorithms.
  829. XMcGraw-Hill 1990.
  830. END_OF_FILE
  831. if test 4394 -ne `wc -c <'libs/src/str/strs.3'`; then
  832.     echo shar: \"'libs/src/str/strs.3'\" unpacked with wrong size!
  833. fi
  834. # end of 'libs/src/str/strs.3'
  835. fi
  836. if test -f 'xinetd/itox.c' -a "${1}" != "-c" ; then 
  837.   echo shar: Will not clobber existing file \"'xinetd/itox.c'\"
  838. else
  839. echo shar: Extracting \"'xinetd/itox.c'\" \(4131 characters\)
  840. sed "s/^X//" >'xinetd/itox.c' <<'END_OF_FILE'
  841. X/*
  842. X * (c) Copyright 1992 by Panagiotis Tsirigotis
  843. X * All rights reserved.  The file named COPYRIGHT specifies the terms 
  844. X * and conditions for redistribution.
  845. X */
  846. X
  847. Xstatic char RCSid[] = "$Id: itox.c,v 6.1 1993/06/20 21:17:37 panos Exp $" ;
  848. X
  849. X#define EQ( s1, s2 )                    ( strcmp( s1, s2 ) == 0 )
  850. X
  851. X#define NUL                                '\0'
  852. X#define NULL                            0
  853. X#define PRIVATE                        static
  854. X
  855. X#define FIELD_WIDTH                    15
  856. X#define DAEMON_DIR_OPTION            "-daemon_dir"
  857. X#define TCPD_NAME                        "tcpd"
  858. X
  859. X#include "sio.h"
  860. X#include "str.h"
  861. X#include "misc.h"
  862. X
  863. Xchar *strchr() ;
  864. X
  865. Xstr_h strp ;
  866. Xint line_count ;
  867. X
  868. X/*
  869. X * This program works only as a filter.
  870. X * Options:
  871. X *     -daemon_dir <dir_name>    :    if you use tcpd, this option specifies the
  872. X *                                            directory where all the daemons are.
  873. X *                                            You must specify this option if you use tcpd
  874. X *
  875. X * Note that we don't bother to free the memory we malloc.
  876. X */
  877. Xint main( argc, argv )
  878. X    int argc ;
  879. X    char *argv[] ;
  880. X{
  881. X    char *s ;
  882. X    int uses_tcpd ;
  883. X    char *daemon_dirpath ;
  884. X    void print_line() ;
  885. X    char *next_word() ;
  886. X
  887. X    if ( argc != 1 && argc != 3 )
  888. X    {
  889. X        Sprint( 2, "Usage: %s [%s dir_path]\n",
  890. X                basename( argv[ 0 ] ), DAEMON_DIR_OPTION ) ;
  891. X        exit( 1 ) ;
  892. X    }
  893. X
  894. X    uses_tcpd = ( argc == 3 ) ;
  895. X
  896. X    if ( uses_tcpd )
  897. X    {
  898. X        int len ;
  899. X
  900. X        daemon_dirpath = argv[ 2 ] ;
  901. X        len = strlen( daemon_dirpath ) ;
  902. X        if ( daemon_dirpath[ len-1 ] == '/' )
  903. X            daemon_dirpath[ --len ] = NUL ;
  904. X    }
  905. X
  906. X    strp = str_parse( (char *)0, " \t", STR_NOFLAGS, (int *)0 ) ;
  907. X
  908. X    while ( s = Srdline( 0 ) )
  909. X    {
  910. X        char *word ;
  911. X        char *p ;
  912. X        char *socket_type, *protocol ;
  913. X        char *service ;
  914. X        int is_rpc ;
  915. X
  916. X        line_count++ ;
  917. X
  918. X        if ( SIOLINELEN( 0 ) == 0 || s[ 0 ] == '#' )
  919. X            continue ;
  920. X
  921. X        str_setstr( strp, s ) ;
  922. X
  923. X        service = word = next_word( "service name" ) ;
  924. X
  925. X        /*
  926. X         * Check if it is an RPC service
  927. X         */
  928. X        p = strchr( word, '/' ) ;
  929. X        if ( p != NULL )
  930. X            *p = 0 ;
  931. X        Sprint( 1, "service %s\n{\n", word ) ;
  932. X        if ( is_rpc = ( p != NULL ) )
  933. X        {
  934. X            print_line( "type", "RPC" ) ;
  935. X            print_line( "rpc_version", p+1 ) ;
  936. X        }
  937. X
  938. X        socket_type = word = next_word( "socket type" ) ;
  939. X        print_line( "socket_type", socket_type ) ;
  940. X
  941. X        word = next_word( "protocol" ) ;
  942. X        p = strchr( word, '/' ) ;
  943. X        protocol = ( p == NULL ) ? word : p+1 ;
  944. X
  945. X        print_line( "protocol", protocol ) ;
  946. X
  947. X        word = next_word( "wait/nowait" ) ;
  948. X        print_line( "wait", EQ( word, "wait" ) ? "yes" : "no" ) ;
  949. X
  950. X        word = next_word( "user" ) ;
  951. X        print_line( "user", word ) ;
  952. X
  953. X        word = next_word( "server" ) ;
  954. X        if ( EQ( word, "internal" ) )
  955. X        {
  956. X            /*
  957. X             * We are in trouble if this is an RPC service
  958. X             */
  959. X            if ( is_rpc )
  960. X            {
  961. X                Sprint( 2,
  962. X                    "The entry for service %s will be wrong because\n", service ) ;
  963. X                Sprint( 2, "we can't handle internal RPC services\n" ) ;
  964. X            }
  965. X            else
  966. X            {
  967. X                print_line( "type", "INTERNAL" ) ;
  968. X                print_line( "id", make_string( 3, service, "-", socket_type ) ) ;
  969. X            }
  970. X        }
  971. X        else
  972. X        {
  973. X            char *server_path = word ;        /* from inetd.conf */
  974. X            char *server_of_server_path = basename( server_path ) ;
  975. X            char *server_name = next_word( "server name" ) ;
  976. X            char *server ;                        /* for xinetd config file */
  977. X
  978. X            if ( EQ( server_of_server_path, TCPD_NAME ) )
  979. X            {
  980. X                if ( ! uses_tcpd )
  981. X                {
  982. X                    Sprint( 2, "You must use option %s if you use %s\n",
  983. X                        DAEMON_DIR_OPTION, TCPD_NAME ) ;
  984. X                    exit( 1 ) ;
  985. X                }
  986. X                if ( server_name[ 0 ] == '/' )
  987. X                    server = server_name ;
  988. X                else
  989. X                    server = make_pathname( 2, daemon_dirpath, server_name ) ;
  990. X            }
  991. X            else
  992. X                server = server_path ;
  993. X
  994. X            print_line( "server", server ) ;
  995. X
  996. X            word = str_component( strp ) ;            /* 1st arg */
  997. X            if ( word != NULL )
  998. X            {
  999. X                Sprint( 1, "\t%-*s = %s", FIELD_WIDTH, "server_args", word ) ;
  1000. X                while ( word = str_component( strp ) )
  1001. X                    Sprint( 1, " %s", word ) ;
  1002. X                Sputchar( 1, '\n' ) ;
  1003. X            }
  1004. X        }
  1005. X
  1006. X        Sprint( 1, "}\n\n" ) ;
  1007. X    }
  1008. X    Sflush( 1 ) ;
  1009. X    exit( 0 ) ;
  1010. X}
  1011. X
  1012. X
  1013. XPRIVATE void print_line( name, value )
  1014. X    char *name, *value ;
  1015. X{
  1016. X    Sprint( 1, "\t%-*s = %s\n", FIELD_WIDTH, name, value ) ;
  1017. X}
  1018. X
  1019. X
  1020. XPRIVATE char *next_word( description )
  1021. X    char *description ;
  1022. X{
  1023. X    char *word = str_component( strp ) ;
  1024. X
  1025. X    if ( word == NULL )
  1026. X    {
  1027. X        Sprint( 2, "Line %d: %s missing \n", line_count, description ) ;
  1028. X        exit( 1 ) ;
  1029. X    }
  1030. X    return( word ) ;
  1031. X}
  1032. X
  1033. END_OF_FILE
  1034. if test 4131 -ne `wc -c <'xinetd/itox.c'`; then
  1035.     echo shar: \"'xinetd/itox.c'\" unpacked with wrong size!
  1036. fi
  1037. # end of 'xinetd/itox.c'
  1038. fi
  1039. if test -f 'xinetd/parsesup.c' -a "${1}" != "-c" ; then 
  1040.   echo shar: Will not clobber existing file \"'xinetd/parsesup.c'\"
  1041. else
  1042. echo shar: Extracting \"'xinetd/parsesup.c'\" \(4301 characters\)
  1043. sed "s/^X//" >'xinetd/parsesup.c' <<'END_OF_FILE'
  1044. X/*
  1045. X * (c) Copyright 1992 by Panagiotis Tsirigotis
  1046. X * All rights reserved.  The file named COPYRIGHT specifies the terms 
  1047. X * and conditions for redistribution.
  1048. X */
  1049. X
  1050. X#include <ctype.h>
  1051. X#include <syslog.h>
  1052. X
  1053. X#include "str.h"
  1054. X#include "pset.h"
  1055. X#include "sio.h"
  1056. X
  1057. X#include "defs.h"
  1058. X#include "parse.h"
  1059. X
  1060. Xvoid parsemsg() ;
  1061. X
  1062. Xextern int line_count ;
  1063. X
  1064. X/*
  1065. X * next_line returns the next line of the file or NULL if the end of file
  1066. X * is reached.
  1067. X * Comment lines and empty lines are skipped.
  1068. X */
  1069. Xchar *next_line( fd )
  1070. X   int fd ;
  1071. X{
  1072. X   for ( ;; )
  1073. X   {
  1074. X      register char *p ;
  1075. X      register char *line = Srdline( fd ) ;
  1076. X
  1077. X      if ( line == NULL )
  1078. X         return( NULL ) ;
  1079. X
  1080. X      line_count++ ;
  1081. X
  1082. X      for ( p = line ;; p++ )
  1083. X         if ( *p == NUL || *p == COMMENT_BEGIN )
  1084. X            break ;                                /* skip this line */
  1085. X         else if ( isspace( *p ) )
  1086. X            continue ;                             /* skip white space */
  1087. X         else
  1088. X            return( line ) ;
  1089. X   }
  1090. X}
  1091. X
  1092. X
  1093. X
  1094. X/*
  1095. X * Input:
  1096. X *        a line of the form
  1097. X *                name [SPACE] OP [SPACE] value [SPACE] value ...
  1098. X *
  1099. X * Recognize the attribute name and operator and place them in *attrp, *opp
  1100. X *
  1101. X * Currently, we allow any non-space character to be used in the
  1102. X * attribute name.
  1103. X *
  1104. X * Return value: a pointer to the character after OP.
  1105. X */
  1106. XPRIVATE char *get_attr_op( line, attrp, opp )
  1107. X    char                *line ;
  1108. X    char                **attrp ;
  1109. X    enum assign_op *opp ;
  1110. X{
  1111. X    register char    *p ;
  1112. X    char                *attr ;
  1113. X    enum assign_op op ;
  1114. X    char                *func = "get_attr_op" ;
  1115. X
  1116. X    /*
  1117. X     * First get the attribute name
  1118. X     */
  1119. X    for ( p = line ; isspace( *p ) ; p++ ) ;        /* skip spaces */
  1120. X    if ( *p == NUL )
  1121. X    {
  1122. X        parsemsg( LOG_ERR, func, "Empty line" ) ;
  1123. X        return( NULL ) ;
  1124. X    }
  1125. X
  1126. X    attr = p ;
  1127. X    for ( ; ! isspace( *p ) ; p++ ) ;                /* skip attribute name */
  1128. X    if ( *p == NUL )
  1129. X    {
  1130. X        parsemsg( LOG_ERR, func, "Nothing after attribute: %s", attr ) ;
  1131. X        return( NULL ) ;
  1132. X    }
  1133. X    *p++ = NUL ;            /* now attribute name is NUL terminated */
  1134. X
  1135. X    while ( isspace( *p ) ) p++ ;        /* skip spaces */
  1136. X
  1137. X    switch ( *p )
  1138. X    {
  1139. X        case NUL:
  1140. X            parsemsg( LOG_ERR, func, "Nothing after attribute: %s", attr ) ;
  1141. X            return( NULL ) ;
  1142. X    
  1143. X        case '=':
  1144. X            op = SET_EQ ;
  1145. X            break ;
  1146. X        
  1147. X        case '+':
  1148. X        case '-':
  1149. X            op = ( *p++ == '+' ) ? PLUS_EQ : MINUS_EQ ;
  1150. X            if ( *p == '=' )
  1151. X                break ;
  1152. X            
  1153. X            /* FALL THROUGH if there is no '=' after the '+' or '-' */
  1154. X        
  1155. X        default:
  1156. X            parsemsg( LOG_ERR, func, "Bad operator for attribute: %s", attr ) ;
  1157. X            return( NULL ) ;
  1158. X    }
  1159. X    *attrp = attr ;
  1160. X    *opp = op ;
  1161. X    return( ++p ) ;        /* skip the '=' */
  1162. X}
  1163. X
  1164. X
  1165. X/*
  1166. X * Parse a line of the form:
  1167. X *            name OP value value value ...
  1168. X * where each value is a string and OP can be '=', '+=', '-='
  1169. X *
  1170. X * NOTE: We do not allocate space for the name and values. Instead we keep
  1171. X *            pointers to the line.
  1172. X */
  1173. Xstatus_e parse_line( line, namep, opp, values )
  1174. X    char                *line ;
  1175. X    char                **namep ;
  1176. X    enum assign_op *opp ;
  1177. X    pset_h            values ;
  1178. X{
  1179. X    char        *value ;
  1180. X    char        *values_string ;
  1181. X    char        *attribute ;
  1182. X    str_h     strp ;
  1183. X    char        *func = "parse_line" ;
  1184. X
  1185. X    if ( ( values_string = get_attr_op( line, &attribute, opp ) ) == NULL )
  1186. X        return( FAILED ) ;
  1187. X
  1188. X    /*
  1189. X     * Now grab the values
  1190. X     */
  1191. X    strp = str_parse( values_string, " \t", STR_RETURN_ERROR, (int *)0 ) ;
  1192. X    if ( strp == NULL )
  1193. X    {
  1194. X        parsemsg( LOG_CRIT, func, ES_NOMEM ) ;
  1195. X        return( FAILED ) ;
  1196. X    }
  1197. X
  1198. X    while ( value = str_component( strp ) )
  1199. X    {
  1200. X        if ( pset_add( values, value ) == NULL )
  1201. X        {
  1202. X            parsemsg( LOG_CRIT, func, ES_NOMEM ) ;
  1203. X            str_endparse( strp ) ;
  1204. X            return( FAILED ) ;
  1205. X        }
  1206. X    }
  1207. X
  1208. X    str_endparse( strp ) ;
  1209. X    *namep = attribute ;
  1210. X    return( OK ) ;
  1211. X}
  1212. X
  1213. X
  1214. Xvoid skip_entry( fd )
  1215. X    register int fd ;
  1216. X{
  1217. X    for ( ;; )
  1218. X    {
  1219. X        register char *line = next_line( fd ) ;
  1220. X
  1221. X        if ( line == NULL )            /* reached EOF ? */
  1222. X        {
  1223. X            parsemsg( LOG_WARNING, "skip_entry",
  1224. X                "missing %c in last service entry", ENTRY_END ) ;
  1225. X            break ;
  1226. X        }
  1227. X
  1228. X        if ( line_has_only_1_char( line, ENTRY_END ) )
  1229. X            break ;
  1230. X    }
  1231. X}
  1232. X
  1233. X
  1234. X
  1235. X/*
  1236. X * Returns TRUE if the given line contains a single instance of the
  1237. X * specified character and no other non-space characters
  1238. X */
  1239. Xint line_has_only_1_char( line, ch )
  1240. X   char *line ;
  1241. X   char ch ;
  1242. X{
  1243. X   register char *p ;
  1244. X   register char target_char = ch ;
  1245. X
  1246. X   for ( p = line ; *p ; p++ )
  1247. X      if ( *p == target_char )
  1248. X         target_char = NUL ;
  1249. X      else if ( ! isspace( *p ) )
  1250. X         return( FALSE ) ;
  1251. X   return( target_char != ch ) ;
  1252. X}
  1253. X
  1254. X
  1255. END_OF_FILE
  1256. if test 4301 -ne `wc -c <'xinetd/parsesup.c'`; then
  1257.     echo shar: \"'xinetd/parsesup.c'\" unpacked with wrong size!
  1258. fi
  1259. # end of 'xinetd/parsesup.c'
  1260. fi
  1261. echo shar: End of archive 9 \(of 31\).
  1262. cp /dev/null ark9isdone
  1263. MISSING=""
  1264. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 ; do
  1265.     if test ! -f ark${I}isdone ; then
  1266.     MISSING="${MISSING} ${I}"
  1267.     fi
  1268. done
  1269. if test "${MISSING}" = "" ; then
  1270.     echo You have unpacked all 31 archives.
  1271.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1272. else
  1273.     echo You still need to unpack the following archives:
  1274.     echo "        " ${MISSING}
  1275. fi
  1276. ##  End of shell archive.
  1277. exit 0
  1278.