#!/bin/bash # ------------------------------------------------------------------- # # Shell program to display changes to "/var/log/messages", # "/var/log/mail" and the "From:" and "Subject" lines of new mail to # root and his normal user account via "root-tail" windowless on root # window of your desktop in a terminal via "tail" colorized with # "ccze". # # Copyright 2002, Thorsten Bonow . # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # Description: # # # NOTE: You must be the superuser to run this script. # # Usage: # # sm_watch [ -h | --help ] [-u user] # # Options: # # -h, --help Display this help message and exit. # -r Display information on root desktop # -t Display information in a terminal # -u user roots normal user account # # # Revision History: # # 12/02/2002 File created by new_script ver. 2.1.0 # 01/15/2003 Implemented alternativ output to terminal instead # of using root-tail # 09/09/2003 Adapted to Debian Linux # See ChangeLog for changes after CVS import # # CVS: $Id: sm_watch,v 1.7 2007-01-21 11:10:53 toto Exp $ # ------------------------------------------------------------------- # ------------------------------------------------------------------- # Constants # ------------------------------------------------------------------- PROGNAME=$(basename $0) VERSION="0.9" # ------------------------------------------------------------------- # Configuration: Adapt to your needs # ------------------------------------------------------------------- # full path required because script is used in root environment # which does not necessarily has full path to applications ROOT_TAIL_BIN="/usr/bin/root-tail" TERMINAL_BIN="/usr/bin/rxvt" TAIL_BIN="/usr/bin/tail" CCZE_BIN="/usr/bin/ccze" NICE_CALL="/usr/bin/nice -n 19" DEFAULT_ROOT_USER="toto" # default user for mailcheck MAIL_FILE_DIR="/var/mail" # directory for mail files MESSAGES_FILE="/var/log/messages" MAIL_FILE="/var/log/exim4/mainlog" FONT_SIZE="-misc-fixed-medium-r-semicondensed--13-*-*-*-c-60-iso8859-1" MAIL_CHECK_TIMEOUT=10 # seconds to wait before # rechecking email ROOT_TAIL_TIMEOUT=3 # seconds for root-tail to sleep # before updates TAIL_TIMEOUT=3 # seconds for tail to sleep # before updates # Window manager dependent size and position of root-tail's area of # root window to draw on. # TWM TWM_SIZE="390x500" TWM_POSITION="-1-30" # Larswm LARSWM_SIZE="390x500" LARSWM_POSITION="-1-30" # Defaults: if [ -n "$VNCDESKTOP" ] ; then DEFAULT_SIZE="$TWM_SIZE" DEFAULT_POSITION="$TWM_POSITION" elif [ "800x600+0+0" == `xwininfo -root | grep "geometry" | awk '{print $2}'` ] ; then DEFAULT_SIZE="$TWM_SIZE" DEFAULT_POSITION="$TWM_POSITION" else DEFAULT_SIZE="$LARSWM_SIZE" DEFAULT_POSITION="$LARSWM_POSITION" fi # Window manager dependent colors # TWM TWM_EMAILCOLOR="gray" TWM_MESSAGESCOLOR="black" TWM_MAILCOLOR="snow" # Larswm LARSWM_EMAILCOLOR="gray" LARSWM_MESSAGESCOLOR="orange" LARSWM_MAILCOLOR="snow" # Defaults: if [ -n "$VNCDESKTOP" ] ; then DEFAULT_EMAILCOLOR="$TWM_EMAILCOLOR" DEFAULT_MESSAGESCOLOR="$TWM_MESSAGESCOLOR" DEFAULT_MAILCOLOR="$TWM_MAILCOLOR" elif [ "800x600+0+0" == `xwininfo -root | grep "geometry" | awk '{print $2}'` ] ; then DEFAULT_EMAILCOLOR="$TWM_EMAILCOLOR" DEFAULT_MESSAGESCOLOR="$TWM_MESSAGESCOLOR" DEFAULT_MAILCOLOR="$TWM_MAILCOLOR" else DEFAULT_EMAILCOLOR="$LARSWM_EMAILCOLOR" DEFAULT_MESSAGESCOLOR="$LARSWM_MESSAGESCOLOR" DEFAULT_MAILCOLOR="$LARSWM_MAILCOLOR" fi # Window manager dependent size and position of terminal # TWM TWM_TERMINAL_SIZE="54x23" TWM_TERMINAL_POSITION="-0-0" # Larswm (if terminal it automatically tiled, this values # are ignored) LARSWM_TERMINAL_SIZE="54x23" LARSWM_TERMINAL_POSITION="+890+661" # Defaults: if [ -n "$VNCDESKTOP" ] ; then DEFAULT_TERMINAL_SIZE="$TWM_TERMINAL_SIZE" DEFAULT_TERMINAL_POSITION="$TWM_TERMINAL_POSITION" elif [ "800x600+0+0" == `xwininfo -root | grep "geometry" | awk '{print $2}'` ] ; then DEFAULT_TERMINAL_SIZE="$TWM_TERMINAL_SIZE" DEFAULT_TERMINAL_POSITION="$TWM_TERMINAL_POSITION" else DEFAULT_TERMINAL_SIZE="$LARSWM_TERMINAL_SIZE" DEFAULT_TERMINAL_POSITION="$LARSWM_TERMINAL_POSITION" fi # NO CHANGES SHOULD BE REQUIRED FROM HERE! # ------------------------------------------------------------------- # Functions # ------------------------------------------------------------------- function clean_up { # ----------------------------------------------------------------------- # Function to remove temporary files and other housekeeping # No arguments # ----------------------------------------------------------------------- kill_root-tail kill_terminal rm -f ${TEMP_FILE1} } function error_exit { # ----------------------------------------------------------------------- # Function for exit due to fatal program error # Accepts 1 argument: # string containing descriptive error message # ----------------------------------------------------------------------- echo "${PROGNAME}: ${1:-"Unknown Error"}" >&2 clean_up exit 1 } function graceful_exit { # ----------------------------------------------------------------------- # Function called for a graceful exit # No arguments # ----------------------------------------------------------------------- clean_up exit } function signal_exit { # ----------------------------------------------------------------------- # Function to handle termination signals # Accepts 1 argument: # signal_spec # ----------------------------------------------------------------------- case $1 in INT) echo "$PROGNAME: Program aborted by user" >&2 clean_up exit ;; TERM) echo "$PROGNAME: Program terminated" >&2 clean_up exit ;; *) error_exit "$PROGNAME: Terminating on unknown signal" ;; esac } function make_temp_files { # ----------------------------------------------------------------------- # Function to create temporary files # No arguments # ----------------------------------------------------------------------- # Use user's local tmp directory if it exists if [ -d ~/tmp ]; then TEMP_DIR=~/tmp else TEMP_DIR=/tmp fi # Temp file for this script, using paranoid method of creation to # insure that file name is not predictable. This is for security to # avoid "tmp race" attacks. If more files are needed, create using # the same form. TEMP_FILE1=$(mktemp -q "${TEMP_DIR}/${PROGNAME}.$$.XXXXXX") if [ "$TEMP_FILE1" == "" ]; then error_exit "cannot create temp file!" fi } function usage { # ----------------------------------------------------------------------- # Function to display usage message (does not exit) # No arguments # ----------------------------------------------------------------------- echo "Usage: ${PROGNAME} [-h | --help] [-r] [-t] [-u user]" } function helptext { # ----------------------------------------------------------------------- # Function to display help message for program # No arguments # ----------------------------------------------------------------------- local tab=$(echo -en "\t\t") cat <<- -EOF- ${PROGNAME} ver. ${VERSION} This is a program to display changes to "/var/log/messages", "/var/log/mail" and the "From:" and "Subject" lines of new mail to root and his normal user account via "root-tail" windowless on root window of your desktop or in a terminal via "tail" colorized with "ccze". $(usage) Options: -h, --help Display this help message and exit. -r Display information on root desktop -t Display information in a terminal -u user roots normal user account NOTE: You must be the superuser to run this script. -EOF- } function root_check { ##### # Function to check if user is root # No arguments ##### if [ "$(id | sed 's/uid=\([0-9]*\).*/\1/')" != "0" ]; then error_exit "You must be the superuser to run this script." fi } function grep_from_and_subject_from_mail { # ----------------------------------------------------------------------- # Function to grep mail file for lines containing "From:" and "Subject:". # Prettyprinting the output. # Arguments: # 1 USERNAME (required) # ----------------------------------------------------------------------- # Fatal error if required arguments are missing if [ "$1" == "" ]; then error_exit "USERNAME: missing argument 1" fi grep "^\(From \|Subject:\)" "${MAIL_FILE_DIR}"/"${1}" | \ sed 's/From /From: /' | sed '/^Subject/a --' >> $TEMP_FILE1 return } # end of grep_from_and_subject_from_mail function timestamp_mail_files { # ----------------------------------------------------------------------- # Function to get the modificatin time of the mail files # No arguments # ----------------------------------------------------------------------- if [[ ${CHECK_ROOT} == "true" ]]; then TIMESTAMP_ROOT=`ls -l "${MAIL_FILE_DIR}"/root | awk '{print $8}'` fi if [[ ${CHECK_USER} == "true" ]]; then TIMESTAMP_USER=`ls -l "${MAIL_FILE_DIR}"/${ROOT_USER}| awk '{print $8}'` fi return } # end of timestamp_mail_files function check_for_new_mails { # ----------------------------------------------------------------------- # Function to compare modification time of mail files with times stored # in "TIMESTAMP_USER/ROOT" variables; set variable "MAIL_UPDATE" # accordingly # No arguments # ----------------------------------------------------------------------- if [[ ${CHECK_ROOT} == "true" ]]; then TIMESTAMP_ROOT_NEW=`ls -l "${MAIL_FILE_DIR}"/root | awk '{print $8}'` fi if [[ ${CHECK_USER} == "true" ]]; then TIMESTAMP_USER_NEW=`ls -l "${MAIL_FILE_DIR}"/${ROOT_USER}| awk '{print $8}'` fi if [[ $TIMESTAMP_ROOT_NEW != $TIMESTAMP_ROOT ]]; then MAIL_UPDATE="true" TIMESTAMP_ROOT="${TIMESTAMP_ROOT_NEW}" fi if [[ $TIMESTAMP_USER_NEW != $TIMESTAMP_USER ]]; then MAIL_UPDATE="true" TIMESTAMP_USER="${TIMESTAMP_USER_NEW}" fi return } # end of check_for_new_mails function start_root-tail { # ----------------------------------------------------------------------- # Function to start root-tail with correct parameters # No arguments # ----------------------------------------------------------------------- if [[ $CHECK_MAIL == "true" ]]; then EMAIL_STRING=""${TEMP_FILE1}","${DEFAULT_EMAILCOLOR}",Mails" else EMAIL_STRING="" fi $NICE_CALL $ROOT_TAIL_BIN -fn "${FONT_SIZE}" -i ${ROOT_TAIL_TIMEOUT} \ -g ${DEFAULT_SIZE}${DEFAULT_POSITION} \ ""${MESSAGES_FILE}","${DEFAULT_MESSAGESCOLOR}","$MESSAGES_FILE"" \ ""${MAIL_FILE}","${DEFAULT_MAILCOLOR}","$MAIL_FILE"" \ $EMAIL_STRING & ROOT_TAIL_PID=$! return } # end of start_root-tail function kill_root-tail { # ----------------------------------------------------------------------- # Function to kill the root-tail instance started by function # "start_root-tail" # No arguments # ----------------------------------------------------------------------- if [[ ${ROOT_TAIL_PID} != "" ]]; then kill "${ROOT_TAIL_PID}" sleep 3 kill -9 "${ROOT_TAIL_PID}" fi return } # end of kill_root-tail function start_terminal { # ----------------------------------------------------------------------- # Function to start terminal with correct parameters # No arguments # ----------------------------------------------------------------------- if [[ $CHECK_MAIL == "true" ]]; then EMAIL_STRING="${TEMP_FILE1}" else EMAIL_STRING="" fi $TERMINAL_BIN +sb -title "${PROGNAME}" -fn "${FONT_SIZE}" \ -g "${DEFAULT_TERMINAL_SIZE}${DEFAULT_TERMINAL_POSITION}" \ -e bash -c "${NICE_CALL} ${TAIL_BIN} -F -s ${TAIL_TIMEOUT} \ ${MESSAGES_FILE} ${MAIL_FILE} ${EMAIL_STRING} | \ ${NICE_CALL} ${CCZE_BIN} --" & TAIL_PID=$! return } # end of start_terminal function kill_terminal { # ----------------------------------------------------------------------- # Function to kill the terminal instance started by function # "start_terminal" # No arguments # ----------------------------------------------------------------------- if [[ ${TAIL_PID} != "" ]]; then kill "${TAIL_PID}" sleep 3 kill -9 "${TAIL_PID}" fi return } # end of kill_terminal # ------------------------------------------------------------------- # Program starts here # ------------------------------------------------------------------- ##### Initialization And Setup ##### # Set file creation mask so that all files are created with 600 permissions. umask 066 root_check # Trap TERM, HUP, and INT signals and properly exit trap "signal_exit TERM" TERM HUP trap "signal_exit INT" INT # Create temporary file(s) make_temp_files ##### Command Line Processing ##### if [ "$1" = "--help" ]; then helptext graceful_exit fi while getopts ":hu:rt" opt; do case $opt in r ) ROOT_OUTPUT="true" ;; t ) TERMINAL_OUTPUT="true" ;; u ) ROOT_USER="$OPTARG" ;; h ) helptext graceful_exit ;; * ) usage clean_up exit 1 esac done ##### Main Logic ##### # Initialisation ROOT_TAIL_PID="" # pid of running root-tail TAIL_PID="" # pid of running tail MAIL_UPDATE="" # true if one of the mail files has changed TIMESTAMP_ROOT="" # modification time of root's mail file TIMESTAMP_USER="" # modification time of root users's mail file MAIL_UPDATE="" # true if new mail has arrived since last check if [[ $ROOT_USER == "" ]]; then ROOT_USER=${DEFAULT_ROOT_USER} fi # check for root's mail file if [ -e "$MAIL_FILE_DIR/root" ]; then CHECK_ROOT="true" echo "Checking emails for root ..." >> ${TEMP_FILE1} grep_from_and_subject_from_mail "root" else CHECK_ROOT="" fi # check for root's normal user account mail file if [ -e "$MAIL_FILE_DIR/$ROOT_USER" ]; then CHECK_USER="true" echo "Checking emails for $ROOT_USER ..." >> ${TEMP_FILE1} grep_from_and_subject_from_mail "${ROOT_USER}" else CHECK_USER="" fi # check if checking of mails is necessary if [[ ${CHECK_ROOT} == "true" || ${CHECK_USER} == "true" ]]; then CHECK_MAIL="true" timestamp_mail_files else CHECK_MAIL="" fi # finally start displaying output via root-tail or in a terminal if [[ ${TERMINAL_OUTPUT} == "true" ]]; then start_terminal fi # select at least one method of displaying data if [[ ${ROOT_OUTPUT} == "true" || ${TERMINAL_OUTPUT} == "" ]]; then start_root-tail fi # loop to update emails if necessary if [[ $CHECK_MAIL == "true" ]]; then while [ 1 ]; do sleep ${MAIL_CHECK_TIMEOUT} check_for_new_mails if [[ ${MAIL_UPDATE} == "true" ]]; then echo "Checking emails ..." > ${TEMP_FILE1} sleep ${ROOT_TAIL_TIMEOUT} # give root-tail time # to update if [[ $CHECK_ROOT == "true" ]]; then grep_from_and_subject_from_mail root fi if [[ $CHECK_USER == "true" ]]; then grep_from_and_subject_from_mail "$ROOT_USER" fi MAIL_UPDATE="" fi done else wait fi graceful_exit