xilun / cbwin

Launch Windows programs from "Bash on Ubuntu on Windows" (WSL)
Other
327 stars 25 forks source link

Using outbash with urxvtc and Xming #11

Closed fpqc closed 8 years ago

fpqc commented 8 years ago

Hi xilun, I was wondering if there was a way to get outbash working with urxvt and Xming. I want to be able to set the clickable links feature in urxvt and have it pipe out to my Windows browser, but right now, it looks like the outbash_port gets reset on every restart. I want to run urxvtd in outbash (which would bind outbash to a port) then run urxvtc so the outbash port is automatically set to be the port bound in the console that started the daemon.

Any idea how to do this, or if you could program it in?

xilun commented 8 years ago

Hi fpqc, what do you mean by "outbash_port gets reset on every restart"?

fpqc commented 8 years ago

I dunno, maybe I'm wrong, but there is an environment variable that gets set called OUTBASH_PORT that changes for each instance of outbash.exe. I was wondering if there was a way to make it so OUTBASH_PORT stays static so I can launch things from urxvtc.

Basically, I want to leave a single cbwin instance running, then be able to do wstart from any vterm I open, or alternatively, and better, have some way that if I use outbash.exe to launch a VTerm in Xming, I can still use it. The purpose of this is so I can do

wstart browser http://google.com

from urxvtc and have it launch my browser.

The problem is that if I do outbash.exe -c "urxvtc", it doesnt work because the "outbash daemon" closes immediately.

xilun commented 8 years ago

I see. For now the only way outbash.exe works is per Windows console, and each instance sets up its own port to get this locality.

When you wcmd something without redirections, is is just launched by the corresponding outbash.exe and inherits its Win32 standard console handles, so it can detect it and use the whole Win32 console API (to the good Windows console instance) instead of being limited to printing characters in a stream. This is even more important than under a Unix TTY, because the Win32 console API is more based on specific functions, and less on control characters.

I'll try to use urxvt and Xming to see if I can come up with something practical. For commands that actually output something it will need to always redirect the stream (because urxvt can not be driven by the Win32 console API) even when the wcmd caller process detects its standard fds are a tty. I'm not really sure if I'll support this scenario in the end, but I'll take a look to see if something simple, and with somewhat acceptable results given the compromises, can be done.

xilun commented 8 years ago

@fpqc how did you get urxvt working? I only can get

$  urxvtc
urxvt: protocol error while reading pty/tty fds from helper process, aborting.

when I try to launch it.

fpqc commented 8 years ago

Open one bash terminal and run

urxvtd -q -o -f (the daemon)

Once the Daemon is running, you can run with

bash.exe -c urxvtc

xilun commented 8 years ago

Ok I understand the situation: the new terminal uses the environment variables of the urxvtc, which in the scenario you envisioned is never useful for the OUTBASH_PORT variable (either points to the Windows console from where urxvtc has been called, or just does not exist)

xilun commented 8 years ago

I think one of the outbash.exe could be used as a session outbash and export its port through a mean more wide than an environment variable, then wcmd/wrun/wstart commands would fallback to that port if OUTBASH_PORT does not exist, and would always use redirections in this case.

fpqc commented 8 years ago

Works for me to have a fallback like you have described!

In the future, once Microsoft upgrades conhost to not be total crap, this kind of hack should not be needed, since outbash will be running in a good Terminal Emulator =]!

I am only running urxvt until MS makes conhost better with 256color and mouse support, although it would be pretty cool if you could figure out a way to have outbash (not just the callers) keep running until all processes spawned by the original outbash.exe die in the nice way that you did it with the Windows console. That would probably mean rewriting outbash as a Windows service that could track instances of bash.exe by PID., which would be a lot more work than just setting up a fallback outbash port.

xilun commented 8 years ago

Yes, I don't think I'll be writing a Windows service anytime soon. Actually outbash might very well be quite short-lived if MS implement a decent way to call Win32 processes from WSL soon, as they told they eventually will.

xilun commented 8 years ago

However, I'm intrigued by your last paragraph.

Do you mean you would like outbash.exe waiting on the WSL processes? Is this because it would run as long as urxvtd does? I'm not sure this is possible reliably, even for a Windows service (at least by only using public Windows APIs). Actually, for now, urxvtd will probably be killed by WSL if you close all your Windows consoles that ran bash.exe

fpqc commented 8 years ago

