#!/bin/bash
#< Compress old syslogs (or compress anything really...)

BASENAME="/bin/basename"
BZIP2="/usr/bin/bzip2"
ECHO="/bin/echo"
EGREP="/bin/egrep"
FIND="/usr/bin/find"
GZIP="/bin/gzip"
ID="/usr/bin/id"

THISPROG=$( ${BASENAME} $0 )

VERBOSE=0

function print_error {
   ${ECHO} "Error: $@" >&2
}

function printv {
   (( VERBOSE )) && {
      ${ECHO} "--> $@"
   }
}

function print_usage {
   {
      ${ECHO} "Usage: ${THISPROG} [-bghv] {-m <n>|-a <n>} path [path1..[pathn]]"   
      ${ECHO} "       -a   Compress logs accessed more than <n> days ago"
      ${ECHO} "       -b   Use bzip compression"
      ${ECHO} "       -g   Use gzip compression"
      ${ECHO} "       -h   Display this usage message"
      ${ECHO} "       -m   Compress logs modified more than <n> days ago"
      ${ECHO} "       -v   Verbose mode"
   } >&2
}

function check_user {
   CURRENT_EUID=$( ${ID} -u )
   if [ "${CURRENT_EUID}" -ne "0" ]; then
      print_error "This script must be run as root"
      exit 1
   fi
}

function check_arguments {
   # 
   # Check for mandatory arguments
   #
   COMPRESS=0
   if [ -n "${BZIP_FLAG}" ]; then
      (( COMPRESS = COMPRESS + 1 ))
   fi
   if [ -n "${GZIP_FLAG}" ]; then
      (( COMPRESS = COMPRESS + 1 ))
   fi
   if [ "${COMPRESS}" -ne "1" ]; then
      print_error "Exactly one of [-b|-g] must be specified"
      exit 1
   fi
   FIND_TIME=0
   if [ -n "${ATIME}" ]; then
      (( FIND_TIME = FIND_TIME + 1 ))
   fi
   if [ -n "${MTIME}" ]; then
      (( FIND_TIME = FIND_TIME + 1 ))
   fi
   if [ "${FIND_TIME}" -ne "1" ]; then
      print_error "Exactly one of [-a|-m] must be specified"
   fi

   #
   # Check that numeric arguments have been passed
   #
   if [ -n "${ATIME}" ]; then
      ${ECHO} "${ATIME}" | ${EGREP} -q '^[0-9]+$' 
      if [ "$?" -ne "0" ]; then
         print_error "Number of days must be expressed as an integer"
         exit 1
      fi
   fi
   if [ -n "${MTIME}" ]; then
      ${ECHO} "${MTIME}" | ${EGREP} -q '^[0-9]+$' 
      if [ "$?" -ne "0" ]; then
         print_error "Number of days must be expressed as an integer"
         exit 1
      fi
   fi
}

function check_paths {
   ERROR_COUNT=0
   for EACHPATH in ${PATHS}; do
      printv "Checking ${EACHPATH}"
      if [ ! -d "${EACHPATH}" ]; then
         print_error "${EACHPATH} is not a directory"
         (( ERROR_COUNT = ERROR_COUNT + 1 ))
      fi
   done
   if [ "${ERROR_COUNT}" -gt "0" ]; then
      exit 1
   fi
}

function perform_compression {
   for COMPRESS_PATH in ${PATHS}; do
      if [ -n "${ATIME}" ]; then
         ${FIND} ${COMPRESS_PATH} -type f -atime +${ATIME} \( ! -name "*.bz2" -a ! -name "*.gz" \) -mount |\
            while read COMPRESS_ME; do
               if [ -n "${BZIP_FLAG}" ]; then
                  ${BZIP2} -9 ${COMPRESS_ME}
               elif [ -n "${GZIP_FLAG}" ]; then
                  ${GZIP} -9 ${COMPRESS_ME}
               fi
            done
      elif [ -n "${MTIME}" ]; then
         ${FIND} ${COMPRESS_PATH} -type f -mtime +${MTIME} \( ! -name "*.bz2" -a ! -name "*.gz" \) -mount |\
            while read COMPRESS_ME; do
               if [ -n "${BZIP_FLAG}" ]; then
                  ${BZIP2} -9 ${COMPRESS_ME}
               elif [ -n "${GZIP_FLAG}" ]; then
                  ${GZIP} -9 ${COMPRESS_ME}
               fi
            done
      fi
   done
}

#
# main()
#
while getopts ":a:m:bghv" OPTION; do
  case ${OPTION} in
     "a")  ATIME="${OPTARG}"       ;;
     "m")  MTIME="${OPTARG}"       ;;
     "b")  BZIP_FLAG=1             ;;
     "g")  GZIP_FLAG=1             ;;
     "h")  print_usage && exit 0   ;;
     "v")  VERBOSE=1               ;;
     *  )  print_usage && exit 1   ;;
  esac
done

shift $(( ${OPTIND} - 1 ))

if [ "$#" -eq "0" ]; then
   print_usage && exit 1
fi

PATHS="$@"

check_user
check_arguments
check_paths
perform_compression

exit 0