[*] First commit

This commit is contained in:
2022-11-13 11:46:30 +01:00
parent 6b057d3b3d
commit a1f085aed4
25 changed files with 2894 additions and 0 deletions

46
tools/arch-binfmt Executable file
View File

@ -0,0 +1,46 @@
#!/bin/bash
#
# /usr/lib/initscripts/arch-binfmt
#
# Configure additional binary formats at boot
#
shopt -s nullglob
declare -a binfmt_d
# files given has argv supersede config files
if (( $# > 0 )); then
for arg; do [[ -r "$arg" ]] && binfmt_d+=("$arg"); done
else
binfmt_d=(
/usr/lib/binfmt.d/*.conf
/etc/binfmt.d/*.conf
/run/binfmt.d/*.conf
)
fi
# check there is file to load
(( ${#binfmt_d[@]} > 0 )) || exit 0
# mount binfmt_misc if api filesystem is missing
mountpoint -q /proc/sys/fs/binfmt_misc ||
mount /proc/sys/fs/binfmt_misc &>/dev/null ||
mount -t binfmt_misc binfmt /proc/sys/fs/binfmt_misc
# files declared later in the binfmt_d array will override earlier
# Example: `/etc/binfmt.d/foo.conf' supersedes `/usr/lib/binfmt.d/foo.conf'.
declare -A fragments
for path in "${binfmt_d[@]}"; do
[[ -f $path ]] && fragments[${path##*/}]=$path
done
for path in "${fragments[@]}"; do
while read -r line; do
[[ ${line:0:1} == '#' ]] && continue
printf "%s" "$line" > /proc/sys/fs/binfmt_misc/register
done < "$path"
done
:
# vim: set ts=2 sw=2 noet:

42
tools/arch-modules Executable file
View File

@ -0,0 +1,42 @@
#!/bin/bash
#
# /usr/lib/initscripts/arch-modules
#
# Configure kernel modules to load at boot following
# http://0pointer.de/public/systemd-man/modules-load.d.html
#
shopt -s nullglob
declare -a modules_d
# files given has argv supersede config files
if (( $# > 0 )); then
for arg; do [[ -r "$arg" ]] && modules_d+=("$arg"); done
else
modules_d=(
/usr/lib/modules-load.d/*.conf
/etc/modules-load.d/*.conf
/run/modules-load.d/*.conf
)
fi
# check there is file to load
(( ${#modules_d[@]} > 0 )) || exit 0
# files declared later in the modules_d array will override earlier
# Example: `/etc/modules-load.d/foo.conf' supersedes `/usr/lib/modules-load.d/foo.conf'.
declare -A fragments
for path in "${modules_d[@]}"; do
[[ -f $path ]] && fragments[${path##*/}]=$path
done
for path in "${fragments[@]}"; do
while read -r line; do
[[ ${line:0:1} == [\#\;] ]] && continue
modprobe -ab "$line"
done < "$path"
done
:
# vim: set ts=2 sw=2 noet:

435
tools/arch-tmpfiles Executable file
View File

@ -0,0 +1,435 @@
#!/bin/bash
#
# /usr/lib/initscripts/arch-tmpfiles
#
# Control creation, deletion, and cleaning of volatile and temporary files
#
warninvalid() {
local description=$1 file=${2:-${files[$TOTALNUM]}} linenum=${3:-${linenums[$TOTALNUM]}}
printf "%s:line %d: ignoring invalid entry: %s\n" "$file" "$linenum" "$description"
(( ++error ))
} >&2
checkparams() {
shift
local path=$1 mode=$2 uid=$3 gid=$4 age=$5
# mode must be valid octal and 3 or 4 digits
if [[ $mode != '-' ]]; then
if [[ ! $mode =~ ^[0-7]{3,4}$ ]]; then
warninvalid "invalid mode '$mode'"
return 1
fi
fi
# uid must be numeric or a valid user name
# don't try to resolve numeric IDs in case they don't exist
if [[ $uid != '-' ]]; then
if [[ $uid != +([0-9]) ]] && ! getent passwd "$uid" >/dev/null; then
warninvalid "unknown user '$uid'"
return 1
fi
fi
# gid must be numeric or a valid group name
# don't try to resolve numeric IDs in case they don't exist
if [[ $gid != '-' ]]; then
if [[ $gid != +([0-9]) ]] && ! getent group "$gid" >/dev/null; then
warninvalid "unknown group '$gid'"
return 1
fi
fi
# age must be list of numerics separated by the following postfixes:
# s, sec, m, min, h, d, w
# also it can be prefixed by '~'
if [[ $age != '-' ]]; then
if [[ ! $age =~ ^~?([0-9]+(s|sec|m|min|h|d|w)?)+$ ]]; then
warninvalid "invalid age '$age'"
return 1
fi
fi
return 0
}
relabel() {
local -a paths=($1)
local mode=$2 uid=$3 gid=$4
for path in "${paths[@]}"; do
if [[ -e $path ]]; then
[[ $uid != '-' ]] && chown $CHOPTS "$uid" "$path"
[[ $gid != '-' ]] && chgrp $CHOPTS "$gid" "$path"
[[ $mode != '-' ]] && chmod $CHOPTS "$mode" "$path"
fi
done
return 0
}
parse_age() {
local seconds=0
local numbers=(${1//[^0-9]/ })
local units=(${1//[0-9]/ })
for (( i = 0; i < ${#numbers[@]}; i++ )); do
if [ "${units[i]}" == "m" ] || [ "${units[i]}" == "min" ]; then
(( seconds += numbers[i] * 60 ))
elif [ "${units[i]}" == "h" ]; then
(( seconds += numbers[i] * 3600 ))
elif [ "${units[i]}" == "d" ]; then
(( seconds += numbers[i] * 86400 ))
elif [ "${units[i]}" == "w" ]; then
(( seconds += numbers[i] * 604800 ))
else
(( seconds += numbers[i] ))
fi
done
echo $seconds
}
in_list() {
local search=$1
for item in "${EXCLUDE_LIST[@]}"; do
[[ "$search" == $item ]] && return 0
done
return 1
}
cleanup_dir() {
local path=$1 age=$2
local depth=1
# keep first level
if [[ ${age:0:1} == '~' ]]; then
depth=2
age=${age#'~'}
fi
local age=$(parse_age $age)
local current_time=$(date +%s)
while read -d '' file; do
# don't try to remove directories which still contains some files
[[ -d "$file" && $(ls -A "$file") ]] && continue
local mod_time=$(stat -c %Y "$file")
if (( (current_time - mod_time) > age )); then
! in_list "$file" && rm -fd "$file"
fi
done < <(find -P "$path" -mindepth $depth -depth -xdev -print0)
}
_f() {
# Create a file if it doesn't exist yet
local path=$1 mode=$2 uid=$3 gid=$4
if [[ ! -e $path ]]; then
install -m"$mode" -o"$uid" -g"$gid" /dev/null "$path"
fi
}
_F() {
# Create or truncate a file
local path=$1 mode=$2 uid=$3 gid=$4
install -m"$mode" -o"$uid" -g"$gid" /dev/null "$path"
}
_d() {
# Create a directory if it doesn't exist yet
local path=$1 mode=$2 uid=$3 gid=$4 age=$5
if (( CLEAN )); then
if [[ $age != '-' ]] && [[ -d "$path" ]]; then
cleanup_dir "$path" "$age"
fi
fi
if (( CREATE )); then
if [[ ! -d "$path" ]]; then
install -d -m"$mode" -o"$uid" -g"$gid" "$path"
fi
fi
}
_D() {
# Create or empty a directory
local path=$1 mode=$2 uid=$3 gid=$4
if [[ -d $path ]] && (( REMOVE )); then
find "$path" -mindepth 1 -maxdepth 1 -xdev -exec rm -rf {} +
fi
_d "$@"
}
_p() {
# Create a named pipe (FIFO) if it doesn't exist yet
local path=$1 mode=$2 uid=$3 gid=$4
if [[ ! -p "$path" ]]; then
mkfifo -m$mode "$path"
chown "$uid:$gid" "$path"
fi
}
_x() {
# Ignore a path during cleaning. Use this type to exclude paths from clean-up as
# controlled with the Age parameter. Note that lines of this type do not
# influence the effect of r or R lines. Lines of this type accept shell-style
# globs in place of of normal path names.
local path=$1
EXCLUDE_LIST+=("$path*(/*)")
}
_X() {
# Ignore a path during cleanup. Use this type to prevent path removal as controlled
# with the Age parameter. Note that if path is a directory, content of a directory is not
# excluded from clean-up, only directory itself. Lines of this type accept
# shell-style globs in place of normal path names.
local path=$1
EXCLUDE_LIST+=("$path")
}
_r() {
# Remove a file or directory if it exists. This may not be used to remove
# non-empty directories, use R for that. Lines of this type accept shell-style
# globs in place of normal path names.
local path
local -a paths=($1)
for path in "${paths[@]}"; do
if [[ -f $path ]]; then
rm -f "$path"
elif [[ -d $path ]]; then
rmdir "$path"
fi
done
}
_R() {
# Recursively remove a path and all its subdirectories (if it is a directory).
# Lines of this type accept shell-style globs in place of normal path names.
local path
local -a paths=($1)
for path in "${paths[@]}"; do
[[ -d $path ]] && rm -rf --one-file-system "$path"
done
}
_z() {
# Set ownership, access mode and relabel security context of a file or
# directory if it exists. Lines of this type accept shell-style globs in
# place of normal path names.
local -a paths=($1)
local mode=$2 uid=$3 gid=$4
relabel "$@"
}
_Z() {
# Recursively set ownership, access mode and relabel security context of a
# path and all its subdirectories (if it is a directory). Lines of this type
# accept shell-style globs in place of normal path names.
CHOPTS=-R relabel "$@"
}
_m() {
# If the specified file path exists, adjust its access mode, group and user to
# the specified values. If it does not exist, do nothing.
relabel "$@"
}
_w() {
# Write the argument parameter to a file, if the file exists. Lines of this
# type accept shell-style globs in place of normal path names. The argument
# parameter will be written without a trailing newline.
local path
local -a paths=($1)
local argument="$6"
for path in "${paths[@]}"; do
[[ -f $path ]] && echo -n "$argument" > "$path"
done
}
_L() {
# Create a symlink if it does not exist yet.
local path=$1 source=$6
if [[ ! -e "$path" && -e "$source" ]]; then
ln -s "$source" "$path"
fi
}
_L+() {
# Create a symlink if it does not exist yet. If a file already exists where the symlink is to be created, it will be removed and be replaced by the symlink.
local path=$1 source=$6
if [[ -e "$source" ]]; then
ln -sf "$source" "$path"
fi
}
process_lines ()
{
local actions="$1"
TOTALNUM=0
while read -a line; do
(( ++TOTALNUM ))
[[ "${line[0]:0:1}" != $actions ]] && continue
# fill empty parameters
[[ "${line[2]}" ]] || line[2]='-'
[[ "${line[3]}" ]] || line[3]='-'
[[ "${line[4]}" ]] || line[4]='-'
[[ "${line[5]}" ]] || line[5]='-'
# skip invalid entries
if ! checkparams "${line[@]}"; then
continue
fi
# fall back on defaults when parameters are passed as '-'
if [[ ${line[2]} = '-' ]]; then
case ${line[0]} in
p|f|F) line[2]=0644 ;;
d|D) line[2]=0755 ;;
esac
fi
if [[ "${line[0]}" = [pfFdD] ]]; then
[[ ${line[3]} = '-' ]] && line[3]='root'
[[ ${line[4]} = '-' ]] && line[4]='root'
fi
"_${line[@]}"
done < <(printf '%s\n' "${lines[@]}")
}
shopt -s nullglob
shopt -s extglob
declare -i CREATE=0 REMOVE=0 CLEAN=0 ONBOOT=0
declare -i error=0 LINENUM=0 TOTALNUM=0
declare FILE=
declare -A fragments
declare -a tmpfiles_d=(
/usr/lib/tmpfiles.d/*.conf
/etc/tmpfiles.d/*.conf
/run/tmpfiles.d/*.conf
)
declare -a EXCLUDE_LIST lines linenums files
while (( $# )); do
case $1 in
--create) CREATE=1 ;;
--remove) REMOVE=1 ;;
--clean) CLEAN=1 ;;
--boot) ONBOOT=1 ;;
*) break ;;
esac
shift
done
if (( !(CREATE + REMOVE + CLEAN) )); then
printf 'usage: %s [--create] [--remove] [--clean] [--boot] [FILES...]\n' "${0##*/}"
exit 1
fi
# directories declared later in the tmpfiles_d array will override earlier
# directories, on a per file basis.
# Example: `/etc/tmpfiles.d/foo.conf' supersedes `/usr/lib/tmpfiles.d/foo.conf'.
for path in "${tmpfiles_d[@]}"; do
[[ -f $path ]] && fragments[${path##*/}]=${path%/*}
done
# catch errors in functions so we can exit with something meaningful
set -E
trap '(( ++error ))' ERR
# loop through the gathered fragments, sorted globally by filename.
# `/run/tmpfiles/foo.conf' will always be read after `/etc/tmpfiles.d/bar.conf'
while read -d '' fragment; do
LINENUM=0
# make sure that a fragment contains only a base filename
if [[ "$fragment" = /* ]] && [[ -f "$fragment" ]]; then
fragments[${fragment##*/}]=${fragment%/*}
fragment=${fragment##*/}
fi
if [[ -z ${fragments[$fragment]} ]]; then
printf 'warning: %s does not found\n' "$fragment"
continue
fi
printf -v FILE '%s/%s' "${fragments[$fragment]}" "$fragment"
### FILE FORMAT ###
# 0 1 2 3 4 5
# Type Path Mode UID GID Age
# d /run/user 0755 root root 10d
# omit read's -r flag to honor escapes here, so that whitespace can be
# escaped for paths. We will _not_ honor quoted paths. Also make sure that
# last line will be processed even if it does not contain terminating '\n'.
while read -a line || [[ -n "${line[@]}" ]]; do
(( ++LINENUM ))
# skip over comments and empty lines
if (( ! ${#line[*]} )) || [[ ${line[0]:0:1} = '#' ]]; then
continue
fi
# process the lines with unsafe operation marker only if --boot option is
# specified
if [[ "${line[0]}" == *! ]]; then
(( ONBOOT )) || continue
line[0]=${line[0]%!}
fi
# whine about invalid entries
if ! type -t _${line[0]} >/dev/null; then
warninvalid "unknown action '${line[0]}'" "$FILE" "$LINENUM"
continue
fi
# path cannot be empty
if [[ -z "${line[1]}" ]]; then
warninvalid "missed path" "$FILE" "$LINENUM"
continue
fi
(( ++TOTALNUM ))
lines[$TOTALNUM]="${line[@]}"
linenums[$TOTALNUM]=$LINENUM
files[$TOTALNUM]="$FILE"
done <"$FILE"
done < <(printf '%s\0' "${@:-${!fragments[@]}}" | sort -z)
# Fill exclude list first
(( CLEAN )) && process_lines "[xX]"
process_lines "[dD]"
(( CREATE )) && process_lines "[fFpzZmwL]"
(( REMOVE )) && process_lines "[rR]"
exit $error
# vim: set ts=2 sw=2 noet:

132
tools/rc.d Executable file
View File

@ -0,0 +1,132 @@
#!/bin/bash
. /etc/rc.conf
. /etc/rc.d/functions
# print usage and exit
usage() {
local name=${0##*/}
cat >&2 << EOF
usage: $name <action> [options] [daemons]
options:
-s, --started Filter started daemons
-S, --stopped Filter stopped daemons
-a, --auto Filter auto started daemons
-A, --noauto Filter manually started daemons
<daemons> is a space separated list of script in /etc/rc.d
<action> can be a start, stop, restart, reload, status, ...
WARNING: initscripts are free to implement or not the above actions.
e.g: $name list
$name list sshd gpm
$name list --started gpm
$name start sshd gpm
$name help
EOF
exit ${1:-1}
}
# filter list of daemons
filter_daemons() {
local -a new_daemons=()
for daemon in "${daemons[@]}"; do
# check if daemons is valid
if ! have_daemon "$daemon"; then
exit 2
fi
# check filter
(( ${filter[started]} )) && ck_daemon "$daemon" && continue
(( ${filter[stopped]} )) && ! ck_daemon "$daemon" && continue
(( ${filter[auto]} )) && ck_autostart "$daemon" && continue
(( ${filter[noauto]} )) && ! ck_autostart "$daemon" && continue
new_daemons+=("$daemon")
done
daemons=("${new_daemons[@]}")
}
(( $# < 1 )) && usage
# ret store the return code of rc.d
declare -i ret=0
# daemons store daemons on which action will be executed
declare -a daemons=()
# filter store current filter mode
declare -A filter=([started]=0 [stopped]=0 [auto]=0 [noauto]=0)
# parse options
argv=$(getopt -l 'started,stopped,auto,noauto' -- 'sSaA' "$@") || usage
eval set -- "$argv"
# create an initial daemon list
while [[ "$1" != -- ]]; do
case "$1" in
-s|--started) filter[started]=1 ;;
-S|--stopped) filter[stopped]=1 ;;
-a|--auto) filter[auto]=1 ;;
-A|--noauto) filter[noauto]=1 ;;
esac
shift
done
# remove --
shift
# get action
action=$1
shift
# get initial daemons list
for daemon; do
daemons+=("$daemon")
done
# going into script directory
cd /etc/rc.d
case $action in
help)
usage 0 2>&1
;;
list)
# list take all daemons by default
[[ -z $daemons ]] && for d in *; do [[ -f /etc/rc.d/"$d" && -x /etc/rc.d/"$d" ]] && daemons+=("$d"); done
filter_daemons
for daemon in "${daemons[@]}"; do
# print running / stopped status
if ! ck_daemon "$daemon"; then
s_status="${C_OTHER}[${C_DONE}STARTED${C_OTHER}]"
else
s_status="${C_OTHER}[${C_FAIL}STOPPED${C_OTHER}]"
fi
# print auto / manual status
if ! ck_autostart "$daemon"; then
s_auto="${C_OTHER}[${C_DONE}AUTO${C_OTHER}]"
else
s_auto="${C_OTHER}[${C_FAIL} ${C_OTHER}]"
fi
printf "$s_status$s_auto${C_CLEAR} $daemon\n"
done
;;
*)
# other actions need an explicit daemons list
[[ -z $daemons ]] && usage
filter_daemons
# set same environment variables as init
runlevel=$(/usr/bin/runlevel)
ENV=('PATH=/usr/bin'
"PREVLEVEL=${runlevel%% *}"
"RUNLEVEL=${runlevel##* }"
"CONSOLE=${CONSOLE:-/dev/console}"
"TERM=$TERM")
cd /
for daemon in "${daemons[@]}"; do
env -i "${ENV[@]}" "/etc/rc.d/$daemon" "$action"
(( ret += !! $? )) # clamp exit value to 0/1
done
;;
esac
exit $ret
# vim: set ts=2 sw=2 ft=sh noet: