home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-06-26 | 27.3 KB | 1,103 lines |
- Newsgroups: comp.sources.unix
- From: panos@cs.colorado.edu (Panos Tsirigotis)
- Subject: v26i266: xinetd-2.1.1 - inetd replacement with access control and logging, Part22/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 266
- Archive-Name: xinetd-2.1.1/part22
-
- #! /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 <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 22 (of 31)."
- # Contents: xinetd/internals.c xinetd/signals.c
- # Wrapped by panos@mystique on Mon Jun 21 14:51:26 1993
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'xinetd/internals.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'xinetd/internals.c'\"
- else
- echo shar: Extracting \"'xinetd/internals.c'\" \(12327 characters\)
- sed "s/^X//" >'xinetd/internals.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: internals.c,v 6.5 1993/06/06 00:13:50 panos Exp $" ;
- X
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <signal.h>
- X#include <time.h>
- X#include <fcntl.h>
- X#include <syslog.h>
- X
- X#include "sio.h"
- X
- X#include "config.h"
- X#include "service.h"
- X#include "server.h"
- X#include "state.h"
- X#include "flags.h"
- X
- Xextern char program_version[] ;
- X
- Xvoid msg() ;
- X
- Xtime_t time() ;
- X
- X
- XPRIVATE void dump_services( fd )
- X int fd ;
- X{
- X register unsigned u ;
- X
- X /*
- X * Dump the current configuration (services + defaults)
- X */
- X Sprint( fd, "Services + defaults:\n" ) ;
- X sc_dump( DEFAULTS( ps ), fd, 0, TRUE ) ;
- X
- X for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ )
- X svc_dump( SP( pset_pointer( SERVICES( ps ), u ) ), fd ) ;
- X}
- X
- X
- Xvoid dump_internal_state()
- X{
- X int dump_fd ;
- X char *dump_file = DUMP_FILE ;
- X time_t current_time ;
- X register int fd ;
- X register unsigned u ;
- X char *func = "dump_internal_state" ;
- X
- X dump_fd = open( dump_file, O_WRONLY + O_CREAT + O_APPEND, DUMP_FILE_MODE ) ;
- X if ( dump_fd == -1 )
- X {
- X msg( LOG_ERR, func, "failed to open %s: %m", dump_file ) ;
- X return ;
- X }
- X Sbuftype( dump_fd, SIO_LINEBUF ) ;
- X
- X /*
- X * Print the program name, version, and timestamp.
- X * Note that the program_version variable contains the program name.
- X */
- X (void) time( ¤t_time ) ;
- X Sprint( dump_fd, "INTERNAL STATE DUMP: %s\n", program_version ) ;
- X Sprint( dump_fd, "Current time: %s\n", ctime( ¤t_time ) ) ;
- X
- X dump_services( dump_fd ) ;
- X
- X /*
- X * Dump the server table
- X */
- X Sprint( dump_fd, "Server table dump:\n" ) ;
- X for ( u = 0 ; u < pset_count( SERVERS( ps ) ) ; u++ )
- X server_dump( SERP( pset_pointer( SERVERS( ps ), u ) ), dump_fd ) ;
- X Sputchar( dump_fd, '\n' ) ;
- X
- X /*
- X * Dump the retry_table
- X */
- X Sprint( dump_fd, "Retry table dump:\n" ) ;
- X for ( u = 0 ; u < pset_count( RETRIES( ps ) ) ; u++ )
- X server_dump( SERP( pset_pointer( RETRIES( ps ), u ) ), dump_fd ) ;
- X Sputchar( dump_fd, '\n' ) ;
- X
- X /*
- X * Dump the socket mask
- X */
- X Sprint( dump_fd, "Socket mask:" ) ;
- X for ( fd = 0 ; fd < ps.ros.max_descriptors ; fd++ )
- X if ( FD_ISSET( fd, &ps.rws.socket_mask ) )
- X Sprint( dump_fd, " %d", fd ) ;
- X Sputchar( dump_fd, '\n' ) ;
- X Sprint( dump_fd, "mask_max = %d\n", ps.rws.mask_max ) ;
- X
- X /*
- X * Dump the descriptors that are open and are *not* in the socket mask
- X */
- X Sprint( dump_fd, "Open descriptors (not in socket mask):" ) ;
- X for ( fd = 0 ; fd < ps.ros.max_descriptors ; fd++ )
- X {
- X struct stat st ;
- X
- X if ( FD_ISSET( fd, &ps.rws.socket_mask ) )
- X continue ;
- X if ( fstat( fd, &st ) == -1 )
- X continue ;
- X Sprint( dump_fd, " %d", fd ) ;
- X }
- X Sputchar( dump_fd, '\n' ) ;
- X Sputchar( dump_fd, '\n' ) ;
- X
- X Sprint( dump_fd, "active_services = %d\n", ps.rws.active_services ) ;
- X Sprint( dump_fd, "available_services = %d\n", ps.rws.available_services ) ;
- X Sprint( dump_fd, "descriptors_free = %d\n", ps.rws.descriptors_free ) ;
- X Sprint( dump_fd, "running_servers = %d\n", pset_count( SERVERS( ps ) ) ) ;
- X Sprint( dump_fd, "Logging service = %s\n",
- X LOG_SERVICE( ps ) != NULL ? "enabled" : "not enabled" ) ;
- X Sprint( dump_fd, "Shutdown service = %s\n",
- X SHUTDOWN_SERVICE( ps ) != NULL ? "enabled" : "not enabled" ) ;
- X Sputchar( dump_fd, '\n' ) ;
- X
- X Sprint( dump_fd, "max_descriptors = %d\n", ps.ros.max_descriptors ) ;
- X Sprint( dump_fd, "process_limit = %d\n", ps.ros.process_limit ) ;
- X Sprint( dump_fd, "config_file = %s\n", ps.ros.config_file ) ;
- X if ( debug.on )
- X Sprint( dump_fd, "debug_fd = %d\n", debug.fd ) ;
- X Sputchar( dump_fd, '\n' ) ;
- X
- X Sprint( dump_fd, "END OF DUMP\n\n" ) ;
- X Sclose( dump_fd ) ;
- X
- X msg( LOG_INFO, func, "generated state dump in file %s", dump_file ) ;
- X}
- X
- X
- X
- X/*
- X * Types of consistency checks
- X */
- Xenum check_type { PERIODIC, USER_REQUESTED } ;
- X
- X
- XPRIVATE void consistency_check( type )
- X enum check_type type ;
- X{
- X register int fd ;
- X fd_set socket_mask_copy ;
- X register unsigned u ;
- X int errors ;
- X unsigned total_running_servers = 0 ;
- X unsigned total_retry_servers = 0 ;
- X unsigned error_count = 0 ;
- X bool_int service_count_check_failed = FALSE ;
- X char *func = "consistency_check" ;
- X PRIVATE unsigned thread_check() ;
- X PRIVATE unsigned refcount_check() ;
- X PRIVATE unsigned service_count_check() ;
- X
- X socket_mask_copy = ps.rws.socket_mask ;
- X
- X for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ )
- X {
- X register struct service *sp = SP( pset_pointer( SERVICES( ps ), u ) ) ;
- X char *sid = SVC_ID( sp ) ;
- X unsigned running_servers ;
- X unsigned retry_servers ;
- X
- X error_count += refcount_check( sp, &running_servers, &retry_servers ) ;
- X
- X if ( SVC_IS_AVAILABLE( sp ) || SVC_IS_DISABLED ( sp ) )
- X {
- X /*
- X * In this case, there may be some servers running
- X */
- X if ( FD_ISSET( SVC_FD( sp ), &socket_mask_copy ) )
- X {
- X if ( SVC_IS_DISABLED( sp ) )
- X {
- X msg( LOG_ERR, func,
- X "fd of disabled service %s still in socket mask", sid ) ;
- X error_count++ ;
- X }
- X FD_CLR( SVC_FD( sp ), &socket_mask_copy ) ;
- X }
- X error_count += thread_check( sp, running_servers, retry_servers ) ;
- X
- X errors = service_count_check( sp, running_servers, retry_servers ) ;
- X if ( ! errors && ! service_count_check_failed )
- X {
- X total_retry_servers += retry_servers ;
- X total_running_servers += running_servers ;
- X }
- X if ( errors )
- X {
- X service_count_check_failed = TRUE ;
- X error_count += errors ;
- X }
- X
- X if ( SVC_IS_DISABLED( sp ) && SVC_RUNNING_SERVERS( sp ) == 0 )
- X {
- X msg( LOG_ERR, func,
- X "disabled service %s has 0 running servers\n", sid ) ;
- X error_count++ ;
- X continue ;
- X }
- X }
- X else
- X {
- X msg( LOG_ERR, func, "service %s not started", SVC_ID( sp ) ) ;
- X error_count++ ;
- X }
- X }
- X
- X if ( ! service_count_check_failed )
- X {
- X if ( total_running_servers != pset_count( SERVERS( ps ) ) )
- X {
- X msg( LOG_ERR, func,
- X "total running servers (%d) != number of running servers (%d)",
- X total_running_servers, pset_count( SERVERS( ps ) ) ) ;
- X error_count++ ;
- X }
- X if ( total_retry_servers != pset_count( RETRIES( ps ) ) )
- X {
- X msg( LOG_ERR, func,
- X "total retry servers (%d) != number of retry servers (%d)",
- X total_retry_servers, pset_count( RETRIES( ps ) ) ) ;
- X error_count++ ;
- X }
- X }
- X
- X /*
- X * Check if there are any descriptors set in socket_mask_copy
- X */
- X for ( fd = 0 ; fd < ps.ros.max_descriptors ; fd++ )
- X if ( FD_ISSET( fd, &socket_mask_copy ) )
- X {
- X msg( LOG_ERR, func,
- X "descriptor %d set in socket mask but there is no service for it",
- X fd ) ;
- X error_count++ ;
- X }
- X
- X if ( error_count > 0 )
- X msg( LOG_WARNING, func,
- X "Consistency check detected %d errors", error_count ) ;
- X else
- X if ( type == USER_REQUESTED || debug.on )
- X msg( LOG_INFO, func, "Consistency check passed" ) ;
- X}
- X
- X
- X/*
- X * Check that the counts of running and retry servers stored in struct service
- X * are accurate
- X */
- XPRIVATE unsigned service_count_check( sp, running_servers, retry_servers )
- X register struct service *sp ;
- X unsigned running_servers ;
- X unsigned retry_servers ;
- X{
- X register char *sid = SVC_ID( sp ) ;
- X int error_count = 0 ;
- X char *func = "service_count_check" ;
- X
- X if ( SVC_RUNNING_SERVERS( sp ) != running_servers )
- X {
- X msg( LOG_ERR, func,
- X "service %s: actual running servers = %d, known running servers = %d",
- X sid, running_servers, SVC_RUNNING_SERVERS( sp ) ) ;
- X error_count++ ;
- X }
- X if ( SVC_RETRIES( sp ) != retry_servers )
- X {
- X msg( LOG_ERR, func,
- X "service %s: actual retry servers = %d, known retry servers = %d",
- X sid, retry_servers, SVC_RETRIES( sp ) ) ;
- X error_count++ ;
- X }
- X
- X if ( error_count && debug.on )
- X msg( LOG_DEBUG, func, "%s: %d errors detected", sid, error_count ) ;
- X
- X return( error_count ) ;
- X}
- X
- X
- X
- X/*
- X * If the service is single-threaded:
- X * if the descriptor is set in the socket mask, there must
- X * be a server running (or to be retried)
- X * If the service is multi-threaded:
- X * the descriptor must be always set
- X */
- XPRIVATE unsigned thread_check( sp, running_servers, retry_servers )
- X register struct service *sp ;
- X unsigned running_servers ;
- X unsigned retry_servers ;
- X{
- X unsigned error_count = 0 ;
- X int sd = SVC_FD( sp ) ;
- X char *sid = SVC_ID( sp ) ;
- X char *func = "thread_check" ;
- X
- X if ( SVC_WAITS( sp ) )
- X {
- X bool_int has_servers = ( running_servers + retry_servers > 0 ) ;
- X
- X if ( has_servers && FD_ISSET( sd, &ps.rws.socket_mask ) )
- X {
- X msg( LOG_ERR, func,
- X"Active single-threaded service %s: server running, descriptor set", sid ) ;
- X error_count++ ;
- X }
- X if ( !has_servers && !FD_ISSET( sd, &ps.rws.socket_mask ) )
- X {
- X msg( LOG_ERR, func,
- X"Active single-threaded service %s: no server running, descriptor not set",
- X sid ) ;
- X error_count++ ;
- X }
- X }
- X else
- X if ( ! FD_ISSET( sd, &ps.rws.socket_mask ) )
- X {
- X msg( LOG_ERR, func,
- X "Active multi-threaded service %s: descriptor not set", sid ) ;
- X error_count++ ;
- X }
- X
- X if ( error_count && debug.on )
- X msg( LOG_DEBUG, func, "%s: %d errors detected", sid, error_count ) ;
- X
- X return( error_count ) ;
- X}
- X
- X
- X
- X/*
- X * Count the number of references to the specified service contained
- X * in the specified table of servers; put the number of servers
- X * in *countp
- X */
- XPRIVATE int count_refs( sp, servers, countp )
- X register struct service *sp ;
- X register pset_h servers ;
- X unsigned *countp ;
- X{
- X register unsigned u ;
- X register struct server *serp ;
- X int refs = 0 ;
- X unsigned count = 0 ;
- X
- X for ( u = 0 ; u < pset_count( servers ) ; u++ )
- X {
- X serp = SERP( pset_pointer( SERVERS( ps ), u ) ) ;
- X if ( SERVER_SERVICE( serp ) == sp )
- X {
- X refs++ ;
- X count++ ;
- X }
- X if ( SERVER_CONNSERVICE( serp ) == sp )
- X refs++ ;
- X /*
- X * XXX: in the future we may want to check if the given service
- X * is any of the alternative services (currently only SPECIAL
- X * services can be alternative services and SPECIAL services
- X * are not included in the service table)
- X */
- X }
- X *countp = count ;
- X return( refs ) ;
- X}
- X
- X
- X/*
- X * Check for reference counting errors.
- X * Returns number of errors found.
- X * Always set the number of running and retry servers.
- X */
- XPRIVATE unsigned refcount_check( sp, running_servers, retry_servers )
- X struct service *sp ;
- X unsigned *running_servers ;
- X unsigned *retry_servers ;
- X{
- X char *sid = SVC_ID( sp ) ;
- X unsigned errors = 0 ;
- X int refs ;
- X int refcount = SVC_REFCOUNT( sp ) ;
- X char *func = "refcount_check" ;
- X
- X if ( ! refcount > 0 )
- X {
- X msg( LOG_ERR, func, "%s service has bad refcount: %d\n",
- X sid, refcount ) ;
- X errors++ ;
- X }
- X
- X /*
- X * The service table holds a reference to the service. The remaining
- X * references must be from servers and connections.
- X */
- X refcount-- ;
- X
- X refs = count_refs( sp, SERVERS( ps ), running_servers ) ;
- X if ( ! errors && refs > refcount )
- X {
- X msg( LOG_ERR, func,
- X "running servers: too many references for %s (%d with max=%d)",
- X sid, refs, refcount ) ;
- X errors++ ;
- X }
- X
- X refs = count_refs( sp, RETRIES( ps ), retry_servers ) ;
- X if ( ! errors && refs > refcount )
- X {
- X msg( LOG_ERR, func,
- X "retry servers: too many references for %s (%d with max=%d)",
- X sid, refs, refcount ) ;
- X errors++ ;
- X }
- X
- X if ( errors && debug.on )
- X msg( LOG_DEBUG, func, "%s: %d errors detected", sid, errors ) ;
- X
- X return( errors ) ;
- X}
- X
- X
- Xvoid user_requested_check()
- X{
- X consistency_check( USER_REQUESTED ) ;
- X}
- X
- X
- Xvoid periodic_check()
- X{
- X consistency_check( PERIODIC ) ;
- X}
- X
- X
- X#ifndef NO_TIMERS
- X
- X#include <sys/time.h>
- X
- X#include "timer.h"
- X
- Xstatic timer_h cc_timer ; /* consistency check timer */
- X
- Xstatus_e create_cc_timer()
- X{
- X cc_timer = timer_create( TIMER_REAL, TIMER_RETURN_ERROR, INT_NULL ) ;
- X return( cc_timer ? OK : FAILED ) ;
- X}
- X
- X
- XPRIVATE void cc_timer_action( tp, arg )
- X timer_h tp ;
- X void *arg ;
- X{
- X#ifdef lint
- X tp = tp ;
- X arg = arg ;
- X#endif
- X M_SET( ps.flags, PERIODIC_CHECK_FLAG ) ;
- X}
- X
- X
- Xvoid enable_periodic_check( interval )
- X unsigned interval ;
- X{
- X struct itimerval itv ;
- X struct timer_action ta ;
- X char *func = "enable_periodic_check" ;
- X
- X itv.it_value.tv_sec = itv.it_interval.tv_sec = interval ;
- X itv.it_value.tv_usec = itv.it_interval.tv_usec = 0 ;
- X ta.ta_flags = debug.on ? TIMER_BLOCK_SAME : TIMER_NOFLAGS ;
- X ta.ta_func = cc_timer_action ;
- X ta.ta_arg = VOID_NULL ;
- X if ( timer_start( cc_timer, &itv, TIMER_RELATIVE, &ta ) == TIMER_ERR )
- X {
- X msg( LOG_ERR, func, "Failed to start concistency timer" ) ;
- X return ;
- X }
- X}
- X
- X#endif /* ! NO_TIMERS */
- X
- END_OF_FILE
- if test 12327 -ne `wc -c <'xinetd/internals.c'`; then
- echo shar: \"'xinetd/internals.c'\" unpacked with wrong size!
- fi
- # end of 'xinetd/internals.c'
- fi
- if test -f 'xinetd/signals.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'xinetd/signals.c'\"
- else
- echo shar: Extracting \"'xinetd/signals.c'\" \(12358 characters\)
- sed "s/^X//" >'xinetd/signals.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: signals.c,v 6.9 1993/06/15 23:25:57 panos Exp $" ;
- X
- X#include <sys/types.h>
- X#include <sys/time.h>
- X#include <signal.h>
- X#include <syslog.h>
- X#include <errno.h>
- X#include <string.h>
- X
- X#include "str.h"
- X
- X#include "state.h"
- X#include "defs.h"
- X#include "config.h"
- X#include "flags.h"
- X
- Xextern int errno ;
- X
- Xvoid msg() ;
- X
- Xvoid exit() ;
- Xtime_t time() ;
- X
- X#define SIGSET_NULL ((sigset_t *)0)
- X#define SIGVEC_NULL ((struct sigvec *)0)
- X#define SIGACTION_NULL ((struct sigaction *)0)
- X
- X#ifdef NO_POSIX_SIGS
- X
- X#ifdef NO_POSIX_TYPES
- X/*
- X * XXX: here we assume that in the case that NO_POSIX_TYPES is not defined
- X * (i.e. the system has posix types) the sigset_t is also typedef'd
- X * to 'int'. Our goal is to work with systems that have defined
- X * sigset_t but do not yet support the posix signal interface.
- X */
- Xtypedef int sigset_t ;
- X
- Xstruct sigaction
- X{
- X void (*sa_handler)() ;
- X sigset_t sa_mask ;
- X int sa_flags ;
- X} ;
- X#endif /* NO_POSIX_TYPES */
- X
- X#ifdef NO_SIGVEC
- X#define sigmask( sig ) ( 1 << ( (sig) -1 ) )
- Xtypedef int (*sighandler_type)() ;
- X#define sigpause( x )
- X#define sigsetmask( x )
- X#endif /* NO_SIGVEC */
- X
- X
- X#define sigsuspend( set ) sigpause( *set )
- X#define sigemptyset( set ) (*set) = 0
- X#define sigaddset( set, sig ) ( ( (*set) |= sigmask( sig ) ), 0 )
- X#define sigismember( set, sig ) ( ( (*set) & sigmask( sig ) ) != 0 )
- X
- X
- X/*
- X * Only works for SIG_SETMASK and SIG_UNBLOCK. Also oset must be NULL.
- X */
- Xint sigprocmask( how, set, oset )
- X int how ;
- X sigset_t *set ;
- X sigset_t *oset ;
- X{
- X if ( how == SIG_BLOCK || oset != NULL )
- X {
- X msg( LOG_ERR, "sigprocmask",
- X "Bad args: how = %d, oset = %p", how, oset ) ;
- X return( -1 ) ;
- X }
- X
- X if ( how == SIG_SETMASK )
- X {
- X (void) sigsetmask( *set ) ;
- X return( 0 ) ;
- X }
- X
- X if ( how == SIG_UNBLOCK )
- X {
- X int current_mask = sigblock( 0 ) ;
- X
- X (void) sigsetmask( current_mask & ~*set ) ;
- X return( 0 ) ;
- X }
- X /* NOTREACHED */
- X}
- X
- X
- X/*
- X * NOTE: This is not a complete imitation of sigaction; in particular it
- X * expects that sap is never NULL and that osap is always NULL.
- X */
- Xint sigaction( sig, sap, osap )
- X int sig ;
- X struct sigaction *sap ;
- X struct sigaction *osap ;
- X{
- X if ( sap == NULL || osap != NULL )
- X {
- X msg( LOG_ERR, "sigaction", "Bad args: sap = %p, osap = %p", sap, osap ) ;
- X return( -1 ) ;
- X }
- X
- X#ifndef NO_SIGVEC
- X {
- X struct sigvec sv ;
- X
- X sv.sv_handler = sap->sa_handler ;
- X sv.sv_mask = sap->sa_mask ;
- X sv.sv_flags = sap->sa_flags ;
- X
- X return( sigvec( sig, &sv, SIGVEC_NULL ) ) ;
- X }
- X#else /* NO_SIGVEC */
- X {
- X sighandler_type new_handler ;
- X
- X new_handler = sa.sa_handler ;
- X return( signal( sig, new_handler ) ? 0 : -1 ) ;
- X }
- X#endif /* ! NO_SIGVEC */
- X}
- X
- X#endif /* NO_POSIX_SIGS */
- X
- X
- X/*
- X * reset_sigs is the list of signals that we need to reset to SIG_DFL.
- X * Currently, these are the signals whose actions we set to SIG_IGN.
- X * In general, we should also include any signals that have a handler
- X * that does anything other than setting a flag. We need to do this
- X * in case such a signal occurs while a forked process is providing
- X * an internal service.
- X */
- Xstatic sigset_t reset_sigs ;
- X
- X/*
- X * nsig is equal to the greatest signal number supported plus 1
- X */
- Xstatic int nsig ;
- X
- X
- X
- X/*
- X * When this function returns FAILED, we check the errno to determine
- X * if it failed because the signal number specified was invalid.
- X * This allows us to determine the number of supported signals.
- X */
- XPRIVATE status_e handle_signal( sig )
- X register int sig ;
- X{
- X struct sigaction sa ;
- X voidfunc sig_handler ;
- X PRIVATE void my_handler() ; /* for the signals we are */
- X /* interested in */
- X PRIVATE void general_handler() ; /* for everything else */
- X
- X switch ( sig )
- X {
- X case RECONFIG_SOFT_SIG:
- X case RECONFIG_HARD_SIG:
- X case TERMINATION_SIG:
- X case STATE_DUMP_SIG:
- X case CONSISTENCY_CHECK_SIG:
- X case SERVER_EXIT_SIG:
- X#ifdef NO_TIMERS
- X case RETRY_SIG:
- X#endif
- X case QUIT_SIG:
- X sig_handler = my_handler ;
- X break ;
- X
- X case SIGTTIN:
- X case SIGTTOU:
- X case SIGTSTP:
- X if ( debug.on )
- X return( OK ) ;
- X /* FALL THROUGH */
- X
- X /*
- X * We may receive a SIGPIPE when handling an internal stream
- X * service and the other end closes the connection.
- X * We only care about internal services that don't require forking.
- X */
- X case SIGPIPE:
- X sig_handler = SIG_IGN ;
- X sigaddset( &reset_sigs, sig ) ;
- X break ;
- X
- X case SIGKILL:
- X case SIGSTOP:
- X return( OK ) ; /* we can't catch these two */
- X
- X /*
- X * If the following two cases are included, SIGSEGV and SIGBUS will
- X * cause core dumps. We want that to happen when we are debugging
- X * xinetd (i.e. DEBUG is defined) and we are not debugging the
- X * signal recovery code (i.e. DEBUG_SIGNALS is not defined).
- X */
- X#if defined( DEBUG ) && !defined( DEBUG_SIGNALS )
- X case SIGSEGV:
- X case SIGBUS:
- X return( OK ) ;
- X#endif
- X
- X case SIGTRAP:
- X if ( debug.on )
- X return( OK ) ;
- X
- X default:
- X sig_handler = general_handler ;
- X }
- X
- X sa.sa_flags = 0 ;
- X sigemptyset( &sa.sa_mask ) ;
- X sa.sa_handler = sig_handler ;
- X return( ( sigaction( sig, &sa, SIGACTION_NULL ) == -1 ) ? FAILED : OK ) ;
- X}
- X
- X
- X
- X/*
- X * Install signal handlers for all signals that can be caught.
- X * This implies that no core dumps are generated by default.
- X */
- Xstatus_e signal_init()
- X{
- X register int sig ;
- X char *func = "install_signal_handlers" ;
- X char *sig_name() ;
- X
- X sigemptyset( &reset_sigs ) ;
- X#ifndef NO_TIMERS
- X sigaddset( &reset_sigs, SIGALRM ) ;
- X#endif
- X
- X for ( sig = 1 ;; sig++ )
- X if ( handle_signal( sig ) == FAILED )
- X if ( errno == EINVAL )
- X {
- X nsig = sig ;
- X break ;
- X }
- X else
- X {
- X msg( LOG_CRIT, func,
- X "Failed to install signal handler for signal %s: %m",
- X sig_name( sig ) ) ;
- X return( FAILED ) ;
- X }
- X return( OK ) ;
- X}
- X
- X
- Xvoid signal_wait()
- X{
- X sigset_t masked_sigs ;
- X
- X sigemptyset( &masked_sigs ) ;
- X (void) sigsuspend( &masked_sigs ) ;
- X}
- X
- X
- X#define MAX_SIGNAL_COUNT 50
- X#define MAX_INTERVAL_SIGNAL_COUNT 10
- X#define SIGNAL_INTERVAL 1 /* second */
- X
- X/*
- X * This function handles SIGSEGV and SIGBUS.
- X * Emergency action is taken if a certain number (MAX_SIGNAL_COUNT) of
- X * these signals is received over the lifetime of the program OR
- X * if a certain number (MAX_INTERVAL_SIGNAL_COUNT) of these signals
- X * is received within a certain time interval (SIGNAL_INTERVAL).
- X *
- X * The action depends on the type of the emergency:
- X * Case 1: MAX_INTERVAL_SIGNAL_COUNT is exceeded
- X * If a setjmp environment is available, do a longjmp, otherwise exit
- X * Case 2: MAX_SIGNAL_COUNT is exceeded
- X * Exit
- X *
- X * NOTE: We try to send a message to the log only once to avoid
- X * looping in this function (in case there is a bug in msg())
- X */
- XPRIVATE void bad_signal()
- X{
- X static time_t interval_start ;
- X static int interval_signal_count ;
- X static int total_signal_count ;
- X time_t current_time ;
- X char *func = "bad_signal" ;
- X
- X total_signal_count++ ;
- X if ( total_signal_count == MAX_SIGNAL_COUNT )
- X {
- X msg( LOG_CRIT, func,
- X "Received %d bad signals. Exiting...", total_signal_count ) ;
- X exit( 1 ) ;
- X }
- X else if ( total_signal_count > MAX_SIGNAL_COUNT )
- X _exit( 1 ) ; /* in case of a problem in exit(3) */
- X
- X (void) time( ¤t_time ) ;
- X
- X if ( interval_signal_count > 0 &&
- X current_time - interval_start <= SIGNAL_INTERVAL )
- X {
- X interval_signal_count++ ;
- X if ( interval_signal_count == MAX_INTERVAL_SIGNAL_COUNT )
- X {
- X if ( ps.rws.env_is_valid )
- X {
- X interval_start = current_time ;
- X interval_signal_count = 1 ;
- X msg( LOG_ERR, func, "Resetting..." ) ;
- X longjmp( ps.rws.env, 1 ) ;
- X /* NOTREACHED */
- X }
- X msg( LOG_CRIT, func,
- X "Received %d signals in %d seconds. Exiting...",
- X interval_signal_count, SIGNAL_INTERVAL ) ;
- X exit( 1 ) ;
- X }
- X else if ( interval_signal_count > MAX_INTERVAL_SIGNAL_COUNT )
- X _exit( 1 ) ; /* shouldn't happen */
- X }
- X else
- X {
- X interval_start = current_time ;
- X interval_signal_count = 1 ;
- X }
- X}
- X
- X
- X#if defined( sun ) && defined( sparc )
- X#undef SP
- X
- X#include <machine/reg.h>
- X#include <machine/frame.h>
- X
- XPRIVATE void stack_trace( scp )
- X struct sigcontext *scp ;
- X{
- X struct frame *fp ;
- X struct rwindow *rwp ;
- X char tracebuf[ 1000 ] ;
- X int len = 0 ;
- X unsigned size = sizeof( tracebuf ) - 1 ;
- X
- X tracebuf[ size ] = NUL ;
- X
- X if ( scp->sc_wbcnt != 0 )
- X return ;
- X rwp = (struct rwindow *) scp->sc_sp ;
- X len = strx_nprint( tracebuf, size, "%#x %#x", scp->sc_pc, rwp->rw_rtn ) ;
- X size -= len ;
- X
- X for ( fp = (struct frame *) rwp->rw_fp ; fp != NULL ; fp = fp->fr_savfp )
- X {
- X int cc ;
- X
- X cc = strx_nprint( &tracebuf[ len ], size,
- X " %#x", (unsigned) fp->fr_savpc ) ;
- X len += cc ;
- X size -= cc ;
- X fp = fp->fr_savfp ;
- X }
- X
- X msg( LOG_CRIT, "stack_trace", "%s", tracebuf ) ;
- X}
- X#endif /* sun && sparc */
- X
- X
- X
- Xchar *sig_name( sig )
- X int sig ;
- X{
- X static char signame_buf[ 30 ] ;
- X
- X#if !defined( NO_SIGLIST ) && defined( NSIG )
- X extern char *sys_siglist[] ;
- X
- X if ( sig < NSIG )
- X return( strx_sprint( signame_buf, sizeof( signame_buf ),
- X "%d (%s)", sig, sys_siglist[ sig ] ) ) ;
- X#endif
- X return( strx_sprint( signame_buf, sizeof( signame_buf ), "%d", sig ) ) ;
- X}
- X
- X
- X/*
- X * For SIGSEGV and SIGBUS we invoke the bad_signal() function (if this is
- X * SunOS, we log the address where the problem occured).
- X *
- X * If we are not running under SunOS, we use the NO_SIGVEC flag to determine
- X * if we have a struct sigcontext (since struct sigcontext is documented in
- X * the sigvec man page).
- X *
- X * For other signals, we just log the fact that they occured.
- X * SIGINT is a special case since in debug.on mode, it will
- X * cause termination.
- X */
- X
- X#ifdef sun
- X
- XPRIVATE void general_handler( sig, code, scp, addr )
- X int sig, code ;
- X struct sigcontext *scp;
- X char *addr;
- X{
- X int pc = scp->sc_pc ;
- X
- X#else /* not a Sun */
- X
- X#ifndef NO_SIGVEC
- X
- XPRIVATE void general_handler( sig, code, scp )
- X int sig, code ;
- X struct sigcontext *scp;
- X{
- X char *addr = NULL ;
- X int pc = scp->sc_pc ;
- X
- X#else /* defined( NO_SIGVEC ) */
- X
- XPRIVATE void general_handler( sig )
- X int sig ;
- X{
- X char *addr = NULL ;
- X int pc = 0 ;
- X
- X#endif /* ! NO_SIGVEC */
- X#endif /* sun */
- X
- X sigset_t badsigs ;
- X char *func = "general_handler" ;
- X
- X /*
- X * Do this here to catch problems like SIGSEGV in msg()
- X */
- X sigemptyset( &badsigs ) ;
- X sigaddset( &badsigs, sig ) ;
- X (void) sigprocmask( SIG_UNBLOCK, &badsigs, SIGSET_NULL ) ;
- X
- X switch ( sig )
- X {
- X case SIGBUS:
- X case SIGSEGV:
- X msg( LOG_CRIT, func,
- X "(%d) Unexpected signal: %s, pc = %#x, address = %#x.",
- X getpid(), sig_name( sig ), pc, addr ) ;
- X#if defined( sun ) && defined( sparc )
- X stack_trace( scp ) ;
- X#endif
- X bad_signal() ;
- X break ;
- X
- X default:
- X msg( LOG_NOTICE, func, "Unexpected signal %s (addr=%#x)",
- X sig_name( sig ), addr ) ;
- X if ( debug.on && sig == SIGINT )
- X exit( 1 ) ;
- X }
- X}
- X
- X
- X/*
- X * The job of this function is to set the flag that corresponds to the
- X * received signal. No other action is taken.
- X */
- XPRIVATE void my_handler( sig )
- X int sig ;
- X{
- X /*
- X * Signals are listed most-frequent-first
- X */
- X switch( sig )
- X {
- X case SERVER_EXIT_SIG:
- X M_SET( ps.flags, CHILD_FLAG ) ;
- X break ;
- X
- X case RETRY_SIG:
- X M_SET( ps.flags, RETRY_FLAG ) ;
- X break ;
- X
- X case RECONFIG_SOFT_SIG:
- X M_SET( ps.flags, SOFT_RECONFIG_FLAG ) ;
- X break ;
- X
- X case RECONFIG_HARD_SIG:
- X M_SET( ps.flags, HARD_RECONFIG_FLAG ) ;
- X break ;
- X
- X case TERMINATION_SIG:
- X M_SET( ps.flags, TERMINATE_FLAG ) ;
- X break ;
- X
- X case STATE_DUMP_SIG:
- X M_SET( ps.flags, DUMP_FLAG ) ;
- X break ;
- X
- X case CONSISTENCY_CHECK_SIG:
- X M_SET( ps.flags, CONSISTENCY_FLAG ) ;
- X break ;
- X
- X case QUIT_SIG:
- X M_SET( ps.flags, QUIT_FLAG ) ;
- X break ;
- X }
- X}
- X
- X
- X/*
- X * Reset all signals to default action. Reset the signal mask
- X *
- X * This function is invoked from a forked process. That is why we
- X * invoke _exit instead of exit (to avoid the possible stdio buffer flushes)
- X */
- Xvoid signal_default_state()
- X{
- X register int sig ;
- X sigset_t empty ;
- X
- X for ( sig = 1 ; sig < nsig ; sig++ )
- X if ( sigismember( &reset_sigs, sig ) == 1 )
- X if ( (int) signal( sig, SIG_DFL ) == -1 )
- X {
- X msg( LOG_ERR, "reset_signals",
- X "signal(3) failed for signal %s: %m", sig_name( sig ) ) ;
- X if ( debug.on )
- X _exit( 1 ) ;
- X }
- X
- X sigemptyset( &empty ) ;
- X (void) sigprocmask( SIG_SETMASK, &empty, SIGSET_NULL ) ;
- X}
- X
- X
- END_OF_FILE
- if test 12358 -ne `wc -c <'xinetd/signals.c'`; then
- echo shar: \"'xinetd/signals.c'\" unpacked with wrong size!
- fi
- # end of 'xinetd/signals.c'
- fi
- echo shar: End of archive 22 \(of 31\).
- cp /dev/null ark22isdone
- 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
-