#!/usr/bin/python
#
# anaconda: The Red Hat Linux Installation program
#
# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
# Red Hat, Inc.  All rights reserved.
#
# 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/>.
#
# Author(s): Brent Fox <bfox@redhat.com>
#            Mike Fulbright <msf@redhat.com>
#            Jakub Jelinek <jakub@redhat.com>
#            Jeremy Katz <katzj@redhat.com>
#            Chris Lumens <clumens@redhat.com>
#            Paul Nasrat <pnasrat@redhat.com>
#            Erik Troan <ewt@rpath.com>
#            Matt Wilson <msw@rpath.com>
#

# This toplevel file is a little messy at the moment...

import atexit, sys, os, re, time, subprocess
from tempfile import mkstemp

# keep up with process ID of the window manager if we start it
wm_pid = None

def exitHandler(anaconda, exitCode=None):
    from pyanaconda import isys
    from pyanaconda.flags import flags

    if exitCode:
        anaconda.intf.shutdown()

        if "nokill" in flags.cmdline:
            isys.vtActivate(1)
            print "anaconda halting due to nokill flag."
            print "The system will be rebooted when you press Ctrl-Alt-Delete."
            while True:
                time.sleep(10000)

    if image_count:
        anaconda.storage.umountFilesystems(ignoreErrors=True, swapoff=False)
        devicetree = anaconda.storage.devicetree
        devicetree.teardownAll()
        for name in devicetree.diskImages:
            device = devicetree.getDeviceByName(name)
            for loop in device.parents:
                loop.controllable = True
            device.deactivate(recursive=True)

    if anaconda.ksdata and not flags.imageInstall:
        from pykickstart.constants import KS_SHUTDOWN, KS_WAIT, KS_REBOOT
        from pyanaconda.iutil import dracut_eject

        if anaconda.ksdata.reboot.eject:
            for drive in anaconda.storage.devicetree.devices:
                if drive.type != "cdrom":
                    continue
                dracut_eject(drive.path)

        if anaconda.ksdata.reboot.action == KS_SHUTDOWN:
            os.system("systemctl --force --no-wall poweroff")
        elif anaconda.ksdata.reboot.action == KS_WAIT:
            os.system("systemctl --force --no-wall halt")
        else: # reboot action is KS_REBOOT or None
            os.system("systemctl --force --no-wall reboot")
    elif not flags.imageInstall:
        os.system("systemctl --force --no-wall reboot")

def startMetacityWM():
    childpid = os.fork()
    if not childpid:
        # after this point the method should never return (or throw an exception
        # outside)
        try:
            args = ['--display', ':1',
                    '--sm-disable']
            iutil.execWithRedirect('metacity', args,
                                   stdout='/dev/null', stderr='/dev/null')
        except BaseException as e:
            # catch all possible exceptions
            log.error("Problems running the window manager: %s" % str(e))
            sys.exit(1)

        log.info("The window manager has terminated.")
        sys.exit(0)
    return childpid

def startAuditDaemon():
    childpid = os.fork()
    if not childpid:
        cmd = '/sbin/auditd'
        try:
            os.execl(cmd, cmd)
        except OSError as e:
            log.error("Error running the audit daemon: %s" % str(e))
        sys.exit(0)
    # auditd will turn into a daemon so catch the immediate child pid now:
    os.waitpid(childpid, 0)

# function to handle X startup special issues for anaconda
def doStartupX11Actions():
    global wm_pid # pid of the anaconda fork where the window manager is running

    setupGraphicalLinks()

    # now start up the window manager
    wm_pid = startMetacityWM()
    log.info("Starting window manager, pid %s." % (wm_pid,))

