17
17
from gettext import gettext as _
22
23
if not const.DEBUG:
23
24
DEBUG_SHELL = False
25
26
def bash_prepare(string):
26
"""Prepares a string for bash by surrounding it with single quotes.
27
"""Prepare a string for bash by surrounding it with single quotes.
29
Returns the formatted string.
27
31
>>> shell.bash_prepare("two'words")
33
>>> print shell.bash_prepare("two'words")
30
37
return "'" + string.replace("'", r"'\''") + "'"
33
40
"""An object which can run commands
34
This is an "abstract" class, only its subclasses should be used"""
41
This is an "abstract" class, only its subclasses should be used.
35
44
def __init__(self):
39
"""Prepares the shell, may ask user for password if necessary"""
48
"""Prepare the shell, asking user for authentication if necessary"""
42
51
def do(self, command, intrShell=False, cwd=None):
43
"""Runs the command in this shell.
44
If intrShell is True, allows the shell to interpret special characters
46
cwd: the current directory for the command"""
52
"""Run the command in this shell.
55
command -- a list of command arguments
56
intrShell -- if True, allow the shell to interpret special
58
cwd -- the current directory for the command
49
63
def set_out_file(self, outfile):
50
"""Sets the file where stdout output is put"""
64
"""Set the file object where stdout output is put"""
57
71
class RootShell(Shell):
58
72
"""A shell that runs commands as root. It will automatically use
94
108
class BashRootShell(Shell):
95
"""The Shell object which has access to a bash terminal run as root
109
"""The Shell object which has access to a bash terminal run as root.
96
110
It uses pexpect, and it runs sudo bash -i"""
97
112
def __init__(self, prompt="epidermisbash:"):
113
"""Initialise this instance.
116
prompt -- the prompt line of the command line (string)
98
119
Shell.__init__(self)
99
120
self.prompt = prompt
100
121
self.outfile = os.tmpfile()
101
122
self.gksubash, self.gksued = None, None
102
123
self.spawn = None
103
124
self.ready = False
105
125
self.gksubash = handy.get_data_file("gksubash.sh")
106
126
self.gksued = handy.get_data_file("gksued.sh")
107
127
if not os.path.exists(self.gksubash):
110
130
raise(Exception("Cannot find gksued.sh"))
112
132
def prepare(self):
113
"""Initializes the bash shell as root, will ask user for
114
password graphically if necessary
115
Will raise a ShellNotReadyException if it fails to prepare itself
133
"""Initialise the bash shell as root, asking user for
134
password graphically if necessary using gksu.
136
This function raises a ShellNotReadyException if it fails to
116
139
# Unfortunately, due to bug #244930, gksu cannot run bash -i correctly
117
140
# This workaround uses sudo, but still asks for the password
118
141
# graphically, if required
119
# See bug: https://bugs.launchpad.net/ubuntu/+source/gksu/+bug/244930"""
142
# See bug: https://bugs.launchpad.net/ubuntu/+source/gksu/+bug/244930
120
145
self.spawn = pexpect.spawn("sh", [self.gksubash, self.gksued])
121
146
self.spawn.logfile = self.outfile
122
147
res = self.spawn.expect(["EPIDERMIS_PASS", "EPIDERMIS_SUDO_RUN_SUCCESSFULLY", \
171
196
def set_out_file(self, outfile):
172
"""sets where the bash should print to, by default, no where
173
outfile: file like object"""
174
197
if not self.spawn is None:
176
199
self.outfile = outfile
179
202
def do(self, command, intrShell=False, cwd=None, expectStr=None, expectNum=1 ):
181
command: the command string as bash would expect, or a list of command
183
expectStr: the string to stop execution at, if not specified, Shell will
185
cwd: the current directory for the command run
186
expectNum: if expectStr is specified, this number indicates the number
187
of times do must expect expectStr
188
intrShell: if False, do will automatically prepare bash on each of the
189
command's list's items. Currently has no effect if command is str"""
206
command -- a list of command arguments
207
intrShell -- if False, do() will automatically bash_prepare on
208
each of the command's list's items. Currently has
209
no effect if command is str
210
cwd -- the current directory for the command run (string)
211
expectStr -- the string to stop execution at, if not specified, Shell will
213
expectNum -- if expectStr is specified, this number indicates the number
214
of times do() must expect expectStr
191
219
if not self.ready:
192
220
raise(ShellNotReadyException())
247
274
class PolicyKitShell(Shell):
248
275
"""An object which can run commands using a DBus service and
249
PolicyKit authentication"""
276
PolicyKit authentication
250
280
def __init__(self):
251
281
self.ready = False
252
282
self.outFile, self.errFile = None, None
269
299
self.errFile = errfile
271
301
def do(self, command, intrShell=False, cwd=None):
273
command: can only be a list
274
If intrShell is True, allows the shell to interpret special characters
276
cwd: current directory"""
305
command -- can only be a list
306
intrShell -- If intrShell is True, allows the shell to interpret
307
special characters such as *
308
cwd -- current directory (string)
277
311
if not isinstance(command, list):
278
312
raise(Exception("Not list"))
279
313
global DEBUG_SHELL
308
342
self.errFile = sys.stderr
310
344
def prepare(self):
311
"""Prepares the shell"""
345
"""Prepare the shell"""
312
346
self.ready = True
313
347
self.outFile = sys.stdout
314
348
return self.ready
316
350
def do(self, command, intrShell=False, cwd=None):
318
command: can only be a list
319
If intrShell is True, allows the shell to interpret special characters
321
cwd: current directory"""
322
351
if not isinstance(command, list):
323
352
raise(Exception("Not list"))
324
353
global DEBUG_SHELL
348
377
return "Shell has not been prepared"
351
"""A function that tries some of BashRootShell's and PolicyKitShell's
380
"""Test some of BashRootShell's and PolicyKitShell's
353
384
bashShell = BashRootShell()
354
385
bashShell.set_out_file(sys.stdout)
355
386
bashShell.prepare()