-
-
Notifications
You must be signed in to change notification settings - Fork 21
Rewrite qubes-i3-sensible-terminal
#24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,35 +1,166 @@ | ||
| #!/bin/sh | ||
| set -eu | ||
| #!/usr/bin/bash --posix | ||
|
|
||
| # Set POSIX-compliant mode to make bash and certain utils more predictable. | ||
| # Bash-specific features are still used, that's intentional | ||
| POSIXLY_CORRECT=1 | ||
| set -o posix | ||
| readonly POSIXLY_CORRECT | ||
| export POSIXLY_CORRECT | ||
|
|
||
| # Set IFS explicitly. POSIX does not enforce whether IFS should be inherited | ||
| # from the environment, so it's safer to set it explicitly | ||
| IFS=$' \t\n' | ||
| export IFS | ||
|
|
||
| # Exit on errors and unset variables | ||
| set -eEu | ||
|
|
||
| declare -r GUIVM_TERMINAL="i3-sensible-terminal" | ||
| declare -r DOMU_TERMINAL="qubes-run-terminal" | ||
| declare -r DOMU_CONSOLE="qvm-console-dispvm" | ||
|
|
||
|
|
||
| print_usage() | ||
| { | ||
| cat << USAGE >&2 | ||
| Usage: $(basename "$0") [--console] [--user USER] | ||
|
|
||
| Options: | ||
| -h, --help print this usage information | ||
| -c, --console launch disposable console instead of terminal | ||
| -u, --user run terminal as specified user | ||
| USAGE | ||
| return 0 | ||
| } | ||
|
|
||
|
|
||
| main() { | ||
| cmd="" | ||
| case "${1-}" in | ||
| console) cmd="$1";; | ||
| "");; | ||
| *) printf '%s\n' "Invalid argument" >&2; exit 1;; | ||
| esac | ||
|
|
||
| guivm_terminal=i3-sensible-terminal | ||
| domU_terminal=qubes-run-terminal | ||
| domU_console=qvm-console-dispvm | ||
| id="$(xprop -root _NET_ACTIVE_WINDOW)" | ||
| id="${id##* }" | ||
| vm="$(xprop -id "$id" | grep '_QUBES_VMNAME(STRING)')" || true | ||
| if test -z "$vm"; then | ||
| exec "$guivm_terminal" | ||
| fi | ||
| vm="${vm#*\"}" | ||
| vm="${vm%\"*}" | ||
|
|
||
| if test "$cmd" = "console"; then | ||
| exec "$domU_console" -- "$vm" | ||
| fi | ||
|
|
||
| if command -v qrexec-client >/dev/null; then | ||
| exec qrexec-client -e -d "$vm" -- \ | ||
| "DEFAULT:QUBESRPC qubes.StartApp+$domU_terminal $vm" | ||
| fi | ||
| exec qvm-run --no-gui --service -- "$vm" qubes.StartApp+"$domU_terminal" | ||
| # Get ID of active window | ||
| local id | ||
| id="$(xprop -root _NET_ACTIVE_WINDOW)" | ||
| id="${id##* }" | ||
| declare -r id | ||
|
|
||
| local vm | ||
| vm="$(xprop -id "$id" | grep '_QUBES_VMNAME(STRING)')" || true | ||
|
|
||
| if test -z "$vm" | ||
| then | ||
| case "$arg_user" in | ||
| DEFAULT) | ||
| exec -- "$GUIVM_TERMINAL" | ||
| ;; | ||
| *) | ||
| exec -- sudo -n -u "$arg_user" -- "$GUIVM_TERMINAL" | ||
| ;; | ||
| esac | ||
| fi | ||
|
|
||
| vm="${vm#*\"}" | ||
| vm="${vm%\"*}" | ||
| declare -r vm | ||
|
|
||
| # Launch console for VM (hvc) | ||
| if test "$arg_console" = "true" | ||
| then | ||
| exec -- "$DOMU_CONSOLE" -- "$vm" | ||
| fi | ||
|
|
||
| if command -v qrexec-client >/dev/null | ||
| then | ||
| exec -- qrexec-client -e -d "$vm" -- \ | ||
| "$arg_user:QUBESRPC qubes.StartApp+$DOMU_TERMINAL $vm" | ||
| fi | ||
|
|
||
| # Else, if qrexec-client can't be used (e.g. in a GUIVM), use qvm-run instead | ||
| case "$arg_user" in | ||
| DEFAULT) | ||
| exec qvm-run --no-gui --service -- "$vm" qubes.StartApp+"$DOMU_TERMINAL" | ||
| ;; | ||
| *) | ||
| exec qvm-run --no-gui --service -u "$arg_user" -- "$vm" qubes.StartApp+"$DOMU_TERMINAL" | ||
| ;; | ||
| esac | ||
| } | ||
|
|
||
| main "$@" | ||
|
|
||
| # Adapted from https://stackoverflow.com/a/29754866 | ||
| parse_options() | ||
| { | ||
| declare -g arg_user="DEFAULT" | ||
| declare -g arg_console="" | ||
|
|
||
| if [ $# -lt 1 ] | ||
| then | ||
| return | ||
| fi | ||
| # Check whether getopt version is "enhanced" | ||
| # shellcheck disable=SC2251 | ||
| ! getopt --test >/dev/null | ||
| if [[ ${PIPESTATUS[0]} -ne 4 ]] | ||
| then | ||
| printf '%s\n' 'This script requires getopt enhanced to work properly' >&2 | ||
| exit 2 | ||
| fi | ||
|
|
||
| # Set available options | ||
| declare -r LONGOPTS=help,console,user: | ||
| declare -r OPTIONS=hcu: | ||
|
|
||
| # Get arguments from "$@" using getopt | ||
| IFS=" " read -r -a PARSED <<< "$(getopt --options=$OPTIONS --longoptions=$LONGOPTS --name "$0" -- "$@")" | ||
| eval set -- "${PARSED[*]}" | ||
|
|
||
| # Write to argument variables | ||
| while true | ||
| do | ||
| case "$1" in | ||
| -h|--help) | ||
| print_usage | ||
| exit 0 | ||
| ;; | ||
| -u|--user) | ||
| arg_user="$2" | ||
| shift 2 | ||
| ;; | ||
| -c|--console) | ||
| arg_console="true" | ||
| shift | ||
| ;; | ||
| --) | ||
| shift | ||
| break | ||
| ;; | ||
| *) | ||
| printf '%s\n' "$(basename "$0"): Invalid argument" >&2 | ||
| print_usage | ||
| exit 2 | ||
| ;; | ||
| esac | ||
| done | ||
|
|
||
| # Handle positional arguments ($1, $2, …) | ||
| if [ $# -gt 0 ] | ||
| then | ||
| case "${1-}" in | ||
| console) | ||
| arg_console="true" | ||
| printf '%s\n' "$(basename "$0"): Positional arguments are deprecated and will be removed in the future. Use --console instead" >&2 | ||
| ;; | ||
| *) | ||
| printf '%s\n' "$(basename "$0"): Invalid argument" >&2 | ||
| print_usage | ||
| exit 2 | ||
| ;; | ||
| esac | ||
| fi | ||
|
|
||
| declare -gr arg_user | ||
| declare -gr arg_console | ||
|
|
||
| return | ||
| } | ||
|
|
||
|
|
||
| parse_options "$@" | ||
| main | ||
Empty file.
Empty file.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried this approach and ran into an issue. It looks like
xpropemits both outputs and error messages tostdout, disregardingstderr. Unless there's a way to make it work properly (or I'm mistaken), I feel like the post-processing of the output withgrepwould be the better approach, sadly.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very weird behavior. To test, make it fail by focusing a dom0 window before running the script, notice that redirecting stderr to dev null doesn't hide errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW, I also get an error here when running the script on xfce. Apparently, Xfce sets two window IDs in the
_NET_ACTIVE_WINDOWproperty, the second one being 0x0. And xprop fails on it, making the script always assume it's dom0.But it does work correctly for me on i3.