Compare commits
	
		
			146 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					9ec5d36bdd | ||
| 
						 | 
					a097933eda | ||
| 
						 | 
					a6f5b1bb63 | ||
| 
						 | 
					e6d01471fe | ||
| 
						 | 
					d4501a9f06 | ||
| 
						 | 
					ec8abea460 | ||
| 
						 | 
					e4ddfa38e0 | ||
| 
						 | 
					21d30bc6d9 | ||
| 
						 | 
					2a1ff6e49c | ||
| 
						 | 
					6762cb875c | ||
| 
						 | 
					6edf516a1f | ||
| 
						 | 
					7e56a49e23 | ||
| 
						 | 
					fa5aea80c5 | ||
| 
						 | 
					0f4fa41574 | ||
| 
						 | 
					5d6dd97bba | ||
| 
						 | 
					37e2944272 | ||
| 
						 | 
					4e0eace837 | ||
| 
						 | 
					faa8318b3b | ||
| 
						 | 
					08da36149c | ||
| 
						 | 
					56870d0db1 | ||
| 
						 | 
					4d47ce440c | ||
| 
						 | 
					958f57d895 | ||
| 
						 | 
					04886efd85 | ||
| 
						 | 
					d980798d64 | ||
| 
						 | 
					414a9aae6c | ||
| 
						 | 
					a7f475ca04 | ||
| 
						 | 
					3c53680018 | ||
| 
						 | 
					f0ad647303 | ||
| 
						 | 
					b35e03b6b1 | ||
| 
						 | 
					2b1392af2f | ||
| 
						 | 
					a3d0e293ee | ||
| 
						 | 
					0200002b8c | ||
| 
						 | 
					f4e2142089 | ||
| 
						 | 
					49a90f27a8 | ||
| 
						 | 
					2ae60ca041 | ||
| 
						 | 
					6b475ab269 | ||
| 
						 | 
					b302b0c094 | ||
| 
						 | 
					40aa69cf3a | ||
| 
						 | 
					5346fbf2c9 | ||
| 
						 | 
					92e6bdee12 | ||
| 
						 | 
					71f275b2aa | ||
| 
						 | 
					6dc0d0af33 | ||
| 
						 | 
					59a9e53378 | ||
| 
						 | 
					122768d339 | ||
| 
						 | 
					fa3c60c0d8 | ||
| 
						 | 
					61905bfcf5 | ||
| 
						 | 
					3e68013631 | ||
| 
						 | 
					b46123f2e1 | ||
| 
						 | 
					109869641f | ||
| 
						 | 
					e8a2305de0 | ||
| 
						 | 
					f62975a1f8 | ||
| 
						 | 
					5bb6f9aa31 | ||
| 
						 | 
					1ab8541a6c | ||
| 
						 | 
					038c03bef3 | ||
| 
						 | 
					e51dc29e2f | ||
| 
						 | 
					c6047f887a | ||
| 
						 | 
					0506d68427 | ||
| 
						 | 
					c3d666acaf | ||
| 
						 | 
					e93b1d76d1 | ||
| 
						 | 
					acf1e43f81 | ||
| 
						 | 
					f383fd87b1 | ||
| 
						 | 
					cfded513cd | ||
| 
						 | 
					16ff3cd8df | ||
| 
						 | 
					38032626a6 | ||
| 
						 | 
					aa7d3a7911 | ||
| 
						 | 
					98262647a9 | ||
| 
						 | 
					5868abe97b | ||
| 
						 | 
					71aad16256 | ||
| 
						 | 
					e275da84de | ||
| 
						 | 
					a6cc7f06cf | ||
| 
						 | 
					c1178c8eeb | ||
| 
						 | 
					3c031ca978 | ||
| 
						 | 
					8e02406d8f | ||
| 
						 | 
					8dbdabcc5e | ||
| 
						 | 
					488d8989c5 | ||
| 
						 | 
					9e14b35da8 | ||
| 
						 | 
					7b4879cb72 | ||
| 
						 | 
					74cfb455c5 | ||
| 
						 | 
					0110487722 | ||
| 
						 | 
					68b9b0bc2a | ||
| 
						 | 
					4616f8f809 | ||
| 
						 | 
					287d71bd25 | ||
| 
						 | 
					c1ffe4d9f2 | ||
| 
						 | 
					4c517bdb2b | ||
| 
						 | 
					110582491f | ||
| 
						 | 
					5dd1d39d20 | ||
| 
						 | 
					1771bc2a83 | ||
| 
						 | 
					87c98ebb01 | ||
| 
						 | 
					4af5a80b0c | ||
| 
						 | 
					fee2ffe559 | ||
| 
						 | 
					8878f8916b | ||
| 
						 | 
					14e3359a9e | ||
| 
						 | 
					918d955fd2 | ||
| 
						 | 
					92cfa0e543 | ||
| 
						 | 
					c2bd33e483 | ||
| 
						 | 
					f42ec82f21 | ||
| 
						 | 
					7affff568a | ||
| 
						 | 
					4f750933fd | ||
| 
						 | 
					50b69d564a | ||
| 
						 | 
					eb18f4f348 | ||
| 
						 | 
					d5f3fe52c8 | ||
| 
						 | 
					bb1bc6eeb7 | ||
| 
						 | 
					53844fd0dc | ||
| 
						 | 
					14938c29ce | ||
| 
						 | 
					8bf501aaf2 | ||
| 
						 | 
					9d05f68b51 | ||
| 
						 | 
					ee2524cd1d | ||
| 
						 | 
					5c81661d47 | ||
| 
						 | 
					fb96c9c127 | ||
| 
						 | 
					6c456f9383 | ||
| 
						 | 
					d220fc2723 | ||
| 
						 | 
					a2447dfb42 | ||
| 
						 | 
					cee3919908 | ||
| 
						 | 
					0feadd2922 | ||
| 
						 | 
					a7c99506d9 | ||
| 
						 | 
					f012930775 | ||
| 
						 | 
					ddbdb69658 | ||
| 
						 | 
					c84ebb94d1 | ||
| 
						 | 
					3de6395ae3 | ||
| 
						 | 
					6bb7ebec48 | ||
| 
						 | 
					a192caf88f | ||
| 
						 | 
					e805c74d31 | ||
| 
						 | 
					318e873481 | ||
| 
						 | 
					0d15898f58 | ||
| 
						 | 
					971e82784c | ||
| 
						 | 
					90d9ea656f | ||
| 
						 | 
					a3d1c8a0e7 | ||
| 
						 | 
					913b2ca537 | ||
| 
						 | 
					3fe99c8b82 | ||
| 
						 | 
					27b8183de2 | ||
| 
						 | 
					f32d8e1bfe | ||
| 
						 | 
					d019f34a83 | ||
| 
						 | 
					bb9c481f02 | ||
| 
						 | 
					82da844b42 | ||
| 
						 | 
					667a09983c | ||
| 
						 | 
					cf429ee359 | ||
| 
						 | 
					6f3e2e2d7d | ||
| 
						 | 
					35b88fb42b | ||
| 
						 | 
					a428c325a9 | ||
| 
						 | 
					3219ecd608 | ||
| 
						 | 
					0d8dc4f798 | ||
| 
						 | 
					f3c70bf5b5 | ||
| 
						 | 
					f5acc66db7 | ||
| 
						 | 
					fdce4769f2 | ||
| 
						 | 
					35b1996704 | ||
| 
						 | 
					3c8e7ed255 | 
@@ -1,4 +1,5 @@
 | 
				
			|||||||
# Using Busybox as your Default Shell with OpenRC
 | 
					Using Busybox as your Default Shell with OpenRC
 | 
				
			||||||
 | 
					===============================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
If you have/bin/sh linked to busybox, you need to be aware of several
 | 
					If you have/bin/sh linked to busybox, you need to be aware of several
 | 
				
			||||||
incompatibilities between busybox's applets and the standalone
 | 
					incompatibilities between busybox's applets and the standalone
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,12 @@
 | 
				
			|||||||
# Features Scheduled for Removal
 | 
					Features Scheduled for Removal
 | 
				
			||||||
 | 
					==============================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The following is a list of files and features that are going to be removed in
 | 
					The following is a list of files and features that are going to be removed in
 | 
				
			||||||
the source tree.  Every entry should contain what exactly is going away, why it
 | 
					the source tree.  Every entry should contain what exactly is going away, why it
 | 
				
			||||||
is happening, and who is going to be doing the work.  When the feature is
 | 
					is happening, and who is going to be doing the work.  When the feature is
 | 
				
			||||||
removed, it should also be removed from this file.
 | 
					removed, it should also be removed from this file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Service pause action
 | 
					# Service pause action
 | 
				
			||||||
 | 
					
 | 
				
			||||||
When: 1.0
 | 
					When: 1.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -13,7 +14,7 @@ Why: The same affect can be obtained with the --nodeps option to stop.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Who:
 | 
					Who:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## start-stop-daemon options --startas, --chuid , --oknodo
 | 
					# start-stop-daemon options --startas, --chuid , --oknodo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
When: 1.0
 | 
					When: 1.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -25,7 +26,7 @@ Why: Obsolete or replaced by other options.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Who:
 | 
					Who:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## runscript and rc symbolic links
 | 
					# runscript and rc symbolic links
 | 
				
			||||||
 | 
					
 | 
				
			||||||
When: 1.0
 | 
					When: 1.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -34,7 +35,7 @@ Why: Deprecated in favor of openrc-run and openrc due to naming
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Who:
 | 
					Who:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## support for the opts variable in service scripts
 | 
					# support for the opts variable in service scripts
 | 
				
			||||||
 | 
					
 | 
				
			||||||
When: 1.0
 | 
					When: 1.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -43,7 +44,7 @@ Why: Deprecated in favor of extra_commands, extra_started_commands
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Who:
 | 
					Who:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## support for local_start and local_stop
 | 
					# support for local_start and local_stop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
When: 1.0
 | 
					When: 1.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -51,7 +52,7 @@ Why: Deprecated in favor of executable scripts in @SYSCONFDIR@/local.d
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Who:
 | 
					Who:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## the mtab service script
 | 
					# the mtab service script
 | 
				
			||||||
 | 
					
 | 
				
			||||||
When: force /etc/mtab to link to /proc/self/mounts in 1.0, remove
 | 
					When: force /etc/mtab to link to /proc/self/mounts in 1.0, remove
 | 
				
			||||||
	  service in 2.0
 | 
						  service in 2.0
 | 
				
			||||||
@@ -61,13 +62,13 @@ Why: /etc/mtab should be a symbolic link to /proc/self/mounts on modern
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Who:
 | 
					Who:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## C API Functions in rc.h
 | 
					# C API Functions in rc.h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
If you have a c program that links to librc and uses functions from
 | 
					If you have a c program that links to librc and uses functions from
 | 
				
			||||||
there, this section will list API functions which are deprecated and
 | 
					there, this section will list API functions which are deprecated and
 | 
				
			||||||
will be removed along with the reason they are being removed.
 | 
					will be removed along with the reason they are being removed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### rc_getline()
 | 
					## rc_getline()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
When: 1.0
 | 
					When: 1.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
# OpenRC History
 | 
					OpenRC History
 | 
				
			||||||
 | 
					==============
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This history of OpenRC was written by Daniel Robbins, Roy Marples, William
 | 
					This history of OpenRC was written by Daniel Robbins, Roy Marples, William
 | 
				
			||||||
Hubbs and others.
 | 
					Hubbs and others.
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										12
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								Makefile
									
									
									
									
									
								
							@@ -15,12 +15,24 @@ include ${TOP}/Makefile.inc
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
SUBDIR=		conf.d etc init.d local.d man scripts sh src support sysctl.d
 | 
					SUBDIR=		conf.d etc init.d local.d man scripts sh src support sysctl.d
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Build bash completion or not
 | 
				
			||||||
 | 
					MKBASHCOMP?=	no
 | 
				
			||||||
 | 
					ifeq (${MKBASHCOMP},yes)
 | 
				
			||||||
 | 
					SUBDIR+=	bash-completion
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Build pkgconfig or not
 | 
					# Build pkgconfig or not
 | 
				
			||||||
MKPKGCONFIG?=	yes
 | 
					MKPKGCONFIG?=	yes
 | 
				
			||||||
ifeq (${MKPKGCONFIG},yes)
 | 
					ifeq (${MKPKGCONFIG},yes)
 | 
				
			||||||
SUBDIR+=	pkgconfig
 | 
					SUBDIR+=	pkgconfig
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Build zsh completion or not
 | 
				
			||||||
 | 
					MKZSHCOMP?=	no
 | 
				
			||||||
 | 
					ifeq (${MKZSHCOMP},yes)
 | 
				
			||||||
 | 
					SUBDIR+=	zsh-completion
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# We need to ensure that runlevels is done last
 | 
					# We need to ensure that runlevels is done last
 | 
				
			||||||
SUBDIR+=	runlevels
 | 
					SUBDIR+=	runlevels
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,3 @@
 | 
				
			|||||||
NAME=		openrc
 | 
					NAME=		openrc
 | 
				
			||||||
VERSION=	0.33.1
 | 
					VERSION=	0.37
 | 
				
			||||||
PKG=		${NAME}-${VERSION}
 | 
					PKG=		${NAME}-${VERSION}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										58
									
								
								NEWS.md
									
									
									
									
									
								
							
							
						
						
									
										58
									
								
								NEWS.md
									
									
									
									
									
								
							@@ -1,8 +1,64 @@
 | 
				
			|||||||
# OpenRC NEWS
 | 
					OpenRC NEWS
 | 
				
			||||||
 | 
					===========
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This file will contain a list of notable changes for each release. Note
 | 
					This file will contain a list of notable changes for each release. Note
 | 
				
			||||||
the information in this file is in reverse order.
 | 
					the information in this file is in reverse order.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## OpenRC 0.37
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					start-stop-daemon now supports logging stdout and stderr of daemons to
 | 
				
			||||||
 | 
					processes instead of files. These processes are defined by the
 | 
				
			||||||
 | 
					output_logger and error_logger variables in standard service scripts, or
 | 
				
			||||||
 | 
					by the  -3/--output-logger or -4/--error-logger switches if you use
 | 
				
			||||||
 | 
					start-stop-daemon directly. For more information on this, see the
 | 
				
			||||||
 | 
					start-stop-daemon man page.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## OpenRC 0.36
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In this release, the modules-load service has been combined into the
 | 
				
			||||||
 | 
					modules service since there is no reason I know of to keep them
 | 
				
			||||||
 | 
					separate. However, modules also provides modules-load in case you were
 | 
				
			||||||
 | 
					using modules-load in  your dependencies.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The consolefont, keymaps, numlock and procfs service scripts no longer
 | 
				
			||||||
 | 
					have a dependency on localmount.
 | 
				
			||||||
 | 
					If you are a linux user and are still separaating / from /usr,
 | 
				
			||||||
 | 
					you will need to add the following line to the appropriate conf.d files:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					rc_need="localmount"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## OpenRC 0.35
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In this version, the cgroups mounting logic has been moved from the
 | 
				
			||||||
 | 
					sysfs service to the cgroups service. This was done so cgroups can be
 | 
				
			||||||
 | 
					mounted inside an lxc/lxd container without using the other parts of the
 | 
				
			||||||
 | 
					sysfs service.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					?As a result of this change, if you are upgrading, you need to add
 | 
				
			||||||
 | 
					cgroups to your sysinit runlevel by running the following command as
 | 
				
			||||||
 | 
					root:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					# rc-update add cgroups sysinit
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For more information, see the following issue:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					https://github.com/openrc/openrc/issues/187
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Consider this your second notification with regard to /etc/mtab being a
 | 
				
			||||||
 | 
					file instead of a symbolic link.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In this version, the mtab service will complain loudly if you have
 | 
				
			||||||
 | 
					mtab_is_file set to yes and recommend that you change this to no and
 | 
				
			||||||
 | 
					restart the mtab service to migrate /etc/mtab to a symbolic link.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If there is a valid technical reason to keep /etc/mtab as a flat file
 | 
				
			||||||
 | 
					instead of a symbolic link to /proc/self/mounts, we are interested and
 | 
				
			||||||
 | 
					we will keep the support in that case. Please open an issue and let us
 | 
				
			||||||
 | 
					know however. Otherwise, consider this your final notice that the mtab
 | 
				
			||||||
 | 
					service will be removed in the future.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## OpenRC 0.33
 | 
					## OpenRC 0.33
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This version removes the "service" binary which was just a copy of
 | 
					This version removes the "service" binary which was just a copy of
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
# OpenRC README
 | 
					OpenRC README
 | 
				
			||||||
 | 
					=============
 | 
				
			||||||
 | 
					
 | 
				
			||||||
OpenRC is a dependency-based init system that works with the
 | 
					OpenRC is a dependency-based init system that works with the
 | 
				
			||||||
system-provided init program, normally `/sbin/init`. Currently, it does
 | 
					system-provided init program, normally `/sbin/init`. Currently, it does
 | 
				
			||||||
@@ -22,6 +23,7 @@ below arguments to the make command
 | 
				
			|||||||
PROGLDFLAGS=-static
 | 
					PROGLDFLAGS=-static
 | 
				
			||||||
LIBNAME=lib64
 | 
					LIBNAME=lib64
 | 
				
			||||||
DESTDIR=/tmp/openrc-image
 | 
					DESTDIR=/tmp/openrc-image
 | 
				
			||||||
 | 
					MKBASHCOMP=no
 | 
				
			||||||
MKNET=no
 | 
					MKNET=no
 | 
				
			||||||
MKPAM=pam
 | 
					MKPAM=pam
 | 
				
			||||||
MKPREFIX=yes
 | 
					MKPREFIX=yes
 | 
				
			||||||
@@ -31,6 +33,7 @@ MKSTATICLIBS=no
 | 
				
			|||||||
MKSYSVINIT=yes
 | 
					MKSYSVINIT=yes
 | 
				
			||||||
MKTERMCAP=ncurses
 | 
					MKTERMCAP=ncurses
 | 
				
			||||||
MKTERMCAP=termcap
 | 
					MKTERMCAP=termcap
 | 
				
			||||||
 | 
					MKZSHCOMP=no
 | 
				
			||||||
PKG_PREFIX=/usr/pkg
 | 
					PKG_PREFIX=/usr/pkg
 | 
				
			||||||
LOCAL_PREFIX=/usr/local
 | 
					LOCAL_PREFIX=/usr/local
 | 
				
			||||||
PREFIX=/usr/local
 | 
					PREFIX=/usr/local
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
# OpenRC Style Guide
 | 
					OpenRC Coding Style Guide
 | 
				
			||||||
 | 
					=========================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This is the openrc style manual.  It governs the coding style of all code
 | 
					This is the openrc style manual.  It governs the coding style of all code
 | 
				
			||||||
in this repository.  Follow it.  Contact openrc@gentoo.org for any questions
 | 
					in this repository.  Follow it.  Contact openrc@gentoo.org for any questions
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
# Setting up the agetty service in OpenRC
 | 
					Setting up the agetty service in OpenRC
 | 
				
			||||||
 | 
					=================================xxxxxx
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The agetty service is an OpenRC specific way to monitor and respawn a
 | 
					The agetty service is an OpenRC specific way to monitor and respawn a
 | 
				
			||||||
getty, using agetty, on Linux. To use this method, make sure you aren't
 | 
					getty, using agetty, on Linux. To use this method, make sure you aren't
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										11
									
								
								bash-completion/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								bash-completion/Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					DIR=	${BASHCOMPDIR}
 | 
				
			||||||
 | 
					CONF=	openrc \
 | 
				
			||||||
 | 
							openrc-service-script \
 | 
				
			||||||
 | 
							rc-service \
 | 
				
			||||||
 | 
							rc-status \
 | 
				
			||||||
 | 
							rc-update \
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MK=	../mk
 | 
				
			||||||
 | 
					include ${MK}/os.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include ${MK}/scripts.mk
 | 
				
			||||||
							
								
								
									
										24
									
								
								bash-completion/openrc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								bash-completion/openrc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					# Copyright (c) 2017 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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# openrc completion command
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					_openrc()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						local cur
 | 
				
			||||||
 | 
						COMPREPLY=()
 | 
				
			||||||
 | 
						cur="${COMP_WORDS[COMP_CWORD]}"
 | 
				
			||||||
 | 
						if [[ ${#COMP_WORDS[*]} -le 2 ]]; then
 | 
				
			||||||
 | 
							COMPREPLY=($(compgen -W "$(rc-status --list)" -- $cur))
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					} &&
 | 
				
			||||||
 | 
					complete -F _openrc openrc
 | 
				
			||||||
							
								
								
									
										29
									
								
								bash-completion/openrc-service-script
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								bash-completion/openrc-service-script
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					# Copyright (c) 2017 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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_openrc_service_script()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						local script="${COMP_WORDS[0]}"
 | 
				
			||||||
 | 
						local cur="${COMP_WORDS[$COMP_CWORD]}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if [[ ( -f "${script}" || -h "${script}" ) && -r "${script}" ]] \
 | 
				
			||||||
 | 
						&& [[ "$(head -n 1 "${script}")" =~ \#\!.*/openrc-run ]]
 | 
				
			||||||
 | 
						then
 | 
				
			||||||
 | 
							[[ $COMP_CWORD -gt 1 ]] && return 1
 | 
				
			||||||
 | 
							COMPREPLY=($(opts="start stop status restart pause zap ineed needsme iuse usesme broken"; \
 | 
				
			||||||
 | 
								eval "$(grep '^opts=' "${script}")"; echo "${opts}"))
 | 
				
			||||||
 | 
							[[ -n "$COMPREPLY" ]] || COMPREPLY=(start stop restart zap)
 | 
				
			||||||
 | 
							COMPREPLY=($(compgen -W "${COMPREPLY[*]}" -- "${cur}"))
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							COMPREPLY=($(compgen -o default -- "${cur}"))
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					complete -F _openrc_service_script */etc/init.d/*
 | 
				
			||||||
							
								
								
									
										113
									
								
								bash-completion/rc-service
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								bash-completion/rc-service
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,113 @@
 | 
				
			|||||||
 | 
					# Copyright (c) 2017 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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# rc-service completion command
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					_rc_service()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						local cur prev numwords opts
 | 
				
			||||||
 | 
						local words i x filename
 | 
				
			||||||
 | 
						local action actionpos
 | 
				
			||||||
 | 
						COMPREPLY=()
 | 
				
			||||||
 | 
						cur="${COMP_WORDS[COMP_CWORD]}"
 | 
				
			||||||
 | 
						prev="${COMP_WORDS[COMP_CWORD-1]}"
 | 
				
			||||||
 | 
						numwords=${#COMP_WORDS[*]}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if [[ ${prev} == '>' || ${prev} == '<' ]] ; then
 | 
				
			||||||
 | 
							COMPREPLY=($(compgen -f -- ${cur}))
 | 
				
			||||||
 | 
							return 0
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						# find action
 | 
				
			||||||
 | 
						for x in ${COMP_LINE} ; do
 | 
				
			||||||
 | 
							if [[ ${x} =~ --(list|exists|resolve) ]] || [[ ${x} =~ -(l|e|r) ]]
 | 
				
			||||||
 | 
							then
 | 
				
			||||||
 | 
								action=${x}
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
						done
 | 
				
			||||||
 | 
						if [[ -n ${action} ]]; then
 | 
				
			||||||
 | 
							for ((i = 0; i < ${numwords}; i++ )); do
 | 
				
			||||||
 | 
								if [[ ${COMP_WORDS[${i}]} == "${action}" ]]; then
 | 
				
			||||||
 | 
									actionpos=${i}
 | 
				
			||||||
 | 
									break
 | 
				
			||||||
 | 
								fi
 | 
				
			||||||
 | 
							done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for ((i = 1; i < ${numwords}; i++ )); do
 | 
				
			||||||
 | 
								if [[ ! ${COMP_WORDS[$i]} == -* ]]; then
 | 
				
			||||||
 | 
									break
 | 
				
			||||||
 | 
								fi
 | 
				
			||||||
 | 
							done
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if [[ ${COMP_CWORD} -eq 3 ]]; then
 | 
				
			||||||
 | 
							return 1
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						# check if an option was typed
 | 
				
			||||||
 | 
						if [[ ${cur} == -* ]]; then
 | 
				
			||||||
 | 
							if [[ ${cur} == --* ]]; then
 | 
				
			||||||
 | 
								opts="--list --exists --resolve"
 | 
				
			||||||
 | 
								COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
 | 
				
			||||||
 | 
								return 0
 | 
				
			||||||
 | 
							elif [[ ${cur} == -* ]]; then
 | 
				
			||||||
 | 
								opts="-l -e -r"
 | 
				
			||||||
 | 
								COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
 | 
				
			||||||
 | 
								return 0
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							# NOTE: This slows things down!
 | 
				
			||||||
 | 
							# (Adapted from bash_completion by Ian Macdonald <ian@caliban.org>)
 | 
				
			||||||
 | 
							# This removes any options from the list of completions that have
 | 
				
			||||||
 | 
							# already been specified on the command line.
 | 
				
			||||||
 | 
							COMPREPLY=($(echo "${COMP_WORDS[@]}" | \
 | 
				
			||||||
 | 
							(while read -d ' ' i; do
 | 
				
			||||||
 | 
								[[ -z ${i} ]] && continue
 | 
				
			||||||
 | 
								# flatten array with spaces on either side,
 | 
				
			||||||
 | 
								# otherwise we cannot grep on word boundaries of
 | 
				
			||||||
 | 
								# first and last word
 | 
				
			||||||
 | 
								COMPREPLY=" ${COMPREPLY[@]} "
 | 
				
			||||||
 | 
								# remove word from list of completions
 | 
				
			||||||
 | 
								COMPREPLY=(${COMPREPLY/ ${i%% *} / })
 | 
				
			||||||
 | 
							done
 | 
				
			||||||
 | 
							echo ${COMPREPLY[@]})))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return 0
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							# no option was typed
 | 
				
			||||||
 | 
							if [[ ${COMP_CWORD} -eq 1 ]]; then			  # if first word typed
 | 
				
			||||||
 | 
								words="$(rc-service --list | grep ^${cur})"		  # complete for init scripts
 | 
				
			||||||
 | 
								COMPREPLY=($(for i in ${words} ; do \
 | 
				
			||||||
 | 
								[[ ${i} == ${cur}* ]] && echo ${i} ; \
 | 
				
			||||||
 | 
								done))
 | 
				
			||||||
 | 
								return 0
 | 
				
			||||||
 | 
							elif [[ ${COMP_CWORD} -eq 2 ]] && [[ ${prev} != -* ]]; then # if second word typed and we didn't type in a function
 | 
				
			||||||
 | 
								filename=$(rc-service --resolve ${prev})
 | 
				
			||||||
 | 
								opts=$(cat ${filename} | grep "^\w*()" | sed "s/().*$//")	# Greps the functions included in the init script
 | 
				
			||||||
 | 
								if [[ "x${opts}" == "x" ]] ; then			   # if no options found loosen the grep algorhythm
 | 
				
			||||||
 | 
									opts=$(cat ${filename} | grep "\w*()" | sed "s/().*$//")
 | 
				
			||||||
 | 
								fi
 | 
				
			||||||
 | 
								COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
 | 
				
			||||||
 | 
								return 0
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
						if [[ ${action} == '--exists' ]] || [[ ${action} == '-e' ]] || \
 | 
				
			||||||
 | 
							[[ ${action} == '--resolve' ]]  || [[ ${action} == '-r' ]]; then
 | 
				
			||||||
 | 
							words="$(rc-service --list | grep ^${cur})"
 | 
				
			||||||
 | 
							COMPREPLY=($(for i in ${words} ; do \
 | 
				
			||||||
 | 
								[[ ${i} == ${cur}* ]] && echo ${i} ; \
 | 
				
			||||||
 | 
							done))
 | 
				
			||||||
 | 
							return 0
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					} &&
 | 
				
			||||||
 | 
					complete -F _rc_service rc-service
 | 
				
			||||||
							
								
								
									
										31
									
								
								bash-completion/rc-status
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								bash-completion/rc-status
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					# Copyright (c) 2017 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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# rc-status completion command
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					_rcstatus()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						local cur
 | 
				
			||||||
 | 
						cur="${COMP_WORDS[COMP_CWORD]}"
 | 
				
			||||||
 | 
						if [[ $COMP_CWORD -eq 1 ]]; then
 | 
				
			||||||
 | 
							if [[ "${cur}" == --* ]]; then
 | 
				
			||||||
 | 
								COMPREPLY=($(compgen -W '--all --list --unused' -- ${cur}))
 | 
				
			||||||
 | 
							elif [[ "${cur}" == -* ]]; then
 | 
				
			||||||
 | 
								COMPREPLY=($(compgen -W '-a -l -u' -- ${cur}))
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								COMPREPLY=($(compgen -W "$(rc-status --list)" -- ${cur}))
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							unset COMPREPLY
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					} &&
 | 
				
			||||||
 | 
					complete -F _rcstatus rc-status
 | 
				
			||||||
							
								
								
									
										42
									
								
								bash-completion/rc-update
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								bash-completion/rc-update
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
				
			|||||||
 | 
					# Copyright (c) 2017 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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# rc-update completion command
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					_rc_update()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						local cur show
 | 
				
			||||||
 | 
						COMPREPLY=()
 | 
				
			||||||
 | 
						cur="${COMP_WORDS[COMP_CWORD]}"
 | 
				
			||||||
 | 
						if [[ $COMP_CWORD -eq 1 ]]; then
 | 
				
			||||||
 | 
							if [[ "${cur}" == -* ]]; then
 | 
				
			||||||
 | 
								COMPREPLY=($(compgen -W '-a -d -s' -- ${cur}))
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								COMPREPLY=($(compgen -W 'add del show' ${cur}))
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							if [[ "${COMP_WORDS[1]}" == "show" ]] || [[ "${COMP_WORDS[1]}" == "-s" ]]; then
 | 
				
			||||||
 | 
								show="TRUE"
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
							if ([[ $COMP_CWORD -eq 3 ]] && [[ -z "$show" ]]) || \
 | 
				
			||||||
 | 
								([[ $COMP_CWORD -eq 2 ]] && [[ -n "$show" ]]); then
 | 
				
			||||||
 | 
							COMPREPLY=($(compgen -W "$(rc-status --list)" -- $cur))
 | 
				
			||||||
 | 
							elif [[ $COMP_CWORD -eq 2 ]]; then
 | 
				
			||||||
 | 
								COMPREPLY=($(compgen -W "$(rc-service --list)" $cur))
 | 
				
			||||||
 | 
							elif [[ ${#COMP_WORDS[*]} -gt 2 ]] ; then
 | 
				
			||||||
 | 
								COMPREPLY=($(compgen -W "$(rc-status --list)" -- $cur))
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								unset COMPREPLY
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					} &&
 | 
				
			||||||
 | 
					complete -F _rc_update rc-update
 | 
				
			||||||
							
								
								
									
										14
									
								
								conf.d/mtab
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								conf.d/mtab
									
									
									
									
									
								
							@@ -1,5 +1,13 @@
 | 
				
			|||||||
 | 
					# As far as we are aware, there are no modern linux tools or use cases
 | 
				
			||||||
 | 
					# which require /etc/mtab to be a separate file from /proc/self/mounts,
 | 
				
			||||||
 | 
					# so this setting should be commented out.
 | 
				
			||||||
 | 
					# If it is set to yes, please comment it out and run this command:
 | 
				
			||||||
 | 
					# # rc-service mtab restart
 | 
				
			||||||
 | 
					# In the future, the mtab service will be removed since we are not aware
 | 
				
			||||||
 | 
					# of any need to manipulate /etc/mtab as a separate file from
 | 
				
			||||||
 | 
					# /proc/self/mounts.
 | 
				
			||||||
 | 
					# If you have a technical reason we should keep this support, please
 | 
				
			||||||
 | 
					# open an issue at https://github.com/openrc/openrc/issues and let us
 | 
				
			||||||
 | 
					# know about your situation.
 | 
				
			||||||
# This setting controls whether /etc/mtab is a file or symbolic link.
 | 
					# This setting controls whether /etc/mtab is a file or symbolic link.
 | 
				
			||||||
# Most of the time, you shouldn't touch this. However, if the default
 | 
					 | 
				
			||||||
# breaks your system in some way, please see the NEWS.md file that comes
 | 
					 | 
				
			||||||
# with OpenRC for the actions to take.
 | 
					 | 
				
			||||||
# mtab_is_file=no
 | 
					# mtab_is_file=no
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -227,6 +227,11 @@ rc_tty_number=12
 | 
				
			|||||||
# /sys/fs/cgroup in hybrid or legacy mode.
 | 
					# /sys/fs/cgroup in hybrid or legacy mode.
 | 
				
			||||||
#rc_controller_cgroups="YES"
 | 
					#rc_controller_cgroups="YES"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# The following setting turns on the memory.use_hierarchy setting in the
 | 
				
			||||||
 | 
					# root memory cgroup for cgroups v1.
 | 
				
			||||||
 | 
					# It must be set to yes in this file if you want this functionality.
 | 
				
			||||||
 | 
					#rc_cggroup_memory_use_hierarchy="NO"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# The following settings allow you to set up values for the cgroups version 1
 | 
					# The following settings allow you to set up values for the cgroups version 1
 | 
				
			||||||
# controllers for your services.
 | 
					# controllers for your services.
 | 
				
			||||||
# They can be set in this file;, however, if you do this, the settings
 | 
					# They can be set in this file;, however, if you do this, the settings
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								init.d/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								init.d/.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,5 +1,6 @@
 | 
				
			|||||||
agetty
 | 
					agetty
 | 
				
			||||||
binfmt
 | 
					binfmt
 | 
				
			||||||
 | 
					cgroups
 | 
				
			||||||
modules-load
 | 
					modules-load
 | 
				
			||||||
bootmisc
 | 
					bootmisc
 | 
				
			||||||
fsck
 | 
					fsck
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,11 +19,12 @@ SRCS-FreeBSD=	hostid.in modules.in moused.in newsyslog.in pf.in rarpd.in \
 | 
				
			|||||||
		rc-enabled.in rpcbind.in savecore.in syslogd.in
 | 
							rc-enabled.in rpcbind.in savecore.in syslogd.in
 | 
				
			||||||
# These are FreeBSD specific
 | 
					# These are FreeBSD specific
 | 
				
			||||||
SRCS-FreeBSD+=	adjkerntz.in devd.in dumpon.in encswap.in ipfw.in \
 | 
					SRCS-FreeBSD+=	adjkerntz.in devd.in dumpon.in encswap.in ipfw.in \
 | 
				
			||||||
		modules-load.in mixer.in nscd.in powerd.in syscons.in
 | 
							mixer.in nscd.in powerd.in syscons.in
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SRCS-Linux=	agetty.in binfmt.in devfs.in dmesg.in hwclock.in consolefont.in \
 | 
					SRCS-Linux=	agetty.in binfmt.in devfs.in cgroups.in dmesg.in hwclock.in \
 | 
				
			||||||
	keymaps.in killprocs.in modules.in modules-load.in mount-ro.in mtab.in \
 | 
						consolefont.in keymaps.in killprocs.in modules.in \
 | 
				
			||||||
	numlock.in procfs.in net-online.in sysfs.in termencoding.in
 | 
						mount-ro.in mtab.in numlock.in procfs.in net-online.in sysfs.in \
 | 
				
			||||||
 | 
					termencoding.in
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Generic BSD scripts
 | 
					# Generic BSD scripts
 | 
				
			||||||
SRCS-NetBSD=	hostid.in moused.in newsyslog.in pf.in rarpd.in rc-enabled.in \
 | 
					SRCS-NetBSD=	hostid.in moused.in newsyslog.in pf.in rarpd.in rc-enabled.in \
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,7 +16,6 @@ term_type="${term_type:-linux}"
 | 
				
			|||||||
command=/sbin/agetty
 | 
					command=/sbin/agetty
 | 
				
			||||||
command_args_foreground="${agetty_options} ${port} ${baud} ${term_type}"
 | 
					command_args_foreground="${agetty_options} ${port} ${baud} ${term_type}"
 | 
				
			||||||
pidfile="/run/${RC_SVCNAME}.pid"
 | 
					pidfile="/run/${RC_SVCNAME}.pid"
 | 
				
			||||||
export EINFO_QUIET="${quiet:-yes}"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
depend() {
 | 
					depend() {
 | 
				
			||||||
	after local
 | 
						after local
 | 
				
			||||||
@@ -29,5 +28,12 @@ start_pre() {
 | 
				
			|||||||
		eerror "symbolic links to it for the ports you want to start"
 | 
							eerror "symbolic links to it for the ports you want to start"
 | 
				
			||||||
		eerror "agetty on and add those to the appropriate runlevels."
 | 
							eerror "agetty on and add those to the appropriate runlevels."
 | 
				
			||||||
		return 1
 | 
							return 1
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							export EINFO_QUIET="${quiet:-yes}"
 | 
				
			||||||
	fi
 | 
						fi
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					stop_pre()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						export EINFO_QUIET="${quiet:-yes}"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										149
									
								
								init.d/cgroups.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								init.d/cgroups.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,149 @@
 | 
				
			|||||||
 | 
					#!@SBINDIR@/openrc-run
 | 
				
			||||||
 | 
					# Copyright (c) 2017 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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					description="Mount the control groups."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cgroup_opts=nodev,noexec,nosuid
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					depend()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						keyword -docker -prefix -systemd-nspawn -vserver
 | 
				
			||||||
 | 
						after sysfs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cgroup1_base()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						grep -qw cgroup /proc/filesystems || return 0
 | 
				
			||||||
 | 
						if ! mountinfo -q /sys/fs/cgroup; then
 | 
				
			||||||
 | 
							ebegin "Mounting cgroup filesystem"
 | 
				
			||||||
 | 
							local opts="${cgroup_opts},mode=755,size=${rc_cgroupsize:-10m}"
 | 
				
			||||||
 | 
							mount -n -t tmpfs -o "${opts}" cgroup_root /sys/fs/cgroup
 | 
				
			||||||
 | 
							eend $?
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ! mountinfo -q /sys/fs/cgroup/openrc; then
 | 
				
			||||||
 | 
							local agent="${RC_LIBEXECDIR}/sh/cgroup-release-agent.sh"
 | 
				
			||||||
 | 
							mkdir /sys/fs/cgroup/openrc
 | 
				
			||||||
 | 
							mount -n -t cgroup \
 | 
				
			||||||
 | 
								-o none,${cgroup_opts},name=openrc,release_agent="$agent" \
 | 
				
			||||||
 | 
								openrc /sys/fs/cgroup/openrc
 | 
				
			||||||
 | 
							printf 1 > /sys/fs/cgroup/openrc/notify_on_release
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cgroup1_controllers()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						yesno "${rc_controller_cgroups:-YES}" && [ -e /proc/cgroups ]  &&
 | 
				
			||||||
 | 
						grep -qw cgroup /proc/filesystems || return 0
 | 
				
			||||||
 | 
						while read -r name _ _ enabled _; do
 | 
				
			||||||
 | 
							case "${enabled}" in
 | 
				
			||||||
 | 
								1)	mountinfo -q "/sys/fs/cgroup/${name}" && continue
 | 
				
			||||||
 | 
									local x
 | 
				
			||||||
 | 
									for x in $rc_cgroup_controllers; do
 | 
				
			||||||
 | 
									[ "${name}" = "blkio" ] && [ "${x}" = "io" ] &&
 | 
				
			||||||
 | 
										continue 2
 | 
				
			||||||
 | 
									[ "${name}" = "${x}" ] &&
 | 
				
			||||||
 | 
									continue 2
 | 
				
			||||||
 | 
									done
 | 
				
			||||||
 | 
									mkdir "/sys/fs/cgroup/${name}"
 | 
				
			||||||
 | 
									mount -n -t cgroup -o "${cgroup_opts},${name}" \
 | 
				
			||||||
 | 
										"${name}" "/sys/fs/cgroup/${name}"
 | 
				
			||||||
 | 
									yesno "${rc_cgroup_memory_use_hierarchy:-no}" &&
 | 
				
			||||||
 | 
										[ "${name}" = memory ] &&
 | 
				
			||||||
 | 
										echo 1 > /sys/fs/cgroup/memory/memory.use_hierarchy
 | 
				
			||||||
 | 
									;;
 | 
				
			||||||
 | 
							esac
 | 
				
			||||||
 | 
						done < /proc/cgroups
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cgroup2_base()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						grep -qw cgroup2 /proc/filesystems || return 0
 | 
				
			||||||
 | 
						local base
 | 
				
			||||||
 | 
						base="$(cgroup2_find_path)"
 | 
				
			||||||
 | 
						mkdir -p "${base}"
 | 
				
			||||||
 | 
						mount -t cgroup2 none -o "${cgroup_opts},nsdelegate" "${base}" 2> /dev/null ||
 | 
				
			||||||
 | 
							mount -t cgroup2 none -o "${cgroup_opts}" "${base}"
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cgroup2_controllers()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						grep -qw cgroup2 /proc/filesystems || return 0
 | 
				
			||||||
 | 
						local active cgroup_path x y
 | 
				
			||||||
 | 
						cgroup_path="$(cgroup2_find_path)"
 | 
				
			||||||
 | 
						[ -z "${cgroup_path}" ] && return 0
 | 
				
			||||||
 | 
						[ -e "${cgroup_path}/cgroup.controllers" ] &&
 | 
				
			||||||
 | 
						read -r active < "${cgroup_path}/cgroup.controllers"
 | 
				
			||||||
 | 
						for x in ${rc_cgroup_controllers}; do
 | 
				
			||||||
 | 
							for y in ${active}; do
 | 
				
			||||||
 | 
							[ "$x" = "$y" ] &&
 | 
				
			||||||
 | 
								[ -e "${cgroup_path}/cgroup.subtree_control" ]&&
 | 
				
			||||||
 | 
								echo "+${x}"  > "${cgroup_path}/cgroup.subtree_control"
 | 
				
			||||||
 | 
							done
 | 
				
			||||||
 | 
						done
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cgroups_hybrid()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						cgroup1_base
 | 
				
			||||||
 | 
						cgroup2_base
 | 
				
			||||||
 | 
						cgroup2_controllers
 | 
				
			||||||
 | 
						cgroup1_controllers
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cgroups_legacy()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						cgroup1_base
 | 
				
			||||||
 | 
						cgroup1_controllers
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cgroups_unified()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						cgroup2_base
 | 
				
			||||||
 | 
						cgroup2_controllers
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					mount_cgroups()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						case "${rc_cgroup_mode:-hybrid}" in
 | 
				
			||||||
 | 
						hybrid) cgroups_hybrid ;;
 | 
				
			||||||
 | 
						legacy) cgroups_legacy ;;
 | 
				
			||||||
 | 
						unified) cgroups_unified ;;
 | 
				
			||||||
 | 
						esac
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					restorecon_cgroups()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if [ -x /sbin/restorecon ]; then
 | 
				
			||||||
 | 
							ebegin "Restoring SELinux contexts in /sys/fs/cgroup"
 | 
				
			||||||
 | 
							restorecon -rF /sys/fs/cgroup >/dev/null 2>&1
 | 
				
			||||||
 | 
							eend $?
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					start()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						# set up kernel support for cgroups
 | 
				
			||||||
 | 
						if [ -d /sys/fs/cgroup ]; then
 | 
				
			||||||
 | 
							mount_cgroups
 | 
				
			||||||
 | 
							restorecon_cgroups
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -13,7 +13,7 @@ description="Sets a font for the consoles."
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
depend()
 | 
					depend()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	need localmount termencoding
 | 
						need termencoding
 | 
				
			||||||
	after hotplug bootmisc modules
 | 
						after hotplug bootmisc modules
 | 
				
			||||||
	keyword -docker -lxc -openvz -prefix -systemd-nspawn -uml -vserver -xenu
 | 
						keyword -docker -lxc -openvz -prefix -systemd-nspawn -uml -vserver -xenu
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,9 +20,12 @@ depend()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
mount_dev()
 | 
					mount_dev()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	local action=--mount devfstype msg=Mounting
 | 
						local action conf_d_dir devfstype msg mountopts
 | 
				
			||||||
 | 
						action=--mount
 | 
				
			||||||
 | 
						conf_d_dir="${RC_SERVICE%/*/*}/conf.d"
 | 
				
			||||||
 | 
						msg=Mounting
 | 
				
			||||||
	# Some devices require exec, Bug #92921
 | 
						# Some devices require exec, Bug #92921
 | 
				
			||||||
	local mountopts="exec,nosuid,mode=0755"
 | 
						mountopts="exec,nosuid,mode=0755"
 | 
				
			||||||
	if yesno ${skip_mount_dev:-no} ; then
 | 
						if yesno ${skip_mount_dev:-no} ; then
 | 
				
			||||||
		einfo "/dev will not be mounted due to user request"
 | 
							einfo "/dev will not be mounted due to user request"
 | 
				
			||||||
		return 0
 | 
							return 0
 | 
				
			||||||
@@ -33,7 +36,7 @@ mount_dev()
 | 
				
			|||||||
		msg=Remounting
 | 
							msg=Remounting
 | 
				
			||||||
	fi
 | 
						fi
 | 
				
			||||||
	if fstabinfo -q /dev; then
 | 
						if fstabinfo -q /dev; then
 | 
				
			||||||
		ebegin "$msg /dev according to @SYSCONFDIR@/fstab"
 | 
							ebegin "$msg /dev according to fstab"
 | 
				
			||||||
		fstabinfo -q $action /dev
 | 
							fstabinfo -q $action /dev
 | 
				
			||||||
		eend $?
 | 
							eend $?
 | 
				
			||||||
		return 0
 | 
							return 0
 | 
				
			||||||
@@ -54,7 +57,7 @@ mount_dev()
 | 
				
			|||||||
		ewarn "is no entry for /dev in fstab."
 | 
							ewarn "is no entry for /dev in fstab."
 | 
				
			||||||
		ewarn "This means /dev will not be mounted."
 | 
							ewarn "This means /dev will not be mounted."
 | 
				
			||||||
		ewarn "To avoid this message, set CONFIG_DEVTMPFS or CONFIG_TMPFS to y"
 | 
							ewarn "To avoid this message, set CONFIG_DEVTMPFS or CONFIG_TMPFS to y"
 | 
				
			||||||
		ewarn "in your kernel configuration or see @SYSCONFDIR@/conf.d/devfs"
 | 
							ewarn "in your kernel configuration or see ${conf_d_dir}/${RC_SVCNAME}"
 | 
				
			||||||
	fi
 | 
						fi
 | 
				
			||||||
	return 0
 | 
						return 0
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,9 +20,9 @@ depend()
 | 
				
			|||||||
start()
 | 
					start()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	local h source x
 | 
						local h source x
 | 
				
			||||||
	if [ -s @SYSCONFDIR@/hostname ] && [ -r @SYSCONFDIR@/hostname ]; then
 | 
						if [ -s /etc/hostname ] && [ -r /etc/hostname ]; then
 | 
				
			||||||
		read h x <@SYSCONFDIR@/hostname
 | 
							read h x </etc/hostname
 | 
				
			||||||
		source="from @SYSCONFDIR@/hostname"
 | 
							source="from /etc/hostname"
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		# HOSTNAME variable used to be defined in caps in conf.d/hostname.
 | 
							# HOSTNAME variable used to be defined in caps in conf.d/hostname.
 | 
				
			||||||
		# It is also a magic variable in bash.
 | 
							# It is also a magic variable in bash.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -105,7 +105,7 @@ start()
 | 
				
			|||||||
			done
 | 
								done
 | 
				
			||||||
			[ -n "$modname" ] &&
 | 
								[ -n "$modname" ] &&
 | 
				
			||||||
				ewarn "The $modname module needs to be configured in" \
 | 
									ewarn "The $modname module needs to be configured in" \
 | 
				
			||||||
					"@SYSCONFDIR@/conf.d/modules or built in."
 | 
										"${RC_SERVICE%/*/*}/conf.d/modules or built in."
 | 
				
			||||||
		fi
 | 
							fi
 | 
				
			||||||
	fi
 | 
						fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,7 +13,7 @@ description="Applies a keymap for the consoles."
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
depend()
 | 
					depend()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	need localmount termencoding
 | 
						need termencoding
 | 
				
			||||||
	after bootmisc clock
 | 
						after bootmisc clock
 | 
				
			||||||
	keyword -docker -lxc -openvz -prefix -systemd-nspawn -uml -vserver -xenu
 | 
						keyword -docker -lxc -openvz -prefix -systemd-nspawn -uml -vserver -xenu
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,7 +9,10 @@
 | 
				
			|||||||
# This file may not be copied, modified, propagated, or distributed
 | 
					# This file may not be copied, modified, propagated, or distributed
 | 
				
			||||||
# except according to the terms contained in the LICENSE file.
 | 
					# except according to the terms contained in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
description="Executes user programs in @SYSCONFDIR@/local.d"
 | 
					conf_d_dir="${RC_SERVICE%/*/*}/conf.d"
 | 
				
			||||||
 | 
					local_d_dir="${RC_SERVICE%/*/*}/local.d"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					description="Executes user programs in ${local_d_dir}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
depend()
 | 
					depend()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -19,12 +22,12 @@ depend()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
start()
 | 
					start()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	ebegin "Starting local"
 | 
						local file has_errors redirect retval
 | 
				
			||||||
 | 
						has_errors=0
 | 
				
			||||||
	local file has_errors=0 redirect retval
 | 
					 | 
				
			||||||
	yesno $rc_verbose || redirect='> /dev/null 2>&1'
 | 
						yesno $rc_verbose || redirect='> /dev/null 2>&1'
 | 
				
			||||||
 | 
						ebegin "Starting local"
 | 
				
			||||||
	eindent
 | 
						eindent
 | 
				
			||||||
	for file in @SYSCONFDIR@/local.d/*.start; do
 | 
						for file in "${local_d_dir}"/*.start; do
 | 
				
			||||||
		if [ -x "${file}" ]; then
 | 
							if [ -x "${file}" ]; then
 | 
				
			||||||
			vebegin "Executing \"${file}\""
 | 
								vebegin "Executing \"${file}\""
 | 
				
			||||||
			eval "${file}" $redirect
 | 
								eval "${file}" $redirect
 | 
				
			||||||
@@ -38,32 +41,32 @@ start()
 | 
				
			|||||||
	eoutdent
 | 
						eoutdent
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if command -v local_start >/dev/null 2>&1; then
 | 
						if command -v local_start >/dev/null 2>&1; then
 | 
				
			||||||
		ewarn "\"@SYSCONFDIR@/conf.d/local\" should be removed."
 | 
							ewarn "\"${conf_d_dir}/local\" should be removed."
 | 
				
			||||||
		ewarn "Please move the code from the local_start function"
 | 
							ewarn "Please move the code from the local_start function"
 | 
				
			||||||
		ewarn "to executable scripts with an .start extension"
 | 
							ewarn "to executable scripts with an .start extension"
 | 
				
			||||||
		ewarn "in \"@SYSCONFDIR@/local.d\""
 | 
							ewarn "in \"${local_d_dir}\""
 | 
				
			||||||
		local_start
 | 
							local_start
 | 
				
			||||||
	fi
 | 
						fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	eend ${has_errors}
 | 
						eend ${has_errors}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# We have to end with a zero exit code, because a failed execution
 | 
						# We have to end with a zero exit code, because a failed execution
 | 
				
			||||||
	# of an executable @SYSCONFDIR@/local.d/*.start file shouldn't result in
 | 
						# of an executable ${local_d_dir}/*.start file shouldn't result in
 | 
				
			||||||
	# marking the local service as failed. Otherwise we are unable to
 | 
						# marking the local service as failed. Otherwise we are unable to
 | 
				
			||||||
	# execute any executable @SYSCONFDIR@/local.d/*.stop file, because a failed
 | 
						# execute any executable ${local_d_dir}/*.stop file, because a failed
 | 
				
			||||||
	# marked service cannot be stopped (and the stop function would
 | 
						# marked service cannot be stopped (and the stop function would
 | 
				
			||||||
	# actually call the executable @SYSCONFDIR@/local.d/*.stop file(s)).
 | 
						# actually call the executable ${local_d_dir}/*.stop file(s)).
 | 
				
			||||||
	return 0
 | 
						return 0
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
stop()
 | 
					stop()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	ebegin "Stopping local"
 | 
						local file has_errors redirect retval
 | 
				
			||||||
 | 
						has_errors=0
 | 
				
			||||||
	local file has_errors=0 redirect retval
 | 
					 | 
				
			||||||
	yesno $rc_verbose || redirect='> /dev/null 2>&1'
 | 
						yesno $rc_verbose || redirect='> /dev/null 2>&1'
 | 
				
			||||||
 | 
						ebegin "Stopping local"
 | 
				
			||||||
	eindent
 | 
						eindent
 | 
				
			||||||
	for file in @SYSCONFDIR@/local.d/*.stop; do
 | 
						for file in "${local_d_dir}"/*.stop; do
 | 
				
			||||||
		if [ -x "${file}" ]; then
 | 
							if [ -x "${file}" ]; then
 | 
				
			||||||
			vebegin "Executing \"${file}\""
 | 
								vebegin "Executing \"${file}\""
 | 
				
			||||||
			eval "${file}" $redirect
 | 
								eval "${file}" $redirect
 | 
				
			||||||
@@ -77,16 +80,16 @@ stop()
 | 
				
			|||||||
	eoutdent
 | 
						eoutdent
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if command -v local_stop >/dev/null 2>&1; then
 | 
						if command -v local_stop >/dev/null 2>&1; then
 | 
				
			||||||
		ewarn "\"@SYSCONFDIR@/conf.d/local\" should be removed."
 | 
							ewarn "\"${conf_d_dir}/local\" should be removed."
 | 
				
			||||||
		ewarn "Please move the code from the local_stop function"
 | 
							ewarn "Please move the code from the local_stop function"
 | 
				
			||||||
		ewarn "to executable scripts with an .stop extension"
 | 
							ewarn "to executable scripts with an .stop extension"
 | 
				
			||||||
		ewarn "in \"@SYSCONFDIR@/local.d\""
 | 
							ewarn "in \"${local_d_dir}\""
 | 
				
			||||||
		local_stop
 | 
							local_stop
 | 
				
			||||||
	fi
 | 
						fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	eend ${has_errors}
 | 
						eend ${has_errors}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# An executable @SYSCONFDIR@/local.d/*.stop file which failed with a
 | 
						# An executable ${local_d_dir}/*.stop file which failed with a
 | 
				
			||||||
	# non-zero exit status is not a reason to mark this service
 | 
						# non-zero exit status is not a reason to mark this service
 | 
				
			||||||
	# as failed, therefore we have to end with a zero exit code.
 | 
						# as failed, therefore we have to end with a zero exit code.
 | 
				
			||||||
	return 0
 | 
						return 0
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,7 +14,7 @@ description="Mounts disks and swap according to /etc/fstab."
 | 
				
			|||||||
depend()
 | 
					depend()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	need fsck
 | 
						need fsck
 | 
				
			||||||
	use lvm modules mtab root
 | 
						use lvm modules root
 | 
				
			||||||
	after clock lvm modules root
 | 
						after clock lvm modules root
 | 
				
			||||||
	keyword -docker -jail -lxc -prefix -systemd-nspawn -vserver
 | 
						keyword -docker -jail -lxc -prefix -systemd-nspawn -vserver
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,72 +0,0 @@
 | 
				
			|||||||
#!@SBINDIR@/openrc-run
 | 
					 | 
				
			||||||
# 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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
description="Loads a list of modules from systemd-compatible locations."
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
depend()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	keyword -docker -lxc -openvz -prefix -systemd-nspawn -vserver
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
find_modfiles()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	local dirs="/usr/lib/modules-load.d /run/modules-load.d /etc/modules-load.d"
 | 
					 | 
				
			||||||
	local basenames files fn x y
 | 
					 | 
				
			||||||
	for x in $dirs; do
 | 
					 | 
				
			||||||
		[ ! -d $x ] && continue
 | 
					 | 
				
			||||||
		for y in $x/*.conf; do
 | 
					 | 
				
			||||||
			[ -f $y ] && basenames="${basenames}\n${y##*/}"
 | 
					 | 
				
			||||||
		done
 | 
					 | 
				
			||||||
	done
 | 
					 | 
				
			||||||
	basenames=$(printf "$basenames" | sort -u)
 | 
					 | 
				
			||||||
	for x in $basenames; do
 | 
					 | 
				
			||||||
		for y in $dirs; do
 | 
					 | 
				
			||||||
			[ -r $y/$x ] &&
 | 
					 | 
				
			||||||
				fn=$y/$x
 | 
					 | 
				
			||||||
		done
 | 
					 | 
				
			||||||
		files="$files $fn"
 | 
					 | 
				
			||||||
	done
 | 
					 | 
				
			||||||
	echo $files
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
load_modules()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	local file m modules rc x
 | 
					 | 
				
			||||||
	file=$1
 | 
					 | 
				
			||||||
	[ -z "$file" ] && return 0
 | 
					 | 
				
			||||||
	while read m x; do
 | 
					 | 
				
			||||||
		case $m in
 | 
					 | 
				
			||||||
			\;*) continue ;;
 | 
					 | 
				
			||||||
			\#*) continue ;;
 | 
					 | 
				
			||||||
			*) modules="$modules $m"
 | 
					 | 
				
			||||||
			;;
 | 
					 | 
				
			||||||
		esac
 | 
					 | 
				
			||||||
	done < $file
 | 
					 | 
				
			||||||
	for x in $modules; do
 | 
					 | 
				
			||||||
		ebegin "Loading module $x"
 | 
					 | 
				
			||||||
		case "$RC_UNAME" in
 | 
					 | 
				
			||||||
			FreeBSD) kldload "$x"; rc=$? ;;
 | 
					 | 
				
			||||||
			Linux) modprobe --use-blacklist -q "$x"; rc=$? ;;
 | 
					 | 
				
			||||||
			*) ;;
 | 
					 | 
				
			||||||
		esac
 | 
					 | 
				
			||||||
		eend $rc "Failed to load $x"
 | 
					 | 
				
			||||||
	done
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
start()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	local x
 | 
					 | 
				
			||||||
	files=$(find_modfiles)
 | 
					 | 
				
			||||||
	for x in $files; do
 | 
					 | 
				
			||||||
		load_modules $x
 | 
					 | 
				
			||||||
	done
 | 
					 | 
				
			||||||
	return 0
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -14,10 +14,65 @@ description="Loads a user defined list of kernel modules."
 | 
				
			|||||||
