summaryrefslogtreecommitdiff
path: root/portato/__init__.py
blob: 736342909bec0094c98a5913e6ab3ac44d5aa1be (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# -*- coding: utf-8 -*-
#
# File: portato/__init__.py
# This file is part of the Portato-Project, a graphical portage-frontend.
#
# Copyright (C) 2006-2009 René 'Necoro' Neumann
# This is free software.  You may redistribute copies of it under the terms of
# the GNU General Public License version 2.
# There is NO WARRANTY, to the extent permitted by law.
#
# Written by René 'Necoro' Neumann <necoro@necoro.net>

from __future__ import absolute_import

import gettext, locale
import sys, os
import subprocess, threading
import atexit
from optparse import OptionParser, SUPPRESS_HELP

from .log import start as logstart
from .constants import LOCALE_DIR, APP, VERSION
from .su import detect_su_command
from .helper import debug, info, error

# listener-handling
__listener = None

def get_listener():
    global __listener
    if __listener is None:
        from .listener import Listener
        __listener = Listener()
    
    return __listener

def get_parser (use_ = False):
    # use_ defaults to False, if it is called from outside
    # where gettext is not yet initialized

    if not use_: _ = lambda s : s
    
    desc = "%prog - A Portage GUI."
    usage = "%prog [options]"
    vers =  "%%prog v. %s" % VERSION

    parser = OptionParser(version = vers, prog = "portato", description = desc, usage = usage)
    
    parser.add_option("--mq", action = "store", nargs = 1, type="long", dest = "mq", default = None,
            help = SUPPRESS_HELP)

    parser.add_option("-F", "--no-fork", action = "store_true", dest = "nofork", default = False,
            help = _("do not fork off as root"))

    return parser

def _sub_start ():
    # set gettext stuff
    locale.setlocale(locale.LC_ALL, '')
    gettext.install(APP, LOCALE_DIR, unicode = True)

def start():

    # set gettext stuff
    locale.setlocale(locale.LC_ALL, '')
    gettext.install(APP, LOCALE_DIR, unicode = True)

    # start logging
    logstart(file=False)

    # run parser
    (options, args) = get_parser().parse_args()

    # close listener at exit
    atexit.register(get_listener().close)

    if options.nofork or os.getuid() == 0: # start GUI
        logstart(file = True) # start logging to file

        from .gui import run
        info("%s v. %s", _("Starting Portato"), VERSION)
        
        get_listener().set_send(options.mq)
        
        try:
            run()
        except KeyboardInterrupt:
            debug("Got KeyboardInterrupt.")
        
    else: # start us again in root modus and launch listener
        
        from . import ipc

        mq = ipc.MessageQueue(None, create = True, exclusive = True)
        
        # start listener
        lt = threading.Thread(target=get_listener().set_recv, args = (mq,))
        lt.setDaemon(False)
        lt.start()
        
        try:
            # set DBUS_SESSION_BUS_ADDRESS to "" to make dbus work as root ;)
            env = os.environ.copy()
            env.update(DBUS_SESSION_BUS_ADDRESS="")
            
            su = detect_su_command()
            if su:
                debug("Using '%s' as su command.", su.bin)
                cmd = su.cmd("%s --no-fork --mq %ld" % (sys.argv[0], mq.key))

                sp = subprocess.Popen(cmd, env = env)

                # wait for process to finish
                try:
                    sp.wait()
                    debug("Subprocess finished")
                except KeyboardInterrupt:
                    debug("Got KeyboardInterrupt.")

            else:
                error(_("No valid su command detected. Aborting."))
        
        finally:
            if lt.isAlive():
                debug("Listener is still running. Close it.")
                get_listener().close()
                lt.join()

            try:
                mq.remove()
            except ipc.MessageQueueRemovedError:
                debug("MessageQueue already removed. Ignore.")