#!/usr/bin/sh

fmenu_fqubes() (

 dmenu_fmc="-f -m 0 -nb $theme_0 -nf $theme_1 -sb $theme_1 -sf $theme_0"

 chosefrom=0

 while [ -n "$chosefrom" ]; do

   chosefrom=$(printf "New qube\nGlobal preferences\nLogs" |\
     dmenu -l 3 -i -p "dom0:" $dmenu_fmc | awk '{print $1}')

   case $chosefrom in

     New)

       fqvm_create;;

     Global)

       fqubes_preferences;;

     Logs)

       fqvm_logs;;

     *)
   esac
 done
)

fmenu_fqvm() (

 get_qube_label

 chosefrom=0

 while [ -n "$chosefrom" ]; do

   chosefrom=$(printf "Applications\nAudio input devices\nBlock devices\nBoot\nBootfrom\nClone\nCommand\nDisk\nFirewall\nKeyboard\nKill\nLogs\nPause\nPCI devices\nPreferences\nReboot\nRemove\nServices\nShutdown\nTags\nUnpause\nUSB devices" |\
     dmenu -l 22 -i -p "$target_qube:" $dmenu_fmc |\
     awk '{print $1}')

   case $chosefrom in

     Applications)

       fqvm_applications;;

     Audio)

       fqvm_devices;;

     Block)

       fqvm_devices;;

     Boot)

       qvm-start --skip-if-running "$target_qube"&;;

     Bootfrom)

       qubes-vm-boot-from-device "$target_qube";;

     Clone)

       fqvm_clone;;

     Command)

       fqvm_run;;

     Disk)

       fqvm_disk;;

     Firewall)

       fqvm_firewall;;

     Keyboard)

       fqvm_keyboard;;

     Kill)

       answer=$(printf "No\nYes" | dmenu -i -p "Kill $target_qube?" $dmenu_fmc)

       if [ "$answer" = "Yes" ]; then

         qvm-kill "$target_qube"& fi;;

     Logs)

       fqvm_logs;;

     Pause)

       answer=$(printf "No\nYes" | dmenu -i -p "Pause $target_qube?" $dmenu_fmc)

       if [ "$answer" = "Yes" ]; then

         qvm-pause "$target_qube"& fi;;

     PCI)

       fqvm_pci;;

     Preferences)

       fqvm_preferences;;

     Reboot)

       answer=$(printf "No\nYes" |\
         dmenu -i -p "Reboot $target_qube?" $dmenu_fmc)

       if [ "$answer" = "Yes" ]; then

         if qvm-check --running "$target_qube" > /dev/null 2>&1; then

           $(qvm-shutdown --wait "$target_qube" && qvm-start "$target_qube")&
         fi
       fi;;

     Remove)

       fqvm_remove;;

     Services)

       fqvm_service;;

     Shutdown)

       answer=$(printf "No\nYes" |\
         dmenu -i -p "Shutdown $target_qube?" $dmenu_fmc)

       if [ "$answer" = "Yes" ]; then

         qvm-shutdown "$target_qube"& fi;;

     Tags)

       fqvm_tags;;

     Unpause)

       qvm-unpause "$target_qube"&;;

     USB)

       fqvm_devices;;

     *)
   esac
 done
)

