#!/bin/bash # LXS - Welcome message (MOTD) # Description: View, edit, or reset the SSH login welcome message (/etc/motd) # Author: LXS # Date: 2025 # Load LXS common library (colors, separator, run_spinner, loggers, helpers) LXS_RAW_BASE="${LXS_RAW_BASE:-https://git.hyko.cx/hykocx/lxs/raw/branch/main}" _lib=$(curl -fsSL "${LXS_RAW_BASE}/lib/common.sh") || { echo "Failed to fetch lib/common.sh" >&2; exit 1; } eval "$_lib" unset _lib export LXS_LOG_FILE="/tmp/lxs_welcome_message.log" require_root "$0" "$@" set -u MOTD_FILE="/etc/motd" BACKUP_FILE="/etc/motd.lxs.bak" DYNAMIC_DIR="/etc/update-motd.d" # ═══════════════════════════════════════════════════════════════════════════ # Arguments # ═══════════════════════════════════════════════════════════════════════════ ACTION="" TEXT="" FROM_FILE="" while [ $# -gt 0 ]; do case "$1" in view|--view|show|--show) ACTION="view" ;; set|--set|edit|--edit) ACTION="set" ;; reset|--reset) ACTION="reset" ;; --text) shift; TEXT=${1:-} ;; --text=*) TEXT="${1#*=}" ;; --from-file) shift; FROM_FILE=${1:-} ;; --from-file=*) FROM_FILE="${1#*=}" ;; -h|--help) cat <&2 exit 1 ;; esac shift done if [ -n "$TEXT" ] && [ -n "$FROM_FILE" ]; then err "--text and --from-file are mutually exclusive" exit 1 fi # ═══════════════════════════════════════════════════════════════════════════ # Helpers # ═══════════════════════════════════════════════════════════════════════════ view_motd() { echo -e "${WHITE}${BOLD}Current welcome message${NC} ${GRAY}(${MOTD_FILE})${NC}" show_separator if [ ! -s "$MOTD_FILE" ]; then echo -e "${GRAY}(empty)${NC}" else cat "$MOTD_FILE" fi show_separator if [ -d "$DYNAMIC_DIR" ] && compgen -G "${DYNAMIC_DIR}/*" >/dev/null; then echo "" warn "Dynamic MOTD scripts are present in ${DYNAMIC_DIR}:" find "$DYNAMIC_DIR" -maxdepth 1 -type f -executable -printf ' • %f\n' | sort echo -e "${GRAY}These run at login and add to the banner.${NC}" fi } backup_motd() { [ -f "$MOTD_FILE" ] || return 0 cp -a "$MOTD_FILE" "$BACKUP_FILE" info "Previous message backed up to ${BACKUP_FILE}" } write_motd() { local src=$1 backup_motd install -m 644 "$src" "$MOTD_FILE" ok "Welcome message updated" echo "" view_motd } set_from_text() { local tmp tmp=$(mktemp /tmp/lxs.motd.XXXXXX) || { err "mktemp failed"; return 1; } # Preserve embedded newlines; ensure a trailing newline. printf '%s\n' "$1" > "$tmp" write_motd "$tmp" rm -f "$tmp" } set_from_file() { local src=$1 if [ ! -r "$src" ]; then err "Cannot read file: ${src}" return 1 fi write_motd "$src" } set_interactive() { local editor=${EDITOR:-} if [ -z "$editor" ]; then if command -v nano >/dev/null 2>&1; then editor="nano" elif command -v vi >/dev/null 2>&1; then editor="vi" else err "No editor found (\$EDITOR unset; nano/vi missing). Use --text or --from-file." return 1 fi fi local tmp tmp=$(mktemp /tmp/lxs.motd.XXXXXX) || { err "mktemp failed"; return 1; } [ -s "$MOTD_FILE" ] && cat "$MOTD_FILE" > "$tmp" info "Opening ${editor}... save and exit to apply, leave empty to cancel." "$editor" "$tmp" if [ ! -s "$tmp" ]; then warn "Empty content — change cancelled." rm -f "$tmp" return 0 fi write_motd "$tmp" rm -f "$tmp" } reset_motd() { if [ ! -s "$MOTD_FILE" ]; then info "Welcome message is already empty." return 0 fi backup_motd : > "$MOTD_FILE" chmod 644 "$MOTD_FILE" ok "Welcome message cleared" } # ═══════════════════════════════════════════════════════════════════════════ # Menu (when no action is given on the CLI) # ═══════════════════════════════════════════════════════════════════════════ if [ -z "$ACTION" ]; then echo -e "${WHITE}${BOLD}LXS - Welcome message${NC}" show_separator echo -e " ${CYAN}[1]${NC} View current message" echo -e " ${GREEN}[2]${NC} Set a new message" echo -e " ${YELLOW}[3]${NC} Reset (clear) the message" echo -e " ${RED}[0]${NC} Cancel" echo "" echo -e -n "${BOLD}Choice [0-3]: ${NC}" read -r choice case "$choice" in 1) ACTION="view" ;; 2) ACTION="set" ;; 3) ACTION="reset" ;; 0|"") info "Cancelled."; exit 0 ;; *) err "Invalid option."; exit 1 ;; esac fi case "$ACTION" in view) view_motd ;; set) if [ -n "$TEXT" ]; then set_from_text "$TEXT" elif [ -n "$FROM_FILE" ]; then set_from_file "$FROM_FILE" else set_interactive fi ;; reset) reset_motd ;; esac