#!/bin/sh
# postinst script for weewx debian package
# Copyright 2013-2024 Matthew Wall
#
# ways this script might be invoked:
#
# postinst configure most-recently-configured-version
# old-postinst abort-upgrade new-version
# conflictor's-postinst abort-remove in-favour package new-version
# postinst abort-remove
# deconfigured's-postinst abort-deconfigure in-favour failed-install-package
#   version [removing conflicting-package version]

# abort if any command returns error
set -e

# get debconf stuff so we can set configuration defaults
. /usr/share/debconf/confmodule

cfgfile=/etc/weewx/weewx.conf
cfgapp="python3 /usr/share/weewx/weectl.py"
ts=`date +"%Y%m%d%H%M%S"`

WEEWX_USER="${WEEWX_USER:-weewx}"
WEEWX_GROUP="${WEEWX_GROUP:-weewx}"
WEEWX_HOME="${WEEWX_HOME:-/var/lib/weewx}"
WEEWX_HTMLDIR="${WEEWX_HTMLDIR:-/var/www/html/weewx}"
WEEWX_USERDIR=/etc/weewx/bin/user
WEEWX_INSTANCES="${WEEWX_INSTANCES:-weewx}"

# insert the driver and stanza into the configuration file
insert_driver() {
    if [ ! -f $cfgfile ]; then
        return
    fi

    # FIXME: generalize this so it does not have to be modified every time a
    #        new station type is added or new station options are added.
    db_get weewx/station_type
    if [ "$RET" != "" ]; then
        sed -i "s%station_type[ ]*=.*%station_type = $RET%" $cfgfile
        if [ "$RET" = "AcuRite" ]; then
            db_get weewx/acurite_model
            sed -i "/\[AcuRite\]/,/\[.*\]/ s%[# ]*model[ ]*=.*%    model = $RET%" $cfgfile
        fi
        if [ "$RET" = "CC3000" ]; then
            db_get weewx/cc3000_model
            sed -i "/\[CC3000\]/,/\[.*\]/ s%[# ]*model[ ]*=.*%    model = $RET%" $cfgfile
            db_get weewx/cc3000_port
            sed -i "/\[CC3000\]/,/\[.*\]/ s% port[ ]*=.*%    port = $RET%" $cfgfile
        fi
        if [ "$RET" = "FineOffsetUSB" ]; then
            db_get weewx/fousb_model
            sed -i "/\[FineOffsetUSB\]/,/\[.*\]/ s%[# ]*model[ ]*=.*%    model = $RET%" $cfgfile
        fi
        if [ "$RET" = "TE923" ]; then
            db_get weewx/te923_model
            sed -i "/\[TE923\]/,/\[.*\]/ s%[# ]*model[ ]*=.*%    model = $RET%" $cfgfile
        fi
        if [ "$RET" = "Ultimeter" ]; then
            db_get weewx/ultimeter_model
            sed -i "/\[Ultimeter\]/,/\[.*\]/ s%[# ]*model[ ]*=.*%    model = $RET%" $cfgfile
            db_get weewx/ultimeter_port
            sed -i "/\[Ultimeter\]/,/\[.*\]/ s% port[ ]*=.*%    port = $RET%" $cfgfile
        fi
        if [ "$RET" = "Vantage" ]; then
            db_get weewx/vantage_type
            sed -i "/\[Vantage\]/,/\[.*\]/ s% type[ ]*=.*%    type = $RET%" $cfgfile
            if [ "$RET" = "serial" ]; then
                db_get weewx/vantage_port
                sed -i "/\[Vantage\]/,/\[.*\]/ s% port[ ]*=.*%    port = $RET%" $cfgfile
            else
                db_get weewx/vantage_host
                sed -i "/\[Vantage\]/,/\[.*\]/ s% host[ ]*=.*%    host = $RET%" $cfgfile
            fi
        fi
        if [ "$RET" = "WMR100" ]; then
            db_get weewx/wmr100_model
            sed -i "/\[WMR100\]/,/\[.*\]/ s%[# ]*model[ ]*=.*%    model = $RET%" $cfgfile
        fi
        if [ "$RET" = "WMR300" ]; then
            db_get weewx/wmr300_model
            sed -i "/\[WMR300\]/,/\[.*\]/ s%[# ]*model[ ]*=.*%    model = $RET%" $cfgfile
        fi
        if [ "$RET" = "WMR9x8" ]; then
            db_get weewx/wmr9x8_model
            sed -i "/\[WMR9x8\]/,/\[.*\]/ s%[# ]*model[ ]*=.*%    model = $RET%" $cfgfile
            db_get weewx/wmr9x8_port
            sed -i "/\[WMR9x8\]/,/\[.*\]/ s% port[ ]*=.*%    port = $RET%" $cfgfile
        fi
        if [ "$RET" = "WS1" ]; then
            db_get weewx/ws1_port
            sed -i "/\[WS1\]/,/\[.*\]/ s% port[ ]*=.*%    port = $RET%" $cfgfile
        fi
        if [ "$RET" = "WS23xx" ]; then
            db_get weewx/ws23xx_model
            sed -i "/\[WS23xx\]/,/\[.*\]/ s%[# ]*model[ ]*=.*%    model = $RET%" $cfgfile
            db_get weewx/ws23xx_port
            sed -i "/\[WS23xx\]/,/\[.*\]/ s%[# ]*port[ ]*=.*%    port = $RET%" $cfgfile
        fi
        if [ "$RET" = "WS28xx" ]; then
            db_get weewx/ws28xx_model
            sed -i "/\[WS28xx\]/,/\[.*\]/ s%[# ]*model[ ]*=.*%    model = $RET%" $cfgfile
            db_get weewx/ws28xx_frequency
            sed -i "/\[WS28xx\]/,/\[.*\]/ s%[# ]*transceiver_frequency[ ]*=.*%    transceiver_frequency = $RET%" $cfgfile
        fi
    fi
}