fqubes_preferences() (

 property=0

 while [ -n "$property" ]; do

   property=$(qubes-prefs |\
     dmenu -l 16 -p "Global preferences:" $dmenu_fmc |\
     awk '{print $1}')

   case $property in

     check_updates_vm)

       value_selected=$(printf "False\nTrue" |\
         dmenu -i -p "Should the system periodically check for domU updates?"\
         $dmenu_fmc);;

     clockvm)

       # List netvms via 'qvm-ls'.
       value_selected=$(printf "$(qvm-ls --raw-data --fields NAME,FLAGS |\
         grep '|...N....$' | cut -d '|' -f1)" |\
         dmenu -l 50 -p "Select new ClockVM" $dmenu_fmc);;

     default_dispvm)

       if [ -n "$LIST_OF_DISPTEMP" ]; then unset LIST_OF_DISPTEMP; fi

       # [mediocre] Look up disposable templates.
       for n in $(qvm-ls --raw-data -O NAME,FLAGS |\
         grep '|a.......$' | cut -d '|' -f1); do

         if qvm-prefs --get "$n" template_for_dispvms |\
           grep True > /dev/null 2>&1; then

           LIST_OF_DISPTEMP="$LIST_OF_DISPTEMP\n$n"
         fi
       done

       value_selected=$(printf "(None)$LIST_OF_DISPTEMP" |\
         dmenu -l 50 -p "Select default dispvm"\
         $dmenu_fmc)

       if [ "$value_selected" = "(None)" ]; then

         value_selected="none"
       fi;;

     default_kernel)

       value_selected=$(true |\
         dmenu -p "Enter the kernel that is to be used as default"\
         $dmenu_fmc)

       if [ -n "$value_selected" ]; then

         answer_selected=$(printf "No\nYes" |\
           dmenu -i -p "Set default kernel to $value_selected?"\
           $dmenu_fmc)

         if [ "$answer_selected" != "Yes" ]; then

           unset $value_selected
         fi
       fi;;

     default_netvm)

       # List netvms via 'qvm-ls'.
       value_selected=$(printf "$(qvm-ls --raw-data --fields NAME,FLAGS |\
         grep '|...N....$' | cut -d '|' -f1)" |\
         dmenu -l 50 -p "Select default netvm" $dmenu_fmc);;

     default_pool)

       value_selected=$(qvm-pool --list | sed '1d' |\
         dmenu -i -l 30 -p "Select default storage pool" \
         $dmenu_fmc | awk '{print $1}');;

     default_pool_kernel)

       value_selected=$(qvm-pool --list | sed '1d' |\
         dmenu -i -l 30 -p "Select default storage pool for kernel volumes" \
         $dmenu_fmc | awk '{print $1}');;

     default_pool_private)

       value_selected=$(qvm-pool --list | sed '1d' |\
         dmenu -i -l 30 -p "Select default storage pool for private volumes" \
         $dmenu_fmc | awk '{print $1}');;

     default_pool_root)

       value_selected=$(qvm-pool --list | sed '1d' |\
         dmenu -i -l 30 -p "Select default storage pool for root volumes" \
         $dmenu_fmc | awk '{print $1}');;

     default_pool_volatile)

       value_selected=$(qvm-pool --list | sed '1d' |\
         dmenu -i -l 30 -p "Select default storage pool for volatile volumes" \
         $dmenu_fmc | awk '{print $1}');;

     default_qrexec_timeout)

       value_selected=$(qubes-prefs --get default_qrexec_timeout |\
         dmenu -p "Enter the time in seconds, after which qrexec connection attempts are deemed a failure"\
         $dmenu_fmc);;

     default_shutdown_timeout)

       value_selected=$(qubes-prefs --get default_shutdown_timeout |\
         dmenu -p "Enter the default time in seconds for vm shutdowns to complete"\
         $dmenu_fmc);;

     default_template)

       # List templatevm's via 'qvm-ls'.
       value_selected=$(qvm-ls --raw-data --fields NAME,FLAGS |\
         grep '|t.......$' | cut -d '|' -f1 |\
         dmenu -l 50 -p "Select default template for" $dmenu_fmc);;

     management_dispvm)

       if [ -n "$LIST_OF_DISPTEMP" ]; then unset LIST_OF_DISPTEMP; fi

         # [mediocre] Look up disposable templates.
         for n in $(qvm-ls --raw-data -O NAME,FLAGS |\
           grep '|a.......$' | cut -d '|' -f1); do

           if qvm-prefs --get "$n" template_for_dispvms |\
             grep True > /dev/null 2>&1; then

             if [ -z "$LIST_OF_DISPTEMP" ]

               then LIST_OF_DISPTEMP=$n

               else LIST_OF_DISPTEMP="$LIST_OF_DISPTEMP\n$n"
             fi
           fi
         done

         value_selected=$(printf "$LIST_OF_DISPTEMP" |\
           dmenu -l 50 -p "Select management dispvm"\
           $dmenu_fmc);;

     stats_interval)

       value_selected=$(true |\
         dmenu -p "Enter interval in seconds for VM stats reporting" $dmenu_fmc);;

     updatevm)

       # List netvms via 'qvm-ls'.
       value_selected=$(printf "$(qvm-ls --raw-data --fields NAME,FLAGS |\
         grep '|...N....$' | cut -d '|' -f1)" |\
         dmenu -l 50 -p "Select new UpdateVM" $dmenu_fmc)

       if [ -n "$value_selected" ]; then

         if ! qvm-check --running "$value_selected" > /dev/null 2>&1; then

           unset value_selected

           echo "Go back..." |\
             dmenu -p "$value_selected needs to be running!"\
             $dmenu_fmc > /dev/null 2>&1
         fi
       fi;;

     *)
   esac

   if [ -n "$value_selected" ]; then

     if ! qubes-prefs --set "$property" "$value_selected"; then

       echo "Go back..." |\
         dmenu -p "Error: Could not set $property to '$value_selected'!"\
         $dmenu_fmc > /dev/null 2>&1
     fi
   fi
 done
)

fqvm_applications() (

 option=0

 while [ -n "$option" ]; do

   option=$(printf "Available\nSelected" |\
     dmenu -i -l 2 -p "$target_qube:" $dmenu_fmc)

   if [ "$option" = "Available" ]; then

     applications=0

     while [ -n "$applications" ]; do

       # Only show applications that arent already selected for $target_qube via 'grep -v'.
       applications=$(qvm-appmenus --get-available --i-understand-format-is-unstable "$target_qube" |\
         grep -vw "$(qvm-appmenus --get-whitelist --i-understand-format-is-unstable "$target_qube")" |\
         dmenu -l 50 -p "$target_qube:" $dmenu_fmc | awk '{print $1}')

       if [ -n "$applications" ]; then

         # Check validity of input.
         if qvm-appmenus --get-available --i-understand-format-is-unstable "$target_qube" |\
           awk '{print $1}' | grep -w "$applications" > /dev/null 2>&1; then

           printf "\n$applications" >> "$HOME"/.local/share/qubes-appmenus/"$target_qube"/whitelisted-appmenus.list

           applications_modified=1
         fi
       fi
     done

   elif [ "$option" = "Selected" ]; then

     applications=0

     while [ -n "$applications" ]; do

       # Show complete application and .desktop names via 'grep'.
       applications=$(qvm-appmenus --get-available --i-understand-format-is-unstable "$target_qube" |\
         grep -w "$(qvm-appmenus --get-whitelist --i-understand-format-is-unstable "$target_qube")" |\
         dmenu -l 50 -p "$target_qube:" $dmenu_fmc | awk '{print $1}')

       if [ -n "$applications" ]; then

         for application in $applications; do

           # Look up linenumber above $application in
           # /whitelisted-appmenus.list and delete whitespace.
           whitespace=$(grep -B1 -wn "$application" <\
             "$HOME"/.local/share/qubes-appmenus/"$target_qube"/whitelisted-appmenus.list |\
             cut -c 1 | sed 2d)

           sed -i "${whitespace}{/^$/d;}" "$HOME"/.local/share/qubes-appmenus/"$target_qube"/whitelisted-appmenus.list
           sed -i "/$application/d" "$HOME"/.local/share/qubes-appmenus/"$target_qube"/whitelisted-appmenus.list

           applications_modified=1
         done
       fi
     done
   fi

   # Only update qvm-appmenus down here, *after* the user
   # has quit the application selection.
   if [ -n "$applications_modified" ]; then

     qvm-appmenus --update "$target_qube" > /dev/null 2>&1

     unset applications_modified
   fi
 done
)

