diff --git a/src/man/xpra.1 b/src/man/xpra.1 index 834bb810e0..1740878223 100644 --- a/src/man/xpra.1 +++ b/src/man/xpra.1 @@ -359,7 +359,7 @@ Modify the server at runtime by issuing commands. The list of commands can be obtained by specifying "help" as command. Some of those commands may support a "help" mode themselves. .SS xpra initenv -This internal command creates the run-xpra script used with ssh +This internal command creates the \fBrun-xpra\fP script used with ssh connections. .SS xpra stop This command attaches to a running xpra server, and requests that it @@ -1215,8 +1215,9 @@ is enabled. \fI~/.xpra/run-xpra\fP A shell script that, when run, starts up xpra with the correct python interpreter, PYTHONPATH, PATH, location of the main xpra script, etc. -Automatically generated by \fBxpra start\fP and used by \fBxpra -attach\fP (see also the discussion of \fB\-\-remote\-xpra\fP). +Automatically generated by \fBxpra initenv\fP, \fBxpra start\fP +and used by \fBxpra attach\fP (see also the discussion of +\fB\-\-remote\-xpra\fP). .\" -------------------------------------------------------------------- .SH BUGS Xpra has no test suite. diff --git a/src/xpra/platform/paths.py b/src/xpra/platform/paths.py index 1938e0fbb9..1dab8a3008 100755 --- a/src/xpra/platform/paths.py +++ b/src/xpra/platform/paths.py @@ -78,10 +78,15 @@ def do_get_download_dir(): return "~" return d -def get_script_bin_dir(): - return env_or_delegate("XPRA_SCRIPT_BIN_DIR", do_get_script_bin_dir) -def do_get_script_bin_dir(): - return "~/.xpra" +def get_script_bin_dirs(): + return envaslist_or_delegate("XPRA_SCRIPT_BIN_DIRS", do_get_script_bin_dirs) +def do_get_script_bin_dirs(): + return ["~/.xpra"] + +def get_remote_run_xpra_scripts(): + return envaslist_or_delegate("XPRA_REMOTE_RUN_XPRA_SCRIPTS", do_get_remote_run_xpra_scripts) +def do_get_remote_run_xpra_scripts(): + return ["$XDG_RUNTIME_DIR/xpra/run-xpra", "~/.xpra/run-xpra", "xpra"] #overriden in platform code: @@ -197,7 +202,7 @@ def do_get_sound_command(): "do_get_socket_dirs", "do_get_default_log_dir", "do_get_download_dir", - "do_get_script_bin_dir") + "do_get_script_bin_dirs") def get_info(): return { diff --git a/src/xpra/platform/win32/paths.py b/src/xpra/platform/win32/paths.py index a76cd26bb4..45f338d9d9 100644 --- a/src/xpra/platform/win32/paths.py +++ b/src/xpra/platform/win32/paths.py @@ -80,6 +80,9 @@ def do_get_download_dir(): DOWNLOAD_PATH = os.path.join(os.environ.get("USERPROFILE", "~"), "Downloads") return DOWNLOAD_PATH +def do_get_script_bin_dirs(): + #we don't save the "run-xpra" script anywhere on win32 + return [] def do_get_socket_dirs(): #ie: C:\Documents and Settings\Username\Application Data\Xpra diff --git a/src/xpra/platform/xposix/paths.py b/src/xpra/platform/xposix/paths.py index 8d46f9bd73..d57bfe6b1d 100644 --- a/src/xpra/platform/xposix/paths.py +++ b/src/xpra/platform/xposix/paths.py @@ -47,6 +47,15 @@ def do_get_icon_dir(): from xpra.platform.paths import get_app_dir return os.path.join(get_app_dir(), "icons") +def do_get_script_bin_dirs(): + #versions before 0.17 only had "~/.xpra/run-xpra" + script_bin_dirs = [] + runtime_dir = _get_xpra_runtime_dir() + if runtime_dir: + script_bin_dirs.append(runtime_dir) + return script_bin_dirs.append("~/.xpra") + + def _get_xpra_runtime_dir(): runtime_dir = os.environ.get("XDG_RUNTIME_DIR") if runtime_dir: diff --git a/src/xpra/scripts/config.py b/src/xpra/scripts/config.py index a131eb852c..2b27b260e4 100755 --- a/src/xpra/scripts/config.py +++ b/src/xpra/scripts/config.py @@ -275,7 +275,6 @@ def read_xpra_defaults(): "auth" : str, "tcp-auth" : str, "wm-name" : str, - "remote-xpra" : str, "session-name" : str, "dock-icon" : str, "tray-icon" : str, @@ -371,6 +370,7 @@ def read_xpra_defaults(): "global-menus" : bool, #arrays of strings: "socket-dirs" : list, + "remote-xpra" : list, "encodings" : list, "video-encoders" : list, "csc-modules" : list, @@ -395,7 +395,7 @@ def get_defaults(): if GLOBAL_DEFAULTS is not None: return GLOBAL_DEFAULTS from xpra.platform.features import DEFAULT_SSH_COMMAND, OPEN_COMMAND, DEFAULT_PULSEAUDIO_COMMAND, XDUMMY, XDUMMY_WRAPPER, DISPLAYFD, DEFAULT_ENV, CAN_DAEMONIZE - from xpra.platform.paths import get_download_dir, get_default_log_dir, get_socket_dirs + from xpra.platform.paths import get_download_dir, get_default_log_dir, get_socket_dirs, get_remote_run_xpra_scripts try: from xpra.platform.info import get_username username = get_username() @@ -423,7 +423,6 @@ def addtrailingslash(v): "auth" : "", "tcp-auth" : "", "wm-name" : DEFAULT_NET_WM_NAME, - "remote-xpra" : "~/.xpra/run-xpra", "session-name" : "", "dock-icon" : "", "tray-icon" : "", @@ -515,6 +514,7 @@ def addtrailingslash(v): "shadow-fullscreen" : False, "global-menus" : True, "socket-dirs" : [], + "remote-xpra" : get_remote_run_xpra_scripts(), "encodings" : ["all"], "video-encoders" : ["all"], "csc-modules" : ["all"], diff --git a/src/xpra/scripts/main.py b/src/xpra/scripts/main.py index fc4cdc0ecc..5437a96577 100755 --- a/src/xpra/scripts/main.py +++ b/src/xpra/scripts/main.py @@ -691,7 +691,7 @@ def ignore(defaults): group.add_option("--remote-xpra", action="store", dest="remote_xpra", default=defaults.remote_xpra, metavar="CMD", - help="How to run xpra on the remote host (default: '%default')") + help="How to run xpra on the remote host (default: %s)" % (" or ".join(defaults.remote_xpra))) group.add_option("--encryption", action="store", dest="encryption", default=defaults.encryption, metavar="ALGO", @@ -983,9 +983,9 @@ def run_mode(script_file, error_cb, options, args, mode, defaults): elif mode=="opengl": return run_glcheck(options) elif mode == "initenv": - from xpra.scripts.server import xpra_runner_shell_script, write_runner_shell_script + from xpra.scripts.server import xpra_runner_shell_script, write_runner_shell_scripts script = xpra_runner_shell_script(script_file, os.getcwd(), options.socket_dir) - write_runner_shell_script(script, False) + write_runner_shell_scripts(script, False) return 0 elif mode == "showconfig": return run_showconfig(options, args) @@ -1088,11 +1088,9 @@ def parse_display_name(error_cb, opts, display_name): "host" : host, "full_ssh" : full_ssh }) - remote_xpra = opts.remote_xpra.split() + desc["remote_xpra"] = opts.remote_xpra if opts.socket_dir: - #ie: XPRA_SOCKET_DIR=/tmp .xpra/run-xpra _proxy :10 - remote_xpra.append("--socket-dir=%s" % opts.socket_dir) - desc["remote_xpra"] = remote_xpra + desc["socket_dir"] = opts.socket_dir if desc.get("password") is None and opts.password_file and os.path.exists(opts.password_file): try: with open(opts.password_file, "rb") as f: @@ -1248,11 +1246,22 @@ def setsid(): flags = CREATE_NEW_PROCESS_GROUP | CREATE_NEW_CONSOLE kwargs["creationflags"] = flags kwargs["stderr"] = PIPE - proxy_cmd = display_desc["remote_xpra"] + display_desc["proxy_command"] + display_desc["display_as_args"] + remote_xpra = display_desc["remote_xpra"] + assert len(remote_xpra)>0 + remote_commands = [] + socket_dir = display_desc.get("socket_dir") + for x in remote_xpra: + #ie: ["~/.xpra/run-xpra"] + ["_proxy"] + [":10"] + pc = [x] + display_desc["proxy_command"] + display_desc["display_as_args"] + if socket_dir: + pc.append("--socket-dir=%s" % socket_dir) + remote_commands.append((" ".join(pc))) + #ie: ~/.xpra/run-xpra _proxy || $XDG_RUNTIME_DIR/run-xpra _proxy + remote_cmd = " || ".join(remote_commands) if INITENV_COMMAND: - cmd += [INITENV_COMMAND+";"+(" ".join(proxy_cmd))] + cmd += [INITENV_COMMAND+";"+remote_cmd] else: - cmd += proxy_cmd + cmd += [remote_cmd] if env: kwargs["env"] = env if debug_cb: diff --git a/src/xpra/scripts/server.py b/src/xpra/scripts/server.py index ca238c4ef0..7bcb9aeec1 100644 --- a/src/xpra/scripts/server.py +++ b/src/xpra/scripts/server.py @@ -150,7 +150,7 @@ def xpra_runner_shell_script(xpra_file, starting_dir, socket_dir): """) return "".join(script) -def write_runner_shell_script(contents, overwrite=True): +def write_runner_shell_scripts(contents, overwrite=True): # This used to be given a display-specific name, but now we give it a # single fixed name and if multiple servers are started then the last one # will clobber the rest. This isn't great, but the tradeoff is that it @@ -159,21 +159,25 @@ def write_runner_shell_script(contents, overwrite=True): # is running on the remote host. Might need to revisit this later if # people run into problems or autodiscovery turns out to be less useful # than expected. - from xpra.platform.paths import get_script_bin_dir - scriptdir = os.path.expanduser(get_script_bin_dir()) - if not os.path.exists(scriptdir): - os.mkdir(scriptdir, 0o700) - scriptpath = os.path.join(scriptdir, "run-xpra") - if os.path.exists(scriptpath) and not overwrite: - return - # Write out a shell-script so that we can start our proxy in a clean - # environment: - with open(scriptpath, "w") as scriptfile: - # Unix is a little silly sometimes: - umask = os.umask(0) - os.umask(umask) - os.fchmod(scriptfile.fileno(), 0o700 & ~umask) - scriptfile.write(contents) + from xpra.platform.paths import get_script_bin_dirs + for d in get_script_bin_dirs(): + scriptdir = osexpand(d) + if not os.path.exists(scriptdir): + os.mkdir(scriptdir, 0o700) + scriptpath = os.path.join(scriptdir, "run-xpra") + if os.path.exists(scriptpath) and not overwrite: + continue + # Write out a shell-script so that we can start our proxy in a clean + # environment: + try: + with open(scriptpath, "w") as scriptfile: + # Unix is a little silly sometimes: + umask = os.umask(0) + os.umask(umask) + os.fchmod(scriptfile.fileno(), 0o700 & ~umask) + scriptfile.write(contents) + except Exception as e: + sys.stderr.write("Error: failed to write script file '%s': %s\n" % (scriptfile, e)) def display_name_check(display_name): @@ -903,7 +907,7 @@ def run_server(error_cb, opts, mode, xpra_file, extra_args, desktop_display=None if os.name=="posix": # Write out a shell-script so that we can start our proxy in a clean # environment: - write_runner_shell_script(script) + write_runner_shell_scripts(script) from xpra.log import Logger log = Logger("server")