Allow services to be in /usr/local/etc/init.d, but disallow them being added to the boot runlevel.
This commit is contained in:
		| @@ -53,42 +53,45 @@ depend() { | ||||
| 	: | ||||
| } | ||||
|  | ||||
| cd /etc/init.d | ||||
| for SVCNAME in *; do | ||||
| 	[ -x "${SVCNAME}" ] || continue | ||||
| for _dir in /etc/init.d /usr/local/etc/init.d; do | ||||
| 	[ -d "${_dir}" ] || continue | ||||
| 	cd "${_dir}" | ||||
| 	for SVCNAME in *; do | ||||
| 		[ -x "${SVCNAME}" ] || continue | ||||
|  | ||||
| 	# Only generate dependencies for runscripts | ||||
| 	read one two < "${SVCNAME}" | ||||
| 	[ "${one}" = "#!/sbin/runscript" ] || continue | ||||
| 	unset one two | ||||
| 		# Only generate dependencies for runscripts | ||||
| 		read one two < "${SVCNAME}" | ||||
| 		[ "${one}" = "#!/sbin/runscript" ] || continue | ||||
| 		unset one two | ||||
|  | ||||
| 	SVCNAME=${SVCNAME##*/} | ||||
| 	( | ||||
| 	# Save stdout in fd3, then remap it to stderr | ||||
| 	exec 3>&1 1>&2 | ||||
| 		SVCNAME=${SVCNAME##*/} | ||||
| 		( | ||||
| 		# Save stdout in fd3, then remap it to stderr | ||||
| 		exec 3>&1 1>&2 | ||||
|  | ||||
| 	rc_c=${SVCNAME%%.*} | ||||
| 	if [ -n "${rc_c}" -a "${rc_c}" != "${SVCNAME}" ]; then | ||||
| 		[ -e /etc/conf.d/"${rc_c}" ] && . /etc/conf.d/"${rc_c}" | ||||
| 	fi | ||||
| 	unset rc_c | ||||
| 		_rc_c=${SVCNAME%%.*} | ||||
| 		if [ -n "${_rc_c}" -a "${_rc_c}" != "${SVCNAME}" ]; then | ||||
| 			[ -e "${_dir}/../conf.d/${_rc_c}" ] && . "${_dir}/../conf.d/${_rc_c}" | ||||
| 		fi | ||||
| 		unset _rc_c | ||||
|  | ||||
| 	[ -e /etc/conf.d/"${SVCNAME}" ] && . /etc/conf.d/"${SVCNAME}" | ||||
| 		[ -e "${_dir}/../conf.d/${SVCNAME}" ] && . "${_dir}/../conf.d/${SVCNAME}" | ||||
|  | ||||
| 	if . /etc/init.d/"${SVCNAME}"; then | ||||
| 		echo "${SVCNAME}" >&3 | ||||
| 		depend | ||||
| 		if . "${_dir}/${SVCNAME}"; then | ||||
| 			echo "${SVCNAME}" >&3 | ||||
| 			depend | ||||
|  | ||||
| 		# Add any user defined depends | ||||
| 		config ${rc_config} ${RC_CONFIG} | ||||
| 		need ${rc_need} ${RC_NEED} | ||||
| 		use ${rc_use} ${RC_USE} | ||||
| 		before ${rc_before} ${RC_BEFORE} | ||||
| 		after ${rc_after} ${RC_AFTER} | ||||
| 		provide ${rc_provide} ${RC_PROVIDE} | ||||
| 		keywords ${rc_keywords} ${RC_KEYWORDS} | ||||
| 	fi | ||||
| 	) | ||||
| 			# Add any user defined depends | ||||
| 			config ${rc_config} ${RC_CONFIG} | ||||
| 			need ${rc_need} ${RC_NEED} | ||||
| 			use ${rc_use} ${RC_USE} | ||||
| 			before ${rc_before} ${RC_BEFORE} | ||||
| 			after ${rc_after} ${RC_AFTER} | ||||
| 			provide ${rc_provide} ${RC_PROVIDE} | ||||
| 			keywords ${rc_keywords} ${RC_KEYWORDS} | ||||
| 		fi | ||||
| 		) | ||||
| 	done | ||||
| done | ||||
|  | ||||
| # vim: set ts=4 : | ||||
|   | ||||
| @@ -673,6 +673,8 @@ bool rc_deptree_update_needed (void) | ||||
| 	/* Quick test to see if anything we use has changed */ | ||||
| 	if (! is_newer_than (RC_DEPTREE, RC_INITDIR) || | ||||
| 		! is_newer_than (RC_DEPTREE, RC_CONFDIR) || | ||||
| 		! is_newer_than (RC_DEPTREE, RC_INITDIR_LOCAL) || | ||||
| 		! is_newer_than (RC_DEPTREE, RC_CONFDIR_LOCAL) || | ||||
| 		! is_newer_than (RC_DEPTREE, "/etc/rc.conf")) | ||||
| 		return (true); | ||||
|  | ||||
|   | ||||
							
								
								
									
										51
									
								
								src/librc.c
									
									
									
									
									
								
							
							
						
						
									
										51
									
								
								src/librc.c
									
									
									
									
									
								
							| @@ -71,6 +71,7 @@ static char **ls_dir (const char *dir, int options) | ||||
| 	DIR *dp; | ||||
| 	struct dirent *d; | ||||
| 	char **list = NULL; | ||||
| 	struct stat buf; | ||||
|  | ||||
| 	if ((dp = opendir (dir)) == NULL)  | ||||
| 		return (NULL); | ||||
| @@ -79,11 +80,14 @@ static char **ls_dir (const char *dir, int options) | ||||
| 		if (d->d_name[0] != '.') { | ||||
| 			if (options & LS_INITD) { | ||||
| 				int l = strlen (d->d_name); | ||||
| 				char *init = rc_strcatpaths (RC_INITDIR, d->d_name, | ||||
| 											 (char *) NULL); | ||||
| 				bool ok = exists (init); | ||||
| 				free (init); | ||||
| 				if (! ok) | ||||
|  | ||||
| 				/* Check that our file really exists. | ||||
| 				 * This is important as a service maybe in a runlevel, but | ||||
| 				 * could also have been removed. */ | ||||
| 				char *file = rc_strcatpaths (dir, d->d_name, NULL); | ||||
| 				int ok = stat (file, &buf); | ||||
| 				free (file); | ||||
| 				if (ok != 0) | ||||
| 					continue; | ||||
|  | ||||
| 				/* .sh files are not init scripts */ | ||||
| @@ -93,8 +97,6 @@ static char **ls_dir (const char *dir, int options) | ||||
| 					continue; | ||||
| 			} | ||||
| 			if (options & LS_DIR) { | ||||
| 				struct stat buf; | ||||
|  | ||||
| 				if (stat (d->d_name, &buf) == 0 && ! S_ISDIR (buf.st_mode)) | ||||
| 					continue; | ||||
| 			} | ||||
| @@ -258,8 +260,15 @@ char *rc_service_resolve (const char *service) | ||||
| 		if (r > 0) | ||||
| 			return (xstrdup (buffer)); | ||||
| 	} | ||||
|  | ||||
| 	snprintf (buffer, sizeof (buffer), RC_INITDIR "/%s", service); | ||||
|  | ||||
| 	/* So we don't exist in /etc/init.d - check /usr/local/etc/init.d */ | ||||
| 	if (stat (buffer, &buf) != 0) { | ||||
| 		snprintf (buffer, sizeof (buffer), RC_INITDIR_LOCAL "/%s", service); | ||||
| 		if (stat (buffer, &buf) != 0) | ||||
| 			return (NULL); | ||||
| 	} | ||||
|  | ||||
| 	return (xstrdup (buffer)); | ||||
| } | ||||
| librc_hidden_def(rc_service_resolve) | ||||
| @@ -717,8 +726,16 @@ char **rc_services_in_runlevel (const char *runlevel) | ||||
| 	char *dir; | ||||
| 	char **list = NULL; | ||||
|  | ||||
| 	if (! runlevel) | ||||
| 		return (ls_dir (RC_INITDIR, LS_INITD)); | ||||
| 	if (! runlevel) { | ||||
| 		int i; | ||||
| 		char **local = ls_dir (RC_INITDIR_LOCAL, LS_INITD); | ||||
|  | ||||
| 		list = ls_dir (RC_INITDIR, LS_INITD); | ||||
| 		STRLIST_FOREACH (local, dir, i) | ||||
| 			rc_strlist_addsortu (&list, dir); | ||||
| 		rc_strlist_free (local); | ||||
| 		return (list); | ||||
| 	} | ||||
|  | ||||
| 	/* These special levels never contain any services */ | ||||
| 	if (strcmp (runlevel, RC_LEVEL_SYSINIT) == 0 || | ||||
| @@ -785,6 +802,20 @@ bool rc_service_add (const char *runlevel, const char *service) | ||||
| 	} | ||||
|  | ||||
| 	init = rc_service_resolve (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) { | ||||
| 		char *tmp = xstrdup (init); | ||||
| 		retval = (strcmp (dirname (tmp), RC_INITDIR) == 0); | ||||
| 		free (tmp); | ||||
| 		if (! retval) { | ||||
| 			free (init); | ||||
| 			errno = EPERM; | ||||
| 			return (false); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	svc = xstrdup (service); | ||||
| 	file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename (svc), | ||||
| 						   (char *) NULL); | ||||
|   | ||||
| @@ -51,6 +51,9 @@ | ||||
| #define RC_INITDIR              "/etc/init.d" | ||||
| #define RC_CONFDIR              "/etc/conf.d" | ||||
|  | ||||
| #define RC_INITDIR_LOCAL        "/usr/local/etc/init.d" | ||||
| #define RC_CONFDIR_LOCAL        "/usr/local/etc/conf.d" | ||||
|  | ||||
| #define RC_KSOFTLEVEL           RC_SVCDIR "/ksoftlevel" | ||||
| #define RC_STARTING             RC_SVCDIR "/rc.starting" | ||||
| #define RC_STOPPING             RC_SVCDIR "/rc.stopping" | ||||
|   | ||||
| @@ -170,7 +170,7 @@ int rc_status (int argc, char **argv) | ||||
|  | ||||
| 	/* Output the services in the order in which they would start */ | ||||
| 	if (geteuid () == 0) | ||||
| 		deptree = _rc_deptree_load (); | ||||
| 		deptree = _rc_deptree_load (NULL); | ||||
| 	else | ||||
| 		deptree = rc_deptree_load (); | ||||
|  | ||||
|   | ||||
| @@ -60,8 +60,6 @@ static ssize_t add (const char *runlevel, const char *service) | ||||
|  | ||||
| 	if (! rc_service_exists (service)) | ||||
| 		eerror ("%s: service `%s' does not exist", applet, service); | ||||
| 	else if (! rc_runlevel_exists (runlevel)) | ||||
| 		eerror ("%s: runlevel `%s' does not exist", applet, runlevel); | ||||
| 	else if (rc_service_in_runlevel (service, runlevel)) { | ||||
| 		ewarn ("%s: %s already installed in runlevel `%s'; skipping", | ||||
| 			   applet, service, runlevel); | ||||
| @@ -80,19 +78,18 @@ static ssize_t delete (const char *runlevel, const char *service) | ||||
| { | ||||
| 	ssize_t retval = -1; | ||||
|  | ||||
| 	if (rc_service_in_runlevel (service, runlevel))	{ | ||||
| 		if (rc_service_delete (runlevel, service)) { | ||||
| 			einfo ("%s removed from runlevel %s", service, runlevel); | ||||
| 			retval = 1; | ||||
| 		} else | ||||
| 			eerror ("%s: failed to remove service `%s' from runlevel `%s': %s", | ||||
| 					applet, service, runlevel, strerror (errno)); | ||||
| 	} else if (! rc_service_exists (service)) | ||||
| 		eerror ("%s: service `%s' does not exist", applet, service); | ||||
| 	else if (! rc_runlevel_exists (runlevel)) | ||||
| 		eerror ("%s: runlevel `%s' does not exist", applet, runlevel); | ||||
| 	else | ||||
| 		retval = 0; | ||||
| 	errno = 0; | ||||
| 	if (rc_service_delete (runlevel, service)) { | ||||
| 		einfo ("%s removed from runlevel %s", service, runlevel); | ||||
| 		return 1; | ||||
| 	} | ||||
|  | ||||
| 	if (errno == ENOENT) | ||||
| 		eerror ("%s: service `%s' is not in the runlevel `%s'", | ||||
| 				applet, service, runlevel); | ||||
| 	else  | ||||
| 		eerror ("%s: failed to remove service `%s' from runlevel `%s': %s", | ||||
| 				applet, service, runlevel, strerror (errno)); | ||||
|  | ||||
| 	return (retval); | ||||
| } | ||||
| @@ -238,11 +235,10 @@ int rc_update (int argc, char **argv) | ||||
| 	} else { | ||||
| 		if (! service) | ||||
| 			eerror ("%s: no service specified", applet); | ||||
| 		else if (! rc_service_exists (service)) | ||||
| 			eerror ("%s: service `%s' does not exist", applet, service); | ||||
| 		else { | ||||
| 			ssize_t num_updated = 0; | ||||
| 			ssize_t (*actfunc)(const char *, const char *); | ||||
| 			size_t ret; | ||||
|  | ||||
| 			if (action & DOADD) { | ||||
| 				actfunc = add; | ||||
| @@ -259,7 +255,12 @@ int rc_update (int argc, char **argv) | ||||
| 				eerrorx ("%s: no runlevels found", applet); | ||||
|  | ||||
| 			STRLIST_FOREACH (runlevels, runlevel, i) { | ||||
| 				ssize_t ret = actfunc (runlevel, service); | ||||
| 				if (! rc_runlevel_exists (runlevel)) { | ||||
| 					eerror ("%s: runlevel `%s' does not exist", applet, runlevel); | ||||
| 					continue; | ||||
| 				} | ||||
|  | ||||
| 				ret = actfunc (runlevel, service); | ||||
| 				if (ret < 0) | ||||
| 					retval = EXIT_FAILURE; | ||||
| 				num_updated += ret; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user