install_weewxconf() {
    if [ ! -f $cfgfile ]; then
        return
    fi

    driver=weewx.drivers.simulator
    db_get weewx/station_type
    if [ "$RET" = "AcuRite" ]; then
        driver=weewx.drivers.acurite
    elif [ "$RET" = "CC3000" ]; then
        driver=weewx.drivers.cc3000
    elif [ "$RET" = "FineOffsetUSB" ]; then
        driver=weewx.drivers.fousb
    elif [ "$RET" = "TE923" ]; then
        driver=weewx.drivers.te923
    elif [ "$RET" = "Ultimeter" ]; then
        driver=weewx.drivers.ultimeter
    elif [ "$RET" = "Vantage" ]; then
        driver=weewx.drivers.vantage
    elif [ "$RET" = "WMR100" ]; then
        driver=weewx.drivers.wmr100
    elif [ "$RET" = "WMR300" ]; then
        driver=weewx.drivers.wmr300
    elif [ "$RET" = "WMR9x8" ]; then
        driver=weewx.drivers.wmr9x8
    elif [ "$RET" = "WS1" ]; then
        driver=weewx.drivers.ws1
    elif [ "$RET" = "WS23xx" ]; then
        driver=weewx.drivers.ws23xx
    elif [ "$RET" = "WS28xx" ]; then
        driver=weewx.drivers.ws28xx
    fi

    # default to US unit system
    units=us
    # get the system's unit system from debconf
    db_get weewx/units
    # sanitize the input.  for backward compatibility, we recognize the older
    # keywords 'US' and 'Metric', which might still be in the system's debconf
    # otherwise, ensure that debconf contains one of 'us', 'metric', or
    # 'metricwx'
    if [ "$RET" = "US" ]; then
        units=us
    elif [ "$RET" = "Metric" ]; then
        units=metric
    elif [ "$RET" = "metric" ]; then
        units=metric
    elif [ "$RET" = "metricwx" ]; then
        units=metricwx
    fi

    db_get weewx/location
    location=$RET

    db_get weewx/latlon
    lat=$(echo $RET | cut -d, -f1 | sed 's/^ //g' | sed 's/ $//g')
    lon=$(echo $RET | cut -d, -f2 | sed 's/^ //g' | sed 's/ $//g')
    if [ "$lat" = "" ]; then lat=0.0; fi
    if [ "$lon" = "" ]; then lon=0.0; fi

    db_get weewx/altitude
    altitude=$(echo $RET | cut -d, -f1 | sed 's/^ //g' | sed 's/ $//g')
    altitude_unit=$(echo $RET | cut -d, -f2 | sed 's/^ //g' | sed 's/ $//g')
    if [ "$altitude_unit" = "feet" ]; then
        altitude_unit=foot
    elif [ "$altitude_unit" = "meters" ]; then
        altitude_unit=meter
    elif [ "$altitude_unit" != "foot" -a "$altitude_unit" != "meter" ]; then
        altitude_unit=foot
    fi

    db_get weewx/register
    if [ "$RET" = 'true' ]; then
      register=y
      db_get weewx/station_url
      station_url_param="--station-url=$RET"
    else
      register=n
      station_url_param=" "
    fi

    $cfgapp station reconfigure --config=$cfgfile \
      --driver=$driver --units=$units --location="$location" \
      --latitude=$lat --longitude=$lon --altitude=$altitude,$altitude_unit \
      --register=$register $station_url_param \
      --no-prompt --no-backup

    insert_driver
}