fqvm_clone() (

 clone_name=$(true |\
   dmenu -p "Enter the name for the clone of $target_qube" $dmenu_fmc)

 if [ -n "$clone_name" ]; then

   option=0

   while [ -n "$option" ]; do

     option=$(printf "Create the clone\nAdvanced options" |\
       dmenu -i -l 2 -p "$target_qube:" $dmenu_fmc | awk '{print $1}')

     if [ "$option" = "Advanced" ]; then

       option_adv=0

       while [ -n "$option_adv" ]; do

         option_adv=$(printf "Class\nPool" |\
             dmenu -i -l 2 -p "$clone_name($target_qube):" $dmenu_fmc)

         if [ "$option_adv" = "Class" ]; then

           class=$(printf "AppVM\nDispVM\nStandaloneVM\nTemplateVM" |\
             dmenu -i -l 4 -p "Choose a class for $clone_name" $dmenu_fmc)

           if [ -n "$pool" ]; then class="-C $class"; fi

         elif [ "$option_adv" = "Pool" ]; then

           pool=$(qvm-pool --list | sed '1d' |\
             dmenu -i -l 10 -p "Select a pool for $clone_name"\
             $dmenu_fmc | awk '{print $1}')

           if [ -n "$pool" ]; then pool="-P $pool"; fi
         fi
       done

     elif [ "$option" = "Create" ]; then

       unset option

       qvm-clone $class $pool "$target_qube" "$clone_name"&
     fi
   done
 fi
)

fqvm_create() (

 new_name=$(true | dmenu -p "Enter the name of the qube to create:" $dmenu_fmc)

 if [ -n "$new_name" ]; then

   label=$(printf "Purple\nBlue\nGray\nGreen\nYellow\nOrange\nRed\nBlack" |\
     dmenu -i -l 8 -p "Select label for $new_name" $dmenu_fmc |\
     awk '{print tolower($0)}')

   if [ -n "$label" ]; then

     QUBEARGS="-l $label"

     class=$(printf "AppVM\nDispVM\nStandaloneVM\nTemplateVM" |\
       dmenu -i -l 4 -p "Choose a class for $new_name" $dmenu_fmc)

     if [ -n "$class" ]; then

       QUBEARGS="$QUBEARGS -C $class"
     fi

     # List templatevm's via 'qvm-ls'.
     template=$(printf "(Default)\n(None)\n$(qvm-ls --raw-data --fields NAME,FLAGS |\
       grep '|t.......$' | cut -d '|' -f1)" |\
       dmenu -l 50 -p "Select template for $new_name" $dmenu_fmc)

     if [ "$template" != "(Default)" ] && [ "$template" != "(None)" ]; then

       QUBEARGS="$QUBEARGS -t $template"
     fi

     netvm=$(printf "(Default)\n(None)\n$(qvm-ls --raw-data --fields NAME,FLAGS |\
       grep '|...N....$' | cut -d '|' -f1)" |\
       dmenu -l 50 -p "Select netvm for $new_name" $dmenu_fmc)

     if [ "$netvm" != "(Default)" ]; then

       if [ "$netvm" = "(None)" ]; then unset netvm; fi

       QUBEARGS="$QUBEARGS --prop netvm=$netvm"
     fi

     provides_network=$(printf "No\nYes" |\
       dmenu -i -p "Should $new_name provide networking for other qubes?" $dmenu_fmc)

     if [ "$provides_network" = "Yes" ]; then

       QUBEARGS="$QUBEARGS --prop provides_network=true"
     fi

     option=0

     while [ -n "$option" ]; do

       option=$(printf "Create the new qube\nAdvanced options" |\
         dmenu -i -l 2 -p "dom0:" $dmenu_fmc | awk '{print $1}')

       if [ "$option" = "Advanced" ]; then

         option_adv=$(printf "Pool" | dmenu -l 1 -p "$new_name:" $dmenu_fmc)

         if [ "$option_adv" = "Pool" ]; then

           pool=$(qvm-pool --list | sed '1d' |\
             dmenu -i -l 10 -p "Select a pool for $new_name" $dmenu_fmc |\
             awk '{print $1}')

           if [ -n "$pool" ]; then pool="-P $pool"; fi
         fi

       elif [ "$option" = "Create" ]; then

         qvm-create $QUBEARGS $pool "$new_name"&

         unset option
       fi
     done
   fi
 fi
)