def set_x_resolution(runres):
    # cant do this if no window manager is running because otherwise when we
    # open and close an X connection in the xutils calls the X server will exit
    # since this is the first X connection (if no window manager is running)
    if runres and opts.display_mode == 'g' and not flags.usevnc and wm_pid :
        try:
            log.info("Setting the screen resolution to: %s.", runres)
            iutil.execWithRedirect("xrandr", 
                                   ["-d", ":1", "-s", runres],
                                   stdout="/dev/tty5", stderr="/dev/tty5")
        except RuntimeError as e:
            log.error("The X resolution not set")
            iutil.execWithRedirect("xrandr",
                                   ["-d", ":1", "-q"],
                                   stdout="/dev/tty5", stderr="/dev/tty5")

def setupPythonUpdates():
    from distutils.sysconfig import get_python_lib

    if not os.path.exists("/tmp/updates"):
        return

    for pkg in os.listdir("/tmp/updates"):
        d = "/tmp/updates/%s" % pkg

        if not os.path.isdir(d):
            continue

        # See if the package exists in /usr/lib{64,}/python/?.?/site-packages.
        # If it does, we can set it up as an update.  If not, the pkg is
        # likely a completely new directory and should not be looked at.
        dest = "%s/%s" % (get_python_lib(), pkg)
        if not os.access(dest, os.R_OK):
            dest = "%s/%s" % (get_python_lib(1), pkg)
            if not os.access(dest, os.R_OK):
                continue
        # Symlink over everything that's in the python libdir but not in
        # the updates directory.
        symlink_updates(dest, d)

    import glob
    import shutil
    for rule in glob.glob("/tmp/updates/*.rules"):
        target = "/etc/udev/rules.d/" + rule.split('/')[-1]
        shutil.copyfile(rule, target)

def symlink_updates(dest_dir, update_dir):    
    contents = os.listdir(update_dir)

    for f in os.listdir(dest_dir):
        dest_path = os.path.join(dest_dir, f)
        update_path = os.path.join(update_dir, f)
        if f in contents:
            # recurse into directories, there might be files missing in updates
            if os.path.isdir(dest_path) and os.path.isdir(update_path):
                symlink_updates(dest_path, update_path)
        else:
            if f.endswith(".pyc") or f.endswith(".pyo"):
                continue
            os.symlink(dest_path, update_path)

def getAnacondaVersion():
    # Using _isys here so we don't drag in the logging stuff, which is always
    # complicated.
    from pyanaconda import _isys
    return _isys.getAnacondaVersion()