# use weewx setup utilities to merge new features into existing weewx.conf.
# user will be prompted about whether to accept the new version or the previous
# configuration.
#
# if they choose existing, then they end up with:
#   weewx.conf           - previous config
#   weewx.conf.x.y.z     - new config
#
# if they choose new, then they end up with:
#   weewx.conf.dpkg-old  - previous config
#   weewx.conf           - new config
#
# new install:
#   weewx.conf           - new config filled with values from debconf
#   weewx.conf-new       - new config (created by dpkg rules)
#
# upgrade:
#   weewx.conf           - previous config
#   weewx.conf-new       - new config (created by dpkg rules)
#   weewx.conf-old-new   - old config upgraded to this version
#
merge_weewxconf() {
    if [ ! -f $cfgfile ]; then
        return
    fi

    if [ -f $cfgfile ]; then
        NEWVER=$($cfgapp --version | cut -d' ' -f2)
        OLDVER=$(get_conf_version $cfgfile)
        if dpkg --compare-versions $OLDVER lt $NEWVER; then
            # this is an old config, so create a maintainer's version
            if [ -f $cfgfile-$NEWVER ]; then
	        MNT=$OLDVER-$NEWVER
                echo "Creating maintainer config file as $cfgfile-$MNT"
                cp -p $cfgfile $cfgfile-$MNT
                $cfgapp station upgrade --config=$cfgfile-$MNT --dist-config=$cfgfile-$NEWVER --what=config --no-backup --yes
            fi
        else
            # this is a new config, so just insert debconf values into it
            echo "Using debconf configuration values from previous install"
            install_weewxconf
        fi
    fi
}

# precompile the bytecode
precompile() {
    rc=$(python3 -m compileall -q -x 'user' /usr/share/weewx)
    if [ "$rc" != "" ]; then
        echo "Pre-compile failed!"
        echo "$rc"
    fi
}

# get the version number from the specified file, without the debian revisions
get_conf_version() {
    v=$(grep '^version.*=' $1 | sed -e 's/\s*version\s*=\s*//' | sed -e 's/-.*//')
    if [ "$v" = "" ]; then
        # someone might have messed with the version string
        v="xxx"
    fi
    echo $v
}

set_permissions() {
    usr=$1
    grp=$2
    dir=$3
    find $3 -type f -exec chmod 664 {} \;
    find $3 -type d -exec chmod 2775 {} \;
    chown -R $usr:$grp $dir
}

