fixes init script for non ipv6 enabled systems #472755
[packages/xinetd.git] / xinetd / conf.c
1 /*
2  * (c) Copyright 1992 by Panagiotis Tsirigotis
3  * (c) Sections 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 #include <sys/stat.h>
11 #include <sys/types.h>
12 #include <netinet/in.h>
13 #include <syslog.h>
14 #include <fcntl.h>
15 #include <string.h>
16 #include <netdb.h>
17 #include <unistd.h>
18
19 #include "sio.h"
20 #include "conf.h"
21 #include "msg.h"
22 #include "main.h"
23
24
25 void cnf_free( struct configuration *confp )
26 {
27    unsigned u ;
28    pset_h sconfs = confp->cnf_service_confs ;
29
30    for ( u = 0 ; u < pset_count( sconfs ) ; u++ )
31       sc_free( SCP( pset_pointer( sconfs, u ) ) ) ;
32    pset_destroy( sconfs ) ;
33    if ( confp->cnf_defaults )
34       sc_free( confp->cnf_defaults ) ;
35
36    CLEAR(*confp);
37 }
38
39
40 /*
41  * Extract from 'confp' the service that matches 'scp'
42  */
43 struct service_config *cnf_extract( struct configuration *confp, 
44                                     struct service_config *scp )
45 {
46    pset_h stab = confp->cnf_service_confs ;
47    unsigned u ;
48
49    for ( u = 0 ; u < pset_count( stab ) ; u++ )
50    {
51       struct service_config *iscp = SCP( pset_pointer( stab, u ) ) ;
52
53       if ( ! EQ( SC_ID(scp), SC_ID(iscp) ) || sc_different_confs( scp, iscp ) )
54          continue ;
55
56       pset_remove_index( stab, u ) ;
57       return( iscp ) ;
58    }
59    return( NULL ) ;
60 }
61
62
63 void cnf_dump( struct configuration *confp, int fd )
64 {
65    pset_h stab; 
66    unsigned u ;
67
68    stab = confp->cnf_service_confs;
69
70    sc_dump( confp->cnf_defaults, fd, 0, TRUE ) ;
71    tabprint( fd, 0, "\n" ) ;
72
73    for ( u = 0 ; u < pset_count( stab ) ; u++ )
74    {
75       sc_dump( SCP( pset_pointer( stab, u ) ), fd, 0, FALSE ) ;
76       Sputchar( fd, '\n' ) ;
77    }
78 }
79
80
81 status_e cnf_init( struct configuration *confp, int *fdp, psi_h *iterp )
82 {
83    int fd ;
84    pset_h pset ;
85    psi_h pset_iter ;
86    struct service_config *scp ;
87    const char *func = "cnf_init" ;
88
89    /*
90     * Open configuration file
91     */
92    fd = open( ps.ros.config_file, O_RDONLY ) ;
93
94    if ( fd == -1 ) {
95       msg( LOG_ERR, func, "open( %s ) failed: %m", ps.ros.config_file ) ;
96       return( FAILED ) ;
97    }
98
99    if ( ( pset = pset_create( 0, 0 ) ) == NULL )
100    {
101       msg( LOG_CRIT, func, "can't create service table" ) ;
102       (void) Sclose( fd ) ;
103       return( FAILED ) ;
104    }
105
106    if ( ( scp = sc_alloc( CHAR_NULL ) ) == NULL )
107    {
108       msg( LOG_ERR, func, "can't allocate defaults service" ) ;
109       pset_destroy( pset ) ;
110       (void) Sclose( fd ) ;
111       return( FAILED ) ;
112    }
113
114    if ( ( pset_iter = psi_create( pset ) ) == NULL )
115    {
116       msg( LOG_ERR, func, "can't create service table iterator" ) ;
117       sc_free( scp ) ;
118       pset_destroy( pset ) ;
119       (void) Sclose( fd ) ;
120       return( FAILED ) ;
121    }
122
123    *fdp = fd ;
124    confp->cnf_service_confs = pset ;
125    confp->cnf_defaults = scp ;
126    *iterp = pset_iter ;
127    return( OK ) ;
128 }
129
130
131 static void destroy_service( struct service *sp )
132 {
133    svc_deactivate( sp ) ;
134    svc_free( sp ) ;
135    sp = NULL;
136 }
137
138
139 /*
140  * Try to start all services.
141  * Return the # of services started.
142  */
143 unsigned cnf_start_services( struct configuration *confp )
144 {
145    pset_h sconfs = confp->cnf_service_confs ;
146    unsigned services_started = 0 ;
147    unsigned u ;
148    const char *func = "cnf_start_services" ;
149
150    for ( u = 0 ; u < pset_count( sconfs ) ; u++ )
151    {
152       struct service_config *scp = SCP( pset_pointer( sconfs, u ) ) ;
153       struct service *sp ;
154
155       if ( ( sp = svc_new( scp ) ) == NULL )
156       {
157          sc_free( scp ) ;
158          scp = NULL;
159          continue ;
160       }
161
162       if ( svc_activate( sp ) == FAILED )
163       {
164          msg( LOG_ERR, func,
165             "Service %s failed to start and is deactivated.",
166                SVC_ID( sp ) ) ;
167          svc_free( sp ) ;
168          scp = NULL;
169          continue ;
170       }
171
172       /*
173        * descriptors_free can be negative without a descriptor-allocating
174        * system call failing because some of the descriptors we reserve
175        * are transient
176        */
177       if ( ps.rws.descriptors_free < 0 )
178       {
179          msg( LOG_ERR, func,
180             "Service %s disabled because of lack of file descriptors",
181                SVC_ID( sp ) ) ;
182          destroy_service( sp ) ;
183          continue ;
184       }
185
186       /*
187        * Activation successful; add service to service table
188        */
189       if ( pset_add( SERVICES( ps ), sp ) == NULL )
190       {
191          out_of_memory( func ) ;
192          destroy_service( sp ) ;
193          break ;
194       }
195
196       SVC_HOLD( sp ) ;
197
198       services_started++ ;
199
200       if ( debug.on )
201          msg( LOG_DEBUG, func, "Started service: %s", SVC_ID( sp ) ) ;
202    }
203
204    /*
205     * All the configurations have been linked to their services
206     * so we don't need to hold references to them in the pset.
207     * We need to clear the pset so that the cnf_free will not free the memory.
208     */
209    pset_clear( sconfs ) ;
210
211    if ( debug.on )
212       msg( LOG_DEBUG, func, "mask_max = %d, services_started = %d",
213             ps.rws.mask_max, services_started ) ;
214          
215    return( services_started ) ;
216 }