def parseOptions(argv=None, cmdline=None):
    from pyanaconda.anaconda_optparse import AnacondaOptionParser
    op = AnacondaOptionParser(version="%prog " + getAnacondaVersion(),
                              bootarg_prefix="inst.", require_prefix=False)

    # NOTE: store_false options will *not* get negated when the user does
    # "option=0" on the boot commandline (store_true options do, though).
    # Basically, don't use store_false unless the option starts with "no".

    # Interface
    op.add_option("-C", "--cmdline", dest="display_mode", action="store_const", const="c",
                  default="g")
    op.add_option("-G", "--graphical", dest="display_mode", action="store_const", const="g")
    op.add_option("-T", "--text", dest="display_mode", action="store_const", const="t")
    op.add_option("-S", "--script", dest="display_mode", action="store_const", const="s")

    # Network
    op.add_option("--noipv4", action="store_true", default=False)
    op.add_option("--noipv6", action="store_true", default=False)
    op.add_option("--proxy")
    op.add_option("--proxyAuth")

    # Method of operation
    op.add_option("--autostep", action="store_true", default=False)
    op.add_option("-d", "--debug", dest="debug", action="store_true", default=False)
    op.add_option("--ks", dest="ksfile", action="store_const", const="/run/install/ks.cfg")
    op.add_option("--kickstart", dest="ksfile")
    op.add_option("--rescue", dest="rescue", action="store_true", default=False)
    op.add_option("--targetarch", "rpmarch", dest="targetArch", type="string")

    op.add_option("-m", "--method", dest="method", default=None)
    op.add_option("--repo", dest="method", default=None)
    op.add_option("--stage2", dest="stage2", default=None)
    op.add_option("--noverifyssl", action="store_true", default=False)

    op.add_option("--liveinst", action="store_true", default=False)

    # Display
    op.add_option("--headless", dest="isHeadless", action="store_true", default=False)
    op.add_option("--nofb")
    op.add_option("--resolution", dest="runres", default=None)
    op.add_option("--serial", action="store_true", default=False)
    op.add_option("--usefbx", dest="xdriver", action="store_const", const="fbdev")
    op.add_option("--virtpconsole")
    op.add_option("--vnc", action="store_true", default=False)
    op.add_option("--vncconnect")
    op.add_option("--vncpassword", default="")
    op.add_option("--xdriver", dest="xdriver", action="store", type="string", default=None)

    # Language
    op.add_option("--keymap")
    op.add_option("--kbdtype")
    op.add_option("--lang")

    # Obvious
    op.add_option("--loglevel")
    op.add_option("--syslog")

    op.add_option("--noselinux", dest="selinux", action="store_false", default=True)
    op.add_option("--selinux", action="store_true")

    op.add_option("--nompath", dest="mpath", action="store_false", default=True)
    op.add_option("--mpath", action="store_true")

    op.add_option("--nodmraid", dest="dmraid", action="store_false", default=True)
    op.add_option("--dmraid", action="store_true")

    op.add_option("--noibft", dest="ibft", action="store_false", default=True)
    op.add_option("--ibft", action="store_true")
    op.add_option("--noiscsi", dest="iscsi", action="store_false", default=False)
    op.add_option("--iscsi", action="store_true")

    # Miscellaneous
    op.add_option("--module", action="append", default=[])
    op.add_option("--nomount", dest="rescue_nomount", action="store_true", default=False)
    op.add_option("--updates", dest="updateSrc", action="store", type="string")
    op.add_option("--dlabel", action="store_true", default=False)
    op.add_option("--image", action="append", dest="images", default=[])
    op.add_option("--memcheck", action="store_true", default=True)
    op.add_option("--nomemcheck", action="store_false", dest="memcheck")

    # some defaults change based on cmdline flags
    if cmdline is not None:
        if "console" in cmdline:
            op.set_defaults(display_mode="t")
            op.set_defaults(serial=True)

    (opts, args) = op.parse_args(argv, cmdline=cmdline)
    return (opts, args, op.deprecated_bootargs)

def setupPythonPath():
    sys.path.append('/usr/share/system-config-date')

def setupEnvironment():
    # Silly GNOME stuff
    if os.environ.has_key('HOME') and not os.environ.has_key("XAUTHORITY"):
        os.environ['XAUTHORITY'] = os.environ['HOME'] + '/.Xauthority'
    os.environ['HOME'] = '/tmp'
    os.environ['LC_NUMERIC'] = 'C'
    os.environ["GCONF_GLOBAL_LOCKS"] = "1"

    # In theory, this gets rid of our LVM file descriptor warnings
    os.environ["LVM_SUPPRESS_FD_WARNINGS"] = "1"

    # make sure we have /sbin and /usr/sbin in our path
    os.environ["PATH"] += ":/sbin:/usr/sbin"

    # we can't let the LD_PRELOAD hang around because it will leak into
    # rpm %post and the like.  ick :/
    if os.environ.has_key("LD_PRELOAD"):
        del os.environ["LD_PRELOAD"]

    os.environ["GLADEPATH"] = "/tmp/updates/:/tmp/updates/data/ui/:ui/:/usr/share/anaconda/ui/:/usr/share/python-meh/"
    os.environ["PIXMAPPATH"] = "/tmp/updates/pixmaps/:/tmp/updates/:/tmp/product/pixmaps/:/tmp/product/:pixmaps/:/usr/share/anaconda/pixmaps/:/usr/share/pixmaps/:/usr/share/anaconda/:/usr/share/python-meh/:/usr/share/icons/Fedora/48x48/apps/"

