Using case select in ash/init hook

I have an mkinitcpio hook for bcachefs which allows the user to boot into a snapshot or rollback the system upon boot.

Here is the hook program in its entirety:

Here is the hook code:

#!/usr/bin/bash


#			*** Make sure 'LABEL' matches your root system label !! ***
#			You can find this using the command 'blkid'

LABEL=ROOT-laptop

# $root (or /@root) will be where all the system files are stored once you've made a snapshot
# to /@root. At that point you'll be able to delete all the files in your original / directory
# (with the exception of .snapshots and @root) by issuing the 'delete root system' option 
# in the menu. From then on /@root will be where all your new system files will reside
root='/@root'

snapshot_dir=/.snapshots


run_latehook() {

	#/usr/lib/initcpio/init

	new_root=/new_root
	mkdir -p $new_root

	mnt=/mnt

	mount -m LABEL="$LABEL" $mnt
	
	cd $mnt$snapshot_dir

	echo -e "\nWhat would you like to do?

<s> boot into a snapshot
<r> restore snapshot
<b> boot root system
<d> delete root system
<e> enter bash

<ENTER> boot @root\n"

	read -s -t 15 -n 1 key

	if [[ "$key" = 's' ]]; then
	
		echo -e "\nType the name of the snapshot you would like to load.\n"
		
		ls "$mnt$snapshot_dir"

		echo

		read snapshot
	
		if [ -d "$snapshot" ]; then

			umount $new_root
			mount --bind "$mnt$snapshot_dir/$snapshot" $new_root
			mount --mkdir --bind "$mnt$snapshot_dir" "$new_root$snapshot_dir"

		else
			
			echo -e "\nThe snapshot \'snapshot\' does not exist!\n"
			
			sleep 2

			mount --bind $mnt $new_root
			mount --mkdir --bind "$mnt$snapshot_dir" "$new_root$snapshot_dir"

		fi
	
	elif [[ "$key" = 'b' ]]; then
	
		umount $new_root
		mount --bind $mnt $new_root
		mount --mkdir --bind "$mnt$snapshot_dir" "$new_root$snapshot_dir"

	elif [[ "$key" = 'r' ]]; then

		echo -e "\nType the name of the snapshot you would like to recover to @root.\n"
		
		ls

		echo

		read snapshot
	
		if [ -d "$snapshot" ]; then
			
			umount $new_root
			
			if [ -d "$mnt$snapshot_dir$root-old" ]; then
				bcachefs subvolume delete "$mnt$snapshot_dir$root-old"
				rm -rf "$mnt$snapshot_dir$root-old"
			fi

			if [ -d "$mnt$root" ]; then
				bcachefs subvolume snapshot "$mnt$root" "$mnt$snapshot_dir$root-old"
				bcachefs subvolume delete $mnt$root
				rm -rf $mnt$root
			fi

			bcachefs subvolume snapshot "$mnt$snapshot_dir/$snapshot" $mnt$root

			mount --bind $mnt$root $new_root
			mount --mkdir --bind "$mnt$snapshot_dir" "$new_root$snapshot_dir"

		else
			
			echo -e "\nThe snapshot \'snapshot\' does not exist!\n"
			
			sleep 2

			mount --bind $mnt $new_root
			mount --mkdir --bind "$mnt$snapshot_dir" "$new_root$snapshot_dir"

		fi


	elif [[ "$key" = 'e' ]]; then

		echo "Entering bash..."
		bash
	
	elif [[ "$key" = 'd' ]]; then
	
	
		# You can check for any main directory in @root. Just make sure the system is there or not 
		# You must keep .snapshots and @root in / or the system won't start
		if [ -d $mnt$root/etc ]; then

			echo "Deleting / (excepting .snapshots and @root)..."
			
			umount $new_root
		
			rm -rf /mnt/bin /mnt/boot /mnt/dev /mnt/efi /mnt/etc /mnt/home /mnt/lib /mnt/lib64 /mnt/'lost+found' /mnt/opt /mnt/proc /mnt/root /mnt/run /mnt/sbin /mnt/srv /mnt/sys /mnt/tmp /mnt/usr /mnt/var
			
			mount --bind "$mnt$root" $new_root
			mount --mkdir --bind "$mnt$snapshot_dir" "$new_root$snapshot_dir"
		
		else
			
			echo -e "\nNo system located at @root. Will not delete main system.\n"
			bash
		
		fi

	else
		
		echo "Booting default (/@root)..."
		sleep 1

		umount $new_root
		
		mount --bind "$mnt$root" $new_root
		mount --mkdir --bind "$mnt$snapshot_dir" "$new_root$snapshot_dir"

	fi

}