fqvm_devices() (

 if ! qvm-check --running "$target_qube" > /dev/null 2>&1; then

   echo "Go back..." |\
     dmenu -p "$target_qube needs to be running, in order to attach devices to it"\
     $dmenu_fmc > /dev/null 2>&1
 else

   # Depending on the device type, we have to 
   # 'awk' different fields later on.
   if [ "$chosefrom" = "Audio" ]; then

     device_type="device mic"

     awk_devicename0=2
     awk_devicename1=10
     awk_targetqube=3

   elif [ "$chosefrom" = "Block" ]; then

     device_type="block"

     awk_devicename0=2
     awk_devicename1=3
     awk_targetqube=4

   elif [ "$chosefrom" = "USB" ]; then

     device_type="usb"

     awk_devicename0=2
     awk_devicename1=10
     awk_targetqube=3
   fi

   devices_list=$(qvm-$device_type)

   device=0

   while [ -n "$device" ]; do

     device=$(echo "$devices_list" |\
       dmenu -l 16 -p "$target_qube:" $dmenu_fmc)

     device_id=$(echo "$device" | awk '{print $1}')

     device_name=$(echo "$device" |\
       awk '{print $'$awk_devicename0'$'$awk_devicename1'}')

     if [ -n "$device" ]; then

       holds_qube=$(echo "$devices_list" | grep "$device_id" |\
         awk '{print $'$awk_targetqube'}')

       if [ -z "$holds_qube" ]; then

         answer=$(printf "No\nYes" |\
           dmenu -i -p "Attach $device_name to $target_qube?"\
           $dmenu_fmc)

         if [ "$answer" = "Yes" ]; then

           unset device

           qvm-$device_type attach "$target_qube" "$device_id"&
         fi

       elif [ "$holds_qube" = "$target_qube" ]; then

         answer=$(printf "No\nYes" |\
           dmenu -i -p "Detach $device_name from $target_qube?"\
           $dmenu_fmc)

         if [ "$answer" = "Yes" ]; then

           unset device

           qvm-$device_type detach "$holds_qube" "$device_id"&
         fi
       else

         answer=$(printf "No\nYes" |\
           dmenu -i -p "Detach $device_name from $holds_qube and attach it to $target_qube?"\
           $dmenu_fmc)

         if [ "$answer" = "Yes" ]; then

           unset device

           $(qvm-$device_type detach "$holds_qube" "$device_id" &&
             qvm-$device_type attach "$target_qube" "$device_id")&
         fi
       fi
     fi
   done
 fi
)

fqvm_disk() (

 qube_class=$(qvm-ls --raw-data -O flags "$target_qube" | cut -c 1)

 # If $target_qube is template or standalone, give option to extend root storage.
 if [ "$qube_class" = "t" ] ||\
   [ "$qube_class" = "s" ] ||\
   [ "$qube_class" = "S" ]; then

   volume=$(printf "Root\nPrivate" |\
     dmenu -l 2 -i -p "$target_qube:" $dmenu_fmc | awk '{print tolower($0)}')

 else

   volume="private"
 fi

 if [ -n "$volume" ]; then

   current_storage=$(( $(qvm-volume info "$target_qube:$volume" size) / 1024/1024 ))

   mebibyte=$(echo "$current_storage" |\
     dmenu -p "Enter the maximum size of $volume storage in MiB to be allocated to $target_qube"\
     $dmenu_fmc)

   if [ -n "$mebibyte" ]; then

     if [ "$mebibyte" -gt "$current_storage" ]; then

       byte=$(( mebibyte * 1024*1024 ))

       answer=$(printf "No\nYes" |\
         dmenu -i -p "Increase the maximum $volume storage size of $target_qube from $current_storage MiB to $mebibyte MiB?"\
         $dmenu_fmc)

       if [ "$answer" = "Yes" ]; then

         qvm-volume extend "$target_qube:$volume" "$byte"&
       fi
     else

       echo "Go back..." |\
         dmenu -p "Error: Can not decrease the maximum $volume storage!"\
         $dmenu_fmc > /dev/null 2>&1
     fi
   fi
 fi
)

fqvm_firewall() (

 rulenumber_selected=0

 while [ -n "$rulenumber_selected" ]; do

   rulenumber_selected=$(qvm-firewall $target_qube list |\
     dmenu -l 50 -p "$target_qube:" $dmenu_fmc | awk '{print $1}')

   if [ -n "$rulenumber_selected" ]; then

     # This will equal "NO" if the user selects the top row,
     # instead of any existing rule.
     if [ "$rulenumber_selected" != "NO" ]; then

       option=$(printf "Add new rule above rule $rulenumber_selected\nRemove rule $rulenumber_selected" |\
         dmenu -i -l 2 -p "$target_qube:" $dmenu_fmc | awk '{print $1}')
     else

       option="Add"
     fi

     if [ "$option" = "Remove" ]; then

       answer=$(printf "No\nYes" |\
         dmenu -i -p "Remove rule $rulenumber_selected?" $dmenu_fmc)

       if [ "$answer" = "Yes" ]; then

         qvm-firewall "$target_qube" del --rule-no "$rulenumber_selected"
       fi

     elif [ "$option" = "Add" ]; then

       if [ -n "$RULEARGS" ]; then unset RULEARGS; fi

       action=$(printf "Accept\nDrop" |\
         dmenu -i -l 2 -p "Select action for the new firewall rule" $dmenu_fmc |\
         awk '{print tolower($0)}')

       if [ -n "$action" ]; then

         RULEARGS="$action"

         specialtarget=$(true |\
           dmenu -p "ACTION=$RULEARGS <specialtarget>" $dmenu_fmc)

         if [ -n "$specialtarget" ]; then

           RULEARGS="$RULEARGS SPECIALTARGET=$specialtarget"
         fi

         dsthost=$(true |\
           dmenu -p "ACTION=$RULEARGS <dsthost>" $dmenu_fmc)

         if [ -n "$dsthost" ]; then

           RULEARGS="$RULEARGS DSTHOST=$dsthost"
         fi

         proto=$(true |\
           dmenu -p "ACTION=$RULEARGS <proto>" $dmenu_fmc)

         if [ -n "$proto" ]; then

           RULEARGS="$RULEARGS PROTO=$proto"
         fi

         if [ "$proto" = "tcp" ] || [ "$proto" = "udp" ]; then

           dstports=$(true |\
             dmenu -p "ACTION=$RULEARGS <dstports>" $dmenu_fmc)

           if [ -n "$dstports" ]; then

             RULEARGS="$RULEARGS DSTPORTS=$dstports"
           fi

         elif [ "$proto" = "icmp" ]; then

           icmptype=$(true |\
             dmenu -p "ACTION=$RULEARGS <icmptype>" $dmenu_fmc)

           if [ -n "$icmptype" ]; then

             RULEARGS="$RULEARGS ICMPTYPE=$icmptype"
           fi
         fi

         expire=$(true |\
           dmenu -p "ACTION=$RULEARGS <expire>" $dmenu_fmc)

         if [ -n "$expire" ]; then

           RULEARGS="EXPIRE=$expire"
         fi

         comment=$(true |\
           dmenu -p "ACTION=$RULEARGS <comment>" $dmenu_fmc)

         if [ -n "$comment" ]; then

           RULEARGS="$RULEARGS COMMENT=$comment"
         fi

         answer=$(printf "No\nYes" |\
           dmenu -i -p "Add the following rule to $target_qube? {{ ACTION=$RULEARGS }}"\
           $dmenu_fmc)

         if [ "$answer" = "Yes" ]; then

           if [ -n "$beforerule" ]; then unset beforerule; fi

           if [ "$rulenumber_selected" != "NO" ]; then

             beforerule=$(echo --before "$rulenumber_selected")
           fi

           RULEARGS=$(echo "$RULEARGS" | awk '{print tolower($0)}')

           if ! qvm-firewall "$target_qube" add $beforerule $RULEARGS; then

             echo "Go back..." | dmenu $dmenu_fmc\
               -p "Error: Failed to add firewall rule! See 'qvm-firewall --help' for more information."\
               > /dev/null 2>&1
           fi
         fi
       fi
     fi
   fi
 done
)

