1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import os
20 import os.path
21 import sys
22 import socket
23 import errno
24 import signal
25 import select
26 import pwd
27 import commands
28 import binascii
29 import struct
30 import subprocess
31 import tempfile
32 import time
33 import shutil
34 import gobject
35 import gtk
36 import util
37 import usermod
38 import errors
39 from config import *
40 import debuglog
41
44
47
49 pass
50
52 pass
53
55 pass
56
57
58
59
61 assert os.geteuid () == 0
62
63 pw = pwd.getpwnam (username)
64
65 dprint ("Setting shell for '%s' to '%s'", username, DEFAULT_SHELL)
66 usermod.set_shell (username, DEFAULT_SHELL)
67
68
69 for i in range (1,30):
70 temp_homedir = usermod.create_temporary_homedir (pw.pw_uid, pw.pw_gid)
71 dprint ("Setting temporary home directory for '%s' to '%s' attempt %d", username, temp_homedir, i)
72 retval = usermod.set_homedir (username, temp_homedir)
73 dprint ("retval=%d", retval)
74 if retval == 0:
75 break
76 time.sleep(1)
77
78 return temp_homedir
79
93
95 assert os.geteuid () == 0
96
97 pw = pwd.getpwnam (username)
98
99
100 argv = CLOBBER_USER_PROCESSES_ARGV + [ pw.pw_name ]
101 dprint ("Clobbering existing processes running as user '%s': %s", pw.pw_name, argv)
102 subprocess.call (argv)
103
105 def is_display_free (display_number):
106 try:
107 d = gtk.gdk.Display (":%d.0" % display_number)
108 d.close ()
109 return False
110 except RuntimeError, e:
111 return True
112
113 display_number = 1
114 while display_number < 100:
115 if is_display_free (display_number):
116 return display_number
117 display_number += 1
118
119 raise ProtoSessionError, _("Unable to find a free X display")
120
121
122
123
124
126 try:
127 os.kill (pid, sig)
128 except os.error, (err, errstr):
129 if err != errno.ESRCH:
130 raise
131
133 __gsignals__ = {
134 "finished" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ())
135 }
136
137 - def __init__ (self, profile_file, display_number):
138 gobject.GObject.__init__ (self)
139
140 self.xauth_cookie = None
141 self.profile_file = profile_file
142 self.display_number = display_number
143 self.display_name = ":%s" % display_number
144
145 self.usr1_pipe_r = 0
146 self.usr1_pipe_w = 0
147
148 self.xephyr_pid = 0
149 self.xephyr_child_watch = 0
150 self.xephyr_xauth_file = None
151
152 self.session_pid = 0
153 self.session_child_watch = 0
154 self.session_xauth_file = None
155
156 self.admin_tool_timeout = 0
157 self.admin_tool_pid = 0
158 self.admin_tool_child_watch = 0
159
160 self.pw = pwd.getpwuid (os.getuid ())
161
163 if self.xephyr_child_watch:
164 gobject.source_remove (self.xephyr_child_watch)
165 self.xephyr_child_watch = 0
166
167 if self.xephyr_pid:
168 safe_kill (self.xephyr_pid, signal.SIGTERM)
169 self.xephyr_pid = 0
170
172 if self.session_child_watch:
173 gobject.source_remove (self.session_child_watch)
174 self.session_child_watch = 0
175
176 if self.session_pid:
177 safe_kill (self.session_pid, signal.SIGTERM)
178 self.session_pid = 0
179
192
194 if self.xephyr_xauth_file:
195 os.remove (self.xephyr_xauth_file)
196 if self.session_xauth_file:
197 os.remove (self.session_xauth_file)
198 if self.usr1_pipe_r:
199 os.close (self.usr1_pipe_r)
200 if self.usr1_pipe_w:
201 os.close (self.usr1_pipe_w)
202 self.force_quit ()
203
204
205
206
207
208
210 self.got_usr1_signal = True
211 os.write (self.usr1_pipe_w, "Y")
212
214 dprint ("Xephyr died")
215
216 self.xephyr_pid = 0
217 self.xephyr_child_watch = 0
218
219 self.emit ("finished");
220
221 self.force_quit ()
222
223
224 if self.main_loop:
225 self.main_loop.quit ()
226
227 return False
228
230 dprint ("Got USR1 signal, quitting mainloop")
231 self.main_loop.quit ()
232 return True
233
235 dprint ("Timed out waiting for USR1, quitting mainloop")
236 self.main_loop.quit ()
237 return True
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
256 if self.xauth_cookie == None:
257 self.xauth_cookie = util.random_string (16)
258
259 xauth_name = "MIT-MAGIC-COOKIE-1"
260 xauth_data = self.xauth_cookie
261
262 if wildcard_addr:
263 family = 0xffff
264 display_addr = ""
265 else:
266 family = 0x0100
267 display_addr = socket.gethostname ()
268
269 display_num_str = self.display_number
270 display_num_len = len (display_num_str)
271
272 display_addr_len = len (display_addr)
273 xauth_name_len = len (xauth_name)
274 xauth_data_len = len (xauth_data)
275
276 pack_format = ">hh%dsh%dsh%dsh%d" % (display_addr_len, display_num_len, xauth_name_len, xauth_data_len)
277
278 blob = struct.pack (pack_format,
279 family,
280 display_addr_len, display_addr,
281 display_num_len, display_num_str,
282 xauth_name_len, xauth_name,
283 xauth_data_len) + xauth_data
284
285 (fd, temp_xauth_file) = tempfile.mkstemp (prefix = ".xauth-")
286 os.write (fd, blob)
287 os.close (fd)
288
289 dprint ("Wrote temporary xauth file to %s" % temp_xauth_file)
290
291 return temp_xauth_file
292
293
294
295
297 (pipe_r, pipe_w) = os.pipe ()
298 pid = os.fork ()
299 if pid == 0:
300 os.close (pipe_r)
301 new_environ = os.environ.copy ()
302 new_environ["DISPLAY"] = display_name
303 new_environ["XAUTHORITY"] = xauth_file
304 argv = [ "python", "-c",
305 "import gtk, os, sys; os.write (int (sys.argv[1]), 'Y'); gtk.main ()" ,
306 str (pipe_w) ]
307 os.execvpe (argv[0], argv, new_environ)
308 os.close (pipe_w)
309 while True:
310 try:
311 select.select ([pipe_r], [], [])
312 break
313 except select.error, (err, errstr):
314 if err != errno.EINTR:
315 raise
316 os.close (pipe_r)
317
318
319
320
321
322
324 dprint ("Starting Xephyr %s" % self.display_name)
325
326 self.xephyr_xauth_file = self.__write_temp_xauth_file (True)
327
328 (self.usr1_pipe_r, self.usr1_pipe_w) = os.pipe ()
329 self.got_usr1_signal = False
330 signal.signal (signal.SIGUSR1, self.__sigusr1_handler)
331
332 self.xephyr_pid = os.fork ()
333 if self.xephyr_pid == 0:
334 signal.signal (signal.SIGUSR1, signal.SIG_IGN)
335
336 argv = XEPHYR_ARGV + \
337 [ "-auth", self.xephyr_xauth_file ]
338 if parent_window:
339 argv += [ "-parent", parent_window ]
340 argv += [ self.display_name ]
341
342 dprint ("Child process launching %s" % argv)
343
344 os.execv (argv[0], argv)
345
346
347 sys.stderr.write ("Failed to launch Xephyr")
348 os._exit (1)
349
350 self.main_loop = gobject.MainLoop ()
351
352 self.xephyr_child_watch = gobject.child_watch_add (self.xephyr_pid,
353 self.__xephyr_child_watch_handler)
354 io_watch = gobject.io_add_watch (self.usr1_pipe_r,
355 gobject.IO_IN | gobject.IO_PRI,
356 self.__usr1_pipe_watch_handler)
357 timeout = gobject.timeout_add_seconds (XEPHYR_USR1_TIMEOUT,
358 self.__usr1_timeout_handler)
359
360 dprint ("Waiting on child process (%d)" % self.xephyr_pid)
361
362 self.main_loop.run ()
363 self.main_loop = None
364
365 signal.signal (signal.SIGUSR1, signal.SIG_IGN)
366
367 gobject.source_remove (timeout)
368 gobject.source_remove (io_watch)
369
370 os.close (self.usr1_pipe_r)
371 self.usr1_pipe_r = 0
372 os.close (self.usr1_pipe_w)
373 self.usr1_pipe_w = 0
374
375 if not self.got_usr1_signal:
376 if self.xephyr_child_watch:
377 gobject.source_remove (self.xephyr_child_watch)
378 self.xephyr_child_watch = 0
379
380 if self.xephyr_pid:
381 safe_kill (self.xephyr_pid, signal.SIGTERM)
382 self.xephyr_pid = 0
383 raise SessionStartError, _("Failed to start Xephyr: timed out waiting for USR1 signal")
384 else:
385 raise SessionStartError, _("Failed to start Xephyr: died during startup")
386
388 dprint ("Session died")
389
390 self.session_pid = 0
391 self.session_child_watch = 0
392
393 self.force_quit ()
394
395 self.emit ("finished")
396
397 return False
398
400 dprint ("Starting session")
401
402 self.session_xauth_file = self.__write_temp_xauth_file (False)
403
404 self.__open_x_connection (self.display_name, self.session_xauth_file)
405
406 self.session_pid = os.fork ()
407 if self.session_pid == 0:
408 new_environ = os.environ.copy ()
409
410 new_environ["DISPLAY"] = self.display_name
411 new_environ["XAUTHORITY"] = self.session_xauth_file
412
413 self.session_xauth_file = None
414
415
416 new_environ["DISABLE_SABAYON_XINITRC"] = "yes"
417
418
419 new_environ["SABAYON_SESSION_RUNNING"] = "yes"
420
421
422 new_environ["RUNNING_UNDER_GDM"] = "yes"
423
424
425
426
427
428 new_environ["GVFS_DISABLE_FUSE"] = "yes"
429
430 dprint ("Child process env: %s" % new_environ)
431
432
433 dprint ("Executing %s" % SESSION_ARGV)
434 os.execve (SESSION_ARGV[0], SESSION_ARGV, new_environ)
435
436
437 sys.stderr.write ("Failed to launch Xsession")
438 os._exit (1)
439
440 self.session_child_watch = gobject.child_watch_add (self.session_pid,
441 self.__session_child_watch_handler)
442
443
445 argv = APPLY_TOOL_ARGV + [ "-s", self.profile_file,
446 ("--admin-log-config=%s" % util.get_admin_log_config_filename ()),
447 ("--readable-log-config=%s" % util.get_readable_log_config_filename ()) ]
448 mprint ("Running sabayon-apply: %s" % argv)
449
450 try:
451 pipe = subprocess.Popen (argv,
452
453 env = os.environ)
454 except Exception, e:
455 raise errors.FatalApplyErrorException (("Could not create the 'sabayon-apply' process: %s\n" +
456 "The command used is '%s'\n" +
457 "Child traceback:\n%s") %
458 (e.message,
459 " ".join (argv),
460 e.child_traceback))
461
462 return_code = pipe.wait ()
463
464
465
466
467 if return_code == util.EXIT_CODE_NORMAL:
468 mprint ("Finished running sabayon-apply with normal exit status")
469 pass
470 elif return_code == util.EXIT_CODE_RECOVERABLE:
471 mprint ("Finished running sabayon-apply with RECOVERABLE exit status")
472
473
474
475
476 raise errors.RecoverableApplyErrorException (_("There was a recoverable error while applying "
477 "the user profile from file '%s'.") % self.profile_file)
478 else:
479
480 mprint ("Finished running sabayon-apply with FATAL exit status")
481
482
483
484
485 raise errors.FatalApplyErrorException (_("There was a fatal error while applying the "
486 "user profile from '%s'.") % self.profile_file)
487
488 - def start (self, parent_window):
494
498
499 gobject.type_register (ProtoSession)
500