Newsgroups: comp.sources.unix From: panos@cs.colorado.edu (Panos Tsirigotis) Subject: v26i257: xinetd-2.1.1 - inetd replacement with access control and logging, Part13/31 Sender: unix-sources-moderator@gw.home.vix.com Approved: vixie@gw.home.vix.com Submitted-By: panos@cs.colorado.edu (Panos Tsirigotis) Posting-Number: Volume 26, Issue 257 Archive-Name: xinetd-2.1.1/part13 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'libs/src/pq/hpq.c' <<'END_OF_FILE' X/* X * (c) Copyright 1993 by Panagiotis Tsirigotis X * All rights reserved. The file named COPYRIGHT specifies the terms X * and conditions for redistribution. X */ X Xstatic char RCSid[] = "$Id: hpq.c,v 1.3 1993/04/01 02:15:46 panos Exp $" ; Xstatic char version[] = VERSION ; X X#include "pq.h" X#include "hpqimpl.h" X X#define PRIVATE static X X#ifndef NULL X#define NULL 0 X#endif X X#define PARENT( i ) ( i >> 1 ) X#define LEFT( i ) ( i << 1 ) X#define RIGHT( i ) ( LEFT( i ) + 1 ) X Xint pq_errno ; X X#define INITIAL_ARRAY_SIZE 100 /* entries */ X X Xpq_h __hpq_create( func, flags, errnop ) X int (*func)() ; X int flags ; X int *errnop ; X{ X register header_s *hp ; X int *errp = ( errnop == NULL ) ? &pq_errno : errnop ; X char *malloc() ; X X /* X * Check if the user has provided the necessary comparison functions X */ X if ( func == NULL ) X HANDLE_ERROR( flags, NULL, errp, PQ_ENOFUNC, X "HPQ __hpq_create: missing object-object comparator\n" ) ; X X hp = HHP( malloc( sizeof( header_s ) ) ) ; X if ( hp == NULL ) X HANDLE_ERROR( flags, NULL, errp, PQ_ENOMEM, X "HPQ __hpq_create: malloc failed\n" ) ; X X /* X * Allocate object array X */ X hp->objects = (pq_obj *) malloc( INITIAL_ARRAY_SIZE * sizeof( pq_obj ) ) ; X if ( hp->objects == NULL ) X { X free( (char *)hp ) ; X HANDLE_ERROR( flags, NULL, errp, PQ_ENOMEM, X "HPQ __hpq_create: malloc failed\n" ) ; X } X X /* X * Initialize the header X */ X hp->is_better = func ; X hp->errnop = errp ; X hp->flags = flags ; X hp->max_size = INITIAL_ARRAY_SIZE ; X hp->cur_size = 0 ; X return( (pq_h) hp ) ; X} X X Xvoid __hpq_destroy( handle ) X pq_h handle ; X{ X header_s *hp = HHP( handle ) ; X X free( (char *) hp->objects ) ; X free( (char *)hp ) ; X} X X Xint __hpq_insert( handle, object ) X pq_h handle ; X pq_obj object ; X{ X register header_s *hp = HHP( handle ) ; X register unsigned i, parent ; X X if ( object == NULL ) X HANDLE_ERROR( hp->flags, PQ_ERR, hp->errnop, PQ_ENULLOBJECT, X "HPQ __hpq_insert: NULL object\n" ) ; X X /* X * Make sure there is room to store the object X */ X if ( hp->cur_size >= hp->max_size && grow( hp ) == PQ_ERR ) X return( PQ_ERR ) ; X X i = hp->cur_size++ ; X parent = PARENT( i ) ; X while ( i > 0 && (*hp->is_better)( object, hp->objects[ parent ] ) ) X { X hp->objects[ i ] = hp->objects[ parent ] ; X i = parent ; X parent = PARENT( i ) ; X } X hp->objects[ i ] = object ; X return( PQ_OK ) ; X} X X X#define CUTOFF (INITIAL_ARRAY_SIZE * 128) X#define INCREMENT CUTOFF X X/* X * Grow the table. X * Algorithm: X * while the table_size is less than CUTOFF, double the size. X * if it grows greater than CUTOFF, increase the size by INCREMENT X * (these number are in entries, not bytes) X */ XPRIVATE int grow( hp ) X header_s *hp ; X{ X unsigned new_size ; X char *new_objects ; X char *realloc() ; X X if ( hp->max_size < CUTOFF ) X new_size = hp->max_size * 2 ; X else X new_size = hp->max_size + INCREMENT ; X X new_objects = realloc( (char *)hp->objects, new_size * sizeof( pq_obj ) ) ; X if ( new_objects == NULL ) X HANDLE_ERROR( hp->flags, PQ_ERR, hp->errnop, PQ_ENOMEM, X "HPQ grow: out of memory\n" ) ; X X hp->max_size = new_size ; X hp->objects = (pq_obj *) new_objects ; X return( PQ_OK ) ; X} X X Xpq_obj __hpq_extract_head( handle ) X pq_h handle ; X{ X register header_s *hp = HHP( handle ) ; X pq_obj object ; X void restore_heap() ; X X if ( hp->cur_size == 0 ) X return( NULL ) ; X X object = hp->objects[ 0 ] ; X hp->objects[ 0 ] = hp->objects[ --hp->cur_size ] ; X restore_heap( hp, 0 ) ; X return( object ) ; X} X X X#define EXISTS( hp, i ) ( i < hp->cur_size ) X#define IS_BETTER( hp, i, j ) \ X ( (*hp->is_better)( hp->objects[ i ], hp->objects[ j ] ) ) X#define SWAP( hp, i, j ) \ X { \ X pq_obj t = hp->objects[ i ] ; \ X hp->objects[ i ] = hp->objects[ j ] ; \ X hp->objects[ j ] = t ; \ X } X XPRIVATE void restore_heap( hp, start ) X register header_s *hp ; X unsigned start ; X{ X register unsigned current = start ; X register unsigned better = current ; X X for ( ;; ) X { X register unsigned left = LEFT( current ) ; X register unsigned right = RIGHT( current ) ; X X /* X * Meaning of variables: X * X * current: the current tree node X * left: its left child X * right: its right child X * better: the best of current,left,right X * X * We start the loop with better == current X * X * The code takes advantage of the fact that the existence of X * the right child implies the existence of the left child. X * It works by finding the better of the two children (and puts X * that in better) and comparing that against current. X */ X if ( EXISTS( hp, right ) ) X better = IS_BETTER( hp, left, right ) ? left : right ; X else if ( EXISTS( hp, left ) ) X better = left ; X X if ( better == current || IS_BETTER( hp, current, better ) ) X break ; X else X { X SWAP( hp, current, better ) ; X current = better ; X } X } X} X X Xint __hpq_delete( handle, object ) X pq_h handle ; X register pq_obj object ; X{ X register header_s *hp = HHP( handle ) ; X register unsigned i ; X X if ( object == NULL ) X HANDLE_ERROR( hp->flags, PQ_ERR, hp->errnop, PQ_ENULLOBJECT, X "HPQ __hpq_delete: NULL object\n" ) ; X X /* X * First find it X */ X for ( i = 0 ;; i++ ) X { X if ( i < hp->cur_size ) X if ( object == hp->objects[ i ] ) X break ; X else X continue ; X else X HANDLE_ERROR( hp->flags, PQ_ERR, hp->errnop, PQ_ENOTFOUND, X "HPQ __hpq_delete: object not found\n" ) ; X } X X hp->objects[ i ] = hp->objects[ --hp->cur_size ] ; X restore_heap( hp, i ) ; X return( PQ_OK ) ; X} X END_OF_FILE if test 5510 -ne `wc -c <'libs/src/pq/hpq.c'`; then echo shar: \"'libs/src/pq/hpq.c'\" unpacked with wrong size! fi # end of 'libs/src/pq/hpq.c' fi if test -f 'libs/src/pset/pset.3' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'libs/src/pset/pset.3'\" else echo shar: Extracting \"'libs/src/pset/pset.3'\" \(5460 characters\) sed "s/^X//" >'libs/src/pset/pset.3' <<'END_OF_FILE' X.\"(c) Copyright 1992, 1993 by Panagiotis Tsirigotis X.\"All rights reserved. The file named COPYRIGHT specifies the terms X.\"and conditions for redistribution. X.\" X.\" $Id: pset.3,v 3.4 1993/04/23 18:16:50 panos Exp $ X.TH PSET 3X "23 April 1993" X.SH NAME Xpset_create, pset_destroy, pset_add, pset_insert, pset_remove, pset_delete, pset_remove_index, pset_clear, pset_count, pset_pointer, pset_compact, pset_sort, pset_apply - routines that handle pointer sets X.SH SYNOPSIS X.LP X.nf X.ft B X#include "pset.h" X.LP X.ft B Xpset_h pset_create( alloc_start, alloc_step ) Xunsigned alloc_start, alloc_step ; X.LP X.ft B Xvoid pset_destroy( pset ) Xpset_h pset ; X.LP X.ft B XANY_TYPE *pset_add( pset, ptr ) Xpset_h pset ; XANY_TYPE *ptr ; X.LP X.ft B Xvoid *pset_insert( pset, ptr ) Xpset_h pset ; Xvoid *ptr ; X.LP X.ft B Xvoid pset_remove( pset, ptr ) Xpset_h pset ; XANY_TYPE *ptr ; X.LP X.ft B Xvoid pset_delete( pset, ptr ) Xpset_h pset ; Xvoid *ptr ; X.LP X.ft B Xvoid pset_remove_index( pset, index ) Xpset_h pset ; Xunsigned index ; X.LP X.ft B Xvoid pset_clear( pset ) Xpset_h pset ; X.LP X.ft B Xunsigned pset_count( pset ) Xpset_h pset ; X.LP X.ft B Xvoid *pset_pointer( pset, index ) Xpset_h pset ; Xunsigned index ; X.LP X.ft B Xvoid pset_compact( pset ) Xpset_h pset ; X.LP X.ft B Xvoid pset_sort( pset, compfunc ) Xpset_h pset ; Xint (*compfunc)() ; X.LP X.ft B Xvoid pset_apply( pset, func, arg ) Xpset_h pset ; Xvoid (*func)() ; Xvoid *arg ; X.SH DESCRIPTION XThis library provides functions that handle sets of pointers. Pointers Xcan be inserted and deleted from sets and the sets can be enumerated. XPointers are inserted in sets in no particular order. However it is Xguaranteed Xthat a sequence of insertions will result in a set which if enumerated Xwill provide the pointers in the same order in which they were inserted X(assuming no intervening deletions). X.LP X.B pset_create() Xcreates a pointer set. X.I alloc_start Xdetermines the initial table size, and X.I alloc_step Xdetermines the amount by which the set size is increased in case of Xoverflow. If any of these parameters is 0, a default value is used. X.LP X.B pset_destroy() Xdestroys the specified pointer set. X.LP X.B pset_add() Xis a macro that adds a pointer to the specified set. XThe pointer can be of any type. X.LP X.B pset_insert() Xinserts a pointer to the specified set. XThis is the same operation as X.B pset_add(). X.LP X.B pset_remove() Xremoves a pointer from the specified set. X.LP X.B pset_delete() Xdeletes a pointer from the specified set. XThis is the same operation as X.B pset_remove(). X.LP X.B pset_remove_index() Xremoves the pointer that is at position X.I index Xin the set. X.I index Xshould be in the range [0, \fBpset_count(pset)\fP) (but there is no Xcheck to enforce this). XAfter this operation, the X.I index Xposition will be occupied by another pointer. X.LP X.B pset_clear() Xremoves all pointers from the specified set. X.LP X.B pset_count() Xreturns the number of pointers in the specified set. X.LP X.B pset_pointer() Xreturns the pointer at position X.I index Xin the specified set. X.I index Xmust be between 0 and X.B "pset_count(pset)." X.B pset_pointer() Xis a macro and it can also be used in the left-hand side of assignments. X.LP X.B pset_compact() Xremoves all NULL pointers from X.I pset. X.LP X.B pset_sort() Xsorts the pointers in X.I pset Xusing the specified function. X.I compfunc Xis invoked with 2 arguments that are pointers pointing to pointers stored in X.I pset. XFor example, if the pset holds pointers to objects of type T, then Xthe function F whose address is in X.I compfunc Xshould be defined as: XF( T **p1, T **p2 ). X.br X.I compfunc Xshould return a negative, zero or positive value Xif its first argument is less than, equal to, or greater than its Xsecond argument. X.LP X.B pset_apply() Xapplies X.I func Xto all pointers in X.I pset. XIf X.I arg Xis not X.SM NULL Xthe function is invoked as: X.RS X(*func)( arg, p ) X.RE Xwhere X.I p Xis a pset pointer. If X.I arg Xis X.SM NULL Xthe function is invoked as: X.RS X(*func)( p ) X.RE X.SH EXAMPLE XThe following code fragment reads lines from standard input Xand places them in a pset. Then it sorts the pset, prints the Xsorted contents to standard output and then it eliminates duplicate Xlines (which it also prints to standard output). X.RS X.sp 1 X.ft B X.nf Xpset_h ph ; Xchar buf[ 80 ] ; Xunsigned u ; Xint compstr() ; Xvoid printstr() ; X.sp 1 Xph = pset_create( 0, 0 ) ; Xwhile ( gets( buf ) ) X.RS Xpset_add( strcpy( malloc( strlen( buf ) + 1 ), buf ) ) ; X.RE Xpset_sort( ph, compstr ) ; Xfor ( u = 0 ; u < pset_count( ph ) ; u++ ) X.RS Xprintf( "%s\\n", (char *) pset_pointer( ph, u ) ) ; X.RE X.RE X.fi X.ft R X.LP XThe function X.I compstr() Xfollows: X.sp 1 X.RS X.ft B X.nf Xint compstr( p1, p2 ) X.RS Xchar **p1, **p2 ; X.RE X{ X.RS Xreturn( strcmp( *p1, *p2 ) ) ; X.RE X} X.RE X.SH "RETURN VALUES" X.LP X.I pset_h Xis a pointer type. Functions that return X.I pset_h Xwill return X.SM NULL Xto indicate an error. X.LP X.B pset_create() Xreturns a pointer set handle or X.SM NULL Xif it fails. X.LP X.B pset_add() Xreturns its second argument if successful or X.SM NULL Xif it fails. X.LP X.B pset_insert() Xreturns its second argument if successful or X.SM NULL Xif it fails. X.LP X.B pset_count() Xalways returns the number of pointers in the set. X.LP X.B pset_pointer() Xalways returns a pointer. There is no check if the specified index is within Xrange. X.SH BUGS X.LP X.B pset_add(), X.B pset_remove(), X.B pset_remove_index(), X.B pset_count(), X.B pset_clear(), X.B pset_pointer() Xand X.B pset_sort() Xare macros, therefore the \fI&\fR operator cannot be applied to them. END_OF_FILE if test 5460 -ne `wc -c <'libs/src/pset/pset.3'`; then echo shar: \"'libs/src/pset/pset.3'\" unpacked with wrong size! fi # end of 'libs/src/pset/pset.3' fi if test -f 'libs/src/sio/impl.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'libs/src/sio/impl.h'\" else echo shar: Extracting \"'libs/src/sio/impl.h'\" \(5528 characters\) sed "s/^X//" >'libs/src/sio/impl.h' <<'END_OF_FILE' X/* X * (c) Copyright 1992, 1993 by Panagiotis Tsirigotis X * All rights reserved. The file named COPYRIGHT specifies the terms X * and conditions for redistribution. X */ X X/* X * $Id: impl.h,v 8.1 1993/03/13 01:15:06 panos Exp $ X */ X X#ifndef SIO_BUFFER_SIZE X X#include "sioconf.h" X X#ifdef HAS_MMAP X#include X X X/* X * A struct map_unit describes a memory mapped area of a file. X * X * addr is the address where the file is mapped. If addr is NULL X * the other fields are meaningless. X * valid_bytes indicates how many bytes are _valid_ in that unit X * mapped_bytes of a unit is how many bytes are mapped in that X * unit ( valid <= mapped ). X * Normally mapped_bytes will be equal to valid_bytes until X * we reach the end of the file. Then if the file size is not a multiple X * of the unit size, only the rest of the file will be mapped at the X * unit, leaving part of what was mapped at the unit before still X * visible (this happens because I chose not to unmap a unit before X * remapping it). In that case valid_bytes shows the size of the "new" X * mapping and mapped_bytes shows how many bytes are really mapped. X * mapped_bytes is used in Sdone() to unmap the units. X */ Xstruct map_unit X{ X caddr_t addr ; X size_t valid_bytes ; X size_t mapped_bytes ; X} ; X X X/* X * Meaning of fields used when memory mapping: X * X * file_offset: it is the offset in the file where the next X * mapping should be done X * X * file_size: size of the file (obtained from stat(2)) X */ Xstruct mmap_descriptor X{ X off_t file_offset ; X off_t file_size ; X struct map_unit first_unit ; X struct map_unit second_unit ; X} ; X Xtypedef struct mmap_descriptor mapd_s ; X X#endif /* HAS_MMAP */ X Xtypedef enum { FAILURE, SUCCESS } status_e ; X X/* X * Descriptor management: convert a descriptor pointer to an input or X * output descriptor pointer X */ X#define IDP( dp ) (&(dp)->descriptor.input_descriptor) X#define ODP( dp ) (&(dp)->descriptor.output_descriptor) X X#define DESCRIPTOR_INITIALIZED( dp ) ((dp)->initialized) X X/* X * Internal constants X */ X#define SIO_BUFFER_SIZE 8192 X#define SIO_NO_TIED_FD (-1) X Xtypedef enum { NO = 0, YES = 1 } boolean_e ; X X#ifndef FALSE X#define FALSE 0 X#define TRUE 1 X#endif X X#ifndef NULL X#define NULL 0 X#endif X X#ifdef MIN X#undef MIN X#endif X#define MIN( a, b ) ( (a) < (b) ? (a) : (b) ) X X#define NUL '\0' X X#define PRIVATE static X X#ifdef DEBUG X Xstatic char *itoa( num ) X unsigned num ; X{ X#define NUMBUF_SIZE 15 X static char numbuf[ NUMBUF_SIZE ] ; X register char *p = &numbuf[ NUMBUF_SIZE ] ; X X *--p = '\0' ; X do X { X *--p = num % 10 + '0' ; X num /= 10 ; X } X while ( num ) ; X return( p ) ; X} X X# define ASSERT( expr ) \ X if ( ! (expr) ) \ X { \ X char *s1 = "SIO assertion << expr >> failed: File: " ; \ X char *s2 = __FILE__ ; \ X char *s3 = ", line: " ; \ X char *s4 = itoa( __LINE__ ) ; \ X char *s5 = "\n" ; \ X (void) write( 2, s1, strlen( s1 ) ) ; \ X (void) write( 2, s2, strlen( s2 ) ) ; \ X (void) write( 2, s3, strlen( s3 ) ) ; \ X (void) write( 2, s4, strlen( s4 ) ) ; \ X (void) write( 2, s5, strlen( s5 ) ) ; \ X exit ( 1 ) ; \ X } X#else X# define ASSERT( expr ) X#endif X X X#include Xextern int errno ; X X/* X * IO_SETUP initializes a descriptor if it is not already initialized. X * It checks if the stream is of the right type (input or output). X * CONTROL_SETUP checks if the descriptor is initialized and if the X * stream is of the right type (input or output). X * X * fd: file descriptor X * dp: descriptor pointer X * op: operation X * ev: error value (if __sio_init fails; __sio_init should set errno) X * X * IO_SETUP will call __sio_init if the descriptor is not initialized. X * Possible errors: X * 1. Using CONTROL_SETUP on an uninitialized descriptor. X * 2. The operation is not appropriate for the descriptor (e.g. X * a read operation on an descriptor used for writing). X * Both errors set errno to EBADF. X */ X#define CONTROL_SETUP( dp, type, ev ) \ X { \ X if ( ! DESCRIPTOR_INITIALIZED( dp ) || dp->stream_type != type ) \ X { \ X errno = EBADF ; \ X return( ev ) ; \ X } \ X } X X X#define IO_SETUP( fd, dp, type, ev ) \ X { \ X if ( DESCRIPTOR_INITIALIZED( dp ) ) \ X { \ X if ( dp->stream_type != type ) \ X { \ X errno = EBADF ; \ X return( ev ) ; \ X } \ X } \ X else if ( __sio_init( dp, fd, type ) == SIO_ERR ) \ X return( ev ) ; \ X } X X X/* X * Internal functions that are visible X */ Xint __sio_readf(), __sio_writef(), __sio_pwritef() ; Xint __sio_extend_buffer(), __sio_init(), __sio_converter(), __sio_more() ; Xstatus_e __sio_switch() ; X X X#ifdef HAS_MEMOPS X#include X#define sio_memcopy( from, to, nbytes ) (void) memcpy( to, from, nbytes ) X#define sio_memscan( from, nbytes, ch ) memchr( from, ch, nbytes ) X#endif X X#ifdef HAS_BCOPY X#define sio_memcopy( from, to, nbytes ) (void) bcopy( from, to, nbytes ) X#endif X X#ifndef sio_memcopy X#define sio_memcopy __sio_memcopy X#define NEED_MEMCOPY Xvoid __sio_memcopy() ; X#endif X X#ifndef sio_memscan Xchar *sio_memscan() ; X#endif X X#endif /* SIO_BUFFER_SIZE */ X END_OF_FILE if test 5528 -ne `wc -c <'libs/src/sio/impl.h'`; then echo shar: \"'libs/src/sio/impl.h'\" unpacked with wrong size! fi # end of 'libs/src/sio/impl.h' fi if test -f 'xinetd/intcommon.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xinetd/intcommon.c'\" else echo shar: Extracting \"'xinetd/intcommon.c'\" \(5511 characters\) sed "s/^X//" >'xinetd/intcommon.c' <<'END_OF_FILE' X/* X * (c) Copyright 1992 by Panagiotis Tsirigotis X * All rights reserved. The file named COPYRIGHT specifies the terms X * and conditions for redistribution. X */ X Xstatic char RCSid[] = "$Id: intcommon.c,v 6.6 1993/06/06 00:14:25 panos Exp $" ; X X#include X#include X#include X#include X#include X#include X Xvoid exit() ; X X#include "int.h" X#include "defs.h" X#include "service.h" X#include "server.h" X#include "config.h" X#include "state.h" X Xvoid msg() ; X X Xvoid int_fail( ip, syscall ) X struct intercept *ip ; X char *syscall ; X{ X msg( LOG_ERR, "fail", "%s failed: %m", syscall ) ; X (*ip->int_ops->exit)() ; X /* NOTREACHED */ X} X X X/* X * Returns either a positive number or -1 X */ Xint int_select( max, read_mask ) X int max ; X fd_set *read_mask ; X{ X char *func = "int_select" ; X X for ( ;; ) X { X int n_ready ; X X n_ready = select( max+1, read_mask, X FD_SET_NULL, FD_SET_NULL, TIMEVAL_NULL ) ; X if ( n_ready > 0 ) X return( n_ready ) ; X else if ( n_ready == -1 ) X if ( errno == EINTR ) X continue ; X else X { X msg( LOG_ERR, func, "select: %m" ) ; X return( -1 ) ; X } X } X} X X Xvoid int_exit( ip ) X struct intercept *ip ; X{ X int status = SERVER_EXITSTATUS( INT_SERVER( ip ) ) ; X char *func = "int_exit" ; X char *sig_name() ; X X if ( debug.on ) X { X if ( PROC_EXITED( status ) ) X msg( LOG_DEBUG, func, "intercepted server died" ) ; X else if ( PROC_SIGNALED( status ) ) X msg( LOG_DEBUG, func, "intercepted server received signal %s", X sig_name( (int) PROC_TERMSIG( status ) ) ) ; X } X _exit( (int) PROC_EXITSTATUS( status ) ) ; X} X X X/* X * The ops vector must be installed before invoking this function X */ Xvoid int_init( ip, serp ) X struct intercept *ip ; X struct server *serp ; X{ X register unsigned u ; X char *func = "int_init" ; X void int_sighandler() ; X X /* X * Sanity test X */ X if ( SERVER_SERVICE( serp ) != SERVER_CONNSERVICE( serp ) ) X { X msg( LOG_ERR, "server service (%s) != connection service (%s)", X SVC_ID( SERVER_SERVICE( serp ) ), X SVC_ID( SERVER_CONNSERVICE( serp ) ) ) ; X exit( 1 ) ; X } X X /* X * Close all unneeded descriptors X */ X for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ ) X { X struct service *sp = SP( pset_pointer( SERVICES( ps ), u ) ) ; X X if ( sp == SERVER_SERVICE( serp ) ) X continue ; X if ( log_get_type( SC_LOG( SVC_CONF( sp ) ) ) == L_FILE ) X xlog_destroy( sp->svc_log ) ; X (void) close( SVC_FD( sp ) ) ; X } X X /* X * Setup signal handling X */ X if ( (int) signal( SERVER_EXIT_SIG, int_sighandler ) == -1 ) X int_fail( ip, "signal" ) ; X if ( (int) signal( INTERCEPT_SIG, int_sighandler ) == -1 ) X int_fail( ip, "signal" ) ; X if ( (int) signal( SIGTERM, int_sighandler ) == -1 ) X int_fail( ip, "signal" ) ; X X /* X * Initialize state X */ X INTERCEPT( ip ) = TRUE ; X *INT_SERVER( ip ) = *serp ; X INT_REMOTE( ip ) = SERVER_FD( serp ) ; X X INT_CONNECTIONS( ip ) = pset_create( 0, 0 ) ; X if ( INT_CONNECTIONS( ip ) == NULL ) X { X msg( LOG_ERR, func, ES_NOMEM ) ; X (*ip->int_ops->exit)() ; X } X} X X X X/* X * Make a new connection to the local server X */ Xchannel_s *int_newconn( ip, sinp, remote_socket ) X struct intercept *ip ; X struct sockaddr_in *sinp ; X int remote_socket ; X{ X struct service *sp = SERVER_SERVICE( INT_SERVER( ip ) ) ; X int socket_type = SVC_SOCKET_TYPE( sp ) ; X struct sockaddr_in *local = INT_LOCALADDR( ip ) ; X char *sid = SVC_ID( sp ) ; X channel_s *chp ; X int sd ; X char *func = "int_newconn" ; X X /* X * Get a socket and connect it to the local address X * X * XXX: should we use SC_PROTOVAL to explicitly specify the protocol ? X */ X if ( ( sd = socket( AF_INET, socket_type, 0 ) ) == -1 ) X { X msg( LOG_ERR, func,"(intercepting %s) socket creation failed: %m", sid ) ; X return( CHANNEL_NULL ) ; X } X X if ( connect( sd, SA( local ), sizeof( *local ) ) == -1 ) X { X msg( LOG_ERR, func, "(intercepting %s) connect failed: %m", sid ) ; X (void) close( sd ) ; X return( CHANNEL_NULL ) ; X } X X chp = NEW_CHANNEL() ; X if ( chp == CHANNEL_NULL ) X { X msg( LOG_ERR, func, ES_NOMEM ) ; X (void) close( sd ) ; X return( CHANNEL_NULL ) ; X } X X if ( pset_add( INT_CONNECTIONS( ip ), chp ) == NULL ) X { X msg( LOG_ERR, func, ES_NOMEM ) ; X FREE_CHANNEL( chp ) ; X (void) close( sd ) ; X return( CHANNEL_NULL ) ; X } X X chp->ch_state = GOOD_CHANNEL ; X chp->ch_from = *sinp ; X chp->ch_local_socket = sd ; X chp->ch_remote_socket = remote_socket ; X return( chp ) ; X} X X X X/* X * Check if the (address,port) in sinp is already in the connection table. X * Return value: X * a connection pointer if the address is found X * NULL if the address if not found X * X * *addr_checked is set to TRUE of FALSE depending on whether there X * is already a connection from the same IP address in the table. X */ Xchannel_s *int_lookupconn( ip, sinp, addr_checked ) X struct intercept *ip ; X struct sockaddr_in *sinp ; X bool_int *addr_checked ; X{ X register unsigned u ; X register pset_h conntab = INT_CONNECTIONS( ip ) ; X X *addr_checked = FALSE ; X X for ( u = 0 ; u < pset_count( conntab ) ; u++ ) X { X register channel_s *chp = CHP( pset_pointer( conntab, u ) ) ; X X if ( chp->ch_from.sin_addr.s_addr == sinp->sin_addr.s_addr ) X { X *addr_checked = TRUE ; X if ( chp->ch_from.sin_port == sinp->sin_port ) X return( chp ) ; X } X } X return( CHANNEL_NULL ) ; X} X END_OF_FILE if test 5511 -ne `wc -c <'xinetd/intcommon.c'`; then echo shar: \"'xinetd/intcommon.c'\" unpacked with wrong size! fi # end of 'xinetd/intcommon.c' fi if test -f 'xinetd/service.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xinetd/service.h'\" else echo shar: Extracting \"'xinetd/service.h'\" \(5412 characters\) sed "s/^X//" >'xinetd/service.h' <<'END_OF_FILE' X/* X * (c) Copyright 1992 by Panagiotis Tsirigotis X * All rights reserved. The file named COPYRIGHT specifies the terms X * and conditions for redistribution. X */ X X#ifndef SERVICE_H X#define SERVICE_H X X#include X#include X X/* X * $Id: service.h,v 6.4 1993/06/06 00:12:45 panos Exp $ X */ X X#include "xlog.h" X X#include "defs.h" X#include "sconf.h" X X X/* X * NOTE: A service can be disabled but not deleted if it has any servers X * running X */ Xtypedef enum /* service states */ X { X SVC_NOT_STARTED = 0, /* no attempt to start it yet */ X SVC_ACTIVE, /* service is available */ X SVC_SUSPENDED, /* service is suspended */ X SVC_DISABLED /* service disabled */ X } state_e ; X X X/* X * NOTE: Clearing the structure will give all its fields their default values X */ Xstruct service X{ X state_e svc_state ; X X int svc_ref_count ; /* number of pointers to this struct */ X X struct service_config *svc_conf ; /* service configuration */ X X int svc_fd ; X X unsigned svc_running_servers ; X unsigned svc_retry_servers ; X X unsigned svc_attempts ; /* # of attempts to start a server */ X time_t svc_start_time ; /* since this time */ X X /* X * svc_shutdown: invoked to playback the protocol and get information X * from the other end. It also sets up the connection X * for an orderly close. X * svc_handler: invoked to handle new requests X */ X voidfunc svc_shutdown_func ; /* ARGS: int sd, char **msgp */ X statfunc svc_handler_func ; /* ARGS: service *, connection * */ X X /* X * These fields are used for access control; they either point to the X * service access control lists or to the default access control lists X */ X pset_h svc_no_access ; X pset_h svc_only_from ; X X /* X * These fields are used to avoid generating too many messages when X * receiving datagrams from a bad address. X */ X struct sockaddr_in svc_last_dgram_addr ; X time_t svc_last_dgram_time ; X X xlog_h svc_log ; X} ; X X#define SP( p ) ( (struct service *) (p) ) X X/* X * Field access macros X */ X#define SVC_CONF( sp ) ( (sp)->svc_conf ) X#define SVC_FD( sp ) ( (sp)->svc_fd ) X#define SVC_RUNNING_SERVERS( sp ) (sp)->svc_running_servers X#define SVC_RETRIES( sp ) (sp)->svc_retry_servers X#define SVC_LOG( sp ) (sp)->svc_log X#define SVC_REFCOUNT( sp ) (sp)->svc_ref_count X#define SVC_ID( sp ) SC_ID( SVC_CONF( sp ) ) X#define SVC_SOCKET_TYPE( sp ) SC_SOCKET_TYPE( SVC_CONF( sp ) ) X X#define SVC_IS_ACTIVE( sp ) ( (sp)->svc_state == SVC_ACTIVE ) X#define SVC_IS_SUSPENDED( sp ) ( (sp)->svc_state == SVC_SUSPENDED ) X#define SVC_IS_AVAILABLE( sp ) ( SVC_IS_ACTIVE(sp) || SVC_IS_SUSPENDED(sp) ) X#define SVC_IS_DISABLED( sp ) ( (sp)->svc_state == SVC_DISABLED ) X X/* X * Predicate checking macros X */ X#define SVC_LOGUSER( sp ) SC_LOGUSER( SVC_CONF( sp ) ) X#define SVC_FORKS( sp ) SC_FORKS( SVC_CONF( sp ) ) X#define SVC_RETRY( sp ) SC_RETRY( SVC_CONF( sp ) ) X#define SVC_WAITS( sp ) SC_WAITS( SVC_CONF( sp ) ) X#define SVC_IS_INTERCEPTED( sp ) SC_IS_INTERCEPTED( SVC_CONF( sp ) ) X#define SVC_ACCEPTS_CONNECTIONS( sp ) \ X SC_ACCEPTS_CONNECTIONS( SVC_CONF( sp ) ) X X#define SVC_IS_LOGGING( sp ) ( (sp)->svc_log != NULL ) X#define SVC_LOGS_ON_SUCCESS( sp ) \ X ( SVC_IS_LOGGING( sp ) && SC_LOGS_ON_SUCCESS( SVC_CONF( sp ) ) ) X#define SVC_LOGS_ON_FAILURE( sp ) \ X ( SVC_IS_LOGGING( sp ) && SC_LOGS_ON_FAILURE( SVC_CONF( sp ) ) ) X#define SVC_LOGS_ON_EXIT( sp ) \ X ( SVC_IS_LOGGING( sp ) && SC_LOGS_ON_EXIT( SVC_CONF( sp ) ) ) X#define SVC_LOGS_USERID_ON_SUCCESS( sp ) \ X ( SVC_IS_LOGGING( sp ) && SC_LOGS_USERID_ON_SUCCESS( SVC_CONF( sp ) ) ) X#define SVC_LOGS_USERID_ON_FAILURE( sp ) \ X ( SVC_IS_LOGGING( sp ) && SC_LOGS_USERID_ON_FAILURE( SVC_CONF( sp ) ) ) X#define SVC_RECORDS( sp ) \ X ( SVC_IS_LOGGING( sp ) && SC_RECORDS( SVC_CONF( sp ) ) ) X X/* X * Reference counting macros X */ X#define SVC_HOLD( sp ) (sp)->svc_ref_count++ X#define SVC_RELE( sp ) \ X ( ( (sp)->svc_ref_count <= 1 ) ? svc_release( sp ) : --(sp)->svc_ref_count ) X X X#define svc_handle( sp, cp ) (*(sp)->svc_handler_func)( sp, cp ) X#define svc_internal( sp, serp ) sc_internal( SVC_CONF( sp ), serp ) X#define svc_make_external( sp ) sc_make_external( SVC_CONF( sp ) ) X X#define svc_dec_running_servers( sp ) \ X { \ X if ( SVC_RUNNING_SERVERS( sp ) > 0 ) \ X (sp)->svc_running_servers-- ; \ X else \ X msg( LOG_ERR, func, \ X "Service %s: server exit with 0 running servers", SVC_ID( sp ) ) ;\ X } X X#define svc_inc_running_servers( sp ) (sp)->svc_running_servers++ X X#define svc_inc_retries( sp ) (sp)->svc_retry_servers++ X#define svc_dec_retries( sp ) (sp)->svc_retry_servers-- X Xstatus_e svc_init() ; Xstruct service *svc_new() ; Xstruct service *svc_make_special() ; Xvoid svc_free() ; Xstatus_e svc_activate() ; Xvoid svc_setup_address_control() ; Xvoid svc_deactivate() ; Xvoid svc_suspend() ; Xvoid svc_resume() ; Xint svc_release() ; Xvoid svc_dump() ; Xvoid svc_request() ; Xstatus_e svc_access_control() ; Xvoid svc_shutdown() ; Xvoid svc_log_success() ; Xvoid svc_log_failure() ; Xvoid svc_log_exit() ; Xvoid svc_logprint() ; Xvoid svc_postmortem() ; X X#endif /* SERVICE_H */ END_OF_FILE if test 5412 -ne `wc -c <'xinetd/service.h'`; then echo shar: \"'xinetd/service.h'\" unpacked with wrong size! fi # end of 'xinetd/service.h' fi echo shar: End of archive 13 \(of 31\). cp /dev/null ark13isdone MISSING="" 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 if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 31 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0