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

  1. Newsgroups: comp.sources.unix
  2. From: panos@cs.colorado.edu (Panos Tsirigotis)
  3. Subject: v26i269: xinetd-2.1.1 - inetd replacement with access control and logging, Part25/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 269
  9. Archive-Name: xinetd-2.1.1/part25
  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 25 (of 31)."
  18. # Contents:  libs/src/sio/sio.c
  19. # Wrapped by panos@mystique on Mon Jun 21 14:51:27 1993
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'libs/src/sio/sio.c' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'libs/src/sio/sio.c'\"
  23. else
  24. echo shar: Extracting \"'libs/src/sio/sio.c'\" \(15212 characters\)
  25. sed "s/^X//" >'libs/src/sio/sio.c' <<'END_OF_FILE'
  26. X/*
  27. X * (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
  28. X * All rights reserved.  The file named COPYRIGHT specifies the terms 
  29. X * and conditions for redistribution.
  30. X */
  31. X
  32. Xstatic char RCSid[] = "$Id: sio.c,v 8.1 1993/03/13 01:15:55 panos Exp $" ;
  33. Xstatic char sio_version[] = VERSION ;
  34. X
  35. X#include <sys/types.h>
  36. X#include <sys/stat.h>
  37. X
  38. X#include "sio.h"
  39. X#include "impl.h"
  40. X
  41. X#ifdef EVENTS
  42. X#include "events.h"
  43. X#endif
  44. X
  45. X/*
  46. X * SIO WRITE FUNCTIONS: Swrite, Sputc
  47. X */
  48. X
  49. X/*
  50. X * Stream write call: arguments same as those of write(2)
  51. X */
  52. Xint Swrite( fd, addr, nbytes )
  53. X    int fd ;
  54. X    register char *addr ;
  55. X    register int nbytes ;
  56. X{
  57. X    register __sio_descriptor_t *dp = &__sio_descriptors[ fd ] ;
  58. X    register __sio_od_t *odp = ODP( dp ) ;
  59. X    register int b_transferred ;
  60. X    register int b_avail ;
  61. X    int total_b_transferred ;
  62. X    int b_written ;
  63. X    int b_in_buffer ;
  64. X
  65. X#ifdef EVENTS
  66. X    EVENT( fd, EV_SWRITE ) ;
  67. X#endif
  68. X
  69. X    IO_SETUP( fd, dp, __SIO_OUTPUT_STREAM, SIO_ERR ) ;
  70. X    ASSERT( odp->start <= odp->nextb && odp->nextb <= odp->buf_end ) ;
  71. X
  72. X    b_avail = odp->buf_end - odp->nextb ;
  73. X    b_transferred = MIN( nbytes, b_avail ) ;
  74. X    sio_memcopy( addr, odp->nextb, b_transferred ) ;
  75. X    odp->nextb += b_transferred ;
  76. X
  77. X    /*
  78. X     * check if we are done
  79. X     */
  80. X    if ( b_transferred == nbytes )
  81. X        return( b_transferred ) ;
  82. X
  83. X    /*
  84. X     * at this point we know that the buffer is full
  85. X     */
  86. X    b_in_buffer = odp->buf_end - odp->start ;
  87. X    b_written = __sio_writef( odp, fd ) ;
  88. X    if ( b_written != b_in_buffer )
  89. X        return( (b_written >= nbytes) ? nbytes : b_written ) ;
  90. X    
  91. X    total_b_transferred = b_transferred ;
  92. X    addr += b_transferred ;
  93. X    nbytes -= b_transferred ;
  94. X
  95. X    for ( ;; )
  96. X    {
  97. X        b_transferred = MIN( nbytes, odp->buffer_size ) ;
  98. X        sio_memcopy( addr, odp->nextb, b_transferred ) ;
  99. X        odp->nextb += b_transferred ;
  100. X        nbytes -= b_transferred ;
  101. X        if ( nbytes == 0 )
  102. X        {
  103. X            total_b_transferred += b_transferred ;
  104. X            break ;
  105. X        }
  106. X        /*
  107. X         * the buffer is full
  108. X         */
  109. X        b_written = __sio_writef( odp, fd ) ;
  110. X        if ( b_written != odp->buffer_size )
  111. X        {
  112. X            if ( b_written != SIO_ERR )
  113. X            {
  114. X                total_b_transferred += b_written ;
  115. X                odp->nextb += b_written ;
  116. X            }
  117. X            break ;
  118. X        }
  119. X        /*
  120. X         * everything is ok
  121. X         */
  122. X        total_b_transferred += b_transferred ;
  123. X        addr += b_transferred ;
  124. X    }
  125. X    return( total_b_transferred ) ;
  126. X}
  127. X
  128. X
  129. X/*
  130. X * Add a character to a file
  131. X */
  132. Xint Sputc( fd, c )
  133. X    int fd ;
  134. X    char c ;
  135. X{
  136. X    register __sio_descriptor_t *dp = &__sio_descriptors[ fd ] ;
  137. X    register __sio_od_t *odp = ODP( dp ) ;
  138. X
  139. X#ifdef EVENTS
  140. X    EVENT( fd, EV_SPUTC ) ;
  141. X#endif
  142. X    
  143. X    IO_SETUP( fd, dp, __SIO_OUTPUT_STREAM, SIO_ERR ) ;
  144. X    ASSERT( odp->start <= odp->nextb && odp->nextb <= odp->buf_end ) ;
  145. X
  146. X    /*
  147. X     * The following is a weak check since we should really be
  148. X     * checking that nextb == buf_end (it would be an error for
  149. X     * nextb to exceed buf_end; btw, the assertion above, when
  150. X     * enabled makes sure this does not occur).
  151. X     *
  152. X     * NOTE: __sio_writef NEVER uses data beyond the end of buffer.
  153. X     */
  154. X    if ( odp->nextb >= odp->buf_end )
  155. X    {
  156. X        int b_in_buffer = odp->buf_end - odp->start ;
  157. X
  158. X        /*
  159. X         * There is nothing we can do if __sio_writef does not manage
  160. X         * to write the whole buffer
  161. X         */
  162. X        if ( __sio_writef( odp, fd ) != b_in_buffer )
  163. X            return( SIO_ERR ) ;
  164. X    }
  165. X    *odp->nextb++ = c ;
  166. X    if ( __SIO_MUST_FLUSH( *odp, c ) && __sio_writef( odp, fd ) == SIO_ERR )
  167. X        return( SIO_ERR ) ;
  168. X    return ( c ) ;
  169. X}
  170. X
  171. X
  172. X
  173. X/*
  174. X * SIO READ FUNCTIONS
  175. X */
  176. X
  177. X/*
  178. X * Stream read call: arguments same as those of read(2)
  179. X */
  180. Xint Sread( fd, addr, nbytes )
  181. X    int fd ;
  182. X    char *addr ;
  183. X    int nbytes ;
  184. X{
  185. X    register __sio_descriptor_t *dp = &__sio_descriptors[ fd ] ;
  186. X    register __sio_id_t *idp = IDP( dp ) ;
  187. X    register int b_transferred ;
  188. X    int b_read ;
  189. X    int total_b_transferred ;
  190. X    int b_left ;
  191. X
  192. X#ifdef EVENTS
  193. X    EVENT( fd, EV_SREAD ) ;
  194. X#endif
  195. X
  196. X    IO_SETUP( fd, dp, __SIO_INPUT_STREAM, SIO_ERR ) ;
  197. X    ASSERT( idp->start <= idp->nextb && idp->nextb <= idp->end ) ;
  198. X
  199. X    b_left = idp->end - idp->nextb ;
  200. X    b_transferred = MIN( b_left, nbytes ) ;
  201. X    sio_memcopy( idp->nextb, addr, b_transferred ) ;
  202. X    idp->nextb += b_transferred ;
  203. X    if ( b_transferred == nbytes )
  204. X        return( b_transferred ) ;
  205. X    
  206. X    nbytes -= b_transferred ;
  207. X    total_b_transferred = b_transferred ;
  208. X    addr += b_transferred ;
  209. X
  210. X    do
  211. X    {
  212. X        b_read = __sio_readf( idp, fd ) ;
  213. X        switch ( b_read )
  214. X        {
  215. X            case SIO_ERR:
  216. X                if ( total_b_transferred == 0 )
  217. X                    return( SIO_ERR ) ;
  218. X                /* FALL THROUGH */
  219. X            
  220. X            case 0:
  221. X                return( total_b_transferred ) ;
  222. X        }
  223. X            
  224. X        b_transferred = MIN( b_read, nbytes ) ;
  225. X        sio_memcopy( idp->nextb, addr, b_transferred ) ;
  226. X        addr += b_transferred ;
  227. X        idp->nextb += b_transferred ;
  228. X        total_b_transferred += b_transferred ;
  229. X        nbytes -= b_transferred ;
  230. X    }
  231. X    while ( nbytes && b_read == idp->buffer_size ) ;
  232. X    return( total_b_transferred ) ;
  233. X}
  234. X
  235. X
  236. X
  237. X/*
  238. X * Read a line from a file
  239. X * Returns a pointer to the beginning of the line or NULL
  240. X */
  241. Xchar *Srdline( fd )
  242. X    int fd ;
  243. X{
  244. X    register __sio_descriptor_t *dp = &__sio_descriptors[ fd ] ;
  245. X    register __sio_id_t *idp = IDP( dp ) ;
  246. X    register char *cp ;
  247. X    register char *line_start ;
  248. X    register int b_left ;
  249. X    register int extension ;
  250. X
  251. X#ifdef EVENTS
  252. X    EVENT( fd, EV_SRDLINE ) ;
  253. X#endif
  254. X
  255. X    IO_SETUP( fd, dp, __SIO_INPUT_STREAM, NULL ) ;
  256. X    ASSERT( idp->start <= idp->nextb && idp->nextb <= idp->end ) ;
  257. X
  258. X#ifdef HAS_MMAP
  259. X    if ( idp->memory_mapped && __sio_switch( idp, fd ) == FAILURE )
  260. X        return( NULL ) ;
  261. X#endif
  262. X
  263. X    b_left = idp->end - idp->nextb ;
  264. X    /*
  265. X     * Look for a '\n'. If the search fails, extend the buffer
  266. X     * and search again (the extension is performed by copying the
  267. X     * bytes that were searched to the auxiliary buffer and reading 
  268. X     * new input in the main buffer).
  269. X     * If the new input still does not contain a '\n' and there is
  270. X     * more space in the main buffer (this can happen with network
  271. X     * connections), read more input until either the buffer is full
  272. X     * or a '\n' is found.
  273. X     * Finally, set cp to point to the '\n', and line_start to
  274. X     * the beginning of the line
  275. X     */
  276. X    if ( b_left && ( cp = sio_memscan( idp->nextb, b_left, '\n' ) ) != NULL )
  277. X    {
  278. X        line_start = idp->nextb ;
  279. X        idp->nextb = cp + 1 ;
  280. X    }
  281. X    else
  282. X    {
  283. X        extension = __sio_extend_buffer( idp, fd, b_left ) ;
  284. X        if ( extension > 0 )
  285. X        {
  286. X            ASSERT( idp->start <= idp->nextb && idp->nextb <= idp->end ) ;
  287. X
  288. X            line_start = idp->start ;
  289. X            cp = sio_memscan( idp->nextb, extension, '\n' ) ;
  290. X            if ( cp != NULL )
  291. X                idp->nextb = cp + 1 ;
  292. X            else
  293. X                for ( ;; )
  294. X                {
  295. X                    idp->nextb = idp->end ;
  296. X                    extension = __sio_more( idp, fd ) ;
  297. X                    if ( extension > 0 )
  298. X                    {
  299. X                        cp = sio_memscan( idp->nextb, extension, '\n' ) ;
  300. X                        if ( cp == NULL )
  301. X                            continue ;
  302. X                        idp->nextb = cp + 1 ;
  303. X                        break ;
  304. X                    }
  305. X                    else
  306. X                    {
  307. X                        /*
  308. X                         * If there is spare room in the buffer avoid trashing
  309. X                         * the last character
  310. X                         */
  311. X                        if ( idp->end < &idp->buf[ idp->buffer_size ] )
  312. X                            cp = idp->end ;
  313. X                        else
  314. X                            cp = &idp->buf[ idp->buffer_size - 1 ] ;
  315. X                        break ;
  316. X                    }
  317. X                }
  318. X        }
  319. X        else                    /* buffer could not be extended */
  320. X            if ( b_left == 0 )
  321. X            {
  322. X                /*
  323. X                 * Set errno to 0 if EOF has been reached
  324. X                 */
  325. X                if ( extension == 0 )
  326. X                    errno = 0 ;
  327. X                return( NULL ) ;
  328. X            }
  329. X            else
  330. X            {
  331. X                line_start = idp->start ;
  332. X                cp = idp->end ;
  333. X                /*
  334. X                 * By setting idp->nextb to be equal to idp->end,
  335. X                 * subsequent calls to Srdline will return NULL because
  336. X                 * __sio_extend_buffer will be invoked and it will return 0.
  337. X                 */
  338. X                idp->nextb = idp->end ;
  339. X            }
  340. X    }
  341. X    *cp = NUL ;
  342. X    idp->line_length = cp - line_start ;
  343. X    return( line_start ) ;
  344. X}
  345. X
  346. X
  347. X/*
  348. X * Get a character from a file
  349. X */
  350. Xint Sgetc( fd )
  351. X    int fd ;
  352. X{
  353. X    register __sio_descriptor_t *dp = &__sio_descriptors[ fd ] ;
  354. X    register __sio_id_t *idp = IDP( dp ) ;
  355. X
  356. X#ifdef EVENTS
  357. X    EVENT( fd, EV_SGETC ) ;
  358. X#endif
  359. X
  360. X    IO_SETUP( fd, dp, __SIO_INPUT_STREAM, SIO_ERR ) ;
  361. X    ASSERT( idp->start <= idp->nextb && idp->nextb <= idp->end ) ;
  362. X    if ( idp->nextb >= idp->end )
  363. X    {
  364. X        register int b_read = __sio_readf( idp, fd ) ;
  365. X
  366. X        if ( b_read == 0 )
  367. X            return( SIO_EOF ) ;
  368. X        else if ( b_read == SIO_ERR )
  369. X            return( SIO_ERR ) ;
  370. X    }
  371. X    return( (int) *idp->nextb++ ) ;
  372. X}
  373. X
  374. X
  375. Xchar *Sfetch( fd, lenp )
  376. X    int fd ;
  377. X    long *lenp ;
  378. X{
  379. X    register __sio_descriptor_t *dp = &__sio_descriptors[ fd ] ;
  380. X    register __sio_id_t *idp = IDP( dp ) ;
  381. X    register int b_read ;
  382. X    register char *p ;
  383. X
  384. X#ifdef EVENTS
  385. X    EVENT( fd, EV_SFETCH ) ;
  386. X#endif
  387. X
  388. X    IO_SETUP( fd, dp, __SIO_INPUT_STREAM, NULL ) ;
  389. X    ASSERT( idp->start <= idp->nextb && idp->nextb <= idp->end ) ;
  390. X    if ( idp->nextb >= idp->end )
  391. X    {
  392. X        b_read = __sio_readf( idp, fd ) ;
  393. X        if ( b_read == SIO_ERR )
  394. X            return( NULL ) ;
  395. X        if ( b_read == 0 )
  396. X        {
  397. X            errno = 0 ;
  398. X            return( NULL ) ;
  399. X        }
  400. X    }
  401. X    *lenp = idp->end - idp->nextb ;
  402. X    p = idp->nextb ;
  403. X    idp->nextb = idp->end ;
  404. X    return( p ) ;
  405. X}
  406. X
  407. X
  408. X
  409. X/*
  410. X * SIO CONTROL FUNCTIONS
  411. X */
  412. X
  413. X/*
  414. X * Undo the last Srdline or Sgetc
  415. X */
  416. Xint Sundo( fd, type )
  417. X    int fd ;
  418. X    int type ;
  419. X{
  420. X    register __sio_descriptor_t *dp = &__sio_descriptors[ fd ] ; 
  421. X    register __sio_id_t *idp = IDP( dp ) ;
  422. X    int retval = 0 ;
  423. X
  424. X#ifdef EVENTS
  425. X    EVENT( fd, EV_SUNDO ) ;
  426. X#endif
  427. X
  428. X    CONTROL_SETUP( dp, __SIO_INPUT_STREAM, SIO_ERR ) ;
  429. X
  430. X    /*
  431. X     * Undo works only for fd's used for input
  432. X     */
  433. X    if ( dp->stream_type != __SIO_INPUT_STREAM )
  434. X        return( SIO_ERR ) ;
  435. X
  436. X    /*
  437. X     * Check if the operation makes sense; if so, do it, otherwise ignore it
  438. X     */
  439. X    switch ( type )
  440. X    {
  441. X        case SIO_UNDO_LINE:
  442. X            if ( idp->nextb - idp->line_length > idp->start )
  443. X            {
  444. X                *--idp->nextb = '\n' ;
  445. X                idp->nextb -= idp->line_length ;
  446. X            }
  447. X            ASSERT( idp->start <= idp->nextb && idp->nextb <= idp->end ) ;
  448. X            break ;
  449. X        
  450. X        case SIO_UNDO_CHAR:
  451. X            if ( idp->nextb > idp->start )
  452. X                idp->nextb-- ;
  453. X            ASSERT( idp->start <= idp->nextb && idp->nextb <= idp->end ) ;
  454. X            break ;
  455. X        
  456. X        default:
  457. X            retval = SIO_ERR ;
  458. X            break ;
  459. X    }
  460. X    return( retval ) ;
  461. X}
  462. X
  463. X
  464. X/*
  465. X * Flush the buffer associated with the given file descriptor
  466. X * The special value, SIO_FLUSH_ALL flushes all buffers
  467. X *
  468. X * Return value:
  469. X *            0 :  if fd is SIO_FLUSH_ALL or if the flush is successful
  470. X *        SIO_ERR: if fd is not SIO_FLUSH_ALL and
  471. X *                                the flush is unsuccessful
  472. X *                            or the descriptor is not initialized or it is not 
  473. X *                                an output descriptor
  474. X */
  475. Xint Sflush( fd )
  476. X    int fd ;
  477. X{
  478. X   register __sio_descriptor_t *dp ;
  479. X   int b_in_buffer ;
  480. X
  481. X#ifdef EVENTS
  482. X    EVENT( fd, EV_SFLUSH ) ;
  483. X#endif
  484. X
  485. X   if ( fd == SIO_FLUSH_ALL )
  486. X   {
  487. X      for ( fd = 0, dp = __sio_descriptors ;
  488. X                fd < N_SIO_DESCRIPTORS ;
  489. X                dp++, fd++ )
  490. X         if ( DESCRIPTOR_INITIALIZED( dp ) &&
  491. X                            dp->stream_type == __SIO_OUTPUT_STREAM )
  492. X            (void) __sio_writef( ODP( dp ), fd ) ;
  493. X      return( 0 ) ;
  494. X   }
  495. X   else
  496. X   {
  497. X      dp = &__sio_descriptors[ fd ] ;
  498. X
  499. X        CONTROL_SETUP( dp, __SIO_OUTPUT_STREAM, SIO_ERR ) ;
  500. X      b_in_buffer = ODP( dp )->nextb - ODP( dp )->start ;
  501. X      if ( __sio_writef( ODP( dp ), fd ) != b_in_buffer )
  502. X         return( SIO_ERR ) ;
  503. X      else
  504. X         return( 0 ) ;
  505. X   }
  506. X}
  507. X
  508. X
  509. X/*
  510. X * Close the file descriptor. This call is provided because
  511. X * a file descriptor may be closed and then reopened. There is
  512. X * no easy way for SIO to identify such a situation, so Sclose
  513. X * must be used.
  514. X *
  515. X * Sclose invokes Sdone which finalizes the buffer.
  516. X * There is no SIO_CLOSE_ALL value for fd because such a thing
  517. X * would imply that the program will exit very soon, therefore
  518. X * the closing of all file descriptors will be done in the kernel
  519. X * (and the finalization will be done by the finalization function
  520. X * NOTE: not true if the OS does not support a finalization function)
  521. X *
  522. X * There is no need to invoke SETUP; Sdone will do it.
  523. X */
  524. Xint Sclose( fd )
  525. X    int fd ;
  526. X{
  527. X#ifdef EVENTS
  528. X    EVENT( fd, EV_SCLOSE ) ;
  529. X#endif
  530. X
  531. X    if ( __SIO_FD_INITIALIZED( fd ) )
  532. X        if ( Sdone( fd ) == SIO_ERR )
  533. X            return( SIO_ERR ) ;
  534. X    return( close( fd ) ) ;
  535. X}
  536. X
  537. X
  538. X
  539. X/*
  540. X * Tie the file descriptor in_fd to the file descriptor out_fd
  541. X * This means that whenever a read(2) is done on in_fd, it is
  542. X * preceded by a write(2) on out_fd.
  543. X * Why this is nice to have:
  544. X *     1) When used in filters it maximizes concurrency
  545. X *        2) When the program prompts the user for something it forces
  546. X *            the prompt string to be displayed even if it does not
  547. X *            end with a '\n' (which would cause a flush).
  548. X * In this implementation, out_fd cannot be a regular file.
  549. X * This is done to avoid non-block-size write's.
  550. X * The file descriptors are initialized if that has not been done
  551. X * already. If any of them is initialized, it must be for the appropriate
  552. X * stream type (input or output).
  553. X *
  554. X * NOTE: the code handles correctly the case when in_fd == out_fd
  555. X */
  556. Xint Stie( in_fd, out_fd )
  557. X    int in_fd, out_fd ;
  558. X{
  559. X    struct stat st ;
  560. X    register __sio_descriptor_t *dp ;
  561. X    int was_initialized ;
  562. X    boolean_e failed = NO ;
  563. X
  564. X#ifdef EVENTS
  565. X    EVENT( in_fd, EV_STIE ) ;
  566. X#endif
  567. X
  568. X    /*
  569. X     * Check if the out_fd is open
  570. X     */
  571. X    if ( fstat( out_fd, &st ) == -1 )
  572. X        return( SIO_ERR ) ;
  573. X
  574. X    /*
  575. X     * If the out_fd refers to a regular file, the request is silently ignored
  576. X     */
  577. X    if ( ( st.st_mode & S_IFMT ) == S_IFREG )
  578. X        return( 0 ) ;
  579. X    
  580. X    dp = &__sio_descriptors[ in_fd ] ;
  581. X    was_initialized = dp->initialized ;        /* remember if it was initialized */
  582. X    IO_SETUP( in_fd, dp, __SIO_INPUT_STREAM, SIO_ERR ) ;
  583. X
  584. X    /*
  585. X     * Perform manual initialization of out_fd to avoid leaving in_fd
  586. X     * initialized if the initialization of out_fd fails.
  587. X     * If out_fd is initialized, check if it is used for output.
  588. X     * If it is not initialized, initialize it for output.
  589. X     */
  590. X    dp = &__sio_descriptors[ out_fd ] ;
  591. X    if ( DESCRIPTOR_INITIALIZED( dp ) )
  592. X    {
  593. X        if ( dp->stream_type != __SIO_OUTPUT_STREAM )
  594. X        {
  595. X            failed = YES ;
  596. X            errno = EBADF ;
  597. X        }
  598. X    }
  599. X    else
  600. X        if ( __sio_init( dp, out_fd, __SIO_OUTPUT_STREAM ) == SIO_ERR )
  601. X            failed = YES ;
  602. X
  603. X    if ( failed == NO )
  604. X    {
  605. X        __SIO_ID( in_fd ).tied_fd = out_fd ;
  606. X        return( 0 ) ;
  607. X    }
  608. X    else
  609. X    {
  610. X        /*
  611. X         * We failed. If we did any initialization, undo it
  612. X         */
  613. X        if ( ! was_initialized )
  614. X        {
  615. X            int save_errno = errno ;
  616. X
  617. X            (void) Sdone( in_fd ) ;
  618. X            errno = save_errno ;
  619. X        }
  620. X        return( SIO_ERR ) ;
  621. X    }
  622. X}
  623. X
  624. X
  625. X/*
  626. X * Untie a file descriptor
  627. X */
  628. Xint Suntie( fd )
  629. X    int fd ;
  630. X{
  631. X    register __sio_descriptor_t *dp = &__sio_descriptors[ fd ] ;
  632. X
  633. X#ifdef EVENTS
  634. X    EVENT( fd, EV_SUNTIE ) ;
  635. X#endif
  636. X
  637. X    CONTROL_SETUP( dp, __SIO_INPUT_STREAM, SIO_ERR ) ;
  638. X    
  639. X    if ( IDP( dp )->tied_fd != SIO_NO_TIED_FD )
  640. X    {
  641. X        IDP( dp )->tied_fd = SIO_NO_TIED_FD ;
  642. X        return( 0 ) ;
  643. X    }
  644. X    else
  645. X    {
  646. X        errno = EBADF ;
  647. X        return( SIO_ERR ) ;
  648. X    }
  649. X}
  650. X
  651. X
  652. X/*
  653. X * Changes the type of buffering on the specified descriptor.
  654. X * As a side-effect, it initializes the descriptor as an output stream.
  655. X */
  656. Xint Sbuftype( fd, type )
  657. X    int fd, type ;
  658. X{
  659. X    register __sio_descriptor_t *dp = &__sio_descriptors[ fd ] ;
  660. X
  661. X#ifdef EVENTS
  662. X    EVENT( fd, EV_SBUFTYPE ) ;
  663. X#endif
  664. X
  665. X    /*
  666. X     * Check for a valid type
  667. X     */
  668. X    if ( type != SIO_LINEBUF && type != SIO_FULLBUF && type != SIO_NOBUF )
  669. X    {
  670. X        errno = EINVAL ;
  671. X        return( SIO_ERR ) ;
  672. X    }
  673. X
  674. X    IO_SETUP( fd, dp, __SIO_OUTPUT_STREAM, SIO_ERR ) ;
  675. X    ODP( dp )->buftype = type ;
  676. X    return( 0 ) ;
  677. X}
  678. X
  679. X
  680. X#ifndef sio_memscan
  681. X
  682. XPRIVATE char *sio_memscan( from, how_many, ch )
  683. X   char *from ;
  684. X   int how_many ;
  685. X   register char ch ;
  686. X{
  687. X   register char *p ;
  688. X   register char *last = from + how_many ;
  689. X
  690. X   for ( p = from ; p < last ; p++ )
  691. X      if ( *p == ch )
  692. X         return( p ) ;
  693. X      return( 0 ) ;
  694. X}
  695. X
  696. X#endif    /* sio_memscan */
  697. X
  698. X
  699. X#ifdef NEED_MEMCOPY
  700. X
  701. Xvoid __sio_memcopy( from, to, nbytes )
  702. X   register char *from, *to ;
  703. X   register int nbytes ;
  704. X{
  705. X   while ( nbytes-- )
  706. X      *to++ = *from++ ;
  707. X}
  708. X
  709. X#endif /* NEED_MEMCOPY */
  710. X
  711. X
  712. END_OF_FILE
  713. if test 15212 -ne `wc -c <'libs/src/sio/sio.c'`; then
  714.     echo shar: \"'libs/src/sio/sio.c'\" unpacked with wrong size!
  715. fi
  716. # end of 'libs/src/sio/sio.c'
  717. fi
  718. echo shar: End of archive 25 \(of 31\).
  719. cp /dev/null ark25isdone
  720. MISSING=""
  721. 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
  722.     if test ! -f ark${I}isdone ; then
  723.     MISSING="${MISSING} ${I}"
  724.     fi
  725. done
  726. if test "${MISSING}" = "" ; then
  727.     echo You have unpacked all 31 archives.
  728.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  729. else
  730.     echo You still need to unpack the following archives:
  731.     echo "        " ${MISSING}
  732. fi
  733. ##  End of shell archive.
  734. exit 0
  735.