~ubuntu-branches/ubuntu/raring/consolekit/raring

« back to all changes in this revision

Viewing changes to .pc/03-cleanup_console_tags.patch/src/main.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2010-11-20 18:17:28 UTC
  • mfrom: (0.1.16 sid)
  • Revision ID: james.westby@ubuntu.com-20101120181728-8e5bwe4ttgmk4j41
Tags: 0.4.3-2
Add 01-retry-console-open-on-EIO.patch: As reported in LP: #544139,
ConsoleKit sometimes fails to track the active VT. This particular case
was tracked down to a race condition that happens if you try to open
/dev/console while the current TTY is currently being closed. This yields
an -EIO error, in which case CK should just try again. Thanks Colin Watson
for the patch!

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) 2006-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 <signal.h>
 
27
#include <errno.h>
 
28
#include <string.h>
 
29
#include <sys/types.h>
 
30
#include <sys/stat.h>
 
31
#include <fcntl.h>
 
32
 
 
33
#include <glib.h>
 
34
#include <glib/gi18n.h>
 
35
#include <glib-object.h>
 
36
 
 
37
#include <dbus/dbus-glib.h>
 
38
#include <dbus/dbus-glib-lowlevel.h>
 
39
 
 
40
#include "ck-sysdeps.h"
 
41
#include "ck-manager.h"
 
42
#include "ck-log.h"
 
43
 
 
44
#define CK_DBUS_NAME         "org.freedesktop.ConsoleKit"
 
45
 
 
46
static gboolean
 
47
timed_exit_cb (GMainLoop *loop)
 
48
{
 
49
        g_main_loop_quit (loop);
 
50
        return FALSE;
 
51
}
 
52
 
 
53
static DBusGProxy *
 
54
get_bus_proxy (DBusGConnection *connection)
 
55
{
 
56
        DBusGProxy *bus_proxy;
 
57
 
 
58
        bus_proxy = dbus_g_proxy_new_for_name (connection,
 
59
                                               DBUS_SERVICE_DBUS,
 
60
                                               DBUS_PATH_DBUS,
 
61
                                               DBUS_INTERFACE_DBUS);
 
62
        return bus_proxy;
 
63
}
 
64
 
 
65
static gboolean
 
66
acquire_name_on_proxy (DBusGProxy *bus_proxy)
 
67
{
 
68
        GError     *error;
 
69
        guint       result;
 
70
        gboolean    res;
 
71
        gboolean    ret;
 
72
 
 
73
        ret = FALSE;
 
74
 
 
75
        if (bus_proxy == NULL) {
 
76
                goto out;
 
77
        }
 
78
 
 
79
        error = NULL;
 
80
        res = dbus_g_proxy_call (bus_proxy,
 
81
                                 "RequestName",
 
82
                                 &error,
 
83
                                 G_TYPE_STRING, CK_DBUS_NAME,
 
84
                                 G_TYPE_UINT, 0,
 
85
                                 G_TYPE_INVALID,
 
86
                                 G_TYPE_UINT, &result,
 
87
                                 G_TYPE_INVALID);
 
88
        if (! res) {
 
89
                if (error != NULL) {
 
90
                        g_warning ("Failed to acquire %s: %s", CK_DBUS_NAME, error->message);
 
91
                        g_error_free (error);
 
92
                } else {
 
93
                        g_warning ("Failed to acquire %s", CK_DBUS_NAME);
 
94
                }
 
95
                goto out;
 
96
        }
 
97
 
 
98
        if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
 
99
                if (error != NULL) {
 
100
                        g_warning ("Failed to acquire %s: %s", CK_DBUS_NAME, error->message);
 
101
                        g_error_free (error);
 
102
                } else {
 
103
                        g_warning ("Failed to acquire %s", CK_DBUS_NAME);
 
104
                }
 
105
                goto out;
 
106
        }
 
107
 
 
108
        ret = TRUE;
 
109
 
 
110
 out:
 
111
        return ret;
 
112
}
 
113
 
 
114
static DBusGConnection *
 
115
get_system_bus (void)
 
