~ubuntu-branches/ubuntu/trusty/gdm/trusty-proposed

« back to all changes in this revision

Viewing changes to .pc/ubuntu_daemon_autologin_tracking.patch/daemon/main.c

  • Committer: Package Import Robot
  • Author(s): Jeremy Bicha, Tim Lunn, Jeremy Bicha, Robert Ancell
  • Date: 2013-05-31 22:36:08 UTC
  • mfrom: (1.4.55)
  • Revision ID: package-import@ubuntu.com-20130531223608-33uo85niksee5460
Tags: 3.8.1.1-0ubuntu1
[ Tim Lunn ]
* New upstream release
* debian/patches/ubuntu_dont_catch_sigsegv.patch:
  - Dropped, obsolete
* debian/rules:
  - Don't rename gdm binary since that's already been
    done in the new version

[ Jeremy Bicha ]
* debian/control.in: Bump minimum glib
* debian/watch: Watch for unstable releases
* debian/patches/00git_logind_check.patch:
  - Dropped, applied in new release
* debian/patches/08_frequent-users_greeter.patch: Refreshed

[ Robert Ancell ]
* New upstream release
* debian/patches/ubuntu_daemon_autologin_tracking.patch:
* debian/patches/ubuntu_ensure_dirs.patch:
* debian/patches/ubuntu_slave-only-set-up-autologin.patch:
  - Applied upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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
 
#include <gio/gio.h>
42
 
 
43
 
#include "gdm-manager.h"
44
 
#include "gdm-log.h"
45
 
#include "gdm-common.h"
46
 
#include "gdm-signal-handler.h"
47
 
 
48
 
#include "gdm-settings.h"
49
 
#include "gdm-settings-direct.h"
50
 
#include "gdm-settings-keys.h"
51
 
 
52
 
#define GDM_DBUS_NAME "org.gnome.DisplayManager"
53
 
 
54
 
static GDBusConnection *get_system_bus (void);
55
 
static gboolean         bus_reconnect (void);
56
 
 
57
 
extern char **environ;
58
 
 
59
 
static GdmManager      *manager       = NULL;
60
 
static int              name_id       = -1;
61
 
static GdmSettings     *settings      = NULL;
62
 
static uid_t            gdm_uid       = -1;
63
 
static gid_t            gdm_gid       = -1;
64
 
 
65
 
static gboolean
66
 
timed_exit_cb (GMainLoop *loop)
67
 
{
68
 
        g_main_loop_quit (loop);
69
 
        return FALSE;
70
 
}
71
 
 
72
 
static void
73
 
bus_connection_closed (void)
74
 
{
75
 
        g_debug ("Disconnected from D-Bus");
76
 
 
77
 
        if (manager == NULL) {
78
 
                /* probably shutting down or something */
79
 
                return;
80
 
        }
81
 
 
82
 
        g_clear_object (&manager);
83
 
 
84
 
        g_timeout_add_seconds (3, (GSourceFunc)bus_reconnect, NULL);
85
 
}
86
 
 
87
 
static GDBusConnection *
88
 
get_system_bus (void)
89
 
{
90
 
        GError          *error;
91
 
        GDBusConnection *bus;
92
 
 
93
 
        error = NULL;
94
 
        bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
95
 
        if (bus == NULL) {
96
 
                g_warning ("Couldn't connect to system bus: %s",
97
 
                           error->message);
98
 
                g_error_free (error);
99
 
                goto out;
100
 
        }
101
 
 
102
 
        g_signal_connect (bus, "closed",
103
 
                          G_CALLBACK (bus_connection_closed), NULL);
104
 
        g_dbus_connection_set_exit_on_close (bus, FALSE);
105
 
 
106
 
 out:
107
 
        return bus;
108
 
}
109
 
 
110
 
static void
111
 
delete_pid (void)
112
 
{
113
 
        g_unlink (GDM_PID_FILE);
114
 
}
115
 
 
116
 