My issue is printing out and selecting files (i.e., the 'boot into a snapshot' option). I'd like the program to print hundreds of snapshot names to pick from and then have the user type the number of the snapshot they choose, so the machine can boot into it.

I found that using 'select case' doesn't seem to working interactively with the script. It will either just bypass it by not allowing the user to select the snapshot, or it'll end up in a kernel panic. My script says #!/usr/bin/bash, but I question if this is actually running ash or maybe a slimmed down version of bash?

So far, I have the machine spit out the snapshot names. Then the user has to manually enter the full snapshot name into the 'read' function.

I'd prefer a way like 'select case', where the person can easily enter the number of the snapshot instead. Or if there's a similar/better way this can be accomplished?

how about this test harness - is that what you are after?:

#!/bin/bash

type_prompt='Select File/Dir> '
PS3="${type_prompt}"

selection=""

select selection in $(< <(ls -1 /tmp)) EXIT
do
     case "$selection" in
          "")
               echo "You selected a non-existing item"
               ;;

          "EXIT")
               echo "You are leaving the loop"
               break
               ;;

          *)
               echo "You selected: [${selection}]"
               ;;

     esac
done

echo "here is the end of the program" 

Really sorry, I'm a day late answering.

I tried this and it resulted in a kernel panic. Doesn't seem to take much whenever I try to use the select case functionality.

Well, something else is wrong with either your environment and/or the way you copy/pasted/ran what was proposed.
This is a very simple test harness and should work "as is".

Well,
$(< <(ls -1 /tmp))
requires bash and much OS support.
Simpler is
$( ls -1 /tmp )
But I don't understand how the /tmp should support the requirement at all ...

That's right - that's what the shebang says in the test harness.

This was meant as a "test harness" to illustrate the use of select/case to build a "menu".

I'm thinking the script isn't running in bash but ash, even if I specifically told it to run in bash. I then put 'ash' after the shebang and it ran the same.

So perhaps it's something to do with how it's being run and executed?

Run your code against shellcheck!
E.g. I get

...
...
In bcachefs-rollback.sh line 389:
				echo -e "\n'$snapshot' recovered to $root.\n"
                                     ^-- SC3036 (error): In dash, echo flags besides -n not supported.


In bcachefs-rollback.sh line 397:
		elif [[ "$key" = 'e' ]]; then
                     ^----------------^ SC3010 (error): In dash, [[ ]] is not supported.


In bcachefs-rollback.sh line 402:
		elif [[ "$key" = 'd' ]]; then
                     ^----------------^ SC3010 (error): In dash, [[ ]] is not supported.


In bcachefs-rollback.sh line 406:
			if [ -d $mnt$root/etc ]; then
                                    ^---^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean: 
			if [ -d $mnt"$root"/etc ]; then


In bcachefs-rollback.sh line 418:
		elif [[ "$key" = '' ]]; then  # ie., <ENTER> was pressed
                     ^---------------^ SC3010 (error): In dash, [[ ]] is not supported.


In bcachefs-rollback.sh line 423:
		elif [[ "$key" = 'q' ]]; then
                     ^----------------^ SC3010 (error): In dash, [[ ]] is not supported.

Fixes:

printf "\n'%s' recovered to %s.\n\n" "$snapshot" "$root"

elif [ "$key" = 'e' ]; then

elif [ "$key" = 'd' ]; then

if [ -d "$mnt$root/etc" ]; then

elif [ -z "$key" ]; then  # ie., <ENTER> was pressed

elif [ "$key" = 'q' ]; then