depend()
 | 
					depend()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	use isapnp
 | 
						use isapnp
 | 
				
			||||||
	want modules-load
 | 
						provide modules-load
 | 
				
			||||||
	keyword -docker -lxc -openvz -prefix -systemd-nspawn -vserver
 | 
						keyword -docker -lxc -openvz -prefix -systemd-nspawn -vserver
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					find_modfiles()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						local dirs="/usr/lib/modules-load.d /run/modules-load.d /etc/modules-load.d"
 | 
				
			||||||
 | 
						local basenames files fn x y
 | 
				
			||||||
 | 
						for x in $dirs; do
 | 
				
			||||||
 | 
							[ ! -d $x ] && continue
 | 
				
			||||||
 | 
							for y in $x/*.conf; do
 | 
				
			||||||
 | 
								[ -f $y ] && basenames="${basenames}\n${y##*/}"
 | 
				
			||||||
 | 
							done
 | 
				
			||||||
 | 
						done
 | 
				
			||||||
 | 
						basenames=$(printf "$basenames" | sort -u)
 | 
				
			||||||
 | 
						for x in $basenames; do
 | 
				
			||||||
 | 
							for y in $dirs; do
 | 
				
			||||||
 | 
								[ -r $y/$x ] &&
 | 
				
			||||||
 | 
									fn=$y/$x
 | 
				
			||||||
 | 
							done
 | 
				
			||||||
 | 
							files="$files $fn"
 | 
				
			||||||
 | 
						done
 | 
				
			||||||
 | 
						echo $files
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					load_modules()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						local file m modules rc x
 | 
				
			||||||
 | 
						file=$1
 | 
				
			||||||
 | 
						[ -z "$file" ] && return 0
 | 
				
			||||||
 | 
						while read m x; do
 | 
				
			||||||
 | 
							case $m in
 | 
				
			||||||
 | 
								\;*) continue ;;
 | 
				
			||||||
 | 
								\#*) continue ;;
 | 
				
			||||||
 | 
								*) modules="$modules $m"
 | 
				
			||||||
 | 
								;;
 | 
				
			||||||
 | 
							esac
 | 
				
			||||||
 | 
						done < $file
 | 
				
			||||||
 | 
						for x in $modules; do
 | 
				
			||||||
 | 
							ebegin "Loading module $x"
 | 
				
			||||||
 | 
							case "$RC_UNAME" in
 | 
				
			||||||
 | 
								FreeBSD) kldload "$x"; rc=$? ;;
 | 
				
			||||||
 | 
								Linux) modprobe --use-blacklist -q "$x"; rc=$? ;;
 | 
				
			||||||
 | 
								*) ;;
 | 
				
			||||||
 | 
							esac
 | 
				
			||||||
 | 
							eend $rc "Failed to load $x"
 | 
				
			||||||
 | 
						done
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					modules_load_d()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						local x
 | 
				
			||||||
 | 
						files=$(find_modfiles)
 | 
				
			||||||
 | 
						for x in $files; do
 | 
				
			||||||
 | 
							load_modules $x
 | 
				
			||||||
 | 
						done
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
FreeBSD_modules()
 | 
					FreeBSD_modules()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	local cnt=0 x
 | 
						local cnt=0 x
 | 
				
			||||||
@@ -82,7 +137,10 @@ Linux_modules()
 | 
				
			|||||||
start()
 | 
					start()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	case "$RC_UNAME" in
 | 
						case "$RC_UNAME" in
 | 
				
			||||||
		FreeBSD|Linux) ${RC_UNAME}_modules ;;
 | 
							FreeBSD|Linux) 
 | 
				
			||||||
 | 
								modules_load_d
 | 
				
			||||||
 | 
								${RC_UNAME}_modules
 | 
				
			||||||
 | 
								;;
 | 
				
			||||||
		*) ;;
 | 
							*) ;;
 | 
				
			||||||
	esac
 | 
						esac
 | 
				
			||||||
	return 0
 | 
						return 0
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,6 +14,7 @@ description="Update /etc/mtab to match what the kernel knows about"
 | 
				
			|||||||
depend()
 | 
					depend()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	after clock
 | 
						after clock
 | 
				
			||||||
 | 
						before localmount
 | 
				
			||||||
	need root
 | 
						need root
 | 
				
			||||||
	keyword -prefix -systemd-nspawn
 | 
						keyword -prefix -systemd-nspawn
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -30,6 +31,10 @@ start()
 | 
				
			|||||||
		einfo "Creating mtab symbolic link"
 | 
							einfo "Creating mtab symbolic link"
 | 
				
			||||||
		ln -snf /proc/self/mounts /etc/mtab
 | 
							ln -snf /proc/self/mounts /etc/mtab
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
 | 
							ewarn "The ${RC_SVCNAME} service will be removed in the future."
 | 
				
			||||||
 | 
							ewarn "Please change the mtab_is_file setting to no and run"
 | 
				
			||||||
 | 
							ewarn "# rc-service mtab restart"
 | 
				
			||||||
 | 
							ewarn "to create the mtab symbolic link."
 | 
				
			||||||
		[ -L /etc/mtab ] && ewarn "Removing /etc/mtab symbolic link"
 | 
							[ -L /etc/mtab ] && ewarn "Removing /etc/mtab symbolic link"
 | 
				
			||||||
		rm -f /etc/mtab
 | 
							rm -f /etc/mtab
 | 
				
			||||||
		einfo "Creating mtab file"
 | 
							einfo "Creating mtab file"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,7 +13,7 @@ description="Delays until the network is online or a specific timeout"
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
depend()
 | 
					depend()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	after modules
 | 
						after modules net
 | 
				
			||||||
	need sysfs
 | 
						need sysfs
 | 
				
			||||||
	provide network-online
 | 
						provide network-online
 | 
				
			||||||
	keyword -docker -jail -lxc -openvz -prefix -systemd-nspawn -uml -vserver
 | 
						keyword -docker -jail -lxc -openvz -prefix -systemd-nspawn -uml -vserver
 | 
				
			||||||
@@ -23,6 +23,7 @@ get_interfaces()
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	local ifname iftype
 | 
						local ifname iftype
 | 
				
			||||||
	for ifname in /sys/class/net/*; do
 | 
						for ifname in /sys/class/net/*; do
 | 
				
			||||||
 | 
							[ -h "${ifname}" ] && continue
 | 
				
			||||||
		read iftype < ${ifname}/type
 | 
							read iftype < ${ifname}/type
 | 
				
			||||||
		[ "$iftype" = "1" ] && printf "%s " ${ifname##*/}
 | 
							[ "$iftype" = "1" ] && printf "%s " ${ifname##*/}
 | 
				
			||||||
	done
 | 
						done
 | 
				
			||||||
@@ -31,7 +32,7 @@ get_interfaces()
 | 
				
			|||||||
start ()
 | 
					start ()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	local carriers configured dev gateway ifcount infinite
 | 
						local carriers configured dev gateway ifcount infinite
 | 
				
			||||||
	local rc state x
 | 
						local carrier operstate rc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ebegin "Checking to see if the network is online"
 | 
						ebegin "Checking to see if the network is online"
 | 
				
			||||||
	rc=0
 | 
						rc=0
 | 
				
			||||||
@@ -44,10 +45,12 @@ start ()
 | 
				
			|||||||
	ifcount=0
 | 
						ifcount=0
 | 
				
			||||||
 	for dev in ${interfaces}; do
 | 
					 	for dev in ${interfaces}; do
 | 
				
			||||||
		: $((ifcount += 1))
 | 
							: $((ifcount += 1))
 | 
				
			||||||
		read x < /sys/class/net/$dev/carrier
 | 
							read carrier < /sys/class/net/$dev/carrier 2> /dev/null ||
 | 
				
			||||||
		[ $x -eq 1 ] && : $((carriers += 1))
 | 
								carrier=
 | 
				
			||||||
		read x < /sys/class/net/$dev/operstate
 | 
							[ "$carrier" = 1 ] && : $((carriers += 1))
 | 
				
			||||||
		[ "$x" = up ] && : $((configured += 1))
 | 
							read operstate < /sys/class/net/$dev/operstate 2> /dev/null ||
 | 
				
			||||||
 | 
								operstate=
 | 
				
			||||||
 | 
							[ "$operstate" = up ] && : $((configured += 1))
 | 
				
			||||||
	done
 | 
						done
 | 
				
			||||||
	[ $configured -eq $ifcount ] && [ $carriers -ge 1 ] && break
 | 
						[ $configured -eq $ifcount ] && [ $carriers -ge 1 ] && break
 | 
				
			||||||
	sleep 1
 | 
						sleep 1
 | 
				
			||||||
@@ -61,8 +64,12 @@ start ()
 | 
				
			|||||||
 if [ $rc -eq 0 ] && yesno ${include_ping_test:-no}; then
 | 
					 if [ $rc -eq 0 ] && yesno ${include_ping_test:-no}; then
 | 
				
			||||||
 	ping_test_host="${ping_test_host:-google.com}"
 | 
					 	ping_test_host="${ping_test_host:-google.com}"
 | 
				
			||||||
 	if [ -n "$ping_test_host" ]; then
 | 
					 	if [ -n "$ping_test_host" ]; then
 | 
				
			||||||
		ping -c 1 $ping_test_host > /dev/null 2>&1
 | 
							while $infinite || [ $timeout -gt 0 ]; do
 | 
				
			||||||
		rc=$?
 | 
								ping -c 1 $ping_test_host > /dev/null 2>&1
 | 
				
			||||||
 | 
								rc=$?
 | 
				
			||||||
 | 
								[ $rc -eq 0 ] && break
 | 
				
			||||||
 | 
								: $((timeout -= 1))
 | 
				
			||||||
 | 
							done
 | 
				
			||||||
	fi
 | 
						fi
 | 
				
			||||||
 fi
 | 
					 fi
 | 
				
			||||||
 eend $rc "The network is offline"
 | 
					 eend $rc "The network is offline"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -76,7 +76,7 @@ tentative()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	case "$RC_UNAME" in
 | 
						case "$RC_UNAME" in
 | 
				
			||||||
	Linux)
 | 
						Linux)
 | 
				
			||||||
		[ -x /sbin/ip ] || [ -x /bin/ip ] || return 1
 | 
							[ -n "$(command -v ip)" ] || return 1
 | 
				
			||||||
		[ -n "$(ip -f inet6 addr show tentative)" ]
 | 
							[ -n "$(ip -f inet6 addr show tentative)" ]
 | 
				
			||||||
		;;
 | 
							;;
 | 
				
			||||||
	*)
 | 
						*)
 | 
				
			||||||
@@ -174,7 +174,7 @@ runip()
 | 
				
			|||||||
