code:
#! /bin/sh -
#
# The installer of Dragora GNU/Linux-Libre
#
# Copyright (c) 2019-2022 Matias Fonzo, <selk@dragora.org>.
#
# 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/>.

# Exit immediately on any error
set -e

PROGRAM="${0##*/}"
TMPDIR="${TMPDIR:-$HOME}"
TMPFILE="${TMPDIR}/${PROGRAM}.${RANDOM-0}$$"
LOCKFILE=/tmp/dragora-installer.lockfile

# Override locale settings
LANG=C
LC_ALL=C
export LANG LC_ALL

unmountFilesystems()
{
    for filesystem in \
     /media/dragora-root/sys   \
     /media/dragora-root/proc  \
     /media/dragora-root/dev   \
     /media/dragora-root       \
     /media/dragora-packages ; \
    do
        if mountpoint -q "$filesystem"
        then
            echo ""
            echo ""
            echo "Unmounting $(findmnt -n -o SOURCE $filesystem) from $filesystem ..."
            if ! umount -v -R "$filesystem"
            then
                echo "    ^ Doing a lazy unmount for \`${filesystem}' ..."
                umount -v -l "$filesystem"
            fi
        fi
    done
    unset -v filesystem
}

chkstatus_or_exit()
{
    status=$?

    # Clean up temporary files
    rm -f -- "$TMPFILE" "$LOCKFILE"

    # Clean up temporary subdirectory if 'PRESERVE' is unset or null
    test -z "$PRESERVE" && rm -rf -- "$SUBTMPDIR"

    # Unmount possible (previously) mounted file systems
    unmountFilesystems

    if test $status -ne 0
    then
        printf '%s\n' "" "^ Return status = $status" 1>&2
        exit 2;
    fi

    unset -v status
}

# Sanity checks

if test ! -d "$TMPDIR"
then
    echo "${PROGRAM}: \`${TMPDIR}' is not a qualified temporary directory" 1>&2
    exit 1;
fi
if test ! -w "$TMPDIR"
then
    echo "${PROGRAM}: \`${TMPDIR}' is not a writable temporary directory" 1>&2
    exit 1;
fi

trap 'chkstatus_or_exit' EXIT HUP INT QUIT ABRT TERM

umask 077;	# Remove access for all but user.

# Set a lock to allow only one instance of the installer

if ( set -C ; echo ": $PROGRAM - locked" > $LOCKFILE ) 2> /dev/null
then
    true
else
    if test -e "$LOCKFILE"
    then
        echo "Only one instance of \`${PROGRAM}' is allowed." 1>&2
        exit 1;
    else
        echo "${PROGRAM}: \`${LOCKFILE}' lock failed." 1>&2
        exit 2;
    fi
fi

# Remove write permission for group and other
umask 022

# Create subdirectory to store the files produced by the installer

# Default sets to "${HOME}/.dragora-installer"
SUBTMPDIR="${TMPDIR}/.${PROGRAM}"
mkdir -p -- "$SUBTMPDIR"
chmod 700 -- "$SUBTMPDIR"

# Detect and prepare initial list of Linux partition(s)

if fdisk -l | sed -e 's|Linux filesystem|Linux|g' | grep -E -q -m 1 'Linux$'
then
    fdisk -l | sed -e 's|Linux filesystem|Linux|g' | grep -E 'Linux$' | \
     sort > "${SUBTMPDIR}/partitions"
else
    cat 1>&2 << EOF
Linux partitions were not detected.

