import time
from typing import Optional
from fortrace.core.qemu_monitor import QEMUMonitorSession
from fortrace.utility.applications.application import (
ApplicationType,
GenericApplication,
ParentNotifier,
)
from fortrace.utility.distribution_constants import ShellType
[docs]
class GenericLinuxTerminal(GenericApplication):
"""Representation of a generic Linux terminal window."""
def __init__(
self,
name: str,
qs: QEMUMonitorSession,
parent_notifier: ParentNotifier,
shell_type: ShellType = ShellType.BASH,
sudo_timeout: float = 300,
):
"""Creates a new Linux Terminal.
Args:
name: name of the terminal emulator (e.g. Terminal, Konsole, ...)
qs: handle to QEMUMonitorSession
parent_notifier: parent_notifier of DesktopEnvironment
shell_type: the default shell of the system
sudo_timeout: the sudo timeout value of the system (default 5 minutes)
"""
super().__init__(name, ApplicationType.TERMINAL, qs, parent_notifier)
self._history = True
self._shell = shell_type
self._sudo_timeout = sudo_timeout
self._last_sudo = 0
[docs]
def send_command(
self,
command: str,
get_output: bool = False,
elevated: bool = False,
password: str = "",
) -> Optional[str]:
"""Send a command to the active terminal emulator.
Args:
command: the command to be sent
get_output: the clipboard is shared between host and guest, so we can get the output by piping the command
to it. However, note that this will show in command history
elevated: run the command as sudo
password: if command should run as sudo, a password must be provided (even if timeout is active)
Returns:
output of entered command, if wished (currently only works with X due limitations of pyperclip
"""
if elevated:
command = "sudo " + command
if get_output:
# TODO: check which display manager is used, so correct clipboard command is appended
command = command + " | wl-copy"
self._qs.send_text(command, True)
# MAYBE password must be entered
if elevated:
if (time.time() - self._last_sudo) >= self._sudo_timeout:
self._qs.send_text(password, True)
self._last_sudo = (
time.time()
) # passwd_timeout is not refreshed by sudo commands
if get_output:
# return pyperclip.paste()
return "" # FIXME: don't rely on pyperclip, since this opens a channel to the host
[docs]
def toggle_command_history(self):
"""Toggle the generation of command history.
Note however, that the command to toggle will be in history.
"""
if self._history:
self._qs.send_text("unset HISTFILE", True)
else:
if self._shell == ShellType.BASH:
self._qs.send_text('set HISTFILE "~/.bash_history"', True)
elif self._shell == ShellType.ZSH:
self._qs.send_text('set HISTFILE "~/.zsh_history"', True)
self._history = ~self._history
[docs]
def change_shell(self, shell_type: ShellType):
if self._shell != shell_type:
self._qs.send_text(str(shell_type), True)
self._shell = shell_type