#!/bin/sh

# Bird - dynamic IP routing daemon

# Turn of auto expansion
set -f

alterator_api_version=1
po_domain="alterator-bird"

# libshell
# set `verbose' to get debug output for `alterator -l -d'
verbose=
. shell-error
. shell-quote


v() {
  verbose "__DEBUG__" $@
}


readonly SERVICE_BIRD="bird"
readonly BIRD_CFG="/etc/bird.conf"


. alterator-sh-functions
. shell-ini-config
. alterator-service-functions
. alterator-postfix-dovecot-functions
. shell-config


readonly msg_no="`_ 'No'`"
readonly msg_yes="`_ 'Yes'`"


# HELPER TO DISPLAY DEBUG DATA IN FRONTEND IN ONE LINE
print_info() {
  echo ' '
  echo "# $@"
  $@ 2>&1
  echo ' '
}


# WRITE ANY DEBUG INFORMATION TO FRONTEND
write_debug_info() {
  local info=

  info="${info}$(print_info "lsof -a -c "$SERVICE_BIRD" -U")"
  info="${info}$(print_info "lsof -c "$SERVICE_BIRD" -t")"
  write_string_param "information" "$info"
}


# PRING STATUS ON/OFF
print_status() {
  v "print_status() -- enter"

  local mode_str="`_ 'OFF'`"
  local mode="off"
  local autostart=

  if service_control "$SERVICE_BIRD" "is-enabled"; then
    v "$SERVICE_BIRD - start on boot"
    autostart="true"
  else
    v "$SERVICE_BIRD - do not start on boot"
    autostart="false"
  fi

  v "print_status() -- autostart: $autostart"

  if service_control "$SERVICE_BIRD" "is-active"; then
    v "$SERVICE_BIRD - is active."
    mode="on"
    mode_str="`_ 'ON'`"
  fi

  write_string_param "label_status" "$mode_str"
  write_string_param "current_status" "$mode"
  write_bool_param "chkbox_autostart" "$autostart"
}


# PRINT CONFIG
print_config() {
  v "print_config() -- enter"

  local contents=

  if [ -r "$BIRD_CFG" ]; then
    contents="$(cat "$BIRD_CFG")"
  fi

  # quote_shell_variable contents "$contents"
  write_string_param "config" "$contents"
}


# DEACTIVATE BIRD SERVICE
do_deactivate() {
  v "do_deactivate() -- enter"

  if service_control "$SERVICE_BIRD" "is-active"; then
    service_control "$SERVICE_BIRD" "stop"
  fi
}

# DEACTIVATE BIRD SERVICE
do_activate() {
  v "do_activate() -- enter"

  if ! service_control "$SERVICE_BIRD" "is-active"; then
    service_start_wait "$SERVICE_BIRD" "start"
  fi
}

# DUMP CONFIG, USED TO SAVE FILE TO LOCAL COMPUTER
dump_config() {
  v "dump_config() -- enter"

  if ! [ -e "$BIRD_CFG" ]; then
    v "dump_config() -- can't find $BIRD_CFG"
    write_error "`_ "Can't find $BIRD_CFG"`"
    return
  fi

  cat "$BIRD_CFG" | write_blob_param "config"
}


# SAVE MODIFIED CONFIG
do_save() {
  v "do_save() -- enter"

  if ! [ -n "$in_config" ]; then
    v "do_save() -- empty request"
    return
  fi

  local tmp="$(mktemp "Bird test new config file.XXX")"

  v "do_save() -- create tmp file $tmp"

  if [ -z "$tmp" ]; then
    v "do_save() - unable to create temp file $tmp"
    return
  fi

  echo "$in_config" > "$tmp"

  local msg=

  if ! msg="$(bird -p -c "$tmp" 2>&1)"; then
    v "do_save() - bad config"
    write_error "$msg"
    return
  fi

  v "do_save() - $tmp - Modified config checked."

  if ! mv -f "$tmp" "$BIRD_CFG"; then
    v "do_save() - can't rewrite $BIRD_CFG"
    rm -f "$tmp"
    return
  fi

  v "do_save() - new config installed."

  if service_control "$SERVICE_BIRD" "is-active"; then
    v "do_save() - restart $SERVICE_BIRD service."
    service_start_wait "$SERVICE_BIRD" "restart"
  fi
}