It will, but if you use run.exe (on Xming website) and a special script to open urxvtd (basically, run urxvtd -q -o -f then $SHELL) (because of the problem you mentioned), you can get it to run in the background at startup, although very weirdly, running outbash instead of bash with run.exe does not properly set the env variable "OUTBASH_PORT".

xilun commented 8 years ago

Note: the explanation for the lack of OUTBASH_PORT environment variable is probably that bash was not launched in interactive mode, because the way that environment variable is set is by using a custom --rcfile, which bash interprets only in interactive mode.

xilun commented 8 years ago

For info: commit fb6f0b1 changes the way the OUTBASH_PORT is set. OUTBASH_PORT should now be set regardless of the command line parameters, and not only when bash is launched in interactive mode. This, in itself, does not solve this issue, though.

fpqc commented 8 years ago

I can just hack it anyway by adding a line to my urxvtd startup script

echo export OUTBASH_PORT=$OUTBASH_PORT > ~/.cbwin chmod +x ~/.cbwin

and then add a line to my .bashrc source ~/.cbwin

I think this will work.

Edit: It still didn't work when using run.exe.

Edit2: Working now! I had to make a script to start wstart inside of VolFS.

Now there's another problem with urxvt crashing when clicking links (not related to cbwin, since it happens with WSL firefox too), but at least if I run my script

winbrowser url

it opens up the url in my Windows browser.

Thanks for all of your help, xilun!

xilun commented 8 years ago

You're welcome! I think I'll add a session mode anyway, so that the caller forces redirections when running under non-windows console. That way text win32 programs will display their output (the best they can) and accept (simple) input in such context.

fpqc commented 8 years ago

For what it's worth, xilun, I don't think Microsoft is going to actually do a built-in version of what cbwin does, since it will require them to actually write the linux-side callers/listeners. The best we can hope for is some kind of IPC directly from the Linux side to the Windows side and vice-versa (since right now, cbwin is forced to make use of IP ports in a way that is insecure as you noted.

I guess one way you could make it secure is by also adding a keycheck so that when you launch outbash, it starts the listener however you do that, but also requires the caller to meet a password check on each call, which could be set for when outbash launches bash so it does bash.exe -c "(OUTBASH_PORT=generated_port OUTBASH_PASS=generated_uuid /bin/bash)" and make it so the callers wcmd, wstart, etc pass the password whenever they are invoked (I am guessing this is also how you might be doing sessions?)

xilun commented 8 years ago

I'm not so sure about MS not eventually providing builtin functions equivalent or better than cbwin. They are less constrained because they can tune what they want on the Win32, console, WSL, and NT kernel sides. They might find a way to get Win32 and Posix pipes compatible enough to be connected directly. The equivalent of the caller could be implemented using an equivament of binfmt_misc and some kinds of parasyscalls. There are a lot of questions to solve though: which win32 processes should be visible with WSL pids, how should they react to signals, ... I've not thought much about all that, but there are prior and existing examples (sfu&co, cygwin) they can consider and see if doing similar things would be possible and a good idea with wsl.

xilun commented 8 years ago

About the pwd idea, I actually would prefer to filter using Windows firewall if this is possible, but it might be unavailable so this kind of pwd technique is also to consider.

xilun commented 8 years ago

Commit 260cd55 let you do the following:

Usage example:

@fpqc can you tell me if this is useful, if you think of small adjustments, or any other ideas? I can do a binary release if you need.

fpqc commented 8 years ago

Haha, that sounds amazing!

I guess the only improvement I would suggest is seeing if you could add a tray icon for when it is in session mode (and/or ask the Xming guy Colin if you can redistribute with run.exe)?

But yeah, totally do a binary release, that's amazing! Also yeah I would totally use

xilun commented 8 years ago

Actually I guess it would be better to have a session process separated from the console ones, to also cover the cases where the Console you launched from disappear. But that's more work, I'll think about it later :) In this case maybe it would get a tray icon, but that's not my priority (especially since I don't know about graphical Win32)

On the caller side it would then be nice to have a more reliable way to detect if we are not in a Windows Console even if OUTBASH_PORT is set, for example outbash.exe -> do some work in the console, start an xterm without unsetting OUTBASH_PORT -> wcmd in the xterm won't force redirections, while ideally it should.

But well, for now the scenario with Xming/urxvtd/urxvtc is good enough, given it's already necessarily hacky to get urxvtd running in the background.

I'll make a binary release of the current version very soon.

fpqc commented 8 years ago

Dled new binary release. Works great! I was able to delete all of my custom scripts!