fqvm_keyboard() (

 # 'qmenu-vm' does not get informed about the installed layouts by the vm itself
 # so it is possible that the selected layout is missing inside the vm.
 # Getting the info from the vm itself however would have security implications
 # so we will not switch to use that method.
 LAYOUT=$(ls /usr/share/X11/xkb/symbols |\
   dmenu -l 50 -p "$target_qube:" $dmenu_fmc)

 if [ -n "$LAYOUT" ]; then

   if test -d /usr/share/X11/xkb/symbols/$LAYOUT; then

     LAYOUT="$LAYOUT/"$(ls /usr/share/X11/xkb/symbols/"$LAYOUT" |\
       dmenu -l 50 -p "$target_qube:" $dmenu_fmc)
   fi

   if ! qvm-run "$target_qube" "setxkbmap $LAYOUT"; then

     echo "Go back..." |\
       dmenu -p "Error: Could not set keyboard layout to '$LAYOUT' in $target_qube! Please check the installed layouts inside the qube itself."\
       $dmenu_fmc > /dev/null 2>&1
   fi
 fi
)

fqvm_logs() (

 if [ "$target_qube" = "dom0" ]; then

   logs="/var/log/xen/console/hypervisor.log"
 else

   logs="/var/log/xen/console/guest-$target_qube.log\n/var/log/qubes/guid.$target_qube.log\n/var/log/qubes/qrexec.$target_qube.log"
 fi

 entry=0

 while [ -n "$entry" ]; do

   entry=$(printf "$logs" |\
     dmenu -i -l 3 -p "$target_qube:" $dmenu_fmc)

   if [ -n "$entry" ]; then

     log=$(dmenu -l 20 -p "$target_qube:" $dmenu_fmc < "$entry")

     if [ -n "$log" ]; then

       echo "$log" > /var/run/qubes/qubes-clipboard.bin

       printf "dom0" > /var/run/qubes/qubes-clipboard.bin.source
     fi
   fi
 done
)

fqvm_pci() (

 if qvm-check --running "$target_qube" > /dev/null 2>&1; then

   echo "Go back..." |\
     dmenu -p "$target_qube needs to be powered off, in order to attach or detach PCI devices"\
     $dmenu_fmc > /dev/null 2>&1
 else

   list_pci=$(qvm-pci)

   if ! qvm-prefs --get "$target_qube" maxmem | grep -w 0 > /dev/null 2>&1; then

     answer_memorybalancing=$(printf "Continue anyways\nDisable dynamic memory balancing" |\
       dmenu -l 2 -i -p "Dynamic memory balancing is enabled in $target_qube, some devices might not work!"\
       $dmenu_fmc | awk '{print $1}')

     if [ "$answer_memorybalancing" = "Disable" ]; then

       qvm-prefs --set "$target_qube" maxmem 0
     fi
   fi

   if qvm-prefs --get "$target_qube" virt_mode |\
     grep -w pvh > /dev/null 2>&1; then

     answer_virtmode=$(printf "Continue anyways\nSelect another virtualisation mode" |\
       dmenu -l 2 -i -p "$target_qube is using PVH for its virtualisation mode, which does not support PCI passthrough!"\
       $dmenu_fmc | awk '{print $1}')

     if [ "$answer_virtmode" = "Select" ]; then

       virtmode_selected=$(printf "HVM\nPV" |\
         dmenu -l 2 -i -p "Select virtualisation mode for $target_qube" $dmenu_fmc)

       if [ -n "$virtmode_selected" ]; then

         qvm-prefs --set "$target_qube" virt_mode "$virtmode_selected"
       fi
     fi
   fi

   device_selected=0

   while [ -n "$device_selected" ]; do

     device_selected=$(echo "$list_pci" |\
       dmenu -l 30 -p "$target_qube:" $dmenu_fmc)

     if [ -n "$device_selected" ]; then

       device_src=$(echo "$device_selected" | awk '{print $1}' | sed 's/:.*//')
       device_bdf=$(echo "$device_selected" | awk '{print $1}' | sed 's/.*://')

       if echo "$device_selected" | grep -w "$target_qube"; then

         answer=$(printf "No\nYes" |\
           dmenu -i -p "Detach \"$device_bdf\" from $target_qube?" $dmenu_fmc)

         if [ "$answer" = "Yes" ]; then

           if ! test_qvm-pci detach "$target_qube" "$device_src":"$device_bdf"; then

             echo "Go back..." |\
               dmenu -p "Error: Failed to detach \"$device_bdf\" from $target_qube!"\
               $dmenu_fmc > /dev/null 2>&1
           fi

           list_pci=$(qvm-pci)
         fi
       else

         answer=$(printf "No\nYes" |\
           dmenu -i -p "Attach \"$device_bdf\" to $target_qube?" $dmenu_fmc)

         if [ "$answer" = "Yes" ]; then

           # Check if there is more than one function
           # that belongs to the same device.
           bdf_count=$(echo "$list_pci" | awk '{print $1}' |\
             grep -c $(echo "$device_bdf" | sed 's/\..*//'))

           if [ "$bdf_count" -gt 1 ]; then

             if [ -n "$pci_option" ]; then unset pci_option; fi

               answer_nsrt=$(printf "No\nYes" |\
                 dmenu -i -p "\"$device_bdf\" is most likely to be attached with the option 'no-strict-reset' enabled. Please be aware of the security implications! Do you want to attach \"$device_bdf\" with the option 'no-strict-reset' set to true?"\
                 $dmenu_fmc)

             if [ "$answer_nsrt" = "Yes" ]; then

               pci_option="-o no-strict-reset=True"
             fi
           fi

           if ! qvm-pci attach --persistent $pci_option "$target_qube" "$device_src:$device_bdf"; then

             echo "Go back..." |\
               dmenu -p "Error: Failed to attach \"$device_bdf\" to $target_qube!"\
               $dmenu_fmc > /dev/null 2>&1
           fi

           list_pci=$(qvm-pci)
         fi
       fi
     fi
   done
 fi
)

