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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.20