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
137
138
139
140
141
142
143
144
|
# -*- 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, PLUGIN_DIR
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"))
parser.add_option("--plugin-dir", action = "store_true", dest = "pdir", default = False,
help = _("print the directory the plugins are located in"))
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()
# plugin dir
if options.pdir:
print PLUGIN_DIR
return
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.")
|