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
cnf_free(struct configuration * confp)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 */
cnf_extract(struct configuration * confp,struct service_config * scp)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
cnf_dump(struct configuration * confp,int fd)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
cnf_init(struct configuration * confp,int * fdp,psi_h * iterp)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
destroy_service(struct service * sp)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 */
cnf_start_services(struct configuration * confp)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 }
217