#!/bin/sh

# PROVIDE: samba_server
# REQUIRE: NETWORKING SERVERS DAEMON ldconfig resolv ntpd %%SAMBA4_SERVICES%%
# BEFORE: LOGIN
# KEYWORD: shutdown

# Add the following lines to /etc/rc.conf.local or /etc/rc.conf
# to enable this service:
#
#samba_server_enable=YES
#
# You can disable/enable any of the Samba daemons by specifying:
#samba_enable=NO
#nmbd_enable=NO
#smbd_enable=NO
# You need to enable winbindd separately, by adding:
#winbindd_enable=YES
# Configuration file can be set with:
#samba_server_config=%%ETCDIR%%/%%SAMBA4_CONFIG%%
#
# shellcheck disable=SC2034,SC2086,SC3043

# shellcheck source=/dev/null
. /etc/rc.subr

name=samba_server
rcvar=samba_server_enable
desc="Samba4 server startup script"

# Load configuration
load_rc_config "${name}"

# Custom commands
extra_commands="reload status configtest"

start_precmd=samba_server_prestart
restart_precmd=samba_server_checkconfig
reload_precmd=samba_server_checkconfig
start_cmd=samba_server_cmd
stop_cmd=samba_server_cmd
status_cmd=samba_server_cmd
configtest_cmd=samba_server_checkconfig
reload_cmd=samba_server_reload_cmd
rcvar_cmd=samba_server_rcvar_cmd
stop_postcmd=samba_server_poststop
# Defaults
samba_server_config_default=%%ETCDIR%%/%%SAMBA4_CONFIG%%
smbcontrol_command=%%PREFIX%%/bin/smbcontrol

samba_server_checkconfig()
{
    printf "Performing sanity check on Samba configuration: "
    if ${testparm_command} >/dev/null 2>&1; then
        echo "OK"
    else
        echo "FAILED"
        return 1
    fi
}

samba_server_prestart()
{
    samba_server_checkconfig
    # Make sure we have our RUNDIR, even if it's on a tmpfs
    if [ -d "${samba_server_piddir}" ] || [ ! -e "${samba_server_piddir}" ]; then
        install -d -m 0755 "${samba_server_piddir}"
    fi
    # https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=200186
    if [ -d "${samba_server_privatedir}" ] || [ ! -e "${samba_server_privatedir}" ]; then
        install -d -m 0700 "${samba_server_privatedir}"
    fi
    # 
    if ! df -t fdescfs -T "${samba_server_piddir}/fd" >/dev/null 2>&1; then
        install -d -m 0555 "${samba_server_piddir}/fd"
        if can_mount fdescfs; then
            mount -t fdescfs -o nodup none "${samba_server_piddir}/fd"
        else
            warn "${name}: cannot fdescfs mount to ${samba_server_piddir}/fd"
        fi
    fi
}

samba_server_poststop()
{
    if df -t fdescfs -T "${samba_server_piddir}/fd" >/dev/null 2>&1; then
        if can_mount fdescfs; then
            umount "${samba_server_piddir}/fd"
        fi
    fi
}

samba_server_rcvar_cmd()
{
    local name rcvar desc
    rcvar=${name}_enable
    # Prevent recursive calling
    unset "${rc_arg}_cmd" "${rc_arg}_precmd" "${rc_arg}_postcmd"
    # Check master variable
    run_rc_command "${_rc_prefix}${rc_arg}" ${rc_extra_args}
    # Check dependent variables
    #unset desc
    for name in ${samba_daemons}; do
        # reset loop vars
        rcvars=''; v=''
        rcvar=${name}_enable
        eval "desc=\${${name}_desc}"
        run_rc_command "${_rc_prefix}${rc_arg}" ${rc_extra_args}
    done
}

samba_server_reload_cmd()
{
    local name rcvar command pidfile force_run
    # Prevent recursive calling
    unset "${rc_arg}_cmd" "${rc_arg}_precmd" "${rc_arg}_postcmd"
    # Ignore rcvar and run command
    if [ -n "${_rc_prefix}" ] && [ "${_rc_prefix}" = "one" ] || [ -n "${rc_force}" ] || [ -n "${rc_fast}" ]; then
        force_run=yes
    fi
    # Apply to all daemons
    for name in ${samba_daemons}; do
        rcvar=${name}_enable
        command="%%PREFIX%%/sbin/${name}"
        pidfile="${samba_server_piddir}/${name}.pid"
        # Daemon should be enabled and running
        if ( [ -n "${rcvar}" ] && checkyesno "${rcvar}" ) || [ -n "$force_run" ]; then
            if [ -n "$(check_pidfile "${pidfile}" "${command}")" ]; then
                debug "reloading ${name} configuration"
                echo "Reloading ${name}."
                ${smbcontrol_command} "${name}" 'reload-config' ${command_args} >/dev/null 2>&1
            fi
        fi
    done
}

