summaryrefslogtreecommitdiff
path: root/portato/__init__.py
blob: 61d6a42fa499f92fcc7cf079bbaa98fa2dac9733 (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
133
134
135
136
# -*- coding: utf-8 -*-
#
# File: portato/__init__.py
# This file is part of the Portato-Project, a graphical portage-frontend.
#
# Copyright (C) 2006-2010 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
from optparse import OptionParser, SUPPRESS_HELP

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

# set better version info
if REVISION:
    VERSION = '%s (git: %s)' % (VERSION, REVISION)

# 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
    _sub_start()

    # start logging
    logstart(file=False)

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

    if options.nofork or os.getuid() == 0: # start GUI
        
        # close listener at exit
        import atexit
        atexit.register(get_listener().close)

        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
        import subprocess, threading
        from .su import detect_su_command

        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.")