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