2
* (c) Copyright 1992 by Panagiotis Tsirigotis
3
* (c) Copyright 1998-2001 by Rob Braun
4
* All rights reserved. The file named COPYRIGHT specifies the terms
5
* and conditions for redistribution.
11
#include <sys/types.h>
21
#include "internals.h"
29
__attribute__ ((noreturn))
31
static void main_loop(void);
32
static void find_bad_fd(void) ;
35
* The following are the only global variables of this program
37
struct program_state ps ;
39
char program_version[] = XINETD_VERSION ;
40
int signals_pending[2] = {-1, -1} ;
43
* This is where the story starts...
45
int main( int argc, char *argv[] )
47
const char *func = "main" ;
49
init_daemon( argc, argv ) ;
52
/* Do the chdir after reading the config file. Relative path names
56
msg(LOG_ERR, func, "Can't chdir to /: %m");
59
/* Print out all the options we're compiled with. Makes support
61
* Also, try to get them all into one syslog message for atomicity
63
msg( LOG_NOTICE, func, "%s started with "
70
#if !defined(LIBWRAP) && !defined(HAVE_LOADAVG)
73
"options compiled in."
76
msg( LOG_NOTICE, func, "Started working: %d available service%s",
77
ps.rws.available_services,
78
( ps.rws.available_services != 1 ) ? "s" : "" ) ;
81
* The reason for doing the setjmp here instead of in main_loop is
82
* that setjmp is not guaranteed to restore register values which
83
* can cause a problem for register variables
85
if ( sigsetjmp( ps.rws.env, 1 ) == 0 )
86
ps.rws.env_is_valid = TRUE ;
96
* What main_loop does:
98
* select on all active services
99
* for each socket where a request is pending
100
* try to start a server
102
static void main_loop(void)
104
const char *func = "main_loop" ;
105
struct timeval tv, *tvptr = NULL;
107
FD_SET(signals_pending[0], &ps.rws.socket_mask);
108
if ( signals_pending[0] > ps.rws.mask_max )
109
ps.rws.mask_max = signals_pending[0] ;
110
if ( signals_pending[1] > ps.rws.mask_max )
111
ps.rws.mask_max = signals_pending[1] ;
120
msg( LOG_DEBUG, func,
121
"active_services = %d", ps.rws.active_services ) ;
123
/* get the next timer value, if there is one, and select for that time */
124
if( (tv.tv_sec = xtimer_nexttime()) >= 0 ) {
131
read_mask = ps.rws.socket_mask ;
132
n_active = select( ps.rws.mask_max+1, &read_mask,
133
FD_SET_NULL, FD_SET_NULL, tvptr ) ;
134
if ( n_active == -1 )
136
if ( errno == EINTR ) {
138
} else if ( errno == EBADF )
142
else if ( n_active == 0 ) {
148
msg( LOG_DEBUG, func, "select returned %d", n_active ) ;
152
if( FD_ISSET(signals_pending[0], &read_mask) ) {
154
if ( --n_active == 0 )
158
for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ )
162
sp = SP( pset_pointer( SERVICES( ps ), u ) ) ;
164
if ( ! SVC_IS_ACTIVE( sp ) )
167
if ( FD_ISSET( SVC_FD( sp ), &read_mask ) )
170
if ( --n_active == 0 )
175
msg( LOG_ERR, func, "%d descriptors still set", n_active ) ;
181
* This function identifies if any of the fd's in the socket mask
182
* is bad. We use it in case select(2) returns EBADF
183
* When we identify such a bad fd, we remove it from the mask
184
* and deactivate the service.
186
static void find_bad_fd(void)
190
unsigned bad_fd_count = 0 ;
191
const char *func = "find_bad_fd" ;
193
for ( fd = 0 ; (unsigned)fd < ps.ros.max_descriptors ; fd++ )
194
if ( FD_ISSET( fd, &ps.rws.socket_mask ) && fstat( fd, &st ) == -1 )
199
for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ )
201
register struct service *sp ;
203
sp = SP( pset_pointer( SERVICES( ps ), u ) ) ;
205
if ( ! SVC_IS_AVAILABLE( sp ) )
208
if ( SVC_FD( sp ) == fd )
211
"file descriptor of service %s has been closed",
213
svc_deactivate( sp ) ;
220
FD_CLR( fd, &ps.rws.socket_mask ) ;
222
"No active service for file descriptor %d\n", fd ) ;
226
if ( bad_fd_count == 0 )
227
msg( LOG_NOTICE, func,
228
"select reported EBADF but no bad file descriptors were found" ) ;
233
* Deactivates all active processes.
234
* The real reason for doing this instead of just exiting is
235
* to deregister the RPC services
237
void quit_program(void)
240
struct service_config *scp = NULL;
241
const char *func = "quit_program" ;
243
destroy_global_access_list() ;
245
for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ ) {
246
scp = SVC_CONF( SP(pset_pointer(SERVICES(ps), u)) );
248
/* This is essentially the same as the following function,
249
* Except we forcibly deactivate them, rather than just
252
if( SC_IS_INTERNAL( scp ) )
253
svc_deactivate( SP( pset_pointer( SERVICES( ps ), u ) ) ) ;
254
if( SC_REDIR_ADDR(scp) != NULL )
255
svc_deactivate( SP( pset_pointer( SERVICES( ps ), u ) ) ) ;
256
if( SC_IS_RPC( scp ) )
257
svc_deactivate( SP( pset_pointer( SERVICES( ps ), u ) ) ) ;
260
if ( ps.ros.pid_file ) {
261
unlink(ps.ros.pid_file);
264
msg( LOG_WARNING, func, "Exiting..." ) ;
269
void terminate_program(void)
272
struct service_config *scp = NULL;
273
void terminate_servers(struct service *);
275
for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ ) {
276
scp = SVC_CONF( SP(pset_pointer(SERVICES(ps), u)) );
278
/* Terminate the service if it is:
279
* 1) internal (if we don't, it'll zombie)
280
* 2) a redirector (again, if we don't it'll zombie)
281
* 3) It's RPC (we must deregister it.
283
if( SC_IS_INTERNAL( scp ) )
284
terminate_servers( SP( pset_pointer( SERVICES( ps ), u ) ) ) ;
285
if( SC_REDIR_ADDR( scp ) != NULL )
286
terminate_servers( SP( pset_pointer( SERVICES( ps ), u ) ) ) ;
287
if( SC_IS_RPC( scp ) )
288
terminate_servers( SP( pset_pointer( SERVICES( ps ), u ) ) ) ;