#!/bin/bash
##
## OpenLDAP: Run slapd with parameters via environment variables
## Copyright (c) 2019 SATOH Fumiyasu @ OSS Technology Corp., Japan
##
## License: GNU General Public License version 3
##

set -u

if [[ -n ${JOURNAL_STREAM-} || $PPID -eq 1 ]]; then
  PNAME=""
else
  PNAME="$0"
fi

run() {
  if [[ -n ${SLAPD_RUN_INFO-set} ]]; then
    echo "${PNAME:+$PNAME: }INFO: Run: $*" >&2
  fi
  "$@"
}

run_or_die() {
  run "$@" || exit $?
}

debug() {
  sed "s#^#${PNAME:+$PNAME: }DEBUG: #" >&2
}

warn() {
  echo "${PNAME:+$PNAME: }WARNING: $*" >&2
}

envdir() {
  local envdir="$1"; shift
  local envfile envname

  for envfile in "$envdir"/*; do
    [[ -f $envfile ]] || continue
    envname="${envfile##*/}"
    [[ $envname =~ ^[A-Za-z_][A-Za-z_0-9]*$ ]] || continue
    if [[ -s $envfile ]]; then
      ## Prefer external environment variables to envdir
      if eval '[[ -z ${'"$envname"'+set} ]]'; then
	IFS= read -r "$envname" <"$envfile" || return $?
	export "$envname"
      fi
    else
      unset "$envname"
    fi
  done

  return 0
}