static void
117
 
write_pid (void)
118
 
{
119
 
        int     pf;
120
 
        ssize_t written;
121
 
        char    pid[9];
122
 
 
123
 
        errno = 0;
124
 
        pf = open (GDM_PID_FILE, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644);
125
 
        if (pf < 0) {
126
 
                g_warning (_("Cannot write PID file %s: possibly out of disk space: %s"),
127
 
                           GDM_PID_FILE,
128
 
                           g_strerror (errno));
129
 
 
130
 
                return;
131
 
        }
132
 
 
133
 
        snprintf (pid, sizeof (pid), "%lu\n", (long unsigned) getpid ());
134
 
        errno = 0;
135
 
        written = write (pf, pid, strlen (pid));
136
 
        close (pf);
137
 
 
138
 
        if (written < 0) {
139
 
                g_warning (_("Cannot write PID file %s: possibly out of disk space: %s"),
140
 
                           GDM_PID_FILE,
141
 
                           g_strerror (errno));
142
 
                return;
143
 
        }
144
 
 
145
 
        atexit (delete_pid);
146
 
}
147
 
 
148
 
static gboolean
149
 
ensure_dir_with_perms (const char *path,
150
 
                       uid_t       uid,
151
 
                       gid_t       gid,
152
 
                       mode_t      mode,
153
 
                       GError    **error)
154
 
{
155
 
        gboolean ret = FALSE;
156
 
 
157
 
        if (g_mkdir_with_parents (path, 0755) == -1) {
158
 
                g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (errno), g_strerror (errno));
159
 
                goto out;
160
 
        }
161
 
        if (g_chmod (path, mode) == -1) {
162
 
                g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (errno), g_strerror (errno));
163
 
                goto out;
164
 
        }
165
 
        if (chown (path, uid, gid) == -1) {
166
 
                g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (errno), g_strerror (errno));
167
 
                goto out;
168
 
        }
169
 
 
170
 
        ret = TRUE;
171
 
 out:
172
 
        return ret;
173
 
}
174
 
 
175
 
static void
176
 
gdm_daemon_ensure_dirs (uid_t uid,
177
 
                        gid_t gid)
178
 
{
179
 
        GError *error = NULL;
180
 
 
181
 
        /* Set up /var/gdm */
182
 
        if (!ensure_dir_with_perms (AUTHDIR, uid, gid, (S_IRWXU | S_IRWXG | S_ISVTX), &error)) {
183
 
                gdm_fail (_("Failed to create AuthDir %s: %s"),
184
 
                          AUTHDIR, error->message);
185
 
        }
186
 
 
187
 
        /* Set up /var/log/gdm */
188
 
        if (!ensure_dir_with_perms (LOGDIR, 0, gid, (S_IRWXU | S_IRWXG | S_ISVTX), &error)) {
189
 
                gdm_fail (_("Failed to create LogDir %s: %s"),
190
 
                          LOGDIR, error->message);
191
 
        }
192
 
}
193
 
 
194
 
static void
195
 
gdm_daemon_lookup_user (uid_t *uidp,
196
 
                        gid_t *gidp)
197
 