def setupLoggingFromOpts(opts):
    if opts.loglevel and anaconda_log.logLevelMap.has_key(opts.loglevel):
        level = anaconda_log.logLevelMap[opts.loglevel]
        anaconda_log.logger.tty_loglevel = level
        anaconda_log.setHandlersLevel(log, level)
        storage_log = logging.getLogger("storage")
        anaconda_log.setHandlersLevel(storage_log, level)

    if opts.syslog:
        anaconda_log.logger.remote_syslog = opts.syslog

# ftp installs pass the password via a file in /tmp so
# ps doesn't show it
def expandFTPMethod(str):
    ret = None

    try:
        filename = str[1:]
        ret = open(filename, "r").readline()
        ret = ret[:len(ret) - 1]
        os.unlink(filename)
        return ret
    except:
        return None

def runVNC(vncS):
    vncS.startServer()

    child = os.fork()
    if child == 0:
        for p in ('/tmp/updates/pyrc.py', \
                '/usr/share/anaconda/pyrc.py'):
            if os.access(p, os.R_OK|os.X_OK):
                os.environ['PYTHONSTARTUP'] = p
                break

        while True:
            # Not having a virtual terminal or otherwise free console
            # are the only places we /really/ need a shell on tty1,
            # and everywhere else this just gets in the way of pdb.  But we
            # don't want to return, because that'll return try to start X
            # a second time.
            if iutil.isConsoleOnVirtualTerminal() or iutil.isS390():
                    time.sleep(10000)
            else:
                    print _("Press <enter> for a shell")
                    sys.stdin.readline()
                    iutil.execConsole()

def gtk_warning(title, reason):
    import gtk
    dialog = gtk.MessageDialog(type = gtk.MESSAGE_ERROR,
                               buttons = gtk.BUTTONS_CLOSE,
                               message_format=reason)
    dialog.set_title(title)
    dialog.run()
    dialog.destroy()

def check_memory(anaconda, opts, display_mode=None):
    reason_strict = _("%s requires %s MB of memory to install, but you only have "
                      "%s MB on this machine.\n")
    reason_graphical = _("The %s graphical installer requires %s MB of memory, but "
                         "you only have %s MB.")

    reboot_extra = _('\n'
                     'Press <return> to reboot your system.\n')
    livecd_title = _("Not enough RAM")
    livecd_extra =_(" Try the text mode installer by running:\n\n"
                    "'/usr/bin/liveinst -T'\n\n from a root "
                    "terminal.")
    nolivecd_extra = _(" Starting text mode.")

    if not display_mode:
        display_mode = anaconda.displayMode

    reason = reason_strict
    total_ram = int(isys.total_memory() / 1024)
    needed_ram = int(isys.MIN_RAM / 1024)
    graphical_ram = needed_ram + int(isys.GUI_INSTALL_EXTRA_RAM / 1024)

    log.info("check_memory(): total:%s, needed:%s, graphical:%s" % \
            (total_ram, needed_ram, graphical_ram))

    if not opts.memcheck:
        log.warning("CHECK_MEMORY DISABLED")
        return

    if needed_ram > total_ram:
        from snack import SnackScreen, ButtonChoiceWindow
        if opts.liveinst:
            stdoutLog.warning(reason % (product.productName, needed_ram, total_ram))
            gtk_warning(livecd_title, reason % (product.productName, needed_ram, total_ram))
        else:
            reason += reboot_extra
            screen = SnackScreen()
            ButtonChoiceWindow(screen, _('Fatal Error'),
                               reason % (product.productName, needed_ram, total_ram),
                               buttons = (_("OK"),))
            screen.finish()
        sys.exit(1)

    # override display mode if machine cannot nicely run X
    if display_mode not in ('t', 'c', 's') and not flags.usevnc:
        needed_ram = graphical_ram
        reason = reason_graphical

        if needed_ram > total_ram:
            if opts.liveinst:
                reason += livecd_extra
                stdoutLog.warning(reason % (product.productName, needed_ram, total_ram))
                title = livecd_title
                gtk_warning(title, reason % (product.productName, needed_ram, total_ram))
                sys.exit(1)
            else:
                reason += nolivecd_extra
                stdoutLog.warning(reason % (product.productName, needed_ram, total_ram))
                anaconda.displayMode = 't'
                time.sleep(2)