routeflush()
 | 
					routeflush()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if [ "$RC_UNAME" = Linux ]; then
 | 
						if [ "$RC_UNAME" = Linux ]; then
 | 
				
			||||||
		if [ -x /sbin/ip ] || [ -x /bin/ip ]; then
 | 
							if [ -n "$(command -v ip)"  ]; then
 | 
				
			||||||
			ip route flush scope global
 | 
								ip route flush scope global
 | 
				
			||||||
			ip route delete default 2>/dev/null
 | 
								ip route delete default 2>/dev/null
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
@@ -346,7 +346,7 @@ stop()
 | 
				
			|||||||
		then
 | 
							then
 | 
				
			||||||
			veinfo "$int"
 | 
								veinfo "$int"
 | 
				
			||||||
			runargs /etc/ifdown."$int" "$downcmd"
 | 
								runargs /etc/ifdown."$int" "$downcmd"
 | 
				
			||||||
			if [ -x /sbin/ip ] || [ -x /bin/ip ]; then
 | 
								if [ -n "$(command -v ip)" ]; then
 | 
				
			||||||
				# We need to do this, otherwise we may
 | 
									# We need to do this, otherwise we may
 | 
				
			||||||
				# fail to add things correctly on restart
 | 
									# fail to add things correctly on restart
 | 
				
			||||||
				ip address flush dev "$int" 2>/dev/null
 | 
									ip address flush dev "$int" 2>/dev/null
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,7 +15,6 @@ ttyn=${rc_tty_number:-${RC_TTY_NUMBER:-12}}
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
depend()
 | 
					depend()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	need localmount
 | 
					 | 
				
			||||||
	keyword -docker -lxc -openvz -prefix -systemd-nspawn -vserver
 | 
						keyword -docker -lxc -openvz -prefix -systemd-nspawn -vserver
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,7 +16,6 @@ depend()
 | 
				
			|||||||
	after clock
 | 
						after clock
 | 
				
			||||||
	use devfs
 | 
						use devfs
 | 
				
			||||||
	want modules
 | 
						want modules
 | 
				
			||||||
	need localmount
 | 
					 | 
				
			||||||
	keyword -docker -lxc -openvz -prefix -systemd-nspawn -vserver
 | 
						keyword -docker -lxc -openvz -prefix -systemd-nspawn -vserver
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -27,8 +26,8 @@ start()
 | 
				
			|||||||
		[ ! -e /proc/sys/fs/binfmt_misc/register ]; then
 | 
							[ ! -e /proc/sys/fs/binfmt_misc/register ]; then
 | 
				
			||||||
		if ! grep -qs binfmt_misc /proc/filesystems &&
 | 
							if ! grep -qs binfmt_misc /proc/filesystems &&
 | 
				
			||||||
			modprobe -q binfmt-misc; then
 | 
								modprobe -q binfmt-misc; then
 | 
				
			||||||
			ewarn "The binfmt-misc module needs to be configured in" \
 | 
								ewarn "The binfmt-misc module needs to be loaded by" \
 | 
				
			||||||
				"@SYSCONFDIR@/conf.d/modules or built in."
 | 
									"the modules service or built in."
 | 
				
			||||||
		fi
 | 
							fi
 | 
				
			||||||
		if grep -qs binfmt_misc /proc/filesystems; then
 | 
							if grep -qs binfmt_misc /proc/filesystems; then
 | 
				
			||||||
			ebegin "Mounting misc binary format filesystem"
 | 
								ebegin "Mounting misc binary format filesystem"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -49,7 +49,7 @@ start()
 | 
				
			|||||||
	fi
 | 
						fi
 | 
				
			||||||
	ebegin "Saving dependency cache"
 | 
						ebegin "Saving dependency cache"
 | 
				
			||||||
	local rc=0 save=
 | 
						local rc=0 save=
 | 
				
			||||||
	for x in shutdowntime softlevel rc.log; do
 | 
						for x in depconfig deptree rc.log shutdowntime softlevel; do
 | 
				
			||||||
		[ -e "$RC_SVCDIR/$x" ] && save="$save $RC_SVCDIR/$x"
 | 
							[ -e "$RC_SVCDIR/$x" ] && save="$save $RC_SVCDIR/$x"
 | 
				
			||||||
	done
 | 
						done
 | 
				
			||||||
	if [ -n "$save" ]; then
 | 
						if [ -n "$save" ]; then
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,7 +11,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
depend()
 | 
					depend()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	after clock
 | 
						after clock root
 | 
				
			||||||
	before localmount
 | 
						before localmount
 | 
				
			||||||
	keyword -docker -jail -lxc -openvz -prefix -systemd-nspawn -vserver
 | 
						keyword -docker -jail -lxc -openvz -prefix -systemd-nspawn -vserver
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,7 +21,7 @@ BSD_sysctl()
 | 
				
			|||||||
	[ -e /etc/sysctl.conf ] || return 0
 | 
						[ -e /etc/sysctl.conf ] || return 0
 | 
				
			||||||
	local retval=0 var= comments= conf=
 | 
						local retval=0 var= comments= conf=
 | 
				
			||||||
	eindent
 | 
						eindent
 | 
				
			||||||
	for conf in @SYSCONFDIR@/sysctl.conf @SYSCONFDIR@/sysctl.d/*.conf; do
 | 
						for conf in /etc/sysctl.conf /etc/sysctl.d/*.conf; do
 | 
				
			||||||
		if [ -r "$conf" ]; then
 | 
							if [ -r "$conf" ]; then
 | 
				
			||||||
			vebegin "applying $conf"
 | 
								vebegin "applying $conf"
 | 
				
			||||||
			while read var comments; do
 | 
								while read var comments; do
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										112
									
								
								init.d/sysfs.in
									
									
									
									
									
								
							
							
						
						
									
										112
									
								
								init.d/sysfs.in
									
									
									
									
									
								
							@@ -107,122 +107,11 @@ mount_misc()
 | 
				
			|||||||
	fi
 | 
						fi
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cgroup1_base()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	grep -qw cgroup /proc/filesystems || return 0
 | 
					 | 
				
			||||||
	if ! mountinfo -q /sys/fs/cgroup; then
 | 
					 | 
				
			||||||
		ebegin "Mounting cgroup filesystem"
 | 
					 | 
				
			||||||
		local opts="${sysfs_opts},mode=755,size=${rc_cgroupsize:-10m}"
 | 
					 | 
				
			||||||
		mount -n -t tmpfs -o "${opts}" cgroup_root /sys/fs/cgroup
 | 
					 | 
				
			||||||
		eend $?
 | 
					 | 
				
			||||||
	fi
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if ! mountinfo -q /sys/fs/cgroup/openrc; then
 | 
					 | 
				
			||||||
		local agent="${RC_LIBEXECDIR}/sh/cgroup-release-agent.sh"
 | 
					 | 
				
			||||||
		mkdir /sys/fs/cgroup/openrc
 | 
					 | 
				
			||||||
		mount -n -t cgroup \
 | 
					 | 
				
			||||||
			-o none,${sysfs_opts},name=openrc,release_agent="$agent" \
 | 
					 | 
				
			||||||
			openrc /sys/fs/cgroup/openrc
 | 
					 | 
				
			||||||
		printf 1 > /sys/fs/cgroup/openrc/notify_on_release
 | 
					 | 
				
			||||||
	fi
 | 
					 | 
				
			||||||
	return 0
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
cgroup1_controllers()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	yesno "${rc_controller_cgroups:-YES}" && [ -e /proc/cgroups ] || return 0
 | 
					 | 
				
			||||||
	while read -r name _ _ enabled rest; do
 | 
					 | 
				
			||||||
		case "${enabled}" in
 | 
					 | 
				
			||||||
			1)	mountinfo -q "/sys/fs/cgroup/${name}" && continue
 | 
					 | 
				
			||||||
				local x
 | 
					 | 
				
			||||||
				for x in $rc_cgroup_controllers; do
 | 
					 | 
				
			||||||
				[ "${name}" = "blkio" ] && [ "${x}" = "io" ] &&
 | 
					 | 
				
			||||||
					continue 2
 | 
					 | 
				
			||||||
				[ "${name}" = "${x}" ] &&
 | 
					 | 
				
			||||||
				continue 2
 | 
					 | 
				
			||||||
				done
 | 
					 | 
				
			||||||
				mkdir "/sys/fs/cgroup/${name}"
 | 
					 | 
				
			||||||
				mount -n -t cgroup -o "${sysfs_opts},${name}" \
 | 
					 | 
				
			||||||
					"${name}" "/sys/fs/cgroup/${name}"
 | 
					 | 
				
			||||||
				;;
 | 
					 | 
				
			||||||
		esac
 | 
					 | 
				
			||||||
	done < /proc/cgroups
 | 
					 | 
				
			||||||
	return 0
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
cgroup2_base()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	local base
 | 
					 | 
				
			||||||
	base="$(cgroup2_find_path)"
 | 
					 | 
				
			||||||
	mkdir -p "${base}"
 | 
					 | 
				
			||||||
	mount -t cgroup2 none -o "${sysfs_opts},nsdelegate" "${base}" 2> /dev/null ||
 | 
					 | 
				
			||||||
		mount -t cgroup2 none -o "${sysfs_opts}" "${base}"
 | 
					 | 
				
			||||||
	return 0
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
cgroup2_controllers()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	local active cgroup_path x y
 | 
					 | 
				
			||||||
	cgroup_path="$(cgroup2_find_path)"
 | 
					 | 
				
			||||||
	[ -z "${cgroup_path}" ] && return 0
 | 
					 | 
				
			||||||
	[ -e "${cgroup_path}/cgroup.controllers" ] &&
 | 
					 | 
				
			||||||
	read -r active < "${cgroup_path}/cgroup.controllers"
 | 
					 | 
				
			||||||
	for x in ${rc_cgroup_controllers}; do
 | 
					 | 
				
			||||||
		for y in ${active}; do
 | 
					 | 
				
			||||||
		[ "$x" = "$y" ] &&
 | 
					 | 
				
			||||||
			[ -e "${cgroup_path}/cgroup.subtree_control" ]&&
 | 
					 | 
				
			||||||
			echo "+${x}"  > "${cgroup_path}/cgroup.subtree_control"
 | 
					 | 
				
			||||||
		done
 | 
					 | 
				
			||||||
	done
 | 
					 | 
				
			||||||
	return 0
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
cgroups_hybrid()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	grep -qw cgroup /proc/filesystems || return 0
 | 
					 | 
				
			||||||
	cgroup1_base
 | 
					 | 
				
			||||||
	if grep -qw cgroup2 /proc/filesystems; then
 | 
					 | 
				
			||||||
		cgroup2_base
 | 
					 | 
				
			||||||
		cgroup2_controllers
 | 
					 | 
				
			||||||
	fi
 | 
					 | 
				
			||||||
	cgroup1_controllers
 | 
					 | 
				
			||||||
	return 0
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
cgroups_legacy()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	grep -qw cgroup /proc/filesystems || return 0
 | 
					 | 
				
			||||||
	cgroup1_base
 | 
					 | 
				
			||||||
	cgroup1_controllers
 | 
					 | 
				
			||||||
	return 0
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
cgroups_unified()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	cgroup2_base
 | 
					 | 
				
			||||||
	cgroup2_controllers
 | 
					 | 
				
			||||||
	return 0
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
mount_cgroups()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	# set up kernel support for cgroups
 | 
					 | 
				
			||||||
	if [ -d /sys/fs/cgroup ]; then
 | 
					 | 
				
			||||||
		case "${rc_cgroup_mode:-hybrid}" in
 | 
					 | 
				
			||||||
		hybrid) cgroups_hybrid ;;
 | 
					 | 
				
			||||||
		legacy) cgroups_legacy ;;
 | 
					 | 
				
			||||||
		unified) cgroups_unified ;;
 | 
					 | 
				
			||||||
		esac
 | 
					 | 
				
			||||||
	fi
 | 
					 | 
				
			||||||
	return 0
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
restorecon_sys()
 | 
					restorecon_sys()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if [ -x /sbin/restorecon ]; then
 | 
						if [ -x /sbin/restorecon ]; then
 | 
				
			||||||
		ebegin "Restoring SELinux contexts in /sys"
 | 
							ebegin "Restoring SELinux contexts in /sys"
 | 
				
			||||||
		restorecon -F /sys/devices/system/cpu/online >/dev/null 2>&1
 | 
							restorecon -F /sys/devices/system/cpu/online >/dev/null 2>&1
 | 
				
			||||||
		restorecon -rF /sys/fs/cgroup >/dev/null 2>&1
 | 
					 | 
				
			||||||
		eend $?
 | 
							eend $?
 | 
				
			||||||
	fi
 | 
						fi
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -231,7 +120,6 @@ start()
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	mount_sys
 | 
						mount_sys
 | 
				
			||||||
	mount_misc
 | 
						mount_misc
 | 
				
			||||||
	mount_cgroups
 | 
					 | 
				
			||||||
	restorecon_sys
 | 
						restorecon_sys
 | 
				
			||||||
	return 0
 | 
						return 0
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@
 | 
				
			|||||||
.\" This file may not be copied, modified, propagated, or distributed
 | 
					.\" This file may not be copied, modified, propagated, or distributed
 | 
				
			||||||
.\"    except according to the terms contained in the LICENSE file.
 | 
					.\"    except according to the terms contained in the LICENSE file.
 | 
				
			||||||
.\"
 | 
					.\"
 | 
				
			||||||
.Dd December 31, 2011
 | 
					.Dd November 30, 2017
 | 
				
			||||||
.Dt openrc-run 8 SMM
 | 
					.Dt openrc-run 8 SMM
 | 
				
			||||||
.Os OpenRC
 | 
					.Os OpenRC
 | 
				
			||||||
.Sh NAME
 | 
					.Sh NAME
 | 
				
			||||||
@@ -111,11 +111,17 @@ The path to the s6 service directory if you are monitoring this service
 | 
				
			|||||||
with S6. The default is /var/svc.d/${RC_SVCNAME}.
 | 
					with S6. The default is /var/svc.d/${RC_SVCNAME}.
 | 
				
			||||||
.It Ar s6_svwait_options_start
 | 
					.It Ar s6_svwait_options_start
 | 
				
			||||||
The options to pass to s6-svwait when starting the service via s6.
 | 
					The options to pass to s6-svwait when starting the service via s6.
 | 
				
			||||||
 | 
					.It Ar s6_force_kill
 | 
				
			||||||
 | 
					Should we force-kill this service if s6_service_timeout_stop expires
 | 
				
			||||||
 | 
					but the service doesn't go down during shutdown? The default is yes.
 | 
				
			||||||
.It Ar s6_service_timeout_stop
 | 
					.It Ar s6_service_timeout_stop
 | 
				
			||||||
The amount of time, in milliseconds, s6-svc should wait for the service
 | 
					The amount of time, in milliseconds, s6-svc should wait for the service
 | 
				
			||||||
to go down when stopping the service. The default is 10000.
 | 
					to go down when stopping the service. The default is 60000.
 | 
				
			||||||
.It Ar start_stop_daemon_args
 | 
					.It Ar start_stop_daemon_args
 | 
				
			||||||
List of arguments passed to start-stop-daemon when starting the daemon.
 | 
					List of arguments passed to start-stop-daemon when starting the daemon.
 | 
				
			||||||
 | 
					.It Ar supervise_daemon_args
 | 
				
			||||||
 | 
					List of arguments passed to supervise-daemon when starting the daemon.
 | 
				
			||||||
 | 
					If undefined, start_stop_daemon_args is used as a fallback.
 | 
				
			||||||
.It Ar command
 | 
					.It Ar command
 | 
				
			||||||
Daemon to start or stop via
 | 
					Daemon to start or stop via
 | 
				
			||||||
.Nm start-stop-daemon
 | 
					.Nm start-stop-daemon
 | 
				
			||||||
@@ -139,21 +145,56 @@ List of arguments to pass to the daemon when starting via
 | 
				
			|||||||
.Nm supervise-daemon .
 | 
					.Nm supervise-daemon .
 | 
				
			||||||
to force the daemon to stay in the foreground
 | 
					to force the daemon to stay in the foreground
 | 
				
			||||||
.It Ar command_background
 | 
					.It Ar command_background
 | 
				
			||||||
Set this to "true", "yes" or "1" (case-insensitive) if you want 
 | 
					Set this to "true", "yes" or "1" (case-insensitive) if you want
 | 
				
			||||||
.Xr start-stop-daemon 8
 | 
					.Xr start-stop-daemon 8
 | 
				
			||||||
to force the daemon into the background. This forces the
 | 
					to force the daemon into the background. This forces the
 | 
				
			||||||
"--make-pidfile" and "--pidfile" options, so the pidfile variable must be set.
 | 
					"--make-pidfile" and "--pidfile" options, so the pidfile variable must be set.
 | 
				
			||||||
.It Ar command_progress
 | 
					.It Ar command_progress
 | 
				
			||||||
Set this to "true", "yes" or "1" (case-insensitive) if you want 
 | 
					Set this to "true", "yes" or "1" (case-insensitive) if you want
 | 
				
			||||||
.Xr start-stop-daemon 8
 | 
					.Xr start-stop-daemon 8
 | 
				
			||||||
to display a progress meter when waiting for a daemon to stop.
 | 
					to display a progress meter when waiting for a daemon to stop.
 | 
				
			||||||
.It Ar command_user
 | 
					.It Ar command_user
 | 
				
			||||||
If the daemon does not support changing to a different user id, you can
 | 
					If the daemon does not support changing to a different user id, you can
 | 
				
			||||||
use this to change the user id before
 | 
					use this to change the user id, and optionally group id,  before
 | 
				
			||||||
.Xr start-stop-daemon 8
 | 
					.Xr start-stop-daemon 8
 | 
				
			||||||
or
 | 
					or
 | 
				
			||||||
.Xr supervise-daemon 8
 | 
					.Xr supervise-daemon 8
 | 
				
			||||||
launches the daemon
 | 
					launches the daemon.
 | 
				
			||||||
 | 
					.It Ar output_log
 | 
				
			||||||
 | 
					This is the path to a file or named pipe where the standard output from
 | 
				
			||||||
 | 
					the service will be redirected. If you are starting this service with
 | 
				
			||||||
 | 
					.Xr start-stop-daemon 8 ,
 | 
				
			||||||
 | 
					,  you must set
 | 
				
			||||||
 | 
					.Pa command_background
 | 
				
			||||||
 | 
					to true. Keep in mind that this path will be inside the chroot if the
 | 
				
			||||||
 | 
					.Pa chroot
 | 
				
			||||||
 | 
					variable is set.
 | 
				
			||||||
 | 
					.It Ar error_log
 | 
				
			||||||
 | 
					The same thing as
 | 
				
			||||||
 | 
					.Pa output_log
 | 
				
			||||||
 | 
					but for the standard error output.
 | 
				
			||||||
 | 
					.It Ar output_logger
 | 
				
			||||||
 | 
					This is a process which will be used to log the standard output from the
 | 
				
			||||||
 | 
					service.  If you are starting this service with
 | 
				
			||||||
 | 
					.Xr start-stop-daemon 8 ,
 | 
				
			||||||
 | 
					,  you must set
 | 
				
			||||||
 | 
					.Pa command_background
 | 
				
			||||||
 | 
					to true. Keep in mind that this command must be executable as a shell
 | 
				
			||||||
 | 
					command inside the chroot if the
 | 
				
			||||||
 | 
					.Pa chroot
 | 
				
			||||||
 | 
					variable is set. Keep in mind also that this command works by accepting
 | 
				
			||||||
 | 
					the stdout of the service on stdin.
 | 
				
			||||||
 | 
					An example of a command that can be run this way is logger if you want
 | 
				
			||||||
 | 
					your service output to go to syslog.
 | 
				
			||||||
 | 
					.It Ar error_logger
 | 
				
			||||||
 | 
					The same thing as
 | 
				
			||||||
 | 
					.Pa output_logger
 | 
				
			||||||
 | 
					but for the standard error output.
 | 
				
			||||||
 | 
					.It Ar directory
 | 
				
			||||||
 | 
					.Xr start-stop-daemon 8
 | 
				
			||||||
 | 
					and
 | 
				
			||||||
 | 
					.Xr supervise-daemon 8
 | 
				
			||||||
 | 
					will chdir to this directory before starting the daemon.
 | 
				
			||||||
.It Ar chroot
 | 
					.It Ar chroot
 | 
				
			||||||
.Xr start-stop-daemon 8
 | 
					.Xr start-stop-daemon 8
 | 
				
			||||||
and
 | 
					and
 | 
				
			||||||
@@ -198,6 +239,8 @@ used along with in_background_fake to support re-entrant services.
 | 
				
			|||||||
.It Ar in_background_fake
 | 
					.It Ar in_background_fake
 | 
				
			||||||
Space separated list of commands which should always succeed when
 | 
					Space separated list of commands which should always succeed when
 | 
				
			||||||
in_background is yes.
 | 
					in_background is yes.
 | 
				
			||||||
 | 
					.It Ar umask
 | 
				
			||||||
 | 
					Set the umask of the daemon.
 | 
				
			||||||
.Pp
 | 
					.Pp
 | 
				
			||||||
Keep in mind that eval is used to process chroot, command, command_args_*,
 | 
					Keep in mind that eval is used to process chroot, command, command_args_*,
 | 
				
			||||||
command_user, pidfile and procname. This may affect how they are
 | 
					command_user, pidfile and procname. This may affect how they are
 | 
				
			||||||
@@ -447,6 +490,7 @@ Also, the -d, -f or -p options should not be specified along with this option.
 | 
				
			|||||||
.Pp
 | 
					.Pp
 | 
				
			||||||
The -q option suppresses all informational output. If it is specified
 | 
					The -q option suppresses all informational output. If it is specified
 | 
				
			||||||
twice, all error messages are suppressed as well.
 | 
					twice, all error messages are suppressed as well.
 | 
				
			||||||
 | 
					.It Xo
 | 
				
			||||||
.Ic fstabinfo
 | 
					.Ic fstabinfo
 | 
				
			||||||
.Op Fl M , -mount
 | 
					.Op Fl M , -mount
 | 
				
			||||||
.Op Fl R , -remount
 | 
					.Op Fl R , -remount
 | 
				
			||||||
@@ -463,6 +507,7 @@ remounted.
 | 
				
			|||||||
.Pp
 | 
					.Pp
 | 
				
			||||||
The -q option suppresses all informational output. If it is specified
 | 
					The -q option suppresses all informational output. If it is specified
 | 
				
			||||||
twice, all error messages are suppressed as well.
 | 
					twice, all error messages are suppressed as well.
 | 
				
			||||||
 | 
					.It Xo
 | 
				
			||||||
.Ic mountinfo
 | 
					.Ic mountinfo
 | 
				
			||||||
.Op Fl f, -fstype-regex Ar regex
 | 
					.Op Fl f, -fstype-regex Ar regex
 | 
				
			||||||
.Op Fl F, -skip-fstype-regex Ar regex
 | 
					.Op Fl F, -skip-fstype-regex Ar regex
 | 
				
			||||||
@@ -477,7 +522,7 @@ twice, all error messages are suppressed as well.
 | 
				
			|||||||
.Op Fl i, -options
 | 
					.Op Fl i, -options
 | 
				
			||||||
.Op Fl s, -fstype
 | 
					.Op Fl s, -fstype
 | 
				
			||||||
.Op Fl t, -node
 | 
					.Op Fl t, -node
 | 
				
			||||||
  .Ar mount1 mount2 ...
 | 
					.Ar mount1 mount2 ...
 | 
				
			||||||
.Xc
 | 
					.Xc
 | 
				
			||||||
The f, F, n, N, o, O, p, P, e and E options specify what you want to
 | 
					The f, F, n, N, o, O, p, P, e and E options specify what you want to
 | 
				
			||||||
search for or skip in the mounted file systems. The i, s and t options
 | 
					search for or skip in the mounted file systems. The i, s and t options
 | 
				
			||||||
@@ -569,7 +614,7 @@ rc_net_tap1_provide="!net"
 | 
				
			|||||||
# It's also possible to negate keywords. This is mainly useful for prefix
 | 
					# It's also possible to negate keywords. This is mainly useful for prefix
 | 
				
			||||||
# users testing OpenRC.
 | 
					# users testing OpenRC.
 | 
				
			||||||
rc_keyword="!-prefix"
 | 
					rc_keyword="!-prefix"
 | 
				
			||||||
# This can also be used to block a script from runining in all
 | 
					# This can also be used to block a script from running in all
 | 
				
			||||||
# containers except one or two
 | 
					# containers except one or two
 | 
				
			||||||
rc_keyword="!-containers !-docker"
 | 
					rc_keyword="!-containers !-docker"
 | 
				
			||||||
.Ed
 | 
					.Ed
 | 
				
			||||||
@@ -708,6 +753,8 @@ Users are encouraged to use the is_newer_than function which returns correctly.
 | 
				
			|||||||
.Xr rc_plugin_hook 3 ,
 | 
					.Xr rc_plugin_hook 3 ,
 | 
				
			||||||
.Xr sh 1p ,
 | 
					.Xr sh 1p ,
 | 
				
			||||||
.Xr start-stop-daemon 8 ,
 | 
					.Xr start-stop-daemon 8 ,
 | 
				
			||||||
 | 
					.Xr supervise-daemon 8 ,
 | 
				
			||||||
.Xr uname 1
 | 
					.Xr uname 1
 | 
				
			||||||
.Sh AUTHORS
 | 
					.Sh AUTHORS
 | 
				
			||||||
.An Roy Marples <roy@marples.name>
 | 
					.An Roy Marples <roy@marples.name>
 | 
				
			||||||
 | 
					.An William Hubbs <w.d.hubbs@gmail.com>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,6 +16,18 @@
 | 
				
			|||||||
.Nd locate and run an OpenRC service with the given arguments
 | 
					.Nd locate and run an OpenRC service with the given arguments
 | 
				
			||||||
.Sh SYNOPSIS
 | 
					.Sh SYNOPSIS
 | 
				
			||||||
.Nm
 | 
					.Nm
 | 
				
			||||||
 | 
					.Op Fl c , -ifcrashed
 | 
				
			||||||
 | 
					.Ar service cmd
 | 
				
			||||||
 | 
					.Op Ar ...
 | 
				
			||||||
 | 
					.Nm
 | 
				
			||||||
 | 
					.Fl d , -debug
 | 
				
			||||||
 | 
					.Ar service cmd
 | 
				
			||||||
 | 
					.Op Ar ...
 | 
				
			||||||
 | 
					.Nm
 | 
				
			||||||
 | 
					.Fl D , -nodeps
 | 
				
			||||||
 | 
					.Ar service cmd
 | 
				
			||||||
 | 
					.Op Ar ...
 | 
				
			||||||
 | 
					.Nm
 | 
				
			||||||
.Op Fl i , -ifexists
 | 
					.Op Fl i , -ifexists
 | 
				
			||||||
.Ar service cmd
 | 
					.Ar service cmd
 | 
				
			||||||
.Op Ar ...
 | 
					.Op Ar ...
 | 
				
			||||||
@@ -28,9 +40,21 @@
 | 
				
			|||||||
.Ar service cmd
 | 
					.Ar service cmd
 | 
				
			||||||
.Op Ar ...
 | 
					.Op Ar ...
 | 
				
			||||||
.Nm
 | 
					.Nm
 | 
				
			||||||
 | 
					.Op Fl s , -ifstarted
 | 
				
			||||||
 | 
					.Ar service cmd
 | 
				
			||||||
 | 
					.Op Ar ...
 | 
				
			||||||
 | 
					.Nm
 | 
				
			||||||
 | 
					.Op Fl S , -ifstopped
 | 
				
			||||||
 | 
					.Ar service cmd
 | 
				
			||||||
 | 
					.Op Ar ...
 | 
				
			||||||
 | 
					.Nm
 | 
				
			||||||
.Fl e , -exists
 | 
					.Fl e , -exists
 | 
				
			||||||
.Ar service
 | 
					.Ar service
 | 
				
			||||||
.Nm
 | 
					.Nm
 | 
				
			||||||
 | 
					.Fl Z , -dry-run
 | 
				
			||||||
 | 
					.Ar service cmd
 | 
				
			||||||
 | 
					.Op Ar ...
 | 
				
			||||||
 | 
					.Nm
 | 
				
			||||||
.Fl l , -list
 | 
					.Fl l , -list
 | 
				
			||||||
.Nm
 | 
					.Nm
 | 
				
			||||||
.Fl r , -resolve
 | 
					.Fl r , -resolve
 | 
				
			||||||
@@ -64,6 +88,15 @@ return 0 if it can find
 | 
				
			|||||||
otherwise -1.
 | 
					otherwise -1.
 | 
				
			||||||
.Fl r , -resolve
 | 
					.Fl r , -resolve
 | 
				
			||||||
does the same and also prints the full path of the service to stdout.
 | 
					does the same and also prints the full path of the service to stdout.
 | 
				
			||||||
 | 
					.Pp
 | 
				
			||||||
 | 
					.Fl d , -debug
 | 
				
			||||||
 | 
					sets -x when running the service script(s).
 | 
				
			||||||
 | 
					.Pp
 | 
				
			||||||
 | 
					.Fl D , -nodeps
 | 
				
			||||||
 | 
					ignores dependencies when running the service.
 | 
				
			||||||
 | 
					.Pp
 | 
				
			||||||
 | 
					.Fl Z , -dry-run
 | 
				
			||||||
 | 
					displays commands rather than executing them.
 | 
				
			||||||
.Sh SEE ALSO
 | 
					.Sh SEE ALSO
 | 
				
			||||||
.Xr openrc 8 ,
 | 
					.Xr openrc 8 ,
 | 
				
			||||||
.Xr stdout 3
 | 
					.Xr stdout 3
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -131,9 +131,34 @@ Modifies the scheduling priority of the daemon.
 | 
				
			|||||||
.It Fl 1 , -stdout Ar logfile
 | 
					.It Fl 1 , -stdout Ar logfile
 | 
				
			||||||
Redirect the standard output of the process to logfile when started with
 | 
					Redirect the standard output of the process to logfile when started with
 | 
				
			||||||
.Fl background .
 | 
					.Fl background .
 | 
				
			||||||
Must be an absolute pathname, but relative to the path optionally given with
 | 
					The logfile Must be an absolute pathname, but relative to the path
 | 
				
			||||||
 | 
					optionally given with
 | 
				
			||||||
.Fl r , -chroot .
 | 
					.Fl r , -chroot .
 | 
				
			||||||
The logfile can also be a named pipe.
 | 
					The logfile can also be a named pipe.
 | 
				
			||||||
 | 
					.It Fl 2 , -stderr Ar logfile
 | 
				
			||||||
 | 
					Redirect the standard error of the process to logfile when started with
 | 
				
			||||||
 | 
					.Fl background .
 | 
				
			||||||
 | 
					The 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 3 , -stdout-logger Ar cmd
 | 
				
			||||||
 | 
					Run cmd as a child process redirecting the standard output to the
 | 
				
			||||||
 | 
					standard input of cmd when started with
 | 
				
			||||||
 | 
					.Fl background .
 | 
				
			||||||
 | 
					Cmd must be an absolute pathname, but relative to the path optionally given with
 | 
				
			||||||
 | 
					.Fl r , -chroot .
 | 
				
			||||||
 | 
					This process must be prepared to accept input on stdin and be able to
 | 
				
			||||||
 | 
					log it or send it to another location.
 | 
				
			||||||
 | 
					.It Fl 4 , -stderr-logger Ar cmd
 | 
				
			||||||
 | 
					Run cmd as a child process and 
 | 
				
			||||||
 | 
					Redirect the standard error of the process to the standard input of cmd
 | 
				
			||||||
 | 
					when started with
 | 
				
			||||||
 | 
					.Fl background .
 | 
				
			||||||
 | 
					Cmd must be an absolute pathname, but relative to the path optionally given with
 | 
				
			||||||
 | 
					.Fl r , -chroot .
 | 
				
			||||||
 | 
					This process must be prepared to accept input on stdin and be able to
 | 
				
			||||||
 | 
					log it or send it to another location.
 | 
				
			||||||
.It Fl w , -wait Ar milliseconds
 | 
					.It Fl w , -wait Ar milliseconds
 | 
				
			||||||
Wait
 | 
					Wait
 | 
				
			||||||
.Ar milliseconds
 | 
					.Ar milliseconds
 | 
				
			||||||
@@ -151,6 +176,7 @@ These options are only used for stopping daemons:
 | 
				
			|||||||
.It Fl R , -retry Ar timeout | Ar signal Ns / Ns Ar timeout
 | 
					.It Fl R , -retry Ar timeout | Ar signal Ns / Ns Ar timeout
 | 
				
			||||||
The retry specification can be either a timeout in seconds or multiple
 | 
					The retry specification can be either a timeout in seconds or multiple
 | 
				
			||||||
signal/timeout pairs (like SIGTERM/5).
 | 
					signal/timeout pairs (like SIGTERM/5).
 | 
				
			||||||
 | 
					If this option is not given, the default is SIGTERM/5.
 | 
				
			||||||
.El
 | 
					.El
 | 
				
			||||||
.Sh ENVIRONMENT
 | 
					.Sh ENVIRONMENT
 | 
				
			||||||
.Va SSD_IONICELEVEL
 | 
					.Va SSD_IONICELEVEL
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -120,6 +120,7 @@ description of --respawn-max for more information.
 | 
				
			|||||||
.It Fl R , -retry Ar timeout | Ar signal Ns / Ns Ar timeout
 | 
					.It Fl R , -retry Ar timeout | Ar signal Ns / Ns Ar timeout
 | 
				
			||||||
The retry specification can be either a timeout in seconds or multiple
 | 
					The retry specification can be either a timeout in seconds or multiple
 | 
				
			||||||
signal/timeout pairs (like SIGTERM/5).
 | 
					signal/timeout pairs (like SIGTERM/5).
 | 
				
			||||||
 | 
					If this option is not given, the default is SIGTERM/5.
 | 
				
			||||||
.It Fl r , -chroot Ar path
 | 
					.It Fl r , -chroot Ar path
 | 
				
			||||||
chroot to this directory before starting the daemon. All other paths, such
 | 
					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.
 | 
					as the path to the daemon, chdir and pidfile, should be relative to the chroot.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,3 +11,5 @@
 | 
				
			|||||||
# Generic definitions
 | 
					# Generic definitions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
include ${MK}/os-BSD.mk
 | 
					include ${MK}/os-BSD.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CPPFLAGS+=	-D_BSD_SOURCE
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,6 +13,6 @@
 | 
				
			|||||||
SFX=		.GNU-kFreeBSD.in
 | 
					SFX=		.GNU-kFreeBSD.in
 | 
				
			||||||
PKG_PREFIX?=	/usr
 | 
					PKG_PREFIX?=	/usr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CPPFLAGS+=	-D_BSD_SOURCE -D_XOPEN_SOURCE=700
 | 
					CPPFLAGS+=	-D_BSD_SOURCE
 | 
				
			||||||
LIBDL=		-Wl,-Bdynamic -ldl
 | 
					LIBDL=		-Wl,-Bdynamic -ldl
 | 
				
			||||||
LIBKVM?=
 | 
					LIBKVM?=
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,5 +11,5 @@
 | 
				
			|||||||
SFX=		.GNU.in
 | 
					SFX=		.GNU.in
 | 
				
			||||||
PKG_PREFIX?=	/usr
 | 
					PKG_PREFIX?=	/usr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CPPFLAGS+=	-D_DEFAULT_SOURCE -D_XOPEN_SOURCE=700 -DMAXPATHLEN=4096 -DPATH_MAX=4096
 | 
					CPPFLAGS+=	-D_DEFAULT_SOURCE -DMAXPATHLEN=4096 -DPATH_MAX=4096
 | 
				
			||||||
LIBDL=		-Wl,-Bdynamic -ldl
 | 
					LIBDL=		-Wl,-Bdynamic -ldl
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,7 +11,7 @@
 | 
				
			|||||||
SFX=		.Linux.in
 | 
					SFX=		.Linux.in
 | 
				
			||||||
PKG_PREFIX?=	/usr
 | 
					PKG_PREFIX?=	/usr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CPPFLAGS+=	-D_DEFAULT_SOURCE -D_XOPEN_SOURCE=700
 | 
					CPPFLAGS+=	-D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200809L
 | 
				
			||||||
LIBDL=		-Wl,-Bdynamic -ldl
 | 
					LIBDL=		-Wl,-Bdynamic -ldl
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ifeq (${MKSELINUX},yes)
 | 
					ifeq (${MKSELINUX},yes)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										11
									
								
								mk/sys.mk
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								mk/sys.mk
									
									
									
									
									
								
							@@ -34,6 +34,7 @@ PICFLAG?=		-fPIC
 | 
				
			|||||||
SYSCONFDIR?=		${PREFIX}/etc
 | 
					SYSCONFDIR?=		${PREFIX}/etc
 | 
				
			||||||
INITDIR?=		${SYSCONFDIR}/init.d
 | 
					INITDIR?=		${SYSCONFDIR}/init.d
 | 
				
			||||||
CONFDIR?=		${SYSCONFDIR}/conf.d
 | 
					CONFDIR?=		${SYSCONFDIR}/conf.d
 | 
				
			||||||
 | 
					CONFMODE?=		0644
 | 
				
			||||||
LOCALDIR?=		${SYSCONFDIR}/local.d
 | 
					LOCALDIR?=		${SYSCONFDIR}/local.d
 | 
				
			||||||
SYSCTLDIR?=		${SYSCONFDIR}/sysctl.d
 | 
					SYSCTLDIR?=		${SYSCONFDIR}/sysctl.d
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -44,20 +45,22 @@ SBINDIR?=		${PREFIX}/sbin
 | 
				
			|||||||
SBINMODE?=		0755
 | 
					SBINMODE?=		0755
 | 
				
			||||||
 | 
					
 | 
				
			||||||
INCDIR?=		${UPREFIX}/include
 | 
					INCDIR?=		${UPREFIX}/include
 | 
				
			||||||
INCMODE?=		0444
 | 
					INCMODE?=		0644
 | 
				
			||||||
 | 
					
 | 
				
			||||||
_LIBNAME_SH=		case `readlink /lib` in /lib64|lib64) echo "lib64";; *) echo "lib";; esac
 | 
					_LIBNAME_SH=		case `readlink /lib` in /lib64|lib64) echo "lib64";; *) echo "lib";; esac
 | 
				
			||||||
_LIBNAME:=		$(shell ${_LIBNAME_SH})
 | 
					_LIBNAME:=		$(shell ${_LIBNAME_SH})
 | 
				
			||||||
LIBNAME?=		${_LIBNAME}
 | 
					LIBNAME?=		${_LIBNAME}
 | 
				
			||||||
LIBDIR?=		${UPREFIX}/${LIBNAME}
 | 
					LIBDIR?=		${UPREFIX}/${LIBNAME}
 | 
				
			||||||
LIBMODE?=		0444
 | 
					LIBMODE?=		0644
 | 
				
			||||||
SHLIBDIR?=		${PREFIX}/${LIBNAME}
 | 
					SHLIBDIR?=		${PREFIX}/${LIBNAME}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
LIBEXECDIR?=		${PREFIX}/libexec/rc
 | 
					LIBEXECDIR?=		${PREFIX}/libexec/rc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MANPREFIX?=		${UPREFIX}/share
 | 
					MANPREFIX?=		${UPREFIX}/share
 | 
				
			||||||
MANDIR?=		${MANPREFIX}/man
 | 
					MANDIR?=		${MANPREFIX}/man
 | 
				
			||||||
MANMODE?=		0444
 | 
					MANMODE?=		0644
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BASHCOMPDIR?=		${UPREFIX}/share/bash-completion/completions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DATADIR?=		${UPREFIX}/share/openrc
 | 
					DATADIR?=		${UPREFIX}/share/openrc
 | 
				
			||||||
DATAMODE?=		0644
 | 
					DATAMODE?=		0644
 | 
				
			||||||
@@ -65,4 +68,4 @@ DATAMODE?=		0644
 | 
				
			|||||||
DOCDIR?=		${UPREFIX}/share/doc
 | 
					DOCDIR?=		${UPREFIX}/share/doc
 | 
				
			||||||
DOCMODE?=		0644
 | 
					DOCMODE?=		0644
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CONFMODE?=		0644
 | 
					ZSHCOMPDIR?=		${UPREFIX}/share/zsh/site-functions
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
# Using runit with OpenRC
 | 
					Using runit with OpenRC
 | 
				
			||||||
 | 
					=======================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Beginning with OpenRC-0.21, we support using runit [1] in place of
 | 
					Beginning with OpenRC-0.21, we support using runit [1] in place of
 | 
				
			||||||
start-stop-daemon for monitoring and restarting daemons.
 | 
					start-stop-daemon for monitoring and restarting daemons.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -38,7 +38,7 @@ BOOT-FreeBSD+=	adjkerntz dumpon syscons
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
BOOT-Linux+=	binfmt hwclock keymaps modules mtab procfs termencoding
 | 
					BOOT-Linux+=	binfmt hwclock keymaps modules mtab procfs termencoding
 | 
				
			||||||
SHUTDOWN-Linux=	killprocs mount-ro
 | 
					SHUTDOWN-Linux=	killprocs mount-ro
 | 
				
			||||||
SYSINIT-Linux=	devfs dmesg sysfs
 | 
					SYSINIT-Linux=	devfs cgroups dmesg sysfs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Generic BSD stuff
 | 
					# Generic BSD stuff
 | 
				
			||||||
BOOT-NetBSD+=	hostid newsyslog savecore syslogd
 | 
					BOOT-NetBSD+=	hostid newsyslog savecore syslogd
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
# Using S6 with OpenRC
 | 
					Using S6 with OpenRC
 | 
				
			||||||
 | 
					====================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Beginning with OpenRC-0.16, we support using the s6 supervision suite
 | 
					Beginning with OpenRC-0.16, we support using the s6 supervision suite
 | 
				
			||||||
from Skarnet Software in place of start-stop-daemon for monitoring
 | 
					from Skarnet Software in place of start-stop-daemon for monitoring
 | 
				
			||||||
@@ -39,6 +40,10 @@ s6_service_path - the path to the s6 service directory. The default is
 | 
				
			|||||||
s6_svwait_options_start - the options to pass to s6-svwait when starting
 | 
					s6_svwait_options_start - the options to pass to s6-svwait when starting
 | 
				
			||||||
the service. If this is not set, s6-svwait will not be called.
 | 
					the service. If this is not set, s6-svwait will not be called.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					s6_force_kill - Should we try to force kill this service if the
 | 
				
			||||||
 | 
					s6_service_timeout_stop timeout expires when shutting down this service?
 | 
				
			||||||
 | 
					The default is yes.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
s6_service_timeout_stop - the amount of time, in milliseconds, s6-svc
 | 
					s6_service_timeout_stop - the amount of time, in milliseconds, s6-svc
 | 
				
			||||||
should wait for a service to go down when stopping.
 | 
					should wait for a service to go down when stopping.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										495
									
								
								service-script-guide.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										495
									
								
								service-script-guide.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,495 @@
 | 
				
			|||||||
 | 
					OpenRC Service Script Writing Guide
 | 
				
			||||||
 | 
					===================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This document is aimed at developers or packagers who
 | 
				
			||||||
 | 
					write OpenRC service scripts, either for their own projects, or for
 | 
				
			||||||
 | 
					the packages they maintain. It contains advice, suggestions, tips,
 | 
				
			||||||
 | 
					tricks, hints, and counsel; cautions, warnings, heads-ups,
 | 
				
			||||||
 | 
					admonitions, proscriptions, enjoinders, and reprimands.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It is intended to prevent common mistakes that are found "in the wild"
 | 
				
			||||||
 | 
					by pointing out those mistakes and suggesting alternatives.  Each
 | 
				
			||||||
 | 
					good/bad thing that you should/not do has a section devoted to it. We
 | 
				
			||||||
 | 
					don't consider anything exotic, and assume that you will use
 | 
				
			||||||
 | 
					start-stop-daemon to manage a fairly typical long-running UNIX
 | 
				
			||||||
 | 
					process.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 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 service scripts 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 and should be used unless you have a very strong reason not to
 | 
				
			||||||
 | 
					use them.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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 `lib/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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Don't write your own start/stop functions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					OpenRC is capable of stopping and starting most daemons based on the
 | 
				
			||||||
 | 
					information that you give it. For a well-behaved daemon that
 | 
				
			||||||
 | 
					backgrounds itself and writes its own PID file by default, the
 | 
				
			||||||
 | 
					following OpenRC variables are likely all that you'll need:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * command
 | 
				
			||||||
 | 
					  * command_args
 | 
				
			||||||
 | 
					  * pidfile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Given those three pieces of information, OpenRC will be able to start
 | 
				
			||||||
 | 
					and stop the daemon on its own. The following is taken from an
 | 
				
			||||||
 | 
					[OpenNTPD](http://www.openntpd.org/) service script:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```sh
 | 
				
			||||||
 | 
					command="/usr/sbin/ntpd"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# The special RC_SVCNAME variable contains the name of this service.
 | 
				
			||||||
 | 
					pidfile="/run/${RC_SVCNAME}.pid"
 | 
				
			||||||
 | 
					command_args="-p ${pidfile}"
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If the daemon runs in the foreground by default but has options to
 | 
				
			||||||
 | 
					background itself and to create a pidfile, then you'll also need
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * command_args_background
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					That variable should contain the flags needed to background your
 | 
				
			||||||
 | 
					daemon, and to make it write a PID file. Take for example the
 | 
				
			||||||
 | 
					following snippet of an
 | 
				
			||||||
 | 
					[NRPE](https://github.com/NagiosEnterprises/nrpe) service script:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```sh
 | 
				
			||||||
 | 
					command="/usr/bin/nrpe"
 | 
				
			||||||
 | 
					command_args="--config=/etc/nagios/nrpe.cfg"
 | 
				
			||||||
 | 
					command_args_background="--daemon"
 | 
				
			||||||
 | 
					pidfile="/run/${RC_SVCNAME}.pid"
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Since NRPE runs as *root* by default, it needs no special permissions
 | 
				
			||||||
 | 
					to write to `/run/nrpe.pid`. OpenRC takes care of starting and
 | 
				
			||||||
 | 
					stopping the daemon with the appropriate arguments, even passing the
 | 
				
			||||||
 | 
					`--daemon` flag during startup to force NRPE into the background (NRPE
 | 
				
			||||||
 | 
					knows how to write its own PID file).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					But what if the daemon isn't so well behaved? What if it doesn't know
 | 
				
			||||||
 | 
					how to background itself or create a pidfile? If it can do neither,
 | 
				
			||||||
 | 
					then use,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * command_background=true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					which will additionally pass `--make-pidfile` to start-stop-daemon,
 | 
				
			||||||
 | 
					causing it to create the `$pidfile` for you (rather than the daemon
 | 
				
			||||||
 | 
					itself being responsible for creating the PID file).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If your daemon doesn't know how to change its own user or group, then
 | 
				
			||||||
 | 
					you can tell start-stop-daemon to launch it as an unprivileged user
 | 
				
			||||||
 | 
					with
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * command_user="user:group"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Finally, if your daemon always forks into the background but fails to
 | 
				
			||||||
 | 
					create a PID file, then your only option is to use
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * procname
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					With `procname`, OpenRC will try to find the running daemon by
 | 
				
			||||||
 | 
					matching the name of its process. That's not so reliable, but daemons
 | 
				
			||||||
 | 
					shouldn't background themselves without creating a PID file in the
 | 
				
			||||||
 | 
					first place. The next example is part of the [CA NetConsole
 | 
				
			||||||
 | 
					Daemon](https://oss.oracle.com/projects/cancd/) service script:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```sh
 | 
				
			||||||
 | 
					command="/usr/sbin/cancd"
 | 
				
			||||||
 | 
					command_args="-p ${CANCD_PORT}
 | 
				
			||||||
 | 
					              -l ${CANCD_LOG_DIR}
 | 
				
			||||||
 | 
					              -o ${CANCD_LOG_FORMAT}"
 | 
				
			||||||
 | 
					command_user="cancd"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# cancd daemonizes itself, but doesn't write a PID file and doesn't
 | 
				
			||||||
 | 
					# have an option to run in the foreground. So, the best we can do
 | 
				
			||||||
 | 
					# is try to match the process name when stopping it.
 | 
				
			||||||
 | 
					procname="cancd"
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To recap, in order of preference:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  1. If the daemon backgrounds itself and creates its own PID file, use
 | 
				
			||||||
 | 
					     `pidfile`.
 | 
				
			||||||
 | 
					  2. If the daemon does not background itself (or has an option to run
 | 
				
			||||||
 | 
					     in the foreground) and does not create a PID file, then use
 | 
				
			||||||
 | 
					     `command_background=true` and `pidfile`.
 | 
				
			||||||
 | 
					  3. If the daemon backgrounds itself and does not create a PID file,
 | 
				
			||||||
 | 
					     use `procname` instead of `pidfile`. But, if your daemon has the
 | 
				
			||||||
 | 
					     option to run in the foreground, then you should do that instead
 | 
				
			||||||
 | 
					     (that would be the case in the previous item).
 | 
				
			||||||
 | 
					  4. The last case, where the daemon does not background itself but
 | 
				
			||||||
 | 
					     does create a PID file, doesn't make much sense. If there's a way
 | 
				
			||||||
 | 
					     to disable the daemon's PID file (or, to write it straight into the
 | 
				
			||||||
 | 
					     garbage), then do that, and use `command_background=true`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Reloading your daemon's configuration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Many daemons will reload their configuration files in response to a
 | 
				
			||||||
 | 
					signal. Suppose your daemon will reload its configuration in response
 | 
				
			||||||
 | 
					to a `SIGHUP`. It's possible to add a new "reload" command to your
 | 
				
			||||||
 | 
					service script that performs this action. First, tell the service
 | 
				
			||||||
 | 
					script about the new command.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```sh
 | 
				
			||||||
 | 
					extra_started_commands="reload"
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					We use `extra_started_commands` as opposed to `extra_commands` because
 | 
				
			||||||
 | 
					the "reload" action is only valid while the daemon is running (that
 | 
				
			||||||
 | 
					is, started). Now, start-stop-daemon can be used to send the signal to
 | 
				
			||||||
 | 
					the appropriate process (assuming you've defined the `pidfile`
 | 
				
			||||||
 | 
					variable elsewhere):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```sh
 | 
				
			||||||
 | 
					reload() {
 | 
				
			||||||
 | 
					  ebegin "Reloading ${RC_SVCNAME}"
 | 
				
			||||||
 | 
					  start-stop-daemon --signal HUP --pidfile "${pidfile}"
 | 
				
			||||||
 | 
					  eend $?
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Don't restart/reload with a broken config
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Often, users will start a daemon, make some configuration change, and
 | 
				
			||||||
 | 
					then attempt to restart the daemon. If the recent configuration change
 | 
				
			||||||
 | 
					contains a mistake, the result will be that the daemon is stopped but
 | 
				
			||||||
 | 
					then cannot be started again (due to the configuration error). It's
 | 
				
			||||||
 | 
					possible to prevent that situation with a function that checks for
 | 
				
			||||||
 | 
					configuration errors, and a combination of the `start_pre` and
 | 
				
			||||||
 | 
					`stop_pre` hooks.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```sh
 | 
				
			||||||
 | 
					checkconfig() {
 | 
				
			||||||
 | 
					  # However you want to check this...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					start_pre() {
 | 
				
			||||||
 | 
					  # If this isn't a restart, make sure that the user's config isn't
 | 
				
			||||||
 | 
					  # busted before we try to start the daemon (this will produce
 | 
				
			||||||
 | 
					  # better error messages than if we just try to start it blindly).
 | 
				
			||||||
 | 
					  #
 | 
				
			||||||
 | 
					  # If, on the other hand, this *is* a restart, then the stop_pre
 | 
				
			||||||
 | 
					  # action will have ensured that the config is usable and we don't
 | 
				
			||||||
 | 
					  # need to do that again.
 | 
				
			||||||
 | 
					  if [ "${RC_CMD}" != "restart" ] ; then
 | 
				
			||||||
 | 
					    checkconfig || return $?
 | 
				
			||||||
 | 
					  fi
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					stop_pre() {
 | 
				
			||||||
 | 
					  # If this is a restart, check to make sure the user's config
 | 
				
			||||||
 | 
					  # isn't busted before we stop the running daemon.
 | 
				
			||||||
 | 
					  if [ "${RC_CMD}" = "restart" ] ; then
 | 
				
			||||||
 | 
					      checkconfig || return $?
 | 
				
			||||||
 | 
					  fi
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To prevent a *reload* with a broken config, keep it simple:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```sh
 | 
				
			||||||
 | 
					reload() {
 | 
				
			||||||
 | 
					  checkconfig || return $?
 | 
				
			||||||
 | 
					  ebegin "Reloading ${RC_SVCNAME}"
 | 
				
			||||||
 | 
					  start-stop-daemon --signal HUP --pidfile "${pidfile}"
 | 
				
			||||||
 | 
					  eend $?
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## PID files should be writable only by root
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PID files must be writable only by *root*, which means additionally
 | 
				
			||||||
 | 
					that they must live in a *root*-owned directory. This directory is
 | 
				
			||||||
 | 
					normally /run under Linux and /var/run under other operating systems.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Some daemons run as an unprivileged user account, and create their PID
 | 
				
			||||||
 | 
					files (as the unprivileged user) in a path like
 | 
				
			||||||
 | 
					`/var/run/foo/foo.pid`. That can usually be exploited by the unprivileged
 | 
				
			||||||
 | 
					user to kill *root* processes, since when a service is stopped, *root*
 | 
				
			||||||
 | 
					usually sends a SIGTERM to the contents of the PID file (which are
 | 
				
			||||||
 | 
					controlled by the unprivileged user). The main warning sign for that
 | 
				
			||||||
 | 
					problem is using `checkpath` to set ownership on the directory
 | 
				
			||||||
 | 
					containing the PID file. For example,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```sh
 | 
				
			||||||
 | 
					# BAD BAD BAD BAD BAD BAD BAD BAD
 | 
				
			||||||
 | 
					start_pre() {
 | 
				
			||||||
 | 
					  # Ensure that the pidfile directory is writable by the foo user/group.
 | 
				
			||||||
 | 
					  checkpath --directory --mode 0700 --owner foo:foo "/var/run/foo"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					# BAD BAD BAD BAD BAD BAD BAD BAD
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If the *foo* user owns `/var/run/foo`, then he can put whatever he wants
 | 
				
			||||||
 | 
					in the `/var/run/foo/foo.pid` file. Even if *root* owns the PID file, the
 | 
				
			||||||
 | 
					*foo* user can delete it and replace it with his own. To avoid
 | 
				
			||||||
 | 
					security concerns, the PID file must be created as *root* and live in
 | 
				
			||||||
 | 
					a *root*-owned directory. If your daemon is responsible for forking
 | 
				
			||||||
 | 
					and writing its own PID file but the PID file is still owned by the
 | 
				
			||||||
 | 
					unprivileged runtime user, then you may have an upstream issue.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Once the PID file is being created as *root* (before dropping
 | 
				
			||||||
 | 
					privileges), it can be written directly to a *root*-owned
 | 
				
			||||||
 | 
					directory.  For example, the *foo* daemon might write
 | 
				
			||||||
 | 
					`/var/run/foo.pid`. No calls to checkpath are needed. Note: there is
 | 
				
			||||||
 | 
					nothing technically wrong with using a directory structure like
 | 
				
			||||||
 | 
					`/var/run/foo/foo.pid`, so long as *root* owns the PID file and the
 | 
				
			||||||
 | 
					directory containing it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Ideally (see "Upstream your service scripts"), your service script
 | 
				
			||||||
 | 
					will be integrated upstream and the build system will determine the
 | 
				
			||||||
 | 
					appropriate directory for the pid file. For example,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```sh
 | 
				
			||||||
 | 
					pidfile="@piddir@/${RC_SVCNAME}.pid"
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A decent example of this is the [Nagios core service
 | 
				
			||||||
 | 
					script](https://github.com/NagiosEnterprises/nagioscore/blob/master/openrc-init.in),
 | 
				
			||||||
 | 
					where the full path to the PID file is specified at build-time.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Don't let the user control the PID file location
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It's usually a mistake to let the end user control the PID file
 | 
				
			||||||
 | 
					location through a conf.d variable, for a few reasons:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  1. When the PID file path is controlled by the user, you need to
 | 
				
			||||||
 | 
					     ensure that its parent directory exists and is writable. This
 | 
				
			||||||
 | 
					     adds unnecessary code to the service script.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  2. If the PID file path changes while the service is running, then
 | 
				
			||||||
 | 
					     you'll find yourself unable to stop the service.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  3. The directory that should contain the PID file is best determined
 | 
				
			||||||
 | 
					     by the upstream build system (see "Upstream your service scripts").
 | 
				
			||||||
 | 
					     On Linux, the preferred location these days is `/run`. Other systems
 | 
				
			||||||
 | 
					     still use `/var/run`, though, and a `./configure` script is the
 | 
				
			||||||
 | 
					     best place to decide which one you want.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  4. Nobody cares where the PID file is located, anyway.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Since OpenRC service names must be unique, a value of
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```sh
 | 
				
			||||||
 | 
					pidfile="/var/run/${RC_SVCNAME}.pid"
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					guarantees that your PID file has a unique name.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Upstream your service scripts (for packagers)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The ideal place for an OpenRC service script is **upstream**. Much like
 | 
				
			||||||
 | 
					systemd services, a well-crafted OpenRC service script should be
 | 
				
			||||||
 | 
					distribution-agnostic, and the best place for it is upstream. Why? For
 | 
				
			||||||
 | 
					two reasons. First, having it upstream means that there's a single
 | 
				
			||||||
 | 
					authoritative source for improvements. Second, a few paths in every
 | 
				
			||||||
 | 
					service script are dependent upon flags passed to the build system. For
 | 
				
			||||||
 | 
					example,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```sh
 | 
				
			||||||
 | 
					command=/usr/bin/foo
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					in an autotools-based build system should really be
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```sh
 | 
				
			||||||
 | 
					command=@bindir@/foo
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					so that the user's value of `--bindir` is respected. If you keep the
 | 
				
			||||||
 | 
					service script in your own distribution's repository, then you have to
 | 
				
			||||||
 | 
					keep the command path and package synchronized yourself, and that's no
 | 
				
			||||||
 | 
					fun.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Be wary of "need net" dependencies
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					There are two things you need to know about "need net" dependencies:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  1. They are not satisfied by the loopback interface, so "need net"
 | 
				
			||||||
 | 
					     requires some *other* interface to be up.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  2. Depending on the value of `rc_depend_strict` in `rc.conf`, the
 | 
				
			||||||
 | 
					     "need net" will be satisfied when either *any* non-loopback
 | 
				
			||||||
 | 
					     interface is up, or when *all* non-loopback interfaces are up.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The first item means that "need net" is wrong for daemons that are
 | 
				
			||||||
 | 
					happy with `0.0.0.0`, and the second point means that "need net" is
 | 
				
			||||||
 | 
					wrong for daemons that need a particular (for example, the WAN)
 | 
				
			||||||
 | 
					interface. We'll consider the two most common users of "need net";
 | 
				
			||||||
 | 
					network clients who access some network resource, and network servers
 | 
				
			||||||
 | 
					who provide them.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Network clients
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Network clients typically want the WAN interface to be up. That may
 | 
				
			||||||
 | 
					tempt you to depend on the WAN interface; but first, you should ask
 | 
				
			||||||
 | 
					yourself a question: does anything bad happen if the WAN interface is
 | 
				
			||||||
 | 
					not available? In other words, if the administrator wants to disable
 | 
				
			||||||
 | 
					the WAN, should the service be stopped? Usually the answer to that
 | 
				
			||||||
 | 
					question is "no," and in that case, you should forego the "net"
 | 
				
			||||||
 | 
					dependency entirely.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Suppose, for example, that your service retrieves virus signature
 | 
				
			||||||
 | 
					updates from the internet. In order to do its job correctly, it needs
 | 
				
			||||||
 | 
					a (working) internet connection. However, the service itself does not
 | 
				
			||||||
 | 
					require the WAN interface to be up: if it is, great; otherwise, the
 | 
				
			||||||
 | 
					worst that will happen is that a "server unavailable" warning will be
 | 
				
			||||||
 | 
					logged. The signature update service will not crash, and—perhaps more
 | 
				
			||||||
 | 
					importantly—you don't want it to terminate if the administrator turns
 | 
				
			||||||
 | 
					off the WAN interface for a second.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Network servers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Network servers are generally easier to handle than their client
 | 
				
			||||||
 | 
					counterparts. Most server daemons listen on `0.0.0.0` (all addresses)
 | 
				
			||||||
 | 
					by default, and are therefore satisfied to have the loopback interface
 | 
				
			||||||
 | 
					present and operational. OpenRC ships with the loopback service in the
 | 
				
			||||||
 | 
					*boot* runlevel, and therefore most server daemons require no further
 | 
				
			||||||
 | 
					network dependencies.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The exceptions to this rule are those daemons who produce negative
 | 
				
			||||||
 | 
					side-effects when the WAN is unavailable. For example, the Nagios
 | 
				
			||||||
 | 
					server daemon will generate "the sky is falling" alerts for as long as
 | 
				
			||||||
 | 
					your monitored hosts are unreachable. So in that case, you should
 | 
				
			||||||
 | 
					require some other interface (often the WAN) to be up. A "need"
 | 
				
			||||||
 | 
					dependency would be appropriate, because you want Nagios to be
 | 
				
			||||||
 | 
					stopped before the network is taken down.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If your daemon can optionally be configured to listen on a particular
 | 
				
			||||||
 | 
					interface, then please see the "Depending on a particular interface"
 | 
				
			||||||
 | 
					section.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Depending on a particular interface
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you need to depend on one particular interface, usually it's not
 | 
				
			||||||
 | 
					easy to determine programmatically what that interface is. For
 | 
				
			||||||
 | 
					example, if your *sshd* daemon listens on `192.168.1.100` (rather than
 | 
				
			||||||
 | 
					`0.0.0.0`), then you have two problems:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  1. Parsing `sshd_config` to figure that out; and
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  2. Determining which network service name corresponds to the
 | 
				
			||||||
 | 
					     interface for `192.168.1.100`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It's generally a bad idea to parse config files in your service
 | 
				
			||||||
 | 
					scripts, but the second problem is the harder one. Instead, the most
 | 
				
			||||||
 | 
					robust (i.e. the laziest) approach is to make the user specify the
 | 
				
			||||||
 | 
					dependency when he makes a change to sshd_config. Include something
 | 
				
			||||||
 | 
					like the following in the service configuration file,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```sh
 | 
				
			||||||
 | 
					# Specify the network service that corresponds to the "bind" setting
 | 
				
			||||||
 | 
					# in your configuration file. For example, if you bind to 127.0.0.1,
 | 
				
			||||||
 | 
					# this should be set to "loopback" which provides the loopback interface.
 | 
				
			||||||
 | 
					rc_need="loopback"
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This is a sensible default for daemons that are happy with `0.0.0.0`,
 | 
				
			||||||
 | 
					but lets the user specify something else, like `rc_need="net.wan"` if
 | 
				
			||||||
 | 
					he needs it. The burden is on the user to determine the appropriate
 | 
				
			||||||
 | 
					service whenever he changes the daemon's configuration file.
 | 
				
			||||||
@@ -33,6 +33,9 @@ else
 | 
				
			|||||||
	kmode="-a"
 | 
						kmode="-a"
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Set the SELinux label on console before everything so we dont lose output
 | 
				
			||||||
 | 
					[ -x /sbin/restorecon ] && /sbin/restorecon -F /dev/console
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Try and set a font and as early as we can
 | 
					# Try and set a font and as early as we can
 | 
				
			||||||
if service_present "$RC_DEFAULTLEVEL" consolefont ||
 | 
					if service_present "$RC_DEFAULTLEVEL" consolefont ||
 | 
				
			||||||
   service_present "$RC_BOOTLEVEL" consolefont; then
 | 
					   service_present "$RC_BOOTLEVEL" consolefont; then
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -83,6 +83,7 @@ elif ! mountinfo -q /run; then
 | 
				
			|||||||
	fi
 | 
						fi
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[ -x /sbin/restorecon ] && /sbin/restorecon -rF /run
 | 
				
			||||||
checkpath -d $RC_SVCDIR
 | 
					checkpath -d $RC_SVCDIR
 | 
				
			||||||
checkpath -d -m 0775 -o root:uucp /run/lock
 | 
					checkpath -d -m 0775 -o root:uucp /run/lock
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -133,11 +133,10 @@ _status()
 | 
				
			|||||||
	elif service_inactive; then
 | 
						elif service_inactive; then
 | 
				
			||||||
		ewarn "status: inactive"
 | 
							ewarn "status: inactive"
 | 
				
			||||||
		return 16
 | 
							return 16
 | 
				
			||||||
 | 
						elif service_crashed; then
 | 
				
			||||||
 | 
							eerror "status: crashed"
 | 
				
			||||||
 | 
							return 32
 | 
				
			||||||
	elif service_started; then
 | 
						elif service_started; then
 | 
				
			||||||
		if service_crashed; then
 | 
					 | 
				
			||||||
			eerror "status: crashed"
 | 
					 | 
				
			||||||
			return 32
 | 
					 | 
				
			||||||
		fi
 | 
					 | 
				
			||||||
		einfo "status: started"
 | 
							einfo "status: started"
 | 
				
			||||||
		return 0
 | 
							return 0
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
@@ -260,12 +259,14 @@ for _cmd; do
 | 
				
			|||||||
		# Apply cgroups settings if defined
 | 
							# Apply cgroups settings if defined
 | 
				
			||||||
		if [ "$(command -v cgroup_add_service)" = "cgroup_add_service" ]
 | 
							if [ "$(command -v cgroup_add_service)" = "cgroup_add_service" ]
 | 
				
			||||||
		then
 | 
							then
 | 
				
			||||||
			if [ -d /sys/fs/cgroup -a ! -w /sys/fs/cgroup ]; then
 | 
								if grep -qs /sys/fs/cgroup /proc/1/mountinfo
 | 
				
			||||||
				eerror "No permission to apply cgroup settings"
 | 
								then
 | 
				
			||||||
				break
 | 
									if [ -d /sys/fs/cgroup -a ! -w /sys/fs/cgroup ]; then
 | 
				
			||||||
 | 
										eerror "No permission to apply cgroup settings"
 | 
				
			||||||
 | 
										break
 | 
				
			||||||
 | 
									fi
 | 
				
			||||||
			fi
 | 
								fi
 | 
				
			||||||
			cgroup_add_service /sys/fs/cgroup/openrc
 | 
								cgroup_add_service
 | 
				
			||||||
			cgroup_add_service /sys/fs/cgroup/systemd/system
 | 
					 | 
				
			||||||
		fi
 | 
							fi
 | 
				
			||||||
		[ "$(command -v cgroup_set_limits)" = "cgroup_set_limits" ] &&
 | 
							[ "$(command -v cgroup_set_limits)" = "cgroup_set_limits" ] &&
 | 
				
			||||||
			cgroup_set_limits
 | 
								cgroup_set_limits
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -184,18 +184,17 @@ cgroup2_set_limits()
 | 
				
			|||||||
	cgroup_path="$(cgroup2_find_path)"
 | 
						cgroup_path="$(cgroup2_find_path)"
 | 
				
			||||||
	[ -d "${cgroup_path}" ] || return 0
 | 
						[ -d "${cgroup_path}" ] || return 0
 | 
				
			||||||
	rc_cgroup_path="${cgroup_path}/${RC_SVCNAME}"
 | 
						rc_cgroup_path="${cgroup_path}/${RC_SVCNAME}"
 | 
				
			||||||
	local OIFS="$IFS"
 | 
					 | 
				
			||||||
	IFS="
 | 
					 | 
				
			||||||
"
 | 
					 | 
				
			||||||
	[ ! -d "${rc_cgroup_path}" ] && mkdir "${rc_cgroup_path}"
 | 
						[ ! -d "${rc_cgroup_path}" ] && mkdir "${rc_cgroup_path}"
 | 
				
			||||||
	printf "%d" 0 > "${rc_cgroup_path}/cgroup.procs"
 | 
						[ -f "${rc_cgroup_path}"/cgroup.procs ] &&
 | 
				
			||||||
	echo "${rc_cgroup_settings}" | while IFS="$OIFS" read -r key value; do
 | 
							printf 0 > "${rc_cgroup_path}"/cgroup.procs
 | 
				
			||||||
		[ -z "${key}" ] || [ -z "${value}" ] && continue
 | 
						[ -z "${rc_cgroup_settings}" ] && return 0
 | 
				
			||||||
		[ ! -e "${rc_cgroup_path}/${key}" ] && continue
 | 
						echo "${rc_cgroup_settings}" | while read -r key value; do
 | 
				
			||||||
		veinfo "${RC_SVCNAME}: cgroups: ${key} ${value}"
 | 
							[ -z "${key}" ] && continue
 | 
				
			||||||
		printf "%s" "${value}" > "${rc_cgroup_path}/${key}"
 | 
							[ -z "${value}" ] && continue
 | 
				
			||||||
 | 
							[ ! -f "${rc_cgroup_path}/${key}" ] && continue
 | 
				
			||||||
 | 
							veinfo "${RC_SVCNAME}: cgroups: setting ${key} to ${value}"
 | 
				
			||||||
 | 
							printf "%s\n" "${value}" > "${rc_cgroup_path}/${key}"
 | 
				
			||||||
	done
 | 
						done
 | 
				
			||||||
	IFS="$OIFS"
 | 
					 | 
				
			||||||
	return 0
 | 
						return 0
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -203,15 +202,21 @@ cgroup_cleanup()
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	cgroup_running || return 0
 | 
						cgroup_running || return 0
 | 
				
			||||||
	ebegin "starting cgroups cleanup"
 | 
						ebegin "starting cgroups cleanup"
 | 
				
			||||||
	local pids
 | 
						local pids loops=0
 | 
				
			||||||
	pids="$(cgroup_get_pids)"
 | 
						pids="$(cgroup_get_pids)"
 | 
				
			||||||
	if [ -n "${pids}" ]; then
 | 
						if [ -n "${pids}" ]; then
 | 
				
			||||||
		kill -s "${stopsig:-TERM}" ${pids} 2> /dev/null
 | 
					 | 
				
			||||||
		kill -s CONT ${pids} 2> /dev/null
 | 
							kill -s CONT ${pids} 2> /dev/null
 | 
				
			||||||
 | 
							kill -s "${stopsig:-TERM}" ${pids} 2> /dev/null
 | 
				
			||||||
		yesno "${rc_send_sighup:-no}" &&
 | 
							yesno "${rc_send_sighup:-no}" &&
 | 
				
			||||||
			kill -s HUP ${pids} 2> /dev/null
 | 
								kill -s HUP ${pids} 2> /dev/null
 | 
				
			||||||
		sleep "${rc_timeout_stopsec:-90}"
 | 
							kill -s "${stopsig:-TERM}" ${pids} 2> /dev/null
 | 
				
			||||||
		yesno "${rc_send_sigkill:-yes}" &&
 | 
							while [ -n "$(cgroup_get_pids)" ] &&
 | 
				
			||||||
 | 
								[ "${loops}" -lt "${rc_timeout_stopsec:-90}" ]; do
 | 
				
			||||||
 | 
								loops=$((loops+1))
 | 
				
			||||||
 | 
								sleep 1
 | 
				
			||||||
 | 
							done
 | 
				
			||||||
 | 
							pids="$(cgroup_get_pids)"
 | 
				
			||||||
 | 
							[ -n "${pids}" ] && yesno "${rc_send_sigkill:-yes}" &&
 | 
				
			||||||
			kill -s KILL ${pids} 2> /dev/null
 | 
								kill -s KILL ${pids} 2> /dev/null
 | 
				
			||||||
	fi
 | 
						fi
 | 
				
			||||||
	cgroup2_remove
 | 
						cgroup2_remove
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										20
									
								
								sh/s6.sh
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								sh/s6.sh
									
									
									
									
									
								
							@@ -12,6 +12,20 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[ -z "${s6_service_path}" ] && s6_service_path="/var/svc.d/${RC_SVCNAME}"
 | 
					[ -z "${s6_service_path}" ] && s6_service_path="/var/svc.d/${RC_SVCNAME}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_s6_force_kill() {
 | 
				
			||||||
 | 
						local pid
 | 
				
			||||||
 | 
						s6_service_link="${RC_SVCDIR}/s6-scan/${s6_service_path##*/}"
 | 
				
			||||||
 | 
						pid="${3%)}"
 | 
				
			||||||
 | 
						[ -z "${pid}" ] && return 0
 | 
				
			||||||
 | 
						if kill -0 "${pid}" 2> /dev/null; then
 | 
				
			||||||
 | 
							ewarn "Sending DOWN & KILL for ${RC_SVCNAME}"
 | 
				
			||||||
 | 
							s6-svc -dk "${s6_service_link}"
 | 
				
			||||||
 | 
							sleep 1
 | 
				
			||||||
 | 
							kill -0 "${pid}" 2>/dev/null && return 1
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
s6_start()
 | 
					s6_start()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if [ ! -d "${s6_service_path}" ]; then
 | 
						if [ ! -d "${s6_service_path}" ]; then
 | 
				
			||||||
