pax_global_header00006660000000000000000000000064147461367530014532gustar00rootroot0000000000000052 comment=eaffb0684d24b2ac852f739d0056b5489f639e29 unit-translator-0.7/000077500000000000000000000000001474613675300145465ustar00rootroot00000000000000unit-translator-0.7/.gitignore000066400000000000000000000000031474613675300165270ustar00rootroot00000000000000*~ unit-translator-0.7/ChangeLog000066400000000000000000000123531474613675300163240ustar00rootroot000000000000002025-01-28 Mark Hindley * Version 0.7 * utrans: handle multiple special exec prefixes. * backends/lsb: fix typo in SecureBits substitution. * backends/lsb: removed doubled quotation of embedded substitutions. * backends/openrc: fix SecureBits handling: convert arguments to integer. * t/input/sssd.service: add real world test of SecureBits. * backends/lsb: drop beta-quality warning. * utrans-deb: support UNIT_TRANSLATOR environment variable to override path to utrans for testing. * backends/cron: protect generated cron fragments from running if systemd is PID1 (and presumably the relevant .timer will be active). 2024-11-11 Mark Hindley * Version 0.6. * utrans-rc: don't take ownership of files already registered with ucfr. * utrans-rc: only register with ucfr if modifications have been made. 2024-11-04 Mark Hindley * Version 0.5. * utrans-rc: revert workaround for #816220, it breaks debconf. * utrans-rc: preserve environment variable DEBIAN_FRONTEND for ucf/debconf. 2024-11-01 Mark Hindley * Quote arguments to unset (shellcheck). * man/utrans-rc.1: document behaviour when source unit change; correct default unit source path. * utrans-rc: use invoke-rc.d(8) rather than service(8). * utrans: fix handling of display-manager Alias: unset and continue if the unit is not the default display-manager. 2024-10-15 Mark Hindley * utrans-rc: verify_installed(): only handle each owned file once. * utrans-rc: pass UCF_FORCE_CONFF* environment variables to ucf(1). * Support service[RootDirectory]. * README.org: add Debian packages and local git checkout instructions to usage. * README.org: update manpage link. * utrans-rc: ignore package source when updating existing translated units. * backends/lsb: support capabilities using setpriv(8). 2024-10-13 Mark Hindley * utrans: fix logic for detecting correct ulimit NPROC flag. * Rework ulimit handling. * Fix socket-activate commandline for ListenDatagram * backends/lsb: use s-s-d --startas so that socket activated services stop correctly. * backends/openrc: ignore '-' prefix to service[WorkingDirectory]. * backends/lsb: support service[WorkingDirectory]. * utrans-rc: minimise, cache and reuse expensive dpkg-query calls. 2024-10-07 Mark Hindley * Version 0.4: Release 2024-09-24 Mark Hindley * utrans: support comma separated list of backends. * utrans-deb: add with thanks to Ralph Ronnquist (rrq@rrq.au). 2024-09-15 Mark Hindley * utrans: chown runtime directories to service[User]:service[Group], if set. * backends/openrc: support RemainAfterExit=no. * backends/openrc: rework capabilities (again!). * utrans-rc: update translated files if source unit has changed. * b/openrc: don't produce linux-specific output on non-linux. * t/update: filter (ignore) expected missing backend errors. * backends/openrc: support service KillMode and SendSIGHUP. 2024-09-09 Mark Hindley * Version 0.3: Release * Fix RuntimeDirectoryPreserve which only controls deletion of RuntimeDirectory itself. * Fix CacheDirectory path. * backends/openrc: cleanup capabilities handling * Fix generated ACPower test * backends/lsb: support Nice, IOSchedulingClass, IOSchedulingPriority, User, Group and UMask 2024-09-01 Mark Hindley * Move shared constraint prefix and trigger handling to frontend. * t/: test each backend individually. * Support '=' backend prefix to skip loading of default backends and provide warning stubs for missing backends. 2024-08-28 Mark Hindley * Ensure environment directives are quoted to protect spaces. * backends/lsb: don't create a pidfile for service[Type]=forking. * Support service[Type] notify-reload. * backends/lsb: handle socket-activated services with start-stop-daemon. * backends/lsb: ensure environment variables are set before they are used. * Rework dependency mapping to avoid duplicates or conflicts. 2024-08-27 Mark Hindley * utrans-rc: support -b option. * utrans-rc: automatically select backends if none are specifically requested. 2024-08-26 Mark Hindley * backends/lsb: merge initial LSB support. * utrans: support DefaultDependencies. 2024-08-25 Mark Hindley * Version 0.2.1: Fixup release. * Makefile: don't remove man/*.1 in clean recipe. 2024-08-25 Mark Hindley * Version 0.2: Release. * man/: write manpages in raw groff. * utrans-rc: ensure variables are not inherited from environment. * utrans-rc: only use timestamp and -u option for default search path. * utrans-rc: include both /lib/systemd/system and /usr/lib/systemd/system by default. utrans-rc: skip install if a dpkg package already provides files in the installation directory. * utrans: fix handling of multiple Requires. * backends/openrc: fix ignoring unknown virtual dependencies. 2024-08-24 Mark Hindley * Version 0.1: Initial Release with openrc, cron, xinetd and inetd backends. unit-translator-0.7/LICENSE000066400000000000000000000025351474613675300155600ustar00rootroot00000000000000BSD-2-Clause License Copyright (c) 2020, K Gopal Krishna. All rights reserved. Copyright (c) 2023-, Mark Hindley. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. unit-translator-0.7/Makefile000066400000000000000000000013251474613675300162070ustar00rootroot00000000000000#! make -f VERSION=0.7 export UTRANS_DATA_DIR ?= $(CURDIR) export SYSTEMD_UNIT_PATH=./input all: sed -i 's#^readonly VERSION=[[:digit:]]\+\(\.[[:digit:]]\)\+#readonly VERSION=$(VERSION)#' utrans sed -i -e '1 s#Version [[:digit:]]\+\(\.[[:digit:]]\)\+#Version $(VERSION)#' \ -e '1 s#"[[:digit:]]\{4\}-[[:digit:]]\{2\}-[[:digit:]]\{2\}"#$(shell date -I)#' man/*.1 check: shellcheck mancheck cd ./t && ./run mancheck: man/*.1 groff -mandoc -t -K utf8 -ww -b -z $? shellcheck: ifeq (, $(shell which shellcheck)) $(warning "No shellcheck found in $(PATH), skipping") else shellcheck --external-sources --exclude SC2155 --severity=info utrans shellcheck utrans-rc endif clean: update-expected: cd ./t && ./update unit-translator-0.7/README.org000066400000000000000000000026451474613675300162230ustar00rootroot00000000000000#+TITLE: Unit Translator #+AUTHOR: Mark Hindley * About Unit Translator is written (/almost purely/) in bash and converts systemd-style units to generic unix equivalents. It is based on Systemd Unit Translator, written by K Gopal Krishna as part of the Google Summer of Code, 2020. * Dependencies - GNU =grep=, =sed=, =awk= * Usage See the [[file:man/utrans.1][Manual]]. Packages for [[https://tracker.debian.org/pkg/unit-translator][Debian and derivatives]] are available. It can also be run directly from a local copy of the [[https://git.devuan.org/LeePen/unit-translator/][=git= repository]]. Set the UTRANS_DATA_DIR and UNIT_TRANSLATOR environment variables:- #+begin_src sh git clone https://git.devuan.org/LeePen/unit-translator UTRANS_DATA_DIR=./unit-translator ./unit-translator/utrans /lib/systemd/system/unit.service /tmp UTRANS_DATA_DIR=./unit-translator UNIT_TRANSLATOR=./unit-translator/utrans ./unit-translator/utrans-rc #+end_src * References - https://linux.die.net/man/8/xinetd - https://manpages.debian.org/unstable/socket-activate/socket-activate.1.en.html - https://www.freedesktop.org/software/systemd/man/systemd.service.html - https://www.freedesktop.org/software/systemd/man/systemd.socket.html - https://www.freedesktop.org/software/systemd/man/systemd.time.html# - https://www.freedesktop.org/software/systemd/man/systemd.timer.html - https://www.freedesktop.org/software/systemd/man/systemd.unit.html unit-translator-0.7/backends/000077500000000000000000000000001474613675300163205ustar00rootroot00000000000000unit-translator-0.7/backends/README000066400000000000000000000023421474613675300172010ustar00rootroot00000000000000Output backends for utrans Backends enable utrans to produce various output formats. The following types are available:- - service (openrc, lsb) - timer (cron) - inetd (xinetd, inetd) Valid backends:- - must be bash scripts. A shebang is not required and the files should not be executable as backends are sourced by the main program. Therefore they inherit the restrictions of the main script (currently errexit, pipefail, nounset, noglob). - must provide a function export_ for each type they wish to handle. The function is called with 2 arguments: the full path to the systemd unit and the base output directory. The backend is responsible for creating any subdirectories it requires and writing files within them. - should use the global associative arrays (unit, service, socket, timer, install) whose keys allow access to the parsed systemd unit. Systemd Before, After, Requires and Wants dependencies are translated to insserv/LSB-style equivalents accessible via the depends[{Before,Requires,Wants}] array. - are recommended to embed the output of gen_origin() at the top of any generated files. This will produce a header with the origin file sha256. unit-translator-0.7/backends/cron000066400000000000000000000045771474613675300172210ustar00rootroot00000000000000# cron output backend # shellcheck shell=bash eval_cron_expr() { local m h dom mon dow case "${timer[OnCalendar]}" in # handle special calendar event expressions minutely) ;; hourly) m=0 ;; daily) m=0 h=0 ;; weekly) m=0 h=0 dow=1 ;; monthly) m=0 h=0 dom=1 ;; quarterly) m=0 h=0 dom=1 m=1,4,7,10 ;; semiannually) m=0 h=0 dom=1 m=1,7 ;; yearly) m=0 h=0 dom=1 m=1 ;; # Parse *) read -ra oncal <<<"${timer[OnCalendar]}" for calsub in "${oncal[@]}"; do # echo "Sub: ${calsub}" if [[ "$calsub" =~ ^([,0-6]|\.\.|Sun|Mon|Tue|Wed|Thu|Fri|Sat)+$ ]]; then declare -l dow="${calsub//../-}" continue echo " dow: ${dow}" fi case "${calsub}" in *-*) # Date # cron is year agnostic, just require mon-dom and dom="${calsub##*-}" calsub="${calsub%-"$dom"}" mon="${calsub##*-}" continue echo " mon: $mon" echo " dom: $dom" ;; *:*) # Time # cron granularity is seconds h="${calsub%%:*}" calsub="${calsub#"${h}":}" m="${calsub%%:*}" continue echo " h: $h" echo " m: $m" ;; esac done ;; esac echo "${m:-*} ${h:-*} ${dom:-*} ${mon:-*} ${dow:-*}" } gen_cron_entry() { local sep crontab=$(eval_cron_expr) printf '# %s\n\n' 'm h dom mon dow user command' printf '%s %s [ -d /run/systemd/system ] || {' "${crontab}" "${service[User]:-root}" while read -r cmd; do printf '%s %s' "${sep:-}" "${cmd#-}" # Ignore - prefix if [[ -z "${cmd%%-*}" ]]; then printf ' || true' fi sep=';' done <<<"${service[ExecStart]}" printf '; }\n' printf '# %s\n' 'Alternatively, if your system is running openrc you could use' printf '# %s %s %s\n' "${crontab}" 'root' "rc-service ${systemd_unit_file%.timer} start" } export_timer() { systemd_unit=$1 base_dir=$2 cron_dir="${base_dir}/cron.d" if [[ -z "${timer[OnCalendar]:-}" ]] ; then # Empty, are any of OnActiveSec, OnBootSec, OnStartupSec, # OnUnitActiveSec, OnUnitInactiveSec, OnClockChange, # OnTimezoneChange supportable? echo "WARNING: timer[OnCalendar] empty, skipping" >&2 return fi mkdir -p "${cron_dir}" cron_d_file="${cron_dir}/$(basename "${systemd_unit}" .timer)" # embed source and sha256 gen_origin >"${cron_d_file}" # generate the cron entry into the appropriate file gen_cron_entry >>"${cron_d_file}" } unit-translator-0.7/backends/inetd000066400000000000000000000013521474613675300173470ustar00rootroot00000000000000# inetd output backend # shellcheck shell=bash export_inetd() { systemd_unit=$1 base_dir=$2 if [[ "${socket[ListenStream]:-}" ]]; then port="${socket[ListenStream]}" type="stream" proto="tcp" flags="wait" elif [[ "${socket[ListenDatagram]:-}" ]]; then port="${socket[ListenDatagram]}" type="dgram" proto="udp" flags="nowait" elif [[ "${socket[ListenSequentialPackets]:-}" ]]; then echo "Sequential Packets not supported by inetd backend" >&2 exit 1 fi # printf 'Run "update-inetd --add ' printf "'%s %s %s %s %s %s %s'\n" "$port" "$type" "$proto" "$flags" "${service[User]:-root}" "${service[ExecStart]// */}" "${service[ExecStart]#* }" } unit-translator-0.7/backends/lsb000066400000000000000000000241461474613675300170320ustar00rootroot00000000000000# LSB output backend # shellcheck shell=bash gen_shebang() { # Shebang printf '%s\n' '#! /bin/sh' } gen_init_d_script() { printf '%s\n' '# kFreeBSD does not accept scripts as interpreters, using #!/bin/sh and sourcing.' printf '%s\n' 'if [ true != "$INIT_D_SCRIPT_SOURCED" ] ; then' printf '%s\n' ' set "$0" "$@"; INIT_D_SCRIPT_SOURCED=true . /lib/init/init-d-script' printf '%s\n' 'fi' } gen_start() { case "${install[WantedBy]:-}" in '') ;; sysinit.target) printf 'S' ;; single.target|basic.target) printf '1' ;; *.target) printf '2 3 4 5' ;; *) echo "WARNING: unknown start target runlevel ${install[WantedBy]}" >&2 ;; esac } gen_stop() { case "${install[WantedBy]:-}" in '') ;; *.target) printf '0 1 6' ;; *) echo "WARNING: unknown stop target runlevel ${install[WantedBy]}" >&2 ;; esac } munge_deps() { self=$(local -; set +o noglob; find /etc/insserv.conf* -type f -exec awk "/$(basename "$lsb_init_script")/ {print \$1}" '{}' ';') for key in Requires Wants After Before; do for dep in ${depends[$key]:-}; do if [[ "$dep" == "$self" ]] ; then remove_depend "$dep" "$key" fi done done add_depends Wants ${depends[After]:-} for dep in ${depends[Requires]:-}; do remove_depend "$dep" Wants done for dep in ${depends[Wants]:-}; do remove_depend "$dep" Before done } gen_lsb_header() { # Uncomment to show the data parsed by the frontend # declare -p unit >&2 # declare -p service >&2 # declare -p depends >&2 # declare -p install >&2 munge_deps printf '%s\n' '### BEGIN INIT INFO' printf '%s %s\n' '# Provides:' "$(basename "${systemd_unit%.*}")${install[Alias]:+ ${install[Alias]%.*}}" printf '%s %s\n' '# Required-Start:' "${depends[Requires]:-}" printf '%s %s\n' '# Required-Stop:' "${depends[Requires]:-}" [[ "${depends[Wants]:-}" ]] && printf '%s %s\n' '# Should-Start:' "${depends[Wants]}" [[ "${depends[Wants]:-}" ]] && printf '%s %s\n' '# Should-Stop:' "${depends[Wants]}" printf '%s %s\n' '# Default-Start:' "$(gen_start)" printf '%s %s\n' '# Default-Stop:' "$(gen_stop)" [[ "${depends[Before]:-}" ]] && printf '%s %s\n' '# X-Start-Before:' "${depends[Before]}" [[ "${depends[Before]:-}" ]] && printf '%s %s\n' '# X-Stop-After:' "${depends[Before]}" # printf '%s %s\n' '# X-Interactive:' 'true' printf '%s %s\n' '# Description:' "${unit[Description]:-None provided}" printf '%s\n' '### END INIT INFO' } gen_lsb_environment() { gen_environment if [[ "${service[ExecStop]:-}${service[ExecReload]:-}" =~ '$MAINPID' ]]; then print_directive MAINPID '$([ ! -f "/run/${DAEMON}.pid" ] || cat "/run/${DAEMON}.pid")' fi } gen_directives() { if [[ "${unit[Description]:-}" ]]; then print_directive DESC "${unit[Description]}" fi print_directive umask "${service[UMask]:-}" if [[ -n "${service[ExecStart]:-}" ]]; then if [[ "${service[Type]}" == 'oneshot' ]] ; then print_directive DAEMON none print_directive NAME "$(basename "${systemd_unit%.*}")" gen_lsb_environment for key in "${!lsb[@]}"; do # Skip directives just for s-s-d [[ "$key" != START_ARGS ]] || continue print_directive "$key" "${lsb[$key]}" done print_sh_function do_start_cmd_override "$(handle_exec_prefixes "${service[ExecStart]}")" else set -- ${service[ExecStart]} if [[ "${service[Type]}" == 'socket' ]]; then print_directive NAME "$(basename "${systemd_unit%.*}")" print_directive COMMAND_NAME none print_directive DAEMON none lsb[START_ARGS]+=' --startas /usr/bin/socket-activate' else case $1 in /*) print_directive DAEMON "$1" ;; -*) print_directive DAEMON "${1#-}" echo "TODO: ignore s-s-d exit status" >&2 ;; @*|+*|!*) echo "WARNING: ignoring special exec prefix" >&2 print_directive DAEMON "${1##@|+|!|!!}" ;; *) print_directive DAEMON "$(PATH=/usr/sbin:/usr/bin:/sbin:/bin: which "$1")" ;; esac fi shift gen_lsb_environment print_directive DAEMON_ARGS "$*" for key in "${!lsb[@]}"; do print_directive "$key" "${lsb[$key]}" done fi fi while read -r ulimit ; do printf 'ulimit %s\n' "$ulimit" done < <(gen_ulimit_args) } # Based on backends/openrc but with /lib/lsb/init-functions functions gen_pre_checks() { for constraint in Assert Condition; do for test in ACPower Architecture Capability ControlGroupController CPUFeature CPUs DirectoryNotEmpty Environment FileIsExecutable FileNotEmpty Firmware FirstBoot Group Host KernelCommandLine KernelVersion Memory NeedsUpdate OSRelease PathExists PathExistsGlob PathIsDirectory PathIsEncrypted PathIsMountPoint PathIsReadWrite PathIsSymbolicLink Security User Virtualization; do while read -r trigger read -r pre read -r p; do t=$(gen_test_case "$test" "$pre" "$p") if [ "${t}" ]; then if [ "${trigger}" ] ; then triggers+=$'\n'"( $t ) ||" else [ $constraint = 'Assert' ] && fail="echo \"Prohibited by ${constraint}${test} ${pre}${p}\"; exit 1" || fail="do_start_cmd_override() { log_warning_msg \" .. Skipped due to ${constraint}${test} ${pre}${p}\" ; }" echo "$t || $fail" fi else echo "WARNING: unsupported test: $constraint $test ${pre}${p}" >&2 echo "# WARNING: skipped unsupported ${constraint}${test} ${pre}${p}" fi done < <(split_constraint "${unit[${constraint}${test}]:-}") done done if [[ "${triggers:-}" ]] ; then printf '( # Triggering conditions\n' # Remove the final trailing '||' print_lines "${triggers%||}" ' ' printf ') || do_start_cmd_override() { log_warning_msg " .. Skipped due to no Triggering Conditions" ; }' fi } gen_functions() { [[ -z "${service[ExecStartPre]:-}" ]] || service[ExecStartPre]+=$'\n' service[ExecStartPre]+=$(gen_pre_checks) # This appears at odds with init-d-script(5) which states:- # # Additionally, it is possible to change the behaviour of the resulting # shell script by overriding some of the internal functions. To do so, # define function with an _override suffix. # # However, this naming doesn't seems to apply to functions that are no-op. print_sh_function do_start_prepare "$(handle_exec_prefixes "${service[ExecStartPre]:-}")" print_sh_function do_start_cleanup "$(handle_exec_prefixes "${service[ExecStartPost]:-}")" print_sh_function do_stop_prepare "$(handle_exec_prefixes "${service[ExecStopPre]:-}")" print_sh_function do_stop_cleanup "$(handle_exec_prefixes "${service[ExecStopPost]:-}")" print_sh_function do_stop_cmd_override "$(handle_exec_prefixes "${service[ExecStop]:-}")" print_sh_function do_reload "$(handle_exec_prefixes "${service[ExecReload]:-}")" } export_service() { systemd_unit=$1 base_dir=$2 init_dir="${base_dir}/init.d" mkdir -p "${init_dir}" lsb_init_script="${init_dir}/$(basename "${systemd_unit%.*}")" if [[ -z "${lsb_init_script##*@}" ]] ; then echo "LSB doesn't support instantiated services" >&2 exit 1 fi # array to hold directives declare -A lsb case "${service[Type]}" in oneshot) ;; simple|exec|idle|dbus|socket) lsb[PIDFILE]="/run/$(basename "${lsb_init_script}").pid" lsb[START_ARGS]="--background --make-pidfile";; notify|notify-reload) lsb[PIDFILE]="/run/$(basename "${lsb_init_script}").pid" lsb[START_ARGS]="--background --make-pidfile --notify-await" if [[ "${service[Type]}" == 'notify-reload' ]]; then lsb[RELOAD_SIGNAL]=HUP fi ;; forking) lsb[PIDFILE]=none ;; esac # run as $user and $group if the systemd service provides one if [[ "${service[User]:-}" ]]; then local user="${service[User]}" if [[ "${service[Group]:-}" ]]; then local group="${service[Group]}" fi lsb[START_ARGS]+=" --chuid ${user}${group:+:"${group}"}" fi if [[ -n "${service[Nice]:-}" ]]; then lsb[START_ARGS]+=" --nicelevel ${service[Nice]}" fi if [[ -n "${service[IOSchedulingClass]:-}" || -n "${service[IOSchedulingPriority]:-}" ]]; then lsb[START_ARGS]+=" --iosched ${service[IOSchedulingClass]:-best-effort}:${service[IOSchedulingPriority]:-4}" fi if [[ -n "${service[UMask]:-}" ]]; then lsb[START_ARGS]+=" --umask ${service[UMask]:-}" fi if [[ -n "${service[WorkingDirectory]:-}" ]]; then lsb[START_ARGS]+=" --chdir ${service[WorkingDirectory]#-}" fi if [[ -n "${service[RootDirectory]:-}" ]]; then lsb[START_ARGS]+=" --chroot ${service[RootDirectory]}" fi if [[ "$(uname -s)" == 'Linux' ]]; then if [[ -n "${service[NoNewPrivileges]:-}" ]] && is_true "${service[NoNewPrivileges]}"; then lsb[SETPRIV_ARGS]+="--no-new-privs " fi if [[ -n "${service[SecureBits]:-}" ]]; then secbits=${service[SecureBits]/-/_} lsb[SETPRIV_ARGS]+="--securebits +${secbits//[$' \r\t\n']/,+} " fi if [[ "${service[CapabilityBoundingSet]+defined}" ]] ; then case "${service[CapabilityBoundingSet]}" in # start-stop-daemon requires CAP_SETUID and CAP_SETGID for --chuid '') lsb[SETPRIV_ARGS]+="--bounding-set -all${service[User]:+,+CAP_SETUID,+CAP_SETGID} " ;; ~*) caps="${service[CapabilityBoundingSet]//CAP_/,-}" if [[ "${service[User]:-}" ]] ; then caps="${caps//,-SET[UG]ID}" fi lsb[SETPRIV_ARGS]+="--bounding-set +all${caps//[$'~ \r\t\n']} " ;; *) caps="${service[CapabilityBoundingSet]//CAP_/,+}" lsb[SETPRIV_ARGS]+="--bounding-set -all${caps//[$' \r\t\n']} " ;; esac fi if [[ "${service[AmbientCapabilities]+defined}" ]] ; then case "${service[AmbientCapabilities]}" in '') lsb[SETPRIV_ARGS]+="--ambient-caps -all ";; ~*) caps="${service[AmbientCapabilities]//CAP_/,-}" lsb[SETPRIV_ARGS]+="--ambient-caps +all${caps//[$'~ \r\t\n']} " ;; *) caps="${service[AmbientCapabilities]//CAP_/,+}" lsb[SETPRIV_ARGS]+="--ambient-caps -all${caps//[$' \r\t\n']} " # TODO: does this require --secbits keep-cap? See # https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#AmbientCapabilities= ;; esac fi fi # shebang gen_shebang >"${lsb_init_script}" # embed source and sha256 gen_origin >>"${lsb_init_script}" # source init-d-script gen_init_d_script >>"${lsb_init_script}" gen_lsb_header >>"${lsb_init_script}" gen_directives >>"${lsb_init_script}" gen_functions >>"${lsb_init_script}" } unit-translator-0.7/backends/openrc000066400000000000000000000341631474613675300175400ustar00rootroot00000000000000# openrc output backend # shellcheck shell=bash # add openrc shebang # # rely on in-built variables and functions available via the # openrc-run interpreter gen_openrc_script_shebang() { printf '%s\n' '#!/sbin/openrc-run' } # Return the complement of the supplied capabilities cap_complement() { declare -A avail="( $(setpriv --list-caps | awk 'BEGIN{ORS=" ";} { print "CAP_" toupper($0), NR }') )" for cap do unset 'avail[${cap}]' done echo "${!avail[@]}" } #cap_complement CAP_CHOWN CAP_LL CAP_ANOTHET # generate variables from the values defined in service[key]. # gen_openrc_script_variables() { local ssd_args # add service description printf '%s\n' "description=\"${unit[Description]:-None provided}.\"" if [ "${unit[Documentation]:-}" ]; then printf '# %s:\n' 'Documentation' while read -r doc; do # shellcheck disable=SC2086 printf '# %s\n' ${doc} # Unquoted to split whitespace done <<<"${unit[Documentation]}" fi printf '\n' if [[ "${service[Type]}" != "forking" && "${service[Type]}" != oneshot ]]; then if [[ "${service[Restart]:-}" != no ]]; then # TODO: supervise-daemon doesn't distinguish Restart categories print_directive supervisor supervise-daemon fi fi gen_openrc_script_exec_event --start "${service[ExecStart]:-}" print_directive umask "${service[UMask]:-}" print_directive directory "${service[WorkingDirectory]:+"${service[WorkingDirectory]#-}"}" # Ignore '-' prefix if [[ -n "${service[RootDirectory]:-}" ]]; then ssd_args="--chroot ${service[RootDirectory]} " fi if [[ -n "${service[Nice]:-}" ]]; then ssd_args+="--nicelevel ${service[Nice]} " fi if [[ "$(uname -s)" == 'Linux' ]] ; then if [[ -n "${service[IOSchedulingClass]:-}" || -n "${service[IOSchedulingPriority]:-}" ]]; then ssd_args+="--iosched ${service[IOSchedulingClass]:-best-effort}:${service[IOSchedulingPriority]:-4} " fi if [[ -n "${service[NoNewPrivileges]:-}" ]] && is_true "${service[NoNewPrivileges]}"; then ssd_args+="--no-new-privs " fi if [[ -n "${service[SecureBits]:-}" ]]; then local secbits=0 for sbit in ${service[SecureBits]}; do case $sbit in # See linux/securebits.h noroot) bit=0;; noroot-locked) bit=1;; no-setuid-fixup) bit=2;; no-setuid-fixup-locked) bit=3;; keep-caps) bit=4;; keep-caps-locked) bit=5;; *) bit=;; esac [ "$bit" ] && ((secbits+=2**bit)) done ssd_args+="--secbits ${secbits} " fi if [[ -n "${service[OOMScoreAdjust]:-}" ]]; then ssh_args+="--oom-score-adj ${service[OOMScoreAdjust]} " fi if [[ "${service[CapabilityBoundingSet]+defined}" ]] ; then # openrc --capabilities use cap_iab_from_text(3) which doesn't # support all/none. So build the complement manually. caps=$(cap_complement ${service[CapabilityBoundingSet]#'~'}) case ${service[CapabilityBoundingSet]} in '') caps_args="!${caps//[$' \n\r\t']/,!}" ;; ~*) caps_args="${caps//[$' \n\r\t']/,}" caps_args+="${service[CapabilityBoundingSet]//[$' ~\n\r\t']/,!}" ;; *) caps_args="!${caps//[$' \n\r\t']/,!}" caps_args+=",${service[CapabilityBoundingSet]//[$' \n\r\t']/,}" ;; esac fi if [[ "${service[AmbientCapabilities]+defined}" ]] ; then case ${service[AmbientCapabilities]} in '') ;; ~*) caps=$(cap_complement ${service[AmbientCapabilities]#'~'}) caps_args+="${caps_args:+,}^${caps//[$' \n\r\t']/,^}" ;; *) caps_args+="${caps_args:+,}^${service[AmbientCapabilities]//[$' \n\r\t']/,^}" ;; esac fi if [[ -n "${caps_args:-}" ]]; then ssd_args+="--capabilities $caps_args " fi fi print_directive start_stop_daemon_args "${ssd_args:-}" } # Replace insserv/LSB dependency with supplied expansion replace_depend() { dep=$1 key=$2 shift 2 # /etc/insserv.conf expansions are preceeded by +, i.e. optional, so move # Requires to Wants if [[ "$key" == Requires ]]; then append_key=Wants else append_key="$key" fi # Remove original remove_depend "$dep" "$key" # Add replacements add_depends "$append_key" "$@" # Remove circular dependencies remove_depend "${openrc_script}" "$key" } # depends[] is insserv/LSB style. Recursively expand virtual references. expand_lsb_depends() { while [[ "${depends[*]}" =~ '$' ]]; do for key in Requires Wants After Before; do for dep in ${depends[$key]:-}; do case "$dep" in # TODO: taken from /etc/insserv.conf. Consider grep rather than harcoding. \$local_fs) replace_depend "$dep" "$key" mountall mountall-bootclean mountoverflowtmp umountfs ;; \$network) replace_depend "$dep" "$key" networking ifupdown ;; \$named) replace_depend "$dep" "$key" named dnsmasq lwresd bind9 unbound pdns-recursor \$network ;; \$remote_fs) replace_depend "$dep" "$key" \$local_fs mountnfs mountnfs-bootclean umountnfs sendsigs ;; \$syslog) replace_depend "$dep" "$key" rsyslog sysklogd syslog-ng dsyslog inetutils-syslogd ;; \$time) replace_depend "$dep" "$key" hwclock ;; # and /etc/insserv.conf.d \$portmap) replace_depend "$dep" "$key" rpcbind ;; \$*) echo "WARNING: ignoring unknown virtual dependency $dep" >&2 replace_depend "$dep" "$key" '' ;; esac done done done } # dependency resolution # # pending: special cases gen_openrc_script_functions() { # if dependencies exist then check which dependency exists. according to the # check, use either one of `need`, `use`, `before` and `after`. if [[ -n "${depends[*]}"|| -n "${install[Alias]:-}" ]]; then expand_lsb_depends printf '%s\n' 'depend() {' if [[ -n "${depends[Requires]:-}" ]]; then printf "%s\n" " need ${depends[Requires]}" fi if [[ -n "${depends[Wants]:-}" ]]; then printf "%s\n" " use ${depends[Wants]}" fi if [[ -n "${depends[Before]:-}" ]]; then printf "%s\n" " before ${depends[Before]}" fi if [[ -n "${depends[After]:-}" ]]; then printf "%s\n" " after ${depends[After]}" fi if [[ -n "${install[Alias]:-}" ]]; then alias=${install[Alias]//.service} printf "%s\n" " provide ${alias#$}" # Could be lsb/insserv style; remove any leading $ fi printf '%s\n' '}' fi for t in Stop Start-Pre Start-Post Stop-Pre Stop-Post Reload ; do gen_openrc_script_exec_event "--${t@L}" "${service[Exec${t/-/}]:-}" done } # generate configuration required by the service gen_openrc_script_conf() { gen_environment if [[ "${service[ExecStop]:-}${service[ExecReload]:-}" =~ '$MAINPID' ]]; then print_directive MAINPID '$([ ! -f "/run/supervise-${RC_SVCNAME}.pid" ] || cat "/run/supervise-${RC_SVCNAME}.pid")' fi if [[ "${service[KillMode]:-control-group}" = 'control-group' ]]; then print_directive rc_cgroup_cleanup YES print_directive rc_send_sighup "${service[SendSIGHUP]:-no}" fi while read -r tmp ; do ulimit+="$tmp " done < <(gen_ulimit_args) print_directive rc_ulimit "${ulimit:-}" } # a generic function that handles all events of type: start, stop, reload, # start_pre, stop_pre, start_post, stop_post. # # this function accepts two arguments: first one is the type of execution # (start, stop, etc) and the second is the actual command performing said # execution. gen_openrc_script_exec_event() { local exec_name exec_args exec_type exec_event # type is {start,stop,restart,reload} and event is the actual $type command exec_type="${1}" exec_event=$(handle_exec_prefixes "${2}") # start generating the script case "${exec_type}" in "--start") # Handle oneshot with a custom start(). Multiple ExecStart possible if [[ "${service[Type]}" == oneshot ]]; then print_sh_function start "${exec_event}" else # Everything before the first space exec_name=${exec_event%% *} # Everything not in $exec_name exec_args=${exec_event#"${exec_name}"} printf '%s\n' "command=\"${exec_name}\"" printf '%s\n' "command_args=\"${exec_args# }\"" # trim initial whitespace fi # run as $user and $group if the systemd service provides one if [[ "${service[User]:-}" ]]; then local user user="${service[User]}" if [[ "${service[Group]:-}" ]]; then local group group="${service[Group]}" printf '%s\n' "command_user=\"${user}:${group}\"" else printf '%s\n' "command_user=\"${user}\"" fi fi # define PID if the systemd service provides one if [[ "${service[PIDFile]:-}" ]]; then local pid_file pid_file="${service[PIDFile]}" printf '%s\n' "pidfile=\"${pid_file}\"" fi ;; "--stop") print_sh_function stop "${exec_event}" ;; "--start-pre") chks=$(cat <&2 echo "# WARNING: skipped unsupported ${constraint}${test} ${pre}${p}" fi unset t trigger pre done < <(split_constraint "${unit[${constraint}${test}]:-}") done done if [[ "${triggers:-}" ]] ; then printf '( # Triggering conditions\n' # Remove the final trailing '||' print_lines "${triggers%||}" ' ' printf ') || start() { einfo "Skipped due to no Triggering Conditions" ; }' fi } export_service() { systemd_unit=$1 base_dir=$2 openrc_init_dir="${base_dir}/init.d" mkdir -p "${openrc_init_dir}" openrc_script=$(basename "${systemd_unit%.*}") # indicate instantiated units if [[ -z "${openrc_script#*@}" ]]; then instantiated=1 openrc_script="${openrc_script/\@/\.}" else instantiated=0 fi # Handle service Type specifics case "${service[Type]}" in oneshot) if ! is_true "${service[RemainAfterExit]:-no}" ; then service[ExecStartPost]+=$'\nmark_service_stopped' fi ;; notify-reload) service[ExecReload]='supervise-daemon "${RC_SVCNAME}" -s HUP' ;; esac # generate the "#!/sbin/openrc-run" shebang which is required to run # openrc scripts gen_openrc_script_shebang >"${openrc_init_dir}/${openrc_script}" # embed source and sha256 gen_origin >>"${openrc_init_dir}/${openrc_script}" # generate and store necessary openrc variables in the appropriate file gen_openrc_script_variables | replace_specifiers >>"${openrc_init_dir}/${openrc_script}" # generate and store necessary openrc functions in the appropriate file gen_openrc_script_functions | replace_specifiers >>"${openrc_init_dir}/${openrc_script}" # make resulting script executable by the owner only chmod u+x "${openrc_init_dir}/${openrc_script}" # Handle directives for conf.d file conf_d_contents=$(gen_openrc_script_conf) if [[ -n "${conf_d_contents:-}" ]]; then openrc_conf_dir="${base_dir}/conf.d" mkdir -p "${openrc_conf_dir}" # generate and store the environment variables in the appropriate file gen_origin >"${openrc_conf_dir}/${openrc_script}" printf '%s\n' "$conf_d_contents" >>"${openrc_conf_dir}/${openrc_script}" fi } unit-translator-0.7/backends/xinetd000066400000000000000000000025031474613675300175360ustar00rootroot00000000000000# xinetd output backend # shellcheck shell=bash gen_xinetd_entry() { printf '%s\n' "service $(basename "${service[ExecStart]// */}")" printf '%s\n' '{' printf '%s\n' " disabled = no" if [[ "${socket[ListenStream]:-}" ]]; then printf '%s\n' " port = ${socket[ListenStream]}" printf '%s\n' " socket_type = stream" printf '%s\n' " wait = no" elif [[ "${socket[ListenDatagram]:-}" ]]; then printf '%s\n' " port = ${socket[ListenDatagram]}" printf '%s\n' " socket_type = dgram" printf '%s\n' " protocol = udp" printf '%s\n' " wait = yes" elif [[ "${socket[ListenSequentialPackets]:-}" ]]; then printf '%s\n' " port = ${socket[ListenSequentialPackets]}" printf '%s\n' " socket_type = seqpacket" printf '%s\n' " protocol = udp" printf '%s\n' " wait = yes" fi printf '%s\n' " user = ${service[User]:-root}" server=${service[ExecStart]%% *} printf '%s\n' " server = $server" server_args=${service[ExecStart]#"${server}"} printf '%s\n' " server_args = ${server_args# }" printf '%s\n' '}' } export_inetd() { systemd_unit=$1 base_dir=$2 xinetd_dir="${base_dir}/xinetd.d" mkdir -p "${xinetd_dir}" xinetd_file="${xinetd_dir}/$(basename "${systemd_unit}" .socket)" # generate a xinetd configuration file gen_xinetd_entry "${systemd_unit%%.socket}" >"${xinetd_file}" } unit-translator-0.7/man/000077500000000000000000000000001474613675300153215ustar00rootroot00000000000000unit-translator-0.7/man/utrans-deb.1000066400000000000000000000020371474613675300174510ustar00rootroot00000000000000.TH "UTRANS-DEB" "1" 2024-10-07 "Version 0.7" "User Commands" .SH "NAME" .PP \fCutrans-deb\fP \- apply \fIutrans\fP to all systemd units in given deb files .SH "SYNOPSIS" \fCutrans [ -b ] * \fP .SH "OPTIONS" .PP The following commandline options are supported:- .TP \fB-b \fP use the comma-separated list of backends for all \fIutrans\fP calls. The last mentioned backend of each type (service, socket, timer) will be used. .SH "DESCRIPTION" .PP \fCutrans-deb\fP uses \fIutrans\fP to translate systemd services, sockets and timers in given \fIdeb\fP files to corresponding generic UNIX configuration and scripting as used in alternative settings that exclude systemd. The translation creates a temporary working directory in the current directory for unpacking of all \fIdeb\fP given files and translation of their units. The result is packed up into a tar file named as the first \fIdeb\fP file with "-services.tgz" appended. .SH SEE ALSO .P utrans(1) .SH "AUTHORS" .PP Copyright 2024, Ralph Ronnquist unit-translator-0.7/man/utrans-rc.1000066400000000000000000000035241474613675300173250ustar00rootroot00000000000000.TH "UTRANS-RC" "1" 2024-09-09 "Version 0.7" "User Commands" .P .SH NAME .P utrans-rc - convert systemd units using utrans(1) and then save or install them .P .SH SYNOPSIS .P utrans-rc [-h] [-b .\&.\&] [-n | -o ] [-u | .\&.\&] .P .SH OPTIONS .P The following commandline options are supported:- .TP \fB-b \fR specify backend used by utrans(1). If unset, automatically detect the appropriate backends to use .TP \fB-h\fR show usage .TP \fB-o \fR save generated files to subdirectories of .TP \fB-n\fR no action; dry run to show what would be done .TP \fB-u\fR only check for new/modified/deleted units and update; ignored if or specified .SH DESCRIPTION .P utrans-rc scans the source directory/directories for systemd.\&service(5) and systemd.\&timer(5) units. If no source directory is specified, \fI[/usr]/lib/systemd/system\fR is scanned. .P Each unit is converted using utrans(1). .P If is specified, generated files are saved there. Otherwise, the files are considered for installation beneath \fI/etc\fR using sudo(8) and ucf(1) to preserve user modifications. However, installation of the whole unit is skipped if .IP \(bu 2 the unit'\&s parent package already includes functionality in the installation directory .IP \(bu 2 it would overwrite any files in a package known to dpkg(1) .P utrans-rc also checks previously generated and installed files for changes in their source units. If any modified units are found they are re-translated. If the source units have been removed, the generated files are disabled and removed (if unmodified). .SH SEE ALSO .P utrans(1), ucf(1) .P .SH COPYRIGHT .P BSD-2-Clause License .P Copyright (c) 2023-2024, Mark Hindley .P .SH AUTHORS .P Mark Hindley unit-translator-0.7/man/utrans.1000066400000000000000000000100401474613675300167120ustar00rootroot00000000000000.TH "UTRANS" "1" 2024-09-09 "Version 0.7" "User Commands" .SH "NAME" .PP \fCutrans\fP \- convert systemd units to generic unix equivalents .SH "SYNOPSIS" \fCutrans [-b [=][,]] [-f ] [-h] [-v] \fP .SH "OPTIONS" .PP The following commandline options are supported:- .TP \fB-b \fP load the specified backend(s). Can be a comma separated list. See \fIBACKENDS\fP below for further details. .TP \fB-f \fP force; valid types are: .IP \fBoverwrite\fP: allow overwriting existing output files .TP \fB-h\fP open manpage .TP \fB-v\fP show version .SH "DESCRIPTION" .PP \fCutrans\fP translates systemd services, sockets and timers to corresponding generic UNIX configuration and scripting as used in alternative settings that exclude systemd. is the pathname for the unit file to translate. .IP \(bu 4 Service units are converted to \fBopenrc-run(8)\fP service scripts. .IP \(bu 4 Socket units are converted either to an \fBxinetd(8)\fP configuration or an \fBopenrc-run(8)\fP script using \fBsocket-activate(1)\fP, depending on the requirements of the socket. .IP \(bu 4 Timer units are converted to a \fBcrontab(5)\fP fragment mapping \fBsystemd.time(7)\fP events to a \fBcron(8)\fP-compatible expressions. .SH "USAGE" .PP \fCutrans\fP accepts two arguments: the \fBsystemd.unit(5)\fP file () and the output directory (). The \fBsystemd.unit(5)\fP file which can be one of \fBsystemd.service(5)\fP, \fBsystemd.socket(5)\fP or \fBsystemd.timer(5)\fP. .PP The script will create files in the following output subdirectories of depending on the unit type: .TS center,allbox; r lx . Unit Output Service T{ An \fBopenrc-run(8)\fP script is created in \fIinit.d\fP and a complementary file is created in \fIconf.d\fP if needed, for sourcing additional additional environment variables. T} Socket T{ Depending upon the socket's configuration, an \fBxinetd(8)\fP configuration fragment is created in \fIxinetd.d\fP, or an \fBopenrc-run(8)\fP script is created in \fIinit.d\fP to start the service with \fBsocket-activate(1)\fP, . T} Timer T{ A separate \fBcrontab(5)\fR fragment is created into \fIcron.d\fP for each timer unit. T} .TE .PP When the unit translation requires other units, then these are searched in the paths defined in the environment variable \fI$SYSTEMD_UNIT_PATH\fP, or in \fI/usr/lib/system/system:/lib/systemd/system\fP by default. .SH "BACKENDS" .PP Backends are used for producing different output for different settings. \fButrans\fR finds and sources backend script fragments from the \fI$UTRANS_DATA_DIR/backends\fP directory or from \fI/usr/share/utrans/backends\fP by default. .PP If the backend is prefixed with \fC=\fP, the default backends are not loaded. .PP The following backends are available: .TS center,allbox; l l lx . Backend Unit Notes openrc Service Loaded by default xinetd Socket Loaded by default cron Timer Loaded by default inetd Socket T{ Only supports ListenStream and ListenDatagram using \fBupdate-inetd(8)\fP T} lsb Service T{ Alpha quality support for scripts with LSB-style \fBinsserv(8)\fP headers T} .TE .PP Contributions of other backends are welcome: see \fIbackends/README\fP for further details. .SH "LIMITATIONS" .PP The following are known cases of poor or variant functionality: .IP \(bu 4 Some special Executable Prefixes are ignored after warning. .IP \(bu 4 Unescaping specifiers doesn't distinguish context: if you require a filesystem path, start the instance with '-'. .PP Patches are welcome at \fIhttps://git.devuan.org/LeePen/unit-translator\fP! .SH SEE ALSO .P utrans-rc(1), openrc(8), socket-activate(1) .SH "COPYRIGHT" .P BSD-2-Clause License \fIhttps://opensource.org/licenses/BSD-2-Clause\fP .P Copyright (c) 2020, K Gopal Krishna. .P Copyright (c) 2023-2024, Mark Hindley .SH "AUTHORS" .PP K Gopal Krishna under the guidance of Benda Xu , Adam Borowski and Mo Zhou . .PP This project was a part of Google Summer of Code, 2020. .PP Mark Hindley unit-translator-0.7/t/000077500000000000000000000000001474613675300150115ustar00rootroot00000000000000unit-translator-0.7/t/expected/000077500000000000000000000000001474613675300166125ustar00rootroot00000000000000unit-translator-0.7/t/expected/cron/000077500000000000000000000000001474613675300175535ustar00rootroot00000000000000unit-translator-0.7/t/expected/cron/cron.d/000077500000000000000000000000001474613675300207365ustar00rootroot00000000000000unit-translator-0.7/t/expected/cron/cron.d/oneshot000066400000000000000000000007251474613675300223440ustar00rootroot00000000000000# Generated by ../utrans from: # c04adf70b0a86fb204f5229920c3383457549d9cfb1307ce6b26ea78414211c4 ./input/oneshot.timer # b05e280c90034554585cb7fbb33cbd93fbabfaa7cf9736cee888077954c9f396 ./input/oneshot.service # m h dom mon dow user command 10 03 * * sun admin [ -d /run/systemd/system ] || { /usr/bin/ls /; binary_found_in_path; /bin/false || true; } # Alternatively, if your system is running openrc you could use # 10 03 * * sun root rc-service oneshot start unit-translator-0.7/t/expected/inetd/000077500000000000000000000000001474613675300177155ustar00rootroot00000000000000unit-translator-0.7/t/expected/inetd/.empty000066400000000000000000000000001474613675300210420ustar00rootroot00000000000000unit-translator-0.7/t/expected/lsb/000077500000000000000000000000001474613675300173725ustar00rootroot00000000000000unit-translator-0.7/t/expected/lsb/init.d/000077500000000000000000000000001474613675300205575ustar00rootroot00000000000000unit-translator-0.7/t/expected/lsb/init.d/oneshot000066400000000000000000000014441474613675300221640ustar00rootroot00000000000000#! /bin/sh # Generated by ../utrans from: # b05e280c90034554585cb7fbb33cbd93fbabfaa7cf9736cee888077954c9f396 ./input/oneshot.service # kFreeBSD does not accept scripts as interpreters, using #!/bin/sh and sourcing. if [ true != "$INIT_D_SCRIPT_SOURCED" ] ; then set "$0" "$@"; INIT_D_SCRIPT_SOURCED=true . /lib/init/init-d-script fi ### BEGIN INIT INFO # Provides: oneshot # Required-Start: $remote_fs # Required-Stop: $remote_fs # Should-Start: $network # Should-Stop: $network # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Description: Test oneshot ### END INIT INFO DESC="Test oneshot" DAEMON="none" NAME="oneshot" do_start_cmd_override() { /usr/bin/ls / binary_found_in_path /bin/false || true } do_start_prepare() { /usr/bin/true } do_stop_cmd_override() { /usr/bin/finish stop } unit-translator-0.7/t/expected/lsb/init.d/openntpd000066400000000000000000000020471474613675300223340ustar00rootroot00000000000000#! /bin/sh # Generated by ../utrans from: # 843c4f9142c604daed198c434b6677a4fd6f45a395434818261679d07aead773 ./input/openntpd.service # kFreeBSD does not accept scripts as interpreters, using #!/bin/sh and sourcing. if [ true != "$INIT_D_SCRIPT_SOURCED" ] ; then set "$0" "$@"; INIT_D_SCRIPT_SOURCED=true . /lib/init/init-d-script fi ### BEGIN INIT INFO # Provides: openntpd # Required-Start: $remote_fs # Required-Stop: $remote_fs # Should-Start: $network # Should-Stop: $network # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Description: OpenNTPd Network Time Protocol ### END INIT INFO DESC="OpenNTPd Network Time Protocol" DAEMON="/usr/sbin/ntpd" RUNTIME_DIRECTORY="/run/openntpd" [ -r /etc/default/openntpd ] && . /etc/default/openntpd DAEMON_ARGS="$DAEMON_OPTS" SETPRIV_ARGS="--no-new-privs --bounding-set -all,+NET_BIND_SERVICE,+SETGID,+SETUID,+SYSLOG,+SYS_CHROOT,+SYS_NICE,+SYS_TIME" PIDFILE="none" do_start_prepare() { mkdir -p "${RUNTIME_DIRECTORY:?}" /usr/sbin/ntpd -n $DAEMON_OPTS } do_stop_cleanup() { rm -r "${RUNTIME_DIRECTORY:?}" } unit-translator-0.7/t/expected/lsb/init.d/polkit000066400000000000000000000012621474613675300220050ustar00rootroot00000000000000#! /bin/sh # Generated by ../utrans from: # 6dac9df426bbaec2bd79b1e71ad2a30d01e40c0c6e1c0d94150f762c7890b8ff ./input/polkit.service # kFreeBSD does not accept scripts as interpreters, using #!/bin/sh and sourcing. if [ true != "$INIT_D_SCRIPT_SOURCED" ] ; then set "$0" "$@"; INIT_D_SCRIPT_SOURCED=true . /lib/init/init-d-script fi ### BEGIN INIT INFO # Provides: polkit # Required-Start: dbus $remote_fs # Required-Stop: dbus $remote_fs # Default-Start: # Default-Stop: # Description: Authorization Manager ### END INIT INFO DESC="Authorization Manager" DAEMON="/usr/lib/polkit-1/polkitd" DAEMON_ARGS="--no-debug" PIDFILE="/run/polkit.pid" START_ARGS="--background --make-pidfile" unit-translator-0.7/t/expected/lsb/init.d/rpcbind000066400000000000000000000022121474613675300221200ustar00rootroot00000000000000#! /bin/sh # Generated by ../utrans from: # 981477a148e26a4b3e312b2f23ceca24095ec285079b2a9c3277473c1ee4318a ./input/rpcbind.socket # 342bd8ea5b9e3053fa924833a3d0b3514851998a93652c3da12ea824bbf6cd7d ./input/rpcbind.service # kFreeBSD does not accept scripts as interpreters, using #!/bin/sh and sourcing. if [ true != "$INIT_D_SCRIPT_SOURCED" ] ; then set "$0" "$@"; INIT_D_SCRIPT_SOURCED=true . /lib/init/init-d-script fi ### BEGIN INIT INFO # Provides: rpcbind # Required-Start: $local_fs # Required-Stop: $local_fs # Should-Start: systemd-tmpfiles-setup # Should-Stop: systemd-tmpfiles-setup # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Description: RPC bind portmap service ### END INIT INFO DESC="RPC bind portmap service" NAME="rpcbind" COMMAND_NAME="none" DAEMON="none" OPTIONS="-w" [ -r /etc/rpcbind.conf ] && . /etc/rpcbind.conf [ -r /etc/default/rpcbind ] && . /etc/default/rpcbind DAEMON_ARGS="--unix::/run/rpcbind.sock --unix::0.0.0.0:111 --unix::[::]:111 --unix-dgram::0.0.0.0:111 --unix-dgram::[::]:111 -- /sbin/rpcbind -f $OPTIONS" PIDFILE="/run/rpcbind.pid" START_ARGS="--background --make-pidfile --startas /usr/bin/socket-activate" unit-translator-0.7/t/expected/lsb/init.d/rsyslog000066400000000000000000000013271474613675300222070ustar00rootroot00000000000000#! /bin/sh # Generated by ../utrans from: # 726b9641b81ede267adc4180b3e25b85122a4e798e0f748cac0e9e3a414e1622 ./input/rsyslog.service # kFreeBSD does not accept scripts as interpreters, using #!/bin/sh and sourcing. if [ true != "$INIT_D_SCRIPT_SOURCED" ] ; then set "$0" "$@"; INIT_D_SCRIPT_SOURCED=true . /lib/init/init-d-script fi ### BEGIN INIT INFO # Provides: rsyslog syslog # Required-Start: $remote_fs # Required-Stop: $remote_fs # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Description: System Logging Service ### END INIT INFO DESC="System Logging Service" DAEMON="/usr/sbin/rsyslogd" DAEMON_ARGS="-n -iNONE" PIDFILE="/run/rsyslog.pid" START_ARGS="--background --make-pidfile --notify-await" ulimit -n 16384 unit-translator-0.7/t/expected/lsb/init.d/ssh000066400000000000000000000026371474613675300213070ustar00rootroot00000000000000#! /bin/sh # Generated by ../utrans from: # 9c36778605edb201ec5b7d1676887fc00249fa1b2582ec89e158c55b45b4659c ./input/ssh.socket # 35b2858970feb78e985900b33ba8cb84249dfadbf296155e5639cafcf1dd40a3 ./input/ssh.service # kFreeBSD does not accept scripts as interpreters, using #!/bin/sh and sourcing. if [ true != "$INIT_D_SCRIPT_SOURCED" ] ; then set "$0" "$@"; INIT_D_SCRIPT_SOURCED=true . /lib/init/init-d-script fi ### BEGIN INIT INFO # Provides: ssh sshd # Required-Start: $remote_fs # Required-Stop: $remote_fs # Should-Start: $network auditd # Should-Stop: $network auditd # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Description: OpenBSD Secure Shell server ### END INIT INFO DESC="OpenBSD Secure Shell server" NAME="ssh" COMMAND_NAME="none" DAEMON="none" RUNTIME_DIRECTORY="/run/sshd" [ -r /etc/default/ssh ] && . /etc/default/ssh MAINPID="$([ ! -f "/run/${DAEMON}.pid" ] || cat "/run/${DAEMON}.pid")" DAEMON_ARGS="--unix::22 -- /usr/sbin/sshd -D $SSHD_OPTS" PIDFILE="/run/ssh.pid" START_ARGS="--background --make-pidfile --startas /usr/bin/socket-activate" do_start_prepare() { mkdir -p -m 0755 "${RUNTIME_DIRECTORY:?}" /usr/sbin/sshd -t [ ! -e '/etc/ssh/sshd_not_to_be_run' ] || do_start_cmd_override() { log_warning_msg " .. Skipped due to ConditionPathExists !/etc/ssh/sshd_not_to_be_run" ; } } do_stop_cleanup() { rm -r "${RUNTIME_DIRECTORY:?}" } do_reload() { /usr/sbin/sshd -t /bin/kill -HUP $MAINPID } unit-translator-0.7/t/expected/lsb/init.d/sssd000066400000000000000000000030461474613675300214610ustar00rootroot00000000000000#! /bin/sh # Generated by ../utrans from: # de718691081fbceb07b5338f5dabec659b76bc404769356bc8c3ae27b375984e ./input/sssd.service # kFreeBSD does not accept scripts as interpreters, using #!/bin/sh and sourcing. if [ true != "$INIT_D_SCRIPT_SOURCED" ] ; then set "$0" "$@"; INIT_D_SCRIPT_SOURCED=true . /lib/init/init-d-script fi ### BEGIN INIT INFO # Provides: sssd # Required-Start: $remote_fs # Required-Stop: $remote_fs # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # X-Start-Before: systemd-user-sessions # X-Stop-After: systemd-user-sessions # Description: System Security Services Daemon ### END INIT INFO DESC="System Security Services Daemon" DAEMON="/usr/sbin/sssd" DEBUG_LOGGER=--logger="--logger=files" [ -r /etc/default/sssd ] && . /etc/default/sssd DAEMON_ARGS="-i ${DEBUG_LOGGER}" SETPRIV_ARGS="--securebits +noroot,+noroot_locked --bounding-set -all,+SETGID,+SETUID,+DAC_READ_SEARCH" PIDFILE="/run/sssd.pid" START_ARGS="--background --make-pidfile --notify-await --chuid root:root" do_start_prepare() { /bin/chown -f -R root:root /etc/sssd || true /bin/chmod -f -R g+r /etc/sssd || true /bin/sh -c "/bin/chown -f root:root /var/lib/sss/db/*.ldb" || true /bin/chown -f -R root:root /var/lib/sss/gpo_cache || true /bin/sh -c "/bin/chown -f root:root /var/log/sssd/*.log" || true ( # Triggering conditions ( [ -d '/etc/sssd/conf.d/' ] && files=$(ls -qA -- '/etc/sssd/conf.d/') && [ -n "$files" ] ) || ( [ -e '/etc/sssd/sssd.conf' ] ) ) || do_start_cmd_override() { log_warning_msg " .. Skipped due to no Triggering Conditions" ; } } unit-translator-0.7/t/expected/lsb/init.d/systemd-hwdb-update000066400000000000000000000022441474613675300243760ustar00rootroot00000000000000#! /bin/sh # Generated by ../utrans from: # 6cf7fde4df7681b9a581e1c4440cded4bc390128256dc04a1a66916ab6f3d7f7 ./input/systemd-hwdb-update.service # kFreeBSD does not accept scripts as interpreters, using #!/bin/sh and sourcing. if [ true != "$INIT_D_SCRIPT_SOURCED" ] ; then set "$0" "$@"; INIT_D_SCRIPT_SOURCED=true . /lib/init/init-d-script fi ### BEGIN INIT INFO # Provides: systemd-hwdb-update # Required-Start: # Required-Stop: # Should-Start: systemd-remount-fs # Should-Stop: systemd-remount-fs # Default-Start: # Default-Stop: # X-Start-Before: systemd-update-done # X-Stop-After: systemd-update-done # Description: Rebuild Hardware Database ### END INIT INFO DESC="Rebuild Hardware Database" DAEMON="none" NAME="systemd-hwdb-update" do_start_cmd_override() { systemd-hwdb update } do_start_prepare() { # WARNING: skipped unsupported ConditionNeedsUpdate /etc ( # Triggering conditions ( [ -d '/etc/udev/hwdb.d/' ] && files=$(ls -qA -- '/etc/udev/hwdb.d/') && [ -n "$files" ] ) || ( [ ! -e '/usr/lib/udev/hwdb.bin' ] ) || ( [ -e '/etc/udev/hwdb.bin' ] ) ) || do_start_cmd_override() { log_warning_msg " .. Skipped due to no Triggering Conditions" ; } } unit-translator-0.7/t/expected/lsb/init.d/systemd-udevd000066400000000000000000000021441474613675300233000ustar00rootroot00000000000000#! /bin/sh # Generated by ../utrans from: # e5b492be4ceeaae3a854d1e1ff7e25ba9818e9b92da937b6861284f2b5f2bdba ./input/systemd-udevd.service # kFreeBSD does not accept scripts as interpreters, using #!/bin/sh and sourcing. if [ true != "$INIT_D_SCRIPT_SOURCED" ] ; then set "$0" "$@"; INIT_D_SCRIPT_SOURCED=true . /lib/init/init-d-script fi ### BEGIN INIT INFO # Provides: systemd-udevd # Required-Start: # Required-Stop: # Should-Start: systemd-udev-load-credentials systemd-sysusers systemd-hwdb-update # Should-Stop: systemd-udev-load-credentials systemd-sysusers systemd-hwdb-update # Default-Start: # Default-Stop: # Description: Rule-based Manager for Device Events and Files ### END INIT INFO DESC="Rule-based Manager for Device Events and Files" DAEMON="/usr/lib/systemd/systemd-udevd" RELOAD_SIGNAL="HUP" SETPRIV_ARGS="--bounding-set +all,-SYS_TIME,-WAKE_ALARM" PIDFILE="/run/systemd-udevd.pid" START_ARGS="--background --make-pidfile --notify-await" do_start_prepare() { [ -r '/sys' ] && [ -w '/sys' ] || do_start_cmd_override() { log_warning_msg " .. Skipped due to ConditionPathIsReadWrite /sys" ; } } unit-translator-0.7/t/expected/openrc/000077500000000000000000000000001474613675300201005ustar00rootroot00000000000000unit-translator-0.7/t/expected/openrc/conf.d/000077500000000000000000000000001474613675300212475ustar00rootroot00000000000000unit-translator-0.7/t/expected/openrc/conf.d/foot-server.000066400000000000000000000004441474613675300235250ustar00rootroot00000000000000# Generated by ../utrans from: # e59b2780e736677dd241446be95ce462d424835f9f89cb8d436edfe8e425b337 ./input/foot-server@.socket # f52ef5b77326683f25aa843089c7f768637f08753a7c57996a8f7b0334de32f6 ./input/foot-server@.service WAYLAND_DISPLAY="%i" rc_cgroup_cleanup="YES" rc_send_sighup="no" unit-translator-0.7/t/expected/openrc/conf.d/oneshot000066400000000000000000000002511474613675300226470ustar00rootroot00000000000000# Generated by ../utrans from: # b05e280c90034554585cb7fbb33cbd93fbabfaa7cf9736cee888077954c9f396 ./input/oneshot.service rc_cgroup_cleanup="YES" rc_send_sighup="no" unit-translator-0.7/t/expected/openrc/conf.d/openntpd000066400000000000000000000004041474613675300230170ustar00rootroot00000000000000# Generated by ../utrans from: # 843c4f9142c604daed198c434b6677a4fd6f45a395434818261679d07aead773 ./input/openntpd.service RUNTIME_DIRECTORY="/run/openntpd" [ -r /etc/default/openntpd ] && . /etc/default/openntpd rc_cgroup_cleanup="YES" rc_send_sighup="no" unit-translator-0.7/t/expected/openrc/conf.d/polkit000066400000000000000000000002501474613675300224710ustar00rootroot00000000000000# Generated by ../utrans from: # 6dac9df426bbaec2bd79b1e71ad2a30d01e40c0c6e1c0d94150f762c7890b8ff ./input/polkit.service rc_cgroup_cleanup="YES" rc_send_sighup="no" unit-translator-0.7/t/expected/openrc/conf.d/rpcbind000066400000000000000000000005141474613675300226130ustar00rootroot00000000000000# Generated by ../utrans from: # 981477a148e26a4b3e312b2f23ceca24095ec285079b2a9c3277473c1ee4318a ./input/rpcbind.socket # 342bd8ea5b9e3053fa924833a3d0b3514851998a93652c3da12ea824bbf6cd7d ./input/rpcbind.service OPTIONS="-w" [ -r /etc/rpcbind.conf ] && . /etc/rpcbind.conf [ -r /etc/default/rpcbind ] && . /etc/default/rpcbind unit-translator-0.7/t/expected/openrc/conf.d/rsyslog000066400000000000000000000002761474613675300227010ustar00rootroot00000000000000# Generated by ../utrans from: # 726b9641b81ede267adc4180b3e25b85122a4e798e0f748cac0e9e3a414e1622 ./input/rsyslog.service rc_cgroup_cleanup="YES" rc_send_sighup="no" rc_ulimit="-n 16384" unit-translator-0.7/t/expected/openrc/conf.d/ssh000066400000000000000000000006001474613675300217630ustar00rootroot00000000000000# Generated by ../utrans from: # 9c36778605edb201ec5b7d1676887fc00249fa1b2582ec89e158c55b45b4659c ./input/ssh.socket # 35b2858970feb78e985900b33ba8cb84249dfadbf296155e5639cafcf1dd40a3 ./input/ssh.service RUNTIME_DIRECTORY="/run/sshd" [ -r /etc/default/ssh ] && . /etc/default/ssh MAINPID="$([ ! -f "/run/supervise-${RC_SVCNAME}.pid" ] || cat "/run/supervise-${RC_SVCNAME}.pid")" unit-translator-0.7/t/expected/openrc/conf.d/sssd000066400000000000000000000003751474613675300221530ustar00rootroot00000000000000# Generated by ../utrans from: # de718691081fbceb07b5338f5dabec659b76bc404769356bc8c3ae27b375984e ./input/sssd.service DEBUG_LOGGER=--logger="--logger=files" [ -r /etc/default/sssd ] && . /etc/default/sssd rc_cgroup_cleanup="YES" rc_send_sighup="no" unit-translator-0.7/t/expected/openrc/conf.d/systemd-hwdb-update000066400000000000000000000002651474613675300250670ustar00rootroot00000000000000# Generated by ../utrans from: # 6cf7fde4df7681b9a581e1c4440cded4bc390128256dc04a1a66916ab6f3d7f7 ./input/systemd-hwdb-update.service rc_cgroup_cleanup="YES" rc_send_sighup="no" unit-translator-0.7/t/expected/openrc/init.d/000077500000000000000000000000001474613675300212655ustar00rootroot00000000000000unit-translator-0.7/t/expected/openrc/init.d/foot-server.000077500000000000000000000017021474613675300235440ustar00rootroot00000000000000#!/sbin/openrc-run # Generated by ../utrans from: # e59b2780e736677dd241446be95ce462d424835f9f89cb8d436edfe8e425b337 ./input/foot-server@.socket # f52ef5b77326683f25aa843089c7f768637f08753a7c57996a8f7b0334de32f6 ./input/foot-server@.service description="Foot terminal server mode for WAYLAND_DISPLAY=${RC_SVCNAME#*.}." # Documentation: # man:foot(1) supervisor="supervise-daemon" command="/usr/bin/socket-activate" command_args="--unix::${XDG_RUNTIME_DIR:-/run}/foot-${RC_SVCNAME#*.}.sock -- /usr/bin/foot --server=3" depend() { use mountnfs mountnfs-bootclean umountnfs sendsigs mountall mountall-bootclean mountoverflowtmp umountfs after mountnfs mountnfs-bootclean umountnfs sendsigs mountall mountall-bootclean mountoverflowtmp umountfs } start_pre() { if [ -z "${RC_SVCNAME#*.}" ]; then eerror "${RC_SVCNAME} cannot be started directly." eerror "You must make symbolic links to the instances you want to start." return 1 fi } unit-translator-0.7/t/expected/openrc/init.d/oneshot000077500000000000000000000011641474613675300226740ustar00rootroot00000000000000#!/sbin/openrc-run # Generated by ../utrans from: # b05e280c90034554585cb7fbb33cbd93fbabfaa7cf9736cee888077954c9f396 ./input/oneshot.service description="Test oneshot." # Documentation: # man:systemd.service(5) start() { /usr/bin/ls / binary_found_in_path /bin/false || true } command_user="admin" depend() { use mountnfs mountnfs-bootclean umountnfs sendsigs mountall mountall-bootclean mountoverflowtmp umountfs after mountnfs mountnfs-bootclean umountnfs sendsigs networking ifupdown mountall mountall-bootclean mountoverflowtmp umountfs } stop() { /usr/bin/finish stop } start_pre() { /usr/bin/true } unit-translator-0.7/t/expected/openrc/init.d/openntpd000077500000000000000000000024761474613675300230530ustar00rootroot00000000000000#!/sbin/openrc-run # Generated by ../utrans from: # 843c4f9142c604daed198c434b6677a4fd6f45a395434818261679d07aead773 ./input/openntpd.service description="OpenNTPd Network Time Protocol." # Documentation: # man:openntpd(8) command="/usr/sbin/ntpd" command_args="$DAEMON_OPTS" start_stop_daemon_args="--no-new-privs --capabilities !CAP_BLOCK_SUSPEND,!CAP_SYS_BOOT,!CAP_NET_BROADCAST,!CAP_SETPCAP,!CAP_SYS_RESOURCE,!CAP_SYS_RAWIO,!CAP_DAC_OVERRIDE,!CAP_KILL,!CAP_FSETID,!CAP_SYS_PTRACE,!CAP_SYS_MODULE,!CAP_SETFCAP,!CAP_LEASE,!CAP_CHOWN,!CAP_NET_ADMIN,!CAP_AUDIT_WRITE,!CAP_WAKE_ALARM,!CAP_MKNOD,!CAP_AUDIT_CONTROL,!CAP_PERFMON,!CAP_MAC_ADMIN,!CAP_IPC_OWNER,!CAP_SYS_PACCT,!CAP_CHECKPOINT_RESTORE,!CAP_FOWNER,!CAP_SYS_ADMIN,!CAP_DAC_READ_SEARCH,!CAP_NET_RAW,!CAP_AUDIT_READ,!CAP_IPC_LOCK,!CAP_LINUX_IMMUTABLE,!CAP_MAC_OVERRIDE,!CAP_BPF,!CAP_SYS_TTY_CONFIG,CAP_NET_BIND_SERVICE,CAP_SETGID,CAP_SETUID,CAP_SYSLOG,CAP_SYS_CHROOT,CAP_SYS_NICE,CAP_SYS_TIME" depend() { use mountnfs mountnfs-bootclean umountnfs sendsigs mountall mountall-bootclean mountoverflowtmp umountfs after mountnfs mountnfs-bootclean umountnfs sendsigs networking ifupdown mountall mountall-bootclean mountoverflowtmp umountfs } start_pre() { mkdir -p "${RUNTIME_DIRECTORY:?}" /usr/sbin/ntpd -n $DAEMON_OPTS } stop_post() { rm -r "${RUNTIME_DIRECTORY:?}" } unit-translator-0.7/t/expected/openrc/init.d/polkit000077500000000000000000000010571474613675300225200ustar00rootroot00000000000000#!/sbin/openrc-run # Generated by ../utrans from: # 6dac9df426bbaec2bd79b1e71ad2a30d01e40c0c6e1c0d94150f762c7890b8ff ./input/polkit.service description="Authorization Manager." # Documentation: # man:polkit(8) supervisor="supervise-daemon" command="/usr/lib/polkit-1/polkitd" command_args="--no-debug" depend() { need dbus use mountnfs mountnfs-bootclean umountnfs sendsigs mountall mountall-bootclean mountoverflowtmp umountfs after dbus mountnfs mountnfs-bootclean umountnfs sendsigs mountall mountall-bootclean mountoverflowtmp umountfs } unit-translator-0.7/t/expected/openrc/init.d/rpcbind000077500000000000000000000012671474613675300226420ustar00rootroot00000000000000#!/sbin/openrc-run # Generated by ../utrans from: # 981477a148e26a4b3e312b2f23ceca24095ec285079b2a9c3277473c1ee4318a ./input/rpcbind.socket # 342bd8ea5b9e3053fa924833a3d0b3514851998a93652c3da12ea824bbf6cd7d ./input/rpcbind.service description="RPC bind portmap service." # Documentation: # man:rpcbind(8) supervisor="supervise-daemon" command="/usr/bin/socket-activate" command_args="--unix::/run/rpcbind.sock --unix::0.0.0.0:111 --unix::[::]:111 --unix-dgram::0.0.0.0:111 --unix-dgram::[::]:111 -- /sbin/rpcbind -f $OPTIONS" depend() { use mountall mountall-bootclean mountoverflowtmp umountfs after systemd-tmpfiles-setup mountall mountall-bootclean mountoverflowtmp umountfs } unit-translator-0.7/t/expected/openrc/init.d/rsyslog000077500000000000000000000011421474613675300227130ustar00rootroot00000000000000#!/sbin/openrc-run # Generated by ../utrans from: # 726b9641b81ede267adc4180b3e25b85122a4e798e0f748cac0e9e3a414e1622 ./input/rsyslog.service description="System Logging Service." # Documentation: # man:rsyslogd(8) # man:rsyslog.conf(5) # https://www.rsyslog.com/doc/ supervisor="supervise-daemon" command="/usr/sbin/rsyslogd" command_args="-n -iNONE" depend() { use mountnfs mountnfs-bootclean umountnfs sendsigs mountall mountall-bootclean mountoverflowtmp umountfs after mountnfs mountnfs-bootclean umountnfs sendsigs mountall mountall-bootclean mountoverflowtmp umountfs provide syslog } unit-translator-0.7/t/expected/openrc/init.d/ssh000077500000000000000000000021261474613675300220110ustar00rootroot00000000000000#!/sbin/openrc-run # Generated by ../utrans from: # 9c36778605edb201ec5b7d1676887fc00249fa1b2582ec89e158c55b45b4659c ./input/ssh.socket # 35b2858970feb78e985900b33ba8cb84249dfadbf296155e5639cafcf1dd40a3 ./input/ssh.service description="OpenBSD Secure Shell server." # Documentation: # man:sshd(8) # man:sshd_config(5) supervisor="supervise-daemon" command="/usr/bin/socket-activate" command_args="--unix::22 -- /usr/sbin/sshd -D $SSHD_OPTS" depend() { use mountnfs mountnfs-bootclean umountnfs sendsigs mountall mountall-bootclean mountoverflowtmp umountfs after auditd mountnfs mountnfs-bootclean umountnfs sendsigs networking ifupdown mountall mountall-bootclean mountoverflowtmp umountfs provide sshd } start_pre() { [ ! -e '/etc/ssh/sshd_not_to_be_run' ] || start() { einfo "Skipped due to ConditionPathExists !/etc/ssh/sshd_not_to_be_run"; } mkdir -p -m 0755 "${RUNTIME_DIRECTORY:?}" /usr/sbin/sshd -t } stop_post() { rm -r "${RUNTIME_DIRECTORY:?}" } extra_started_commands="reload" reload() { ebegin "Reloading ${RC_SVCNAME}" /usr/sbin/sshd -t /bin/kill -HUP $MAINPID } unit-translator-0.7/t/expected/openrc/init.d/sssd000077500000000000000000000033621474613675300221730ustar00rootroot00000000000000#!/sbin/openrc-run # Generated by ../utrans from: # de718691081fbceb07b5338f5dabec659b76bc404769356bc8c3ae27b375984e ./input/sssd.service description="System Security Services Daemon." supervisor="supervise-daemon" command="/usr/sbin/sssd" command_args="-i ${DEBUG_LOGGER}" command_user="root:root" start_stop_daemon_args="--secbits 3 --capabilities !CAP_BLOCK_SUSPEND,!CAP_SYS_BOOT,!CAP_NET_BROADCAST,!CAP_SETPCAP,!CAP_SYS_RESOURCE,!CAP_SYS_RAWIO,!CAP_DAC_OVERRIDE,!CAP_KILL,!CAP_FSETID,!CAP_SYS_PTRACE,!CAP_SYS_MODULE,!CAP_SETFCAP,!CAP_LEASE,!CAP_CHOWN,!CAP_NET_ADMIN,!CAP_AUDIT_WRITE,!CAP_WAKE_ALARM,!CAP_MKNOD,!CAP_AUDIT_CONTROL,!CAP_SYS_CHROOT,!CAP_PERFMON,!CAP_MAC_ADMIN,!CAP_IPC_OWNER,!CAP_SYSLOG,!CAP_SYS_PACCT,!CAP_CHECKPOINT_RESTORE,!CAP_FOWNER,!CAP_SYS_ADMIN,!CAP_NET_RAW,!CAP_SYS_NICE,!CAP_AUDIT_READ,!CAP_NET_BIND_SERVICE,!CAP_IPC_LOCK,!CAP_LINUX_IMMUTABLE,!CAP_MAC_OVERRIDE,!CAP_BPF,!CAP_SYS_TIME,!CAP_SYS_TTY_CONFIG,,CAP_SETGID,CAP_SETUID,CAP_DAC_READ_SEARCH," depend() { use mountnfs mountnfs-bootclean umountnfs sendsigs mountall mountall-bootclean mountoverflowtmp umountfs before systemd-user-sessions after mountnfs mountnfs-bootclean umountnfs sendsigs mountall mountall-bootclean mountoverflowtmp umountfs } start_pre() { ( # Triggering conditions ( [ -d '/etc/sssd/conf.d/' ] && files=$(ls -qA -- '/etc/sssd/conf.d/') && [ -n "$files" ] ) || ( [ -e '/etc/sssd/sssd.conf' ] ) ) || start() { einfo "Skipped due to no Triggering Conditions" ; } /bin/chown -f -R root:root /etc/sssd || true /bin/chmod -f -R g+r /etc/sssd || true /bin/sh -c "/bin/chown -f root:root /var/lib/sss/db/*.ldb" || true /bin/chown -f -R root:root /var/lib/sss/gpo_cache || true /bin/sh -c "/bin/chown -f root:root /var/log/sssd/*.log" || true } unit-translator-0.7/t/expected/openrc/init.d/systemd-hwdb-update000077500000000000000000000013061474613675300251050ustar00rootroot00000000000000#!/sbin/openrc-run # Generated by ../utrans from: # 6cf7fde4df7681b9a581e1c4440cded4bc390128256dc04a1a66916ab6f3d7f7 ./input/systemd-hwdb-update.service description="Rebuild Hardware Database." # Documentation: # man:hwdb(7) # man:systemd-hwdb(8) start() { systemd-hwdb update } depend() { before systemd-update-done after systemd-remount-fs } start_pre() { # WARNING: skipped unsupported ConditionNeedsUpdate /etc ( # Triggering conditions ( [ -d '/etc/udev/hwdb.d/' ] && files=$(ls -qA -- '/etc/udev/hwdb.d/') && [ -n "$files" ] ) || ( [ ! -e '/usr/lib/udev/hwdb.bin' ] ) || ( [ -e '/etc/udev/hwdb.bin' ] ) ) || start() { einfo "Skipped due to no Triggering Conditions" ; } } unit-translator-0.7/t/expected/openrc/init.d/systemd-udevd000077500000000000000000000024611474613675300240130ustar00rootroot00000000000000#!/sbin/openrc-run # Generated by ../utrans from: # e5b492be4ceeaae3a854d1e1ff7e25ba9818e9b92da937b6861284f2b5f2bdba ./input/systemd-udevd.service description="Rule-based Manager for Device Events and Files." # Documentation: # man:systemd-udevd.service(8) # man:udev(7) supervisor="supervise-daemon" command="/usr/lib/systemd/systemd-udevd" command_args="" start_stop_daemon_args="--capabilities CAP_BLOCK_SUSPEND,CAP_SYS_BOOT,CAP_NET_BROADCAST,CAP_SETPCAP,CAP_SYS_RESOURCE,CAP_SYS_RAWIO,CAP_DAC_OVERRIDE,CAP_KILL,CAP_FSETID,CAP_SYS_PTRACE,CAP_SYS_MODULE,CAP_SETFCAP,CAP_LEASE,CAP_SETGID,CAP_CHOWN,CAP_NET_ADMIN,CAP_AUDIT_WRITE,CAP_SETUID,CAP_MKNOD,CAP_AUDIT_CONTROL,CAP_SYS_CHROOT,CAP_PERFMON,CAP_MAC_ADMIN,CAP_IPC_OWNER,CAP_SYSLOG,CAP_SYS_PACCT,CAP_CHECKPOINT_RESTORE,CAP_FOWNER,CAP_SYS_ADMIN,CAP_DAC_READ_SEARCH,CAP_NET_RAW,CAP_SYS_NICE,CAP_AUDIT_READ,CAP_NET_BIND_SERVICE,CAP_IPC_LOCK,CAP_LINUX_IMMUTABLE,CAP_MAC_OVERRIDE,CAP_BPF,CAP_SYS_TTY_CONFIG,!CAP_SYS_TIME,!CAP_WAKE_ALARM" depend() { use systemd-udev-load-credentials after systemd-sysusers systemd-hwdb-update } start_pre() { [ -r '/sys' ] && [ -w '/sys' ] || start() { einfo "Skipped due to ConditionPathIsReadWrite /sys"; } } extra_started_commands="reload" reload() { ebegin "Reloading ${RC_SVCNAME}" supervise-daemon "${RC_SVCNAME}" -s HUP } unit-translator-0.7/t/expected/openrc/init.d/template.000077500000000000000000000014671474613675300231140ustar00rootroot00000000000000#!/sbin/openrc-run # Generated by ../utrans from: # 851aafc0f2d2360df42ffec0187ccf32752bf28a20e9ca7523e7bb85fb8649b7 ./input/template@.service description="Template service: ${RC_SVCNAME#*.}." # Documentation: # man:systemd.service(5) supervisor="supervise-daemon" command="/usr/bin/echo" command_args="${RC_SVCNAME#*.}" depend() { use oneshot mountnfs mountnfs-bootclean umountnfs sendsigs mountall mountall-bootclean mountoverflowtmp umountfs after oneshot mountnfs mountnfs-bootclean umountnfs sendsigs mountall mountall-bootclean mountoverflowtmp umountfs } stop() { /usr/bin/echo ${RC_SVCNAME#*.} } start_pre() { if [ -z "${RC_SVCNAME#*.}" ]; then eerror "${RC_SVCNAME} cannot be started directly." eerror "You must make symbolic links to the instances you want to start." return 1 fi } unit-translator-0.7/t/expected/xinetd/000077500000000000000000000000001474613675300201055ustar00rootroot00000000000000unit-translator-0.7/t/expected/xinetd/xinetd.d/000077500000000000000000000000001474613675300216225ustar00rootroot00000000000000unit-translator-0.7/t/expected/xinetd/xinetd.d/inetd000066400000000000000000000002331474613675300226460ustar00rootroot00000000000000service svcd { disabled = no port = 6566 socket_type = stream wait = no user = unpriv server = /usr/sbin/svcd server_args = } unit-translator-0.7/t/input/000077500000000000000000000000001474613675300161505ustar00rootroot00000000000000unit-translator-0.7/t/input/foot-server@.service000066400000000000000000000004621474613675300221070ustar00rootroot00000000000000[Service] ExecStart=/usr/bin/foot --server=3 Environment=WAYLAND_DISPLAY=%i UnsetEnvironment=LISTEN_PID LISTEN_FDS LISTEN_FDNAMES NonBlocking=true [Unit] Requires=%N.socket Description=Foot terminal server mode for WAYLAND_DISPLAY=%i Documentation=man:foot(1) [Install] WantedBy=wayland-instance@.target unit-translator-0.7/t/input/foot-server@.socket000066400000000000000000000001231474613675300217310ustar00rootroot00000000000000[Socket] ListenStream=%t/foot-%i.sock [Install] WantedBy=wayland-instance@.target unit-translator-0.7/t/input/inetd.socket000066400000000000000000000002011474613675300204560ustar00rootroot00000000000000[Unit] Description=Test inetd socket [Socket] ListenStream=6566 Accept=yes MaxConnections=64 [Install] WantedBy=sockets.target unit-translator-0.7/t/input/inetd@.service000066400000000000000000000002261474613675300207350ustar00rootroot00000000000000[Unit] Description=Test inetd Service Requires=inetd.socket [Service] ExecStart=/usr/sbin/svcd User=unpriv Group=unpriv [Install] Also=inetd.socket unit-translator-0.7/t/input/masked.service000077700000000000000000000000001474613675300225232/dev/nullustar00rootroot00000000000000unit-translator-0.7/t/input/oneshot.service000066400000000000000000000005161474613675300212130ustar00rootroot00000000000000[Unit] Description=Test oneshot After=network.target remote-fs.target Documentation=man:systemd.service(5) [Service] Type=oneshot RemainAfterExit=yes ExecStartPre=/usr/bin/true ExecStart=/usr/bin/ls / ExecStart=binary_found_in_path ExecStart=-/bin/false ExecStop=/usr/bin/finish stop User=admin [Install] WantedBy=multi-user.target unit-translator-0.7/t/input/oneshot.timer000066400000000000000000000003251474613675300206710ustar00rootroot00000000000000[Unit] Description=Test oneshot timer [Timer] # Run on Sunday at 3:10am, to avoid running foul of DST changes OnCalendar=Sun *-*-* 03:10:00 RandomizedDelaySec=60 Persistent=true [Install] WantedBy=timers.target unit-translator-0.7/t/input/openntpd.service000066400000000000000000000013261474613675300213630ustar00rootroot00000000000000[Unit] Description=OpenNTPd Network Time Protocol Documentation=man:openntpd(8) Conflicts=systemd-timesyncd.service After=network.target [Service] Type=forking EnvironmentFile=-/etc/default/openntpd ExecStart=/usr/sbin/ntpd $DAEMON_OPTS ExecStartPre=/usr/sbin/ntpd -n $DAEMON_OPTS Restart=on-failure RuntimeDirectory=openntpd # security profile PrivateTmp=true PrivateDevices=true ProtectSystem=full ProtectHome=true CapabilityBoundingSet=CAP_NET_BIND_SERVICE CapabilityBoundingSet=CAP_SETGID CapabilityBoundingSet=CAP_SETUID CapabilityBoundingSet=CAP_SYSLOG CapabilityBoundingSet=CAP_SYS_CHROOT CapabilityBoundingSet=CAP_SYS_NICE CapabilityBoundingSet=CAP_SYS_TIME NoNewPrivileges=true [Install] WantedBy=multi-user.target unit-translator-0.7/t/input/polkit.service000066400000000000000000000002541474613675300210350ustar00rootroot00000000000000[Unit] Description=Authorization Manager Documentation=man:polkit(8) [Service] Type=dbus BusName=org.freedesktop.PolicyKit1 ExecStart=/usr/lib/polkit-1/polkitd --no-debug unit-translator-0.7/t/input/rpcbind.service000066400000000000000000000011621474613675300211530ustar00rootroot00000000000000[Unit] Description=RPC bind portmap service Documentation=man:rpcbind(8) DefaultDependencies=no RequiresMountsFor=/run/rpcbind # Make sure we use the IP addresses listed for # rpcbind.socket, no matter how this unit is started. Requires=rpcbind.socket After=systemd-tmpfiles-setup.service Wants=remote-fs-pre.target rpcbind.target Before=remote-fs-pre.target rpcbind.target [Service] Environment="OPTIONS=-w" ExecStart=/sbin/rpcbind -f $OPTIONS EnvironmentFile=-/etc/rpcbind.conf EnvironmentFile=-/etc/default/rpcbind Type=notify KillMode=process Restart=on-failure [Install] Also=rpcbind.socket WantedBy=multi-user.target unit-translator-0.7/t/input/rpcbind.socket000066400000000000000000000005051474613675300210030ustar00rootroot00000000000000[Unit] Description=RPCbind Server Activation Socket DefaultDependencies=no [Socket] ListenStream=/run/rpcbind.sock # RPC netconfig can't handle ipv6/ipv4 dual sockets BindIPv6Only=ipv6-only ListenStream=0.0.0.0:111 ListenDatagram=0.0.0.0:111 ListenStream=[::]:111 ListenDatagram=[::]:111 [Install] WantedBy=sockets.target unit-translator-0.7/t/input/rsyslog.service000066400000000000000000000007251474613675300212400ustar00rootroot00000000000000[Unit] Description=System Logging Service Requires=syslog.socket Documentation=man:rsyslogd(8) Documentation=man:rsyslog.conf(5) Documentation=https://www.rsyslog.com/doc/ [Service] Type=notify ExecStart=/usr/sbin/rsyslogd -n -iNONE StandardOutput=null Restart=on-failure # Increase the default a bit in order to allow many simultaneous # files to be monitored, we might need a lot of fds. LimitNOFILE=16384 [Install] WantedBy=multi-user.target Alias=syslog.service unit-translator-0.7/t/input/ssh.service000066400000000000000000000010321474613675300203230ustar00rootroot00000000000000[Unit] Description=OpenBSD Secure Shell server Documentation=man:sshd(8) man:sshd_config(5) After=network.target auditd.service ConditionPathExists=!/etc/ssh/sshd_not_to_be_run [Service] EnvironmentFile=-/etc/default/ssh ExecStartPre=/usr/sbin/sshd -t ExecStart=/usr/sbin/sshd -D $SSHD_OPTS ExecReload=/usr/sbin/sshd -t ExecReload=/bin/kill -HUP $MAINPID KillMode=process Restart=on-failure RestartPreventExitStatus=255 Type=notify RuntimeDirectory=sshd RuntimeDirectoryMode=0755 [Install] WantedBy=multi-user.target Alias=sshd.service unit-translator-0.7/t/input/ssh.socket000066400000000000000000000003041474613675300201540ustar00rootroot00000000000000[Unit] Description=OpenBSD Secure Shell server socket Before=sockets.target ConditionPathExists=!/etc/ssh/sshd_not_to_be_run [Socket] ListenStream=22 Accept=no [Install] WantedBy=sockets.target unit-translator-0.7/t/input/sssd.service000066400000000000000000000020341474613675300205050ustar00rootroot00000000000000[Unit] Description=System Security Services Daemon # SSSD must be running before we permit user sessions Before=systemd-user-sessions.service nss-user-lookup.target Wants=nss-user-lookup.target StartLimitIntervalSec=50s StartLimitBurst=5 ConditionPathExists=|/etc/sssd/sssd.conf ConditionDirectoryNotEmpty=|/etc/sssd/conf.d/ [Service] Environment=DEBUG_LOGGER=--logger=files EnvironmentFile=-/etc/default/sssd ExecStartPre=+-/bin/chown -f -R root:root /etc/sssd ExecStartPre=+-/bin/chmod -f -R g+r /etc/sssd ExecStartPre=+-/bin/sh -c "/bin/chown -f root:root /var/lib/sss/db/*.ldb" ExecStartPre=+-/bin/chown -f -R root:root /var/lib/sss/gpo_cache ExecStartPre=+-/bin/sh -c "/bin/chown -f root:root /var/log/sssd/*.log" ExecStart=/usr/sbin/sssd -i ${DEBUG_LOGGER} Type=notify NotifyAccess=main Restart=on-abnormal CapabilityBoundingSet= CAP_SETGID CAP_SETUID CAP_DAC_READ_SEARCH SecureBits=noroot noroot-locked User=root Group=root # Note: SSSD package was built without support of running as non-privileged user [Install] WantedBy=multi-user.target unit-translator-0.7/t/input/systemd-hwdb-update.service000066400000000000000000000015021474613675300234220ustar00rootroot00000000000000# SPDX-License-Identifier: LGPL-2.1-or-later # # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] Description=Rebuild Hardware Database Documentation=man:hwdb(7) man:systemd-hwdb(8) ConditionNeedsUpdate=/etc ConditionPathExists=|!/usr/lib/udev/hwdb.bin ConditionPathExists=|/etc/udev/hwdb.bin ConditionDirectoryNotEmpty=|/etc/udev/hwdb.d/ DefaultDependencies=no After=systemd-remount-fs.service Before=sysinit.target systemd-update-done.service Conflicts=shutdown.target Before=shutdown.target [Service] Type=oneshot RemainAfterExit=yes ExecStart=systemd-hwdb update TimeoutSec=90s unit-translator-0.7/t/input/systemd-udevd.service000066400000000000000000000025301474613675300223270ustar00rootroot00000000000000# SPDX-License-Identifier: LGPL-2.1-or-later # # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] Description=Rule-based Manager for Device Events and Files Documentation=man:systemd-udevd.service(8) man:udev(7) DefaultDependencies=no After=systemd-sysusers.service systemd-hwdb-update.service Before=sysinit.target Wants=systemd-udev-load-credentials.service ConditionPathIsReadWrite=/sys [Service] CapabilityBoundingSet=~CAP_SYS_TIME CAP_WAKE_ALARM Delegate=pids DelegateSubgroup=udev Type=notify-reload # Note that udev will reset the value internally for its workers OOMScoreAdjust=-1000 Sockets=systemd-udevd-control.socket systemd-udevd-kernel.socket Restart=always RestartSec=0 ExecStart=/usr/lib/systemd/systemd-udevd KillMode=mixed TasksMax=infinity PrivateMounts=yes ProtectHostname=yes MemoryDenyWriteExecute=yes RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6 RestrictRealtime=yes RestrictSUIDSGID=yes SystemCallFilter=@system-service @module @raw-io bpf SystemCallFilter=~@clock SystemCallErrorNumber=EPERM SystemCallArchitectures=native LockPersonality=yes IPAddressDeny=any WatchdogSec=3min unit-translator-0.7/t/input/template@.service000066400000000000000000000004161474613675300214460ustar00rootroot00000000000000[Unit] Description=Template service: %i After=oneshot.service Wants=oneshot.service Documentation=man:systemd.service(5) [Service] Type=simple KillMode=mixed TimeoutStopSec=120s ExecStart=/usr/bin/echo %i ExecStop=/usr/bin/echo %i [Install] WantedBy=multi-user.target unit-translator-0.7/t/run000077500000000000000000000007701474613675300155470ustar00rootroot00000000000000#!/bin/sh set -e : ${UTRANS:=../utrans} for backend in openrc cron xinetd inetd lsb ; do echo "Testing $backend backend" >&2 output=$(mktemp -d) trap 'rm -rf ${output}' EXIT find ./input -maxdepth 1 ! -type d -print -exec "$UTRANS" -f overwrite -b ="${backend}" '{}' "${output}" ';' 2>&1 | # Filter expected missing backend errors. grep -vx "ERROR: backend for [a-z]\+ unit not available\." diff -u -r -x '.*' expected/"${backend}" "${output}" rm -rf "${output}" done unit-translator-0.7/t/update000077500000000000000000000005741474613675300162270ustar00rootroot00000000000000#!/bin/sh set -e for backend in openrc cron xinetd inetd lsb ; do echo "Updating expected output for $backend backend" >&2 find ./input -maxdepth 1 ! -type d ! -name '*.~' -exec ../utrans -f overwrite -b ="${backend}" '{}' ./expected/"${backend}" ';' 2>&1 | # Filter expected missing backend errors. grep -vx "ERROR: backend for [a-z]\+ unit not available\." done unit-translator-0.7/utrans000077500000000000000000000501551474613675300160160ustar00rootroot00000000000000#!/usr/bin/env bash # NAME # ---- # utrans: convert systemd units to generic unix equivalents # # AUTHORS # ------- # [https://salsa.debian.org/kayg/systemd-unit-translator] # # K Gopal Krishna under the guidance of Benda Xu # , Adam Borowski and Mo Zhou # . # # This project was a part of Google Summer of Code, 2020. # # [https://git.devuan.org/leepen/unit-translator] # # Mark Hindley # # LICENSE # ------- # BSD-2-Clause License # # Copyright (c) 2020, K Gopal Krishna . All rights reserved. # Copyright (c) 2023-, Mark Hindley . All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Safety options for bash set -o errexit set -o pipefail set -o nounset set -o noglob set -o noclobber readonly VERSION=0.7 # +++ Miscellaneous Functions +++ # read a boolean value and returns true or false # usage: is_true val # val boolean value is_true() { case "$1" in 1 | [Oo][Nn] | [Tt]* | [Yy]*) true ;; *) false ;; esac } # print_usage(): # accepted options: none # accepted arguments: none # # print how to use the translator print_usage() { printf '%s\n' 'Unit Translator' printf '\n%s\n' ' Usage: utrans [-b ] [-h] [-v] /path/to/unit/file /path/to/destination/directory' printf '\n%s\n' ' Supported options:' printf '%s\n' ' -b : load backend(s)' printf '%s\n' ' -f : force' printf '%s\n' ' -h: open manpage' printf '%s\n' ' -v: show version' exit 1 } # print version print_version() { printf '%s version %s\n' 'Unit Translator' "$VERSION" exit } # find unit in load path unit_path_find() { unit=$1 IFS=':' read -ra systemd_unit_path <<< "${SYSTEMD_UNIT_PATH:-/usr/lib/systemd/system:/lib/systemd/system}" for dir in "${systemd_unit_path[@]}"; do if [[ -s "$dir/$unit" ]]; then echo "$dir/$unit" && return fi done } # handle or ignore special executable prefixes handle_exec_prefixes() { exec_event=$1 special_exec_prefix="^(\@|\-|\:|\+|\!|\!\!)(.*)" readarray -t _exec <<<"${exec_event}" for exec_line in "${_exec[@]}"; do [ "${exec_line}" ] || continue while [[ "${exec_line}" =~ ${special_exec_prefix} ]]; do exec_line="${BASH_REMATCH[2]}" case "${BASH_REMATCH[1]}" in -) exec_line+=' || true' ;; *) echo "WARNING: ignoring special exec prefix ${BASH_REMATCH[1]}" >&2 ;; esac done printf '%s\n' "${exec_line}" done } # print shell-style assignment directives print_directive() { local d=$1 local s=${2:-} if [[ -n "$s" ]]; then printf '%s="%s"\n' "${d}" "${s%% }" # Trim trailing whitespace fi } # print string, possibly multiline, optionally add prefix, skip any blank lines. print_lines() { str=$1 prfx=${2:-} while IFS= read -r line || [[ -n "$line" ]]; do [[ -z "$line" ]] || printf "%s%s\n" "${prfx}" "${line}" done <<< "$str" } # print shell-style function, if body not empty print_sh_function() { name=$1 body=$2 if [[ "$body" ]]; then printf '%s\n' "${name}() {" print_lines "${body}" ' ' printf '%s\n' "}" fi } # --- Miscellaneous Functions --- # +++ Backend functions +++ # Stubs missing_backend() { echo "ERROR: backend for $1 unit not available." >&2 exit 2 } export_service () { missing_backend service ; } export_socket () { missing_backend socket ; } export_inetd () { missing_backend inetd ; } export_timer () { missing_backend timer ; } # --- Backend functions --- # +++ Parsing-related Functions +++ # parse_section(): # accepted options: none # accepted arguments: two # "${1}": the file to filter # "${2}": the section to filter # parse_section() { local file section key start value local -A var file="${1}" section="${2}" start=0 while IFS= read -r line || [ -n "$line" ]; do if [[ "${start}" -eq 1 ]]; then if [[ "${line}" =~ ^\[.*\] ]]; then break elif [[ "${line}" =~ ^# ]]; then continue elif [[ "${line}" =~ .*=.* ]]; then while [[ "${line}" =~ \\$ ]]; do read -r continuation line="${line::-1} $continuation" done key="${line%%=*}" value="${line#*=}" if [[ -n "${var["${key}"]:-}" ]]; then var["${key}"]+=$'\n' fi var["${key}"]+="${value}" fi fi if [[ "${line}" == "[$section]" ]]; then start=1 fi done <"${file}" if [[ -n "${var[*]}" ]]; then for k in "${!var[@]}"; do printf '[%s]=%q\n' "$k" "${var[$k]}" done fi } # --- Parsing-related Functions --- # +++ Service-related Functions +++ # generate origin and sha256 header gen_origin() { printf '# Generated by %s from:\n# %s\n' "$0" "$(sha256sum "${systemd_unit}")" if [[ "${socket_service_unit:-}" ]] ; then printf '# %s\n' "$(sha256sum "${socket_service_unit}")" elif [[ -n "${systemd_unit##*.service}" ]] ; then printf '# %s\n' "$(sha256sum "${systemd_unit%.*}.service")" fi printf '\n' } # Generate generic shell-style environment directives. gen_environment() { while read -r line; do # Remove any surrounding paired quotes [[ "${line}" == \"*\" || "${line}" == \'*\' ]] && line="${line:1:-1}" print_directive "${line%=*}" "${line#*=}" done <<<"${service[Environment]:-}" while read -r file; do [[ "${file}" ]] || continue if [[ -z "${file%%-*}" ]]; then printf '[ -r %s ] && ' "${file#-}" fi printf '. %s\n' "${file#-}" # Ignore - prefix done <<<"${service[EnvironmentFile]:-}" } # Add dependencies, avoid duplicates and excess whitespace. add_depends() { key=$1 shift for add in "$@"; do for d in ${depends[$key]:-}; do [[ "$d" == "$add" ]] && continue 2 # Already present done [[ -z "${depends[$key]:-}" ]] || depends[$key]+=' ' depends[$key]+="$add" done } # Remove dependency from depends[key] remove_depend() { dep=$1 key=$2 shift 2 # shellcheck disable=SC2086 set -- ${depends[$key]:-} # split whitespace for d ; do shift [[ "$d" == "$dep" ]] && continue set -- "$@" "$d" done depends[$key]="$*" } # Split constraints into trigger prefix condition split_constraint() { while read -r constraint; do unset trigger prefix case "$constraint" in "") return ;; !*) prefix='!' ;; \|!*) trigger='|' prefix='!' ;; \|*) trigger='|' ;; esac cat</dev/null ; [ ${ac_chk:-} \$? -ne 1 ]" ;; # NeedsUpdate) ;; # FirstBoot) ;; PathExists) echo "[ ${pre:+$pre }-e '$p' ]" ;; PathExistsGlob) echo "[ ${pre:+$pre }-n \"\$(find $(dirname "$p") -maxdepth 1 -wholename '$p' -print -quit)\" ]" ;; PathIsDirectory) echo "[ ${pre:+$pre }-d '$p' ]" ;; PathIsSymbolicLink) echo "[ ${pre:+$pre }-L '$p' ]" ;; PathIsMountPoint) echo "${pre:+$pre }mountpoint -q '$p'" ;; PathIsReadWrite) echo "[ ${pre:+$pre }-r '$p' ] && [ ${pre:+$pre }-w '$p' ]" ;; # PathIsEncrypted) ;; DirectoryNotEmpty) echo "[ -d '$p' ] && files=\$(ls -qA -- '$p') && [ ${pre:+$pre }-n \"\$files\" ]" ;; FileNotEmpty) echo "[ ${pre:+$pre }-s '$p' ]" ;; FileIsExecutable) echo "[ ${pre:+$pre }-x '$p' ]" ;; # User) ;; # Group) ;; # ControlGroupController) ;; Memory) echo "[ \$(( \$(head -1 /proc/meminfo | tr -s '[:space:]' | cut -f2 -d' ') * 1024)) -ge '$p' ]" ;; CPUs) echo "[ \$(grep -c ^processor /proc/cpuinfo) -ge '$p' ]" ;; CPUFeature) echo "grep '^flags\s\+:' /proc/cpuinfo | grep -q '$p'" ;; # OSRelease) ;; esac } # Translate dependencies to insserv style names. Backends can process further, # as required. map_known_dependencies() { if [[ -n "${service[BusName]:-}" ]]; then service[Type]=dbus fi # Set default Type case "${service[Type]:=simple}" in simple) ;; exec) ;; oneshot) ;; idle) ;; dbus) add_depends Requires dbus add_depends After dbus ;; notify) ;; notify-reload) ;; forking) ;; esac if [[ "${unit[DefaultDependencies]:-yes}" == 'yes' ]]; then # sysinit.target add_depends Requires \$remote_fs add_depends After \$remote_fs # basic.target: not required explicitly as insserv.conf includes # $local_fs in $remote_fs. # add_depends After \$local_fs fi case "${unit[RequiresMountsFor]:-}" in /run*) add_depends Requires \$local_fs add_depends After \$local_fs ;; /*) add_depends Requires \$remote_fs add_depends After \$remote_fs ;; esac # Handle display-manager.service if [[ "${install[Alias]:-}" == 'display-manager.service' ]]; then if grep -q "${service[ExecStart]}" /etc/X11/default-display-manager ; then install[Alias]=\$x-display-manager else unset 'install[Alias]' fi fi # Handle runtime directories for dir in Runtime State Cache Logs Configuration; do if [[ -n "${service[${dir}Directory]:-}" ]]; then add_depends Requires \$remote_fs add_depends After \$remote_fs case "$dir" in Runtime) dirbase='/run' is_true "${service[RuntimeDirectoryPreserve]:-no}" || service[ExecStopPost]+=$'\n'"rm -r \"\${${dir@U}_DIRECTORY:?}\"" ;; State) dirbase='/var/lib' ;; Cache) dirbase='/var/cache' ;; Logs) dirbase='/var/log' ;; Configuration) dirbase='/etc' ;; *) ! echo 'ERROR: unknown runtime directory' >&2 ;; esac rtdir="mkdir -p ${service[${dir}DirectoryMode]:+-m ${service[${dir}DirectoryMode]} }\"\${${dir@U}_DIRECTORY:?}\""$'\n' if [[ "${service[User]:-}" ]]; then rtdir+="chown \"${service[User]}${service[Group]:+:${service[Group]}}\" \"\${${dir@U}_DIRECTORY:?}\""$'\n' fi # Prepend service[ExecStartPre]="${rtdir}${service[ExecStartPre]:-}" service[Environment]+=$'\n'"${dir@U}_DIRECTORY=${dirbase}/${service[${dir}Directory]}" fi done for key in After Before Requires Wants; do read -ra dependencies <<<"${unit[${key}]:-}" for dependency in "${dependencies[@]}"; do # This is circular, ignore it. See NetworkManager-wait-online.service [[ "$dependency" != "${install[WantedBy]:-}" ]] || continue case "${dependency}" in *%*.*) echo "WARNING: dependencies with specifiers not supported" >&2 ;; sysinit.target) # Not for Before [[ "$key" == 'Before' ]] || add_depends "${key}" \$local_fs ;; local-fs.target) add_depends "${key}" \$local_fs ;; network-pre.target) add_depends "${key}" \$local_fs \$network ;; network*.target | systemd-networkd.service) add_depends "${key}" \$network ;; local-fs-pre.target) add_depends "${key}" mountkernfs ;; time-sync.target) add_depends "${key}" \$time ;; systemd-modules-load.service) add_depends "${key}" kmod ;; systemd-sysctl.service) add_depends "${key}" procps ;; nss-lookup.target) add_depends "${key}" \$named \$network ;; rpcbind.target) add_depends "${key}" \$portmap ;; remote-fs.target|basic.target) add_depends "${key}" \$remote_fs ;; syslog.socket) # systemd specific, ignore unit[${key}]=${unit[$key]/syslog.socket/} ;; display-manager.service|graphical.target) add_depends "${key}" \$x-display-manager ;; *.target) # TODO ;; *.mount) #TODO ;; *) [[ "${dependency%.*}" == "${systemd_unit_file%.*}" ]] && continue add_depends "${key}" "${dependency%.*}" ;; esac done done } # --- Service-related Functions --- # +++ Socket-related Functions +++ map_known_socket_types() { for listen_type in ListenStream ListenDatagram ListenSequentialPacket; do for listen_type_format in ${socket[${listen_type}]:-}; do if [[ "${listen_type_format:-}" =~ [1-9][0-9]{0,4} ]]; then if is_true "${socket[Accept]:-}"; then use_socket_activate=false fi elif [[ "${listen_type_format:-}" =~ ^/.* ]]; then use_socket_activate=true fi done done } # Add socket-activate to ExecStart. gen_socket_activate_cmdline() { printf '%s' '/usr/bin/socket-activate ' # handle Stream and Datagram listen-types while read -r listener; do [ "$listener" ] || continue printf '%s' "--unix::${listener} " done <<<"${socket[ListenStream]:-}" while read -r listener; do [ "$listener" ] || continue printf '%s' "--unix-dgram::${listener} " done <<<"${socket[ListenDatagram]:-}" # end of specifiying options printf '%s' '-- ' # append the service command printf '%s' "${service[ExecStart]}" } gen_ulimit_args() { # Missing in dash: LOCKS SIGPENDING MSGQUEUE NICE # Different in dash: NPROC -p # No equivalent: RTTIME for l in CPU FSIZE DATA STACK CORE RSS NOFILE AS NPROC MEMLOCK LOCKS SIGPENDING MSGQUEUE NICE RTPRIO; do for v in ${service[Limit${l}]:-}; do [ "$v" = infinity ] && v=unlimited case $l in CPU) p=-t ;; FSIZE) p=-f ;; DATA) p=-d ;; STACK) p=-s ;; CORE) p=-c ;; RSS) p=-m ;; NOFILE) p=-n ;; AS) p=-v ;; NPROC) p=-u ulimit $p >/dev/null 2>&1 && p=-p ;; MEMLOCK) p=-l ;; LOCKS) p=-x ;; SIGPENDING) p=-i ;; MSGQUEUE) p=-q ;; NICE) p=-e ;; RTPRIO) p=-r ;; RTTIME) continue ;; *) echo "WARNING: unexpected ulimit" >&2 continue ;; esac # Check that the ulimit flag is accepted before printing ulimit "$p" >/dev/null 2>&1 && printf '%s %s\n' "$p" "$v" done done } # --- Socket-related Functions --- translate() { systemd_unit="${1}" systemd_unit_file="$(basename "${systemd_unit}")" dest_dir="${2}" # parse key-value pairs from the [Unit] section declare -A unit="( $(parse_section "${systemd_unit}" Unit) )" # and the [Install] section declare -A install="( $(parse_section "${systemd_unit}" Install) )" # variable to pass calculated dependencies to backend declare -A depends # if the file provided is of type .service... if [[ "${systemd_unit}" == *.service ]]; then # Use a name-matched socket instead if [[ -f "${systemd_unit%.service}.socket" ]]; then echo "Using ${systemd_unit%.service}.socket" >&2 translate "${systemd_unit%.service}.socket" "$dest_dir" exit fi # parse key-value pairs from the [Service] section declare -A service="( $(parse_section "${systemd_unit}" Service) )" # map known dependencies map_known_dependencies for required in ${unit[Requires]:-} ; do case "$required" in *.socket|*.service) echo "$systemd_unit_file Requires ${required}" >&2 service_required_unit=$(unit_path_find "${required}") if [ "${service_required_unit}" ]; then echo "Found ${service_required_unit}" >&2 # Process in subshell ( set +o noclobber # may already have been processed, allow clobber translate "${service_required_unit}" "$dest_dir" ) # continue else echo "Failed to find required unit (${required})." >&2 exit 1 fi ;; esac done export_service "${systemd_unit}" "${dest_dir}" elif [[ "${systemd_unit}" == *.socket ]]; then # parse key-value pairs from the [Socket] section declare -A socket="( $(parse_section "${systemd_unit}" Socket) )" if is_true "${socket[Accept]:-}"; then socket_service_unit=$(unit_path_find "${socket[Service]:-${systemd_unit_file%%.socket}@.service}") else socket_service_unit=$(unit_path_find "${socket[Service]:-${systemd_unit_file%%.socket}.service}") fi if [[ -z "${socket_service_unit}" ]]; then echo "Failed to find ${socket[Service]:-${systemd_unit_file%%.socket}@.service}" >&2 exit 1 fi # parse key-value pairs from the [Service] section of the accompanying service file declare -A service="( $(parse_section "${socket_service_unit}" Service) )" # parse key-value pairs from the [Unit] section of the accompanying service file declare -A unit="( $(parse_section "${socket_service_unit}" Unit) )" # and append the [Install] section declare -A install+="( $(parse_section "${socket_service_unit}" Install) )" # map known dependencies map_known_dependencies # determine the type of listener and the tool to be used map_known_socket_types # if the flag has been set to false... if [[ -n "${use_socket_activate:-}" && "${use_socket_activate}" != "true" ]]; then export_inetd "${systemd_unit}" "${dest_dir}" else service[Type]=socket # TODO handle fork/not in socket-activate service[ExecStart]="$(gen_socket_activate_cmdline)" # Make subdirectories for filesystem sockets in start_pre() while read -r listener; do if [[ -z "${listener%%/*}" && -n "${listener%/*/*}" ]]; then service[ExecStartPre]+="$(printf '\n%s\n' "mkdir -p $(dirname "${listener}")")" fi done <<<"${socket[ListenStream]:-} ${socket[ListenDatagram]:-}" export_service "${systemd_unit}" "${dest_dir}" fi elif [[ "${systemd_unit}" == *.timer ]]; then # parse key-value pairs from the [Timer] section declare -A timer="( $(parse_section "${systemd_unit}" Timer) )" # parse key-value pairs from the [Service] section from the accompanying service file declare -A service="( $(parse_section "${systemd_unit%%.timer}.service" Service) )" export_timer "${systemd_unit}" "${dest_dir}" fi } main() { default_backends='openrc xinetd cron' backends= while getopts "b:f:hv" o; do case "${o}" in b) if [ -z "${OPTARG##=*}" ] ; then default_backends= OPTARG="${OPTARG#=}" # Remove prefix fi backends+=" ${OPTARG//,/ }" ;; f) case "$OPTARG" in overwrite) set +o noclobber;; *) echo "ERROR: invalid argument to -f"; exit 1 ;; esac ;; h) man utrans ;; v) print_version ;; *) print_usage ;; esac done shift $((OPTIND-1)) [ $# -lt 2 ] && print_usage if [[ ! -s ${1} ]]; then echo "WARNING: ignoring masked unit ${1}" >&2 else # Source backends for backend in ${default_backends} ${backends}; do # shellcheck source=./backends/cron # shellcheck source=./backends/openrc # shellcheck source=./backends/lsb # shellcheck source=./backends/xinetd # shellcheck source=./backends/inetd . "${UTRANS_DATA_DIR:-/usr/share/utrans}/backends/${backend}" done translate "$@" fi } main "${@}" unit-translator-0.7/utrans-deb000077500000000000000000000017461474613675300165500ustar00rootroot00000000000000#!/bin/bash # # [ -b ] * shopt -s nullglob TEMP="$(mktemp -d -p .)" trap "rm -rf $TEMP" 0 2 die() { echo "** ERROR: $*" ; exit 1 ; } BACKENDS= if [ "$1" = "-b" ] ; then BACKENDS="-b $2" # replace any ; by space shift 2 fi FIRST= for DEB in "${@}" ; do [ -f "$DEB" ] || die "Unkown deb file: $DEB" [ -z "$FIRST" ] && FIRST="${DEB##*/}" dpkg -x "$DEB" "$TEMP" || die "Cannot unpack $DEB" done export SYSTEMD_UNIT_PATH=$TEMP/usr/lib/systemd/system:$TEMP/lib/systemd/system readarray -t UNITS </dev/null) EOF for S in "${UNITS[@]}" ; do F="${S##*/}" case "${F##*.}" in service|socket|timer) ${UNIT_TRANSLATOR:=utrans} $BACKENDS -f overwrite "$S" "$TEMP/out" || \ die "Failed translating $F" ;; esac done readarray -t OUT </dev/null) EOF [ -z "$OUT" ] && die "Nothing translated" tar czf "$FIRST-services.tgz" -C "$TEMP/out" "${OUT[@]#$TEMP/out/}" unit-translator-0.7/utrans-rc000077500000000000000000000174121474613675300164170ustar00rootroot00000000000000#!/bin/sh set -e readonly PACKAGE_NAME=utrans-rc TS="/var/tmp/${PACKAGE_NAME}.stamp" # args: exit status usage() { cat <..] [ -n | -o ] [ -u | .. ] Options:- -b : specify output backend, see utrans(1) -h: show this usage -o : save ouput to subdirectories of this directory -n: no install, just show what would be done -u: update mode EOF exit $(($1+0)) } # Return status dpkg_known_files() { ret=1 # False # Some equivalent LSB scripts have .sh appended to their name. for file do [ -z "${file##/etc/init.d/*}" ] && set -- "$@" "${file}.sh" done for file do while read -r owner conffile ; do [ -z "$owner" ] || [ -z "$conffile" ] || [ "$file" != "$conffile" ] && continue echo "Skipping: $conffile owned by ${owner%:}" >&2 ret=0 # True done </dev/null)} EOF done return $ret } do_install() { for target do source="${OUTPUT_DIR}${target#/etc}" owner=$(ucfq -w "$target" | awk -F: '{print $2}') case "$owner" in '') ;; "$PACKAGE_NAME") cmp --quiet "$source" "$target" && continue ;; *) echo "Skipping $target already registered to $owner" >&2 continue ;; esac echo "Considering new $target" >&2 if [ "$NO_ACT" ] ; then echo "DRYRUN: try install $target" >&2 continue fi if [ -f "$target" ] ; then sha256=$(sha256sum "$target") mode=$(stat -c '%a' "$target") fi sudo chown root:root "$source" target_dir=$(dirname "$target") sudo mkdir -p "${target_dir}" sudo --preserve-env=UCF_FORCE_CONFFNEW,UCF_FORCE_CONFFOLD,UCF_FORCE_CONFFMISS,DEBIAN_FRONTEND \ ucf "$source" "$target" if [ -z "$owner" ] && [ -f "$target" ] && sha256sum --status --check 2>/dev/null </dev/null <&2 sudo chmod 755 "$target" # awk could be mawk with incomplete POSIX regex support origin=$(awk '/^# [0-9a-f]+ .*\.service$/ {print $3}' "$target") awk -F= '/^WantedBy=.*\.target$/ {print $2}' "$origin" | while IFS= read -r wb; do if binary_in_path rc-update ; then case "$wb" in '') echo "WARNING: no WantedBy in $origin, skipping runlevel setup" >&2 && continue ;; poweroff.target|reboot.target) orl=off ;; rescue.target) orl=recovery ;; shutdown.target) orl=shutdown ;; sysinit.target) orl=sysinit ;; *.target) orl=default ;; esac sudo rc-update show "$orl" | grep -q "$rc_name | $orl" && continue sudo rc-update add "$rc_name" "$orl" else sudo update-rc.d "$rc_name" defaults fi done fi fi ;; esac done } # Verify source units for files we have registered with ucf verify_installed() { # Reverse sort: process /etc/init.d before /etc/conf.d for owned in $(ucfq -w "$PACKAGE_NAME" | awk -F: '{if ($3) print $1}' | sort -r); do for f in $(awk '/^# [0-9a-f]+ .+\..+$/ {print $2, $3}' "$owned" | sha256sum -c 2>/dev/null | awk -F: '/FAILED/ {print $1}') ; do if [ -f "$f" ] ; then echo "Modified source unit: $f" >&2 translate_try_install "$f" || continue else echo "Deleted source unit: $f" >&2 case "$owned" in /etc/init.d/*) echo "Disabling $owned" >&2 rc_name=$(basename "$owned") sudo invoke-rc.d "$rc_name" stop || true sudo update-rc.d "$rc_name" remove || true sudo chmod -x "$owned" esac if [ "$(ucfq -w "$owned")" = "$owned:$PACKAGE_NAME:Yes:No" ] ; then echo "Removing unmodified $owned" >&2 sudo rm -f "$owned" "$owned.ucf-"* fi echo "Disowning $owned" >&2 sudo ucfr --purge "$PACKAGE_NAME" "$owned" sudo ucf --purge "$owned" fi continue 2 # Next $owned done done } binary_in_path() { PATH=/usr/sbin:/usr/bin:/sbin:/bin: command -v "$1" >/dev/null } detect_backends() { binary_in_path openrc || set -- lsb binary_in_path xinetd || set -- "$@" inetd if [ $# -gt 0 ] ; then echo "Using auto backends: $*" >&2 echo "$@" | sed 's/^\| / -b /g' fi } try_install() { unit=$1 pkg=$2 if [ "$pkg" ] && [ "$last_pkg" != "$pkg" ] ; then # This is expensive, so reuse if possible. pkg_list=$(dpkg-query -L "$pkg") last_pkg="$pkg" fi PKG_HAS_SUPPORT= # Handle all files generated by unit together set -- while read -r file ; do if [ -z "$file" ] ; then echo "WARNING: no output files, skipping." >&2 return fi target="/etc${file#"$OUTPUT_DIR"}" if grep -q "^$(dirname "$target")" <&2 PKG_HAS_SUPPORT=1 break fi set -- "$target" "$@" done <&2 fi ;; -*) echo "ERROR: long options not supported" >&2 usage 1 ;; \?) usage 1 ;; # Bad short option from getopts esac done shift $((OPTIND-1)) if [ -z "$BACKENDS" ] ; then BACKENDS=$(detect_backends) fi if [ -z "$OUTPUT_DIR" ]; then OUTPUT_DIR=$(mktemp -d) TRY_INSTALL=1 trap 'rm -rf "$OUTPUT_DIR"' EXIT verify_installed else unset TS OP_MODE fi if [ $# -eq 0 ] ; then set -- /usr/lib/systemd/system /lib/systemd/system else if [ "$OP_MODE" ] ; then echo "WARNING: ignoring update mode for non-default SOURCE_DIR" >&2 unset OP_MODE fi unset TS fi # Sigh, dpkg-query can't be sure to find the package with an # absolute path after usrmerge moving. So use a dpkg-query # pattern-match and anchor with awk at beginning (directory) and # end. unit_owners() { for src_path do shift set "$@" "${src_path#/}" done dpkg-query -S "$@" | sort -u 2>/dev/null } DPKG_SOURCE=$(unit_owners "$@") unit_binsrc() { unit=$1 awk -F: -v regex="${unit#/usr}\$" '$2 ~ regex {print $1}' <&2 else echo "Processing $u" >&2 translate_try_install "$u" "$binsrc" fi done # Update timestamp [ -z "$TS" ] || sudo sh -c ":>$TS"