View | Details | Raw Unified
Collapse All | Expand All

(-) a/src/librc/librc-depend.c (-29 / +70 lines)
 Lines 182-188   valid_service(const char *runlevel, const char *service, const char *type) Link Here 
{
{
	RC_SERVICE state;
	RC_SERVICE state;
	
	
	if (strcmp(type, "ineed") == 0 ||
	if (!runlevel ||
	    strcmp(type, "ineed") == 0 ||
	    strcmp(type, "needsme") == 0)
	    strcmp(type, "needsme") == 0)
		return true;
		return true;
 Lines 251-257   get_provided1(const char *runlevel, RC_STRINGLIST *providers, Link Here 
   provided dependancy can change depending on runlevel state.
   provided dependancy can change depending on runlevel state.
   */
   */
static RC_STRINGLIST *
static RC_STRINGLIST *
get_provided (const RC_DEPINFO *depinfo, const char *runlevel, int options)
get_provided(const RC_DEPINFO *depinfo, const char *runlevel, int options)
{
{
	RC_DEPTYPE *dt;
	RC_DEPTYPE *dt;
	RC_STRINGLIST *providers = rc_stringlist_new();
	RC_STRINGLIST *providers = rc_stringlist_new();
 Lines 682-723   rc_deptree_update_needed(void) Link Here 
}
}
librc_hidden_def(rc_deptree_update_needed)
librc_hidden_def(rc_deptree_update_needed)
/* This is a 5 phase operation
/* This is a 6 phase operation
   Phase 1 is a shell script which loads each init script and config in turn
   Phase 1 is a shell script which loads each init script and config in turn
   and echos their dependency info to stdout
   and echos their dependency info to stdout
   Phase 2 takes that and populates a depinfo object with that data
   Phase 2 takes that and populates a depinfo object with that data
   Phase 3 adds any provided services to the depinfo object
   Phase 3 adds any provided services to the depinfo object
   Phase 4 scans that depinfo object and puts in backlinks
   Phase 4 scans that depinfo object and puts in backlinks
   Phase 5 saves the depinfo object to disk
   Phase 5 removes broken before dependencies
   Phase 6 saves the depinfo object to disk
   */
   */
bool
bool
rc_deptree_update(void)
rc_deptree_update(void)
{
{
	FILE *fp;
	FILE *fp;
	RC_DEPTREE *deptree;
	RC_DEPTREE *deptree, *providers;
	RC_DEPTREE *providers;
	RC_DEPINFO *depinfo = NULL, *depinfo_np, *di;
	RC_DEPINFO *depinfo = NULL;
	RC_DEPTYPE *deptype = NULL, *dt_np, *dt, *provide;
	RC_DEPINFO *depinfo_np;
	RC_STRINGLIST *config, *types, *sorted, *visited;
	RC_DEPINFO *di;
	RC_STRING *s, *s2, *s2_np, *s3, *s4;
	RC_DEPTYPE *deptype = NULL;
	RC_DEPTYPE *dt;
	RC_DEPTYPE *dt_np;
	RC_STRINGLIST *config;
	RC_STRING *s;
	RC_STRING *s2;
	RC_DEPTYPE *provide;
	char *line = NULL;
	char *line = NULL;
	size_t len = 0;
	size_t len = 0;
	char *depend;
	char *depend, *depends, *service, *type, *nosys;
	char *depends;
	size_t i, k, l;
	char *service;
	bool retval = true;
	char *type;
	size_t i;
	size_t k;
	size_t l;
	int retval = true;
	const char *sys = rc_sys();
	const char *sys = rc_sys();
	char *nosys;
	/* Some init scripts need RC_LIBDIR to source stuff
	/* Some init scripts need RC_LIBDIR to source stuff
	   Ideally we should be setting our full env instead */
	   Ideally we should be setting our full env instead */
 Lines 876-882   rc_deptree_update(void) Link Here 
			TAILQ_FOREACH(s, deptype->services, entries) {
			TAILQ_FOREACH(s, deptype->services, entries) {
				di = get_depinfo(deptree, s->value);
				di = get_depinfo(deptree, s->value);
				if (!di) {
				if (!di) {
					if (strcmp (deptype->type, "ineed") == 0)
					if (strcmp(deptype->type, "ineed") == 0)
						fprintf (stderr,
						fprintf (stderr,
							 "Service `%s' needs non"
							 "Service `%s' needs non"
							 " existant service `%s'\n",
							 " existant service `%s'\n",
 Lines 895-907   rc_deptree_update(void) Link Here 
			}
			}
		}
		}
	/* Phase 5 - save to disk
	/* Phase 5 - Remove broken before directives */
	types = rc_stringlist_new();
	rc_stringlist_add(types, "ineed");
	rc_stringlist_add(types, "iuse");
	rc_stringlist_add(types, "iafter");
	STAILQ_FOREACH(depinfo, deptree, entries) {
		deptype = get_deptype(depinfo, "ibefore");
		if (!deptype)
			continue;
		sorted = NULL;
		visited = rc_stringlist_new();
		visit_service(deptree, types, &sorted, visited, depinfo,
			      NULL, 0);
		rc_stringlist_free(visited);
		if (!sorted)
			continue;
		TAILQ_FOREACH_SAFE(s2, deptype->services, entries, s2_np) {
			TAILQ_FOREACH(s3, sorted, entries) {
				di = get_depinfo(deptree, s3->value);
				if (!di)
					continue;
				if (strcmp(s2->value, s3->value) == 0) {
					dt = get_deptype(di, "iafter");
					if (dt)
						rc_stringlist_delete(dt->services, depinfo->service);
					break;
				}
				dt = get_deptype(di, "iprovide");
				if (!dt)
					continue;
				TAILQ_FOREACH(s4, dt->services, entries) {
					if (strcmp(s4->value, s2->value) == 0)
						break;
				}
				if (s4) {
					di = get_depinfo(deptree, s4->value);
					if (di) {
						dt = get_deptype(di, "iafter");
						if (dt)
							rc_stringlist_delete(dt->services, depinfo->service);
					}
					break;
				}
			}
			if (s3)
				rc_stringlist_delete(deptype->services, s2->value);
		}
		rc_stringlist_free(sorted);
	}
	rc_stringlist_free(types);
	/* Phase 6 - save to disk
	   Now that we're purely in C, do we need to keep a shell parseable file?
	   Now that we're purely in C, do we need to keep a shell parseable file?
	   I think yes as then it stays human readable
	   I think yes as then it stays human readable
	   This works and should be entirely shell parseable provided that depend
	   This works and should be entirely shell parseable provided that depend
	   names don't have any non shell variable characters in
	   names don't have any non shell variable characters in
	   */
	   */
	if ((fp = fopen (RC_DEPTREE_CACHE, "w"))) {
	if ((fp = fopen(RC_DEPTREE_CACHE, "w"))) {
		i = 0;
		i = 0;
		STAILQ_FOREACH(depinfo, deptree, entries) {
		STAILQ_FOREACH(depinfo, deptree, entries) {
			fprintf(fp, "depinfo_%zu_service='%s'\n",
			fprintf(fp, "depinfo_%zu_service='%s'\n",
 Lines 935-945   rc_deptree_update(void) Link Here 
				RC_DEPCONFIG, strerror(errno));
				RC_DEPCONFIG, strerror(errno));
			retval = false;
			retval = false;
		}
		}
		rc_stringlist_free (config);
	} else {
	} else {
		unlink(RC_DEPCONFIG);
		unlink(RC_DEPCONFIG);
	}
	}
	rc_stringlist_free(config);
	rc_deptree_free(deptree);
	rc_deptree_free(deptree);
	return retval;
	return retval;
}
}