@@ -41,7 +55,11 @@ s6_stop()
 | 
				
			|||||||
 fi
 | 
					 fi
 | 
				
			||||||
	s6_service_link="${RC_SVCDIR}/s6-scan/${s6_service_path##*/}"
 | 
						s6_service_link="${RC_SVCDIR}/s6-scan/${s6_service_path##*/}"
 | 
				
			||||||
	ebegin "Stopping ${name:-$RC_SVCNAME}"
 | 
						ebegin "Stopping ${name:-$RC_SVCNAME}"
 | 
				
			||||||
	s6-svc -wD -d -T ${s6_service_timeout_stop:-10000} "${s6_service_link}"
 | 
						s6-svc -d -wD -T ${s6_service_timeout_stop:-60000} "${s6_service_link}"
 | 
				
			||||||
 | 
						set -- $(s6-svstat "${s6_service_link}")
 | 
				
			||||||
 | 
						[ "$1" = "up" ] && 
 | 
				
			||||||
 | 
							yesno "${s6_force_kill:-yes}" &&
 | 
				
			||||||
 | 
								_s6_force_kill "$@"
 | 
				
			||||||
	set -- $(s6-svstat "${s6_service_link}")
 | 
						set -- $(s6-svstat "${s6_service_link}")
 | 
				
			||||||
	[ "$1" = "down" ]
 | 
						[ "$1" = "down" ]
 | 
				
			||||||
	eend $? "Failed to stop ${name:-$RC_SVCNAME}"
 | 
						eend $? "Failed to stop ${name:-$RC_SVCNAME}"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -38,15 +38,25 @@ ssd_start()
 | 
				
			|||||||
		service_inactive && _inactive=true
 | 
							service_inactive && _inactive=true
 | 
				
			||||||
		mark_service_inactive
 | 
							mark_service_inactive
 | 
				
			||||||
	fi
 | 
						fi
 | 
				
			||||||
 | 
						[ -n "$output_logger" ] && 
 | 
				
			||||||
 | 
							output_logger_arg="--stdout-logger \"$output_logger\""
 | 
				
			||||||
 | 
						[ -n "$error_logger" ] && 
 | 
				
			||||||
 | 
							error_logger_arg="--stderr-logger \"$error_logger\""
 | 
				
			||||||
	#the eval call is necessary for cases like:
 | 
						#the eval call is necessary for cases like:
 | 
				
			||||||
	# command_args="this \"is a\" test"
 | 
						# command_args="this \"is a\" test"
 | 
				
			||||||
	# to work properly.
 | 
						# to work properly.
 | 
				
			||||||
	eval start-stop-daemon --start \
 | 
						eval start-stop-daemon --start \
 | 
				
			||||||
		--exec $command \
 | 
							--exec $command \
 | 
				
			||||||
		${chroot:+--chroot} $chroot \
 | 
							${chroot:+--chroot} $chroot \
 | 
				
			||||||
 | 
							${directory:+--chdir} $directory \
 | 
				
			||||||
 | 
							${output_log+--stdout} $output_log \
 | 
				
			||||||
 | 
							${error_log+--stderr} $error_log \
 | 
				
			||||||
 | 
							${output_logger_arg} \
 | 
				
			||||||
 | 
							${error_logger_arg} \
 | 
				
			||||||
		${procname:+--name} $procname \
 | 
							${procname:+--name} $procname \
 | 
				
			||||||
		${pidfile:+--pidfile} $pidfile \
 | 
							${pidfile:+--pidfile} $pidfile \
 | 
				
			||||||
		${command_user+--user} $command_user \
 | 
							${command_user+--user} $command_user \
 | 
				
			||||||
 | 
							${umask+--umask} $umask \
 | 
				
			||||||
		$_background $start_stop_daemon_args \
 | 
							$_background $start_stop_daemon_args \
 | 
				
			||||||
		-- $command_args $command_args_background
 | 
							-- $command_args $command_args_background
 | 
				
			||||||
	if eend $? "Failed to start ${name:-$RC_SVCNAME}"; then
 | 
						if eend $? "Failed to start ${name:-$RC_SVCNAME}"; then
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,15 +22,19 @@ supervise_start()
 | 
				
			|||||||
	# The eval call is necessary for cases like:
 | 
						# The eval call is necessary for cases like:
 | 
				
			||||||
	# command_args="this \"is a\" test"
 | 
						# command_args="this \"is a\" test"
 | 
				
			||||||
	# to work properly.
 | 
						# to work properly.
 | 
				
			||||||
	eval supervise-daemon --start \
 | 
						eval supervise-daemon "${RC_SVCNAME}" --start \
 | 
				
			||||||
		${retry:+--retry} $retry \
 | 
							${retry:+--retry} $retry \
 | 
				
			||||||
 | 
							${directory:+--chdir} $directory  \
 | 
				
			||||||
		${chroot:+--chroot} $chroot \
 | 
							${chroot:+--chroot} $chroot \
 | 
				
			||||||
 | 
							${output_log+--stdout} ${output_log} \
 | 
				
			||||||
 | 
							${error_log+--stderr} $error_log \
 | 
				
			||||||
		${pidfile:+--pidfile} $pidfile \
 | 
							${pidfile:+--pidfile} $pidfile \
 | 
				
			||||||
		${respawn_delay:+--respawn-delay} $respawn_delay \
 | 
							${respawn_delay:+--respawn-delay} $respawn_delay \
 | 
				
			||||||
		${respawn_max:+--respawn-max} $respawn_max \
 | 
							${respawn_max:+--respawn-max} $respawn_max \
 | 
				
			||||||
		${respawn_period:+--respawn-period} $respawn_period \
 | 
							${respawn_period:+--respawn-period} $respawn_period \
 | 
				
			||||||
		${command_user+--user} $command_user \
 | 
							${command_user+--user} $command_user \
 | 
				
			||||||
		$supervise_daemon_args \
 | 
							${umask+--umask} $umask \
 | 
				
			||||||
 | 
							${supervise_daemon_args:-${start_stop_daemon_args}} \
 | 
				
			||||||
		$command \
 | 
							$command \
 | 
				
			||||||
		-- $command_args $command_args_foreground
 | 
							-- $command_args $command_args_foreground
 | 
				
			||||||
	rc=$?
 | 
						rc=$?
 | 
				
			||||||
@@ -49,14 +53,48 @@ supervise_stop()
 | 
				
			|||||||
	pidfile="${startpidfile:-$pidfile}"
 | 
						pidfile="${startpidfile:-$pidfile}"
 | 
				
			||||||
	[ -n "$pidfile" ] || return 0
 | 
						[ -n "$pidfile" ] || return 0
 | 
				
			||||||
	ebegin "Stopping ${name:-$RC_SVCNAME}"
 | 
						ebegin "Stopping ${name:-$RC_SVCNAME}"
 | 
				
			||||||
	supervise-daemon --stop \
 | 
						supervise-daemon "${RC_SVCNAME}" --stop \
 | 
				
			||||||
		${pidfile:+--pidfile} $chroot$pidfile \
 | 
							${pidfile:+--pidfile} $chroot$pidfile \
 | 
				
			||||||
		${stopsig:+--signal} $stopsig
 | 
							${stopsig:+--signal} $stopsig
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	eend $? "Failed to stop ${name:-$RC_SVCNAME}"
 | 
						eend $? "Failed to stop ${name:-$RC_SVCNAME}"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_check_supervised()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						local child_pid start_time
 | 
				
			||||||
 | 
						child_pid="$(service_get_value "child_pid")"
 | 
				
			||||||
 | 
						start_time="$(service_get_value "start_time")"
 | 
				
			||||||
 | 
						if [ -n "${child_pid}" ] && [ -n "${start_time}" ]; then
 | 
				
			||||||
 | 
							return 1
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
supervise_status()
 | 
					supervise_status()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	_status
 | 
						if service_stopping; then
 | 
				
			||||||
 | 
							ewarn "status: stopping"
 | 
				
			||||||
 | 
							return 4
 | 
				
			||||||
 | 
						elif service_starting; then
 | 
				
			||||||
 | 
							ewarn "status: starting"
 | 
				
			||||||
 | 
							return 8
 | 
				
			||||||
 | 
						elif service_inactive; then
 | 
				
			||||||
 | 
							ewarn "status: inactive"
 | 
				
			||||||
 | 
							return 16
 | 
				
			||||||
 | 
						elif service_started; then
 | 
				
			||||||
 | 
							if service_crashed; then
 | 
				
			||||||
 | 
								if ! _check_supervised; then
 | 
				
			||||||
 | 
									eerror "status: unsupervised"
 | 
				
			||||||
 | 
									return 64
 | 
				
			||||||
 | 
								fi
 | 
				
			||||||
 | 
								eerror "status: crashed"
 | 
				
			||||||
 | 
								return 32
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
							einfo "status: started"
 | 
				
			||||||
 | 
							return 0
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							einfo "status: stopped"
 | 
				
			||||||
 | 
							return 3
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,9 +28,11 @@
 | 
				
			|||||||
#if __GNUC__ > 2 || defined(__INTEL_COMPILER)
 | 
					#if __GNUC__ > 2 || defined(__INTEL_COMPILER)
 | 
				
			||||||
# define _dead __attribute__((__noreturn__))
 | 
					# define _dead __attribute__((__noreturn__))
 | 
				
			||||||
# define _unused __attribute__((__unused__))
 | 
					# define _unused __attribute__((__unused__))
 | 
				
			||||||
 | 
					# define _xasprintf(a, b)  __attribute__((__format__(__printf__, a, b)))
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
# define _dead
 | 
					# define _dead
 | 
				
			||||||
# define _unused
 | 
					# define _unused
 | 
				
			||||||
 | 
					# define _xasprintf(a, b)
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
 | 
					#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
 | 
				
			||||||
@@ -53,6 +55,7 @@
 | 
				
			|||||||
	} while (/* CONSTCOND */ 0)
 | 
						} while (/* CONSTCOND */ 0)
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdarg.h>
 | 
				
			||||||
#include <stdbool.h>
 | 
					#include <stdbool.h>
 | 
				
			||||||
#include <sys/stat.h>
 | 
					#include <sys/stat.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -96,8 +99,10 @@ _unused static char *xstrdup(const char *str)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#undef ERRX
 | 
					#undef ERRX
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* basename_c never modifies the argument. As such, if there is a trailing
 | 
					/*
 | 
				
			||||||
 * slash then an empty string is returned. */
 | 
					 * basename_c never modifies the argument. As such, if there is a trailing
 | 
				
			||||||
 | 
					 * slash then an empty string is returned.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
_unused static const char *basename_c(const char *path)
 | 
					_unused static const char *basename_c(const char *path)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const char *slash = strrchr(path, '/');
 | 
						const char *slash = strrchr(path, '/');
 | 
				
			||||||