def setupGraphicalLinks():
    for i in ( "imrc", "im_palette.pal", "gtk-2.0", "pango", "fonts",
               "fb.modes"):
        try:
            if os.path.exists("/mnt/runtime/etc/%s" %(i,)):
                os.symlink ("../mnt/runtime/etc/" + i, "/etc/" + i)
        except:
            pass

def startDebugger(signum, frame):
    import epdb
    epdb.serve(skip=1)

def setupDisplay(anaconda, opts):
    graphical_failed = 0
    vncS = vnc.VncServer()          # The vnc Server object.
    vncS.anaconda = anaconda

    anaconda.displayMode = opts.display_mode
    anaconda.isHeadless = opts.isHeadless or iutil.isS390()

    if opts.vnc:
        flags.usevnc = 1
        anaconda.displayMode = 'g'
        vncS.password = opts.vncpassword

        # Only consider vncconnect when vnc is a param
        if opts.vncconnect:
            cargs = string.split(opts.vncconnect, ":")
            vncS.vncconnecthost = cargs[0]
            if len(cargs) > 1 and len(cargs[1]) > 0:
                if len(cargs[1]) > 0:
                    vncS.vncconnectport = cargs[1]

    if opts.serial:
        flags.serial = True
    if opts.virtpconsole:
        flags.virtpconsole = opts.virtpconsole

    if opts.xdriver:
        anaconda.xdriver = opts.xdriver
        anaconda.writeXdriver(root="/")

    if anaconda.rescue:
        anaconda.displayMode = 'r'
    else:
        if anaconda.ksdata:
            if anaconda.ksdata.vnc.enabled:
                flags.usevnc = 1
                anaconda.displayMode = 'g'

                if vncS.password == "":
                    vncS.password = anaconda.ksdata.vnc.password

                if vncS.vncconnecthost == "":
                    vncS.vncconnecthost = anaconda.ksdata.vnc.host

                if vncS.vncconnectport == "":
                    vncS.vncconnectport = anaconda.ksdata.vnc.port

            flags.vncquestion = False

        # disable VNC over text question when not enough memory is available
        if iutil.memInstalled() < isys.MIN_GUI_RAM:
            flags.vncquestion = False

        if os.environ.has_key('DISPLAY'):
            flags.preexisting_x11 = True

        if anaconda.displayMode == 't' and flags.vncquestion:
            #we prefer vnc over text mode, so ask about that
            title = _("Would you like to use VNC?")
            message = _("Text mode provides a limited set of installation "
                        "options. It does not allow you to specify your "
                        "own partitioning layout or package selections. "
                        "Would you like to use VNC mode instead?")

            ret = vnc.askVncWindow(title, message)
            if ret != -1:
                anaconda.displayMode = 'g'
                flags.usevnc = 1
                if ret is not None:
                    vncS.password = ret

        log.info("Display mode = %s" % anaconda.displayMode)
        check_memory(anaconda, opts)

        # Should we try to start Xorg?
        want_x = anaconda.displayMode == 'g' and \
                 not (flags.preexisting_x11 or flags.usevnc)

        # X on a headless (e.g. s390) system? Nonsense!
        if want_x and anaconda.isHeadless:
            stdoutLog.warning(_("DISPLAY variable not set. Starting text mode."))
            anaconda.displayMode = 't'
            graphical_failed = 1
            time.sleep(2)
            want_x = False

        # Is Xorg is actually available?
        if want_x and not os.access("/usr/bin/Xorg", os.X_OK):
            stdoutLog.warning(_("Graphical installation is not available. "
                                "Starting text mode."))
            time.sleep(2)
            anaconda.displayMode = 't'
            want_x = False

        if want_x:
            # The following code depends on no SIGCHLD being delivered,
            # possibly only except the one from a failing X.org. Thus
            # make sure before entering this section that all the other
            # children of anaconda have terminated or were forked into
            # an orphan (which won't deliver a SIGCHLD to mess up the
            # fragile signaling below). start X with its USR1 handler
            # set to ignore.  this will make it send us SIGUSR1 if it
            # succeeds.  if it fails, catch SIGCHLD and bomb out.
            def sigchld_handler(num, frame):
                raise OSError(0, "SIGCHLD caught when trying to start the X server.")

            def sigusr1_handler(num, frame):
                log.debug("X server has signalled a successful start.")

            def preexec_fn():
                signal.signal(signal.SIGUSR1, signal.SIG_IGN)

            old_sigusr1 = signal.signal(signal.SIGUSR1, sigusr1_handler)
            old_sigchld = signal.signal(signal.SIGCHLD, sigchld_handler)
            xout = open("/dev/tty5", "w")
            try:
                proc = subprocess.Popen(["Xorg", "-br",
                                         "-logfile", "/tmp/X.log",
                                         ":1", "vt6", "-s", "1440", "-ac",
                                         "-nolisten", "tcp", "-dpi", "96",
                                         "-noreset"],
                                         close_fds=True,
                                         stdout=xout, stderr=xout,
                                         preexec_fn=preexec_fn)

                signal.pause()
                os.environ["DISPLAY"] = ":1"
                doStartupX11Actions()
            except (OSError, RuntimeError):
                stdoutLog.warning("X startup failed, falling back to text mode")
                anaconda.displayMode = 't'
                graphical_failed = 1
                time.sleep(2)
            finally:
                signal.signal(signal.SIGUSR1, old_sigusr1)
                signal.signal(signal.SIGCHLD, old_sigchld)

        set_x_resolution(opts.runres)

        if anaconda.displayMode == 't' and graphical_failed and \
             not anaconda.ksdata:
            ret = vnc.askVncWindow()
            if ret != -1:
                anaconda.displayMode = 'g'
                flags.usevnc = 1
                if ret is not None:
                    vncS.password = ret

        # if they want us to use VNC do that now
        if anaconda.displayMode == 'g' and flags.usevnc:
            runVNC(vncS)
            doStartupX11Actions()

    # with X running we can initialize the UI interface
    anaconda.initInterface()
    anaconda.instClass.configure(anaconda)