{
198
 
        char          *username;
199
 
        char          *groupname;
200
 
        uid_t          uid;
201
 
        gid_t          gid;
202
 
        struct passwd *pwent;
203
 
        struct group  *grent;
204
 
 
205
 
        username = NULL;
206
 
        groupname = NULL;
207
 
        uid = 0;
208
 
        gid = 0;
209
 
 
210
 
        gdm_settings_direct_get_string (GDM_KEY_USER, &username);
211
 
        gdm_settings_direct_get_string (GDM_KEY_GROUP, &groupname);
212
 
 
213
 
        if (username == NULL || groupname == NULL) {
214
 
                return;
215
 
        }
216
 
 
217
 
        g_debug ("Changing user:group to %s:%s", username, groupname);
218
 
 
219
 
        /* Lookup user and groupid for the GDM user */
220
 
        gdm_get_pwent_for_name (username, &pwent);
221
 
 
222
 
        /* Set uid and gid */
223
 
        if G_UNLIKELY (pwent == NULL) {
224
 
                gdm_fail (_("Can't find the GDM user '%s'. Aborting!"), username);
225
 
        } else {
226
 
                uid = pwent->pw_uid;
227
 
        }
228
 
 
229
 
        if G_UNLIKELY (uid == 0) {
230
 
                gdm_fail (_("The GDM user should not be root. Aborting!"));
231
 
        }
232
 
 
233
 
        grent = getgrnam (groupname);
234
 
 
235
 
        if G_UNLIKELY (grent == NULL) {
236
 
                gdm_fail (_("Can't find the GDM group '%s'. Aborting!"), groupname);
237
 
        } else  {
238
 
                gid = grent->gr_gid;
239
 
        }
240
 
 
241
 
        if G_UNLIKELY (gid == 0) {
242
 
                gdm_fail (_("The GDM group should not be root. Aborting!"));
243
 
        }
244
 
 
245
 
        if (uidp != NULL) {
246
 
                *uidp = uid;
247
 
        }
248
 
 
249
 
        if (gidp != NULL) {
250
 
                *gidp = gid;
251
 
        }
252
 
 
253
 
        g_free (username);
254
 
        g_free (groupname);
255
 
}
256
 
 
257
 
static gboolean
258
 
signal_cb (int      signo,
259
 
           gpointer data)
260
 
{
261
 
        int ret;
262
 
 
263
 
        g_debug ("Got callback for signal %d", signo);
264
 
 
265
 
        ret = TRUE;
266
 
 
267
 
        switch (signo) {
268
 
        case SIGFPE:
269
 
        case SIGPIPE:
270
 
                /* let the fatal signals interrupt us */
271
 
                g_debug ("Caught signal %d, shutting down abnormally.", signo);
272
 
                ret = FALSE;
273
 
 
274
 
                break;
275
 
 
276
 
        case SIGINT:
277
 
        case SIGTERM:
278
 
                /* let the fatal signals interrupt us */
279
 
                g_debug ("Caught signal %d, shutting down normally.", signo);
280
 
                ret = FALSE;
281
 
 
282
 
                break;
283
 
 
284
 
        case SIGHUP:
285
 
                g_debug ("Got HUP signal");
286
 
                /* Reread config stuff like system config files, VPN service
287
 
                 * files, etc
288
 
                 */
289
 
                g_object_unref (settings);
290
 
                settings = gdm_settings_new ();
291
 
                if (settings != NULL) {
292
 
                        if (! gdm_settings_direct_init (settings, DATADIR "/gdm/gdm.schemas", "/")) {
293
 
                                g_warning ("Unable to initialize settings");
294
 
                        }
295
 
                }
296
 
 
297
 
                ret = TRUE;
298
 
 
299
 
                break;
300
 
 
301
 
        case SIGUSR1:
302
 
                g_debug ("Got USR1 signal");
303
 
                /* FIXME:
304
 
                 * Play with log levels or something
305
 
                 */
306
 
                ret = TRUE;
307
 
 
308
 
                gdm_log_toggle_debug ();
309
 
 
310
 
                break;
311
 
 
312
 
        default:
313
 
                g_debug ("Caught unhandled signal %d", signo);
314
 
                ret = TRUE;
315
 
 
316
 
                break;
317
 
        }
318
 
 
319
 
        return ret;
320
 
}
321
 
 
322
 
static gboolean
323
 
is_debug_set (void)
324
 
{
325
 
        gboolean debug = FALSE;
326
 
 
327
 
        /* enable debugging for unstable builds */
328
 
        if (gdm_is_version_unstable ()) {
329
 
                return TRUE;
330
 
        }
331
 
 
332
 
        gdm_settings_direct_get_boolean (GDM_KEY_DEBUG, &debug);
333
 
        return debug;
334
 
}
335
 
 
336
 