fqvm_preferences() (

 property=0

 while [ -n "$property" ]; do

   property=$(qvm-prefs "$target_qube" |\
     dmenu -l 45 -p "$target_qube:" $dmenu_fmc |\
     awk '{print $1}')

   if [ -n "$property" ]; then

     case $property in

       autostart)

         value_selected=$(printf "False\nTrue" |\
           dmenu -i -p "Set autostart of $target_qube to:" $dmenu_fmc);;

       debug)

         value_selected=$(printf "False\nTrue" |\
           dmenu -i -p "Set debug mode of $target_qube to:" $dmenu_fmc);;

       default_dispvm)

         if [ -n "$LIST_OF_DISPTEMP" ]; then unset LIST_OF_DISPTEMP; fi

         # [mediocre] Look up disposable templates.
         for n in $(qvm-ls --raw-data -O NAME,FLAGS |\
           grep '|a.......$' | cut -d '|' -f1); do

           if qvm-prefs --get "$n" template_for_dispvms |\
             grep True > /dev/null 2>&1; then

             LIST_OF_DISPTEMP="$LIST_OF_DISPTEMP\n$n"
           fi
         done

         value_selected=$(printf "(Default)\n(None)$LIST_OF_DISPTEMP" |\
           dmenu -l 50 -p "Select default dispvm for $target_qube" $dmenu_fmc)

         if [ "$value_selected" = "(None)" ]; then

           value_selected="None"

         elif [ "$value_selected" = "(Default)" ]; then

           value_selected="--default"
         fi;;

       default_user)

         value_selected=$(echo "--default" |\
           dmenu -p "Enter the name of the default user for $target_qube"\
           $dmenu_fmc);;

       include_in_backups)

         value_selected=$(printf "False\nTrue" |\
           dmenu -i -p "Include $target_qube in backups?" $dmenu_fmc);;

       kernel)

         value_selected=$(echo "--default" |\
           dmenu -p "Enter kernel to be used by $target_qube" $dmenu_fmc)

         if [ -n "$value_selected" ]; then

           answer_selected=$(printf "No\nYes" |\
             dmenu -i -p "Set kernel of $target_qube to $value_selected?"\
             $dmenu_fmc)

           if [ "$answer_selected" != "Yes" ]; then

             unset value_selected
           fi
         fi;;

       kernelopts)

         value_selected=$(echo "--default" |\
           dmenu -p "Enter kernel options for $target_qube" $dmenu_fmc)

         if [ -n "$value_selected" ]; then

           answer_selected=$(printf "No\nYes" |\
             dmenu -i -p "Set kernel options for $target_qube to \"$value_selected\"?"\
             $dmenu_fmc)

           if [ "$answer_selected" != "Yes" ]; then

             unset value_selected
           fi
         fi;;

       label)

         if qvm-check --running "$target_qube" > /dev/null 2>&1; then

           echo "Go back..." |\
             dmenu -p "$target_qube needs to be powered off, in order to change its label"\
             $dmenu_fmc > /dev/null 2>&1
         else

           value_selected=$(printf "Purple\nBlue\nGray\nGreen\nYellow\nOrange\nRed\nBlack" |\
             dmenu -i -l 8 -p "Select label for $target_qube" $dmenu_fmc |\
             awk '{print tolower($0)}')
         fi;;

       mac)

         value_selected=$(echo "--default" |\
           dmenu -p "Enter new MAC address for $target_qube" $dmenu_fmc)

         if [ -n "$value_selected" ]; then

           answer_selected=$(printf "No\nYes" |\
             dmenu -i -p "Set MAC address of $target_qube to $value_selected?"\
             $dmenu_fmc)

           if [ "$answer_selected" != "Yes" ]; then

             unset value_selected 
           fi
         fi;;

       maxmem)

         value_selected=$(echo "--default" |\
           dmenu -p "Enter the maximum amount of memory in MB to be allocated to $target_qube. Setting it to 0 will disable dynamic memory balancing."\
           $dmenu_fmc)

         if [ -n "$value_selected" ]; then

           answer_selected=$(printf "No\nYes" |\
             dmenu -i -p "Set maximum memory of $target_qube to $value_selected MB?"\
             $dmenu_fmc)

           if [ "$answer_selected" != "Yes" ]; then

             unset value_selected
           fi
         fi;;

       memory)

         value_selected=$(echo "--default" |\
           dmenu -p "Enter the amount of initial memory in MB to be allocated to $target_qube"\
           $dmenu_fmc)

         if [ -n "$value_selected" ]; then

           answer_selected=$(printf "No\nYes" |\
             dmenu -i -p "Set initial memory of $target_qube to $value_selected MB?" $dmenu_fmc)

           if [ "$answer_selected" != "Yes" ]; then

             unset answer_selected
           fi
         fi;;

       netvm)

         # List netvms via 'qvm-ls'.
         value_selected=$(printf "(Default)\n(None)\n$(qvm-ls --raw-data --fields NAME,FLAGS |\
           grep '|...N....$' | cut -d '|' -f1)" |\
           dmenu -l 50 -p "Select netvm for $target_qube" $dmenu_fmc)

         if [ "$value_selected" = "(None)" ]; then

           value_selected="None"

         elif [ "$value_selected" = "(Default)" ]; then

           value_selected="--default"
         fi;;

       provides_network)

         value_selected=$(printf "False\nTrue" |\
           dmenu -i -p "Should $target_qube provide networking for other qubes?"\
           $dmenu_fmc);;

       qrexec_timeout)

         value_selected=$(echo "--default" |\
           dmenu -p "Enter the time in seconds, after which qrexec attempt is deemed a failure for $target_qube"\
           $dmenu_fmc)

         if [ -n "$value_selected" ]; then

           answer_selected=$(printf "No\nYes" |\
             dmenu -i -p "Set qrexec timeout for $target_qube to $value_selected seconds?"\
             $dmenu_fmc)

           if [ "$answer_selected" != "Yes" ]; then

             unset value_selected
           fi
         fi;;

       shutdown_timeout)

         value_selected=$(echo "--default" |\
           dmenu -p "Enter the time in seconds for shutdown, after which $target_qube may be forcefully powered off"\
           $dmenu_fmc)

         if [ -n "$value_selected" ]; then

           answer_selected=$(printf "No\nYes" |\
             dmenu -i -p "Set shutdown timeout for $target_qube to $value_selected seconds?"\
             $dmenu_fmc)

           if [ "$answer_selected" != "Yes" ]; then

             unset value_selected
           fi
         fi;;

       template)

         if qvm-check --running "$target_qube" > /dev/null 2>&1; then

           echo "Go back..." |\
             dmenu -p "$target_qube needs to be powered off, in order to change its template"\
             $dmenu_fmc > /dev/null 2>&1
         else

           # List templatevm's via 'qvm-ls'.
           value_selected=$(printf "(Default)\n$(qvm-ls --raw-data --fields NAME,FLAGS |\
             grep '|t.......$' | cut -d '|' -f1)" |\
             dmenu -l 50 -p "Select template for $target_qube" $dmenu_fmc)

           if [ "$value_selected" = "(Default)" ]; then

             value_selected="--default"
           fi
         fi;;

       template_for_dispvms)

         value_selected=$(printf "False\nTrue" |\
           dmenu -i -p "Should $target_qube be used as a template for disposable qubes?"\
           $dmenu_fmc);;

       vcpus)

         value_selected=$(echo "--default" |\
           dmenu -p "Enter the number of CPU cores that should be made available to $target_qube"\
           $dmenu_fmc)

         if [ -n "$value_selected" ]; then

           answer_selected=$(printf "No\nYes" |\
             dmenu -i -p "Set number of CPU cores available to $target_qube to $value_selected?"\
             $dmenu_fmc)

           if [ "$answer_selected" != "Yes" ]; then

             unset value_selected
           fi
         fi;;

       virt_mode)

         value_selected=$(printf "PVH\nHVM\nPV" |\
           dmenu -i -l 3 -p "Select virtualisation mode for $target_qube"\
           $dmenu_fmc);;

       *)
     esac

     if [ -n "$value_selected" ]; then

       if ! qvm-prefs --set "$target_qube" "$property" "$value_selected"; then

         echo "Go back..." |\
           dmenu -p "Error: Could not set $property to '$value_selected'!"\
           $dmenu_fmc > /dev/null 2>&1
       fi

       unset value_selected
     fi
   fi
 done
)