# if this is an upgrade and the owner of the previous data is other than weewx
# or root, then use that user as the weewx user.  net effect is that we convert
# ownership to weewx:weewx for anything other than a previous install with
# customized ownership.
get_user_info() {
    if [ -d $WEEWX_HOME ]; then
        TMP_USER=$(stat -c "%U" $WEEWX_HOME)
        if [ "$TMP_USER" != "root" -a "$TMP_USER" != "weewx" -a "$TMP_USER" != "UNKNOWN" ]; then
            WEEWX_USER=$TMP_USER
            WEEWX_GROUP=$(stat -c "%G" $WEEWX_HOME)
        fi
    fi
    echo "Using $WEEWX_USER:$WEEWX_GROUP as user:group"
}

# create the user that the daemon will run as, but only if not already exist
create_user() {
    if ! getent group | grep -q "^$WEEWX_GROUP:"; then
        echo -n "Adding system group $WEEWX_GROUP..."
        addgroup --quiet --system $WEEWX_GROUP || true
        echo "done"
    fi
    if ! getent passwd | grep -q "^$WEEWX_USER:"; then
        echo -n "Adding system user $WEEWX_USER..."
        adduser --quiet --system --ingroup $WEEWX_GROUP \
                --no-create-home --home $WEEWX_HOME \
                --disabled-password weewx || true
        echo "done"
    fi
}

# add the user who is installing into the weewx group, if appropriate
add_to_group() {
    # add user only if the group is not a privileged group
    if [ "$WEEWX_GROUP" != "root" ]; then
        # see who is running the installation
        inst_user=$(id -nu)
        if [ "x$SUDO_USER" != "x" ]; then
            inst_user=$SUDO_USER
        fi
        # put the user who is doing the installation into the weewx group,
        # but only if it is not root or the weewx user.
        if [ "x$inst_user" != "x" -a "$inst_user" != "root" -a "$inst_user" != "$WEEWX_USER" ]; then
            # if user is already in the group, then skip it
            if ! getent group $WEEWX_GROUP | grep -q $inst_user; then
                echo "Adding user $inst_user to group $WEEWX_GROUP"
                usermod -aG $WEEWX_GROUP $inst_user
            else
                echo "User $inst_user is already in group $WEEWX_GROUP"
            fi
        fi
    fi
}

# if there is a defaults file, check to ensure it does not contain something
# that would interfere with the installation.  if it does, save a copy and
# replace parameters with values that we know will work.
setup_defaults() {
    dflts=/etc/default/weewx
    if [ -f $dflts ]; then
        WEEWX_PYTHON=$(grep "^WEEWX_PYTHON\s*=" $dflts | sed -e "s/WEEWX_PYTHON\s*=\s*//")
        if [ ! -z "$WEEWX_PYTHON" -a "$WEEWX_PYTHON" != "python3" ]; then
            REPLACE_PYTHON=1
        fi
        WEEWX_BINDIR=$(grep "^WEEWX_BINDIR\s*=" $dflts | sed -e "s/WEEWX_BINDIR\s*=\s*//")
        if [ ! -z "$WEEWX_BINDIR" -a "$WEEWX_BINDIR" != "/usr/share/weewx" ]; then
            REPLACE_BINDIR=1
        fi
        if [ "$REPLACE_PYTHON" != "" -o "$REPLACE_BINDIR" != "" ]; then
            echo "Saving old defaults to ${dflts}-$ts"
            cp -p $dflts ${dflts}-$ts
            if [ "$REPLACE_PYTHON" != "" ]; then
                sed -i -e "s:^WEEWX_PYTHON\s*=.*:WEEWX_PYTHON=python3:" $dflts
            fi
            if [ "$REPLACE_BINDIR" != "" ]; then
                sed -i -e "s:^WEEWX_BINDIR\s*=.*:WEEWX_BINDIR=/usr/share/weewx:" $dflts
            fi
        fi
    fi
}

