# -*-eselect-*- vim: ft=eselect # Copyright 1999-2013 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 or later # $Id: $ DESCRIPTION="Switch between settingsd implementations" MAINTAINER="lxnay@gentoo.org" VERSION="0.1" # Directory where eselect settingsd must install root directory trees # whose files will be symlinked onto the real system. SETTINGSD_DIR="${EROOT}/%SETTINGSD_DIR%" # File containing the current settingsd implementation. CURRENT_SETTINGSD_FILE="${EROOT}/etc/env.d/eselect-settingsd/current" # Convert source ${1} to be relative to destination, parent directory # of ${2}. This is slightly different between relative_name, because # source and destination may not exist. _relative_name() { local s="${1}" local d="${2}" local parents= local d_dir=$(dirname "${d}") while [[ "${d_dir}" != "/" ]]; do parents+="../" d_dir="$(dirname "${d_dir}")" done parents="${parents:-.}" parents="${parents%/}" echo "${parents}${s}" } find_targets() { local d= local dname= local legit= for d in "${SETTINGSD_DIR}/"*; do [[ ! -d "${d}" ]] && continue dname=$(basename "${d}") echo "${dname}" done } _get_target_dir() { local target="${1}" if is_number "${target}"; then local targets=( $(find_targets) ) target=${targets[target-1]} fi local target_dir="${SETTINGSD_DIR}/${target}" [[ -z "${target}" || ! -d "${target_dir}" ]] \ && die -q "Target \"${target}\" doesn't appear to be valid!" echo ${target_dir} } _get_settingsd_files() { local target="${1}" local target_dir=$(_get_target_dir "${target}") files="$(find "${target_dir}" -type f -print 2>/dev/null)" files+=" $(find "${target_dir}" -type l -print 2>/dev/null)" echo ${files} } _clean_old_target() { local target="${1}" local target_dir=$(_get_target_dir "${target}") local f= local files=( $(_get_settingsd_files "${target}") ) for f in "${files[@]}"; do f="${f#${target_dir}}" [[ -L "${f}" ]] && rm -f "${f}" done } set_settingsd() { local target="${1}" local target_dir=$(_get_target_dir "${target}") echo "Setting the settingsd implementation to ${target}" # TODO: differential removal? local old_target=$(get_settingsd) [[ -n "${old_target}" ]] && _clean_old_target "${old_target}" echo "${target}" > "${CURRENT_SETTINGSD_FILE}.tmp" || { rm -f "${CURRENT_SETTINGSD_FILE}.tmp"; die "Cannot save the current temp. settingsd state" } local s= d= local files=( $(_get_settingsd_files "${target}") ) for s in "${files[@]}"; do d="${s#${target_dir}}" s=$(_relative_name "${s}" "${d}") ln -sf "${s}" "${d}.tmp" || { rm -f "${d}.tmp"; die "Cannot symlink ${s} to ${d}.tmp"; } mv "${d}.tmp" "${d}" || die "Cannot mv ${d}.tmp" done mv "${CURRENT_SETTINGSD_FILE}.tmp" "${CURRENT_SETTINGSD_FILE}" || \ die "Cannot save the current settingsd state" # silently reload dbus /usr/bin/dbus-send --print-reply --system --type=method_call \ --dest=org.freedesktop.DBus \ / org.freedesktop.DBus.ReloadConfig > /dev/null } get_settingsd() { cat "${CURRENT_SETTINGSD_FILE}" 2> /dev/null } describe_show() { echo "Show the current init implementation" } describe_show_options() { echo "--quiet : only print the actual settingsd implementation" echo "--silent : same as --quiet" } do_show() { local quiet= local settingsd= while [[ $# -gt 0 ]]; do case ${1##--} in quiet|silent) quiet="1" ;; esac shift done settingsd=$(get_settingsd) [[ -z "${settingsd}" ]] && write_list_start "Current :" if [[ -n "${settingsd}" ]]; then if [[ -n "${settingsd}" ]]; then echo "${settingsd}" else write_kv_list_entry "${settingsd}" "" fi else if [[ -z "${quiet}" ]]; then write_kv_list_entry "(unset)" "" fi fi } describe_list() { echo "List available settingsd implementations" } describe_list_options() { echo "--quiet : only print the actual list of implementations" echo "--silent : same as --quiet" } do_list() { local quiet= local i= local settingsd=$(get_settingsd) local targets=( $(find_targets) ) while [[ $# -gt 0 ]]; do case ${1##--} in quiet|silent) quiet="1" ;; esac shift done [[ -z "${quiet}" ]] && \ write_list_start "Available settingsd implementations:" for (( i = 0; i < ${#targets[@]}; i++ )); do if [[ -z "${quiet}" ]]; then [[ "${targets[i]}" == "${settingsd}" ]] && \ targets[i]=$(highlight_marker "${targets[i]}") else echo "${targets[i]}" fi done [[ -z "${quiet}" ]] && \ write_numbered_list -m "(none found)" "${targets[@]}" } describe_set() { echo "Set a new settingsd implementation" } describe_set_parameters() { echo "" } describe_set_options() { echo "target : Target name or number (from 'list' action)" echo "--use-old : use the old value if target is already set" } do_set() { local use_old= local target="${1}" while [[ $# -gt 0 ]]; do case ${1##--} in use-old) use_old="1" ;; esac shift done [[ -z "${target}" ]] && \ die -q "You didn't tell me what to set the symlink to" [[ ${#} -gt 1 ]] && die -q "Too many parameters" if [[ "${use_old}" = "1" ]]; then old_target=$(get_settingsd) target="${old_target:-${target}}" fi set_settingsd "${target}" || die -q "Couldn't set a new settingsd" }