fqvm_remove() {

 if qvm-check --running "$target_qube" > /dev/null 2>&1; then

   echo "Go back..." |\
     dmenu -p "$target_qube needs to be powered off, in order to be removed"\
     $dmenu_fmc > /dev/null 2>&1
 else

   confirmation=$(true |\
     dmenu -p "Enter the name of the qube '$target_qube' in order to remove it"\
     $dmenu_fmc)

   if [ "$target_qube" = "$confirmation" ]; then

     confirmation_semifinal=$(printf "No\nYes" |\
       dmenu -i -p "Are you sure you want to remove $target_qube permanently?"\
       $dmenu_fmc)

     if [ "$confirmation_semifinal" = "Yes" ]; then

       confirmation_final=$(printf "No\nYes" |
         dmenu -i -p "Are you really sure you want to remove $target_qube permanently?"\
         $dmenu_fmc)

       if [ "$confirmation_final" = "Yes" ]; then

         qvm-remove -f "$target_qube"&

         unset chosefrom
       fi
     fi
   fi
 fi
}

fqvm_run() (

 commandtr=$(true |\
   dmenu -p "Run command in $target_qube:" $dmenu_fmc)

 if [ -n "$commandtr" ]; then qvm-run "$target_qube" "$commandtr"& fi
)

