#!/bin/sh
set -eu
# vim: set ts=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
#
# Copyright (c) 2020-2024 Red Hat, Inc.
# Author: Sergio Correia <scorreia@redhat.com>
#
# Non-systemd clevis unlocker
# Modifications sponsored by PMGA Tech LLP
#
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

. clevis-luks-common-functions

# Make sure to exit cleanly if SIGTERM is received.
trap 'echo "Exiting due to SIGTERM" && exit 0' TERM

loop=
while getopts ":l" o; do
    case "${o}" in
    l) loop=true;;
    *) ;;
    esac
done

to_unlock() {
    _devices=''
    for _d in $(blkid -t TYPE=crypto_LUKS -o device); do
        if ! bindings="$(clevis luks list -d "${_d}" 2>/dev/null)" \
                         || [ -z "${bindings}" ]; then
            continue
        fi
        _uuid="$(cryptsetup luksUUID "${_d}")"
        if clevis_is_luks_device_by_uuid_open "${_uuid}"; then
            continue
        fi
        _devices="$(printf '%s\n%s' "${_devices}" "${_d}")"
    done
    echo "${_devices}" | sed -e 's/^\n$//'
}

while true; do
    for d in $(to_unlock); do
        uuid="$(cryptsetup luksUUID "${d}")"
        if ! clevis luks unlock -d "${d}"; then
            echo "Unable to unlock ${d} (UUID=${uuid})" >&2
            continue
        fi
        echo "Unlocked ${d} (UUID=${uuid}) successfully" >&2
    done

    [ "${loop}" != true ] && break
    # Checking for pending devices to be unlocked.
    if remaining=$(to_unlock) && [ -z "${remaining}" ]; then
        break;
    fi

    sleep 0.5
done