# put the init files in place
setup_init() {
    if [ "$1" = "systemd" ]; then
        # prefer /usr/lib but fall back to /lib
        dst="/usr/lib/systemd/system"
        if [ ! -d $dst ]; then
            dst="/lib/systemd/system"
        fi
        if [ -d $dst ]; then
            echo "Installing systemd units"
            for f in weewx.service weewx@.service; do
                sed \
 -e "s/User=.*/User=${WEEWX_USER}/" \
 -e "s/Group=.*/Group=${WEEWX_GROUP}/" \
 /etc/weewx/systemd/$f > $dst/$f
            done
            systemctl daemon-reload > /dev/null 2>&1 || true
        fi
    elif [ "$1" = "sysv" ]; then
        echo "Installing SysV rc script"
        cp /etc/weewx/init.d/weewx-multi /etc/init.d/weewx
        chmod 755 /etc/init.d/weewx
    fi
}

# remove any previous init configuration that could interfere
migrate_init() {
    if [ -f /etc/init.d/weewx-multi ]; then
	update-rc.d weewx-multi remove > /dev/null 2>&1 || true
	mv /etc/init.d/weewx-multi /etc/init.d/weewx-multi.dpkg-old
    fi
    if [ "$1" = "systemd" ]; then
	if [ -f /etc/init.d/weewx ]; then
	    update-rc.d weewx remove > /dev/null 2>&1 || true
	    mv /etc/init.d/weewx /etc/init.d/weewx.dpkg-old
	fi
    fi
}

# put the udev rules in place
setup_udev() {
    # prefer /usr/lib but fall back to /lib
    dst=/usr/lib/udev/rules.d
    if [ ! -d $dst ]; then
        dst=/lib/udev/rules.d
    fi
    if [ -d $dst ]; then
        echo "Installing udev rules"
        sed \
 -e "s/GROUP=\"weewx\"/GROUP=\"${WEEWX_GROUP}\"/" \
 /etc/weewx/udev/weewx.rules > $dst/60-weewx.rules
    fi
}

# create the skins if skins do not already exist
setup_skins() {
    if [ ! -d /etc/weewx/skins ]; then
        echo "Creating skins directory /etc/weewx/skins"
        cp -rp /usr/share/weewx/weewx_data/skins /etc/weewx
    fi
}

# create the user extensions directory if one does not already exist
setup_user_dir() {
    if [ ! -d $WEEWX_USERDIR ]; then
        echo "Creating user extension directory $WEEWX_USERDIR"
        mkdir -p $WEEWX_USERDIR
        cp /usr/share/weewx/weewx_data/bin/user/__init__.py $WEEWX_USERDIR
        cp /usr/share/weewx/weewx_data/bin/user/extensions.py $WEEWX_USERDIR
    fi
}

# create the database directory.  set ownership on everything in the directory
# but do not mess with permissions.
setup_database_dir() {
    echo "Configuring database directory $WEEWX_HOME"
    mkdir -p $WEEWX_HOME
    chmod 2775 $WEEWX_HOME
    find $WEEWX_HOME -name "*.sdb" -exec chmod 664 {} \;
    chown -R $WEEWX_USER:$WEEWX_GROUP $WEEWX_HOME
}

# create the reporting directory
setup_reporting_dir() {
    echo "Configuring reporting directory $WEEWX_HTMLDIR"
    mkdir -p $WEEWX_HTMLDIR
    set_permissions $WEEWX_USER $WEEWX_GROUP $WEEWX_HTMLDIR
}

