source: proiecte/PPPP/gdm/daemon/gdm-greeter-server.c @ 134

Last change on this file since 134 was 134, checked in by (none), 14 years ago

gdm sources with the modifications for webcam

File size: 49.1 KB
Line 
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 <fcntl.h>
26#include <unistd.h>
27#include <string.h>
28#include <sys/types.h>
29#include <sys/wait.h>
30#include <errno.h>
31#include <ctype.h>
32#include <pwd.h>
33#include <grp.h>
34
35#if defined (_POSIX_PRIORITY_SCHEDULING) && defined (HAVE_SCHED_YIELD)
36#include <sched.h>
37#endif
38
39#include <glib.h>
40#include <glib/gi18n.h>
41#include <glib-object.h>
42#define DBUS_API_SUBJECT_TO_CHANGE
43#include <dbus/dbus-glib.h>
44#include <dbus/dbus-glib-lowlevel.h>
45
46#include "gdm-greeter-server.h"
47
48#define GDM_GREETER_SERVER_DBUS_PATH      "/org/gnome/DisplayManager/GreeterServer"
49#define GDM_GREETER_SERVER_DBUS_INTERFACE "org.gnome.DisplayManager.GreeterServer"
50
51#define GDM_GREETER_SERVER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_GREETER_SERVER, GdmGreeterServerPrivate))
52
53struct GdmGreeterServerPrivate
54{
55        char           *user_name;
56        char           *group_name;
57        char           *display_id;
58
59        DBusServer     *server;
60        char           *server_address;
61        DBusConnection *greeter_connection;
62};
63
64enum {
65        PROP_0,
66        PROP_USER_NAME,
67        PROP_GROUP_NAME,
68        PROP_DISPLAY_ID,
69};
70
71enum {
72        BEGIN_AUTO_LOGIN,
73        BEGIN_VERIFICATION,
74        BEGIN_VERIFICATION_FOR_USER,
75        QUERY_ANSWER,
76        SESSION_SELECTED,
77        HOSTNAME_SELECTED,
78        LANGUAGE_SELECTED,
79        LAYOUT_SELECTED,
80        USER_SELECTED,
81        CANCELLED,
82        CONNECTED,
83        DISCONNECTED,
84        START_SESSION_WHEN_READY,
85        START_SESSION_LATER,
86        LAST_SIGNAL
87};
88
89static guint signals [LAST_SIGNAL] = { 0, };
90
91static void     gdm_greeter_server_class_init   (GdmGreeterServerClass *klass);
92static void     gdm_greeter_server_init         (GdmGreeterServer      *greeter_server);
93static void     gdm_greeter_server_finalize     (GObject               *object);
94
95G_DEFINE_TYPE (GdmGreeterServer, gdm_greeter_server, G_TYPE_OBJECT)
96
97static gboolean
98send_dbus_message (DBusConnection *connection,
99                   DBusMessage    *message)
100{
101        gboolean is_connected;
102        gboolean sent;
103
104        g_return_val_if_fail (message != NULL, FALSE);
105
106        if (connection == NULL) {
107                g_debug ("GreeterServer: There is no valid connection");
108                return FALSE;
109        }
110
111        is_connected = dbus_connection_get_is_connected (connection);
112        if (! is_connected) {
113                g_warning ("GreeterServer: Not connected!");
114                return FALSE;
115        }
116
117        sent = dbus_connection_send (connection, message, NULL);
118        dbus_connection_flush (connection);
119
120        return sent;
121}
122
123static void
124send_dbus_string_and_int_signal (GdmGreeterServer *greeter_server,
125                                 const char       *name,
126                                 const char       *text,
127                                 int               number)
128{
129        DBusMessage    *message;
130        DBusMessageIter iter;
131        const char     *str;
132
133        if (text != NULL) {
134                str = text;
135        } else {
136                str = "";
137        }
138
139        g_return_if_fail (greeter_server != NULL);
140
141        message = dbus_message_new_signal (GDM_GREETER_SERVER_DBUS_PATH,
142                                           GDM_GREETER_SERVER_DBUS_INTERFACE,
143                                           name);
144
145        dbus_message_iter_init_append (message, &iter);
146        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &str);
147        dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &number);
148
149        g_debug ("GreeterServer: Sending %s (%s %d)", name, str, number);
150        if (! send_dbus_message (greeter_server->priv->greeter_connection, message)) {
151                g_debug ("GreeterServer: Could not send %s signal", name);
152        }
153
154        dbus_message_unref (message);
155}
156
157static void
158send_dbus_string_signal (GdmGreeterServer *greeter_server,
159                         const char       *name,
160                         const char       *text)
161{
162        DBusMessage    *message;
163        DBusMessageIter iter;
164        const char     *str;
165
166        if (text != NULL) {
167                str = text;
168        } else {
169                str = "";
170        }
171
172        g_return_if_fail (greeter_server != NULL);
173
174        message = dbus_message_new_signal (GDM_GREETER_SERVER_DBUS_PATH,
175                                           GDM_GREETER_SERVER_DBUS_INTERFACE,
176                                           name);
177
178        dbus_message_iter_init_append (message, &iter);
179        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &str);
180
181        g_debug ("GreeterServer: Sending %s (%s)", name, str);
182        if (! send_dbus_message (greeter_server->priv->greeter_connection, message)) {
183                g_debug ("GreeterServer: Could not send %s signal", name);
184        }
185
186        dbus_message_unref (message);
187}
188
189static void
190send_dbus_void_signal (GdmGreeterServer *greeter_server,
191                       const char       *name)
192{
193        DBusMessage    *message;
194
195        g_return_if_fail (greeter_server != NULL);
196
197        message = dbus_message_new_signal (GDM_GREETER_SERVER_DBUS_PATH,
198                                           GDM_GREETER_SERVER_DBUS_INTERFACE,
199                                           name);
200
201        if (! send_dbus_message (greeter_server->priv->greeter_connection, message)) {
202                g_debug ("GreeterServer: Could not send %s signal", name);
203        }
204
205        dbus_message_unref (message);
206}
207
208gboolean
209gdm_greeter_server_info_query (GdmGreeterServer *greeter_server,
210                               const char       *text)
211{
212        send_dbus_string_signal (greeter_server, "InfoQuery", text);
213
214        return TRUE;
215}
216
217gboolean
218gdm_greeter_server_secret_info_query (GdmGreeterServer *greeter_server,
219                                      const char       *text)
220{
221        send_dbus_string_signal (greeter_server, "SecretInfoQuery", text);
222        return TRUE;
223}
224
225gboolean
226gdm_greeter_server_info (GdmGreeterServer *greeter_server,
227                         const char       *text)
228{
229        send_dbus_string_signal (greeter_server, "Info", text);
230        return TRUE;
231}
232
233gboolean
234gdm_greeter_server_problem (GdmGreeterServer *greeter_server,
235                            const char       *text)
236{
237        send_dbus_string_signal (greeter_server, "Problem", text);
238        return TRUE;
239}
240
241gboolean
242gdm_greeter_server_reset (GdmGreeterServer *greeter_server)
243{
244        send_dbus_void_signal (greeter_server, "Reset");
245        return TRUE;
246}
247
248gboolean
249gdm_greeter_server_ready (GdmGreeterServer *greeter_server)
250{
251        send_dbus_void_signal (greeter_server, "Ready");
252        return TRUE;
253}
254
255void
256gdm_greeter_server_selected_user_changed (GdmGreeterServer *greeter_server,
257                                          const char       *username)
258{
259        send_dbus_string_signal (greeter_server, "SelectedUserChanged", username);
260}
261
262void
263gdm_greeter_server_default_language_name_changed (GdmGreeterServer *greeter_server,
264                                                  const char       *language_name)
265{
266        send_dbus_string_signal (greeter_server, "DefaultLanguageNameChanged", language_name);
267}
268
269void
270gdm_greeter_server_default_layout_name_changed (GdmGreeterServer *greeter_server,
271                                                const char       *layout_name)
272{
273        send_dbus_string_signal (greeter_server, "DefaultLayoutNameChanged", layout_name);
274}
275
276void
277gdm_greeter_server_default_session_name_changed (GdmGreeterServer *greeter_server,
278                                                 const char       *session_name)
279{
280        send_dbus_string_signal (greeter_server, "DefaultSessionNameChanged", session_name);
281}
282
283void
284gdm_greeter_server_request_timed_login (GdmGreeterServer *greeter_server,
285                                        const char       *username,
286                                        int               delay)
287{
288        send_dbus_string_and_int_signal (greeter_server, "TimedLoginRequested", username, delay);
289}
290
291void
292gdm_greeter_server_user_authorized (GdmGreeterServer *greeter_server)
293{
294        send_dbus_void_signal (greeter_server, "UserAuthorized");
295}
296
297/* Note: Use abstract sockets like dbus does by default on Linux. Abstract
298 * sockets are only available on Linux.
299 */
300static char *
301generate_address (void)
302{
303        char *path;
304#if defined (__linux__)
305        int   i;
306        char  tmp[9];
307
308        for (i = 0; i < 8; i++) {
309                if (g_random_int_range (0, 2) == 0) {
310                        tmp[i] = g_random_int_range ('a', 'z' + 1);
311                } else {
312                        tmp[i] = g_random_int_range ('A', 'Z' + 1);
313                }
314        }
315        tmp[8] = '\0';
316
317        path = g_strdup_printf ("unix:abstract=/tmp/gdm-greeter-%s", tmp);
318#else
319        path = g_strdup ("unix:tmpdir=/tmp");
320#endif
321
322        return path;
323}
324
325static DBusHandlerResult
326handle_begin_verification (GdmGreeterServer *greeter_server,
327                           DBusConnection   *connection,
328                           DBusMessage      *message)
329{
330        DBusMessage *reply;
331
332        g_debug ("GreeterServer: BeginVerification");
333
334        reply = dbus_message_new_method_return (message);
335        dbus_connection_send (connection, reply, NULL);
336        dbus_message_unref (reply);
337
338        g_signal_emit (greeter_server, signals [BEGIN_VERIFICATION], 0);
339
340        return DBUS_HANDLER_RESULT_HANDLED;
341}
342
343static DBusHandlerResult
344handle_begin_auto_login (GdmGreeterServer *greeter_server,
345                         DBusConnection   *connection,
346                         DBusMessage      *message)
347{
348        DBusMessage *reply;
349        DBusError    error;
350        const char  *text;
351
352
353        dbus_error_init (&error);
354        if (! dbus_message_get_args (message, &error,
355                                     DBUS_TYPE_STRING, &text,
356                                     DBUS_TYPE_INVALID)) {
357                g_warning ("ERROR: %s", error.message);
358        }
359
360        g_debug ("GreeterServer: BeginAutoLogin for '%s'", text);
361
362        reply = dbus_message_new_method_return (message);
363        dbus_connection_send (connection, reply, NULL);
364        dbus_message_unref (reply);
365
366        g_signal_emit (greeter_server, signals [BEGIN_AUTO_LOGIN], 0, text);
367
368        return DBUS_HANDLER_RESULT_HANDLED;
369}
370
371static DBusHandlerResult
372handle_begin_verification_for_user (GdmGreeterServer *greeter_server,
373                                    DBusConnection   *connection,
374                                    DBusMessage      *message)
375{
376        DBusMessage *reply;
377        DBusError    error;
378        const char  *text;
379
380        dbus_error_init (&error);
381        if (! dbus_message_get_args (message, &error,
382                                     DBUS_TYPE_STRING, &text,
383                                     DBUS_TYPE_INVALID)) {
384                g_warning ("ERROR: %s", error.message);
385        }
386
387        g_debug ("GreeterServer: BeginVerificationForUser for '%s'", text);
388
389        reply = dbus_message_new_method_return (message);
390        dbus_connection_send (connection, reply, NULL);
391        dbus_message_unref (reply);
392
393        g_signal_emit (greeter_server, signals [BEGIN_VERIFICATION_FOR_USER], 0, text);
394
395        return DBUS_HANDLER_RESULT_HANDLED;
396}
397
398static DBusHandlerResult
399handle_answer_query (GdmGreeterServer *greeter_server,
400                     DBusConnection   *connection,
401                     DBusMessage      *message)
402{
403        DBusMessage *reply;
404        DBusError    error;
405        const char  *text;
406
407        dbus_error_init (&error);
408        if (! dbus_message_get_args (message, &error,
409                                     DBUS_TYPE_STRING, &text,
410                                     DBUS_TYPE_INVALID)) {
411                g_warning ("ERROR: %s", error.message);
412        }
413
414        g_debug ("GreeterServer: AnswerQuery");
415
416        reply = dbus_message_new_method_return (message);
417        dbus_connection_send (connection, reply, NULL);
418        dbus_message_unref (reply);
419
420        g_signal_emit (greeter_server, signals [QUERY_ANSWER], 0, text);
421
422        return DBUS_HANDLER_RESULT_HANDLED;
423}
424
425static DBusHandlerResult
426handle_select_session (GdmGreeterServer *greeter_server,
427                       DBusConnection   *connection,
428                       DBusMessage      *message)
429{
430        DBusMessage *reply;
431        DBusError    error;
432        const char  *text;
433
434        dbus_error_init (&error);
435        if (! dbus_message_get_args (message, &error,
436                                     DBUS_TYPE_STRING, &text,
437                                     DBUS_TYPE_INVALID)) {
438                g_warning ("ERROR: %s", error.message);
439        }
440
441        g_debug ("GreeterServer: SelectSession: %s", text);
442
443        reply = dbus_message_new_method_return (message);
444        dbus_connection_send (connection, reply, NULL);
445        dbus_message_unref (reply);
446
447        g_signal_emit (greeter_server, signals [SESSION_SELECTED], 0, text);
448
449        return DBUS_HANDLER_RESULT_HANDLED;
450}
451
452static DBusHandlerResult
453handle_select_hostname (GdmGreeterServer *greeter_server,
454                        DBusConnection   *connection,
455                        DBusMessage      *message)
456{
457        DBusMessage *reply;
458        DBusError    error;
459        const char  *text;
460
461        dbus_error_init (&error);
462        if (! dbus_message_get_args (message, &error,
463                                     DBUS_TYPE_STRING, &text,
464                                     DBUS_TYPE_INVALID)) {
465                g_warning ("ERROR: %s", error.message);
466        }
467
468        g_debug ("GreeterServer: SelectHostname: %s", text);
469
470        reply = dbus_message_new_method_return (message);
471        dbus_connection_send (connection, reply, NULL);
472        dbus_message_unref (reply);
473
474        g_signal_emit (greeter_server, signals [HOSTNAME_SELECTED], 0, text);
475
476        return DBUS_HANDLER_RESULT_HANDLED;
477}
478
479static DBusHandlerResult
480handle_select_language (GdmGreeterServer *greeter_server,
481                        DBusConnection  *connection,
482                        DBusMessage     *message)
483{
484        DBusMessage *reply;
485        DBusError    error;
486        const char  *text;
487
488        dbus_error_init (&error);
489        if (! dbus_message_get_args (message, &error,
490                                     DBUS_TYPE_STRING, &text,
491                                     DBUS_TYPE_INVALID)) {
492                g_warning ("ERROR: %s", error.message);
493        }
494
495        g_debug ("GreeterServer: SelectLanguage: %s", text);
496
497        reply = dbus_message_new_method_return (message);
498        dbus_connection_send (connection, reply, NULL);
499        dbus_message_unref (reply);
500
501        g_signal_emit (greeter_server, signals [LANGUAGE_SELECTED], 0, text);
502
503        return DBUS_HANDLER_RESULT_HANDLED;
504}
505
506static DBusHandlerResult
507handle_select_layout (GdmGreeterServer *greeter_server,
508                      DBusConnection  *connection,
509                      DBusMessage     *message)
510{
511        DBusMessage *reply;
512        DBusError    error;
513        const char  *text;
514
515        dbus_error_init (&error);
516        if (! dbus_message_get_args (message, &error,
517                                     DBUS_TYPE_STRING, &text,
518                                     DBUS_TYPE_INVALID)) {
519                g_warning ("ERROR: %s", error.message);
520        }
521
522        g_debug ("GreeterServer: SelectLayout: %s", text);
523
524        reply = dbus_message_new_method_return (message);
525        dbus_connection_send (connection, reply, NULL);
526        dbus_message_unref (reply);
527
528        g_signal_emit (greeter_server, signals [LAYOUT_SELECTED], 0, text);
529
530        return DBUS_HANDLER_RESULT_HANDLED;
531}
532
533static DBusHandlerResult
534handle_select_user (GdmGreeterServer *greeter_server,
535                    DBusConnection   *connection,
536                    DBusMessage      *message)
537{
538        DBusMessage *reply;
539        DBusError    error;
540        const char  *text;
541
542        dbus_error_init (&error);
543        if (! dbus_message_get_args (message, &error,
544                                     DBUS_TYPE_STRING, &text,
545                                     DBUS_TYPE_INVALID)) {
546                g_warning ("ERROR: %s", error.message);
547        }
548
549        g_debug ("GreeterServer: SelectUser: %s", text);
550
551        reply = dbus_message_new_method_return (message);
552        dbus_connection_send (connection, reply, NULL);
553        dbus_message_unref (reply);
554
555        g_signal_emit (greeter_server, signals [USER_SELECTED], 0, text);
556
557        return DBUS_HANDLER_RESULT_HANDLED;
558}
559
560static DBusHandlerResult
561handle_cancel (GdmGreeterServer *greeter_server,
562               DBusConnection   *connection,
563               DBusMessage      *message)
564{
565        DBusMessage *reply;
566
567        reply = dbus_message_new_method_return (message);
568        dbus_connection_send (connection, reply, NULL);
569        dbus_message_unref (reply);
570
571        g_signal_emit (greeter_server, signals [CANCELLED], 0);
572
573        return DBUS_HANDLER_RESULT_HANDLED;
574}
575
576static DBusHandlerResult
577handle_disconnect (GdmGreeterServer *greeter_server,
578                   DBusConnection   *connection,
579                   DBusMessage      *message)
580{
581        DBusMessage *reply;
582
583        reply = dbus_message_new_method_return (message);
584        dbus_connection_send (connection, reply, NULL);
585        dbus_message_unref (reply);
586
587        g_signal_emit (greeter_server, signals [DISCONNECTED], 0);
588
589        return DBUS_HANDLER_RESULT_HANDLED;
590}
591
592static DBusHandlerResult
593handle_get_display_id (GdmGreeterServer *greeter_server,
594                       DBusConnection   *connection,
595                       DBusMessage      *message)
596{
597        DBusMessage    *reply;
598        DBusMessageIter iter;
599
600        reply = dbus_message_new_method_return (message);
601        dbus_message_iter_init_append (reply, &iter);
602        dbus_message_iter_append_basic (&iter, DBUS_TYPE_OBJECT_PATH, &greeter_server->priv->display_id);
603        dbus_connection_send (connection, reply, NULL);
604        dbus_message_unref (reply);
605
606        return DBUS_HANDLER_RESULT_HANDLED;
607}
608
609static DBusHandlerResult
610handle_start_session_when_ready (GdmGreeterServer *greeter_server,
611                                 DBusConnection   *connection,
612                                 DBusMessage      *message)
613{
614        DBusMessage *reply;
615        DBusError    error;
616        gboolean     should_start_session;
617
618        dbus_error_init (&error);
619        if (! dbus_message_get_args (message, &error,
620                                     DBUS_TYPE_BOOLEAN, &should_start_session,
621                                     DBUS_TYPE_INVALID)) {
622                g_warning ("ERROR: %s", error.message);
623        }
624
625        g_debug ("GreeterServer: %sStartSessionWhenReady",
626                 should_start_session? "" : "Don't ");
627
628        reply = dbus_message_new_method_return (message);
629        dbus_connection_send (connection, reply, NULL);
630        dbus_message_unref (reply);
631
632        if (should_start_session) {
633                g_signal_emit (greeter_server, signals [START_SESSION_WHEN_READY], 0);
634        } else {
635                g_signal_emit (greeter_server, signals [START_SESSION_LATER] ,0);
636        }
637
638        return DBUS_HANDLER_RESULT_HANDLED;
639}
640
641static DBusHandlerResult
642greeter_handle_child_message (DBusConnection *connection,
643                              DBusMessage    *message,
644                              void           *user_data)
645{
646        GdmGreeterServer *greeter_server = GDM_GREETER_SERVER (user_data);
647
648        if (dbus_message_is_method_call (message, GDM_GREETER_SERVER_DBUS_INTERFACE, "BeginVerification")) {
649                return handle_begin_verification (greeter_server, connection, message);
650        } else if (dbus_message_is_method_call (message, GDM_GREETER_SERVER_DBUS_INTERFACE, "BeginVerificationForUser")) {
651                return handle_begin_verification_for_user (greeter_server, connection, message);
652        } else if (dbus_message_is_method_call (message, GDM_GREETER_SERVER_DBUS_INTERFACE, "BeginAutoLogin")) {
653                return handle_begin_auto_login (greeter_server, connection, message);
654        } else if (dbus_message_is_method_call (message, GDM_GREETER_SERVER_DBUS_INTERFACE, "AnswerQuery")) {
655                return handle_answer_query (greeter_server, connection, message);
656        } else if (dbus_message_is_method_call (message, GDM_GREETER_SERVER_DBUS_INTERFACE, "SelectSession")) {
657                return handle_select_session (greeter_server, connection, message);
658        } else if (dbus_message_is_method_call (message, GDM_GREETER_SERVER_DBUS_INTERFACE, "HostnameSession")) {
659                return handle_select_hostname (greeter_server, connection, message);
660        } else if (dbus_message_is_method_call (message, GDM_GREETER_SERVER_DBUS_INTERFACE, "SelectLanguage")) {
661                return handle_select_language (greeter_server, connection, message);
662        } else if (dbus_message_is_method_call (message, GDM_GREETER_SERVER_DBUS_INTERFACE, "SelectLayout")) {
663                return handle_select_layout (greeter_server, connection, message);
664        } else if (dbus_message_is_method_call (message, GDM_GREETER_SERVER_DBUS_INTERFACE, "SelectUser")) {
665                return handle_select_user (greeter_server, connection, message);
666        } else if (dbus_message_is_method_call (message, GDM_GREETER_SERVER_DBUS_INTERFACE, "Cancel")) {
667                return handle_cancel (greeter_server, connection, message);
668        } else if (dbus_message_is_method_call (message, GDM_GREETER_SERVER_DBUS_INTERFACE, "Disconnect")) {
669                return handle_disconnect (greeter_server, connection, message);
670        } else if (dbus_message_is_method_call (message, GDM_GREETER_SERVER_DBUS_INTERFACE, "GetDisplayId")) {
671                return handle_get_display_id (greeter_server, connection, message);
672        } else if (dbus_message_is_method_call (message, GDM_GREETER_SERVER_DBUS_INTERFACE, "StartSessionWhenReady")) {
673                return handle_start_session_when_ready (greeter_server, connection, message);
674        }
675
676        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
677}
678
679static DBusHandlerResult
680do_introspect (DBusConnection *connection,
681               DBusMessage    *message)
682{
683        DBusMessage *reply;
684        GString     *xml;
685        char        *xml_string;
686
687        g_debug ("GreeterServer: Do introspect");
688
689        /* standard header */
690        xml = g_string_new ("<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n"
691                            "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
692                            "<node>\n"
693                            "  <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
694                            "    <method name=\"Introspect\">\n"
695                            "      <arg name=\"data\" direction=\"out\" type=\"s\"/>\n"
696                            "    </method>\n"
697                            "  </interface>\n");
698
699        /* interface */
700        xml = g_string_append (xml,
701                               "  <interface name=\"org.gnome.DisplayManager.GreeterServer\">\n"
702                               "    <method name=\"BeginVerification\">\n"
703                               "    <method name=\"BeginTimedLogin\">\n"
704                               "    </method>\n"
705                               "    <method name=\"BeginVerificationForUser\">\n"
706                               "      <arg name=\"username\" direction=\"in\" type=\"s\"/>\n"
707                               "    </method>\n"
708                               "    <method name=\"AnswerQuery\">\n"
709                               "      <arg name=\"text\" direction=\"in\" type=\"s\"/>\n"
710                               "    </method>\n"
711                               "    <method name=\"SelectSession\">\n"
712                               "      <arg name=\"text\" direction=\"in\" type=\"s\"/>\n"
713                               "    </method>\n"
714                               "    <method name=\"SelectLanguage\">\n"
715                               "      <arg name=\"text\" direction=\"in\" type=\"s\"/>\n"
716                               "    </method>\n"
717                               "    <method name=\"SelectUser\">\n"
718                               "      <arg name=\"text\" direction=\"in\" type=\"s\"/>\n"
719                               "    </method>\n"
720                               "    <method name=\"SelectHostname\">\n"
721                               "      <arg name=\"text\" direction=\"in\" type=\"s\"/>\n"
722                               "    </method>\n"
723                               "    <method name=\"Cancel\">\n"
724                               "    </method>\n"
725                               "    <method name=\"Disconnect\">\n"
726                               "    </method>\n"
727                               "    <method name=\"GetDisplayId\">\n"
728                               "      <arg name=\"id\" direction=\"out\" type=\"o\"/>\n"
729                               "    </method>\n"
730                               "    <method name=\"StartSessionWhenReady\">\n"
731                               "      <arg name=\"should_start_session\" type=\"b\"/>\n"
732                               "    </method>\n"
733                               "    <signal name=\"Info\">\n"
734                               "      <arg name=\"text\" type=\"s\"/>\n"
735                               "    </signal>\n"
736                               "    <signal name=\"Problem\">\n"
737                               "      <arg name=\"text\" type=\"s\"/>\n"
738                               "    </signal>\n"
739                               "    <signal name=\"InfoQuery\">\n"
740                               "      <arg name=\"text\" type=\"s\"/>\n"
741                               "    </signal>\n"
742                               "    <signal name=\"SecretInfoQuery\">\n"
743                               "      <arg name=\"text\" type=\"s\"/>\n"
744                               "    </signal>\n"
745                               "    <signal name=\"SelectedUserChanged\">\n"
746                               "      <arg name=\"username\" type=\"s\"/>\n"
747                               "    </signal>\n"
748                               "    <signal name=\"DefaultLanguageNameChanged\">\n"
749                               "      <arg name=\"language_name\" type=\"s\"/>\n"
750                               "    </signal>\n"
751                               "    <signal name=\"DefaultLayoutNameChanged\">\n"
752                               "      <arg name=\"layout_name\" type=\"s\"/>\n"
753                               "    </signal>\n"
754                               "    <signal name=\"DefaultSessionNameChanged\">\n"
755                               "    <signal name=\"DefaultSessionNameChanged\">\n"
756                               "      <arg name=\"session_name\" type=\"s\"/>\n"
757                               "    </signal>\n"
758                               "    <signal name=\"TimedLoginRequested\">\n"
759                               "      <arg name=\"username\" type=\"s\"/>\n"
760                               "      <arg name=\"delay\" type=\"i\"/>\n"
761                               "    </signal>\n"
762                               "    <signal name=\"Ready\">\n"
763                               "    </signal>\n"
764                               "    <signal name=\"Reset\">\n"
765                               "    </signal>\n"
766                               "    <signal name=\"UserAuthorized\">\n"
767                               "    </signal>\n"
768                               "  </interface>\n");
769
770        reply = dbus_message_new_method_return (message);
771
772        xml = g_string_append (xml, "</node>\n");
773        xml_string = g_string_free (xml, FALSE);
774
775        dbus_message_append_args (reply,
776                                  DBUS_TYPE_STRING, &xml_string,
777                                  DBUS_TYPE_INVALID);
778
779        g_free (xml_string);
780
781        if (reply == NULL) {
782                g_error ("No memory");
783        }
784
785        if (! dbus_connection_send (connection, reply, NULL)) {
786                g_error ("No memory");
787        }
788
789        dbus_message_unref (reply);
790
791        return DBUS_HANDLER_RESULT_HANDLED;
792}
793
794static DBusHandlerResult
795greeter_server_message_handler (DBusConnection  *connection,
796                                DBusMessage     *message,
797                                void            *user_data)
798{
799        const char *dbus_destination = dbus_message_get_destination (message);
800        const char *dbus_path        = dbus_message_get_path (message);
801        const char *dbus_interface   = dbus_message_get_interface (message);
802        const char *dbus_member      = dbus_message_get_member (message);
803
804        g_debug ("greeter_server_message_handler: destination=%s obj_path=%s interface=%s method=%s",
805                 dbus_destination ? dbus_destination : "(null)",
806                 dbus_path        ? dbus_path        : "(null)",
807                 dbus_interface   ? dbus_interface   : "(null)",
808                 dbus_member      ? dbus_member      : "(null)");
809
810        if (dbus_message_is_method_call (message, "org.freedesktop.DBus", "AddMatch")) {
811                DBusMessage *reply;
812
813                reply = dbus_message_new_method_return (message);
814
815                if (reply == NULL) {
816                        g_error ("No memory");
817                }
818
819                if (! dbus_connection_send (connection, reply, NULL)) {
820                        g_error ("No memory");
821                }
822
823                dbus_message_unref (reply);
824
825                return DBUS_HANDLER_RESULT_HANDLED;
826        } else if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected") &&
827                   strcmp (dbus_message_get_path (message), DBUS_PATH_LOCAL) == 0) {
828
829                /*dbus_connection_unref (connection);*/
830
831                return DBUS_HANDLER_RESULT_HANDLED;
832        } else if (dbus_message_is_method_call (message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
833                return do_introspect (connection, message);
834        } else {
835                return greeter_handle_child_message (connection, message, user_data);
836        }
837
838        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
839}
840
841static void
842greeter_server_unregister_handler (DBusConnection  *connection,
843                                   void            *user_data)
844{
845        g_debug ("greeter_server_unregister_handler");
846}
847
848static DBusHandlerResult
849connection_filter_function (DBusConnection *connection,
850                            DBusMessage    *message,
851                            void           *user_data)
852{
853        GdmGreeterServer *greeter_server = GDM_GREETER_SERVER (user_data);
854        const char       *dbus_path      = dbus_message_get_path (message);
855        const char       *dbus_interface = dbus_message_get_interface (message);
856        const char       *dbus_message   = dbus_message_get_member (message);
857
858        g_debug ("GreeterServer: obj_path=%s interface=%s method=%s",
859                 dbus_path      ? dbus_path      : "(null)",
860                 dbus_interface ? dbus_interface : "(null)",
861                 dbus_message   ? dbus_message   : "(null)");
862
863        if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected")
864            && strcmp (dbus_path, DBUS_PATH_LOCAL) == 0) {
865
866                g_debug ("GreeterServer: Disconnected");
867
868                dbus_connection_unref (connection);
869                greeter_server->priv->greeter_connection = NULL;
870
871                return DBUS_HANDLER_RESULT_HANDLED;
872        }
873
874        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
875}
876
877static dbus_bool_t
878allow_user_function (DBusConnection *connection,
879                     unsigned long   uid,
880                     void           *data)
881{
882        GdmGreeterServer *greeter_server = GDM_GREETER_SERVER (data);
883        struct passwd    *pwent;
884
885        if (greeter_server->priv->user_name == NULL) {
886                return FALSE;
887        }
888
889        pwent = getpwnam (greeter_server->priv->user_name);
890        if (pwent == NULL) {
891                return FALSE;
892        }
893
894        if (pwent->pw_uid == uid) {
895                return TRUE;
896        }
897
898        return FALSE;
899}
900
901static void
902handle_connection (DBusServer      *server,
903                   DBusConnection  *new_connection,
904                   void            *user_data)
905{
906        GdmGreeterServer *greeter_server = GDM_GREETER_SERVER (user_data);
907
908        g_debug ("GreeterServer: Handing new connection");
909
910        if (greeter_server->priv->greeter_connection == NULL) {
911                DBusObjectPathVTable vtable = { &greeter_server_unregister_handler,
912                                                &greeter_server_message_handler,
913                                                NULL, NULL, NULL, NULL
914                };
915
916                greeter_server->priv->greeter_connection = new_connection;
917                dbus_connection_ref (new_connection);
918                dbus_connection_setup_with_g_main (new_connection, NULL);
919
920                g_debug ("GreeterServer: greeter connection is %p", new_connection);
921
922                dbus_connection_add_filter (new_connection,
923                                            connection_filter_function,
924                                            greeter_server,
925                                            NULL);
926
927                dbus_connection_set_unix_user_function (new_connection,
928                                                        allow_user_function,
929                                                        greeter_server,
930                                                        NULL);
931
932                dbus_connection_register_object_path (new_connection,
933                                                      GDM_GREETER_SERVER_DBUS_PATH,
934                                                      &vtable,
935                                                      greeter_server);
936
937                g_signal_emit (greeter_server, signals[CONNECTED], 0);
938
939        }
940}
941
942gboolean
943gdm_greeter_server_start (GdmGreeterServer *greeter_server)
944{
945        DBusError   error;
946        gboolean    ret;
947        char       *address;
948        const char *auth_mechanisms[] = {"EXTERNAL", NULL};
949
950        ret = FALSE;
951
952        g_debug ("GreeterServer: Creating D-Bus server for greeter");
953
954        address = generate_address ();
955
956        dbus_error_init (&error);
957        greeter_server->priv->server = dbus_server_listen (address, &error);
958        g_free (address);
959
960        if (greeter_server->priv->server == NULL) {
961                g_warning ("Cannot create D-BUS server for the greeter: %s", error.message);
962                /* FIXME: should probably fail if we can't create the socket */
963                goto out;
964        }
965
966        dbus_server_setup_with_g_main (greeter_server->priv->server, NULL);
967        dbus_server_set_auth_mechanisms (greeter_server->priv->server, auth_mechanisms);
968        dbus_server_set_new_connection_function (greeter_server->priv->server,
969                                                 handle_connection,
970                                                 greeter_server,
971                                                 NULL);
972        ret = TRUE;
973
974        g_free (greeter_server->priv->server_address);
975        greeter_server->priv->server_address = dbus_server_get_address (greeter_server->priv->server);
976
977        g_debug ("GreeterServer: D-Bus server listening on %s", greeter_server->priv->server_address);
978
979 out:
980
981        return ret;
982}
983
984gboolean
985gdm_greeter_server_stop (GdmGreeterServer *greeter_server)
986{
987        gboolean ret;
988
989        ret = FALSE;
990
991        g_debug ("GreeterServer: Stopping greeter server...");
992
993        return ret;
994}
995
996char *
997gdm_greeter_server_get_address (GdmGreeterServer *greeter_server)
998{
999        return g_strdup (greeter_server->priv->server_address);
1000}
1001
1002static void
1003_gdm_greeter_server_set_display_id (GdmGreeterServer *greeter_server,
1004                                    const char       *display_id)
1005{
1006        g_free (greeter_server->priv->display_id);
1007        greeter_server->priv->display_id = g_strdup (display_id);
1008}
1009
1010static void
1011_gdm_greeter_server_set_user_name (GdmGreeterServer *greeter_server,
1012                                  const char *name)
1013{
1014        g_free (greeter_server->priv->user_name);
1015        greeter_server->priv->user_name = g_strdup (name);
1016}
1017
1018static void
1019_gdm_greeter_server_set_group_name (GdmGreeterServer *greeter_server,
1020                                    const char *name)
1021{
1022        g_free (greeter_server->priv->group_name);
1023        greeter_server->priv->group_name = g_strdup (name);
1024}
1025
1026static void
1027gdm_greeter_server_set_property (GObject      *object,
1028                                guint         prop_id,
1029                                const GValue *value,
1030                                GParamSpec   *pspec)
1031{
1032        GdmGreeterServer *self;
1033
1034        self = GDM_GREETER_SERVER (object);
1035
1036        switch (prop_id) {
1037        case PROP_DISPLAY_ID:
1038                _gdm_greeter_server_set_display_id (self, g_value_get_string (value));
1039                break;
1040        case PROP_USER_NAME:
1041                _gdm_greeter_server_set_user_name (self, g_value_get_string (value));
1042                break;
1043        case PROP_GROUP_NAME:
1044                _gdm_greeter_server_set_group_name (self, g_value_get_string (value));
1045                break;
1046        default:
1047                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1048                break;
1049        }
1050}
1051
1052static void
1053gdm_greeter_server_get_property (GObject    *object,
1054                                guint       prop_id,
1055                                GValue     *value,
1056                                GParamSpec *pspec)
1057{
1058        GdmGreeterServer *self;
1059
1060        self = GDM_GREETER_SERVER (object);
1061
1062        switch (prop_id) {
1063        case PROP_DISPLAY_ID:
1064                g_value_set_string (value, self->priv->display_id);
1065                break;
1066        case PROP_USER_NAME:
1067                g_value_set_string (value, self->priv->user_name);
1068                break;
1069        case PROP_GROUP_NAME:
1070                g_value_set_string (value, self->priv->group_name);
1071                break;
1072        default:
1073                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1074                break;
1075        }
1076}
1077
1078static GObject *
1079gdm_greeter_server_constructor (GType                  type,
1080                               guint                  n_construct_properties,
1081                               GObjectConstructParam *construct_properties)
1082{
1083        GdmGreeterServer      *greeter_server;
1084
1085        greeter_server = GDM_GREETER_SERVER (G_OBJECT_CLASS (gdm_greeter_server_parent_class)->constructor (type,
1086                                                                                       n_construct_properties,
1087                                                                                       construct_properties));
1088
1089        return G_OBJECT (greeter_server);
1090}
1091
1092static void
1093gdm_greeter_server_class_init (GdmGreeterServerClass *klass)
1094{
1095        GObjectClass    *object_class = G_OBJECT_CLASS (klass);
1096
1097        object_class->get_property = gdm_greeter_server_get_property;
1098        object_class->set_property = gdm_greeter_server_set_property;
1099        object_class->constructor = gdm_greeter_server_constructor;
1100        object_class->finalize = gdm_greeter_server_finalize;
1101
1102        g_type_class_add_private (klass, sizeof (GdmGreeterServerPrivate));
1103
1104        g_object_class_install_property (object_class,
1105                                         PROP_DISPLAY_ID,
1106                                         g_param_spec_string ("display-id",
1107                                                              "display id",
1108                                                              "display id",
1109                                                              NULL,
1110                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
1111         g_object_class_install_property (object_class,
1112                                         PROP_USER_NAME,
1113                                         g_param_spec_string ("user-name",
1114                                                              "user name",
1115                                                              "user name",
1116                                                              GDM_USERNAME,
1117                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
1118        g_object_class_install_property (object_class,
1119                                         PROP_GROUP_NAME,
1120                                         g_param_spec_string ("group-name",
1121                                                              "group name",
1122                                                              "group name",
1123                                                              GDM_GROUPNAME,
1124                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
1125        signals [BEGIN_VERIFICATION] =
1126                g_signal_new ("begin-verification",
1127                              G_OBJECT_CLASS_TYPE (object_class),
1128                              G_SIGNAL_RUN_FIRST,
1129                              G_STRUCT_OFFSET (GdmGreeterServerClass, begin_verification),
1130                              NULL,
1131                              NULL,
1132                              g_cclosure_marshal_VOID__VOID,
1133                              G_TYPE_NONE,
1134                              0);
1135        signals [BEGIN_AUTO_LOGIN] =
1136                g_signal_new ("begin-auto-login",
1137                              G_OBJECT_CLASS_TYPE (object_class),
1138                              G_SIGNAL_RUN_FIRST,
1139                              G_STRUCT_OFFSET (GdmGreeterServerClass, begin_auto_login),
1140                              NULL,
1141                              NULL,
1142                              g_cclosure_marshal_VOID__STRING,
1143                              G_TYPE_NONE,
1144                              1,
1145                              G_TYPE_STRING);
1146        signals [BEGIN_VERIFICATION_FOR_USER] =
1147                g_signal_new ("begin-verification-for-user",
1148                              G_OBJECT_CLASS_TYPE (object_class),
1149                              G_SIGNAL_RUN_FIRST,
1150                              G_STRUCT_OFFSET (GdmGreeterServerClass, begin_verification_for_user),
1151                              NULL,
1152                              NULL,
1153                              g_cclosure_marshal_VOID__STRING,
1154                              G_TYPE_NONE,
1155                              1,
1156                              G_TYPE_STRING);
1157        signals [QUERY_ANSWER] =
1158                g_signal_new ("query-answer",
1159                              G_OBJECT_CLASS_TYPE (object_class),
1160                              G_SIGNAL_RUN_FIRST,
1161                              G_STRUCT_OFFSET (GdmGreeterServerClass, query_answer),
1162                              NULL,
1163                              NULL,
1164                              g_cclosure_marshal_VOID__STRING,
1165                              G_TYPE_NONE,
1166                              1,
1167                              G_TYPE_STRING);
1168        signals [SESSION_SELECTED] =
1169                g_signal_new ("session-selected",
1170                              G_OBJECT_CLASS_TYPE (object_class),
1171                              G_SIGNAL_RUN_FIRST,
1172                              G_STRUCT_OFFSET (GdmGreeterServerClass, session_selected),
1173                              NULL,
1174                              NULL,
1175                              g_cclosure_marshal_VOID__STRING,
1176                              G_TYPE_NONE,
1177                              1,
1178                              G_TYPE_STRING);
1179        signals [HOSTNAME_SELECTED] =
1180                g_signal_new ("hostname-selected",
1181                              G_OBJECT_CLASS_TYPE (object_class),
1182                              G_SIGNAL_RUN_FIRST,
1183                              G_STRUCT_OFFSET (GdmGreeterServerClass, hostname_selected),
1184                              NULL,
1185                              NULL,
1186                              g_cclosure_marshal_VOID__STRING,
1187                              G_TYPE_NONE,
1188                              1,
1189                              G_TYPE_STRING);
1190        signals [LANGUAGE_SELECTED] =
1191                g_signal_new ("language-selected",
1192                              G_OBJECT_CLASS_TYPE (object_class),
1193                              G_SIGNAL_RUN_FIRST,
1194                              G_STRUCT_OFFSET (GdmGreeterServerClass, language_selected),
1195                              NULL,
1196                              NULL,
1197                              g_cclosure_marshal_VOID__STRING,
1198                              G_TYPE_NONE,
1199                              1,
1200                              G_TYPE_STRING);
1201        signals [LAYOUT_SELECTED] =
1202                g_signal_new ("layout-selected",
1203                              G_OBJECT_CLASS_TYPE (object_class),
1204                              G_SIGNAL_RUN_FIRST,
1205                              G_STRUCT_OFFSET (GdmGreeterServerClass, layout_selected),
1206                              NULL,
1207                              NULL,
1208                              g_cclosure_marshal_VOID__STRING,
1209                              G_TYPE_NONE,
1210                              1,
1211                              G_TYPE_STRING);
1212        signals [USER_SELECTED] =
1213                g_signal_new ("user-selected",
1214                              G_OBJECT_CLASS_TYPE (object_class),
1215                              G_SIGNAL_RUN_FIRST,
1216                              G_STRUCT_OFFSET (GdmGreeterServerClass, user_selected),
1217                              NULL,
1218                              NULL,
1219                              g_cclosure_marshal_VOID__STRING,
1220                              G_TYPE_NONE,
1221                              1,
1222                              G_TYPE_STRING);
1223        signals [CANCELLED] =
1224                g_signal_new ("cancelled",
1225                              G_OBJECT_CLASS_TYPE (object_class),
1226                              G_SIGNAL_RUN_FIRST,
1227                              G_STRUCT_OFFSET (GdmGreeterServerClass, cancelled),
1228                              NULL,
1229                              NULL,
1230                              g_cclosure_marshal_VOID__VOID,
1231                              G_TYPE_NONE,
1232                              0);
1233        signals [CONNECTED] =
1234                g_signal_new ("connected",
1235                              G_OBJECT_CLASS_TYPE (object_class),
1236                              G_SIGNAL_RUN_FIRST,
1237                              G_STRUCT_OFFSET (GdmGreeterServerClass, connected),
1238                              NULL,
1239                              NULL,
1240                              g_cclosure_marshal_VOID__VOID,
1241                              G_TYPE_NONE,
1242                              0);
1243        signals [DISCONNECTED] =
1244                g_signal_new ("disconnected",
1245                              G_OBJECT_CLASS_TYPE (object_class),
1246                              G_SIGNAL_RUN_FIRST,
1247                              G_STRUCT_OFFSET (GdmGreeterServerClass, disconnected),
1248                              NULL,
1249                              NULL,
1250                              g_cclosure_marshal_VOID__VOID,
1251                              G_TYPE_NONE,
1252                              0);
1253
1254        signals [START_SESSION_WHEN_READY] =
1255                g_signal_new ("start-session-when-ready",
1256                              G_OBJECT_CLASS_TYPE (object_class),
1257                              G_SIGNAL_RUN_FIRST,
1258                              G_STRUCT_OFFSET (GdmGreeterServerClass, start_session_when_ready),
1259                              NULL,
1260                              NULL,
1261                              g_cclosure_marshal_VOID__VOID,
1262                              G_TYPE_NONE,
1263                              0);
1264
1265        signals [START_SESSION_LATER] =
1266                g_signal_new ("start-session-later",
1267                              G_OBJECT_CLASS_TYPE (object_class),
1268                              G_SIGNAL_RUN_FIRST,
1269                              G_STRUCT_OFFSET (GdmGreeterServerClass, start_session_later),
1270                              NULL,
1271                              NULL,
1272                              g_cclosure_marshal_VOID__VOID,
1273                              G_TYPE_NONE,
1274                              0);
1275}
1276
1277static void
1278gdm_greeter_server_init (GdmGreeterServer *greeter_server)
1279{
1280
1281        greeter_server->priv = GDM_GREETER_SERVER_GET_PRIVATE (greeter_server);
1282}
1283
1284static void
1285gdm_greeter_server_finalize (GObject *object)
1286{
1287        GdmGreeterServer *greeter_server;
1288
1289        g_return_if_fail (object != NULL);
1290        g_return_if_fail (GDM_IS_GREETER_SERVER (object));
1291
1292        greeter_server = GDM_GREETER_SERVER (object);
1293
1294        g_return_if_fail (greeter_server->priv != NULL);
1295
1296        gdm_greeter_server_stop (greeter_server);
1297
1298        G_OBJECT_CLASS (gdm_greeter_server_parent_class)->finalize (object);
1299}
1300
1301GdmGreeterServer *
1302gdm_greeter_server_new (const char *display_id)
1303{
1304        GObject *object;
1305
1306        object = g_object_new (GDM_TYPE_GREETER_SERVER,
1307                               "display-id", display_id,
1308                               NULL);
1309
1310        return GDM_GREETER_SERVER (object);
1311}
Note: See TracBrowser for help on using the repository browser.