Compare commits
	
		
			58 Commits
		
	
	
		
			0.47
			...
			cgroup-nam
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| db5559bb50 | |||
|   | 3d30b6fdda | ||
|   | 4574b5d8e4 | ||
|   | 6b42019697 | ||
|   | 42408e7488 | ||
|   | 957140cb78 | ||
|   | 536794dfad | ||
|   | 7ac2080e31 | ||
|   | 12e1e88475 | ||
|   | c45fe9fba5 | ||
|   | 961c479e1d | ||
|   | f9c92d7822 | ||
|   | 97689d6c44 | ||
|   | 439cce426d | ||
|   | bfdafe4463 | ||
|   | 179ff285ca | ||
|   | f9bbbfbf4b | ||
|   | 59a175541d | ||
|   | 65b13eb86f | ||
|   | fda9dcd1f2 | ||
|   | 6f180e9424 | ||
|   | 88e5d98d05 | ||
|   | 1433552435 | ||
|   | 554ccab718 | ||
|   | 228b3c6c99 | ||
|   | 965de92b37 | ||
|   | b85d771e1f | ||
|   | cf9286d2d8 | ||
|   | 9934e9f96e | ||
|   | f1e5510ccf | ||
|   | 1b72c3a7ab | ||
|   | c4785f1b99 | ||
|   | e447562aaa | ||
|   | c199c5cf6e | ||
|   | 5bfb592d75 | ||
|   | b2c4eb97b5 | ||
|   | e740913fcb | ||
|   | 1bc34a39cd | ||
|   | c1cd3c9830 | ||
|   | 86efc43d0e | ||
|   | cd53239701 | ||
|   | 92662ddc44 | ||
|   | 1b6a35488d | ||
|   | 1eccb7f5e6 | ||
|   | fe37fc9322 | ||
|   | edf5f830e3 | ||
|   | 863e1a5c87 | ||
|   | 0b9c3c0803 | ||
|   | a3c721b682 | ||
|   | 3f82d5b1a3 | ||
|   | 0b4732520f | ||
|   | bbd3acfc67 | ||
|   | 910e3e2a0e | ||
|   | 5f04dcc951 | ||
|   | 8f52c64c37 | ||
|   | 09d405fb3e | ||
|   | 36e4e04ba9 | ||
|   | eb8831a141 | 
| @@ -4,8 +4,8 @@ | ||||
| test_task: | ||||
|   freebsd_instance: | ||||
|     matrix: | ||||
|       image: freebsd-13-1-release-amd64 | ||||
|       image: freebsd-12-4-release-amd64 | ||||
|       image: freebsd-13-2-release-amd64 | ||||
|       image: freebsd-13-3-release-amd64 | ||||
|   env: | ||||
|     OS: FreeBSD | ||||
|   procfs_script: > | ||||
|   | ||||
							
								
								
									
										52
									
								
								NEWS.md
									
									
									
									
									
								
							
							
						
						
									
										52
									
								
								NEWS.md
									
									
									
									
									
								
							| @@ -4,6 +4,58 @@ OpenRC NEWS | ||||
