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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.20