Home
       qmenu-vm - qmenu - 🇶 manage qubes os via dmenu - fixed forked version
  HTML git clone https://git.drkhsh.at/qmenu.git
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       qmenu-vm (39095B)
       ---
            1 #!/bin/sh
            2 
            3 fmenu_fqubes() (
            4 
            5  dmenu_fmc="-f -m 0"
            6 
            7  chosefrom=0
            8 
            9  while [ -n "$chosefrom" ]; do
           10 
           11    chosefrom=$(printf "New qube\nGlobal preferences\nLogs" |\
           12      dmenu -l 3 -i -p "dom0:" $dmenu_fmc | awk '{print $1}')
           13 
           14    case $chosefrom in
           15 
           16      New)
           17 
           18        fqvm_create;;
           19 
           20      Global)
           21 
           22        fqubes_preferences;;
           23 
           24      Logs)
           25 
           26        fqvm_logs;;
           27 
           28      *)
           29    esac
           30  done
           31 )
           32 
           33 fmenu_fqvm() (
           34 
           35  get_qube_label
           36 
           37  chosefrom=0
           38 
           39  while [ -n "$chosefrom" ]; do
           40 
           41    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" |\
           42      dmenu -l 22 -i -p "$target_qube:" $dmenu_fmc |\
           43      awk '{print $1}')
           44 
           45    case $chosefrom in
           46 
           47      Applications)
           48 
           49        fqvm_applications;;
           50 
           51      Audio)
           52 
           53        fqvm_devices;;
           54 
           55      Block)
           56 
           57        fqvm_devices;;
           58 
           59      Boot)
           60 
           61        qvm-start --skip-if-running "$target_qube"&;;
           62 
           63      Bootfrom)
           64 
           65        qubes-vm-boot-from-device "$target_qube";;
           66 
           67      Clone)
           68 
           69        fqvm_clone;;
           70 
           71      Command)
           72 
           73        fqvm_run;;
           74 
           75      Disk)
           76 
           77        fqvm_disk;;
           78 
           79      Firewall)
           80 
           81        fqvm_firewall;;
           82 
           83      Keyboard)
           84 
           85        fqvm_keyboard;;
           86 
           87      Kill)
           88 
           89        answer=$(printf "No\nYes" | dmenu -i -p "Kill $target_qube?" $dmenu_fmc)
           90 
           91        if [ "$answer" = "Yes" ]; then
           92 
           93          qvm-kill "$target_qube"& fi;;
           94 
           95      Logs)
           96 
           97        fqvm_logs;;
           98 
           99      Pause)
          100 
          101        answer=$(printf "No\nYes" | dmenu -i -p "Pause $target_qube?" $dmenu_fmc)
          102 
          103        if [ "$answer" = "Yes" ]; then
          104 
          105          qvm-pause "$target_qube"& fi;;
          106 
          107      PCI)
          108 
          109        fqvm_pci;;
          110 
          111      Preferences)
          112 
          113        fqvm_preferences;;
          114 
          115      Reboot)
          116 
          117        answer=$(printf "No\nYes" |\
          118          dmenu -i -p "Reboot $target_qube?" $dmenu_fmc)
          119 
          120        if [ "$answer" = "Yes" ]; then
          121 
          122          if qvm-check --running "$target_qube" > /dev/null 2>&1; then
          123 
          124            $(qvm-shutdown --wait "$target_qube" && qvm-start "$target_qube")&
          125          fi
          126        fi;;
          127 
          128      Remove)
          129 
          130        fqvm_remove;;
          131 
          132      Services)
          133 
          134        fqvm_service;;
          135 
          136      Shutdown)
          137 
          138        answer=$(printf "No\nYes" |\
          139          dmenu -i -p "Shutdown $target_qube?" $dmenu_fmc)
          140 
          141        if [ "$answer" = "Yes" ]; then
          142 
          143          qvm-shutdown "$target_qube"& fi;;
          144 
          145      Tags)
          146 
          147        fqvm_tags;;
          148 
          149      Unpause)
          150 
          151        qvm-unpause "$target_qube"&;;
          152 
          153      USB)
          154 
          155        fqvm_devices;;
          156 
          157      *)
          158    esac
          159  done
          160 )
          161 
          162 fqubes_preferences() (
          163 
          164  property=0
          165 
          166  while [ -n "$property" ]; do
          167 
          168    property=$(qubes-prefs |\
          169      dmenu -l 16 -p "Global preferences:" $dmenu_fmc |\
          170      awk '{print $1}')
          171 
          172    case $property in
          173 
          174      check_updates_vm)
          175 
          176        value_selected=$(printf "False\nTrue" |\
          177          dmenu -i -p "Should the system periodically check for domU updates?"\
          178          $dmenu_fmc);;
          179 
          180      clockvm)
          181 
          182        # List netvms via 'qvm-ls'.
          183        value_selected=$(printf "$(qvm-ls --raw-data --fields NAME,FLAGS |\
          184          grep '|...N....$' | cut -d '|' -f1)" |\
          185          dmenu -l 50 -p "Select new ClockVM" $dmenu_fmc);;
          186 
          187      default_dispvm)
          188 
          189        if [ -n "$LIST_OF_DISPTEMP" ]; then unset LIST_OF_DISPTEMP; fi
          190 
          191        # [mediocre] Look up disposable templates.
          192        for n in $(qvm-ls --raw-data -O NAME,FLAGS |\
          193          grep '|a.......$' | cut -d '|' -f1); do
          194 
          195          if qvm-prefs --get "$n" template_for_dispvms |\
          196            grep True > /dev/null 2>&1; then
          197 
          198            LIST_OF_DISPTEMP="$LIST_OF_DISPTEMP\n$n"
          199          fi
          200        done
          201 
          202        value_selected=$(printf "(None)$LIST_OF_DISPTEMP" |\
          203          dmenu -l 50 -p "Select default dispvm"\
          204          $dmenu_fmc)
          205 
          206        if [ "$value_selected" = "(None)" ]; then
          207 
          208          value_selected="none"
          209        fi;;
          210 
          211      default_kernel)
          212 
          213        value_selected=$(true |\
          214          dmenu -p "Enter the kernel that is to be used as default"\
          215          $dmenu_fmc)
          216 
          217        if [ -n "$value_selected" ]; then
          218 
          219          answer_selected=$(printf "No\nYes" |\
          220            dmenu -i -p "Set default kernel to $value_selected?"\
          221            $dmenu_fmc)
          222 
          223          if [ "$answer_selected" != "Yes" ]; then
          224 
          225            unset $value_selected
          226          fi
          227        fi;;
          228 
          229      default_netvm)
          230 
          231        # List netvms via 'qvm-ls'.
          232        value_selected=$(printf "$(qvm-ls --raw-data --fields NAME,FLAGS |\
          233          grep '|...N....$' | cut -d '|' -f1)" |\
          234          dmenu -l 50 -p "Select default netvm" $dmenu_fmc);;
          235 
          236      default_pool)
          237 
          238        value_selected=$(qvm-pool --list | sed '1d' |\
          239          dmenu -i -l 30 -p "Select default storage pool" \
          240          $dmenu_fmc | awk '{print $1}');;
          241 
          242      default_pool_kernel)
          243 
          244        value_selected=$(qvm-pool --list | sed '1d' |\
          245          dmenu -i -l 30 -p "Select default storage pool for kernel volumes" \
          246          $dmenu_fmc | awk '{print $1}');;
          247 
          248      default_pool_private)
          249 
          250        value_selected=$(qvm-pool --list | sed '1d' |\
          251          dmenu -i -l 30 -p "Select default storage pool for private volumes" \
          252          $dmenu_fmc | awk '{print $1}');;
          253 
          254      default_pool_root)
          255 
          256        value_selected=$(qvm-pool --list | sed '1d' |\
          257          dmenu -i -l 30 -p "Select default storage pool for root volumes" \
          258          $dmenu_fmc | awk '{print $1}');;
          259 
          260      default_pool_volatile)
          261 
          262        value_selected=$(qvm-pool --list | sed '1d' |\
          263          dmenu -i -l 30 -p "Select default storage pool for volatile volumes" \
          264          $dmenu_fmc | awk '{print $1}');;
          265 
          266      default_qrexec_timeout)
          267 
          268        value_selected=$(qubes-prefs --get default_qrexec_timeout |\
          269          dmenu -p "Enter the time in seconds, after which qrexec connection attempts are deemed a failure"\
          270          $dmenu_fmc);;
          271 
          272      default_shutdown_timeout)
          273 
          274        value_selected=$(qubes-prefs --get default_shutdown_timeout |\
          275          dmenu -p "Enter the default time in seconds for vm shutdowns to complete"\
          276          $dmenu_fmc);;
          277 
          278      default_template)
          279 
          280        # List templatevm's via 'qvm-ls'.
          281        value_selected=$(qvm-ls --raw-data --fields NAME,FLAGS |\
          282          grep '|t.......$' | cut -d '|' -f1 |\
          283          dmenu -l 50 -p "Select default template for" $dmenu_fmc);;
          284 
          285      management_dispvm)
          286 
          287        if [ -n "$LIST_OF_DISPTEMP" ]; then unset LIST_OF_DISPTEMP; fi
          288 
          289          # [mediocre] Look up disposable templates.
          290          for n in $(qvm-ls --raw-data -O NAME,FLAGS |\
          291            grep '|a.......$' | cut -d '|' -f1); do
          292 
          293            if qvm-prefs --get "$n" template_for_dispvms |\
          294              grep True > /dev/null 2>&1; then
          295 
          296              if [ -z "$LIST_OF_DISPTEMP" ]
          297 
          298                then LIST_OF_DISPTEMP=$n
          299 
          300                else LIST_OF_DISPTEMP="$LIST_OF_DISPTEMP\n$n"
          301              fi
          302            fi
          303          done
          304 
          305          value_selected=$(printf "$LIST_OF_DISPTEMP" |\
          306            dmenu -l 50 -p "Select management dispvm"\
          307            $dmenu_fmc);;
          308 
          309      stats_interval)
          310 
          311        value_selected=$(true |\
          312          dmenu -p "Enter interval in seconds for VM stats reporting" $dmenu_fmc);;
          313 
          314      updatevm)
          315 
          316        # List netvms via 'qvm-ls'.
          317        value_selected=$(printf "$(qvm-ls --raw-data --fields NAME,FLAGS |\
          318          grep '|...N....$' | cut -d '|' -f1)" |\
          319          dmenu -l 50 -p "Select new UpdateVM" $dmenu_fmc)
          320 
          321        if [ -n "$value_selected" ]; then
          322 
          323          if ! qvm-check --running "$value_selected" > /dev/null 2>&1; then
          324 
          325            unset value_selected
          326 
          327            echo "Go back..." |\
          328              dmenu -p "$value_selected needs to be running!"\
          329              $dmenu_fmc > /dev/null 2>&1
          330          fi
          331        fi;;
          332 
          333      *)
          334    esac
          335 
          336    if [ -n "$value_selected" ]; then
          337 
          338      if ! qubes-prefs --set "$property" "$value_selected"; then
          339 
          340        echo "Go back..." |\
          341          dmenu -p "Error: Could not set $property to '$value_selected'!"\
          342          $dmenu_fmc > /dev/null 2>&1
          343      fi
          344    fi
          345  done
          346 )
          347 
          348 fqvm_applications() (
          349 
          350  option=0
          351 
          352  while [ -n "$option" ]; do
          353 
          354    option=$(printf "Available\nSelected" |\
          355      dmenu -i -l 2 -p "$target_qube:" $dmenu_fmc)
          356 
          357    if [ "$option" = "Available" ]; then
          358 
          359      applications=0
          360 
          361      while [ -n "$applications" ]; do
          362 
          363        # Only show applications that arent already selected for $target_qube via 'grep -v'.
          364        applications=$(qvm-appmenus --get-available --i-understand-format-is-unstable "$target_qube" |\
          365          grep -vw "$(qvm-appmenus --get-whitelist --i-understand-format-is-unstable "$target_qube")" |\
          366          dmenu -l 50 -p "$target_qube:" $dmenu_fmc | awk '{print $1}')
          367 
          368        if [ -n "$applications" ]; then
          369 
          370          # Check validity of input.
          371          if qvm-appmenus --get-available --i-understand-format-is-unstable "$target_qube" |\
          372            awk '{print $1}' | grep -w "$applications" > /dev/null 2>&1; then
          373 
          374            printf "\n$applications" >> "$HOME"/.local/share/qubes-appmenus/"$target_qube"/whitelisted-appmenus.list
          375 
          376            applications_modified=1
          377          fi
          378        fi
          379      done
          380 
          381    elif [ "$option" = "Selected" ]; then
          382 
          383      applications=0
          384 
          385      while [ -n "$applications" ]; do
          386 
          387        # Show complete application and .desktop names via 'grep'.
          388        applications=$(qvm-appmenus --get-available --i-understand-format-is-unstable "$target_qube" |\
          389          grep -w "$(qvm-appmenus --get-whitelist --i-understand-format-is-unstable "$target_qube")" |\
          390          dmenu -l 50 -p "$target_qube:" $dmenu_fmc | awk '{print $1}')
          391 
          392        if [ -n "$applications" ]; then
          393 
          394          for application in $applications; do
          395 
          396            # Look up linenumber above $application in
          397            # /whitelisted-appmenus.list and delete whitespace.
          398            whitespace=$(grep -B1 -wn "$application" <\
          399              "$HOME"/.local/share/qubes-appmenus/"$target_qube"/whitelisted-appmenus.list |\
          400              cut -c 1 | sed 2d)
          401 
          402            sed -i "${whitespace}{/^$/d;}" "$HOME"/.local/share/qubes-appmenus/"$target_qube"/whitelisted-appmenus.list
          403            sed -i "/$application/d" "$HOME"/.local/share/qubes-appmenus/"$target_qube"/whitelisted-appmenus.list
          404 
          405            applications_modified=1
          406          done
          407        fi
          408      done
          409    fi
          410 
          411    # Only update qvm-appmenus down here, *after* the user
          412    # has quit the application selection.
          413    if [ -n "$applications_modified" ]; then
          414 
          415      qvm-appmenus --update "$target_qube" > /dev/null 2>&1
          416 
          417      unset applications_modified
          418    fi
          419  done
          420 )
          421 
          422 fqvm_clone() (
          423 
          424  clone_name=$(true |\
          425    dmenu -p "Enter the name for the clone of $target_qube" $dmenu_fmc)
          426 
          427  if [ -n "$clone_name" ]; then
          428 
          429    option=0
          430 
          431    while [ -n "$option" ]; do
          432 
          433      option=$(printf "Create the clone\nAdvanced options" |\
          434        dmenu -i -l 2 -p "$target_qube:" $dmenu_fmc | awk '{print $1}')
          435 
          436      if [ "$option" = "Advanced" ]; then
          437 
          438        option_adv=0
          439 
          440        while [ -n "$option_adv" ]; do
          441 
          442          option_adv=$(printf "Class\nPool" |\
          443              dmenu -i -l 2 -p "$clone_name($target_qube):" $dmenu_fmc)
          444 
          445          if [ "$option_adv" = "Class" ]; then
          446 
          447            class=$(printf "AppVM\nDispVM\nStandaloneVM\nTemplateVM" |\
          448              dmenu -i -l 4 -p "Choose a class for $clone_name" $dmenu_fmc)
          449 
          450            if [ -n "$pool" ]; then class="-C $class"; fi
          451 
          452          elif [ "$option_adv" = "Pool" ]; then
          453 
          454            pool=$(qvm-pool --list | sed '1d' |\
          455              dmenu -i -l 10 -p "Select a pool for $clone_name"\
          456              $dmenu_fmc | awk '{print $1}')
          457 
          458            if [ -n "$pool" ]; then pool="-P $pool"; fi
          459          fi
          460        done
          461 
          462      elif [ "$option" = "Create" ]; then
          463 
          464        unset option
          465 
          466        qvm-clone $class $pool "$target_qube" "$clone_name"&
          467      fi
          468    done
          469  fi
          470 )
          471 
          472 fqvm_create() (
          473 
          474  new_name=$(true | dmenu -p "Enter the name of the qube to create:" $dmenu_fmc)
          475 
          476  if [ -n "$new_name" ]; then
          477 
          478    label=$(printf "Purple\nBlue\nGray\nGreen\nYellow\nOrange\nRed\nBlack" |\
          479      dmenu -i -l 8 -p "Select label for $new_name" $dmenu_fmc |\
          480      awk '{print tolower($0)}')
          481 
          482    if [ -n "$label" ]; then
          483 
          484      QUBEARGS="-l $label"
          485 
          486      class=$(printf "AppVM\nDispVM\nStandaloneVM\nTemplateVM" |\
          487        dmenu -i -l 4 -p "Choose a class for $new_name" $dmenu_fmc)
          488 
          489      if [ -n "$class" ]; then
          490 
          491        QUBEARGS="$QUBEARGS -C $class"
          492      fi
          493 
          494      # List templatevm's via 'qvm-ls'.
          495      template=$(printf "(Default)\n(None)\n$(qvm-ls --raw-data --fields NAME,FLAGS |\
          496        grep '|t.......$' | cut -d '|' -f1)" |\
          497        dmenu -l 50 -p "Select template for $new_name" $dmenu_fmc)
          498 
          499      if [ "$template" != "(Default)" ] && [ "$template" != "(None)" ]; then
          500 
          501        QUBEARGS="$QUBEARGS -t $template"
          502      fi
          503 
          504      netvm=$(printf "(Default)\n(None)\n$(qvm-ls --raw-data --fields NAME,FLAGS |\
          505        grep '|...N....$' | cut -d '|' -f1)" |\
          506        dmenu -l 50 -p "Select netvm for $new_name" $dmenu_fmc)
          507 
          508      if [ "$netvm" != "(Default)" ]; then
          509 
          510        if [ "$netvm" = "(None)" ]; then unset netvm; fi
          511 
          512        QUBEARGS="$QUBEARGS --prop netvm=$netvm"
          513      fi
          514 
          515      provides_network=$(printf "No\nYes" |\
          516        dmenu -i -p "Should $new_name provide networking for other qubes?" $dmenu_fmc)
          517 
          518      if [ "$provides_network" = "Yes" ]; then
          519 
          520        QUBEARGS="$QUBEARGS --prop provides_network=true"
          521      fi
          522 
          523      option=0
          524 
          525      while [ -n "$option" ]; do
          526 
          527        option=$(printf "Create the new qube\nAdvanced options" |\
          528          dmenu -i -l 2 -p "dom0:" $dmenu_fmc | awk '{print $1}')
          529 
          530        if [ "$option" = "Advanced" ]; then
          531 
          532          option_adv=$(printf "Pool" | dmenu -l 1 -p "$new_name:" $dmenu_fmc)
          533 
          534          if [ "$option_adv" = "Pool" ]; then
          535 
          536            pool=$(qvm-pool --list | sed '1d' |\
          537              dmenu -i -l 10 -p "Select a pool for $new_name" $dmenu_fmc |\
          538              awk '{print $1}')
          539 
          540            if [ -n "$pool" ]; then pool="-P $pool"; fi
          541          fi
          542 
          543        elif [ "$option" = "Create" ]; then
          544 
          545          qvm-create $QUBEARGS $pool "$new_name"&
          546 
          547          unset option
          548        fi
          549      done
          550    fi
          551  fi
          552 )
          553 
          554 fqvm_devices() (
          555 
          556  if ! qvm-check --running "$target_qube" > /dev/null 2>&1; then
          557 
          558    echo "Go back..." |\
          559      dmenu -p "$target_qube needs to be running, in order to attach devices to it"\
          560      $dmenu_fmc > /dev/null 2>&1
          561  else
          562 
          563    # Depending on the device type, we have to 
          564    # 'awk' different fields later on.
          565    if [ "$chosefrom" = "Audio" ]; then
          566 
          567      device_type="device mic"
          568 
          569      awk_devicename0=2
          570      awk_devicename1=10
          571      awk_targetqube=3
          572 
          573    elif [ "$chosefrom" = "Block" ]; then
          574 
          575      device_type="block"
          576 
          577      awk_devicename0=2
          578      awk_devicename1=3
          579      awk_targetqube=4
          580 
          581    elif [ "$chosefrom" = "USB" ]; then
          582 
          583      device_type="usb"
          584 
          585      awk_devicename0=2
          586      awk_devicename1=10
          587      awk_targetqube=3
          588    fi
          589 
          590    devices_list=$(qvm-$device_type)
          591 
          592    device=0
          593 
          594    while [ -n "$device" ]; do
          595 
          596      device=$(echo "$devices_list" |\
          597        dmenu -l 16 -p "$target_qube:" $dmenu_fmc)
          598 
          599      device_id=$(echo "$device" | awk '{print $1}')
          600 
          601      device_name=$(echo "$device" |\
          602        awk '{print $'$awk_devicename0'$'$awk_devicename1'}')
          603 
          604      if [ -n "$device" ]; then
          605 
          606        holds_qube=$(echo "$devices_list" | grep "$device_id" |\
          607          awk '{print $'$awk_targetqube'}')
          608 
          609        if [ -z "$holds_qube" ]; then
          610 
          611          answer=$(printf "No\nYes" |\
          612            dmenu -i -p "Attach $device_name to $target_qube?"\
          613            $dmenu_fmc)
          614 
          615          if [ "$answer" = "Yes" ]; then
          616 
          617            unset device
          618 
          619            qvm-$device_type attach "$target_qube" "$device_id"&
          620          fi
          621 
          622        elif [ "$holds_qube" = "$target_qube" ]; then
          623 
          624          answer=$(printf "No\nYes" |\
          625            dmenu -i -p "Detach $device_name from $target_qube?"\
          626            $dmenu_fmc)
          627 
          628          if [ "$answer" = "Yes" ]; then
          629 
          630            unset device
          631 
          632            qvm-$device_type detach "$holds_qube" "$device_id"&
          633          fi
          634        else
          635 
          636          answer=$(printf "No\nYes" |\
          637            dmenu -i -p "Detach $device_name from $holds_qube and attach it to $target_qube?"\
          638            $dmenu_fmc)
          639 
          640          if [ "$answer" = "Yes" ]; then
          641 
          642            unset device
          643 
          644            $(qvm-$device_type detach "$holds_qube" "$device_id" &&
          645              qvm-$device_type attach "$target_qube" "$device_id")&
          646          fi
          647        fi
          648      fi
          649    done
          650  fi
          651 )
          652 
          653 fqvm_disk() (
          654 
          655  qube_class=$(qvm-ls --raw-data -O flags "$target_qube" | cut -c 1)
          656 
          657  # If $target_qube is template or standalone, give option to extend root storage.
          658  if [ "$qube_class" = "t" ] ||\
          659    [ "$qube_class" = "s" ] ||\
          660    [ "$qube_class" = "S" ]; then
          661 
          662    volume=$(printf "Root\nPrivate" |\
          663      dmenu -l 2 -i -p "$target_qube:" $dmenu_fmc | awk '{print tolower($0)}')
          664 
          665  else
          666 
          667    volume="private"
          668  fi
          669 
          670  if [ -n "$volume" ]; then
          671 
          672    current_storage=$(( $(qvm-volume info "$target_qube:$volume" size) / 1024/1024 ))
          673 
          674    mebibyte=$(echo "$current_storage" |\
          675      dmenu -p "Enter the maximum size of $volume storage in MiB to be allocated to $target_qube"\
          676      $dmenu_fmc)
          677 
          678    if [ -n "$mebibyte" ]; then
          679 
          680      if [ "$mebibyte" -gt "$current_storage" ]; then
          681 
          682        byte=$(( mebibyte * 1024*1024 ))
          683 
          684        answer=$(printf "No\nYes" |\
          685          dmenu -i -p "Increase the maximum $volume storage size of $target_qube from $current_storage MiB to $mebibyte MiB?"\
          686          $dmenu_fmc)
          687 
          688        if [ "$answer" = "Yes" ]; then
          689 
          690          qvm-volume extend "$target_qube:$volume" "$byte"&
          691        fi
          692      else
          693 
          694        echo "Go back..." |\
          695          dmenu -p "Error: Can not decrease the maximum $volume storage!"\
          696          $dmenu_fmc > /dev/null 2>&1
          697      fi
          698    fi
          699  fi
          700 )
          701 
          702 fqvm_firewall() (
          703 
          704  rulenumber_selected=0
          705 
          706  while [ -n "$rulenumber_selected" ]; do
          707 
          708    rulenumber_selected=$(qvm-firewall $target_qube list |\
          709      dmenu -l 50 -p "$target_qube:" $dmenu_fmc | awk '{print $1}')
          710 
          711    if [ -n "$rulenumber_selected" ]; then
          712 
          713      # This will equal "NO" if the user selects the top row,
          714      # instead of any existing rule.
          715      if [ "$rulenumber_selected" != "NO" ]; then
          716 
          717        option=$(printf "Add new rule above rule $rulenumber_selected\nRemove rule $rulenumber_selected" |\
          718          dmenu -i -l 2 -p "$target_qube:" $dmenu_fmc | awk '{print $1}')
          719      else
          720 
          721        option="Add"
          722      fi
          723 
          724      if [ "$option" = "Remove" ]; then
          725 
          726        answer=$(printf "No\nYes" |\
          727          dmenu -i -p "Remove rule $rulenumber_selected?" $dmenu_fmc)
          728 
          729        if [ "$answer" = "Yes" ]; then
          730 
          731          qvm-firewall "$target_qube" del --rule-no "$rulenumber_selected"
          732        fi
          733 
          734      elif [ "$option" = "Add" ]; then
          735 
          736        if [ -n "$RULEARGS" ]; then unset RULEARGS; fi
          737 
          738        action=$(printf "Accept\nDrop" |\
          739          dmenu -i -l 2 -p "Select action for the new firewall rule" $dmenu_fmc |\
          740          awk '{print tolower($0)}')
          741 
          742        if [ -n "$action" ]; then
          743 
          744          RULEARGS="$action"
          745 
          746          specialtarget=$(true |\
          747            dmenu -p "ACTION=$RULEARGS <specialtarget>" $dmenu_fmc)
          748 
          749          if [ -n "$specialtarget" ]; then
          750 
          751            RULEARGS="$RULEARGS SPECIALTARGET=$specialtarget"
          752          fi
          753 
          754          dsthost=$(true |\
          755            dmenu -p "ACTION=$RULEARGS <dsthost>" $dmenu_fmc)
          756 
          757          if [ -n "$dsthost" ]; then
          758 
          759            RULEARGS="$RULEARGS DSTHOST=$dsthost"
          760          fi
          761 
          762          proto=$(true |\
          763            dmenu -p "ACTION=$RULEARGS <proto>" $dmenu_fmc)
          764 
          765          if [ -n "$proto" ]; then
          766 
          767            RULEARGS="$RULEARGS PROTO=$proto"
          768          fi
          769 
          770          if [ "$proto" = "tcp" ] || [ "$proto" = "udp" ]; then
          771 
          772            dstports=$(true |\
          773              dmenu -p "ACTION=$RULEARGS <dstports>" $dmenu_fmc)
          774 
          775            if [ -n "$dstports" ]; then
          776 
          777              RULEARGS="$RULEARGS DSTPORTS=$dstports"
          778            fi
          779 
          780          elif [ "$proto" = "icmp" ]; then
          781 
          782            icmptype=$(true |\
          783              dmenu -p "ACTION=$RULEARGS <icmptype>" $dmenu_fmc)
          784 
          785            if [ -n "$icmptype" ]; then
          786 
          787              RULEARGS="$RULEARGS ICMPTYPE=$icmptype"
          788            fi
          789          fi
          790 
          791          expire=$(true |\
          792            dmenu -p "ACTION=$RULEARGS <expire>" $dmenu_fmc)
          793 
          794          if [ -n "$expire" ]; then
          795 
          796            RULEARGS="EXPIRE=$expire"
          797          fi
          798 
          799          comment=$(true |\
          800            dmenu -p "ACTION=$RULEARGS <comment>" $dmenu_fmc)
          801 
          802          if [ -n "$comment" ]; then
          803 
          804            RULEARGS="$RULEARGS COMMENT=$comment"
          805          fi
          806 
          807          answer=$(printf "No\nYes" |\
          808            dmenu -i -p "Add the following rule to $target_qube? {{ ACTION=$RULEARGS }}"\
          809            $dmenu_fmc)
          810 
          811          if [ "$answer" = "Yes" ]; then
          812 
          813            if [ -n "$beforerule" ]; then unset beforerule; fi
          814 
          815            if [ "$rulenumber_selected" != "NO" ]; then
          816 
          817              beforerule=$(echo --before "$rulenumber_selected")
          818            fi
          819 
          820            RULEARGS=$(echo "$RULEARGS" | awk '{print tolower($0)}')
          821 
          822            if ! qvm-firewall "$target_qube" add $beforerule $RULEARGS; then
          823 
          824              echo "Go back..." | dmenu $dmenu_fmc\
          825                -p "Error: Failed to add firewall rule! See 'qvm-firewall --help' for more information."\
          826                > /dev/null 2>&1
          827            fi
          828          fi
          829        fi
          830      fi
          831    fi
          832  done
          833 )
          834 
          835 fqvm_keyboard() (
          836 
          837  # 'qmenu-vm' does not get informed about the installed layouts by the vm itself
          838  # so it is possible that the selected layout is missing inside the vm.
          839  # Getting the info from the vm itself however would have security implications
          840  # so we will not switch to use that method.
          841  LAYOUT=$(ls /usr/share/X11/xkb/symbols |\
          842    dmenu -l 50 -p "$target_qube:" $dmenu_fmc)
          843 
          844  if [ -n "$LAYOUT" ]; then
          845 
          846    if test -d /usr/share/X11/xkb/symbols/$LAYOUT; then
          847 
          848      LAYOUT="$LAYOUT/"$(ls /usr/share/X11/xkb/symbols/"$LAYOUT" |\
          849        dmenu -l 50 -p "$target_qube:" $dmenu_fmc)
          850    fi
          851 
          852    if ! qvm-run "$target_qube" "setxkbmap $LAYOUT"; then
          853 
          854      echo "Go back..." |\
          855        dmenu -p "Error: Could not set keyboard layout to '$LAYOUT' in $target_qube! Please check the installed layouts inside the qube itself."\
          856        $dmenu_fmc > /dev/null 2>&1
          857    fi
          858  fi
          859 )
          860 
          861 fqvm_logs() (
          862 
          863  if [ "$target_qube" = "dom0" ]; then
          864 
          865    logs="/var/log/xen/console/hypervisor.log"
          866  else
          867 
          868    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"
          869  fi
          870 
          871  entry=0
          872 
          873  while [ -n "$entry" ]; do
          874 
          875    entry=$(printf "$logs" |\
          876      dmenu -i -l 3 -p "$target_qube:" $dmenu_fmc)
          877 
          878    if [ -n "$entry" ]; then
          879 
          880      log=$(dmenu -l 20 -p "$target_qube:" $dmenu_fmc < "$entry")
          881 
          882      if [ -n "$log" ]; then
          883 
          884        echo "$log" > /var/run/qubes/qubes-clipboard.bin
          885 
          886        printf "dom0" > /var/run/qubes/qubes-clipboard.bin.source
          887      fi
          888    fi
          889  done
          890 )
          891 
          892 fqvm_pci() (
          893 
          894  if qvm-check --running "$target_qube" > /dev/null 2>&1; then
          895 
          896    echo "Go back..." |\
          897      dmenu -p "$target_qube needs to be powered off, in order to attach or detach PCI devices"\
          898      $dmenu_fmc > /dev/null 2>&1
          899  else
          900 
          901    list_pci=$(qvm-pci)
          902 
          903    if ! qvm-prefs --get "$target_qube" maxmem | grep -w 0 > /dev/null 2>&1; then
          904 
          905      answer_memorybalancing=$(printf "Continue anyways\nDisable dynamic memory balancing" |\
          906        dmenu -l 2 -i -p "Dynamic memory balancing is enabled in $target_qube, some devices might not work!"\
          907        $dmenu_fmc | awk '{print $1}')
          908 
          909      if [ "$answer_memorybalancing" = "Disable" ]; then
          910 
          911        qvm-prefs --set "$target_qube" maxmem 0
          912      fi
          913    fi
          914 
          915    if qvm-prefs --get "$target_qube" virt_mode |\
          916      grep -w pvh > /dev/null 2>&1; then
          917 
          918      answer_virtmode=$(printf "Continue anyways\nSelect another virtualisation mode" |\
          919        dmenu -l 2 -i -p "$target_qube is using PVH for its virtualisation mode, which does not support PCI passthrough!"\
          920        $dmenu_fmc | awk '{print $1}')
          921 
          922      if [ "$answer_virtmode" = "Select" ]; then
          923 
          924        virtmode_selected=$(printf "HVM\nPV" |\
          925          dmenu -l 2 -i -p "Select virtualisation mode for $target_qube" $dmenu_fmc)
          926 
          927        if [ -n "$virtmode_selected" ]; then
          928 
          929          qvm-prefs --set "$target_qube" virt_mode "$virtmode_selected"
          930        fi
          931      fi
          932    fi
          933 
          934    device_selected=0
          935 
          936    while [ -n "$device_selected" ]; do
          937 
          938      device_selected=$(echo "$list_pci" |\
          939        dmenu -l 30 -p "$target_qube:" $dmenu_fmc)
          940 
          941      if [ -n "$device_selected" ]; then
          942 
          943        device_src=$(echo "$device_selected" | awk '{print $1}' | sed 's/:.*//')
          944        device_bdf=$(echo "$device_selected" | awk '{print $1}' | sed 's/.*://')
          945 
          946        if echo "$device_selected" | grep -w "$target_qube"; then
          947 
          948          answer=$(printf "No\nYes" |\
          949            dmenu -i -p "Detach \"$device_bdf\" from $target_qube?" $dmenu_fmc)
          950 
          951          if [ "$answer" = "Yes" ]; then
          952 
          953            if ! test_qvm-pci detach "$target_qube" "$device_src":"$device_bdf"; then
          954 
          955              echo "Go back..." |\
          956                dmenu -p "Error: Failed to detach \"$device_bdf\" from $target_qube!"\
          957                $dmenu_fmc > /dev/null 2>&1
          958            fi
          959 
          960            list_pci=$(qvm-pci)
          961          fi
          962        else
          963 
          964          answer=$(printf "No\nYes" |\
          965            dmenu -i -p "Attach \"$device_bdf\" to $target_qube?" $dmenu_fmc)
          966 
          967          if [ "$answer" = "Yes" ]; then
          968 
          969            # Check if there is more than one function
          970            # that belongs to the same device.
          971            bdf_count=$(echo "$list_pci" | awk '{print $1}' |\
          972              grep -c $(echo "$device_bdf" | sed 's/\..*//'))
          973 
          974            if [ "$bdf_count" -gt 1 ]; then
          975 
          976              if [ -n "$pci_option" ]; then unset pci_option; fi
          977 
          978                answer_nsrt=$(printf "No\nYes" |\
          979                  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?"\
          980                  $dmenu_fmc)
          981 
          982              if [ "$answer_nsrt" = "Yes" ]; then
          983 
          984                pci_option="-o no-strict-reset=True"
          985              fi
          986            fi
          987 
          988            if ! qvm-pci attach --persistent $pci_option "$target_qube" "$device_src:$device_bdf"; then
          989 
          990              echo "Go back..." |\
          991                dmenu -p "Error: Failed to attach \"$device_bdf\" to $target_qube!"\
          992                $dmenu_fmc > /dev/null 2>&1
          993            fi
          994 
          995            list_pci=$(qvm-pci)
          996          fi
          997        fi
          998      fi
          999    done
         1000  fi
         1001 )
         1002 
         1003 fqvm_preferences() (
         1004 
         1005  property=0
         1006 
         1007  while [ -n "$property" ]; do
         1008 
         1009    property=$(qvm-prefs "$target_qube" |\
         1010      dmenu -l 45 -p "$target_qube:" $dmenu_fmc |\
         1011      awk '{print $1}')
         1012 
         1013    if [ -n "$property" ]; then
         1014 
         1015      case $property in
         1016 
         1017        autostart)
         1018 
         1019          value_selected=$(printf "False\nTrue" |\
         1020            dmenu -i -p "Set autostart of $target_qube to:" $dmenu_fmc);;
         1021 
         1022        debug)
         1023 
         1024          value_selected=$(printf "False\nTrue" |\
         1025            dmenu -i -p "Set debug mode of $target_qube to:" $dmenu_fmc);;
         1026 
         1027        default_dispvm)
         1028 
         1029          if [ -n "$LIST_OF_DISPTEMP" ]; then unset LIST_OF_DISPTEMP; fi
         1030 
         1031          # [mediocre] Look up disposable templates.
         1032          for n in $(qvm-ls --raw-data -O NAME,FLAGS |\
         1033            grep '|a.......$' | cut -d '|' -f1); do
         1034 
         1035            if qvm-prefs --get "$n" template_for_dispvms |\
         1036              grep True > /dev/null 2>&1; then
         1037 
         1038              LIST_OF_DISPTEMP="$LIST_OF_DISPTEMP\n$n"
         1039            fi
         1040          done
         1041 
         1042          value_selected=$(printf "(Default)\n(None)$LIST_OF_DISPTEMP" |\
         1043            dmenu -l 50 -p "Select default dispvm for $target_qube" $dmenu_fmc)
         1044 
         1045          if [ "$value_selected" = "(None)" ]; then
         1046 
         1047            value_selected="None"
         1048 
         1049          elif [ "$value_selected" = "(Default)" ]; then
         1050 
         1051            value_selected="--default"
         1052          fi;;
         1053 
         1054        default_user)
         1055 
         1056          value_selected=$(echo "--default" |\
         1057            dmenu -p "Enter the name of the default user for $target_qube"\
         1058            $dmenu_fmc);;
         1059 
         1060        include_in_backups)
         1061 
         1062          value_selected=$(printf "False\nTrue" |\
         1063            dmenu -i -p "Include $target_qube in backups?" $dmenu_fmc);;
         1064 
         1065        kernel)
         1066 
         1067          value_selected=$(echo "--default" |\
         1068            dmenu -p "Enter kernel to be used by $target_qube" $dmenu_fmc)
         1069 
         1070          if [ -n "$value_selected" ]; then
         1071 
         1072            answer_selected=$(printf "No\nYes" |\
         1073              dmenu -i -p "Set kernel of $target_qube to $value_selected?"\
         1074              $dmenu_fmc)
         1075 
         1076            if [ "$answer_selected" != "Yes" ]; then
         1077 
         1078              unset value_selected
         1079            fi
         1080          fi;;
         1081 
         1082        kernelopts)
         1083 
         1084          value_selected=$(echo "--default" |\
         1085            dmenu -p "Enter kernel options for $target_qube" $dmenu_fmc)
         1086 
         1087          if [ -n "$value_selected" ]; then
         1088 
         1089            answer_selected=$(printf "No\nYes" |\
         1090              dmenu -i -p "Set kernel options for $target_qube to \"$value_selected\"?"\
         1091              $dmenu_fmc)
         1092 
         1093            if [ "$answer_selected" != "Yes" ]; then
         1094 
         1095              unset value_selected
         1096            fi
         1097          fi;;
         1098 
         1099        label)
         1100 
         1101          if qvm-check --running "$target_qube" > /dev/null 2>&1; then
         1102 
         1103            echo "Go back..." |\
         1104              dmenu -p "$target_qube needs to be powered off, in order to change its label"\
         1105              $dmenu_fmc > /dev/null 2>&1
         1106          else
         1107 
         1108            value_selected=$(printf "Purple\nBlue\nGray\nGreen\nYellow\nOrange\nRed\nBlack" |\
         1109              dmenu -i -l 8 -p "Select label for $target_qube" $dmenu_fmc |\
         1110              awk '{print tolower($0)}')
         1111          fi;;
         1112 
         1113        mac)
         1114 
         1115          value_selected=$(echo "--default" |\
         1116            dmenu -p "Enter new MAC address for $target_qube" $dmenu_fmc)
         1117 
         1118          if [ -n "$value_selected" ]; then
         1119 
         1120            answer_selected=$(printf "No\nYes" |\
         1121              dmenu -i -p "Set MAC address of $target_qube to $value_selected?"\
         1122              $dmenu_fmc)
         1123 
         1124            if [ "$answer_selected" != "Yes" ]; then
         1125 
         1126              unset value_selected 
         1127            fi
         1128          fi;;
         1129 
         1130        maxmem)
         1131 
         1132          value_selected=$(echo "--default" |\
         1133            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."\
         1134            $dmenu_fmc)
         1135 
         1136          if [ -n "$value_selected" ]; then
         1137 
         1138            answer_selected=$(printf "No\nYes" |\
         1139              dmenu -i -p "Set maximum memory of $target_qube to $value_selected MB?"\
         1140              $dmenu_fmc)
         1141 
         1142            if [ "$answer_selected" != "Yes" ]; then
         1143 
         1144              unset value_selected
         1145            fi
         1146          fi;;
         1147 
         1148        memory)
         1149 
         1150          value_selected=$(echo "--default" |\
         1151            dmenu -p "Enter the amount of initial memory in MB to be allocated to $target_qube"\
         1152            $dmenu_fmc)
         1153 
         1154          if [ -n "$value_selected" ]; then
         1155 
         1156            answer_selected=$(printf "No\nYes" |\
         1157              dmenu -i -p "Set initial memory of $target_qube to $value_selected MB?" $dmenu_fmc)
         1158 
         1159            if [ "$answer_selected" != "Yes" ]; then
         1160 
         1161              unset answer_selected
         1162            fi
         1163          fi;;
         1164 
         1165        netvm)
         1166 
         1167          # List netvms via 'qvm-ls'.
         1168          value_selected=$(printf "(Default)\n(None)\n$(qvm-ls --raw-data --fields NAME,FLAGS |\
         1169            grep '|...N....$' | cut -d '|' -f1)" |\
         1170            dmenu -l 50 -p "Select netvm for $target_qube" $dmenu_fmc)
         1171 
         1172          if [ "$value_selected" = "(None)" ]; then
         1173 
         1174            value_selected="None"
         1175 
         1176          elif [ "$value_selected" = "(Default)" ]; then
         1177 
         1178            value_selected="--default"
         1179          fi;;
         1180 
         1181        provides_network)
         1182 
         1183          value_selected=$(printf "False\nTrue" |\
         1184            dmenu -i -p "Should $target_qube provide networking for other qubes?"\
         1185            $dmenu_fmc);;
         1186 
         1187        qrexec_timeout)
         1188 
         1189          value_selected=$(echo "--default" |\
         1190            dmenu -p "Enter the time in seconds, after which qrexec attempt is deemed a failure for $target_qube"\
         1191            $dmenu_fmc)
         1192 
         1193          if [ -n "$value_selected" ]; then
         1194 
         1195            answer_selected=$(printf "No\nYes" |\
         1196              dmenu -i -p "Set qrexec timeout for $target_qube to $value_selected seconds?"\
         1197              $dmenu_fmc)
         1198 
         1199            if [ "$answer_selected" != "Yes" ]; then
         1200 
         1201              unset value_selected
         1202            fi
         1203          fi;;
         1204 
         1205        shutdown_timeout)
         1206 
         1207          value_selected=$(echo "--default" |\
         1208            dmenu -p "Enter the time in seconds for shutdown, after which $target_qube may be forcefully powered off"\
         1209            $dmenu_fmc)
         1210 
         1211          if [ -n "$value_selected" ]; then
         1212 
         1213            answer_selected=$(printf "No\nYes" |\
         1214              dmenu -i -p "Set shutdown timeout for $target_qube to $value_selected seconds?"\
         1215              $dmenu_fmc)
         1216 
         1217            if [ "$answer_selected" != "Yes" ]; then
         1218 
         1219              unset value_selected
         1220            fi
         1221          fi;;
         1222 
         1223        template)
         1224 
         1225          if qvm-check --running "$target_qube" > /dev/null 2>&1; then
         1226 
         1227            echo "Go back..." |\
         1228              dmenu -p "$target_qube needs to be powered off, in order to change its template"\
         1229              $dmenu_fmc > /dev/null 2>&1
         1230          else
         1231 
         1232            # List templatevm's via 'qvm-ls'.
         1233            value_selected=$(printf "(Default)\n$(qvm-ls --raw-data --fields NAME,FLAGS |\
         1234              grep '|t.......$' | cut -d '|' -f1)" |\
         1235              dmenu -l 50 -p "Select template for $target_qube" $dmenu_fmc)
         1236 
         1237            if [ "$value_selected" = "(Default)" ]; then
         1238 
         1239              value_selected="--default"
         1240            fi
         1241          fi;;
         1242 
         1243        template_for_dispvms)
         1244 
         1245          value_selected=$(printf "False\nTrue" |\
         1246            dmenu -i -p "Should $target_qube be used as a template for disposable qubes?"\
         1247            $dmenu_fmc);;
         1248 
         1249        vcpus)
         1250 
         1251          value_selected=$(echo "--default" |\
         1252            dmenu -p "Enter the number of CPU cores that should be made available to $target_qube"\
         1253            $dmenu_fmc)
         1254 
         1255          if [ -n "$value_selected" ]; then
         1256 
         1257            answer_selected=$(printf "No\nYes" |\
         1258              dmenu -i -p "Set number of CPU cores available to $target_qube to $value_selected?"\
         1259              $dmenu_fmc)
         1260 
         1261            if [ "$answer_selected" != "Yes" ]; then
         1262 
         1263              unset value_selected
         1264            fi
         1265          fi;;
         1266 
         1267        virt_mode)
         1268 
         1269          value_selected=$(printf "PVH\nHVM\nPV" |\
         1270            dmenu -i -l 3 -p "Select virtualisation mode for $target_qube"\
         1271            $dmenu_fmc);;
         1272 
         1273        *)
         1274      esac
         1275 
         1276      if [ -n "$value_selected" ]; then
         1277 
         1278        if ! qvm-prefs --set "$target_qube" "$property" "$value_selected"; then
         1279 
         1280          echo "Go back..." |\
         1281            dmenu -p "Error: Could not set $property to '$value_selected'!"\
         1282            $dmenu_fmc > /dev/null 2>&1
         1283        fi
         1284 
         1285        unset value_selected
         1286      fi
         1287    fi
         1288  done
         1289 )
         1290 
         1291 fqvm_remove() {
         1292 
         1293  if qvm-check --running "$target_qube" > /dev/null 2>&1; then
         1294 
         1295    echo "Go back..." |\
         1296      dmenu -p "$target_qube needs to be powered off, in order to be removed"\
         1297      $dmenu_fmc > /dev/null 2>&1
         1298  else
         1299 
         1300    confirmation=$(true |\
         1301      dmenu -p "Enter the name of the qube '$target_qube' in order to remove it"\
         1302      $dmenu_fmc)
         1303 
         1304    if [ "$target_qube" = "$confirmation" ]; then
         1305 
         1306      confirmation_semifinal=$(printf "No\nYes" |\
         1307        dmenu -i -p "Are you sure you want to remove $target_qube permanently?"\
         1308        $dmenu_fmc)
         1309 
         1310      if [ "$confirmation_semifinal" = "Yes" ]; then
         1311 
         1312        confirmation_final=$(printf "No\nYes" |
         1313          dmenu -i -p "Are you really sure you want to remove $target_qube permanently?"\
         1314          $dmenu_fmc)
         1315 
         1316        if [ "$confirmation_final" = "Yes" ]; then
         1317 
         1318          qvm-remove -f "$target_qube"&
         1319 
         1320          unset chosefrom
         1321        fi
         1322      fi
         1323    fi
         1324  fi
         1325 }
         1326 
         1327 fqvm_run() (
         1328 
         1329  commandtr=$(true |\
         1330    dmenu -p "Run command in $target_qube:" $dmenu_fmc)
         1331 
         1332  if [ -n "$commandtr" ]; then qvm-run "$target_qube" "$commandtr"& fi
         1333 )
         1334 
         1335 fqvm_service() (
         1336 
         1337  service=0
         1338 
         1339  while [ -n "$service" ]; do
         1340 
         1341    service=$(qvm-service "$target_qube" --list |\
         1342      dmenu -l 32 -p "$target_qube:" $dmenu_fmc | awk '{print $1}')
         1343 
         1344    if [ -n "$service" ]; then
         1345 
         1346      # If the service has already been added to the list,
         1347      # give option to unset it.
         1348      if qvm-service "$target_qube" --list | grep -w "$service"; then
         1349 
         1350         unset="\nUnset"
         1351      fi
         1352 
         1353      value=$(printf "Disable\nEnable$unset" |\
         1354        dmenu -l 3 -i -p "Select value for '$service'" $dmenu_fmc)
         1355 
         1356      if [ "$value" = "Disable" ]; then
         1357 
         1358        if ! qvm-service "$target_qube" "$service" off; then
         1359 
         1360          echo "Go back..." | dmenu -p "Error: Could not deactivate $service!"\
         1361            $dmenu_fmc > /dev/null 2>&1
         1362        fi
         1363 
         1364      elif [ "$value" = "Enable" ]; then
         1365 
         1366        if ! qvm-service "$target_qube" "$service" on; then
         1367 
         1368          echo "Go back..." | dmenu -p "Error: Could not activate $service!"\
         1369            $dmenu_fmc > /dev/null 2>&1
         1370        fi
         1371 
         1372      elif [ "$value" = "Unset" ]; then
         1373 
         1374        if ! qvm-service "$target_qube" "$service" --unset; then
         1375 
         1376          echo "Go back..." | dmenu -p "Error: Could not unset $service!"\
         1377            $dmenu_fmc > /dev/null 2>&1
         1378        fi
         1379      fi
         1380 
         1381      if [ -n "$unset" ]; then unset unset; fi
         1382    fi
         1383  done
         1384 )
         1385 
         1386 fqvm_tags() (
         1387 
         1388  tag=0
         1389 
         1390  while [ -n "$tag" ]; do
         1391 
         1392    tag=$(qvm-tags "$target_qube" list |\
         1393      dmenu -l 15 -p "$target_qube:" $dmenu_fmc | awk '{print $1}')
         1394 
         1395    if [ -n "$tag" ]; then
         1396 
         1397      if qvm-tags "$target_qube" list | grep -w "$tag"; then
         1398 
         1399        answer=$(printf "No\nYes" |\
         1400          dmenu -i -p "Remove tag '$tag' from $target_qube?" $dmenu_fmc)
         1401 
         1402        if [ "$answer" = "Yes" ]; then
         1403 
         1404          qvm-tags "$target_qube" del "$tag"
         1405        fi
         1406      else
         1407 
         1408        qvm-tags "$target_qube" add "$tag"
         1409      fi
         1410    fi
         1411  done
         1412 )
         1413 
         1414 get_qube_label() {
         1415 
         1416  qube_label=$(qvm-ls --raw-data "$target_qube" -O LABEL)
         1417 
         1418  # Change label colors according to ~/.config/qmenu.conf if that file exists.
         1419  if [ -f "$HOME/.config/qmenu.conf" ]; then
         1420 
         1421    qube_label=$(grep "^$qube_label=" "$HOME"/.config/qmenu.conf | cut -d= -f2)
         1422  fi
         1423 
         1424  # Note that the '-m 0' option in 'dmenu' is important
         1425  # for security, as it restricts it to monitor 0.
         1426  dmenu_fmc="-f -m 0 -sb $qube_label"
         1427 }
         1428 
         1429 rearrange_qube_list() {
         1430 
         1431  qube_list=$(echo "$qube_list" |\
         1432    awk -v ListInOrder="LABEL,purple,blue,gray,green,yellow,orange,red,black" '
         1433    BEGIN {
         1434    split(ListInOrder, a, ",")
         1435    for (i = 1; i <= length(a); ++i) ListToOrdinal[a[i]] = i
         1436    }
         1437    {print ListToOrdinal[$3] "-" $0}
         1438    ' | sort -t- -k1,1n | cut -d- -f2-)
         1439 }
         1440 
         1441 case $1 in
         1442 
         1443   --all)
         1444 
         1445     # As of 20190823, 'qvm-ls --all' will not list dom0 because of a bug.
         1446     # As a workaround, we will 'shift' $1 and, if needed, $2.
         1447     shift
         1448     if [ -n "$1" ]; then shift; fi;;
         1449 
         1450   --focused)
         1451 
         1452     target_qube=$(xprop -id "$(xdotool getwindowfocus)" |\
         1453       grep -w '^_QUBES_VMNAME(STRING)' | cut -d\" -f2)
         1454 
         1455     if [ -z "$target_qube" ]; then
         1456 
         1457       target_qube=dom0
         1458 
         1459       fmenu_fqubes
         1460     else
         1461 
         1462       fmenu_fqvm
         1463     fi
         1464 
         1465     exit 1;;
         1466 
         1467   --halted|--paused|--running|--tags=*);;
         1468 
         1469   *)
         1470 
         1471     printf "qmenu-vm [OPTION]\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"
         1472 
         1473     if [ "$1" = "--help" ]; then exit 0; else exit 2; fi
         1474 esac
         1475 
         1476 while true; do
         1477 
         1478   # Load 'qvm-ls' into a variable so that it doesnt
         1479   # need to reload again after every user operation.
         1480   qube_list=$(qvm-ls --no-spinner $1 -O NAME,STATE,LABEL,CLASS\
         1481 ,TEMPLATE,NETVM,IP,PRIV-MAX,PRIV-CURR,PRIV-USED,ROOT-MAX\
         1482 ,ROOT-CURR,ROOT-USED,KERNEL,KERNELOPTS)
         1483 
         1484   rearrange_qube_list
         1485 
         1486   if [ -n "$target_qube" ]; then unset target_qube; fi
         1487 
         1488   # Get out of the while loop and refresh 'qvm-ls' by loading it again
         1489   # into $qube_list, whenever the user selects the 'qvm-ls' top row.
         1490   while [ "$target_qube" != "NAME" ]; do
         1491 
         1492     target_qube=$(echo "$qube_list" | dmenu -f -m 0 -l 69 |\
         1493       awk '{print $1}')
         1494 
         1495     if [ -z "$target_qube" ]; then exit 1
         1496 
         1497     elif [ "$target_qube" != "NAME" ]; then
         1498 
         1499       if [ "$target_qube" = "dom0" ]; then
         1500 
         1501         fmenu_fqubes
         1502       else
         1503 
         1504         fmenu_fqvm
         1505       fi
         1506     fi
         1507   done
         1508 done