#!/usr/bin/python -u import argparse import os import subprocess import tempfile import time import signal import sys from gi.repository import SugarRunner helpers_dir = "@helpersdir@" window_process = None result = 0 def _usr1_signal_handler(number, frame): global result result = 1 def _setpgrp_preexec(): os.setpgrp() def _get_screen_dpi(): from gi.repository import Gtk settings = Gtk.Settings.get_default() return settings.get_property('gtk-xft-dpi') / 1024 def _write_xkb_config(): f, name = tempfile.mkstemp(prefix="sugar-xkbconfig-") subprocess.check_call(["setxkbmap", "-print"], stdout=f) os.environ["SUGAR_RUNNER_XKBCONFIG"] = name def _allow_to_run_x(): try: with open("/etc/X11/Xwrapper.config") as f: if "allowed_users=anybody" in f.read(): return except IOError: return print "We need to allow everybody to run the X server" tweak_wrapper = os.path.join(helpers_dir, "tweak-xwrapper") subprocess.check_call(["sudo", "-k", tweak_wrapper]) def _run_xephyr_window(resolution): args = [os.path.join(helpers_dir, "xephyr-window")] if resolution is not None: args.extend(["--resolution", resolution]) process = subprocess.Popen(args, stdout=subprocess.PIPE) return process, process.stdout.readline().strip() def _get_tty_number(): tty = subprocess.check_output(["tty"]) head, tail = os.path.split(tty) return tail.strip().replace("tty", "") # Setup an unencrypted keyring so that it # doesn't bother us with password dialogs def _setup_keyring(data_home_dir): keyrings_dir = os.path.join(data_home_dir, "keyrings") if not os.path.exists(keyrings_dir): try: os.makedirs(keyrings_dir) except OSError: pass with open(os.path.join(keyrings_dir, "default"), "w") as f: f.write("default") with open(os.path.join(keyrings_dir, "default.keyring"), "w") as f: f.write("[keyring]\n" "display-name=default\n" "lock-on-idle=false\n" "lock-timeout=0") def _ensure_dir(path): try: os.mkdir(path) except: pass def _get_home_dirs(args): base_home_dir = args.home_dir if base_home_dir is None: base_home_dir = os.path.expanduser("~/.sugar-runner") _ensure_dir(base_home_dir) home_dirs = {} for home_name in ["cache", "config", "data"]: home_dirs[home_name] = os.path.join(base_home_dir, home_name) for path in home_dirs.values(): _ensure_dir(path) return home_dirs def _setup_variables(args, home_dirs): to_unset = ["GPG_AGENT_INFO", "SSH_AUTH_SOCK", "GNOME_KEYRING_CONTROL", "GNOME_KEYRING_PID", "SESSION_MANAGER"] for name in to_unset: if name in os.environ: del os.environ[name] if args.output is not None: os.environ["SUGAR_RUNNER_OUTPUT"] = args.output if args.test_command is not None: os.environ["SUGAR_RUNNER_TEST_COMMAND"] = args.test_command if args.test_log is not None: os.environ["SUGAR_RUNNER_TEST_LOG"] = args.test_log os.environ["XDG_CACHE_HOME"] = home_dirs["cache"] os.environ["XDG_DATA_HOME"] = home_dirs["data"] os.environ["XDG_CONFIG_HOME"] = home_dirs["config"] # Disable Unity custom gtk scrollbars os.environ["LIBOVERLAY_SCROLLBAR"] = "0" # Allow to close with Shift+Alt+Q os.environ["SUGAR_EMULATOR"] = "yes" parser = argparse.ArgumentParser(description="Run sugar") parser.add_argument("--resolution", help="screen resolution") parser.add_argument("--output", help="name of the output") parser.add_argument("--home-dir", help="path to the home directory") parser.add_argument("--test-log", help="path where to log the test output") parser.add_argument("--test-command", help="command line of the test to run") parser.add_argument("--virtual", action="store_true", help="use an a virtual server") args = parser.parse_args() home_dirs = _get_home_dirs(args) _setup_variables(args, home_dirs) _setup_keyring(home_dirs["data"]) xinit_args = ["xinit", os.path.join(helpers_dir, "xinitrc"), "--"] display = SugarRunner.find_free_display() if args.virtual: xinit_args.append("/usr/bin/Xvfb") xinit_args.append(display) xinit_args.extend(["-ac", "-noreset", "-shmem", "-screen", "0", "1024x768x16"]) elif "DISPLAY" in os.environ: _write_xkb_config() window_process, xid = _run_xephyr_window(args.resolution) xinit_args.append("/usr/bin/Xephyr") xinit_args.append(display) xinit_args.extend(["-dpi", str(_get_screen_dpi())]) xinit_args.extend(["-parent", xid]) else: _allow_to_run_x() xinit_args.append(display) xinit_args.append("vt%s" % _get_tty_number()) os.environ["SUGAR_RUNNER_PID"] = str(os.getpid()) signal.signal(signal.SIGUSR1, _usr1_signal_handler) try: xinit_process = subprocess.Popen(xinit_args, preexec_fn=_setpgrp_preexec) result = None while result is None: result = xinit_process.poll() time.sleep(0.1) except KeyboardInterrupt: pass if window_process: window_process.terminate() sys.exit(result)