Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/python
- import os
- import sys
- import subprocess
- import time
- import signal
- import errno
- import imp
- import grp
- import pwd
- import debconf
- sys.path.insert(0, '/usr/lib/ubiquity')
- import ubiquity.frontend
- from ubiquity import osextras
- from ubiquity import gsettings
- from ubiquity.misc import create_bool
- from ubiquity.casper import get_casper
- from ubiquity.debconfcommunicator import DebconfCommunicator
- def ck_open_session(uid):
- import dbus
- bus = dbus.SystemBus ()
- manager_obj = bus.get_object ('org.freedesktop.ConsoleKit',
- '/org/freedesktop/ConsoleKit/Manager')
- manager = dbus.Interface (manager_obj, 'org.freedesktop.ConsoleKit.Manager')
- params = dbus.Array ([], signature = "(sv)")
- params.append(("unix-user", dbus.Int32(uid)))
- params.append(("session-type", dbus.String("")))
- params.append(("x11-display", dbus.String(os.environ['DISPLAY'])))
- params.append(("x11-display-device", dbus.String('/dev/tty7')))
- params.append(("is-local", dbus.Boolean(True)))
- cookie = manager.OpenSessionWithParameters(params)
- os.environ['XDG_SESSION_COOKIE'] = cookie
- def set_locale():
- db = DebconfCommunicator('ubiquity', cloexec=True)
- locale = ''
- try:
- locale = db.get('debian-installer/locale')
- except debconf.DebconfError:
- pass
- db.shutdown()
- if not locale:
- return
- default_locale = open('/etc/default/locale', 'w')
- print >>default_locale, 'LANG="%s"' % locale
- default_locale.close()
- environment = open('/etc/environment')
- environment_lines = environment.readlines()
- environment.close()
- environment = open('/etc/environment', 'w')
- seen_lang = False
- for line in environment_lines:
- if line.startswith('LANG='):
- print >>environment, 'LANG="%s"' % locale
- seen_lang = True
- else:
- print >>environment, line.rstrip('\n')
- if not seen_lang:
- print >>environment, 'LANG="%s"' % locale
- environment.close()
- locale_gen = open('/etc/locale.gen', 'w')
- print >>locale_gen, '%s UTF-8' % locale
- locale_gen.close()
- logfile = open('/var/log/installer/dm', 'a')
- subprocess.call(['/usr/sbin/locale-gen', locale],
- stdout=logfile, stderr=logfile)
- logfile.close()
- class XStartupError(EnvironmentError):
- pass
- class MissingProgramError(EnvironmentError):
- pass
- class DM:
- def __init__(self, vt, display, default_username):
- self.vt = vt
- self.display = display
- self.server_started = False
- self.username = get_casper('USERNAME', default_username)
- try:
- self.uid, self.gid = pwd.getpwnam(self.username)[2:4]
- except KeyError:
- import syslog
- syslog.syslog('Could not find %s, falling back to root.' %
- self.username)
- self.username = 'root'
- self.uid, self.gid = 0, 0
- os.environ['SUDO_USER'] = self.username
- self.homedir = pwd.getpwnam(self.username)[5]
- self.uid = int(self.uid)
- self.gid = int(self.gid)
- self.groups = []
- for g in grp.getgrall():
- if self.username in g[3] or g[0] == self.username:
- self.groups.append(g[2])
- # Look for a frontend module; we won't actually use it (yet), but
- # this lets us find out which window manager etc. to launch. Be
- # careful that importing this here will cause the underlying library
- # to try to talk to the X server, which won't go well.
- frontend_names = ['gtk_ui', 'kde_ui']
- self.frontend = None
- for f in frontend_names:
- try:
- imp.find_module(f, ubiquity.frontend.__path__)
- self.frontend = f
- break
- except ImportError:
- pass
- else:
- raise AttributeError('No frontend available; tried %s' %
- ', '.join(frontend_names))
- db = DebconfCommunicator('ubiquity', cloexec=True)
- try:
- self.force_failsafe = create_bool(db.get('ubiquity/force_failsafe_graphics'))
- except debconf.DebconfError:
- self.force_failsafe = False
- db.shutdown()
- def sigusr1_handler(self, signum, frame):
- self.server_started = True
- def active_vt(self):
- import fcntl
- import array
- console = os.open('/dev/tty0', os.O_RDONLY | os.O_NOCTTY)
- try:
- VT_GETSTATE = 0x5603
- vt_stat = array.array('H', [0, 0, 0])
- fcntl.ioctl(console, VT_GETSTATE, vt_stat)
- return vt_stat[0]
- finally:
- os.close(console)
- def drop_privileges(self):
- os.setgroups(self.groups)
- os.setgid(self.gid)
- os.setuid(self.uid)
- def server_preexec(self):
- signal.signal(signal.SIGUSR1, signal.SIG_IGN)
- def run_hooks(self, hookdir):
- if os.path.isdir(hookdir):
- # Exclude hooks containing '.', so that *.dpkg-* et al are avoided.
- hooks = [entry for entry in os.listdir(hookdir)
- if '.' not in entry]
- for hookentry in hooks:
- hook = os.path.join(hookdir, hookentry)
- with open('/var/log/installer/dm', 'a') as logfile:
- subprocess.call(
- hook, stdout=logfile, stderr=logfile,
- preexec_fn=self.drop_privileges)
- def run(self, *program):
- # extract the program basename to see if we are in oem-config or ubiquity
- program_basename = os.path.basename(program[0])
- null = open('/dev/null', 'w')
- try:
- os.makedirs('/var/log/installer')
- except OSError, e:
- # be happy if someone already created the path
- if e.errno != errno.EEXIST:
- raise
- logfile = open('/var/log/installer/dm', 'w')
- signal.signal(signal.SIGUSR1, self.sigusr1_handler)
- signal.signal(signal.SIGTTIN, signal.SIG_IGN)
- signal.signal(signal.SIGTTOU, signal.SIG_IGN)
- servercommand = ['X', '-br', '-ac', '-noreset', '-nolisten', 'tcp']
- try:
- plymouth_running = subprocess.call(['plymouth', '--ping']) == 0
- except OSError:
- plymouth_running = False
- if plymouth_running:
- subprocess.call(['plymouth', 'deactivate'])
- if subprocess.call(['plymouth', '--has-active-vt']) == 0:
- self.vt = 'vt%d' % self.active_vt()
- servercommand.append('-nr')
- else:
- subprocess.call(['plymouth', 'quit'])
- plymouth_running = False
- servercommand.extend([self.vt, self.display])
- for attempt in ('main', 'fbdev', 'vesa'):
- command = list(servercommand)
- if attempt == 'main' and self.force_failsafe:
- continue
- elif attempt != 'main':
- # TODO cjwatson 2010-02-11: This is a bodge. The
- # duplication is nasty, but fortunately bullet-proof X
- # actually turns out not to be very complicated nowadays.
- # Most of the complexity is in the fallback session, which I
- # haven't attempted to integrate here, so you won't get
- # things like interactive reconfiguration. I believe Evan
- # is working on doing that, but is blocked on a couple of
- # Upstart bugs; once all that's resolved, we should back
- # this out.
- if attempt == 'fbdev' and not os.path.exists('/dev/fb0'):
- continue
- xorg_conf_failsafe = '/etc/X11/xorg.conf.failsafe'
- command.extend(['-config', xorg_conf_failsafe])
- command.extend(['-logfile', '/var/log/Xorg.%s.log' % attempt])
- xorg_conf_failsafe_file = open(xorg_conf_failsafe, 'w')
- print >>xorg_conf_failsafe_file, '''\
- Section "Device"
- Identifier "Configured Video Device"
- Driver "%s"
- EndSection
- Section "Monitor"
- Identifier "Configured Monitor"
- EndSection
- Section "Screen"
- Identifier "Default Screen"
- Monitor "Configured Monitor"
- Device "Configured Video Device"
- EndSection
- ''' % attempt
- xorg_conf_failsafe_file.close()
- server = subprocess.Popen(
- command, stdin=null, stdout=logfile, stderr=logfile,
- preexec_fn=self.server_preexec)
- # Really we should select on a pipe or something, but it's not
- # worth the effort for now.
- try:
- timeout = 60
- while not self.server_started:
- status = server.poll()
- if type(status) is int and status != 0:
- if plymouth_running:
- subprocess.call(['plymouth', 'quit'])
- raise XStartupError('X server exited with return code '
- + str(status))
- if timeout == 0:
- if plymouth_running:
- subprocess.call(['plymouth', 'quit'])
- raise XStartupError('X server failed to start after 60'
- ' seconds')
- time.sleep(1)
- timeout -= 1
- if plymouth_running:
- subprocess.call(['plymouth', 'quit', '--retain-splash'])
- except XStartupError:
- if attempt == 'vesa':
- raise
- if self.server_started:
- break
- os.environ['DISPLAY'] = self.display
- os.environ['HOME'] = self.homedir
- # Give ubiquity a UID and GID that it can drop privileges to.
- os.environ['SUDO_UID'] = str(self.uid)
- os.environ['SUDO_GID'] = str(self.gid)
- os.environ['GVFS_DISABLE_FUSE' ] = '1'
- ck_open_session(self.uid)
- # run simple, custom scripts during install time
- if program_basename == 'ubiquity':
- self.run_hooks('/usr/lib/ubiquity/dm-scripts/install')
- # run simple, custom scripts during oem-config
- if program_basename == 'oem-config-wrapper':
- self.run_hooks('/usr/lib/ubiquity/dm-scripts/oem')
- # Session bus, apparently needed by most interfaces now
- if ('DBUS_SESSION_BUS_ADDRESS' not in os.environ and
- osextras.find_on_path('dbus-launch')):
- dbus_subp = subprocess.Popen(
- ['dbus-launch', '--exit-with-session'],
- stdin=null, stdout=subprocess.PIPE, stderr=logfile,
- preexec_fn=self.drop_privileges)
- for line in dbus_subp.stdout:
- try:
- name, value = line.rstrip('\n').split('=', 1)
- os.environ[name] = value
- except ValueError:
- pass
- dbus_subp.stdout.close()
- dbus_subp.wait()
- gconfd_running = False
- if (self.frontend == 'gtk_ui' and
- osextras.find_on_path('gconftool-2')):
- subprocess.call(['gconftool-2', '--spawn'],
- stdin=null, stdout=logfile, stderr=logfile,
- preexec_fn=self.drop_privileges)
- gconfd_running = True
- extras = []
- if self.frontend == 'gtk_ui':
- gconf_dir = ('xml:readwrite:%s' %
- os.path.expanduser('~%s/.gconf' %
- self.username))
- accessibility = False
- if (osextras.find_on_path('gconftool-2') and
- gsettings._gsettings_exists()):
- # Set number of workspaces to 1 in metacity
- # (still using gconf, GNOME: #621204)
- subprocess.call(
- ['gconftool-2', '--config-source', gconf_dir,
- '--type', 'int', '--set',
- '/apps/metacity/general/num_workspaces', '1',],
- stdin=null, stdout=logfile, stderr=logfile,
- preexec_fn=self.drop_privileges)
- # Set gsettings keys
- gsettings_keys = [
- ('org.gnome.desktop.lockdown', 'disable-lock-screen', 'true'),
- ('org.gnome.desktop.lockdown', 'disable-user-switching', 'true'),
- ]
- for gs_schema, gs_key, gs_value in gsettings_keys:
- gsettings.set(gs_schema, gs_key, gs_value, self.username)
- accessibility = gsettings.get('org.gnome.desktop.interface',
- 'toolkit-accessibility', self.username)
- # Accessibility infrastructure
- with open('/proc/cmdline', 'r') as fp:
- if (accessibility == True or 'maybe-ubiquity' in fp.readline()):
- if os.path.exists('/usr/lib/at-spi2-core/at-spi-bus-launcher'):
- extras.append(subprocess.Popen(
- ['/usr/lib/at-spi2-core/at-spi-bus-launcher',
- '--launch-immediately'],
- stdin=null, stdout=logfile, stderr=logfile,
- preexec_fn=self.drop_privileges))
- os.environ['GTK_MODULES'] = 'gail:atk-bridge'
- # Set a desktop wallpaper.
- with open('/proc/cmdline', 'r') as fp:
- for background in ('/usr/share/backgrounds/edubuntu_default.png',
- '/usr/share/xfce4/backdrops/macinnis_wallpaper.png',
- '/usr/share/xfce4/backdrops/xubuntu-precise-right.png',
- '/usr/share/backgrounds/warty-final-ubuntu.png'):
- exists = os.access(background, os.R_OK)
- if (exists and not 'access=v1' in fp.readline()):
- extras.append(subprocess.Popen(['/usr/lib/ubiquity/wallpaper', background],
- stdin=null, stdout=logfile, stderr=logfile,
- preexec_fn=self.drop_privileges))
- break
- if self.frontend == 'gtk_ui':
- if gconfd_running and osextras.find_on_path('metacity'):
- wm_cmd = ['metacity', '--sm-disable']
- elif osextras.find_on_path('xfwm4'):
- wm_cmd = ['xfwm4']
- elif osextras.find_on_path('matchbox-window-manager'):
- wm_cmd = ['matchbox-window-manager']
- elif osextras.find_on_path('openbox-lubuntu'):
- wm_cmd = ['openbox-lubuntu']
- elif osextras.find_on_path('openbox'):
- wm_cmd = ['openbox']
- else:
- raise MissingProgramError('No window manager found (tried '
- 'metacity, xfwm4, matchbox-window-manager, '
- 'openbox-lubuntu, openbox)')
- wm = subprocess.Popen(wm_cmd,
- stdin=null, stdout=logfile, stderr=logfile,
- preexec_fn=self.drop_privileges)
- if os.path.exists('/usr/lib/gnome-settings-daemon/gnome-settings-daemon'):
- proc = subprocess.Popen(
- ['/usr/lib/gnome-settings-daemon/gnome-settings-daemon'],
- stdin=null, stdout=logfile, stderr=logfile,
- preexec_fn=self.drop_privileges)
- extras.append(proc)
- if os.path.exists('/usr/bin/xfsettingsd'):
- extras.append(subprocess.Popen(
- ['xsetroot', '-solid', 'black'],
- stdin=null, stdout=logfile, stderr=logfile,
- preexec_fn=self.drop_privileges))
- extras.append(subprocess.Popen(
- ['/usr/bin/xfsettingsd'],
- stdin=null, stdout=logfile, stderr=logfile,
- preexec_fn=self.drop_privileges))
- if osextras.find_on_path('lxsession'):
- proc = subprocess.Popen(
- ['lxsession','-s','Lubuntu', '-e', 'LXDE', '-a'],
- stdin=null, stdout=logfile, stderr=logfile,
- preexec_fn=self.drop_privileges)
- extras.append(proc)
- if os.path.exists('/usr/lib/ubiquity/panel') and "xfwm4" not in wm_cmd:
- if "openbox-lubuntu" not in wm_cmd and "openbox" not in wm_cmd:
- extras.append(subprocess.Popen(
- ['/usr/lib/ubiquity/panel'],
- stdin=null, stdout=logfile, stderr=logfile,
- preexec_fn=self.drop_privileges))
- if osextras.find_on_path('nm-applet'):
- extras.append(subprocess.Popen(
- ['nm-applet'],
- stdin=null, stdout=logfile, stderr=logfile,
- preexec_fn=self.drop_privileges))
- if osextras.find_on_path('ibus-daemon'):
- extras.append(subprocess.Popen(
- ['ibus-daemon'],
- stdin=null, stdout=logfile, stderr=logfile,
- preexec_fn=self.drop_privileges))
- # Simply start bluetooth-applet, ubiquity-bluetooth-agent will
- # override it from casper to make sure it also covers the regular
- # live session
- if osextras.find_on_path('bluetooth-applet'):
- extras.append(subprocess.Popen(
- ['bluetooth-applet'],
- stdin=null, stdout=logfile, stderr=logfile,
- preexec_fn=self.drop_privileges))
- # Accessibility tools
- if accessibility == True:
- with open('/proc/cmdline', 'r') as fp:
- if 'access=m2' in fp.readline():
- if osextras.find_on_path('onboard'):
- extras.append(subprocess.Popen(['onboard'],
- stdin=null, stdout=logfile, stderr=logfile,
- preexec_fn=self.drop_privileges))
- else:
- if osextras.find_on_path('orca'):
- time.sleep(15)
- extras.append(subprocess.Popen(['orca', '-n'],
- stdin=null, stdout=logfile, stderr=logfile,
- preexec_fn=self.drop_privileges))
- elif self.frontend == 'kde_ui':
- # Don't show the background image in v1 accessibility profile.
- os.setegid(self.gid)
- os.seteuid(self.uid)
- path = '/usr/share/wallpapers/kde-default.png'
- with open('/proc/cmdline', 'r') as fp:
- if (os.access(path, os.R_OK)
- and not 'access=v1' in fp.readline()):
- # Draw a background image for the install progress window.
- from PyQt4.QtCore import Qt
- from PyQt4 import QtGui
- a = QtGui.QApplication(sys.argv)
- root_win = a.desktop()
- wallpaper = QtGui.QPixmap(path)
- wallpaper = wallpaper.scaled(root_win.width(),
- root_win.height(), Qt.KeepAspectRatioByExpanding,
- Qt.SmoothTransformation)
- palette = QtGui.QPalette()
- palette.setBrush(root_win.backgroundRole(),
- QtGui.QBrush(wallpaper))
- root_win.setPalette(palette)
- root_win.setCursor(Qt.ArrowCursor)
- a.processEvents()
- # Force garbage collection so we don't end up with stray X
- # resources when we kill the X server (LP: #556555).
- del a
- os.seteuid(0)
- os.setegid(0)
- subprocess.call(
- ['kwriteconfig', '--file', 'kwinrc', '--group', 'Compositing',
- '--key', 'Enabled', 'false'],
- stdin=null, stdout=logfile, stderr=logfile,
- preexec_fn=self.drop_privileges)
- wm = subprocess.Popen('kwin',
- stdin=null, stdout=logfile, stderr=logfile,
- preexec_fn=self.drop_privileges)
- greeter = subprocess.Popen(program, stdin=null, stdout=logfile, stderr=logfile)
- ret = greeter.wait()
- reboot = False
- if ret != 0:
- db = DebconfCommunicator('ubiquity', cloexec=True)
- try:
- error_cmd = db.get('ubiquity/failure_command')
- if error_cmd:
- subprocess.call(['sh', '-c', error_cmd])
- except debconf.DebconfError:
- pass
- reboot = False
- try:
- if '--automatic' in program:
- reboot = db.get('ubiquity/reboot_on_failure') == 'true'
- except debconf.DebconfError:
- pass
- if reboot:
- question = 'ubiquity/install_failed_reboot'
- else:
- question = 'ubiquity/install_failed'
- title = ''
- message = ''
- try:
- title = unicode(db.metaget(question, 'description'),
- 'utf-8', 'replace')
- message = unicode(db.metaget(question, 'extended_description'),
- 'utf-8', 'replace')
- except debconf.DebconfError:
- pass
- db.shutdown()
- if title and message:
- if self.frontend == 'gtk_ui':
- cmd = ['zenity', '--error', '--title=%s' % title,
- '--text=%s' % message]
- subprocess.call(cmd)
- elif self.frontend == 'kde_ui':
- cmd = ['kdialog', '--title=%s' % title,
- '--msgbox=%s' % message]
- subprocess.call(cmd)
- else:
- # Not ideal, but if we cannot let the user know what's
- # going on, it's best to drop them into a desktop and let
- # them figure it out.
- reboot = False
- def kill_if_exists(pid, signum):
- try:
- os.kill(pid, signum)
- except OSError, e:
- if e.errno != errno.ESRCH:
- raise
- def sigalrm_handler(signum, frame):
- kill_if_exists(wm.pid, signal.SIGKILL)
- for extra in extras:
- kill_if_exists(extra.pid, signal.SIGKILL)
- kill_if_exists(wm.pid, signal.SIGTERM)
- for extra in extras:
- kill_if_exists(extra.pid, signal.SIGTERM)
- if gconfd_running:
- subprocess.call(['gconftool-2', '--shutdown'],
- stdin=null, stdout=logfile, stderr=logfile,
- preexec_fn=self.drop_privileges)
- signal.signal(signal.SIGALRM, sigalrm_handler)
- signal.alarm(1) # low patience with WMs failing to exit on demand
- processes = set(extras)
- processes.add(wm)
- while processes:
- done = set()
- for process in processes:
- try:
- process.wait()
- done.add(process)
- except OSError, e:
- if e.errno == errno.EINTR:
- continue
- raise
- processes -= done
- signal.alarm(0)
- # Clear the console so we don't see boot-time messages on switch
- try:
- vthandle = open('/dev/tty' + self.vt[2:], 'r+')
- subprocess.call(['clear'], stdin=vthandle, stdout=vthandle)
- except IOError:
- pass
- kill_if_exists(server.pid, signal.SIGTERM)
- server.wait()
- if reboot:
- subprocess.Popen(['reboot'])
- if ret is not None and ret >= 0:
- return ret
- else:
- return 1
- if len(sys.argv) < 4:
- sys.stderr.write('Usage: %s <vt[1-N]> <:[0-N]> <username> <program> '
- '[<arguments>]\n' % sys.argv[0])
- sys.exit(1)
- vt, display, username = sys.argv[1:4]
- try:
- dm = DM(vt, display, username)
- except XStartupError:
- sys.exit(1)
- ret = dm.run(*sys.argv[4:])
- if ret == 0:
- set_locale()
- sys.exit(ret)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement