/[baselayout]/trunk/src/librc-depend.c
Gentoo

Diff of /trunk/src/librc-depend.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 2785 Revision 2786
6 6
7#include "librc.h" 7#include "librc.h"
8 8
9#define GENDEP RC_LIBDIR "/sh/gendepends.sh" 9#define GENDEP RC_LIBDIR "/sh/gendepends.sh"
10 10
11static const char *bootlevel = NULL;
12
11/* We use this so we can pass our char array through many functions */ 13/* We use this so we can pass our char array through many functions */
12struct lhead 14struct lhead
13{ 15{
14 char **list; 16 char **list;
15}; 17};
16 18
17static char *get_shell_value (char *string) 19static char *get_shell_value (char *string)
18{ 20{
19 char *p = string; 21 char *p = string;
20 char *e; 22 char *e;
21 23
22 if (! string) 24 if (! string)
23 return (NULL); 25 return (NULL);
24 26
25 if (*p == '\'') 27 if (*p == '\'')
26 p++; 28 p++;
27 29
28 e = p + strlen (p) - 1; 30 e = p + strlen (p) - 1;
29 if (*e == '\n') 31 if (*e == '\n')
30 *e-- = 0; 32 *e-- = 0;
31 if (*e == '\'') 33 if (*e == '\'')
32 *e-- = 0; 34 *e-- = 0;
33 35
34 if (*p != 0) 36 if (*p != 0)
35 return p; 37 return p;
36 38
37 return (NULL); 39 return (NULL);
38} 40}
39 41
40void rc_free_deptree (rc_depinfo_t *deptree) 42void rc_free_deptree (rc_depinfo_t *deptree)
41{ 43{
42 rc_depinfo_t *di = deptree; 44 rc_depinfo_t *di = deptree;
43 while (di) 45 while (di)
44 { 46 {
45 rc_depinfo_t *dip = di->next; 47 rc_depinfo_t *dip = di->next;
46 rc_deptype_t *dt = di->depends; 48 rc_deptype_t *dt = di->depends;
47 free (di->service); 49 free (di->service);
48 while (dt) 50 while (dt)
49 { 51 {
50 rc_deptype_t *dtp = dt->next; 52 rc_deptype_t *dtp = dt->next;
51 free (dt->type); 53 free (dt->type);
52 rc_strlist_free (dt->services); 54 rc_strlist_free (dt->services);
53 free (dt); 55 free (dt);
54 dt = dtp; 56 dt = dtp;
55 } 57 }
56 free (di); 58 free (di);
57 di = dip; 59 di = dip;
58 } 60 }
59} 61}
60librc_hidden_def(rc_free_deptree) 62librc_hidden_def(rc_free_deptree)
61 63
62rc_depinfo_t *rc_load_deptree (void) 64rc_depinfo_t *rc_load_deptree (void)
63{ 65{
64 FILE *fp; 66 FILE *fp;
65 rc_depinfo_t *deptree = NULL; 67 rc_depinfo_t *deptree = NULL;
66 rc_depinfo_t *depinfo = NULL; 68 rc_depinfo_t *depinfo = NULL;
67 rc_deptype_t *deptype = NULL; 69 rc_deptype_t *deptype = NULL;
68 char buffer [RC_LINEBUFFER]; 70 char buffer [RC_LINEBUFFER];
69 char *type; 71 char *type;
70 char *p; 72 char *p;
71 char *e; 73 char *e;
72 int i; 74 int i;
73 75
74 /* Update our deptree, but only if we need too */ 76 /* Update our deptree, but only if we need too */
75 rc_update_deptree (false); 77 rc_update_deptree (false);
76 78
77 if (! (fp = fopen (RC_DEPTREE, "r"))) 79 if (! (fp = fopen (RC_DEPTREE, "r")))
78 return (NULL); 80 return (NULL);
79 81
80 while (fgets (buffer, RC_LINEBUFFER, fp)) 82 while (fgets (buffer, RC_LINEBUFFER, fp))
81 { 83 {
82 p = buffer; 84 p = buffer;
83 e = strsep (&p, "_"); 85 e = strsep (&p, "_");
84 if (! e || strcmp (e, "depinfo") != 0) 86 if (! e || strcmp (e, "depinfo") != 0)
85 continue; 87 continue;
86 88
87 e = strsep (&p, "_"); 89 e = strsep (&p, "_");
88 if (! e || sscanf (e, "%d", &i) != 1) 90 if (! e || sscanf (e, "%d", &i) != 1)
89 continue; 91 continue;
90 92
91 if (! (type = strsep (&p, "_="))) 93 if (! (type = strsep (&p, "_=")))
92 continue; 94 continue;
93 95
94 if (strcmp (type, "service") == 0) 96 if (strcmp (type, "service") == 0)
95 { 97 {
96 /* Sanity */ 98 /* Sanity */
97 e = get_shell_value (p); 99 e = get_shell_value (p);
98 if (! e || strlen (e) == 0) 100 if (! e || strlen (e) == 0)
99 continue; 101 continue;
100 102
101 if (! deptree) 103 if (! deptree)
102 { 104 {
103 deptree = rc_xmalloc (sizeof (rc_depinfo_t)); 105 deptree = rc_xmalloc (sizeof (rc_depinfo_t));
104 depinfo = deptree; 106 depinfo = deptree;
105 } 107 }
106 else 108 else
107 { 109 {
108 depinfo->next = rc_xmalloc (sizeof (rc_depinfo_t)); 110 depinfo->next = rc_xmalloc (sizeof (rc_depinfo_t));
109 depinfo = depinfo->next; 111 depinfo = depinfo->next;
110 } 112 }
111 memset (depinfo, 0, sizeof (rc_depinfo_t)); 113 memset (depinfo, 0, sizeof (rc_depinfo_t));
112 depinfo->service = rc_xstrdup (e); 114 depinfo->service = rc_xstrdup (e);
113 deptype = NULL; 115 deptype = NULL;
114 continue; 116 continue;
115 } 117 }
116 118
117 e = strsep (&p, "="); 119 e = strsep (&p, "=");
118 if (! e || sscanf (e, "%d", &i) != 1) 120 if (! e || sscanf (e, "%d", &i) != 1)
119 continue; 121 continue;
120 122
121 /* Sanity */ 123 /* Sanity */
122 e = get_shell_value (p); 124 e = get_shell_value (p);
123 if (! e || strlen (e) == 0) 125 if (! e || strlen (e) == 0)
124 continue; 126 continue;
125 127
126 if (! deptype) 128 if (! deptype)
127 { 129 {
128 depinfo->depends = rc_xmalloc (sizeof (rc_deptype_t)); 130 depinfo->depends = rc_xmalloc (sizeof (rc_deptype_t));
129 deptype = depinfo->depends; 131 deptype = depinfo->depends;
130 memset (deptype, 0, sizeof (rc_deptype_t)); 132 memset (deptype, 0, sizeof (rc_deptype_t));
131 } 133 }
132 else 134 else
133 if (strcmp (deptype->type, type) != 0) 135 if (strcmp (deptype->type, type) != 0)
134 { 136 {
135 deptype->next = rc_xmalloc (sizeof (rc_deptype_t)); 137 deptype->next = rc_xmalloc (sizeof (rc_deptype_t));
136 deptype = deptype->next; 138 deptype = deptype->next;
137 memset (deptype, 0, sizeof (rc_deptype_t)); 139 memset (deptype, 0, sizeof (rc_deptype_t));
138 } 140 }
139 141
140 if (! deptype->type) 142 if (! deptype->type)
141 deptype->type = rc_xstrdup (type); 143 deptype->type = rc_xstrdup (type);
142 144
143 deptype->services = rc_strlist_addsort (deptype->services, e); 145 deptype->services = rc_strlist_addsort (deptype->services, e);
144 } 146 }
145 fclose (fp); 147 fclose (fp);
146 148
147 return (deptree); 149 return (deptree);
148} 150}
149librc_hidden_def(rc_load_deptree) 151librc_hidden_def(rc_load_deptree)
150 152
151rc_depinfo_t *rc_get_depinfo (rc_depinfo_t *deptree, const char *service) 153rc_depinfo_t *rc_get_depinfo (rc_depinfo_t *deptree, const char *service)
152{ 154{
153 rc_depinfo_t *di; 155 rc_depinfo_t *di;
154 156
155 if (! deptree || ! service) 157 if (! deptree || ! service)
156 return (NULL); 158 return (NULL);
157 159
158 for (di = deptree; di; di = di->next) 160 for (di = deptree; di; di = di->next)
159 if (strcmp (di->service, service) == 0) 161 if (strcmp (di->service, service) == 0)
160 return (di); 162 return (di);
161 163
162 return (NULL); 164 return (NULL);
163} 165}
164librc_hidden_def(rc_get_depinfo) 166librc_hidden_def(rc_get_depinfo)
165 167
166rc_deptype_t *rc_get_deptype (rc_depinfo_t *depinfo, const char *type) 168rc_deptype_t *rc_get_deptype (rc_depinfo_t *depinfo, const char *type)
167{ 169{
168 rc_deptype_t *dt; 170 rc_deptype_t *dt;
169 171
170 if (! depinfo || !type) 172 if (! depinfo || !type)
171 return (NULL); 173 return (NULL);
172 174
173 for (dt = depinfo->depends; dt; dt = dt->next) 175 for (dt = depinfo->depends; dt; dt = dt->next)
174 if (strcmp (dt->type, type) == 0) 176 if (strcmp (dt->type, type) == 0)
175 return (dt); 177 return (dt);
176 178
177 return (NULL); 179 return (NULL);
178} 180}
179librc_hidden_def(rc_get_deptype) 181librc_hidden_def(rc_get_deptype)
180 182
181static bool valid_service (const char *runlevel, const char *service) 183static bool valid_service (const char *runlevel, const char *service)
182{ 184{
183 return ((strcmp (runlevel, RC_LEVEL_BOOT) != 0 && 185 return ((strcmp (runlevel, bootlevel) != 0 &&
184 rc_service_in_runlevel (service, RC_LEVEL_BOOT)) || 186 rc_service_in_runlevel (service, bootlevel)) ||
185 rc_service_in_runlevel (service, runlevel) || 187 rc_service_in_runlevel (service, runlevel) ||
186 rc_service_state (service, rc_service_coldplugged) || 188 rc_service_state (service, rc_service_coldplugged) ||
187 rc_service_state (service, rc_service_started)); 189 rc_service_state (service, rc_service_started));
188} 190}
189 191
190static bool get_provided1 (const char *runlevel, struct lhead *providers, 192static bool get_provided1 (const char *runlevel, struct lhead *providers,
191 rc_deptype_t *deptype, 193 rc_deptype_t *deptype,
192 const char *level, bool coldplugged, 194 const char *level, bool coldplugged,
193 rc_service_state_t state) 195 rc_service_state_t state)
194{ 196{
195 char *service; 197 char *service;
196 int i; 198 int i;
197 bool retval = false; 199 bool retval = false;
198 char *bootlevel = getenv ("RC_BOOTLEVEL");
199 200
200 STRLIST_FOREACH (deptype->services, service, i) 201 STRLIST_FOREACH (deptype->services, service, i)
201 { 202 {
202 bool ok = true; 203 bool ok = true;
203 if (level) 204 if (level)
204 ok = rc_service_in_runlevel (service, level); 205 ok = rc_service_in_runlevel (service, level);
205 else if (coldplugged) 206 else if (coldplugged)
206 ok = (rc_service_state (service, rc_service_coldplugged) && 207 ok = (rc_service_state (service, rc_service_coldplugged) &&
207 ! rc_service_in_runlevel (service, runlevel) && 208 ! rc_service_in_runlevel (service, runlevel) &&
208 ! rc_service_in_runlevel (service, bootlevel)); 209 ! rc_service_in_runlevel (service, bootlevel));
209 210
210 if (! ok) 211 if (! ok)
211 continue; 212 continue;
212 213
213 switch (state) { 214 switch (state) {
214 case rc_service_started: 215 case rc_service_started:
215 ok = rc_service_state (service, state); 216 ok = rc_service_state (service, state);
216 break; 217 break;
217 case rc_service_inactive: 218 case rc_service_inactive:
218 case rc_service_starting: 219 case rc_service_starting:
219 case rc_service_stopping: 220 case rc_service_stopping:
220 ok = (rc_service_state (service, rc_service_starting) || 221 ok = (rc_service_state (service, rc_service_starting) ||
221 rc_service_state (service, rc_service_stopping) || 222 rc_service_state (service, rc_service_stopping) ||
222 rc_service_state (service, rc_service_inactive)); 223 rc_service_state (service, rc_service_inactive));
223 break; 224 break;
224 default: 225 default:
225 break; 226 break;
226 } 227 }
227 228
228 if (! ok) 229 if (! ok)
229 continue; 230 continue;
230 231
231 retval = true; 232 retval = true;
232 providers->list = rc_strlist_add (providers->list, service); 233 providers->list = rc_strlist_add (providers->list, service);
233 } 234 }
234 235
235 return (retval); 236 return (retval);
236} 237}
237 238
238/* Work out if a service is provided by another service. 239/* Work out if a service is provided by another service.
239 For example metalog provides logger. 240 For example metalog provides logger.
240 We need to be able to handle syslogd providing logger too. 241 We need to be able to handle syslogd providing logger too.
243 244
244 If there are any bugs in rc-depend, they will probably be here as 245 If there are any bugs in rc-depend, they will probably be here as
245 provided dependancy can change depending on runlevel state. 246 provided dependancy can change depending on runlevel state.
246 */ 247 */
247static char **get_provided (rc_depinfo_t *deptree, rc_depinfo_t *depinfo, 248static char **get_provided (rc_depinfo_t *deptree, rc_depinfo_t *depinfo,
248 const char *runlevel, int options) 249 const char *runlevel, int options)
249{ 250{
250 rc_deptype_t *dt; 251 rc_deptype_t *dt;
251 struct lhead providers; 252 struct lhead providers;
252 char *service; 253 char *service;
253 int i; 254 int i;
254 char *bootlevel;
255 255
256 if (! deptree || ! depinfo) 256 if (! deptree || ! depinfo)
257 return (NULL); 257 return (NULL);
258 if (rc_service_exists (depinfo->service)) 258 if (rc_service_exists (depinfo->service))
259 return (NULL); 259 return (NULL);
260 260
261 dt = rc_get_deptype (depinfo, "providedby"); 261 dt = rc_get_deptype (depinfo, "providedby");
262 if (! dt) 262 if (! dt)
263 return (NULL); 263 return (NULL);
264 264
265 memset (&providers, 0, sizeof (struct lhead)); 265 memset (&providers, 0, sizeof (struct lhead));
266 /* If we are stopping then all depends are true, regardless of state. 266 /* If we are stopping then all depends are true, regardless of state.
267 This is especially true for net services as they could force a restart 267 This is especially true for net services as they could force a restart
268 of the local dns resolver which may depend on net. */ 268 of the local dns resolver which may depend on net. */
269 if (options & RC_DEP_STOP) 269 if (options & RC_DEP_STOP)
270 { 270 {
271 STRLIST_FOREACH (dt->services, service, i) 271 STRLIST_FOREACH (dt->services, service, i)
272 providers.list = rc_strlist_add (providers.list, service); 272 providers.list = rc_strlist_add (providers.list, service);
273 273
274 return (providers.list); 274 return (providers.list);
275 } 275 }
276 276
277 /* If we're strict, then only use what we have in our runlevel */ 277 /* If we're strict, then only use what we have in our runlevel
278 * and bootlevel */
278 if (options & RC_DEP_STRICT) 279 if (options & RC_DEP_STRICT)
279 { 280 {
280 STRLIST_FOREACH (dt->services, service, i) 281 STRLIST_FOREACH (dt->services, service, i)
281 if (rc_service_in_runlevel (service, runlevel)) 282 if (rc_service_in_runlevel (service, runlevel) ||
283 rc_service_in_runlevel (service, bootlevel))
282 providers.list = rc_strlist_add (providers.list, service); 284 providers.list = rc_strlist_add (providers.list, service);
283 285
284 if (providers.list) 286 if (providers.list)
285 return (providers.list); 287 return (providers.list);
286 } 288 }
287 289
288 /* OK, we're not strict or there were no services in our runlevel. 290 /* OK, we're not strict or there were no services in our runlevel.
289 This is now where the logic gets a little fuzzy :) 291 This is now where the logic gets a little fuzzy :)
290 If there is >1 running service then we return NULL. 292 If there is >1 running service then we return NULL.
291 We do this so we don't hang around waiting for inactive services and 293 We do this so we don't hang around waiting for inactive services and
292 our need has already been satisfied as it's not strict. 294 our need has already been satisfied as it's not strict.
293 We apply this to our runlevel, coldplugged services, then bootlevel 295 We apply this to our runlevel, coldplugged services, then bootlevel
294 and finally any running.*/ 296 and finally any running.*/
295#define DO \ 297#define DO \
296 if (providers.list && providers.list[0] && providers.list[1]) \ 298 if (providers.list && providers.list[0] && providers.list[1]) \
297 { \ 299 { \
298 rc_strlist_free (providers.list); \ 300 rc_strlist_free (providers.list); \
299 return (NULL); \ 301 return (NULL); \
300 } \ 302 } \
301 else if (providers.list) \ 303 else if (providers.list) \
302 return providers.list; \ 304 return providers.list; \
303 305
304 /* Anything in the runlevel has to come first */ 306 /* Anything in the runlevel has to come first */
305 if (get_provided1 (runlevel, &providers, dt, runlevel, false, rc_service_started)) 307 if (get_provided1 (runlevel, &providers, dt, runlevel, false, rc_service_started))
306 { DO } 308 { DO }
307 if (get_provided1 (runlevel, &providers, dt, runlevel, false, rc_service_starting)) 309 if (get_provided1 (runlevel, &providers, dt, runlevel, false, rc_service_starting))
310 return (providers.list);
311 if (get_provided1 (runlevel, &providers, dt, runlevel, false, rc_service_stopped))
312 return (providers.list);
313
314 /* Check coldplugged services */
315 if (get_provided1 (runlevel, &providers, dt, NULL, true, rc_service_started))
316 { DO }
317 if (get_provided1 (runlevel, &providers, dt, NULL, true, rc_service_starting))
318 return (providers.list);
319
320 /* Check bootlevel if we're not in it */
321 if (bootlevel && strcmp (runlevel, bootlevel) != 0)
322 {
323 if (get_provided1 (runlevel, &providers, dt, bootlevel, false, rc_service_started))
324 { DO }
325 if (get_provided1 (runlevel, &providers, dt, bootlevel, false, rc_service_starting))
326 return (providers.list);
327 }
328
329 /* Check coldplugged services */
330 if (get_provided1 (runlevel, &providers, dt, NULL, true, rc_service_stopped))
331
332 /* Check manually started */
333 if (get_provided1 (runlevel, &providers, dt, NULL, false, rc_service_started))
334 { DO }
335 if (get_provided1 (runlevel, &providers, dt, NULL, false, rc_service_starting))
336 return (providers.list);
337
338 /* Nothing started then. OK, lets get the stopped services */
339 if (get_provided1 (runlevel, &providers, dt, runlevel, false, rc_service_stopped))
340 return (providers.list);
341
342 if (bootlevel && (strcmp (runlevel, bootlevel) != 0)
343 && (get_provided1 (runlevel, &providers, dt, bootlevel, false, rc_service_stopped)))
344 return (providers.list);
345
346 /* Still nothing? OK, list all services */
347 STRLIST_FOREACH (dt->services, service, i)
348 providers.list = rc_strlist_add (providers.list, service);
349
308 return (providers.list); 350 return (providers.list);
309 if (get_provided1 (runlevel, &providers, dt, runlevel, false, rc_service_stopped))
310 return (providers.list);
311
312 /* Check coldplugged services */
313 if (get_provided1 (runlevel, &providers, dt, NULL, true, rc_service_started))
314 { DO }
315 if (get_provided1 (runlevel, &providers, dt, NULL, true, rc_service_starting))
316 return (providers.list);
317
318 /* Check bootlevel if we're not in it */
319 bootlevel = getenv ("RC_BOOTLEVEL");
320 if (bootlevel && strcmp (runlevel, bootlevel) != 0)
321 {
322 if (get_provided1 (runlevel, &providers, dt, bootlevel, false, rc_service_started))
323 { DO }
324 if (get_provided1 (runlevel, &providers, dt, bootlevel, false, rc_service_starting))
325 return (providers.list);
326 }
327
328 /* Check coldplugged services */
329 if (get_provided1 (runlevel, &providers, dt, NULL, true, rc_service_stopped))
330
331 /* Check manually started */
332 if (get_provided1 (runlevel, &providers, dt, NULL, false, rc_service_started))
333 { DO }
334 if (get_provided1 (runlevel, &providers, dt, NULL, false, rc_service_starting))
335 return (providers.list);
336
337 /* Nothing started then. OK, lets get the stopped services */
338 if (get_provided1 (runlevel, &providers, dt, runlevel, false, rc_service_stopped))
339 return (providers.list);
340
341 if (bootlevel && (strcmp (runlevel, bootlevel) != 0)
342 && (get_provided1 (runlevel, &providers, dt, bootlevel, false, rc_service_stopped)))
343 return (providers.list);
344
345 /* Still nothing? OK, list all services */
346 STRLIST_FOREACH (dt->services, service, i)
347 providers.list = rc_strlist_add (providers.list, service);
348
349 return (providers.list);
350} 351}
351 352
352static void visit_service (rc_depinfo_t *deptree, char **types, 353static void visit_service (rc_depinfo_t *deptree, char **types,
353 struct lhead *sorted, struct lhead *visited, 354 struct lhead *sorted, struct lhead *visited,
354 rc_depinfo_t *depinfo, 355 rc_depinfo_t *depinfo,
355 const char *runlevel, int options) 356 const char *runlevel, int options)
356{ 357{
357 int i, j, k; 358 int i, j, k;
358 char *lp, *item; 359 char *lp, *item;
359 char *service; 360 char *service;
360 rc_depinfo_t *di; 361 rc_depinfo_t *di;
361 rc_deptype_t *dt; 362 rc_deptype_t *dt;
362 char **provides; 363 char **provides;
363 char *svcname; 364 char *svcname;
364 365
365 if (! deptree || !sorted || !visited || !depinfo) 366 if (! deptree || !sorted || !visited || !depinfo)
366 return; 367 return;
367 368
368 /* Check if we have already visited this service or not */ 369 /* Check if we have already visited this service or not */
369 STRLIST_FOREACH (visited->list, item, i) 370 STRLIST_FOREACH (visited->list, item, i)
370 if (strcmp (item, depinfo->service) == 0) 371 if (strcmp (item, depinfo->service) == 0)
371 return; 372 return;
372 373
373 /* Add ourselves as a visited service */ 374 /* Add ourselves as a visited service */
374 visited->list = rc_strlist_add (visited->list, depinfo->service); 375 visited->list = rc_strlist_add (visited->list, depinfo->service);
375 376
376 STRLIST_FOREACH (types, item, i) 377 STRLIST_FOREACH (types, item, i)
377 { 378 {
378 if ((dt = rc_get_deptype (depinfo, item))) 379 if ((dt = rc_get_deptype (depinfo, item)))
379 { 380 {
380 STRLIST_FOREACH (dt->services, service, j) 381 STRLIST_FOREACH (dt->services, service, j)
381 { 382 {
382 if (! options & RC_DEP_TRACE || strcmp (item, "iprovide") == 0) 383 if (! options & RC_DEP_TRACE || strcmp (item, "iprovide") == 0)
383 { 384 {
384 sorted->list = rc_strlist_add (sorted->list, service); 385 sorted->list = rc_strlist_add (sorted->list, service);
385 continue; 386 continue;
386 } 387 }
387 388
388 di = rc_get_depinfo (deptree, service); 389 di = rc_get_depinfo (deptree, service);
389 if ((provides = get_provided (deptree, di, runlevel, options))) 390 if ((provides = get_provided (deptree, di, runlevel, options)))
390 { 391 {
391 STRLIST_FOREACH (provides, lp, k) 392 STRLIST_FOREACH (provides, lp, k)
392 { 393 {
393 di = rc_get_depinfo (deptree, lp); 394 di = rc_get_depinfo (deptree, lp);
394 if (di && (strcmp (item, "ineed") == 0 || 395 if (di && (strcmp (item, "ineed") == 0 ||
395 valid_service (runlevel, di->service))) 396 valid_service (runlevel, di->service)))
396 visit_service (deptree, types, sorted, visited, di, 397 visit_service (deptree, types, sorted, visited, di,
397 runlevel, options | RC_DEP_TRACE); 398 runlevel, options | RC_DEP_TRACE);
398 } 399 }
399 rc_strlist_free (provides); 400 rc_strlist_free (provides);
400 } 401 }
401 else 402 else
402 if (di && (strcmp (item, "ineed") == 0 || 403 if (di && (strcmp (item, "ineed") == 0 ||
403 valid_service (runlevel, service))) 404 valid_service (runlevel, service)))
404 visit_service (deptree, types, sorted, visited, di, 405 visit_service (deptree, types, sorted, visited, di,
405 runlevel, options | RC_DEP_TRACE); 406 runlevel, options | RC_DEP_TRACE);
406 } 407 }
407 } 408 }
408 } 409 }
409 410
410 /* Now visit the stuff we provide for */ 411 /* Now visit the stuff we provide for */
411 if (options & RC_DEP_TRACE && (dt = rc_get_deptype (depinfo, "iprovide"))) 412 if (options & RC_DEP_TRACE && (dt = rc_get_deptype (depinfo, "iprovide")))
412 { 413 {
413 STRLIST_FOREACH (dt->services, service, i) 414 STRLIST_FOREACH (dt->services, service, i)
414 { 415 {
415 if ((di = rc_get_depinfo (deptree, service))) 416 if ((di = rc_get_depinfo (deptree, service)))
416 if ((provides = get_provided (deptree, di, runlevel, options))) 417 if ((provides = get_provided (deptree, di, runlevel, options)))
417 { 418 {
418 STRLIST_FOREACH (provides, lp, j) 419 STRLIST_FOREACH (provides, lp, j)
419 if (strcmp (lp, depinfo->service) == 0) 420 if (strcmp (lp, depinfo->service) == 0)
420 { 421 {
421 visit_service (deptree, types, sorted, visited, di, 422 visit_service (deptree, types, sorted, visited, di,
422 runlevel, options | RC_DEP_TRACE); 423 runlevel, options | RC_DEP_TRACE);
423 break; 424 break;
424 } 425 }
425 rc_strlist_free (provides); 426 rc_strlist_free (provides);
426 } 427 }
427 } 428 }
428 } 429 }
429 430
430 /* We've visited everything we need, so add ourselves unless we 431 /* We've visited everything we need, so add ourselves unless we
431 are also the service calling us or we are provided by something */ 432 are also the service calling us or we are provided by something */
432 svcname = getenv("SVCNAME"); 433 svcname = getenv("SVCNAME");
433 if (! svcname || strcmp (svcname, depinfo->service) != 0) 434 if (! svcname || strcmp (svcname, depinfo->service) != 0)
434 if (! rc_get_deptype (depinfo, "providedby")) 435 if (! rc_get_deptype (depinfo, "providedby"))
435 sorted->list = rc_strlist_add (sorted->list, depinfo->service); 436 sorted->list = rc_strlist_add (sorted->list, depinfo->service);
436} 437}
437 438
438char **rc_get_depends (rc_depinfo_t *deptree, 439char **rc_get_depends (rc_depinfo_t *deptree,
439 char **types, char **services, 440 char **types, char **services,
440 const char *runlevel, int options) 441 const char *runlevel, int options)
441{ 442{
442 struct lhead sorted; 443 struct lhead sorted;
443 struct lhead visited; 444 struct lhead visited;
444 rc_depinfo_t *di; 445 rc_depinfo_t *di;
445 char *service; 446 char *service;
446 int i; 447 int i;
447 448
448 if (! deptree || ! types || ! services) 449 if (! deptree || ! types || ! services)
449 return (NULL); 450 return (NULL);
450 451
451 memset (&sorted, 0, sizeof (struct lhead)); 452 memset (&sorted, 0, sizeof (struct lhead));
452 memset (&visited, 0, sizeof (struct lhead)); 453 memset (&visited, 0, sizeof (struct lhead));
453 454
455 bootlevel = getenv ("RC_BOOTLEVEL");
456 if (! bootlevel)
457 bootlevel = RC_LEVEL_BOOT;
458
454 STRLIST_FOREACH (services, service, i) 459 STRLIST_FOREACH (services, service, i)
455 { 460 {
456 di = rc_get_depinfo (deptree, service); 461 di = rc_get_depinfo (deptree, service);
457 visit_service (deptree, types, &sorted, &visited, di, runlevel, options); 462 visit_service (deptree, types, &sorted, &visited, di, runlevel, options);
458 } 463 }
459 464
460 rc_strlist_free (visited.list); 465 rc_strlist_free (visited.list);
461 return (sorted.list); 466 return (sorted.list);
462} 467}
463librc_hidden_def(rc_get_depends) 468librc_hidden_def(rc_get_depends)
464 469
465char **rc_order_services (rc_depinfo_t *deptree, const char *runlevel, 470char **rc_order_services (rc_depinfo_t *deptree, const char *runlevel,
466 int options) 471 int options)
467{ 472{
468 char **list = NULL; 473 char **list = NULL;
469 char **types = NULL; 474 char **types = NULL;
470 char **services = NULL; 475 char **services = NULL;
471 bool reverse = false; 476 bool reverse = false;
472 477
473 if (! runlevel) 478 if (! runlevel)
474 return (NULL); 479 return (NULL);
475 480
481 bootlevel = getenv ("RC_BOOTLEVEL");
482 if (! bootlevel)
483 bootlevel = RC_LEVEL_BOOT;
484
476 /* When shutting down, list all running services */ 485 /* When shutting down, list all running services */
477 if (strcmp (runlevel, RC_LEVEL_SINGLE) == 0 || 486 if (strcmp (runlevel, RC_LEVEL_SINGLE) == 0 ||
478 strcmp (runlevel, RC_LEVEL_SHUTDOWN) == 0 || 487 strcmp (runlevel, RC_LEVEL_SHUTDOWN) == 0 ||
479 strcmp (runlevel, RC_LEVEL_REBOOT) == 0) 488 strcmp (runlevel, RC_LEVEL_REBOOT) == 0)
480 { 489 {
481 list = rc_ls_dir (list, RC_SVCDIR_STARTING, RC_LS_INITD); 490 list = rc_ls_dir (list, RC_SVCDIR_STARTING, RC_LS_INITD);
482 list = rc_ls_dir (list, RC_SVCDIR_INACTIVE, RC_LS_INITD); 491 list = rc_ls_dir (list, RC_SVCDIR_INACTIVE, RC_LS_INITD);
483 list = rc_ls_dir (list, RC_SVCDIR_STARTED, RC_LS_INITD); 492 list = rc_ls_dir (list, RC_SVCDIR_STARTED, RC_LS_INITD);
484 reverse = true; 493 reverse = true;
485 } 494 }
486 else 495 else
487 { 496 {
488 list = rc_services_in_runlevel (runlevel); 497 list = rc_services_in_runlevel (runlevel);
489 498
490 /* Add coldplugged services */ 499 /* Add coldplugged services */
491 list = rc_ls_dir (list, RC_SVCDIR_COLDPLUGGED, RC_LS_INITD); 500 list = rc_ls_dir (list, RC_SVCDIR_COLDPLUGGED, RC_LS_INITD);
492 501
502
493 /* If we're not the boot runlevel then add that too */ 503 /* If we're not the boot runlevel then add that too */
494 if (strcmp (runlevel, RC_LEVEL_BOOT) != 0) 504 if (strcmp (runlevel, bootlevel) != 0)
495 { 505 {
496 char *path = rc_strcatpaths (RC_RUNLEVELDIR, RC_LEVEL_BOOT, 506 char *path = rc_strcatpaths (RC_RUNLEVELDIR, bootlevel,
497 (char *) NULL); 507 (char *) NULL);
498 list = rc_ls_dir (list, path, RC_LS_INITD); 508 list = rc_ls_dir (list, path, RC_LS_INITD);
499 free (path); 509 free (path);
500 } 510 }
501 } 511 }
502 512
503 /* Now we have our lists, we need to pull in any dependencies 513 /* Now we have our lists, we need to pull in any dependencies
504 and order them */ 514 and order them */
505 types = rc_strlist_add (NULL, "ineed"); 515 types = rc_strlist_add (NULL, "ineed");
506 types = rc_strlist_add (types, "iuse"); 516 types = rc_strlist_add (types, "iuse");
507 types = rc_strlist_add (types, "iafter"); 517 types = rc_strlist_add (types, "iafter");
508 services = rc_get_depends (deptree, types, list, runlevel, 518 services = rc_get_depends (deptree, types, list, runlevel,
509 RC_DEP_STRICT | RC_DEP_TRACE | options); 519 RC_DEP_STRICT | RC_DEP_TRACE | options);
510 rc_strlist_free (list); 520 rc_strlist_free (list);
511 rc_strlist_free (types); 521 rc_strlist_free (types);
512 522
513 if (reverse) 523 if (reverse)
514 rc_strlist_reverse (services); 524 rc_strlist_reverse (services);
515 525
516 return (services); 526 return (services);
517} 527}
518librc_hidden_def(rc_order_services) 528librc_hidden_def(rc_order_services)
519 529
520static bool is_newer_than (const char *file, const char *target) 530static bool is_newer_than (const char *file, const char *target)
521{ 531{
522 struct stat buf; 532 struct stat buf;
523 time_t mtime; 533 time_t mtime;
524 534
525 if (stat (file, &buf) != 0 || buf.st_size == 0) 535 if (stat (file, &buf) != 0 || buf.st_size == 0)
526 return (false); 536 return (false);
527 mtime = buf.st_mtime; 537 mtime = buf.st_mtime;
528 538
529 /* Of course we are newever than targets that don't exist 539 /* Of course we are newever than targets that don't exist
530 Such as broken symlinks */ 540 Such as broken symlinks */
531 if (stat (target, &buf) != 0) 541 if (stat (target, &buf) != 0)
532 return (true); 542 return (true);
533 543
534 if (mtime < buf.st_mtime) 544 if (mtime < buf.st_mtime)
535 return (false); 545 return (false);
536 546
537 if (rc_is_dir (target)) 547 if (rc_is_dir (target))
538 { 548 {
539 char **targets = rc_ls_dir (NULL, target, 0); 549 char **targets = rc_ls_dir (NULL, target, 0);
540 char *t; 550 char *t;
541 int i; 551 int i;
542 bool newer = true; 552 bool newer = true;
543 STRLIST_FOREACH (targets, t, i) 553 STRLIST_FOREACH (targets, t, i)
544 { 554 {
545 char *path = rc_strcatpaths (target, t, (char *) NULL); 555 char *path = rc_strcatpaths (target, t, (char *) NULL);
546 newer = is_newer_than (file, path); 556 newer = is_newer_than (file, path);
547 free (path); 557 free (path);
548 if (! newer) 558 if (! newer)
549 break; 559 break;
550 } 560 }
551 rc_strlist_free (targets); 561 rc_strlist_free (targets);
552 return (newer); 562 return (newer);
553 } 563 }
554 564
555 return (true); 565 return (true);
556} 566}
557 567
558typedef struct deppair 568typedef struct deppair
559{ 569{
560 const char *depend; 570 const char *depend;
561 const char *addto; 571 const char *addto;
562} deppair_t; 572} deppair_t;
563 573
564static const deppair_t deppairs[] = { 574static const deppair_t deppairs[] = {
565 { "ineed", "needsme" }, 575 { "ineed", "needsme" },
566 { "iuse", "usesme" }, 576 { "iuse", "usesme" },
567 { "iafter", "ibefore" }, 577 { "iafter", "ibefore" },
568 { "ibefore", "iafter" }, 578 { "ibefore", "iafter" },
569 { "iprovide", "providedby" }, 579 { "iprovide", "providedby" },
570 { NULL, NULL } 580 { NULL, NULL }
571}; 581};
572 582
573static const char *depdirs[] = 583static const char *depdirs[] =
574{ 584{
575 RC_SVCDIR "starting", 585 RC_SVCDIR "starting",
576 RC_SVCDIR "started", 586 RC_SVCDIR "started",
577 RC_SVCDIR "stopping", 587 RC_SVCDIR "stopping",
578 RC_SVCDIR "inactive", 588 RC_SVCDIR "inactive",
579 RC_SVCDIR "wasinactive", 589 RC_SVCDIR "wasinactive",
580 RC_SVCDIR "failed", 590 RC_SVCDIR "failed",
581 RC_SVCDIR "coldplugged", 591 RC_SVCDIR "coldplugged",
582 RC_SVCDIR "daemons", 592 RC_SVCDIR "daemons",
583 RC_SVCDIR "options", 593 RC_SVCDIR "options",
584 RC_SVCDIR "exclusive", 594 RC_SVCDIR "exclusive",
585 RC_SVCDIR "scheduled", 595 RC_SVCDIR "scheduled",
586 NULL 596 NULL
587}; 597};
588 598
589/* This is a 5 phase operation 599/* This is a 5 phase operation
590 Phase 1 is a shell script which loads each init script and config in turn 600 Phase 1 is a shell script which loads each init script and config in turn
591 and echos their dependency info to stdout 601 and echos their dependency info to stdout
594 Phase 4 scans that depinfo object and puts in backlinks 604 Phase 4 scans that depinfo object and puts in backlinks
595 Phase 5 saves the depinfo object to disk 605 Phase 5 saves the depinfo object to disk
596 */ 606 */
597int rc_update_deptree (bool force) 607int rc_update_deptree (bool force)
598{ 608{
599 char *depends; 609 char *depends;
600 char *service; 610 char *service;
601 char *type; 611 char *type;
602 char *depend; 612 char *depend;
603 int retval = 0; 613 int retval = 0;
604 FILE *fp; 614 FILE *fp;
605 rc_depinfo_t *deptree; 615 rc_depinfo_t *deptree;
606 rc_depinfo_t *depinfo; 616 rc_depinfo_t *depinfo;
607 rc_depinfo_t *di; 617 rc_depinfo_t *di;
608 rc_depinfo_t *last_depinfo = NULL; 618 rc_depinfo_t *last_depinfo = NULL;
609 rc_deptype_t *deptype; 619 rc_deptype_t *deptype;
610 rc_deptype_t *dt; 620 rc_deptype_t *dt;
611 rc_deptype_t *last_deptype = NULL; 621 rc_deptype_t *last_deptype = NULL;
612 char buffer[RC_LINEBUFFER]; 622 char buffer[RC_LINEBUFFER];
613 int len; 623 int len;
614 int i; 624 int i;
615 int j; 625 int j;
616 int k; 626 int k;
617 bool already_added; 627 bool already_added;
618 628
619 /* Create base directories if needed */ 629 /* Create base directories if needed */
620 for (i = 0; depdirs[i]; i++) 630 for (i = 0; depdirs[i]; i++)
621 if (! rc_is_dir (depdirs[i])) 631 if (! rc_is_dir (depdirs[i]))
622 if (mkdir (depdirs[i], 0755) != 0) 632 if (mkdir (depdirs[i], 0755) != 0)
623 eerrorx ("mkdir `%s': %s", depdirs[i], strerror (errno)); 633 eerrorx ("mkdir `%s': %s", depdirs[i], strerror (errno));
624 634
625 if (! force) 635 if (! force)
626 if (is_newer_than (RC_DEPTREE, RC_INITDIR) && 636 if (is_newer_than (RC_DEPTREE, RC_INITDIR) &&
627 is_newer_than (RC_DEPTREE, RC_CONFDIR) && 637 is_newer_than (RC_DEPTREE, RC_CONFDIR) &&
628 is_newer_than (RC_DEPTREE, "/etc/rc.conf")) 638 is_newer_than (RC_DEPTREE, "/etc/rc.conf"))
629 return 0; 639 return 0;
630 640
631 ebegin ("Caching service dependencies"); 641 ebegin ("Caching service dependencies");
632 642
633 /* Some init scripts need RC_LIBDIR to source stuff 643 /* Some init scripts need RC_LIBDIR to source stuff
634 Ideally we should be setting our full env instead */ 644 Ideally we should be setting our full env instead */
635 if (! getenv ("RC_LIBDIR")) 645 if (! getenv ("RC_LIBDIR"))
636 setenv ("RC_LIBDIR", RC_LIBDIR, 0); 646 setenv ("RC_LIBDIR", RC_LIBDIR, 0);
637 647
638 /* Phase 1 */ 648 /* Phase 1 */
639 if (! (fp = popen (GENDEP, "r"))) 649 if (! (fp = popen (GENDEP, "r")))
640 eerrorx ("popen: %s", strerror (errno)); 650 eerrorx ("popen: %s", strerror (errno));
641 651
642 deptree = rc_xmalloc (sizeof (rc_depinfo_t)); 652 deptree = rc_xmalloc (sizeof (rc_depinfo_t));
643 memset (deptree, 0, sizeof (rc_depinfo_t)); 653 memset (deptree, 0, sizeof (rc_depinfo_t));
644 memset (buffer, 0, RC_LINEBUFFER); 654 memset (buffer, 0, RC_LINEBUFFER);
645 655
646 /* Phase 2 */ 656 /* Phase 2 */
647 while (fgets (buffer, RC_LINEBUFFER, fp)) 657 while (fgets (buffer, RC_LINEBUFFER, fp))
648 { 658 {
649 /* Trim the newline */ 659 /* Trim the newline */
650 if (buffer[strlen (buffer) - 1] == '\n') 660 if (buffer[strlen (buffer) - 1] == '\n')
651 buffer[strlen(buffer) -1] = 0; 661 buffer[strlen(buffer) -1] = 0;
652 662
653 depends = buffer; 663 depends = buffer;
654 service = strsep (&depends, " "); 664 service = strsep (&depends, " ");
655 if (! service) 665 if (! service)
656 continue; 666 continue;
657 type = strsep (&depends, " "); 667 type = strsep (&depends, " ");
658 668
659 for (depinfo = deptree; depinfo; depinfo = depinfo->next) 669 for (depinfo = deptree; depinfo; depinfo = depinfo->next)
660 { 670 {
661 last_depinfo = depinfo; 671 last_depinfo = depinfo;
662 if (depinfo->service && strcmp (depinfo->service, service) == 0) 672 if (depinfo->service && strcmp (depinfo->service, service) == 0)
663 break; 673 break;
664 } 674 }
665 675
666 if (! depinfo) 676 if (! depinfo)
667 { 677 {
668 if (! last_depinfo->service) 678 if (! last_depinfo->service)
669 depinfo = last_depinfo; 679 depinfo = last_depinfo;
670 else 680 else
671 { 681 {
672 last_depinfo->next = rc_xmalloc (sizeof (rc_depinfo_t)); 682 last_depinfo->next = rc_xmalloc (sizeof (rc_depinfo_t));
673 depinfo = last_depinfo->next; 683 depinfo = last_depinfo->next;
674 } 684 }
675 memset (depinfo, 0, sizeof (rc_depinfo_t)); 685 memset (depinfo, 0, sizeof (rc_depinfo_t));
676 depinfo->service = rc_xstrdup (service); 686 depinfo->service = rc_xstrdup (service);
677 } 687 }
678 688
679 /* We may not have any depends */ 689 /* We may not have any depends */
680 if (! type || ! depends) 690 if (! type || ! depends)
681 continue; 691 continue;
682 692
683 last_deptype = NULL; 693 last_deptype = NULL;
684 for (deptype = depinfo->depends; deptype; deptype = deptype->next) 694 for (deptype = depinfo->depends; deptype; deptype = deptype->next)
685 { 695 {
686 last_deptype = deptype; 696 last_deptype = deptype;
687 if (strcmp (deptype->type, type) == 0) 697 if (strcmp (deptype->type, type) == 0)
688 break; 698 break;
689 } 699 }
690 700
691 if (! deptype) 701 if (! deptype)
692 { 702 {
693 if (! last_deptype) 703 if (! last_deptype)
694 { 704 {
695 depinfo->depends = rc_xmalloc (sizeof (rc_deptype_t)); 705 depinfo->depends = rc_xmalloc (sizeof (rc_deptype_t));
696 deptype = depinfo->depends; 706 deptype = depinfo->depends;
697 } 707 }
698 else 708 else
699 { 709 {
700 last_deptype->next = rc_xmalloc (sizeof (rc_deptype_t)); 710 last_deptype->next = rc_xmalloc (sizeof (rc_deptype_t));
701 deptype = last_deptype->next; 711 deptype = last_deptype->next;
702 } 712 }
703 memset (deptype, 0, sizeof (rc_deptype_t)); 713 memset (deptype, 0, sizeof (rc_deptype_t));
704 deptype->type = rc_xstrdup (type); 714 deptype->type = rc_xstrdup (type);
705 } 715 }
706 716
707 /* Now add each depend to our type. 717 /* Now add each depend to our type.
708 We do this individually so we handle multiple spaces gracefully */ 718 We do this individually so we handle multiple spaces gracefully */
709 while ((depend = strsep (&depends, " "))) 719 while ((depend = strsep (&depends, " ")))
710 { 720 {
711 if (depend[0] == 0) 721 if (depend[0] == 0)
712 continue; 722 continue;
713 723
714 /* .sh files are not init scripts */ 724 /* .sh files are not init scripts */
715 len = strlen (depend); 725 len = strlen (depend);
716 if (len > 2 && 726 if (len > 2 &&
717 depend[len - 3] == '.' && 727 depend[len - 3] == '.' &&
718 depend[len - 2] == 's' && 728 depend[len - 2] == 's' &&
719 depend[len - 1] == 'h') 729 depend[len - 1] == 'h')
720 continue; 730 continue;
721 731
722 deptype->services = rc_strlist_addsort (deptype->services, depend); 732 deptype->services = rc_strlist_addsort (deptype->services, depend);
723 } 733 }
724 734
725 } 735 }
726 pclose (fp); 736 pclose (fp);
727 737
728 /* Phase 3 - add our providors to the tree */ 738 /* Phase 3 - add our providors to the tree */
729 for (depinfo = deptree; depinfo; depinfo = depinfo->next) 739 for (depinfo = deptree; depinfo; depinfo = depinfo->next)
730 { 740 {
731 if ((deptype = rc_get_deptype (depinfo, "iprovide"))) 741 if ((deptype = rc_get_deptype (depinfo, "iprovide")))
732 STRLIST_FOREACH (deptype->services, service, i) 742 STRLIST_FOREACH (deptype->services, service, i)
733 { 743 {
734 for (di = deptree; di; di = di->next) 744 for (di = deptree; di; di = di->next)
735 { 745 {
736 last_depinfo = di; 746 last_depinfo = di;
737 if (strcmp (di->service, service) == 0) 747 if (strcmp (di->service, service) == 0)
738 break; 748 break;
739 } 749 }
740 if (! di) 750 if (! di)
741 { 751 {
742 last_depinfo->next = rc_xmalloc (sizeof (rc_depinfo_t)); 752 last_depinfo->next = rc_xmalloc (sizeof (rc_depinfo_t));
743 di = last_depinfo->next; 753 di = last_depinfo->next;
744 memset (di, 0, sizeof (rc_depinfo_t)); 754 memset (di, 0, sizeof (rc_depinfo_t));
745 di->service = rc_xstrdup (service); 755 di->service = rc_xstrdup (service);
746 } 756 }
747 } 757 }
748 } 758 }
749 759
750 /* Phase 4 - backreference our depends */ 760 /* Phase 4 - backreference our depends */
751 for (depinfo = deptree; depinfo; depinfo = depinfo->next) 761 for (depinfo = deptree; depinfo; depinfo = depinfo->next)
752 { 762 {
753 for (i = 0; deppairs[i].depend; i++) 763 for (i = 0; deppairs[i].depend; i++)
754 { 764 {
755 deptype = rc_get_deptype (depinfo, deppairs[i].depend); 765 deptype = rc_get_deptype (depinfo, deppairs[i].depend);
756 if (! deptype) 766 if (! deptype)
757 continue; 767 continue;
758 768
759 STRLIST_FOREACH (deptype->services, service, j) 769 STRLIST_FOREACH (deptype->services, service, j)
760 { 770 {
761 di = rc_get_depinfo (deptree, service); 771 di = rc_get_depinfo (deptree, service);
762 if (! di) 772 if (! di)
763 { 773 {
764 if (strcmp (deptype->type, "ineed") == 0) 774 if (strcmp (deptype->type, "ineed") == 0)
765 { 775 {
766 eerror ("Service `%s' needs non existant service `%s'", 776 eerror ("Service `%s' needs non existant service `%s'",
767 depinfo->service, service); 777 depinfo->service, service);
768 retval = -1; 778 retval = -1;
769 } 779 }
770 continue; 780 continue;
771 } 781 }
772 782
773 /* Add our deptype now */ 783 /* Add our deptype now */
774 last_deptype = NULL; 784 last_deptype = NULL;
775 for (dt = di->depends; dt; dt = dt->next) 785 for (dt = di->depends; dt; dt = dt->next)
776 { 786 {
777 last_deptype = dt; 787 last_deptype = dt;
778 if (strcmp (dt->type, deppairs[i].addto) == 0) 788 if (strcmp (dt->type, deppairs[i].addto) == 0)
779 break; 789 break;
780 } 790 }
781 if (! dt) 791 if (! dt)
782 { 792 {
783 if (! last_deptype) 793 if (! last_deptype)
784 { 794 {
785 di->depends = rc_xmalloc (sizeof (rc_deptype_t)); 795 di->depends = rc_xmalloc (sizeof (rc_deptype_t));
786 dt = di->depends; 796 dt = di->depends;
787 } 797 }
788 else 798 else
789 { 799 {
790 last_deptype->next = rc_xmalloc (sizeof (rc_deptype_t)); 800 last_deptype->next = rc_xmalloc (sizeof (rc_deptype_t));
791 dt = last_deptype->next; 801 dt = last_deptype->next;
792 } 802 }
793 memset (dt, 0, sizeof (rc_deptype_t)); 803 memset (dt, 0, sizeof (rc_deptype_t));
794 dt->type = rc_xstrdup (deppairs[i].addto); 804 dt->type = rc_xstrdup (deppairs[i].addto);
795 } 805 }
796 806
797 already_added = false; 807 already_added = false;
798 STRLIST_FOREACH (dt->services, service, k) 808 STRLIST_FOREACH (dt->services, service, k)
799 if (strcmp (service, depinfo->service) == 0) 809 if (strcmp (service, depinfo->service) == 0)
800 { 810 {
801 already_added = true; 811 already_added = true;
802 break; 812 break;
803 } 813 }
804 814
805 if (! already_added) 815 if (! already_added)
806 dt->services = rc_strlist_addsort (dt->services, 816 dt->services = rc_strlist_addsort (dt->services,
807 depinfo->service); 817 depinfo->service);
808 } 818 }
809 } 819 }
810 } 820 }
811 821
812 /* Phase 5 - save to disk 822 /* Phase 5 - save to disk
813 Now that we're purely in C, do we need to keep a shell parseable file? 823 Now that we're purely in C, do we need to keep a shell parseable file?
814 I think yes as then it stays human readable 824 I think yes as then it stays human readable
815 This works and should be entirely shell parseable provided that depend 825 This works and should be entirely shell parseable provided that depend
816 names don't have any non shell variable characters in 826 names don't have any non shell variable characters in
817 */ 827 */
818 if (! (fp = fopen (RC_DEPTREE, "w"))) 828 if (! (fp = fopen (RC_DEPTREE, "w")))
819 eerror ("fopen `%s': %s", RC_DEPTREE, strerror (errno)); 829 eerror ("fopen `%s': %s", RC_DEPTREE, strerror (errno));
820 else 830 else
821 { 831 {
822 i = 0; 832 i = 0;
823 for (depinfo = deptree; depinfo; depinfo = depinfo->next) 833 for (depinfo = deptree; depinfo; depinfo = depinfo->next)
824 { 834 {
825 fprintf (fp, "depinfo_%d_service='%s'\n", i, depinfo->service); 835 fprintf (fp, "depinfo_%d_service='%s'\n", i, depinfo->service);
826 for (deptype = depinfo->depends; deptype; deptype = deptype->next) 836 for (deptype = depinfo->depends; deptype; deptype = deptype->next)
827 { 837 {
828 k = 0; 838 k = 0;
829 STRLIST_FOREACH (deptype->services, service, j) 839 STRLIST_FOREACH (deptype->services, service, j)
830 { 840 {
831 fprintf (fp, "depinfo_%d_%s_%d='%s'\n", i, deptype->type, 841 fprintf (fp, "depinfo_%d_%s_%d='%s'\n", i, deptype->type,
832 k, service); 842 k, service);
833 k++; 843 k++;
834 } 844 }
835 } 845 }
836 i++; 846 i++;
837 } 847 }
838 fclose (fp); 848 fclose (fp);
839 } 849 }
840 850
841 rc_free_deptree (deptree); 851 rc_free_deptree (deptree);
842 852
843 eend (retval, "Failed to update the service dependency tree"); 853 eend (retval, "Failed to update the service dependency tree");
844 return (retval); 854 return (retval);
845} 855}
846librc_hidden_def(rc_update_deptree) 856librc_hidden_def(rc_update_deptree)

Legend:
Removed from v.2785  
changed lines
  Added in v.2786

  ViewVC Help
Powered by ViewVC 1.1.20