# set the permissions on the configuration, skins, and extensions
set_config_permissions() {
    echo "Setting permissions $WEEWX_USER:$WEEWX_GROUP on /etc/weewx"
    set_permissions $WEEWX_USER $WEEWX_GROUP /etc/weewx
    # ensure that the configuration files are not world-readable so that
    # we protect any passwords and tokens
    chmod 660 /etc/weewx/*.conf*
}

# if there are any existing extensions in the V4 location, copy them to the
# V5 location, then move aside the old location
migrate_extensions() {
    if [ -d /usr/share/weewx/user ]; then
        echo "Migrating old extensions to $WEEWX_USERDIR"
        mkdir -p $WEEWX_USERDIR
        cp -rp /usr/share/weewx/user/* $WEEWX_USERDIR
        echo "Saving old extensions to /usr/share/weewx/user-$ts"
        mv /usr/share/weewx/user /usr/share/weewx/user-$ts
    fi
}

# we explicitly do *not* pay attention to the systemd.preset, since that
# just causes unnecessary confusion, for example between presets for a
# server or workstation configuration, or even from one version of systemd
# to another.  just always enable weewx.
enable_weewxd() {
    echo "Enabling startup using $1"
    if [ "$1" = "systemd" ]; then
	cfgs=$2
	if [ "$cfgs" = "" ]; then
	    systemctl enable weewx > /dev/null 2>&1 || true
	else
	    for i in $cfgs; do
		systemctl enable weewx@$i > /dev/null 2>&1 || true
	    done
	fi
    elif [ "$1" = "sysv" ]; then
        update-rc.d weewx defaults > /dev/null 2>&1 || true
    fi
}

start_weewxd() {
    echo "Starting weewxd using $1"
    if [ "$1" = "systemd" ]; then
	cfgs=$2
	if [ "$cfgs" = "" ]; then
	    systemctl start weewx > /dev/null 2>&1 || true
	else
	    for i in $cfgs; do
		systemctl start weewx@$i > /dev/null 2>&1 || true
	    done
	fi
    elif [ "$1" = "sysv" ]; then
        invoke-rc.d weewx start > /dev/null 2>&1 || true
    fi
}

# just in case there is an old weewxd running somehow, shut it down.  this is
# normally not necessary, since the prerm for prior version does a shutdown.
stop_old_weewxd() {
    if [ -f /etc/init.d/weewx-multi ]; then
	invoke-rc.d weewx-multi stop > /dev/null 2>&1 || true
    fi
    if [ "$1" = "systemd" ]; then
	systemctl stop weewx > /dev/null 2>&1 || true
    elif [ "$1" = "sysv" ]; then
        invoke-rc.d weewx stop > /dev/null 2>&1 || true
    fi
}

# see how many instances of weewxd are running
count_instances() {
    NUM_INSTANCES=$(ps ax | grep weewxd | egrep -v grep | wc -l)
    echo $NUM_INSTANCES
}


# see which init system is running
pid1=none
if [ -d /run/systemd/system ]; then
    pid1=systemd
else
    pid1=sysv
fi

# things we have to do in an upgrade or install:
#  - permisisons
#  - ownership
#  - sysv-to-systemd
#  - v4 extensions to v5 extensions
#  - multiple instances
case "$1" in
    configure)
        num_weewxd=1
	if [ "$2" != "" ]; then
            # this is an upgrade, so see if weewx is already running
            num_weewxd=$(count_instances)
            echo "Found $num_weewxd running instances of weewxd"
            # this is an upgrade, so ensure that weewx is not running
            stop_old_weewxd $pid1
	fi
        get_user_info
        create_user
        add_to_group
        setup_defaults $pid1
        setup_udev

        if [ "$2" != "" ]; then
            # this is an upgrade so create a maintainers version by merging
            merge_weewxconf
            # migrate any extensions from V4 location to V5
            migrate_extensions
	    # remove any previous init configuration that might interfere
	    migrate_init $pid1
        else
            # virgin install so insert debconf values into the config file
            install_weewxconf
        fi

        setup_skins
        setup_user_dir
        setup_database_dir
        setup_reporting_dir
        precompile
        set_config_permissions
        setup_init $pid1
        enable_weewxd $pid1
        # always try to start weewx
	start_weewxd $pid1
        ;;

    abort-remove)
        ;;
esac

# let debconf know that we are finished
db_stop

#DEBHELPER#

exit 0