int
337
 
main (int    argc,
338
 
      char **argv)
339
 
{
340
 
        GMainLoop          *main_loop;
341
 
        GOptionContext     *context;
342
 
        GError             *error = NULL;
343
 
        int                 ret;
344
 
        gboolean            res;
345
 
        GdmSignalHandler   *signal_handler;
346
 
        static gboolean     do_timed_exit    = FALSE;
347
 
        static gboolean     print_version    = FALSE;
348
 
        static gboolean     fatal_warnings   = FALSE;
349
 
        static GOptionEntry entries []   = {
350
 
                { "fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &fatal_warnings, N_("Make all warnings fatal"), NULL },
351
 
                { "timed-exit", 0, 0, G_OPTION_ARG_NONE, &do_timed_exit, N_("Exit after a time (for debugging)"), NULL },
352
 
                { "version", 0, 0, G_OPTION_ARG_NONE, &print_version, N_("Print GDM version"), NULL },
353
 
 
354
 
                { NULL }
355
 
        };
356
 
 
357
 
        bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
358
 
        textdomain (GETTEXT_PACKAGE);
359
 
        setlocale (LC_ALL, "");
360
 
 
361
 
        ret = 1;
362
 
 
363
 
        g_type_init ();
364
 
 
365
 
        context = g_option_context_new (_("GNOME Display Manager"));
366
 
        g_option_context_add_main_entries (context, entries, NULL);
367
 
        g_option_context_set_ignore_unknown_options (context, TRUE);
368
 
 
369
 
        error = NULL;
370
 
        res = g_option_context_parse (context, &argc, &argv, &error);
371
 
        g_option_context_free (context);
372
 
        if (! res) {
373
 
                g_warning ("%s", error->message);
374
 
                g_error_free (error);
375
 
                goto out;
376
 
        }
377
 
 
378
 
        if (print_version) {
379
 
                g_print ("GDM %s\n", VERSION);
380
 
                exit (1);
381
 
        }
382
 
 
383
 
        if (fatal_warnings) {
384
 
                GLogLevelFlags fatal_mask;
385
 
 
386
 
                fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
387
 
                fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
388
 
                g_log_set_always_fatal (fatal_mask);
389
 
        }
390
 
 
391
 
        gdm_log_init ();
392
 
 
393
 
        settings = gdm_settings_new ();
394
 
        if (settings == NULL) {
395
 
                g_warning ("Unable to initialize settings");
396
 
                goto out;
397
 
        }
398
 
 
399
 
        if (! gdm_settings_direct_init (settings, DATADIR "/gdm/gdm.schemas", "/")) {
400
 
                g_warning ("Unable to initialize settings");
401
 
                goto out;
402
 
        }
403
 
 
404
 
        gdm_log_set_debug (is_debug_set ());
405
 
 
406
 
        gdm_daemon_lookup_user (&gdm_uid, &gdm_gid);
407
 
 
408
 
        gdm_daemon_ensure_dirs (gdm_uid, gdm_gid);
409
 
 
410
 
        /* XDM compliant error message */
411
 
        if (getuid () != 0) {
412
 
                /* make sure the pid file doesn't get wiped */
413
 
                g_warning (_("Only the root user can run GDM"));
414
 
                exit (-1);
415
 
        }
416
 
 
417
 
        /* Connect to the bus, own the name and start the manager */
418
 
        bus_reconnect ();
419
 
 
420
 
        /* pid file */
421
 
        delete_pid ();
422
 
        write_pid ();
423
 
 
424
 
        g_chdir (AUTHDIR);
425
 
 
426
 
        main_loop = g_main_loop_new (NULL, FALSE);
427
 
 
428
 
        signal_handler = gdm_signal_handler_new ();
429
 
        gdm_signal_handler_set_fatal_func (signal_handler,
430
 
                                           (GDestroyNotify)g_main_loop_quit,
431
 
                                           main_loop);
432
 
        gdm_signal_handler_add_fatal (signal_handler);
433
 
        gdm_signal_handler_add (signal_handler, SIGTERM, signal_cb, NULL);
434
 
        gdm_signal_handler_add (signal_handler, SIGINT, signal_cb, NULL);
435
 
        gdm_signal_handler_add (signal_handler, SIGFPE, signal_cb, NULL);
436
 
        gdm_signal_handler_add (signal_handler, SIGHUP, signal_cb, NULL);
437
 
        gdm_signal_handler_add (signal_handler, SIGUSR1, signal_cb, NULL);
438
 
 
439
 
        if (do_timed_exit) {
440
 
                g_timeout_add_seconds (30, (GSourceFunc) timed_exit_cb, main_loop);
441
 
        }
442
 
 
443
 
        g_main_loop_run (main_loop);
444
 
 
445
 
        g_debug ("GDM finished, cleaning up...");
446
 
 
447
 
        g_clear_object (&manager);
448
 
        g_clear_object (&settings);
449
 
        g_clear_object (&signal_handler);
450
 
 
451
 
        gdm_settings_direct_shutdown ();
452
 
        gdm_log_shutdown ();
453
 
 
454
 
        g_main_loop_unref (main_loop);
455
 
 
456
 
        ret = 0;
457
 
 
458
 
 out:
459
 
        if (error) {
460
 
                g_printerr ("%s\n", error->message);
461
 
                g_clear_error (&error);
462
 
        }
463
 
        return ret;
464
 
}
465
 
 
466
 
static void
467
 
on_name_acquired (GDBusConnection *bus,
468
 
                  const char      *name,
469
 
                  gpointer         user_data)
470
 
{
471
 
        gboolean xdmcp_enabled;
472
 
        gboolean show_local_greeter;
473
 
 
474
 
        manager = gdm_manager_new ();
475
 
        if (manager == NULL) {
476
 
                g_warning ("Could not construct manager object");
477
 
                exit (1);
478
 
        }
479
 
 
480
 
        g_debug ("Successfully connected to D-Bus");
481
 
 
482
 
        gdm_manager_start (manager);
483
 
 
484
 
        show_local_greeter = TRUE;
485
 
        gdm_settings_direct_get_boolean (GDM_KEY_SHOW_LOCAL_GREETER, &show_local_greeter);
486
 
        gdm_manager_set_show_local_greeter (manager, show_local_greeter);
487
 
 
488
 
        xdmcp_enabled = FALSE;
489
 
        gdm_settings_direct_get_boolean (GDM_KEY_XDMCP_ENABLE, &xdmcp_enabled);
490
 
        gdm_manager_set_xdmcp_enabled (manager, xdmcp_enabled);
491
 
}
492
 
 
493
 
static void
494
 
on_name_lost (GDBusConnection *bus,
495
 
              const char      *name,
496
 
              gpointer         user_data)
497
 
{
498
 
        g_debug ("Lost GDM name on bus");
499
 
 
500
 
        bus_connection_closed ();
501
 
}
502
 
 
503
 
static gboolean
504
 
bus_reconnect ()
505
 
{
506
 
        GDBusConnection *bus;
507
 
        gboolean         ret;
508
 
 
509
 
        ret = TRUE;
510
 
 
511
 
        bus = get_system_bus ();
512
 
        if (bus == NULL) {
513
 
                goto out;
514
 
        }
515
 
 
516
 
        name_id = g_bus_own_name_on_connection (bus,
517
 
                                                GDM_DBUS_NAME,
518
 
                                                G_BUS_NAME_OWNER_FLAGS_NONE,
519
 
                                                on_name_acquired,
520
 
                                                on_name_lost,
521
 
                                                NULL,
522
 
                                                NULL);
523
 
 
524
 
        ret = FALSE;
525
 
 out:
526
 
        return ret;
527
 
}