diff --git a/README.org b/README.org
index cd6f7d0..78aea47 100644
--- a/README.org
+++ b/README.org
@@ -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
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
#!/bin/sh
#+end_src
@@ -147,7 +162,6 @@ set_menu() {
MENU="term"
fi
}
-
#+end_src
** =menu=
@@ -165,7 +179,7 @@ menu() {
MODE="$1" PROMPT="$2"
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" = "error" ] && zenity --title "$TITLE" --text "$PROMPT" --error > /dev/stderr
[ "$MODE" = "entry" ] && zenity --title "$TITLE" --text "$PROMPT" --entry
@@ -193,3 +207,531 @@ menu() {
}
#+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 \"
+
+
+
+
+
+ 3BDC00FF8091FE1FC38073C821106600000000000000
+ FFFF00FFF0FFFFFFFFFFFFFFFFF0FF00000000000000
+
+
+
+
+
+
+ 3BEA00008131FE450031C173C840000090007A
+ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+
+
+
+
+\" > /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 \"
+
+
+
+
+
+ 3BDC00FF8091FE1FC38073C821106600000000000000
+ FFFF00FFF0FFFFFFFFFFFFFFFFF0FF00000000000000
+
+
+
+
+
+
+ 3BEA00008131FE450031C173C840000090007A
+ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+
+
+
+
+\" > /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 \"
+
+
+
+
+
+ 3BDC00FF8091FE1FC38073C821106600000000000000
+ FFFF00FFF0FFFFFFFFFFFFFFFFF0FF00000000000000
+
+
+
+
+
+
+ 3BEA00008131FE450031C173C840000090007A
+ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+
+
+
+
+\" > /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