# INSTALL NEW UPLOADED CONFIG
install_config() {

  v "install_config() - enter"

  if ! [ -r "$in_path_cfg" ]; then
    write_error "$msg"
    v "Can't process "
    write_error "`_ "Can't install new config"`"
    return
  fi

  local msg=
  if ! msg="$(bird -p -c "$in_path_cfg" 2>&1)"; then
    v "install_config() - $in_path_cfg bad config"
    write_error "$msg"
    return
  fi

  v "install_config() - $in_path_cfg checked."

  if ! mv -f "$in_path_cfg" "$BIRD_CFG"; then
    v "install_config() - can't rewrite $BIRD_CFG"
    rm -f "$in_path_cfg"
    return
  fi

  v "install_config() - new config was installed"

  return 0
}


# SHOW BIRD ROUTING DAEMON STATUS
list_status() {
  v "list_status() -- enter"

  local cmds=()
  cmds=( "${cmds[@]}" "show interfaces" )
  cmds=( "${cmds[@]}" "show memory" )
  cmds=( "${cmds[@]}" "show bfd sessions" )
  cmds=( "${cmds[@]}" "show ospf" )
  cmds=( "${cmds[@]}" "show protocols all" )
  cmds=( "${cmds[@]}" "show static" )
  local result=

  if ! service_control "$SERVICE_BIRD" "is-active"; then
    v "$SERVICE_BIRD - is inactive"
    return
  fi

  for cmd in "${cmds[@]}"; do
    # do not use `birdc' command, it uses readline, which is incompatible with sed
    result="$(echo "$cmd" | birdcl | sed -n -e '/bird>/,/bird>/{/bird>/b;p}')"
    write_table_item "label_status_name" "$cmd" "label_status_info" ""
    result="${result:-n/a}"
    write_table_item "label_status_name" "" "label_status_info" "$result"
  done
}

# CHANGE BOOT BEHAVIOR
change_bootstart()
{
  if [ -z "$in_onoff" ]; then
    v "config_ifaces_change() -- bad call, lack of arguments"
    return
  fi

  local mode=
  if test_bool "$in_onoff"; then
    mode="enable"
  else
    mode="disable"
  fi

  v "$SERVICE_BIRD - set to $mode"
  service_control "$SERVICE_BIRD" "$mode"
}



# MAIN LOOP
on_message() {
  case "$in_action" in

    dump_config)
      v "dump config request"
      dump_config

      ;;

    newconfig)
      v "new config request"
      install_config

      ;;

    read)
      write_debug_info

      case "$in__objects" in
        status)
          # READ STATUS
          v "read status"
          print_status
          print_config

          ;;

        *)
          # UNDEFINED READ REQUEST
          v "undefined read request: $in__objects" 1>&2

          ;;
      esac
      ;;

    write)

      case "$in__objects" in
        valid_cfg)
          # CHECK CONFIGURATION
          v "write request: check config"
          do_check_cfg

          ;;

        save)
          # SAVE CONFIG & RUN
          v "write request: save"
          do_save

          ;;

        off)
          # TURN OFF
          v "write request: off"
          do_deactivate

          ;;

        on)
          # TURN ON
          v "write request: on"
          do_activate

          ;;

        *)
          # UNDEFINED WRITE REQUEST
          v "undefined write request: $in__objects" 1>&2

          ;;

      esac
      ;;

    list)

      case "$in__objects" in

        list_status)
          # LIST ON/OFF BIRD SERVICE
          v "list configuration status"
          list_status

          ;;

        *)
          # UNDEFINED LIST REQUEST
          v "undefined list request: $in__objects" 1>&2

          ;;

      esac
      ;;

    *)
      # UNDEFINED ACTION
      :
      ;;
  esac
}

alterator_export_proc change_bootstart

message_loop

# vim: autoindent tabstop=2 shiftwidth=2 expandtab softtabstop=2 filetype=sh
