1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- |
---|
2 | * |
---|
3 | * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu> |
---|
4 | * |
---|
5 | * This program is free software; you can redistribute it and/or modify |
---|
6 | * it under the terms of the GNU General Public License as published by |
---|
7 | * the Free Software Foundation; either version 2 of the License, or |
---|
8 | * (at your option) any later version. |
---|
9 | * |
---|
10 | * This program is distributed in the hope that it will be useful, |
---|
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
13 | * GNU General Public License for more details. |
---|
14 | * |
---|
15 | * You should have received a copy of the GNU General Public License |
---|
16 | * along with this program; if not, write to the Free Software |
---|
17 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
---|
18 | * |
---|
19 | */ |
---|
20 | |
---|
21 | #include "config.h" |
---|
22 | |
---|
23 | #include <stdlib.h> |
---|
24 | #include <stdio.h> |
---|
25 | #include <unistd.h> |
---|
26 | #include <errno.h> |
---|
27 | #include <string.h> |
---|
28 | #include <sys/types.h> |
---|
29 | #include <sys/stat.h> |
---|
30 | #include <fcntl.h> |
---|
31 | #include <pwd.h> |
---|
32 | #include <grp.h> |
---|
33 | #include <sys/wait.h> |
---|
34 | #include <locale.h> |
---|
35 | #include <signal.h> |
---|
36 | |
---|
37 | #include <glib.h> |
---|
38 | #include <glib/gi18n.h> |
---|
39 | #include <glib/gstdio.h> |
---|
40 | #include <glib-object.h> |
---|
41 | |
---|
42 | #define DBUS_API_SUBJECT_TO_CHANGE |
---|
43 | #include <dbus/dbus-glib.h> |
---|
44 | #include <dbus/dbus-glib-lowlevel.h> |
---|
45 | |
---|
46 | #include "gdm-manager.h" |
---|
47 | #include "gdm-log.h" |
---|
48 | #include "gdm-common.h" |
---|
49 | #include "gdm-signal-handler.h" |
---|
50 | |
---|
51 | #include "gdm-settings.h" |
---|
52 | #include "gdm-settings-direct.h" |
---|
53 | #include "gdm-settings-keys.h" |
---|
54 | |
---|
55 | #define GDM_DBUS_NAME "org.gnome.DisplayManager" |
---|
56 | |
---|
57 | static void bus_proxy_destroyed_cb (DBusGProxy *bus_proxy, |
---|
58 | GdmManager **managerp); |
---|
59 | |
---|
60 | extern char **environ; |
---|
61 | |
---|
62 | static GdmManager *manager = NULL; |
---|
63 | static GdmSettings *settings = NULL; |
---|
64 | static uid_t gdm_uid = -1; |
---|
65 | static gid_t gdm_gid = -1; |
---|
66 | |
---|
67 | static gboolean |
---|
68 | timed_exit_cb (GMainLoop *loop) |
---|
69 | { |
---|
70 | g_main_loop_quit (loop); |
---|
71 | return FALSE; |
---|
72 | } |
---|
73 | |
---|
74 | static DBusGProxy * |
---|
75 | get_bus_proxy (DBusGConnection *connection) |
---|
76 | { |
---|
77 | DBusGProxy *bus_proxy; |
---|
78 | |
---|
79 | bus_proxy = dbus_g_proxy_new_for_name (connection, |
---|
80 | DBUS_SERVICE_DBUS, |
---|
81 | DBUS_PATH_DBUS, |
---|
82 | DBUS_INTERFACE_DBUS); |
---|
83 | return bus_proxy; |
---|
84 | } |
---|
85 | |
---|
86 | static gboolean |
---|
87 | acquire_name_on_proxy (DBusGProxy *bus_proxy) |
---|
88 | { |
---|
89 | GError *error; |
---|
90 | guint result; |
---|
91 | gboolean res; |
---|
92 | gboolean ret; |
---|
93 | |
---|
94 | ret = FALSE; |
---|
95 | |
---|
96 | if (bus_proxy == NULL) { |
---|
97 | goto out; |
---|
98 | } |
---|
99 | |
---|
100 | error = NULL; |
---|
101 | res = dbus_g_proxy_call (bus_proxy, |
---|
102 | "RequestName", |
---|
103 | &error, |
---|
104 | G_TYPE_STRING, GDM_DBUS_NAME, |
---|
105 | G_TYPE_UINT, 0, |
---|
106 | G_TYPE_INVALID, |
---|
107 | G_TYPE_UINT, &result, |
---|
108 | G_TYPE_INVALID); |
---|
109 | if (! res) { |
---|
110 | if (error != NULL) { |
---|
111 | g_warning ("Failed to acquire %s: %s", GDM_DBUS_NAME, error->message); |
---|
112 | g_error_free (error); |
---|
113 | } else { |
---|
114 | g_warning ("Failed to acquire %s", GDM_DBUS_NAME); |
---|
115 | } |
---|
116 | goto out; |
---|
117 | } |
---|
118 | |
---|
119 | if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { |
---|
120 | if (error != NULL) { |
---|
121 | g_warning ("Failed to acquire %s: %s", GDM_DBUS_NAME, error->message); |
---|
122 | g_error_free (error); |
---|
123 | } else { |
---|
124 | g_warning ("Failed to acquire %s", GDM_DBUS_NAME); |
---|
125 | } |
---|
126 | goto out; |
---|
127 | } |
---|
128 | |
---|
129 | ret = TRUE; |
---|
130 | |
---|
131 | out: |
---|
132 | return ret; |
---|
133 | } |
---|
134 | |
---|
135 | static DBusGConnection * |
---|
136 | get_system_bus (void) |
---|
137 | { |
---|
138 | GError *error; |
---|
139 | DBusGConnection *bus; |
---|
140 | DBusConnection *connection; |
---|
141 | |
---|
142 | error = NULL; |
---|
143 | bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); |
---|
144 | if (bus == NULL) { |
---|
145 | g_warning ("Couldn't connect to system bus: %s", |
---|
146 | error->message); |
---|
147 | g_error_free (error); |
---|
148 | goto out; |
---|
149 | } |
---|
150 | |
---|
151 | connection = dbus_g_connection_get_connection (bus); |
---|
152 | dbus_connection_set_exit_on_disconnect (connection, FALSE); |
---|
153 | |
---|
154 | out: |
---|
155 | return bus; |
---|
156 | } |
---|
157 | |
---|
158 | static gboolean |
---|
159 | bus_reconnect (GdmManager *manager) |
---|
160 | { |
---|
161 | DBusGConnection *bus; |
---|
162 | DBusGProxy *bus_proxy; |
---|
163 | gboolean ret; |
---|
164 | |
---|
165 | ret = TRUE; |
---|
166 | |
---|
167 | bus = get_system_bus (); |
---|
168 | if (bus == NULL) { |
---|
169 | goto out; |
---|
170 | } |
---|
171 | |
---|
172 | bus_proxy = get_bus_proxy (bus); |
---|
173 | if (bus_proxy == NULL) { |
---|
174 | g_warning ("Could not construct bus_proxy object; will retry"); |
---|
175 | goto out; |
---|
176 | } |
---|
177 | |
---|
178 | if (! acquire_name_on_proxy (bus_proxy) ) { |
---|
179 | g_warning ("Could not acquire name; will retry"); |
---|
180 | goto out; |
---|
181 | } |
---|
182 | |
---|
183 | manager = gdm_manager_new (); |
---|
184 | if (manager == NULL) { |
---|
185 | g_warning ("Could not construct manager object"); |
---|
186 | exit (1); |
---|
187 | } |
---|
188 | |
---|
189 | g_signal_connect (bus_proxy, |
---|
190 | "destroy", |
---|
191 | G_CALLBACK (bus_proxy_destroyed_cb), |
---|
192 | &manager); |
---|
193 | |
---|
194 | g_debug ("Successfully reconnected to D-Bus"); |
---|
195 | |
---|
196 | gdm_manager_start (manager); |
---|
197 | |
---|
198 | ret = FALSE; |
---|
199 | |
---|
200 | out: |
---|
201 | return ret; |
---|
202 | } |
---|
203 | |
---|
204 | static void |
---|
205 | bus_proxy_destroyed_cb (DBusGProxy *bus_proxy, |
---|
206 | GdmManager **managerp) |
---|
207 | { |
---|
208 | g_debug ("Disconnected from D-Bus"); |
---|
209 | |
---|
210 | if (managerp == NULL || *managerp == NULL) { |
---|
211 | /* probably shutting down or something */ |
---|
212 | return; |
---|
213 | } |
---|
214 | |
---|
215 | g_object_unref (*managerp); |
---|
216 | *managerp = NULL; |
---|
217 | |
---|
218 | g_timeout_add_seconds (3, (GSourceFunc)bus_reconnect, managerp); |
---|
219 | } |
---|
220 | |
---|
221 | static void |
---|
222 | delete_pid (void) |
---|
223 | { |
---|
224 | g_unlink (GDM_PID_FILE); |
---|
225 | } |
---|
226 | |
---|
227 | static void |
---|
228 | write_pid (void) |
---|
229 | { |
---|
230 | int pf; |
---|
231 | ssize_t written; |
---|
232 | char pid[9]; |
---|
233 | |
---|
234 | errno = 0; |
---|
235 | pf = open (GDM_PID_FILE, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644); |
---|
236 | if (pf < 0) { |
---|
237 | g_warning (_("Cannot write PID file %s: possibly out of diskspace: %s"), |
---|
238 | GDM_PID_FILE, |
---|
239 | g_strerror (errno)); |
---|
240 | |
---|
241 | return; |
---|
242 | } |
---|
243 | |
---|
244 | snprintf (pid, sizeof (pid), "%lu\n", (long unsigned) getpid ()); |
---|
245 | errno = 0; |
---|
246 | written = write (pf, pid, strlen (pid)); |
---|
247 | close (pf); |
---|
248 | |
---|
249 | if (written < 0) { |
---|
250 | g_warning (_("Cannot write PID file %s: possibly out of diskspace: %s"), |
---|
251 | GDM_PID_FILE, |
---|
252 | g_strerror (errno)); |
---|
253 | return; |
---|
254 | } |
---|
255 | |
---|
256 | g_atexit (delete_pid); |
---|
257 | } |
---|
258 | |
---|
259 | static void |
---|
260 | check_logdir (void) |
---|
261 | { |
---|
262 | struct stat statbuf; |
---|
263 | int r; |
---|
264 | const char *log_path; |
---|
265 | |
---|
266 | log_path = LOGDIR; |
---|
267 | |
---|
268 | r = g_stat (log_path, &statbuf); |
---|
269 | if (r < 0 || ! S_ISDIR (statbuf.st_mode)) { |
---|
270 | if (g_mkdir (log_path, 0755) < 0) { |
---|
271 | gdm_fail (_("Logdir %s does not exist or isn't a directory."), |
---|
272 | log_path); |
---|
273 | } |
---|
274 | g_chmod (log_path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); |
---|
275 | } |
---|
276 | } |
---|
277 | |
---|
278 | static void |
---|
279 | check_servauthdir (const char *auth_path, |
---|
280 | struct stat *statbuf) |
---|
281 | { |
---|
282 | int r; |
---|
283 | |
---|
284 | /* Enter paranoia mode */ |
---|
285 | r = g_stat (auth_path, statbuf); |
---|
286 | if (r < 0) { |
---|
287 | gdm_fail (_("Authdir %s does not exist. Aborting."), auth_path); |
---|
288 | } |
---|
289 | |
---|
290 | if (! S_ISDIR (statbuf->st_mode)) { |
---|
291 | gdm_fail (_("Authdir %s is not a directory. Aborting."), auth_path); |
---|
292 | } |
---|
293 | } |
---|
294 | |
---|
295 | static void |
---|
296 | set_effective_user (uid_t uid) |
---|
297 | { |
---|
298 | int res; |
---|
299 | |
---|
300 | res = 0; |
---|
301 | |
---|
302 | if (geteuid () != uid) { |
---|
303 | res = seteuid (uid); |
---|
304 | } |
---|
305 | |
---|
306 | if (res != 0) { |
---|
307 | g_error ("Cannot set uid to %d: %s", |
---|
308 | (int)uid, |
---|
309 | g_strerror (errno)); |
---|
310 | } |
---|
311 | } |
---|
312 | |
---|
313 | static void |
---|
314 | set_effective_group (gid_t gid) |
---|
315 | { |
---|
316 | int res; |
---|
317 | |
---|
318 | res = 0; |
---|
319 | if (getegid () != gid) { |
---|
320 | res = setegid (gid); |
---|
321 | } |
---|
322 | |
---|
323 | if (res != 0) { |
---|
324 | g_error ("Cannot set gid to %d: %s", |
---|
325 | (int)gid, |
---|
326 | g_strerror (errno)); |
---|
327 | } |
---|
328 | } |
---|
329 | |
---|
330 | static void |
---|
331 | set_effective_user_group (uid_t uid, |
---|
332 | gid_t gid) |
---|
333 | { |
---|
334 | set_effective_user (0); |
---|
335 | set_effective_group (gid); |
---|
336 | if (uid != 0) { |
---|
337 | set_effective_user (0); |
---|
338 | } |
---|
339 | } |
---|
340 | |
---|
341 | static void |
---|
342 | gdm_daemon_check_permissions (uid_t uid, |
---|
343 | gid_t gid) |
---|
344 | { |
---|
345 | struct stat statbuf; |
---|
346 | const char *auth_path; |
---|
347 | |
---|
348 | auth_path = LOGDIR; |
---|
349 | |
---|
350 | /* Enter paranoia mode */ |
---|
351 | check_servauthdir (auth_path, &statbuf); |
---|
352 | |
---|
353 | set_effective_user_group (0, 0); |
---|
354 | |
---|
355 | /* Now set things up for us as */ |
---|
356 | chown (auth_path, 0, gid); |
---|
357 | g_chmod (auth_path, (S_IRWXU|S_IRWXG|S_ISVTX)); |
---|
358 | |
---|
359 | set_effective_user_group (uid, gid); |
---|
360 | |
---|
361 | /* Again paranoid */ |
---|
362 | check_servauthdir (auth_path, &statbuf); |
---|
363 | |
---|
364 | if G_UNLIKELY (statbuf.st_uid != 0 || statbuf.st_gid != gid) { |
---|
365 | gdm_fail (_("Authdir %s is not owned by user %d, group %d. Aborting."), |
---|
366 | auth_path, |
---|
367 | (int)uid, |
---|
368 | (int)gid); |
---|
369 | } |
---|
370 | |
---|
371 | if G_UNLIKELY (statbuf.st_mode != (S_IFDIR|S_IRWXU|S_IRWXG|S_ISVTX)) { |
---|
372 | gdm_fail (_("Authdir %s has wrong permissions %o. Should be %o. Aborting."), |
---|
373 | auth_path, |
---|
374 | statbuf.st_mode, |
---|
375 | (S_IRWXU|S_IRWXG|S_ISVTX)); |
---|
376 | } |
---|
377 | } |
---|
378 | |
---|
379 | static void |
---|
380 | gdm_daemon_change_user (uid_t *uidp, |
---|
381 | gid_t *gidp) |
---|
382 | { |
---|
383 | char *username; |
---|
384 | char *groupname; |
---|
385 | uid_t uid; |
---|
386 | gid_t gid; |
---|
387 | struct passwd *pwent; |
---|
388 | struct group *grent; |
---|
389 | |
---|
390 | username = NULL; |
---|
391 | groupname = NULL; |
---|
392 | uid = 0; |
---|
393 | gid = 0; |
---|
394 | |
---|
395 | gdm_settings_direct_get_string (GDM_KEY_USER, &username); |
---|
396 | gdm_settings_direct_get_string (GDM_KEY_GROUP, &groupname); |
---|
397 | |
---|
398 | if (username == NULL || groupname == NULL) { |
---|
399 | return; |
---|
400 | } |
---|
401 | |
---|
402 | g_debug ("Changing user:group to %s:%s", username, groupname); |
---|
403 | |
---|
404 | /* Lookup user and groupid for the GDM user */ |
---|
405 | pwent = getpwnam (username); |
---|
406 | |
---|
407 | /* Set uid and gid */ |
---|
408 | if G_UNLIKELY (pwent == NULL) { |
---|
409 | gdm_fail (_("Can't find the GDM user '%s'. Aborting!"), username); |
---|
410 | } else { |
---|
411 | uid = pwent->pw_uid; |
---|
412 | } |
---|
413 | |
---|
414 | if G_UNLIKELY (uid == 0) { |
---|
415 | gdm_fail (_("The GDM user should not be root. Aborting!")); |
---|
416 | } |
---|
417 | |
---|
418 | grent = getgrnam (groupname); |
---|
419 | |
---|
420 | if G_UNLIKELY (grent == NULL) { |
---|
421 | gdm_fail (_("Can't find the GDM group '%s'. Aborting!"), groupname); |
---|
422 | } else { |
---|
423 | gid = grent->gr_gid; |
---|
424 | } |
---|
425 | |
---|
426 | if G_UNLIKELY (gid == 0) { |
---|
427 | gdm_fail (_("The GDM group should not be root. Aborting!")); |
---|
428 | } |
---|
429 | |
---|
430 | /* gid remains 'gdm' */ |
---|
431 | set_effective_user_group (uid, gid); |
---|
432 | |
---|
433 | if (uidp != NULL) { |
---|
434 | *uidp = uid; |
---|
435 | } |
---|
436 | |
---|
437 | if (gidp != NULL) { |
---|
438 | *gidp = gid; |
---|
439 | } |
---|
440 | |
---|
441 | g_free (username); |
---|
442 | g_free (groupname); |
---|
443 | } |
---|
444 | |
---|
445 | static gboolean |
---|
446 | signal_cb (int signo, |
---|
447 | gpointer data) |
---|
448 | { |
---|
449 | int ret; |
---|
450 | |
---|
451 | g_debug ("Got callback for signal %d", signo); |
---|
452 | |
---|
453 | ret = TRUE; |
---|
454 | |
---|
455 | switch (signo) { |
---|
456 | case SIGFPE: |
---|
457 | case SIGPIPE: |
---|
458 | /* let the fatal signals interrupt us */ |
---|
459 | g_debug ("Caught signal %d, shutting down abnormally.", signo); |
---|
460 | ret = FALSE; |
---|
461 | |
---|
462 | break; |
---|
463 | |
---|
464 | case SIGINT: |
---|
465 | case SIGTERM: |
---|
466 | /* let the fatal signals interrupt us */ |
---|
467 | g_debug ("Caught signal %d, shutting down normally.", signo); |
---|
468 | ret = FALSE; |
---|
469 | |
---|
470 | break; |
---|
471 | |
---|
472 | case SIGHUP: |
---|
473 | g_debug ("Got HUP signal"); |
---|
474 | /* FIXME: |
---|
475 | * Reread config stuff like system config files, VPN service files, etc |
---|
476 | */ |
---|
477 | ret = TRUE; |
---|
478 | |
---|
479 | break; |
---|
480 | |
---|
481 | case SIGUSR1: |
---|
482 | g_debug ("Got USR1 signal"); |
---|
483 | /* FIXME: |
---|
484 | * Play with log levels or something |
---|
485 | */ |
---|
486 | ret = TRUE; |
---|
487 | |
---|
488 | gdm_log_toggle_debug (); |
---|
489 | |
---|
490 | break; |
---|
491 | |
---|
492 | default: |
---|
493 | g_debug ("Caught unhandled signal %d", signo); |
---|
494 | ret = TRUE; |
---|
495 | |
---|
496 | break; |
---|
497 | } |
---|
498 | |
---|
499 | return ret; |
---|
500 | } |
---|
501 | |
---|
502 | int |
---|
503 | main (int argc, |
---|
504 | char **argv) |
---|
505 | { |
---|
506 | GMainLoop *main_loop; |
---|
507 | GOptionContext *context; |
---|
508 | DBusGProxy *bus_proxy; |
---|
509 | DBusGConnection *connection; |
---|
510 | GError *error; |
---|
511 | int ret; |
---|
512 | gboolean res; |
---|
513 | gboolean xdmcp_enabled; |
---|
514 | GdmSignalHandler *signal_handler; |
---|
515 | static gboolean debug = FALSE; |
---|
516 | static gboolean do_timed_exit = FALSE; |
---|
517 | static gboolean print_version = FALSE; |
---|
518 | static gboolean fatal_warnings = FALSE; |
---|
519 | static GOptionEntry entries [] = { |
---|
520 | { "debug", 0, 0, G_OPTION_ARG_NONE, &debug, N_("Enable debugging code"), NULL }, |
---|
521 | { "fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &fatal_warnings, N_("Make all warnings fatal"), NULL }, |
---|
522 | { "timed-exit", 0, 0, G_OPTION_ARG_NONE, &do_timed_exit, N_("Exit after a time - for debugging"), NULL }, |
---|
523 | { "version", 0, 0, G_OPTION_ARG_NONE, &print_version, N_("Print GDM version"), NULL }, |
---|
524 | |
---|
525 | { NULL } |
---|
526 | }; |
---|
527 | |
---|
528 | bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); |
---|
529 | textdomain (GETTEXT_PACKAGE); |
---|
530 | setlocale (LC_ALL, ""); |
---|
531 | |
---|
532 | ret = 1; |
---|
533 | |
---|
534 | gdm_set_fatal_warnings_if_unstable (); |
---|
535 | |
---|
536 | g_type_init (); |
---|
537 | |
---|
538 | context = g_option_context_new (_("GNOME Display Manager")); |
---|
539 | g_option_context_add_main_entries (context, entries, NULL); |
---|
540 | g_option_context_set_ignore_unknown_options (context, TRUE); |
---|
541 | |
---|
542 | error = NULL; |
---|
543 | res = g_option_context_parse (context, &argc, &argv, &error); |
---|
544 | g_option_context_free (context); |
---|
545 | if (! res) { |
---|
546 | g_warning ("%s", error->message); |
---|
547 | g_error_free (error); |
---|
548 | goto out; |
---|
549 | } |
---|
550 | |
---|
551 | if (fatal_warnings) { |
---|
552 | GLogLevelFlags fatal_mask; |
---|
553 | |
---|
554 | fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK); |
---|
555 | fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL; |
---|
556 | g_log_set_always_fatal (fatal_mask); |
---|
557 | } |
---|
558 | |
---|
559 | connection = get_system_bus (); |
---|
560 | if (connection == NULL) { |
---|
561 | goto out; |
---|
562 | } |
---|
563 | |
---|
564 | bus_proxy = get_bus_proxy (connection); |
---|
565 | if (bus_proxy == NULL) { |
---|
566 | g_warning ("Could not construct bus_proxy object; bailing out"); |
---|
567 | goto out; |
---|
568 | } |
---|
569 | |
---|
570 | if (! acquire_name_on_proxy (bus_proxy) ) { |
---|
571 | g_warning ("Could not acquire name; bailing out"); |
---|
572 | goto out; |
---|
573 | } |
---|
574 | |
---|
575 | gdm_log_init (); |
---|
576 | |
---|
577 | settings = gdm_settings_new (); |
---|
578 | if (settings == NULL) { |
---|
579 | g_warning ("Unable to initialize settings"); |
---|
580 | goto out; |
---|
581 | } |
---|
582 | |
---|
583 | if (! gdm_settings_direct_init (settings, GDMCONFDIR "/gdm.schemas", "/")) { |
---|
584 | g_warning ("Unable to initialize settings"); |
---|
585 | goto out; |
---|
586 | } |
---|
587 | |
---|
588 | gdm_log_set_debug (debug); |
---|
589 | |
---|
590 | gdm_daemon_change_user (&gdm_uid, &gdm_gid); |
---|
591 | gdm_daemon_check_permissions (gdm_uid, gdm_gid); |
---|
592 | |
---|
593 | set_effective_user_group (0, 0); |
---|
594 | check_logdir (); |
---|
595 | |
---|
596 | /* XDM compliant error message */ |
---|
597 | if (getuid () != 0) { |
---|
598 | /* make sure the pid file doesn't get wiped */ |
---|
599 | g_warning (_("Only root wants to run GDM")); |
---|
600 | exit (-1); |
---|
601 | } |
---|
602 | |
---|
603 | /* pid file */ |
---|
604 | delete_pid (); |
---|
605 | write_pid (); |
---|
606 | |
---|
607 | g_chdir (AUTHDIR); |
---|
608 | |
---|
609 | manager = gdm_manager_new (); |
---|
610 | |
---|
611 | if (manager == NULL) { |
---|
612 | goto out; |
---|
613 | } |
---|
614 | |
---|
615 | xdmcp_enabled = FALSE; |
---|
616 | gdm_settings_direct_get_boolean (GDM_KEY_XDMCP_ENABLE, &xdmcp_enabled); |
---|
617 | gdm_manager_set_xdmcp_enabled (manager, xdmcp_enabled); |
---|
618 | |
---|
619 | g_signal_connect (bus_proxy, |
---|
620 | "destroy", |
---|
621 | G_CALLBACK (bus_proxy_destroyed_cb), |
---|
622 | &manager); |
---|
623 | |
---|
624 | main_loop = g_main_loop_new (NULL, FALSE); |
---|
625 | |
---|
626 | signal_handler = gdm_signal_handler_new (); |
---|
627 | gdm_signal_handler_set_fatal_func (signal_handler, |
---|
628 | (GDestroyNotify)g_main_loop_quit, |
---|
629 | main_loop); |
---|
630 | gdm_signal_handler_add_fatal (signal_handler); |
---|
631 | gdm_signal_handler_add (signal_handler, SIGTERM, signal_cb, NULL); |
---|
632 | gdm_signal_handler_add (signal_handler, SIGINT, signal_cb, NULL); |
---|
633 | gdm_signal_handler_add (signal_handler, SIGFPE, signal_cb, NULL); |
---|
634 | gdm_signal_handler_add (signal_handler, SIGHUP, signal_cb, NULL); |
---|
635 | gdm_signal_handler_add (signal_handler, SIGUSR1, signal_cb, NULL); |
---|
636 | |
---|
637 | if (do_timed_exit) { |
---|
638 | g_timeout_add_seconds (30, (GSourceFunc) timed_exit_cb, main_loop); |
---|
639 | } |
---|
640 | |
---|
641 | gdm_manager_start (manager); |
---|
642 | |
---|
643 | g_main_loop_run (main_loop); |
---|
644 | |
---|
645 | g_debug ("GDM finished, cleaning up..."); |
---|
646 | |
---|
647 | if (manager != NULL) { |
---|
648 | g_object_unref (manager); |
---|
649 | } |
---|
650 | |
---|
651 | if (settings != NULL) { |
---|
652 | g_object_unref (settings); |
---|
653 | } |
---|
654 | |
---|
655 | if (signal_handler != NULL) { |
---|
656 | g_object_unref (signal_handler); |
---|
657 | } |
---|
658 | |
---|
659 | gdm_settings_direct_shutdown (); |
---|
660 | gdm_log_shutdown (); |
---|
661 | |
---|
662 | g_main_loop_unref (main_loop); |
---|
663 | |
---|
664 | ret = 0; |
---|
665 | |
---|
666 | out: |
---|
667 | |
---|
668 | return ret; |
---|
669 | } |
---|