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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2571 - (hide annotations) (download) (as text)
Tue Apr 10 14:03:37 2007 UTC (11 years, 4 months ago) by uberlord
File MIME type: text/x-csrc
File size: 23954 byte(s)
int -> time_t
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     if (stat (target, &buf) != 0)
524     return (false);
525    
526     if (mtime < buf.st_mtime)
527     return (false);
528    
529     if (rc_is_dir (target))
530     {
531     char **targets = rc_ls_dir (NULL, target, 0);
532     char *t;
533     int i;
534     bool newer = true;
535     STRLIST_FOREACH (targets, t, i)
536 uberlord 2569 {
537     char *path = rc_strcatpaths (target, t, (char *) NULL);
538     newer = is_newer_than (file, path);
539     free (path);
540     if (! newer)
541     break;
542     }
543 uberlord 2547 rc_strlist_free (targets);
544     return (newer);
545     }
546    
547     return (true);
548     }
549    
550     typedef struct deppair
551     {
552     const char *depend;
553     const char *addto;
554     } deppair_t;
555    
556     static const deppair_t deppairs[] = {
557     { "ineed", "needsme" },
558     { "iuse", "usesme" },
559     { "iafter", "ibefore" },
560     { "ibefore", "iafter" },
561     { "iprovide", "providedby" },
562     { NULL, NULL }
563     };
564    
565     static const char *depdirs[] =
566     {
567     RC_SVCDIR "starting",
568     RC_SVCDIR "started",
569     RC_SVCDIR "stopping",
570     RC_SVCDIR "inactive",
571     RC_SVCDIR "wasinactive",
572     RC_SVCDIR "failed",
573     RC_SVCDIR "coldplugged",
574     RC_SVCDIR "daemons",
575     RC_SVCDIR "options",
576     RC_SVCDIR "exclusive",
577     RC_SVCDIR "scheduled",
578     RC_SVCDIR "ebuffer",
579     NULL
580     };
581    
582     /* This is a 5 phase operation
583     Phase 1 is a shell script which loads each init script and config in turn
584     and echos their dependency info to stdout
585     Phase 2 takes that and populates a depinfo object with that data
586     Phase 3 adds any provided services to the depinfo object
587     Phase 4 scans that depinfo object and puts in backlinks
588     Phase 5 saves the depinfo object to disk
589     */
590     int rc_update_deptree (bool force)
591     {
592     char *depends;
593     char *service;
594     char *type;
595     char *depend;
596     int retval = 0;
597     FILE *fp;
598     rc_depinfo_t *deptree;
599     rc_depinfo_t *depinfo;
600     rc_depinfo_t *di;
601     rc_depinfo_t *last_depinfo = NULL;
602     rc_deptype_t *deptype;
603     rc_deptype_t *dt;
604     rc_deptype_t *last_deptype = NULL;
605     char buffer[RC_LINEBUFFER];
606     int len;
607     int i;
608     int j;
609     int k;
610     bool already_added;
611    
612     /* Create base directories if needed */
613     for (i = 0; depdirs[i]; i++)
614     if (! rc_is_dir (depdirs[i]))
615     if (mkdir (depdirs[i], 0755) != 0)
616 uberlord 2569 eerrorx ("mkdir `%s': %s", depdirs[i], strerror (errno));
617 uberlord 2547
618     if (! force)
619     if (is_newer_than (RC_DEPTREE, RC_INITDIR) &&
620 uberlord 2569 is_newer_than (RC_DEPTREE, RC_CONFDIR) &&
621     is_newer_than (RC_DEPTREE, "/etc/rc.conf"))
622     return 0;
623 uberlord 2547
624     ebegin ("Caching service dependencies");
625    
626     /* Some init scripts need RC_LIBDIR to source stuff
627     Ideally we should be setting our full env instead */
628     if (! getenv ("RC_LIBDIR"))
629     setenv ("RC_LIBDIR", RC_LIBDIR, 0);
630    
631     /* Phase 1 */
632 uberlord 2550 if (! (fp = popen (GENDEP, "r")))
633 uberlord 2547 eerrorx ("popen: %s", strerror (errno));
634    
635     deptree = rc_xmalloc (sizeof (rc_depinfo_t));
636     memset (deptree, 0, sizeof (rc_depinfo_t));
637     memset (buffer, 0, RC_LINEBUFFER);
638    
639     /* Phase 2 */
640     while (fgets (buffer, RC_LINEBUFFER, fp))
641     {
642     /* Trim the newline */
643     if (buffer[strlen (buffer) - 1] == '\n')
644 uberlord 2569 buffer[strlen(buffer) -1] = 0;
645 uberlord 2547
646     depends = buffer;
647     service = strsep (&depends, " ");
648     if (! service)
649 uberlord 2569 continue;
650 uberlord 2547 type = strsep (&depends, " ");
651    
652     for (depinfo = deptree; depinfo; depinfo = depinfo->next)
653 uberlord 2569 {
654     last_depinfo = depinfo;
655     if (depinfo->service && strcmp (depinfo->service, service) == 0)
656     break;
657     }
658 uberlord 2547
659     if (! depinfo)
660 uberlord 2569 {
661     if (! last_depinfo->service)
662     depinfo = last_depinfo;
663     else
664     {
665     last_depinfo->next = rc_xmalloc (sizeof (rc_depinfo_t));
666     depinfo = last_depinfo->next;
667     }
668     memset (depinfo, 0, sizeof (rc_depinfo_t));
669     depinfo->service = strdup (service);
670     }
671 uberlord 2547
672     /* We may not have any depends */
673     if (! type || ! depends)
674 uberlord 2569 continue;
675 uberlord 2547
676     last_deptype = NULL;
677     for (deptype = depinfo->depends; deptype; deptype = deptype->next)
678 uberlord 2569 {
679     last_deptype = deptype;
680     if (strcmp (deptype->type, type) == 0)
681     break;
682     }
683 uberlord 2547
684     if (! deptype)
685 uberlord 2569 {
686     if (! last_deptype)
687     {
688     depinfo->depends = rc_xmalloc (sizeof (rc_deptype_t));
689     deptype = depinfo->depends;
690     }
691     else
692     {
693     last_deptype->next = rc_xmalloc (sizeof (rc_deptype_t));
694     deptype = last_deptype->next;
695     }
696     memset (deptype, 0, sizeof (rc_deptype_t));
697     deptype->type = strdup (type);
698     }
699 uberlord 2547
700     /* Now add each depend to our type.
701 uberlord 2569 We do this individually so we handle multiple spaces gracefully */
702 uberlord 2547 while ((depend = strsep (&depends, " ")))
703 uberlord 2569 {
704     if (depend[0] == 0)
705     continue;
706 uberlord 2547
707 uberlord 2569 /* .sh files are not init scripts */
708     len = strlen (depend);
709     if (len > 2 &&
710     depend[len - 3] == '.' &&
711     depend[len - 2] == 's' &&
712     depend[len - 1] == 'h')
713     continue;
714 uberlord 2547
715 uberlord 2569 deptype->services = rc_strlist_addsort (deptype->services, depend);
716     }
717 uberlord 2547
718     }
719     pclose (fp);
720    
721     /* Phase 3 - add our providors to the tree */
722     for (depinfo = deptree; depinfo; depinfo = depinfo->next)
723     {
724     if ((deptype = rc_get_deptype (depinfo, "iprovide")))
725 uberlord 2569 STRLIST_FOREACH (deptype->services, service, i)
726     {
727     for (di = deptree; di; di = di->next)
728     {
729     last_depinfo = di;
730     if (strcmp (di->service, service) == 0)
731     break;
732     }
733     if (! di)
734     {
735     last_depinfo->next = rc_xmalloc (sizeof (rc_depinfo_t));
736     di = last_depinfo->next;
737     memset (di, 0, sizeof (rc_depinfo_t));
738     di->service = strdup (service);
739     }
740     }
741 uberlord 2547 }
742    
743     /* Phase 4 - backreference our depends */
744     for (depinfo = deptree; depinfo; depinfo = depinfo->next)
745     {
746     for (i = 0; deppairs[i].depend; i++)
747 uberlord 2569 {
748     deptype = rc_get_deptype (depinfo, deppairs[i].depend);
749     if (! deptype)
750     continue;
751 uberlord 2547
752 uberlord 2569 STRLIST_FOREACH (deptype->services, service, j)
753     {
754     di = rc_get_depinfo (deptree, service);
755     if (! di)
756     {
757     if (strcmp (deptype->type, "ineed") == 0)
758     {
759     eerror ("Service `%s' needs non existant service `%s'",
760     depinfo->service, service);
761     retval = -1;
762     }
763     continue;
764     }
765 uberlord 2547
766 uberlord 2569 /* Add our deptype now */
767     last_deptype = NULL;
768     for (dt = di->depends; dt; dt = dt->next)
769     {
770     last_deptype = dt;
771     if (strcmp (dt->type, deppairs[i].addto) == 0)
772     break;
773     }
774     if (! dt)
775     {
776     if (! last_deptype)
777     {
778     di->depends = rc_xmalloc (sizeof (rc_deptype_t));
779     dt = di->depends;
780     }
781     else
782     {
783     last_deptype->next = rc_xmalloc (sizeof (rc_deptype_t));
784     dt = last_deptype->next;
785     }
786     memset (dt, 0, sizeof (rc_deptype_t));
787     dt->type = strdup (deppairs[i].addto);
788     }
789 uberlord 2547
790 uberlord 2569 already_added = false;
791     STRLIST_FOREACH (dt->services, service, k)
792     if (strcmp (service, depinfo->service) == 0)
793     {
794     already_added = true;
795     break;
796     }
797 uberlord 2547
798 uberlord 2569 if (! already_added)
799     dt->services = rc_strlist_addsort (dt->services,
800     depinfo->service);
801     }
802     }
803 uberlord 2547 }
804    
805     /* Phase 5 - save to disk
806     Now that we're purely in C, do we need to keep a shell parseable file?
807     I think yes as then it stays human readable
808     This works and should be entirely shell parseable provided that depend
809     names don't have any non shell variable characters in
810     */
811 uberlord 2550 if (! (fp = fopen (RC_DEPTREE, "w")))
812 uberlord 2547 eerror ("fopen `%s': %s", RC_DEPTREE, strerror (errno));
813     else
814     {
815     i = 0;
816     for (depinfo = deptree; depinfo; depinfo = depinfo->next)
817 uberlord 2569 {
818     fprintf (fp, "depinfo_%d_service='%s'\n", i, depinfo->service);
819     for (deptype = depinfo->depends; deptype; deptype = deptype->next)
820     {
821     k = 0;
822     STRLIST_FOREACH (deptype->services, service, j)
823     {
824     fprintf (fp, "depinfo_%d_%s_%d='%s'\n", i, deptype->type,
825     k, service);
826     k++;
827     }
828     }
829     i++;
830     }
831 uberlord 2547 fclose (fp);
832     }
833    
834     rc_free_deptree (deptree);
835    
836     eend (retval, "Failed to update the service dependency tree");
837     return (retval);
838     }

  ViewVC Help
Powered by ViewVC 1.1.20