| This file will contain a list of notable changes for each release. Note | ||||
| the information in this file is in reverse order. | ||||
|  | ||||
| ## OpenRC 0.54 | ||||
|  | ||||
| This release drops the support for the split-usr build option. | ||||
| Also, it drops the support for ncurses/termcap and uses ansi codes | ||||
| directly for color support on terminals that support them. | ||||
|  | ||||
| ## OpenRC 0.53 | ||||
|  | ||||
| The names of cgroups for services started by OpenRC are now prefixed by | ||||
| "openrc." This is done because some services, like docker, create their | ||||
| own cgroups. | ||||
|  | ||||
| It is now possible to override the mount options used to mount the | ||||
| cgroups filesystems. | ||||
| ## OpenRC 0.52 | ||||
|  | ||||
| This release drops the "runscript" and "rc" binaries. | ||||
| These binaries have been deprecated for multiple years, so it should be | ||||
| fine to remove them at this point. | ||||
|  | ||||
| There was an issue before this release with the default setting for | ||||
| cgroups being inconsistent. This is fixed. | ||||
|  | ||||
| Start-stop-daemon did not work correctly on Linux 6.6 systems. | ||||
| This has been fixed in this release as well. | ||||
|  | ||||
| ## OpenRC 0.51 | ||||
|  | ||||
| The default RC_CGROUP_MODE has been updated to unified. | ||||
| This benefits users since it will assign each service to its own cgroup, | ||||
| making resource nanagement better over all. | ||||
|  | ||||
| OUTPUT_LOGGER and ERROR_LOGGER have been implemented for | ||||
| supervise-daemon. For mor einformation on these settings, please check | ||||
| the man page. | ||||
|  | ||||
| ## OpenRC 0.50 | ||||
|  | ||||
| This is a bug fix release which fixes a significant performance issue on | ||||
| musl libc systems. | ||||
|  | ||||
| ## OpenRC 0.49 | ||||
|  | ||||
| This release adds support for glibc's builtin  | ||||
| strlcpy, strlcat etc functions, which will be in posix next. | ||||
| Also, it fixes completions. | ||||
|  | ||||
|  | ||||
| ## OpenRC 0.48 | ||||
|  | ||||
| This release is a maintenance release; it has no user-facing changes. | ||||
|  | ||||
| ## OpenRC 0.47 | ||||
|  | ||||
| This release is primarily an internal cleanup release. | ||||
|   | ||||
| @@ -92,13 +92,11 @@ _rc_service() | ||||
| 			return 0 | ||||
| 		elif [[ ${COMP_CWORD} -eq 2 ]] && [[ ${prev} != -* ]]; then # if second word typed and we didn't type in a function | ||||
| 			rc-service --exists "$prev" || return | ||||
| 			shopt -s extglob | ||||
| 			while read -r _ line; do | ||||
| 				if [[ $line == +([[:alnum:]_]):* ]]; then | ||||
| 					opts+="${line%%:*} " | ||||
| 				fi | ||||
| 			done < <(rc-service "$prev" describe 2>&1) | ||||
| 			shopt -u extglob | ||||
| 			COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) | ||||
| 			return 0 | ||||
| 		fi | ||||
|   | ||||
							
								
								
									
										2
									
								
								conf.d/cgroups
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								conf.d/cgroups
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| # override cgroup mount options | ||||
| #cgroup_opts=nodev,noexec,nosuid | ||||
| @@ -199,7 +199,10 @@ rc_tty_number=12 | ||||
| # cgroups version 1 on /sys/fs/cgroup. | ||||
| # "legacy" mounts cgroups version 1 on /sys/fs/cgroup | ||||
| # "unified" mounts cgroups version 2 on /sys/fs/cgroup | ||||
| #rc_cgroup_mode="hybrid" | ||||
| #rc_cgroup_mode="unified" | ||||
|  | ||||
| # override cgroup controller name | ||||
| #rc_cgroup_name=openrc | ||||
|  | ||||
| # This is a list of controllers which should be enabled for cgroups version 2 | ||||
| # when hybrid mode is being used. | ||||
|   | ||||
| @@ -11,7 +11,9 @@ | ||||
|  | ||||
| description="Mount the control groups." | ||||
|  | ||||
| cgroup_opts=nodev,noexec,nosuid | ||||
| : "${cgroup_opts:="nodev,noexec,nosuid"}" | ||||
|  | ||||
| rc_cgroup_name=${rc_cgroup_name:-openrc} | ||||
|  | ||||
| depend() | ||||
| { | ||||
| @@ -29,13 +31,13 @@ cgroup1_base() | ||||
| 		eend $? | ||||
| 	fi | ||||
|  | ||||
| 	if ! mountinfo -q /sys/fs/cgroup/openrc; then | ||||
| 	if ! mountinfo -q /sys/fs/cgroup/"${rc_cgroup_name}"; then | ||||
| 		local agent="${RC_LIBEXECDIR}/sh/cgroup-release-agent.sh" | ||||
| 		mkdir /sys/fs/cgroup/openrc | ||||
| 		mkdir /sys/fs/cgroup/"${rc_cgroup_name}" | ||||
| 		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 | ||||
| 			-o none,${cgroup_opts},name="${rc_cgroup_name}",release_agent="$agent" \ | ||||
| 			"${rc_cgroup_name}" /sys/fs/cgroup/"${rc_cgroup_name}" | ||||
| 		printf 1 > /sys/fs/cgroup/"${rc_cgroup_name}"/notify_on_release | ||||
| 	fi | ||||
| 	return 0 | ||||
| } | ||||
| @@ -74,6 +76,7 @@ cgroup2_base() | ||||
| 	mkdir -p "${base}" | ||||
| 	mount -t cgroup2 none -o "${cgroup_opts},nsdelegate" "${base}" 2> /dev/null || | ||||
| 		mount -t cgroup2 none -o "${cgroup_opts}" "${base}" | ||||
|  mkdir -p ${base}/"${rc_cgroup_name}" | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| @@ -81,13 +84,13 @@ cgroup2_controllers() | ||||
| { | ||||
| 	grep -qw cgroup2 /proc/filesystems || return 0 | ||||
| 	local active cgroup_path x y | ||||
| 	cgroup_path="$(cgroup2_find_path)" | ||||
| 	cgroup_path="$(cgroup2_find_path)/${rc_cgroup_name}" | ||||
| 	[ -z "${cgroup_path}" ] && return 0 | ||||
| 	[ ! -e "${cgroup_path}/cgroup.controllers" ] && return 0 | ||||
| 	[ ! -e "${cgroup_path}/cgroup.subtree_control" ]&& return 0 | ||||
| 	read -r active < "${cgroup_path}/cgroup.controllers" | ||||
| 	for x in ${active}; do | ||||
| 	case "$rc_cgroup_mode" in | ||||
| 	case "${rc_cgroup_mode:-unified}" in | ||||
| 		unified) | ||||
| 			echo "+${x}"  > "${cgroup_path}/cgroup.subtree_control" | ||||
| 			;; | ||||
| @@ -128,7 +131,7 @@ cgroups_unified() | ||||
|  | ||||
| mount_cgroups() | ||||
| { | ||||
| 	case "${rc_cgroup_mode:-hybrid}" in | ||||
| 	case "${rc_cgroup_mode:-unified}" in | ||||
| 	hybrid) cgroups_hybrid ;; | ||||
| 	legacy) cgroups_legacy ;; | ||||
| 	unified) cgroups_unified ;; | ||||
|   | ||||
| @@ -158,13 +158,6 @@ is true. | ||||
| prefixes the string | ||||
| .Fa prefix | ||||
| to the above functions. | ||||
| .Sh IMPLEMENTATION NOTES | ||||
| einfo can optionally be linked against the | ||||
| .Lb libtermcap | ||||
| so that we can correctly query the connected console for our color and | ||||
| cursor escape codes. | ||||
| If not, then we have a hard coded list of terminals we know about that support | ||||
| the commonly used codes for color and cursor position. | ||||
| .Sh ENVIRONMENT | ||||
| .Va EINFO_QUIET | ||||
| when set to true makes the | ||||
|   | ||||
| @@ -84,6 +84,8 @@ Print the action(s) that would be taken, but don't actually do anything. | ||||
| The return value is set as if the command was taken and worked. | ||||
| .It Fl v , -verbose | ||||
| Print the action(s) that are taken just before doing them. | ||||
| .It Fl q , -quiet | ||||
| Run quietly (repeat to suppress errors). | ||||
| .It Fl P , -progress | ||||
| Echo a . to the console for each second elapsed whilst waiting. | ||||
| .El | ||||
| @@ -183,10 +185,6 @@ Wait | ||||
| after starting and check that daemon is still running. | ||||
| Useful for daemons that check configuration after forking or stopping race | ||||
| conditions where the pidfile is written out after forking. | ||||
| .It Fl 2 , -stderr Ar logfile | ||||
| The same thing as | ||||
| .Fl 1 , -stdout | ||||
| but with the standard error output. | ||||
| .El | ||||
| .Pp | ||||
| These options are only used for stopping daemons: | ||||
|   | ||||
| @@ -158,6 +158,23 @@ The logfile can also be a named pipe. | ||||
| The same thing as | ||||
| .Fl 1 , -stdout | ||||
| but with the standard error output. | ||||
| .It Fl -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 -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 -capabilities Ar cap-list | ||||
| Start the daemon with the listed inheritable, ambient and bounding capabilities. | ||||
| The format is the same as in cap_iab(3). | ||||
|   | ||||
							
								
								
									
										35
									
								
								meson.build
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								meson.build
									
									
									
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| project('OpenRC', 'c', | ||||
|   version : '0.47', | ||||
|   version : '0.54', | ||||
|   license: 'BSD-2', | ||||
|   default_options : [ | ||||
|     'c_std=c99', | ||||
| @@ -83,16 +83,9 @@ else | ||||
|   pkg_prefix = option_pkg_prefix | ||||
| endif | ||||
|  | ||||
| if get_option('split-usr') == 'auto' | ||||
|   split_usr = run_command('test', '-L', '/bin', check: false).returncode() != 0 | ||||
| else | ||||
|   split_usr = get_option('split-usr') == 'true' | ||||
| endif | ||||
|  | ||||
| rootprefix = get_option('rootprefix') | ||||
| rootprefix_default = fs.is_symlink('/bin') ? '/usr' : '/' | ||||
| if rootprefix == '' | ||||
| rootprefix = rootprefix_default | ||||
| rootprefix = '/' | ||||
| endif | ||||
|  | ||||
| bindir = rootprefix / get_option('bindir') | ||||
| @@ -133,15 +126,6 @@ else | ||||
|   cc_selinux_flags = [] | ||||
| endif | ||||
|  | ||||
| termcap = get_option('termcap') | ||||
| if termcap != '' | ||||
|   termcap_dep = dependency(termcap) | ||||
|   termcap_flags = '-DHAVE_TERMCAP' | ||||
|   else | ||||
|   termcap_dep = [] | ||||
|   termcap_flags = [] | ||||
| endif | ||||
|  | ||||
| if get_option('buildtype').startswith('debug') | ||||
|   cc_debug_flags = ['-DRC_DEBUG'] | ||||
| else | ||||
| @@ -176,7 +160,10 @@ cc_warning_flags_test = [ | ||||
|   '-Wsequence-point', | ||||
|   '-Wshadow', | ||||
|   '-Wwrite-strings', | ||||
|   '-Werror=implicit-int', | ||||
|   '-Werror=implicit-function-declaration', | ||||
|   '-Werror=int-conversion', | ||||
|   '-Werror=incompatible-function-pointer-types', | ||||
|   ] | ||||
| cc_warning_flags = cc.get_supported_arguments(cc_warning_flags_test) | ||||
| cc_flags = [cc_debug_flags, cc_os_flags, cc_warning_flags] | ||||
| @@ -192,12 +179,14 @@ if cc.compiles(malloc_attribute_test, name : 'malloc attribute with arguments') | ||||
|   add_project_arguments('-DHAVE_MALLOC_EXTENDED_ATTRIBUTE', language: 'c') | ||||
| endif | ||||
|  | ||||
| if cc.has_function('closefrom', prefix: '#define _GNU_SOURCE\n#include <unistd.h>') | ||||
|   add_project_arguments('-DHAVE_CLOSEFROM', language: 'c') | ||||
| if cc.has_function('close_range', prefix: '#define _GNU_SOURCE\n#include <unistd.h>') | ||||
|   add_project_arguments('-DHAVE_CLOSE_RANGE', language: 'c') | ||||
| elif cc.has_header('linux/close_range.h') | ||||
|   add_project_arguments('-DHAVE_LINUX_CLOSE_RANGE_H', language: 'c') | ||||
| endif | ||||
| if cc.has_function('close_range', prefix: '#define _GNU_SOURCE\n#include <unistd.h>') and \ | ||||
|     cc.has_header_symbol('unistd.h', 'CLOSE_RANGE_CLOEXEC', prefix: '#define _GNU_SOURCE') | ||||
|   add_project_arguments('-DHAVE_CLOSE_RANGE_CLOEXEC', language: 'c') | ||||
|  | ||||
| if cc.has_function('strlcpy', prefix: '#define _GNU_SOURCE\n#include <string.h>') | ||||
|   add_project_arguments('-DHAVE_STRLCPY', language: 'c') | ||||
| endif | ||||
|  | ||||
| incdir = include_directories('src/shared') | ||||
|   | ||||
| @@ -26,14 +26,7 @@ option('selinux', type : 'feature', value : 'auto', | ||||
|   description : 'enable SELinux support') | ||||
| option('shell', type : 'string', value : '/bin/sh', | ||||
|   description : 'Default posix compatible shell') | ||||
| option('split-usr', type : 'combo', | ||||
|   choices : ['auto', 'true', 'false'], | ||||
|   description : '''/bin, /sbin aren't symlinks into /usr''') | ||||
| option('sysvinit', type : 'boolean', value : false, | ||||
|   description : 'enable SysVinit compatibility (linux only)') | ||||
| option('termcap', type : 'combo', | ||||
|   choices : | ||||
|     [ '', 'ncurses', 'termcap' ], | ||||
|   description : 'the termcap library to use') | ||||
| option('zsh-completions', type : 'boolean', | ||||
|   description : 'install zsh completions') | ||||
|   | ||||
| @@ -12,7 +12,7 @@ | ||||
| # This file may not be copied, modified, propagated, or distributed | ||||
| #    except according to the terms contained in the LICENSE file. | ||||
|  | ||||
| cgroup=/sys/fs/cgroup/openrc | ||||
| cgroup=/sys/fs/cgroup/"${rc_cgroup_name:-openrc}" | ||||
| PATH=/bin:/usr/bin:/sbin:/usr/sbin | ||||
| if [ -d ${cgroup}/"$1" ]; then | ||||
| 	rmdir ${cgroup}/"$1" | ||||
|   | ||||
| @@ -11,6 +11,8 @@ | ||||
| extra_stopped_commands="${extra_stopped_commands} cgroup_cleanup" | ||||
| description_cgroup_cleanup="Kill all processes in the cgroup" | ||||
|  | ||||
| cg2_sv_name="${RC_SVCNAME}.sv" | ||||
|  | ||||
| cgroup_find_path() | ||||
| { | ||||
| 	local OIFS name dir result | ||||
| @@ -35,9 +37,9 @@ cgroup_get_pids() | ||||
| 	cgroup_pids= | ||||
| 	cgroup_procs="$(cgroup2_find_path)" | ||||
| 	if [ -n "${cgroup_procs}" ]; then | ||||
| 		cgroup_procs="${cgroup_procs}/${RC_SVCNAME}/cgroup.procs" | ||||
| 		cgroup_procs="${cgroup_procs}/${rc_cgroup_name}/${cg2_sv_name}/cgroup.procs" | ||||
| 	else | ||||
| 		cgroup_procs="/sys/fs/cgroup/openrc/${RC_SVCNAME}/tasks" | ||||
| 		cgroup_procs="/sys/fs/cgroup/"${rc_cgroup_name}"/${RC_SVCNAME}/tasks" | ||||
| 	fi | ||||
| 	[ -f "${cgroup_procs}" ] || return 0 | ||||
| 	while read -r p; do | ||||
| @@ -51,7 +53,7 @@ cgroup_running() | ||||
| { | ||||
| 	[ -d "/sys/fs/cgroup/unified/${RC_SVCNAME}" ] || | ||||
| 			[ -d "/sys/fs/cgroup/${RC_SVCNAME}" ] || | ||||
| 			[ -d "/sys/fs/cgroup/openrc/${RC_SVCNAME}" ] | ||||
| 			[ -d "/sys/fs/cgroup/"${rc_cgroup_name}"/${RC_SVCNAME}" ] | ||||
| } | ||||
|  | ||||
| cgroup_set_values() | ||||
| @@ -61,7 +63,7 @@ cgroup_set_values() | ||||
| 	local controller h | ||||
| 	controller="$1" | ||||
| 	h=$(cgroup_find_path "$1") | ||||
| 	cgroup="/sys/fs/cgroup/${1}${h}openrc_${RC_SVCNAME}" | ||||
| 	cgroup="/sys/fs/cgroup/${1}${h}"${rc_cgroup_name}"_${RC_SVCNAME}" | ||||
| 	[ -d "$cgroup" ] || mkdir -p "$cgroup" | ||||
|  | ||||
| 	set -- $2 | ||||
| @@ -108,7 +110,7 @@ cgroup_add_service() | ||||
| 		[ -w "${d}"/tasks ] && printf "%d" 0 > "${d}"/tasks | ||||
| 	done | ||||
|  | ||||
| 	openrc_cgroup=/sys/fs/cgroup/openrc | ||||
| 	openrc_cgroup=/sys/fs/cgroup/"${rc_cgroup_name}" | ||||
| 	if [ -d "$openrc_cgroup" ]; then | ||||
| 		cgroup="$openrc_cgroup/$RC_SVCNAME" | ||||
| 		mkdir -p "$cgroup" | ||||
| @@ -154,7 +156,7 @@ cgroup_set_limits() | ||||
| cgroup2_find_path() | ||||
| { | ||||
| 	if grep -qw cgroup2 /proc/filesystems; then | ||||
| 		case "${rc_cgroup_mode:-hybrid}" in | ||||
| 		case "${rc_cgroup_mode:-unified}" in | ||||
| 			hybrid) printf "/sys/fs/cgroup/unified" ;; | ||||
| 			unified) printf "/sys/fs/cgroup" ;; | ||||
| 		esac | ||||
| @@ -167,7 +169,7 @@ cgroup2_remove() | ||||
| 	local cgroup_path rc_cgroup_path | ||||
| 	cgroup_path="$(cgroup2_find_path)" | ||||
| 	[ -z "${cgroup_path}" ] && return 0 | ||||
| 	rc_cgroup_path="${cgroup_path}/${RC_SVCNAME}" | ||||
| 	rc_cgroup_path="${cgroup_path}/${rc_cgroup_name}/${cg2_sv_name}" | ||||
| 	[ ! -d "${rc_cgroup_path}" ] || | ||||
| 		[ ! -e "${rc_cgroup_path}"/cgroup.events ] && | ||||
| 		return 0 | ||||
| @@ -191,7 +193,7 @@ cgroup2_set_limits() | ||||
| 	cgroup_path="$(cgroup2_find_path)" | ||||
| 	[ -z "${cgroup_path}" ] && return 0 | ||||
| 	mountinfo -q "${cgroup_path}"|| return 0 | ||||
| 	rc_cgroup_path="${cgroup_path}/${RC_SVCNAME}" | ||||
| 	rc_cgroup_path="${cgroup_path}/${rc_cgroup_name}/${cg2_sv_name}" | ||||
| 	[ ! -d "${rc_cgroup_path}" ] && mkdir "${rc_cgroup_path}" | ||||
| 	[ -f "${rc_cgroup_path}"/cgroup.procs ] && | ||||
| 		printf 0 > "${rc_cgroup_path}"/cgroup.procs | ||||
| @@ -210,7 +212,7 @@ cgroup2_kill_cgroup() { | ||||
| 	local cgroup_path | ||||
| 	cgroup_path="$(cgroup2_find_path)" | ||||
| 	[ -z "${cgroup_path}" ] && return 1 | ||||
| 	rc_cgroup_path="${cgroup_path}/${RC_SVCNAME}" | ||||
| 	rc_cgroup_path="${cgroup_path}/${rc_cgroup_name}/${cg2_sv_name}" | ||||
| 	if [ -f "${rc_cgroup_path}"/cgroup.kill ]; then | ||||
| 		printf "%d" 1 > "${rc_cgroup_path}"/cgroup.kill | ||||
| 	fi | ||||
|   | ||||
| @@ -30,6 +30,8 @@ supervise_start() | ||||
| 		${chroot:+--chroot} $chroot \ | ||||
| 		${output_log+--stdout} ${output_log} \ | ||||
| 		${error_log+--stderr} $error_log \ | ||||
| 		${output_logger:+--stdout-logger \"$output_logger\"} \ | ||||
| 		${error_logger:+--stderr-logger \"$error_logger\"} \ | ||||
| 		${pidfile:+--pidfile} $pidfile \ | ||||
| 		${respawn_delay:+--respawn-delay} $respawn_delay \ | ||||
| 		${respawn_max:+--respawn-max} $respawn_max \ | ||||
| @@ -38,7 +40,7 @@ supervise_start() | ||||
| 		${healthcheck_timer:+--healthcheck-timer} $healthcheck_timer \ | ||||
| 		${capabilities+--capabilities} "$capabilities" \ | ||||
| 		${secbits:+--secbits} "$secbits" \ | ||||
| 		${no_new_privs:+--no_new_privs} \ | ||||
| 		${no_new_privs:+--no-new-privs} \ | ||||
| 		${command_user+--user} $command_user \ | ||||
| 		${umask+--umask} $umask \ | ||||
| 		${supervise_daemon_args-${start_stop_daemon_args}} \ | ||||
|   | ||||
| @@ -78,7 +78,7 @@ int main(int argc, char **argv) | ||||
| 		if (strcmp(applet, "eend") == 0 || | ||||
| 		    strcmp(applet, "ewend") == 0 || | ||||
| 		    strcmp(applet, "veend") == 0 || | ||||
| 		    strcmp(applet, "vweend") == 0 || | ||||
| 		    strcmp(applet, "vewend") == 0 || | ||||
| 		    strcmp(applet, "ewaitfile") == 0) | ||||
| 		{ | ||||
| 			errno = 0; | ||||
|   | ||||
| @@ -23,6 +23,7 @@ | ||||
| #include <string.h> | ||||
| #include <unistd.h> | ||||
| #include <stdbool.h> | ||||
| #include <spawn.h> | ||||
|  | ||||
| /* Yay for linux and its non liking of POSIX functions. | ||||
|    Okay, we could use getfsent but the man page says use getmntent instead | ||||
| @@ -63,6 +64,8 @@ | ||||
| #include "_usage.h" | ||||
| #include "helpers.h" | ||||
|  | ||||
| extern char **environ; | ||||
|  | ||||
| const char *applet = NULL; | ||||
| const char *extraopts = NULL; | ||||
| const char getoptstring[] = "MRbmop:t:" getoptstring_COMMON; | ||||
| @@ -112,7 +115,7 @@ do_mount(struct ENT *ent, bool remount) | ||||
| { | ||||
| 	char *argv[10]; | ||||
| 	pid_t pid; | ||||
| 	int status; | ||||
| 	int status, err; | ||||
|  | ||||
| 	argv[0] = UNCONST("mount"); | ||||
| 	argv[1] = UNCONST("-o"); | ||||
| @@ -137,23 +140,14 @@ do_mount(struct ENT *ent, bool remount) | ||||
| 		argv[8] = NULL; | ||||
| #endif | ||||
| 	} | ||||
| 	switch (pid = vfork()) { | ||||
| 	case -1: | ||||
| 		eerrorx("%s: vfork: %s", applet, strerror(errno)); | ||||
| 		/* NOTREACHED */ | ||||
| 	case 0: | ||||
| 		execvp(argv[0], argv); | ||||
| 		eerror("%s: execvp: %s", applet, strerror(errno)); | ||||
| 		_exit(EXIT_FAILURE); | ||||
| 		/* NOTREACHED */ | ||||
| 	default: | ||||
| 		waitpid(pid, &status, 0); | ||||
| 		if (WIFEXITED(status)) | ||||
| 			return WEXITSTATUS(status); | ||||
| 		else | ||||
| 			return -1; | ||||
| 		/* NOTREACHED */ | ||||
| 	} | ||||
| 	err = posix_spawnp(&pid, argv[0], NULL, NULL, argv, environ); | ||||
| 	if (err) | ||||
| 		eerrorx("%s: posix_spawnp: %s", applet, strerror(err)); | ||||
| 	while (waitpid(pid, &status, 0) < 0 && errno == EINTR); | ||||
| 	if (WIFEXITED(status)) | ||||
| 		return WEXITSTATUS(status); | ||||
| 	else | ||||
| 		return -1; | ||||
| } | ||||
|  | ||||
| #define OUTPUT_FILE      (1 << 1) | ||||
|   | ||||
| @@ -13,13 +13,8 @@ | ||||
| #ifndef __EINFO_H__ | ||||
| #define __EINFO_H__ | ||||
|  | ||||
| #if defined(__GNUC__) | ||||
| # define EINFO_PRINTF(a, b)  __attribute__((__format__(__printf__, a, b))) | ||||
| # define EINFO_XPRINTF(a, b) __attribute__((__noreturn__,__format__(__printf__, a, b))) | ||||
| #else | ||||
| # define EINFO_PRINTF(a, b) | ||||
| # define EINFO_XPRINTF(a, b) | ||||
| #endif | ||||
| #define EINFO_PRINTF(a, b)  __attribute__((__format__(__printf__, a, b))) | ||||
| #define EINFO_XPRINTF(a, b) __attribute__((__noreturn__, __format__(__printf__, a, b))) | ||||
|  | ||||
| #include <sys/types.h> | ||||
| #include <stdbool.h> | ||||
| @@ -74,22 +69,22 @@ void elog(int, const char * EINFO_RESTRICT, ...) EINFO_PRINTF(2, 3); | ||||
|  * The x suffix means function will exit() returning failure. | ||||
|  */ | ||||
| /*@{*/ | ||||
| int einfon(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2); | ||||
| int ewarnn(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2); | ||||
| int eerrorn(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2); | ||||
| int einfo(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2); | ||||
| int ewarn(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2); | ||||
| void ewarnx(const char * __EINFO_RESTRICT, ...) EINFO_XPRINTF(1, 2); | ||||
| int eerror(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2); | ||||
| void eerrorx(const char * __EINFO_RESTRICT, ...) EINFO_XPRINTF(1, 2); | ||||
| int einfon(const char * EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2); | ||||
| int ewarnn(const char * EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2); | ||||
| int eerrorn(const char * EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2); | ||||
| int einfo(const char * EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2); | ||||
| int ewarn(const char * EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2); | ||||
| void ewarnx(const char * EINFO_RESTRICT, ...) EINFO_XPRINTF(1, 2); | ||||
| int eerror(const char * EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2); | ||||
| void eerrorx(const char * EINFO_RESTRICT, ...) EINFO_XPRINTF(1, 2); | ||||
|  | ||||
| int einfovn(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2); | ||||
| int ewarnvn(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2); | ||||
| int ebeginvn(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2); | ||||
| int eendvn(int, const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(2, 3); | ||||
| int ewendvn(int, const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(2, 3); | ||||
| int einfov(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2); | ||||
| int ewarnv(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2); | ||||
| int einfovn(const char * EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2); | ||||
| int ewarnvn(const char * EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2); | ||||
| int ebeginvn(const char * EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2); | ||||
| int eendvn(int, const char * EINFO_RESTRICT, ...) EINFO_PRINTF(2, 3); | ||||
| int ewendvn(int, const char * EINFO_RESTRICT, ...) EINFO_PRINTF(2, 3); | ||||
| int einfov(const char * EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2); | ||||
| int ewarnv(const char * EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2); | ||||
| /*@}*/ | ||||
|  | ||||
| /*! @ingroup ebegin | ||||
|   | ||||
| @@ -4,7 +4,7 @@ | ||||
| */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007-2015 The OpenRC Authors. | ||||
|  * Copyright (c) 2007-2024 The OpenRC Authors. | ||||
|  * See the Authors file at the top-level directory of this distribution and | ||||
|  * https://github.com/OpenRC/openrc/blob/HEAD/AUTHORS | ||||
|  * | ||||
| @@ -26,9 +26,6 @@ | ||||
| #include <string.h> | ||||
| #include <strings.h> | ||||
| #include <syslog.h> | ||||
| #ifdef HAVE_TERMCAP | ||||
| # include <termcap.h> | ||||
| #endif | ||||
| #include <unistd.h> | ||||
|  | ||||
| #include "einfo.h" | ||||
| @@ -53,8 +50,7 @@ | ||||
| #define HILITE                  6 | ||||
| #define BRACKET                 4 | ||||
|  | ||||
| /* We fallback to these escape codes if termcap isn't available | ||||
|  * like say /usr isn't mounted */ | ||||
| /* ANSI escape codes which mimic termcap */ | ||||
| #define AF "\033[3%dm" | ||||
| #define CE "\033[K" | ||||
| #define CH "\033[%dC" | ||||
| @@ -97,13 +93,7 @@ static char *goto_column = NULL; | ||||
| static const char *term = NULL; | ||||
| static bool term_is_cons25 = false; | ||||
|  | ||||
| /* Termcap buffers and pointers | ||||
|  * Static buffers suck hard, but some termcap implementations require them */ | ||||
| #ifdef HAVE_TERMCAP | ||||
| static char termcapbuf[2048]; | ||||
| static char tcapbuf[512]; | ||||
| #else | ||||
| /* No curses support, so we hardcode a list of colour capable terms | ||||
| /* Hardcoded list of colour capable terms | ||||
|  * Only terminals without "color" in the name need to be explicitly listed */ | ||||
| static const char *const color_terms[] = { | ||||
| 	"Eterm", | ||||
| @@ -142,13 +132,11 @@ static const char *const color_terms[] = { | ||||
| 	"wsvt25", | ||||
| 	"xterm", | ||||
| 	"xterm-debian", | ||||
| 	"xterm-kitty", | ||||
| 	NULL | ||||
| }; | ||||
| #endif | ||||
|  | ||||
| /* strlcat and strlcpy are nice, shame glibc does not define them */ | ||||
| #ifdef __GLIBC__ | ||||
| #  if !defined (__UCLIBC__) && !defined (__dietlibc__) | ||||
| #ifndef HAVE_STRLCPY | ||||
| static size_t | ||||
| strlcat(char *dst, const char *src, size_t size) | ||||
| { | ||||
| @@ -176,7 +164,6 @@ strlcat(char *dst, const char *src, size_t size) | ||||
|  | ||||
| 	return dst_n + (s - src); | ||||
| } | ||||
| #  endif | ||||
| #endif | ||||
|  | ||||
| static bool | ||||
| @@ -239,7 +226,6 @@ is_verbose(void) | ||||
| } | ||||
|  | ||||
| /* Fake tgoto call - very crapy, but works for our needs */ | ||||
| #ifndef HAVE_TERMCAP | ||||
| static char * | ||||
| tgoto(const char *cap, int col, int line) | ||||
| { | ||||
| @@ -302,7 +288,6 @@ tgoto(const char *cap, int col, int line) | ||||
| 	*p = '\0'; | ||||
| 	return buf; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| static bool | ||||
| colour_terminal(FILE * EINFO_RESTRICT f) | ||||
| @@ -315,9 +300,6 @@ colour_terminal(FILE * EINFO_RESTRICT f) | ||||
| 	const char *bold; | ||||
| 	char tmp[100]; | ||||
| 	unsigned int i = 0; | ||||
| #ifdef HAVE_TERMCAP | ||||
| 	char *bp; | ||||
| #endif | ||||
|  | ||||
| 	if (f && !isatty(fileno(f))) | ||||
| 		return false; | ||||
| @@ -339,65 +321,33 @@ colour_terminal(FILE * EINFO_RESTRICT f) | ||||
| 	if (strcmp(term, "cons25") == 0) | ||||
| 		term_is_cons25 = true; | ||||
|  | ||||
| #ifdef HAVE_TERMCAP | ||||
| 	/* Check termcap to see if we can do colour or not */ | ||||
| 	if (tgetent(termcapbuf, term) == 1) { | ||||
| 		bp = tcapbuf; | ||||
| 		_af = tgetstr("AF", &bp); | ||||
| 		_ce = tgetstr("ce", &bp); | ||||
| 		_ch = tgetstr("ch", &bp); | ||||
| 		/* Our ch use also works with RI .... for now */ | ||||
| 		if (!_ch) | ||||
| 			_ch = tgetstr("RI", &bp); | ||||
| 		_md = tgetstr("md", &bp); | ||||
| 		_me = tgetstr("me", &bp); | ||||
| 		_up = tgetstr("up", &bp); | ||||
| 	} | ||||
| 	if (strstr(term, "color")) | ||||
| 		in_colour = 1; | ||||
|  | ||||
| 	/* Cheat here as vanilla BSD has the whole termcap info in /usr | ||||
| 	 * which is not available to us when we boot */ | ||||
| 	if (term_is_cons25 || strcmp(term, "wsvt25") == 0) { | ||||
| #else | ||||
| 		if (strstr(term, "color")) | ||||
| 	while (color_terms[i] && in_colour != 1) { | ||||
| 		if (strcmp(color_terms[i], term) == 0) { | ||||
| 			in_colour = 1; | ||||
|  | ||||
| 		while (color_terms[i] && in_colour != 1) { | ||||
| 			if (strcmp(color_terms[i], term) == 0) { | ||||
| 				in_colour = 1; | ||||
| 			} | ||||
| 			i++; | ||||
| 		} | ||||
|  | ||||
| 		if (in_colour != 1) { | ||||
| 			in_colour = 0; | ||||
| 			return false; | ||||
| 		} | ||||
| #endif | ||||
| 		if (!_af) | ||||
| 			_af = AF; | ||||
| 		if (!_ce) | ||||
| 			_ce = CE; | ||||
| 		if (!_ch) | ||||
| 			_ch = CH; | ||||
| 		if (!_md) | ||||
| 			_md = MD; | ||||
| 		if (!_me) | ||||
| 			_me = ME; | ||||
| 		if (!_up) | ||||
| 			_up = UP; | ||||
| #ifdef HAVE_TERMCAP | ||||
| 		i++; | ||||
| 	} | ||||
|  | ||||
| 	if (!_af || !_ce || !_me || !_md || !_up) { | ||||
| 	if (in_colour != 1) { | ||||
| 		in_colour = 0; | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	/* Many termcap databases don't have ch or RI even though they | ||||
| 	 * do work */ | ||||
| 	if (!_af) | ||||
| 		_af = AF; | ||||
| 	if (!_ce) | ||||
| 		_ce = CE; | ||||
| 	if (!_ch) | ||||
| 		_ch = CH; | ||||
| #endif | ||||
| 	if (!_md) | ||||
| 		_md = MD; | ||||
| 	if (!_me) | ||||
| 		_me = ME; | ||||
| 	if (!_up) | ||||
| 		_up = UP; | ||||
|  | ||||
| 	/* Now setup our colours */ | ||||
| 	p = ebuffer; | ||||
|   | ||||
| @@ -1,9 +1,7 @@ | ||||
| libeinfo_version = '1' | ||||
|  | ||||
| libeinfo = library('einfo', ['libeinfo.c'], | ||||
|   c_args : termcap_flags, | ||||
|   include_directories : incdir, | ||||
|   dependencies : termcap_dep, | ||||
|   link_depends : 'einfo.map', | ||||
|   version : libeinfo_version, | ||||
|   install : true, | ||||
|   | ||||
| @@ -402,7 +402,7 @@ rc_service_daemon_set(const char *service, const char *exec, | ||||
| 	bool retval = false; | ||||
| 	DIR *dp; | ||||
| 	struct dirent *d; | ||||
| 	RC_STRINGLIST *match; | ||||
| 	RC_STRINGLIST *match, *renamelist; | ||||
| 	int i = 0; | ||||
| 	FILE *fp; | ||||
|  | ||||
| @@ -416,11 +416,17 @@ rc_service_daemon_set(const char *service, const char *exec, | ||||
| 	/* Regardless, erase any existing daemon info */ | ||||
| 	if ((dp = opendir(dirpath))) { | ||||
| 		match = _match_list(exec, argv, pidfile); | ||||
| 		renamelist = rc_stringlist_new(); | ||||
| 		while ((d = readdir(dp))) { | ||||
| 			if (d->d_name[0] == '.') | ||||
| 				continue; | ||||
|  | ||||
| 			xasprintf(&file, "%s/%s", dirpath, d->d_name); | ||||
| 			if (rc_stringlist_find(renamelist, file)) { | ||||
| 				free(file); | ||||
| 				continue; | ||||
| 			} | ||||
|  | ||||
| 			nfiles++; | ||||
|  | ||||
| 			if (!*oldfile) { | ||||
| @@ -432,11 +438,15 @@ rc_service_daemon_set(const char *service, const char *exec, | ||||
| 			} else { | ||||
| 				rename(file, oldfile); | ||||
| 				strlcpy(oldfile, file, sizeof(oldfile)); | ||||
| 				/* Add renamed file to renamelist, as this new file name could | ||||
| 				 * be read again from readdir() */ | ||||
| 				rc_stringlist_add(renamelist, oldfile); | ||||
| 			} | ||||
| 			free(file); | ||||
| 		} | ||||
| 		closedir(dp); | ||||
| 		rc_stringlist_free(match); | ||||
| 		rc_stringlist_free(renamelist); | ||||
| 	} | ||||
|  | ||||
| 	/* Now store our daemon info */ | ||||
|   | ||||
| @@ -127,7 +127,7 @@ rc_getline(char **line, size_t *len, FILE *fp) | ||||
| } | ||||
|  | ||||
| char * | ||||
| rc_proc_getent(const char *ent _unused) | ||||
| rc_proc_getent(const char *ent RC_UNUSED) | ||||
| { | ||||
| #ifdef __linux__ | ||||
| 	FILE *fp; | ||||
| @@ -287,6 +287,7 @@ static RC_STRINGLIST *rc_config_kcl(RC_STRINGLIST *config) | ||||
| 	overrides = rc_stringlist_new(); | ||||
|  | ||||
| 	/* A list of variables which may be overridden on the kernel command line */ | ||||
| 	rc_stringlist_add(overrides, "rc_interactive"); | ||||
| 	rc_stringlist_add(overrides, "rc_parallel"); | ||||
|  | ||||
| 	TAILQ_FOREACH(override, overrides, entries) { | ||||
|   | ||||
| @@ -249,7 +249,7 @@ detect_prefix(const char *systype) | ||||
| } | ||||
|  | ||||
| static const char * | ||||
| detect_container(const char *systype _unused) | ||||
| detect_container(const char *systype RC_UNUSED) | ||||
| { | ||||
| #ifdef __FreeBSD__ | ||||
| 	if (systype) { | ||||
| @@ -313,7 +313,7 @@ detect_container(const char *systype _unused) | ||||
| } | ||||
|  | ||||
| static const char * | ||||
| detect_vm(const char *systype _unused) | ||||
| detect_vm(const char *systype RC_UNUSED) | ||||
| { | ||||
| #ifdef __NetBSD__ | ||||
| 	if (systype) { | ||||
|   | ||||
| @@ -6,12 +6,3 @@ executable('openrc-run', | ||||
|   include_directories: [incdir, einfo_incdir, rc_incdir], | ||||
|   install: true, | ||||
|   install_dir: sbindir) | ||||
|  | ||||
| executable('runscript', | ||||
|   ['openrc-run.c', misc_c, plugin_c, selinux_c, usage_c, version_h], | ||||
|   c_args : [cc_audit_flags, cc_branding_flags, cc_pam_flags, cc_selinux_flags], | ||||
|   link_with: [libeinfo, librc], | ||||
|   dependencies: [audit_dep, dl_dep, pam_dep, pam_misc_dep, selinux_dep, util_dep, crypt_dep], | ||||
|   include_directories: [incdir, einfo_incdir, rc_incdir], | ||||
|   install: true, | ||||
|   install_dir: sbindir) | ||||
|   | ||||
| @@ -107,7 +107,8 @@ static RC_STRINGLIST *deptypes_mwua;	/* need+want+use+after deps for stopping */ | ||||
| static void | ||||
| handle_signal(int sig) | ||||
| { | ||||
| 	int serrno = errno; | ||||
| 	int serrno = errno, status; | ||||
| 	pid_t pid; | ||||
| 	const char *signame = NULL; | ||||
| 	struct winsize ws; | ||||
|  | ||||
| @@ -117,12 +118,13 @@ handle_signal(int sig) | ||||
| 		break; | ||||
|  | ||||
| 	case SIGCHLD: | ||||
| 		if (signal_pipe[1] > -1) { | ||||
| 			if (write(signal_pipe[1], &sig, sizeof(sig)) == -1) | ||||
| 				eerror("%s: send: %s", | ||||
| 				    service, strerror(errno)); | ||||
| 		} else | ||||
| 			rc_waitpid(-1); | ||||
| 		while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { | ||||
| 			if (signal_pipe[1] > -1 && pid == service_pid) { | ||||
| 				if (write(signal_pipe[1], &status, sizeof(status)) == -1) | ||||
| 					eerror("%s: send: %s", | ||||
| 					    service, strerror(errno)); | ||||
| 			} | ||||
| 		} | ||||
| 		break; | ||||
|  | ||||
| 	case SIGWINCH: | ||||
| @@ -438,6 +440,7 @@ svc_exec(const char *arg1, const char *arg2) | ||||
| 			if (errno != EINTR) { | ||||
| 				eerror("%s: poll: %s", | ||||
| 				    service, strerror(errno)); | ||||
| 				ret = -1; | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| @@ -448,9 +451,20 @@ svc_exec(const char *arg1, const char *arg2) | ||||
| 				write_prefix(buffer, bytes, &prefixed); | ||||
| 			} | ||||
|  | ||||
| 			/* Only SIGCHLD signals come down this pipe */ | ||||
| 			if (fd[0].revents & (POLLIN | POLLHUP)) | ||||
| 			/* signal_pipe receives service_pid's exit status */ | ||||
| 			if (fd[0].revents & (POLLIN | POLLHUP)) { | ||||
| 				if ((s = read(signal_pipe[0], &ret, sizeof(ret))) != sizeof(ret)) { | ||||
| 					eerror("%s: receive failed: %s", service, | ||||
| 						s < 0 ? strerror(errno) : "short read"); | ||||
| 					ret = -1; | ||||
| 					break; | ||||
| 				} | ||||
| 				ret = WEXITSTATUS(ret); | ||||
| 				if (ret != 0 && errno == ECHILD) | ||||
| 					/* killall5 -9 could cause this */ | ||||
| 					ret = 0; | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @@ -473,11 +487,6 @@ svc_exec(const char *arg1, const char *arg2) | ||||
| 		master_tty = -1; | ||||
| 	} | ||||
|  | ||||
| 	ret = rc_waitpid(service_pid); | ||||
| 	ret = WEXITSTATUS(ret); | ||||
| 	if (ret != 0 && errno == ECHILD) | ||||
| 		/* killall5 -9 could cause this */ | ||||
| 		ret = 0; | ||||
| 	service_pid = 0; | ||||
|  | ||||
| 	return ret; | ||||
| @@ -612,7 +621,7 @@ svc_start_check(void) | ||||
| 	} | ||||
|  | ||||
| 	if (exclusive_fd == -1) | ||||
| 		exclusive_fd = svc_lock(applet); | ||||
| 		exclusive_fd = svc_lock(applet, !deps); | ||||
| 	if (exclusive_fd == -1) { | ||||
| 		if (errno == EACCES) | ||||
| 			eerrorx("%s: superuser access required", applet); | ||||
| @@ -864,7 +873,7 @@ svc_stop_check(RC_SERVICE *state) | ||||
| 		exit(EXIT_FAILURE); | ||||
|  | ||||
| 	if (exclusive_fd == -1) | ||||
| 		exclusive_fd = svc_lock(applet); | ||||
| 		exclusive_fd = svc_lock(applet, !deps); | ||||
| 	if (exclusive_fd == -1) { | ||||
| 		if (errno == EACCES) | ||||
| 			eerrorx("%s: superuser access required", applet); | ||||
| @@ -1041,26 +1050,6 @@ svc_stop(void) | ||||
| static void | ||||
| svc_restart(void) | ||||
| { | ||||
| 	/* This is hairy and a better way needs to be found I think! | ||||
| 	 * The issue is this - openvpn need net and dns. net can restart | ||||
| 	 * dns via resolvconf, so you could have openvpn trying to restart | ||||
| 	 * dnsmasq which in turn is waiting on net which in turn is waiting | ||||
| 	 * on dnsmasq. | ||||
| 	 * The work around is for resolvconf to restart its services with | ||||
| 	 * --nodeps which means just that. | ||||
| 	 * The downside is that there is a small window when our status is | ||||
| 	 * invalid. | ||||
| 	 * One workaround would be to introduce a new status, | ||||
| 	 * or status locking. */ | ||||
| 	if (!deps) { | ||||
| 		RC_SERVICE state = rc_service_state(service); | ||||
| 		if (state & RC_SERVICE_STARTED || state & RC_SERVICE_INACTIVE) | ||||
| 			svc_exec("stop", "start"); | ||||
| 		else | ||||
| 			svc_exec("start", NULL); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	if (!(rc_service_state(service) & RC_SERVICE_STOPPED)) { | ||||
| 		get_started_services(); | ||||
| 		svc_stop(); | ||||
| @@ -1108,7 +1097,6 @@ service_plugable(void) | ||||
| int main(int argc, char **argv) | ||||
| { | ||||
| 	bool doneone = false; | ||||
| 	bool runscript = false; | ||||
| 	int retval, opt, depoptions = RC_DEP_TRACE; | ||||
| 	RC_STRING *svc; | ||||
| 	char *path = NULL; | ||||
| @@ -1126,8 +1114,6 @@ int main(int argc, char **argv) | ||||
| 	} | ||||
|  | ||||
| 	applet = basename_c(argv[0]); | ||||
| 	if (strcmp(applet, "runscript") == 0) | ||||
| 		runscript = true; | ||||
|  | ||||
| 	if (stat(argv[1], &stbuf) != 0) { | ||||
| 		fprintf(stderr, "openrc-run `%s': %s\n", | ||||
| @@ -1300,9 +1286,6 @@ int main(int argc, char **argv) | ||||
| 	applet_list = rc_stringlist_new(); | ||||
| 	rc_stringlist_add(applet_list, applet); | ||||
|  | ||||
| 	if (runscript) | ||||
| 		ewarn("%s uses runscript, please convert to openrc-run.", service); | ||||
|  | ||||
| 	/* Now run each option */ | ||||
| 	retval = EXIT_SUCCESS; | ||||
| 	while (optind < argc) { | ||||
|   | ||||
| @@ -42,8 +42,7 @@ static sigjmp_buf jbuf; | ||||
| /* | ||||
|  *	Alarm handler | ||||
|  */ | ||||
| /*ARGSUSED*/ | ||||
| _noreturn static void handler(int arg _unused) | ||||
| RC_NORETURN static void handler(int arg RC_UNUSED) | ||||
| { | ||||
| 	siglongjmp(jbuf, 1); | ||||
| } | ||||
|   | ||||
| @@ -170,7 +170,7 @@ static void sleep_no_interrupt(int seconds) | ||||
| 		duration = remaining; | ||||
| } | ||||
|  | ||||
| _noreturn static void stop_shutdown(int sig) | ||||
| RC_NORETURN static void stop_shutdown(int sig) | ||||
| { | ||||
| 	(void) sig; | ||||
| 	unlink(nologin_file); | ||||
|   | ||||
| @@ -6,12 +6,3 @@ executable('openrc', | ||||
|   include_directories: [incdir, einfo_incdir, rc_incdir], | ||||
|   install: true, | ||||
|   install_dir: sbindir) | ||||
|  | ||||
| executable('rc', | ||||
|   ['rc.c', 'rc-logger.c', misc_c, plugin_c, usage_c, version_h], | ||||
|   c_args : cc_branding_flags, | ||||
|   link_with: [libeinfo, librc], | ||||
|   dependencies: [dl_dep, util_dep], | ||||
|   include_directories: [incdir, einfo_incdir, rc_incdir], | ||||
|   install: true, | ||||
|   install_dir: sbindir) | ||||
|   | ||||
| @@ -87,6 +87,7 @@ static RC_HOOK hook_out; | ||||
| struct termios *termios_orig = NULL; | ||||
|  | ||||
| RC_PIDLIST service_pids; | ||||
| RC_PIDLIST free_these_pids; | ||||
|  | ||||
| static void | ||||
| clean_failed(void) | ||||
| @@ -116,8 +117,7 @@ clean_failed(void) | ||||
| static void | ||||
| cleanup(void) | ||||
| { | ||||
| 	RC_PID *p1 = LIST_FIRST(&service_pids); | ||||
| 	RC_PID *p2; | ||||
| 	RC_PID *p, *tmp; | ||||
|  | ||||
| 	if (!rc_in_logger && !rc_in_plugin && | ||||
| 	    applet && (strcmp(applet, "rc") == 0 || strcmp(applet, "openrc") == 0)) | ||||
| @@ -139,10 +139,13 @@ cleanup(void) | ||||
| 		rc_logger_close(); | ||||
| 	} | ||||
|  | ||||
| 	while (p1) { | ||||
| 		p2 = LIST_NEXT(p1, entries); | ||||
| 		free(p1); | ||||
| 		p1 = p2; | ||||
| 	LIST_FOREACH_SAFE(p, &service_pids, entries, tmp) { | ||||
| 		LIST_REMOVE(p, entries); | ||||
| 		free(p); | ||||
| 	} | ||||
| 	LIST_FOREACH_SAFE(p, &free_these_pids, entries, tmp) { | ||||
| 		LIST_REMOVE(p, entries); | ||||
| 		free(p); | ||||
| 	} | ||||
|  | ||||
| 	rc_stringlist_free(main_hotplugged_services); | ||||
| @@ -344,22 +347,46 @@ static char *get_krunlevel(void) | ||||
| static void | ||||
| add_pid(pid_t pid) | ||||
| { | ||||
| 	sigset_t sset, old; | ||||
| 	RC_PID *p = xmalloc(sizeof(*p)); | ||||
| 	p->pid = pid; | ||||
|  | ||||
| 	/* this list will be accessed inside the SIGCHLD signal handler. | ||||
| 	 * so we need to ensure that the SIGCHLD handler doesn't get invoked | ||||
| 	 * while the list is at an inconsistent state. | ||||
| 	 */ | ||||
| 	sigemptyset(&sset); | ||||
| 	sigaddset(&sset, SIGCHLD); | ||||
| 	sigprocmask(SIG_SETMASK, &sset, &old); | ||||
| 	LIST_INSERT_HEAD(&service_pids, p, entries); | ||||
| 	sigprocmask(SIG_SETMASK, &old, NULL); | ||||
| } | ||||
|  | ||||
| static void | ||||
| remove_pid(pid_t pid) | ||||
| remove_pid(pid_t pid, bool inside_signal) | ||||
| { | ||||
| 	RC_PID *p; | ||||
| 	sigset_t sset, old; | ||||
| 	RC_PID *p, *tmp; | ||||
|  | ||||
| 	LIST_FOREACH(p, &service_pids, entries) | ||||
| 	    if (p->pid == pid) { | ||||
| 		    LIST_REMOVE(p, entries); | ||||
| 		    free(p); | ||||
| 		    return; | ||||
| 	    } | ||||
| 	/* same rationale for blocking SIGCHLD as add_pid() */ | ||||
| 	sigemptyset(&sset); | ||||
| 	sigaddset(&sset, SIGCHLD); | ||||
| 	sigprocmask(SIG_SETMASK, &sset, &old); | ||||
| 	LIST_FOREACH(p, &service_pids, entries) { | ||||
| 		if (p->pid == pid) { | ||||
| 			LIST_REMOVE(p, entries); | ||||
| 			LIST_INSERT_HEAD(&free_these_pids, p, entries); | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	/* only call free if we're not inside a signal handler */ | ||||
| 	if (!inside_signal) { | ||||
| 		LIST_FOREACH_SAFE(p, &free_these_pids, entries, tmp) { | ||||
| 			LIST_REMOVE(p, entries); | ||||
| 			free(p); | ||||
| 		} | ||||
| 	} | ||||
| 	sigprocmask(SIG_SETMASK, &old, NULL); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -397,7 +424,7 @@ handle_signal(int sig) | ||||
|  | ||||
| 		/* Remove that pid from our list */ | ||||
| 		if (pid > 0) | ||||
| 			remove_pid(pid); | ||||
| 			remove_pid(pid, true); | ||||
| 		break; | ||||
|  | ||||
| 	case SIGWINCH: | ||||
| @@ -500,7 +527,7 @@ runlevel_config(const char *service, const char *level) | ||||
| 	char *conf, *dir; | ||||
| 	bool retval; | ||||
|  | ||||
| 	dir = dirname(init); | ||||
| 	dir = dirname(dirname(init)); | ||||
| 	xasprintf(&conf, "%s/conf.d/%s.%s", dir, service, level); | ||||
| 	retval = exists(conf); | ||||
| 	free(conf); | ||||
| @@ -606,7 +633,7 @@ stop: | ||||
| 			add_pid(pid); | ||||
| 			if (!parallel) { | ||||
| 				rc_waitpid(pid); | ||||
| 				remove_pid(pid); | ||||
| 				remove_pid(pid, false); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| @@ -672,7 +699,7 @@ do_start_services(const RC_STRINGLIST *start_services, bool parallel) | ||||
| 			add_pid(pid); | ||||
| 			if (!parallel) { | ||||
| 				rc_waitpid(pid); | ||||
| 				remove_pid(pid); | ||||
| 				remove_pid(pid, false); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| @@ -690,7 +717,7 @@ do_start_services(const RC_STRINGLIST *start_services, bool parallel) | ||||
| } | ||||
|  | ||||
| #ifdef RC_DEBUG | ||||
| _noreturn static void | ||||
| RC_NORETURN static void | ||||
| handle_bad_signal(int sig) | ||||
| { | ||||
| 	char pid[10]; | ||||
| @@ -745,6 +772,7 @@ int main(int argc, char **argv) | ||||
|  | ||||
| 	applet = basename_c(argv[0]); | ||||
| 	LIST_INIT(&service_pids); | ||||
| 	LIST_INIT(&free_these_pids); | ||||
| 	atexit(cleanup); | ||||
| 	if (!applet) | ||||
| 		eerrorx("arguments required"); | ||||
| @@ -809,8 +837,6 @@ int main(int argc, char **argv) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (strcmp(applet, "rc") == 0) | ||||
| 		ewarn("rc is deprecated, please use openrc instead."); | ||||
| 	newlevel = argv[optind++]; | ||||
| 	/* To make life easier, we only have the shutdown runlevel as | ||||
| 	 * nothing really needs to know that we're rebooting. | ||||
|   | ||||
| @@ -88,7 +88,7 @@ delete(const char *runlevel, const char *service) | ||||
|  | ||||
| 	errno = 0; | ||||
| 	if (rc_service_delete(runlevel, service)) { | ||||
| 		einfo("service %s removed from runlevel %s", | ||||
| 		einfo("service %s deleted from runlevel %s", | ||||
| 		    service, runlevel); | ||||
| 		return 1; | ||||
| 	} | ||||
| @@ -97,7 +97,7 @@ delete(const char *runlevel, const char *service) | ||||
| 		eerror("%s: service `%s' is not in the runlevel `%s'", | ||||
| 		    applet, service, runlevel); | ||||
| 	else | ||||
| 		eerror("%s: failed to remove service `%s' from runlevel `%s': %s", | ||||
| 		eerror("%s: failed to delete service `%s' from runlevel `%s': %s", | ||||
| 		    applet, service, runlevel, strerror (errno)); | ||||
|  | ||||
| 	return retval; | ||||
| @@ -144,7 +144,7 @@ static int | ||||
| delstack(const char *runlevel, const char *stack) | ||||
| { | ||||
| 	if (rc_runlevel_unstack(runlevel, stack)) { | ||||
| 		einfo("runlevel %s removed from runlevel %s", stack, runlevel); | ||||
| 		einfo("runlevel %s deleted from runlevel %s", stack, runlevel); | ||||
| 		return 1; | ||||
| 	} | ||||
|  | ||||
| @@ -152,7 +152,7 @@ delstack(const char *runlevel, const char *stack) | ||||
| 		eerror("%s: runlevel `%s' is not in the runlevel `%s'", | ||||
| 		    applet, stack, runlevel); | ||||
| 	else | ||||
| 		eerror("%s: failed to remove runlevel `%s' from runlevel `%s': %s", | ||||
| 		eerror("%s: failed to delete runlevel `%s' from runlevel `%s': %s", | ||||
| 		    applet, stack, runlevel, strerror (errno)); | ||||
|  | ||||
| 	return -1; | ||||
|   | ||||
| @@ -36,7 +36,7 @@ void set_quiet_options(void) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| _noreturn void show_version(void) | ||||
| RC_NORETURN void show_version(void) | ||||
| { | ||||
| 	const char *systype = NULL; | ||||
|  | ||||
| @@ -51,7 +51,7 @@ _noreturn void show_version(void) | ||||
| 	exit(EXIT_SUCCESS); | ||||
| } | ||||
|  | ||||
| _noreturn void usage(int exit_status) | ||||
| RC_NORETURN void usage(int exit_status) | ||||
| { | ||||
| 	const char * const has_arg[] = { "", "<arg>", "[arg]" }; | ||||
| 	int i; | ||||
|   | ||||
| @@ -21,6 +21,7 @@ | ||||
| #include <stdarg.h> | ||||
| #include <stdbool.h> | ||||
| #include <stddef.h> | ||||
| #include <stdint.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| @@ -28,29 +29,16 @@ | ||||
|  | ||||
| #define ERRX fprintf (stderr, "out of memory\n"); exit (1) | ||||
|  | ||||
| #define UNCONST(a)		((void *)(unsigned long)(const void *)(a)) | ||||
| #define UNCONST(a)		((void *)(uintptr_t)(const void *)(a)) | ||||
|  | ||||
| #ifdef lint | ||||
| # define _unused | ||||
| #endif | ||||
| #if __GNUC__ > 2 || defined(__INTEL_COMPILER) | ||||
| # define _dead __attribute__((__noreturn__)) | ||||
| # define _noreturn __attribute__ ((__noreturn__)) | ||||
| # define _unused __attribute__((__unused__)) | ||||
| # define _xasprintf(a, b)  __attribute__((__format__(__printf__, a, b))) | ||||
| #else | ||||
| # define _dead | ||||
| # define _noreturn | ||||
| # define _unused | ||||
| # define _xasprintf(a, b) | ||||
| #endif | ||||
| #define RC_UNUSED __attribute__((__unused__)) | ||||
| #define RC_NORETURN __attribute__((__noreturn__)) | ||||
| #define RC_PRINTF(a, b)  __attribute__((__format__(__printf__, a, b))) | ||||
|  | ||||
| #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) | ||||
|  | ||||
| #ifdef __GLIBC__ | ||||
| #  if !defined (__UCLIBC__) && !defined (__dietlibc__) | ||||
| #ifndef HAVE_STRLCPY | ||||
| #    define strlcpy(dst, src, size) snprintf(dst, size, "%s", src) | ||||
| #  endif | ||||
| #endif | ||||
|  | ||||
| #ifndef timespecsub | ||||
| @@ -65,7 +53,7 @@ | ||||
| 	} while (/* CONSTCOND */ 0) | ||||
| #endif | ||||
|  | ||||
| _unused static void *xmalloc (size_t size) | ||||
| RC_UNUSED static void *xmalloc (size_t size) | ||||
| { | ||||
| 	void *value = malloc(size); | ||||
|  | ||||
| @@ -76,7 +64,7 @@ _unused static void *xmalloc (size_t size) | ||||
| 	/* NOTREACHED */ | ||||
| } | ||||
|  | ||||
| _unused static void *xrealloc(void *ptr, size_t size) | ||||
| RC_UNUSED static void *xrealloc(void *ptr, size_t size) | ||||
| { | ||||
| 	void *value = realloc(ptr, size); | ||||
|  | ||||
| @@ -87,7 +75,7 @@ _unused static void *xrealloc(void *ptr, size_t size) | ||||
| 	/* NOTREACHED */ | ||||
| } | ||||
|  | ||||
| _unused static char *xstrdup(const char *str) | ||||
| RC_UNUSED static char *xstrdup(const char *str) | ||||
| { | ||||
| 	char *value; | ||||
|  | ||||
| @@ -109,7 +97,7 @@ _unused static char *xstrdup(const char *str) | ||||
|  * 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) | ||||
| RC_UNUSED static const char *basename_c(const char *path) | ||||
| { | ||||
| 	const char *slash = strrchr(path, '/'); | ||||
|  | ||||
| @@ -118,14 +106,14 @@ _unused static const char *basename_c(const char *path) | ||||
| 	return (path); | ||||
| } | ||||
|  | ||||
| _unused static bool exists(const char *pathname) | ||||
| RC_UNUSED static bool exists(const char *pathname) | ||||
| { | ||||
| 	struct stat buf; | ||||
|  | ||||
| 	return (stat(pathname, &buf) == 0); | ||||
| } | ||||
|  | ||||
| _unused static bool existss(const char *pathname) | ||||
| RC_UNUSED static bool existss(const char *pathname) | ||||
| { | ||||
| 	struct stat buf; | ||||
|  | ||||
| @@ -140,7 +128,7 @@ _unused static bool existss(const char *pathname) | ||||
|  * 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, ...) | ||||
| RC_UNUSED RC_PRINTF(2,3) static int xasprintf(char **strp, const char *fmt, ...) | ||||
| { | ||||
| 	va_list ap; | ||||
| 	int len; | ||||
|   | ||||
| @@ -10,6 +10,10 @@ schedules_c = files([ | ||||
|   'schedules.c', | ||||
|   ]) | ||||
|  | ||||
| pipes_c = files([ | ||||
| 	'pipes.c', | ||||
| 	]) | ||||
|  | ||||
| if selinux_dep.found() | ||||
|   selinux_c = files([ | ||||
|     'selinux.c', | ||||
|   | ||||
| @@ -15,10 +15,18 @@ | ||||
|  *    except according to the terms contained in the LICENSE file. | ||||
|  */ | ||||
|  | ||||
| #ifdef HAVE_CLOSE_RANGE | ||||
| /* For close_range() */ | ||||
| # define _GNU_SOURCE | ||||
| #endif | ||||
|  | ||||
| #include <ctype.h> | ||||
| #include <errno.h> | ||||
| #include <fcntl.h> | ||||
| #include <limits.h> | ||||
| #ifdef HAVE_LINUX_CLOSE_RANGE_H | ||||
| #  include <linux/close_range.h> | ||||
| #endif | ||||
| #include <signal.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| @@ -26,6 +34,7 @@ | ||||
| #include <sys/file.h> | ||||
| #include <sys/time.h> | ||||
| #ifdef __linux__ | ||||
| #  include <sys/syscall.h> /* for close_range */ | ||||
| #  include <sys/sysinfo.h> | ||||
| #endif | ||||
| #include <sys/types.h> | ||||
| @@ -234,7 +243,7 @@ signal_setup_restart(int sig, void (*handler)(int)) | ||||
| } | ||||
|  | ||||
| int | ||||
| svc_lock(const char *applet) | ||||
| svc_lock(const char *applet, bool ignore_lock_failure) | ||||
| { | ||||
| 	char *file = NULL; | ||||
| 	int fd; | ||||
| @@ -245,6 +254,14 @@ svc_lock(const char *applet) | ||||
| 	if (fd == -1) | ||||
| 		return -1; | ||||
| 	if (flock(fd, LOCK_EX | LOCK_NB) == -1) { | ||||
| 		if (ignore_lock_failure) { | ||||
| 			/* Two services with a need b, and b's start() | ||||
| 			 * calling restart --no-deps on a would cause | ||||
| 			 * harmless errors: just ignore them. | ||||
| 			 * See https://github.com/OpenRC/openrc/issues/224 | ||||
| 			 */ | ||||
| 			exit(EXIT_SUCCESS); | ||||
| 		} | ||||
| 		eerror("Call to flock failed: %s", strerror(errno)); | ||||
| 		close(fd); | ||||
| 		return -1; | ||||
| @@ -274,7 +291,7 @@ exec_service(const char *service, const char *arg) | ||||
| 	sigset_t old; | ||||
| 	struct sigaction sa; | ||||
|  | ||||
| 	fd = svc_lock(basename_c(service)); | ||||
| 	fd = svc_lock(basename_c(service), false); | ||||
| 	if (fd == -1) | ||||
| 		return -1; | ||||
|  | ||||
| @@ -492,3 +509,30 @@ pid_t get_pid(const char *applet,const char *pidfile) | ||||
|  | ||||
| 	return pid; | ||||
| } | ||||
|  | ||||
| #ifndef HAVE_CLOSE_RANGE | ||||
| static inline int close_range(int first RC_UNUSED, | ||||
| 			      int last RC_UNUSED, | ||||
| 			      unsigned int flags RC_UNUSED) | ||||
| { | ||||
| #ifdef SYS_close_range | ||||
| 	return syscall(SYS_close_range, first, last, flags); | ||||
| #else | ||||
| 	errno = ENOSYS; | ||||
| 	return -1; | ||||
| #endif | ||||
| } | ||||
| #endif | ||||
| #ifndef CLOSE_RANGE_CLOEXEC | ||||
| # define CLOSE_RANGE_CLOEXEC	(1U << 2) | ||||
| #endif | ||||
|  | ||||
| void | ||||
| cloexec_fds_from(int first) | ||||
| { | ||||
| 	int i; | ||||
| 	if (close_range(first, UINT_MAX, CLOSE_RANGE_CLOEXEC) < 0) { | ||||
| 		for (i = getdtablesize() - 1; i >= first; --i) | ||||
| 			fcntl(i, F_SETFD, FD_CLOEXEC); | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -50,7 +50,7 @@ void env_filter(void); | ||||
| void env_config(void); | ||||
| 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 *, bool); | ||||
| int svc_unlock(const char *, int); | ||||
| pid_t exec_service(const char *, const char *); | ||||
|  | ||||
| @@ -73,4 +73,6 @@ void from_time_t(char *time_string, time_t tv); | ||||
| time_t to_time_t(char *timestring); | ||||
| pid_t get_pid(const char *applet, const char *pidfile); | ||||
|  | ||||
| void cloexec_fds_from(int); | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| executable('start-stop-daemon', | ||||
|   ['start-stop-daemon.c', 'pipes.c', misc_c, schedules_c, | ||||
|   ['start-stop-daemon.c', pipes_c, misc_c, schedules_c, | ||||
| 	selinux_c, usage_c, version_h], | ||||
|   c_args : [cc_audit_flags, cc_branding_flags, cc_pam_flags, cc_cap_flags, cc_selinux_flags], | ||||
|   link_with: [libeinfo, librc], | ||||
|   | ||||
| @@ -179,9 +179,9 @@ extern char **environ; | ||||
| # define SYS_ioprio_set __NR_ioprio_set | ||||
| #endif | ||||
| #if !defined(__DragonFly__) | ||||
| static inline int ioprio_set(int which _unused, | ||||
| 			     int who _unused, | ||||
| 			     int ioprio _unused) | ||||
| static inline int ioprio_set(int which RC_UNUSED, | ||||
| 			     int who RC_UNUSED, | ||||
| 			     int ioprio RC_UNUSED) | ||||
| { | ||||
| #ifdef SYS_ioprio_set | ||||
| 	return syscall(SYS_ioprio_set, which, who, ioprio); | ||||
| @@ -1098,12 +1098,7 @@ int main(int argc, char **argv) | ||||
| 				|| rc_yesno(getenv("EINFO_QUIET"))) | ||||
| 			dup2(stderr_fd, STDERR_FILENO); | ||||
|  | ||||
| #ifdef HAVE_CLOSEFROM | ||||
| 		closefrom(3); | ||||
| #else | ||||
| 		for (i = getdtablesize() - 1; i >= 3; --i) | ||||
| 			close(i); | ||||
| #endif | ||||
| 		cloexec_fds_from(3); | ||||
|  | ||||
| 		if (scheduler != NULL) { | ||||
| 			int scheduler_index; | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| executable('supervise-daemon', | ||||
|   ['supervise-daemon.c', misc_c, plugin_c, schedules_c, usage_c, version_h], | ||||
|   ['supervise-daemon.c', pipes_c, misc_c, plugin_c, schedules_c, usage_c, version_h], | ||||
|   c_args : [cc_branding_flags, cc_pam_flags, cc_cap_flags, cc_selinux_flags], | ||||
|   link_with: [libeinfo, librc], | ||||
|   dependencies: [dl_dep, pam_dep, cap_dep, util_dep, selinux_dep], | ||||
|   | ||||
| @@ -22,11 +22,6 @@ | ||||
| #define ONE_SECOND    1000000000 | ||||
| #define ONE_MS           1000000 | ||||
|  | ||||
| #ifdef HAVE_CLOSE_RANGE_CLOEXEC | ||||
| /* For close_range() */ | ||||
| # define _GNU_SOURCE | ||||
| #endif | ||||
|  | ||||
| #include <errno.h> | ||||
| #include <fcntl.h> | ||||
| #include <getopt.h> | ||||
| @@ -67,6 +62,7 @@ static struct pam_conv conv = { NULL, NULL}; | ||||
| #include "queue.h" | ||||
| #include "rc.h" | ||||
| #include "misc.h" | ||||
| #include "pipes.h" | ||||
| #include "plugin.h" | ||||
| #include "schedules.h" | ||||
| #include "_usage.h" | ||||
| @@ -84,6 +80,8 @@ enum { | ||||
|   LONGOPT_OOM_SCORE_ADJ, | ||||
|   LONGOPT_NO_NEW_PRIVS, | ||||
|   LONGOPT_SECBITS, | ||||
|   LONGOPT_STDERR_LOGGER, | ||||
|   LONGOPT_STDOUT_LOGGER, | ||||
| }; | ||||
|  | ||||
| const char *applet = NULL; | ||||
| @@ -115,6 +113,8 @@ const struct option longopts[] = { | ||||
| 	{ "user",         1, NULL, 'u'}, | ||||
| 	{ "stdout",       1, NULL, '1'}, | ||||
| 	{ "stderr",       1, NULL, '2'}, | ||||
| 	{ "stdout-logger",1, NULL, LONGOPT_STDOUT_LOGGER}, | ||||
| 	{ "stderr-logger",1, NULL, LONGOPT_STDERR_LOGGER}, | ||||
| 	{ "reexec",       0, NULL, '3'}, | ||||
| 	longopts_COMMON | ||||
| }; | ||||
| @@ -143,6 +143,8 @@ const char * const longopts_help[] = { | ||||
| 	"Change the process user", | ||||
| 	"Redirect stdout to file", | ||||
| 	"Redirect stderr to file", | ||||
| 	"Redirect stdout to process", | ||||
| 	"Redirect stderr to process", | ||||
| 	"reexec (used internally)", | ||||
| 	longopts_help_COMMON | ||||
| }; | ||||
| @@ -165,6 +167,8 @@ static int stdout_fd; | ||||
| static int stderr_fd; | ||||
| static char *redirect_stderr = NULL; | ||||
| static char *redirect_stdout = NULL; | ||||
| static char *stderr_process = NULL; | ||||
| static char *stdout_process = NULL; | ||||
| #ifdef TIOCNOTTY | ||||
| static int tty_fd = -1; | ||||
| #endif | ||||
| @@ -192,8 +196,8 @@ extern char **environ; | ||||
| # define SYS_ioprio_set __NR_ioprio_set | ||||
| #endif | ||||
| #if !defined(__DragonFly__) | ||||
| static inline int ioprio_set(int which _unused, int who _unused, | ||||
| 			     int ioprio _unused) | ||||
| static inline int ioprio_set(int which RC_UNUSED, int who RC_UNUSED, | ||||
| 			     int ioprio RC_UNUSED) | ||||
| { | ||||
| #ifdef SYS_ioprio_set | ||||
| 	return syscall(SYS_ioprio_set, which, who, ioprio); | ||||
| @@ -208,7 +212,7 @@ static void cleanup(void) | ||||
| 	free(changeuser); | ||||
| } | ||||
|  | ||||
| _noreturn static void re_exec_supervisor(void) | ||||
| RC_NORETURN static void re_exec_supervisor(void) | ||||
| { | ||||
| 	syslog(LOG_WARNING, "Re-executing for %s", svcname); | ||||
| 	execlp("supervise-daemon", "supervise-daemon", svcname, "--reexec", | ||||
| @@ -354,7 +358,7 @@ static pid_t exec_command(const char *cmd) | ||||
| 	return pid; | ||||
| } | ||||
|  | ||||
| _noreturn static void child_process(char *exec, char **argv) | ||||
| RC_NORETURN static void child_process(char *exec, char **argv) | ||||
| { | ||||
| 	RC_STRINGLIST *env_list; | ||||
| 	RC_STRING *env; | ||||
| @@ -554,6 +558,12 @@ _noreturn static void child_process(char *exec, char **argv) | ||||
| 			eerrorx("%s: unable to open the logfile" | ||||
| 				    " for stdout `%s': %s", | ||||
| 				    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 ((stderr_fd = open(redirect_stderr, | ||||
| @@ -562,19 +572,22 @@ _noreturn static void child_process(char *exec, char **argv) | ||||
| 			eerrorx("%s: unable to open the logfile" | ||||
| 			    " for stderr `%s': %s", | ||||
| 			    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)); | ||||
| 	} | ||||
|  | ||||
| 	dup2(stdin_fd, STDIN_FILENO); | ||||
| 	if (redirect_stdout || rc_yesno(getenv("EINFO_QUIET"))) | ||||
| 	if (redirect_stdout || stdout_process || rc_yesno(getenv("EINFO_QUIET"))) | ||||
| 		dup2(stdout_fd, STDOUT_FILENO); | ||||
| 	if (redirect_stderr || rc_yesno(getenv("EINFO_QUIET"))) | ||||
| 	if (redirect_stderr || stderr_process || rc_yesno(getenv("EINFO_QUIET"))) | ||||
| 		dup2(stderr_fd, STDERR_FILENO); | ||||
|  | ||||
| #ifdef HAVE_CLOSE_RANGE_CLOEXEC | ||||
| 	if (close_range(3, UINT_MAX, CLOSE_RANGE_CLOEXEC) < 0) | ||||
| #endif | ||||
| 		for (i = getdtablesize() - 1; i >= 3; --i) | ||||
| 			fcntl(i, F_SETFD, FD_CLOEXEC); | ||||
| 	cloexec_fds_from(3); | ||||
|  | ||||
| 	cmdline = make_cmdline(argv); | ||||
| 	syslog(LOG_INFO, "Child command line: %s", cmdline); | ||||
| 	free(cmdline); | ||||
| @@ -587,7 +600,7 @@ _noreturn static void child_process(char *exec, char **argv) | ||||
| 	eerrorx("%s: failed to exec `%s': %s", applet, exec,strerror(errno)); | ||||
| } | ||||
|  | ||||
| _noreturn static void supervisor(char *exec, char **argv) | ||||
| RC_NORETURN static void supervisor(char *exec, char **argv) | ||||
| { | ||||
| 	FILE *fp; | ||||
| 	char buf[2048]; | ||||
| @@ -1047,6 +1060,14 @@ int main(int argc, char **argv) | ||||
| 			reexec = true; | ||||
| 			break; | ||||
|  | ||||
| 		case LONGOPT_STDOUT_LOGGER:   /* --stdout-logger "command to run for stdout logging" */ | ||||
| 			stdout_process = optarg; | ||||
| 			break; | ||||
|  | ||||
| 		case LONGOPT_STDERR_LOGGER:  /* --stderr-logger "command to run for stderr logging" */ | ||||
| 			stderr_process = optarg; | ||||
| 			break; | ||||
|  | ||||
| 		case_RC_COMMON_GETOPT | ||||
| 		} | ||||
|  | ||||
|   | ||||
| @@ -1,55 +1,54 @@ | ||||
| Using supervise-daemon | ||||
| ====================== | ||||
| # Using supervise-daemon | ||||
|  | ||||
| Beginning with OpenRC-0.21 we have our own daemon supervisor, | ||||
| supervise-daemon., which can start a daemon and restart it if it | ||||
| `supervise-daemon`, which can start a daemon and restart it if it | ||||
| terminates unexpectedly. | ||||
|  | ||||
| The following is a brief guide on using this capability. | ||||
|  | ||||
| * Use Default start, stop and status functions | ||||
| * **Use Default start, stop and status functions**. | ||||
|   If you write your own start, stop and status functions in your service | ||||
|   script, none of this will work. You must allow OpenRC to use the default | ||||
|   functions. | ||||
|  | ||||
| * Daemons must not fork | ||||
|   Any daemon that you would like to have monitored by supervise-daemon | ||||
| * **Daemons must not fork**. | ||||
|   Any daemon that you would like to have monitored by `supervise-daemon` | ||||
|   must not fork. Instead, it must stay in the foreground. If the daemon | ||||
|   forks, the supervisor will be unable to monitor it. | ||||
|  | ||||
|   If the daemon can be configured to not fork, this should be done in the | ||||
|   daemon's configuration file, or by adding a command line option that | ||||
|   instructs it not to fork to the command_args_foreground variable shown | ||||
|   instructs it not to fork to the `command_args_foreground` variable shown | ||||
|   below. | ||||
|  | ||||
| # Health Checks | ||||
| ## Health checks | ||||
|  | ||||
| Health checks are a way to make sure a service monitored by | ||||
| supervise-daemon stays healthy. To configure a health check for a | ||||
| service, you need to write a healthcheck() function, and optionally an | ||||
| unhealthy() function in the service script. Also, you will need to set | ||||
| the healthcheck_timer and optionally healthcheck_delay variables. | ||||
| `supervise-daemon` stays healthy. To configure a health check for a | ||||
| service, you need to write a `healthcheck()` function, and optionally an | ||||
| `unhealthy()` function in the service script. Also, you will need to set | ||||
| the `healthcheck_timer` and optionally `healthcheck_delay` variables. | ||||
|  | ||||
| ## healthcheck() function | ||||
| ### healthcheck() function | ||||
|  | ||||
| The healthcheck() function is run repeatedly based on the settings of | ||||
| the healthcheck_* variables. This function should return zero if the | ||||
| The `healthcheck()` function is run repeatedly based on the settings of | ||||
| the `healthcheck_*` variables. This function should return zero if the | ||||
| service is currently healthy or non-zero otherwise. | ||||
|  | ||||
| ## unhealthy() function | ||||
| ### unhealthy() function | ||||
|  | ||||
| If the healthcheck() function returns non-zero, the unhealthy() function | ||||
| If the `healthcheck()` function returns non-zero, the `unhealthy()` function | ||||
| is run, then the service is restarted. Since the service will be | ||||
| restarted by the supervisor, the unhealthy function should not try to | ||||
| restart it; the purpose of the function is to allow any cleanup tasks | ||||
| other than restarting the service to be run. | ||||
|  | ||||
| # Variable Settings | ||||
| ## Variable settings | ||||
|  | ||||
| The most important setting is the supervisor variable. At the top of | ||||
| your service script, you should set this variable as follows: | ||||
|  | ||||
| ``` sh | ||||
| ```sh | ||||
| supervisor=supervise-daemon | ||||
| ``` | ||||
|  | ||||
| @@ -57,29 +56,29 @@ Several other variables affect the way services behave under | ||||
| supervise-daemon. They are documented on the  openrc-run man page, but I | ||||
| will list them here for convenience: | ||||
|  | ||||
| ``` sh | ||||
| ```sh | ||||
| command_args_foreground="arguments" | ||||
| ``` | ||||
|  | ||||
| This 	should be used if the daemon you want to monitor | ||||
| This should be used if the daemon you want to monitor | ||||
| forks and goes to the background by default. This should be set to the | ||||
| command line option that instructs the daemon to stay in the foreground. | ||||
|  | ||||
| ``` sh | ||||
| ```sh | ||||
| healthcheck_delay=seconds | ||||
| ``` | ||||
|  | ||||
| This is the delay, in seconds, before the first health check is run. | ||||
| If it is not set, we use the value of healthcheck_timer. | ||||
| If it is not set, we use the value of `healthcheck_timer`. | ||||
|  | ||||
| ``` sh | ||||
| ```sh | ||||
| healthcheck_timer=seconds | ||||
| ``` | ||||
|  | ||||
| This is the  number of seconds between health checks. If it is not set, | ||||
| no health checks will be run. | ||||
|  | ||||
| ``` sh | ||||
| ```sh | ||||
| respawn_delay | ||||
| ``` | ||||
|  | ||||
| @@ -87,7 +86,7 @@ This is the number of seconds to delay before attempting to respawn a | ||||
| supervised process after it dies unexpectedly. | ||||
| The default is to respawn immediately. | ||||
|  | ||||
| ``` sh | ||||
| ```sh | ||||
| respawn_max=x | ||||
| ``` | ||||
|  | ||||
| @@ -95,17 +94,17 @@ This is the maximum number of times to respawn a supervised process | ||||
| during the given respawn period. | ||||
| The default is 10. 0 means unlimited. | ||||
|  | ||||
| ``` sh | ||||
| ```sh | ||||
| respawn_period=seconds | ||||
| ``` | ||||
|  | ||||
| This works in conjunction with respawn_max and respawn_delay above to | ||||
| This works in conjunction with `respawn_max` and `respawn_delay` above to | ||||
| decide if a process should not be respawned for some reason. | ||||
|  | ||||
| For example, if respawn period is 10 and respawn_max is 2, the process | ||||
| For example, if respawn period is 10 and `respawn_max` is 2, the process | ||||
| would need to die 3 times within 10 seconds to no longer be respawned. | ||||
| Note that respawn_delay will delay all of this, so in the above scenario | ||||
| a respawn_delay of greater than 5 will cause infinite respawns. | ||||
| Note that `respawn_delay` will delay all of this, so in the above scenario | ||||
| a `respawn_delay` of greater than 5 will cause infinite respawns. | ||||
|  | ||||
| By default, this is unset and respawn_max applies to the entire lifetime | ||||
| By default, this is unset and `respawn_max` applies to the entire lifetime | ||||
| of the service. | ||||
|   | ||||
| @@ -11,8 +11,7 @@ sysvinit="$4" | ||||
| if [ "${os}" != Linux ]; then | ||||
| 	install -d "${DESTDIR}/${rc_libexecdir}"/init.d | ||||
| fi | ||||
| install -d "${DESTDIR}/${rc_libexecdir}"/tmp | ||||
| install -m 644 "${MESON_BUILD_ROOT}/src/shared/version" "${DESTDIR}/${rc_libexecdir}" | ||||
| if [ "${os}" = Linux ] && [ "${sysvinit}" = yes ]; then | ||||
| 	ln -s openrc-init "${DESTDIR}/${sbindir}"/init | ||||
| 	ln -sf openrc-init "${DESTDIR}/${sbindir}"/init | ||||
| fi | ||||
|   | ||||
		Reference in New Issue
	
	Block a user