if __name__ == "__main__":
    setupPythonPath()

    # Allow a file to be loaded as early as possible
    try:
        import updates_disk_hook
    except ImportError:
        pass

    # this handles setting up updates for pypackages to minimize the set needed
    setupPythonUpdates()

    # do this early so we can set flags before initializing logging
    from pyanaconda.flags import flags
    (opts, args, depr) = parseOptions(cmdline=flags.cmdline)
    if opts.images:
        flags.imageInstall = True

    # Set up logging as early as possible.
    import logging
    from pyanaconda import anaconda_log
    anaconda_log.init()
    anaconda_log.logger.setupVirtio()

    log = logging.getLogger("anaconda")
    stdoutLog = logging.getLogger("anaconda.stdout")

    if os.geteuid() != 0:
        stdoutLog.error("anaconda must be run as root.")
        sys.exit(0)

    log.info("%s %s" % (sys.argv[0], getAnacondaVersion()))

    # TODO: uncomment this when we're sure that we're doing the right thing
    # with flags.cmdline *everywhere* it appears...
    #for arg in depr:
    #    stdoutLog.warn("Boot argument '%s' is deprecated. "
    #                   "In the future, use 'inst.%s'.", arg, arg)

    # pull this in to get product name and versioning
    from pyanaconda import product
    from pyanaconda.constants import ROOT_PATH, DEFAULT_LANG

    from pyanaconda import isys
    isys.initLog()

    import signal, string, time

    from pyanaconda import iutil
    from pyanaconda import vnc
    from pyanaconda import kickstart

    # Write out the default locale before anything imports locale (#731356)
    deflang, defcode = DEFAULT_LANG.split('.')
    iutil.execWithRedirect("localedef",
                           ["-i", deflang, "-f", defcode, DEFAULT_LANG])

    # to set UTF8 mode on the terminal, we need LANG to be set usefully
    if os.environ.get("LANG", "C") == "C":
        os.environ['LANG'] = DEFAULT_LANG
    print "\033%G" # UTF8 power go!

    import gettext
    _ = lambda x: gettext.ldgettext("anaconda", x)

    from pyanaconda import Anaconda
    anaconda = Anaconda()
    iutil.setup_translations(gettext)

    # reset python's default SIGINT handler
    signal.signal(signal.SIGINT, signal.SIG_DFL)
    signal.signal(signal.SIGSEGV, isys.handleSegv)

    setupEnvironment()
    # make sure we have /var/log soon, some programs fail to start without it
    iutil.mkdirChain("/var/log")

    pidfile = open("/var/run/anaconda.pid", "w")
    pidfile.write("%s\n" % (os.getpid(),))
    del pidfile
    # add our own additional signal handlers
    signal.signal(signal.SIGHUP, startDebugger)

    anaconda.opts = opts

    # check memory, just the text mode for now:
    check_memory(anaconda, opts, 't')

    # Now that we've got arguments, do some extra processing.
    setupLoggingFromOpts(opts)

    # Default is to prompt to mount the installed system.
    anaconda.rescue_mount = not opts.rescue_nomount

    if opts.dlabel: #autodetected driverdisc in use
        flags.dlabel = True

    if opts.noipv4:
        flags.useIPv4 = False

    if opts.noipv6:
        flags.useIPv6 = False

    if opts.proxy:
        anaconda.proxy = opts.proxy

        if opts.proxyAuth:
            filename = opts.proxyAuth
            ret = open(filename, "r").readlines()
            os.unlink(filename)

            anaconda.proxyUsername = ret[0].rstrip()
            if len(ret) == 2:
                anaconda.proxyPassword = ret[1].rstrip()

    if opts.updateSrc:
        anaconda.updateSrc = opts.updateSrc

    if opts.method:
        if opts.method[0] == '@':
            opts.method = expandFTPMethod(opts.method)

        anaconda.setMethodstr(opts.method)
    else:
        anaconda.methodstr = None

    if opts.stage2:
        if opts.stage2[0] == '@':
            opts.stage2 = expandFTPMethod(opts.stage2)

        anaconda.stage2 = opts.stage2

    if opts.noverifyssl:
        flags.noverifyssl = True

    if opts.liveinst:
        flags.livecdInstall = True

    if opts.module:
        for mod in opts.module:
            (path, name) = string.split(mod, ":")
            anaconda.extraModules.append((path, name))

    if opts.ibft:
        flags.ibft = 1

    if opts.iscsi:
        flags.iscsi = 1

    if opts.targetArch:
        flags.targetarch = opts.targetArch

    # set flags
    flags.dmraid = opts.dmraid
    flags.mpath = opts.mpath
    flags.selinux = opts.selinux

    if not flags.livecdInstall and not flags.imageInstall:
        startAuditDaemon()

    # setup links required for all install types
    for i in ( "services", "protocols", "nsswitch.conf", "joe", "selinux",
               "mke2fs.conf" ):
        try:
            if os.path.exists("/mnt/runtime/etc/" + i):
                os.symlink ("../mnt/runtime/etc/" + i, "/etc/" + i)
        except:
            pass

    if opts.debug:
        flags.debug = True

    if opts.rescue:
        anaconda.rescue = True

    log.info("anaconda called with cmdline = %s" %(sys.argv,))
    log.info("Default encoding = %s " % sys.getdefaultencoding())

    os.system("udevadm control --env=ANACONDA=1")

    # parse (not execute) kickstart now, the ks commands can affect things like
    # UI interface type or enabling rescue mode
    if opts.ksfile:
        kickstart.preScriptPass(anaconda, opts.ksfile)
        anaconda.ksdata = kickstart.parseKickstart(anaconda, opts.ksfile)
        if anaconda.ksdata.rescue.rescue:
            anaconda.rescue = True

        # Setup the storage config options from the kickstart file
        anaconda.storage.config.zeroMbr = anaconda.ksdata.zerombr.zerombr
        anaconda.storage.config.ignoreDiskInteractive = anaconda.ksdata.ignoredisk.interactive
        anaconda.storage.config.ignoredDisks = anaconda.ksdata.ignoredisk.ignoredisk
        anaconda.storage.config.exclusiveDisks = anaconda.ksdata.ignoredisk.onlyuse

        if anaconda.ksdata.clearpart.type is not None:
            anaconda.storage.config.clearPartType = anaconda.ksdata.clearpart.type
            anaconda.storage.config.clearPartDisks = anaconda.ksdata.clearpart.drives
            if anaconda.ksdata.clearpart.initAll:
                anaconda.storage.config.reinitializeDisks = anaconda.ksdata.clearpart.initAll

        # Set up display options.
        # NOTE: kickstart overrides cmdline, because kickstart gets parsed last
        if anaconda.ksdata.displaymode.displayMode is not None:
            # this is derived from pykickstart.constants.DISPLAY_MODE_*
            displaymap = ['cmdline', 'graphical', 'text']
            display_mode = displaymap[anaconda.ksdata.displaymode.displayMode]
            log.info("kickstart forcing %s mode" % display_mode)
            opts.display_mode = display_mode[0] # 'c', 'g', or 't'

    # now start the interface
    setupDisplay(anaconda, opts)
    # setting the install steps requires interface to be running
    if opts.ksfile:
        kickstart.setSteps(anaconda)
    else:
        anaconda.instClass.setSteps(anaconda)
    if anaconda.rescue:
        anaconda.dispatch.request_steps("rescue")

    image_count = 0
    for image in opts.images:
        image_spec = image.rsplit(":", 1)
        path = image_spec[0]
        if len(image_spec) == 2 and image_spec[1].strip():
            name = image_spec[1].strip()
        else:
            name = os.path.splitext(os.path.basename(path))[0]

        if "/" in name or name in anaconda.storage.config.diskImages.keys():
            name = "diskimg%d" % image_count

        log.info("naming disk image '%s' '%s'" % (path, name))
        anaconda.storage.config.diskImages[name] = path
        image_count += 1
        flags.imageInstall = True

    if image_count:
        anaconda.storage.setupDiskImages()
        anaconda.dispatch.skip_steps("filtertype")
        anaconda.simpleFilter = True

    # comment out the next line to make exceptions non-fatal
    from pyanaconda.exception import initExceptionHandling
    anaconda.mehConfig = initExceptionHandling(anaconda)

    # add our own additional signal handlers
    signal.signal(signal.SIGUSR2, lambda signum, frame: anaconda.dumpState())

    if opts.lang:
        # this is lame, but make things match what we expect (#443408)
        opts.lang = opts.lang.replace(".utf8", ".UTF-8")
        anaconda.dispatch.skip_steps("language")
        anaconda.instLanguage.instLang = opts.lang
        anaconda.instLanguage.buildLocale()
        anaconda.instLanguage.systemLang = opts.lang
        anaconda.timezone.setTimezoneInfo(anaconda.instLanguage.getDefaultTimeZone())

    if opts.keymap:
        anaconda.dispatch.skip_steps("keyboard")
        anaconda.keyboard.set(opts.keymap)
        anaconda.keyboard.activate()

    # set up the headless case
    if anaconda.isHeadless:
        anaconda.dispatch.skip_steps("keyboard")

    atexit.register(exitHandler, anaconda)

    try:
        anaconda.dispatch.run()
    except SystemExit as code:
        exitHandler(anaconda, code)
    except RuntimeError as errtxt:
        if anaconda.displayMode == 'c':
            print errtxt
            while True:
                time.sleep(10000)
        raise

# vim:tw=78:ts=4:et:sw=4