samba_server_cmd()
{
    local name rcvar rcvars v command pidfile samba_daemons samba_postcmd result force_run
    # Stop processes in the reverse order
    if [ "${rc_arg}" = "stop" ] ; then
        samba_daemons=$(reverse_list ${samba_daemons})
    fi
    # Within the cmd itself we operate with the global _precmd, _cmd and _postcmd
    samba_postcmd=$_postcmd
    # Prevent recursive calling
    unset "${rc_arg}_cmd" "${rc_arg}_precmd" "${rc_arg}_postcmd"
    # Ignore rcvar and run command
    if [ -n "${_rc_prefix}" ] && [ "${_rc_prefix}" = "one" ] || [ -n "${rc_force}" ] || [ -n "${rc_fast}" ]; then
        force_run=yes
    fi
    # Assume success
    result=0
    # Apply to all daemons
    for name in ${samba_daemons}; do
        # XXX
        #rcvars=''; v=''
        rcvar=${name}_enable
        command="%%PREFIX%%/sbin/${name}"
        pidfile="${samba_server_piddir}/${name}.pid"
        # Daemon should be enabled and running
        if ( [ -n "${rcvar}" ] && checkyesno "${rcvar}" ) || [ -n "$force_run" ]; then
            run_rc_command "${_rc_prefix}${rc_arg}" ${rc_extra_args}
            # If any of the commands failed, take it as a global result
            result=$((result || $?))
        fi
    done
    if [ -n "${samba_postcmd}" ]; then
        eval "_postcmd=${samba_postcmd}"
    fi
    return $result
}

samba_server_config_init()
{
    local name
    # Defaults
    samba_server_enable=${samba_server_enable:=NO}
    samba_server_config=${samba_server_config=${samba_server_config_default}}
    samba_server_configfile_arg=${samba_server_config:+--configfile="${samba_server_config}"}                   #"
    #testparm_command="%%PREFIX%%/bin/samba-tool testparm --suppress-prompt --verbose ${samba_server_configfile_arg}"
    testparm_command="%%PREFIX%%/bin/testparm --suppress-prompt --verbose ${samba_server_config}"
    # Determine what daemons are necessary to run Samba in the current role
    samba_server_role=$(${testparm_command} --parameter-name='server role' 2>/dev/null)
    case "${samba_server_role}" in
        active\ directory\ domain\ controller)
            samba_daemons="samba"
            ;;
        auto|*)
            samba_daemons="nmbd smbd winbindd"
            ;;
    esac
    # Load daemons configuration
    for name in ${samba_daemons}; do
        load_rc_config "${name}"
        # If samba_server_enable is 'YES'
        if [ -n "${rcvar}" ] && checkyesno "${rcvar}"; then
            if [ "${name}" != "winbindd" ]; then
                # Set variable to 'YES' only if it is unset
                eval "${name}_enable=\${${name}_enable-YES}"
            else
                # Winbindd
                samba_server_idmap=$(${testparm_command} --parameter-name='idmap uid' 2>/dev/null)
                if [ -n "${samba_server_idmap}" ]; then
                    winbindd_enable="YES"
                fi
            fi
        fi
        # If variable is empty, set it to 'NO'
        eval "${name}_enable=\${${name}_enable:-NO}"
    done
    # Fetch parameters from configuration file
    samba_server_lockdir="$(${testparm_command} --parameter-name='lock directory' 2>/dev/null)"
    samba_server_lockdir=${samba_server_lockdir:=%%SAMBA4_LOCKDIR%%}
    samba_server_piddir="$(${testparm_command} --parameter-name='pid directory' 2>/dev/null)"
    samba_server_piddir=${samba_server_piddir:=%%SAMBA4_RUNDIR%%}
    samba_server_privatedir="$(${testparm_command} --parameter-name='private dir' 2>/dev/null)"
    samba_server_privatedir=${samba_server_privatedir:=%%SAMBA4_PRIVATEDIR%%}
}

can_mount()
{
    local kld
    kld=$1
    if ! load_kld $kld; then
        return 1
    fi
    if [ $(${SYSCTL_N} security.jail.jailed) -eq 0 ]; then
        return 0
    fi
    if [ $(${SYSCTL_N} security.jail.mount_allowed) -eq 1 ] &&
       [ $(${SYSCTL_N} security.jail.mount_${kld}_allowed) -eq 1 ]; then
        return 0
    fi
    return 1
}

# Load configuration variables
samba_server_config_init
nmbd_desc="NetBIOS name server"
smbd_desc="SMB/CIFS services server"
winbindd_desc="Name Service Switch server"
# Common flags
command_args=${samba_server_configfile_arg}
samba_flags=${samba_flags="--daemon"}
nmbd_flags=${nmbd_flags="--daemon"}
smbd_flags=${smbd_flags="--daemon"}
winbindd_flags=${winbindd_flags="--daemon"}
# Requirements
required_files="${samba_server_config}"
required_dirs="${samba_server_lockdir}"

run_rc_command "$1"