116
{
 
117
        GError          *error;
 
118
        DBusGConnection *bus;
 
119
        DBusConnection  *connection;
 
120
 
 
121
        error = NULL;
 
122
        bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
 
123
        if (bus == NULL) {
 
124
                g_warning ("Couldn't connect to system bus: %s",
 
125
                           error->message);
 
126
                g_error_free (error);
 
127
                goto out;
 
128
        }
 
129
 
 
130
        connection = dbus_g_connection_get_connection (bus);
 
131
        dbus_connection_set_exit_on_disconnect (connection, FALSE);
 
132
 
 
133
 out:
 
134
        return bus;
 
135
}
 
136
 
 
137
static void
 
138
bus_proxy_destroyed_cb (DBusGProxy *bus_proxy,
 
139
                        GMainLoop  *loop)
 
140
{
 
141
        g_debug ("Disconnected from D-Bus");
 
142
        g_main_loop_quit (loop);
 
143
}
 
144
 
 
145
static void
 
146
delete_pid (void)
 
147
{
 
148
        unlink (CONSOLE_KIT_PID_FILE);
 
149
}
 
150
 
 
151
/* copied from nautilus */
 
152
static int debug_log_pipes[2];
 
153
 
 
154
static gboolean
 
155
debug_log_io_cb (GIOChannel  *io,
 
156
                 GIOCondition condition,
 
157
                 gpointer     data)
 
158
{
 
159
        char a;
 
160
 
 
161
        while (read (debug_log_pipes[0], &a, 1) != 1)
 
162
                ;
 
163
 
 
164
        ck_log_toggle_debug ();
 
165
 
 
166
        return TRUE;
 
167
}
 
168
 
 
169
static void
 
170
sigusr1_handler (int sig)
 
171
{
 
172
        while (write (debug_log_pipes[1], "a", 1) != 1)
 
173
                ;
 
174
}
 
175
 
 
176
static void
 
177
setup_debug_log_signals (void)
 
178
{
 
179
        struct sigaction sa;
 
180
        GIOChannel      *io;
 
181
 
 
182
        if (pipe (debug_log_pipes) == -1) {
 
183
                g_error ("Could not create pipe() for debug log");
 
184
        }
 
185
 
 
186
        io = g_io_channel_unix_new (debug_log_pipes[0]);
 
187
        g_io_add_watch (io, G_IO_IN, debug_log_io_cb, NULL);
 
188
 
 
189
        sa.sa_handler = sigusr1_handler;
 
190
        sigemptyset (&sa.sa_mask);
 
191
        sa.sa_flags = 0;
 
192
        sigaction (SIGUSR1, &sa, NULL);
 
193
}
 
194
 
 
195
static void
 
196
setup_debug_log (gboolean debug)
 
197
{
 
198
        ck_log_init ();
 
199
        ck_log_set_debug (debug);
 
200
        setup_debug_log_signals ();
 
201
}
 
202
 
 
203
static void
 
204
create_pid_file (void)
 