fqvm_service() (

 service=0

 while [ -n "$service" ]; do

   service=$(qvm-service "$target_qube" --list |\
     dmenu -l 32 -p "$target_qube:" $dmenu_fmc | awk '{print $1}')

   if [ -n "$service" ]; then

     # If the service has already been added to the list,
     # give option to unset it.
     if qvm-service "$target_qube" --list | grep -w "$service"; then

        unset="\nUnset"
     fi

     value=$(printf "Disable\nEnable$unset" |\
       dmenu -l 3 -i -p "Select value for '$service'" $dmenu_fmc)

     if [ "$value" = "Disable" ]; then

       if ! qvm-service "$target_qube" "$service" off; then

         echo "Go back..." | dmenu -p "Error: Could not deactivate $service!"\
           $dmenu_fmc > /dev/null 2>&1
       fi

     elif [ "$value" = "Enable" ]; then

       if ! qvm-service "$target_qube" "$service" on; then

         echo "Go back..." | dmenu -p "Error: Could not activate $service!"\
           $dmenu_fmc > /dev/null 2>&1
       fi

     elif [ "$value" = "Unset" ]; then

       if ! qvm-service "$target_qube" "$service" --unset; then

         echo "Go back..." | dmenu -p "Error: Could not unset $service!"\
           $dmenu_fmc > /dev/null 2>&1
       fi
     fi

     if [ -n "$unset" ]; then unset unset; fi
   fi
 done
)

fqvm_tags() (

 tag=0

 while [ -n "$tag" ]; do

   tag=$(qvm-tags "$target_qube" list |\
     dmenu -l 15 -p "$target_qube:" $dmenu_fmc | awk '{print $1}')

   if [ -n "$tag" ]; then

     if qvm-tags "$target_qube" list | grep -w "$tag"; then

       answer=$(printf "No\nYes" |\
         dmenu -i -p "Remove tag '$tag' from $target_qube?" $dmenu_fmc)

       if [ "$answer" = "Yes" ]; then

         qvm-tags "$target_qube" del "$tag"
       fi
     else

       qvm-tags "$target_qube" add "$tag"
     fi
   fi
 done
)

get_qube_label() {

 qube_label=$(qvm-ls --raw-data "$target_qube" -O LABEL)

 # Change label colors according to ~/.config/qmenu.conf if that file exists.
 if [ -f "$HOME/.config/qmenu.conf" ]; then

   qube_label=$(grep "^$qube_label=" "$HOME"/.config/qmenu.conf | cut -d= -f2)
 fi

 # Note that the '-m 0' option in 'dmenu' is important
 # for security, as it restricts it to monitor 0.
 dmenu_fmc="-f -m 0 -nb $theme_0 -nf $theme_1 -sb $qube_label -sf $theme_1"
}

rearrange_qube_list() {

 qube_list=$(echo "$qube_list" |\
   awk -v ListInOrder="LABEL,purple,blue,gray,green,yellow,orange,red,black" '
   BEGIN {
   split(ListInOrder, a, ",")
   for (i = 1; i <= length(a); ++i) ListToOrdinal[a[i]] = i
   }
   {print ListToOrdinal[$3] "-" $0}
   ' | sort -t- -k1,1n | cut -d- -f2-)
}





if [ "$2" = "--light-theme" ]; then

  theme_0='#ffffff'
  theme_1='#000000'
else

  theme_0='#000000'
  theme_1='#ffffff'
fi

case $1 in

  --all)

    # As of 20190823, 'qvm-ls --all' will not list dom0 because of a bug.
    # As a workaround, we will 'shift' $1 and, if needed, $2.
    shift
    if [ -n "$1" ]; then shift; fi;;

  --focused)

    target_qube=$(xprop -id "$(xdotool getwindowfocus)" |\
      grep -w '^_QUBES_VMNAME(STRING)' | cut -d\" -f2)

    if [ -z "$target_qube" ]; then

      target_qube=dom0

      fmenu_fqubes
    else

      fmenu_fqvm
    fi

    exit 1;;

  --halted|--paused|--running|--tags=*);;

  *)

    printf "qmenu-vm [OPTION] (--light-theme)\nList, manage and configure your qubes.\n\n --all\n --focused\n --halted\n --paused\n --running\n --tags=[TAG]\n\n\nqmenu v1.3\n<https://github.com/sine3o14nnae/qmenu/>\n<https://gitlab.com/sine3o14nnae/qmenu/>\n\n"

    if [ "$1" = "--help" ]; then exit 0; else exit 2; fi
esac

while true; do

  # Load 'qvm-ls' into a variable so that it doesnt
  # need to reload again after every user operation.
  qube_list=$(qvm-ls --no-spinner $1 -O NAME,STATE,LABEL,CLASS\
,TEMPLATE,NETVM,IP,PRIV-MAX,PRIV-CURR,PRIV-USED,ROOT-MAX\
,ROOT-CURR,ROOT-USED,KERNEL,KERNELOPTS)

  rearrange_qube_list

  if [ -n "$target_qube" ]; then unset target_qube; fi

  # Get out of the while loop and refresh 'qvm-ls' by loading it again
  # into $qube_list, whenever the user selects the 'qvm-ls' top row.
  while [ "$target_qube" != "NAME" ]; do

    target_qube=$(echo "$qube_list" | dmenu -f -m 0 -l 69 \
      -nb $theme_0 -nf $theme_1 -sb $theme_1 -sf $theme_0 |\
      awk '{print $1}')

    if [ -z "$target_qube" ]; then exit 1

    elif [ "$target_qube" != "NAME" ]; then

      if [ "$target_qube" = "dom0" ]; then

        fmenu_fqubes
      else

        fmenu_fqvm
      fi
    fi
  done
done
