How to run a command in a new terminal window in the same process as the original

terminal

What is the equivalent of xfce4-terminal -e bash -c 'myCommand' that doesn't start a new process with the terminal, but that still opens a new terminal window for the output (which will also need to take input)? I want the original terminal (which isn't visible, anyway) to halt until the new visible one is done.

Let's say I have a Python GUI that calls the aforementioned command. I want the Python script to halt while the newly opened terminal window runs its command, and to continue after it stops.

EDIT: In response to requests for more information about my situation, here it is, more specifically:

I've made an IDE, using Python 3.x, with Tkinter as the GUI. There is no terminal window open simply because it's a GUI-based program (and if there were, it would be in the background, anyway, and no one would have a particular reason to know to look and see whether it was saying anything, since the whole IDE is in a GUI).

I'm making an option to asymmetrically encrypt selected text using the gpg command-line tool (which is more convenient and documented than the Python modules for my other more prominent uses of it, which are beyond the scope of this question; plus there aren't as many licensing issues with using compiled binaries). For symmetric encryption, I don't have a problem because I don't need an open terminal window, but asymmetric encryption tends to prompt for more stuff that may or may not be important, and the user needs to respond to those prompts.

The text to be encrypted is saved to a temporary file, and gpg is to encrypt the whole file (since the text may be arbitrarily long and that might cause problems if it were outputted to a terminal instead of saved to a file).

So, when the user selects text and executes the method, I want a terminal window to pop up with the prompt from gpg. Ideally, the user would say yes or no, and press enter, and the terminal window would disappear; then the selected text would be replaced with asymmetrically encrypted text. However, what actually happens is the terminal window pops up and the program attempts to get the encrypted text before it's actually encrypted (because it doesn't wait for the user to input anything). I do not want the user to have to manually tell the IDE that it's time to encrypt it after saying yes or no.

You might think you could use pipes to route GUI-based user input to the hidden terminal. However, such as y | gpg -a --encrypt --recipient test@user.com tempFile.txt does not work for some odd reason.

Best Answer

When you run a new terminal emulator, that creates a new terminal (/dev/pts/NUMBER on Linux). A program doesn't have to be started by that terminal to output there (try running tty in a terminal, then in another terminal run echo hello >/dev/pts/NUMBER). So you can tell your Python script to read and write from the terminal; all you need is to find out the path to the device file.

With xterm, it's pretty easy: run xterm -e 'tty >&3; myCommand' with file descriptor 3 connected to a pipe from which your program reads the path to the terminal device.

p = subprocess.Popen("xterm -e 'tty >&3; exec sleep 99999999' 3>&1",
                     shell=True, stdout=subprocess.PIPE)
tty_path = readline(p.stdout)
tty = open(tty_path, 'r+')

Your Python program can now read and write to tty. When you've finished, kill the terminal emulator (os.kill(p.pid, signal.SIGTERM)).

With a terminal emulator that's based on a single process for multiple windows such as xfce4-terminal, what you want to do is considerably harder. Running xfce4-terminal breaks links between the parent process and the child of the terminal emulator, and doesn't give you a nice PID that you can kill. You could use a named pipe to communicate but it's a bot harder to set up.

Related Question