#!/bin/sh
#
# Shared routines for Google utility scripts.
#
# Copyright 2008 Google Inc. All Rights Reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
#   notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
#   copyright notice, this list of conditions and the following disclaimer
#   in the documentation and/or other materials provided with the
#   distribution.
# * Neither the name of Google Inc. nor the names of its
#   contributors may be used to endorse or promote products derived from
#   this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

DRYRUN=
DRYMSG=""

enable_dry_run() {
  DRYRUN=1
  DRYMSG="DRY RUN "
}

GUIMSG=true

enable_gui_output() {
  if [ "$DISPLAY" ]; then
    type xmessage > /dev/null 2>&1 && GUIMSG=xmessage
    type gmessage > /dev/null 2>&1 && GUIMSG=gmessage
    type kmessage > /dev/null 2>&1 && GUIMSG=kmessage
  fi
}

close_progress() {
  if [ $PROGRESSPID ]; then
    kill $PROGRESSPID > /dev/null 2>&1
  fi
  unset PROGRESSPID
}

splash_on() {
  if [ -n "$SPLASH_PID" ]; then
    kill -10 "$SPLASH_PID" > /dev/null 2>&1
  fi
}

splash_off() {
  if [ -n "$SPLASH_PID" ]; then
    kill -12 "$SPLASH_PID" > /dev/null 2>&1
  fi
}

prompt_err() {
  splash_off
  close_progress
  echo "${DRYMSG}ERROR: $@"
  $GUIMSG -center -buttons "    OK    " -title "Error" "$@"
  rc=$?
  splash_on
  return $rc
}

prompt_info() {
  splash_off
  close_progress
  echo "${DRYMSG}INFO: $@"
  $GUIMSG -center -buttons "    OK    " -title "Information" "$@"
  rc=$?
  splash_on
  return $rc
}

_prompt_yesno() {
  local TITLE="$1"
  shift
  splash_off
  close_progress
  echo "$@"
  if [ "$DISPLAY" ]; then
    $GUIMSG -center -buttons "    Yes    ":0,"    No    ":1 -default "    Yes    " -title "$TITLE" "$@"
    rc=$?
    splash_on
    return $rc # 0-Yes, 1-No
  fi
  while [ "$YNREAD" != "n" ] &&
        [ "$YNREAD" != "N" ] &&
        [ "$YNREAD" != "y" ] &&
        [ "$YNREAD" != "Y" ]; do
    read -p "Select (Y)es/(N)o?: " YNREAD
    if [ "$YNREAD" = "y" ] || [ "$YNREAD" = "Y" ]; then
      splash_on
      return 0
    elif [ "$YNREAD" = "n" ] || [ "$YNREAD" = "N" ]; then
      splash_on
      return 1
    fi
  done
}

prompt_yesno() {
  _prompt_yesno "Warning" "$@"
}

prompt_info_yesno() {
  _prompt_yesno "Information" "$@"
}

prompt_yesno_never() {
  splash_off
  close_progress
  echo "$@"
  if [ "$DISPLAY" ]; then
    $GUIMSG -center -buttons "    Yes    ":0,"    No    ":1," No don't ask again ":2 \
    -default "    Yes    " -title "Warning" "$@"
    rc=$?
    splash_on
    return $rc # 0-Yes, 1-No
  fi
  while [ "$YNREAD" != "n" ] &&
        [ "$YNREAD" != "N" ] &&
        [ "$YNREAD" != "d" ] &&
        [ "$YNREAD" != "D" ] &&
        [ "$YNREAD" != "y" ] &&
        [ "$YNREAD" != "Y" ]; do
    read -p "Select (Y)es/(N)o/(D)on't ask again?: " YNREAD
    if [ "$YNREAD" = "y" ] || [ "$YNREAD" = "Y" ]; then
      splash_on
      return 0
    elif [ "$YNREAD" = "n" ] || [ "$YNREAD" = "N" ]; then
      splash_on
      return 1
    elif [ "$YNREAD" = "d" ] || [ "$YNREAD" = "D" ]; then
      splash_on
      return 2
    fi
  done
}

prompt_continue() {
  splash_off
  close_progress
  echo "$@"
  if [ "$DISPLAY" ]; then
    $GUIMSG -center -buttons "    Continue    ":0,"    Quit    ":1 -title "Warning" "$@"
    rc=$?
    splash_on
    return $rc # 0-Continue, 1-Quit
  fi
  while [ "$YNREAD" != "c" ] &&
        [ "$YNREAD" != "C" ] &&
        [ "$YNREAD" != "q" ] &&
        [ "$YNREAD" != "Q" ]; do
    read -p "Select (C)ontinue/(Q)uit?: " YNREAD
    if [ "$YNREAD" = "c" ] || [ "$YNREAD" = "C" ]; then
      splash_on
      return 0
    elif [ "$YNREAD" = "q" ] || [ "$YNREAD" = "Q" ]; then
      splash_on
      return 1
    fi
  done
}

prompt_progress() {
  splash_off
  close_progress
  echo "$@"
  $GUIMSG -center -buttons "" -title "Working..." "$@" &
  rc=$?
  PROGRESSPID=$!
  splash_on
  return $rc
}

prep_fetch() {
  if [ "$FETCHPROG" ]; then
    return 0;
  fi

  FETCHCOMMANDS="curl wget w3m"
  for FETCHPROG in $FETCHCOMMANDS; do
    if [ "$(which $FETCHPROG 2>/dev/null)" ]; then
      break
    fi
    unset FETCHPROG
  done

  if [ ! "$FETCHPROG" ] ; then
    prompt_err "Couldn't find a program to use to download files.
  Please install one of the following programs:
  $FETCHCOMMANDS"
    return 1
  fi
}

