Compare commits
	
		
			48 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 5bfb7d6c77 | ||
|   | 12c8248b5f | ||
|   | 820ef6dab6 | ||
|   | 87884db667 | ||
|   | 94077d264e | ||
|   | 3351c8b4c3 | ||
|   | a8214af2fe | ||
|   | 9a372812c7 | ||
|   | 3fa9015b8e | ||
|   | 3b5a8b331e | ||
|   | b3a04e797e | ||
|   | 92e2f2c7cc | ||
|   | ad23d5b8db | ||
|   | 62410eaf4b | ||
|   | fd80b6fc67 | ||
|   | 5d130cc45c | ||
|   | 1c3c2cf6d8 | ||
|   | 171e856ec8 | ||
|   | beaa71df0a | ||
|   | 7eaf71176b | ||
|   | 2c1f6a16e1 | ||
|   | e82653782e | ||
|   | e52b5f59c2 | ||
|   | 8a7e4d38a7 | ||
|   | 47dd5e37cb | ||
|   | e277ae57ef | ||
|   | 69f052b611 | ||
|   | e4eacf02ca | ||
|   | 30c3561b6b | ||
|   | 5f2850366e | ||
|   | 1cb7eec31f | ||
|   | cd7883d25d | ||
|   | 62b49b2a3a | ||
|   | 4c814a0a28 | ||
|   | 36dde4e7f2 | ||
|   | 649f63d882 | ||
|   | 55a28f5d25 | ||
|   | 6c09421375 | ||
|   | 79359f77cc | ||
|   | f79a7a7be1 | ||
|   | 73482cf13a | ||
|   | 0910c455d3 | ||
|   | f5e06bc55a | ||
|   | e7ae08c38d | ||
|   | 6da0abc085 | ||
|   | b34df9dd81 | ||
|   | 6f02069746 | ||
|   | d4c7207ef3 | 
| @@ -38,7 +38,7 @@ Who: | ||||
|  | ||||
| When: 1.0 | ||||
|  | ||||
| Why: Depprecated in favor of extra_commands, extra_started_commands | ||||
| Why: Deprecated in favor of extra_commands, extra_started_commands | ||||
| 	 and extra_stopped_commands. | ||||
|  | ||||
| Who: | ||||
| @@ -47,7 +47,7 @@ Who: | ||||
|  | ||||
| When: 1.0 | ||||
|  | ||||
| Why: Depprecated in favor of executable scripts in @SYSCONFDIR@/local.d | ||||
| Why: Deprecated in favor of executable scripts in @SYSCONFDIR@/local.d | ||||
|  | ||||
| Who: | ||||
|  | ||||
| @@ -76,13 +76,3 @@ Why: The getline() function was standardized in POSIX.1-2008, so it | ||||
|  | ||||
| Who: | ||||
|  | ||||
| ### rc_sys() | ||||
|  | ||||
| When: 1.0 | ||||
|  | ||||
| Why: The OpenRC code now uses two internal functions, detect_container() | ||||
| 	 and detect_vm() to handle this. rc_sys() is broken because it | ||||
| 	 doesn't differentiate between containers and vm's. | ||||
|  | ||||
| Who: | ||||
|  | ||||
|   | ||||
| @@ -1,3 +1,3 @@ | ||||
| NAME=		openrc | ||||
| VERSION=	0.20 | ||||
| VERSION=	0.21 | ||||
| PKG=		${NAME}-${VERSION} | ||||
|   | ||||
							
								
								
									
										14
									
								
								NEWS.md
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								NEWS.md
									
									
									
									
									
								
							| @@ -3,6 +3,20 @@ | ||||
| This file will contain a list of notable changes for each release. Note | ||||
| the information in this file is in reverse order. | ||||
|  | ||||
| ## OpenRC-0.21 | ||||
|  | ||||
| This version adds a daemon supervisor which can start daemons and | ||||
| restart them if they crash. See supervise-daemon-guide.md in the | ||||
| distribution for details on its use. | ||||
|  | ||||
| It is now possible to mark certain mount points as critical. If these | ||||
| mount points are unable to be mounted, localmount or netmount will fail. | ||||
| This is handled in /etc/conf.d/localmount and /etc/conf.d/netmount. See | ||||
| these files for the setup. | ||||
|  | ||||
| The deprecation messages in 0.13.x for runscript and rc are now | ||||
| made visible in preparation for the removal of these binaries in 1.0. | ||||
|  | ||||
| ## OpenRC-0.19 | ||||
|  | ||||
| This version adds a net-online service. By default, this | ||||
|   | ||||
| @@ -9,7 +9,7 @@ wipe_tmp="YES" | ||||
| # This may be useful if you need the kernel boot log afterwards | ||||
| log_dmesg="YES" | ||||
|  | ||||
| # Save the previous dmesg log to dmesc.old | ||||
| # Save the previous dmesg log to dmesg.old | ||||
| # This may be useful if you need to compare the current boot to the | ||||
| # previous one. | ||||
| #previous_dmesg=no | ||||
|   | ||||
| @@ -1,3 +1,10 @@ | ||||
| # Stop the unmounting of certain points. | ||||
| # This could be useful for some NFS related work. | ||||
| #no_umounts="/dir1:/var/dir2" | ||||
| # | ||||
| # Mark certain mount points as critical. | ||||
| # This contains aspace separated list of mount points which should be | ||||
| # considered critical. If one of these mount points cannot be mounted, | ||||
| # localmount will fail. | ||||
| # By default, this is empty. | ||||
| #critical_mounts="/home /var" | ||||
|   | ||||
| @@ -38,3 +38,10 @@ | ||||
| # other words, please change it to be more suited to your system. | ||||
| # | ||||
| rc_need="net" | ||||
| # | ||||
| # Mark certain mount points as critical. | ||||
| # This contains aspace separated list of mount points which should be | ||||
| # considered critical. If one of these mount points cannot be mounted, | ||||
| # netmount will fail. | ||||
| # By default, this is empty. | ||||
| #critical_mounts="/home /var" | ||||
|   | ||||
							
								
								
									
										251
									
								
								guide.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										251
									
								
								guide.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,251 @@ | ||||
