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