Skip to content

motdgen, issuegen: write staged changes to a tempfile #44

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions usr/lib/console-login-helper-messages/libutil.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/bash
#
# Collection of util functions and common definitions for
# console-login-helper-messages scripts.

PKG_NAME="console-login-helper-messages"

tempfile_template="${PKG_NAME}.XXXXXXXXXX.tmp"
# Use same filesystem, under /run, as where snippets are generated, so
# that rename operations through `mv` are atomic.
tempfile_dir="/run/${PKG_NAME}"
# Default SELinux context at destination is applied, e.g. for sshd which
# requires that written files in `/run/motd.d` maintain the type
# `pam_var_run_t`.
mv_Z="mv -Z"

# Write stdin to a tempfile, and rename the tempfile to the path given
# as an argument. When called from multiple processes on the same
# generated file path, this avoids interleaving writes to the generated
# file by using `mv` to overwrite the file.
write_via_tempfile() {
local generated_file="$1"
local staged_file="$(mktemp --tmpdir="${tempfile_dir}" "${tempfile_template}")"
cat > "${staged_file}"
${mv_Z} "${staged_file}" "${generated_file}"
}

# Write concatenation of all files with a given suffix from a list of
# source directories to a target file. The target file is the first
# argument; suffix the second; and source directories the remaining,
# searched in the given order in the list. Atomicity of the write to
# the target file is given by appending file contents to a tempfile
# before moving to the target file.
cat_via_tempfile() {
local generated_file="$1"
local filter_suffix="$2"
shift 2
local source_dirs="$@"
local staged_file="$(mktemp --tmpdir="${tempfile_dir}" "${tempfile_template}")"
for source_dir in ${source_dirs[@]}; do
# Ignore stderr, and let the command succeed if no files are
# found in the source directory.
cat "${source_dir}"/*"$filter_suffix" 2>/dev/null >> "${staged_file}" || :
done
${mv_Z} "${staged_file}" "${generated_file}"
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[Unit]
Description=Generate /run/motd.d/console-login-helper-messages.motd
Description=Generate console-login-helper-messages motd snippet
Documentation=https://github.com/coreos/console-login-helper-messages
Before=systemd-user-sessions.service

Expand Down
4 changes: 3 additions & 1 deletion usr/libexec/console-login-helper-messages/gensnippet_udev_if
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@

set -e

. /usr/lib/console-login-helper-messages/libutil.sh
. /usr/libexec/console-login-helper-messages/issuegen.defs

# Add/remove data from udev rules.
outfile="${RUN_SNIPPETS}/22_${INTERFACE}.issue"
case "${ACTION}" in
add)
echo "${INTERFACE}: \\4{${INTERFACE}} \\6{${INTERFACE}}" > ${outfile}
echo "${INTERFACE}: \\4{${INTERFACE}} \\6{${INTERFACE}}" \
| write_via_tempfile ${outfile}
;;
remove)
rm -f ${outfile}
Expand Down
13 changes: 6 additions & 7 deletions usr/libexec/console-login-helper-messages/issuegen
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

set -e

. /usr/lib/console-login-helper-messages/libutil.sh
. /usr/libexec/console-login-helper-messages/issuegen.defs

# Provide key fingerprints via issue.
Expand All @@ -22,16 +23,14 @@ mkdir -p "${SSH_DIR}"
SSH_KEY_OUTDIR="${RUN_SNIPPETS}"
for KEY_FILE in $(find "${SSH_DIR}" -name 'ssh_host_*_key') ; do
ssh-keygen -l -f "${KEY_FILE}"
done | awk '{print "SSH host key: " $2 " " $4}' > "${SSH_KEY_OUTDIR}/21_ssh_host_keys.issue"
done \
| awk '{print "SSH host key: " $2 " " $4}' \
| write_via_tempfile "${SSH_KEY_OUTDIR}/21_ssh_host_keys.issue"


# Generate a final issue message from compiling the snippets.
# Pick 40 as a prefix as other files can order around it easily.
generated_file="/run/${PKG_NAME}/40_${PKG_NAME}.issue"
generated_string=''
# Hack around files potentially not existing in the below paths with `|| true`.
generated_string+=$(cat ${ETC_SNIPPETS}/* 2>/dev/null || true)
generated_string+=$(cat ${RUN_SNIPPETS}/* 2>/dev/null || true)
generated_string+=$(cat ${USR_LIB_SNIPPETS}/* 2>/dev/null || true)
source_dirs=("${ETC_SNIPPETS}" "${RUN_SNIPPETS}" "${USR_LIB_SNIPPETS}")

echo "${generated_string}" > "${generated_file}"
cat_via_tempfile "${generated_file}" ".issue" "${source_dirs[@]}"
46 changes: 21 additions & 25 deletions usr/libexec/console-login-helper-messages/motdgen
Original file line number Diff line number Diff line change
Expand Up @@ -9,35 +9,31 @@
# Get updated system information and generate a motd
# to display this at login.

. /usr/lib/console-login-helper-messages/libutil.sh

set -e

PKG_NAME=console-login-helper-messages
MOTD_DIR_PUBLIC=motd.d
# Should only be read by this script.
MOTD_DIR_PRIVATE="${PKG_NAME}/motd.d"
MOTD_SNIPPETS_PATH="${PKG_NAME}/motd.d"
ETC_SNIPPETS="/etc/${MOTD_SNIPPETS_PATH}"
RUN_SNIPPETS="/run/${MOTD_SNIPPETS_PATH}"
USR_LIB_SNIPPETS="/usr/lib/${MOTD_SNIPPETS_PATH}"

staged="/run/${PKG_NAME}/40_${PKG_NAME}.motd.staged"
# Pick 40 as an index as other files can order around it easily.
generated="/run/motd.d/40_${PKG_NAME}.motd"
# Parts of this script write to the `${RUN_SNIPPETS}` directory,
# make sure it is created upfront.
mkdir -p "${RUN_SNIPPETS}"

mkdir -p "/run/${MOTD_DIR_PRIVATE}"
mkdir -p "/run/${MOTD_DIR_PUBLIC}"
rm -f "${generated}"

# Write distro release information to MOTD, in distro-specific color.
source /usr/lib/os-release
echo -e "\e[${ANSI_COLOR}m${PRETTY_NAME}\e[39m" > "/run/${MOTD_DIR_PRIVATE}/21_os_release.motd"

# Generate a motd from files found in the private (package-specific) directories,
# and place the motd in a public directory.
if [[ -d "/etc/${MOTD_DIR_PRIVATE}" ]]; then
cat /etc/${MOTD_DIR_PRIVATE}/* 2>/dev/null >> "${staged}" || true
fi
if [[ -d /run/"${MOTD_DIR_PRIVATE}" ]]; then
cat /run/${MOTD_DIR_PRIVATE}/* 2>/dev/null >> "${staged}" || true
fi
if [[ -d /usr/lib/"${MOTD_DIR_PRIVATE}" ]]; then
cat /usr/lib/${MOTD_DIR_PRIVATE}/* 2>/dev/null >> "${staged}" || true
fi

cat "${staged}" > "${generated}"
rm -rf "${staged}"
OS_RELEASE_OUTDIR="${RUN_SNIPPETS}"
echo -e "\e[${ANSI_COLOR}m${PRETTY_NAME}\e[39m" \
| write_via_tempfile "${OS_RELEASE_OUTDIR}/21_os_release.motd"


# Generate a final motd from compiling the snippets.
# Pick 40 as a prefix as other files can order around it easily.
generated_file="/run/motd.d/40_${PKG_NAME}.motd"
source_dirs=("${ETC_SNIPPETS}" "${RUN_SNIPPETS}" "${USR_LIB_SNIPPETS}")

cat_via_tempfile "${generated_file}" ".motd" "${source_dirs[@]}"