| # Purpose and description | ||||
|  | ||||
| OpenRC is an init system for Unixoid operating systems. It takes care of  | ||||
| startup and shutdown of the whole system, including services. | ||||
|  | ||||
| It evolved out of the Gentoo "Baselayout" package which was a custom pure-shell  | ||||
| startup solution. (This was both hard to maintain and debug, and not very  | ||||
| performant) | ||||
|  | ||||
| Most of the core parts are written in C99 for performance and flexibility  | ||||
| reasons, while everything else is posix sh. | ||||
| The License is 2-clause BSD | ||||
|  | ||||
| Current size is about 10k LoC C, and about 4k LoC shell. | ||||
|  | ||||
| OpenRC is known to work on Linux, many BSDs (FreeBSD, OpenBSD, DragonFlyBSD at  | ||||
| least) and HURD. | ||||
|  | ||||
| Services are stateful (i.e. start; start will lead to "it's already started") | ||||
|  | ||||
| # Startup | ||||
|  | ||||
| Usually PID1 (aka. init) calls the OpenRC binary ("/sbin/openrc" by default). | ||||
| (The default setup assumes sysvinit for this) | ||||
|  | ||||
| openrc scans the runlevels (default: "/etc/runlevels") and builds a dependency  | ||||
| graph, then starts the needed service scripts, either serialized (default) or in  | ||||
| parallel. | ||||
|  | ||||
| When all the init scripts are started openrc terminates. There is no persistent  | ||||
| daemon. (Integration with tools like monit, runit or s6 can be done) | ||||
|  | ||||
| # Shutdown | ||||
|  | ||||
| On change to runlevel 0/6 or running "reboot", "halt" etc., openrc stops all  | ||||
| services that are started and runs the services in the "shutdown" runlevel. | ||||
|  | ||||
| # Modifying Service Scripts | ||||
|  | ||||
| Any service can, at any time, be started/stopped/restarted by executing  | ||||
| "rc-service someservice start", "rc-service someservice stop", etc. | ||||
| Another, less preferred method, is to run the service script directly, | ||||
| e.g. "/etc/init.d/service start", "/etc/init.d/service stop", etc. | ||||
|  | ||||
| OpenRC will take care of dependencies, e.g starting apache will start network  | ||||
| first, and stopping network will stop apache first. | ||||
|  | ||||
| There is a special command "zap" that makes OpenRC 'forget' that a service is  | ||||
| started; this is mostly useful to reset a crashed service to stopped state  | ||||
| without invoking the (possibly broken) stop function of the service script. | ||||
|  | ||||
| Calling "openrc" without any arguments will try to reset all services so | ||||
| that the current runlevel is satisfied; if you manually started apache it will be  | ||||
| stopped, and if squid died but is in the current runlevel it'll be restarted. | ||||
|  | ||||
| There is a "service" helper that emulates the syntax seen on e.g. older Redhat  | ||||
| and Ubuntu ("service nginx start" etc.) | ||||
|  | ||||
| # Runlevels | ||||
|  | ||||
| OpenRC has a concept of runlevels, similar to what sysvinit historically  | ||||
| offered. A runlevel is basically a collection of services that needs to be  | ||||
| started. Instead of random numbers they are named, and users can create their  | ||||
| own if needed. This allows, for example, to have a default runlevel with  | ||||
| "everything" enabled, and a "powersaving" runlevel where some services are  | ||||
| disabled. | ||||
|  | ||||
| The "rc-status" helper will print all currently active runlevels and the state  | ||||
| of init scripts in them: | ||||
|  | ||||
| # rc-status | ||||
|  * Caching service dependencies ... [ ok ] | ||||
| Runlevel: default | ||||
|  modules                     [  started  ] | ||||
|  lvm                         [  started  ] | ||||
|  | ||||
| All runlevels are represented as folders in /etc/runlevels/ with symlinks to  | ||||
| the actual init scripts. | ||||
|  | ||||
| Calling openrc with an argument ("openrc default") will switch to that | ||||
| runlevel; this will start and stop services as needed. | ||||
|  | ||||
| Managing runlevels is usually done through the "rc-update" helper, but could of  | ||||
| course be done by hand if desired. | ||||
| e.g. "rc-update add nginx default" - add nginx to the default runlevel | ||||
| Note: This will not auto-start nginx! You'd still have to trigger "rc" or run  | ||||
| the initscript by hand. | ||||
|  | ||||
| FIXME: Document stacked runlevels | ||||
|  | ||||
| The default startup uses the runlevels "boot", "sysinit" and "default", in that  | ||||
| order. Shutdown uses the "shutdown" runlevel. | ||||
|  | ||||
|  | ||||
| # Syntax of Service Scripts | ||||
|  | ||||
| Service scripts are shell scripts. OpenRC aims at using only the standardized  | ||||
| POSIX sh subset for portability reasons. The default interpreter (build-time  | ||||
| toggle) is /bin/sh, so using for example mksh is not a problem. | ||||
|  | ||||
| OpenRC has been tested with busybox sh, ash, dash, bash, mksh, zsh and possibly  | ||||
| others. Using busybox sh has been difficult as it replaces commands with  | ||||
| builtins that don't offer the expected features. | ||||
|  | ||||
| The interpreter for initscripts is #!/sbin/openrc-run | ||||
| Not using this interpreter will break the use of dependencies and is not  | ||||
| supported. (iow: if you insist on using #!/bin/sh you're on your own) | ||||
|  | ||||
| A "depend" function declares the dependencies of this service script. | ||||
| All scripts must have start/stop/status functions, but defaults are provided. | ||||
| Extra functions can be added easily: | ||||
|  | ||||
| extra_commands="checkconfig" | ||||
| checkconfig() { | ||||
| 	doSomething | ||||
| } | ||||
|  | ||||
| This exports the checkconfig function so that "/etc/init.d/someservice  | ||||
| checkconfig" will be available, and it "just" runs this function. | ||||
|  | ||||
| While commands defined in extra_commands are always available, commands | ||||
| defined in extra_started_commands will only work when the service is started | ||||
| and those defined in extra_stopped_commands will only work when the service is | ||||
| stopped. This can be used for implementing graceful reload and similar | ||||
| behaviour. | ||||
|  | ||||
| Adding a restart function will not work, this is a design decision within  | ||||
| OpenRC. Since there may be dependencies involved (e.g. network -> apache) a  | ||||
| restart function is in general not going to work.  | ||||
| restart is internally mapped to stop() + start() (plus handling dependencies). | ||||
| If a service needs to behave differently when it is being restarted vs | ||||
| started or stopped, it should test the $RC_CMD variable, for example: | ||||
|  | ||||
|     [ "$RC_CMD" = restart ] && do_something | ||||
|  | ||||
|  | ||||
| # The Depend Function | ||||
|  | ||||
| This function declares the dependencies for a service script. This | ||||
| determines the order the service scripts start. | ||||
|  | ||||
| depend() { | ||||
| 	need net | ||||
| 	use dns logger netmount | ||||
| 	want coolservice | ||||
| } | ||||
|  | ||||
| "need" declares a hard dependency - net always needs to be started before this  | ||||
| 	service does | ||||
| "use" is a soft dependency - if dns, logger or netmount is in this runlevel  | ||||
| 	start it before, but we don't care if it's not in this runlevel. | ||||
| 	"want" is between need and use - try to start coolservice if it is | ||||
| 	installed on the system, regardless of whether it is in the | ||||
| 	runlevel, but we don't care if it starts. | ||||
| "before" declares that we need to be started before another service | ||||
| "after" declares that we need to be started after another service, without  | ||||
| 	creating a dependency (so on calling stop the two are independent) | ||||
| "provide" allows multiple implementations to provide one service type, e.g.: | ||||
| 	'provide cron' is set in all cron-daemons, so any one of them started  | ||||
| 	satisfies a cron dependency | ||||
| "keyword" allows platform-specific overrides, e.g. "keyword -lxc" makes this  | ||||
| 	service script a noop in lxc containers. Useful for things like keymaps,  | ||||
| 	module loading etc. that are either platform-specific or not available  | ||||
| 	in containers/virtualization/... | ||||
|  | ||||
| FIXME: Anything missing in this list? | ||||
|  | ||||
| # The Default Functions | ||||
|  | ||||
| All service scripts are assumed to have the following functions: | ||||
|  | ||||
| start() | ||||
| stop() | ||||
| status() | ||||
|  | ||||
| There are default implementations in rc/sh/openrc-run.sh - this allows very  | ||||
| compact service scripts. These functions can be overridden per service script as  | ||||
| needed. | ||||
|  | ||||
| The default functions assume the following variables to be set in the service  | ||||
| script: | ||||
|  | ||||
| command= | ||||
| command_args= | ||||
| pidfile= | ||||
|  | ||||
| Thus the 'smallest' service scripts can be half a dozen lines long | ||||
|  | ||||
| # The Magic of Conf.d | ||||
|  | ||||
| Most service scripts need default values. It would be fragile to | ||||
| explicitly source some arbitrary files. By convention openrc-run will source | ||||
| the matching file in /etc/conf.d/ for any script in /etc/init.d/ | ||||
|  | ||||
| This allows you to set random startup-related things easily. Example: | ||||
|  | ||||
| conf.d/foo: | ||||
| START_OPTS="--extraparameter sausage" | ||||
|  | ||||
| init.d/foo: | ||||
| start() { | ||||
| 	/usr/sbin/foo-daemon ${STARTOPTS} | ||||
| } | ||||
|  | ||||
| The big advantage of this split is that most of the time editing of the init  | ||||
| script can be avoided. | ||||
|  | ||||
| # Start-Stop-Daemon | ||||
|  | ||||
| OpenRC has its own modified version of s-s-d, which is historically related and  | ||||
| mostly syntax-compatible to Debian's s-s-d, but has been rewritten from scratch. | ||||
|  | ||||
| It helps with starting daemons, backgrounding, creating PID files and many  | ||||
| other convenience functions related to managing daemons. | ||||
|  | ||||
| # /etc/rc.conf | ||||
|  | ||||
| This file manages the default configuration for OpenRC, and it has examples of  | ||||
| per-service-script variables. | ||||
|  | ||||
| Among these are rc_parallel (for parallelized startup), rc_log (logs all boot  | ||||
| messages to a file), and a few others. | ||||
|  | ||||
| # ulimit and CGroups | ||||
|  | ||||
| Setting ulimit and nice values per service can be done through the rc_ulimit  | ||||
| variable. | ||||
|  | ||||
| Under Linux, OpenRC can optionally use CGroups for process management. | ||||
| By default each service script's processes are migrated to their own CGroup. | ||||
|  | ||||
| By changing certain values in the conf.d file limits can be enforced per  | ||||
| service. It is easy to find orphan processes of a service that persist after  | ||||
| stop(), but by default these will NOT be terminated. | ||||
| To change this add rc_cgroup_cleanup="yes" in the conf.d files for services  | ||||
| where you desire this functionality. | ||||
|  | ||||
| # Caching | ||||
|  | ||||
| For performance reasons OpenRC keeps a cache of pre-parsed initscript metadata | ||||
| (e.g. depend). The default location for this is /${RC_SVCDIR}/cache. | ||||
|  | ||||
| The cache uses mtime to check for file staleness. Should any service script | ||||
| change it'll re-source the relevant files and update the cache | ||||
|  | ||||
| # Convenience functions | ||||
|  | ||||
| OpenRC has wrappers for many common output tasks in libeinfo. | ||||
| This allows to print colour-coded status notices and other things. | ||||
| To make the output consistent the bundled initscripts all use ebegin/eend to  | ||||
| print nice messages. | ||||
| @@ -20,10 +20,8 @@ start() | ||||
| { | ||||
| 	ebegin "Terminating remaining processes" | ||||
| 	killall5 -15 ${killall5_opts} | ||||
| 	sleep 1 | ||||
| 	eend 0 | ||||
| 	ebegin "Killing remaining processes" | ||||
| 	killall5 -9 ${killall5_opts} | ||||
| 	sleep 1 | ||||
| 	eend 0 | ||||
| } | ||||
|   | ||||
| @@ -22,7 +22,7 @@ depend() | ||||
| start() | ||||
| { | ||||
| 	# Mount local filesystems in /etc/fstab. | ||||
| 	local types="noproc" x= no_netdev= rc= | ||||
| 	local critical= types="noproc" x= no_netdev= rc= | ||||
| 	for x in $net_fs_list $extra_net_fs_list; do | ||||
| 		types="${types},no${x}" | ||||
| 	done | ||||
| @@ -37,8 +37,17 @@ start() | ||||
| 	mount -at "$types" $no_netdev | ||||
| 	eend $? "Some local filesystem failed to mount" | ||||
| 	rc=$? | ||||
| 	if [ "$RC_UNAME" != Linux ]; then | ||||
| 	if [ -z "$critical_mounts" ]; then | ||||
| 		rc=0 | ||||
| 	else | ||||
| 		for x in ${critical_mounts}; do | ||||
| 		fstabinfo -q $x || continue | ||||
| 		if ! mountinfo -q $x; then | ||||
| 			critical=x | ||||
| 			eerror "Failed to mount $x" | ||||
| 		fi | ||||
| 		done | ||||
| 		[ -z "$critical" ] && rc=0 | ||||
| 	fi | ||||
| 	return $rc | ||||
| } | ||||
|   | ||||
| @@ -21,7 +21,7 @@ depend() | ||||
| 		esac | ||||
| 	done | ||||
|  	config /etc/fstab | ||||
| 	want $mywant	 | ||||
| 	want $mywant | ||||
| 	use afc-client amd openvpn | ||||
| 	use dns | ||||
| 	keyword -jail -prefix -systemd-nspawn -vserver -lxc | ||||
| @@ -37,13 +37,22 @@ start() | ||||
| 	ebegin "Mounting network filesystems" | ||||
| 	mount -at $fs | ||||
| 	rc=$? | ||||
| 	if [ "$RC_UNAME" = Linux ]; then | ||||
| 	if [ "$RC_UNAME" = Linux ] && [ $rc = 0 ]; then | ||||
| 		mount -a -O _netdev | ||||
| 		rc=$? | ||||
| 	fi | ||||
| 	ewend $rc "Could not mount all network filesystems" | ||||
| 	if [ "$RC_UNAME" != Linux ]; then | ||||
| 	if [ -z "$critical_mounts" ]; then | ||||
| 		rc=0 | ||||
| 	else | ||||
| 		for x in ${critical_mounts}; do | ||||
| 		fstabinfo -q $x || continue | ||||
| 		if ! mountinfo -q $x; then | ||||
| 			critical=x | ||||
| 			eerror "Failed to mount $x" | ||||
| 		fi | ||||
| 		done | ||||
| 		[ -z "$critical" ] && rc=0 | ||||
| 	fi | ||||
| 	return $rc | ||||
| } | ||||
| @@ -72,7 +81,7 @@ stop() | ||||
| 	retval=$? | ||||
|  | ||||
| 	eoutdent | ||||
| 	if [ "$RC_UNAME" = Linux ]; then | ||||
| 	if [ "$RC_UNAME" = Linux ] && [ $retval = 0 ]; then | ||||
| 		umount -a -O _netdev | ||||
| 		retval=$? | ||||
| 	fi | ||||
|   | ||||
| @@ -49,7 +49,7 @@ start() | ||||
| 	fi | ||||
| 	ebegin "Saving dependency cache" | ||||
| 	local rc=0 save= | ||||
| 	for x in deptree depconfig shutdowntime softlevel nettree rc.log; do | ||||
| 	for x in deptree depconfig shutdowntime softlevel rc.log; do | ||||
| 		[ -e "$RC_SVCDIR/$x" ] && save="$save $RC_SVCDIR/$x" | ||||
| 	done | ||||
| 	if [ -n "$save" ]; then | ||||
|   | ||||
| @@ -88,6 +88,15 @@ mount_misc() | ||||
| 		fi | ||||
| 	fi | ||||
|  | ||||
| 	# Setup Kernel Support for persistent storage | ||||
| 	if [ -d /sys/fs/pstore ] && ! mountinfo -q /sys/fs/pstore; then | ||||
| 		if grep -qs 'pstore$' /proc/filesystems; then | ||||
| 			ebegin "Mounting persistent storage (pstore) filesystem" | ||||
| 			mount -t pstore pstore -o ${sysfs_opts} /sys/fs/pstore | ||||
| 			eend $? | ||||
| 		fi | ||||
| 	fi | ||||
|  | ||||
| 	# setup up kernel support for efivarfs | ||||
| 	# slightly complicated, as if it's build as a module but NOT yet loaded, | ||||
| 	# it will NOT appear in /proc/filesystems yet | ||||
|   | ||||
| @@ -6,7 +6,7 @@ MAN3=		einfo.3 \ | ||||
| 		rc_config.3 rc_deptree.3 rc_find_pids.3 rc_plugin_hook.3 \ | ||||
| 		rc_runlevel.3 rc_service.3 rc_stringlist.3 | ||||
| MAN8=		rc-service.8 rc-status.8 rc-update.8 openrc.8 openrc-run.8 \ | ||||
| 		service.8 start-stop-daemon.8 | ||||
| 		service.8 start-stop-daemon.8 supervise-daemon.8 | ||||
|  | ||||
| ifeq (${OS},Linux) | ||||
| MAN8 += rc-sstat.8 | ||||
|   | ||||
| @@ -95,10 +95,17 @@ String describing the service. | ||||
| .It Ar description_$command | ||||
| String describing the extra command. | ||||
| .It Ar supervisor | ||||
| Supervisor to use to monitor this daemon. If this is unset, | ||||
| start-stop-daemon will be used. The only alternate supervisor we support | ||||
| in this release is S6 from Skarnet software. To use this, set | ||||
| Supervisor to use to monitor this daemon. If this is unset or invalid, | ||||
| start-stop-daemon will be used. | ||||
| Currently, we support s6 from scarnet software, and supervise-daemon | ||||
| which is a light-weight supervisor internal to OpenRC. | ||||
| To use s6, set | ||||
| supervisor=s6. | ||||
| or set | ||||
| supervisor=supervise-daemon | ||||
| to use supervise-daemon. | ||||
| Note that supervise-daemon is still in early development, so it is | ||||
| considered experimental. | ||||
| .It Ar s6_service_path | ||||
| The path to the s6 service directory if you are monitoring this service | ||||
| with S6. The default is /var/svc.d/${RC_SVCNAME}. | ||||
| @@ -112,10 +119,16 @@ List of arguments passed to start-stop-daemon when starting the daemon. | ||||
| .It Ar command | ||||
| Daemon to start or stop via | ||||
| .Nm start-stop-daemon | ||||
| or | ||||
| .Nm supervise-daemon | ||||
| if no start or stop function is defined by the service. | ||||
| .It Ar command_args | ||||
| List of arguments to pass to the daemon when starting via | ||||
| .Nm start-stop-daemon . | ||||
| .It Ar command_args_foreground | ||||
| List of arguments to pass to the daemon when starting via | ||||
| .Nm supervise-daemon . | ||||
| to force the daemon to stay in the foreground | ||||
| .It Ar command_background | ||||
| Set this to "true", "yes" or "1" (case-insensitive) to force the daemon into | ||||
| the background. This implies the "--make-pidfile" and "--pidfile" option of | ||||
| @@ -123,6 +136,8 @@ the background. This implies the "--make-pidfile" and "--pidfile" option of | ||||
| so the pidfile variable must be set. | ||||
| .It Ar chroot | ||||
| .Xr start-stop-daemon 8 | ||||
| and | ||||
| .Xr supervise-daemon 8 | ||||
| will chroot into this path before writing the pid file or starting the daemon. | ||||
| .It Ar pidfile | ||||
| Pidfile to use for the above defined command. | ||||
| @@ -172,9 +187,9 @@ The service will start after these services and stop before these services. | ||||
| The service will start before these services and stop after these services. | ||||
| .It Ic provide | ||||
| The service provides this virtual service. For example, named provides dns. | ||||
| Virtual services take precedence over real services, so it is highly | ||||
| recommended that you do not have a real service that has the same name | ||||
| as a virtual service. | ||||
| Note that it is not legal to have a virtual and real service with the | ||||
| same name. If you do this, you will receive an error message, and you | ||||
| must rename either the real or virtual service. | ||||
| .It Ic config | ||||
| We should recalculate our dependencies if the listed files have changed. | ||||
| .It Ic keyword | ||||
|   | ||||
| @@ -20,6 +20,14 @@ | ||||
| .Ar service cmd | ||||
| .Op Ar ... | ||||
| .Nm | ||||
| .Op Fl I , -ifinactive | ||||
| .Ar service cmd | ||||
| .Op Ar ... | ||||
| .Nm | ||||
| .Op Fl N , -ifnotstarted | ||||
| .Ar service cmd | ||||
| .Op Ar ... | ||||
| .Nm | ||||
| .Fl e , -exists | ||||
| .Ar service | ||||
| .Nm | ||||
| @@ -36,6 +44,13 @@ If | ||||
| is given then | ||||
| .Nm | ||||
| returns 0 even if the service does not exist. | ||||
| If | ||||
| .Fl I , -ifinactive | ||||
| or | ||||
| .Fl N , -ifnotstarted | ||||
| is given then | ||||
| .Nm | ||||
| returns 0 if the service exists but is in the wrong state. | ||||
| .Pp | ||||
| If given the | ||||
| .Fl l , -list | ||||
|   | ||||
							
								
								
									
										142
									
								
								man/supervise-daemon.8
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										142
									
								
								man/supervise-daemon.8
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,142 @@ | ||||
| .\" Copyright (c) 2007-2015 The OpenRC Authors. | ||||
| .\" See the Authors file at the top-level directory of this distribution and | ||||
| .\" https://github.com/OpenRC/openrc/blob/master/AUTHORS | ||||
| .\" | ||||
| .\" This file is part of OpenRC. It is subject to the license terms in | ||||
| .\" the LICENSE file found in the top-level directory of this | ||||
| .\" distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE | ||||
| .\" This file may not be copied, modified, propagated, or distributed | ||||
| .\"    except according to the terms contained in the LICENSE file. | ||||
| .\" | ||||
| .Dd April 27, 2016 | ||||
| .Dt supervise-DAEMON 8 SMM | ||||
| .Os OpenRC | ||||
| .Sh NAME | ||||
| .Nm supervise-daemon | ||||
| .Nd starts a daemon and restarts it if it crashes | ||||
| .Sh SYNOPSIS | ||||
| .Nm | ||||
| .Fl d , -chdir | ||||
| .Ar path | ||||
| .Fl e , -env | ||||
| .Ar var=value | ||||
| .Fl g , -group | ||||
| .Ar group | ||||
| .Fl I , -ionice | ||||
| .Ar arg | ||||
| .Fl k , -umask | ||||
| .Ar value | ||||
| .Fl N , -nicelevel | ||||
| .Ar level | ||||
| .Fl p , -pidfile | ||||
| .Ar pidfile | ||||
| .Fl u , -user | ||||
| .Ar user | ||||
| .Fl r , -chroot | ||||
| .Ar chrootpath | ||||
| .Fl 1 , -stdout | ||||
| .Ar logfile | ||||
| .Fl 2 , -stderr | ||||
| .Ar logfile | ||||
| .Fl S , -start | ||||
| .Ar daemon | ||||
| .Op Fl - | ||||
| .Op Ar arguments | ||||
| .Nm | ||||
| .Fl K , -stop | ||||
| .Ar daemon | ||||
| .Fl p , -pidfile | ||||
| .Ar pidfile | ||||
| .Fl r , -chroot | ||||
| .Ar chrootpath | ||||
| .Sh DESCRIPTION | ||||
| .Nm | ||||
| provides a consistent method of starting, stopping and restarting | ||||
| daemons. If | ||||
| .Fl K , -stop | ||||
| is not provided, then we assume we are starting the daemon. | ||||
| .Nm | ||||
| only works with daemons which do not fork. Also, it uses its own pid | ||||
| file, so the daemon should not write a pid file, or the pid file passed | ||||
| to  | ||||
| .Nm | ||||
| should not be the one the daemon writes. | ||||
| .Pp | ||||
| Here are the options to specify the daemon and how it should start or stop: | ||||
| .Bl -tag -width indent | ||||
| .It Fl p , -pidfile Ar pidfile | ||||
| When starting, we write a | ||||
| .Ar pidfile | ||||
| so we know which supervisor to stop.  When stopping we only stop the pid(s) | ||||
| listed in the | ||||
| .Ar pidfile . | ||||
| .It Fl u , -user Ar user Ns Op : Ns Ar group | ||||
| Start the daemon as the | ||||
| .Ar user | ||||
| and update $HOME accordingly or stop daemons | ||||
| owned by the user. You can optionally append a | ||||
| .Ar group | ||||
| name here also. | ||||
| .It Fl v , -verbose | ||||
| Print the action(s) that are taken just before doing them. | ||||
| .Pp | ||||
| The options are as follows: | ||||
| .Bl -tag -width indent | ||||
| .It Fl d , -chdir Ar path | ||||
| chdir to this directory before starting the daemon. | ||||
| .It Fl e , -env Ar VAR=VALUE | ||||
| Set the environment variable VAR to VALUE. | ||||
| .It Fl g , -group Ar group | ||||
| Start the daemon as in the group. | ||||
| .It Fl I , -ionice Ar class Ns Op : Ns Ar data | ||||
| Modifies the IO scheduling priority of the daemon. | ||||
| Class can be 0 for none, 1 for real time, 2 for best effort and 3 for idle. | ||||
| Data can be from 0 to 7 inclusive. | ||||
| .It Fl k , -umask Ar mode | ||||
| Set the umask of the daemon. | ||||
| .It Fl N , -nicelevel Ar level | ||||
| Modifies the scheduling priority of the daemon. | ||||
| .It Fl r , -chroot Ar path | ||||
| chroot to this directory before starting the daemon. All other paths, such | ||||
| as the path to the daemon, chdir and pidfile, should be relative to the chroot. | ||||
| .It Fl u , -user Ar user | ||||
| Start the daemon as the specified user. | ||||
| .It Fl 1 , -stdout Ar logfile | ||||
| Redirect the standard output of the process to logfile. | ||||
| Must be an absolute pathname, but relative to the path optionally given with | ||||
| .Fl r , -chroot . | ||||
| The logfile can also be a named pipe. | ||||
| .It Fl 2 , -stderr Ar logfile | ||||
| The same thing as | ||||
| .Fl 1 , -stdout | ||||
| but with the standard error output. | ||||
| .El | ||||
| .Sh ENVIRONMENT | ||||
| .Va SSD_NICELEVEL | ||||
| can also set the scheduling priority of the daemon, but the command line | ||||
| option takes precedence. | ||||
| .Sh NOTE | ||||
| .Nm | ||||
| uses | ||||
| .Xr getopt 3 | ||||
| to parse its options, which allows it to accept the `--' option which will | ||||
| cause it to stop processing options at that point. Any subsequent arguments | ||||
| are passed as arguments to the daemon to start and used when finding a daemon | ||||
| to stop or signal. | ||||
| .Sh SEE ALSO | ||||
| .Xr chdir 2 , | ||||
| .Xr chroot 2 , | ||||
| .Xr getopt 3 , | ||||
| .Xr nice 2 , | ||||
| .Xr rc_find_pids 3 | ||||
| .Sh BUGS | ||||
| .Nm | ||||
| cannot stop an interpreted daemon that no longer exists without a pidfile. | ||||
| .Sh HISTORY | ||||
| .Nm | ||||
| first appeared in Debian. | ||||
| .Pp | ||||
| This is a complete re-implementation with the process finding code in the | ||||
| OpenRC library (librc, -lrc) so other programs can make use of it. | ||||
| .Sh AUTHORS | ||||
| .An William Hubbs <w.d.hubbs@gmail.com> | ||||
| @@ -3,6 +3,7 @@ include ../mk/net.mk | ||||
| BOOT=		bootmisc fsck hostname localmount loopback \ | ||||
| 		root swap swapfiles sysctl urandom ${BOOT-${OS}} | ||||
| DEFAULT=	local netmount | ||||
| NONETWORK=	local | ||||
| SHUTDOWN=	savecache ${SHUTDOWN-${OS}} | ||||
| SYSINIT=	${SYSINIT-${OS}} | ||||
|  | ||||
| @@ -10,6 +11,7 @@ LEVELDIR=	${DESTDIR}/${SYSCONFDIR}/runlevels | ||||
| SYSINITDIR=	${LEVELDIR}/sysinit | ||||
| BOOTDIR=	${LEVELDIR}/boot | ||||
| DEFAULTDIR=	${LEVELDIR}/default | ||||
| NONETWORKDIR=	${LEVELDIR}/nonetwork | ||||
| SHUTDOWNDIR=	${LEVELDIR}/shutdown | ||||
|  | ||||
| ifeq (${MKNET},yes) | ||||
| @@ -72,6 +74,14 @@ install: | ||||
| 			fi; \ | ||||
| 			ln -snf ${INITDIR}/"$$x" ${DEFAULTDIR}/"$$x" || exit $$?; done \ | ||||
| 	fi | ||||
| 	if ! test -d "${NONETWORKDIR}"; then \ | ||||
| 		${INSTALL} -d ${NONETWORKDIR} || exit $$?; \ | ||||
| 		for x in ${NONETWORK}; do \ | ||||
| 			if test "${MKPREFIX}" = yes; then \ | ||||
| 				grep -q "keyword .*-prefix" ${INITFILES}/"$$x" && continue; \ | ||||
| 			fi; \ | ||||
| 			ln -snf ${INITDIR}/"$$x" ${NONETWORKDIR}/"$$x" || exit $$?; done \ | ||||
| 	fi | ||||
| 	if ! test -d "${SHUTDOWNDIR}"; then \ | ||||
| 		${INSTALL} -d ${SHUTDOWNDIR} || exit $$?; \ | ||||
| 		for x in ${SHUTDOWN}; do \ | ||||
|   | ||||
| @@ -52,8 +52,8 @@ if [ ! -d $scandir ]; then | ||||
| 	exit 1 | ||||
| fi | ||||
|  | ||||
| # Make sure s6-svscan is running  | ||||
| if ! pgrep s6-svscan >/dev/null ; then  | ||||
| # Make sure s6-svscan is running | ||||
| if ! pgrep s6-svscan >/dev/null ; then | ||||
| 	printf "s6-svscan is not running\n" | ||||
| 	exit 1 | ||||
| fi | ||||
| @@ -141,7 +141,7 @@ do | ||||
| 	fi | ||||
| done | ||||
|  | ||||
| # Cleanup  | ||||
| # Cleanup | ||||
| rm -f $statfile 2>/dev/null | ||||
|  | ||||
| printf "\n\n" | ||||
|   | ||||
| @@ -1,7 +1,8 @@ | ||||
| DIR=	${LIBEXECDIR}/sh | ||||
| SRCS=	init.sh.in functions.sh.in gendepends.sh.in \ | ||||
| 	openrc-run.sh.in rc-functions.sh.in tmpfiles.sh.in ${SRCS-${OS}} | ||||
| INC=	rc-mount.sh functions.sh rc-functions.sh s6.sh start-stop-daemon.sh | ||||
| INC=	functions.sh rc-mount.sh rc-functions.sh s6.sh start-stop-daemon.sh \ | ||||
| 		supervise-daemon.sh | ||||
| BIN=	gendepends.sh init.sh openrc-run.sh tmpfiles.sh ${BIN-${OS}} | ||||
|  | ||||
| INSTALLAFTER=	_installafter | ||||
|   | ||||
| @@ -22,7 +22,7 @@ apply_file() { | ||||
|  | ||||
| 	### FILE FORMAT ### | ||||
| 	# See https://www.kernel.org/doc/Documentation/binfmt_misc.txt | ||||
| 	while read line; do | ||||
| 	while read -r line; do | ||||
| 		LINENUM=$(( LINENUM+1 )) | ||||
| 		case $line in | ||||
| 			\#*) continue ;; | ||||
|   | ||||
| @@ -154,6 +154,7 @@ start() | ||||
| 	local func=ssd_start | ||||
| 	case "$supervisor" in | ||||
| 		s6) func=s6_start ;; | ||||
| 		supervise-daemon) func=supervise_start ;; | ||||
| 		?*) | ||||
| 			ewarn "Invalid supervisor, \"$supervisor\", using start-stop-daemon" | ||||
| 			;; | ||||
| @@ -166,6 +167,7 @@ stop() | ||||
| 	local func=ssd_stop | ||||
| 	case "$supervisor" in | ||||
| 		s6) func=s6_stop ;; | ||||
| 		supervise-daemon) func=supervise_stop ;; | ||||
| 		?*) | ||||
| 			ewarn "Invalid supervisor, \"$supervisor\", using start-stop-daemon" | ||||
| 			;; | ||||
| @@ -178,6 +180,7 @@ status() | ||||
| 	local func=ssd_status | ||||
| 	case "$supervisor" in | ||||
| 		s6) func=s6_status ;; | ||||
| 		supervise-daemon) func=supervise_status ;; | ||||
| 		?*) | ||||
| 			ewarn "Invalid supervisor, \"$supervisor\", using start-stop-daemon" | ||||
| 			;; | ||||
| @@ -215,6 +218,7 @@ fi | ||||
| # load service supervisor functions | ||||
| sourcex "@LIBEXECDIR@/sh/s6.sh" | ||||
| sourcex "@LIBEXECDIR@/sh/start-stop-daemon.sh" | ||||
| sourcex "@LIBEXECDIR@/sh/supervise-daemon.sh" | ||||
|  | ||||
| # Set verbose mode | ||||
| if yesno "${rc_verbose:-$RC_VERBOSE}"; then | ||||
| @@ -244,7 +248,7 @@ for _cmd; do | ||||
| 		break | ||||
| 	fi | ||||
| done | ||||
|   | ||||
|  | ||||
| # Load our script | ||||
| sourcex "$RC_SERVICE" | ||||
|  | ||||
|   | ||||
							
								
								
									
										2
									
								
								sh/s6.sh
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								sh/s6.sh
									
									
									
									
									
								
							| @@ -41,7 +41,7 @@ s6_stop() | ||||
|  fi | ||||
| 	s6_service_link="${RC_SVCDIR}/s6-scan/${s6_service_path##*/}" | ||||
| 	ebegin "Stopping ${name:-$RC_SVCNAME}" | ||||
| 	s6-svc -Dd -T ${s6_service_timeout_stop:-10000} "${s6_service_link}" | ||||
| 	s6-svc -wD -d -T ${s6_service_timeout_stop:-10000} "${s6_service_link}" | ||||
| 	set -- $(s6-svstat "${s6_service_link}") | ||||
| 	[ "$1" = "down" ] | ||||
| 	eend $? "Failed to stop $RC_SVCNAME" | ||||
|   | ||||
| @@ -40,6 +40,7 @@ ssd_start() | ||||
| 	fi | ||||
| 	eval start-stop-daemon --start \ | ||||
| 		--exec $command \ | ||||
| 		${chroot:+--chroot} $chroot \ | ||||
| 		${procname:+--name} $procname \ | ||||
| 		${pidfile:+--pidfile} $pidfile \ | ||||
| 		${command_user+--user} $command_user \ | ||||
| @@ -47,6 +48,7 @@ ssd_start() | ||||
| 		-- $command_args $command_args_background | ||||
| 	if eend $? "Failed to start $RC_SVCNAME"; then | ||||
| 		service_set_value "command" "${command}" | ||||
| 		[ -n "${chroot}" ] && service_set_value "chroot" "${chroot}" | ||||
| 		[ -n "${pidfile}" ] && service_set_value "pidfile" "${pidfile}" | ||||
| 		[ -n "${procname}" ] && service_set_value "procname" "${procname}" | ||||
| 		return 0 | ||||
| @@ -62,9 +64,11 @@ ssd_start() | ||||
| ssd_stop() | ||||
| { | ||||
| 	local startcommand="$(service_get_value "command")" | ||||
| 	local startchroot="$(service_get_value "chroot")" | ||||
| 	local startpidfile="$(service_get_value "pidfile")" | ||||
| 	local startprocname="$(service_get_value "procname")" | ||||
| 	command="${startcommand:-$command}" | ||||
| 	chroot="${startchroot:-$chroot}" | ||||
| 	pidfile="${startpidfile:-$pidfile}" | ||||
| 	procname="${startprocname:-$procname}" | ||||
| 	[ -n "$command" -o -n "$procname" -o -n "$pidfile" ] || return 0 | ||||
| @@ -73,7 +77,7 @@ ssd_stop() | ||||
| 		${retry:+--retry} $retry \ | ||||
| 		${command:+--exec} $command \ | ||||
| 		${procname:+--name} $procname \ | ||||
| 		${pidfile:+--pidfile} $pidfile \ | ||||
| 		${pidfile:+--pidfile} $chroot$pidfile \ | ||||
| 		${stopsig:+--signal} $stopsig | ||||
|  | ||||
| 	eend $? "Failed to stop $RC_SVCNAME" | ||||
|   | ||||
							
								
								
									
										55
									
								
								sh/supervise-daemon.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								sh/supervise-daemon.sh
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | ||||
| # start / stop / status functions for supervise-daemon | ||||
|  | ||||
| # Copyright (c) 2016 The OpenRC Authors. | ||||
| # See the Authors file at the top-level directory of this distribution and | ||||
| # https://github.com/OpenRC/openrc/blob/master/AUTHORS | ||||
| # | ||||
| # This file is part of OpenRC. It is subject to the license terms in | ||||
| # the LICENSE file found in the top-level directory of this | ||||
| # distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE | ||||
| # This file may not be copied, modified, propagated, or distributed | ||||
| #    except according to the terms contained in the LICENSE file. | ||||
|  | ||||
| supervise_start() | ||||
| { | ||||
| 	if [ -z "$command" ]; then | ||||
| 		ewarn "The command variable is undefined." | ||||
| 		ewarn "There is nothing for ${name:-$RC_SVCNAME} to start." | ||||
| 		return 1 | ||||
| 	fi | ||||
|  | ||||
| 	ebegin "Starting ${name:-$RC_SVCNAME}" | ||||
| 	eval supervise-daemon --start \ | ||||
| 		${chroot:+--chroot} $chroot \ | ||||
| 		${pidfile:+--pidfile} $pidfile \ | ||||
| 		${command_user+--user} $command_user \ | ||||
| 		$supervise_daemon_args \ | ||||
| 		$command \ | ||||
| 		-- $command_args $command_args_foreground | ||||
| 	rc=$? | ||||
| 	if [ $rc = 0 ]; then | ||||
| 		[ -n "${chroot}" ] && service_set_value "chroot" "${chroot}" | ||||
| 		[ -n "${pidfile}" ] && service_set_value "pidfile" "${pidfile}" | ||||
| 	fi | ||||
| 	eend $rc "failed to start $RC_SVCNAME" | ||||
| } | ||||
|  | ||||
| supervise_stop() | ||||
| { | ||||
| 	local startchroot="$(service_get_value "chroot")" | ||||
| 	local startpidfile="$(service_get_value "pidfile")" | ||||
| 	chroot="${startchroot:-$chroot}" | ||||
| 	pidfile="${startpidfile:-$pidfile}" | ||||
| 	[ -n "$pidfile" ] || return 0 | ||||
| 	ebegin "Stopping ${name:-$RC_SVCNAME}" | ||||
| 	supervise-daemon --stop \ | ||||
| 		${pidfile:+--pidfile} $chroot$pidfile \ | ||||
| 		${stopsig:+--signal} $stopsig | ||||
|  | ||||
| 	eend $? "Failed to stop $RC_SVCNAME" | ||||
| } | ||||
|  | ||||
| supervise_status() | ||||
| { | ||||
| 	_status | ||||
| } | ||||
| @@ -26,7 +26,6 @@ | ||||
| #include <unistd.h> | ||||
|  | ||||
| #include "helpers.h" | ||||
| #include "rc.h" | ||||
|  | ||||
| #define RC_LEVEL_BOOT           "boot" | ||||
| #define RC_LEVEL_DEFAULT        "default" | ||||
| @@ -61,10 +60,6 @@ int is_writable(const char *); | ||||
| #define service_stop(service)  exec_service(service, "stop"); | ||||
|  | ||||
| int parse_mode(mode_t *, char *); | ||||
| const char *detect_prefix(void); | ||||
| const char *get_systype(void); | ||||
| const char *detect_container(void); | ||||
| const char *detect_vm(void); | ||||
|  | ||||
| /* Handy function so we can wrap einfo around our deptree */ | ||||
| RC_DEPTREE *_rc_deptree_load (int, int *); | ||||
|   | ||||
| @@ -717,14 +717,16 @@ rc_deptree_update_needed(time_t *newest, char *file) | ||||
| } | ||||
| librc_hidden_def(rc_deptree_update_needed) | ||||
|  | ||||
| /* This is a 6 phase operation | ||||
| /* This is a 7 phase operation | ||||
|    Phase 1 is a shell script which loads each init script and config in turn | ||||
|    and echos their dependency info to stdout | ||||
|    Phase 2 takes that and populates a depinfo object with that data | ||||
|    Phase 3 adds any provided services to the depinfo object | ||||
|    Phase 4 scans that depinfo object and puts in backlinks | ||||
|    Phase 5 removes broken before dependencies | ||||
|    Phase 6 saves the depinfo object to disk | ||||
|    Phase 6 looks for duplicate services indicating a real and virtual service | ||||
|    with the same names | ||||
|    Phase 7 saves the depinfo object to disk | ||||
|    */ | ||||
| bool | ||||
| rc_deptree_update(void) | ||||
| @@ -733,15 +735,16 @@ rc_deptree_update(void) | ||||
| 	RC_DEPTREE *deptree, *providers; | ||||
| 	RC_DEPINFO *depinfo = NULL, *depinfo_np, *di; | ||||
| 	RC_DEPTYPE *deptype = NULL, *dt_np, *dt, *provide; | ||||
| 	RC_STRINGLIST *config, *types, *sorted, *visited; | ||||
| 	RC_STRINGLIST *config, *dupes, *types, *sorted, *visited; | ||||
| 	RC_STRING *s, *s2, *s2_np, *s3, *s4; | ||||
| 	char *line = NULL; | ||||
| 	size_t len = 0; | ||||
| 	char *depend, *depends, *service, *type, *nosys, *onosys; | ||||
| 	size_t i, k, l; | ||||
| 	bool retval = true; | ||||
| 	const char *sys = NULL; | ||||
| 	const char *sys = rc_sys(); | ||||
| 	struct utsname uts; | ||||
| 	int serrno; | ||||
|  | ||||
| 	/* Some init scripts need RC_LIBEXECDIR to source stuff | ||||
| 	   Ideally we should be setting our full env instead */ | ||||
| @@ -847,9 +850,6 @@ rc_deptree_update(void) | ||||
|  | ||||
| 	/* Phase 2 - if we're a special system, remove services that don't | ||||
| 	 * work for them. This doesn't stop them from being run directly. */ | ||||
| 	sys = detect_container(); | ||||
| 		if (!sys) | ||||
| 			sys = detect_vm(); | ||||
| 	if (sys) { | ||||
| 		len = strlen(sys); | ||||
| 		nosys = xmalloc(len + 2); | ||||
| @@ -999,7 +999,22 @@ rc_deptree_update(void) | ||||
| 	} | ||||
| 	rc_stringlist_free(types); | ||||
|  | ||||
| 	/* Phase 6 - save to disk | ||||
| 	/* Phase 6 - Print errors for duplicate services */ | ||||
| 	dupes = rc_stringlist_new(); | ||||
| 	TAILQ_FOREACH(depinfo, deptree, entries) { | ||||
| 		serrno = errno; | ||||
| 		errno = 0; | ||||
| 		rc_stringlist_addu(dupes,depinfo->service); | ||||
| 		if (errno == EEXIST) { | ||||
| 			fprintf(stderr, | ||||
| 					"Error: %s is the name of a real and virtual service.\n", | ||||
| 					depinfo->service); | ||||
| 		} | ||||
| 		errno = serrno; | ||||
| 	} | ||||
| 	rc_stringlist_free(dupes); | ||||
|  | ||||
| 	/* Phase 7 - save to disk | ||||
| 	   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 | ||||
| 	   This works and should be entirely shell parseable provided that depend | ||||
|   | ||||
| @@ -198,13 +198,9 @@ found: | ||||
| #endif | ||||
|  | ||||
|  | ||||
| const char * | ||||
| rc_sys(void) | ||||
| static const char * | ||||
| get_systype(void) | ||||
| { | ||||
| #ifdef PREFIX | ||||
| 	return RC_SYS_PREFIX; | ||||
| #endif | ||||
|  | ||||
| 	char *systype = rc_conf_value("rc_sys"); | ||||
| 	if (systype) { | ||||
| 		char *s = systype; | ||||
| @@ -215,10 +211,37 @@ rc_sys(void) | ||||
| 			s++; | ||||
| 		} | ||||
| 	} | ||||
| 	return systype; | ||||
| } | ||||
|  | ||||
| static const char * | ||||
| detect_prefix(const char *systype) | ||||
| { | ||||
| #ifdef PREFIX | ||||
| 	return RC_SYS_PREFIX; | ||||
| #else | ||||
| 	if (systype) { | ||||
| 		if (strcmp(systype, RC_SYS_NONE) == 0) | ||||
| 			return NULL; | ||||
| 		if (strcmp(systype, RC_SYS_PREFIX) == 0) | ||||
| 			return RC_SYS_PREFIX; | ||||
| 	} | ||||
|  | ||||
| 	return NULL; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| static const char * | ||||
| detect_container(const char *systype) | ||||
| { | ||||
| #ifdef __FreeBSD__ | ||||
| 	if (systype && strcmp(systype, RC_SYS_JAIL) == 0) | ||||
| 		return RC_SYS_JAIL; | ||||
| 	if (systype) { | ||||
| 		if (strcmp(systype, RC_SYS_NONE) == 0) | ||||
| 		       return NULL; | ||||
| 		if (strcmp(systype, RC_SYS_JAIL) == 0) | ||||
| 			return RC_SYS_JAIL; | ||||
| 	} | ||||
|  | ||||
| 	int jailed = 0; | ||||
| 	size_t len = sizeof(jailed); | ||||
|  | ||||
| @@ -227,25 +250,10 @@ rc_sys(void) | ||||
| 			return RC_SYS_JAIL; | ||||
| #endif | ||||
|  | ||||
| #ifdef __NetBSD__ | ||||
| 	if (systype) { | ||||
| 		if(strcmp(systype, RC_SYS_XEN0) == 0) | ||||
| 				return RC_SYS_XEN0; | ||||
| 		if (strcmp(systype, RC_SYS_XENU) == 0) | ||||
| 			return RC_SYS_XENU; | ||||
| 	} | ||||
| 	if (exists("/kern/xen/privcmd")) | ||||
| 		return RC_SYS_XEN0; | ||||
| 	if (exists("/kern/xen")) | ||||
| 		return RC_SYS_XENU; | ||||
| #endif | ||||
|  | ||||
| #ifdef __linux__ | ||||
| 	if (systype) { | ||||
| 		if (strcmp(systype, RC_SYS_XEN0) == 0) | ||||
| 			return RC_SYS_XEN0; | ||||
| 		if (strcmp(systype, RC_SYS_XENU) == 0) | ||||
| 			return RC_SYS_XENU; | ||||
| 		if (strcmp(systype, RC_SYS_NONE) == 0) | ||||
| 			return NULL; | ||||
| 		if (strcmp(systype, RC_SYS_UML) == 0) | ||||
| 			return RC_SYS_UML; | ||||
| 		if (strcmp(systype, RC_SYS_VSERVER) == 0) | ||||
| @@ -261,11 +269,7 @@ rc_sys(void) | ||||
| 		if (strcmp(systype, RC_SYS_DOCKER) == 0) | ||||
| 				return RC_SYS_DOCKER; | ||||
| 	} | ||||
| 	if (exists("/proc/xen")) { | ||||
| 		if (file_regex("/proc/xen/capabilities", "control_d")) | ||||
| 			return RC_SYS_XEN0; | ||||
| 		return RC_SYS_XENU; | ||||
| 	} else if (file_regex("/proc/cpuinfo", "UML")) | ||||
| 	if (file_regex("/proc/cpuinfo", "UML")) | ||||
| 		return RC_SYS_UML; | ||||
| 	else if (file_regex("/proc/self/status", | ||||
| 		"(s_context|VxID):[[:space:]]*[1-9]")) | ||||
| @@ -287,6 +291,61 @@ rc_sys(void) | ||||
|  | ||||
| 	return NULL; | ||||
| } | ||||
|  | ||||
| static const char * | ||||
| detect_vm(const char *systype) | ||||
| { | ||||
| #ifdef __NetBSD__ | ||||
| 	if (systype) { | ||||
| 		if (strcmp(systype, RC_SYS_NONE) == 0) | ||||
| 			return NULL; | ||||
| 		if (strcmp(systype, RC_SYS_XEN0) == 0) | ||||
| 			return RC_SYS_XEN0; | ||||
| 		if (strcmp(systype, RC_SYS_XENU) == 0) | ||||
| 			return RC_SYS_XENU; | ||||
| 	} | ||||
| 	if (exists("/kern/xen/privcmd")) | ||||
| 		return RC_SYS_XEN0; | ||||
| 	if (exists("/kern/xen")) | ||||
| 		return RC_SYS_XENU; | ||||
| #endif | ||||
|  | ||||
| #ifdef __linux__ | ||||
| 	if (systype) { | ||||
| 		if (strcmp(systype, RC_SYS_NONE) == 0) | ||||
| 			return NULL; | ||||
| 		if (strcmp(systype, RC_SYS_XEN0) == 0) | ||||
| 			return RC_SYS_XEN0; | ||||
| 		if (strcmp(systype, RC_SYS_XENU) == 0) | ||||
| 			return RC_SYS_XENU; | ||||
| 	} | ||||
| 	if (exists("/proc/xen")) { | ||||
| 		if (file_regex("/proc/xen/capabilities", "control_d")) | ||||
| 			return RC_SYS_XEN0; | ||||
| 		return RC_SYS_XENU; | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| 	return NULL; | ||||
| } | ||||
|  | ||||
| const char * | ||||
| rc_sys(void) | ||||
| { | ||||
| 	const char *systype; | ||||
| 	const char *sys; | ||||
|  | ||||
| 	systype = get_systype(); | ||||
| 	sys = detect_prefix(systype); | ||||
| 	if (!sys) { | ||||
| 		sys = detect_container(systype); | ||||
| 		if (!sys) { | ||||
| 			sys = detect_vm(systype); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return sys; | ||||
| } | ||||
| librc_hidden_def(rc_sys) | ||||
|  | ||||
| static const char * | ||||
|   | ||||
| @@ -318,6 +318,7 @@ bool rc_service_daemons_crashed(const char *); | ||||
|  * Some services cannot work in these systems, or we do something else. */ | ||||
| #define RC_SYS_DOCKER  "DOCKER" | ||||
| #define RC_SYS_JAIL    "JAIL" | ||||
| #define RC_SYS_NONE    "" | ||||
| #define RC_SYS_OPENVZ  "OPENVZ" | ||||
| #define RC_SYS_LXC     "LXC" | ||||
| #define RC_SYS_PREFIX  "PREFIX" | ||||
|   | ||||
							
								
								
									
										1
									
								
								src/rc/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								src/rc/.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -5,6 +5,7 @@ rc-update | ||||
| runscript | ||||
| service | ||||
| start-stop-daemon | ||||
| supervise-daemon | ||||
| einfon | ||||
| einfo | ||||
| ewarnn | ||||
|   | ||||
| @@ -1,4 +1,9 @@ | ||||
| SRCS=	rc.c 	rc-logger.c rc-misc.c rc-plugin.c | ||||
| SRCS=	checkpath.c do_e.c do_mark_service.c do_service.c \ | ||||
| 		do_value.c fstabinfo.c is_newer_than.c is_older_than.c \ | ||||
| 		mountinfo.c openrc-run.c rc-abort.c rc.c \ | ||||
| 		rc-depend.c rc-logger.c rc-misc.c rc-plugin.c \ | ||||
| 		rc-service.c rc-status.c rc-update.c \ | ||||
| 		shell_var.c start-stop-daemon.c supervise-daemon.c swclock.c _usage.c | ||||
|  | ||||
| ifeq (${MKSELINUX},yes) | ||||
| SRCS+=		rc-selinux.c | ||||
| @@ -11,7 +16,8 @@ SBINDIR=	${PREFIX}/sbin | ||||
| LINKDIR=	${LIBEXECDIR} | ||||
|  | ||||
| BINPROGS=	rc-status | ||||
| SBINPROGS = openrc openrc-run rc rc-service rc-update runscript service start-stop-daemon | ||||
| SBINPROGS = openrc openrc-run rc rc-service rc-update runscript service \ | ||||
| 			start-stop-daemon supervise-daemon | ||||
| RC_BINPROGS=	einfon einfo ewarnn ewarn eerrorn eerror ebegin eend ewend \ | ||||
| 				eindent eoutdent esyslog eval_ecolors ewaitfile \ | ||||
| 				veinfo vewarn vebegin veend vewend veindent veoutdent \ | ||||
| @@ -69,13 +75,17 @@ install: all | ||||
| 	if test "${MKPAM}" = pam; then \ | ||||
| 		${INSTALL} -d ${DESTDIR}${PAMDIR}; \ | ||||
| 		${INSTALL} -m ${PAMMODE} start-stop-daemon.pam ${DESTDIR}${PAMDIR}/start-stop-daemon; \ | ||||
| 		${INSTALL} -m ${PAMMODE} supervise-daemon.pam ${DESTDIR}${PAMDIR}/supervise-daemon; \ | ||||
| 	fi | ||||
|  | ||||
| check test:: | ||||
|  | ||||
| all: ${ALL_PROGS} | ||||
|  | ||||
| checkpath: checkpath.o _usage.o rc-misc.o rc-selinux.o | ||||
| checkpath: checkpath.o _usage.o rc-misc.o | ||||
| ifeq (${MKSELINUX},yes) | ||||
| checkpath: rc-selinux.o | ||||
| endif | ||||
| 	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD} | ||||
|  | ||||
| einfon einfo ewarnn ewarn eerrorn eerror ebegin eend ewend \ | ||||
| @@ -101,10 +111,13 @@ mark_service_hotplugged mark_service_failed: do_mark_service.o rc-misc.o | ||||
| mountinfo: mountinfo.o _usage.o rc-misc.o | ||||
| 	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD} | ||||
|  | ||||
| openrc rc: rc.o rc-logger.o rc-misc.o rc-plugin.o rc-selinux.o _usage.o | ||||
| openrc rc: rc.o rc-logger.o rc-misc.o rc-plugin.o _usage.o | ||||
| 	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD} | ||||
|  | ||||
| openrc-run runscript: openrc-run.o _usage.o rc-misc.o rc-plugin.o | ||||
| ifeq (${MKSELINUX},yes) | ||||
| openrc-run runscript: rc-selinux.o | ||||
| endif | ||||
| 	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD} | ||||
|  | ||||
| rc-abort: rc-abort.o | ||||
| @@ -125,6 +138,9 @@ rc-update: rc-update.o _usage.o rc-misc.o | ||||
| start-stop-daemon: start-stop-daemon.o _usage.o rc-misc.o | ||||
| 	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD} | ||||
|  | ||||
| supervise-daemon: supervise-daemon.o _usage.o rc-misc.o | ||||
| 	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD} | ||||
|  | ||||
| service_get_value service_set_value get_options save_options: do_value.o rc-misc.o | ||||
| 	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD} | ||||
|  | ||||
|   | ||||
| @@ -13,6 +13,7 @@ | ||||
| #include <ctype.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include "rc.h" | ||||
| #include "rc-misc.h" | ||||
| #include "_usage.h" | ||||
| #include "version.h" | ||||
| @@ -46,10 +47,7 @@ _noreturn void show_version(void) | ||||
| 	const char *systype = NULL; | ||||
|  | ||||
| 	printf("%s (OpenRC", applet); | ||||
| 	systype = detect_container(); | ||||
| 	if (!systype) | ||||
| 		systype = detect_vm(); | ||||
| 	if (systype) | ||||
| 	if ((systype = rc_sys())) | ||||
| 		printf(" [%s]", systype); | ||||
| 	printf(") %s", VERSION); | ||||
| #ifdef BRANDING | ||||
|   | ||||
| @@ -30,6 +30,7 @@ | ||||
| #include <unistd.h> | ||||
|  | ||||
| #include "einfo.h" | ||||
| #include "rc.h" | ||||
| #include "rc-misc.h" | ||||
| #include "rc-selinux.h" | ||||
| #include "_usage.h" | ||||
|   | ||||
| @@ -28,6 +28,7 @@ | ||||
| #include <unistd.h> | ||||
|  | ||||
| #include "einfo.h" | ||||
| #include "rc.h" | ||||
| #include "rc-misc.h" | ||||
|  | ||||
| const char *applet = NULL; | ||||
|   | ||||
| @@ -15,6 +15,7 @@ | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
|  | ||||
| #include "rc.h" | ||||
| #include "rc-misc.h" | ||||
|  | ||||
| int main(int argc, char **argv) | ||||
|   | ||||
| @@ -15,6 +15,7 @@ | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
|  | ||||
| #include "rc.h" | ||||
| #include "rc-misc.h" | ||||
|  | ||||
| int main(int argc, char **argv) | ||||
|   | ||||
| @@ -390,6 +390,14 @@ svc_exec(const char *arg1, const char *arg2) | ||||
| 		} | ||||
|  | ||||
| 		if (exists(RC_SVCDIR "/openrc-run.sh")) { | ||||
| 			if (arg2) | ||||
| 				einfov("Executing: %s %s %s %s %s", | ||||
| 					RC_SVCDIR "/openrc-run.sh", RC_SVCDIR "/openrc-run.sh", | ||||
| 					service, arg1, arg2); | ||||
| 			else | ||||
| 				einfov("Executing: %s %s %s %s", | ||||
| 					RC_SVCDIR "/openrc-run.sh", RC_SVCDIR "/openrc-run.sh", | ||||
| 					service, arg1); | ||||
| 			execl(RC_SVCDIR "/openrc-run.sh", | ||||
| 			    RC_SVCDIR "/openrc-run.sh", | ||||
| 			    service, arg1, arg2, (char *) NULL); | ||||
| @@ -397,6 +405,16 @@ svc_exec(const char *arg1, const char *arg2) | ||||
| 			    service, strerror(errno)); | ||||
| 			_exit(EXIT_FAILURE); | ||||
| 		} else { | ||||
| 			if (arg2) | ||||
| 				einfov("Executing: %s %s %s %s %s", | ||||
| 					RC_LIBEXECDIR "/sh/openrc-run.sh", | ||||
| 					RC_LIBEXECDIR "/sh/openrc-run.sh", | ||||
| 			    	service, arg1, arg2); | ||||
| 			else | ||||
| 				einfov("Executing: %s %s %s %s", | ||||
| 					RC_LIBEXECDIR "/sh/openrc-run.sh", | ||||
| 					RC_LIBEXECDIR "/sh/openrc-run.sh", | ||||
| 			    	service, arg1); | ||||
| 			execl(RC_LIBEXECDIR "/sh/openrc-run.sh", | ||||
| 			    RC_LIBEXECDIR "/sh/openrc-run.sh", | ||||
| 			    service, arg1, arg2, (char *) NULL); | ||||
| @@ -1088,6 +1106,7 @@ service_plugable(void) | ||||
| int main(int argc, char **argv) | ||||
| { | ||||
| 	bool doneone = false; | ||||
| 	bool runscript = false; | ||||
| 	int retval, opt, depoptions = RC_DEP_TRACE; | ||||
| 	RC_STRING *svc; | ||||
| 	char path[PATH_MAX], lnk[PATH_MAX]; | ||||
| @@ -1103,6 +1122,10 @@ int main(int argc, char **argv) | ||||
| 		exit(EXIT_FAILURE); | ||||
| 	} | ||||
|  | ||||
| 	applet = basename_c(argv[0]); | ||||
| 	if (strcmp(applet, "runscript") == 0) | ||||
| 		runscript = true; | ||||
|  | ||||
| 	if (stat(argv[1], &stbuf) != 0) { | ||||
| 		fprintf(stderr, "openrc-run `%s': %s\n", | ||||
| 		    argv[1], strerror(errno)); | ||||
| @@ -1150,6 +1173,9 @@ int main(int argc, char **argv) | ||||
| 	if (argc < 3) | ||||
| 		usage(EXIT_FAILURE); | ||||
|  | ||||
| 	if (runscript) | ||||
| 		ewarn("%s uses runscript, please convert to openrc-run.", service); | ||||
|  | ||||
| 	/* Change dir to / to ensure all init scripts don't use stuff in pwd */ | ||||
| 	if (chdir("/") == -1) | ||||
| 		eerror("chdir: %s", strerror(errno)); | ||||
|   | ||||
							
								
								
									
										171
									
								
								src/rc/rc-misc.c
									
									
									
									
									
								
							
							
						
						
									
										171
									
								
								src/rc/rc-misc.c
									
									
									
									
									
								
							| @@ -27,7 +27,6 @@ | ||||
| #include <ctype.h> | ||||
| #include <fcntl.h> | ||||
| #include <limits.h> | ||||
| #  include <regex.h> | ||||
| #include <signal.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| @@ -53,6 +52,7 @@ rc_conf_yesno(const char *setting) | ||||
| static const char *const env_whitelist[] = { | ||||
| 	"EERROR_QUIET", "EINFO_QUIET", | ||||
| 	"IN_BACKGROUND", "IN_HOTPLUG", | ||||
| 	"LANG", "LC_MESSAGES", "TERM", | ||||
| 	NULL | ||||
| }; | ||||
|  | ||||
| @@ -68,6 +68,12 @@ env_filter(void) | ||||
|  | ||||
| 	/* Add the user defined list of vars */ | ||||
| 	env_allow = rc_stringlist_split(rc_conf_value("rc_env_allow"), " "); | ||||
| 	/* | ||||
| 	 * If '*' is an entry in rc_env_allow, do nothing as we are to pass | ||||
| 	 * through all environment variables. | ||||
| 	 */ | ||||
| 	if (rc_stringlist_find(env_allow, "*")) | ||||
| 		return; | ||||
| 	profile = rc_config_load(RC_PROFILE_ENV); | ||||
|  | ||||
| 	/* Copy the env and work from this so we can manipulate it safely */ | ||||
| @@ -125,7 +131,7 @@ env_config(void) | ||||
| 	char *np; | ||||
| 	char *npp; | ||||
| 	char *tok; | ||||
| 	const char *sys = NULL; | ||||
| 	const char *sys = rc_sys(); | ||||
| 	char buffer[PATH_MAX]; | ||||
|  | ||||
| 	/* Ensure our PATH is prefixed with the system locations first | ||||
| @@ -176,9 +182,7 @@ env_config(void) | ||||
| 	} else | ||||
| 		setenv("RC_DEFAULTLEVEL", RC_LEVEL_DEFAULT, 1); | ||||
|  | ||||
| 	sys = detect_container(); | ||||
| 	if (!sys) | ||||
| 		sys = detect_vm(); | ||||
| 	if (sys) | ||||
| 		setenv("RC_SYS", sys, 1); | ||||
|  | ||||
| #ifdef PREFIX | ||||
| @@ -335,163 +339,6 @@ is_writable(const char *path) | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static bool file_regex(const char *file, const char *regex) | ||||
| { | ||||
| 	FILE *fp; | ||||
| 	char *line = NULL; | ||||
| 	size_t len = 0; | ||||
| 	regex_t re; | ||||
| 	bool retval = true; | ||||
| 	int result; | ||||
|  | ||||
| 	if (!(fp = fopen(file, "r"))) | ||||
| 		return false; | ||||
|  | ||||
| 	if ((result = regcomp(&re, regex, REG_EXTENDED | REG_NOSUB)) != 0) { | ||||
| 		fclose(fp); | ||||
| 		line = xmalloc(sizeof(char) * BUFSIZ); | ||||
| 		regerror(result, &re, line, BUFSIZ); | ||||
| 		fprintf(stderr, "file_regex: %s", line); | ||||
| 		free(line); | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	while ((rc_getline(&line, &len, fp))) { | ||||
| 		char *str = line; | ||||
| 		/* some /proc files have \0 separated content so we have to | ||||
| 		   loop through the 'line' */ | ||||
| 		do { | ||||
| 			if (regexec(&re, str, 0, NULL, 0) == 0) | ||||
| 				goto found; | ||||
| 			str += strlen(str) + 1; | ||||
| 			/* len is the size of allocated buffer and we don't | ||||
| 			   want call regexec BUFSIZE times. find next str */ | ||||
| 			while (str < line + len && *str == '\0') | ||||
| 				str++; | ||||
| 		} while (str < line + len); | ||||
| 	} | ||||
| 	retval = false; | ||||
| found: | ||||
| 	fclose(fp); | ||||
| 	free(line); | ||||
| 	regfree(&re); | ||||
|  | ||||
| 	return retval; | ||||
| } | ||||
|  | ||||
| const char *detect_prefix(void) | ||||
| { | ||||
| #ifdef PREFIX | ||||
| 	return RC_SYS_PREFIX; | ||||
| #else | ||||
| 	return NULL; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| const char *get_systype(void) | ||||
| { | ||||
| 	char *systype = rc_conf_value("rc_sys"); | ||||
| 	if (systype) { | ||||
| 		char *s = systype; | ||||
| 		/* Convert to uppercase */ | ||||
| 		while (s && *s) { | ||||
| 			if (islower((unsigned char) *s)) | ||||
| 				*s = toupper((unsigned char) *s); | ||||
| 			s++; | ||||
| 		} | ||||
| 	} | ||||
| 	return systype; | ||||
| } | ||||
|  | ||||
| const char *detect_container(void) | ||||
| { | ||||
| 	const char *systype = get_systype(); | ||||
|  | ||||
| #ifdef __FreeBSD__ | ||||
| 	if (systype && strcmp(systype, RC_SYS_JAIL) == 0) | ||||
| 		return RC_SYS_JAIL; | ||||
| 	int jailed = 0; | ||||
| 	size_t len = sizeof(jailed); | ||||
|  | ||||
| 	if (sysctlbyname("security.jail.jailed", &jailed, &len, NULL, 0) == 0) | ||||
| 		if (jailed == 1) | ||||
| 			return RC_SYS_JAIL; | ||||
| #endif | ||||
|  | ||||
| #ifdef __linux__ | ||||
| 	if (systype) { | ||||
| 		if (strcmp(systype, RC_SYS_UML) == 0) | ||||
| 			return RC_SYS_UML; | ||||
| 		if (strcmp(systype, RC_SYS_VSERVER) == 0) | ||||
| 			return RC_SYS_VSERVER; | ||||
| 		if (strcmp(systype, RC_SYS_OPENVZ) == 0) | ||||
| 			return RC_SYS_OPENVZ; | ||||
| 		if (strcmp(systype, RC_SYS_LXC) == 0) | ||||
| 			return RC_SYS_LXC; | ||||
| 		if (strcmp(systype, RC_SYS_RKT) == 0) | ||||
| 				return RC_SYS_RKT; | ||||
| 		if (strcmp(systype, RC_SYS_SYSTEMD_NSPAWN) == 0) | ||||
| 				return RC_SYS_SYSTEMD_NSPAWN; | ||||
| 		if (strcmp(systype, RC_SYS_DOCKER) == 0) | ||||
| 				return RC_SYS_DOCKER; | ||||
| 	} | ||||
| 	if (file_regex("/proc/cpuinfo", "UML")) | ||||
| 		return RC_SYS_UML; | ||||
| 	else if (file_regex("/proc/self/status", | ||||
| 		"(s_context|VxID):[[:space:]]*[1-9]")) | ||||
| 		return RC_SYS_VSERVER; | ||||
| 	else if (exists("/proc/vz/veinfo") && !exists("/proc/vz/version")) | ||||
| 		return RC_SYS_OPENVZ; | ||||
| 	else if (file_regex("/proc/self/status", | ||||
| 		"envID:[[:space:]]*[1-9]")) | ||||
| 		return RC_SYS_OPENVZ; /* old test */ | ||||
| 	else if (file_regex("/proc/1/environ", "container=lxc")) | ||||
| 		return RC_SYS_LXC; | ||||
| 	else if (file_regex("/proc/1/environ", "container=rkt")) | ||||
| 		return RC_SYS_RKT; | ||||
| 	else if (file_regex("/proc/1/environ", "container=systemd-nspawn")) | ||||
| 		return RC_SYS_SYSTEMD_NSPAWN; | ||||
| 	else if (file_regex("/proc/1/environ", "container=docker")) | ||||
| 		return RC_SYS_DOCKER; | ||||
| #endif | ||||
|  | ||||
| 	return NULL; | ||||
| } | ||||
|  | ||||
| const char *detect_vm(void) | ||||
| { | ||||
| 	const char *systype = get_systype(); | ||||
|  | ||||
| #ifdef __NetBSD__ | ||||
| 	if (systype) { | ||||
| 		if(strcmp(systype, RC_SYS_XEN0) == 0) | ||||
| 				return RC_SYS_XEN0; | ||||
| 		if (strcmp(systype, RC_SYS_XENU) == 0) | ||||
| 			return RC_SYS_XENU; | ||||
| 	} | ||||
| 	if (exists("/kern/xen/privcmd")) | ||||
| 		return RC_SYS_XEN0; | ||||
| 	if (exists("/kern/xen")) | ||||
| 		return RC_SYS_XENU; | ||||
| #endif | ||||
|  | ||||
| #ifdef __linux__ | ||||
| 	if (systype) { | ||||
| 		if (strcmp(systype, RC_SYS_XEN0) == 0) | ||||
| 			return RC_SYS_XEN0; | ||||
| 		if (strcmp(systype, RC_SYS_XENU) == 0) | ||||
| 			return RC_SYS_XENU; | ||||
| 	} | ||||
| 	if (exists("/proc/xen")) { | ||||
| 		if (file_regex("/proc/xen/capabilities", "control_d")) | ||||
| 			return RC_SYS_XEN0; | ||||
| 		return RC_SYS_XENU; | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| 	return NULL; | ||||
| } | ||||
|  | ||||
| RC_DEPTREE * _rc_deptree_load(int force, int *regen) | ||||
| { | ||||
| 	int fd; | ||||
|   | ||||
| @@ -15,8 +15,6 @@ | ||||
|  *    except according to the terms contained in the LICENSE file. | ||||
|  */ | ||||
|  | ||||
| #ifdef HAVE_SELINUX | ||||
|  | ||||
| #include <stddef.h> | ||||
| #include <errno.h> | ||||
| #include <dlfcn.h> | ||||
| @@ -372,7 +370,7 @@ void selinux_setup(char **argv) | ||||
| 	 * which will open the pty with initrc_devpts_t, if it doesnt exist, | ||||
| 	 * fall back to plain exec | ||||
| 	 */ | ||||
| 	if (access("/usr/sbin/open_init_pty", X_OK)) { | ||||
| 	if (!access("/usr/sbin/open_init_pty", X_OK)) { | ||||
| 		if (execvp("/usr/sbin/open_init_pty", argv)) { | ||||
| 			perror("execvp"); | ||||
| 			exit(-1); | ||||
| @@ -386,5 +384,3 @@ out: | ||||
| 	free(run_init_t); | ||||
| 	free(curr_t); | ||||
| } | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -25,10 +25,10 @@ void selinux_setup(char **argv); | ||||
|  | ||||
| /* always return false for selinux_util_open() */ | ||||
| #define selinux_util_open() (0) | ||||
| #define selinux_util_label(x) do { } while(0) | ||||
| #define selinux_util_close() do { } while(0) | ||||
| #define selinux_util_label(x) do { } while (0) | ||||
| #define selinux_util_close() do { } while (0) | ||||
|  | ||||
| #define selinux_setup(x) do { } while(0) | ||||
| #define selinux_setup(x) do { } while (0) | ||||
|  | ||||
| #endif | ||||
|  | ||||
|   | ||||
| @@ -29,10 +29,12 @@ | ||||
|  | ||||
| const char *applet = NULL; | ||||
| const char *extraopts = NULL; | ||||
| const char *getoptstring = "e:ilr:" getoptstring_COMMON; | ||||
| const char *getoptstring = "e:ilr:IN" getoptstring_COMMON; | ||||
| const struct option longopts[] = { | ||||
| 	{ "exists",   1, NULL, 'e' }, | ||||
| 	{ "ifexists", 0, NULL, 'i' }, | ||||
| 	{ "ifinactive", 0, NULL, 'I' }, | ||||
| 	{ "ifnotstarted", 0, NULL, 'N' }, | ||||
| 	{ "list",     0, NULL, 'l' }, | ||||
| 	{ "resolve",  1, NULL, 'r' }, | ||||
| 	longopts_COMMON | ||||
| @@ -40,6 +42,8 @@ const struct option longopts[] = { | ||||
| const char * const longopts_help[] = { | ||||
| 	"tests if the service exists or not", | ||||
| 	"if the service exists then run the command", | ||||
| 	"if the service is inactive then run the command", | ||||
| 	"if the service is not started then run the command", | ||||
| 	"list all available services", | ||||
| 	"resolve the service name to an init script", | ||||
| 	longopts_help_COMMON | ||||
| @@ -56,7 +60,10 @@ int main(int argc, char **argv) | ||||
| 	char *service; | ||||
| 	RC_STRINGLIST *list; | ||||
| 	RC_STRING *s; | ||||
| 	RC_SERVICE state; | ||||
| 	bool if_exists = false; | ||||
| 	bool if_inactive = false; | ||||
| 	bool if_notstarted = false; | ||||
|  | ||||
| 	applet = basename_c(argv[0]); | ||||
| 	/* Ensure that we are only quiet when explicitly told to be */ | ||||
| @@ -77,6 +84,12 @@ int main(int argc, char **argv) | ||||
| 		case 'i': | ||||
| 			if_exists = true; | ||||
| 			break; | ||||
| 		case 'I': | ||||
| 			if_inactive = true; | ||||
| 			break; | ||||
| 		case 'N': | ||||
| 			if_notstarted = true; | ||||
| 			break; | ||||
| 		case 'l': | ||||
| 			list = rc_services_in_runlevel(NULL); | ||||
| 			if (TAILQ_FIRST(list) == NULL) | ||||
| @@ -113,6 +126,11 @@ int main(int argc, char **argv) | ||||
| 			return 0; | ||||
| 		eerrorx("%s: service `%s' does not exist", applet, *argv); | ||||
| 	} | ||||
| 	state = rc_service_state(*argv); | ||||
| 	if (if_inactive && ! (state & RC_SERVICE_INACTIVE)) | ||||
| 		return 0; | ||||
| 	if (if_notstarted && (state & RC_SERVICE_STARTED)) | ||||
| 		return 0; | ||||
| 	*argv = service; | ||||
| 	execv(*argv, argv); | ||||
| 	eerrorx("%s: %s", applet, strerror(errno)); | ||||
|   | ||||
							
								
								
									
										27
									
								
								src/rc/rc.c
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								src/rc/rc.c
									
									
									
									
									
								
							| @@ -281,15 +281,10 @@ open_shell(void) | ||||
| 	struct passwd *pw; | ||||
|  | ||||
| #ifdef __linux__ | ||||
| 	const char *sys = NULL; | ||||
| 	 | ||||
| 	sys = detect_container(); | ||||
| 	if (!sys) | ||||
| 		sys = detect_vm(); | ||||
| 	const char *sys = rc_sys(); | ||||
|  | ||||
| 	/* VSERVER and OPENVZ systems cannot really drop to shells */ | ||||
| 	if (sys && | ||||
| 	    (strcmp(sys, "VSERVER") == 0 || strcmp(sys, "OPENVZ") == 0)) | ||||
| 	/* VSERVER systems cannot really drop to shells */ | ||||
| 	if (sys && strcmp(sys, RC_SYS_VSERVER) == 0) | ||||
| 	{ | ||||
| 		execl("/sbin/halt", "/sbin/halt", "-f", (char *) NULL); | ||||
| 		eerrorx("%s: unable to exec `/sbin/halt': %s", | ||||
| @@ -491,10 +486,7 @@ do_sysinit() | ||||
| 	    uts.machine); | ||||
| #endif | ||||
|  | ||||
| 	sys = detect_container(); | ||||
| 	if (!sys) | ||||
| 		sys = detect_vm(); | ||||
| 	if (sys) | ||||
| 	if ((sys = rc_sys())) | ||||
| 		printf(" [%s]", sys); | ||||
|  | ||||
| 	printf("%s\n\n", ecolor(ECOLOR_NORMAL)); | ||||
| @@ -509,10 +501,7 @@ do_sysinit() | ||||
|  | ||||
| 	/* init may have mounted /proc so we can now detect or real | ||||
| 	 * sys */ | ||||
| 	sys = detect_container(); | ||||
| 	if (!sys) | ||||
| 		sys = detect_vm(); | ||||
| 	if (sys) | ||||
| 	if ((sys = rc_sys())) | ||||
| 		setenv("RC_SYS", sys, 1); | ||||
| } | ||||
|  | ||||
| @@ -832,9 +821,7 @@ int main(int argc, char **argv) | ||||
| 			eerrorx("%s: %s", applet, strerror(errno)); | ||||
| 			/* NOTREACHED */ | ||||
| 		case 'S': | ||||
| 			systype = detect_container(); | ||||
| 			if (!systype) | ||||
| 				systype = detect_vm(); | ||||
| 			systype = rc_sys(); | ||||
| 			if (systype) | ||||
| 				printf("%s\n", systype); | ||||
| 			exit(EXIT_SUCCESS); | ||||
| @@ -843,6 +830,8 @@ int main(int argc, char **argv) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (strcmp(applet, "rc") == 0) | ||||
| 		ewarn("rc is deprecated, please use openrc instead."); | ||||
| 	newlevel = argv[optind++]; | ||||
| 	/* To make life easier, we only have the shutdown runlevel as | ||||
| 	 * nothing really needs to know that we're rebooting. | ||||
|   | ||||
| @@ -1242,7 +1242,7 @@ int main(int argc, char **argv) | ||||
| 		if (redirect_stdout) { | ||||
| 			if ((stdout_fd = open(redirect_stdout, | ||||
| 				    O_WRONLY | O_CREAT | O_APPEND, | ||||
| 				    S_IRUSR | S_IWUSR)) == -1) | ||||
| 				    S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)) == -1) | ||||
| 				eerrorx("%s: unable to open the logfile" | ||||
| 				    " for stdout `%s': %s", | ||||
| 				    applet, redirect_stdout, strerror(errno)); | ||||
| @@ -1250,7 +1250,7 @@ int main(int argc, char **argv) | ||||
| 		if (redirect_stderr) { | ||||
| 			if ((stderr_fd = open(redirect_stderr, | ||||
| 				    O_WRONLY | O_CREAT | O_APPEND, | ||||
| 				    S_IRUSR | S_IWUSR)) == -1) | ||||
| 				    S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)) == -1) | ||||
| 				eerrorx("%s: unable to open the logfile" | ||||
| 				    " for stderr `%s': %s", | ||||
| 				    applet, redirect_stderr, strerror(errno)); | ||||
|   | ||||
							
								
								
									
										726
									
								
								src/rc/supervise-daemon.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										726
									
								
								src/rc/supervise-daemon.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,726 @@ | ||||
| /* | ||||
|  * supervise-daemon | ||||
|  * This is an experimental supervisor for daemons. | ||||
|  * It will start a deamon and make sure it restarts if it crashes. | ||||
|  */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2016 The OpenRC Authors. | ||||
|  * See the Authors file at the top-level directory of this distribution and | ||||
|  * https://github.com/OpenRC/openrc/blob/master/AUTHORS | ||||
|  * | ||||
|  * This file is part of OpenRC. It is subject to the license terms in | ||||
|  * the LICENSE file found in the top-level directory of this | ||||
|  * distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE | ||||
|  * This file may not be copied, modified, propagated, or distributed | ||||
|  *    except according to the terms contained in the LICENSE file. | ||||
|  */ | ||||
|  | ||||
| /* nano seconds */ | ||||
| #define POLL_INTERVAL   20000000 | ||||
| #define WAIT_PIDFILE   500000000 | ||||
| #define ONE_SECOND    1000000000 | ||||
| #define ONE_MS           1000000 | ||||
|  | ||||
| #include <sys/types.h> | ||||
| #include <sys/ioctl.h> | ||||
| #include <sys/resource.h> | ||||
| #include <sys/stat.h> | ||||
| #include <termios.h> | ||||
| #include <sys/time.h> | ||||
| #include <sys/wait.h> | ||||
|  | ||||
| #ifdef __linux__ | ||||
| #include <sys/syscall.h> /* For io priority */ | ||||
| #endif | ||||
|  | ||||
| #include <ctype.h> | ||||
| #include <errno.h> | ||||
| #include <fcntl.h> | ||||
| #include <getopt.h> | ||||
| #include <limits.h> | ||||
| #include <grp.h> | ||||
| #include <pwd.h> | ||||
| #include <signal.h> | ||||
| #include <stddef.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <syslog.h> | ||||
| #include <time.h> | ||||
| #include <unistd.h> | ||||
|  | ||||
| #ifdef HAVE_PAM | ||||
| #include <security/pam_appl.h> | ||||
|  | ||||
| /* We are not supporting authentication conversations */ | ||||
| static struct pam_conv conv = { NULL, NULL}; | ||||
| #endif | ||||
|  | ||||
| #include "einfo.h" | ||||
| #include "queue.h" | ||||
| #include "rc.h" | ||||
| #include "rc-misc.h" | ||||
| #include "_usage.h" | ||||
|  | ||||
| const char *applet = NULL; | ||||
| const char *extraopts = NULL; | ||||
| const char *getoptstring = "d:e:g:I:Kk:N:p:r:Su:1:2:" \ | ||||
| 	getoptstring_COMMON; | ||||
| const struct option longopts[] = { | ||||
| 	{ "chdir",        1, NULL, 'd'}, | ||||
| 	{ "env",          1, NULL, 'e'}, | ||||
| 	{ "group",        1, NULL, 'g'}, | ||||
| 	{ "ionice",       1, NULL, 'I'}, | ||||
| 	{ "stop",         0, NULL, 'K'}, | ||||
| 	{ "umask",        1, NULL, 'k'}, | ||||
| 	{ "nicelevel",    1, NULL, 'N'}, | ||||
| 	{ "pidfile",      1, NULL, 'p'}, | ||||
| 	{ "user",         1, NULL, 'u'}, | ||||
| 	{ "chroot",       1, NULL, 'r'}, | ||||
| 	{ "start",        0, NULL, 'S'}, | ||||
| 	{ "stdout",       1, NULL, '1'}, | ||||
| 	{ "stderr",       1, NULL, '2'}, | ||||
| 	longopts_COMMON | ||||
| }; | ||||
| const char * const longopts_help[] = { | ||||
| 	"Change the PWD", | ||||
| 	"Set an environment string", | ||||
| 	"Change the process group", | ||||
| 	"Set an ionice class:data when starting", | ||||
| 	"Stop daemon", | ||||
| 	"Set the umask for the daemon", | ||||
| 	"Set a nicelevel when starting", | ||||
| 	"Match pid found in this file", | ||||
| 	"Change the process user", | ||||
| 	"Chroot to this directory", | ||||
| 	"Start daemon", | ||||
| 	"Redirect stdout to file", | ||||
| 	"Redirect stderr to file", | ||||
| 	longopts_help_COMMON | ||||
| }; | ||||
| const char *usagestring = NULL; | ||||
|  | ||||
| static int nicelevel = 0; | ||||
| static int ionicec = -1; | ||||
| static int ioniced = 0; | ||||
| static char *changeuser, *ch_root, *ch_dir; | ||||
| static uid_t uid = 0; | ||||
| static gid_t gid = 0; | ||||
| static int devnull_fd = -1; | ||||
| static int stdin_fd; | ||||
| static int stdout_fd; | ||||
| static int stderr_fd; | ||||
| static char *redirect_stderr = NULL; | ||||
| static char *redirect_stdout = NULL; | ||||
| static bool exiting = false; | ||||
| #ifdef TIOCNOTTY | ||||
| static int tty_fd = -1; | ||||
| #endif | ||||
|  | ||||
| extern char **environ; | ||||
|  | ||||
| #if !defined(SYS_ioprio_set) && defined(__NR_ioprio_set) | ||||
| # define SYS_ioprio_set __NR_ioprio_set | ||||
| #endif | ||||
| #if !defined(__DragonFly__) | ||||
| static inline int ioprio_set(int which, int who, int ioprio) | ||||
| { | ||||
| #ifdef SYS_ioprio_set | ||||
| 	return syscall(SYS_ioprio_set, which, who, ioprio); | ||||
| #else | ||||
| 	return 0; | ||||
| #endif | ||||
| } | ||||
| #endif | ||||
|  | ||||
| static void cleanup(void) | ||||
| { | ||||
| 	free(changeuser); | ||||
| } | ||||
|  | ||||
| static pid_t get_pid(const char *pidfile) | ||||
| { | ||||
| 	FILE *fp; | ||||
| 	pid_t pid; | ||||
|  | ||||
| 	if (! pidfile) | ||||
| 		return -1; | ||||
|  | ||||
| 	if ((fp = fopen(pidfile, "r")) == NULL) { | ||||
| 		ewarnv("%s: fopen `%s': %s", applet, pidfile, strerror(errno)); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	if (fscanf(fp, "%d", &pid) != 1) { | ||||
| 		ewarnv("%s: no pid found in `%s'", applet, pidfile); | ||||
| 		fclose(fp); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	fclose(fp); | ||||
|  | ||||
| 	return pid; | ||||
| } | ||||
|  | ||||
| static void child_process(char *exec, char **argv) | ||||
| { | ||||
| 	RC_STRINGLIST *env_list; | ||||
| 	RC_STRING *env; | ||||
| 	int i; | ||||
| 	char *p; | ||||
| 	char *token; | ||||
| 	size_t len; | ||||
| 	char *newpath; | ||||
| 	char *np; | ||||
| 	char **c; | ||||
| 	char cmdline[PATH_MAX]; | ||||
|  | ||||
| #ifdef HAVE_PAM | ||||
| 	pam_handle_t *pamh = NULL; | ||||
| 	int pamr; | ||||
| 	const char *const *pamenv = NULL; | ||||
| #endif | ||||
|  | ||||
| 	setsid(); | ||||
|  | ||||
| 	if (nicelevel) { | ||||
| 		if (setpriority(PRIO_PROCESS, getpid(), nicelevel) == -1) | ||||
| 			eerrorx("%s: setpriority %d: %s", applet, nicelevel, | ||||
| 					strerror(errno)); | ||||
| 	} | ||||
|  | ||||
| 	if (ionicec != -1 && ioprio_set(1, getpid(), ionicec | ioniced) == -1) | ||||
| 		eerrorx("%s: ioprio_set %d %d: %s", applet, ionicec, ioniced, | ||||
| 				strerror(errno)); | ||||
|  | ||||
| 	if (ch_root && chroot(ch_root) < 0) | ||||
| 		eerrorx("%s: chroot `%s': %s", applet, ch_root, strerror(errno)); | ||||
|  | ||||
| 	if (ch_dir && chdir(ch_dir) < 0) | ||||
| 		eerrorx("%s: chdir `%s': %s", applet, ch_dir, strerror(errno)); | ||||
|  | ||||
| #ifdef HAVE_PAM | ||||
| 	if (changeuser != NULL) { | ||||
| 		pamr = pam_start("supervise-daemon", | ||||
| 		    changeuser, &conv, &pamh); | ||||
|  | ||||
| 		if (pamr == PAM_SUCCESS) | ||||
| 			pamr = pam_acct_mgmt(pamh, PAM_SILENT); | ||||
| 		if (pamr == PAM_SUCCESS) | ||||
| 			pamr = pam_open_session(pamh, PAM_SILENT); | ||||
| 		if (pamr != PAM_SUCCESS) | ||||
| 			eerrorx("%s: pam error: %s", applet, pam_strerror(pamh, pamr)); | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| 	if (gid && setgid(gid)) | ||||
| 		eerrorx("%s: unable to set groupid to %d", applet, gid); | ||||
| 	if (changeuser && initgroups(changeuser, gid)) | ||||
| 		eerrorx("%s: initgroups (%s, %d)", applet, changeuser, gid); | ||||
| 	if (uid && setuid(uid)) | ||||
| 		eerrorx ("%s: unable to set userid to %d", applet, uid); | ||||
|  | ||||
| 	/* Close any fd's to the passwd database */ | ||||
| 	endpwent(); | ||||
|  | ||||
| #ifdef TIOCNOTTY | ||||
| 	ioctl(tty_fd, TIOCNOTTY, 0); | ||||
| 	close(tty_fd); | ||||
| #endif | ||||
|  | ||||
| 	/* Clean the environment of any RC_ variables */ | ||||
| 	env_list = rc_stringlist_new(); | ||||
| 	i = 0; | ||||
| 	while (environ[i]) | ||||
| 		rc_stringlist_add(env_list, environ[i++]); | ||||
|  | ||||
| #ifdef HAVE_PAM | ||||
| 	if (changeuser != NULL) { | ||||
| 		pamenv = (const char *const *)pam_getenvlist(pamh); | ||||
| 		if (pamenv) { | ||||
| 			while (*pamenv) { | ||||
| 				/* Don't add strings unless they set a var */ | ||||
| 				if (strchr(*pamenv, '=')) | ||||
| 					putenv(xstrdup(*pamenv)); | ||||
| 				else | ||||
| 					unsetenv(*pamenv); | ||||
| 				pamenv++; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| 	TAILQ_FOREACH(env, env_list, entries) { | ||||
| 		if ((strncmp(env->value, "RC_", 3) == 0 && | ||||
| 			strncmp(env->value, "RC_SERVICE=", 10) != 0 && | ||||
| 			strncmp(env->value, "RC_SVCNAME=", 10) != 0) || | ||||
| 		    strncmp(env->value, "SSD_NICELEVEL=", 14) == 0) | ||||
| 		{ | ||||
| 			p = strchr(env->value, '='); | ||||
| 			*p = '\0'; | ||||
| 			unsetenv(env->value); | ||||
| 			continue; | ||||
| 		} | ||||
| 	} | ||||
| 	rc_stringlist_free(env_list); | ||||
|  | ||||
| 	/* For the path, remove the rcscript bin dir from it */ | ||||
| 	if ((token = getenv("PATH"))) { | ||||
| 		len = strlen(token); | ||||
| 		newpath = np = xmalloc(len + 1); | ||||
| 		while (token && *token) { | ||||
| 			p = strchr(token, ':'); | ||||
| 			if (p) { | ||||
| 				*p++ = '\0'; | ||||
| 				while (*p == ':') | ||||
| 					p++; | ||||
| 			} | ||||
| 			if (strcmp(token, RC_LIBEXECDIR "/bin") != 0 && | ||||
| 			    strcmp(token, RC_LIBEXECDIR "/sbin") != 0) | ||||
| 			{ | ||||
| 				len = strlen(token); | ||||
| 				if (np != newpath) | ||||
| 					*np++ = ':'; | ||||
| 				memcpy(np, token, len); | ||||
| 				np += len; | ||||
| 				} | ||||
| 			token = p; | ||||
| 		} | ||||
| 		*np = '\0'; | ||||
| 		unsetenv("PATH"); | ||||
| 		setenv("PATH", newpath, 1); | ||||
| 	} | ||||
|  | ||||
| 	stdin_fd = devnull_fd; | ||||
| 	stdout_fd = devnull_fd; | ||||
| 	stderr_fd = devnull_fd; | ||||
| 	if (redirect_stdout) { | ||||
| 		if ((stdout_fd = open(redirect_stdout, | ||||
| 			    O_WRONLY | O_CREAT | O_APPEND, | ||||
| 			    S_IRUSR | S_IWUSR)) == -1) | ||||
| 			eerrorx("%s: unable to open the logfile" | ||||
| 				    " for stdout `%s': %s", | ||||
| 				    applet, redirect_stdout, strerror(errno)); | ||||
| 	} | ||||
| 	if (redirect_stderr) { | ||||
| 		if ((stderr_fd = open(redirect_stderr, | ||||
| 			    O_WRONLY | O_CREAT | O_APPEND, | ||||
| 			    S_IRUSR | S_IWUSR)) == -1) | ||||
| 			eerrorx("%s: unable to open the logfile" | ||||
| 			    " for stderr `%s': %s", | ||||
| 			    applet, redirect_stderr, strerror(errno)); | ||||
| 	} | ||||
|  | ||||
| 	dup2(stdin_fd, STDIN_FILENO); | ||||
| 	if (redirect_stdout || rc_yesno(getenv("EINFO_QUIET"))) | ||||
| 		dup2(stdout_fd, STDOUT_FILENO); | ||||
| 	if (redirect_stderr || rc_yesno(getenv("EINFO_QUIET"))) | ||||
| 		dup2(stderr_fd, STDERR_FILENO); | ||||
|  | ||||
| 	for (i = getdtablesize() - 1; i >= 3; --i) | ||||
| 		close(i); | ||||
|  | ||||
| 	*cmdline = '\0'; | ||||
| 	c = argv; | ||||
| 	while (*c) { | ||||
| 		strcat(cmdline, *c); | ||||
| 		strcat(cmdline, " "); | ||||
| 		c++; | ||||
| 	} | ||||
| 	syslog(LOG_INFO, "Running command line: %s", cmdline); | ||||
| 	execvp(exec, argv); | ||||
|  | ||||
| #ifdef HAVE_PAM | ||||
| 	if (changeuser != NULL && pamr == PAM_SUCCESS) | ||||
| 		pam_close_session(pamh, PAM_SILENT); | ||||
| #endif | ||||
| 	eerrorx("%s: failed to exec `%s': %s", applet, exec,strerror(errno)); | ||||
| } | ||||
|  | ||||
| static void handle_signal(int sig) | ||||
| { | ||||
| 	int serrno = errno; | ||||
| 	char signame[10] = { '\0' }; | ||||
|  | ||||
| 	switch (sig) { | ||||
| 	case SIGINT: | ||||
| 		snprintf(signame, sizeof(signame), "SIGINT"); | ||||
| 		break; | ||||
| 	case SIGTERM: | ||||
| 		snprintf(signame, sizeof(signame), "SIGTERM"); | ||||
| 		break; | ||||
| 	case SIGQUIT: | ||||
| 		snprintf(signame, sizeof(signame), "SIGQUIT"); | ||||
| 		break; | ||||
| 	} | ||||
|  | ||||
| 	if (*signame != 0) { | ||||
| 		syslog(LOG_INFO, "%s: caught signal %s, exiting", applet, signame); | ||||
| 		exiting = true; | ||||
| 	} else | ||||
| 		syslog(LOG_INFO, "%s: caught unknown signal %d", applet, sig); | ||||
|  | ||||
| 	/* Restore errno */ | ||||
| 	errno = serrno; | ||||
| } | ||||
|  | ||||
| static char * expand_home(const char *home, const char *path) | ||||
| { | ||||
| 	char *opath, *ppath, *p, *nh; | ||||
| 	size_t len; | ||||
| 	struct passwd *pw; | ||||
|  | ||||
| 	if (!path || *path != '~') | ||||
| 		return xstrdup(path); | ||||
|  | ||||
| 	opath = ppath = xstrdup(path); | ||||
| 	if (ppath[1] != '/' && ppath[1] != '\0') { | ||||
| 		p = strchr(ppath + 1, '/'); | ||||
| 		if (p) | ||||
| 			*p = '\0'; | ||||
| 		pw = getpwnam(ppath + 1); | ||||
| 		if (pw) { | ||||
| 			home = pw->pw_dir; | ||||
| 			ppath = p; | ||||
| 			if (ppath) | ||||
| 				*ppath = '/'; | ||||
| 		} else | ||||
| 			home = NULL; | ||||
| 	} else | ||||
| 		ppath++; | ||||
|  | ||||
| 	if (!home) { | ||||
| 	free(opath); | ||||
| 		return xstrdup(path); | ||||
| 	} | ||||
| 	if (!ppath) { | ||||
| 		free(opath); | ||||
| 		return xstrdup(home); | ||||
| 	} | ||||
|  | ||||
| 	len = strlen(ppath) + strlen(home) + 1; | ||||
| 	nh = xmalloc(len); | ||||
| 	snprintf(nh, len, "%s%s", home, ppath); | ||||
| 	free(opath); | ||||
| 	return nh; | ||||
| } | ||||
|  | ||||
| int main(int argc, char **argv) | ||||
| { | ||||
| 	int opt; | ||||
| 	bool start = false; | ||||
| 	bool stop = false; | ||||
| 	char *exec = NULL; | ||||
| 	char *pidfile = NULL; | ||||
| 	char *home = NULL; | ||||
| 	int tid = 0; | ||||
| 	pid_t child_pid, pid; | ||||
| 	char *svcname = getenv("RC_SVCNAME"); | ||||
| 	char *tmp; | ||||
| 	char *p; | ||||
| 	char *token; | ||||
| 	int i; | ||||
| 	char exec_file[PATH_MAX]; | ||||
| 	struct passwd *pw; | ||||
| 	struct group *gr; | ||||
| 	FILE *fp; | ||||
| 	mode_t numask = 022; | ||||
|  | ||||
| 	applet = basename_c(argv[0]); | ||||
| 	atexit(cleanup); | ||||
|  | ||||
| 	signal_setup(SIGINT, handle_signal); | ||||
| 	signal_setup(SIGQUIT, handle_signal); | ||||
| 	signal_setup(SIGTERM, handle_signal); | ||||
| 	openlog(applet, LOG_PID, LOG_DAEMON); | ||||
|  | ||||
| 	if ((tmp = getenv("SSD_NICELEVEL"))) | ||||
| 		if (sscanf(tmp, "%d", &nicelevel) != 1) | ||||
| 			eerror("%s: invalid nice level `%s' (SSD_NICELEVEL)", | ||||
| 			    applet, tmp); | ||||
|  | ||||
| 	/* Get our user name and initial dir */ | ||||
| 	p = getenv("USER"); | ||||
| 	home = getenv("HOME"); | ||||
| 	if (home == NULL || p == NULL) { | ||||
| 		pw = getpwuid(getuid()); | ||||
| 		if (pw != NULL) { | ||||
| 			if (p == NULL) | ||||
| 				setenv("USER", pw->pw_name, 1); | ||||
| 			if (home == NULL) { | ||||
| 				setenv("HOME", pw->pw_dir, 1); | ||||
| 				home = pw->pw_dir; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	while ((opt = getopt_long(argc, argv, getoptstring, longopts, | ||||
| 		    (int *) 0)) != -1) | ||||
| 		switch (opt) { | ||||
| 		case 'I': /* --ionice */ | ||||
| 			if (sscanf(optarg, "%d:%d", &ionicec, &ioniced) == 0) | ||||
| 				eerrorx("%s: invalid ionice `%s'", | ||||
| 				    applet, optarg); | ||||
| 			if (ionicec == 0) | ||||
| 				ioniced = 0; | ||||
| 			else if (ionicec == 3) | ||||
| 				ioniced = 7; | ||||
| 			ionicec <<= 13; /* class shift */ | ||||
| 			break; | ||||
|  | ||||
| 		case 'K':  /* --stop */ | ||||
| 			stop = true; | ||||
| 			break; | ||||
|  | ||||
| 		case 'N':  /* --nice */ | ||||
| 			if (sscanf(optarg, "%d", &nicelevel) != 1) | ||||
| 				eerrorx("%s: invalid nice level `%s'", | ||||
| 				    applet, optarg); | ||||
| 			break; | ||||
|  | ||||
| 		case 'S':  /* --start */ | ||||
| 			start = true; | ||||
| 			break; | ||||
|  | ||||
| 		case 'd':  /* --chdir /new/dir */ | ||||
| 			ch_dir = optarg; | ||||
| 			break; | ||||
|  | ||||
| 		case 'e': /* --env */ | ||||
| 			putenv(optarg); | ||||
| 			break; | ||||
|  | ||||
| 		case 'g':  /* --group <group>|<gid> */ | ||||
| 			if (sscanf(optarg, "%d", &tid) != 1) | ||||
| 				gr = getgrnam(optarg); | ||||
| 			else | ||||
| 				gr = getgrgid((gid_t)tid); | ||||
| 			if (gr == NULL) | ||||
| 				eerrorx("%s: group `%s' not found", | ||||
| 				    applet, optarg); | ||||
| 			gid = gr->gr_gid; | ||||
| 			break; | ||||
|  | ||||
| 		case 'k': | ||||
| 			if (parse_mode(&numask, optarg)) | ||||
| 				eerrorx("%s: invalid mode `%s'", | ||||
| 				    applet, optarg); | ||||
| 			break; | ||||
|  | ||||
| 		case 'p':  /* --pidfile <pid-file> */ | ||||
| 			pidfile = optarg; | ||||
| 			break; | ||||
|  | ||||
| 		case 'r':  /* --chroot /new/root */ | ||||
| 			ch_root = optarg; | ||||
| 			break; | ||||
|  | ||||
| 		case 'u':  /* --user <username>|<uid> */ | ||||
| 		{ | ||||
| 			p = optarg; | ||||
| 			tmp = strsep(&p, ":"); | ||||
| 			changeuser = xstrdup(tmp); | ||||
| 			if (sscanf(tmp, "%d", &tid) != 1) | ||||
| 				pw = getpwnam(tmp); | ||||
| 			else | ||||
| 				pw = getpwuid((uid_t)tid); | ||||
|  | ||||
| 			if (pw == NULL) | ||||
| 				eerrorx("%s: user `%s' not found", | ||||
| 				    applet, tmp); | ||||
| 			uid = pw->pw_uid; | ||||
| 			home = pw->pw_dir; | ||||
| 			unsetenv("HOME"); | ||||
| 			if (pw->pw_dir) | ||||
| 				setenv("HOME", pw->pw_dir, 1); | ||||
| 			unsetenv("USER"); | ||||
| 			if (pw->pw_name) | ||||
| 				setenv("USER", pw->pw_name, 1); | ||||
| 			if (gid == 0) | ||||
| 				gid = pw->pw_gid; | ||||
|  | ||||
| 			if (p) { | ||||
| 				tmp = strsep (&p, ":"); | ||||
| 				if (sscanf(tmp, "%d", &tid) != 1) | ||||
| 					gr = getgrnam(tmp); | ||||
| 				else | ||||
| 					gr = getgrgid((gid_t) tid); | ||||
|  | ||||
| 				if (gr == NULL) | ||||
| 					eerrorx("%s: group `%s'" | ||||
| 					    " not found", | ||||
| 					    applet, tmp); | ||||
| 				gid = gr->gr_gid; | ||||
| 			} | ||||
| 		} | ||||
| 		break; | ||||
|  | ||||
| 		case '1':   /* --stdout /path/to/stdout.lgfile */ | ||||
| 			redirect_stdout = optarg; | ||||
| 			break; | ||||
|  | ||||
| 		case '2':  /* --stderr /path/to/stderr.logfile */ | ||||
| 			redirect_stderr = optarg; | ||||
| 			break; | ||||
|  | ||||
| 		case_RC_COMMON_GETOPT | ||||
| 		} | ||||
|  | ||||
| 	if (!pidfile) | ||||
| 		eerrorx("%s: --pidfile must be specified", applet); | ||||
|  | ||||
| 	endpwent(); | ||||
| 	argc -= optind; | ||||
| 	argv += optind; | ||||
| 	exec = *argv; | ||||
|  | ||||
| 	if (start) { | ||||
| 		if (!exec) | ||||
| 			eerrorx("%s: nothing to start", applet); | ||||
| 	} | ||||
|  | ||||
| 	/* Expand ~ */ | ||||
| 	if (ch_dir && *ch_dir == '~') | ||||
| 		ch_dir = expand_home(home, ch_dir); | ||||
| 	if (ch_root && *ch_root == '~') | ||||
| 		ch_root = expand_home(home, ch_root); | ||||
| 	if (exec) { | ||||
| 		if (*exec == '~') | ||||
| 			exec = expand_home(home, exec); | ||||
|  | ||||
| 		/* Validate that the binary exists if we are starting */ | ||||
| 		if (*exec == '/' || *exec == '.') { | ||||
| 			/* Full or relative path */ | ||||
| 			if (ch_root) | ||||
| 				snprintf(exec_file, sizeof(exec_file), | ||||
| 				    "%s/%s", ch_root, exec); | ||||
| 			else | ||||
| 				snprintf(exec_file, sizeof(exec_file), | ||||
| 				    "%s", exec); | ||||
| 		} else { | ||||
| 			/* Something in $PATH */ | ||||
| 			p = tmp = xstrdup(getenv("PATH")); | ||||
| 			*exec_file = '\0'; | ||||
| 			while ((token = strsep(&p, ":"))) { | ||||
| 				if (ch_root) | ||||
| 					snprintf(exec_file, sizeof(exec_file), | ||||
| 					    "%s/%s/%s", | ||||
| 					    ch_root, token, exec); | ||||
| 				else | ||||
| 					snprintf(exec_file, sizeof(exec_file), | ||||
| 					    "%s/%s", token, exec); | ||||
| 				if (exists(exec_file)) | ||||
| 					break; | ||||
| 				*exec_file = '\0'; | ||||
| 			} | ||||
| 			free(tmp); | ||||
| 		} | ||||
| 	} | ||||
| 	if (start && !exists(exec_file)) | ||||
| 		eerrorx("%s: %s does not exist", applet, | ||||
| 		    *exec_file ? exec_file : exec); | ||||
|  | ||||
| 	if (stop) { | ||||
| 		pid = get_pid(pidfile); | ||||
| 		if (pid == -1) | ||||
| 			i = pid; | ||||
| 		else | ||||
| 			i = kill(pid, SIGTERM); | ||||
| 		if (i != 0) | ||||
| 			/* We failed to stop something */ | ||||
| 			exit(EXIT_FAILURE); | ||||
|  | ||||
| 		/* Even if we have not actually killed anything, we should | ||||
| 		 * remove information about it as it may have unexpectedly | ||||
| 		 * crashed out. We should also return success as the end | ||||
| 		 * result would be the same. */ | ||||
| 		if (pidfile && exists(pidfile)) | ||||
| 			unlink(pidfile); | ||||
| 		if (svcname) | ||||
| 			rc_service_daemon_set(svcname, exec, | ||||
| 			    (const char *const *)argv, | ||||
| 			    pidfile, false); | ||||
| 		exit(EXIT_SUCCESS); | ||||
| 	} | ||||
|  | ||||
| 	pid = get_pid(pidfile); | ||||
| 	if (pid != -1) | ||||
| 		if (kill(pid, 0) == 0) | ||||
| 			eerrorx("%s: %s is already running", applet, exec); | ||||
|  | ||||
| 	einfov("Detaching to start `%s'", exec); | ||||
| 	eindentv(); | ||||
|  | ||||
| 	/* Remove existing pidfile */ | ||||
| 	if (pidfile) | ||||
| 		unlink(pidfile); | ||||
|  | ||||
| 	/* | ||||
| 	 * Make sure we can write a pid file | ||||
| 	 */ | ||||
| 	fp = fopen(pidfile, "w"); | ||||
| 	if (! fp) | ||||
| 		eerrorx("%s: fopen `%s': %s", applet, pidfile, strerror(errno)); | ||||
| 		fclose(fp); | ||||
|  | ||||
| 	child_pid = fork(); | ||||
| 	if (child_pid == -1) | ||||
| 		eerrorx("%s: fork: %s", applet, strerror(errno)); | ||||
|  | ||||
| 	/* first parent process, do nothing. */ | ||||
| 	if (child_pid != 0) | ||||
| 		exit(EXIT_SUCCESS); | ||||
|  | ||||
| 	child_pid = fork(); | ||||
| 	if (child_pid == -1) | ||||
| 		eerrorx("%s: fork: %s", applet, strerror(errno)); | ||||
|  | ||||
| 	if (child_pid != 0) { | ||||
| 		/* this is the supervisor */ | ||||
| 		umask(numask); | ||||
|  | ||||
| #ifdef TIOCNOTTY | ||||
| 		tty_fd = open("/dev/tty", O_RDWR); | ||||
| #endif | ||||
|  | ||||
| 		devnull_fd = open("/dev/null", O_RDWR); | ||||
|  | ||||
| 		fp = fopen(pidfile, "w"); | ||||
| 		if (! fp) | ||||
| 			eerrorx("%s: fopen `%s': %s", applet, pidfile, strerror(errno)); | ||||
| 		fprintf(fp, "%d\n", getpid()); | ||||
| 		fclose(fp); | ||||
|  | ||||
| 		/* | ||||
| 		 * Supervisor main loop | ||||
| 		 */ | ||||
| 		i = 0; | ||||
| 		while (!exiting) { | ||||
| 			wait(&i); | ||||
| 			if (exiting) { | ||||
| 				syslog(LOG_INFO, "stopping %s, pid %d", exec, child_pid); | ||||
| 				kill(child_pid, SIGTERM); | ||||
| 			} else { | ||||
| 				if (WIFEXITED(i)) | ||||
| 					syslog(LOG_INFO, "%s, pid %d, exited with return code %d", | ||||
| 							exec, child_pid, WEXITSTATUS(i)); | ||||
| 				else if (WIFSIGNALED(i)) | ||||
| 					syslog(LOG_INFO, "%s, pid %d, terminated by signal %d", | ||||
| 							exec, child_pid, WTERMSIG(i)); | ||||
| 				child_pid = fork(); | ||||
| 				if (child_pid == -1) | ||||
| 					eerrorx("%s: fork: %s", applet, strerror(errno)); | ||||
| 				if (child_pid == 0) | ||||
| 					child_process(exec, argv); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if (svcname) | ||||
| 			rc_service_daemon_set(svcname, exec, | ||||
| 									(const char * const *) argv, pidfile, true); | ||||
|  | ||||
| 		exit(EXIT_SUCCESS); | ||||
| 	} else if (child_pid == 0) | ||||
| 		child_process(exec, argv); | ||||
| } | ||||
							
								
								
									
										6
									
								
								src/rc/supervise-daemon.pam
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/rc/supervise-daemon.pam
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| #%PAM-1.0 | ||||
|  | ||||
| auth            required        pam_permit.so | ||||
| account         required        pam_permit.so | ||||
| password        required        pam_deny.so | ||||
| session         optional        pam_limits.so | ||||
| @@ -30,6 +30,7 @@ | ||||
| #include <utime.h> | ||||
|  | ||||
| #include "einfo.h" | ||||
| #include "rc.h" | ||||
| #include "rc-misc.h" | ||||
| #include "_usage.h" | ||||
|  | ||||
|   | ||||
| @@ -85,12 +85,14 @@ eend $? "Trailing newlines need to be deleted:"$'\n'"${out}" | ||||
|  | ||||
| ebegin "Checking for obsolete functions" | ||||
| out=$(cd ${top_srcdir}; find src -name '*.[ch]' \ | ||||
| 	! -name queue.h \ | ||||
| 	-exec grep -n -E '\<(malloc|memory|sys/(errno|fcntl|signal|stropts|termios|unistd))\.h\>' {} +) | ||||
| [ -z "${out}" ] | ||||
| eend $? "Avoid these obsolete functions:"$'\n'"${out}" | ||||
|  | ||||
| ebegin "Checking for x* func usage" | ||||
| out=$(cd ${top_srcdir}; find src -name '*.[ch]' \ | ||||
| 	! -name queue.h \ | ||||
| 	-exec grep -n -E '\<(malloc|strdup)[[:space:]]*\(' {} + \ | ||||
| 	| grep -v \ | ||||
| 		-e src/includes/helpers.h \ | ||||
| @@ -100,6 +102,7 @@ eend $? "These need to be using the x* variant:"$'\n'"${out}" | ||||
|  | ||||
| ebegin "Checking spacing style" | ||||
| out=$(cd ${top_srcdir}; find src -name '*.[ch]' \ | ||||
| 	! -name queue.h \ | ||||
| 	-exec grep -n -E \ | ||||
| 		-e '\<(for|if|switch|while)\(' \ | ||||
| 		-e '\<(for|if|switch|while) \( ' \ | ||||
|   | ||||
							
								
								
									
										49
									
								
								supervise-daemon-guide.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								supervise-daemon-guide.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| # Using supervise-daemon | ||||
|  | ||||
| Beginning with OpenRC-0.21 we have our own daemon supervisor, | ||||
| supervise-daemon., which can start a daemon and restart it if it | ||||
| terminates unexpectedly. | ||||
|  | ||||
| The following is a brief guide on using this capability. | ||||
|  | ||||
| ## Use Default start, stop and status functions | ||||
|  | ||||
| If you write your own start, stop and status functions in your service | ||||
| script, none of this will work. You must allow OpenRC to use the default | ||||
| functions. | ||||
|  | ||||
| ## Daemons must not fork | ||||
|  | ||||
| Any deamon that you would like to have monitored by supervise-daemon | ||||
| must not fork. Instead, it must stay in the foreground. If the daemon | ||||
| itself forks, the supervisor will be unable to monitor it. | ||||
|  | ||||
| If the daemon can be configured to not fork, this should be done in the | ||||
| daemon's configuration file, or by adding a command line option that | ||||
| instructs it not to fork to the command_args_foreground variable shown | ||||
| below. | ||||
|  | ||||
| ## Variable Settings | ||||
|  | ||||
| The most important setting is the supervisor variable. At the top of | ||||
| your service script, you should set this variable as follows: | ||||
|  | ||||
| supervisor=supervise-daemon | ||||
|  | ||||
| Several other variables affect the way services behave under | ||||
| supervise-daemon. They are documented on the  openrc-run man page, but I | ||||
| will list them here for convenience: | ||||
|  | ||||
| pidfile=/pid/of/supervisor.pid | ||||
|  | ||||
| If you are using start-stop-daemon to monitor your scripts, the pidfile | ||||
| is the path to the pidfile the daemon creates. If, on the other hand, | ||||
| you are using supervise-daemon, this is the path to the pidfile the | ||||
| supervisor creates. | ||||
|  | ||||
| command_args_foreground should be used if the daemon you want to monitor | ||||
| forks and goes to the background by default. This should be set to the | ||||
| command line option that instructs the daemon to stay in the foreground. | ||||
|  | ||||
| This is very early support, so feel free to file bugs if you have | ||||
| issues. | ||||
| @@ -21,7 +21,3 @@ LD_LIBRARY_PATH=${top_builddir}/src/libeinfo:${top_builddir}/src/librc:${LD_LIBR | ||||
| PATH=${top_builddir}/src/rc:${PATH} | ||||
| export LD_LIBRARY_PATH PATH | ||||
|  | ||||
| cd ${top_srcdir}/src/rc | ||||
| ${MAKE:-make} links >/dev/null | ||||
| cd - | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user