A Linux partition is required to continue the installation.  You can
use utilities such as fdisk(8), cfdisk(8) or parted(8) to create at
least one Linux partition.  Then run \`${PROGRAM}' again.
EOF
    exit 1;
fi

# Determine the maximum size of the terminal to be used on the dialogues

echo "Checking terminal size ..."
LINES="${LINES:-$(tput lines)}"
COLUMNS="${COLUMNS:-$(tput cols)}"

export SUBTMPDIR LINES COLUMNS

dialog --colors \
 --backtitle "\\ZbThe installer of Dragora GNU/Linux-Libre 3.0" \
 --title "INSTALLER INFORMATION" \
 --cr-wrap --msgbox \
"Welcome to \\Z3${PROGRAM}\\Zn.

    This program will help you install Dragora 3.0 on your computer.

Use the cursor keys to move around in the installer's menus.

Press \\Z3[Tab]\\Zn to jump to the next option and \
\\Z3[Shift]\\Zn\\Zb\\Z7+\\Zn\\Z3[Tab]\\Zn to jump to the previous one.

Use \\Z3[Space]\\Zn to select or unselect an item, \\Z3[Enter]\\Zn to \
confirm or proceed to the next menu.

You can use \\Z3[Ctrl]\\Zn\\Zb\\Z7+\\Zn\\Z3[C]\\Zn to abort the \
installation at any time.

To quit a dialog (such as the one you are in), press \\Z3[Esc]\\Zn.

" $((LINES - 4)) $((COLUMNS - 8))

# Try to detect and mount the hybrid ISO image, there may be a USB memory
# stick already inserted.  If not, the media menu will be displayed.

mkdir -p -- /media/dragora-packages

if ! blkid -t LABEL="Dragora Packages" > /dev/null
then
    dialog --colors \
     --backtitle "\\ZbInstallation Medium" \
     --title "Pendrive/SDCard/CDROM" \
     --cr-wrap --msgbox \
"
Please insert the medium labeled \"Dragora Packages\" and
press \\Z3[Enter]\\Zn to continue.  Otherwise, a media selection
menu will be displayed.
" 9 60
    if blkid -t LABEL="Dragora Packages" > /dev/null
    then
        if ! mountpoint -q /media/dragora-packages
        then
            mount -v -t iso9660 LABEL="Dragora Packages" \
             /media/dragora-packages
            echo '/media/dragora-packages/packages' \
             > "${SUBTMPDIR}/MediumFound"
            sleep 1
        fi
    else
        . @PARTS@MenuMedia
    fi
else
    if ! mountpoint -q /media/dragora-packages
    then
        mount -v -t iso9660 LABEL="Dragora Packages" /media/dragora-packages
        sleep 2
    fi
    echo '/media/dragora-packages/packages' > "${SUBTMPDIR}/MediumFound"
fi

# Attempt to unmount possible pre-mounted filesystem(s)
mountpoint -q /media/dragora-root/sys && umount /media/dragora-root/sys
mountpoint -q /media/dragora-root/proc && umount /media/dragora-root/proc
mountpoint -q /media/dragora-root/dev && umount /media/dragora-root/dev

# Clean up possible empty mount-directories
rmdir -- /media/dragora-packages /media/dragora-root 2> /dev/null || true

# Double-check to see the installation directory
if test ! -f "${SUBTMPDIR}/MediumFound"
then
   dialog --colors \
     --backtitle "\\ZbInstallation Medium" \
     --title "MEDIUM NOT FOUND" \
     --sleep 7 --cr-wrap --infobox \
"
No means of installation was found to proceed
with the installation of Dragora.

Please check your drives and the directory
containing the software packages...
" 9 49
    exit 99;
fi

. @PARTS@MakeSwap;		# Swap devices.
. @PARTS@MakeFS;		# Linux partitions.
. @PARTS@FstabEdit;		# File system table edition (fstab).
. @PARTS@MountRoot;		# Mount root partition for installation.
. @PARTS@FstabMounts;		# Mount rest of file systems from fstab.
. @PARTS@ShowSeries;		# Software series.
. @PARTS@InstallPackages;	# Package installation.
. @PARTS@PostInstall;		# Post-installation.
. @PARTS@SetPassword;		# Password for root.
. @PARTS@MenuBootloader;	# Boot loader installation.
. @PARTS@ConfServices;		# Running services.

if test -e /media/dragora-root/etc/fstab
then
    if mountpoint -q /media/dragora-packages
    then
        umount /media/dragora-packages
    fi
    if test -s "${SUBTMPDIR}/SeTCDdev"
    then
        _status=0
        dialog --clear --colors \
         --title "The Setup for Dragora has been completed" \
         --cr-wrap --msgbox \
"
If you are ready, press \\Z3[Enter]\\Zn to eject
the installation disc...
" 8 0 || _status=$?

        if test $_status -eq 0
        then
            cdrom_device="$(cat -- "${SUBTMPDIR}/CDDevice")"

            # Try to eject using SCSI commands, fallback on CDROM eject command
            eject --scsi "$cdrom_device" || eject --cdrom "$cdrom_device"

            dialog \
             --title "The Setup for Dragora has been completed" \
             --msgbox "\\nPlease remove the installation disc.\\n" 7 44 || true

            # Attempt to use the tray close command
            eject -t "$cdrom_device" > /dev/null 2>&1 || true
        fi
        unset -v _status cdrom_device
    fi
fi

sync

_status=0
dialog --clear --colors \
 --backtitle "\\ZbSystem restart" \
 --title "The Setup for Dragora has been completed." \
 --cr-wrap --yesno \
"
Would you like to reboot the system now?
" 7 44 || _status=$?
case $_status in
0)
    unset -v _status
    dialog --clear
    unmountFilesystems
    exec reboot -d -f
    ;;
*)
    unset -v _status
    unmountFilesystems
    echo ""
    echo ""
    echo ""
    echo "Going out to the shell..."
    echo ""
    echo ""
    exit 0
    ;;
esac


code:
# This file is part of the 'dragora-installer'.
#
# Purpose: Show detected services to activate/deactivate.

addEntry()
{
    service=$1
    description=$2

    if test -s "/media/dragora-root/etc/perp/${service}/rc.main"
    then
        # Detect current changes for previous installations

        sticky_bit=$(find /media/dragora-root/etc/perp -name "$service" -perm -1000 -print)

        if test -n "$sticky_bit"
        then
            _toggle_flag=on
        else
            _toggle_flag=off
        fi

        echo "\"${service}\" \"\" $_toggle_flag \"${description}\" \\" \
         >> "${SUBTMPDIR}/ConfServices"
    fi

    unset -v service description sticky_bit _toggle_flag
}

cat << EOF > "${SUBTMPDIR}/ConfServices"
dialog --colors \\
 --backtitle "\\ZbChoosing the running services" \\
 --title "PERSISTENT PROCESS ON BOOT" --no-cancel \\
 --item-help --checklist \\
"A \"persistent process\" is any program intended to be \\
long-running, highly available, and purpose critical. \\
Also known and often described as a \"service\", a persistent \\
process normally provides some essential, on-demand system \\
service.\\n\\n\\
Please select the daemons that you want to start, monitor, log,\\n\\
and control as persistent processes from system startup." 15 71 0 \\
EOF

addEntry acpid "Advanced Configuration and Power Interface event daemon."
addEntry connmand "A daemon for managing Internet connections."
addEntry crond "Cron daemon. [required]"
addEntry dbus "D-Bus daemon."
addEntry devmon "Device monitor (udevil)."
addEntry dhcpcd "DHCP client/daemon (If selected you should deselect 'connmand' to avoid conflicts)"
addEntry inetd "Internet super-server."
addEntry sshd "The OpenSSH (SSH) daemon."
addEntry syslogd "Log systems messages. [required]"
addEntry udevd "Device event managing daemon. [required]"

unset -f addEntry

echo ' 2> "${SUBTMPDIR}/return-ConfServices"' >> "${SUBTMPDIR}/ConfServices"

# Show the menu

. "${SUBTMPDIR}/ConfServices"
test -s "${SUBTMPDIR}/return-ConfServices" || return 0;

# Set sticky bit according to the selection
for service in acpid connmand crond dbus devmon dhcpcd inetd \
               sshd syslogd udevd ; \
do
    if grep -q -o -m 1 "$service" "${SUBTMPDIR}/return-ConfServices"
    then
        chmod a+t /media/dragora-root/etc/perp/${service}
    else
        chmod a-t /media/dragora-root/etc/perp/${service}
    fi
done
unset -v service

repo_name: dustdfg/dragora

license: mit


code:
# This file is part of the 'dragora-installer'.
#
# Purpose: Edition of the file system table (fstab).

# Re-order fstab adding information

sort -k 1 "${SUBTMPDIR}/fstab" | uniq > "${SUBTMPDIR}/fstab.sorted"

# To avoid populating the fstab twice (eg. when 'PRESERVE' is given)
if test ! -e "${SUBTMPDIR}/FstabEdit.flag"
then
    cat << EOF > "${SUBTMPDIR}/fstab"
#
# /etc/fstab - Static information about the filesystems.
#
# For more information, type "man 5 fstab".
#
# Filesystem				Mountpoint	Type		Options		Dump|Check
EOF
    cat "${SUBTMPDIR}/fstab.sorted" >> "${SUBTMPDIR}/fstab"

    printf '%-43s %-14s %-12s %-16s %-3s %s\n' \
     "/dev/fd0"    "/media/floppy" "auto"       "noauto,owner,rw"     "0" "0" \
     "#/dev/cdrom" "/media/cdrom" "iso9660,udf" "noauto,owner,ro"     "0" "0" \
     "tmp"         "/tmp"         "tmpfs"       "defaults"            "0" "0" \
     >> "${SUBTMPDIR}/fstab"

    touch "${SUBTMPDIR}/FstabEdit.flag"
fi

# Show menu to edit the produced fstab (if desired)

dialog --no-shadow --colors \
 --backtitle "\\ZbFile system table information" \
 --title "FILE SYSTEM TABLE EDITOR" \
 --ok-label "Save/Continue" --no-cancel \
 --defaultno --editbox "${SUBTMPDIR}/fstab" \
 $((LINES - 8)) $COLUMNS 2> "${SUBTMPDIR}/fstab.edit"

# Check for differences and offer menu to view or apply changes

diff -u "${SUBTMPDIR}/fstab" "${SUBTMPDIR}/fstab.edit" \
 > "${SUBTMPDIR}/fstab.diff" 2> /dev/null || true

if test -s "${SUBTMPDIR}/fstab.diff"
then
    while true
    do
        dialog --colors \
         --backtitle "\\ZbFile system table modification" \
         --title "FILE SYSTEM TABLE FROM THE INSTALLER" \
         --help-button --help-label "View Diff" \
         --cr-wrap --yesno \
"The file system table has been modified.

Would you like to apply the changes made?.  If you choose 'No',
the installer will continue with the default fstab file.
" 8 66 || _status=$?

        case "${_status:-0}" in
        0) ## Button "Yes"
            cp -f -- "${SUBTMPDIR}/fstab.edit" "${SUBTMPDIR}/fstab"
            break;
            ;;
        1) ## Button "No"
            break;
            ;;
        2) ## Button "View Diff"
            dialog --no-shadow --colors \
             --backtitle \
"\\ZbFile system table modification (unified difference)" \
             --title "FILE SYSTEM TABLE CHANGES" \
             --exit-label "Return" \
             --cr-wrap --textbox "${SUBTMPDIR}/fstab.diff" \
             $((LINES - 8)) $COLUMNS || continue;
            ;;
        *) ## "Escape from L.A"
            unset -v _status
            return 99;
        esac
    done

    unset -v _status
fi


code:
# This file is part of the 'dragora-installer'.
#
# Purpose: Make mount points and mount non-root filesystems from fstab.

# Make declared mount points from fstab, exclude:
# commentaries, root, and possible swapfile.
makeMountPoints()
{
    grep -E -v '^#|swap|/ ' "${SUBTMPDIR}/fstab" | \
     awk '{ print substr($2,2) }' | while read -r directory
      do
          test -n "$directory" || continue

          # Make sure to translate converted blank spaces (\040)
          # into common spaces for directory creation (see MakeFS)
          directory="$(printf '%s' "$directory" | tr '\\040' ' ')"

          if test ! -d "/media/dragora-root/${directory}"
          then
              mkdir -p -- "/media/dragora-root/${directory}"
          fi
      done
}

mountNonRoot()
{
    if test -s "${SUBTMPDIR}/fstab"
    then
        awk '!/^#/ && !/\/ / && !/swap/ && !/fd0/ && !/tmp/{ print $1,$2 }' \
         "${SUBTMPDIR}/fstab" | while IFS=" " read -r device mntpoint
         do
             umount "$device" > /dev/null 2>&1 || true

             mntpoint="$(printf '%s' "$mntpoint" | tr '\\040' ' ')"
             mntpoint="/media/dragora-root/${mntpoint}"

             echo ""
             umount -v "$device" || true
             mount -v "$device" "$mntpoint" || exit $?
             sleep 2
         done
    fi
}

dialog --colors \
 --backtitle "\\ZbNon-root partition(s)" \
 --title "NON-ROOT MOUNTS" --sleep 2 \
 --infobox "Preparing to mount the rest of the file systems..." 3 54

makeMountPoints
mountNonRoot

if test ! -e /media/dragora-root/etc/fstab
then
    # Copy fstab into the root partition
    mkdir -p -- /media/dragora-root/etc || true
    cp -f -- "${SUBTMPDIR}/fstab" /media/dragora-root/etc/
else
    # Offer the possibility to overwrite the fstab file only if
    # there is a difference, since there is no point in asking to
    # overwrite the (newly) created and copied file

    if test \
"$(cmp -s "${SUBTMPDIR}/fstab" /media/dragora-root/etc/fstab; printf $?)" = "1"
    then
        dialog --no-shadow --colors \
         --backtitle "\\ZbFile system table (fstab)" \
         --title "EXISTING FILE SYSTEM TABLE" \
         --cr-wrap --yesno \
"A file system table already exists on the mounted root partition:
    /media/dragora-root/etc/fstab

Overwrite this file only if:
  - This is a new installation.
  - You are installing a new kernel image.
  - To create a boot disk with a new kernel.

In this case, you must configure the system to boot properly.

Do not overwrite the file system table if you are adding
software to the existing system...

Do you want to replace the existing fstab with the new one?
" 19 69 || { unset makeMountPoints mountNonRoot ; return 0; }

        mkdir -p -- /media/dragora-root/etc || true
        cp -f -- "${SUBTMPDIR}/fstab" /media/dragora-root/etc/
    fi
fi

unset makeMountPoints mountNonRoot


code:
# This file is part of the 'dragora-installer'.
#
# Purpose: Installation of .tlz packages from series.

# Show menu

dialog --colors \
 --backtitle "\ZbPackage installation" \
 --title "SELECT THE INSTALLATION MODE" \
 --no-cancel --menu "" 6 58 0 \
"All"     "Install all packages from chosen series" \
"Expert"  "Select packages individually" \
 2> ${SUBTMPDIR}/return-InstallPackages

# Check menu options

case "$(cat -- ${SUBTMPDIR}/return-InstallPackages)" in
All )
    # Clean for subsequent filling
    : > ${SUBTMPDIR}/return-InstallPackages_All

    # Read (selected) series
    IFS= read -r REPLY < ${SUBTMPDIR}/return-ShowSeries

    for serie in $REPLY
    do
        find -- "${MEDIUM_SOURCE}"/@ARCH@ "${MEDIUM_SOURCE}"/noarch \
         -type f \( -name "*@${serie}.tlz" -a ! -name "*-pass*" \) \
          -printf '%p\n' >> ${SUBTMPDIR}/return-InstallPackages_All \
           2> /dev/null || true
    done
    unset -v REPLY serie

    # Proceed to install the packages from selected series

    if test -s ${SUBTMPDIR}/return-InstallPackages_All
    then
       sort ${SUBTMPDIR}/return-InstallPackages_All \
        > ${SUBTMPDIR}/return-InstallPackages_All.sorted

        # Set some packages at the top of the list to give priority

        count=0
        total=3
        while test $count -lt $total
        do
            for string in hierarchyfs etc 'musl@libs' barelibs
            do
                ed -l -s ${SUBTMPDIR}/return-InstallPackages_All.sorted << EOF
/${string}/m${count}
w
EOF
            count=$((count+1))
            done
        done
        unset -v count total string

        echo ""

        # Calculate total number of packages installed to reflect
        # the progress during package installation

        x=1
        total="$(awk 'END{ print NR }' ${SUBTMPDIR}/return-InstallPackages_All.sorted)"

        while read -r package
        do
            qi install \
             --rootdir=/media/dragora-root \
             --packagedir=/usr/pkg \
             --targetdir=/ \
             --prune "$package"

            printf "%${COLUMNS}s %s\n" \
             "$(tput bold)$(tput setaf 3)^ ${x} / ${total}$(tput sgr0)"

            x=$((x+1));		# Increment counter.
        done < ${SUBTMPDIR}/return-InstallPackages_All.sorted

        unset -v x total
    else
        echo "${PROGRAM}: All: Error the package list is empty." 1>&2
        exit 99;
    fi
    ;;
Expert )
    # Clean for subsequent filling
    : > ${SUBTMPDIR}/search-InstallPackages_Expert

    # Read (selected) series
    IFS= read -r REPLY < ${SUBTMPDIR}/return-ShowSeries

    for serie in $REPLY
    do
        find -- "${MEDIUM_SOURCE}"/@ARCH@ "${MEDIUM_SOURCE}"/noarch \
         -type f \( -name "*@${serie}.tlz" -a ! -name "*-pass*" \) \
          -printf '%p\n' >> ${SUBTMPDIR}/search-InstallPackages_Expert \
           2> /dev/null || true
    done
    unset -v REPLY serie

    if test -s ${SUBTMPDIR}/search-InstallPackages_Expert
    then
       sort ${SUBTMPDIR}/search-InstallPackages_Expert \
        > ${SUBTMPDIR}/search-InstallPackages_Expert.sorted
    else
        echo "${PROGRAM}: Expert: The package list is empty." 1>&2
        exit 99;
    fi

    # Dialog, package checklist composition

    cat << EOF > ${SUBTMPDIR}/InstallPackages_Expert
dialog --colors --no-shadow \\
 --backtitle "\ZbPackage selection from chosen series" \\
 --title "SOFTWARE PACKAGES" \\
 --no-cancel --item-help --checklist \\
"The following packages have been found according to the series.\n\n\\
Please use the cursor keys and \\Z3[Space]\\Zn to deselect the packages\n\\
you do not want to install.  By default, all packages are selected." \\
$(( LINES - 6 )) $COLUMNS 16 \\
EOF

    # Populate checklist item using information from meta files
    while read -r meta
    do
        if ! . "${meta}.txt"
        then
            echo "${PROGRAM}: Error no meta file(s) available." 1>&2
            exit 99;
        fi

        echo "\"${full_pkgname%@*}\" \"@${pkgcategory}\" ON \"${blurb}\" \\" \
         >> ${SUBTMPDIR}/InstallPackages_Expert
    done < ${SUBTMPDIR}/search-InstallPackages_Expert.sorted

    # Add tail to get the answers
    echo ' 2> ${SUBTMPDIR}/return-InstallPackages_Expert' \
     >> ${SUBTMPDIR}/InstallPackages_Expert

    touch ${SUBTMPDIR}/return-InstallPackages_Expert

    # Show the menu
    . ${SUBTMPDIR}/InstallPackages_Expert

    # Proceed to install the chosen packages

    if test -s ${SUBTMPDIR}/return-InstallPackages_Expert
    then
       tr ' ' '\n' < ${SUBTMPDIR}/return-InstallPackages_Expert | \
        sort > ${SUBTMPDIR}/return-InstallPackages_Expert.sorted

        # Set some packages at the top of the list to give priority

        count=0
        total=3
        while test $count -lt $total
        do
            for string in hierarchyfs etc 'musl$' barelibs
            do
                ed -l -s ${SUBTMPDIR}/return-InstallPackages_Expert.sorted << EOF
/${string}/m${count}
w
EOF
            count=$((count+1))
            done
        done
        unset -v count total string
    else
        echo "${PROGRAM}: Expert: Error the package list is empty." 1>&2
        exit 99;
    fi

    echo ""

    # Calculate total number of packages installed to reflect
    # the progress during package installation

    x=1
    total="$(awk 'END{ print NR }' ${SUBTMPDIR}/return-InstallPackages_Expert.sorted)"

    # Proceed to install if there is a match in the search list
    while read -r line
    do
        grep -s "${line}[@]" \
         ${SUBTMPDIR}/search-InstallPackages_Expert.sorted | \
          qi install \
           --rootdir=/media/dragora-root \
           --packagedir=/usr/pkg \
           --targetdir=/ \
           --prune -

        printf "%${COLUMNS}s %s\n" \
         "$(tput bold)$(tput setaf 3)^ ${x} / ${total}$(tput sgr0)"

        x=$((x+1));		# Increment counter.
    done < ${SUBTMPDIR}/return-InstallPackages_Expert.sorted

    unset -v x total
    ;;
esac


code:
# This file is part of the 'dragora-installer'.
#
# Purpose: Set Linux partition(s) and mount points.

# Add or refresh list of partitions taking initial
# list of partitions and temporary fstab into account
makeMenu()
{
    while read -r line
    do
        test -n "$line" || continue

        # Get device name and size

        device="${line%% *}"
        size="$(lsblk --noheadings --nodeps --output SIZE "$device")"

        # Get device mount point and file system type

        devpoint="$(awk -v patr="$device" '$1 == patr { print $2 }' \
                     "${SUBTMPDIR}/fstab" 2> /dev/null)"
        formatfs="$(awk -v patr="$device" '$1 == patr { print $3 }' \
                     "${SUBTMPDIR}/fstab" 2> /dev/null)"

        if test -z "$formatfs" || test "$formatfs" = defaults
        then
            formatfs="$(blkid -s TYPE -o value "$device" 2> /dev/null)"
        fi

        # Write entry to be showed on the MakeFS menu

        echo "\"${device}\" \"${formatfs:-Linux}${size} $devpoint\" \\" \
         >> "${SUBTMPDIR}/MakeFS"

    done < "${SUBTMPDIR}/partitions"

    # End Of
    echo ' 2> "${SUBTMPDIR}/return-MakeFS" || _code=$?' \
     >> "${SUBTMPDIR}/MakeFS"
}

# Ask to assign a valid mount point
askMountPoint()
{
    dialog --colors \
     --backtitle "\\ZbSetting Linux partitions: Mount point for $1" \
     --title "MOUNT POINT" \
     --no-cancel --ok-label "Continue" \
     --cr-wrap --inputbox \
"A mount point can be assigned to the partition.

* Consider declaring a complete path such as \"/storage\".
* If you declare the single slash \"/\" it will be
  designated for the (main) system partition.

Note: If you use directory names that contain spaces,
the same will be converted using the octal character
040, which is interpreted by the file system table.

Enter a mount point for \"${1}\":
(If you leave this blank, any previous entries will be deleted)." 20 62 \
     2> "${SUBTMPDIR}/return-MakeFS_askMountPoint" || return 0

    # We remove possible single/double quotes from the answer.
    # Also we convert any blank space (tab or space) into the
    # octal space character (040) to be handled by fstab(5).
    # This is in case that the user introduce a directory with
    # blank spaces.  We are not managing the octal tab character
    # (011) since TAB is a functional key in dialog(1).

    mntpoint="$(sed -e "s/[\\'\"]//g" -e 's/[[:blank:]]/\\040/g' \
                  "${SUBTMPDIR}/return-MakeFS_askMountPoint")"

    if test -n "$mntpoint"
    then
        # Determine the sixth field for the fstab
        case $mntpoint in
        /)  fs_passno=1;;
        *)  fs_passno=2;;
        esac

        # Refresh file system type information
        formatfs="$(blkid -s TYPE -o value "$1" 2> /dev/null)"

        # Write fstab entry

        printf '%-43s %-14s %-12s %-16s %-3s %s\n' \
         "$1" "$mntpoint" "$formatfs" "defaults" "1" "${fs_passno}" \
         >> "${SUBTMPDIR}/fstab"

        unset -v fs_passno formatfs

        # Remove possible duplicates
        if test "$(grep -c "^$1" "${SUBTMPDIR}"/fstab)" -gt 1
        then
            repeated="$(grep -m 1 -n "^$1" "${SUBTMPDIR}"/fstab)"
            repeated="${repeated%%:*}"
            sed -i "${repeated}d" "${SUBTMPDIR}/fstab"
            unset -v repeated
        fi
    else # Remove the whole fstab entry
        if test -n "$1" && test -s "${SUBTMPDIR}/fstab"
        then
            escape_slash="$(printf '%s' "$1" | sed 's/\//\\\//g')"
            sed -i "/${escape_slash}/d" "${SUBTMPDIR}/fstab"
            unset -v escape_slash
        fi
    fi
    unset -v mntpoint
}

_mkfs()
{
    helper="$1"
    devname="$2"

    dialog --colors \
     --backtitle "\\ZbPartitions - ${devname}" \
     --title "FILE SYSTEM FORMAT" \
     --ok-label "Format" --cr-wrap --checklist \
"The following device can be formatted using the \"${helper}\" helper:

$(fdisk -l "$devname" | head -n 1)" 13 55 1 \
"$devname"    "Check for bad blocks (slow)" off \
    2> "${SUBTMPDIR}/return-MakeFS_mkfs" || return $?

    dialog --clear

    echo "Making ${helper#*.} filesystem for $devname ..."
    echo ""

    if test -s "${SUBTMPDIR}/return-MakeFS_mkfs"
    then
        $helper -F -F -c $devname
    else
        $helper -F -F $devname
    fi
    sleep 4

    unset -v helper devname
}

_mkbtrfs()
{
    dialog --clear

    echo "Making btrfs filesystem for $1 ..."
    echo ""

    mkfs.btrfs -f -d single -m single "$1"
    sleep 4
}

_mkreiser4()
{
    # Check if the device name is a SDD
    case $1 in
    *nvme*)
        reiser_sdd=-d
        ;;
    esac

    dialog --clear

    echo "Making reiser4 filesystem for $1 ..."
    echo ""

    mkfs.reiser4 -yf $reiser_sdd -o create=reg40,node=node41 "$1"
    sleep 4

    unset -v reiser_sdd
}

_mkxfs()
{
    dialog --clear

    echo "Making xfs filesystem for $1 ..."
    echo ""

    mkfs.xfs -f "$1"
    sleep 4
}

formatMenu()
{
    dialog --colors \
     --backtitle "\\Zb${1}: Setting a file system" \
     --title "FILE SYSTEM SELECTION" \
     --default-item "ext3" \
     --item-help --cr-wrap --menu \
"Choose a file system for '${1}':" 13 58 6 \
"ext2"     "Second extended filesystem"       "ext2 remains the preferred file system for flash-based storage media due to its lack of a journal" \
"ext3"     "Third  extended filesystem"       "ext3 is suitable for both 32-bit and 64-bit systems" \
"ext4"     "Fourth extended filesystem"       "We suggest using it more for a 64-bit system than for a 32-bit system" \
"btrfs"    "Btrfs filesystem"                 "A modern copy on write (CoW) filesystem for GNU/Linux" \
"reiser4"  "Reiser4 filesystem"               "Reiser4 is a successor of ReiserFS (a general-purpose, journaling file system)" \
"xfs"      "XFS filesystem"                   "XFS is a high-performance 64-bit journaling file system suitable for real-time applications" \
    2> "${SUBTMPDIR}/return-MakeFS_formatMenu" || _status=$?

    if test -n "$_status" && test $_status -ne 0
    then
        return "$_status";
    fi
    unset -v _status

    # Try to unmount the device if it is already mounted
    umount "$1" > /dev/null 2>&1 || true

    # Check for selected options to give the proper format
    case "$(cat -- "${SUBTMPDIR}"/return-MakeFS_formatMenu)" in
    ext2)
        _mkfs mkfs.ext2 "$1"
        ;;
    ext3)
        _mkfs mkfs.ext3 "$1"
        ;;
    ext4)
        _mkfs mkfs.ext4 "$1"
        ;;
    btrfs)
        _mkbtrfs "$1"
        ;;
    reiser4)
        _mkreiser4 "$1"
        ;;
    xfs)
        _mkxfs "$1"
        ;;
    esac
}

# Compose partition menu to be displayed

while true
do
    cat << EOF > "${SUBTMPDIR}/MakeFS"
dialog --colors \\
 --backtitle "\\ZbPartitions and mount points" \\
 --title "Setting Linux partitions" \\
 --ok-button "Establish" --extra-button \\
 --extra-label "Done" \\
 --cr-wrap --menu \\
"The following Linux partitions has been detected:

    Selecting a partition gives you the possibility to set up
a file system or a mount point for the boot stage of the system.
Once this has been established, choose the \\"Done\\" button
to continue with the installation." 16 65 5 \\
EOF
    makeMenu && . "${SUBTMPDIR}/MakeFS"
    case "${_code:-$?}" in
    0)
        partition="$(cat -- "${SUBTMPDIR}"/return-MakeFS)"

        if test -z "$partition"
        then
            echo "${PROGRAM}: Error the partition list is empty." 1>&2
            exit 99;
        fi

        if test -n "$(blkid -s TYPE -o value "$partition" 2> /dev/null)"
        then
            dialog --colors \
             --backtitle "\\ZbPartitions and mount points" \
             --title "$partition" \
             --no-cancel --cr-wrap --menu \
"Selected device already contains a file system!

You can assign a mount point for system startup, you also
have the ability to re-format the partition.  If you choose
the latter, you will lose all your data and will be asked
for a mounting point.

What would you like to do for '${partition}'?" 17 64 3 \
             "0" "Assign a mount point" \
             "1" "Format again (data loss risk)" \
             "<" "Return to previous menu" \
            2> "${SUBTMPDIR}/return-MakeFS_case" || continue;

            case "$(cat -- "${SUBTMPDIR}"/return-MakeFS_case)" in
            0)  askMountPoint "$partition";;
            1)  formatMenu "$partition" && askMountPoint "$partition";;
            esac
        else
            formatMenu "$partition" && askMountPoint "$partition"
        fi
        ;;
    3)
        # To verify the existence of the designated system mount point
        if grep -qs -m 1 '/ ' "${SUBTMPDIR}/fstab"
        then
            break;
        else
            dialog --colors \
             --backtitle "\\ZbPartitions and mount points: Unknown mount point for root partition" \
             --title "NO MOUNT POINT FOR MAIN SYSTEM" \
             --ok-label "Return" --cr-wrap --msgbox \
"
There is no declared mount point for the root partition.

    Please go back and assign a mount point for the
root partition.  Remember that the mount point must
be declared as \"/\" (without quotes and spaces).
" 11 60 || { unset -v _code ; continue; }
        fi
        ;;
    *)
        exit "$_code"
        ;;
    esac
    unset -v _code;	# To take the value again.
done

unset makeMenu _mkfs _mkxfs FormatMenu _code

path: archive/dragora-installer/parts/MakeFS


code:
# This file is part of the 'dragora-installer'.
#
# Purpose: Swap detector, formatter.

# A function to produce the fstab entry for the physical swap partition
add_fstabEntry()
{
    printf '%-43s %-14s %-12s %-16s %-3s %s\n' \
     "$1" "swap" "swap" "defaults" "0" "0" >> "${SUBTMPDIR}/fstab"
}

# Get and print device size
get_size()
{
    lsblk --noheadings --nodeps --output SIZE "$1"
}

# Add device names to the checklist (to be shown)
set_checklist()
{
    while IFS= read -r line
    do
        echo "\"${line}\" \"$(get_size $line)\" ON \\" >> "$2"
    done < "$1"

    # End Of
    echo " 2> \${SUBTMPDIR}/$3" >> "$2"
}

### Detection and addition of inactive/active swap devices

swaplist="$(fdisk -l | awk '/Linux swap/{ print $1 }')"

if test -z "$swaplist"
then
    dialog --colors \
     --backtitle "\\ZbSwap detection" \
     --title "NO SWAP PARTITION DETECTED" \
     --cr-wrap --yesno \
"No swap partition has been detected.

Setting up a swap partition is recommended because
it will enable the system to use available physical
memory (RAM) more efficiently and also provide a
safeguard in situations where RAM is exhausted.

If you want to make use of hibernation (suspend to
disk), a swap partition of sufficient size is
required.

Would you like to proceed without a swap partition?" 17 55 || \
    {
        printf '%s' \
"
Please create a swap partition using fdisk(8) or cfdisk(8).
Then re-run the installer to give it the proper formatting.

You can also use mkswap(8) and swapon(8) to format and
activate the partition in advance.
"
        exit 99;
    }
    unset add_fstabEntry get_size set_checklist swaplist
    return 0
fi

rm -f "${SUBTMPDIR}/MakeSwap_active.list" \
      "${SUBTMPDIR}/MakeSwap_inactive.list"
for device in $swaplist
do
    if swapon --noheadings --show=NAME | grep -q "$device"
    then
        echo "$device" >> "${SUBTMPDIR}/MakeSwap_active.list"
    else
        echo "$device" >> "${SUBTMPDIR}/MakeSwap_inactive.list"
    fi
done
unset -v device swaplist

### ^ End Of 'Detection, addition of active and inactive swap devices'

### Check for active swap devices

if test -s "${SUBTMPDIR}/MakeSwap_active.list"
then
    # Compose output file to be shown

    printf '%s\n' \
     'dialog --colors \'                                           \
     ' --backtitle "\\ZbActive Swap devices" \'                    \
     ' --title "ACTIVE SWAP DEVICES" \'                            \
     ' --nocancel --cr-wrap --checklist \'                         \
'"The following swap devices have already been activated:'         \
''                                                                 \
'By default all partitions are marked to be added to the'          \
'file system representation table (/etc/fstab) in order to'        \
'be loaded at boot time.  You can deselect the partition(s)'       \
'you do not want to add or load at system startup using'           \
'the \\Z3[Space]\\Zn key, then press \\Z3[Enter]\Zn to continue."  \
16 65 3 \' > "${SUBTMPDIR}/MakeSwap_active"

    set_checklist "${SUBTMPDIR}/MakeSwap_active.list" \
     "${SUBTMPDIR}/MakeSwap_active" return-MakeSwap_active
fi

if test -s "${SUBTMPDIR}/MakeSwap_active"
then
    . "${SUBTMPDIR}/MakeSwap_active"

    if test -s "${SUBTMPDIR}/return-MakeSwap_active"
    then
        # Append new line for reading
        echo "" >> "${SUBTMPDIR}/return-MakeSwap_active"

        IFS= read -r REPLY < "${SUBTMPDIR}/return-MakeSwap_active" || exit 2;

        for device in $REPLY
        do
            add_fstabEntry "$device"
        done

        unset -v REPLY device
    fi
fi

### ^ End Of 'Check for active swap devices'

### Check for inactive swap devices

if test -s "${SUBTMPDIR}/MakeSwap_inactive.list"
then
    # Compose output file to be shown

    printf '%s\n' \
     'dialog --colors \'                                           \
     ' --backtitle "\\ZbInactive Swap devices" \'                  \
     ' --title "INACTIVE SWAP DEVICES" \'                          \
     ' --nocancel --cr-wrap --checklist \'                         \
'"The following swap partitions has been detected:'                \
''                                                                 \
'By default all partitions found will be formatted and added'      \
'to the file system representation table (/etc/fstab) in order'    \
'to be loaded at boot time.  You can deselect the partition(s)'    \
'you do not want to format or load at system startup using'        \
'the \\Z3[Space]\\Zn key, then press \\Z3[Enter]\Zn to continue."  \
16 65 3 \' > "${SUBTMPDIR}/MakeSwap_inactive"

    set_checklist "${SUBTMPDIR}/MakeSwap_inactive.list" \
     "${SUBTMPDIR}/MakeSwap_inactive" return-MakeSwap_inactive
fi

if test -s "${SUBTMPDIR}/MakeSwap_inactive"
then
    . "${SUBTMPDIR}/MakeSwap_inactive"

    if test -s "${SUBTMPDIR}/return-MakeSwap_inactive"
    then
        # Append new line for reading
        echo "" >> "${SUBTMPDIR}/return-MakeSwap_inactive"

        IFS= read -r REPLY < "${SUBTMPDIR}/return-MakeSwap_inactive" || exit 2;

        for device in $REPLY
        do
            # Set up temporary random files related to the menu
            tempfile="${SUBTMPDIR}/return_MakeSwap_format${RANDOM-0}$$"

            dialog --colors \
             --backtitle "\\ZbInactive Swap device"  \
             --title "SWAP FORMAT FOR $device"       \
             --ok-label "Format"                     \
             --cancel-label "Ignore & Continue"      \
             --cr-wrap --checklist                   \
"A swap device has been chosen.

We offer the possibility to format it properly,
as well as you can simply ignore this part and
continue if you previously formatted it:

Device name: $device [$(get_size $device)]" 14 51 1 \
"$device"    "Check for bad blocks (slow)" off \
            2> $tempfile || continue;

            dialog --clear

            echo "Making swap device $device ..."
            echo ""

            if test -s "$tempfile"
            then
                mkswap -c "$device"
            else
                mkswap "$device"
            fi

            echo ""
            echo "Activating swap device (${device}) ..."
            echo ""

            swapon -v -f "$device"
            sleep 6
            add_fstabEntry "$device"
        done

        unset -v REPLY device tempfile
    fi
fi

### ^ End Of 'Check for inactive swap devices'

unset -f add_fstabEntry get_size set_checklist


code:
#! /bin/bash -
#
# This file is part of the 'dragora-installer'.
#
# Purpose: Installation of GRUB boot loader into /media/dragora-root.

# Exit immediately on any error
set -e

# Make sure to have /proc and /dev available to install GRUB
if ! mountpoint -q /media/dragora-root/dev
then
    mount --bind /dev /media/dragora-root/dev
fi
if ! mountpoint -q /media/dragora-root/proc
then
    mount -t proc proc /media/dragora-root/proc
fi
if ! mountpoint -q /media/dragora-root/sys
then
    mount -t sysfs sysfs /media/dragora-root/sys
fi

# Loop for the main menu
while true
do
    dialog --colors \
     --backtitle "\\ZbBoot loader installation" \
     --title "GRand Unified Bootloader" \
     --default-button "${_default_button:-ok}" \
     --ok-label "Install" \
     --cancel-label "Ignore & Continue" \
     --menu \
"It's time to install a boot loader (GNU GRUB).\\n\\n\
If you do not have a boot loader, it is recommended to install it in\\n\
the Master Boot Record (MBR).  It is possible to overwrite your current \
boot loader.\\n\\n\
You can also install the boot loader on the Root partition (superblock), \
but note that the partition needs the boot flag to boot.  If you have not \
used this flag before when you created the partitions you can do so later \
by invoking 'cfdisk' or 'fdisk'." 19 72 2 \
     "0" "Install GRUB on the Master Boot Record" \
     "1" "Install GRUB on the Super block" \
     2> "${SUBTMPDIR}/return-MenuBootloader" || _status=$?
    if test -n "$_status" && test $_status -gt 0
    then
        if test $_status -eq 1
        then
            return 0		# Ignore exit status on 'Cancel'.
        fi
        return "$_status"	# Any other dialog(1) code.
    fi

    answer="$(cat -- "${SUBTMPDIR}"/return-MenuBootloader)"

    # Check for selected options
    case $answer in
    0 | 1) ## Master Boot Record or Super block

        # Defining the title of the subsequent menu
        if test "$answer" = 0
        then
            _submenu_title="Master Boot Record"
        else
            _submenu_title="Super block"
        fi

        # Check if it is a logical volume
        if pvs | grep -q dev
        then
            array=()

            pvs --ignorelockingfailure --noheadings | awk '{ print $1 }' | \
             while IFS='' read -r line
            do
                array+=("$line")
            done

            # Verify in which partition to install
            if (( ${#array[*]} > 1 ))
            then
                i=0
                for partition in "${array[@]}"
                do
                    partition="${partition/[0-9]*/}"
                    xlist[i++]=$partition
                    xlist[i++]=""
                done
                unset -v i partition

                # Remove possible duplicate elements
                xlist=( $(printf '%s\n' "${xlist[@]}" | awk '!s[$0]++') )

                dialog --colors \
                 --backtitle "\\ZbBoot loader installation" \
                 --title "$_submenu_title" \
                 --menu \
"More than one disk or partition has been detected.\\n\\n\
Please select the boot loader destination:" 0 0 0 "${xlist[@]}" \
                 2> "${SUBTMPDIR}/return-MenuBootloader_cases" || continue;
                BOOT_DEVICE="$(cat -- "${SUBTMPDIR}"/return-MenuBootloader_cases)"
            else
                BOOT_DEVICE="${array[0]}"
            fi

            unset -v array xlist
        fi
        unset -v _submenu_title

        # To fallback if 'BOOT_DEVICE' is not defined, null
        BOOT_DEVICE="${BOOT_DEVICE:=$(cat -- "${SUBTMPDIR}"/root_device)}"

        # If the superblock was not chosen, we do not need
        # the device number to install on the MBR
        if test "$answer" != 1
        then
            BOOT_DEVICE="${BOOT_DEVICE/[0-9]*/}"
        fi
        unset -v answer

        # GRUB Installation

        dialog --clear
        echo "Boot loader installation on $BOOT_DEVICE ..."
        echo ""

        mkdir -p -- /media/dragora-root/boot/grub
        echo ""
        chroot /media/dragora-root /usr/sbin/grub-install --force $BOOT_DEVICE
        echo ""
        echo "Generating configuration file (as /boot/grub/grub.cfg) ..."
        echo ""
        chroot /media/dragora-root /usr/sbin/grub-mkconfig -o /boot/grub/grub.cfg
        sleep 5

        unset -v BOOT_DEVICE

        _default_button=cancel
        continue;
        ;;
    esac
done


code:
# This file is part of the 'dragora-installer'.
#
# Purpose: Medium selector (CD-DVD/Pendrive/SD/Hard disk).

# Show media menu

while true
do
    dialog --colors \
     --backtitle "\\ZbSelecting the installation medium" \
     --title "INSTALLATION ORIGIN" \
     --menu \
"Please select the installation medium containing the software packages \
to install Dragora:" 10 54 2 \
     "0" "CDROM" \
     "1" "Local or mounted directory" \
     2> "${SUBTMPDIR}/return-MenuMedia"

    # Check for selected options
    case "$(cat -- "${SUBTMPDIR}"/return-MenuMedia)" in
    0) ## CDROM

        # Scan device name(s) containing the packages to install Dragora
        for name in hda hdb hdc hdd hde hdf hdh sr0 sr1 sr2 sr3 \
                    pcd0 pcd1 pcd2 pcd3 aztcd cdu535 gscd0 \
                    sonycd optcd sjcd mcdx0 mcdx1 sbpcd \
                    cm205cd cm206cd mcd dvd cdrom ; \
        do
            # Prepend path for device files
            name=/dev/${name}

            dialog --colors \
             --backtitle "\\ZbCDROM: Discovering drive name" \
             --title "Searching CDROM drive" --sleep 1 \
             --infobox "Checking device: $name" 3 33

            test -b "$name" || continue

            # Prepare to mount and check the package directory

            if mountpoint -q /media/dragora-packages
            then
                umount /media/dragora-packages
            fi

            echo  "Mounting ${name} under /media/dragora-packages ..."
            sleep 3

            if mount -t iso9660 $name /media/dragora-packages > /dev/null 2>&1
            then
                if test ! -e /media/dragora-packages/packages
                then
                    dialog --colors \
                     --backtitle "\\ZbCDROM: Dragora packages" \
                     --title "CD/DVD Content" \
                     --msgbox \
"The ${name} device was successfully mounted under the\\n\
/media/dragora-packages directory.  However, the contents\\n\
for the Dragora packages were not found.  They are\\n\
searched through /media/dragora-packages/packages.\\n\
\\n\
The installer can check for another device name (such as\\n\
a secondary CDROM drive) looking for the package directory\\n\
in order to install Dragora.\\n\
\\n\
Press \\Z3[Enter]\Zn to proceed..." 14 63
                continue
                else
                    # Save reference directory
                    echo "/media/dragora-packages/packages" \
                     > "${SUBTMPDIR}/MediumFound"

                    # Save device name to eject later
                    echo "$name" > "${SUBTMPDIR}/CDDevice"
                    break 2;
                fi
            fi
        done
        unset -v name

        dialog --colors \
         --backtitle "\\ZbSelecting the installation medium: CDROM (medium not found)" \
         --title "CDROM detection" \
         --ok-label "Return" \
         --msgbox \
"It was not possible to detect the device name for your CDROM drive.\\n\\n\
Please return to the previous menu by pressing \\Z3[Enter]\Zn in order to\\n\
try by other means..." 9 71
        ;;
    1) ## Local or mounted directory
        while true
        do
            dialog --colors \
             --backtitle "\\ZbSelecting the installation medium: Local or mounted directory" \
             --title "Define valid directory" \
             --cancel-label "- Back" --inputbox \
"Please enter a directory path containing the packages to\\n\
install Dragora.  Note: the package directory search is\\n\
relative to the specified directory.  For example, if you\\n\
enter \"/media/harddisk\" the installer will complete the\\n\
path by adding \"/media/harddisk/packages\"." 12 62 \
             2> "${SUBTMPDIR}/return-MenuMedia_case1" || continue 2;

            answer="$(cat -- "${SUBTMPDIR}"/return-MenuMedia_case1)"
            test -n "$answer" || continue

            if test ! -d "/${answer}/packages"
            then
                dialog --colors \
                 --backtitle "\\ZbSelecting the installation medium: Local or mounted directory" \
                 --title "Directory not found" \
                 --ok-label "Return" --msgbox \
"The \"packages\" subdirectory does not exist\\n\
under the specified directory:\\n\
/${answer#/*}" 8 47
                continue
            fi

            echo "/${answer}/packages" > "${SUBTMPDIR}/MediumFound"
            unset -v answer
            break 2;
        done
        ;;
    esac
done


code:
# This file is part of the 'dragora-installer'.
#
# Purpose: Mount root partition, device from declared fstab.

dialog --colors \
 --backtitle "\\ZbRoot partition" \
 --title "ROOT MOUNT" --sleep 2 \
 --infobox "Preparing to mount designated root partition for installation..." 3 68

# Figure out device name from fstab
ROOT_DEVICE="$(awk '$2 == "/" { print $1 }' "${SUBTMPDIR}/fstab" | cut -f 1 -d ' ')"

# Expose 'ROOT_DEVICE' for MenuBootloader
echo "$ROOT_DEVICE" > "${SUBTMPDIR}/root_device"

# Create mount-point destination
mkdir -p -- /media/dragora-root

if mountpoint -q /media/dragora-root
then
    umount /media/dragora-root
fi
umount "$ROOT_DEVICE" > /dev/null 2>&1 || true

dialog --clear

echo "Mounting $ROOT_DEVICE on /media/dragora-root ..."
sleep 1
mount -v "$ROOT_DEVICE" /media/dragora-root
sleep 2

# This will be used later (e.g bootloader entry)
export ROOT_DEVICE


code:
# This file is part of the 'dragora-installer'.
#
# Purpose: Steps after installing Dragora.

echo ""
echo "-> Running post-install instructions from the installer ..."

# Copy local config files to the system partition

# Cover keyboard map if it has been changed, previously
if test -e /etc/rc.conf
then
    # Assume the local config (from the livecd) has been changed
    if ! grep -F -m 1 -q 'RC_KEYMAP=qwerty/us' /etc/rc.conf
    then
        # Make backup of existent rc.conf at /media/dragora-root/etc
        if test -e /media/dragora-root/etc/rc.conf
        then
            cp -p /media/dragora-root/etc/rc.conf \
                  /media/dragora-root/etc/rc.conf.bak || true
        fi
        cp -f /etc/rc.conf /media/dragora-root/etc/ || true
    fi
fi

# Copy GPM run control file
if test -e /etc/rc.d/rc.gpm && test ! -e /media/dragora-root/etc/rc.d/rc.gpm
then
    cp -f /etc/rc.d/rc.gpm /media/dragora-root/etc/rc.d/rc.gpm && \
     chmod 755 /media/dragora-root/etc/rc.d/rc.gpm || true
fi

# Create index of scalable font files for X

echo ""
echo "* Creating index of scalable font files for X, if possible ..."
if test -d /media/dragora-root/usr/share/fonts
then
    for directory in /media/dragora-root/usr/share/fonts/X11/*
    do
        test -d "$directory" || continue

        directory="$(echo "$directory" | sed -e 's|^/media/dragora-root||')"

        chroot /media/dragora-root /usr/bin/mkfontscale -b -s -l "$directory" || true
        chroot /media/dragora-root /usr/bin/mkfontscale "$directory" || true
    done
    unset -v directory

    # Build font information cache files

    echo ""
    echo "* Building font information cache files ..."
    chroot /media/dragora-root /usr/bin/fc-cache -f --system-only || true
else
    echo "  /usr/share/fonts does not exist at /media/dragora-root/" 1>&2
fi

echo ""
echo "* Updating index for the GNU Info document system, if possible ..."
chroot /media/dragora-root \
 /usr/bin/find -L /usr/share/info -maxdepth 1 ! -name dir \
  -exec /usr/bin/install-info '{}' /usr/share/info/dir \; || true

echo ""
echo "* Updating database of manual pages, if possible ..."
mkdir -p /media/dragora-root/var/cache/man && \
 chroot /media/dragora-root /usr/bin/mandb --quiet 2> /dev/null || true

# Delete "lost+found" directory on recent file system creation
rmdir /media/dragora-root/lost+found 2> /dev/null || true


code:
# This file is part of the 'dragora-installer'.
#
# Purpose: Set super-user (root) password.

# Make sure to have /dev available for passwd(1)
if ! mountpoint -q /media/dragora-root/dev
then
    mount --bind /dev /media/dragora-root/dev
fi

while test "$(grep -m 1 "^root:" /media/dragora-root/etc/shadow | cut -f 2 -d :)" = x
do
    _status=0

    dialog --colors \
     --backtitle "\\ZbSystem administrator password" \
     --title "PASSWORD NOT DETECTED" \
     --ok-button "Continue" --msgbox \
"No password has been detected for the system administrator\\n\
(root) account.\\n\\nIt is important to set it in order to \
have access to the entire system.  Please do it now!" 10 62 || _status=$?
    if test $_status -eq 0
    then
        echo ""
        chroot /media/dragora-root /usr/bin/passwd root
        echo ""
        echo " To continue, press [Enter]..."
        IFS= read -r REPLY < /dev/tty || exit 2;
        unset -v REPLY
        continue;
    elif test $_status -eq 255
    then
        dialog \
         --title "System administrator password" \
         --defaultno --yesno \
"\\nAre you sure you want to leave this without a password?\\n\
You will not have full access to the system." 8 59 || continue;
    fi
    break;
done
unset -v _status

# Refresh shadow files
chroot /media/dragora-root /usr/sbin/shadowconfig off > /dev/null 2>&1 || true
chroot /media/dragora-root /usr/sbin/shadowconfig on  > /dev/null 2>&1 || true

dialog --clear


code:
# This file is part of the 'dragora-installer'.
#
# Purpose: Search to show the detected series of the found medium.

MEDIUM_SOURCE="$(cat -- ${SUBTMPDIR}/MediumFound)"
export MEDIUM_SOURCE

cat << EOF > ${SUBTMPDIR}/ShowSeries
dialog --colors \\
 --backtitle "\ZbChoosing the series" \\
 --title "SOFTWARE SERIES" \\
 --no-cancel --item-help --checklist \\
"The following series of software were found for installation.\n\n\\
Use the cursor keys and \\Z3[Space]\\Zn to deselect the software series\n\\
that you do not want to include.  Once ready, press \\Z3[Enter]\Zn to \
continue..." $(( LINES - 5 )) 68 12 \\
EOF

find -- "$MEDIUM_SOURCE" -type f \( -name '*@*.tlz' -a ! -name '*-pass*' \) \
 -exec sh -c 'name="${1##*@}"; name="${name%.tlz}"; echo "$name"' _ {} \; | \
  sort -u | while read -r category
do
    case $category in
    boot*)
        echo '"boot" "" ON "Necessary software to boot the system." \' >> ${SUBTMPDIR}/ShowSeries
        ;;
    compressors*)
        echo '"compressors" "" ON "Several compressors at user-level." \' >> ${SUBTMPDIR}/ShowSeries
        ;;
    daemons*)
        echo '"daemons" "" ON "System-related daemons." \' >> ${SUBTMPDIR}/ShowSeries
        ;;
    data*)
        echo '"data" "" ON "Essential configuration files." \' >> ${SUBTMPDIR}/ShowSeries
        ;;
    db*)
        echo '"db" "" ON "Databases such as BerkeleyDB, GDBM, and the system Time Zone Database (tzdb)." \' >> ${SUBTMPDIR}/ShowSeries
        ;;
    devel*)
        echo '"devel" "" ON "Compilers, programming languages and debuggers." \' >> ${SUBTMPDIR}/ShowSeries
        ;;
    dict*)
        echo '"dict" "" ON "Spell checker software and dictionaries." \' >> ${SUBTMPDIR}/ShowSeries
        ;;
    docbook*)
        echo '"docbook" "" ON "SGML and XML support for DocBook documents." \' >> ${SUBTMPDIR}/ShowSeries
        ;;
    gnupg*)
        echo '"gnupg" "" ON "The GNU privacy guard." \' >> ${SUBTMPDIR}/ShowSeries
        ;;
    kernel*)
        echo '"kernel" "" ON "The Linux-libre kernel and related." \' >> ${SUBTMPDIR}/ShowSeries
        ;;
    libs*)
        echo '"libs" "" ON "The system libraries." \' >> ${SUBTMPDIR}/ShowSeries
        ;;
    lua*)
        echo '"lua" "" ON "The Lua programming language and modules." \' >> ${SUBTMPDIR}/ShowSeries
        ;;
    manuals*)
        echo '"manuals" "" ON "The manual pages." \' >> ${SUBTMPDIR}/ShowSeries
        ;;
    networking*)
        echo '"networking" "" ON "Clients and servers for networking." \' >> ${SUBTMPDIR}/ShowSeries
        ;;
    perl*)
        echo '"perl" "" ON "The Perl programming language and modules." \' >> ${SUBTMPDIR}/ShowSeries
        ;;
    python*)
        echo '"python" "" ON "The Python programming language and modules." \' >> ${SUBTMPDIR}/ShowSeries
        ;;
    ruby*)
        echo '"ruby" "" ON "The Ruby programming language and modules." \' >> ${SUBTMPDIR}/ShowSeries
        ;;
    shells*)
        echo '"shells" "" ON "Command interpreters for the system." \' >> ${SUBTMPDIR}/ShowSeries
        ;;
    tools*)
        echo '"tools" "" ON "Tools and complements of the base system." \' >> ${SUBTMPDIR}/ShowSeries
        ;;
    x-apps*)
        echo '"x-apps" "" ON "A useful collection of applications for the X Window System." \' >> ${SUBTMPDIR}/ShowSeries
        ;;
    x-libs*)
        echo '"x-libs" "" ON "A useful collection of libraries for the X Window System." \' >> ${SUBTMPDIR}/ShowSeries
        ;;
    xorg_app*)
        echo '"xorg_app" "" ON "The X Window System applications." \' >> ${SUBTMPDIR}/ShowSeries
        ;;
    xorg_data*)
        echo '"xorg_data" "" ON "Bitmaps, cursor themes and configuration files." \' >> ${SUBTMPDIR}/ShowSeries
        ;;
    xorg_doc*)
        echo '"xorg_doc" "" ON "The X Window System documentation." \' >> ${SUBTMPDIR}/ShowSeries
        ;;
    xorg_driver*)
        echo '"xorg_driver" "" ON "Video and Input drivers for the X Window System." \' >> ${SUBTMPDIR}/ShowSeries
        ;;
    xorg_extra*)
        echo '"xorg_extra" "" ON "Extra libraries and essential utilities for the X Window System." \' >> ${SUBTMPDIR}/ShowSeries
        ;;
    xorg_font*)
        echo '"xorg_font" "" ON "The X Window System font files." \' >> ${SUBTMPDIR}/ShowSeries
        ;;
    xorg_lib*)
        echo '"xorg_lib" "" ON "The X Window System libraries." \' >> ${SUBTMPDIR}/ShowSeries
        ;;
    xorg_mesa*)
        echo '"xorg_mesa" "" ON "The Mesa 3D graphics library." \' >> ${SUBTMPDIR}/ShowSeries
        ;;
    xorg_proto*)
        echo '"xorg_proto" "" ON "The X Window System header(s) for development." \' >> ${SUBTMPDIR}/ShowSeries
        ;;
    xorg_util*)
        echo '"xorg_util" "" ON "The X Window System utilities." \' >> ${SUBTMPDIR}/ShowSeries
        ;;
    xorg_xcb*)
        echo '"xorg_xcb" "" ON "The XCB protocol." \' >> ${SUBTMPDIR}/ShowSeries
        ;;
    xorg_xserver*)
        echo '"xorg_xserver" "" ON "The X Window System server." \' >> ${SUBTMPDIR}/ShowSeries
        ;;
    tde_i18n*)
        echo '"tde_i18n" "" ON "Internationalization translations for TDE." \' >> ${SUBTMPDIR}/ShowSeries
        ;;
    tde*)
        echo '"tde" "" ON "The Trinity Desktop Environment (TDE)." \' >> ${SUBTMPDIR}/ShowSeries
        ;;
    *)
        echo "\"${category}\" \"\" ON \"Description not available.\" \\" >> ${SUBTMPDIR}/ShowSeries
        ;;
    esac
done

# Check if there are any detected series
if test ! -f ${SUBTMPDIR}/ShowSeries || test ! -s ${SUBTMPDIR}/ShowSeries
then
    echo "${PROGRAM}: Error no series found.  Aborting..." 1>&2
    exit 99;
fi
echo ' 2> ${SUBTMPDIR}/return-ShowSeries' >> ${SUBTMPDIR}/ShowSeries

touch ${SUBTMPDIR}/return-ShowSeries

. ${SUBTMPDIR}/ShowSeries;	# Show menu.
if test ! -f ${SUBTMPDIR}/return-ShowSeries || test ! -s ${SUBTMPDIR}/return-ShowSeries
then
    echo "${PROGRAM}: No series were selected.  Aborting..." 1>&2
    exit 99;
fi

# Append a new line for reading (this will be done from 'InstallPackages')
echo "" >> ${SUBTMPDIR}/return-ShowSeries


code:
#! /bin/bash -
# Specific script for the final Dragora release process.
#
# Copyright (c) 2021-2022 Matias Fonzo, <selk@dragora.org>.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

#
## ChangeLog (current version is 0.2).
#
#= Version 0.3:
#
# - Use the -f (force) option when building on the phase1.
#
#= Version 0.2:
#
# - Switch /bin/sh to /bin/bash for catching errors on pipes.
#
# - Upgrade packages on 'phase-2' to ensure no dependency on
#   /tools (temporary system) or to ensure possible system
#   breaks by cutting symbolic links using qi/graft.
#
#= Version 0.1:
#
# - Initial version.
#

set -e -o pipefail

rm -f /build-phase1-log.txt /build-phase2-log.txt

#
# Build all the packages to conform the final system.
#

echo ""
echo "*** Building Dragora for release [phase-1]..."
echo ""
echo "Using 1 parallel job for the compiler."
echo ""

qi order /usr/src/qi/recipes/*.order | \
 qi build -f -j1 -p -i - 2>&1 | tee build-phase1-log.txt

#
# Build all the important packages against the final system
#

# Variables.
#
# Parallel jobs for the final system (phase-2)
#
# The default is to use the maximum number of
# processors (physical/threading)
JOBS="${JOBS:-$(nproc)}"

# Declare recipes that do not require reconstruction:
exclude_list='!/pass-?|^data\/|docbook\/|xorg\/doc\/|xorg\/font\/|tde\/tde-i18n|devel\/fortify-headers|kernel\/headers|kernel\/generic|kernel\/buildtree-generic|kernel\/firmware|tools\/dragora-installer/'

echo ""
echo "*** Building Dragora for release [phase-2]..."
echo ""
echo "Using $JOBS parallel job(s) for the compiler."
echo ""

if test -d /tools
then
    mv -f /tools /tools-to-be-renamed
    sync
fi

qi order /usr/src/qi/recipes/*.order | awk "$exclude_list" | \
 qi build -f -j${JOBS} -p -u - 2>&1 | tee build-phase2-log.txt

unset -v JOBS exclude_list

if test -d /tools-to-be-renamed
then
    mv -f /tools-to-be-renamed /tools
    sync
fi

echo ""
echo "^^^ Done."
echo ""

path: archive/dragora-tools/build-for-release


code:
#! /bin/sh -
#
# A script to configure the keyboard map on console
#
# Copyright (c) 2019-2021 Matias Fonzo, <selk@dragora.org>.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Exit immediately on any error
set -e

PROGRAM="${0##*/}"
TMPDIR="${TMPDIR:-$HOME}"
TMPFILE="${TMPDIR}/.${PROGRAM}.${RANDOM-0}$$"
OUTPUT="${TMPFILE}.data"
LOCKFILE=/var/lock/dragora-keymap.lockfile
KEYMAPS="${KEYMAPS:-/usr/share/keymaps/i386}"

chkstatus_or_exit()
{
    status=$?

    # Clean up temporary files
    rm -f -- "$TMPFILE" "$LOCKFILE"

    if test $status -ne 0
    then
        printf '%s\n' "" "Return status = $status" 1>&2
        exit 2;
    fi

    unset -v status
}

# Sanity checks

if test ! -d "$TMPDIR"
then
    echo "${PROGRAM}: \`${TMPDIR}' is not a qualified temporary directory" 1>&2
    exit 1;
fi
if test ! -w "$TMPDIR"
then
    echo "${PROGRAM}: \`${TMPDIR}' is not a writable temporary directory" 1>&2
    exit 1;
fi
if test ! -d "$KEYMAPS"
then
    echo "${PROGRAM}: Directory \`${KEYMAPS}' for keyboard maps does not exist as such" 1>&2
    exit 1;
fi

trap 'chkstatus_or_exit' EXIT HUP INT QUIT ABRT TERM

umask 077;      # Remove access for all but user.

# Unfortunately, loadkeys(1) is limited to the superuser;
# we set a lock to allow only one instance of the script.

if ( set -C ; echo ": $PROGRAM - locked" > $LOCKFILE ) 2> /dev/null
then
    true
else
    if test -e "$LOCKFILE"
    then
        echo "Only one instance of \`${PROGRAM}' is allowed." 1>&2
        exit 1;
    else
        echo "${PROGRAM}: \`${LOCKFILE}' lock failed." 1>&2
        exit 2;
    fi
fi

### Search for keyboard map files

search="$(find "$KEYMAPS" \( -type l -o -type f \) -name '*.map*' -print | LC_ALL=C sort 2> /dev/tty)"

if test -z "$search"
then
    echo "No keyboard maps were found in \`${KEYMAPS}'." 1>&2
    exit 1;
fi

### Compose output file to be shown

# Header
printf '%s\n' \
 'dialog --colors \'                                         \
 ' --backtitle "\\Zb${PROGRAM} - Keyboard map selection" \'  \
 ' --title "MAIN MENU" --default-item "qwerty/us" --menu \'  \
 '"Welcome to \\Z3${PROGRAM}\\Zn!\\n\\n\'                    \
 'The following menu list is organized as keyboard \\n\'     \
 '\"layout/language\". \\n\\n\'                              \
 'Select a keyboard map for the console:" 20 56 6 \'         \
 > "$OUTPUT"

# Append 'search' to the body

for item in $search
do
    level="${item%/*}"		# Remove all except the last slash.
    level="${level##*/}"	# Starting-point under which it was found.
    item="${item%.map*}"	# Remove extension(s).
    item="${item##*/}"		# Get the base name.

    # Ignore unwanted map directories
    case $level in
    include | fgGIod)
        continue
        ;;
    *)
        echo "\"${level}/$item\"        \"\" \\" >> "$OUTPUT"
        ;;
    esac
done
unset -v item level search

# End of
printf "2> \$TMPFILE\\n\\n" >> "$OUTPUT"

# Import menu
. "$OUTPUT"

# Read answer from 'TMPFILE'

echo "" >> "$TMPFILE";		# Append new line for reading.
IFS= read -r REPLY < "$TMPFILE" || exit 2;

# Compose values by layout/map to be set

layout="${REPLY%/*}"
map="${REPLY##*/}"

unset -v REPLY

# Temporary files are not needed anymore
rm -f -- "$TMPFILE" "$OUTPUT"

umask 022;	# Remove write permission for group and other.

# Set keyboard map
loadkeys "${layout}/$map"

while true
do
    testkeys="$(
     dialog --colors \
      --no-mouse --no-cancel --no-ok \
      --backtitle "\\Zb${PROGRAM} - Keyboard map check" \
      --title "SELECTED KEYMAP: ${layout}/$map" \
      --inputbox \
"Try the chosen keyboard map by typing something.  Once satisfied\\n\
type \\Zb\\Z71\\Zn (or \\Zb\\Z7y\\Zn) then hit \\Zb\\Z7ENTER\\Zn \
to continue.  To choose a different keyboard map, type \\Zb\\Z72\\Zn (or \
\\Zb\\Z7n\\Zn) plus \\Zb\\Z7ENTER\\Zn." 10 68 2>&1 > /dev/tty
    )"
    case $testkeys in
    1 | Y | y)
        break
        ;;
    2 | N | n)
        rm -f -- "$LOCKFILE"
        exec "$0"
        ;;
    esac
done
unset -v testkeys

dialog --colors \
 --backtitle "\\Zb${PROGRAM} - Configuration file" \
 --title "/etc/rc.conf" --yesno \
"Would do you like to save this change for the next reboot?" 5 62
echo ""
echo "Setting 'RC_KEYMAP=${layout}/$map' on /etc/rc.conf ..."
echo ",s/^\\(RC_KEYMAP\\)=.*/\\1=${layout}\\/${map}/"$'\nw' | \
 ed /etc/rc.conf && echo Done.

path: archive/dragora-tools/dragora-keymap


code:
#! /bin/sh -
#
# A mouse configuration tool for gpm(8)
#
# Copyright (c) 2018-2021 Matias Fonzo, <selk@dragora.org>.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Exit immediately on any error
set -e

PROGRAM="${0##*/}"
TMPDIR="${TMPDIR:-$HOME}"
TMPFILE="${TMPDIR}/.${PROGRAM}.${RANDOM-0}$$"
LOCKFILE=/var/lock/dragora-mouse.lockfile

chkstatus_or_exit()
{
    status=$?

    # Clean up temporary files
    rm -f -- "$TMPFILE" "$LOCKFILE"

    if test $status -ne 0
    then
        printf '%s\n' "" "Return status = $status" 1>&2
        exit 2;
    fi

    unset -v status
}

# Sanity checks

if test ! -d "$TMPDIR"
then
    echo "${PROGRAM}: \`${TMPDIR}' is not a qualified temporary directory" 1>&2
    exit 1;
fi
if test ! -w "$TMPDIR"
then
    echo "${PROGRAM}: \`${TMPDIR}' is not a writable temporary directory" 1>&2
    exit 1;
fi

trap 'chkstatus_or_exit' EXIT HUP INT QUIT ABRT TERM

umask 077;	# Remove access for all but user.

# Unfortunately, gpm(8) is limited to the superuser;
# we set a lock to allow only one instance of the script.

if ( set -C ; echo ": $PROGRAM - locked" > $LOCKFILE ) 2> /dev/null
then
    true
else
    if test -e "$LOCKFILE"
    then
        echo "Only one instance of \`${PROGRAM}' is allowed." 1>&2
        exit 1;
    else
        echo "${PROGRAM}: \`${LOCKFILE}' lock failed." 1>&2
        exit 2;
    fi
fi

dialog --colors \
 --backtitle "\\Zb${PROGRAM} - Mouse Configuration" \
 --title "MAIN MENU" --menu \
"Welcome to \\Z3${PROGRAM}\\Zn!\\n\
    A configuration tool for the mouse selection.\\n\\n\
The following list is ordered by mouse type and brief description.\\n\
\\Zbp\\Zns2 is the most common model for laptops.  Otherwise, you can\\n\
select the \\Zbu\\Znsb model from the list below.\\n\\n\
Select a mouse type:" 20 71 6 \
"ps2"        "Common protocol for PS2 mice"                  \
"usb"        "Common protocol for USB mice"                  \
"bare"       "Microsoft compatible, 2 buttons"               \
"exps2"      "IntelliMouse Explorer, 3 buttons"              \
"imps2"      "Microsoft Intellimouse, 2 or 3 buttons"        \
"js"         "Mouse emulation with a Joystick"               \
"logi"       "Logitech devices"                              \
"logim"      "Logitech into Mouse-Systems compatible"        \
"mman"       "The MouseMan and similar devices"              \
"ms"         "Microsoft-compatible, 3 buttons"               \
"ms3"        "Microsoft Intellimouse, 3 buttons"             \
"msc"        "Mouse-Systems compatible, most 3-button mice"  \
"ncr"        "Ncr3125pen found on some laptops"              \
"netmouse"   "Genius NetMouse, 4 buttons"                    \
"pnp"        "Plug and Play mice, does not work with 'ms'"   \
"twid"       "Twidddler keyboard"                            \
"acecad"     "Acecad tablet, in absolute mode"               \
"genitizer"  "Genitizer tablet, in relative mode"            \
"wacom"      "Wacom Protocol IV tablets"                     \
"wp"         "Genius WizardPad tablet"                       \
2> "$TMPFILE"

# Read answer from 'TMPFILE'

echo "" >> "$TMPFILE";		# Append new line for reading.
IFS= read -r REPLY < "$TMPFILE" || exit 2;

# Check cases to determine the corresponding device name

case $REPLY in
ps2 | imps2 | exps2 | ncr | netmouse)
    DEVICE=psaux
    ;;
usb)
    REPLY=imps2
    DEVICE=input/mice
    ;;
acecad | bare | genitizer | logi* | twid | wacom | mman | ms* | pnp | wp)
    dialog --colors \
     --backtitle "\\Zb${PROGRAM} - Serial Port" \
     --title "MOUSE DEVICE" \
     --no-cancel --menu \
"The protocol \\Zb\\Z1${REPLY}\\Zn requires a serial port.\\n\\n\
Which device name would you like to use?" 13 52 4 \
      "ttyS0"  "Serial port 0, COM1 under DOS" \
      "ttyS1"  "Serial port 1, COM2 under DOS" \
      "ttyS2"  "Serial port 2, COM3 under DOS" \
      "ttyS3"  "Serial port 3, COM4 under DOS" \
    2> "$TMPFILE"
    echo "" >> "$TMPFILE";	# Append new line for reading.
    IFS= read -r DEVICE < "$TMPFILE" || exit 2;
    ;;
js)
    DEVICE=js0
    ;;
esac

# Temporary file is not needed anymore
rm -f -- "$TMPFILE"

umask 022;	# Remove write permission for group and other.

printf '%s\n' \
 "#! /bin/sh -"                                                      \
 "# Stop/Start gpm(8) the mouse server."                             \
 "# Automatically generated by dragora-mouse(8)."                    \
 ""                                                                  \
 "if pidof gpm > /dev/null"                                          \
 "then"                                                              \
 "    echo \"Stopping running gpm instance: gpm -k\""                \
 "    if ! gpm -k"                                                   \
 "    then"                                                          \
 "        echo \"Sending the TERM signal to gpm\""                   \
 "        killall -TERM gpm"                                         \
 "    fi"                                                            \
 "    sleep 1"                                                       \
 "fi"                                                                \
 ""                                                                  \
 "echo \"(Startup) Starting gpm: gpm -m /dev/${DEVICE} -t $REPLY\""  \
 "gpm -m /dev/${DEVICE} -t $REPLY"                                   \
 ""                                                                  \
 > /etc/rc.d/rc.gpm-sample
chmod 755 /etc/rc.d/rc.gpm-sample

dialog --colors \
 --backtitle "\\Zb${PROGRAM} - Startup File" \
 --title "RUN CONTROL" --yesno \
"A run control file could be created to load your settings\\n\
at boot time.  The file will be saved as \\Z1/etc/rc.d/rc.gpm\\Zn\\n\\n\
Would you like to load this file at boot time?" 8 63 && \
  mv -f -- /etc/rc.d/rc.gpm-sample /etc/rc.d/rc.gpm

dialog --colors \
 --backtitle "\\Zb${PROGRAM} - Mouse Session" \
 --title "MOUSE SESSION" --yesno \
"\\ZbGPM\\Zn is a cut and paste utility and mouse server for \
virtual consoles.  It is useful to avoid typing everything by \
hand\\Zb!\\Zn\\n\\n\
Would you like to run it now?" 9 58
echo ""
echo "Stopping any running gpm instance"
gpm -k 2> /dev/null || killall gpm 2> /dev/null || true;
sleep 1
echo ""
echo "Starting gpm: gpm -m /dev/${DEVICE} -t $REPLY"
gpm -m /dev/${DEVICE} -t $REPLY

path: archive/dragora-tools/dragora-mouse


code:
# dwm version
VERSION = 6.1

# Customize below to fit your system

# paths
PREFIX = /usr
MANPREFIX = ${PREFIX}/share/man

X11INC = /usr/include/X11
X11LIB = /usr/lib/X11

# Xinerama, comment if you don't want it
XINERAMALIBS  = -lXinerama
XINERAMAFLAGS = -DXINERAMA

# freetype
FREETYPELIBS = -lfontconfig -lXft
FREETYPEINC = /usr/include/freetype2
# OpenBSD (uncomment)
#FREETYPEINC = ${X11INC}/freetype2

# includes and libs
INCS = -I${X11INC} -I${FREETYPEINC}
LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS}

# flags
CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
#CFLAGS   = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS}
CFLAGS   = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS}
LDFLAGS  = ${LIBS}

# Solaris
#CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\"
#LDFLAGS = ${LIBS}

# compiler and linker
CC = cc


code:
[Desktop Entry]
Encoding=UTF-8
Name=Dwm
Comment=Dynamic Window Manager
Exec=dwm
Icon=dwm
Type=XSession


code:
#! /bin/sh -

userresources=$HOME/.Xresources
usermodmap=$HOME/.Xmodmap
sysresources=/etc/X11/xinit/.Xresources
sysmodmap=/etc/X11/xinit/.Xmodmap

# merge in defaults and keymaps

if [ -f $sysresources ]; then
    xrdb -merge $sysresources
fi

if [ -f $sysmodmap ]; then
    xmodmap $sysmodmap
fi

if [ -f "$userresources" ]; then
    xrdb -merge "$userresources"
fi

if [ -f "$usermodmap" ]; then
    xmodmap "$usermodmap"
fi

# Start dwm, display status info in the bar

while xsetroot -name "$(date) $(uptime | sed 's/.*,//')"
do
    sleep 1
done &
exec dwm

path: archive/dwm/xinitrc-dwm


code:
#ifndef _ERROR_H_
#define _ERROR_H_

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

static unsigned int error_message_count = 0;

static inline void error(int status, int errnum, const char* format, ...)
{
	va_list ap;
	fprintf(stderr, "%s: ", program_invocation_name);
	va_start(ap, format);
	vfprintf(stderr, format, ap);
	va_end(ap);
	if (errnum)
		fprintf(stderr, ": %s", strerror(errnum));
	fprintf(stderr, "\n");
	error_message_count++;
	if (status)
		exit(status);
}

#endif	/* _ERROR_H_ */


code:
#
# /etc/fstab - Static information about the filesystems.
#
# For more information, type "man 5 fstab".
#
# Filesystem	Mountpoint	Type	Options			Dump/Check
tmp		/tmp		tmpfs	defaults		0 0

path: archive/etc/fstab


code:
root:x:0:root
bin:x:1:root,bin
daemon:x:2:root,bin,daemon
sys:x:3:root,bin,sys
adm:x:4:bin,adm,log
tty:x:5:
kmem:x:6:
tape:x:7:
uucp:x:8:uucp
dialout:x:9:uucp
floppy:x:10:
disk:x:11:
scanner:x:12:
lp:x:13:lp
cdrom:x:14:
audio:x:15:
video:x:16:
plugdev:x:17:
netdev:x:18:
input:x:19:
games:x:20:
mail:x:21:
news:x:22:
utmp:x:23:
wheel:x:24:
shadow:x:25:
locate:x:26:
log:x:27:
kvm:x:28:
messagebus:x:30:
sshd:x:31:
nobody:x:98:nobody
nogroup:x:99:
users:x:100:

path: archive/etc/group


code:
root:x::root
bin:x::root,bin
daemon:x::root,bin,daemon
sys:x::root,bin,sys
adm:x::bin,adm,log
tty:x::
kmem:x::
tape:x::
uucp:x::uucp
dialout:x::uucp
floppy:x::
disk:x::
scanner:x::
lp:x::lp
cdrom:x::
audio:x::
video:x::
plugdev:x::
netdev:x::
input:x::
games:x::
mail:x::
news:x::
utmp:x::
wheel:x::
shadow:x::
locate:x::
log:x::
kvm:x::
messagebus:x::
sshd:x::
nobody:x::nobody
nogroup:x::
users:x::

path: archive/etc/gshadow


code:
#
# /etc/host.conf - Resolver configuration file.
#
# For more information, type "man 5 host.conf".
#
order hosts,bind
multi on


code:
#
# /etc/hosts - Static table lookup for host names.
#
# Syntax: IP_address canonical_hostname [aliases...]
#
# For more information, type "man 5 hosts".
#

# The following lines are desirable for IPv4 capable hosts
127.0.0.1	localhost

# 127.0.1.1 is often used for the FQDN of the machine
127.0.1.1	localhost.localdomain	localhost
#192.168.1.10	foo.mydomain.org	foo
#192.168.1.13	bar.mydomain.org	bar

# The following lines are desirable for IPv6 capable hosts
::1	localhost ip6-localhost ip6-loopback
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters

path: archive/etc/hosts


code:
# /etc/inittab:
#
# The inittab(5) file describes which processes are started at
# boot-up and during normal operation distinguishes multiple
# runlevels, each of which can have its own set of processes
# that are started.
#
# Copyright (c) 2018, 2021 Matias Fonzo, <selk@dragora.org>.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Init runlevels in Dragora
#  0  =  Halt or power-off
#  1  =  Single-user mode
#  2  =  -> 3
#  3  =  Multi-user mode
#  4  =  X Window sessions
#  5  =  ^ 4
#  6  =  Reboot

# Set default runlevel
id:3:initdefault:

# System initialization
si::sysinit:/etc/rc.d/rc.startup

# Runlevel scripts
r0:0:wait:/etc/rc.d/rc.shutdown
r1:1S:wait:/etc/rc.d/rc.single
r3:2345:wait:/etc/rc.d/rc.multiuser
r4:45:respawn:/etc/rc.d/rc.x11
r6:6:wait:/etc/rc.d/rc.reboot

# What to do when the "magic keys" are pressed
ca::ctrlaltdel:/sbin/shutdown -t 3 -r now

# Virtual consoles to log in
c1:123:respawn:/sbin/agetty --noclear tty1 38400 linux
c2:123:respawn:/sbin/agetty tty2 38400 linux
c3:12345:respawn:/sbin/agetty tty3 38400 linux
#c4:12345:respawn:/sbin/agetty tty4 38400 linux
#c5:12345:respawn:/sbin/agetty tty5 38400 linux
#c6:12345:respawn:/sbin/agetty tty6 38400 linux

# Local serial lines
#s1:12345:respawn:/sbin/agetty -L always ttyS0 115200 vt100
#s2:12345:respawn:/sbin/agetty -L always ttyS1 115200 vt100

path: archive/etc/inittab


code: Dragora GNU+\s-libre \r (\l) \t

path: archive/etc/issue


code:
    * To set up a keyboard map, type: dragora-keymap
    * To set the mouse to console, type: dragora-mouse
    * To run the installer, type: dragora-installer

https://www.dragora.org

path: archive/etc/motd


code:
NAME=Dragora
VERSION=3.0.0
ID=dragora
VERSION_CODENAME=D3
VERSION_ID=3.0.0
PRETTY_NAME="Dragora GNU/Linux-Libre 3.0.0 (D3)"
HOME_URL=https://www.dragora.org
BUILD_ID=20191014

path: archive/etc/os-release


code:
#
# /etc/profile - System-wide startup file for shells.
#

# Compose system path resetting the Input Field Separator
IFS='
 	'
PATH="${PATH}:/usr/local/games:/usr/games"

# Default mask: remove write permission for group and other
umask 022

# Set basic primary prompt
PS1='$PWD \$ '

# Set default terminal type if unset
test -n "${TERM+$TERM}" || TERM=linux

# Set default classification and conversion of characters
LC_CTYPE=C.UTF-8

export PATH LC_CTYPE

# Load profile(s)
for script in /etc/profile.d/*.sh
do
    if test -r "$script"
    then
        . "$script"
    fi
done
unset -v script

path: archive/etc/profile


code:
#
# /etc/rc.conf - System configuration information.
#

RC_HWCLOCK=utc
RC_HOSTNAME=dragora
RC_ESPEAKUP=off
RC_ESPEAKUP_VOICE=default
RC_KEYMAP=qwerty/us
RC_BLANKTIME=15


code:
#! /bin/sh -
#
# /etc/rc.d/rc.local - Local instructions for the boot process.
#


code:
#! /bin/sh -
#
# Multi-user mode script
#
# Copyright (c) 2018-2022 Matias Fonzo, <selk@dragora.org>.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# To reflect the name of this script
RC="[${0##*/}]"

umask 022
IFS='
 	'
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/usr/sbin:/bin:/usr/bin
LC_ALL=C

### X11-related database

echo "${RC}: Updating X11 database (X.Org), if available"

echo "${RC}: X font index cache ..."
if command -v mkfontscale > /dev/null
then
    for directory in /usr/share/fonts/X11/*
    do
        if test ! -e "${directory}/fonts.dir"
        then
            echo "Using \`mkfontscale' for missing fonts.dir at $directory" 1>&2
            mkfontscale -b -s -l "$directory" && mkfontscale "$directory"
        fi
    done
    unset -v directory
fi

echo "${RC}: fontconfig cache: fc-cache --system-only /usr/share/fonts/X11 &"
if command -v fc-cache > /dev/null
then
    fc-cache --system-only /usr/share/fonts/X11 &
else
    echo "    Could not find fc-cache(1)" 1>&2
fi

echo "${RC}: GTK+-2.0 modules: gtk-query-immodules-2.0 --update-cache &"
if command -v gtk-query-immodules-2.0 > /dev/null
then
    gtk-query-immodules-2.0 --update-cache &
else
    echo "    Could not find gtk-query-immodules-2.0" 1>&2
fi

echo "${RC}: GTK+-3.0 modules: gtk-query-immodules-3.0 --update-cache &"
if command -v gtk-query-immodules-3.0 > /dev/null
then
    gtk-query-immodules-3.0 --update-cache &
else
    echo "    Could not find gtk-query-immodules-3.0" 1>&2
fi

echo "${RC}: GDK pixbuffer loaders: gdk-pixbuf-query-loaders --update-cache &"
if command -v gdk-pixbuf-query-loaders > /dev/null
then
    gdk-pixbuf-query-loaders --update-cache &
else
    echo "    Could not find gdk-pixbuf-query-loaders(1)" 1>&2
fi

echo "${RC}: Glib schemas: glib-compile-schemas /usr/share/glib-2.0/schemas"
if command -v glib-compile-schemas > /dev/null
then
    if test -r /usr/share/glib-2.0/schemas
    then
        glib-compile-schemas /usr/share/glib-2.0/schemas
    else
        echo "    Could not read /usr/share/glib-2.0/schemas" 1>&2
    fi
else
    echo "    Could not find glib-compile-schemas(1)" 1>&2
fi

echo "${RC}: MIME database: update-mime-database /usr/share/mime &"
if command -v update-mime-database > /dev/null
then
    update-mime-database /usr/share/mime &
else
    echo "    Could not find update-mime-database(1)" 1>&2
fi

echo "${RC}: Desktop database: update-desktop-database -q &"
if command -v update-desktop-database > /dev/null
then
    update-desktop-database -q &
else
    echo "    Could not find update-desktop-database(1)" 1>&2
fi

### ^ End Of 'X11-related database'

# Start FUSE filesystem

if test -x /etc/rc.d/rc.fuse
then
    /etc/rc.d/rc.fuse start
fi

# Start services through perpd(8) instances

echo "${RC}: Starting process supervisor under perpd(8) instances"
if ! pidof perpd > /dev/null
then
    perpboot -d /etc/perp
else
    echo "    perpd(8) is already running." 1>&2
fi

# Start GPM (General Purpose Mouse daemon)

if test -x /etc/rc.d/rc.gpm
then
    /etc/rc.d/rc.gpm
fi

# Verify the /etc/fstab file to activate the quota file system

echo "${RC}: Checking quota availability"
if grep -E -q -m 1 '(usr|grp)quota' /etc/fstab
then
    echo "${RC}: Checking /etc/fstab for quota usage"
    if quotacheck -vugcm
    then
        echo "${RC}: Turning ON quota file system: quotaon -vaug"
        quotaon -vaug
    fi
else
    echo "${RC}: No quota filesystem declared on /etc/fstab." 1>&2
fi

# Start user-local instructions

if test -x /etc/rc.d/rc.local
then
    echo "${RC}: Running /etc/rc.d/rc.local"
    /etc/rc.d/rc.local
fi


code:
#! /bin/sh -
#
# Prepare to halt or reboot the system
#
# Copyright (c) 2017-2021 Matias Fonzo, <selk@dragora.org>.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# To reflect the name of this script
RC="[${0##*/}]"

umask 022
IFS='
 	'
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/usr/sbin:/bin:/usr/bin
LC_ALL=C

# Set linefeed mode to avoid staircase effect
stty onlcr 0>&1

# Be immune to the following signals
trap "" HUP INT QUIT ABRT TERM

# Save system clock

if grep -q '^RC_HWCLOCK=local' /etc/rc.conf
then
    echo "${RC}: Saving hardware clock in local time"
    hwclock --systohc --localtime
else
    echo "${RC}: Saving hardware clock in UTC"
    hwclock --systohc --utc
fi

# Stop any quota file system (if needed)

if grep -E -q -m 1 '(usr|grp)quota' /etc/fstab
then
    echo "${RC}: Setting any quota file system to OFF"
    quotaoff -va
fi

# Save the random number generator, see random(4)

echo "${RC}: Saving random number generator"
echo "    /dev/urandom <-> /etc/random-seed ..."

# Get the pool size from /proc or use a default value
size="$(cat /proc/sys/kernel/random/poolsize)" || size=512

# Save seed file containing the whole entropy pool
dd if=/dev/urandom of=/etc/random-seed count=1 bs=$size
chmod 600 /etc/random-seed; unset -v size

# Try to write a login record (at /var/log/wtmp)
halt -w

# Flush file system buffers, update super block
sync

# Stop FUSE filesystem
if test -x /etc/rc.d/rc.fuse
then
    /etc/rc.d/rc.fuse stop > /dev/null
fi

# Kill all processes, except the one that is currently running
echo "${RC}: Sending the TERM signal to all the processes"
killall5 -15 -o $$
sleep 9

echo "${RC}: Deactivating swap devices"
swapoff -v -a

echo "${RC}: Unmounting local and remote file systems"
umount -v -a -r
sleep 1
sync

echo "${RC}: Remounting root filesystem in read-only mode"
mount -v -n -o remount,ro /

# Wait for completion of all the processes
wait

# Reboot, or halt the system
case $0 in
*.reboot)
    echo "Rebooting ..."
    exec reboot -d -f
    ;;
*)
    exec halt -d -f -p
    ;;
esac


code:
#! /bin/sh -
#
# Single-user mode script
#
# Copyright (c) 2018, 2020 Matias Fonzo, <selk@dragora.org>.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

RC="[${0##*/}]"	# To reflect the name of the script between [].
IFS='
 	'
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/usr/sbin:/bin:/usr/bin
LC_ALL=C

echo ""
echo "Entering to single-user mode ..."

# Stop any quota file system (if needed)

if grep -E -q -m 1 '(usr|grp)quota' /etc/fstab
then
    echo "${RC}: Setting any quota file system to OFF"
    quotaoff -va
fi

# Be immune to the following signals
trap "" HUP INT QUIT ABRT TERM

echo "${RC}: Sending the HUP signal to all the processes"
killall5 -1 -o $$
sleep 7

echo "${RC}: Sending the TERM signal to all the processes"
killall5 -15 -o $$
sleep 9

exec telinit 1


code:
#! /bin/sh -
#
# Boot-time system initialization script
#
# Copyright (c) 2017-2022 Matias Fonzo, <selk@dragora.org>.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

RC="[${0##*/}]"	# To reflect the name of the script between [].
umask 022
IFS='
 	'
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/usr/sbin:/bin:/usr/bin
LC_ALL=C

### Mount virtual file systems

echo "${RC}: Mounting kernel based file systems"
mount -v -n -o nosuid,noexec,nodev -t proc proc /proc
mount -v -n -o nosuid,noexec,nodev -t sysfs sysfs /sys
if ! mountpoint -q /dev
then
    mount -v -n -t devtmpfs devtmpfs /dev
fi
mkdir -p /dev/pts /dev/shm /run
mount -v -n -o mode=0620,gid=5 -t devpts devpts /dev/pts
mount -v -n -o defaults -t tmpfs devshm /dev/shm
mount -v -n -o defaults -t tmpfs tmpfs /run
mkdir -p /run/lock
chmod 1777 /run/lock /dev/shm

### ^ End Of 'Mount virtual file systems'

### Start the dynamic device management

echo "${RC}: Starting event managing daemon: udevd --daemon"
udevd --daemon

# Request device uevents to replay events at system coldplug
udevadm trigger --type=subsystems --action=add
udevadm trigger --type=devices    --action=add
udevadm trigger --type=devices    --action=change

echo "${RC}: Waiting for pending udev events: udevadm settle --timeout=80"
udevadm settle --timeout=80

### ^ End Of 'Start the dynamic device management'

# Re-mount the root filesystem in *read-only mode*, if needed
if test -w /
then
    echo "${RC}: Remounting root filesystem in read-only mode"
    mount -v -n -o remount,ro /
fi

### Mount control groups

if grep -q cgroup /proc/filesystems
then
    if test -d /sys/fs/cgroup
    then
        echo "${RC}: Mounting Cgroup controllers (version 1)"

        # Cgroup controllers v1 must be mounted against a tmpfs(5)
        mount -v -n -t tmpfs cgroup_root /sys/fs/cgroup

        # Comount all v1 controllers against the same hierarchy
        mount -v -n -t cgroup cgroup /sys/fs/cgroup
    fi
fi

### ^ End Of 'Mount control groups'

### Initialization of the Logical Volume Manager (version 2)

if lvm version
then
    echo "${RC}: LVM2: Scanning for new volume groups"
    modprobe dm-mod
    vgscan --mknodes --ignorelockingfailure 2> /dev/null && \
    vgchange --ignorelockingfailure -a y
fi

### ^ End Of 'Initialization of the Logical Volume Manager (version 2)'

# Activate swap partition if any available
swapon -a

### Set system clock (1/2)

# Avoid unnecessary fsck runs at boot time, especially for
# already existing (multiple) systems not designed for UTC
hwclock --hctosys --localtime

### Perform file system checks

echo "${RC}: Performing file system checks"
if test ! -f /fastboot
then
    # Limit number of filesystem checkers using the max. number of processors
    FSCK_MAX_INST=$(nproc 2> /dev/null) || FSCK_MAX_INST=1

    # Force checks if the regular file '/forcefsck' exists
    test -f /forcefsck && forcefsck_flag=-f

    echo "*** Checking root file system"
    fsck $forcefsck_flag -a -C
    status=$?

    if test $status -gt 1
    then
        if test $status -eq 32
        then
            echo "fsck(8) canceled by user request." 1>&2
        else
            if test $status -ge 4
            then
                printf '%s' 1>&2 \
"^ Return status = $status
"'A maintenance shell will be started ...

If you do not know how to correct the file system errors,
please see the filesystem-specific checker manual pages for
further details.
'
                unset -v FSCK_MAX_INST forcefsck_flag status
                sulogin || {
                    echo "Executing \`/bin/sh' as emergency shell ..." 1>&2
                    /bin/sh -
                }
            fi
            echo "The system will be restarted now."
            umount -v -n -a -r
            mount -v -n -o remount,ro /
            reboot -n -f;
            exit 99
        fi
    fi
    unset -v status

    echo "*** Checking local file system(s)"
    fsck $forcefsck_flag -A -C -R -T -a

    unset -v FSCK_MAX_INST forcefsck_flag
else
    echo "WARNING: /fastboot is present: Ignoring checks" 1>&2
fi

### ^ End Of 'Perform file system checks'

### Parse config file

# The given values on /proc/cmdline have priority
# over those present at "/etc/rc.conf"
if grep -q -m 1 RC_ /proc/cmdline
then
    tr -s '[:space:]' '[\n*]' < /proc/cmdline | \
     while IFS='=' read -r variable value
     do
         case $variable in
         RC_?*)
             # Set variable value avoiding possible code execution
             eval "$variable=\${value}"
             ;;
         esac
     done
fi
if test -f /etc/rc.conf
then
    while IFS='=' read -r variable value
    do
        case $variable in
        RC_?*)
            if test -z "$variable"
            then
                eval "$variable=\${value}"
            fi
            ;;
        esac
    done < /etc/rc.conf
fi

# Use default values if the following variables are not defined

RC_HWCLOCK="${RC_HWCLOCK:-utc}"
RC_HOSTNAME="${RC_HOSTNAME:-dragora}"
RC_ESPEAKUP="${RC_ESPEAKUP:-off}"
RC_EVOICE="${RC_ESPEAKUP_VOICE:-default}"
RC_KEYMAP="${RC_KEYMAP:-qwerty/us}"
RC_BLANKTIME="${RC_BLANKTIME:-15}"

### ^ End Of 'Parse config file'

### Set system clock (2/2)

if test "$RC_HWCLOCK" = utc
then
    echo "${RC}: Setting system time from the hardware clock to UTC"
    hwclock --hctosys --utc
else
    echo "${RC}: The system time was already set to local time" 1>&2
fi
unset -v RC_HWCLOCK

### ^ End Of 'Set system clock'

# Re-mount the root filesystem in *read-write mode*

echo "${RC}: Remounting root filesystem in read-write mode ..."
if ! test -w /
then
    mount -v -n -o remount,rw /
else
    echo "    The root filesystem is already in read-write mode." 1>&2
fi

# Mount local file systems only

echo "${RC}: Mounting of local file systems declared in /etc/fstab"
mount -v -a -t no,proc,sysfs,devtmpfs,shm,devpts,usbfs,cifs,smbfs,nfs

# Activate swap partitions or swap files

echo "${RC}: Activating swap devices, if any ..."
swapon -v -a

# Update kernel modules

if test -s "/lib/modules/$(uname -r)/modules.dep"
then
    echo "${RC}: Refreshing kernel module list: depmod --quick"
    depmod --quick
else
    echo "${RC}: Generating kernel module dependency list: depmod --all"
    depmod --all
fi

# Re-create hierarchy for temporary files (if needed)

mkdir -p /tmp /tmp/.font-unix /tmp/.ICE-unix /tmp/.X11-unix
chmod 1777 /tmp /tmp/.font-unix /tmp/.ICE-unix /tmp/.X11-unix

# Re-create file records for logins and logouts
touch \
 /var/log/btmp /var/log/lastlog /var/log/faillog /var/log/wtmp /var/run/utmp
chgrp utmp /var/log/lastlog /var/run/utmp
chmod 664 /var/log/lastlog /var/run/utmp
chmod 600 /var/log/btmp

# Seek and destroy temporary files

rm -f /etc/nologin /fastboot /forcefsck

# Set default system host name

echo "$RC_HOSTNAME" > /proc/sys/kernel/hostname
unset -v RC_HOSTNAME

# Set kernel parameters at runtime

echo "${RC}: Setting kernel parameters: sysctl -q --system"
sysctl -q --system

# Start the loopback device

echo "${RC}: Starting loopback device ..."
if ip -Version
then
    ip addr del 127.0.0.1/8 dev lo 2> /dev/null
    ip addr add 127.0.0.1/8 dev lo brd + scope host
    ip link set lo up
elif ifconfig --version
then
    ifconfig lo up
fi

# Initialize the random number generator, see random(4)

echo "${RC}: Initializing random number generator"
echo "    /etc/random-seed <-> /dev/urandom ..."

touch /etc/random-seed
if test -s /etc/random-seed
then
    cat /etc/random-seed > /dev/urandom
fi

# Get the pool size from /proc or use a default value
size="$(cat /proc/sys/kernel/random/poolsize)" || size=512

# Save seed file containing the whole entropy pool
dd if=/dev/urandom of=/etc/random-seed count=1 bs=$size
chmod 600 /etc/random-seed; unset -v size

### Configure ISA Plug-and-Play devices (legacy)

if command -v isapnp > /dev/null && command -v pnpdump > /dev/null
then
    if test -e /etc/isapnp.conf
    then
        echo "${RC}: Setting ISA PnP devices using /etc/isapnp.conf"
        isapnp /etc/isapnp.conf
    else
        echo "${RC}: Creating resource information for ISA PnP devices"
        pnpdump > /etc/isapnp.conf

        echo "${RC}: Setting devices from the new /etc/isapnp.conf"
        isapnp /etc/isapnp.conf
    fi
fi

### ^ End Of 'Configure ISA Plug-and-Play devices (legacy)'

# Start sound or speech engine

if test -x /etc/rc.d/rc.alsa
then
    /etc/rc.d/rc.alsa start
fi
if test "$RC_ESPEAKUP" != off
then
    echo "${RC}: Activating software synthesizer: espeakup -V $RC_ESPEAKUP_VOICE"
    modprobe speakup_soft
    espeakup -V "$RC_ESPEAKUP_VOICE"
fi
unset -v RC_ESPEAKUP RC_ESPEAKUP_VOICE

# Load keyboard map, set terminal attributes

echo "${RC}: Loading keyboard map: loadkeys $RC_KEYMAP"
loadkeys "$RC_KEYMAP"
unset -v RC_KEYMAP

echo "${RC}: Setting screen blanking interval: setterm -blank $RC_BLANKTIME"
setterm -blank "$RC_BLANKTIME"
unset -v RC_BLANKTIME


code:
#! /bin/sh -
#
# Multi-user mode with X11 session manager
#
# Copyright (c) 2018, 2020-2021 Matias Fonzo, <selk@dragora.org>.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# To reflect the name of this script
RC="[${0##*/}]"

umask 022
IFS='
 	'
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin:/opt/trinity/bin
LC_ALL=C

echo ""
echo "${RC}: Looking for a graphical session manager ..."

command -v gdm && exec gdm -nodaemon
command -v kdm && exec kdm -nodaemon
command -v tdm && exec tdm -nodaemon
command -v xdm && exec xdm -nodaemon

# Setback to INIT 3 in case of failure

echo ""
echo "    If this message appears, it means that you do not have any"
echo "of the following combinations of session managers installed:"
echo "GDM, KDM, TDM, or XDM."
echo ""
exec telinit 3


code:
#
# /etc/securetty - Lists of terminals from which root can log in.
#
# For more information, type "man 5 securetty".
#

# Physical consoles
console
tty1
tty2
tty3
tty4
tty5
tty6
tty7
tty8
tty9
tty10
tty11
tty12

# UART serial ports (remote TTYs)
#ttyS0
#ttyS1
#ttyS2
#ttyS3
#ttyS4
#ttyS5
#ttyS6
# 192nd UART serial port
#ttyS191

path: archive/etc/securetty


code:
#
# /etc/shells - List of valid login shells.
#
/bin/sh
/bin/mksh
/bin/bash

path: archive/etc/shells


code:
#
# .bashrc - Individual per-interactive-shell startup file (GNU Bash).
#

# Set primary prompt
PS1='\u@\h:\w\$ '

# Secondary prompt string
PS2='> '

# Extended pattern matching language
shopt -s extglob