]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blob - src/session.c
Unset environment variables when switch display servers.
[sojka/lightdm.git] / src / session.c
1 /*
2  * Copyright (C) 2010-2011 Robert Ancell.
3  * Author: Robert Ancell <robert.ancell@canonical.com>
4  *
5  * This program is free software: you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License as published by the Free Software
7  * Foundation, either version 3 of the License, or (at your option) any later
8  * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
9  * license.
10  */
11
12 #include <config.h>
13
14 #include <stdlib.h>
15 #include <string.h>
16 #include <errno.h>
17 #include <unistd.h>
18 #include <sys/wait.h>
19 #include <fcntl.h>
20 #include <glib/gstdio.h>
21 #include <grp.h>
22 #include <pwd.h>
23
24 #include "session.h"
25 #include "configuration.h"
26 #include "console-kit.h"
27 #include "login1.h"
28 #include "guest-account.h"
29
30 enum {
31     GOT_MESSAGES,
32     AUTHENTICATION_COMPLETE,
33     STOPPED,
34     LAST_SIGNAL
35 };
36 static guint signals[LAST_SIGNAL] = { 0 };
37
38 struct SessionPrivate
39 {
40     /* Display server running on */
41     DisplayServer *display_server;
42
43     /* PID of child process */
44     GPid pid;
45
46     /* Pipes to talk to child */
47     int to_child_input;
48     int from_child_output;
49     GIOChannel *from_child_channel;
50     guint from_child_watch;
51     guint child_watch;
52
53     /* User to authenticate as */
54     gchar *username;
55
56     /* TRUE if is a guest account */
57     gboolean is_guest;
58
59     /* User object that matches the current username */
60     User *user;
61
62     /* PAM service to use */
63     gchar *pam_service;
64
65     /* TRUE if should run PAM authentication phase */
66     gboolean do_authenticate;
67
68     /* TRUE if can handle PAM prompts */
69     gboolean is_interactive;
70
71     /* Messages being requested by PAM */
72     int messages_length;
73     struct pam_message *messages;
74
75     /* Authentication result from PAM */
76     gboolean authentication_started;
77     gboolean authentication_complete;
78     int authentication_result;
79     gchar *authentication_result_string;
80
81     /* File to log to */
82     gchar *log_filename;
83
84     /* Seat class */
85     gchar *class;
86
87     /* tty this session is running on */
88     gchar *tty;
89
90     /* X display connected to */
91     gchar *xdisplay;
92     XAuthority *x_authority;
93     gboolean x_authority_use_system_location;
94
95     /* Remote host this session is being controlled from */
96     gchar *remote_host_name;
97
98     /* Console kit cookie */
99     gchar *console_kit_cookie;
100
101     /* login1 session */
102     gchar *login1_session;
103
104     /* Environment to set in child */
105     GList *env;
106
107     /* Command to run in child */
108     gchar **argv;
109
110     /* True if have run command */
111     gboolean command_run;
112
113     /* TRUE if stopping this session */
114     gboolean stopping;
115 };
116
117 /* Maximum length of a string to pass between daemon and session */
118 #define MAX_STRING_LENGTH 65535
119
120 G_DEFINE_TYPE (Session, session, G_TYPE_OBJECT);
121
122 Session *
123 session_new (void)
124 {
125     return g_object_new (SESSION_TYPE, NULL);
126 }
127
128 void
129 session_set_pam_service (Session *session, const gchar *pam_service)
130 {
131     g_return_if_fail (session != NULL);
132     g_free (session->priv->pam_service);
133     session->priv->pam_service = g_strdup (pam_service);
134 }
135
136 void
137 session_set_username (Session *session, const gchar *username)
138 {
139     g_return_if_fail (session != NULL);
140     g_free (session->priv->username);
141     session->priv->username = g_strdup (username);
142 }
143
144 void
145 session_set_do_authenticate (Session *session, gboolean do_authenticate)
146 {
147     g_return_if_fail (session != NULL);
148     session->priv->do_authenticate = do_authenticate;
149 }
150
151 void
152 session_set_is_interactive (Session *session, gboolean is_interactive)
153 {
154     g_return_if_fail (session != NULL);
155     session->priv->is_interactive = is_interactive;
156 }
157
158 void
159 session_set_is_guest (Session *session, gboolean is_guest)
160 {
161     g_return_if_fail (session != NULL);
162     session->priv->is_guest = is_guest;
163 }
164
165 gboolean
166 session_get_is_guest (Session *session)
167 {
168     g_return_val_if_fail (session != NULL, FALSE);
169     return session->priv->is_guest;
170 }
171
172 void
173 session_set_log_file (Session *session, const gchar *filename)
174 {
175     g_return_if_fail (session != NULL);
176     g_free (session->priv->log_filename);
177     session->priv->log_filename = g_strdup (filename);
178 }
179
180 void
181 session_set_class (Session *session, const gchar *class)
182 {
183     g_return_if_fail (session != NULL);
184     g_free (session->priv->class);
185     session->priv->class = g_strdup (class);
186 }
187
188 void
189 session_set_display_server (Session *session, DisplayServer *display_server)
190 {
191     g_return_if_fail (session != NULL);
192     g_return_if_fail (display_server != NULL);
193     if (session->priv->display_server)
194     {
195         display_server_disconnect_session (session->priv->display_server, session);
196         g_object_unref (session->priv->display_server);
197     }
198     session->priv->display_server = g_object_ref (display_server);
199 }
200
201 DisplayServer *
202 session_get_display_server (Session *session)
203 {
204     g_return_val_if_fail (session != NULL, NULL);
205     return session->priv->display_server;
206 }
207
208 void
209 session_set_tty (Session *session, const gchar *tty)
210 {
211     g_return_if_fail (session != NULL);
212     g_free (session->priv->tty);
213     session->priv->tty = g_strdup (tty);
214 }
215
216 void
217 session_set_xdisplay (Session *session, const gchar *xdisplay)
218 {
219     g_return_if_fail (session != NULL);
220     g_free (session->priv->xdisplay);
221     session->priv->xdisplay = g_strdup (xdisplay);
222 }
223
224 void
225 session_set_x_authority (Session *session, XAuthority *authority, gboolean use_system_location)
226 {
227     g_return_if_fail (session != NULL);
228     if (session->priv->x_authority)
229     {
230         g_object_unref (session->priv->x_authority);
231         session->priv->x_authority = NULL;
232     }
233     if (authority)
234         session->priv->x_authority = g_object_ref (authority);
235     session->priv->x_authority_use_system_location = use_system_location;
236 }
237
238 void
239 session_set_remote_host_name (Session *session, const gchar *remote_host_name)
240 {
241     g_return_if_fail (session != NULL);
242     g_free (session->priv->remote_host_name);
243     session->priv->remote_host_name = g_strdup (remote_host_name);
244 }
245
246 static GList *
247 find_env_entry (Session *session, const gchar *name)
248 {
249     GList *link;
250
251     for (link = session->priv->env; link; link = link->next)
252     {
253         const gchar *entry = link->data;
254
255         if (g_str_has_prefix (entry, name) && entry[strlen (name)] == '=')
256             return link;
257     }
258
259     return NULL;
260 }
261
262 void
263 session_set_env (Session *session, const gchar *name, const gchar *value)
264 {
265     GList *link;
266     gchar *entry;
267
268     g_return_if_fail (session != NULL);
269     g_return_if_fail (value != NULL);
270
271     entry = g_strdup_printf ("%s=%s", name, value);
272
273     link = find_env_entry (session, name);
274     if (link)
275     {
276         g_free (link->data);
277         link->data = entry;
278     }
279     else
280         session->priv->env = g_list_append (session->priv->env, entry);
281 }
282
283 void
284 session_unset_env (Session *session, const gchar *name)
285 {
286     GList *link;
287
288     g_return_if_fail (session != NULL);
289   
290     link = find_env_entry (session, name);
291     if (!link)
292         return;
293
294     g_free (link->data);
295     session->priv->env = g_list_remove_link (session->priv->env, link);
296 }
297
298 void
299 session_set_argv (Session *session, gchar **argv)
300 {
301     g_return_if_fail (session != NULL);
302     session->priv->argv = g_strdupv (argv);
303 }
304
305 User *
306 session_get_user (Session *session)
307 {
308     g_return_val_if_fail (session != NULL, NULL);
309
310     if (session->priv->username == NULL)
311         return NULL;
312
313     if (!session->priv->user)
314         session->priv->user = accounts_get_user_by_name (session->priv->username);
315
316     return session->priv->user;
317 }
318
319 static void
320 write_data (Session *session, const void *buf, size_t count)
321 {
322     if (write (session->priv->to_child_input, buf, count) != count)
323         g_warning ("Error writing to session: %s", strerror (errno));
324 }
325
326 static void
327 write_string (Session *session, const char *value)
328 {
329     int length;
330
331     length = value ? strlen (value) : -1;
332     write_data (session, &length, sizeof (length));
333     if (value)
334         write_data (session, value, sizeof (char) * length);
335 }
336
337 static void
338 write_xauth (Session *session, XAuthority *x_authority)
339 {
340     guint16 family;
341     gsize length;
342
343     if (!x_authority)
344     {
345         write_string (session, NULL);
346         return;
347     }
348
349     write_string (session, x_authority_get_authorization_name (session->priv->x_authority));
350     family = x_authority_get_family (session->priv->x_authority);
351     write_data (session, &family, sizeof (family));
352     length = x_authority_get_address_length (session->priv->x_authority);
353     write_data (session, &length, sizeof (length));
354     write_data (session, x_authority_get_address (session->priv->x_authority), length);
355     write_string (session, x_authority_get_number (session->priv->x_authority));
356     length = x_authority_get_authorization_data_length (session->priv->x_authority);
357     write_data (session, &length, sizeof (length));
358     write_data (session, x_authority_get_authorization_data (session->priv->x_authority), length);
359 }
360
361 static ssize_t
362 read_from_child (Session *session, void *buf, size_t count)
363 {
364     ssize_t n_read;
365     n_read = read (session->priv->from_child_output, buf, count);
366     if (n_read < 0)
367         g_warning ("Error reading from session: %s", strerror (errno));
368     return n_read;
369 }
370
371 static gchar *
372 read_string_from_child (Session *session)
373 {
374     int length;
375     char *value;
376
377     if (read_from_child (session, &length, sizeof (length)) <= 0)
378         return NULL;
379     if (length < 0)
380         return NULL;
381     if (length > MAX_STRING_LENGTH)
382     {
383         g_warning ("Invalid string length %d from child", length);
384         return NULL;
385     }
386
387     value = g_malloc (sizeof (char) * (length + 1));
388     read_from_child (session, value, length);
389     value[length] = '\0';
390
391     return value;
392 }
393
394 static void
395 session_watch_cb (GPid pid, gint status, gpointer data)
396 {
397     Session *session = data;
398
399     session->priv->pid = 0;
400
401     if (WIFEXITED (status))
402         g_debug ("Session %d exited with return value %d", pid, WEXITSTATUS (status));
403     else if (WIFSIGNALED (status))
404         g_debug ("Session %d terminated with signal %d", pid, WTERMSIG (status));
405
406     /* If failed during authentication then report this as an authentication failure */
407     if (session->priv->authentication_started && !session->priv->authentication_complete)
408     {
409         g_debug ("Session %d failed during authentication", pid);
410         session->priv->authentication_complete = TRUE;
411         session->priv->authentication_result = PAM_CONV_ERR;
412         g_free (session->priv->authentication_result_string);
413         session->priv->authentication_result_string = g_strdup ("Authentication stopped before completion");
414         g_signal_emit (G_OBJECT (session), signals[AUTHENTICATION_COMPLETE], 0);
415     }
416
417     g_signal_emit (G_OBJECT (session), signals[STOPPED], 0);
418
419     /* Delete account if it is a guest one */
420     if (session->priv->is_guest)
421         guest_account_cleanup (session->priv->username);
422
423     /* Drop our reference on the child process, it has terminated */
424     g_object_unref (session);
425 }
426
427 static gboolean
428 from_child_cb (GIOChannel *source, GIOCondition condition, gpointer data)
429 {
430     Session *session = data;
431     gchar *username;
432     ssize_t n_read;
433     gboolean auth_complete;
434
435     /* Remote end gone */
436     if (condition == G_IO_HUP)
437     {
438         session->priv->from_child_watch = 0;
439         return FALSE;
440     }
441
442     /* Get the username currently being authenticated (may change during authentication) */
443     username = read_string_from_child (session);
444     if (g_strcmp0 (username, session->priv->username) != 0)
445     {
446         g_free (session->priv->username);
447         session->priv->username = username;
448         if (session->priv->user)
449             g_object_unref (session->priv->user);
450         session->priv->user = NULL;
451     }
452     else
453         g_free (username);
454
455     /* Check if authentication completed */
456     n_read = read_from_child (session, &auth_complete, sizeof (auth_complete));
457     if (n_read < 0)
458         g_debug ("Error reading from child: %s", strerror (errno));
459     if (n_read <= 0)
460     {
461         session->priv->from_child_watch = 0;
462         return FALSE;
463     }
464
465     if (auth_complete)
466     {
467         session->priv->authentication_complete = TRUE;
468         read_from_child (session, &session->priv->authentication_result, sizeof (session->priv->authentication_result));
469         g_free (session->priv->authentication_result_string);
470         session->priv->authentication_result_string = read_string_from_child (session);
471
472         g_debug ("Session %d authentication complete with return value %d: %s", session->priv->pid, session->priv->authentication_result, session->priv->authentication_result_string);
473
474         /* No longer expect any more messages */
475         session->priv->from_child_watch = 0;
476
477         g_signal_emit (G_OBJECT (session), signals[AUTHENTICATION_COMPLETE], 0);
478
479         return FALSE;
480     }
481     else
482     {
483         int i;
484
485         session->priv->messages_length = 0;
486         read_from_child (session, &session->priv->messages_length, sizeof (session->priv->messages_length));
487         session->priv->messages = calloc (session->priv->messages_length, sizeof (struct pam_message));
488         for (i = 0; i < session->priv->messages_length; i++)
489         {
490             struct pam_message *m = &session->priv->messages[i];
491             read_from_child (session, &m->msg_style, sizeof (m->msg_style));
492             m->msg = read_string_from_child (session);
493         }
494
495         g_debug ("Session %d got %d message(s) from PAM", session->priv->pid, session->priv->messages_length);
496
497         g_signal_emit (G_OBJECT (session), signals[GOT_MESSAGES], 0);
498     }
499
500     return TRUE;
501 }
502
503 gboolean
504 session_start (Session *session)
505 {
506     g_return_val_if_fail (session != NULL, FALSE);
507     g_return_val_if_fail (session->priv->display_server != NULL, FALSE);
508     return SESSION_GET_CLASS (session)->start (session);
509 }
510
511 gboolean
512 session_get_is_started (Session *session)
513 {
514     return session->priv->pid != 0;
515 }
516
517 static gboolean
518 session_real_start (Session *session)
519 {
520     int version;
521     int to_child_pipe[2], from_child_pipe[2];
522     int to_child_output, from_child_input;
523
524     g_return_val_if_fail (session->priv->pid == 0, FALSE);
525
526     display_server_connect_session (session->priv->display_server, session);
527
528     /* Create pipes to talk to the child */
529     if (pipe (to_child_pipe) < 0 || pipe (from_child_pipe) < 0)
530     {
531         g_warning ("Failed to create pipe to communicate with session process: %s", strerror (errno));
532         return FALSE;
533     }
534     to_child_output = to_child_pipe[0];
535     session->priv->to_child_input = to_child_pipe[1];
536     session->priv->from_child_output = from_child_pipe[0];
537     from_child_input = from_child_pipe[1];
538     session->priv->from_child_channel = g_io_channel_unix_new (session->priv->from_child_output);
539     session->priv->from_child_watch = g_io_add_watch (session->priv->from_child_channel, G_IO_IN | G_IO_HUP, from_child_cb, session);
540
541     /* Don't allow the daemon end of the pipes to be accessed in child processes */
542     fcntl (session->priv->to_child_input, F_SETFD, FD_CLOEXEC);
543     fcntl (session->priv->from_child_output, F_SETFD, FD_CLOEXEC);
544
545     /* Create the guest account if it is one */
546     if (session->priv->is_guest && session->priv->username == NULL)
547     {
548         session->priv->username = guest_account_setup ();
549         if (!session->priv->username)
550             return FALSE;
551     }
552
553     /* Run the child */
554     session->priv->pid = fork ();
555     if (session->priv->pid < 0)
556     {
557         g_debug ("Failed to fork session child process: %s", strerror (errno));
558         return FALSE;
559     }
560
561     if (session->priv->pid == 0)
562     {
563         /* Run us again in session child mode */
564         execlp ("lightdm",
565                 "lightdm",
566                 "--session-child",
567                 g_strdup_printf ("%d", to_child_output),
568                 g_strdup_printf ("%d", from_child_input),
569                 NULL);
570         _exit (EXIT_FAILURE);
571     }
572
573     /* Hold a reference on this object until the child process terminates so we
574      * can handle the watch callback even if it is no longer used. Otherwise a
575      * zombie process will remain */
576     g_object_ref (session);
577
578     /* Listen for session termination */
579     session->priv->authentication_started = TRUE;
580     session->priv->child_watch = g_child_watch_add (session->priv->pid, session_watch_cb, session);
581
582     /* Close the ends of the pipes we don't need */
583     close (to_child_output);
584     close (from_child_input);
585
586     /* Indicate what version of the protocol we are using */
587     version = 1;
588     write_data (session, &version, sizeof (version));
589
590     /* Send configuration */
591     write_string (session, session->priv->pam_service);
592     write_string (session, session->priv->username);
593     write_data (session, &session->priv->do_authenticate, sizeof (session->priv->do_authenticate));
594     write_data (session, &session->priv->is_interactive, sizeof (session->priv->is_interactive));
595     write_string (session, session->priv->class);
596     write_string (session, session->priv->tty);
597     write_string (session, session->priv->remote_host_name);
598     write_string (session, session->priv->xdisplay);
599     write_xauth (session, session->priv->x_authority);
600
601     g_debug ("Started session %d with service '%s', username '%s'", session->priv->pid, session->priv->pam_service, session->priv->username);
602
603     return TRUE;
604 }
605
606 const gchar *
607 session_get_username (Session *session)
608 {
609     g_return_val_if_fail (session != NULL, NULL);
610     return session->priv->username;
611 }
612
613 const gchar *
614 session_get_console_kit_cookie (Session *session)
615 {
616     g_return_val_if_fail (session != NULL, NULL);
617     return session->priv->console_kit_cookie;
618 }
619
620 void
621 session_respond (Session *session, struct pam_response *response)
622 {
623     int error = PAM_SUCCESS;
624     int i;
625
626     g_return_if_fail (session != NULL);
627
628     write_data (session, &error, sizeof (error));
629     for (i = 0; i < session->priv->messages_length; i++)
630     {
631         write_string (session, response[i].resp);
632         write_data (session, &response[i].resp_retcode, sizeof (response[i].resp_retcode));
633     }
634
635     /* Delete the old messages */
636     for (i = 0; i < session->priv->messages_length; i++)
637         g_free ((char *) session->priv->messages[i].msg);
638     g_free (session->priv->messages);
639     session->priv->messages = NULL;
640     session->priv->messages_length = 0;
641 }
642
643 void
644 session_respond_error (Session *session, int error)
645 {
646     g_return_if_fail (session != NULL);
647     g_return_if_fail (error != PAM_SUCCESS);
648
649     write_data (session, &error, sizeof (error));
650 }
651
652 int
653 session_get_messages_length (Session *session)
654 {
655     g_return_val_if_fail (session != NULL, 0);
656     return session->priv->messages_length;
657 }
658
659 const struct pam_message *
660 session_get_messages (Session *session)
661 {
662     g_return_val_if_fail (session != NULL, NULL);
663     return session->priv->messages;
664 }
665
666 gboolean
667 session_get_is_authenticated (Session *session)
668 {
669     g_return_val_if_fail (session != NULL, FALSE);
670     return session->priv->authentication_complete && session->priv->authentication_result == PAM_SUCCESS;
671 }
672
673 int
674 session_get_authentication_result (Session *session)
675 {
676     g_return_val_if_fail (session != NULL, 0);
677     return session->priv->authentication_result;
678 }
679
680 const gchar *
681 session_get_authentication_result_string (Session *session)
682 {
683     g_return_val_if_fail (session != NULL, NULL);
684     return session->priv->authentication_result_string;
685 }
686
687 void
688 session_run (Session *session)
689 {
690     g_return_if_fail (session->priv->display_server != NULL);
691     return SESSION_GET_CLASS (session)->run (session);
692 }
693
694 static void
695 session_real_run (Session *session)
696 {
697     gsize i, argc;
698     gchar *command, *x_authority_filename;
699     GList *link;
700
701     g_return_if_fail (session != NULL);
702     g_return_if_fail (!session->priv->command_run);
703     g_return_if_fail (session_get_is_authenticated (session));
704     g_return_if_fail (session->priv->argv != NULL);
705     g_return_if_fail (session->priv->pid != 0);
706
707     display_server_connect_session (session->priv->display_server, session);
708
709     session->priv->command_run = TRUE;
710
711     command = g_strjoinv (" ", session->priv->argv);
712     g_debug ("Session %d running command %s", session->priv->pid, command);
713     g_free (command);
714
715     /* Create authority location */
716     if (session->priv->x_authority_use_system_location)
717     {
718         gchar *run_dir, *dir;
719
720         run_dir = config_get_string (config_get_instance (), "LightDM", "run-directory");
721         dir = g_build_filename (run_dir, session->priv->username, NULL);
722         g_free (run_dir);
723
724         if (g_mkdir_with_parents (dir, S_IRWXU) < 0)
725             g_warning ("Failed to set create system authority dir %s: %s", dir, strerror (errno));          
726         if (getuid () == 0)
727         {
728             if (chown (dir, user_get_uid (session_get_user (session)), user_get_gid (session_get_user (session))) < 0)
729                 g_warning ("Failed to set ownership of user authority dir: %s", strerror (errno));
730         }
731
732         x_authority_filename = g_build_filename (dir, "xauthority", NULL);
733         g_free (dir);
734     }
735     else
736         x_authority_filename = g_build_filename (user_get_home_directory (session_get_user (session)), ".Xauthority", NULL);
737
738     write_string (session, session->priv->log_filename);
739     write_string (session, session->priv->tty);
740     write_string (session, x_authority_filename);
741     g_free (x_authority_filename);
742     write_string (session, session->priv->xdisplay);
743     write_xauth (session, session->priv->x_authority);
744     argc = g_list_length (session->priv->env);
745     write_data (session, &argc, sizeof (argc));
746     for (link = session->priv->env; link; link = link->next)
747         write_string (session, (gchar *) link->data);
748     argc = g_strv_length (session->priv->argv);
749     write_data (session, &argc, sizeof (argc));
750     for (i = 0; i < argc; i++)
751         write_string (session, session->priv->argv[i]);
752
753     if (login1_is_running ())
754         session->priv->login1_session = read_string_from_child (session);
755     if (!session->priv->login1_session)
756         session->priv->console_kit_cookie = read_string_from_child (session);
757 }
758
759 void
760 session_lock (Session *session)
761 {
762     g_return_if_fail (session != NULL);
763     if (getuid () == 0)
764     {
765         if (login1_is_running ())
766             login1_lock_session (session->priv->login1_session);
767         if (!session->priv->login1_session)
768             ck_lock_session (session->priv->console_kit_cookie);
769     }
770 }
771
772 void
773 session_unlock (Session *session)
774 {
775     g_return_if_fail (session != NULL);
776     if (getuid () == 0)
777     {
778         if (login1_is_running ())
779             login1_unlock_session (session->priv->login1_session);
780         if (!session->priv->login1_session)
781             ck_unlock_session (session->priv->console_kit_cookie);
782     }
783 }
784
785 void
786 session_stop (Session *session)
787 {
788     g_return_if_fail (session != NULL);
789
790     if (session->priv->stopping)
791         return;
792     session->priv->stopping = TRUE;
793
794     return SESSION_GET_CLASS (session)->stop (session);
795 }
796
797 static void
798 session_real_stop (Session *session)
799 {
800     g_return_if_fail (session != NULL);
801
802     if (session->priv->pid > 0)
803     {
804         g_debug ("Session %d: Sending SIGTERM", session->priv->pid);
805         kill (session->priv->pid, SIGTERM);
806         // FIXME: Handle timeout
807     }
808     else
809         g_signal_emit (G_OBJECT (session), signals[STOPPED], 0);
810 }
811
812 gboolean
813 session_get_is_stopping (Session *session)
814 {
815     g_return_val_if_fail (session != NULL, FALSE);
816     return session->priv->stopping;
817 }
818
819 static void
820 session_init (Session *session)
821 {
822     session->priv = G_TYPE_INSTANCE_GET_PRIVATE (session, SESSION_TYPE, SessionPrivate);
823     session->priv->log_filename = g_strdup (".xsession-errors");
824 }
825
826 static void
827 session_finalize (GObject *object)
828 {
829     Session *self = SESSION (object);
830     int i;
831
832     if (self->priv->display_server)
833         g_object_unref (self->priv->display_server);
834     if (self->priv->pid)
835         kill (self->priv->pid, SIGKILL);
836     if (self->priv->from_child_channel)
837         g_io_channel_unref (self->priv->from_child_channel);
838     if (self->priv->from_child_watch)
839         g_source_remove (self->priv->from_child_watch);
840     if (self->priv->child_watch)
841         g_source_remove (self->priv->child_watch);
842     g_free (self->priv->username);
843     if (self->priv->user)
844         g_object_unref (self->priv->user);
845     g_free (self->priv->pam_service);
846     for (i = 0; i < self->priv->messages_length; i++)
847         g_free ((char *) self->priv->messages[i].msg);
848     g_free (self->priv->messages);
849     g_free (self->priv->authentication_result_string);
850     g_free (self->priv->log_filename);
851     g_free (self->priv->class);
852     g_free (self->priv->tty);
853     g_free (self->priv->xdisplay);
854     if (self->priv->x_authority)
855         g_object_unref (self->priv->x_authority);
856     g_free (self->priv->remote_host_name);
857     g_free (self->priv->login1_session);
858     g_free (self->priv->console_kit_cookie);
859     g_list_free_full (self->priv->env, g_free);
860     g_strfreev (self->priv->argv);
861
862     G_OBJECT_CLASS (session_parent_class)->finalize (object);
863 }
864
865 static void
866 session_class_init (SessionClass *klass)
867 {
868     GObjectClass *object_class = G_OBJECT_CLASS (klass);
869
870     klass->start = session_real_start;
871     klass->run = session_real_run;
872     klass->stop = session_real_stop;
873     object_class->finalize = session_finalize;
874
875     g_type_class_add_private (klass, sizeof (SessionPrivate));
876
877     signals[GOT_MESSAGES] =
878         g_signal_new ("got-messages",
879                       G_TYPE_FROM_CLASS (klass),
880                       G_SIGNAL_RUN_LAST,
881                       G_STRUCT_OFFSET (SessionClass, got_messages),
882                       NULL, NULL,
883                       NULL,
884                       G_TYPE_NONE, 0);
885
886     signals[AUTHENTICATION_COMPLETE] =
887         g_signal_new ("authentication-complete",
888                       G_TYPE_FROM_CLASS (klass),
889                       G_SIGNAL_RUN_LAST,
890                       G_STRUCT_OFFSET (SessionClass, authentication_complete),
891                       NULL, NULL,
892                       NULL,
893                       G_TYPE_NONE, 0);
894
895     signals[STOPPED] =
896         g_signal_new ("stopped",
897                       G_TYPE_FROM_CLASS (klass),
898                       G_SIGNAL_RUN_LAST,
899                       G_STRUCT_OFFSET (SessionClass, stopped),
900                       NULL, NULL,
901                       NULL,
902                       G_TYPE_NONE, 0);
903 }