File: //sbin/firstboot
#! /usr/bin/python
#
# firstboot
#
# Copyright (C) 2011 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Red Hat Author(s): Martin Gracik <[email protected]>
#
import optparse
import os
import sys
import tempfile
import traceback
from collections import namedtuple
import firstboot.frontend
import firstboot.loader
from firstboot.constants import *
# XXX
from firstboot.config import *
import meh
import meh.dump
import gettext
_ = lambda x: gettext.ldgettext("firstboot", x)
ABRT_DIR = "/var/tmp/abrt"
def exception_handler(type, value, tb, obj):
# write exception to a file
fd, path = tempfile.mkstemp(prefix='/var/tmp/firstboot-', suffix='.trace')
exception_lines = traceback.format_exception(type, value, tb)
os.write(fd, "".join(exception_lines))
os.close(fd)
meh_conf = meh.Config(programName='firstboot',
programVersion='19.12')
# python-meh expects the exception data in a named tuple
ExcInfo = namedtuple("ExcInfo", ["type", "value", "stack"])
exc_info = ExcInfo(type, value, tb)
dump_obj = meh.dump.ReverseExceptionDump(exc_info, meh_conf)
exn_dump = dump_obj.traceback_and_object_dump(obj)
fd, path = tempfile.mkstemp(prefix='firstboot-tb-')
os.write(fd, exn_dump)
os.close(fd)
# that's basically what python-meh's Save button does, except that the
# following code just creates directories ABRT wants for reporting bug
import report
params = dict()
params.update(dump_obj.environment_info)
# turn the python-meh package info to a key/value pairs
pkg_info = params.pop("pkg_info", None)
if pkg_info:
params["pkg_name"] = pkg_info.name
params["pkg_version"] = pkg_info.version
params["pkg_release"] = pkg_info.release
params["pkg_epoch"] = pkg_info.epoch
params["pkg_arch"] = pkg_info.arch
params["package"] = "%s-%s-%s.%s" % (pkg_info.name, pkg_info.version,
pkg_info.release, pkg_info.arch)
params.setdefault('component', 'firstboot')
params.setdefault('package', 'firstboot-19.12')
params['hashmarkername'] = 'firstboot'
params['duphash'] = dump_obj.hash
params['reason'] = dump_obj.desc
params['description'] = 'Traceback from firstboot:\n%s' % str(dump_obj)
params['firstboot-tb'] = exn_dump
params['uid'] = "%d" % os.geteuid()
problem_data = report.createPythonUnhandledExceptionSignature(**params)
problem_data.create_dump_dir(ABRT_DIR)
if __name__ == '__main__':
# set up exception handling first
sys.excepthook = lambda ty, value, tb: exception_handler(ty, value, tb,
config)
# only root can do this
if not os.geteuid() == 0:
print >> sys.stderr, _('only root can do this')
sys.exit(1)
parser = optparse.OptionParser()
parser.add_option('-m', '--moduledir', dest='module_dir')
parser.add_option('-r', '--reconfig',
action='store_true', default=False)
parser.add_option('-s', '--autoscreenshot',
action='store_true', default=False)
parser.add_option('-t', '--test',
action='store_true', default=False)
parser.add_option('--themedir', dest='theme_dir')
opts, args = parser.parse_args()
# XXX should we run?
if os.path.isfile('/etc/sysconfig/firstboot'):
with open('/etc/sysconfig/firstboot') as fobj:
for line in fobj:
if line.strip() == 'RUN_FIRSTBOOT=NO':
os.system('systemctl stop firstboot-graphical.service > /dev/null 2>&1')
os.system('systemctl stop firstboot-text.service > /dev/null 2>&1')
# disable the service so that it doesn't run on every boot just to find
# out it should kill itself
os.system("systemctl disable firstboot-graphical.service")
sys.exit(0)
if not opts.module_dir:
opts.module_dir = MODULE_DIR
if not opts.theme_dir:
themes = [d for d in os.listdir(THEME_DIR) if d != 'default']
if themes:
opts.theme_dir = os.path.join(THEME_DIR, themes[0])
else:
opts.theme_dir = os.path.join(THEME_DIR, 'default')
# XXX set the theme dir in config
config.themeDir = opts.theme_dir
frontend = None
if 'DISPLAY' not in os.environ:
frontend = firstboot.frontend.Frontend()
frontend.set_lang()
frontend.startx()
frontend.init_gtk()
frontend.start_wm()
frontend.merge_xres()
# these modules import gtk, so we need to have a display first
import firstboot.interface
# XXX set up the interface
config.frontend = frontend
config.interface = firstboot.interface.Interface(opts.autoscreenshot,
opts.test)
# load modules
loader = firstboot.loader.Loader()
modules = loader.load_modules(module_dir=opts.module_dir,
reconfig=opts.reconfig)
reboot_required = False
if modules:
# TODO rewrite the interface
config.interface.moduleList = modules
config.interface.createMainWindow()
config.interface.createScreens()
config.interface.createSidebar()
reboot_required = config.interface.run()
if frontend is not None:
frontend.kill()
if not opts.test:
with open('/etc/sysconfig/firstboot', 'w') as f:
f.write('RUN_FIRSTBOOT=NO\n')
if opts.reconfig:
try:
os.unlink('/etc/reconfigSys')
except OSError:
pass
# disable the service so that it doesn't run on every boot just to find
# out it should kill itself
os.system("systemctl disable firstboot-graphical.service")
if reboot_required:
os.system("/sbin/reboot")