completed

This commit is contained in:
tavo-wasd 2024-07-11 10:17:28 -06:00
parent 0e3fdddf51
commit 7707e2cb4f

View file

@ -5,6 +5,21 @@ Script de instalación de firma digital. Busca ser compatible con el estándar d
shell de POSIX a nivel de sintaxis, pero su funcionalidad está limitada a Linux shell de POSIX a nivel de sintaxis, pero su funcionalidad está limitada a Linux
y macOS. y macOS.
*Probado en estas distribuciones:*
- [X] Debian 12
- [ ] Fedora 40
- [ ] Arch Linux [date]
* TODO [0/4]
- [ ] Check if installation is successful
- [ ] Check if already installed
- [ ] Uninstall
- [ ] Allow to use already set variables
* Shebang
#+begin_src shell #+begin_src shell
#!/bin/sh #!/bin/sh
#+end_src #+end_src
@ -147,7 +162,6 @@ set_menu() {
MENU="term" MENU="term"
fi fi
} }
#+end_src #+end_src
** =menu= ** =menu=
@ -165,7 +179,7 @@ menu() {
MODE="$1" PROMPT="$2" MODE="$1" PROMPT="$2"
if [ "$MENU" = "zenity" ] ; then if [ "$MENU" = "zenity" ] ; then
echo_debug "MENU: $MENU MODE: $MODE PROMPT: $PROMPT" > /dev/stderr # DEBUG echo_debug "MENU: $MENU MODE: $MODE PROMPT: $PROMPT" > /dev/stderr
[ "$MODE" = "info" ] && zenity --title "$TITLE" --text "$PROMPT" --info [ "$MODE" = "info" ] && zenity --title "$TITLE" --text "$PROMPT" --info
[ "$MODE" = "error" ] && zenity --title "$TITLE" --text "$PROMPT" --error > /dev/stderr [ "$MODE" = "error" ] && zenity --title "$TITLE" --text "$PROMPT" --error > /dev/stderr
[ "$MODE" = "entry" ] && zenity --title "$TITLE" --text "$PROMPT" --entry [ "$MODE" = "entry" ] && zenity --title "$TITLE" --text "$PROMPT" --entry
@ -193,3 +207,531 @@ menu() {
} }
#+end_src #+end_src
* Lenguaje
=/etc/default/locale= contiene información del lenguage por defecto, obtiene el
lenguaje de esta locación si no está previamente definido (por el sistema o por
el usuario utilizando, por ejemplo, =LANG=es=). Utiliza español por defecto
si logra definir el lenguaje.
#+begin_src shell
set_lang() {
# See: /var/lib/AccountsService/users/
! [ "$LANG" ] && [ -f "/etc/default/locale" ] && . /etc/default/locale
SLANG="${LANG%%_*}"
[ -z "$SLANG" ] && SLANG="es"
if [ "$SLANG" = "es" ] ; then
TITLE="Instalador firma digital"
PROMPT_WELCOME="Bienvenido al asistente de instalación de certificados para firma digial."
PROMPT_ERR_DEPS="Error, la instalación requiere de los siguientes programas no presentes: "
PROMPT_SERIAL="Ingrese el número serial impreso al reverso de la tarjeta."
PROMPT_ERR_SERIAL="Error al obtener el número serial de la tarjeta, abortando."
PROMPT_DOWNLOAD="Descargando desde Centro de Soporte Firma Digital..."
PROMPT_DEPS_INSTALL="Instalando dependencias y otros complementos..."
PROMPT_PASS_DEPS_INSTALL="Ingrese la contraseña del equipo para instalar los componentes"
PROMPT_ERR_DEPS_INSTALL="Error instalando dependencias."
PROMPT_ERR_DOWNLOAD="Error al descargar el fichero, abortando."
PROMPT_END_SUCCESS="El instalador ha concluido."
elif [ "$SLANG" = "en" ] ; then
TITLE="Digital signature installer"
PROMPT_WELCOME="Welcome to the digital signing certificate installation wizard."
PROMPT_ERR_DEPS="Error, installation requires the following programs not present: "
PROMPT_SERIAL="Enter the serial number printed on the back of the card."
PROMPT_ERR_SERIAL="Error obtaining the card serial number, aborting."
PROMPT_DOWNLOAD="Downloading from the Digital Signature Support Center..."
PROMPT_DEPS_INSTALL="Installing dependencies and other components..."
PROMPT_PASS_DEPS_INSTALL="Enter your computer password to install components"
PROMPT_ERR_DEPS_INSTALL="Error installing dependencies."
PROMPT_ERR_DOWNLOAD="Error downloading file, aborting."
PROMPT_END_SUCCESS="The installer has completed."
elif [ "$SLANG" = "fr" ] ; then
TITLE="Installation de signature"
PROMPT_WELCOME="Bienvenue dans l'assistant d'installation du certificat de signature."
PROMPT_ERR_DEPS="Erreur, l'installation requise des programmes suivants ne présente pas: "
PROMPT_SERIAL="Entrez le numéro de série imprimé au dos de la carte."
PROMPT_ERR_SERIAL="Erreur d'obtention du numéro de série de la carte, abandon."
PROMPT_DOWNLOAD="Téléchargement du fichier depuis le Centre de support des signatures numériques..."
PROMPT_DEPS_INSTALL="Installation des dépendances et d'autres composants..."
PROMPT_PASS_DEPS_INSTALL="Entrez le mot de passe de votre ordinateur pour installer les composants"
PROMPT_ERR_DEPS_INSTALL="Erreur lors de l'installation des dépendances."
PROMPT_ERR_DOWNLOAD="Erreur de téléchargement du fichier, abandon."
PROMPT_END_SUCCESS="Le programme d'installation est terminé."
fi
}
#+end_src
* Instalación
Proceso de instalación para dependiendo de su base, ya sea con el =$ID= o
=$ID_LIKE=, esto se define en =get_version=.
Se deshabilita =SC2016= ya que esta parte debe correr sin expandir las
variables.
** Debian
#+begin_src shell
debian_install_certs() {
# Source: https://fran.cr/instalar-firma-digital-costa-rica-gnu-linux-ubuntu-debian/
echo_debug "Instalando dependencias"
pseudo apt-get install -y unzip binutils p11-kit pcscd bubblewrap icedtea-netx > /dev/null || return 1
echo_debug "Extraer fichero"
[ -z "$SAVE_DIR" ] || [ -z "$SAVE_FILE" ] && return 1
(cd "$SAVE_DIR" && unzip -u "$SAVE_FILE" > /dev/null) || return 1
echo_debug "Copiar certificados"
for cert in "$(find "$SAVE_DIR" -name "Certificados")"/* ; do
certname="${cert##*/}"
pseudo cp "$cert" /usr/local/share/ca-certificates/"${certname%.cer}.crt"
done
echo_debug "Extraer módulo privativo"
PACKAGE="$(find "$SAVE_DIR" -name "idprotectclient[-_]*.deb")"
PACKAGE_DIR="${PACKAGE%/*}"
PACKAGE="${PACKAGE##*/}"
[ -z "$PACKAGE_DIR" ] || [ -z "$PACKAGE" ] && return 1
(cd "$PACKAGE_DIR" && ar p "$PACKAGE" data.tar.gz | tar zx ./usr/lib/x64-athena/libASEP11.so)
pseudo cp -p "$PACKAGE_DIR"/usr/lib/x64-athena/libASEP11.so /usr/lib/x86_64-linux-gnu/
echo_debug "Symlinks y componentes..."
# shellcheck disable=SC2016
pseudo sh -c '
# --- Certificados ---
for file in /usr/local/share/ca-certificates/*.crt ; do openssl x509 -inform DER -in "$file" -out "$file.tmp" 2> /dev/null ; done
find /usr/local/share/ca-certificates/ -type f -empty -delete
for i in /usr/local/share/ca-certificates/*.tmp ; do mv "$i" "${i%.tmp}" ; done
update-ca-certificates --fresh > /dev/null
# --- Instalación del módulo PKCS#11 ---
mkdir -p /usr/lib/x64-athena
mkdir -p /Firma_Digital/LIBRERIAS
ln -sf /usr/lib/x86_64-linux-gnu/libASEP11.so /usr/lib/x64-athena/
ln -sf /usr/lib/x86_64-linux-gnu/libASEP11.so /usr/lib/
ln -sf /usr/lib/x86_64-linux-gnu/libASEP11.so /usr/local/lib/
ln -sf /usr/lib/x86_64-linux-gnu/libASEP11.so /Firma_Digital/LIBRERIAS/
ln -sf /usr/local/share/ca-certificates /Firma_Digital/CERTIFICADOS
systemctl enable --now pcscd.socket > /dev/null
'
echo_debug "Configurando IDPClientDB"
pseudo sh -c "
mkdir -p /etc/Athena
echo \"<?xml version=\"1.0\" encoding=\"utf-8\" ?>
<IDProtect>
<TokenLibs>
<IDProtect>
<Cards>
<IDProtectXF>
<ATR type='hexBinary'>3BDC00FF8091FE1FC38073C821106600000000000000</ATR>
<ATRMask type='hexBinary'>FFFF00FFF0FFFFFFFFFFFFFFFFF0FF00000000000000</ATRMask>
</IDProtectXF>
</Cards>
</IDProtect>
<ChipDoc>
<Cards>
<ChipDocEMV>
<ATR type='hexBinary'>3BEA00008131FE450031C173C840000090007A</ATR>
<ATRMask type='hexBinary'>FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</ATRMask>
</ChipDocEMV>
</Cards>
</ChipDoc>
</TokenLibs>
</IDProtect>\" > /etc/Athena/IDPClientDB.xml
"
echo_debug "Configurando p11-kit/modules"
pseudo sh -c "
mkdir -p /usr/share/p11-kit/modules
echo 'remote: |bwrap --unshare-all --dir /tmp --ro-bind /etc/Athena /etc/Athena --proc /proc --dev /dev --ro-bind /usr /usr --ro-bind /lib /lib --ro-bind /lib64 /lib64 --ro-bind /var/run/pcscd /var/run/pcscd --ro-bind /run/pcscd /run/pcscd p11-kit remote /usr/lib/x86_64-linux-gnu/libASEP11.so' > /usr/share/p11-kit/modules/firma-digital.module
"
echo_debug "Configurando p11-kit update symlinks"
pseudo sh -c "
mkdir -p /usr/local/sbin
echo \"#!/bin/sh
FIREFOX_LIB=/usr/lib/firefox/libnssckbi.so
FIREFOX_ESR_LIB=/usr/lib/firefox-esr/libnssckbi.so
THUNDERBIRD_LIB=/usr/lib/thunderbird/libnssckbi.so
NSS_LIB=/usr/lib/x86_64-linux-gnu/nss/libnssckbi.so
if [ -e \"\$FIREFOX_LIB\" ]
then
if ! [ -L \"\$FIREFOX_LIB\" ]
then
echo \"Firefox libnssckbi.so is not a symlink. Fixing...\"
mv -f \"\$FIREFOX_LIB\" \"\$FIREFOX_LIB\".bak
ln -s /usr/lib/x86_64-linux-gnu/p11-kit-proxy.so \"\$FIREFOX_LIB\"
fi
fi
if [ -e \"\$FIREFOX_ESR_LIB\" ]
then
if ! [ -L \"\$FIREFOX_ESR_LIB\" ]
then
echo \"Firefox ESR libnssckbi.so is not a symlink. Fixing...\"
mv -f \"\$FIREFOX_ESR_LIB\" \"\$FIREFOX_ESR_LIB\".bak
ln -s /usr/lib/x86_64-linux-gnu/p11-kit-proxy.so \"\$FIREFOX_ESR_LIB\"
fi
fi
if [ -e \"\$THUNDERBIRD_LIB\" ]
then
if ! [ -L \"\$THUNDERBIRD_LIB\" ]
then
echo \"Thunderbird libnssckbi.so is not a symlink. Fixing...\"
mv -f \"\$THUNDERBIRD_LIB\" \"\$THUNDERBIRD_LIB\".bak
ln -s /usr/lib/x86_64-linux-gnu/p11-kit-proxy.so \"\$THUNDERBIRD_LIB\"
fi
fi
if [ -e \"\$NSS_LIB\" ]
then
if ! [ -L \"\$NSS_LIB\" ]
then
echo \"NSS libnssckbi.so is not a symlink. Fixing...\"
mv -f \"\$NSS_LIB\" \"\$NSS_LIB\".bak
ln -s /usr/lib/x86_64-linux-gnu/p11-kit-proxy.so \"\$NSS_LIB\"
fi
fi\" > /usr/local/sbin/update-p11-kit-symlinks
chmod +x /usr/local/sbin/update-p11-kit-symlinks
"
echo_debug "Configurando módulo mantenimiento systemd"
pseudo sh -c "
mkdir -p /etc/systemd/system
echo \"[Unit]
Description=mantenimiento de enlaces a p11-kit-proxy
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/update-p11-kit-symlinks
[Install]
WantedBy=multi-user.target
\" > /etc/systemd/system/p11-kit-proxy-updater.service
systemctl enable --now p11-kit-proxy-updater.service > /dev/null
"
echo_debug "Instalando trust module pk11"
pseudo sh -c "
mkdir -p /etc/pkcs11/modules
echo 'disable-in:' > /etc/pkcs11/modules/p11-kit-trust.module
"
}
#+end_src
** Fedora
#+begin_src shell
fedora_install_certs() {
# Source: https://fran.cr/instalar-firma-digital-costa-rica-gnu-linux-fedora/
echo_debug "Instalando dependencias"
pseudo dnf -y install unzip pcsc-lite icedtea-web > /dev/null || return 1
echo_debug "Extraer fichero"
[ -z "$SAVE_DIR" ] || [ -z "$SAVE_FILE" ] && return 1
(cd "$SAVE_DIR" && unzip -u "$SAVE_FILE" > /dev/null) || return 1
echo_debug "Copiar certificados"
pseudo cp -p "$(find "$SAVE_DIR" -name "Certificados")"/* /usr/share/pki/ca-trust-source/anchors/
pseudo update-ca-trust
echo_debug "Extraer módulo privativo"
PACKAGE="$(find "$SAVE_DIR" -name "idprotectclient[-_]*.rpm")"
PACKAGE_DIR="${PACKAGE%/*}"
PACKAGE="${PACKAGE##*/}"
[ -z "$PACKAGE_DIR" ] || [ -z "$PACKAGE" ] && return 1
(cd "$PACKAGE_DIR" &&
rm -r ./usr/lib/x64-athena/libASEP11.so
rpm2cpio "$PACKAGE" | cpio -dim ./usr/lib/x64-athena/libASEP11.so) || return 1
pseudo cp -p "$PACKAGE_DIR"/usr/lib/x64-athena/libASEP11.so /usr/lib64/
echo_debug "Symlinks y componentes..."
pseudo sh -c '
mkdir -p /usr/lib/x64-athena/
mkdir -p /Firma_Digital/LIBRERIAS/
ln -sf /usr/lib64/libASEP11.so /usr/lib/x64-athena/
ln -sf /usr/lib64/libASEP11.so /usr/lib/
ln -sf /usr/lib64/libASEP11.so /usr/local/lib/
ln -sf /usr/lib64/libASEP11.so /Firma_Digital/LIBRERIAS/
ln -sf /usr/share/pki/ca-trust-source/anchors /Firma_Digital/CERTIFICADOS
systemctl enable --now pcscd.socket > /dev/null
'
echo_debug "Configurando IDPClientDB"
pseudo sh -c "
mkdir -p /etc/Athena
echo \"<?xml version=\"1.0\" encoding=\"utf-8\" ?>
<IDProtect>
<TokenLibs>
<IDProtect>
<Cards>
<IDProtectXF>
<ATR type='hexBinary'>3BDC00FF8091FE1FC38073C821106600000000000000</ATR>
<ATRMask type='hexBinary'>FFFF00FFF0FFFFFFFFFFFFFFFFF0FF00000000000000</ATRMask>
</IDProtectXF>
</Cards>
</IDProtect>
<ChipDoc>
<Cards>
<ChipDocEMV>
<ATR type='hexBinary'>3BEA00008131FE450031C173C840000090007A</ATR>
<ATRMask type='hexBinary'>FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</ATRMask>
</ChipDocEMV>
</Cards>
</ChipDoc>
</TokenLibs>
</IDProtect>\" > /etc/Athena/IDPClientDB.xml
"
echo_debug "Configurando p11-kit/modules"
pseudo sh -c "
mkdir -p /usr/share/p11-kit/modules
echo 'remote: |bwrap --unshare-all --dir /tmp --proc /proc --dev /dev --ro-bind /etc/Athena /etc/Athena --ro-bind /usr /usr --ro-bind /var/run/pcscd /var/run/pcscd --ro-bind /run/pcscd /run/pcscd --symlink /usr/lib64 /lib64 p11-kit remote /usr/lib64/libASEP11.so' > /usr/share/p11-kit/modules/firma-digital.module
"
}
#+end_src
** Arch Linux
#+begin_src shell
arch_install_certs() {
echo_debug "Instalando dependencias"
pseudo pacman -S --noconfirm --needed unzip cpio rpm-tools pcsclite ccid jre8-openjdk icedtea-web > /dev/null || return 1
echo_debug "Extraer fichero"
[ -z "$SAVE_DIR" ] || [ -z "$SAVE_FILE" ] && return 1
(cd "$SAVE_DIR" && unzip -u "$SAVE_FILE" > /dev/null)
echo_debug "Copiar certificados"
pseudo cp -p "$(find "$SAVE_DIR" -name "Certificados")"/* /usr/share/ca-certificates/trust-source/anchors/
pseudo update-ca-trust
echo_debug "Extraer módulo privativo"
[ -z "$PACKAGE_DIR" ] || [ -z "$PACKAGE" ] && return 1
(cd "$PACKAGE_DIR" && rpm2cpio "$PACKAGE" | cpio -dim ./usr/lib/x64-athena/libASEP11.so)
pseudo cp -p "$PACKAGE_DIR"/usr/lib/x64-athena/libASEP11.so /usr/lib/
echo_debug "Symlinks y componentes..."
pseudo sh -c '
mkdir -p /usr/lib/x64-athena/
mkdir -p /Firma_Digital/LIBRERIAS/
ln -sf /usr/lib/libASEP11.so /usr/lib/x64-athena/
ln -sf /usr/lib/libASEP11.so /usr/local/lib/
ln -sf /usr/lib/libASEP11.so /Firma_Digital/LIBRERIAS/
ln -sf /usr/share/ca-certificates/trust-source/anchors /Firma_Digital/CERTIFICADOS
ln -sf /usr/lib/p11-kit-proxy.so /usr/lib/firefox/libosclientcerts.so
systemctl enable --now pcscd.socket > /dev/null
'
echo_debug "Configurando IDPClientDB"
pseudo sh -c "
mkdir -p /etc/Athena
echo \"<?xml version=\"1.0\" encoding=\"utf-8\" ?>
<IDProtect>
<TokenLibs>
<IDProtect>
<Cards>
<IDProtectXF>
<ATR type='hexBinary'>3BDC00FF8091FE1FC38073C821106600000000000000</ATR>
<ATRMask type='hexBinary'>FFFF00FFF0FFFFFFFFFFFFFFFFF0FF00000000000000</ATRMask>
</IDProtectXF>
</Cards>
</IDProtect>
<ChipDoc>
<Cards>
<ChipDocEMV>
<ATR type='hexBinary'>3BEA00008131FE450031C173C840000090007A</ATR>
<ATRMask type='hexBinary'>FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</ATRMask>
</ChipDocEMV>
</Cards>
</ChipDoc>
</TokenLibs>
</IDProtect>\" > /etc/Athena/IDPClientDB.xml
"
echo_debug "Configurando p11-kit/modules"
pseudo sh -c "
mkdir -p /usr/share/p11-kit/modules
echo 'remote: |bwrap --unshare-all --dir /tmp --proc /proc --dev /dev --ro-bind /etc/Athena /etc/Athena --ro-bind /usr /usr --ro-bind /lib64 /lib64 --ro-bind /run/pcscd /run/pcscd p11-kit remote /usr/lib/libASEP11.so' > /usr/share/p11-kit/modules/firma-digital.module
"
}
#+end_src
** Función wrapper
Encargarse de la instalación simplemente llamando =install_certs=.
#+begin_src shell
install_certs() {
[ -z "$SUDO_PASSWORD" ] && return 1
[ -z "$SAVE_FILE" ] && return 1
SAVE_DIR="${SAVE_FILE%/*}"
if [ "$ID" = "macos" ] ; then
open "$SAVE_FILE" || return 1
elif [ "$ID" = "debian" ] ; then
debian_install_certs || return 1
elif [ "$ID" = "fedora" ] ; then
fedora_install_certs || return 1
elif [ "$ID" = "arch" ] ; then
arch_install_certs || return 1
elif [ "$ID" = "centos" ] ; then
echo || return 1
fi
}
#+end_src
* Main
** TODO Inicializar [0/2]
- [ ] Tirar =exit 1= en caso de no poder seleccionar una versión o un menu.
- [ ] Agregar otras dependencias mínimas, o que no conviene instalarlas en el script (sudo)
#+begin_src shell
set_lang
set_version
set_menu
if ! command -v curl > /dev/null ; then
menu error "$PROMPT_ERR_DEPS curl"
exit 1
fi
menu info "$PROMPT_WELCOME"
#+end_src
** No. Serial
#+begin_src shell
SERIAL="${SERIAL:=$(menu entry "$PROMPT_SERIAL")}"
if [ -z "$SERIAL" ] ; then
menu error "$PROMPT_ERR_SERIAL"
exit 1
fi
#+end_src
** Proceso de descarga
*** Obtener URL e información del fichero
#+begin_src shell
ARCHIVE="$(get_archive)"
TEMPKEY="${ARCHIVE##* }"
FILE="${ARCHIVE%% *}"
DOWNLOAD_URL="$(
printf 'https://soportefirmadigital.com/sfdj/getiso.aspx?tempkey=%s' \
"$TEMPKEY"
)"
SIZE="$(curl -sI "$DOWNLOAD_URL" |
sed '/[Cc]ontent-[Ll]ength/!d;s/^.*: //g' |
awk '{$1/=1024;printf "%d",$1}'
)"
if [ "$SIZE" -lt 500 ] || [ -z "$FILE" ] ; then
menu error "$PROMPT_ERR_DOWNLOAD"
exit 1
fi
#+end_src
*** Descarga
Se desactiva =SC2009= para asegurarse de tener el ID correcto, ya que terminará
el proceso en caso de seguir activo.
#+begin_src shell
SAVE_DIR="/tmp/soportefirmadigital"
SAVE_FILE="$SAVE_DIR/$FILE"
mkdir -p "$SAVE_DIR"
if [ "$MENU" = "zenity" ] ; then
(curl -sL "$DOWNLOAD_URL" -o "$SAVE_FILE") &
while true ; do
sleep 0.5
DOWN="$(du "$SAVE_FILE" 2>/dev/null | awk '{print $1}')"
[ -z "$DOWN" ] && DOWN=0
r=$(((DOWN*10000)/SIZE))
printf '%d\n' ${r%??}
done | zenity --title "$TITLE" --text "$PROMPT_DOWNLOAD" --progress --auto-close
elif [ "$MENU" = "term" ] ; then
menu info "$PROMPT_DOWNLOAD" && echo
curl "$DOWNLOAD_URL" -o "$SAVE_FILE" --progress-bar
fi
# shellcheck disable=SC2009
ACTIVE="$(ps -t | grep 'curl.*soportefirmadigital' | sed '/grep/d')"
ACTIVE="${ACTIVE# }"
ACTIVEID="${ACTIVE%% *}"
if [ -n "$ACTIVE" ] ; then
menu error "$PROMPT_ERR_DOWNLOAD"
echo_debug "Killing process ID: $ACTIVEID from: $ACTIVE" # DEBUG
kill "$ACTIVEID"
exit 1
fi
#+end_src
** Proceso de instalación
*** Permisos elevados
#+begin_src shell
SUDO_PASSWORD="${SUDO_PASSWORD:=$(menu pass "$PROMPT_PASS_DEPS_INSTALL")}"
if [ -z "$SUDO_PASSWORD" ] || ! pseudo whoami >/dev/null 2>&1 ; then
menu error "$PROMPT_ERR_DEPS_INSTALL"
exit 1
fi
#+end_src
*** Instalación
#+begin_src shell
if [ "$MENU" = "zenity" ] ; then
# Attempt to install, forward output to program
# but keep exit code of install function
( ( ( (install_certs; echo $? >&3) |
zenity --title "$TITLE" --text "$PROMPT_DEPS_INSTALL" --progress --pulsate --auto-close >&4) 3>&1 ) |
(read -r xs; exit "$xs") ) 4>&1
#install_certs # Just run this instead to see debug info # DEBUG
# Ignore as this is needed for this "workaround"
# shellcheck disable=SC2181
if [ "$?" != "0" ] ; then
menu error "$PROMPT_ERR_DEPS_INSTALL"
exit 1
fi
elif [ "$MENU" = "term" ] ; then
menu info "$PROMPT_DEPS_INSTALL" && echo
! install_certs && menu error "$PROMPT_ERR_DEPS_INSTALL" && exit 1
fi
#+end_src
** Finalización
#+begin_src shell
menu info "$PROMPT_END_SUCCESS\n"
exit 0
#+end_src