diff options
| author | Roy Marples <roy@marples.name> | 2008-10-10 08:37:21 +0000 | 
|---|---|---|
| committer | Roy Marples <roy@marples.name> | 2008-10-10 08:37:21 +0000 | 
| commit | d6da8e8c48feb8faf9287fc86fbbf0890c37a87c (patch) | |
| tree | e6cdf21f0f3a3270b705fe14b876f92b14b38dbf /src | |
| parent | 247766695cd7c5e8d83dff72f7eb7e6578bf57b8 (diff) | |
| download | openrc-d6da8e8c48feb8faf9287fc86fbbf0890c37a87c.tar.xz | |
sysinit is now a real runlevel that handles things like udev, dmesg and
mounting various bits in /dev and /sys.
init.sh JUST mounts /lib/rc/init.d (and /proc for Linux systems)
To make development of this easier we now return an empty RC_STRINGLIST
instead of a NULL for empty things.
If you don't have a udev init script installed, don't reboot your box OR
roll back to an older OpenRC version.
Diffstat (limited to 'src')
| -rw-r--r-- | src/includes/rc-misc.h | 1 | ||||
| -rw-r--r-- | src/librc/librc-depend.c | 108 | ||||
| -rw-r--r-- | src/librc/librc-misc.c | 12 | ||||
| -rw-r--r-- | src/librc/librc.c | 246 | ||||
| -rw-r--r-- | src/rc/rc-depend.c | 27 | ||||
| -rw-r--r-- | src/rc/rc-misc.c | 115 | ||||
| -rw-r--r-- | src/rc/rc-service.c | 14 | ||||
| -rw-r--r-- | src/rc/rc.c | 215 | ||||
| -rw-r--r-- | src/rc/runscript.c | 663 | 
9 files changed, 637 insertions, 764 deletions
diff --git a/src/includes/rc-misc.h b/src/includes/rc-misc.h index 12154b95..e0cfde74 100644 --- a/src/includes/rc-misc.h +++ b/src/includes/rc-misc.h @@ -143,7 +143,6 @@ char *rc_conf_value(const char *var);  bool rc_conf_yesno(const char *var);  void env_filter(void);  void env_config(void); -bool service_plugable(const char *service);  int signal_setup(int sig, void (*handler)(int));  pid_t exec_service(const char *, const char *); diff --git a/src/librc/librc-depend.c b/src/librc/librc-depend.c index 20196aff..f020e6d3 100644 --- a/src/librc/librc-depend.c +++ b/src/librc/librc-depend.c @@ -187,12 +187,21 @@ valid_service(const char *runlevel, const char *service, const char *type)  	    strcmp(type, "needsme") == 0)  		return true; +	if (rc_service_in_runlevel(service, runlevel)) +		return true; +	if (strcmp(runlevel, RC_LEVEL_SYSINIT) != 0 && +	    strcmp(runlevel, bootlevel) != 0) +	{ +		if (rc_service_in_runlevel(service, bootlevel)) +			return true; +	} +  	state = rc_service_state(service); -	return ((strcmp(runlevel, bootlevel) != 0 && -		 rc_service_in_runlevel(service, bootlevel)) || -		rc_service_in_runlevel(service, runlevel) || -		state & RC_SERVICE_COLDPLUGGED || -		state & RC_SERVICE_STARTED); +	if (state & RC_SERVICE_COLDPLUGGED || +	    state & RC_SERVICE_STARTED) +		return true; + +	return false;  }  static bool @@ -344,7 +353,7 @@ get_provided(const RC_DEPINFO *depinfo, const char *runlevel, int options)  static void  visit_service(const RC_DEPTREE *deptree,  	      const RC_STRINGLIST *types, -	      RC_STRINGLIST **sorted, +	      RC_STRINGLIST *sorted,  	      RC_STRINGLIST *visited,  	      const RC_DEPINFO *depinfo,  	      const char *runlevel, int options) @@ -373,9 +382,7 @@ visit_service(const RC_DEPTREE *deptree,  			if (!(options & RC_DEP_TRACE) ||  			    strcmp(type->value, "iprovide") == 0)  			{ -				if (!*sorted) -					*sorted = rc_stringlist_new(); -				rc_stringlist_add(*sorted, service->value); +				rc_stringlist_add(sorted, service->value);  				continue;  			} @@ -420,12 +427,10 @@ visit_service(const RC_DEPTREE *deptree,  	/* We've visited everything we need, so add ourselves unless we  	   are also the service calling us or we are provided by something */  	svcname = getenv("RC_SVCNAME"); -	if (!svcname || strcmp(svcname, depinfo->service) != 0) -		if (!get_deptype(depinfo, "providedby")) { -			if (!*sorted) -				*sorted = rc_stringlist_new(); -			rc_stringlist_add(*sorted, depinfo->service); -		} +	if (!svcname || strcmp(svcname, depinfo->service) != 0) { +		if (!get_deptype(depinfo, "providedby")) +			rc_stringlist_add(sorted, depinfo->service); +	}  }  RC_STRINGLIST * @@ -437,15 +442,15 @@ rc_deptree_depend(const RC_DEPTREE *deptree,  	RC_STRINGLIST *svcs;  	RC_STRING *svc; +	svcs = rc_stringlist_new();  	if (!(di = get_depinfo(deptree, service)) ||  	    !(dt = get_deptype(di, type)))  	{  		errno = ENOENT; -		return NULL; +		return svcs;  	}  	/* For consistency, we copy the array */ -	svcs = rc_stringlist_new();  	TAILQ_FOREACH(svc, dt->services, entries)  		rc_stringlist_add(svcs, svc->value);  	return svcs; @@ -458,7 +463,7 @@ rc_deptree_depends(const RC_DEPTREE *deptree,  		   const RC_STRINGLIST *services,  		   const char *runlevel, int options)  { -	RC_STRINGLIST *sorted = NULL; +	RC_STRINGLIST *sorted = rc_stringlist_new();  	RC_STRINGLIST *visited = rc_stringlist_new();  	RC_DEPINFO *di;  	const RC_STRING *service; @@ -472,7 +477,7 @@ rc_deptree_depends(const RC_DEPTREE *deptree,  			continue;  		}  		if (types) -			visit_service(deptree, types, &sorted, visited, +			visit_service(deptree, types, sorted, visited,  				      di, runlevel, options);  	}  	rc_stringlist_free(visited); @@ -499,42 +504,25 @@ rc_deptree_order(const RC_DEPTREE *deptree, const char *runlevel, int options)  	{  		list = rc_services_in_state(RC_SERVICE_STARTED);  		list2 = rc_services_in_state(RC_SERVICE_INACTIVE); -		if (list2) { -			if (list) { -				TAILQ_CONCAT(list, list2, entries); -				free(list2); -			} else -				list = list2; -		} +		TAILQ_CONCAT(list, list2, entries); +		free(list2);  		list2 = rc_services_in_state(RC_SERVICE_STARTING); -		if (list2) { -			if (list) { -				TAILQ_CONCAT(list, list2, entries); -				free(list2); -			} else -				list = list2; -		} +		TAILQ_CONCAT(list, list2, entries); +		free(list2);  	} else { -		list = rc_services_in_runlevel(runlevel); -		/* Add coldplugged services */ -		list2 = rc_services_in_state(RC_SERVICE_COLDPLUGGED); -		if (list2) { -			if (list) { +		list = rc_services_in_runlevel(RC_LEVEL_SYSINIT); +		if (strcmp(runlevel, RC_LEVEL_SYSINIT) != 0) { +			list2 = rc_services_in_runlevel(runlevel); +			TAILQ_CONCAT(list, list2, entries); +			free(list2); +			list2 = rc_services_in_state(RC_SERVICE_COLDPLUGGED); +			TAILQ_CONCAT(list, list2, entries); +			free(list2); +			/* If we're not the boot runlevel then add that too */ +			if (strcmp(runlevel, bootlevel) != 0) { +				list2 = rc_services_in_runlevel(bootlevel);  				TAILQ_CONCAT(list, list2, entries);  				free(list2); -			} else -				list = list2; -		} - -		/* If we're not the boot runlevel then add that too */ -		if (strcmp(runlevel, bootlevel) != 0) { -			list2 = rc_services_in_runlevel (bootlevel); -			if (list2) { -				if (list) { -					TAILQ_CONCAT(list, list2, entries); -					free(list2); -				} else -					list = list2;  			}  		}  	} @@ -683,15 +671,13 @@ rc_deptree_update_needed(void)  	/* Some init scripts dependencies change depending on config files  	 * outside of baselayout, like syslog-ng, so we check those too. */  	config = rc_config_list(RC_DEPCONFIG); -	if (config) { -		TAILQ_FOREACH(s, config, entries) { -			if (!rc_newer_than(RC_DEPTREE_CACHE, s->value)) { -				newer = true; -				break; -			} +	TAILQ_FOREACH(s, config, entries) { +		if (!rc_newer_than(RC_DEPTREE_CACHE, s->value)) { +			newer = true; +			break;  		} -		rc_stringlist_free(config);  	} +	rc_stringlist_free(config);  	return newer;  }  librc_hidden_def(rc_deptree_update_needed) @@ -907,13 +893,11 @@ rc_deptree_update(void)  		deptype = get_deptype(depinfo, "ibefore");  		if (!deptype)  			continue; -		sorted = NULL; +		sorted = rc_stringlist_new();  		visited = rc_stringlist_new(); -		visit_service(deptree, types, &sorted, visited, depinfo, +		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); diff --git a/src/librc/librc-misc.c b/src/librc/librc-misc.c index b6157009..749fd812 100644 --- a/src/librc/librc-misc.c +++ b/src/librc/librc-misc.c @@ -84,10 +84,10 @@ RC_STRINGLIST *rc_config_list(const char *file)  	size_t len = 0;  	char *p;  	char *token; -	RC_STRINGLIST *list = NULL; +	RC_STRINGLIST *list = rc_stringlist_new();  	if (!(fp = fopen(file, "r"))) -		return NULL; +		return list;  	while ((rc_getline(&buffer, &len, fp))) {  		p = buffer; @@ -104,8 +104,6 @@ RC_STRINGLIST *rc_config_list(const char *file)  				if (token[strlen(token) - 1] == '\n')  					token[strlen(token) - 1] = 0; -				if (!list) -					list = rc_stringlist_new();  				rc_stringlist_add(list, token);  			}  		} @@ -131,9 +129,6 @@ RC_STRINGLIST *rc_config_load(const char *file)  	char *p;  	list = rc_config_list(file); -	if (!list) -		return NULL; -  	config = rc_stringlist_new();  	TAILQ_FOREACH(line, list, entries) {  		/* Get entry */ @@ -203,9 +198,6 @@ char *rc_config_value(RC_STRINGLIST *list, const char *entry)  	RC_STRING *line;  	char *p; -	if (!list) -		return NULL; -  	TAILQ_FOREACH(line, list, entries) {  		p = strchr(line->value, '=');  		if (p && diff --git a/src/librc/librc.c b/src/librc/librc.c index e97425ef..b625b06a 100644 --- a/src/librc/librc.c +++ b/src/librc/librc.c @@ -67,7 +67,8 @@ static const rc_service_state_name_t rc_service_state_names[] = {  #define LS_INITD	0x01  #define LS_DIR   0x02 -static RC_STRINGLIST *ls_dir(const char *dir, int options) +static RC_STRINGLIST * +ls_dir(const char *dir, int options)  {  	DIR *dp;  	struct dirent *d; @@ -77,15 +78,15 @@ static RC_STRINGLIST *ls_dir(const char *dir, int options)  	char file[PATH_MAX];  	int r; +	list = rc_stringlist_new();  	if ((dp = opendir(dir)) == NULL) -		return NULL; - +		return list;  	while (((d = readdir(dp)) != NULL)) {  		if (d->d_name[0] != '.') {  			if (options & LS_INITD) {  				/* Check that our file really exists. -				 * This is important as a service maybe in a runlevel, but -				 * could also have been removed. */ +				 * This is important as a service maybe in a +				 * runlevel, but could have been removed. */  				snprintf(file, sizeof(file), "%s/%s",  					 dir, d->d_name);  				r = stat(file, &buf); @@ -104,17 +105,15 @@ static RC_STRINGLIST *ls_dir(const char *dir, int options)  				    ! S_ISDIR(buf.st_mode))  					continue;  			} -			if (! list) -				list = rc_stringlist_new();  			rc_stringlist_add(list, d->d_name);  		}  	}  	closedir(dp); -  	return list;  } -static bool rm_dir(const char *pathname, bool top) +static bool +rm_dir(const char *pathname, bool top)  {  	DIR *dp;  	struct dirent *d; @@ -127,16 +126,17 @@ static bool rm_dir(const char *pathname, bool top)  	errno = 0;  	while (((d = readdir(dp)) != NULL) && errno == 0) { -		if (strcmp(d->d_name, ".") != 0 && strcmp(d->d_name, "..") != 0) { -			snprintf(file, sizeof(file), "%s/%s", pathname, d->d_name); -			 +		if (strcmp(d->d_name, ".") != 0 && +		    strcmp(d->d_name, "..") != 0) +		{ +			snprintf(file, sizeof(file), +				 "%s/%s", pathname, d->d_name);  			if (stat(file, &s) != 0) {  				retval = false;  				break;  			} -  			if (S_ISDIR(s.st_mode)) { -				if (! rm_dir(file, true)) +				if (!rm_dir(file, true))  				{  					retval = false;  					break; @@ -151,7 +151,7 @@ static bool rm_dir(const char *pathname, bool top)  	}  	closedir(dp); -	if (! retval) +	if (!retval)  		return false;  	if (top && rmdir(pathname) != 0) @@ -162,7 +162,8 @@ static bool rm_dir(const char *pathname, bool top)  /* Other systems may need this at some point, but for now it's Linux only */  #ifdef __linux__ -static bool file_regex(const char *file, const char *regex) +static bool +file_regex(const char *file, const char *regex)  {  	FILE *fp;  	char *line = NULL; @@ -171,12 +172,12 @@ static bool file_regex(const char *file, const char *regex)  	bool retval = false;  	int result; -	if (! (fp = fopen(file, "r"))) +	if (!(fp = fopen(file, "r")))  		return false;  	if ((result = regcomp(&re, regex, REG_EXTENDED | REG_NOSUB)) != 0) {  		fclose(fp); -		line = xmalloc(sizeof (char) * BUFSIZ); +		line = xmalloc(sizeof(char) * BUFSIZ);  		regerror(result, &re, line, BUFSIZ);  		fprintf(stderr, "file_regex: %s", line);  		free(line); @@ -197,8 +198,8 @@ static bool file_regex(const char *file, const char *regex)  }  #endif - -const char *rc_sys(void) +const char * +rc_sys(void)  {  #ifdef PREFIX  	return RC_SYS_PREFIX; @@ -242,7 +243,8 @@ const char *rc_sys(void)  }  librc_hidden_def(rc_sys) -static const char *rc_parse_service_state(RC_SERVICE state) +static const char * +rc_parse_service_state(RC_SERVICE state)  {  	int i; @@ -250,17 +252,18 @@ static const char *rc_parse_service_state(RC_SERVICE state)  		if (rc_service_state_names[i].state == state)  			return rc_service_state_names[i].name;  	} -  	return NULL;  } -bool rc_runlevel_starting(void) +bool +rc_runlevel_starting(void)  {  	return exists(RC_STARTING);  }  librc_hidden_def(rc_runlevel_starting) -bool rc_runlevel_stopping(void) +bool +rc_runlevel_stopping(void)  {  	return exists(RC_STOPPING);  } @@ -272,15 +275,17 @@ RC_STRINGLIST *rc_runlevel_list(void)  }  librc_hidden_def(rc_runlevel_list) -char *rc_runlevel_get(void) +char * +rc_runlevel_get(void)  {  	FILE *fp;  	char *runlevel = NULL; +	size_t i;  	if ((fp = fopen(RC_RUNLEVEL, "r"))) {  		runlevel = xmalloc(sizeof(char) * PATH_MAX);  		if (fgets(runlevel, PATH_MAX, fp)) { -			int i = strlen(runlevel) - 1; +			i = strlen(runlevel) - 1;  			if (runlevel[i] == '\n')  				runlevel[i] = 0;  		} else @@ -288,7 +293,7 @@ char *rc_runlevel_get(void)  		fclose(fp);  	} -	if (! runlevel || ! *runlevel) { +	if (!runlevel || !*runlevel) {  		free(runlevel);  		runlevel = xstrdup(RC_LEVEL_SYSINIT);  	} @@ -297,11 +302,12 @@ char *rc_runlevel_get(void)  }  librc_hidden_def(rc_runlevel_get) -bool rc_runlevel_set(const char *runlevel) +bool +rc_runlevel_set(const char *runlevel)  {  	FILE *fp = fopen(RC_RUNLEVEL, "w"); -	if (! fp) +	if (!fp)  		return false;  	fprintf(fp, "%s", runlevel);  	fclose(fp); @@ -309,14 +315,14 @@ bool rc_runlevel_set(const char *runlevel)  }  librc_hidden_def(rc_runlevel_set) -bool rc_runlevel_exists(const char *runlevel) +bool +rc_runlevel_exists(const char *runlevel)  {  	char path[PATH_MAX];  	struct stat buf; -	if (! runlevel) +	if (!runlevel)  		return false; -  	snprintf(path, sizeof(path), "%s/%s", RC_RUNLEVELDIR, runlevel);  	if (stat(path, &buf) == 0 && S_ISDIR(buf.st_mode))  		return true; @@ -325,14 +331,15 @@ bool rc_runlevel_exists(const char *runlevel)  librc_hidden_def(rc_runlevel_exists)  /* Resolve a service name to it's full path */ -char *rc_service_resolve(const char *service) +char * +rc_service_resolve(const char *service)  {  	char buffer[PATH_MAX];  	char file[PATH_MAX];  	int r;  	struct stat buf; -	if (! service) +	if (!service)  		return NULL;  	if (service[0] == '/') @@ -377,14 +384,15 @@ char *rc_service_resolve(const char *service)  }  librc_hidden_def(rc_service_resolve) -bool rc_service_exists(const char *service) +bool +rc_service_exists(const char *service)  {  	char *file;  	bool retval = false;  	int len;  	struct stat buf; -	if (! service) +	if (!service)  		return false;  	len = strlen(service); @@ -395,7 +403,7 @@ bool rc_service_exists(const char *service)  	    service[len - 1] == 'h')  		return false; -	if (! (file = rc_service_resolve(service))) +	if (!(file = rc_service_resolve(service)))  		return false;  	if (stat(file, &buf) == 0 && buf.st_mode & S_IXUGO) @@ -406,7 +414,8 @@ bool rc_service_exists(const char *service)  librc_hidden_def(rc_service_exists)  #define OPTSTR ". '%s'; echo \"${opts}\"" -RC_STRINGLIST *rc_service_extra_commands(const char *service) +RC_STRINGLIST * +rc_service_extra_commands(const char *service)  {  	char *svc;  	char *cmd = NULL; @@ -418,10 +427,9 @@ RC_STRINGLIST *rc_service_extra_commands(const char *service)  	FILE *fp;  	size_t l; -	if (! (svc = rc_service_resolve(service))) +	if (!(svc = rc_service_resolve(service)))  		return NULL; -  	l = strlen(OPTSTR) + strlen(svc) + 1;  	cmd = xmalloc(sizeof(char) * l);  	snprintf(cmd, l, OPTSTR, svc); @@ -431,7 +439,7 @@ RC_STRINGLIST *rc_service_extra_commands(const char *service)  		rc_getline(&buffer, &len, fp);  		p = buffer;  		while ((token = strsep(&p, " "))) { -			if (! commands) +			if (!commands)  				commands = rc_stringlist_new();  			rc_stringlist_add(commands, token);  		} @@ -444,7 +452,8 @@ RC_STRINGLIST *rc_service_extra_commands(const char *service)  librc_hidden_def(rc_service_extra_commands)  #define DESCSTR ". '%s'; echo \"${description%s%s}\"" -char *rc_service_description(const char *service, const char *option) +char * +rc_service_description(const char *service, const char *option)  {  	char *svc;  	char *cmd; @@ -453,7 +462,7 @@ char *rc_service_description(const char *service, const char *option)  	FILE *fp;  	size_t l; -	if (! (svc = rc_service_resolve(service))) +	if (!(svc = rc_service_resolve(service)))  		return NULL;  	if (!option) @@ -472,7 +481,8 @@ char *rc_service_description(const char *service, const char *option)  }  librc_hidden_def(rc_service_description) -bool rc_service_in_runlevel(const char *service, const char *runlevel) +bool +rc_service_in_runlevel(const char *service, const char *runlevel)  {  	char file[PATH_MAX]; @@ -482,7 +492,8 @@ bool rc_service_in_runlevel(const char *service, const char *runlevel)  }  librc_hidden_def(rc_service_in_runlevel) -bool rc_service_mark(const char *service, const RC_SERVICE state) +bool +rc_service_mark(const char *service, const RC_SERVICE state)  {  	char file[PATH_MAX];  	int i = 0; @@ -496,11 +507,10 @@ bool rc_service_mark(const char *service, const RC_SERVICE state)  	RC_STRING *dir;  	int serrno; -	if (! init) +	if (!init)  		return false;  	base = basename_c(service); -  	if (state != RC_SERVICE_STOPPED) {  		if (!exists(init)) {  			free(init); @@ -583,29 +593,26 @@ bool rc_service_mark(const char *service, const RC_SERVICE state)  	if (state == RC_SERVICE_STARTED || state == RC_SERVICE_STOPPED) {  		snprintf(file, sizeof(file), RC_SVCDIR "/%s", "scheduled");  		dirs = ls_dir(file, 0); -		if (dirs) { -			TAILQ_FOREACH(dir, dirs, entries) { -				snprintf(was, sizeof(was), "%s/%s/%s", -					 file, dir->value, base); -				unlink(was); - -				/* Try and remove the dir - we don't care about errors */ -				snprintf(was, sizeof(was), "%s/%s", -					 file, dir->value); -				serrno = errno; -				rmdir(was); -				errno = serrno; -			} -			rc_stringlist_free(dirs); +		TAILQ_FOREACH(dir, dirs, entries) { +			snprintf(was, sizeof(was), "%s/%s/%s", +				 file, dir->value, base); +			unlink(was); + +			/* Try and remove the dir; we don't care about errors */ +			snprintf(was, sizeof(was), "%s/%s", file, dir->value); +			serrno = errno; +			rmdir(was); +			errno = serrno;  		} +		rc_stringlist_free(dirs);  	} -  	free(init);  	return true;  }  librc_hidden_def(rc_service_mark) -RC_SERVICE rc_service_state(const char *service) +RC_SERVICE +rc_service_state(const char *service)  {  	int i;  	int state = RC_SERVICE_STOPPED; @@ -627,25 +634,24 @@ RC_SERVICE rc_service_state(const char *service)  	if (state & RC_SERVICE_STOPPED) {  		dirs = ls_dir(RC_SVCDIR "/scheduled", 0); -		if (dirs) { -			TAILQ_FOREACH (dir, dirs, entries) { -				snprintf(file, sizeof(file), -					 RC_SVCDIR "/scheduled/%s/%s", -					 dir->value, service); -				if (exists(file)) { -					state |= RC_SERVICE_SCHEDULED; -					break; -				} +		TAILQ_FOREACH (dir, dirs, entries) { +			snprintf(file, sizeof(file), +				 RC_SVCDIR "/scheduled/%s/%s", +				 dir->value, service); +			if (exists(file)) { +				state |= RC_SERVICE_SCHEDULED; +				break;  			} -			rc_stringlist_free(dirs);  		} +		rc_stringlist_free(dirs);  	}  	return state;  }  librc_hidden_def(rc_service_state) -char *rc_service_value_get(const char *service, const char *option) +char * +rc_service_value_get(const char *service, const char *option)  {  	FILE *fp;  	char *line = NULL; @@ -663,8 +669,9 @@ char *rc_service_value_get(const char *service, const char *option)  }  librc_hidden_def(rc_service_value_get) -bool rc_service_value_set(const char *service, const char *option, -			  const char *value) +bool +rc_service_value_set(const char *service, const char *option, +		     const char *value)  {  	FILE *fp;  	char file[PATH_MAX]; @@ -685,8 +692,8 @@ bool rc_service_value_set(const char *service, const char *option,  librc_hidden_def(rc_service_value_set) -bool rc_service_schedule_start(const char *service, -			       const char *service_to_start) +bool +rc_service_schedule_start(const char *service, const char *service_to_start)  {  	char file[PATH_MAX];  	char *p = file; @@ -703,32 +710,34 @@ bool rc_service_schedule_start(const char *service,  		return false;  	init = rc_service_resolve(service_to_start); -	snprintf(p, sizeof(file) - (p - file), "/%s", basename_c(service_to_start)); +	snprintf(p, sizeof(file) - (p - file), +		 "/%s", basename_c(service_to_start));  	retval = (exists(file) || symlink(init, file) == 0);  	free(init); -  	return retval;  }  librc_hidden_def(rc_service_schedule_start) -bool rc_service_schedule_clear(const char *service) +bool +rc_service_schedule_clear(const char *service)  {  	char dir[PATH_MAX];  	snprintf(dir, sizeof(dir), RC_SVCDIR "/scheduled/%s",  		 basename_c(service)); -	if (! rm_dir(dir, true) && errno == ENOENT) +	if (!rm_dir(dir, true) && errno == ENOENT)  		return true;  	return false;  }  librc_hidden_def(rc_service_schedule_clear) -RC_STRINGLIST *rc_services_in_runlevel(const char *runlevel) +RC_STRINGLIST * +rc_services_in_runlevel(const char *runlevel)  {  	char dir[PATH_MAX]; -	RC_STRINGLIST *list; +	RC_STRINGLIST *list = NULL; -	if (! runlevel) { +	if (!runlevel) {  #ifdef RC_PKG_INITDIR  		RC_STRINGLIST *pkg = ls_dir(RC_PKG_INITDIR, LS_INITD);  #endif @@ -739,36 +748,32 @@ RC_STRINGLIST *rc_services_in_runlevel(const char *runlevel)  		list = ls_dir(RC_INITDIR, LS_INITD);  #ifdef RC_PKG_INITDIR -		if (pkg) { -			TAILQ_CONCAT(list, pkg, entries); -			free(pkg); -		} +		TAILQ_CONCAT(list, pkg, entries); +		free(pkg);  #endif  #ifdef RC_LOCAL_INITDIR -		if (local) { -			TAILQ_CONCAT(list, local, entries); -			free(local); -		} +		TAILQ_CONCAT(list, local, entries); +		free(local);  #endif  		return list;  	}  	/* These special levels never contain any services */ -	if (strcmp(runlevel, RC_LEVEL_SYSINIT) == 0 || -	    strcmp(runlevel, RC_LEVEL_SINGLE) == 0) { -		return NULL;  +	if (strcmp(runlevel, RC_LEVEL_SINGLE) != 0) { +		snprintf(dir, sizeof(dir), RC_RUNLEVELDIR "/%s", runlevel); +		list = ls_dir(dir, LS_INITD);  	} - -	snprintf(dir, sizeof(dir), RC_RUNLEVELDIR "/%s", runlevel); -	list = ls_dir(dir, LS_INITD); +	if (!list) +		list = rc_stringlist_new();  	return list;  }  librc_hidden_def(rc_services_in_runlevel) -RC_STRINGLIST *rc_services_in_state(RC_SERVICE state) +RC_STRINGLIST * +rc_services_in_state(RC_SERVICE state)  {  	RC_STRINGLIST *services; -	RC_STRINGLIST *list = NULL; +	RC_STRINGLIST *list;  	RC_STRINGLIST *dirs;  	RC_STRING *d;  	char dir[PATH_MAX]; @@ -780,28 +785,26 @@ RC_STRINGLIST *rc_services_in_state(RC_SERVICE state)  	if (state != RC_SERVICE_SCHEDULED)  		return ls_dir(dir, LS_INITD); -  	dirs = ls_dir(dir, 0); +	list = rc_stringlist_new();  	if (! dirs) -		return NULL; +		return list;  	TAILQ_FOREACH(d, dirs, entries) {  		snprintf(p, sizeof(dir) - (p - dir), "/%s", d->value);  		services = ls_dir(dir, LS_INITD); -		if (! list) -			services = list; -		else if (services) { +		if (services) {  			TAILQ_CONCAT(list, services, entries);  			free(services);  		}  	}  	rc_stringlist_free(dirs); -  	return list;  }  librc_hidden_def(rc_services_in_state) -bool rc_service_add(const char *runlevel, const char *service) +bool +rc_service_add(const char *runlevel, const char *service)  {  	bool retval;  	char *init; @@ -811,7 +814,7 @@ bool rc_service_add(const char *runlevel, const char *service)  	char binit[PATH_MAX];  	char *i; -	if (! rc_runlevel_exists(runlevel)) { +	if (!rc_runlevel_exists(runlevel)) {  		errno = ENOENT;  		return false;  	} @@ -827,12 +830,11 @@ bool rc_service_add(const char *runlevel, const char *service)  	/* We need to ensure that only things in /etc/init.d are added  	 * to the boot runlevel */ -	if (strcmp (runlevel, RC_LEVEL_BOOT) == 0) { +	if (strcmp(runlevel, RC_LEVEL_BOOT) == 0) {  		p = realpath(dirname(init), path); -		if (! *p) { +		if (!*p) {  			free(init);  			return false; -  		}  		if (strcmp(path, RC_INITDIR) != 0) {  			free(init); @@ -849,7 +851,8 @@ bool rc_service_add(const char *runlevel, const char *service)  }  librc_hidden_def(rc_service_add) -bool rc_service_delete (const char *runlevel, const char *service) +bool +rc_service_delete(const char *runlevel, const char *service)  {  	char file[PATH_MAX]; @@ -861,32 +864,27 @@ bool rc_service_delete (const char *runlevel, const char *service)  }  librc_hidden_def(rc_service_delete) -RC_STRINGLIST *rc_services_scheduled_by(const char *service) +RC_STRINGLIST * +rc_services_scheduled_by(const char *service)  {  	RC_STRINGLIST *dirs = ls_dir(RC_SVCDIR "/scheduled", 0); -	RC_STRINGLIST *list = NULL; +	RC_STRINGLIST *list = rc_stringlist_new();  	RC_STRING *dir;  	char file[PATH_MAX]; -	if (! dirs) -		return NULL; -  	TAILQ_FOREACH (dir, dirs, entries) {  		snprintf(file, sizeof(file), RC_SVCDIR "/scheduled/%s/%s",  			 dir->value, service); -		if (exists(file)) { -			if (! list) -				list = rc_stringlist_new(); +		if (exists(file))  			rc_stringlist_add(list, file); -		}  	}  	rc_stringlist_free(dirs); -  	return list;  }  librc_hidden_def(rc_services_scheduled_by) -RC_STRINGLIST *rc_services_scheduled(const char *service) +RC_STRINGLIST * +rc_services_scheduled(const char *service)  {  	char dir[PATH_MAX]; diff --git a/src/rc/rc-depend.c b/src/rc/rc-depend.c index 1166d4c6..1cd32ffd 100644 --- a/src/rc/rc-depend.c +++ b/src/rc/rc-depend.c @@ -48,7 +48,8 @@  extern const char *applet; -RC_DEPTREE *_rc_deptree_load(int *regen) { +RC_DEPTREE * +_rc_deptree_load(int *regen) {  	int fd;  	int retval;  	int serrno = errno; @@ -65,12 +66,10 @@ RC_DEPTREE *_rc_deptree_load(int *regen) {  		if (regen)  			*regen = 1; -  		ebegin("Caching service dependencies");  		retval = rc_deptree_update();  		eend (retval ? 0 : -1, "Failed to update the dependency tree");  	} -  	return rc_deptree_load();  } @@ -96,7 +95,8 @@ static const char * const longopts_help[] = {  };  #include "_usage.c" -int rc_depend(int argc, char **argv) +int +rc_depend(int argc, char **argv)  {  	RC_STRINGLIST *list;  	RC_STRINGLIST *types; @@ -112,7 +112,6 @@ int rc_depend(int argc, char **argv)  	char *token;  	types = rc_stringlist_new(); -  	while ((opt = getopt_long(argc, argv, getoptstring,  				  longopts, (int *) 0)) != -1)  	{ @@ -145,14 +144,14 @@ int rc_depend(int argc, char **argv)  		ebegin("Caching service dependencies");  		update = rc_deptree_update();  		eend(update ? 0 : -1, "%s: %s", applet, strerror(errno)); -		if (! update) +		if (!update)  			eerrorx("Failed to update the dependency tree");  	} -	if (! (deptree = _rc_deptree_load(NULL))) +	if (!(deptree = _rc_deptree_load(NULL)))  		eerrorx("failed to load deptree"); -	if (! runlevel) +	if (!runlevel)  		runlevel = rc_runlevel_get();  	services = rc_stringlist_new(); @@ -161,8 +160,9 @@ int rc_depend(int argc, char **argv)  		rc_stringlist_add(list, argv[optind]);  		errno = 0;  		depends = rc_deptree_depends(deptree, NULL, list, runlevel, 0); -		if (! depends && errno == ENOENT) -			eerror("no dependency info for service `%s'", argv[optind]); +		if (!depends && errno == ENOENT) +			eerror("no dependency info for service `%s'", +			       argv[optind]);  		else  			rc_stringlist_add(services, argv[optind]); @@ -170,7 +170,7 @@ int rc_depend(int argc, char **argv)  		rc_stringlist_free(list);  		optind++;  	} -	if (! TAILQ_FIRST(services)) { +	if (!TAILQ_FIRST(services)) {  		rc_stringlist_free(services);  		rc_stringlist_free(types);  		rc_deptree_free(deptree); @@ -181,12 +181,13 @@ int rc_depend(int argc, char **argv)  	}  	/* If we don't have any types, then supply some defaults */ -	if (! TAILQ_FIRST(types)) { +	if (!TAILQ_FIRST(types)) {  		rc_stringlist_add(types, "ineed");  		rc_stringlist_add(types, "iuse");  	} -	depends = rc_deptree_depends(deptree, types, services, runlevel, options); +	depends = rc_deptree_depends(deptree, types, services, +				     runlevel, options);  	if (TAILQ_FIRST(depends)) {  		TAILQ_FOREACH(s, depends, entries) { diff --git a/src/rc/rc-misc.c b/src/rc/rc-misc.c index 27846382..58af1418 100644 --- a/src/rc/rc-misc.c +++ b/src/rc/rc-misc.c @@ -62,13 +62,15 @@ static RC_STRINGLIST *rc_conf = NULL;  extern char** environ;  #ifdef DEBUG_MEMORY -static void _free_rc_conf(void) +static void +_free_rc_conf(void)  {  	rc_stringlist_free(rc_conf);  }  #endif -char *rc_conf_value(const char *setting) +char * +rc_conf_value(const char *setting)  {  	RC_STRINGLIST *old;  	RC_STRING *s; @@ -83,31 +85,28 @@ char *rc_conf_value(const char *setting)  		/* Support old configs */  		if (exists(RC_CONF_OLD)) {  			old = rc_config_load(RC_CONF_OLD); -			if (old) { -				if (rc_conf) { -					TAILQ_CONCAT(rc_conf, old, entries); -					free(old); -				} else -					rc_conf = old; -			} +			TAILQ_CONCAT(rc_conf, old, entries); +#ifdef DEBUG_MEMORY +			free(old); +#endif  		}  		/* Convert old uppercase to lowercase */ -		if (rc_conf) -			TAILQ_FOREACH(s, rc_conf, entries) { -				p = s->value; -				while (p && *p && *p != '=') { -					if (isupper((unsigned char)*p)) -						*p = tolower((unsigned char)*p); -					p++; -				} +		TAILQ_FOREACH(s, rc_conf, entries) { +			p = s->value; +			while (p && *p && *p != '=') { +				if (isupper((unsigned char)*p)) +					*p = tolower((unsigned char)*p); +				p++;  			} +		}  	}  	return rc_config_value(rc_conf, setting);  } -bool rc_conf_yesno(const char *setting) +bool +rc_conf_yesno(const char *setting)  {  	return rc_yesno(rc_conf_value (setting));  } @@ -122,10 +121,11 @@ static const char *const env_whitelist[] = {  	NULL  }; -void env_filter(void) +void +env_filter(void)  {  	RC_STRINGLIST *env_allow; -	RC_STRINGLIST *profile = NULL; +	RC_STRINGLIST *profile;  	RC_STRINGLIST *env_list;  	RC_STRING *env;  	char *e; @@ -133,8 +133,7 @@ void env_filter(void)  	/* Add the user defined list of vars */  	env_allow = rc_stringlist_split(rc_conf_value("rc_env_allow"), " "); -	if (exists(PROFILE_ENV)) -		profile = rc_config_load(PROFILE_ENV); +	profile = rc_config_load(PROFILE_ENV);  	/* Copy the env and work from this so we can manipulate it safely */  	env_list = rc_stringlist_new(); @@ -163,21 +162,22 @@ void env_filter(void)  	}  	/* Now add anything missing from the profile */ -	if (profile) { -		TAILQ_FOREACH(env, profile, entries) { -			e = strchr(env->value, '='); -			*e = '\0'; -			if (!getenv(env->value)) -				setenv(env->value, e + 1, 1); -		} +	TAILQ_FOREACH(env, profile, entries) { +		e = strchr(env->value, '='); +		*e = '\0'; +		if (!getenv(env->value)) +			setenv(env->value, e + 1, 1);  	} -		 + +#ifdef DEBUG_MEMORY  	rc_stringlist_free(env_list);  	rc_stringlist_free(env_allow);  	rc_stringlist_free(profile); +#endif  } -void env_config(void) +void +env_config(void)  {  	size_t pplen = strlen(PATH_PREFIX);  	char *path; @@ -203,7 +203,8 @@ void env_config(void)  		e = p = xmalloc(sizeof(char) * l);  		p += snprintf(p, l, "%s", PATH_PREFIX); -		/* Now go through the env var and only add bits not in our PREFIX */ +		/* Now go through the env var and only add bits not in our +		 * PREFIX */  		while ((token = strsep(&path, ":"))) {  			np = npp = xstrdup(PATH_PREFIX);  			while ((tok = strsep(&npp, ":"))) @@ -259,48 +260,8 @@ void env_config(void)  		setenv("EINFO_COLOR", "NO", 1);  } -bool service_plugable(const char *service) -{ -	char *list; -	char *p; -	char *star; -	char *token; -	bool allow = true; -	char *match = rc_conf_value("rc_plug_services"); -	bool truefalse; - -	if (! match) -		return true; - -	list = xstrdup(match); -	p = list; -	while ((token = strsep(&p, " "))) { -		if (token[0] == '!') { -			truefalse = false; -			token++; -		} else -			truefalse = true; - -		star = strchr(token, '*'); -		if (star) { -			if (strncmp(service, token, (size_t)(star - token)) == 0) -			{ -				allow = truefalse; -				break; -			} -		} else { -			if (strcmp(service, token) == 0) { -				allow = truefalse; -				break; -			} -		} -	} - -	free(list); -	return allow; -} - -int signal_setup(int sig, void (*handler)(int)) +int +signal_setup(int sig, void (*handler)(int))  {  	struct sigaction sa; @@ -310,7 +271,8 @@ int signal_setup(int sig, void (*handler)(int))  	return sigaction(sig, &sa, NULL);  } -pid_t exec_service(const char *service, const char *arg) +pid_t +exec_service(const char *service, const char *arg)  {  	char *file;  	char fifo[PATH_MAX]; @@ -320,7 +282,7 @@ pid_t exec_service(const char *service, const char *arg)  	struct sigaction sa;  	file = rc_service_resolve(service); -	if (! exists(file)) { +	if (!exists(file)) {  		rc_service_mark(service, RC_SERVICE_STOPPED);  		free(file);  		return 0; @@ -368,7 +330,6 @@ pid_t exec_service(const char *service, const char *arg)  	sigprocmask(SIG_SETMASK, &old, NULL);  	free(file); -  	return pid;  } diff --git a/src/rc/rc-service.c b/src/rc/rc-service.c index 11b6b58f..ab3d47b2 100644 --- a/src/rc/rc-service.c +++ b/src/rc/rc-service.c @@ -58,7 +58,8 @@ static const char * const longopts_help[] = {  };  #include "_usage.c" -int rc_service(int argc, char **argv) +int +rc_service(int argc, char **argv)  {  	int opt;  	char *service; @@ -75,17 +76,21 @@ int rc_service(int argc, char **argv)  		case 'e':  			service = rc_service_resolve(optarg);  			opt = service ? EXIT_SUCCESS : EXIT_FAILURE; +#ifdef DEBUG_MEMORY  			free(service); +#endif  			return opt;  			/* NOTREACHED */  		case 'l':  			list = rc_services_in_runlevel(NULL); -			if (! list) +			if (!TAILQ_FIRST(list))  				return EXIT_FAILURE;  			rc_stringlist_sort(&list);  			TAILQ_FOREACH(s, list, entries)  				printf("%s\n", s->value); +#ifdef DEBUG_MEMORY  			rc_stringlist_free(list); +#endif  			return EXIT_SUCCESS;  			/* NOTREACHED */  		case 'r': @@ -93,7 +98,9 @@ int rc_service(int argc, char **argv)  			if (!service)  				return EXIT_FAILURE;  			printf("%s\n", service); +#ifdef DEBUG_MEMORY  			free(service); +#endif  			return EXIT_SUCCESS;  			/* NOTREACHED */ @@ -103,13 +110,10 @@ int rc_service(int argc, char **argv)  	argc -= optind;  	argv += optind; -  	if (!*argv)  		eerrorx("%s: you need to specify a service", applet); -  	if (!(service = rc_service_resolve(*argv)))  		eerrorx("%s: service `%s' does not exist", applet, *argv); -  	*argv = service;  	execv(*argv, argv);  	eerrorx("%s: %s", applet, strerror(errno)); diff --git a/src/rc/rc.c b/src/rc/rc.c index 4fee7002..cb4045f0 100644 --- a/src/rc/rc.c +++ b/src/rc/rc.c @@ -43,12 +43,6 @@ const char rc_copyright[] = "Copyright (c) 2007-2008 Roy Marples";  #include <sys/utsname.h>  #include <sys/wait.h> -/* So we can coldplug net devices */ -#ifdef BSD -# include <sys/socket.h> -# include <ifaddrs.h> -#endif -  #ifdef __linux__  # include <asm/setup.h> /* for COMMAND_LINE_SIZE */  #endif @@ -519,115 +513,10 @@ static void handle_signal(int sig)  	errno = serrno;  } -static void do_coldplug(void) -{ -	size_t l; -	DIR *dp; -	struct dirent *d; -	char *service; -	RC_STRING *s; -#ifdef BSD -	struct ifaddrs *ifap; -	struct ifaddrs *ifa; -	char *p; -#endif - -	errno = 0; -	if (!rc_conf_yesno("rc_coldplug") && errno != ENOENT) -		return; - -	/* We need to ensure our state dirs exist. -	 * We should have a better call than this, but oh well. */ -	rc_deptree_update_needed(); - -#ifdef BSD -	if (getifaddrs(&ifap) == 0) { -		for (ifa = ifap; ifa; ifa = ifa->ifa_next) { -			if (ifa->ifa_addr->sa_family != AF_LINK) -				continue; - -			l = strlen("net.") + strlen(ifa->ifa_name) + 1; -			service = xmalloc(sizeof (char) * l); -			snprintf(service, l, "net.%s", ifa->ifa_name); -			if (rc_service_exists(service) && -			    service_plugable(service)) -				rc_service_mark(service, RC_SERVICE_COLDPLUGGED); -			free(service); -		} -		freeifaddrs (ifap); -	} - -	/* The mice are a little more tricky. -	 * If we coldplug anything else, we'll probably do it here. */ -	if ((dp = opendir("/dev"))) { -		while ((d = readdir(dp))) { -			if (strncmp(d->d_name, "psm", 3) == 0 || -			    strncmp(d->d_name, "ums", 3) == 0) -			{ -				p = d->d_name + 3; -				if (p && isdigit((unsigned char)*p)) { -					l = strlen("moused.") + strlen(d->d_name) + 1; -					service = xmalloc(sizeof(char) * l); -					snprintf (service, l, "moused.%s", d->d_name); -					if (rc_service_exists (service) && -					    service_plugable (service)) -						rc_service_mark (service, RC_SERVICE_COLDPLUGGED); -					free(service); -				} -			} -		} -		closedir (dp); -	} - -#else - -	/* udev likes to start services before we're ready when it does -	 * its coldplugging thing. runscript knows when we're not ready so it -	 * stores a list of coldplugged services in DEVBOOT for us to pick up -	 * here when we are ready for them */ -	if ((dp = opendir(DEVBOOT))) { -		while ((d = readdir(dp))) { -			if (d->d_name[0] == '.' && -			    (d->d_name[1] == '\0' || -			     (d->d_name[1] == '.' && d->d_name[2] == '\0'))) -				continue; - -			if (rc_service_exists(d->d_name) && -			    service_plugable(d->d_name)) -				rc_service_mark(d->d_name, RC_SERVICE_COLDPLUGGED); - -			l = strlen(DEVBOOT "/") + strlen(d->d_name) + 1; -			service = xmalloc(sizeof (char) * l); -			snprintf(service, l, DEVBOOT "/%s", d->d_name); -			if (unlink(service)) -				eerror("%s: unlink `%s': %s", applet, service, -					strerror(errno)); -			free(service); -		} -		closedir(dp); -		rmdir(DEVBOOT); -	} -#endif - -	if (rc_yesno(getenv("EINFO_QUIET"))) -		return; - -	/* Load our list of coldplugged services and display them */ -	einfon("Device initiated services:%s", ecolor(ECOLOR_HILITE)); -	coldplugged_services = rc_services_in_state(RC_SERVICE_COLDPLUGGED); -	if (coldplugged_services) -		TAILQ_FOREACH(s, coldplugged_services, entries) -			printf(" %s", s->value); -	printf("%s\n", ecolor(ECOLOR_NORMAL)); -} -  static void do_newlevel(const char *newlevel)  {  	struct utsname uts;  	const char *sys; -#ifdef __linux__ -	char *cmd; -#endif  	if (strcmp(newlevel, RC_LEVEL_SYSINIT) == 0  #ifndef PREFIX @@ -669,39 +558,13 @@ static void do_newlevel(const char *newlevel)  			       ecolor(ECOLOR_GOOD), ecolor(ECOLOR_NORMAL));  		setenv("RC_RUNLEVEL", newlevel, 1); -		rc_plugin_run(RC_HOOK_RUNLEVEL_START_IN, newlevel); -		hook_out = RC_HOOK_RUNLEVEL_START_OUT;  		run_program(INITSH); - -#ifdef __linux__ -		/* If we requested a runlevel, save it now */ -		if ((cmd = proc_getent("rc_runlevel"))) { -			set_krunlevel(cmd); -			free(cmd); -		} else if ((cmd = proc_getent("softlevel"))) { -			set_krunlevel(cmd); -			free(cmd); -		} else -		    set_krunlevel(NULL); -#endif - -		/* Setup our coldplugged services now */ -		do_coldplug(); - -		rc_plugin_run(RC_HOOK_RUNLEVEL_START_OUT, newlevel); -		hook_out = 0; - -		if (want_interactive()) -			mark_interactive(); - -		exit(EXIT_SUCCESS);  	} else if (strcmp(newlevel, RC_LEVEL_SINGLE) == 0) {  #ifndef PREFIX  		if (! RUNLEVEL ||  		    (strcmp(RUNLEVEL, "S") != 0 &&  		     strcmp(RUNLEVEL, "1") != 0))  		{ -			/* Remember the current runlevel for when we come back */  			set_krunlevel(runlevel);  			single_user();  		} @@ -883,7 +746,12 @@ interactive_option:  			if (! parallel) {  				rc_waitpid(pid);  				remove_pid(pid); +				/* Attempt to open the logger as a service may  +				 * mount the needed /dev/pts for this to work */ +				if (rc_logger_tty == -1) +					rc_logger_open(runlevel);  			} +		  		}  	} @@ -1076,7 +944,8 @@ int main(int argc, char **argv)  	{  		/* Try not to join boot and krunlevels together */  		if (! newlevel || -		    strcmp(newlevel, getenv("RC_BOOTLEVEL")) != 0) +		    (strcmp(newlevel, getenv("RC_BOOTLEVEL")) != 0 && +		     strcmp(newlevel, RC_LEVEL_SYSINIT) != 0))  			if (get_krunlevel(krunlevel, sizeof(krunlevel)))  				newlevel = krunlevel;  	} else if (! RUNLEVEL || @@ -1135,21 +1004,11 @@ int main(int argc, char **argv)  	 * correct order for stopping them */  	stop_services = rc_services_in_state(RC_SERVICE_STARTED);  	tmplist = rc_services_in_state(RC_SERVICE_INACTIVE); -	if (tmplist) { -		if (stop_services) { -			TAILQ_CONCAT(stop_services, tmplist, entries); -			free(tmplist); -		} else -			stop_services = tmplist; -	} +	TAILQ_CONCAT(stop_services, tmplist, entries); +	free(tmplist);  	tmplist = rc_services_in_state(RC_SERVICE_STARTING); -	if (tmplist) { -		if (stop_services) { -			TAILQ_CONCAT(stop_services, tmplist, entries); -			free(tmplist); -		} else -			stop_services = tmplist; -	} +	TAILQ_CONCAT(stop_services, tmplist, entries); +	free(tmplist);  	if (stop_services)  		rc_stringlist_sort(&stop_services); @@ -1171,24 +1030,30 @@ int main(int argc, char **argv)  	    strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 &&  	    strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_REBOOT) != 0)  	{ -		/* We need to include the boot runlevel services if we're not in it */ -		start_services = rc_services_in_runlevel(bootlevel); -		if (strcmp (newlevel ? newlevel : runlevel, bootlevel) != 0) { -			tmplist = rc_services_in_runlevel(newlevel ? newlevel : runlevel); -			if (tmplist) { -				if (start_services) { -					TAILQ_CONCAT(start_services, tmplist, entries); -					free(tmplist); -				} else -					start_services = tmplist; +		start_services = rc_services_in_runlevel(RC_LEVEL_SYSINIT); +		if (strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SYSINIT) +		    != 0) +		{ +			/* We need to include the boot runlevel services */ +			tmplist = rc_services_in_runlevel(bootlevel); +			TAILQ_CONCAT(start_services, tmplist, entries); +			free(tmplist); +			if (strcmp (newlevel ? newlevel : runlevel, bootlevel) +			    != 0) +			{ +				tmplist = rc_services_in_runlevel(newlevel ? +								  newlevel : +								  runlevel); +				TAILQ_CONCAT(start_services, tmplist, entries); +				free(tmplist);  			} -		} -		if (coldplugged_services) { -			if (!start_services) -				start_services = rc_stringlist_new(); -			TAILQ_FOREACH(service, coldplugged_services, entries) -				rc_stringlist_addu(start_services, service->value); +			if (coldplugged_services) { +				if (!start_services) +					start_services = rc_stringlist_new(); +				TAILQ_FOREACH(service, coldplugged_services, entries) +					rc_stringlist_addu(start_services, service->value); +			}  		}  	} @@ -1265,14 +1130,15 @@ int main(int argc, char **argv)  	if (start_services) {  		do_start_services(parallel); +		/* FIXME: If we skip the boot runlevel and go straight +		 * to default from sysinit, we should now re-evaluate our +		 * start services + coldplugged services and call +		 * do_start_services a second time. */  		/* Wait for our services to finish */  		wait_for_services();  	} -	rc_plugin_run(RC_HOOK_RUNLEVEL_START_OUT, runlevel); -	hook_out = 0; -  #ifdef __linux__  	/* mark any services skipped as stopped */  	if (PREVLEVEL && strcmp(PREVLEVEL, "N") == 0) { @@ -1285,12 +1151,15 @@ int main(int argc, char **argv)  	}  #endif +	rc_plugin_run(RC_HOOK_RUNLEVEL_START_OUT, runlevel); +	hook_out = 0; +  	/* If we're in the boot runlevel and we regenerated our dependencies  	 * we need to delete them so that they are regenerated again in the -	 * default runlevel as they may depend on things that are now available */ +	 * default runlevel as they may depend on things that are now +	 * available */  	if (regen && strcmp(runlevel, bootlevel) == 0)  		unlink(RC_DEPTREE_CACHE);  	return EXIT_SUCCESS;  } - diff --git a/src/rc/runscript.c b/src/rc/runscript.c index e263a4f4..d0425ab7 100644 --- a/src/rc/runscript.c +++ b/src/rc/runscript.c @@ -108,9 +108,8 @@ static RC_STRINGLIST *types_mua = NULL;  static void (*selinux_run_init_old)(void);  static void (*selinux_run_init_new)(int argc, char **argv); -static void setup_selinux(int argc, char **argv); - -static void setup_selinux(int argc, char **argv) +static void +setup_selinux(int argc, char **argv)  {  	void *lib_handle = NULL; @@ -141,7 +140,8 @@ static void setup_selinux(int argc, char **argv)  }  #endif -static void handle_signal(int sig) +static void +handle_signal(int sig)  {  	int serrno = errno;  	char signame[10] = { '\0' }; @@ -155,7 +155,8 @@ static void handle_signal(int sig)  	case SIGCHLD:  		if (signal_pipe[1] > -1) {  			if (write(signal_pipe[1], &sig, sizeof(sig)) == -1) -				eerror("%s: send: %s", service, strerror(errno)); +				eerror("%s: send: %s", +				       service, strerror(errno));  		} else  			rc_waitpid(-1);  		break; @@ -168,15 +169,15 @@ static void handle_signal(int sig)  		break;  	case SIGINT: -		if (! signame[0]) +		if (!signame[0])  			snprintf(signame, sizeof(signame), "SIGINT");  		/* FALLTHROUGH */  	case SIGTERM: -		if (! signame[0]) +		if (!signame[0])  			snprintf(signame, sizeof(signame), "SIGTERM");  		/* FALLTHROUGH */  	case SIGQUIT: -		if (! signame[0]) +		if (!signame[0])  			snprintf(signame, sizeof(signame), "SIGQUIT");  		/* Send the signal to our children too */  		if (service_pid > 0) @@ -192,18 +193,17 @@ static void handle_signal(int sig)  	errno = serrno;  } -static time_t get_mtime(const char *pathname, bool follow_link) +static time_t +get_mtime(const char *pathname, bool follow_link)  {  	struct stat buf;  	int retval; -	if (! pathname) +	if (!pathname)  		return 0; -  	retval = follow_link ? stat(pathname, &buf) : lstat(pathname, &buf); -	if (! retval) +	if (!retval)  		return buf.st_mtime; -  	errno = 0;  	return 0;  } @@ -211,7 +211,8 @@ static time_t get_mtime(const char *pathname, bool follow_link)  static const char *const tests[] = {  	"starting", "started", "stopping", "inactive", "wasinactive", NULL  }; -static bool in_control() +static bool +in_control()  {  	char file[PATH_MAX];  	time_t m; @@ -221,17 +222,18 @@ static bool in_control()  	if (sighup)  		return false; -	if (! *mtime_test || ! exists(mtime_test)) +	if (!*mtime_test || !exists(mtime_test))  		return false;  	if (rc_service_state(applet) & RC_SERVICE_STOPPED)  		return false; -	if (! (mtime = get_mtime(mtime_test, false))) +	if (!(mtime = get_mtime(mtime_test, false)))  		return false;  	while (tests[i]) { -		snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s", tests[i], applet); +		snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s", +			 tests[i], applet);  		if (exists(file)) {  			m = get_mtime(file, false);  			if (mtime < m && m != 0) @@ -243,7 +245,8 @@ static bool in_control()  	return true;  } -static void uncoldplug() +static void +uncoldplug()  {  	char file[PATH_MAX]; @@ -252,11 +255,13 @@ static void uncoldplug()  		eerror("%s: unlink `%s': %s", applet, file, strerror(errno));  } -static void start_services(RC_STRINGLIST *list) { +static void +start_services(RC_STRINGLIST *list) +{  	RC_STRING *svc;  	RC_SERVICE state = rc_service_state (service); -	if (! list) +	if (!list)  		return;  	if (state & RC_SERVICE_INACTIVE || @@ -265,28 +270,30 @@ static void start_services(RC_STRINGLIST *list) {  	    state & RC_SERVICE_STARTED)  	{  		TAILQ_FOREACH(svc, list, entries) { -			if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) { -				if (state & RC_SERVICE_INACTIVE || -				    state & RC_SERVICE_WASINACTIVE) -				{ -					rc_service_schedule_start(service, svc->value); -					ewarn("WARNING: %s is scheduled to started" -					      " when %s has started", -					       svc->value, applet); -				} else -					service_start(svc->value); -			} +			if (!(rc_service_state(svc->value) & +			      RC_SERVICE_STOPPED)) +				continue; +			if (state & RC_SERVICE_INACTIVE || +			    state & RC_SERVICE_WASINACTIVE) +			{ +				rc_service_schedule_start(service, +							  svc->value); +				ewarn("WARNING: %s is scheduled to started" +				      " when %s has started", +				       svc->value, applet); +			} else +				service_start(svc->value);  		}  	}  } -static void restore_state(void) +static void +restore_state(void)  {  	RC_SERVICE state; -	if (rc_in_plugin || ! in_control()) +	if (rc_in_plugin || !in_control())  		return; -  	state = rc_service_state(applet);  	if (state & RC_SERVICE_STOPPING) {  		if (state & RC_SERVICE_WASINACTIVE) @@ -310,17 +317,20 @@ static void restore_state(void)  	}  } -static void cleanup(void) +static void +cleanup(void)  {  	restore_state(); -	if (! rc_in_plugin) { +	if (!rc_in_plugin) {  		if (hook_out) {  			rc_plugin_run(hook_out, applet);  			if (hook_out == RC_HOOK_SERVICE_START_DONE) -				rc_plugin_run(RC_HOOK_SERVICE_START_OUT, applet); +				rc_plugin_run(RC_HOOK_SERVICE_START_OUT, +					      applet);  			else if (hook_out == RC_HOOK_SERVICE_STOP_DONE) -				rc_plugin_run(RC_HOOK_SERVICE_STOP_OUT, applet); +				rc_plugin_run(RC_HOOK_SERVICE_STOP_OUT, +					      applet);  		}  		if (restart_services) @@ -353,7 +363,9 @@ static void cleanup(void)  		unlink(mtime_test);  } -static int write_prefix(const char *buffer, size_t bytes, bool *prefixed) { +static int +write_prefix(const char *buffer, size_t bytes, bool *prefixed) +{  	unsigned int i;  	const char *ec = ecolor(ECOLOR_HILITE);  	const char *ec_normal = ecolor(ECOLOR_NORMAL); @@ -374,7 +386,7 @@ static int write_prefix(const char *buffer, size_t bytes, bool *prefixed) {  		if (buffer[i] == '\033')  			*prefixed = true; -		if (! *prefixed) { +		if (!*prefixed) {  			ret += write(fd, ec, strlen(ec));  			ret += write(fd, prefix, strlen(prefix));  			ret += write(fd, ec_normal, strlen(ec_normal)); @@ -389,11 +401,11 @@ static int write_prefix(const char *buffer, size_t bytes, bool *prefixed) {  	/* Release the lock */  	close(lock_fd); -  	return ret;  } -static bool svc_exec(const char *arg1, const char *arg2) +static bool +svc_exec(const char *arg1, const char *arg2)  {  	bool execok;  	int fdout = fileno(stdout); @@ -430,7 +442,6 @@ static bool svc_exec(const char *arg1, const char *arg2)  		/* If the below call fails due to not enough ptys then we don't  		 * prefix the output, but we still work */  		openpty(&master_tty, &slave_tty, NULL, &tt, &ws); -  		if (master_tty >= 0 &&  		    (flags = fcntl(master_tty, F_GETFD, 0)) == 0)  		     fcntl(master_tty, F_SETFD, flags | FD_CLOEXEC); @@ -450,13 +461,15 @@ static bool svc_exec(const char *arg1, const char *arg2)  		}  		if (exists(RC_SVCDIR "/runscript.sh")) { -			execl(RC_SVCDIR "/runscript.sh", RC_SVCDIR "/runscript.sh", +			execl(RC_SVCDIR "/runscript.sh", +			      RC_SVCDIR "/runscript.sh",  			      service, arg1, arg2, (char *) NULL);  			eerror("%s: exec `" RC_SVCDIR "/runscript.sh': %s",  				service, strerror(errno));  			_exit(EXIT_FAILURE);  		} else { -			execl(RC_LIBDIR "/sh/runscript.sh", RC_LIBDIR "/sh/runscript.sh", +			execl(RC_LIBDIR "/sh/runscript.sh", +			      RC_LIBDIR "/sh/runscript.sh",  			      service, arg1, arg2, (char *) NULL);  			eerror("%s: exec `" RC_LIBDIR "/sh/runscript.sh': %s",  			       service, strerror(errno)); @@ -474,7 +487,8 @@ static bool svc_exec(const char *arg1, const char *arg2)  		if ((s = select(selfd, &rset, NULL, NULL, NULL)) == -1) {  			if (errno != EINTR) { -				eerror("%s: select: %s", service, strerror(errno)); +				eerror("%s: select: %s", service, +				       strerror(errno));  				break;  			}  		} @@ -509,7 +523,8 @@ static bool svc_exec(const char *arg1, const char *arg2)  	return execok;  } -static bool svc_wait(const char *svc) +static bool +svc_wait(const char *svc)  {  	char fifo[PATH_MAX];  	struct timespec ts; @@ -525,12 +540,13 @@ static bool svc_wait(const char *svc)  		forever = true;  	rc_stringlist_free(keywords); -	snprintf(fifo, sizeof(fifo), RC_SVCDIR "/exclusive/%s", basename_c(svc)); +	snprintf(fifo, sizeof(fifo), RC_SVCDIR "/exclusive/%s", +		 basename_c(svc));  	ts.tv_sec = 0;  	ts.tv_nsec = WAIT_INTERVAL;  	while (nloops) { -		if (! exists(fifo)) { +		if (!exists(fifo)) {  			retval = true;  			break;  		} @@ -540,7 +556,7 @@ static bool svc_wait(const char *svc)  				break;  		} -		if (! forever) +		if (!forever)  			nloops --;  		if (--sloops == 0) { @@ -549,12 +565,13 @@ static bool svc_wait(const char *svc)  		}  	} -	if (! exists(fifo)) +	if (!exists(fifo))  		retval = true;  	return retval;  } -static RC_SERVICE svc_status(void) +static RC_SERVICE +svc_status(void)  {  	char status[10];  	int (*e) (const char *fmt, ...) EINFO_PRINTF(1, 2) = einfo; @@ -586,19 +603,21 @@ static RC_SERVICE svc_status(void)  	return state;  } -static void make_exclusive(void) +static void +make_exclusive(void)  {  	/* We create a fifo so that other services can wait until we complete */ -	if (! *exclusive) -		snprintf(exclusive, sizeof(exclusive), RC_SVCDIR "/exclusive/%s", -			 applet); +	if (!*exclusive) +		snprintf(exclusive, sizeof(exclusive), +			 RC_SVCDIR "/exclusive/%s", applet);  	if (mkfifo(exclusive, 0600) != 0 && errno != EEXIST &&  	    (errno != EACCES || geteuid () == 0))  		eerrorx ("%s: unable to create fifo `%s': %s",  			 applet, exclusive, strerror(errno)); -	snprintf(mtime_test, sizeof(mtime_test), RC_SVCDIR "/exclusive/%s.%d", applet, getpid()); +	snprintf(mtime_test, sizeof(mtime_test), +		 RC_SVCDIR "/exclusive/%s.%d", applet, getpid());  	if (exists(mtime_test) && unlink(mtime_test) != 0) {  		eerror("%s: unlink `%s': %s", @@ -614,28 +633,28 @@ static void make_exclusive(void)  	}  } -static void unlink_mtime_test(void) +static void +unlink_mtime_test(void)  {  	if (unlink(mtime_test) != 0) -		eerror("%s: unlink `%s': %s", applet, mtime_test, strerror(errno)); +		eerror("%s: unlink `%s': %s", +		       applet, mtime_test, strerror(errno));  	*mtime_test = '\0';  } -static void get_started_services(void) +static void +get_started_services(void)  {  	RC_STRINGLIST *tmp = rc_services_in_state(RC_SERVICE_INACTIVE); +  	rc_stringlist_free(restart_services);  	restart_services = rc_services_in_state(RC_SERVICE_STARTED); -	if (tmp) { -		if (restart_services) { -			TAILQ_CONCAT(restart_services, tmp, entries); -			free(tmp); -		} else -			restart_services = tmp; -	} +	TAILQ_CONCAT(restart_services, tmp, entries); +	free(tmp);  } -static void setup_types(void) +static void +setup_types(void)  {  	types_b = rc_stringlist_new();  	rc_stringlist_add(types_b, "broken"); @@ -661,7 +680,8 @@ static void setup_types(void)  	rc_stringlist_add(types_mua, "beforeme");  } -static void svc_start(bool deps) +static void +svc_start(bool deps)  {  	bool started;  	bool background = false; @@ -682,6 +702,10 @@ static void svc_start(bool deps)  		    ! state & RC_SERVICE_STOPPED)  			exit(EXIT_FAILURE);  		background = true; +		rc_service_mark(service, RC_SERVICE_COLDPLUGGED); +		if (rc_runlevel_starting()) +			ewarnx("WARNING: %s will be started when the runlevel" +			       " has finished.", applet);  	}  	if (state & RC_SERVICE_STARTED) { @@ -692,16 +716,16 @@ static void svc_start(bool deps)  	else if (state & RC_SERVICE_STOPPING)  		ewarnx("WARNING: %s is stopping", applet);  	else if (state & RC_SERVICE_INACTIVE && ! background) -		ewarnx("WARNING: %s has already started, but is inactive", applet); +		ewarnx("WARNING: %s has already started, but is inactive", +		       applet); -	if (! rc_service_mark(service, RC_SERVICE_STARTING)) { +	if (!rc_service_mark(service, RC_SERVICE_STARTING)) {  		if (errno == EACCES)  			eerrorx("%s: superuser access required", applet);  		eerrorx("ERROR: %s has been started by something else", applet);  	}  	make_exclusive(); -  	hook_out = RC_HOOK_SERVICE_START_OUT;  	rc_plugin_run(RC_HOOK_SERVICE_START_IN, applet); @@ -710,15 +734,14 @@ static void svc_start(bool deps)  		depoptions |= RC_DEP_STRICT;  	if (deps) { -		if (! deptree && ((deptree = _rc_deptree_load(NULL)) == NULL)) +		if (!deptree && ((deptree = _rc_deptree_load(NULL)) == NULL))  			eerrorx("failed to load deptree"); - -		if (! types_b) +		if (!types_b)  			setup_types();  		services = rc_deptree_depends(deptree, types_b, applet_list,  				runlevel, 0); -		if (services && TAILQ_FIRST(services)) { +		if (TAILQ_FIRST(services)) {  			eerrorn("ERROR: `%s' needs ", applet);  			first = true;  			TAILQ_FOREACH(svc, services, entries) { @@ -733,12 +756,14 @@ static void svc_start(bool deps)  		rc_stringlist_free(services);  		services = NULL; -		need_services = rc_deptree_depends(deptree, types_n, applet_list, -				runlevel, depoptions); -		use_services = rc_deptree_depends(deptree, types_nu, applet_list, -				runlevel, depoptions); +		need_services = rc_deptree_depends(deptree, types_n, +						   applet_list,	runlevel, +						   depoptions); +		use_services = rc_deptree_depends(deptree, types_nu, +						  applet_list, runlevel, +						  depoptions); -		if (! rc_runlevel_starting() && use_services) +		if (!rc_runlevel_starting()) {  			TAILQ_FOREACH(svc, use_services, entries) {  				state = rc_service_state(svc->value);  				/* Don't stop failed services again. @@ -753,90 +778,89 @@ static void svc_start(bool deps)  						rc_waitpid(pid);  				}  			} +		}  		/* Now wait for them to start */  		services = rc_deptree_depends(deptree, types_nua, applet_list,  					      runlevel, depoptions); - -		if (services) { -			/* We use tmplist to hold our scheduled by list */ -			tmplist = NULL; -			TAILQ_FOREACH(svc, services, entries) { -				state = rc_service_state(svc->value); -				if (state & RC_SERVICE_STARTED) +		/* We use tmplist to hold our scheduled by list */ +		tmplist = rc_stringlist_new(); +		TAILQ_FOREACH(svc, services, entries) { +			state = rc_service_state(svc->value); +			if (state & RC_SERVICE_STARTED) +				continue; + +			/* Don't wait for services which went inactive but are +			 * now in starting state which we are after */ +			if (state & RC_SERVICE_STARTING && +			    state & RC_SERVICE_WASINACTIVE) +			{ +				if (!rc_stringlist_find(need_services, +							svc->value) && +				    !rc_stringlist_find(use_services, +							svc->value))  					continue; +			} -				/* Don't wait for services which went inactive but are now in -				 * starting state which we are after */ -				if (state & RC_SERVICE_STARTING && +			if (!svc_wait(svc->value)) +				eerror("%s: timed out waiting for %s", +				       applet, svc->value); +			state = rc_service_state(svc->value); +			if (state & RC_SERVICE_STARTED) +				continue; +			if (rc_stringlist_find(need_services, svc->value)) { +				if (state & RC_SERVICE_INACTIVE ||  				    state & RC_SERVICE_WASINACTIVE)  				{ -					if (!rc_stringlist_find(need_services, svc->value) && -					    !rc_stringlist_find(use_services, svc->value)) -						continue; -				} - -				if (!svc_wait(svc->value)) -					eerror ("%s: timed out waiting for %s", +					rc_stringlist_add(tmplist, svc->value); +				} else if (!TAILQ_FIRST(tmplist)) +					eerrorx("ERROR: cannot start %s as" +						" %s would not start",  						applet, svc->value); -				state = rc_service_state(svc->value); -				if (state & RC_SERVICE_STARTED) -					continue; -				if (rc_stringlist_find(need_services, svc->value)) { -					if (state & RC_SERVICE_INACTIVE || -					    state & RC_SERVICE_WASINACTIVE) -					{ -						if (! tmplist) -							tmplist = rc_stringlist_new(); -						rc_stringlist_add(tmplist, svc->value); -					} else if (!tmplist) -						eerrorx("ERROR: cannot start %s as" -							" %s would not start", -							applet, svc->value); -				}  			} +		} -			if (tmplist && TAILQ_FIRST(tmplist)) { -				/* Set the state now, then unlink our exclusive so that -				   our scheduled list is preserved */ -				rc_service_mark(service, RC_SERVICE_STOPPED); -				unlink_mtime_test(); +		if (TAILQ_FIRST(tmplist)) { +			/* Set the state now, then unlink our exclusive so that +			   our scheduled list is preserved */ +			rc_service_mark(service, RC_SERVICE_STOPPED); +			unlink_mtime_test(); +			rc_stringlist_free(use_services); +			use_services = NULL; +			len = 0; +			n = 0; +			TAILQ_FOREACH(svc, tmplist, entries) { +				rc_service_schedule_start(svc->value, service); +				use_services = rc_deptree_depend(deptree,  +								 "iprovide", +								 svc->value); +				TAILQ_FOREACH(svc2, use_services, entries) +					rc_service_schedule_start(svc2->value, +								  service);  				rc_stringlist_free(use_services);  				use_services = NULL; -				len = 0; -				n = 0; -				TAILQ_FOREACH(svc, tmplist, entries) { -					rc_service_schedule_start(svc->value, service); -					use_services = rc_deptree_depend(deptree, "iprovide", -							svc->value); -					if (use_services) { -						TAILQ_FOREACH (svc2, use_services, entries) -							rc_service_schedule_start(svc2->value, service); -						rc_stringlist_free(use_services); -						use_services = NULL; -					} -					len += strlen(svc->value) + 2; -					n++; -				} - -				len += 5; -				tmp = p = xmalloc(sizeof(char) * len); -				TAILQ_FOREACH(svc, tmplist, entries) { -					if (p != tmp) -						p += snprintf(p, len, ", "); -					p += snprintf(p, len - (p - tmp), "%s", svc->value); -				} -				rc_stringlist_free(tmplist); -				tmplist = NULL; -				ewarnx("WARNING: %s is scheduled to start when %s has started", -						applet, tmp); -				free(tmp); +				len += strlen(svc->value) + 2; +				n++;  			} -			rc_stringlist_free(services); -			services = NULL; +			len += 5; +			tmp = p = xmalloc(sizeof(char) * len); +			TAILQ_FOREACH(svc, tmplist, entries) { +				if (p != tmp) +					p += snprintf(p, len, ", "); +				p += snprintf(p, len - (p - tmp), +					      "%s", svc->value); +			} +			rc_stringlist_free(tmplist); +			tmplist = NULL; +			ewarnx("WARNING: %s is scheduled to start when " +			       "%s has started", applet, tmp); +			free(tmp);  		} + +		rc_stringlist_free(services); +		services = NULL;  	}  	if (ibsave) @@ -848,13 +872,15 @@ static void svc_start(bool deps)  		unsetenv("IN_BACKGROUND");  	if (in_control()) { -		if (! started) +		if (!started)  			eerrorx("ERROR: %s failed to start", applet);  	} else {  		if (rc_service_state(service) & RC_SERVICE_INACTIVE) -			ewarnx("WARNING: %s has started, but is inactive", applet); +			ewarnx("WARNING: %s has started, but is inactive", +			       applet);  		else -			ewarnx("WARNING: %s not under our control, aborting", applet); +			ewarnx("WARNING: %s not under our control, aborting", +			       applet);  	}  	rc_service_mark(service, RC_SERVICE_STARTED); @@ -865,28 +891,23 @@ static void svc_start(bool deps)  	/* Now start any scheduled services */  	services = rc_services_scheduled(service); -	if (services) { -		TAILQ_FOREACH(svc, services, entries) -			if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) -				service_start(svc->value); -		rc_stringlist_free(services); -		services = NULL; -	} +	TAILQ_FOREACH(svc, services, entries) +		if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) +			service_start(svc->value); +	rc_stringlist_free(services); +	services = NULL;  	/* Do the same for any services we provide */  	if (deptree) {  		tmplist = rc_deptree_depend(deptree, "iprovide", applet); -		if (tmplist) { -			TAILQ_FOREACH(svc, tmplist, entries) { -				services = rc_services_scheduled(svc->value); -				if (! services) -					continue; -				TAILQ_FOREACH(svc2, services, entries) -					if (rc_service_state(svc2->value) & RC_SERVICE_STOPPED) -						service_start(svc2->value); -				rc_stringlist_free(services); -				services = NULL; -			} +		TAILQ_FOREACH(svc, tmplist, entries) { +			services = rc_services_scheduled(svc->value); +			TAILQ_FOREACH(svc2, services, entries) +				if (rc_service_state(svc2->value) & +				    RC_SERVICE_STOPPED) +					service_start(svc2->value); +			rc_stringlist_free(services); +			services = NULL;  		}  		rc_stringlist_free(tmplist);  		tmplist = NULL; @@ -896,20 +917,21 @@ static void svc_start(bool deps)  	rc_plugin_run(RC_HOOK_SERVICE_START_OUT, applet);  } -static void svc_stop(bool deps) +static void +svc_stop(bool deps)  {  	bool stopped;  	RC_SERVICE state = rc_service_state(service);  	int depoptions = RC_DEP_TRACE;  	RC_STRING *svc; -	if (rc_runlevel_stopping() && -	    state & RC_SERVICE_FAILED) -		exit (EXIT_FAILURE); + +	if (rc_runlevel_stopping() && state & RC_SERVICE_FAILED) +		exit(EXIT_FAILURE);  	if (rc_yesno(getenv("IN_HOTPLUG")) || in_background) -		if (! (state & RC_SERVICE_STARTED) && -		    ! (state & RC_SERVICE_INACTIVE)) +		if (!(state & RC_SERVICE_STARTED) && +		    !(state & RC_SERVICE_INACTIVE))  			exit (EXIT_FAILURE);  	if (state & RC_SERVICE_STOPPED) { @@ -918,7 +940,7 @@ static void svc_stop(bool deps)  	} else if (state & RC_SERVICE_STOPPING)  		ewarnx("WARNING: %s is already stopping", applet); -	if (! rc_service_mark(service, RC_SERVICE_STOPPING)) { +	if (!rc_service_mark(service, RC_SERVICE_STOPPING)) {  		if (errno == EACCES)  			eerrorx("%s: superuser access required", applet);  		eerrorx("ERROR: %s has been stopped by something else", applet); @@ -929,90 +951,87 @@ static void svc_stop(bool deps)  	hook_out = RC_HOOK_SERVICE_STOP_OUT;  	rc_plugin_run(RC_HOOK_SERVICE_STOP_IN, applet); -	if (! rc_runlevel_stopping() && +	if (!rc_runlevel_stopping() &&  	    rc_service_in_runlevel(service, RC_LEVEL_BOOT))  		ewarn ("WARNING: you are stopping a boot service"); -	if (deps && ! (state & RC_SERVICE_WASINACTIVE)) { +	if (deps && !(state & RC_SERVICE_WASINACTIVE)) {  		errno = 0;  		if (rc_conf_yesno("rc_depend_strict") || errno == ENOENT)  			depoptions |= RC_DEP_STRICT; -		if (! deptree && ((deptree = _rc_deptree_load(NULL)) == NULL)) -			eerrorx ("failed to load deptree"); +		if (!deptree && ((deptree = _rc_deptree_load(NULL)) == NULL)) +			eerrorx("failed to load deptree"); -		if (! types_m) +		if (!types_m)  			setup_types();  		services = rc_deptree_depends(deptree, types_m, applet_list,  					      runlevel, depoptions); -		if (services) { -			TAILQ_FOREACH_REVERSE(svc, services, rc_stringlist, entries) { +		tmplist = rc_stringlist_new(); +		TAILQ_FOREACH_REVERSE(svc, services, rc_stringlist, entries) { +			state = rc_service_state(svc->value); +			/* Don't stop failed services again. +			 * If you remove this check, ensure that the +			 * exclusive file isn't created. */ +			if (state & RC_SERVICE_FAILED && +			    rc_runlevel_stopping()) +				continue; +			if (state & RC_SERVICE_STARTED || +			    state & RC_SERVICE_INACTIVE) +			{ +				svc_wait(svc->value);  				state = rc_service_state(svc->value); -				/* Don't stop failed services again. -				 * If you remove this check, ensure that the -				 * exclusive file isn't created. */ -				if (state & RC_SERVICE_FAILED && -				    rc_runlevel_stopping()) -					continue;  				if (state & RC_SERVICE_STARTED ||  				    state & RC_SERVICE_INACTIVE)  				{ -					svc_wait(svc->value); -					state = rc_service_state(svc->value); -					if (state & RC_SERVICE_STARTED || -					    state & RC_SERVICE_INACTIVE) -					{ -						pid_t pid = service_stop(svc->value); -						if (! rc_conf_yesno("rc_parallel")) -							rc_waitpid(pid); -						if (! tmplist) -							tmplist = rc_stringlist_new(); -						rc_stringlist_add(tmplist, svc->value); -					} +					pid_t pid = service_stop(svc->value); +					if (!rc_conf_yesno("rc_parallel")) +						rc_waitpid(pid); +					rc_stringlist_add(tmplist, svc->value);  				}  			} -			rc_stringlist_free(services); -			services = NULL;  		} +		rc_stringlist_free(services); +		services = NULL; -		if (tmplist) { -			TAILQ_FOREACH(svc, tmplist, entries) { -				if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) +		TAILQ_FOREACH(svc, tmplist, entries) { +			if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) +				continue; +			svc_wait(svc->value); +			if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) +				continue; +			if (rc_runlevel_stopping()) { +				/* If shutting down, we should stop even +				 * if a dependant failed */ +				if (runlevel && +				    (strcmp(runlevel, +					    RC_LEVEL_SHUTDOWN) == 0 || +				     strcmp(runlevel, +					    RC_LEVEL_REBOOT) == 0 || +				     strcmp(runlevel, +					    RC_LEVEL_SINGLE) == 0))  					continue; -				svc_wait(svc->value); -				if (! (rc_service_state(svc->value) & RC_SERVICE_STOPPED)) { -					if (rc_runlevel_stopping()) { -						/* If shutting down, we should stop even -						 * if a dependant failed */ -						if (runlevel && -						    (strcmp(runlevel, RC_LEVEL_SHUTDOWN) == 0 || -						     strcmp(runlevel, RC_LEVEL_REBOOT) == 0 || -						     strcmp(runlevel, RC_LEVEL_SINGLE) == 0)) -							continue; -						rc_service_mark(service, RC_SERVICE_FAILED); -					} -					eerrorx("ERROR: cannot stop %s as %s is still up", -							applet, svc->value); -				} +				rc_service_mark(service, RC_SERVICE_FAILED);  			} -			rc_stringlist_free(tmplist); -			tmplist = NULL; +			eerrorx("ERROR: cannot stop %s as %s " +				"is still up", applet, svc->value);  		} +		rc_stringlist_free(tmplist); +		tmplist = NULL; +	 -		/* We now wait for other services that may use us and are stopping -		   This is important when a runlevel stops */ +		/* We now wait for other services that may use us and are +		 * stopping. This is important when a runlevel stops */  		services = rc_deptree_depends(deptree, types_mua, applet_list,  					      runlevel, depoptions); -		if (services) { -			TAILQ_FOREACH(svc, services, entries) { -				if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) -					continue; -				svc_wait(svc->value); -			} -			rc_stringlist_free(services); -			services = NULL; +		TAILQ_FOREACH(svc, services, entries) { +			if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) +				continue; +			svc_wait(svc->value);  		} +		rc_stringlist_free(services); +		services = NULL;  	}  	/* If we're stopping localmount, set LC_ALL=C so that @@ -1028,10 +1047,10 @@ static void svc_stop(bool deps)  	if (ibsave)  		unsetenv("IN_BACKGROUND"); -	if (! in_control()) +	if (!in_control())  		ewarnx("WARNING: %s not under our control, aborting", applet); -	if (! stopped) +	if (!stopped)  		eerrorx("ERROR: %s failed to stop", applet);  	if (in_background) @@ -1047,17 +1066,21 @@ static void svc_stop(bool deps)  	rc_plugin_run(RC_HOOK_SERVICE_STOP_OUT, applet);  } -static void svc_restart(bool deps) +static void +svc_restart(bool deps)  {  	/* This is hairly and a better way needs to be found I think! -	   The issue is this - openvpn need net and dns. net can restart -	   dns via resolvconf, so you could have openvpn trying to restart dnsmasq -	   which in turn is waiting on net which in turn is waiting on dnsmasq. -	   The work around is for resolvconf to restart it's services with --nodeps -	   which means just that. The downside is that there is a small window when -	   our status is invalid. -	   One workaround would be to introduce a new status, or status locking. */ -	if (! deps) { +	 * The issue is this - openvpn need net and dns. net can restart +	 * dns via resolvconf, so you could have openvpn trying to restart +	 * dnsmasq which in turn is waiting on net which in turn is waiting +	 * on dnsmasq. +	 * The work around is for resolvconf to restart it's services with +	 * --nodeps which means just that. +	 * The downside is that there is a small window when our status is +	 * invalid. +	 * One workaround would be to introduce a new status, +	 * or status locking. */ +	if (!deps) {  		RC_SERVICE state = rc_service_state(service);  		if (state & RC_SERVICE_STARTED || state & RC_SERVICE_INACTIVE)  			svc_exec("stop", "start"); @@ -1066,7 +1089,7 @@ static void svc_restart(bool deps)  		return;  	} -	if (! (rc_service_state(service) & RC_SERVICE_STOPPED)) { +	if (!(rc_service_state(service) & RC_SERVICE_STOPPED)) {  		get_started_services();  		svc_stop(deps);  	} @@ -1077,6 +1100,51 @@ static void svc_restart(bool deps)  	restart_services = NULL;  } +static bool +service_plugable(void) +{ +	char *list; +	char *p; +	char *star; +	char *token; +	bool allow = true; +	char *match = rc_conf_value("rc_plug_services"); +	bool truefalse; + +	if (! match) +		return true; + +	list = xstrdup(match); +	p = list; +	while ((token = strsep(&p, " "))) { +		if (token[0] == '!') { +			truefalse = false; +			token++; +		} else +			truefalse = true; + +		star = strchr(token, '*'); +		if (star) { +			if (strncmp(applet, token, +				    (size_t)(star - token)) == 0) +			{ +				allow = truefalse; +				break; +			} +		} else { +			if (strcmp(applet, token) == 0) { +				allow = truefalse; +				break; +			} +		} +	} + +#ifdef DEBUG_MEMORY +	free(list); +#endif +	return allow; +} +  #include "_usage.h"  #define getoptstring "dDsv" getoptstring_COMMON  #define extraopts "stop | start | restart | describe | zap" @@ -1086,7 +1154,7 @@ static const struct option longopts[] = {  	{ "nodeps",     0, NULL, 'D'},  	longopts_COMMON  }; -static const char * const longopts_help[] = { +static const char *const longopts_help[] = {  	"set xtrace when running the script",  	"only run commands when started",  	"ignore dependencies", @@ -1094,7 +1162,8 @@ static const char * const longopts_help[] = {  };  #include "_usage.c" -int runscript(int argc, char **argv) +int +runscript(int argc, char **argv)  {  	bool deps = true;  	bool doneone = false; @@ -1112,7 +1181,7 @@ int runscript(int argc, char **argv)  	struct stat stbuf;  	/* Show help if insufficient args */ -	if (argc < 2 || ! exists(argv[1])) { +	if (argc < 2 || !exists(argv[1])) {  		fprintf(stderr, "runscript should not be run directly\n");  		exit(EXIT_FAILURE);  	} @@ -1165,20 +1234,6 @@ int runscript(int argc, char **argv)  	/* Change dir to / to ensure all init scripts don't use stuff in pwd */  	chdir("/"); -#ifdef __linux__ -	/* coldplug events can trigger init scripts, but we don't want to run -	 * them until after rc sysinit has completed so we punt them to the -	 * boot runlevel */ -	if (exists("/dev/.rcsysinit")) { -		eerror("%s: cannot run until sysvinit completes", applet); -		if (mkdir("/dev/.rcboot", 0755) != 0 && errno != EEXIST) -			eerrorx("%s: mkdir `/dev/.rcboot': %s", applet, strerror(errno)); -		snprintf(exclusive, sizeof(exclusive), "/dev/.rcboot/%s", applet); -		symlink(service, exclusive); -		exit (EXIT_FAILURE); -	} -#endif -  	if ((runlevel = xstrdup (getenv ("RC_RUNLEVEL"))) == NULL) {  		env_filter();  		env_config(); @@ -1198,15 +1253,16 @@ int runscript(int argc, char **argv)  	if (rc_conf_yesno("rc_parallel")) {  		/* Get the longest service name */  		services = rc_services_in_runlevel(NULL); -		if (services) { -			TAILQ_FOREACH(svc, services, entries) { -				ll = strlen(svc->value); -				if (ll > l) -					l = ll; -			} -			rc_stringlist_free(services); -			services = NULL; -		} else l = strlen(applet); +		TAILQ_FOREACH(svc, services, entries) { +			ll = strlen(svc->value); +			if (ll > l) +				l = ll; +		} +		rc_stringlist_free(services); +		services = NULL; +		ll = strlen(applet); +		if (ll > l) +			l = ll;  		/* Make our prefix string */  		prefix = xmalloc(sizeof(char) * l + 1); @@ -1227,13 +1283,14 @@ int runscript(int argc, char **argv)  	argv++;  	/* Right then, parse any options there may be */ -	while ((opt = getopt_long(argc, argv, getoptstring, longopts, (int *) 0)) != -1) +	while ((opt = getopt_long(argc, argv, getoptstring, +				  longopts, (int *)0)) != -1)  		switch (opt) {  		case 'd':  			setenv("RC_DEBUG", "yes", 1);  			break;  		case 's': -			if (! (rc_service_state(service) & RC_SERVICE_STARTED)) +			if (!(rc_service_state(service) & RC_SERVICE_STARTED))  				exit(EXIT_FAILURE);  			break;  		case 'D': @@ -1251,7 +1308,7 @@ int runscript(int argc, char **argv)  	}  	if (rc_yesno(getenv("IN_HOTPLUG"))) { -		if (! rc_conf_yesno("rc_hotplug") || ! service_plugable(applet)) +		if (!rc_conf_yesno("rc_hotplug") || !service_plugable())  			eerrorx("%s: not allowed to be hotplugged", applet);  	} @@ -1286,8 +1343,8 @@ int runscript(int argc, char **argv)  		doneone = true; -		if (strcmp (optarg, "describe") == 0 || -		    strcmp (optarg, "help") == 0) +		if (strcmp(optarg, "describe") == 0 || +		    strcmp(optarg, "help") == 0)  		{  			save = prefix;  			eprefix(NULL); @@ -1304,25 +1361,25 @@ int runscript(int argc, char **argv)  			   strcmp(optarg, "iprovide") == 0)  		{  			errno = 0; -			if (rc_conf_yesno("rc_depend_strict") || errno == ENOENT) +			if (rc_conf_yesno("rc_depend_strict") || +			    errno == ENOENT)  				depoptions |= RC_DEP_STRICT; -			if (! deptree && ((deptree = _rc_deptree_load(NULL)) == NULL)) +			if (!deptree && +			    ((deptree = _rc_deptree_load(NULL)) == NULL))  				eerrorx("failed to load deptree");  			tmplist = rc_stringlist_new();  			rc_stringlist_add(tmplist, optarg); -			services = rc_deptree_depends(deptree, tmplist, applet_list, +			services = rc_deptree_depends(deptree, tmplist, +						      applet_list,  						      runlevel, depoptions);  			rc_stringlist_free(tmplist); -			tmplist = NULL; -			if (services) { -				TAILQ_FOREACH(svc, services, entries) -					printf("%s ", svc->value); -				printf ("\n"); -				rc_stringlist_free(services); -				services = NULL; -			} +			TAILQ_FOREACH(svc, services, entries) +				printf("%s ", svc->value); +			printf ("\n"); +			rc_stringlist_free(services); +			services = NULL;  		} else if (strcmp (optarg, "status") == 0) {  			RC_SERVICE r = svc_status();  			retval = (int) r; @@ -1332,7 +1389,8 @@ int runscript(int argc, char **argv)  			if (strcmp(optarg, "conditionalrestart") == 0 ||  			    strcmp(optarg, "condrestart") == 0)  			{ -				if (rc_service_state(service) & RC_SERVICE_STARTED) +				if (rc_service_state(service) & +				    RC_SERVICE_STARTED)  					svc_restart(deps);  			} else if (strcmp(optarg, "restart") == 0) {  				svc_restart (deps); @@ -1341,37 +1399,44 @@ int runscript(int argc, char **argv)  			} else if (strcmp(optarg, "stop") == 0) {  				if (deps && in_background)  					get_started_services(); -  				svc_stop(deps); -  				if (deps) {  					if (! in_background &&  					    ! rc_runlevel_stopping() && -					    rc_service_state(service) & RC_SERVICE_STOPPED) +					    rc_service_state(service) & +					    RC_SERVICE_STOPPED)  						uncoldplug();  					if (in_background && -					    rc_service_state(service) & RC_SERVICE_INACTIVE) +					    rc_service_state(service) & +					    RC_SERVICE_INACTIVE)  					{ -						TAILQ_FOREACH(svc, restart_services, entries) -							if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) +						TAILQ_FOREACH(svc, +							      restart_services,  +							      entries) +							if (rc_service_state(svc->value) & +							    RC_SERVICE_STOPPED)  								rc_service_schedule_start(service, svc->value);  					}  				}  			} else if (strcmp(optarg, "zap") == 0) { -				einfo("Manually resetting %s to stopped state", applet); -				if (!rc_service_mark(applet, RC_SERVICE_STOPPED)) -					eerrorx("rc_service_mark: %s", strerror(errno)); +				einfo("Manually resetting %s to stopped state", +				      applet); +				if (!rc_service_mark(applet, +						     RC_SERVICE_STOPPED)) +					eerrorx("rc_service_mark: %s", +						strerror(errno));  				uncoldplug();  			} else  				svc_exec(optarg, NULL); -			/* We should ensure this list is empty after an action is done */ +			/* We should ensure this list is empty after +			 * an action is done */  			rc_stringlist_free(restart_services);  			restart_services = NULL;  		} -		if (! doneone) +		if (!doneone)  			usage(EXIT_FAILURE);  	}  | 
