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

  1. Newsgroups: comp.sources.unix
  2. From: panos@cs.colorado.edu (Panos Tsirigotis)
  3. Subject: v26i275: xinetd-2.1.1 - inetd replacement with access control and logging, Part31/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 275
  9. Archive-Name: xinetd-2.1.1/part31
  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 31 (of 31)."
  18. # Contents:  libs/src/sio/siosup.c
  19. # Wrapped by panos@mystique on Mon Jun 21 14:51:29 1993
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'libs/src/sio/siosup.c' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'libs/src/sio/siosup.c'\"
  23. else
  24. echo shar: Extracting \"'libs/src/sio/siosup.c'\" \(24088 characters\)
  25. sed "s/^X//" >'libs/src/sio/siosup.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: siosup.c,v 8.4 1993/03/17 07:35:24 panos Exp $" ;
  33. X
  34. X#include <sys/types.h>
  35. X#include <sys/stat.h>
  36. X#include <fcntl.h>
  37. X
  38. X#include "impl.h"
  39. X#include "sio.h"
  40. X
  41. X#ifdef EVENTS
  42. X#include "events.h"
  43. X#endif
  44. X
  45. Xchar *malloc() ;
  46. Xchar *realloc() ;
  47. X
  48. X
  49. Xstatic __sio_descriptor_t static_descriptor_array[ N_SIO_DESCRIPTORS ] ;
  50. Xstatic int n_descriptors = N_SIO_DESCRIPTORS ;
  51. X__sio_descriptor_t *__sio_descriptors = static_descriptor_array ;
  52. X
  53. X#ifdef EVENTS
  54. Xstatic events_s static___sio_events[ N_SIO_DESCRIPTORS ] ;
  55. Xevents_s *__sio_events = static___sio_events ;
  56. X#endif
  57. X
  58. X
  59. X/*
  60. X * Code for finalization
  61. X */
  62. X#ifdef HAS_FINALIZATION_FUNCTION
  63. Xstatic int finalizer_installed ;
  64. X
  65. XSIO_DEFINE_FIN( sio_cleanup )
  66. X{
  67. X   (void) Sflush( SIO_FLUSH_ALL ) ;
  68. X}
  69. X#endif /* HAS_FINALIZATION_FUNCTION */
  70. X
  71. X
  72. X
  73. X#ifdef HAS_MMAP
  74. X
  75. X#define CHAR_NULL                ((char *)0)
  76. X
  77. X/*
  78. X * PAGES_MAPPED gives the size of each map unit in pages
  79. X */
  80. X#define PAGES_MAPPED                2
  81. X
  82. Xstatic size_t map_unit_size = 0 ;            /* bytes */
  83. Xstatic size_t page_size = 0 ;                    /* bytes */
  84. X
  85. Xstatic mapd_s static_mapd_array[ N_SIO_DESCRIPTORS ] ;
  86. Xstatic mapd_s *mmap_descriptors = static_mapd_array ;
  87. X
  88. X#define MDP( fd )                ( mmap_descriptors + (fd) )
  89. X
  90. X
  91. X/*
  92. X * NOTES ON MEMORY MAPPING:
  93. X *
  94. X *     1. Memory mapping works only for file descriptors opened for input
  95. X *        2. Mapping an object to a part of the address space where another
  96. X *            object is mapped will cause the old mapping to disappear (i.e. mmap
  97. X *            will not fail)
  98. X *
  99. X * Memory mapping interface:
  100. X *        SIO_MMAP : maps a file into a portion of the address space.
  101. X *        SIO_MUNMAP: unmap a portion of the address space
  102. X *        SIO_MNEED: indicate to the OS that we will need a portion of
  103. X *                         our address space.
  104. X *
  105. X * The map_unit_size variable defines how much of the file is mapped at
  106. X * a time. It is a multiple of the operating system page size. It is
  107. X * not less than SIO_BUFFER_SIZE unless SIO_BUFFER_SIZE is not a
  108. X * multiple of the page size (so the SIO_BUFFER_SIZE overrides
  109. X * PAGES_MAPPED).
  110. X *
  111. X * NOTE: All memory mapping code is in this file only
  112. X */
  113. X
  114. X
  115. X/*
  116. X * Macros used by the memory mapping code
  117. X */
  118. X#define FIRST_TIME( dp )                    ( dp->buf == NULL )
  119. X#define FATAL_ERROR( msg )                    perror( msg ), exit( 1 )
  120. X
  121. X/*
  122. X * Functions to support memory mapping:
  123. X *
  124. X *            try_memory_mapping
  125. X *            buffer_setup
  126. X *            __sio_switch
  127. X *            initial_map
  128. X *            map_unit
  129. X */
  130. X
  131. X/*
  132. X * try_memory_mapping attempts to setup the specified descriptor
  133. X * for memory mapping. 
  134. X * It returns FAILURE if it fails and SUCCESS if it is successful.
  135. X * If HAS_MMAP is not defined, the function is defined to be FAILURE.
  136. X *
  137. X * Sets fields:
  138. X *        memory_mapped:             TRUE or FALSE
  139. X *        
  140. X * Also sets the following fields if memory_mapped is TRUE:
  141. X *    file_offset, file_size, buffer_size
  142. X *
  143. X */
  144. XPRIVATE status_e try_memory_mapping( fd, idp, stp )
  145. X    int fd ;
  146. X    register __sio_id_t *idp ;
  147. X    struct stat *stp ;
  148. X{
  149. X    int access ;
  150. X
  151. X#ifdef EVENTS
  152. X    EVENT( fd, EV_TRY_MEMORY_MAPPING ) ;
  153. X#endif
  154. X
  155. X    /*
  156. X     * Do not try memory mapping if:
  157. X     *        1) The file is not a regular file
  158. X     *        2) The file is a regular file but has zero-length
  159. X     *        3) The file pointer is not positioned at the beginning of the file
  160. X     *        4) The fcntl to obtain the file descriptor flags fails
  161. X     *        5) The access mode is not O_RDONLY or O_RDWR
  162. X     *
  163. X     * The operations are done in this order to avoid the system calls
  164. X     * if possible.
  165. X     */
  166. X    if ( ( ( stp->st_mode & S_IFMT ) != S_IFREG ) ||
  167. X          ( stp->st_size == 0 ) ||
  168. X          ( lseek( fd, (long)0, 1 ) != 0 ) ||
  169. X          ( ( access = fcntl( fd, F_GETFL, 0 ) ) == -1 ) ||
  170. X          ( ( access &= 0x3 ) != O_RDONLY && access != O_RDWR ) )
  171. X    {
  172. X        idp->memory_mapped = FALSE ;
  173. X        return( FAILURE ) ;
  174. X    }
  175. X
  176. X    /*
  177. X     * Determine page_size and map_unit_size.
  178. X     * Note that the code works even if PAGES_MAPPED is 0.
  179. X     */
  180. X    if ( page_size == 0 )
  181. X    {
  182. X        page_size = getpagesize() ;
  183. X        map_unit_size = page_size * PAGES_MAPPED ;
  184. X        if ( map_unit_size < SIO_BUFFER_SIZE )
  185. X            if ( map_unit_size > 0 && SIO_BUFFER_SIZE % map_unit_size == 0 )
  186. X                map_unit_size = SIO_BUFFER_SIZE ;
  187. X            else
  188. X                map_unit_size = page_size ;
  189. X    }
  190. X    
  191. X    MDP(fd)->file_offset = 0 ;
  192. X    MDP(fd)->file_size = stp->st_size ;
  193. X    idp->buffer_size = map_unit_size ;
  194. X    idp->buf = CHAR_NULL ;
  195. X    idp->memory_mapped = TRUE ;
  196. X
  197. X    return( SUCCESS ) ;
  198. X}
  199. X
  200. X
  201. X/*
  202. X * Copy the current_unit to the primary buffer
  203. X *
  204. X * Sets fields: start, end, nextb
  205. X * Also sets the file pointer
  206. X */
  207. XPRIVATE void buffer_setup( idp, fd, mu_cur, mu_next )
  208. X    __sio_id_t *idp ;
  209. X    int fd ;
  210. X    struct map_unit *mu_cur ;
  211. X    struct map_unit *mu_next ;
  212. X{
  213. X    off_t new_offset ;
  214. X
  215. X    sio_memcopy( mu_cur->addr, idp->buf, mu_cur->valid_bytes ) ;
  216. X    idp->start = idp->buf ;
  217. X    idp->end = idp->buf + mu_cur->valid_bytes ;
  218. X    idp->nextb = idp->buf + ( idp->nextb - mu_cur->addr ) ;
  219. X
  220. X    if ( mu_next->addr != CHAR_NULL )
  221. X        new_offset = MDP(fd)->file_offset - mu_next->valid_bytes ;
  222. X    else
  223. X        new_offset = MDP(fd)->file_offset ;
  224. X    (void) lseek( fd, new_offset, 0 ) ;
  225. X}
  226. X
  227. X
  228. X/*
  229. X * Switch from memory mapping to buffered I/O
  230. X * If any mapping has occured, then the current unit is
  231. X * copied into the buffer that is allocated.
  232. X * Any data in the next unit is ignored.
  233. X * We rely on idp->buf to identify the current unit (so it
  234. X * better be equal to the address of one of the units).
  235. X *
  236. X * Sets fields:
  237. X *            start, end, nextb
  238. X */
  239. Xstatus_e __sio_switch( idp, fd )
  240. X    register __sio_id_t *idp ;
  241. X    int fd ;
  242. X{
  243. X    register mapd_s *mdp = MDP( fd ) ;
  244. X    struct map_unit *mu_cur, *mu_next ;
  245. X    unsigned buffer_size = idp->buffer_size ;
  246. X    char *buf_addr = idp->buf ;
  247. X    int first_time = FIRST_TIME( idp ) ;
  248. X    void buffer_setup() ;
  249. X    status_e setup_read_buffer() ;
  250. X
  251. X#ifdef EVENTS
  252. X    EVENT( fd, EV_SIO_SWITCH ) ;
  253. X#endif
  254. X
  255. X    /*
  256. X     * Initialize stream for buffering
  257. X     */
  258. X    if ( setup_read_buffer( idp, buffer_size ) == FAILURE )
  259. X        return( FAILURE ) ;
  260. X
  261. X    if ( ! first_time )
  262. X    {
  263. X        /*
  264. X         * Find current, next unit
  265. X         */
  266. X        if ( buf_addr == mdp->first_unit.addr )
  267. X        {
  268. X            mu_cur = &mdp->first_unit ;
  269. X            mu_next = &mdp->second_unit ;
  270. X        }
  271. X        else
  272. X        {
  273. X            mu_cur = &mdp->second_unit ;
  274. X            mu_next = &mdp->first_unit ;
  275. X        }
  276. X
  277. X        buffer_setup( idp, fd, mu_cur, mu_next ) ;
  278. X        /*
  279. X         * Destroy all mappings
  280. X         */
  281. X        (void) SIO_MUNMAP( mu_cur->addr, mu_cur->mapped_bytes ) ;
  282. X        if ( mu_next->addr != NULL )
  283. X            (void) SIO_MUNMAP( mu_next->addr, mu_next->mapped_bytes ) ;
  284. X    }
  285. X    else
  286. X        idp->start = idp->end = idp->nextb = idp->buf ;
  287. X
  288. X    idp->memory_mapped = FALSE ;
  289. X    return( SUCCESS ) ;
  290. X}
  291. X
  292. X
  293. X/*
  294. X * initial_map does the first memory map on the file descriptor.
  295. X * It attempts to map both units.
  296. X * The mapping always starts at file offset 0.
  297. X *
  298. X * SETS FIELDS:
  299. X *            first_unit.*, second_unit.*
  300. X *            file_offset
  301. X *
  302. X * Returns: 
  303. X *            number of bytes mapped in first_unit
  304. X *    or
  305. X *            0 to indicate that mmap failed.
  306. X */
  307. XPRIVATE int initial_map( mdp, fd )
  308. X    register mapd_s *mdp ;
  309. X    int fd ;
  310. X{
  311. X    register caddr_t addr ;
  312. X    register size_t requested_length = 2 * map_unit_size ;
  313. X    register size_t mapped_length = MIN( mdp->file_size, requested_length ) ;
  314. X    size_t bytes_left ;
  315. X    register size_t bytes_in_unit ;
  316. X
  317. X#ifdef EVENTS
  318. X    EVENT( fd, EV_INITIAL_MAP ) ;
  319. X#endif
  320. X
  321. X    addr = SIO_MMAP( CHAR_NULL, mapped_length, fd, 0 ) ;
  322. X    if ( (int) addr == -1 )
  323. X        return( 0 ) ;
  324. X
  325. X    SIO_MNEED( addr, mapped_length ) ;
  326. X
  327. X    /*
  328. X     * Map as much as possible in the first unit
  329. X     */
  330. X    bytes_in_unit = MIN( mapped_length, map_unit_size ) ;
  331. X    mdp->first_unit.addr             = addr ;
  332. X    mdp->first_unit.mapped_bytes     = bytes_in_unit ;
  333. X    mdp->first_unit.valid_bytes     = bytes_in_unit ;
  334. X
  335. X    /*
  336. X     * If there is more, map it in the second unit.
  337. X     */
  338. X    bytes_left = mapped_length - bytes_in_unit ;
  339. X    if ( bytes_left > 0 )
  340. X    {
  341. X        mdp->second_unit.addr             = addr + bytes_in_unit ;
  342. X        mdp->second_unit.mapped_bytes = bytes_left ;
  343. X        mdp->second_unit.valid_bytes     = bytes_left ;
  344. X    }
  345. X    else
  346. X        mdp->second_unit.addr             = CHAR_NULL ;
  347. X
  348. X    mdp->file_offset = mapped_length ;
  349. X
  350. X    return( mdp->first_unit.valid_bytes ) ;
  351. X}
  352. X
  353. X
  354. X/*
  355. X * ALGORITHM:
  356. X *
  357. X *        if ( there are more bytes in the file )
  358. X *        {
  359. X *            map them at the given unit
  360. X *            update offset
  361. X *            issue SIO_MNEED()
  362. X *        }
  363. X *        else
  364. X *            unmap the unit
  365. X */
  366. XPRIVATE status_e map_unit( mdp, fd, mup )
  367. X    register mapd_s *mdp ;
  368. X    int fd ;
  369. X    register struct map_unit *mup ;
  370. X{
  371. X    register size_t bytes_left = mdp->file_size - mdp->file_offset ;
  372. X    register size_t bytes_to_map = MIN( bytes_left, map_unit_size ) ;
  373. X
  374. X#ifdef EVENTS
  375. X    EVENT( fd, EV_MAP_UNIT ) ;
  376. X#endif
  377. X
  378. X    if ( bytes_to_map > 0 )
  379. X    {
  380. X        if ( (int) SIO_MMAP( mup->addr, bytes_to_map,
  381. X                                                            fd, mdp->file_offset ) == -1 )
  382. X            return( FAILURE ) ;            /* XXX: need to do more ? */
  383. X        
  384. X        mup->valid_bytes = bytes_to_map ;
  385. X        ASSERT( mup->valid_bytes <= mup->mapped_bytes ) ;
  386. X        mdp->file_offset += bytes_to_map ;
  387. X        SIO_MNEED( mup->addr, mup->valid_bytes ) ;
  388. X    }
  389. X    else
  390. X    {
  391. X        (void) SIO_MUNMAP( mup->addr, mup->mapped_bytes ) ;
  392. X        mup->addr = CHAR_NULL ;
  393. X    }
  394. X    return( SUCCESS ) ;
  395. X}
  396. X
  397. X#else
  398. X
  399. X#define try_memory_mapping( x, y, z )                FAILURE
  400. X
  401. X#endif /* HAS_MMAP */
  402. X
  403. X
  404. XPRIVATE status_e setup_read_buffer( idp, buf_size )
  405. X    register __sio_id_t *idp ;
  406. X    unsigned buf_size ;
  407. X{
  408. X    register char *buf ;
  409. X
  410. X    /*
  411. X     * First allocate space for 2 buffers: primary and auxiliary
  412. X     */
  413. X    buf = malloc( buf_size * 2 ) ;
  414. X    if ( buf == NULL )
  415. X        return( FAILURE ) ;
  416. X
  417. X    /*
  418. X     * The descriptor buf field should point to the start of the main buffer
  419. X     */
  420. X    idp->buf = buf + buf_size ;
  421. X    idp->buffer_size = buf_size ;
  422. X    return( SUCCESS ) ;
  423. X}
  424. X
  425. X
  426. XPRIVATE status_e init_input_stream( idp, fd, stp )
  427. X    register __sio_id_t *idp ;
  428. X    int fd ;
  429. X    struct stat *stp ;
  430. X{
  431. X#ifdef EVENTS
  432. X    EVENT( fd, EV_INIT_INPUT_STREAM ) ;
  433. X#endif
  434. X
  435. X    /*
  436. X     * First initialize the fields relevant to buffering: buf, buffer_size
  437. X     */
  438. X    if ( try_memory_mapping( fd, idp, stp ) == FAILURE )
  439. X    {
  440. X        /*
  441. X         * Try to use normal buffering
  442. X         */
  443. X        unsigned buf_size = (unsigned)
  444. X                            ( stp->st_blksize ? stp->st_blksize : SIO_BUFFER_SIZE ) ;
  445. X        
  446. X        if ( setup_read_buffer( idp, buf_size ) == FAILURE )
  447. X            return( FAILURE ) ;
  448. X    }
  449. X
  450. X     /*
  451. X     * Initialize remaining descriptor fields
  452. X     */
  453. X    idp->max_line_length = 2 * idp->buffer_size - 1 ;
  454. X    idp->start = idp->end = idp->nextb = idp->buf ;
  455. X    idp->tied_fd = SIO_NO_TIED_FD ;
  456. X
  457. X    return( SUCCESS ) ;
  458. X}
  459. X
  460. X
  461. XPRIVATE status_e init_output_stream( odp, fd, stp )
  462. X    register __sio_od_t *odp ;
  463. X    int fd ;
  464. X    struct stat *stp ;
  465. X{
  466. X    register unsigned buf_size ;
  467. X    register char *buf ;
  468. X
  469. X#ifdef EVENTS
  470. X    EVENT( fd, EV_INIT_OUTPUT_STREAM ) ;
  471. X#endif
  472. X
  473. X    buf_size = (unsigned)
  474. X                        ( stp->st_blksize ? stp->st_blksize : SIO_BUFFER_SIZE ) ;
  475. X    buf = malloc( buf_size ) ;
  476. X    if ( buf == NULL )
  477. X        return( FAILURE ) ;
  478. X    
  479. X    /*
  480. X     * Initialize buffering fields
  481. X     */
  482. X    odp->buf = buf ;
  483. X    odp->buffer_size = buf_size ;
  484. X    odp->buf_end = odp->buf + buf_size ;
  485. X
  486. X    /*
  487. X     * Initialize remaining fields
  488. X     */
  489. X    odp->start = odp->nextb = odp->buf ;
  490. X    if ( isatty( fd ) )
  491. X        odp->buftype = SIO_LINEBUF ;
  492. X
  493. X    if ( fd == 2 )
  494. X        odp->buftype = SIO_NOBUF ;
  495. X
  496. X    return( SUCCESS ) ;
  497. X}
  498. X
  499. X
  500. X#ifndef HAS_ISATTY
  501. X
  502. X#ifdef HAS_SYSVTTY
  503. X
  504. X#include <termio.h>
  505. X
  506. XPRIVATE int isatty( fd )
  507. X    int fd ;
  508. X{
  509. X    struct termio t ;
  510. X
  511. X    if ( ioctl( fd, TCGETA, &t ) == -1 && errno == ENOTTY )
  512. X        return( FALSE ) ;
  513. X    else
  514. X        return( TRUE ) ;
  515. X}
  516. X#endif    /* HAS_SYSVTTY */
  517. X
  518. X#ifdef HAS_BSDTTY
  519. X
  520. X#include <sgtty.h>
  521. X
  522. XPRIVATE int isatty( fd )
  523. X    int fd ;
  524. X{
  525. X    struct sgttyb s ;
  526. X
  527. X    if ( ioctl( fd, TIOCGETP, &s ) == -1 && errno == ENOTTY )
  528. X        return( FALSE ) ;
  529. X    else
  530. X        return( TRUE ) ;
  531. X}
  532. X#endif    /* HAS_BSDTTY */
  533. X
  534. X#endif    /* ! HAS_ISATTY */
  535. X
  536. X
  537. X/*
  538. X * Initialize stream I/O for a file descriptor.
  539. X *
  540. X * Arguments:
  541. X *        fd:                file descriptor
  542. X *        dp:                descriptor pointer
  543. X *        stream_type:     either __SIO_INPUT_STREAM or __SIO_OUTPUT_STREAM
  544. X *
  545. X * Returns
  546. X *        0             if successful
  547. X *      SIO_ERR    if the file descriptor is not valid (sets errno)
  548. X *   exits        if stream_type is not __SIO_INPUT_STREAM or __SIO_OUTPUT_STREAM
  549. X */
  550. Xint __sio_init( dp, fd, stream_type )
  551. X    register __sio_descriptor_t *dp ;
  552. X    int fd ;
  553. X    enum __sio_stream stream_type ;
  554. X{
  555. X    struct stat st ;
  556. X    void terminate() ;
  557. X
  558. X#ifdef EVENTS
  559. X    EVENT( fd, EV_SIO_INIT ) ;
  560. X#endif
  561. X
  562. X    if ( fstat( fd, &st ) == -1 )
  563. X        return( SIO_ERR ) ;
  564. X
  565. X    switch ( stream_type )
  566. X    {
  567. X        case __SIO_INPUT_STREAM:
  568. X            if ( init_input_stream( IDP( dp ), fd, &st ) == FAILURE )
  569. X                return( SIO_ERR ) ;
  570. X            break ;
  571. X
  572. X        case __SIO_OUTPUT_STREAM:
  573. X            if ( init_output_stream( ODP( dp ), fd, &st ) == FAILURE )
  574. X                return( SIO_ERR ) ;
  575. X            break ;
  576. X            
  577. X        default:
  578. X            terminate( "SIO __sio_init: bad stream type (internal error).\n" ) ;
  579. X            /* NOTREACHED */
  580. X    }
  581. X    dp->stream_type = stream_type ;
  582. X    dp->initialized = TRUE ;
  583. X
  584. X#ifdef HAS_FINALIZATION_FUNCTION
  585. X    if ( ! finalizer_installed )
  586. X    {
  587. X        if ( ! SIO_FINALIZE( sio_cleanup ) )
  588. X        {
  589. X            char *s = "SIO __sio_init: finalizer installation failed\n" ;
  590. X
  591. X            (void) write( 2, s, strlen( s ) ) ;
  592. X        }
  593. X        else
  594. X            finalizer_installed = TRUE ;
  595. X    }
  596. X#endif /* HAS_FINALIZATION_FUNCTION */
  597. X
  598. X    return( 0 ) ;
  599. X}
  600. X
  601. X
  602. X/*
  603. X * __sio_writef writes the data in the buffer to the file descriptor.
  604. X *
  605. X * It tries to write as much data as possible until either all data
  606. X * are written or an error occurs. EINTR is the only error that is
  607. X * ignored.
  608. X * In case an error occurs but some data were written, that number
  609. X * is returned instead of SIO_ERR.
  610. X *
  611. X * Fields modified:
  612. X *        When successful: start, nextb
  613. X *        When not successful: start
  614. X *
  615. X * Return value:
  616. X *        Number of bytes written
  617. X *        SIO_ERR, if write(2) fails and no data were written
  618. X */ 
  619. Xint __sio_writef( odp, fd )
  620. X    register __sio_od_t *odp ;
  621. X    int fd ;
  622. X{
  623. X    register int b_in_buffer ;
  624. X    register int cc_total = 0 ;
  625. X
  626. X#ifdef EVENTS
  627. X    EVENT( fd, EV_SIO_WRITEF ) ;
  628. X#endif
  629. X
  630. X    /*
  631. X     * Make sure we don't exceed the buffer limits
  632. X     *    Maybe we should log this ?            XXX
  633. X     */
  634. X    if ( odp->nextb > odp->buf_end )
  635. X        odp->nextb = odp->buf_end ;
  636. X
  637. X    b_in_buffer = odp->nextb - odp->start ;
  638. X
  639. X    if ( b_in_buffer == 0 )
  640. X        return( 0 ) ;
  641. X    
  642. X    for ( ;; )
  643. X    {
  644. X        register int cc ;
  645. X
  646. X        cc = write( fd, odp->start, b_in_buffer ) ;
  647. X        if ( cc == b_in_buffer )
  648. X        {
  649. X            odp->start = odp->nextb = odp->buf ;
  650. X            cc_total += cc ;
  651. X            break ;
  652. X        }
  653. X        else if ( cc == -1 )
  654. X        {
  655. X            if ( errno == EINTR )
  656. X                continue ;
  657. X            else
  658. X                /*
  659. X                 * If some bytes were written, return that number, otherwise
  660. X                 * return SIO_ERR
  661. X                 */
  662. X                return( ( cc_total != 0 ) ? cc_total : SIO_ERR ) ;
  663. X        }
  664. X        else            /* some bytes were written */
  665. X        {
  666. X            odp->start += cc ;            /* advance start of buffer */
  667. X            b_in_buffer -= cc ;            /* decrease number bytes left in buffer */
  668. X            cc_total += cc ;                /* count the bytes that were written */
  669. X        }
  670. X    }
  671. X    return( cc_total ) ;
  672. X}
  673. X
  674. X
  675. X/*
  676. X * __sio_readf reads data from the file descriptor into the buffer.
  677. X * Unlike __sio_writef it does NOT try to read as much data as will fit
  678. X * in the buffer. It ignores EINTR.
  679. X *
  680. X * Returns: # of bytes read or SIO_ERR
  681. X *
  682. X * Fields set:
  683. X *         If it does not return SIO_ERR, it sets start, nextb, end
  684. X *            If it returns SIO_ERR, it does not change anything
  685. X */
  686. Xint __sio_readf( idp, fd )
  687. X    register __sio_id_t *idp ;
  688. X    int fd ;
  689. X{
  690. X    register int cc ;
  691. X
  692. X#ifdef EVENTS
  693. X    EVENT( fd, EV_SIO_READF ) ;
  694. X#endif
  695. X
  696. X    /*
  697. X     * First check for a tied fd and flush the stream if necessary
  698. X     *
  699. X     *         XXX    the return value of __sio_writef is not checked.
  700. X     *                    Is that right ?
  701. X     */
  702. X    if ( idp->tied_fd != SIO_NO_TIED_FD )
  703. X        (void) __sio_writef( &__SIO_OD( idp->tied_fd ), idp->tied_fd ) ;
  704. X
  705. X#ifdef HAS_MMAP
  706. X    if ( idp->memory_mapped )
  707. X    {
  708. X        register mapd_s *mdp = MDP( fd ) ;
  709. X
  710. X        /*
  711. X         * The functions initial_map and map_unit may fail.
  712. X         * In either case, we switch to buffered I/O.
  713. X         * If initial_map fails, we have read no data, so we
  714. X         * should perform a read(2).
  715. X         * If map_unit fails (for the next unit), we still have
  716. X         * the data in the current unit, so we can return.
  717. X         */
  718. X        if ( FIRST_TIME( idp ) )
  719. X        {
  720. X            cc = initial_map( mdp, fd ) ;
  721. X            if ( cc > 0 )
  722. X                idp->buf = mdp->first_unit.addr ;
  723. X            else
  724. X            {
  725. X                if ( __sio_switch( idp, fd ) == FAILURE )
  726. X                    return( SIO_ERR ) ;
  727. X                cc = -1 ;
  728. X            }
  729. X        }
  730. X        else
  731. X        {
  732. X            register struct map_unit *mu_cur, *mu_next ;
  733. X
  734. X            if ( idp->buf == mdp->first_unit.addr )
  735. X            {
  736. X                mu_cur = &mdp->first_unit ;
  737. X                mu_next = &mdp->second_unit ;
  738. X            }
  739. X            else
  740. X            {
  741. X                mu_cur = &mdp->second_unit ;
  742. X                mu_next = &mdp->first_unit ;
  743. X            }
  744. X
  745. X            if ( mu_next->addr != NULL )
  746. X            {
  747. X                idp->buf = mu_next->addr ;
  748. X                cc = mu_next->valid_bytes ;
  749. X                /*
  750. X                 * XXX:  Here we may return SIO_ERR even though there
  751. X                 *           are data in the current unit because the switch
  752. X                 *           fails (possibly because malloc failed).
  753. X                 */
  754. X                if ( map_unit( mdp, fd, mu_cur ) == FAILURE &&
  755. X                                        __sio_switch( idp, fd ) == FAILURE )
  756. X                    return( SIO_ERR ) ;
  757. X            }
  758. X            else
  759. X                cc = 0 ;
  760. X        }
  761. X        if ( cc >= 0 )
  762. X        {
  763. X            idp->end = idp->buf + cc ;
  764. X            idp->start = idp->nextb = idp->buf ;
  765. X            return( cc ) ;
  766. X        }
  767. X    }
  768. X#endif /* HAS_MMAP */
  769. X
  770. X    for ( ;; )
  771. X    {
  772. X        cc = read( fd, idp->buf, (int) idp->buffer_size ) ;
  773. X        if ( cc == -1 )
  774. X            if ( errno == EINTR )
  775. X                continue ;
  776. X            else
  777. X                return( SIO_ERR ) ;
  778. X        else
  779. X            break ;
  780. X    }
  781. X
  782. X    idp->end = idp->buf + cc ;
  783. X    idp->start = idp->nextb = idp->buf ;
  784. X    return( cc ) ;
  785. X}
  786. X
  787. X
  788. X/*
  789. X * __sio_extend_buffer is used by Srdline to extend the buffer
  790. X * If successful, it returns the number of bytes that have been read.
  791. X * If it fails (because of end-of-file or I/O error), it returns 0 or -1.
  792. X *
  793. X * Fields modified:
  794. X *     idp->start points to the start of the buffer area (which is in the
  795. X *     auxiliary buffer)
  796. X *        Also, if successful, idp->nextb is set to idp->buf, idp->end is modified.
  797. X */
  798. Xint __sio_extend_buffer( idp, fd, b_left )
  799. X    register __sio_id_t *idp ;
  800. X    int fd ;
  801. X    register int b_left ;
  802. X{
  803. X    register int b_read ;
  804. X
  805. X#ifdef EVENTS
  806. X    EVENT( fd, EV_SIO_EXTEND_BUFFER ) ;
  807. X#endif
  808. X
  809. X    /*
  810. X     * copy to auxiliary buffer
  811. X     */
  812. X    if ( b_left )
  813. X        sio_memcopy( idp->nextb, idp->buf - b_left, b_left ) ;
  814. X    b_read = __sio_readf( idp, fd ) ;
  815. X    idp->start = idp->buf - b_left ;
  816. X    return( b_read ) ;
  817. X}
  818. X
  819. X
  820. X/*
  821. X * __sio_more tries to read more data from the given file descriptor iff
  822. X * there is free space in the buffer.
  823. X * __sio_more is used only by Srdline and only AFTER __sio_extend_buffer
  824. X * has been called. This implies that 
  825. X *        a) this is not a memory mapped file
  826. X *        b) __sio_readf has been called (so we don't need to check for tied fd's
  827. X *
  828. X * Fields modified (only if successful):
  829. X *            idp->end
  830. X *
  831. X * Return value: the number of bytes read.
  832. X */
  833. Xint __sio_more( idp, fd )
  834. X    register __sio_id_t *idp ;
  835. X    int fd ;
  836. X{
  837. X    register int b_left = &idp->buf[ idp->buffer_size ] - idp->end ;
  838. X    register int cc ;
  839. X
  840. X#ifdef EVENTS
  841. X    EVENT( fd, EV_SIO_MORE ) ;
  842. X#endif
  843. X
  844. X    if ( b_left <= 0 )
  845. X        return( 0 ) ;
  846. X    
  847. X    for ( ;; )
  848. X    {
  849. X        cc = read( fd, idp->end, b_left ) ;
  850. X        if ( cc >= 0 )
  851. X        {
  852. X            idp->end += cc ;
  853. X            return( cc ) ;
  854. X        }
  855. X        else
  856. X            if ( errno == EINTR )
  857. X                continue ;
  858. X            else
  859. X                return( SIO_ERR ) ;
  860. X    }
  861. X}
  862. X
  863. X
  864. X/*
  865. X * Finalize a buffer by unmapping the file or freeing the malloc'ed memory
  866. X */
  867. Xint Sdone( fd )
  868. X    int fd ;
  869. X{
  870. X    register __sio_descriptor_t *dp = &__sio_descriptors[ fd ] ;
  871. X
  872. X#ifdef EVENTS
  873. X    EVENT( fd, EV_SDONE ) ;
  874. X#endif
  875. X
  876. X    if ( ! DESCRIPTOR_INITIALIZED( dp ) )
  877. X    {
  878. X        errno = EBADF ;
  879. X        return( SIO_ERR ) ;
  880. X    }
  881. X
  882. X    switch ( dp->stream_type )
  883. X    {
  884. X        case __SIO_INPUT_STREAM:
  885. X            {
  886. X                register __sio_id_t *idp = IDP( dp ) ;
  887. X
  888. X#ifdef HAS_MMAP
  889. X                if ( idp->memory_mapped )
  890. X                {
  891. X                    register mapd_s *mdp = MDP( fd ) ;
  892. X
  893. X                    if ( mdp->first_unit.addr != CHAR_NULL )
  894. X                        (void) SIO_MUNMAP( mdp->first_unit.addr,
  895. X                                                        mdp->first_unit.mapped_bytes ) ;
  896. X                    if ( mdp->second_unit.addr != CHAR_NULL )
  897. X                        (void) SIO_MUNMAP( mdp->second_unit.addr,
  898. X                                                        mdp->second_unit.mapped_bytes ) ;
  899. X                    idp->memory_mapped = FALSE ;
  900. X                }
  901. X                else
  902. X#endif    /* HAS_MMAP */
  903. X                    free( idp->buf - idp->buffer_size ) ;
  904. X                    idp->nextb = idp->end = NULL ;
  905. X            }
  906. X            break ;
  907. X        
  908. X        case __SIO_OUTPUT_STREAM:
  909. X            {
  910. X                register __sio_od_t *odp = ODP( dp ) ;
  911. X
  912. X                if ( Sflush( fd ) == SIO_ERR )
  913. X                    return( SIO_ERR ) ;
  914. X                free( odp->buf ) ;
  915. X                odp->nextb = odp->buf_end = NULL ;
  916. X            }
  917. X            break ;
  918. X        
  919. X        default:
  920. X            terminate( "SIO Sdone: bad stream type\n" ) ;
  921. X    }
  922. X
  923. X    dp->initialized = FALSE ;
  924. X    return( 0 ) ;
  925. X}
  926. X
  927. X
  928. XPRIVATE char *expand( area, old_size, new_size, is_static )
  929. X    char *area ;
  930. X    unsigned old_size, new_size ;
  931. X    int is_static ;
  932. X{
  933. X    char *new_area ;
  934. X
  935. X    if ( is_static )
  936. X    {
  937. X        if ( ( new_area = malloc( new_size ) ) == NULL )
  938. X            return( NULL ) ;
  939. X        sio_memcopy( area, new_area, old_size ) ;
  940. X    }
  941. X    else
  942. X        if ( ( new_area = realloc( area, new_size ) ) == NULL )
  943. X            return( NULL ) ;
  944. X    return( new_area ) ;
  945. X}
  946. X
  947. X
  948. X#include <sys/time.h>
  949. X#include <sys/resource.h>
  950. X
  951. XPRIVATE int get_fd_limit()
  952. X{
  953. X#ifdef RLIMIT_NOFILE
  954. X
  955. X    struct rlimit rl ;
  956. X
  957. X    (void) getrlimit( RLIMIT_NOFILE, &rl ) ;
  958. X    return( rl.rlim_cur ) ;
  959. X
  960. X#else
  961. X
  962. X    return( N_SIO_DESCRIPTORS ) ;
  963. X
  964. X#endif
  965. X}
  966. X
  967. X/*
  968. X * Expand the descriptor array (and if we use memory mapping the
  969. X * memory mapping descriptors). We first expand the memory mapping
  970. X * descriptors.
  971. X * There is no problem if the expansion of the SIO descriptors fails
  972. X * (i.e. there is no need to undo anything).
  973. X */
  974. Xint Smorefds()
  975. X{
  976. X    char *p ;
  977. X    int is_static ;
  978. X    unsigned new_size, old_size ;
  979. X    int n_fds = get_fd_limit() ;
  980. X
  981. X    if ( n_fds <= n_descriptors )
  982. X        return( 0 ) ;
  983. X
  984. X#ifdef EVENTS
  985. X    old_size = n_descriptors * sizeof( events_s ) ;
  986. X    new_size = n_fds * sizeof( events_s ) ;
  987. X    is_static = ( __sio_events == static___sio_events ) ;
  988. X    p = expand( (char *)__sio_events, old_size, new_size, is_static ) ;
  989. X    if ( p == NULL )
  990. X        return( SIO_ERR ) ;
  991. X    __sio_events = (events_s *) p ;
  992. X
  993. X    /*
  994. X     * Clear the codes field of the extra events structs.
  995. X     * We have to do this because a non-null codes field implies that
  996. X     * events recording is on for that fd
  997. X     */
  998. X    {
  999. X        int i ;
  1000. X
  1001. X        for ( i = n_descriptors ; i < n_fds ; i++ )
  1002. X            __sio_events[i].codes = NULL ;
  1003. X    }
  1004. X#endif    /* EVENTS */
  1005. X
  1006. X#ifdef HAS_MMAP
  1007. X    old_size = n_descriptors * sizeof( mapd_s ) ;
  1008. X    new_size = n_fds * sizeof( mapd_s ) ;
  1009. X    is_static = ( mmap_descriptors == static_mapd_array ) ;
  1010. X    p = expand( (char *)mmap_descriptors, old_size, new_size, is_static ) ;
  1011. X    if ( p == NULL )
  1012. X        return( SIO_ERR ) ;
  1013. X    mmap_descriptors = (mapd_s *) p ;
  1014. X#endif    /* HAS_MMAP */
  1015. X    
  1016. X    old_size = n_descriptors * sizeof( __sio_descriptor_t ) ;
  1017. X    new_size = n_fds * sizeof( __sio_descriptor_t ) ;
  1018. X    is_static =  ( __sio_descriptors == static_descriptor_array ) ;
  1019. X    p = expand( (char *)__sio_descriptors, old_size, new_size, is_static ) ;
  1020. X    if ( p == NULL )
  1021. X        return( SIO_ERR ) ;
  1022. X    __sio_descriptors = (__sio_descriptor_t *) p ;
  1023. X
  1024. X    n_descriptors = n_fds ;
  1025. X    return( 0 ) ;
  1026. X}
  1027. X
  1028. X
  1029. X#ifdef EVENTS
  1030. X
  1031. X/*
  1032. X * Enable recording of events for the specified file descriptor
  1033. X */
  1034. Xint __sio_enable_events( fd )
  1035. X    int fd ;
  1036. X{
  1037. X    char *p = malloc( EVENT_ENTRIES * sizeof( short ) ) ;
  1038. X
  1039. X    if ( p == NULL )
  1040. X        return( SIO_ERR ) ;
  1041. X
  1042. X    __sio_events[ fd ].codes = (short *) p ;
  1043. X    return( 0 ) ;
  1044. X}
  1045. X
  1046. X
  1047. X/*
  1048. X * Disable recording of events for the specified file descriptor
  1049. X */
  1050. Xvoid __sio_disable_events( fd )
  1051. X    int fd ;
  1052. X{
  1053. X    if ( __sio_events[ fd ].codes != NULL )
  1054. X    {
  1055. X        free( (char *) __sio_events[ fd ].codes ) ;
  1056. X        __sio_events[ fd ].codes = NULL ;
  1057. X    }
  1058. X}
  1059. X
  1060. X
  1061. X/*
  1062. X * Move stored events to buf
  1063. X */
  1064. Xint __sio_get_events( fd, buf, size )
  1065. X    int fd ;
  1066. X    char *buf ;
  1067. X    int size ;
  1068. X{
  1069. X    events_s *evp = &__sio_events[ fd ] ;
  1070. X    int bufentries ;
  1071. X    int range1, range2 ;
  1072. X    int diff ;
  1073. X    char *p ;
  1074. X    int cc ;
  1075. X    int cc_total ;
  1076. X    int move_entries ;
  1077. X
  1078. X    if ( evp->codes == NULL )
  1079. X        return( 0 ) ;
  1080. X    
  1081. X    diff = evp->next - evp->start ;
  1082. X    if ( diff == 0 )
  1083. X        return( 0 ) ;
  1084. X
  1085. X    if ( diff > 0 )
  1086. X    {
  1087. X        range1 = diff ;
  1088. X        range2 = 0 ;
  1089. X    }
  1090. X    else
  1091. X    {
  1092. X        range1 = EVENT_ENTRIES - evp->start ;
  1093. X        range2 = evp->next ;
  1094. X    }
  1095. X
  1096. X    bufentries = size / sizeof( short ) ;
  1097. X    p = buf ;
  1098. X    cc_total = 0 ;
  1099. X
  1100. X    move_entries = MIN( range1, bufentries ) ;
  1101. X    cc = move_entries * sizeof( short ) ;
  1102. X    sio_memcopy( (char *) &evp->codes[ evp->start ], p, cc ) ;
  1103. X    cc_total += cc ;
  1104. X    p += cc ;
  1105. X    bufentries -= range1 ;
  1106. X    ADD( evp->start, move_entries ) ;
  1107. X
  1108. X    if ( bufentries == 0 || range2 == 0 )
  1109. X        return( cc_total ) ;
  1110. X
  1111. X    move_entries = MIN( range2, bufentries ) ;
  1112. X    cc = move_entries * sizeof( short ) ;
  1113. X    sio_memcopy(  (char *) &evp->codes[ evp->start ], p, cc ) ;
  1114. X    cc_total += cc ;
  1115. X    ADD( evp->start, move_entries ) ;
  1116. X
  1117. X    return( cc_total ) ;
  1118. X}
  1119. X
  1120. X#endif     /* EVENTS */
  1121. X
  1122. X
  1123. X/*
  1124. X * Simple function that prints the string s at stderr and then calls
  1125. X * exit
  1126. X */
  1127. XPRIVATE void terminate( s )
  1128. X    char *s ;
  1129. X{
  1130. X    (void) write( 2, s, strlen( s ) ) ;
  1131. X    (void) abort() ;
  1132. X    exit( 1 ) ;                /* in case abort fails */
  1133. X}
  1134. X
  1135. END_OF_FILE
  1136. if test 24088 -ne `wc -c <'libs/src/sio/siosup.c'`; then
  1137.     echo shar: \"'libs/src/sio/siosup.c'\" unpacked with wrong size!
  1138. fi
  1139. # end of 'libs/src/sio/siosup.c'
  1140. fi
  1141. echo shar: End of archive 31 \(of 31\).
  1142. cp /dev/null ark31isdone
  1143. MISSING=""
  1144. 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
  1145.     if test ! -f ark${I}isdone ; then
  1146.     MISSING="${MISSING} ${I}"
  1147.     fi
  1148. done
  1149. if test "${MISSING}" = "" ; then
  1150.     echo You have unpacked all 31 archives.
  1151.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1152. else
  1153.     echo You still need to unpack the following archives:
  1154.     echo "        " ${MISSING}
  1155. fi
  1156. ##  End of shell archive.
  1157. exit 0
  1158.