fixes init script for non ipv6 enabled systems #472755
[packages/xinetd.git] / xinetd / main.c
1 /*
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.
6  */
7
8
9 #include "config.h"
10
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <sys/time.h>
14 #include <errno.h>
15 #include <syslog.h>
16 #include <unistd.h>
17
18 #include "main.h"
19 #include "init.h"
20 #include "msg.h"
21 #include "internals.h"
22 #include "signals.h"
23 #include "service.h"
24 #include "sconf.h"
25 #include "xtimer.h"
26 #include "sensor.h"
27 #include "xmdns.h"
28
29 #ifdef __GNUC__
30 __attribute__ ((noreturn))
31 #endif
32 static void main_loop(void);
33 static void find_bad_fd(void) ;
34
35 /*
36  * The following are the only global variables of this program
37  */
38 struct program_state ps ;
39 struct debug debug ;
40 char program_version[] = XINETD_VERSION ;
41 int signals_pending[2] = {-1, -1} ;
42
43 /*
44  * This is where the story starts...
45  */
46 int main( int argc, char *argv[] )
47 {
48    const char            *func = "main" ;
49
50    init_daemon( argc, argv ) ;
51 #ifdef HAVE_MDNS
52    xinetd_mdns_init();
53 #endif
54    init_services() ;
55
56    /* Do the chdir after reading the config file.  Relative path names
57     * will work better.  
58     */
59    if (chdir("/") < 0) {
60       msg(LOG_ERR, func, "Can't chdir to /: %m");
61    }
62
63    /* Print out all the options we're compiled with.  Makes support 
64     * a tad easier.
65     * Also, try to get them all into one syslog message for atomicity
66     */
67    msg( LOG_NOTICE, func, "%s started with "
68 #ifdef LIBWRAP
69    "libwrap "
70 #endif
71 #ifdef HAVE_LOADAVG
72    "loadavg "
73 #endif
74 #ifdef HAVE_MDNS
75    "mdns "
76 #endif
77 #ifdef HAVE_HOWL
78    "howl "
79 #endif
80 #ifdef HAVE_DNSREGISTRATION
81    "rendezvous "
82 #endif
83 #if !defined(LIBWRAP) && !defined(HAVE_LOADAVG) && !defined(HAVE_MDNS) && !defined(HAVE_HOWL) && !defined(HAVE_DNSREGISTRATION)
84    "no "
85 #endif
86    "options compiled in."
87    , XINETD_VERSION );
88
89    msg( LOG_NOTICE, func, "Started working: %d available service%s",
90       ps.rws.available_services,
91          ( ps.rws.available_services != 1 ) ? "s" : "" ) ;
92
93    /*
94     * The reason for doing the setjmp here instead of in main_loop is
95     * that setjmp is not guaranteed to restore register values which
96     * can cause a problem for register variables
97     */
98    if ( sigsetjmp( ps.rws.env, 1 ) == 0 )
99       ps.rws.env_is_valid = TRUE ;
100
101    main_loop() ;
102
103    /* NOTREACHED */
104    exit(1);
105 }
106
107
108 /*
109  * What main_loop does:
110  *
111  *      select on all active services
112  *      for each socket where a request is pending
113  *         try to start a server
114  */
115 static void main_loop(void)
116 {
117    const char      *func = "main_loop" ;
118    struct timeval   tv, *tvptr = NULL;
119
120    FD_SET(signals_pending[0], &ps.rws.socket_mask);
121    if ( signals_pending[0] > ps.rws.mask_max )
122       ps.rws.mask_max = signals_pending[0] ;
123    if ( signals_pending[1] > ps.rws.mask_max )
124       ps.rws.mask_max = signals_pending[1] ;
125
126    for ( ;; )
127    {
128       fd_set read_mask ;
129       int n_active ;
130       unsigned u ;
131
132       if ( debug.on ) 
133          msg( LOG_DEBUG, func,
134                "active_services = %d", ps.rws.active_services ) ;
135
136       /* get the next timer value, if there is one, and select for that time */
137       if( (tv.tv_sec = xtimer_nexttime()) >= 0 ) {
138          tv.tv_usec = 0;
139          tvptr = &tv;
140       } else {
141          tvptr = NULL;
142       }
143
144       read_mask = ps.rws.socket_mask ;
145       n_active = select( ps.rws.mask_max+1, &read_mask,
146                         FD_SET_NULL, FD_SET_NULL, tvptr ) ;
147       if ( n_active == -1 )
148       {
149          if ( errno == EINTR ) {
150             continue ;
151          } else if ( errno == EBADF )
152             find_bad_fd() ;
153          continue ;
154       }
155       else if ( n_active == 0 ) {
156          xtimer_poll();
157          continue ;
158       }
159
160       if ( debug.on )
161          msg( LOG_DEBUG, func, "select returned %d", n_active ) ;
162
163       xtimer_poll();
164
165       if( FD_ISSET(signals_pending[0], &read_mask) ) {
166          check_pipe();
167             if ( --n_active == 0 )
168                continue ;
169       }
170
171 #ifdef HAVE_MDNS
172       if( xinetd_mdns_poll() == 0 )
173          if ( --n_active == 0 )
174             continue ;
175 #endif
176
177       for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ )
178       {
179          struct service *sp ;
180
181          sp = SP( pset_pointer( SERVICES( ps ), u ) ) ;
182
183          if ( ! SVC_IS_ACTIVE( sp ) )
184             continue ;
185
186          if ( FD_ISSET( SVC_FD( sp ), &read_mask ) )
187          {
188             svc_request( sp ) ;
189             if ( --n_active == 0 )
190                break ;
191          }
192       }
193       if ( n_active > 0 )
194          msg( LOG_ERR, func, "%d descriptors still set", n_active ) ;
195    }
196 }
197
198
199 /*
200  * This function identifies if any of the fd's in the socket mask
201  * is bad. We use it in case select(2) returns EBADF
202  * When we identify such a bad fd, we remove it from the mask
203  * and deactivate the service.
204  */
205 static void find_bad_fd(void)
206 {
207    int fd ;
208    struct stat st ;
209    unsigned bad_fd_count = 0 ;
210    const char *func = "find_bad_fd" ;
211
212    for ( fd = 0 ; (unsigned)fd < ps.ros.max_descriptors ; fd++ )
213       if ( FD_ISSET( fd, &ps.rws.socket_mask ) && fstat( fd, &st ) == -1 )
214       {
215          int found = FALSE ;
216          unsigned u ;
217
218          for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ )
219          {
220             register struct service *sp ;
221
222             sp = SP( pset_pointer( SERVICES( ps ), u ) ) ;
223
224             if ( ! SVC_IS_AVAILABLE( sp ) )
225                continue ;
226
227             if ( SVC_FD( sp ) == fd )
228             {
229                msg( LOG_ERR, func,
230                   "file descriptor of service %s has been closed",
231                               SVC_ID( sp ) ) ;
232                svc_deactivate( sp ) ;
233                found = TRUE ;
234                break ;
235             }
236          }
237          if ( ! found )
238          {
239             FD_CLR( fd, &ps.rws.socket_mask ) ;
240             msg( LOG_ERR, func,
241                "No active service for file descriptor %d\n", fd ) ;
242             bad_fd_count++ ;
243          }
244       }
245    if ( bad_fd_count == 0 )
246       msg( LOG_NOTICE, func,
247          "select reported EBADF but no bad file descriptors were found" ) ;
248 }
249
250
251 /*
252  * Deactivates all active processes.
253  * The real reason for doing this instead of just exiting is
254  * to deregister the RPC services
255  */
256 void quit_program(void)
257 {
258    unsigned u ;
259    struct service_config *scp = NULL;
260    const char *func = "quit_program" ;
261
262    destroy_global_access_list() ;
263    
264    for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ ) {
265       scp = SVC_CONF( SP(pset_pointer(SERVICES(ps), u)) );
266       
267       /* This is essentially the same as the following function, 
268        * Except we forcibly deactivate them, rather than just 
269        * send signals.
270        */
271       if( SC_IS_INTERNAL( scp ) )
272          svc_deactivate( SP( pset_pointer( SERVICES( ps ), u ) ) ) ;
273       if( SC_REDIR_ADDR(scp) != NULL )
274          svc_deactivate( SP( pset_pointer( SERVICES( ps ), u ) ) ) ;
275       if( SC_IS_RPC( scp ) )
276          svc_deactivate( SP( pset_pointer( SERVICES( ps ), u ) ) ) ;
277    }
278
279    if ( ps.ros.pid_file ) {
280       unlink(ps.ros.pid_file);
281    }
282
283    msg( LOG_WARNING, func, "Exiting..." ) ;
284    exit( 0 ) ;
285 }
286
287
288 void terminate_program(void)
289 {
290    unsigned u ;
291    struct service_config *scp = NULL;
292    void terminate_servers(struct service *);
293
294    for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ ) {
295       scp = SVC_CONF( SP(pset_pointer(SERVICES(ps), u)) );
296
297       /* Terminate the service if it is:
298        * 1) internal (if we don't, it'll zombie)
299        * 2) a redirector (again, if we don't it'll zombie)
300        * 3) It's RPC (we must deregister it.
301        */
302       if( SC_IS_INTERNAL( scp ) )
303          terminate_servers( SP( pset_pointer( SERVICES( ps ), u ) ) ) ;
304       if( SC_REDIR_ADDR( scp ) != NULL )
305          terminate_servers( SP( pset_pointer( SERVICES( ps ), u ) ) ) ;
306       if( SC_IS_RPC( scp ) )
307          terminate_servers( SP( pset_pointer( SERVICES( ps ), u ) ) ) ;
308    }
309    quit_program() ;
310 }
311