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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.20