205
{
 
206
        char   *dirname;
 
207
        int     res;
 
208
        int     pf;
 
209
        ssize_t written;
 
210
        char    pid[9];
 
211
 
 
212
        /* remove old pid file */
 
213
        unlink (CONSOLE_KIT_PID_FILE);
 
214
 
 
215
        dirname = g_path_get_dirname (CONSOLE_KIT_PID_FILE);
 
216
        errno = 0;
 
217
        res = g_mkdir_with_parents (dirname,
 
218
                                    S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
 
219
        if (res < 0) {
 
220
                g_warning ("Unable to create directory %s (%s)",
 
221
                           dirname,
 
222
                           g_strerror (errno));
 
223
        }
 
224
        g_free (dirname);
 
225
 
 
226
        /* make a new pid file */
 
227
        if ((pf = open (CONSOLE_KIT_PID_FILE, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644)) > 0) {
 
228
                snprintf (pid, sizeof (pid), "%lu\n", (long unsigned) getpid ());
 
229
                written = write (pf, pid, strlen (pid));
 
230
                close (pf);
 
231
                g_atexit (delete_pid);
 
232
        } else {
 
233
                g_warning ("Unable to write pid file %s: %s",
 
234
                           CONSOLE_KIT_PID_FILE,
 
235
                           g_strerror (errno));
 
236
        }
 
237
}
 
238
 
 
239
int
 
240
main (int    argc,
 
241
      char **argv)
 
242
{
 
243
        GMainLoop       *loop;
 
244
        CkManager       *manager;
 
245
        GOptionContext  *context;
 
246
        DBusGProxy      *bus_proxy;
 
247
        DBusGConnection *connection;
 
248
        GError          *error;
 
249
        int              ret;
 
250
        gboolean         res;
 
251
        static gboolean     debug            = FALSE;
 
252
        static gboolean     no_daemon        = FALSE;
 
253
        static gboolean     do_timed_exit    = FALSE;
 
254
        static GOptionEntry entries []   = {
 
255
                { "debug", 0, 0, G_OPTION_ARG_NONE, &debug, N_("Enable debugging code"), NULL },
 
256
                { "no-daemon", 0, 0, G_OPTION_ARG_NONE, &no_daemon, N_("Don't become a daemon"), NULL },
 
257
                { "timed-exit", 0, 0, G_OPTION_ARG_NONE, &do_timed_exit, N_("Exit after a time - for debugging"), NULL },
 
258
                { NULL }
 
259
        };
 
260
 
 
261
        ret = 1;
 
262
 
 
263
        if (! g_thread_supported ()) {
 
264
                g_thread_init (NULL);
 
265
        }
 
266
        dbus_g_thread_init ();
 
267
        g_type_init ();
 
268
 
 
269
        if (! ck_is_root_user ()) {
 
270
                g_warning ("Must be run as root");
 
271
                exit (1);
 
272
        }
 
273
 
 
274
        if (debug) {
 
275
                g_setenv ("G_DEBUG", "fatal_criticals", FALSE);
 
276
                g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL);
 
277
        }
 
278
 
 
279
        context = g_option_context_new (_("Console kit daemon"));
 
280
        g_option_context_add_main_entries (context, entries, NULL);
 
281
        error = NULL;
 
282
        res = g_option_context_parse (context, &argc, &argv, &error);
 
283
        g_option_context_free (context);
 
284
        if (! res) {
 
285
                g_warning ("%s", error->message);
 
286
                g_error_free (error);
 
287
                goto out;
 
288
        }
 
289
 
 
290
        if (! no_daemon && daemon (0, 0)) {
 
291
                g_error ("Could not daemonize: %s", g_strerror (errno));
 
292
        }
 
293
 
 
294
        setup_debug_log (debug);
 
295
 
 
296
        g_debug ("initializing console-kit-daemon %s", VERSION);
 
297
 
 
298
        connection = get_system_bus ();
 
299
        if (connection == NULL) {
 
300
                goto out;
 
301
        }
 
302
 
 
303
        manager = ck_manager_new ();
 
304
 
 
305
        if (manager == NULL) {
 
306
                goto out;
 
307
        }
 
308
 
 
309
        bus_proxy = get_bus_proxy (connection);
 
310
        if (bus_proxy == NULL) {
 
311
                g_warning ("Could not construct bus_proxy object; bailing out");
 
312
                goto out;
 
313
        }
 
314
 
 
315
        if (! acquire_name_on_proxy (bus_proxy) ) {
 
316
                g_warning ("Could not acquire name; bailing out");
 
317
                goto out;
 
318
        }
 
319
 
 
320
        create_pid_file ();
 
321
 
 
322
        loop = g_main_loop_new (NULL, FALSE);
 
323
 
 
324
        g_signal_connect (bus_proxy,
 
325
                          "destroy",
 
326
                          G_CALLBACK (bus_proxy_destroyed_cb),
 
327
                          loop);
 
328
 
 
329
        if (do_timed_exit) {
 
330
                g_timeout_add (1000 * 30, (GSourceFunc) timed_exit_cb, loop);
 
331
        }
 
332
 
 
333
        g_main_loop_run (loop);
 
334
 
 
335
        if (manager != NULL) {
 
336
                g_object_unref (manager);
 
337
        }
 
338
 
 
339
        g_main_loop_unref (loop);
 
340
 
 
341
        ret = 0;
 
342
 
 
343
 out:
 
344
 
 
345
        return ret;
 
346
}