do_fetch() {
  URL="$1"
  SAVEFILE="$2"

  if [ ! "$FETCHPROG" ]; then
    prep_fetch
  fi

  prompt_progress "Fetching '$URL'."

  # Don't actually download anything for a dry run.
  if [ $DRYRUN ]; then
    return 0
  fi

  case $FETCHPROG in
    curl )
      HTTPCODE=$(curl -w "%{http_code}" -s "$URL" -o "$SAVEFILE")
      ;;
    wget )
      HTTPCODE=$(wget --server-response -O "$SAVEFILE" "$URL" 2>&1 | sed -e '/HTTP\/1/!d;s#.*HTTP/... \([0-9]\+\) .*#\1#')
      ;;
    w3m )
      HTTPCODE=$(w3m -dump_head "$URL" | sed -e '/HTTP\/1/!d;s#.*HTTP/... \([0-9]\+\) .*#\1#')
      w3m -dump_source "$URL" > "$SAVEFILE"
      ;;
    * )
      prompt_err "Unknown fetch command '$FETCHPROG'."
      return 1
      ;;
  esac

  if [ "$HTTPCODE" -ne "200" ] || [ ! -f "$SAVEFILE" ]; then
    prompt_err "Failed to download from $URL"
    return 1
  fi
}

guess_distro() {
  if [ "$DISTRO" ]; then
    return 0
  fi

  if [ -f /etc/lsb-release ]; then
    eval $(sed -e '/DISTRIB_ID/!d' /etc/lsb-release)
    if [ "$DISTRIB_ID" ]; then
      case $DISTRIB_ID in
      *buntu)
        DISTRO=Ubuntu
        ;;
      Mandriva*)
        DISTRO=Mandriva
        ;;
      * )
        # TODO Update as necessary to canonicalize values used by other distros.
        DISTRO="$DISTRIB_ID"
        ;;
      esac
      return 0
    fi
  fi

  if [ -f /etc/debian_release ] || [ -f /etc/debian_version ]; then
    DISTRO=Debian
    return 0
  fi

  if [ -f /etc/fedora-release ]; then
    DISTRO=Fedora
    return 0
  fi

  if [ -f /etc/SuSE-release ]; then
    DISTRO=Suse
    return 0
  fi

  if [ -f /etc/mandriva-release ]; then
    DISTRO=Mandriva
    return 0
  fi

  if [ -f /etc/redhat-release ] || [ -f /etc/redhat_version ]; then
    rpm -q yum > /dev/null 2>&1
    if [ $? -eq 0 ] ; then
      DISTRO=RHEL
    else
      DISTRO=Redhat
    fi
    return 0
  fi

  return 1
}

run_as_root() {
  ROOTCMD=$1
  shift
  local ARGS=""
  while [ $# -gt 0 ]; do
    ARGS="$ARGS\"$1\" "
    shift
  done

  if [ `id -u` != '0' ]; then
    sleep 1
    splash_off
    SAVE_SPLASH_PID="$SPLASH_PID"
    unset SPLASH_PID
GETROOTMSG="
The following command requires root privileges:
$ROOTCMD $ARGS
"

    # Only run GUI tools if we're in X.
    if [ "$DISPLAY" ]; then
      ROOTPRG=$(which gksu 2>/dev/null)
      if [ "$ROOTPRG" ]; then
        prompt_progress "${GETROOTMSG}Trying 'gksu'. Enter your password if prompted."
        # NOTE - gksu is supposed to return non-zero if it fails or is cancelled,
        # but it seems to always return 0 unless the password is wrong, so we
        # have to jump through some hoops to see if the command actually runs.
        # We'll put the command in a temp file that deletes itself on run.
        # If the temp file is gone, we'll assume it ran.
        GKSUSTAT=$(mktemp)
        echo "$ROOTCMD $ARGS" >> $GKSUSTAT
        echo "rm '$GKSUSTAT'" >> $GKSUSTAT
        prompt_progress "Running '$ROOTCMD $ARGS'."
        $ROOTPRG sh $GKSUSTAT
        if [ $? -eq 0 ] && [ ! -f "$GKSUSTAT" ]; then
          SPLASH_PID="$SAVE_SPLASH_PID"
          splash_on
          return 0
        fi
      fi
    fi

    # Only run command-line tools if we're in a terminal.
    if [ "$TERM" ] && [ "$TERM" != "dumb" ]; then
      # Temporarily disable GUI output so dialogs don't take focus away from
      # the terminal, which is where the user needs to enter the password.
      SAVE_GUIMSG=$GUIMSG
      GUIMSG=true

      ROOTPRG=$(which sudo 2>/dev/null)
      if [ "$ROOTPRG" ]; then
        prompt_progress "${GETROOTMSG}Trying 'sudo'. Enter your password if prompted."
        eval $ROOTPRG $ROOTCMD $ARGS
        if [ $? -eq 0 ]; then
          GUIMSG=$SAVE_GUIMSG
          SPLASH_PID="$SAVE_SPLASH_PID"
          splash_on
          return 0
        fi
      fi

      prompt_progress "${GETROOTMSG}Trying 'su'. Enter root's password when prompted."
      su root -c "$ROOTCMD $ARGS"
      if [ $? -eq 0 ]; then
        GUIMSG=$SAVE_GUIMSG
        SPLASH_PID="$SAVE_SPLASH_PID"
        splash_on
        return 0
      fi

      GUIMSG=$SAVE_GUIMSG
    fi

    SPLASH_PID="$SAVE_SPLASH_PID"
    echo
    prompt_err "Could not run '$ROOTCMD' as root.
Please re-run from a root login."
    return 1
  else
    eval $ROOTCMD $ARGS
  fi
}