@@ -121,4 +126,49 @@ _unused static bool existss(const char *pathname)
 | 
				
			|||||||
	return (stat(pathname, &buf) == 0 && buf.st_size != 0);
 | 
						return (stat(pathname, &buf) == 0 && buf.st_size != 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * This is an OpenRC specific version of the asprintf() function.
 | 
				
			||||||
 | 
					 * We do this to avoid defining the _GNU_SOURCE feature test macro on
 | 
				
			||||||
 | 
					 * glibc systems and to insure that we have a consistent function across
 | 
				
			||||||
 | 
					 * platforms. This also allows us to call our xmalloc and xrealloc
 | 
				
			||||||
 | 
					 * functions to handle memory allocation.
 | 
				
			||||||
 | 
					 * this function was originally written by Mike Frysinger.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					_unused _xasprintf(2,3) static int xasprintf(char **strp, const char *fmt, ...)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						va_list ap;
 | 
				
			||||||
 | 
						int len;
 | 
				
			||||||
 | 
						int memlen;
 | 
				
			||||||
 | 
						char *ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Start with a buffer size that should cover the vast majority of uses
 | 
				
			||||||
 | 
						 * (path construction).
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						memlen = 4096;
 | 
				
			||||||
 | 
						ret = xmalloc(memlen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						va_start(ap, fmt);
 | 
				
			||||||
 | 
						len = vsnprintf(ret, memlen, fmt, ap);
 | 
				
			||||||
 | 
						va_end(ap);
 | 
				
			||||||
 | 
						if (len >= memlen) {
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * Output was truncated, so increase buffer to exactly what we need.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							memlen = len + 1;
 | 
				
			||||||
 | 
							ret = xrealloc(ret, memlen);
 | 
				
			||||||
 | 
							va_start(ap, fmt);
 | 
				
			||||||
 | 
							len = vsnprintf(ret, len + 1, fmt, ap);
 | 
				
			||||||
 | 
							va_end(ap);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (len < 0 || len >= memlen) {
 | 
				
			||||||
 | 
							/* Give up! */
 | 
				
			||||||
 | 
							fprintf(stderr, "xasprintf: unable to format a buffer\n");
 | 
				
			||||||
 | 
							free(ret);
 | 
				
			||||||
 | 
							exit(1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						*strp = ret;
 | 
				
			||||||
 | 
						return len;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -47,6 +47,7 @@ bool rc_conf_yesno(const char *var);
 | 
				
			|||||||
void env_filter(void);
 | 
					void env_filter(void);
 | 
				
			||||||
void env_config(void);
 | 
					void env_config(void);
 | 
				
			||||||
int signal_setup(int sig, void (*handler)(int));
 | 
					int signal_setup(int sig, void (*handler)(int));
 | 
				
			||||||
 | 
					int signal_setup_restart(int sig, void (*handler)(int));
 | 
				
			||||||
int svc_lock(const char *);
 | 
					int svc_lock(const char *);
 | 
				
			||||||
int svc_unlock(const char *, int);
 | 
					int svc_unlock(const char *, int);
 | 
				
			||||||
pid_t exec_service(const char *, const char *);
 | 
					pid_t exec_service(const char *, const char *);
 | 
				
			||||||
@@ -65,9 +66,6 @@ int parse_mode(mode_t *, char *);
 | 
				
			|||||||
/* Handy function so we can wrap einfo around our deptree */
 | 
					/* Handy function so we can wrap einfo around our deptree */
 | 
				
			||||||
RC_DEPTREE *_rc_deptree_load (int, int *);
 | 
					RC_DEPTREE *_rc_deptree_load (int, int *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Test to see if we can see pid 1 or not */
 | 
					 | 
				
			||||||
bool _rc_can_find_pids(void);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
RC_SERVICE lookup_service_state(const char *service);
 | 
					RC_SERVICE lookup_service_state(const char *service);
 | 
				
			||||||
void from_time_t(char *time_string, time_t tv);
 | 
					void from_time_t(char *time_string, time_t tv);
 | 
				
			||||||
time_t to_time_t(char *timestring);
 | 
					time_t to_time_t(char *timestring);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -80,9 +80,12 @@ rc_find_pids(const char *exec, const char *const *argv, uid_t uid, pid_t pid)
 | 
				
			|||||||
	DIR *procdir;
 | 
						DIR *procdir;
 | 
				
			||||||
	struct dirent *entry;
 | 
						struct dirent *entry;
 | 
				
			||||||
	FILE *fp;
 | 
						FILE *fp;
 | 
				
			||||||
 | 
						int rc;
 | 
				
			||||||
	bool container_pid = false;
 | 
						bool container_pid = false;
 | 
				
			||||||
	bool openvz_host = false;
 | 
						bool openvz_host = false;
 | 
				
			||||||
	char *line = NULL;
 | 
						char *line = NULL;
 | 
				
			||||||
 | 
						char my_ns[30];
 | 
				
			||||||
 | 
						char proc_ns[30];
 | 
				
			||||||
	size_t len = 0;
 | 
						size_t len = 0;
 | 
				
			||||||
	pid_t p;
 | 
						pid_t p;
 | 
				
			||||||
	char buffer[PATH_MAX];
 | 
						char buffer[PATH_MAX];
 | 
				
			||||||
@@ -131,6 +134,14 @@ rc_find_pids(const char *exec, const char *const *argv, uid_t uid, pid_t pid)
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memset(my_ns, 0, sizeof(my_ns));
 | 
				
			||||||
 | 
						memset(proc_ns, 0, sizeof(proc_ns));
 | 
				
			||||||
 | 
						if (exists("/proc/self/ns/pid")) {
 | 
				
			||||||
 | 
							rc = readlink("/proc/self/ns/pid", my_ns, sizeof(my_ns));
 | 
				
			||||||
 | 
							if (rc <= 0)
 | 
				
			||||||
 | 
								my_ns[0] = '\0';
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while ((entry = readdir(procdir)) != NULL) {
 | 
						while ((entry = readdir(procdir)) != NULL) {
 | 
				
			||||||
		if (sscanf(entry->d_name, "%d", &p) != 1)
 | 
							if (sscanf(entry->d_name, "%d", &p) != 1)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
@@ -138,6 +149,14 @@ rc_find_pids(const char *exec, const char *const *argv, uid_t uid, pid_t pid)
 | 
				
			|||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		if (pid != 0 && pid != p)
 | 
							if (pid != 0 && pid != p)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
							snprintf(buffer, sizeof(buffer), "/proc/%d/ns/pid", p);
 | 
				
			||||||
 | 
							if (exists(buffer)) {
 | 
				
			||||||
 | 
								rc = readlink(buffer, proc_ns, sizeof(proc_ns));
 | 
				
			||||||
 | 
								if (rc <= 0)
 | 
				
			||||||
 | 
									proc_ns[0] = '\0';
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (strlen(my_ns) && strlen (proc_ns) && strcmp(my_ns, proc_ns))
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
		if (uid) {
 | 
							if (uid) {
 | 
				
			||||||
			snprintf(buffer, sizeof(buffer), "/proc/%d", p);
 | 
								snprintf(buffer, sizeof(buffer), "/proc/%d", p);
 | 
				
			||||||
			if (stat(buffer, &sb) != 0 || sb.st_uid != uid)
 | 
								if (stat(buffer, &sb) != 0 || sb.st_uid != uid)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -542,52 +542,41 @@ rc_deptree_order(const RC_DEPTREE *deptree, const char *runlevel, int options)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
librc_hidden_def(rc_deptree_order)
 | 
					librc_hidden_def(rc_deptree_order)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Given a time, recurse the target path to find out if there are
 | 
				
			||||||
 | 
					   any older (or newer) files.   If false, sets the time to the
 | 
				
			||||||
 | 
					   oldest (or newest) found.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
static bool
 | 
					static bool
 | 
				
			||||||
mtime_check(const char *source, const char *target, bool newer,
 | 
					deep_mtime_check(const char *target, bool newer,
 | 
				
			||||||
	    time_t *rel, char *file)
 | 
						    time_t *rel, char *file)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct stat buf;
 | 
						struct stat buf;
 | 
				
			||||||
	time_t mtime;
 | 
					 | 
				
			||||||
	bool retval = true;
 | 
						bool retval = true;
 | 
				
			||||||
	DIR *dp;
 | 
						DIR *dp;
 | 
				
			||||||
	struct dirent *d;
 | 
						struct dirent *d;
 | 
				
			||||||
	char path[PATH_MAX];
 | 
						char path[PATH_MAX];
 | 
				
			||||||
	int serrno = errno;
 | 
						int serrno = errno;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* We have to exist */
 | 
					 | 
				
			||||||
	if (stat(source, &buf) != 0)
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
	mtime = buf.st_mtime;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* If target does not exist, return true to mimic shell test */
 | 
						/* If target does not exist, return true to mimic shell test */
 | 
				
			||||||
	if (stat(target, &buf) != 0)
 | 
						if (stat(target, &buf) != 0)
 | 
				
			||||||
		return true;
 | 
							return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (newer) {
 | 
						if (newer) {
 | 
				
			||||||
		if (mtime < buf.st_mtime) {
 | 
							if (*rel < buf.st_mtime) {
 | 
				
			||||||
			if (rel == NULL)
 | 
					 | 
				
			||||||
				return false;
 | 
					 | 
				
			||||||
			retval = false;
 | 
								retval = false;
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
		if (rel != NULL) {
 | 
								if (file)
 | 
				
			||||||
			if (*rel < buf.st_mtime) {
 | 
									strlcpy(file, target, PATH_MAX);
 | 
				
			||||||
				if (file)
 | 
								*rel = buf.st_mtime;
 | 
				
			||||||
					strlcpy(file, target, PATH_MAX);
 | 
					 | 
				
			||||||
				*rel = buf.st_mtime;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		if (mtime > buf.st_mtime) {
 | 
							if (*rel > buf.st_mtime) {
 | 
				
			||||||
			if (rel == NULL)
 | 
					 | 
				
			||||||
				return false;
 | 
					 | 
				
			||||||
			retval = false;
 | 
								retval = false;
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
		if (rel != NULL) {
 | 
								if (file)
 | 
				
			||||||
			if (*rel > buf.st_mtime) {
 | 
									strlcpy(file, target, PATH_MAX);
 | 
				
			||||||
				if (file)
 | 
								*rel = buf.st_mtime;
 | 
				
			||||||
					strlcpy(file, target, PATH_MAX);
 | 
					 | 
				
			||||||
				*rel = buf.st_mtime;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -602,16 +591,38 @@ mtime_check(const char *source, const char *target, bool newer,
 | 
				
			|||||||
		if (d->d_name[0] == '.')
 | 
							if (d->d_name[0] == '.')
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		snprintf(path, sizeof(path), "%s/%s", target, d->d_name);
 | 
							snprintf(path, sizeof(path), "%s/%s", target, d->d_name);
 | 
				
			||||||
		if (!mtime_check(source, path, newer, rel, file)) {
 | 
							if (!deep_mtime_check(path, newer, rel, file)) {
 | 
				
			||||||
			retval = false;
 | 
								retval = false;
 | 
				
			||||||
			if (rel == NULL)
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	closedir(dp);
 | 
						closedir(dp);
 | 
				
			||||||
	return retval;
 | 
						return retval;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Recursively check if target is older/newer than source.
 | 
				
			||||||
 | 
					 * If false, return the filename and most different time (if
 | 
				
			||||||
 | 
					 * the return value arguments are non-null).
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static bool
 | 
				
			||||||
 | 
					mtime_check(const char *source, const char *target, bool newer,
 | 
				
			||||||
 | 
						    time_t *rel, char *file)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct stat buf;
 | 
				
			||||||
 | 
						time_t mtime;
 | 
				
			||||||
 | 
						bool retval = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* We have to exist */
 | 
				
			||||||
 | 
						if (stat(source, &buf) != 0)
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						mtime = buf.st_mtime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    retval = deep_mtime_check(target,newer,&mtime,file);
 | 
				
			||||||
 | 
					    if (rel) {
 | 
				
			||||||
 | 
					        *rel = mtime;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return retval;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool
 | 
					bool
 | 
				
			||||||
rc_newer_than(const char *source, const char *target,
 | 
					rc_newer_than(const char *source, const char *target,
 | 
				
			||||||
	      time_t *newest, char *file)
 | 
						      time_t *newest, char *file)
 | 
				
			||||||
@@ -670,6 +681,8 @@ rc_deptree_update_needed(time_t *newest, char *file)
 | 
				
			|||||||
	RC_STRINGLIST *config;
 | 
						RC_STRINGLIST *config;
 | 
				
			||||||
	RC_STRING *s;
 | 
						RC_STRING *s;
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
 | 
						struct stat buf;
 | 
				
			||||||
 | 
						time_t mtime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Create base directories if needed */
 | 
						/* Create base directories if needed */
 | 
				
			||||||
	for (i = 0; depdirs[i]; i++)
 | 
						for (i = 0; depdirs[i]; i++)
 | 
				
			||||||
@@ -677,42 +690,48 @@ rc_deptree_update_needed(time_t *newest, char *file)
 | 
				
			|||||||
			fprintf(stderr, "mkdir `%s': %s\n", depdirs[i], strerror(errno));
 | 
								fprintf(stderr, "mkdir `%s': %s\n", depdirs[i], strerror(errno));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Quick test to see if anything we use has changed and we have
 | 
						/* Quick test to see if anything we use has changed and we have
 | 
				
			||||||
	 * data in our deptree */
 | 
						 * data in our deptree. */
 | 
				
			||||||
	if (!existss(RC_DEPTREE_CACHE))
 | 
					
 | 
				
			||||||
		return true;
 | 
						if (stat(RC_DEPTREE_CACHE, &buf) == 0) {
 | 
				
			||||||
	if (!rc_newer_than(RC_DEPTREE_CACHE, RC_INITDIR, newest, file))
 | 
							mtime = buf.st_mtime;
 | 
				
			||||||
		return true;
 | 
						} else {
 | 
				
			||||||
	if (!rc_newer_than(RC_DEPTREE_CACHE, RC_CONFDIR, newest, file))
 | 
							/* No previous cache found.
 | 
				
			||||||
		return true;
 | 
							 * We still run the scan, in case of clock skew; we still need to return
 | 
				
			||||||
 | 
							 * the newest time.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							newer = true;
 | 
				
			||||||
 | 
							mtime = time(NULL);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						newer |= !deep_mtime_check(RC_INITDIR,true,&mtime,file);
 | 
				
			||||||
 | 
						newer |= !deep_mtime_check(RC_CONFDIR,true,&mtime,file);
 | 
				
			||||||
#ifdef RC_PKG_INITDIR
 | 
					#ifdef RC_PKG_INITDIR
 | 
				
			||||||
	if (!rc_newer_than(RC_DEPTREE_CACHE, RC_PKG_INITDIR, newest, file))
 | 
					    newer |= !deep_mtime_check(RC_PKG_INITDIR,true,&mtime,file);
 | 
				
			||||||
		return true;
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef RC_PKG_CONFDIR
 | 
					#ifdef RC_PKG_CONFDIR
 | 
				
			||||||
	if (!rc_newer_than(RC_DEPTREE_CACHE, RC_PKG_CONFDIR, newest, file))
 | 
					    newer |= !deep_mtime_check(RC_PKG_CONFDIR,true,&mtime,file);
 | 
				
			||||||
		return true;
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef RC_LOCAL_INITDIR
 | 
					#ifdef RC_LOCAL_INITDIRs
 | 
				
			||||||
	if (!rc_newer_than(RC_DEPTREE_CACHE, RC_LOCAL_INITDIR, newest, file))
 | 
					    newer |= !deep_mtime_check(RC_LOCAL_INITDIR,true,&mtime,file);
 | 
				
			||||||
		return true;
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef RC_LOCAL_CONFDIR
 | 
					#ifdef RC_LOCAL_CONFDIR
 | 
				
			||||||
	if (!rc_newer_than(RC_DEPTREE_CACHE, RC_LOCAL_CONFDIR, newest, file))
 | 
					    newer |= !deep_mtime_check(RC_LOCAL_CONFDIR,true,&mtime,file);
 | 
				
			||||||
		return true;
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
	if (!rc_newer_than(RC_DEPTREE_CACHE, RC_CONF, newest, file))
 | 
					    newer |= !deep_mtime_check(RC_CONF,true,&mtime,file);
 | 
				
			||||||
		return true;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Some init scripts dependencies change depending on config files
 | 
						/* Some init scripts dependencies change depending on config files
 | 
				
			||||||
	 * outside of baselayout, like syslog-ng, so we check those too. */
 | 
						 * outside of baselayout, like syslog-ng, so we check those too. */
 | 
				
			||||||
	config = rc_config_list(RC_DEPCONFIG);
 | 
						config = rc_config_list(RC_DEPCONFIG);
 | 
				
			||||||
	TAILQ_FOREACH(s, config, entries) {
 | 
						TAILQ_FOREACH(s, config, entries) {
 | 
				
			||||||
		if (!rc_newer_than(RC_DEPTREE_CACHE, s->value, newest, file)) {
 | 
							newer |= !deep_mtime_check(s->value, true, &mtime, file);
 | 
				
			||||||
			newer = true;
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	rc_stringlist_free(config);
 | 
						rc_stringlist_free(config);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Return newest file time, if requested */
 | 
				
			||||||
 | 
						if ((newer) && (newest != NULL)) {
 | 
				
			||||||
 | 
						    *newest = mtime;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return newer;
 | 
						return newer;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
librc_hidden_def(rc_deptree_update_needed)
 | 
					librc_hidden_def(rc_deptree_update_needed)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -50,6 +50,7 @@ static const rc_service_state_name_t rc_service_state_names[] = {
 | 
				
			|||||||
	{ RC_SERVICE_HOTPLUGGED,  "hotplugged" },
 | 
						{ RC_SERVICE_HOTPLUGGED,  "hotplugged" },
 | 
				
			||||||
	{ RC_SERVICE_FAILED,      "failed" },
 | 
						{ RC_SERVICE_FAILED,      "failed" },
 | 
				
			||||||
	{ RC_SERVICE_SCHEDULED,   "scheduled"},
 | 
						{ RC_SERVICE_SCHEDULED,   "scheduled"},
 | 
				
			||||||
 | 
						{ RC_SERVICE_CRASHED,     "crashed"},
 | 
				
			||||||
	{ 0, NULL}
 | 
						{ 0, NULL}
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -848,6 +849,10 @@ rc_service_state(const char *service)
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (state & RC_SERVICE_STARTED) {
 | 
				
			||||||
 | 
							if (rc_service_daemons_crashed(service))
 | 
				
			||||||
 | 
								state |= RC_SERVICE_CRASHED;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if (state & RC_SERVICE_STOPPED) {
 | 
						if (state & RC_SERVICE_STOPPED) {
 | 
				
			||||||
		dirs = ls_dir(RC_SVCDIR "/scheduled", 0);
 | 
							dirs = ls_dir(RC_SVCDIR "/scheduled", 0);
 | 
				
			||||||
		TAILQ_FOREACH(dir, dirs, entries) {
 | 
							TAILQ_FOREACH(dir, dirs, entries) {
 | 
				
			||||||
@@ -894,12 +899,15 @@ rc_service_value_set(const char *service, const char *option,
 | 
				
			|||||||
		return false;
 | 
							return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	snprintf(p, sizeof(file) - (p - file), "/%s", option);
 | 
						snprintf(p, sizeof(file) - (p - file), "/%s", option);
 | 
				
			||||||
	if (!(fp = fopen(file, "w")))
 | 
						if (value) {
 | 
				
			||||||
		return false;
 | 
							if (!(fp = fopen(file, "w")))
 | 
				
			||||||
	if (value)
 | 
								return false;
 | 
				
			||||||
		fprintf(fp, "%s", value);
 | 
							fprintf(fp, "%s", value);
 | 
				
			||||||
	fclose(fp);
 | 
							fclose(fp);
 | 
				
			||||||
	return true;
 | 
						} else {
 | 
				
			||||||
 | 
							unlink(file);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
librc_hidden_def(rc_service_value_set)
 | 
					librc_hidden_def(rc_service_value_set)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -188,7 +188,8 @@ typedef enum
 | 
				
			|||||||
	/* Optional states service could also be in */
 | 
						/* Optional states service could also be in */
 | 
				
			||||||
	RC_SERVICE_FAILED      = 0x0200,
 | 
						RC_SERVICE_FAILED      = 0x0200,
 | 
				
			||||||
	RC_SERVICE_SCHEDULED   = 0x0400,
 | 
						RC_SERVICE_SCHEDULED   = 0x0400,
 | 
				
			||||||
	RC_SERVICE_WASINACTIVE = 0x0800
 | 
						RC_SERVICE_WASINACTIVE = 0x0800,
 | 
				
			||||||
 | 
						RC_SERVICE_CRASHED     = 0x1000,
 | 
				
			||||||
} RC_SERVICE;
 | 
					} RC_SERVICE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*! Add the service to the runlevel
 | 
					/*! Add the service to the runlevel
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								src/rc/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								src/rc/.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -56,6 +56,7 @@ mark_service_inactive
 | 
				
			|||||||
mark_service_wasinactive
 | 
					mark_service_wasinactive
 | 
				
			||||||
mark_service_hotplugged
 | 
					mark_service_hotplugged
 | 
				
			||||||
mark_service_failed
 | 
					mark_service_failed
 | 
				
			||||||
 | 
					mark_service_crashed
 | 
				
			||||||
rc-abort
 | 
					rc-abort
 | 
				
			||||||
rc
 | 
					rc
 | 
				
			||||||
openrc
 | 
					openrc
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,8 +5,8 @@ include ${MK}/os.mk
 | 
				
			|||||||
SRCS=	checkpath.c do_e.c do_mark_service.c do_service.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 \
 | 
							do_value.c fstabinfo.c is_newer_than.c is_older_than.c \
 | 
				
			||||||
		mountinfo.c openrc-run.c rc-abort.c rc.c \
 | 
							mountinfo.c openrc-run.c rc-abort.c rc.c \
 | 
				
			||||||
		rc-depend.c rc-logger.c rc-misc.c rc-plugin.c \
 | 
							rc-depend.c rc-logger.c rc-misc.c rc-pipes.c \
 | 
				
			||||||
		rc-service.c rc-status.c rc-update.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
 | 
							shell_var.c start-stop-daemon.c supervise-daemon.c swclock.c _usage.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ifeq (${MKSELINUX},yes)
 | 
					ifeq (${MKSELINUX},yes)
 | 
				
			||||||
@@ -41,6 +41,7 @@ RC_SBINPROGS=	mark_service_starting mark_service_started \
 | 
				
			|||||||
		mark_service_stopping mark_service_stopped \
 | 
							mark_service_stopping mark_service_stopped \
 | 
				
			||||||
		mark_service_inactive mark_service_wasinactive \
 | 
							mark_service_inactive mark_service_wasinactive \
 | 
				
			||||||
		mark_service_hotplugged mark_service_failed \
 | 
							mark_service_hotplugged mark_service_failed \
 | 
				
			||||||
 | 
							mark_service_crashed \
 | 
				
			||||||
		rc-abort swclock
 | 
							rc-abort swclock
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ifeq (${OS},Linux)
 | 
					ifeq (${OS},Linux)
 | 
				
			||||||
@@ -123,7 +124,8 @@ is_older_than: is_older_than.o rc-misc.o
 | 
				
			|||||||
mark_service_starting mark_service_started \
 | 
					mark_service_starting mark_service_started \
 | 
				
			||||||
mark_service_stopping mark_service_stopped \
 | 
					mark_service_stopping mark_service_stopped \
 | 
				
			||||||
mark_service_inactive mark_service_wasinactive \
 | 
					mark_service_inactive mark_service_wasinactive \
 | 
				
			||||||
mark_service_hotplugged mark_service_failed: do_mark_service.o rc-misc.o
 | 
					mark_service_hotplugged mark_service_failed \
 | 
				
			||||||
 | 
					mark_service_crashed: do_mark_service.o rc-misc.o
 | 
				
			||||||
	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
 | 
						${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mountinfo: mountinfo.o _usage.o rc-misc.o
 | 
					mountinfo: mountinfo.o _usage.o rc-misc.o
 | 
				
			||||||
@@ -156,7 +158,7 @@ rc-service: rc-service.o _usage.o rc-misc.o
 | 
				
			|||||||
rc-update: rc-update.o _usage.o rc-misc.o
 | 
					rc-update: rc-update.o _usage.o rc-misc.o
 | 
				
			||||||
	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
 | 
						${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
start-stop-daemon: start-stop-daemon.o _usage.o rc-misc.o rc-schedules.o
 | 
					start-stop-daemon: start-stop-daemon.o _usage.o rc-misc.o rc-pipes.o rc-schedules.o
 | 
				
			||||||
	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
 | 
						${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
supervise-daemon: supervise-daemon.o _usage.o rc-misc.o rc-schedules.o
 | 
					supervise-daemon: supervise-daemon.o _usage.o rc-misc.o rc-schedules.o
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -73,25 +73,32 @@ static int do_check(char *path, uid_t uid, gid_t gid, mode_t mode,
 | 
				
			|||||||
	inode_t type, bool trunc, bool chowner, bool selinux_on)
 | 
						inode_t type, bool trunc, bool chowner, bool selinux_on)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct stat st;
 | 
						struct stat st;
 | 
				
			||||||
	int fd, flags;
 | 
						int fd;
 | 
				
			||||||
 | 
						int flags;
 | 
				
			||||||
	int r;
 | 
						int r;
 | 
				
			||||||
 | 
						int readfd;
 | 
				
			||||||
 | 
						int readflags;
 | 
				
			||||||
	int u;
 | 
						int u;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memset(&st, 0, sizeof(st));
 | 
						memset(&st, 0, sizeof(st));
 | 
				
			||||||
	if (lstat(path, &st) || trunc) {
 | 
						flags = O_CREAT|O_NDELAY|O_WRONLY|O_NOCTTY;
 | 
				
			||||||
 | 
						readflags = O_NDELAY|O_NOCTTY|O_RDONLY;
 | 
				
			||||||
 | 
					#ifdef O_CLOEXEC
 | 
				
			||||||
 | 
						flags |= O_CLOEXEC;
 | 
				
			||||||
 | 
						readflags |= O_CLOEXEC;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef O_NOFOLLOW
 | 
				
			||||||
 | 
						flags |= O_NOFOLLOW;
 | 
				
			||||||
 | 
						readflags |= O_NOFOLLOW;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						if (trunc)
 | 
				
			||||||
 | 
							flags |= O_TRUNC;
 | 
				
			||||||
 | 
						readfd = open(path, readflags);
 | 
				
			||||||
 | 
						if (readfd == -1 || (type == inode_file && trunc)) {
 | 
				
			||||||
		if (type == inode_file) {
 | 
							if (type == inode_file) {
 | 
				
			||||||
			einfo("%s: creating file", path);
 | 
								einfo("%s: creating file", path);
 | 
				
			||||||
			if (!mode) /* 664 */
 | 
								if (!mode) /* 664 */
 | 
				
			||||||
				mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
 | 
									mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
 | 
				
			||||||
			flags = O_CREAT|O_NDELAY|O_WRONLY|O_NOCTTY;
 | 
					 | 
				
			||||||
#ifdef O_CLOEXEC
 | 
					 | 
				
			||||||
			flags |= O_CLOEXEC;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#ifdef O_NOFOLLOW
 | 
					 | 
				
			||||||
			flags |= O_NOFOLLOW;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
			if (trunc)
 | 
					 | 
				
			||||||
				flags |= O_TRUNC;
 | 
					 | 
				
			||||||
			u = umask(0);
 | 
								u = umask(0);
 | 
				
			||||||
			fd = open(path, flags, mode);
 | 
								fd = open(path, flags, mode);
 | 
				
			||||||
			umask(u);
 | 
								umask(u);
 | 
				
			||||||
@@ -99,7 +106,9 @@ static int do_check(char *path, uid_t uid, gid_t gid, mode_t mode,
 | 
				
			|||||||
				eerror("%s: open: %s", applet, strerror(errno));
 | 
									eerror("%s: open: %s", applet, strerror(errno));
 | 
				
			||||||
				return -1;
 | 
									return -1;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			close (fd);
 | 
								if (readfd != -1 && trunc)
 | 
				
			||||||
 | 
									close(readfd);
 | 
				
			||||||
 | 
								readfd = fd;
 | 
				
			||||||
		} else if (type == inode_dir) {
 | 
							} else if (type == inode_dir) {
 | 
				
			||||||
			einfo("%s: creating directory", path);
 | 
								einfo("%s: creating directory", path);
 | 
				
			||||||
			if (!mode) /* 775 */
 | 
								if (!mode) /* 775 */
 | 
				
			||||||
@@ -113,7 +122,12 @@ static int do_check(char *path, uid_t uid, gid_t gid, mode_t mode,
 | 
				
			|||||||
				    strerror (errno));
 | 
									    strerror (errno));
 | 
				
			||||||
				return -1;
 | 
									return -1;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			mode = 0;
 | 
								readfd = open(path, readflags);
 | 
				
			||||||
 | 
								if (readfd == -1) {
 | 
				
			||||||
 | 
									eerror("%s: unable to open directory: %s", applet,
 | 
				
			||||||
 | 
											strerror(errno));
 | 
				
			||||||
 | 
									return -1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		} else if (type == inode_fifo) {
 | 
							} else if (type == inode_fifo) {
 | 
				
			||||||
			einfo("%s: creating fifo", path);
 | 
								einfo("%s: creating fifo", path);
 | 
				
			||||||
			if (!mode) /* 600 */
 | 
								if (!mode) /* 600 */
 | 
				
			||||||
@@ -126,56 +140,76 @@ static int do_check(char *path, uid_t uid, gid_t gid, mode_t mode,
 | 
				
			|||||||
				    strerror (errno));
 | 
									    strerror (errno));
 | 
				
			||||||
				return -1;
 | 
									return -1;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								readfd = open(path, readflags);
 | 
				
			||||||
 | 
								if (readfd == -1) {
 | 
				
			||||||
 | 
									eerror("%s: unable to open fifo: %s", applet,
 | 
				
			||||||
 | 
											strerror(errno));
 | 
				
			||||||
 | 
									return -1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						}
 | 
				
			||||||
 | 
						if (fstat(readfd, &st) != -1) {
 | 
				
			||||||
		if (type != inode_dir && S_ISDIR(st.st_mode)) {
 | 
							if (type != inode_dir && S_ISDIR(st.st_mode)) {
 | 
				
			||||||
			eerror("%s: is a directory", path);
 | 
								eerror("%s: is a directory", path);
 | 
				
			||||||
 | 
								close(readfd);
 | 
				
			||||||
			return 1;
 | 
								return 1;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (type != inode_file && S_ISREG(st.st_mode)) {
 | 
							if (type != inode_file && S_ISREG(st.st_mode)) {
 | 
				
			||||||
			eerror("%s: is a file", path);
 | 
								eerror("%s: is a file", path);
 | 
				
			||||||
 | 
								close(readfd);
 | 
				
			||||||
			return 1;
 | 
								return 1;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (type != inode_fifo && S_ISFIFO(st.st_mode)) {
 | 
							if (type != inode_fifo && S_ISFIFO(st.st_mode)) {
 | 
				
			||||||
			eerror("%s: is a fifo", path);
 | 
								eerror("%s: is a fifo", path);
 | 
				
			||||||
 | 
								close(readfd);
 | 
				
			||||||
			return -1;
 | 
								return -1;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (mode && (st.st_mode & 0777) != mode) {
 | 
							if (mode && (st.st_mode & 0777) != mode) {
 | 
				
			||||||
		if ((type != inode_dir) && (st.st_nlink > 1)) {
 | 
								if ((type != inode_dir) && (st.st_nlink > 1)) {
 | 
				
			||||||
			eerror("%s: chmod: %s %s", applet, "Too many hard links to", path);
 | 
									eerror("%s: chmod: %s %s", applet, "Too many hard links to", path);
 | 
				
			||||||
			return -1;
 | 
									close(readfd);
 | 
				
			||||||
 | 
									return -1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (S_ISLNK(st.st_mode)) {
 | 
				
			||||||
 | 
									eerror("%s: chmod: %s %s", applet, path, " is a symbolic link");
 | 
				
			||||||
 | 
									close(readfd);
 | 
				
			||||||
 | 
									return -1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								einfo("%s: correcting mode", path);
 | 
				
			||||||
 | 
								if (fchmod(readfd, mode)) {
 | 
				
			||||||
 | 
									eerror("%s: chmod: %s", applet, strerror(errno));
 | 
				
			||||||
 | 
									close(readfd);
 | 
				
			||||||
 | 
									return -1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (S_ISLNK(st.st_mode)) {
 | 
					 | 
				
			||||||
			eerror("%s: chmod: %s %s", applet, path, " is a symbolic link");
 | 
					 | 
				
			||||||
			return -1;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		einfo("%s: correcting mode", path);
 | 
					 | 
				
			||||||
		if (chmod(path, mode)) {
 | 
					 | 
				
			||||||
			eerror("%s: chmod: %s", applet, strerror(errno));
 | 
					 | 
				
			||||||
			return -1;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (chowner && (st.st_uid != uid || st.st_gid != gid)) {
 | 
							if (chowner && (st.st_uid != uid || st.st_gid != gid)) {
 | 
				
			||||||
		if ((type != inode_dir) && (st.st_nlink > 1)) {
 | 
								if ((type != inode_dir) && (st.st_nlink > 1)) {
 | 
				
			||||||
			eerror("%s: chown: %s %s", applet, "Too many hard links to", path);
 | 
									eerror("%s: chown: %s %s", applet, "Too many hard links to", path);
 | 
				
			||||||
			return -1;
 | 
									close(readfd);
 | 
				
			||||||
		}
 | 
									return -1;
 | 
				
			||||||
		if (S_ISLNK(st.st_mode)) {
 | 
								}
 | 
				
			||||||
			eerror("%s: chown: %s %s", applet, path, " is a symbolic link");
 | 
								if (S_ISLNK(st.st_mode)) {
 | 
				
			||||||
			return -1;
 | 
									eerror("%s: chown: %s %s", applet, path, " is a symbolic link");
 | 
				
			||||||
		}
 | 
									close(readfd);
 | 
				
			||||||
		einfo("%s: correcting owner", path);
 | 
									return -1;
 | 
				
			||||||
		if (chown(path, uid, gid)) {
 | 
								}
 | 
				
			||||||
			eerror("%s: chown: %s", applet, strerror(errno));
 | 
								einfo("%s: correcting owner", path);
 | 
				
			||||||
			return -1;
 | 
								if (fchown(readfd, uid, gid)) {
 | 
				
			||||||
 | 
									eerror("%s: chown: %s", applet, strerror(errno));
 | 
				
			||||||
 | 
									close(readfd);
 | 
				
			||||||
 | 
									return -1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							if (selinux_on)
 | 
				
			||||||
 | 
								selinux_util_label(path);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							eerror("fstat: %s: %s", path, strerror(errno));
 | 
				
			||||||
 | 
							close(readfd);
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						close(readfd);
 | 
				
			||||||
	if (selinux_on)
 | 
					 | 
				
			||||||
		selinux_util_label(path);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -68,9 +68,7 @@ int main(int argc, char **argv)
 | 
				
			|||||||
		ok = rc_service_started_daemon(service, exec, NULL, idx);
 | 
							ok = rc_service_started_daemon(service, exec, NULL, idx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	} else if (strcmp(applet, "service_crashed") == 0) {
 | 
						} else if (strcmp(applet, "service_crashed") == 0) {
 | 
				
			||||||
		ok = (_rc_can_find_pids() &&
 | 
							ok = ( rc_service_daemons_crashed(service) && errno != EACCES);
 | 
				
			||||||
		    rc_service_daemons_crashed(service) &&
 | 
					 | 
				
			||||||
		    errno != EACCES);
 | 
					 | 
				
			||||||
	} else
 | 
						} else
 | 
				
			||||||
		eerrorx("%s: unknown applet", applet);
 | 
							eerrorx("%s: unknown applet", applet);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -141,7 +141,7 @@ do_mount(struct ENT *ent, bool remount)
 | 
				
			|||||||
		/* NOTREACHED */
 | 
							/* NOTREACHED */
 | 
				
			||||||
	case 0:
 | 
						case 0:
 | 
				
			||||||
		execvp(argv[0], argv);
 | 
							execvp(argv[0], argv);
 | 
				
			||||||
		eerror("%s: execv: %s", applet, strerror(errno));
 | 
							eerror("%s: execvp: %s", applet, strerror(errno));
 | 
				
			||||||
		_exit(EXIT_FAILURE);
 | 
							_exit(EXIT_FAILURE);
 | 
				
			||||||
		/* NOTREACHED */
 | 
							/* NOTREACHED */
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -65,7 +65,7 @@ static int mount_proc(void)
 | 
				
			|||||||
			break;
 | 
								break;
 | 
				
			||||||
		case 0:
 | 
							case 0:
 | 
				
			||||||
			/* attempt to mount /proc */
 | 
								/* attempt to mount /proc */
 | 
				
			||||||
			execl("mount", "mount", "-t", "proc", "proc", "/proc", NULL);
 | 
								execlp("mount", "mount", "-t", "proc", "proc", "/proc", NULL);
 | 
				
			||||||
			syslog(LOG_ERR, "Unable to execute mount");
 | 
								syslog(LOG_ERR, "Unable to execute mount");
 | 
				
			||||||
			exit(1);
 | 
								exit(1);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
@@ -87,10 +87,11 @@ static int mount_proc(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static bool is_user_process(pid_t pid)
 | 
					static bool is_user_process(pid_t pid)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char buf[PATH_MAX+1];
 | 
						char *buf = NULL;
 | 
				
			||||||
	FILE *fp;
 | 
						FILE *fp;
 | 
				
			||||||
	char path[PATH_MAX+1];
 | 
						char *path = NULL;
 | 
				
			||||||
	pid_t temp_pid;
 | 
						pid_t temp_pid;
 | 
				
			||||||
 | 
						size_t size;
 | 
				
			||||||
	bool user_process = true;
 | 
						bool user_process = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while (pid >0 && user_process) {
 | 
						while (pid >0 && user_process) {
 | 
				
			||||||
@@ -98,8 +99,9 @@ static bool is_user_process(pid_t pid)
 | 
				
			|||||||
			user_process = false;
 | 
								user_process = false;
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		snprintf(path, sizeof(path), "/proc/%d/status", pid);
 | 
							xasprintf(&path, "/proc/%d/status", pid);
 | 
				
			||||||
		fp = fopen(path, "r");
 | 
							fp = fopen(path, "r");
 | 
				
			||||||
 | 
							free(path);
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * if we could not open the file, the process disappeared, which
 | 
							 * if we could not open the file, the process disappeared, which
 | 
				
			||||||
		 * leaves us no way to determine for sure whether it was a user
 | 
							 * leaves us no way to determine for sure whether it was a user
 | 
				
			||||||
@@ -112,11 +114,14 @@ static bool is_user_process(pid_t pid)
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		temp_pid = -1;
 | 
							temp_pid = -1;
 | 
				
			||||||
		while (! feof(fp)) {
 | 
							while (! feof(fp)) {
 | 
				
			||||||
			buf[0] = 0;
 | 
								buf = NULL;
 | 
				
			||||||
			if (fgets(buf, sizeof(buf), fp))
 | 
								if (getline(&buf, &size, fp) != -1) {
 | 
				
			||||||
				sscanf(buf, "PPid: %d", &temp_pid);
 | 
									sscanf(buf, "PPid: %d", &temp_pid);
 | 
				
			||||||
			else
 | 
									free(buf);
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									free(buf);
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		fclose(fp);
 | 
							fclose(fp);
 | 
				
			||||||
		if (temp_pid == -1) {
 | 
							if (temp_pid == -1) {
 | 
				
			||||||
@@ -135,7 +140,7 @@ static int signal_processes(int sig, RC_STRINGLIST *omits, bool dryrun)
 | 
				
			|||||||
	sigset_t oldsigs;
 | 
						sigset_t oldsigs;
 | 
				
			||||||
	DIR *dir;
 | 
						DIR *dir;
 | 
				
			||||||
	struct dirent	*d;
 | 
						struct dirent	*d;
 | 
				
			||||||
	char buf[PATH_MAX+1];
 | 
						char *buf = NULL;
 | 
				
			||||||
	pid_t pid;
 | 
						pid_t pid;
 | 
				
			||||||
	int sendcount = 0;
 | 
						int sendcount = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -170,7 +175,11 @@ static int signal_processes(int sig, RC_STRINGLIST *omits, bool dryrun)
 | 
				
			|||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Is this a process we have been requested to omit? */
 | 
							/* Is this a process we have been requested to omit? */
 | 
				
			||||||
		sprintf(buf, "%d", pid);
 | 
							if (buf) {
 | 
				
			||||||
 | 
								free(buf);
 | 
				
			||||||
 | 
								buf = NULL;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							xasprintf(&buf, "%d", pid);
 | 
				
			||||||
		if (rc_stringlist_find(omits, buf))
 | 
							if (rc_stringlist_find(omits, buf))
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -248,7 +248,6 @@ find_mounts(struct args *args)
 | 
				
			|||||||
	struct opt *o;
 | 
						struct opt *o;
 | 
				
			||||||
	int netdev;
 | 
						int netdev;
 | 
				
			||||||
	char *tmp;
 | 
						char *tmp;
 | 
				
			||||||
	size_t l;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((nmnts = getmntinfo(&mnts, MNT_NOWAIT)) == 0)
 | 
						if ((nmnts = getmntinfo(&mnts, MNT_NOWAIT)) == 0)
 | 
				
			||||||
		eerrorx("getmntinfo: %s", strerror (errno));
 | 
							eerrorx("getmntinfo: %s", strerror (errno));
 | 
				
			||||||
@@ -264,11 +263,7 @@ find_mounts(struct args *args)
 | 
				
			|||||||
				if (! options)
 | 
									if (! options)
 | 
				
			||||||
					options = xstrdup(o->o_name);
 | 
										options = xstrdup(o->o_name);
 | 
				
			||||||
				else {
 | 
									else {
 | 
				
			||||||
					l = strlen(options) +
 | 
										xasprintf(&tmp, "%s,%s", options, o->o_name);
 | 
				
			||||||
					    strlen(o->o_name) + 2;
 | 
					 | 
				
			||||||
					tmp = xmalloc(sizeof (char) * l);
 | 
					 | 
				
			||||||
					snprintf(tmp, l, "%s,%s", options,
 | 
					 | 
				
			||||||
					    o->o_name);
 | 
					 | 
				
			||||||
					free(options);
 | 
										free(options);
 | 
				
			||||||
					options = tmp;
 | 
										options = tmp;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
@@ -315,6 +310,7 @@ find_mounts(struct args *args)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	FILE *fp;
 | 
						FILE *fp;
 | 
				
			||||||
	char *buffer;
 | 
						char *buffer;
 | 
				
			||||||
 | 
						size_t size;
 | 
				
			||||||
	char *p;
 | 
						char *p;
 | 
				
			||||||
	char *from;
 | 
						char *from;
 | 
				
			||||||
	char *to;
 | 
						char *to;
 | 
				
			||||||
@@ -329,8 +325,8 @@ find_mounts(struct args *args)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	list = rc_stringlist_new();
 | 
						list = rc_stringlist_new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	buffer = xmalloc(sizeof(char) * PATH_MAX * 3);
 | 
						buffer = NULL;
 | 
				
			||||||
	while (fgets(buffer, PATH_MAX * 3, fp)) {
 | 
						while (getline(&buffer, &size, fp) != -1) {
 | 
				
			||||||
		netdev = -1;
 | 
							netdev = -1;
 | 
				
			||||||
		p = buffer;
 | 
							p = buffer;
 | 
				
			||||||
		from = strsep(&p, " ");
 | 
							from = strsep(&p, " ");
 | 
				
			||||||
@@ -346,6 +342,8 @@ find_mounts(struct args *args)
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		process_mount(list, args, from, to, fst, opts, netdev);
 | 
							process_mount(list, args, from, to, fst, opts, netdev);
 | 
				
			||||||
 | 
							free(buffer);
 | 
				
			||||||
 | 
							buffer = NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	free(buffer);
 | 
						free(buffer);
 | 
				
			||||||
	fclose(fp);
 | 
						fclose(fp);
 | 
				
			||||||
@@ -380,7 +378,7 @@ int main(int argc, char **argv)
 | 
				
			|||||||
	regex_t *skip_point_regex = NULL;
 | 
						regex_t *skip_point_regex = NULL;
 | 
				
			||||||
	RC_STRINGLIST *nodes;
 | 
						RC_STRINGLIST *nodes;
 | 
				
			||||||
	RC_STRING *s;
 | 
						RC_STRING *s;
 | 
				
			||||||
	char real_path[PATH_MAX + 1];
 | 
						char *real_path = NULL;
 | 
				
			||||||
	int opt;
 | 
						int opt;
 | 
				
			||||||
	int result;
 | 
						int result;
 | 
				
			||||||
	char *this_path;
 | 
						char *this_path;
 | 
				
			||||||
@@ -450,9 +448,12 @@ int main(int argc, char **argv)
 | 
				
			|||||||
			eerrorx("%s: `%s' is not a mount point",
 | 
								eerrorx("%s: `%s' is not a mount point",
 | 
				
			||||||
			    argv[0], argv[optind]);
 | 
								    argv[0], argv[optind]);
 | 
				
			||||||
		this_path = argv[optind++];
 | 
							this_path = argv[optind++];
 | 
				
			||||||
		if (realpath(this_path, real_path))
 | 
							real_path = realpath(this_path, NULL);
 | 
				
			||||||
 | 
							if (real_path)
 | 
				
			||||||
			this_path = real_path;
 | 
								this_path = real_path;
 | 
				
			||||||
		rc_stringlist_add(args.mounts, this_path);
 | 
							rc_stringlist_add(args.mounts, this_path);
 | 
				
			||||||
 | 
							free(real_path);
 | 
				
			||||||
 | 
							real_path = NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	nodes = find_mounts(&args);
 | 
						nodes = find_mounts(&args);
 | 
				
			||||||
	rc_stringlist_free(args.mounts);
 | 
						rc_stringlist_free(args.mounts);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,6 +35,7 @@
 | 
				
			|||||||
#include "rc-wtmp.h"
 | 
					#include "rc-wtmp.h"
 | 
				
			||||||
#include "version.h"
 | 
					#include "version.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const char *path_default = "/sbin:/usr/sbin:/bin:/usr/bin";
 | 
				
			||||||
static const char *rc_default_runlevel = "default";
 | 
					static const char *rc_default_runlevel = "default";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static pid_t do_openrc(const char *runlevel)
 | 
					static pid_t do_openrc(const char *runlevel)
 | 
				
			||||||
@@ -53,7 +54,7 @@ static pid_t do_openrc(const char *runlevel)
 | 
				
			|||||||
			sigemptyset(&signals);
 | 
								sigemptyset(&signals);
 | 
				
			||||||
			sigprocmask(SIG_SETMASK, &signals, NULL);
 | 
								sigprocmask(SIG_SETMASK, &signals, NULL);
 | 
				
			||||||
			printf("Starting %s runlevel\n", runlevel);
 | 
								printf("Starting %s runlevel\n", runlevel);
 | 
				
			||||||
			execl("/sbin/openrc", "/sbin/openrc", runlevel, NULL);
 | 
								execlp("openrc", "openrc", runlevel, NULL);
 | 
				
			||||||
			perror("exec");
 | 
								perror("exec");
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
@@ -88,7 +89,7 @@ static void init(const char *default_runlevel)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void handle_reexec(char *my_name)
 | 
					static void handle_reexec(char *my_name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	execl(my_name, my_name, "reexec", NULL);
 | 
						execlp(my_name, my_name, "reexec", NULL);
 | 
				
			||||||
	return;
 | 
						return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -183,6 +184,9 @@ int main(int argc, char **argv)
 | 
				
			|||||||
	sigaction(SIGINT, &sa, NULL);
 | 
						sigaction(SIGINT, &sa, NULL);
 | 
				
			||||||
	reboot(RB_DISABLE_CAD);
 | 
						reboot(RB_DISABLE_CAD);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* set default path */
 | 
				
			||||||
 | 
						setenv("PATH", path_default, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (! reexec)
 | 
						if (! reexec)
 | 
				
			||||||
		init(default_runlevel);
 | 
							init(default_runlevel);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -109,7 +109,7 @@ static void
 | 
				
			|||||||
handle_signal(int sig)
 | 
					handle_signal(int sig)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int serrno = errno;
 | 
						int serrno = errno;
 | 
				
			||||||
	char signame[10] = { '\0' };
 | 
						char *signame = NULL;
 | 
				
			||||||
	struct winsize ws;
 | 
						struct winsize ws;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (sig) {
 | 
						switch (sig) {
 | 
				
			||||||
@@ -134,20 +134,22 @@ handle_signal(int sig)
 | 
				
			|||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case SIGINT:
 | 
						case SIGINT:
 | 
				
			||||||
		if (!signame[0])
 | 
							if (!signame)
 | 
				
			||||||
			snprintf(signame, sizeof(signame), "SIGINT");
 | 
								xasprintf(&signame, "SIGINT");
 | 
				
			||||||
		/* FALLTHROUGH */
 | 
							/* FALLTHROUGH */
 | 
				
			||||||
	case SIGTERM:
 | 
						case SIGTERM:
 | 
				
			||||||
		if (!signame[0])
 | 
							if (!signame)
 | 
				
			||||||
			snprintf(signame, sizeof(signame), "SIGTERM");
 | 
								xasprintf(&signame, "SIGTERM");
 | 
				
			||||||
		/* FALLTHROUGH */
 | 
							/* FALLTHROUGH */
 | 
				
			||||||
	case SIGQUIT:
 | 
						case SIGQUIT:
 | 
				
			||||||
		if (!signame[0])
 | 
							if (!signame)
 | 
				
			||||||
			snprintf(signame, sizeof(signame), "SIGQUIT");
 | 
								xasprintf(&signame, "SIGQUIT");
 | 
				
			||||||
		/* Send the signal to our children too */
 | 
							/* Send the signal to our children too */
 | 
				
			||||||
		if (service_pid > 0)
 | 
							if (service_pid > 0)
 | 
				
			||||||
			kill(service_pid, sig);
 | 
								kill(service_pid, sig);
 | 
				
			||||||
		eerrorx("%s: caught %s, aborting", applet, signame);
 | 
							eerror("%s: caught %s, aborting", applet, signame);
 | 
				
			||||||
 | 
							free(signame);
 | 
				
			||||||
 | 
							exit(EXIT_FAILURE);
 | 
				
			||||||
		/* NOTREACHED */
 | 
							/* NOTREACHED */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
@@ -161,11 +163,12 @@ handle_signal(int sig)
 | 
				
			|||||||
static void
 | 
					static void
 | 
				
			||||||
unhotplug()
 | 
					unhotplug()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char file[PATH_MAX];
 | 
						char *file = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	snprintf(file, sizeof(file), RC_SVCDIR "/hotplugged/%s", applet);
 | 
						xasprintf(&file, RC_SVCDIR "/hotplugged/%s", applet);
 | 
				
			||||||
	if (exists(file) && unlink(file) != 0)
 | 
						if (exists(file) && unlink(file) != 0)
 | 
				
			||||||
		eerror("%s: unlink `%s': %s", applet, file, strerror(errno));
 | 
							eerror("%s: unlink `%s': %s", applet, file, strerror(errno));
 | 
				
			||||||
 | 
						free(file);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
@@ -485,7 +488,7 @@ svc_exec(const char *arg1, const char *arg2)
 | 
				
			|||||||
static bool
 | 
					static bool
 | 
				
			||||||
svc_wait(const char *svc)
 | 
					svc_wait(const char *svc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char file[PATH_MAX];
 | 
						char *file = NULL;
 | 
				
			||||||
	int fd;
 | 
						int fd;
 | 
				
			||||||
	bool forever = false;
 | 
						bool forever = false;
 | 
				
			||||||
	RC_STRINGLIST *keywords;
 | 
						RC_STRINGLIST *keywords;
 | 
				
			||||||
@@ -498,8 +501,7 @@ svc_wait(const char *svc)
 | 
				
			|||||||
		forever = true;
 | 
							forever = true;
 | 
				
			||||||
	rc_stringlist_free(keywords);
 | 
						rc_stringlist_free(keywords);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	snprintf(file, sizeof(file), RC_SVCDIR "/exclusive/%s",
 | 
						xasprintf(&file, RC_SVCDIR "/exclusive/%s", basename_c(svc));
 | 
				
			||||||
	    basename_c(svc));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	interval.tv_sec = 0;
 | 
						interval.tv_sec = 0;
 | 
				
			||||||
	interval.tv_nsec = WAIT_INTERVAL;
 | 
						interval.tv_nsec = WAIT_INTERVAL;
 | 
				
			||||||
@@ -512,23 +514,29 @@ svc_wait(const char *svc)
 | 
				
			|||||||
		if (fd != -1) {
 | 
							if (fd != -1) {
 | 
				
			||||||
			if (flock(fd, LOCK_SH | LOCK_NB) == 0) {
 | 
								if (flock(fd, LOCK_SH | LOCK_NB) == 0) {
 | 
				
			||||||
				close(fd);
 | 
									close(fd);
 | 
				
			||||||
 | 
									free(file);
 | 
				
			||||||
				return true;
 | 
									return true;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			close(fd);
 | 
								close(fd);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (errno == ENOENT)
 | 
							if (errno == ENOENT) {
 | 
				
			||||||
 | 
								free(file);
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		if (errno != EWOULDBLOCK)
 | 
							}
 | 
				
			||||||
			eerrorx("%s: open `%s': %s", applet, file,
 | 
							if (errno != EWOULDBLOCK) {
 | 
				
			||||||
 | 
								eerror("%s: open `%s': %s", applet, file,
 | 
				
			||||||
			    strerror(errno));
 | 
								    strerror(errno));
 | 
				
			||||||
 | 
								free(file);
 | 
				
			||||||
 | 
								exit(EXIT_FAILURE);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		if (nanosleep(&interval, NULL) == -1) {
 | 
							if (nanosleep(&interval, NULL) == -1) {
 | 
				
			||||||
			if (errno != EINTR)
 | 
								if (errno != EINTR)
 | 
				
			||||||
				return false;
 | 
									goto finish;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (!forever) {
 | 
							if (!forever) {
 | 
				
			||||||
			timespecsub(&timeout, &interval, &timeout);
 | 
								timespecsub(&timeout, &interval, &timeout);
 | 
				
			||||||
			if (timeout.tv_sec <= 0)
 | 
								if (timeout.tv_sec <= 0)
 | 
				
			||||||
				return false;
 | 
									goto finish;
 | 
				
			||||||
			timespecsub(&warn, &interval, &warn);
 | 
								timespecsub(&warn, &interval, &warn);
 | 
				
			||||||
			if (warn.tv_sec <= 0) {
 | 
								if (warn.tv_sec <= 0) {
 | 
				
			||||||
				ewarn("%s: waiting for %s (%d seconds)",
 | 
									ewarn("%s: waiting for %s (%d seconds)",
 | 
				
			||||||
@@ -538,6 +546,8 @@ svc_wait(const char *svc)
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					finish:
 | 
				
			||||||
 | 
						free(file);
 | 
				
			||||||
	return false;
 | 
						return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1105,9 +1115,10 @@ int main(int argc, char **argv)
 | 
				
			|||||||
	bool runscript = false;
 | 
						bool runscript = false;
 | 
				
			||||||
	int retval, opt, depoptions = RC_DEP_TRACE;
 | 
						int retval, opt, depoptions = RC_DEP_TRACE;
 | 
				
			||||||
	RC_STRING *svc;
 | 
						RC_STRING *svc;
 | 
				
			||||||
	char path[PATH_MAX], lnk[PATH_MAX];
 | 
						char *path = NULL;
 | 
				
			||||||
 | 
						char *lnk = NULL;
 | 
				
			||||||
	char *dir, *save = NULL, *saveLnk = NULL;
 | 
						char *dir, *save = NULL, *saveLnk = NULL;
 | 
				
			||||||
	char pidstr[10];
 | 
						char *pidstr = NULL;
 | 
				
			||||||
	size_t l = 0, ll;
 | 
						size_t l = 0, ll;
 | 
				
			||||||
 	const char *file;
 | 
					 	const char *file;
 | 
				
			||||||
	struct stat stbuf;
 | 
						struct stat stbuf;
 | 
				
			||||||
@@ -1134,12 +1145,14 @@ int main(int argc, char **argv)
 | 
				
			|||||||
	 * This works fine, provided that we ONLY allow multiplexed services
 | 
						 * This works fine, provided that we ONLY allow multiplexed services
 | 
				
			||||||
	 * to exist in the same directory as the master link.
 | 
						 * to exist in the same directory as the master link.
 | 
				
			||||||
	 * Also, the master link as to be a real file in the init dir. */
 | 
						 * Also, the master link as to be a real file in the init dir. */
 | 
				
			||||||
	if (!realpath(argv[1], path)) {
 | 
						path = realpath(argv[1], NULL);
 | 
				
			||||||
 | 
						if (!path) {
 | 
				
			||||||
		fprintf(stderr, "realpath: %s\n", strerror(errno));
 | 
							fprintf(stderr, "realpath: %s\n", strerror(errno));
 | 
				
			||||||
		exit(EXIT_FAILURE);
 | 
							exit(EXIT_FAILURE);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	memset(lnk, 0, sizeof(lnk));
 | 
						lnk = xmalloc(4096);
 | 
				
			||||||
	if (readlink(argv[1], lnk, sizeof(lnk)-1)) {
 | 
						memset(lnk, 0, 4096);
 | 
				
			||||||
 | 
						if (readlink(argv[1], lnk, 4096)) {
 | 
				
			||||||
		dir = dirname(path);
 | 
							dir = dirname(path);
 | 
				
			||||||
		if (strchr(lnk, '/')) {
 | 
							if (strchr(lnk, '/')) {
 | 
				
			||||||
			save = xstrdup(dir);
 | 
								save = xstrdup(dir);
 | 
				
			||||||
@@ -1153,8 +1166,7 @@ int main(int argc, char **argv)
 | 
				
			|||||||
		} else
 | 
							} else
 | 
				
			||||||
			file = basename_c(argv[1]);
 | 
								file = basename_c(argv[1]);
 | 
				
			||||||
		ll = strlen(dir) + strlen(file) + 2;
 | 
							ll = strlen(dir) + strlen(file) + 2;
 | 
				
			||||||
		service = xmalloc(ll);
 | 
							xasprintf(&service, "%s/%s", dir, file);
 | 
				
			||||||
		snprintf(service, ll, "%s/%s", dir, file);
 | 
					 | 
				
			||||||
		if (stat(service, &stbuf) != 0) {
 | 
							if (stat(service, &stbuf) != 0) {
 | 
				
			||||||
			free(service);
 | 
								free(service);
 | 
				
			||||||
			service = xstrdup(lnk);
 | 
								service = xstrdup(lnk);
 | 
				
			||||||
@@ -1162,6 +1174,7 @@ int main(int argc, char **argv)
 | 
				
			|||||||
		free(save);
 | 
							free(save);
 | 
				
			||||||
		free(saveLnk);
 | 
							free(saveLnk);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						free(lnk);
 | 
				
			||||||
	if (!service)
 | 
						if (!service)
 | 
				
			||||||
		service = xstrdup(path);
 | 
							service = xstrdup(path);
 | 
				
			||||||
	applet = basename_c(service);
 | 
						applet = basename_c(service);
 | 
				
			||||||
@@ -1185,7 +1198,7 @@ int main(int argc, char **argv)
 | 
				
			|||||||
	/* Set an env var so that we always know our pid regardless of any
 | 
						/* Set an env var so that we always know our pid regardless of any
 | 
				
			||||||
	   subshells the init script may create so that our mark_service_*
 | 
						   subshells the init script may create so that our mark_service_*
 | 
				
			||||||
	   functions can always instruct us of this change */
 | 
						   functions can always instruct us of this change */
 | 
				
			||||||
	snprintf(pidstr, sizeof(pidstr), "%d", (int) getpid());
 | 
						xasprintf(&pidstr, "%d", (int) getpid());
 | 
				
			||||||
	setenv("RC_OPENRC_PID", pidstr, 1);
 | 
						setenv("RC_OPENRC_PID", pidstr, 1);
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * RC_RUNSCRIPT_PID is deprecated, but we will keep it for a while
 | 
						 * RC_RUNSCRIPT_PID is deprecated, but we will keep it for a while
 | 
				
			||||||
@@ -1255,6 +1268,9 @@ int main(int argc, char **argv)
 | 
				
			|||||||
		case_RC_COMMON_GETOPT
 | 
							case_RC_COMMON_GETOPT
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (rc_yesno(getenv("RC_NODEPS")))
 | 
				
			||||||
 | 
							deps = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* If we're changing runlevels and not called by rc then we cannot
 | 
						/* If we're changing runlevels and not called by rc then we cannot
 | 
				
			||||||
	   work with any dependencies */
 | 
						   work with any dependencies */
 | 
				
			||||||
	if (deps && getenv("RC_PID") == NULL &&
 | 
						if (deps && getenv("RC_PID") == NULL &&
 | 
				
			||||||
@@ -1269,6 +1285,8 @@ int main(int argc, char **argv)
 | 
				
			|||||||
		unsetenv("IN_BACKGROUND");
 | 
							unsetenv("IN_BACKGROUND");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (rc_yesno(getenv("IN_DRYRUN")))
 | 
				
			||||||
 | 
						dry_run = true;
 | 
				
			||||||
	if (rc_yesno(getenv("IN_HOTPLUG"))) {
 | 
						if (rc_yesno(getenv("IN_HOTPLUG"))) {
 | 
				
			||||||
		if (!service_plugable())
 | 
							if (!service_plugable())
 | 
				
			||||||
			eerrorx("%s: not allowed to be hotplugged", applet);
 | 
								eerrorx("%s: not allowed to be hotplugged", applet);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -87,6 +87,8 @@ write_log(int logfd, const char *buffer, size_t bytes)
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!in_escape) {
 | 
							if (!in_escape) {
 | 
				
			||||||
 | 
								if (!isprint((int) *p) && *p != '\n')
 | 
				
			||||||
 | 
									goto cont;
 | 
				
			||||||
			if (write(logfd, p++, 1) == -1)
 | 
								if (write(logfd, p++, 1) == -1)
 | 
				
			||||||
				eerror("write: %s", strerror(errno));
 | 
									eerror("write: %s", strerror(errno));
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -51,7 +51,8 @@ rc_conf_yesno(const char *setting)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static const char *const env_whitelist[] = {
 | 
					static const char *const env_whitelist[] = {
 | 
				
			||||||
	"EERROR_QUIET", "EINFO_QUIET",
 | 
						"EERROR_QUIET", "EINFO_QUIET",
 | 
				
			||||||
	"IN_BACKGROUND", "IN_HOTPLUG",
 | 
						"IN_BACKGROUND", "IN_DRYRUN", "IN_HOTPLUG",
 | 
				
			||||||
 | 
						"RC_DEBUG", "RC_NODEPS",
 | 
				
			||||||
	"LANG", "LC_MESSAGES", "TERM",
 | 
						"LANG", "LC_MESSAGES", "TERM",
 | 
				
			||||||
	"EINFO_COLOR", "EINFO_VERBOSE",
 | 
						"EINFO_COLOR", "EINFO_VERBOSE",
 | 
				
			||||||
	NULL
 | 
						NULL
 | 
				
			||||||
@@ -131,7 +132,8 @@ env_config(void)
 | 
				
			|||||||
	char *npp;
 | 
						char *npp;
 | 
				
			||||||
	char *tok;
 | 
						char *tok;
 | 
				
			||||||
	const char *sys = rc_sys();
 | 
						const char *sys = rc_sys();
 | 
				
			||||||
	char buffer[PATH_MAX];
 | 
						char *buffer = NULL;
 | 
				
			||||||
 | 
						size_t size = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Ensure our PATH is prefixed with the system locations first
 | 
						/* Ensure our PATH is prefixed with the system locations first
 | 
				
			||||||
	   for a little extra security */
 | 
						   for a little extra security */
 | 
				
			||||||
@@ -170,8 +172,7 @@ env_config(void)
 | 
				
			|||||||
	free(e);
 | 
						free(e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((fp = fopen(RC_KRUNLEVEL, "r"))) {
 | 
						if ((fp = fopen(RC_KRUNLEVEL, "r"))) {
 | 
				
			||||||
		memset(buffer, 0, sizeof (buffer));
 | 
							if (getline(&buffer, &size, fp) != -1) {
 | 
				
			||||||
		if (fgets(buffer, sizeof (buffer), fp)) {
 | 
					 | 
				
			||||||
			l = strlen (buffer) - 1;
 | 
								l = strlen (buffer) - 1;
 | 
				
			||||||
			if (buffer[l] == '\n')
 | 
								if (buffer[l] == '\n')
 | 
				
			||||||
				buffer[l] = 0;
 | 
									buffer[l] = 0;
 | 
				
			||||||
@@ -181,6 +182,7 @@ env_config(void)
 | 
				
			|||||||
	} else
 | 
						} else
 | 
				
			||||||
		setenv("RC_DEFAULTLEVEL", RC_LEVEL_DEFAULT, 1);
 | 
							setenv("RC_DEFAULTLEVEL", RC_LEVEL_DEFAULT, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						free(buffer);
 | 
				
			||||||
	if (sys)
 | 
						if (sys)
 | 
				
			||||||
		setenv("RC_SYS", sys, 1);
 | 
							setenv("RC_SYS", sys, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -217,14 +219,27 @@ signal_setup(int sig, void (*handler)(int))
 | 
				
			|||||||
	return sigaction(sig, &sa, NULL);
 | 
						return sigaction(sig, &sa, NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					signal_setup_restart(int sig, void (*handler)(int))
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct sigaction sa;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memset(&sa, 0, sizeof (sa));
 | 
				
			||||||
 | 
						sigemptyset(&sa.sa_mask);
 | 
				
			||||||
 | 
						sa.sa_handler = handler;
 | 
				
			||||||
 | 
						sa.sa_flags = SA_RESTART;
 | 
				
			||||||
 | 
						return sigaction(sig, &sa, NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
svc_lock(const char *applet)
 | 
					svc_lock(const char *applet)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char file[PATH_MAX];
 | 
						char *file = NULL;
 | 
				
			||||||
	int fd;
 | 
						int fd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	snprintf(file, sizeof(file), RC_SVCDIR "/exclusive/%s", applet);
 | 
						xasprintf(&file, RC_SVCDIR "/exclusive/%s", applet);
 | 
				
			||||||
	fd = open(file, O_WRONLY | O_CREAT | O_NONBLOCK, 0664);
 | 
						fd = open(file, O_WRONLY | O_CREAT | O_NONBLOCK, 0664);
 | 
				
			||||||
 | 
						free(file);
 | 
				
			||||||
	if (fd == -1)
 | 
						if (fd == -1)
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
	if (flock(fd, LOCK_EX | LOCK_NB) == -1) {
 | 
						if (flock(fd, LOCK_EX | LOCK_NB) == -1) {
 | 
				
			||||||
@@ -238,11 +253,12 @@ svc_lock(const char *applet)
 | 
				
			|||||||
int
 | 
					int
 | 
				
			||||||
svc_unlock(const char *applet, int fd)
 | 
					svc_unlock(const char *applet, int fd)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char file[PATH_MAX];
 | 
						char *file = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	snprintf(file, sizeof(file), RC_SVCDIR "/exclusive/%s", applet);
 | 
						xasprintf(&file, RC_SVCDIR "/exclusive/%s", applet);
 | 
				
			||||||
	close(fd);
 | 
						close(fd);
 | 
				
			||||||
	unlink(file);
 | 
						unlink(file);
 | 
				
			||||||
 | 
						free(file);
 | 
				
			||||||
	return -1;
 | 
						return -1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -346,7 +362,7 @@ RC_DEPTREE * _rc_deptree_load(int force, int *regen)
 | 
				
			|||||||
	int serrno = errno;
 | 
						int serrno = errno;
 | 
				
			||||||
	int merrno;
 | 
						int merrno;
 | 
				
			||||||
	time_t t;
 | 
						time_t t;
 | 
				
			||||||
	char file[PATH_MAX];
 | 
						char *file = NULL;
 | 
				
			||||||
	struct stat st;
 | 
						struct stat st;
 | 
				
			||||||
	struct utimbuf ut;
 | 
						struct utimbuf ut;
 | 
				
			||||||
	FILE *fp;
 | 
						FILE *fp;
 | 
				
			||||||
@@ -368,7 +384,10 @@ RC_DEPTREE * _rc_deptree_load(int force, int *regen)
 | 
				
			|||||||
		eend (retval, "Failed to update the dependency tree");
 | 
							eend (retval, "Failed to update the dependency tree");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (retval == 0) {
 | 
							if (retval == 0) {
 | 
				
			||||||
			stat(RC_DEPTREE_CACHE, &st);
 | 
								if (stat(RC_DEPTREE_CACHE, &st) != 0) {
 | 
				
			||||||
 | 
									eerror("stat(%s): %s", RC_DEPTREE_CACHE, strerror(errno));
 | 
				
			||||||
 | 
									return NULL;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			if (st.st_mtime < t) {
 | 
								if (st.st_mtime < t) {
 | 
				
			||||||
				eerror("Clock skew detected with `%s'", file);
 | 
									eerror("Clock skew detected with `%s'", file);
 | 
				
			||||||
				eerrorn("Adjusting mtime of `" RC_DEPTREE_CACHE
 | 
									eerrorn("Adjusting mtime of `" RC_DEPTREE_CACHE
 | 
				
			||||||
@@ -392,34 +411,6 @@ RC_DEPTREE * _rc_deptree_load(int force, int *regen)
 | 
				
			|||||||
	return rc_deptree_load();
 | 
						return rc_deptree_load();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool _rc_can_find_pids(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	RC_PIDLIST *pids;
 | 
					 | 
				
			||||||
	RC_PID *pid;
 | 
					 | 
				
			||||||
	RC_PID *pid2;
 | 
					 | 
				
			||||||
	bool retval = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (geteuid() == 0)
 | 
					 | 
				
			||||||
		return true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* If we cannot see process 1, then we don't test to see if
 | 
					 | 
				
			||||||
	 * services crashed or not */
 | 
					 | 
				
			||||||
	pids = rc_find_pids(NULL, NULL, 0, 1);
 | 
					 | 
				
			||||||
	if (pids) {
 | 
					 | 
				
			||||||
		pid = LIST_FIRST(pids);
 | 
					 | 
				
			||||||
		if (pid) {
 | 
					 | 
				
			||||||
			retval = true;
 | 
					 | 
				
			||||||
			while (pid) {
 | 
					 | 
				
			||||||
				pid2 = LIST_NEXT(pid, entries);
 | 
					 | 
				
			||||||
				free(pid);
 | 
					 | 
				
			||||||
				pid = pid2;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		free(pids);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return retval;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const struct {
 | 
					static const struct {
 | 
				
			||||||
	const char * const name;
 | 
						const char * const name;
 | 
				
			||||||
	RC_SERVICE bit;
 | 
						RC_SERVICE bit;
 | 
				
			||||||
@@ -432,6 +423,7 @@ static const struct {
 | 
				
			|||||||
	{ "service_hotplugged",  RC_SERVICE_HOTPLUGGED,  },
 | 
						{ "service_hotplugged",  RC_SERVICE_HOTPLUGGED,  },
 | 
				
			||||||
	{ "service_wasinactive", RC_SERVICE_WASINACTIVE, },
 | 
						{ "service_wasinactive", RC_SERVICE_WASINACTIVE, },
 | 
				
			||||||
	{ "service_failed",      RC_SERVICE_FAILED,      },
 | 
						{ "service_failed",      RC_SERVICE_FAILED,      },
 | 
				
			||||||
 | 
						{ "service_crashed",     RC_SERVICE_CRASHED,     },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
RC_SERVICE lookup_service_state(const char *service)
 | 
					RC_SERVICE lookup_service_state(const char *service)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										57
									
								
								src/rc/rc-pipes.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								src/rc/rc-pipes.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,57 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * rc-pipes.c
 | 
				
			||||||
 | 
					 * Helper to handle spawning processes and connecting them to pipes.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2018 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.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "rc-pipes.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const int pipe_read_end = 0;
 | 
				
			||||||
 | 
					static const int pipe_write_end = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Starts a command with stdin redirected from a pipe
 | 
				
			||||||
 | 
					 * Returns the write end of the pipe or -1
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int rc_pipe_command(char *cmd)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int pfd[2];
 | 
				
			||||||
 | 
						pid_t pid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (pipe(pfd) < 0)
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pid = fork();
 | 
				
			||||||
 | 
						if (pid < 0)
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						else if (pid > 0) {
 | 
				
			||||||
 | 
							/* parent */
 | 
				
			||||||
 | 
							close(pfd[0]);
 | 
				
			||||||
 | 
							return pfd[pipe_write_end];
 | 
				
			||||||
 | 
						} else if (pid == 0) {
 | 
				
			||||||
 | 
							/* child */
 | 
				
			||||||
 | 
							close(pfd[pipe_write_end]);
 | 
				
			||||||
 | 
							if (pfd[0] != STDIN_FILENO) {
 | 
				
			||||||
 | 
								if (dup2(pfd[0], STDIN_FILENO) < 0)
 | 
				
			||||||
 | 
									exit(1);
 | 
				
			||||||
 | 
								close(pfd[0]);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							execl("/bin/sh", "sh", "-c", cmd, NULL);
 | 
				
			||||||
 | 
							exit(1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										18
									
								
								src/rc/rc-pipes.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/rc/rc-pipes.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2018 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.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef RC_PIPES_H
 | 
				
			||||||
 | 
					#define RC_PIPES_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int rc_pipe_command(char *cmd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
@@ -68,7 +68,7 @@ rc_plugin_load(void)
 | 
				
			|||||||
	DIR *dp;
 | 
						DIR *dp;
 | 
				
			||||||
	struct dirent *d;
 | 
						struct dirent *d;
 | 
				
			||||||
	PLUGIN *plugin;
 | 
						PLUGIN *plugin;
 | 
				
			||||||
	char file[PATH_MAX];
 | 
						char *file = NULL;
 | 
				
			||||||
	void *h;
 | 
						void *h;
 | 
				
			||||||
	int (*fptr)(RC_HOOK, const char *);
 | 
						int (*fptr)(RC_HOOK, const char *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -85,8 +85,9 @@ rc_plugin_load(void)
 | 
				
			|||||||
		if (d->d_name[0] == '.')
 | 
							if (d->d_name[0] == '.')
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		snprintf(file, sizeof(file), RC_PLUGINDIR "/%s",  d->d_name);
 | 
							xasprintf(&file, RC_PLUGINDIR "/%s",  d->d_name);
 | 
				
			||||||
		h = dlopen(file, RTLD_LAZY);
 | 
							h = dlopen(file, RTLD_LAZY);
 | 
				
			||||||
 | 
							free(file);
 | 
				
			||||||
		if (h == NULL) {
 | 
							if (h == NULL) {
 | 
				
			||||||
			eerror("dlopen: %s", dlerror());
 | 
								eerror("dlopen: %s", dlerror());
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -307,6 +307,9 @@ int run_stop_schedule(const char *applet,
 | 
				
			|||||||
	const char *const *p;
 | 
						const char *const *p;
 | 
				
			||||||
	bool progressed = false;
 | 
						bool progressed = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!(pid > 0 || exec || uid || (argv && *argv)))
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (exec)
 | 
						if (exec)
 | 
				
			||||||
		einfov("Will stop %s", exec);
 | 
							einfov("Will stop %s", exec);
 | 
				
			||||||
	if (pid > 0)
 | 
						if (pid > 0)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -256,19 +256,19 @@ static int read_context_file(const char *filename, char **context)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	int ret = -1;
 | 
						int ret = -1;
 | 
				
			||||||
	FILE *fp;
 | 
						FILE *fp;
 | 
				
			||||||
	char filepath[PATH_MAX];
 | 
						char *filepath = NULL;
 | 
				
			||||||
	char *line = NULL;
 | 
						char *line = NULL;
 | 
				
			||||||
	char *p;
 | 
						char *p;
 | 
				
			||||||
	char *p2;
 | 
						char *p2;
 | 
				
			||||||
	size_t len = 0;
 | 
						size_t len = 0;
 | 
				
			||||||
	ssize_t read;
 | 
						ssize_t read;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memset(filepath, '\0', PATH_MAX);
 | 
						xasprintf(&filepath, "%s/%s", selinux_contexts_path(), filename);
 | 
				
			||||||
	snprintf(filepath, PATH_MAX - 1, "%s/%s", selinux_contexts_path(), filename);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fp = fopen(filepath, "r");
 | 
						fp = fopen(filepath, "r");
 | 
				
			||||||
	if (fp == NULL) {
 | 
						if (fp == NULL) {
 | 
				
			||||||
		eerror("Failed to open context file: %s", filename);
 | 
							eerror("Failed to open context file: %s", filename);
 | 
				
			||||||
 | 
							free(filepath);
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -294,6 +294,7 @@ static int read_context_file(const char *filename, char **context)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	free(line);
 | 
						free(line);
 | 
				
			||||||
 | 
						free(filepath);
 | 
				
			||||||
	fclose(fp);
 | 
						fclose(fp);
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,23 +29,33 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const char *applet = NULL;
 | 
					const char *applet = NULL;
 | 
				
			||||||
const char *extraopts = NULL;
 | 
					const char *extraopts = NULL;
 | 
				
			||||||
const char *getoptstring = "e:ilr:IN" getoptstring_COMMON;
 | 
					const char *getoptstring = "cdDe:ilr:INsSZ" getoptstring_COMMON;
 | 
				
			||||||
const struct option longopts[] = {
 | 
					const struct option longopts[] = {
 | 
				
			||||||
 | 
						{ "debug",     0, NULL, 'd' },
 | 
				
			||||||
 | 
						{ "nodeps",     0, NULL, 'D' },
 | 
				
			||||||
	{ "exists",   1, NULL, 'e' },
 | 
						{ "exists",   1, NULL, 'e' },
 | 
				
			||||||
 | 
						{ "ifcrashed", 0, NULL, 'c' },
 | 
				
			||||||
	{ "ifexists", 0, NULL, 'i' },
 | 
						{ "ifexists", 0, NULL, 'i' },
 | 
				
			||||||
	{ "ifinactive", 0, NULL, 'I' },
 | 
						{ "ifinactive", 0, NULL, 'I' },
 | 
				
			||||||
	{ "ifnotstarted", 0, NULL, 'N' },
 | 
						{ "ifnotstarted", 0, NULL, 'N' },
 | 
				
			||||||
 | 
						{ "ifstarted", 0, NULL, 's' },
 | 
				
			||||||
 | 
						{ "ifstopped", 0, NULL, 'S' },
 | 
				
			||||||
	{ "list",     0, NULL, 'l' },
 | 
						{ "list",     0, NULL, 'l' },
 | 
				
			||||||
	{ "resolve",  1, NULL, 'r' },
 | 
						{ "resolve",  1, NULL, 'r' },
 | 
				
			||||||
 | 
						{ "dry-run",     0, NULL, 'Z' },
 | 
				
			||||||
	longopts_COMMON
 | 
						longopts_COMMON
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
const char * const longopts_help[] = {
 | 
					const char * const longopts_help[] = {
 | 
				
			||||||
 | 
						"set xtrace when running the command",
 | 
				
			||||||
 | 
						"ignore dependencies",
 | 
				
			||||||
	"tests if the service exists or not",
 | 
						"tests if the service exists or not",
 | 
				
			||||||
 | 
						"if the service is crashed then run the command",
 | 
				
			||||||
	"if the service exists then run the command",
 | 
						"if the service exists then run the command",
 | 
				
			||||||
	"if the service is inactive then run the command",
 | 
						"if the service is inactive then run the command",
 | 
				
			||||||
	"if the service is not started then run the command",
 | 
						"if the service is not started then run the command",
 | 
				
			||||||
	"list all available services",
 | 
						"list all available services",
 | 
				
			||||||
	"resolve the service name to an init script",
 | 
						"resolve the service name to an init script",
 | 
				
			||||||
 | 
						"dry run (show what would happen)",
 | 
				
			||||||
	longopts_help_COMMON
 | 
						longopts_help_COMMON
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
const char *usagestring = ""							\
 | 
					const char *usagestring = ""							\
 | 
				
			||||||
@@ -61,9 +71,12 @@ int main(int argc, char **argv)
 | 
				
			|||||||
	RC_STRINGLIST *list;
 | 
						RC_STRINGLIST *list;
 | 
				
			||||||
	RC_STRING *s;
 | 
						RC_STRING *s;
 | 
				
			||||||
	RC_SERVICE state;
 | 
						RC_SERVICE state;
 | 
				
			||||||
 | 
						bool if_crashed = false;
 | 
				
			||||||
	bool if_exists = false;
 | 
						bool if_exists = false;
 | 
				
			||||||
	bool if_inactive = false;
 | 
						bool if_inactive = false;
 | 
				
			||||||
	bool if_notstarted = false;
 | 
						bool if_notstarted = false;
 | 
				
			||||||
 | 
						bool if_started = false;
 | 
				
			||||||
 | 
						bool if_stopped = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	applet = basename_c(argv[0]);
 | 
						applet = basename_c(argv[0]);
 | 
				
			||||||
	/* Ensure that we are only quiet when explicitly told to be */
 | 
						/* Ensure that we are only quiet when explicitly told to be */
 | 
				
			||||||
@@ -73,12 +86,21 @@ int main(int argc, char **argv)
 | 
				
			|||||||
		    longopts, (int *) 0)) != -1)
 | 
							    longopts, (int *) 0)) != -1)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		switch (opt) {
 | 
							switch (opt) {
 | 
				
			||||||
 | 
							case 'd':
 | 
				
			||||||
 | 
								setenv("RC_DEBUG", "yes", 1);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 'D':
 | 
				
			||||||
 | 
								setenv("RC_NODEPS", "yes", 1);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
		case 'e':
 | 
							case 'e':
 | 
				
			||||||
			service = rc_service_resolve(optarg);
 | 
								service = rc_service_resolve(optarg);
 | 
				
			||||||
			opt = service ? EXIT_SUCCESS : EXIT_FAILURE;
 | 
								opt = service ? EXIT_SUCCESS : EXIT_FAILURE;
 | 
				
			||||||
			free(service);
 | 
								free(service);
 | 
				
			||||||
			return opt;
 | 
								return opt;
 | 
				
			||||||
			/* NOTREACHED */
 | 
								/* NOTREACHED */
 | 
				
			||||||
 | 
							case 'c':
 | 
				
			||||||
 | 
								if_crashed = true;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
		case 'i':
 | 
							case 'i':
 | 
				
			||||||
			if_exists = true;
 | 
								if_exists = true;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
@@ -106,6 +128,15 @@ int main(int argc, char **argv)
 | 
				
			|||||||
			free(service);
 | 
								free(service);
 | 
				
			||||||
			return EXIT_SUCCESS;
 | 
								return EXIT_SUCCESS;
 | 
				
			||||||
			/* NOTREACHED */
 | 
								/* NOTREACHED */
 | 
				
			||||||
 | 
							case 's':
 | 
				
			||||||
 | 
								if_started = true;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 'S':
 | 
				
			||||||
 | 
								if_stopped = true;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 'Z':
 | 
				
			||||||
 | 
								setenv("IN_DRYRUN", "yes", 1);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		case_RC_COMMON_GETOPT
 | 
							case_RC_COMMON_GETOPT
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -121,10 +152,16 @@ int main(int argc, char **argv)
 | 
				
			|||||||
		eerrorx("%s: service `%s' does not exist", applet, *argv);
 | 
							eerrorx("%s: service `%s' does not exist", applet, *argv);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	state = rc_service_state(*argv);
 | 
						state = rc_service_state(*argv);
 | 
				
			||||||
 | 
						if (if_crashed &&  ! (rc_service_daemons_crashed(*argv) && errno != EACCES))
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
	if (if_inactive && ! (state & RC_SERVICE_INACTIVE))
 | 
						if (if_inactive && ! (state & RC_SERVICE_INACTIVE))
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	if (if_notstarted && (state & RC_SERVICE_STARTED))
 | 
						if (if_notstarted && (state & RC_SERVICE_STARTED))
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
						if (if_started && ! (state & RC_SERVICE_STARTED))
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						if (if_stopped && ! (state & RC_SERVICE_STOPPED))
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
	*argv = service;
 | 
						*argv = service;
 | 
				
			||||||
	execv(*argv, argv);
 | 
						execv(*argv, argv);
 | 
				
			||||||
	eerrorx("%s: %s", applet, strerror(errno));
 | 
						eerrorx("%s: %s", applet, strerror(errno));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -54,7 +54,6 @@ const char *usagestring = ""						\
 | 
				
			|||||||
	"Usage: rc-status [options] <runlevel>...\n"		\
 | 
						"Usage: rc-status [options] <runlevel>...\n"		\
 | 
				
			||||||
	"   or: rc-status [options] [-a | -c | -l | -m | -r | -s | -u]";
 | 
						"   or: rc-status [options] [-a | -c | -l | -m | -r | -s | -u]";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool test_crashed = false;
 | 
					 | 
				
			||||||
static RC_DEPTREE *deptree;
 | 
					static RC_DEPTREE *deptree;
 | 
				
			||||||
static RC_STRINGLIST *types;
 | 
					static RC_STRINGLIST *types;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -128,6 +127,8 @@ print_service(const char *service)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	char status[60];
 | 
						char status[60];
 | 
				
			||||||
	char uptime [40];
 | 
						char uptime [40];
 | 
				
			||||||
 | 
						char *child_pid = NULL;
 | 
				
			||||||
 | 
						char *start_time = NULL;
 | 
				
			||||||
	int cols =  printf(" %s", service);
 | 
						int cols =  printf(" %s", service);
 | 
				
			||||||
	const char *c = ecolor(ECOLOR_GOOD);
 | 
						const char *c = ecolor(ECOLOR_GOOD);
 | 
				
			||||||
	RC_SERVICE state = rc_service_state(service);
 | 
						RC_SERVICE state = rc_service_state(service);
 | 
				
			||||||
@@ -143,11 +144,16 @@ print_service(const char *service)
 | 
				
			|||||||
		color = ECOLOR_WARN;
 | 
							color = ECOLOR_WARN;
 | 
				
			||||||
	} else if (state & RC_SERVICE_STARTED) {
 | 
						} else if (state & RC_SERVICE_STARTED) {
 | 
				
			||||||
		errno = 0;
 | 
							errno = 0;
 | 
				
			||||||
		if (test_crashed &&
 | 
							if (rc_service_daemons_crashed(service) && errno != EACCES)
 | 
				
			||||||
		    rc_service_daemons_crashed(service) &&
 | 
					 | 
				
			||||||
		    errno != EACCES)
 | 
					 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			snprintf(status, sizeof(status), " crashed ");
 | 
								child_pid = rc_service_value_get(service, "child_pid");
 | 
				
			||||||
 | 
								start_time = rc_service_value_get(service, "start_time");
 | 
				
			||||||
 | 
								if (start_time && child_pid)
 | 
				
			||||||
 | 
									snprintf(status, sizeof(status), " unsupervised ");
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									snprintf(status, sizeof(status), " crashed ");
 | 
				
			||||||
 | 
								free(child_pid);
 | 
				
			||||||
 | 
								free(start_time);
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			get_uptime(service, uptime, 40);
 | 
								get_uptime(service, uptime, 40);
 | 
				
			||||||
			snprintf(status, sizeof(status), " started %s", uptime);
 | 
								snprintf(status, sizeof(status), " started %s", uptime);
 | 
				
			||||||
@@ -231,8 +237,6 @@ int main(int argc, char **argv)
 | 
				
			|||||||
	char *p, *runlevel = NULL;
 | 
						char *p, *runlevel = NULL;
 | 
				
			||||||
	int opt, retval = 0;
 | 
						int opt, retval = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	test_crashed = _rc_can_find_pids();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	applet = basename_c(argv[0]);
 | 
						applet = basename_c(argv[0]);
 | 
				
			||||||
	while ((opt = getopt_long(argc, argv, getoptstring, longopts,
 | 
						while ((opt = getopt_long(argc, argv, getoptstring, longopts,
 | 
				
			||||||
				  (int *) 0)) != -1)
 | 
									  (int *) 0)) != -1)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -62,7 +62,7 @@ add(const char *runlevel, const char *service)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	if (!rc_service_exists(service)) {
 | 
						if (!rc_service_exists(service)) {
 | 
				
			||||||
		if (errno == ENOEXEC)
 | 
							if (errno == ENOEXEC)
 | 
				
			||||||
			eerror("%s: service `%s' is not executeable",
 | 
								eerror("%s: service `%s' is not executable",
 | 
				
			||||||
			    applet, service);
 | 
								    applet, service);
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			eerror("%s: service `%s' does not exist",
 | 
								eerror("%s: service `%s' does not exist",
 | 
				
			||||||
@@ -166,7 +166,7 @@ show(RC_STRINGLIST *runlevels, bool verbose)
 | 
				
			|||||||
	RC_STRING *runlevel;
 | 
						RC_STRING *runlevel;
 | 
				
			||||||
	RC_STRINGLIST *in;
 | 
						RC_STRINGLIST *in;
 | 
				
			||||||
	bool inone;
 | 
						bool inone;
 | 
				
			||||||
	char buffer[PATH_MAX];
 | 
						char *buffer = NULL;
 | 
				
			||||||
	size_t l;
 | 
						size_t l;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rc_stringlist_sort(&services);
 | 
						rc_stringlist_sort(&services);
 | 
				
			||||||
@@ -182,9 +182,11 @@ show(RC_STRINGLIST *runlevels, bool verbose)
 | 
				
			|||||||
				inone = true;
 | 
									inone = true;
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				l = strlen(runlevel->value);
 | 
									l = strlen(runlevel->value);
 | 
				
			||||||
 | 
									buffer = xmalloc(l+1);
 | 
				
			||||||
				memset (buffer, ' ', l);
 | 
									memset (buffer, ' ', l);
 | 
				
			||||||
				buffer[l] = 0;
 | 
									buffer[l] = 0;
 | 
				
			||||||
				rc_stringlist_add (in, buffer);
 | 
									rc_stringlist_add (in, buffer);
 | 
				
			||||||
 | 
									free(buffer);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										27
									
								
								src/rc/rc.c
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								src/rc/rc.c
									
									
									
									
									
								
							@@ -78,9 +78,6 @@ const char *usagestring = ""					\
 | 
				
			|||||||
#define INITSH                  RC_LIBEXECDIR "/sh/init.sh"
 | 
					#define INITSH                  RC_LIBEXECDIR "/sh/init.sh"
 | 
				
			||||||
#define INITEARLYSH             RC_LIBEXECDIR "/sh/init-early.sh"
 | 
					#define INITEARLYSH             RC_LIBEXECDIR "/sh/init-early.sh"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SHUTDOWN                "/sbin/shutdown"
 | 
					 | 
				
			||||||
#define SULOGIN                 "/sbin/sulogin"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define INTERACTIVE             RC_SVCDIR "/interactive"
 | 
					#define INTERACTIVE             RC_SVCDIR "/interactive"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define DEVBOOT			"/dev/.rcboot"
 | 
					#define DEVBOOT			"/dev/.rcboot"
 | 
				
			||||||
@@ -288,8 +285,8 @@ open_shell(void)
 | 
				
			|||||||
	/* VSERVER systems cannot really drop to shells */
 | 
						/* VSERVER systems cannot really drop to shells */
 | 
				
			||||||
	if (sys && strcmp(sys, RC_SYS_VSERVER) == 0)
 | 
						if (sys && strcmp(sys, RC_SYS_VSERVER) == 0)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		execl("/sbin/halt", "/sbin/halt", "-f", (char *) NULL);
 | 
							execlp("halt", "halt", "-f", (char *) NULL);
 | 
				
			||||||
		eerrorx("%s: unable to exec `/sbin/halt': %s",
 | 
							eerrorx("%s: unable to exec `halt -f': %s",
 | 
				
			||||||
		    applet, strerror(errno));
 | 
							    applet, strerror(errno));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -336,26 +333,26 @@ set_krunlevel(const char *level)
 | 
				
			|||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static size_t
 | 
					static char *get_krunlevel(void)
 | 
				
			||||||
get_krunlevel(char *buffer, int buffer_len)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						char *buffer = NULL;
 | 
				
			||||||
	FILE *fp;
 | 
						FILE *fp;
 | 
				
			||||||
	size_t i = 0;
 | 
						size_t i = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!exists(RC_KRUNLEVEL))
 | 
						if (!exists(RC_KRUNLEVEL))
 | 
				
			||||||
		return 0;
 | 
							return NULL;
 | 
				
			||||||
	if (!(fp = fopen(RC_KRUNLEVEL, "r"))) {
 | 
						if (!(fp = fopen(RC_KRUNLEVEL, "r"))) {
 | 
				
			||||||
		eerror("fopen `%s': %s", RC_KRUNLEVEL, strerror(errno));
 | 
							eerror("fopen `%s': %s", RC_KRUNLEVEL, strerror(errno));
 | 
				
			||||||
		return 0;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (fgets(buffer, buffer_len, fp)) {
 | 
						if (getline(&buffer, &i, fp) != -1) {
 | 
				
			||||||
		i = strlen(buffer);
 | 
							i = strlen(buffer);
 | 
				
			||||||
		if (buffer[i - 1] == '\n')
 | 
							if (buffer[i - 1] == '\n')
 | 
				
			||||||
			buffer[i - 1] = 0;
 | 
								buffer[i - 1] = 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	fclose(fp);
 | 
						fclose(fp);
 | 
				
			||||||
	return i;
 | 
						return buffer;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
@@ -505,6 +502,9 @@ do_sysinit()
 | 
				
			|||||||
	 * sys */
 | 
						 * sys */
 | 
				
			||||||
	if ((sys = rc_sys()))
 | 
						if ((sys = rc_sys()))
 | 
				
			||||||
		setenv("RC_SYS", sys, 1);
 | 
							setenv("RC_SYS", sys, 1);
 | 
				
			||||||
 | 
						/* force an update of the dependency tree */
 | 
				
			||||||
 | 
						if ((main_deptree = _rc_deptree_load(1, NULL)) == NULL)
 | 
				
			||||||
 | 
							eerrorx("failed to load deptree");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool
 | 
					static bool
 | 
				
			||||||
@@ -743,7 +743,7 @@ int main(int argc, char **argv)
 | 
				
			|||||||
	RC_STRING *service;
 | 
						RC_STRING *service;
 | 
				
			||||||
	bool going_down = false;
 | 
						bool going_down = false;
 | 
				
			||||||
	int depoptions = RC_DEP_STRICT | RC_DEP_TRACE;
 | 
						int depoptions = RC_DEP_STRICT | RC_DEP_TRACE;
 | 
				
			||||||
	char krunlevel [PATH_MAX];
 | 
						char *krunlevel = NULL;
 | 
				
			||||||
	char pidstr[10];
 | 
						char pidstr[10];
 | 
				
			||||||
	int opt;
 | 
						int opt;
 | 
				
			||||||
	bool parallel;
 | 
						bool parallel;
 | 
				
			||||||
@@ -892,7 +892,8 @@ int main(int argc, char **argv)
 | 
				
			|||||||
		    (strcmp(newlevel, RC_LEVEL_SYSINIT) != 0 &&
 | 
							    (strcmp(newlevel, RC_LEVEL_SYSINIT) != 0 &&
 | 
				
			||||||
			strcmp(newlevel, getenv("RC_BOOTLEVEL")) != 0))
 | 
								strcmp(newlevel, getenv("RC_BOOTLEVEL")) != 0))
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if (get_krunlevel(krunlevel, sizeof(krunlevel))) {
 | 
								krunlevel = get_krunlevel();
 | 
				
			||||||
 | 
								if (krunlevel) {
 | 
				
			||||||
				newlevel = krunlevel;
 | 
									newlevel = krunlevel;
 | 
				
			||||||
				set_krunlevel(NULL);
 | 
									set_krunlevel(NULL);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -59,13 +59,14 @@ static struct pam_conv conv = { NULL, NULL};
 | 
				
			|||||||
#include "queue.h"
 | 
					#include "queue.h"
 | 
				
			||||||
#include "rc.h"
 | 
					#include "rc.h"
 | 
				
			||||||
#include "rc-misc.h"
 | 
					#include "rc-misc.h"
 | 
				
			||||||
 | 
					#include "rc-pipes.h"
 | 
				
			||||||
#include "rc-schedules.h"
 | 
					#include "rc-schedules.h"
 | 
				
			||||||
#include "_usage.h"
 | 
					#include "_usage.h"
 | 
				
			||||||
#include "helpers.h"
 | 
					#include "helpers.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const char *applet = NULL;
 | 
					const char *applet = NULL;
 | 
				
			||||||
const char *extraopts = NULL;
 | 
					const char *extraopts = NULL;
 | 
				
			||||||
const char *getoptstring = "I:KN:PR:Sa:bc:d:e:g:ik:mn:op:s:tu:r:w:x:1:2:" \
 | 
					const char *getoptstring = "I:KN:PR:Sa:bc:d:e:g:ik:mn:op:s:tu:r:w:x:1:2:3:4:" \
 | 
				
			||||||
	getoptstring_COMMON;
 | 
						getoptstring_COMMON;
 | 
				
			||||||
const struct option longopts[] = {
 | 
					const struct option longopts[] = {
 | 
				
			||||||
	{ "ionice",       1, NULL, 'I'},
 | 
						{ "ionice",       1, NULL, 'I'},
 | 
				
			||||||
@@ -93,6 +94,8 @@ const struct option longopts[] = {
 | 
				
			|||||||
	{ "exec",         1, NULL, 'x'},
 | 
						{ "exec",         1, NULL, 'x'},
 | 
				
			||||||
	{ "stdout",       1, NULL, '1'},
 | 
						{ "stdout",       1, NULL, '1'},
 | 
				
			||||||
	{ "stderr",       1, NULL, '2'},
 | 
						{ "stderr",       1, NULL, '2'},
 | 
				
			||||||
 | 
						{ "stdout-logger",1, NULL, '3'},
 | 
				
			||||||
 | 
						{ "stderr-logger",1, NULL, '4'},
 | 
				
			||||||
	{ "progress",     0, NULL, 'P'},
 | 
						{ "progress",     0, NULL, 'P'},
 | 
				
			||||||
	longopts_COMMON
 | 
						longopts_COMMON
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@@ -122,6 +125,8 @@ const char * const longopts_help[] = {
 | 
				
			|||||||
	"Binary to start/stop",
 | 
						"Binary to start/stop",
 | 
				
			||||||
	"Redirect stdout to file",
 | 
						"Redirect stdout to file",
 | 
				
			||||||
	"Redirect stderr to file",
 | 
						"Redirect stderr to file",
 | 
				
			||||||
 | 
						"Redirect stdout to process",
 | 
				
			||||||
 | 
						"Redirect stderr to process",
 | 
				
			||||||
	"Print dots each second while waiting",
 | 
						"Print dots each second while waiting",
 | 
				
			||||||
	longopts_help_COMMON
 | 
						longopts_help_COMMON
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@@ -254,6 +259,7 @@ int main(int argc, char **argv)
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int opt;
 | 
						int opt;
 | 
				
			||||||
 | 
						size_t size = 0;
 | 
				
			||||||
	bool start = false;
 | 
						bool start = false;
 | 
				
			||||||
	bool stop = false;
 | 
						bool stop = false;
 | 
				
			||||||
	bool oknodo = false;
 | 
						bool oknodo = false;
 | 
				
			||||||
@@ -275,10 +281,13 @@ int main(int argc, char **argv)
 | 
				
			|||||||
	int tid = 0;
 | 
						int tid = 0;
 | 
				
			||||||
	char *redirect_stderr = NULL;
 | 
						char *redirect_stderr = NULL;
 | 
				
			||||||
	char *redirect_stdout = NULL;
 | 
						char *redirect_stdout = NULL;
 | 
				
			||||||
 | 
						char *stderr_process = NULL;
 | 
				
			||||||
 | 
						char *stdout_process = NULL;
 | 
				
			||||||
	int stdin_fd;
 | 
						int stdin_fd;
 | 
				
			||||||
	int stdout_fd;
 | 
						int stdout_fd;
 | 
				
			||||||
	int stderr_fd;
 | 
						int stderr_fd;
 | 
				
			||||||
	pid_t pid, spid;
 | 
						pid_t pid, spid;
 | 
				
			||||||
 | 
						RC_PIDLIST *pids;
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
	char *svcname = getenv("RC_SVCNAME");
 | 
						char *svcname = getenv("RC_SVCNAME");
 | 
				
			||||||
	RC_STRINGLIST *env_list;
 | 
						RC_STRINGLIST *env_list;
 | 
				
			||||||
@@ -286,10 +295,10 @@ int main(int argc, char **argv)
 | 
				
			|||||||
	char *tmp, *newpath, *np;
 | 
						char *tmp, *newpath, *np;
 | 
				
			||||||
	char *p;
 | 
						char *p;
 | 
				
			||||||
	char *token;
 | 
						char *token;
 | 
				
			||||||
	char exec_file[PATH_MAX];
 | 
						char *exec_file = NULL;
 | 
				
			||||||
	struct passwd *pw;
 | 
						struct passwd *pw;
 | 
				
			||||||
	struct group *gr;
 | 
						struct group *gr;
 | 
				
			||||||
	char line[130];
 | 
						char *line = NULL;
 | 
				
			||||||
	FILE *fp;
 | 
						FILE *fp;
 | 
				
			||||||
	size_t len;
 | 
						size_t len;
 | 
				
			||||||
	mode_t numask = 022;
 | 
						mode_t numask = 022;
 | 
				
			||||||
@@ -498,6 +507,14 @@ int main(int argc, char **argv)
 | 
				
			|||||||
			redirect_stderr = optarg;
 | 
								redirect_stderr = optarg;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case '3':   /* --stdout-logger "command to run for stdout logging" */
 | 
				
			||||||
 | 
								stdout_process = optarg;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case '4':  /* --stderr-logger "command to run for stderr logging" */
 | 
				
			||||||
 | 
								stderr_process = optarg;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		case_RC_COMMON_GETOPT
 | 
							case_RC_COMMON_GETOPT
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -549,6 +566,9 @@ int main(int argc, char **argv)
 | 
				
			|||||||
		if (redirect_stdout || redirect_stderr)
 | 
							if (redirect_stdout || redirect_stderr)
 | 
				
			||||||
			eerrorx("%s: --stdout and --stderr are only relevant"
 | 
								eerrorx("%s: --stdout and --stderr are only relevant"
 | 
				
			||||||
			    " with --start", applet);
 | 
								    " with --start", applet);
 | 
				
			||||||
 | 
							if (stdout_process || stderr_process)
 | 
				
			||||||
 | 
								eerrorx("%s: --stdout-logger and --stderr-logger are only relevant"
 | 
				
			||||||
 | 
								    " with --start", applet);
 | 
				
			||||||
		if (start_wait)
 | 
							if (start_wait)
 | 
				
			||||||
			ewarn("using --wait with --stop has no effect,"
 | 
								ewarn("using --wait with --stop has no effect,"
 | 
				
			||||||
			    " use --retry instead");
 | 
								    " use --retry instead");
 | 
				
			||||||
@@ -561,6 +581,15 @@ int main(int argc, char **argv)
 | 
				
			|||||||
		if ((redirect_stdout || redirect_stderr) && !background)
 | 
							if ((redirect_stdout || redirect_stderr) && !background)
 | 
				
			||||||
			eerrorx("%s: --stdout and --stderr are only relevant"
 | 
								eerrorx("%s: --stdout and --stderr are only relevant"
 | 
				
			||||||
			    " with --background", applet);
 | 
								    " with --background", applet);
 | 
				
			||||||
 | 
							if ((stdout_process || stderr_process) && !background)
 | 
				
			||||||
 | 
								eerrorx("%s: --stdout-logger and --stderr-logger are only relevant"
 | 
				
			||||||
 | 
								    " with --background", applet);
 | 
				
			||||||
 | 
							if (redirect_stdout && stdout_process)
 | 
				
			||||||
 | 
								eerrorx("%s: do not use --stdout and --stdout-logger together",
 | 
				
			||||||
 | 
										applet);
 | 
				
			||||||
 | 
							if (redirect_stderr && stderr_process)
 | 
				
			||||||
 | 
								eerrorx("%s: do not use --stderr and --stderr-logger together",
 | 
				
			||||||
 | 
										applet);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Expand ~ */
 | 
						/* Expand ~ */
 | 
				
			||||||
@@ -576,26 +605,22 @@ int main(int argc, char **argv)
 | 
				
			|||||||
		if (*exec == '/' || *exec == '.') {
 | 
							if (*exec == '/' || *exec == '.') {
 | 
				
			||||||
			/* Full or relative path */
 | 
								/* Full or relative path */
 | 
				
			||||||
			if (ch_root)
 | 
								if (ch_root)
 | 
				
			||||||
				snprintf(exec_file, sizeof(exec_file),
 | 
									xasprintf(&exec_file, "%s/%s", ch_root, exec);
 | 
				
			||||||
				    "%s/%s", ch_root, exec);
 | 
					 | 
				
			||||||
			else
 | 
								else
 | 
				
			||||||
				snprintf(exec_file, sizeof(exec_file),
 | 
									xasprintf(&exec_file, "%s", exec);
 | 
				
			||||||
				    "%s", exec);
 | 
					 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			/* Something in $PATH */
 | 
								/* Something in $PATH */
 | 
				
			||||||
			p = tmp = xstrdup(getenv("PATH"));
 | 
								p = tmp = xstrdup(getenv("PATH"));
 | 
				
			||||||
			*exec_file = '\0';
 | 
								exec_file = NULL;
 | 
				
			||||||
			while ((token = strsep(&p, ":"))) {
 | 
								while ((token = strsep(&p, ":"))) {
 | 
				
			||||||
				if (ch_root)
 | 
									if (ch_root)
 | 
				
			||||||
					snprintf(exec_file, sizeof(exec_file),
 | 
										xasprintf(&exec_file, "%s/%s/%s", ch_root, token, exec);
 | 
				
			||||||
					    "%s/%s/%s",
 | 
					 | 
				
			||||||
					    ch_root, token, exec);
 | 
					 | 
				
			||||||
				else
 | 
									else
 | 
				
			||||||
					snprintf(exec_file, sizeof(exec_file),
 | 
										xasprintf(&exec_file, "%s/%s", token, exec);
 | 
				
			||||||
					    "%s/%s", token, exec);
 | 
									if (exec_file && exists(exec_file))
 | 
				
			||||||
				if (exists(exec_file))
 | 
					 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				*exec_file = '\0';
 | 
									free(exec_file);
 | 
				
			||||||
 | 
									exec_file = NULL;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			free(tmp);
 | 
								free(tmp);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -603,8 +628,8 @@ int main(int argc, char **argv)
 | 
				
			|||||||
	if (start && !exists(exec_file)) {
 | 
						if (start && !exists(exec_file)) {
 | 
				
			||||||
		eerror("%s: %s does not exist", applet,
 | 
							eerror("%s: %s does not exist", applet,
 | 
				
			||||||
		    *exec_file ? exec_file : exec);
 | 
							    *exec_file ? exec_file : exec);
 | 
				
			||||||
 | 
							free(exec_file);
 | 
				
			||||||
		exit(EXIT_FAILURE);
 | 
							exit(EXIT_FAILURE);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (start && retry)
 | 
						if (start && retry)
 | 
				
			||||||
		ewarn("using --retry with --start has no effect,"
 | 
							ewarn("using --retry with --start has no effect,"
 | 
				
			||||||
@@ -616,7 +641,10 @@ int main(int argc, char **argv)
 | 
				
			|||||||
	if (interpreted && !pidfile) {
 | 
						if (interpreted && !pidfile) {
 | 
				
			||||||
		fp = fopen(exec_file, "r");
 | 
							fp = fopen(exec_file, "r");
 | 
				
			||||||
		if (fp) {
 | 
							if (fp) {
 | 
				
			||||||
			p = fgets(line, sizeof(line), fp);
 | 
								line = NULL;
 | 
				
			||||||
 | 
								if (getline(&line, &size, fp) == -1)
 | 
				
			||||||
 | 
									eerrorx("%s: %s", applet, strerror(errno));
 | 
				
			||||||
 | 
								p = line;
 | 
				
			||||||
			fclose(fp);
 | 
								fclose(fp);
 | 
				
			||||||
			if (p != NULL && line[0] == '#' && line[1] == '!') {
 | 
								if (p != NULL && line[0] == '#' && line[1] == '!') {
 | 
				
			||||||
				p = line + 2;
 | 
									p = line + 2;
 | 
				
			||||||
@@ -628,7 +656,8 @@ int main(int argc, char **argv)
 | 
				
			|||||||
				if (p[len] == '\n')
 | 
									if (p[len] == '\n')
 | 
				
			||||||
					p[len] = '\0';
 | 
										p[len] = '\0';
 | 
				
			||||||
				token = strsep(&p, " ");
 | 
									token = strsep(&p, " ");
 | 
				
			||||||
				strncpy(exec_file, token, sizeof(exec_file));
 | 
									free(exec_file);
 | 
				
			||||||
 | 
									xasprintf(&exec_file, "%s", token);
 | 
				
			||||||
				opt = 0;
 | 
									opt = 0;
 | 
				
			||||||
				for (nav = argv; *nav; nav++)
 | 
									for (nav = argv; *nav; nav++)
 | 
				
			||||||
					opt++;
 | 
										opt++;
 | 
				
			||||||
@@ -656,8 +685,15 @@ int main(int argc, char **argv)
 | 
				
			|||||||
			parse_schedule(applet, "0", sig);
 | 
								parse_schedule(applet, "0", sig);
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			parse_schedule(applet, NULL, sig);
 | 
								parse_schedule(applet, NULL, sig);
 | 
				
			||||||
 | 
							if (pidfile) {
 | 
				
			||||||
 | 
								pid = get_pid(applet, pidfile);
 | 
				
			||||||
 | 
								if (pid == -1 && errno != ENOENT)
 | 
				
			||||||
 | 
									exit(EXIT_FAILURE);
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								pid = 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		i = run_stop_schedule(applet, exec, (const char *const *)margv,
 | 
							i = run_stop_schedule(applet, exec, (const char *const *)margv,
 | 
				
			||||||
		    get_pid(applet, pidfile), uid, test, progress, false);
 | 
							    pid, uid, test, progress, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (i < 0)
 | 
							if (i < 0)
 | 
				
			||||||
			/* We failed to stop something */
 | 
								/* We failed to stop something */
 | 
				
			||||||
@@ -683,10 +719,14 @@ int main(int argc, char **argv)
 | 
				
			|||||||
	else
 | 
						else
 | 
				
			||||||
		pid = 0;
 | 
							pid = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (do_stop(applet, exec, (const char * const *)margv, pid, uid,
 | 
						if (pid)
 | 
				
			||||||
		0, test, false) > 0)
 | 
							pids = rc_find_pids(NULL, NULL, 0, pid);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							pids = rc_find_pids(exec, (const char * const *) argv, uid, 0);
 | 
				
			||||||
 | 
						if (pids)
 | 
				
			||||||
		eerrorx("%s: %s is already running", applet, exec);
 | 
							eerrorx("%s: %s is already running", applet, exec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						free(pids);
 | 
				
			||||||
	if (test) {
 | 
						if (test) {
 | 
				
			||||||
		if (rc_yesno(getenv("EINFO_QUIET")))
 | 
							if (rc_yesno(getenv("EINFO_QUIET")))
 | 
				
			||||||
			exit (EXIT_SUCCESS);
 | 
								exit (EXIT_SUCCESS);
 | 
				
			||||||
@@ -872,6 +912,12 @@ int main(int argc, char **argv)
 | 
				
			|||||||
				eerrorx("%s: unable to open the logfile"
 | 
									eerrorx("%s: unable to open the logfile"
 | 
				
			||||||
				    " for stdout `%s': %s",
 | 
									    " for stdout `%s': %s",
 | 
				
			||||||
				    applet, redirect_stdout, strerror(errno));
 | 
									    applet, redirect_stdout, strerror(errno));
 | 
				
			||||||
 | 
							}else if (stdout_process) {
 | 
				
			||||||
 | 
								stdout_fd = rc_pipe_command(stdout_process);
 | 
				
			||||||
 | 
								if (stdout_fd == -1)
 | 
				
			||||||
 | 
									eerrorx("%s: unable to open the logging process"
 | 
				
			||||||
 | 
									    " for stdout `%s': %s",
 | 
				
			||||||
 | 
									    applet, stdout_process, strerror(errno));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (redirect_stderr) {
 | 
							if (redirect_stderr) {
 | 
				
			||||||
			if ((stderr_fd = open(redirect_stderr,
 | 
								if ((stderr_fd = open(redirect_stderr,
 | 
				
			||||||
@@ -880,13 +926,21 @@ int main(int argc, char **argv)
 | 
				
			|||||||
				eerrorx("%s: unable to open the logfile"
 | 
									eerrorx("%s: unable to open the logfile"
 | 
				
			||||||
				    " for stderr `%s': %s",
 | 
									    " for stderr `%s': %s",
 | 
				
			||||||
				    applet, redirect_stderr, strerror(errno));
 | 
									    applet, redirect_stderr, strerror(errno));
 | 
				
			||||||
 | 
							}else if (stderr_process) {
 | 
				
			||||||
 | 
								stderr_fd = rc_pipe_command(stderr_process);
 | 
				
			||||||
 | 
								if (stderr_fd == -1)
 | 
				
			||||||
 | 
									eerrorx("%s: unable to open the logging process"
 | 
				
			||||||
 | 
									    " for stderr `%s': %s",
 | 
				
			||||||
 | 
									    applet, stderr_process, strerror(errno));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (background)
 | 
							if (background)
 | 
				
			||||||
			dup2(stdin_fd, STDIN_FILENO);
 | 
								dup2(stdin_fd, STDIN_FILENO);
 | 
				
			||||||
		if (background || redirect_stdout || rc_yesno(getenv("EINFO_QUIET")))
 | 
							if (background || redirect_stdout || stdout_process
 | 
				
			||||||
 | 
									|| rc_yesno(getenv("EINFO_QUIET")))
 | 
				
			||||||
			dup2(stdout_fd, STDOUT_FILENO);
 | 
								dup2(stdout_fd, STDOUT_FILENO);
 | 
				
			||||||
		if (background || redirect_stderr || rc_yesno(getenv("EINFO_QUIET")))
 | 
							if (background || redirect_stderr || stderr_process
 | 
				
			||||||
 | 
									|| rc_yesno(getenv("EINFO_QUIET")))
 | 
				
			||||||
			dup2(stderr_fd, STDERR_FILENO);
 | 
								dup2(stderr_fd, STDERR_FILENO);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (i = getdtablesize() - 1; i >= 3; --i)
 | 
							for (i = getdtablesize() - 1; i >= 3; --i)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -67,7 +67,7 @@ static struct pam_conv conv = { NULL, NULL};
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const char *applet = NULL;
 | 
					const char *applet = NULL;
 | 
				
			||||||
const char *extraopts = NULL;
 | 
					const char *extraopts = NULL;
 | 
				
			||||||
const char *getoptstring = "D:d:e:g:I:Kk:m:N:p:R:r:Su:1:2:" \
 | 
					const char *getoptstring = "D:d:e:g:I:Kk:m:N:p:R:r:Su:1:2:3" \
 | 
				
			||||||
	getoptstring_COMMON;
 | 
						getoptstring_COMMON;
 | 
				
			||||||
const struct option longopts[] = {
 | 
					const struct option longopts[] = {
 | 
				
			||||||
	{ "respawn-delay",        1, NULL, 'D'},
 | 
						{ "respawn-delay",        1, NULL, 'D'},
 | 
				
			||||||
@@ -87,6 +87,7 @@ const struct option longopts[] = {
 | 
				
			|||||||
	{ "user",         1, NULL, 'u'},
 | 
						{ "user",         1, NULL, 'u'},
 | 
				
			||||||
	{ "stdout",       1, NULL, '1'},
 | 
						{ "stdout",       1, NULL, '1'},
 | 
				
			||||||
	{ "stderr",       1, NULL, '2'},
 | 
						{ "stderr",       1, NULL, '2'},
 | 
				
			||||||
 | 
						{ "reexec",       0, NULL, '3'},
 | 
				
			||||||
	longopts_COMMON
 | 
						longopts_COMMON
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
const char * const longopts_help[] = {
 | 
					const char * const longopts_help[] = {
 | 
				
			||||||
@@ -107,6 +108,7 @@ const char * const longopts_help[] = {
 | 
				
			|||||||
	"Change the process user",
 | 
						"Change the process user",
 | 
				
			||||||
	"Redirect stdout to file",
 | 
						"Redirect stdout to file",
 | 
				
			||||||
	"Redirect stderr to file",
 | 
						"Redirect stderr to file",
 | 
				
			||||||
 | 
						"reexec (used internally)",
 | 
				
			||||||
	longopts_help_COMMON
 | 
						longopts_help_COMMON
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
const char *usagestring = NULL;
 | 
					const char *usagestring = NULL;
 | 
				
			||||||
@@ -127,6 +129,13 @@ static bool exiting = false;
 | 
				
			|||||||
#ifdef TIOCNOTTY
 | 
					#ifdef TIOCNOTTY
 | 
				
			||||||
static int tty_fd = -1;
 | 
					static int tty_fd = -1;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					static pid_t child_pid;
 | 
				
			||||||
 | 
					static int respawn_count = 0;
 | 
				
			||||||
 | 
					static int respawn_delay = 0;
 | 
				
			||||||
 | 
					static int respawn_max = 10;
 | 
				
			||||||
 | 
					static int respawn_period = 5;
 | 
				
			||||||
 | 
					static char *pidfile = NULL;
 | 
				
			||||||
 | 
					static char *svcname = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern char **environ;
 | 
					extern char **environ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -150,8 +159,89 @@ static void cleanup(void)
 | 
				
			|||||||
	free(changeuser);
 | 
						free(changeuser);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void child_process(char *exec, char **argv, char *svcname,
 | 
					static void re_exec_supervisor(void)
 | 
				
			||||||
		int start_count)
 | 
					{
 | 
				
			||||||
 | 
						syslog(LOG_WARNING, "Re-executing for %s", svcname);
 | 
				
			||||||
 | 
						execlp("supervise-daemon", "supervise-daemon", svcname, "--reexec",
 | 
				
			||||||
 | 
								(char *) NULL);
 | 
				
			||||||
 | 
						syslog(LOG_ERR, "Unable to execute supervise-daemon: %s",
 | 
				
			||||||
 | 
								strerror(errno));
 | 
				
			||||||
 | 
						exit(EXIT_FAILURE);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_signal(int sig)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int serrno = errno;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						syslog(LOG_WARNING, "caught signal %d", sig);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (sig == SIGTERM)
 | 
				
			||||||
 | 
							exiting = true;
 | 
				
			||||||
 | 
						/* Restore errno */
 | 
				
			||||||
 | 
						errno = serrno;
 | 
				
			||||||
 | 
						if (! exiting)
 | 
				
			||||||
 | 
							re_exec_supervisor();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static char *make_cmdline(char **argv)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						char **c;
 | 
				
			||||||
 | 
						char *cmdline = NULL;
 | 
				
			||||||
 | 
						size_t len = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (c = argv; c && *c; c++)
 | 
				
			||||||
 | 
							len += (strlen(*c) + 1);
 | 
				
			||||||
 | 
						cmdline = xmalloc(len+1);
 | 
				
			||||||
 | 
						memset(cmdline, 0, len+1);
 | 
				
			||||||
 | 
						for (c = argv; c && *c; c++) {
 | 
				
			||||||
 | 
							strcat(cmdline, *c);
 | 
				
			||||||
 | 
							strcat(cmdline, " ");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return cmdline;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void child_process(char *exec, char **argv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	RC_STRINGLIST *env_list;
 | 
						RC_STRINGLIST *env_list;
 | 
				
			||||||
	RC_STRING *env;
 | 
						RC_STRING *env;
 | 
				
			||||||
@@ -161,8 +251,7 @@ static void child_process(char *exec, char **argv, char *svcname,
 | 
				
			|||||||
	size_t len;
 | 
						size_t len;
 | 
				
			||||||
	char *newpath;
 | 
						char *newpath;
 | 
				
			||||||
	char *np;
 | 
						char *np;
 | 
				
			||||||
	char **c;
 | 
						char *cmdline = NULL;
 | 
				
			||||||
	char cmdline[PATH_MAX];
 | 
					 | 
				
			||||||
	time_t start_time;
 | 
						time_t start_time;
 | 
				
			||||||
	char start_count_string[20];
 | 
						char start_count_string[20];
 | 
				
			||||||
	char start_time_string[20];
 | 
						char start_time_string[20];
 | 
				
			||||||
@@ -176,11 +265,13 @@ static void child_process(char *exec, char **argv, char *svcname,
 | 
				
			|||||||
	setsid();
 | 
						setsid();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (svcname) {
 | 
						if (svcname) {
 | 
				
			||||||
start_time = time(NULL);
 | 
							start_time = time(NULL);
 | 
				
			||||||
from_time_t(start_time_string, start_time);
 | 
							from_time_t(start_time_string, start_time);
 | 
				
			||||||
		rc_service_value_set(svcname, "start_time", start_time_string);
 | 
							rc_service_value_set(svcname, "start_time", start_time_string);
 | 
				
			||||||
sprintf(start_count_string, "%i", start_count);
 | 
							sprintf(start_count_string, "%i", respawn_count);
 | 
				
			||||||
		rc_service_value_set(svcname, "start_count", start_count_string);
 | 
							rc_service_value_set(svcname, "start_count", start_count_string);
 | 
				
			||||||
 | 
							sprintf(start_count_string, "%d", getpid());
 | 
				
			||||||
 | 
							rc_service_value_set(svcname, "child_pid", start_count_string);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (nicelevel) {
 | 
						if (nicelevel) {
 | 
				
			||||||
@@ -320,15 +411,9 @@ sprintf(start_count_string, "%i", start_count);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	for (i = getdtablesize() - 1; i >= 3; --i)
 | 
						for (i = getdtablesize() - 1; i >= 3; --i)
 | 
				
			||||||
		fcntl(i, F_SETFD, FD_CLOEXEC);
 | 
							fcntl(i, F_SETFD, FD_CLOEXEC);
 | 
				
			||||||
 | 
						cmdline = make_cmdline(argv);
 | 
				
			||||||
	*cmdline = '\0';
 | 
						syslog(LOG_INFO, "Child command line: %s", cmdline);
 | 
				
			||||||
	c = argv;
 | 
						free(cmdline);
 | 
				
			||||||
	while (*c) {
 | 
					 | 
				
			||||||
		strcat(cmdline, *c);
 | 
					 | 
				
			||||||
		strcat(cmdline, " ");
 | 
					 | 
				
			||||||
		c++;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	syslog(LOG_INFO, "Running command line: %s", cmdline);
 | 
					 | 
				
			||||||
	execvp(exec, argv);
 | 
						execvp(exec, argv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_PAM
 | 
					#ifdef HAVE_PAM
 | 
				
			||||||
@@ -338,108 +423,166 @@ sprintf(start_count_string, "%i", start_count);
 | 
				
			|||||||
	eerrorx("%s: failed to exec `%s': %s", applet, exec,strerror(errno));
 | 
						eerrorx("%s: failed to exec `%s': %s", applet, exec,strerror(errno));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handle_signal(int sig)
 | 
					static void supervisor(char *exec, char **argv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int serrno = errno;
 | 
						FILE *fp;
 | 
				
			||||||
	char signame[10] = { '\0' };
 | 
						int i;
 | 
				
			||||||
 | 
						int nkilled;
 | 
				
			||||||
 | 
						time_t respawn_now= 0;
 | 
				
			||||||
 | 
						time_t first_spawn= 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (sig) {
 | 
					#ifndef RC_DEBUG
 | 
				
			||||||
	case SIGINT:
 | 
						signal_setup_restart(SIGHUP, handle_signal);
 | 
				
			||||||
		snprintf(signame, sizeof(signame), "SIGINT");
 | 
						signal_setup_restart(SIGINT, handle_signal);
 | 
				
			||||||
		break;
 | 
						signal_setup_restart(SIGQUIT, handle_signal);
 | 
				
			||||||
	case SIGTERM:
 | 
						signal_setup_restart(SIGILL, handle_signal);
 | 
				
			||||||
		snprintf(signame, sizeof(signame), "SIGTERM");
 | 
						signal_setup_restart(SIGABRT, handle_signal);
 | 
				
			||||||
		break;
 | 
						signal_setup_restart(SIGFPE, handle_signal);
 | 
				
			||||||
	case SIGQUIT:
 | 
						signal_setup_restart(SIGSEGV, handle_signal);
 | 
				
			||||||
		snprintf(signame, sizeof(signame), "SIGQUIT");
 | 
						signal_setup_restart(SIGPIPE, handle_signal);
 | 
				
			||||||
		break;
 | 
						signal_setup_restart(SIGALRM, handle_signal);
 | 
				
			||||||
 | 
						signal_setup(SIGTERM, handle_signal);
 | 
				
			||||||
 | 
						signal_setup_restart(SIGUSR1, handle_signal);
 | 
				
			||||||
 | 
						signal_setup_restart(SIGUSR2, handle_signal);
 | 
				
			||||||
 | 
						signal_setup_restart(SIGBUS, handle_signal);
 | 
				
			||||||
 | 
					#ifdef SIGPOLL
 | 
				
			||||||
 | 
						signal_setup_restart(SIGPOLL, handle_signal);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						signal_setup_restart(SIGPROF, handle_signal);
 | 
				
			||||||
 | 
						signal_setup_restart(SIGSYS, handle_signal);
 | 
				
			||||||
 | 
						signal_setup_restart(SIGTRAP, handle_signal);
 | 
				
			||||||
 | 
						signal_setup_restart(SIGVTALRM, handle_signal);
 | 
				
			||||||
 | 
						signal_setup_restart(SIGXCPU, handle_signal);
 | 
				
			||||||
 | 
						signal_setup_restart(SIGXFSZ, handle_signal);
 | 
				
			||||||
 | 
					#ifdef SIGEMT
 | 
				
			||||||
 | 
						signal_setup_restart(SIGEMT, handle_signal);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						signal_setup_restart(SIGIO, handle_signal);
 | 
				
			||||||
 | 
					#ifdef SIGPWR
 | 
				
			||||||
 | 
						signal_setup_restart(SIGPWR, handle_signal);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef SIGUNUSED
 | 
				
			||||||
 | 
						signal_setup_restart(SIGUNUSED, handle_signal);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef SIGRTMIN
 | 
				
			||||||
 | 
						for (i = SIGRTMIN; i <= SIGRTMAX; i++)
 | 
				
			||||||
 | 
							signal_setup_restart(i, handle_signal);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fp = fopen(pidfile, "w");
 | 
				
			||||||
 | 
						if (! fp)
 | 
				
			||||||
 | 
							eerrorx("%s: fopen `%s': %s", applet, pidfile, strerror(errno));
 | 
				
			||||||
 | 
						fprintf(fp, "%d\n", getpid());
 | 
				
			||||||
 | 
						fclose(fp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (svcname)
 | 
				
			||||||
 | 
							rc_service_daemon_set(svcname, exec, (const char * const *) argv,
 | 
				
			||||||
 | 
									pidfile, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* remove the controlling tty */
 | 
				
			||||||
 | 
					#ifdef TIOCNOTTY
 | 
				
			||||||
 | 
						ioctl(tty_fd, TIOCNOTTY, 0);
 | 
				
			||||||
 | 
						close(tty_fd);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Supervisor main loop
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						i = 0;
 | 
				
			||||||
 | 
						while (!exiting) {
 | 
				
			||||||
 | 
							wait(&i);
 | 
				
			||||||
 | 
							if (exiting) {
 | 
				
			||||||
 | 
								signal_setup(SIGCHLD, SIG_IGN);
 | 
				
			||||||
 | 
								syslog(LOG_INFO, "stopping %s, pid %d", exec, child_pid);
 | 
				
			||||||
 | 
								nkilled = run_stop_schedule(applet, exec, NULL, child_pid, 0,
 | 
				
			||||||
 | 
										false, false, true);
 | 
				
			||||||
 | 
								if (nkilled > 0)
 | 
				
			||||||
 | 
									syslog(LOG_INFO, "killed %d processes", nkilled);
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								sleep(respawn_delay);
 | 
				
			||||||
 | 
								if (respawn_max > 0 && respawn_period > 0) {
 | 
				
			||||||
 | 
									respawn_now = time(NULL);
 | 
				
			||||||
 | 
									if (first_spawn == 0)
 | 
				
			||||||
 | 
										first_spawn = respawn_now;
 | 
				
			||||||
 | 
									if (respawn_now - first_spawn > respawn_period) {
 | 
				
			||||||
 | 
										respawn_count = 0;
 | 
				
			||||||
 | 
										first_spawn = 0;
 | 
				
			||||||
 | 
									} else
 | 
				
			||||||
 | 
										respawn_count++;
 | 
				
			||||||
 | 
									if (respawn_count >= respawn_max) {
 | 
				
			||||||
 | 
										syslog(LOG_WARNING,
 | 
				
			||||||
 | 
												"respawned \"%s\" too many times, exiting", exec);
 | 
				
			||||||
 | 
										exiting = true;
 | 
				
			||||||
 | 
										continue;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (WIFEXITED(i))
 | 
				
			||||||
 | 
									syslog(LOG_WARNING, "%s, pid %d, exited with return code %d",
 | 
				
			||||||
 | 
											exec, child_pid, WEXITSTATUS(i));
 | 
				
			||||||
 | 
								else if (WIFSIGNALED(i))
 | 
				
			||||||
 | 
									syslog(LOG_WARNING, "%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 (*signame != 0) {
 | 
						if (pidfile && exists(pidfile))
 | 
				
			||||||
		syslog(LOG_INFO, "%s: caught signal %s, exiting", applet, signame);
 | 
							unlink(pidfile);
 | 
				
			||||||
		exiting = true;
 | 
						if (svcname) {
 | 
				
			||||||
	} else
 | 
							rc_service_daemon_set(svcname, exec, (const char *const *)argv,
 | 
				
			||||||
		syslog(LOG_INFO, "%s: caught unknown signal %d", applet, sig);
 | 
									pidfile, false);
 | 
				
			||||||
 | 
							rc_service_mark(svcname, RC_SERVICE_STOPPED);
 | 
				
			||||||
	/* Restore errno */
 | 
							rc_service_value_set(svcname, "child_pid", NULL);
 | 
				
			||||||
	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) {
 | 
						exit(EXIT_SUCCESS);
 | 
				
			||||||
		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 main(int argc, char **argv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int opt;
 | 
						int opt;
 | 
				
			||||||
 | 
						char **c;
 | 
				
			||||||
 | 
						int x;
 | 
				
			||||||
	bool start = false;
 | 
						bool start = false;
 | 
				
			||||||
	bool stop = false;
 | 
						bool stop = false;
 | 
				
			||||||
 | 
						bool reexec = false;
 | 
				
			||||||
	char *exec = NULL;
 | 
						char *exec = NULL;
 | 
				
			||||||
	char *pidfile = NULL;
 | 
					 | 
				
			||||||
	char *retry = NULL;
 | 
						char *retry = NULL;
 | 
				
			||||||
	int nkilled;
 | 
					 | 
				
			||||||
	int sig = SIGTERM;
 | 
						int sig = SIGTERM;
 | 
				
			||||||
	char *home = NULL;
 | 
						char *home = NULL;
 | 
				
			||||||
	int tid = 0;
 | 
						int tid = 0;
 | 
				
			||||||
	pid_t child_pid, pid;
 | 
						pid_t pid;
 | 
				
			||||||
	char *svcname = getenv("RC_SVCNAME");
 | 
					 | 
				
			||||||
	char *tmp;
 | 
						char *tmp;
 | 
				
			||||||
	char *p;
 | 
						char *p;
 | 
				
			||||||
	char *token;
 | 
						char *token;
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
	int n;
 | 
						int n;
 | 
				
			||||||
	char exec_file[PATH_MAX];
 | 
						char *exec_file = NULL;
 | 
				
			||||||
	int respawn_count = 0;
 | 
						char *varbuf = NULL;
 | 
				
			||||||
	int respawn_delay = 0;
 | 
					 | 
				
			||||||
	int respawn_max = 10;
 | 
					 | 
				
			||||||
	int respawn_period = 5;
 | 
					 | 
				
			||||||
	time_t respawn_now= 0;
 | 
					 | 
				
			||||||
	time_t first_spawn= 0;
 | 
					 | 
				
			||||||
	struct timespec ts;
 | 
						struct timespec ts;
 | 
				
			||||||
	struct passwd *pw;
 | 
						struct passwd *pw;
 | 
				
			||||||
	struct group *gr;
 | 
						struct group *gr;
 | 
				
			||||||
	FILE *fp;
 | 
						FILE *fp;
 | 
				
			||||||
	mode_t numask = 022;
 | 
						mode_t numask = 022;
 | 
				
			||||||
 | 
						int child_argc = 0;
 | 
				
			||||||
 | 
						char **child_argv = NULL;
 | 
				
			||||||
 | 
						char *str = NULL;
 | 
				
			||||||
 | 
						char *cmdline = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	applet = basename_c(argv[0]);
 | 
						applet = basename_c(argv[0]);
 | 
				
			||||||
	atexit(cleanup);
 | 
						atexit(cleanup);
 | 
				
			||||||
 | 
						svcname = getenv("RC_SVCNAME");
 | 
				
			||||||
 | 
						if (!svcname)
 | 
				
			||||||
 | 
							eerrorx("%s: The RC_SVCNAME environment variable is not set", applet);
 | 
				
			||||||
 | 
						openlog(applet, LOG_PID, LOG_DAEMON);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (argc >= 1 && svcname && strcmp(argv[1], svcname))
 | 
				
			||||||
 | 
							eerrorx("%s: the first argument is %s and must be %s",
 | 
				
			||||||
 | 
									applet, argv[1], svcname);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((tmp = getenv("SSD_NICELEVEL")))
 | 
						if ((tmp = getenv("SSD_NICELEVEL")))
 | 
				
			||||||
		if (sscanf(tmp, "%d", &nicelevel) != 1)
 | 
							if (sscanf(tmp, "%d", &nicelevel) != 1)
 | 
				
			||||||
@@ -461,6 +604,11 @@ int main(int argc, char **argv)
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cmdline = make_cmdline(argv);
 | 
				
			||||||
 | 
						if (svcname) {
 | 
				
			||||||
 | 
							argc--;
 | 
				
			||||||
 | 
							argv++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	while ((opt = getopt_long(argc, argv, getoptstring, longopts,
 | 
						while ((opt = getopt_long(argc, argv, getoptstring, longopts,
 | 
				
			||||||
		    (int *) 0)) != -1)
 | 
							    (int *) 0)) != -1)
 | 
				
			||||||
		switch (opt) {
 | 
							switch (opt) {
 | 
				
			||||||
@@ -493,8 +641,8 @@ int main(int argc, char **argv)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		case 'P':  /* --respawn-period time */
 | 
							case 'P':  /* --respawn-period time */
 | 
				
			||||||
			n = sscanf(optarg, "%d", &respawn_period);
 | 
								n = sscanf(optarg, "%d", &respawn_period);
 | 
				
			||||||
			if (n	!= 1 || respawn_delay < 1)
 | 
								if (n	!= 1 || respawn_period < 1)
 | 
				
			||||||
				eerrorx("Invalid respawn-delay value '%s'", optarg);
 | 
									eerrorx("Invalid respawn-period value '%s'", optarg);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		case 'S':  /* --start */
 | 
							case 'S':  /* --start */
 | 
				
			||||||
@@ -590,86 +738,180 @@ int main(int argc, char **argv)
 | 
				
			|||||||
		case '2':  /* --stderr /path/to/stderr.logfile */
 | 
							case '2':  /* --stderr /path/to/stderr.logfile */
 | 
				
			||||||
			redirect_stderr = optarg;
 | 
								redirect_stderr = optarg;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
							case '3':  /* --reexec */
 | 
				
			||||||
 | 
								reexec = true;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		case_RC_COMMON_GETOPT
 | 
							case_RC_COMMON_GETOPT
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!pidfile)
 | 
						if (!pidfile && !reexec)
 | 
				
			||||||
		eerrorx("%s: --pidfile must be specified", applet);
 | 
							eerrorx("%s: --pidfile must be specified", applet);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	endpwent();
 | 
						endpwent();
 | 
				
			||||||
	argc -= optind;
 | 
						argc -= optind;
 | 
				
			||||||
	argv += optind;
 | 
						argv += optind;
 | 
				
			||||||
	exec = *argv;
 | 
						exec = *argv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (start) {
 | 
					 | 
				
			||||||
		if (!exec)
 | 
					 | 
				
			||||||
			eerrorx("%s: nothing to start", applet);
 | 
					 | 
				
			||||||
		if (respawn_delay * respawn_max > respawn_period) {
 | 
					 | 
				
			||||||
			ewarn("%s: Please increase the value of --respawn-period to more "
 | 
					 | 
				
			||||||
				"than %d to avoid infinite respawning", applet, 
 | 
					 | 
				
			||||||
				respawn_delay * respawn_max);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if (retry)
 | 
					 | 
				
			||||||
			parse_schedule(applet, retry, sig);
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
			parse_schedule(applet, NULL, sig);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Expand ~ */
 | 
						/* Expand ~ */
 | 
				
			||||||
	if (ch_dir && *ch_dir == '~')
 | 
						if (ch_dir && *ch_dir == '~')
 | 
				
			||||||
		ch_dir = expand_home(home, ch_dir);
 | 
							ch_dir = expand_home(home, ch_dir);
 | 
				
			||||||
	if (ch_root && *ch_root == '~')
 | 
						if (ch_root && *ch_root == '~')
 | 
				
			||||||
		ch_root = expand_home(home, 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 */
 | 
						umask(numask);
 | 
				
			||||||
		if (*exec == '/' || *exec == '.') {
 | 
					
 | 
				
			||||||
			/* Full or relative path */
 | 
						if (reexec) {
 | 
				
			||||||
			if (ch_root)
 | 
							str = rc_service_value_get(svcname, "argc");
 | 
				
			||||||
				snprintf(exec_file, sizeof(exec_file),
 | 
							sscanf(str, "%d", &child_argc);
 | 
				
			||||||
				    "%s/%s", ch_root, exec);
 | 
							child_argv = xmalloc((child_argc + 1) * sizeof(char *));
 | 
				
			||||||
			else
 | 
							memset(child_argv, 0, (child_argc + 1) * sizeof(char *));
 | 
				
			||||||
				snprintf(exec_file, sizeof(exec_file),
 | 
							for (x = 0; x < child_argc; x++) {
 | 
				
			||||||
				    "%s", exec);
 | 
								xasprintf(&varbuf, "argv_%d", x);
 | 
				
			||||||
		} else {
 | 
								str = rc_service_value_get(svcname, varbuf);
 | 
				
			||||||
			/* Something in $PATH */
 | 
								child_argv[x] = str;
 | 
				
			||||||
			p = tmp = xstrdup(getenv("PATH"));
 | 
								free(varbuf);
 | 
				
			||||||
			*exec_file = '\0';
 | 
								varbuf = NULL;
 | 
				
			||||||
			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);
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
							free(str);
 | 
				
			||||||
	if (start && !exists(exec_file))
 | 
							str = rc_service_value_get(svcname, "child_pid");
 | 
				
			||||||
		eerrorx("%s: %s does not exist", applet,
 | 
							sscanf(str, "%d", &child_pid);
 | 
				
			||||||
		    *exec_file ? exec_file : exec);
 | 
							free(str);
 | 
				
			||||||
 | 
							exec = rc_service_value_get(svcname, "exec");
 | 
				
			||||||
 | 
							pidfile = rc_service_value_get(svcname, "pidfile");
 | 
				
			||||||
 | 
							retry = rc_service_value_get(svcname, "retry");
 | 
				
			||||||
 | 
							if (retry) {
 | 
				
			||||||
 | 
								parse_schedule(applet, retry, sig);
 | 
				
			||||||
 | 
								rc_service_value_set(svcname, "retry", retry);
 | 
				
			||||||
 | 
							} else
 | 
				
			||||||
 | 
								parse_schedule(applet, NULL, sig);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (stop) {
 | 
							str = rc_service_value_get(svcname, "respawn_delay");
 | 
				
			||||||
 | 
							sscanf(str, "%d", &respawn_delay);
 | 
				
			||||||
 | 
							str = rc_service_value_get(svcname, "respawn_max");
 | 
				
			||||||
 | 
							sscanf(str, "%d", &respawn_max);
 | 
				
			||||||
 | 
							supervisor(exec, child_argv);
 | 
				
			||||||
 | 
						} else if (start) {
 | 
				
			||||||
 | 
							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)
 | 
				
			||||||
 | 
										xasprintf(&exec_file, "%s/%s", ch_root, exec);
 | 
				
			||||||
 | 
									else
 | 
				
			||||||
 | 
										xasprintf(&exec_file, "%s", exec);
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									/* Something in $PATH */
 | 
				
			||||||
 | 
									p = tmp = xstrdup(getenv("PATH"));
 | 
				
			||||||
 | 
									exec_file = NULL;
 | 
				
			||||||
 | 
									while ((token = strsep(&p, ":"))) {
 | 
				
			||||||
 | 
										if (ch_root)
 | 
				
			||||||
 | 
											xasprintf(&exec_file, "%s/%s/%s", ch_root, token, exec);
 | 
				
			||||||
 | 
										else
 | 
				
			||||||
 | 
											xasprintf(&exec_file, "%s/%s", token, exec);
 | 
				
			||||||
 | 
										if (exec_file && exists(exec_file))
 | 
				
			||||||
 | 
											break;
 | 
				
			||||||
 | 
										free(exec_file);
 | 
				
			||||||
 | 
										exec_file = NULL;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									free(tmp);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (!exists(exec_file)) {
 | 
				
			||||||
 | 
									eerror("%s: %s does not exist", applet,
 | 
				
			||||||
 | 
									    *exec_file ? exec_file : exec);
 | 
				
			||||||
 | 
									free(exec_file);
 | 
				
			||||||
 | 
									exit(EXIT_FAILURE);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else
 | 
				
			||||||
 | 
								eerrorx("%s: nothing to start", applet);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							pid = get_pid(applet, pidfile);
 | 
				
			||||||
 | 
							if (pid != -1)
 | 
				
			||||||
 | 
								if (do_stop(applet, exec, (const char * const *)argv, pid, uid,
 | 
				
			||||||
 | 
											0, false, true) > 0)
 | 
				
			||||||
 | 
									eerrorx("%s: %s is already running", applet, exec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (respawn_delay * respawn_max > respawn_period)
 | 
				
			||||||
 | 
								ewarn("%s: Please increase the value of --respawn-period to more "
 | 
				
			||||||
 | 
									"than %d to avoid infinite respawning", applet, 
 | 
				
			||||||
 | 
									respawn_delay * respawn_max);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (retry) {
 | 
				
			||||||
 | 
								parse_schedule(applet, retry, sig);
 | 
				
			||||||
 | 
								rc_service_value_set(svcname, "retry", retry);
 | 
				
			||||||
 | 
							} else
 | 
				
			||||||
 | 
								parse_schedule(applet, NULL, sig);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							einfov("Detaching to start `%s'", exec);
 | 
				
			||||||
 | 
							syslog(LOG_INFO, "Supervisor command line: %s", cmdline);
 | 
				
			||||||
 | 
							free(cmdline);
 | 
				
			||||||
 | 
							cmdline = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* 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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							rc_service_value_set(svcname, "pidfile", pidfile);
 | 
				
			||||||
 | 
							varbuf = NULL;
 | 
				
			||||||
 | 
							xasprintf(&varbuf, "%i", respawn_delay);
 | 
				
			||||||
 | 
							rc_service_value_set(svcname, "respawn_delay", varbuf);
 | 
				
			||||||
 | 
							xasprintf(&varbuf, "%i", respawn_max);
 | 
				
			||||||
 | 
							rc_service_value_set(svcname, "respawn_max", varbuf);
 | 
				
			||||||
 | 
							xasprintf(&varbuf, "%i", respawn_period);
 | 
				
			||||||
 | 
							rc_service_value_set(svcname, "respawn_period", varbuf);
 | 
				
			||||||
 | 
							child_pid = fork();
 | 
				
			||||||
 | 
							if (child_pid == -1)
 | 
				
			||||||
 | 
								eerrorx("%s: fork: %s", applet, strerror(errno));
 | 
				
			||||||
 | 
							if (child_pid != 0)
 | 
				
			||||||
 | 
								/* first parent process, do nothing. */
 | 
				
			||||||
 | 
								exit(EXIT_SUCCESS);
 | 
				
			||||||
 | 
					#ifdef TIOCNOTTY
 | 
				
			||||||
 | 
							tty_fd = open("/dev/tty", O_RDWR);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
							devnull_fd = open("/dev/null", O_RDWR);
 | 
				
			||||||
 | 
							child_pid = fork();
 | 
				
			||||||
 | 
							if (child_pid == -1)
 | 
				
			||||||
 | 
								eerrorx("%s: fork: %s", applet, strerror(errno));
 | 
				
			||||||
 | 
							else if (child_pid != 0) {
 | 
				
			||||||
 | 
								c = argv;
 | 
				
			||||||
 | 
								x = 0;
 | 
				
			||||||
 | 
								while (c && *c) {
 | 
				
			||||||
 | 
									varbuf = NULL;
 | 
				
			||||||
 | 
									xasprintf(&varbuf, "argv_%-d",x);
 | 
				
			||||||
 | 
									rc_service_value_set(svcname, varbuf, *c);
 | 
				
			||||||
 | 
									free(varbuf);
 | 
				
			||||||
 | 
									varbuf = NULL;
 | 
				
			||||||
 | 
									x++;
 | 
				
			||||||
 | 
									c++;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								xasprintf(&varbuf, "%d", x);
 | 
				
			||||||
 | 
									rc_service_value_set(svcname, "argc", varbuf);
 | 
				
			||||||
 | 
								rc_service_value_set(svcname, "exec", exec);
 | 
				
			||||||
 | 
								supervisor(exec, argv);
 | 
				
			||||||
 | 
							} else
 | 
				
			||||||
 | 
								child_process(exec, argv);
 | 
				
			||||||
 | 
						} else if (stop) {
 | 
				
			||||||
		pid = get_pid(applet, pidfile);
 | 
							pid = get_pid(applet, pidfile);
 | 
				
			||||||
		if (pid != -1) {
 | 
							if (pid != -1) {
 | 
				
			||||||
			i = kill(pid, SIGTERM);
 | 
								i = kill(pid, SIGTERM);
 | 
				
			||||||
			if (i != 0)
 | 
								if (i != 0)
 | 
				
			||||||
				/* We failed to send the signal */
 | 
									/* We failed to send the signal */
 | 
				
			||||||
				exit(EXIT_FAILURE);
 | 
									ewarn("Unable to shut down the supervisor");
 | 
				
			||||||
 | 
								else {
 | 
				
			||||||
			/* wait for the supervisor to go down */
 | 
									/* wait for the supervisor to go down */
 | 
				
			||||||
			while (kill(pid, 0) == 0) {
 | 
									while (kill(pid, 0) == 0) {
 | 
				
			||||||
				ts.tv_sec = 0;
 | 
										ts.tv_sec = 0;
 | 
				
			||||||
				ts.tv_nsec = 1;
 | 
										ts.tv_nsec = 1;
 | 
				
			||||||
				nanosleep(&ts, NULL);
 | 
										nanosleep(&ts, NULL);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -687,119 +929,4 @@ int main(int argc, char **argv)
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		exit(EXIT_SUCCESS);
 | 
							exit(EXIT_SUCCESS);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	pid = get_pid(applet, 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);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef TIOCNOTTY
 | 
					 | 
				
			||||||
	tty_fd = open("/dev/tty", O_RDWR);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	devnull_fd = open("/dev/null", O_RDWR);
 | 
					 | 
				
			||||||
	child_pid = fork();
 | 
					 | 
				
			||||||
	if (child_pid == -1)
 | 
					 | 
				
			||||||
		eerrorx("%s: fork: %s", applet, strerror(errno));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (child_pid != 0) {
 | 
					 | 
				
			||||||
		/* this is the supervisor */
 | 
					 | 
				
			||||||
		umask(numask);
 | 
					 | 
				
			||||||
		openlog(applet, LOG_PID, LOG_DAEMON);
 | 
					 | 
				
			||||||
		signal_setup(SIGTERM, handle_signal);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		fp = fopen(pidfile, "w");
 | 
					 | 
				
			||||||
		if (! fp)
 | 
					 | 
				
			||||||
			eerrorx("%s: fopen `%s': %s", applet, pidfile, strerror(errno));
 | 
					 | 
				
			||||||
		fprintf(fp, "%d\n", getpid());
 | 
					 | 
				
			||||||
		fclose(fp);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (svcname)
 | 
					 | 
				
			||||||
			rc_service_daemon_set(svcname, exec,
 | 
					 | 
				
			||||||
									(const char * const *) argv, pidfile, true);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* remove the controlling tty */
 | 
					 | 
				
			||||||
#ifdef TIOCNOTTY
 | 
					 | 
				
			||||||
		ioctl(tty_fd, TIOCNOTTY, 0);
 | 
					 | 
				
			||||||
		close(tty_fd);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/*
 | 
					 | 
				
			||||||
		 * Supervisor main loop
 | 
					 | 
				
			||||||
		 */
 | 
					 | 
				
			||||||
		i = 0;
 | 
					 | 
				
			||||||
		while (!exiting) {
 | 
					 | 
				
			||||||
			wait(&i);
 | 
					 | 
				
			||||||
			if (exiting) {
 | 
					 | 
				
			||||||
				signal_setup(SIGCHLD, SIG_IGN);
 | 
					 | 
				
			||||||
				syslog(LOG_INFO, "stopping %s, pid %d", exec, child_pid);
 | 
					 | 
				
			||||||
				nkilled = run_stop_schedule(applet, exec, NULL, child_pid,
 | 
					 | 
				
			||||||
						0, false, false, true);
 | 
					 | 
				
			||||||
				if (nkilled > 0)
 | 
					 | 
				
			||||||
					syslog(LOG_INFO, "killed %d processes", nkilled);
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				sleep(respawn_delay);
 | 
					 | 
				
			||||||
				if (respawn_max > 0 && respawn_period > 0) {
 | 
					 | 
				
			||||||
					respawn_now = time(NULL);
 | 
					 | 
				
			||||||
					if (first_spawn == 0)
 | 
					 | 
				
			||||||
						first_spawn = respawn_now;
 | 
					 | 
				
			||||||
					if (respawn_now - first_spawn > respawn_period) {
 | 
					 | 
				
			||||||
						respawn_count = 0;
 | 
					 | 
				
			||||||
						first_spawn = 0;
 | 
					 | 
				
			||||||
					} else
 | 
					 | 
				
			||||||
						respawn_count++;
 | 
					 | 
				
			||||||
					if (respawn_count >= respawn_max) {
 | 
					 | 
				
			||||||
						syslog(LOG_WARNING, "respawned \"%s\" too many times, "
 | 
					 | 
				
			||||||
								"exiting", exec);
 | 
					 | 
				
			||||||
						exiting = true;
 | 
					 | 
				
			||||||
						continue;
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				if (WIFEXITED(i))
 | 
					 | 
				
			||||||
					syslog(LOG_WARNING, "%s, pid %d, exited with return code %d",
 | 
					 | 
				
			||||||
							exec, child_pid, WEXITSTATUS(i));
 | 
					 | 
				
			||||||
				else if (WIFSIGNALED(i))
 | 
					 | 
				
			||||||
					syslog(LOG_WARNING, "%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, svcname, respawn_count);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (pidfile && exists(pidfile))
 | 
					 | 
				
			||||||
			unlink(pidfile);
 | 
					 | 
				
			||||||
		if (svcname) {
 | 
					 | 
				
			||||||
			rc_service_daemon_set(svcname, exec,
 | 
					 | 
				
			||||||
			    (const char *const *)argv,
 | 
					 | 
				
			||||||
			    pidfile, false);
 | 
					 | 
				
			||||||
			rc_service_mark(svcname, RC_SERVICE_STOPPED);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		exit(EXIT_SUCCESS);
 | 
					 | 
				
			||||||
	} else if (child_pid == 0)
 | 
					 | 
				
			||||||
		child_process(exec, argv, svcname, respawn_count);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
# Using supervise-daemon
 | 
					Using supervise-daemon
 | 
				
			||||||
 | 
					======================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Beginning with OpenRC-0.21 we have our own daemon supervisor,
 | 
					Beginning with OpenRC-0.21 we have our own daemon supervisor,
 | 
				
			||||||
supervise-daemon., which can start a daemon and restart it if it
 | 
					supervise-daemon., which can start a daemon and restart it if it
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
# deptree2dot - Graph the OpenRC Dependency Tree
 | 
					deptree2dot - Graph the OpenRC Dependency Tree
 | 
				
			||||||
 | 
					==============================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This utility can be used to graph the OpenRC dependency tree. It
 | 
					This utility can be used to graph the OpenRC dependency tree. It
 | 
				
			||||||
requires perl5.x and converts the tree to a .dot file which can be
 | 
					requires perl5.x and converts the tree to a .dot file which can be
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,5 @@ BIN=	${OBJS}
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
MK=	../../mk
 | 
					MK=	../../mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SED_EXTRA+= -e 's:@VARBASE@:/var:g'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
include ${MK}/os.mk
 | 
					include ${MK}/os.mk
 | 
				
			||||||
include ${MK}/scripts.mk
 | 
					include ${MK}/scripts.mk
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,6 @@
 | 
				
			|||||||
 | 
					Example OpenRC Service Scripts
 | 
				
			||||||
 | 
					##############################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The service scripts in this directory are meant as examples only.
 | 
					The service scripts in this directory are meant as examples only.
 | 
				
			||||||
They are not installed by default as the scripts will need tweaking on a
 | 
					They are not installed by default as the scripts will need tweaking on a
 | 
				
			||||||
per distro basis. They are also non essential to the operation of the system.
 | 
					per distro basis. They are also non essential to the operation of the system.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,7 +11,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
command=@PKG_PREFIX@/sbin/avahi-dnsconfd
 | 
					command=@PKG_PREFIX@/sbin/avahi-dnsconfd
 | 
				
			||||||
command_args="$avahi_dnsconfd_args -D"
 | 
					command_args="$avahi_dnsconfd_args -D"
 | 
				
			||||||
pidfile=@VARBASE@/run/avahi-dnsconfd.pid
 | 
					pidfile=/var/run/avahi-dnsconfd.pid
 | 
				
			||||||
name="Avahi DNS Configuration Daemon"
 | 
					name="Avahi DNS Configuration Daemon"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
depend()
 | 
					depend()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,7 +11,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
command=@PKG_PREFIX@/sbin/avahi-daemon
 | 
					command=@PKG_PREFIX@/sbin/avahi-daemon
 | 
				
			||||||
command_args="$avahid_args -D"
 | 
					command_args="$avahid_args -D"
 | 
				
			||||||
pidfile=@VARBASE@/run/avahi-daemon/pid
 | 
					pidfile=/var/run/avahi-daemon/pid
 | 
				
			||||||
name="Avahi Service Advertisement Daemon"
 | 
					name="Avahi Service Advertisement Daemon"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
depend()
 | 
					depend()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,7 +10,7 @@
 | 
				
			|||||||
# except according to the terms contained in the LICENSE file.
 | 
					# except according to the terms contained in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
command=@PKG_PREFIX@/bin/dbus-daemon
 | 
					command=@PKG_PREFIX@/bin/dbus-daemon
 | 
				
			||||||
pidfile=@VARBASE@/run/dbus/pid
 | 
					pidfile=/var/run/dbus/pid
 | 
				
			||||||
command_args="${dbusd_args---system}"
 | 
					command_args="${dbusd_args---system}"
 | 
				
			||||||
name="Message Bus Daemon"
 | 
					name="Message Bus Daemon"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,7 +11,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
command=@PKG_PREFIX@/sbin/dnsmasq
 | 
					command=@PKG_PREFIX@/sbin/dnsmasq
 | 
				
			||||||
command_args=$dnsmasq_args
 | 
					command_args=$dnsmasq_args
 | 
				
			||||||
pidfile=@VARBASE@/run/dnsmasq.pid
 | 
					pidfile=/var/run/dnsmasq.pid
 | 
				
			||||||
required_files=/etc/dnsmasq.conf
 | 
					required_files=/etc/dnsmasq.conf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extra_started_commands="reload"
 | 
					extra_started_commands="reload"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,7 +10,7 @@
 | 
				
			|||||||
# except according to the terms contained in the LICENSE file.
 | 
					# except according to the terms contained in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
command=@PKG_PREFIX@/sbin/hald
 | 
					command=@PKG_PREFIX@/sbin/hald
 | 
				
			||||||
pidfile=@VARBASE@/run/hald/hald.pid
 | 
					pidfile=/var/run/hald/hald.pid
 | 
				
			||||||
command_args=$hald_args
 | 
					command_args=$hald_args
 | 
				
			||||||
name="Hardware Abstraction Layer Daemon"
 | 
					name="Hardware Abstraction Layer Daemon"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,7 +11,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
command=/usr/sbin/named
 | 
					command=/usr/sbin/named
 | 
				
			||||||
command_args=$named_args
 | 
					command_args=$named_args
 | 
				
			||||||
pidfile=@VARBASE@/run/named.pid
 | 
					pidfile=/var/run/named.pid
 | 
				
			||||||
name="Domain Name server"
 | 
					name="Domain Name server"
 | 
				
			||||||
extra_started_commands="reload"
 | 
					extra_started_commands="reload"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -20,7 +20,7 @@ uid=named
 | 
				
			|||||||
case "$RC_UNAME" in
 | 
					case "$RC_UNAME" in
 | 
				
			||||||
	FreeBSD)
 | 
						FreeBSD)
 | 
				
			||||||
		uid=bind
 | 
							uid=bind
 | 
				
			||||||
		pidfile=@VARBASE@/run/named/pid
 | 
							pidfile=/var/run/named/pid
 | 
				
			||||||
		;;
 | 
							;;
 | 
				
			||||||
	Linux)
 | 
						Linux)
 | 
				
			||||||
		uid=bind
 | 
							uid=bind
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,7 +14,7 @@ name="OpenVPN"
 | 
				
			|||||||
[ "$vpn" != openvpn ] && name="$name ($vpn)"
 | 
					[ "$vpn" != openvpn ] && name="$name ($vpn)"
 | 
				
			||||||
command=@PKG_PREFIX@/sbin/openvpn
 | 
					command=@PKG_PREFIX@/sbin/openvpn
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pidfile=@VARBASE@/run/"$RC_SVCNAME".pid
 | 
					pidfile=/var/run/"$RC_SVCNAME".pid
 | 
				
			||||||
: ${openvpn_dir:=@PKG_PREFIX@/etc/openvpn}
 | 
					: ${openvpn_dir:=@PKG_PREFIX@/etc/openvpn}
 | 
				
			||||||
: ${openvpn_config:=$openvpn_dir/$vpn.conf}
 | 
					: ${openvpn_config:=$openvpn_dir/$vpn.conf}
 | 
				
			||||||
command_args="$openvpn_args --daemon --config $openvpn_config"
 | 
					command_args="$openvpn_args --daemon --config $openvpn_config"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,7 +10,7 @@
 | 
				
			|||||||
# except according to the terms contained in the LICENSE file.
 | 
					# except according to the terms contained in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
command=@PKG_PREFIX@/sbin/polkitd
 | 
					command=@PKG_PREFIX@/sbin/polkitd
 | 
				
			||||||
pidfile=@VARBASE@/run/polkitd/polkitd.pid
 | 
					pidfile=/var/run/polkitd/polkitd.pid
 | 
				
			||||||
command_args="$polkitd_args"
 | 
					command_args="$polkitd_args"
 | 
				
			||||||
name="PolicyKit Daemon"
 | 
					name="PolicyKit Daemon"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user