#!/bin/ksh
##
## daemontools: add/remove a service to/from system-wide service supervision
## Copyright (c) 2008-2010 SATOH Fumiyasu @ OSS Technology, Inc.
##               <http://www.osstech.co.jp/>
##
## License: GNU General Public Lisence version 2 or later
## Date: 2010-04-06, since 2008-04-24
##

set -u
umask 0022

PATH="/opt/osstech/bin:/opt/osstech/sbin:/bin:/sbin:/usr/bin:/usr/sbin"
export PATH

perr() {
  echo "$0: ERROR: $*" 1>&2
}

pdie() {
  perr "$*"
  exit 1
}

if type readlink >/dev/null 2>&1; then
  : OK
elif type perl >/dev/null 2>&1; then
  readlink() { perl -e 'print readlink($ARGV[0]),"\n"' "$@"; }
elif type python >/dev/null 2>&1; then
  readlink() { python -c 'import os;import sys;print os.readlink(sys.argv[1])' "$@"; }
else
  pdie "readlink command not found"
fi

## ======================================================================

svscan_dir="${SVSCAN_DIR:-/opt/osstech/etc/svscan}"

cmd_usage="\
Usage: $0 --add|--remove SVDIR [SVNAME]
       $0 --list [SVNAME]

Options:
  --add
    Add a service directory to the system-wide service supervision
  --remove
    Remove a service directory from the system-wide service supervision
  --list
    Print the service names of all system-widely registered services

Argument:
  SVDIR
    Service directory
  SVNAME
    Service name (default: basename of SVDIR)
"

## ======================================================================

[ $# -ge 1 ] || { echo "$cmd_usage"; exit 1; }
opt="$1"; shift

cd "$svscan_dir" || pdie "Cannot change working directory: $svscan_dir"

case "$opt" in
-l|--list)
  sv_name="${1:-}"
  if [ -z "$sv_name" ]; then
    find . -name . -o -type d -prune -o -type l ! -name ".*" -print |sed 's|^\./||'
    exit 0
  fi
  test -h "$sv_name" || pdie "Service not registered: $sv_name"
  echo "$sv_name -> `readlink "$sv_name"`"
  exit 0
  ;;
-a|--add|-r|--remove)
  [ $# -ge 1 ] || { echo "$cmd_usage"; exit 1; }

  sv_dir="$1"; shift
  sv_name="${1:-`basename "$sv_dir"`}"
  sv_link="$svscan_dir/$sv_name"
  [ -d "$sv_dir" ] || pdie "Service directory not exist, or not a directory: $sv_dir"
  case "$sv_name" in
  .*) pdie "Service name must not start with a dot: $sv_name";;
  */*) pdie "Service name must not contain a slash: $sv_name";;
  esac

  case "$opt" in
  -a|--add)
    if [ -e "$sv_link" ]; then
      [ -h "$sv_link" ] ||
        pdie "Service link exists, but not a symbolic link: $sv_link"
      sv_dir_c="`readlink "$sv_link"`"
      [ x"$sv_dir_c" = x"$sv_dir" ] ||
        pdie "Service link exists, but point to another directory: $sv_link -> $sv_dir_c"
      echo "service already added: $sv_name"
      exit 0
    fi
    svok "$sv_dir" >/dev/null 2>&1 &&
      pdie "Service directory is currently controlled by a supervise: $sv_dir"
    ln -s "$sv_dir" "$sv_link" || pdie "Cannot add service: $sv_dir"
    exit 0
    ;;
  -r|--remove)
    sv_log_dir="$sv_dir/log"
    [ -e "$sv_link" ] ||
      pdie "Service not removed: $sv_name"
    [ -h "$sv_link" ] ||
      pdie "Service link not a symbolic link: $sv_link"
    [ x"$sv_dir" = x"`readlink "$sv_link"`" ] ||
      pdie "Service link not point to service directory: $sv_link"
    rm "$sv_link"
    if svok "$sv_dir" >/dev/null 2>&1; then
      svc -dx "$sv_dir" ||
	pdie "Cannot send down and exit commands to service: $sv_dir"
    fi
    if svok "$sv_log_dir" >/dev/null 2>&1; then
      svc -dx "$sv_log_dir" ||
	pdie "Cannot send down and exit commands to service: $sv_log_dir"
    fi
    exit 0
    ;;
  esac
  ;;
*)
  pdie "Invalid option: $opt"
  exit 1
  ;;
esac

