From 2c37f041937f468596158d76bb8ecb3442b0e4b4 Mon Sep 17 00:00:00 2001 From: CyberLeo Date: Mon, 3 Jan 2011 07:23:03 -0600 Subject: [PATCH] Add fixusers script to handle bash-config symlinks in user directories --- share/fixuser | 197 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100755 share/fixuser diff --git a/share/fixuser b/share/fixuser new file mode 100755 index 0000000..d26d014 --- /dev/null +++ b/share/fixuser @@ -0,0 +1,197 @@ +#!/bin/sh + +pebkac() { + [ "${*}" ] && printf "%s\n\n" "${*}" + cat < [user ...] + + -c Check symlinks for sanity + -i Install symlinks + -r Remove symlinks + +This script will adjust the bash-config symlinks in the homedir of +the supplied user, or all users if unspecified. + +This script will avoid tampering with files that it thinks are +manually added. Use -c to check, and verify the files manually +afterwards. + +EOF + exit "${#}" +} + +files="bash_profile bashrc" + +userlist() { + # Ignore users with shell not in /etc/shells + # Ignore users with invalid homedir + # Ignore subsequent users with the same homedir (root, toor, daemon, etc) + # List all remaining usernames + local _home_cache + getent passwd | while IFS=: read user pass uid gid gecos home shell extra + do + getent shells "${shell}" >&- || continue + [ -d "${home}" ] || continue + echo "${_home_cache}" | grep -q " ${home} " && continue + _home_cache="${_home_cache} ${home} " + echo "${user}" + done +} + +userdir() { + [ "${1}" ] || return 1 + # This is a loop because read will not work after pipe due to subshell isolation + getent passwd "${1}" | while IFS=: read user pass uid gid gecos home shell extra + do + echo "${home}" + break + done +} + +mine() { + [ "${1}" ] || return 1 + user="${1}"; shift + [ "${#}" -eq 0 ] && set - ${files} + while [ "${1}" ] + do + file="${1}" + link="$(userdir "${user}")/.${file}" + real="/usr/local/etc/bash-config/${file}" + if [ ! -L "${link}" ] || [ "$(realpath "$(readlink "${link}")")" != "${real}" ] + then + return 1 + fi + shift + done + return 0 +} + +gone() { + [ "${1}" ] || return 1 + user="${1}"; shift + [ "${#}" -eq 0 ] && set - ${files} + while [ "${1}" ] + do + file="${1}" + link="$(userdir "${user}")/.${file}" + [ -f "${link}" ] && return 1 + shift + done + return 0 +} + +check() { + [ "${1}" ] || return 1 + user="${1}"; shift + [ "${#}" -eq 0 ] && set - ${files} + echo "Checking user ${user}..." + while [ "${1}" ] + do + file="${1}" + if gone "${user}" "${file}" + then + echo " File ${file} does not exist." + else + if mine "${user}" "${file}" + then + echo " File ${file} is mine." + else + echo " File ${file} exists, but is not mine." + fi + fi + shift + done +} + +install() { + [ "${1}" ] || return 1 + user="${1}" + if mine "${user}" + then + echo "User symlinks appear to be correct" + return 0 + fi + + if ! gone "${user}" + then + echo "User files (${files}) appear to exist, and are not mine" + echo "Refusing to molest them" + return 1 + fi + + for file in ${files} + do + link="$(userdir "${user}")/.${file}" + real="/usr/local/etc/bash-config/${file}" + [ "${link%%.${file}}" = "/" ] && return 1 + su "${user}" -c "ln -s '${real}' '${link}'" || return $? + done + return 0 +} + +remove() { + [ "${1}" ] || return 1 + user="${1}" + if gone "${user}" + then + echo "User symlinks already removed" + return 0 + fi + + if ! mine "${user}" + then + echo "User files (${files}) appear to exist, and are not mine" + echo "Refusing to molest them" + return 1 + fi + + for file in ${files} + do + link="$(userdir "${user}")/.${file}" + [ "${link%%.${file}}" = "/" ] && return 1 + rm -f "${link}" || return $? + done + return 0 +} + +state() { + [ -z "${cmd}" ] || pebkac "Only specify one of -c -i -r" + cmd="${1}" +} + +cmd="" + +while getopts "cir" opt +do + case "${opt}" in + c) state check ;; + i) state install ;; + r) state remove ;; + [?]) pebkac "Unrecognized option ${OPTARG}" ;; + esac +done +shift $(( $OPTIND - 1 )) + +[ "${cmd}" ] || pebkac + +# Default to current user if not root +if [ "$(id -u)" -gt 0 ] +then + if [ "${*}" -a "${*}" != "${USER}" ] + then + echo "Mortal users can only modify themselves" >&2 + exit 1 + fi + [ "${#}" -eq 0 ] && set - ${USER} +else + [ "${#}" -eq 0 ] && set - $(userlist) +fi + +printf "Working on user(s) " +echo "${@}" + +while [ "${1}" ] +do + "${cmd}" "${1}" + shift +done -- 2.42.0