## Backward compatibility for the old envdir (slapd-svconf for daemontools)
ulimit() {
  if [[ $# -le 1 ]]; then
    builtin ulimit "$@"
    return
  fi

  local resource="$1"; shift
  local limit="$1"; shift

  if [[ $limit == = ]]; then
    limit=$(builtin ulimit -H "$resource")
  fi
  builtin ulimit "$resource" "$limit"
}

if [[ -n ${SLAPD_RUN_DEBUG-} ]]; then
  PS4="${PNAME:+$PNAME: }DEBUG: "
  set -x
fi

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

envdir="${SLAPD_RUN_ENVDIR-/opt/osstech/etc/openldap/service/slapd/env}"

if [[ -n $envdir ]]; then
  run_or_die envdir "$envdir"

  if [[ -n ${SLAPD_SYSLOG_SOCKET_PATH-} && ! -S $SLAPD_SYSLOG_SOCKET_PATH ]]; then
    warn "No syslog socket at SLAPD_SYSLOG_SOCKET_PATH environment: $SLAPD_SYSLOG_SOCKET_PATH"
    unset SLAPD_SYSLOG_SOCKET_PATH
  fi

  ## Backward compatibility for the old envdir (slapd-svconf for daemontools)
  [[ -n ${WORKINGDIR-} ]] && export SLAPD_WORKINGDIR="$WORKINGDIR"
  [[ -n ${COMMAND-} ]] && export SLAPD_COMMAND="$COMMAND"
  [[ -n ${CONFIGFILE-} ]] && export SLAPD_CONF="$CONFIGFILE"
  [[ -n ${SERVICES-} ]] && export SLAPD_SERVICES="$SERVICES"
  [[ -n ${DEBUGLEVEL-} ]] && export SLAPD_DEBUG_LEVEL="$DEBUGLEVEL"
  [[ -n ${SYSLOGLEVEL-} ]] && export SLAPD_SYSLOG_LEVEL="$SYSLOGLEVEL"
  [[ -n ${SYSLOGFACILITY-} ]] && export SLAPD_SYSLOG_FACILITY="$SYSLOGFACILITY"
  [[ -n ${OPTIONS-} ]] && export SLAPD_OPTIONS="$OPTIONS"
  if [[ -n ${DEBUGGER-} ]]; then
    export SLAPD_WRAPPER_COMMAND="env"
    export SLAPD_WRAPPER_OPTIONS="$DEBUGGER"
  fi
  if [[ -n ${MEMORYLIMIT-} ]]; then
    export SLAPD_LIMIT_DATA="$MEMORYLIMIT"
    export SLAPD_LIMIT_STACK="$MEMORYLIMIT"
    export SLAPD_LIMIT_MEMLOCK="$MEMORYLIMIT"
    export SLAPD_LIMIT_AS="$MEMORYLIMIT"
  fi
  [[ -n ${DATALIMIT-} ]] && export SLAPD_LIMIT_DATA="$DATALIMIT"
  [[ -n ${STACKLIMIT-} ]] && export SLAPD_LIMIT_STACK="$STACKLIMIT"
  [[ -n ${OPENFILELIMIT-} ]] && export SLAPD_LIMIT_NOFILE="$OPENFILELIMIT"
  [[ -n ${COREFILELIMIT-} ]] && export SLAPD_LIMIT_CORE="$COREFILELIMIT"
fi

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

${SLAPD_RUN_PRE:+run_or_die source "$SLAPD_RUN_PRE"}

## ----------------------------------------------------------------------

command_default="/opt/osstech/sbin/slapd"
config_default="/opt/osstech/etc/openldap/slapd.conf"
user_default="ldap"
ldapi_service_default="ldapi:///"
services_default="ldap:/// ldaps:///"
debug_level_default="none"

config="${SLAPD_CONF:-$config_default}"
if [[ -d $config ]]; then
  config_opts=(-F "$config")
else
  config_opts=(-f "$config")
fi

## ----------------------------------------------------------------------

SLAPD_RUN_ARGS=(
  ${SLAPD_NO_RUN:+true}
  ${SLAPD_NICE:+nice -n "$SLAPD_NICE"}
  ${SLAPD_IONICE:+ionice ${SLAPD_IONICE_CLASS:+-c "$SLAPD_IONICE_CLASS"} -n "$SLAPD_IONICE"}
  ${SLAPD_WRAPPER_COMMAND:+"$SLAPD_WRAPPER_COMMAND" ${SLAPD_WRAPPER_OPTIONS-}}
  "${SLAPD_COMMAND:-$command_default}"
  -d "${SLAPD_DEBUG_LEVEL:-$debug_level_default}"
  "${config_opts[@]}"
  -u "${SLAPD_USER:-$user_default}"
  ${SLAPD_GROUP:+-g "$SLAPD_GROUP"}
  -h "${SLAPD_LDAPI_SERVICE:-$ldapi_service_default} ${SLAPD_SERVICES:-$services_default}"
  ${SLAPD_SYSLOG_LEVEL:+-s "$SLAPD_SYSLOG_LEVEL"}
  ${SLAPD_SYSLOG_FACILITY:+-l "$SLAPD_SYSLOG_FACILITY"}
  ${SLAPD_OPTIONS-}
)

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

${SLAPD_UMASK:+run_or_die umask "$SLAPD_UMASK"}
${SLAPD_WORKINGDIR:+run_or_die cd "$SLAPD_WORKINGDIR"}

## Seconds
${SLAPD_LIMIT_CPU:+run_or_die ulimit -t "$SLAPD_LIMIT_CPU"}
## Bytes
${SLAPD_LIMIT_FSIZE:+run_or_die ulimit -f "$SLAPD_LIMIT_FSIZE"}
## Bytes
${SLAPD_LIMIT_DATA:+run_or_die ulimit -d "$SLAPD_LIMIT_DATA"}
## Bytes
${SLAPD_LIMIT_STACK:+run_or_die ulimit -s "$SLAPD_LIMIT_STACK"}
## Bytes
${SLAPD_LIMIT_CORE:+run_or_die ulimit -c "$SLAPD_LIMIT_CORE"}
## Bytes
${SLAPD_LIMIT_RSS:+run_or_die ulimit -m "$SLAPD_LIMIT_RSS"}
## Number of File
${SLAPD_LIMIT_NOFILE:+run_or_die ulimit -n "$SLAPD_LIMIT_NOFILE"}
## Bytes
${SLAPD_LIMIT_AS:+run_or_die ulimit -v "$SLAPD_LIMIT_AS"}
## Number of Processes
${SLAPD_LIMIT_NPROC:+run_or_die ulimit -u "$SLAPD_LIMIT_NPROC"}
## Bytes
${SLAPD_LIMIT_MEMLOCK:+run_or_die ulimit -l "$SLAPD_LIMIT_MEMLOCK"}
## Number of Locks
${SLAPD_LIMIT_LOCKS:+run_or_die ulimit -x "$SLAPD_LIMIT_LOCKS"}
## Number of Queued Signals
${SLAPD_LIMIT_SIGPENDING:+run_or_die ulimit -i "$SLAPD_LIMIT_SIGPENDING"}
## Bytes
${SLAPD_LIMIT_MSGQUEUE:+run_or_die ulimit -q "$SLAPD_LIMIT_MSGQUEUE"}
## Nice Level
${SLAPD_LIMIT_NICE:+run_or_die ulimit -e "$SLAPD_LIMIT_NICE"}
## Realtime Priority
${SLAPD_LIMIT_RTPRIO:+run_or_die ulimit -r "$SLAPD_LIMIT_RTPRIO"}

${SLAPD_RUN_POST:+run_or_die source "$SLAPD_RUN_POST"}

if [[ -n ${SLAPD_RUN_DEBUG-} ]]; then
  { umask; pwd; ulimit -a; env; } |debug
fi

run_or_die exec "${SLAPD_RUN_ARGS[@]}"
