2 * Copyright (C) 2010-2011 Robert Ancell.
3 * Author: Robert Ancell <robert.ancell@canonical.com>
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
20 #include <glib/gstdio.h>
25 #include "configuration.h"
26 #include "console-kit.h"
28 #include "guest-account.h"
29 #include "shared-data-manager.h"
33 AUTHENTICATION_COMPLETE,
37 static guint signals[LAST_SIGNAL] = { 0 };
41 /* Configuration for this session */
42 SessionConfig *config;
44 /* Display server running on */
45 DisplayServer *display_server;
47 /* PID of child process */
50 /* Pipes to talk to child */
52 int from_child_output;
53 GIOChannel *from_child_channel;
54 guint from_child_watch;
57 /* User to authenticate as */
60 /* TRUE if is a guest account */
63 /* User object that matches the current username */
66 /* PAM service to use */
69 /* TRUE if should run PAM authentication phase */
70 gboolean do_authenticate;
72 /* TRUE if can handle PAM prompts */
73 gboolean is_interactive;
75 /* Messages being requested by PAM */
77 struct pam_message *messages;
79 /* Authentication result from PAM */
80 gboolean authentication_started;
81 gboolean authentication_complete;
82 int authentication_result;
83 gchar *authentication_result_string;
89 /* tty this session is running on */
92 /* X display connected to */
94 XAuthority *x_authority;
95 gboolean x_authority_use_system_location;
97 /* Remote host this session is being controlled from */
98 gchar *remote_host_name;
100 /* Console kit cookie */
101 gchar *console_kit_cookie;
103 /* login1 session ID */
104 gchar *login1_session_id;
106 /* Environment to set in child */
109 /* Command to run in child */
112 /* True if have run command */
113 gboolean command_run;
115 /* TRUE if stopping this session */
119 /* Maximum length of a string to pass between daemon and session */
120 #define MAX_STRING_LENGTH 65535
122 static void session_logger_iface_init (LoggerInterface *iface);
124 G_DEFINE_TYPE_WITH_CODE (Session, session, G_TYPE_OBJECT,
125 G_IMPLEMENT_INTERFACE (
126 LOGGER_TYPE, session_logger_iface_init));
131 return g_object_new (SESSION_TYPE, NULL);
135 session_set_config (Session *session, SessionConfig *config)
137 g_return_if_fail (session != NULL);
139 g_clear_object (&session->priv->config);
140 session->priv->config = g_object_ref (config);
144 session_get_config (Session *session)
146 g_return_val_if_fail (session != NULL, NULL);
147 return session->priv->config;
151 session_get_session_type (Session *session)
153 g_return_val_if_fail (session != NULL, NULL);
154 return session_config_get_session_type (session_get_config (session));
158 session_set_pam_service (Session *session, const gchar *pam_service)
160 g_return_if_fail (session != NULL);
161 g_free (session->priv->pam_service);
162 session->priv->pam_service = g_strdup (pam_service);
166 session_set_username (Session *session, const gchar *username)
168 g_return_if_fail (session != NULL);
169 g_free (session->priv->username);
170 session->priv->username = g_strdup (username);
174 session_set_do_authenticate (Session *session, gboolean do_authenticate)
176 g_return_if_fail (session != NULL);
177 session->priv->do_authenticate = do_authenticate;
181 session_set_is_interactive (Session *session, gboolean is_interactive)
183 g_return_if_fail (session != NULL);
184 session->priv->is_interactive = is_interactive;
188 session_set_is_guest (Session *session, gboolean is_guest)
190 g_return_if_fail (session != NULL);
191 session->priv->is_guest = is_guest;
195 session_get_is_guest (Session *session)
197 g_return_val_if_fail (session != NULL, FALSE);
198 return session->priv->is_guest;
202 session_set_log_file (Session *session, const gchar *filename, LogMode log_mode)
204 g_return_if_fail (session != NULL);
205 g_free (session->priv->log_filename);
206 session->priv->log_filename = g_strdup (filename);
207 session->priv->log_mode = log_mode;
211 session_set_display_server (Session *session, DisplayServer *display_server)
213 g_return_if_fail (session != NULL);
214 g_return_if_fail (display_server != NULL);
215 if (session->priv->display_server)
217 display_server_disconnect_session (session->priv->display_server, session);
218 g_object_unref (session->priv->display_server);
220 session->priv->display_server = g_object_ref (display_server);
224 session_get_display_server (Session *session)
226 g_return_val_if_fail (session != NULL, NULL);
227 return session->priv->display_server;
231 session_set_tty (Session *session, const gchar *tty)
233 g_return_if_fail (session != NULL);
234 g_free (session->priv->tty);
235 session->priv->tty = g_strdup (tty);
239 session_set_xdisplay (Session *session, const gchar *xdisplay)
241 g_return_if_fail (session != NULL);
242 g_free (session->priv->xdisplay);
243 session->priv->xdisplay = g_strdup (xdisplay);
247 session_set_x_authority (Session *session, XAuthority *authority, gboolean use_system_location)
249 g_return_if_fail (session != NULL);
250 g_clear_object (&session->priv->x_authority);
252 session->priv->x_authority = g_object_ref (authority);
253 session->priv->x_authority_use_system_location = use_system_location;
257 session_set_remote_host_name (Session *session, const gchar *remote_host_name)
259 g_return_if_fail (session != NULL);
260 g_free (session->priv->remote_host_name);
261 session->priv->remote_host_name = g_strdup (remote_host_name);
265 find_env_entry (Session *session, const gchar *name)
269 for (link = session->priv->env; link; link = link->next)
271 const gchar *entry = link->data;
273 if (g_str_has_prefix (entry, name) && entry[strlen (name)] == '=')
281 session_set_env (Session *session, const gchar *name, const gchar *value)
286 g_return_if_fail (session != NULL);
287 g_return_if_fail (value != NULL);
289 entry = g_strdup_printf ("%s=%s", name, value);
291 link = find_env_entry (session, name);
298 session->priv->env = g_list_append (session->priv->env, entry);
302 session_get_env (Session *session, const gchar *name)
307 link = find_env_entry (session, name);
313 return entry + strlen (name) + 1;
317 session_unset_env (Session *session, const gchar *name)
321 g_return_if_fail (session != NULL);
323 link = find_env_entry (session, name);
328 session->priv->env = g_list_delete_link (session->priv->env, link);
332 session_set_argv (Session *session, gchar **argv)
334 g_return_if_fail (session != NULL);
335 session->priv->argv = g_strdupv (argv);
339 session_get_user (Session *session)
341 g_return_val_if_fail (session != NULL, NULL);
343 if (session->priv->username == NULL)
346 if (!session->priv->user)
347 session->priv->user = accounts_get_user_by_name (session->priv->username);
349 return session->priv->user;
353 write_data (Session *session, const void *buf, size_t count)
355 if (write (session->priv->to_child_input, buf, count) != count)
356 l_warning (session, "Error writing to session: %s", strerror (errno));
360 write_string (Session *session, const char *value)
364 length = value ? strlen (value) : -1;
365 write_data (session, &length, sizeof (length));
367 write_data (session, value, sizeof (char) * length);
371 write_xauth (Session *session, XAuthority *x_authority)
378 write_string (session, NULL);
382 write_string (session, x_authority_get_authorization_name (session->priv->x_authority));
383 family = x_authority_get_family (session->priv->x_authority);
384 write_data (session, &family, sizeof (family));
385 length = x_authority_get_address_length (session->priv->x_authority);
386 write_data (session, &length, sizeof (length));
387 write_data (session, x_authority_get_address (session->priv->x_authority), length);
388 write_string (session, x_authority_get_number (session->priv->x_authority));
389 length = x_authority_get_authorization_data_length (session->priv->x_authority);
390 write_data (session, &length, sizeof (length));
391 write_data (session, x_authority_get_authorization_data (session->priv->x_authority), length);
395 read_from_child (Session *session, void *buf, size_t count)
398 n_read = read (session->priv->from_child_output, buf, count);
400 l_warning (session, "Error reading from session: %s", strerror (errno));
405 read_string_from_child (Session *session)
410 if (read_from_child (session, &length, sizeof (length)) <= 0)
414 if (length > MAX_STRING_LENGTH)
416 l_warning (session, "Invalid string length %d from child", length);
420 value = g_malloc (sizeof (char) * (length + 1));
421 read_from_child (session, value, length);
422 value[length] = '\0';
428 session_watch_cb (GPid pid, gint status, gpointer data)
430 Session *session = data;
432 session->priv->child_watch = 0;
434 if (WIFEXITED (status))
435 l_debug (session, "Exited with return value %d", WEXITSTATUS (status));
436 else if (WIFSIGNALED (status))
437 l_debug (session, "Terminated with signal %d", WTERMSIG (status));
439 /* do this as late as possible for log messages prefix */
440 session->priv->pid = 0;
442 /* If failed during authentication then report this as an authentication failure */
443 if (session->priv->authentication_started && !session->priv->authentication_complete)
445 l_debug (session, "Failed during authentication");
446 session->priv->authentication_complete = TRUE;
447 session->priv->authentication_result = PAM_CONV_ERR;
448 g_free (session->priv->authentication_result_string);
449 session->priv->authentication_result_string = g_strdup ("Authentication stopped before completion");
450 g_signal_emit (G_OBJECT (session), signals[AUTHENTICATION_COMPLETE], 0);
453 g_signal_emit (G_OBJECT (session), signals[STOPPED], 0);
455 /* Delete account if it is a guest one */
456 if (session->priv->is_guest)
457 guest_account_cleanup (session->priv->username);
459 /* Drop our reference on the child process, it has terminated */
460 g_object_unref (session);
464 from_child_cb (GIOChannel *source, GIOCondition condition, gpointer data)
466 Session *session = data;
469 gboolean auth_complete;
471 /* Remote end gone */
472 if (condition == G_IO_HUP)
474 session->priv->from_child_watch = 0;
478 /* Get the username currently being authenticated (may change during authentication) */
479 username = read_string_from_child (session);
480 if (g_strcmp0 (username, session->priv->username) != 0)
482 g_free (session->priv->username);
483 session->priv->username = username;
484 g_clear_object (&session->priv->user);
489 /* Check if authentication completed */
490 n_read = read_from_child (session, &auth_complete, sizeof (auth_complete));
492 l_debug (session, "Error reading from child: %s", strerror (errno));
495 session->priv->from_child_watch = 0;
501 session->priv->authentication_complete = TRUE;
502 read_from_child (session, &session->priv->authentication_result, sizeof (session->priv->authentication_result));
503 g_free (session->priv->authentication_result_string);
504 session->priv->authentication_result_string = read_string_from_child (session);
506 l_debug (session, "Authentication complete with return value %d: %s", session->priv->authentication_result, session->priv->authentication_result_string);
508 /* No longer expect any more messages */
509 session->priv->from_child_watch = 0;
511 g_signal_emit (G_OBJECT (session), signals[AUTHENTICATION_COMPLETE], 0);
519 session->priv->messages_length = 0;
520 read_from_child (session, &session->priv->messages_length, sizeof (session->priv->messages_length));
521 session->priv->messages = calloc (session->priv->messages_length, sizeof (struct pam_message));
522 for (i = 0; i < session->priv->messages_length; i++)
524 struct pam_message *m = &session->priv->messages[i];
525 read_from_child (session, &m->msg_style, sizeof (m->msg_style));
526 m->msg = read_string_from_child (session);
529 l_debug (session, "Got %d message(s) from PAM", session->priv->messages_length);
531 g_signal_emit (G_OBJECT (session), signals[GOT_MESSAGES], 0);
538 session_start (Session *session)
540 g_return_val_if_fail (session != NULL, FALSE);
541 return SESSION_GET_CLASS (session)->start (session);
545 session_get_is_started (Session *session)
547 return session->priv->pid != 0;
551 session_real_start (Session *session)
554 int to_child_pipe[2], from_child_pipe[2];
555 int to_child_output, from_child_input;
558 g_return_val_if_fail (session->priv->pid == 0, FALSE);
560 if (session->priv->display_server)
561 display_server_connect_session (session->priv->display_server, session);
563 /* Create pipes to talk to the child */
564 if (pipe (to_child_pipe) < 0 || pipe (from_child_pipe) < 0)
566 g_warning ("Failed to create pipe to communicate with session process: %s", strerror (errno));
569 to_child_output = to_child_pipe[0];
570 session->priv->to_child_input = to_child_pipe[1];
571 session->priv->from_child_output = from_child_pipe[0];
572 from_child_input = from_child_pipe[1];
573 session->priv->from_child_channel = g_io_channel_unix_new (session->priv->from_child_output);
574 session->priv->from_child_watch = g_io_add_watch (session->priv->from_child_channel, G_IO_IN | G_IO_HUP, from_child_cb, session);
576 /* Don't allow the daemon end of the pipes to be accessed in child processes */
577 fcntl (session->priv->to_child_input, F_SETFD, FD_CLOEXEC);
578 fcntl (session->priv->from_child_output, F_SETFD, FD_CLOEXEC);
580 /* Create the guest account if it is one */
581 if (session->priv->is_guest && session->priv->username == NULL)
583 session->priv->username = guest_account_setup ();
584 if (!session->priv->username)
589 arg0 = g_strdup_printf ("%d", to_child_output);
590 arg1 = g_strdup_printf ("%d", from_child_input);
591 session->priv->pid = fork ();
592 if (session->priv->pid == 0)
594 /* Run us again in session child mode */
599 _exit (EXIT_FAILURE);
604 if (session->priv->pid < 0)
606 g_debug ("Failed to fork session child process: %s", strerror (errno));
610 /* Hold a reference on this object until the child process terminates so we
611 * can handle the watch callback even if it is no longer used. Otherwise a
612 * zombie process will remain */
613 g_object_ref (session);
615 /* Listen for session termination */
616 session->priv->authentication_started = TRUE;
617 session->priv->child_watch = g_child_watch_add (session->priv->pid, session_watch_cb, session);
619 /* Close the ends of the pipes we don't need */
620 close (to_child_output);
621 close (from_child_input);
623 /* Indicate what version of the protocol we are using */
625 write_data (session, &version, sizeof (version));
627 /* Send configuration */
628 write_string (session, session->priv->pam_service);
629 write_string (session, session->priv->username);
630 write_data (session, &session->priv->do_authenticate, sizeof (session->priv->do_authenticate));
631 write_data (session, &session->priv->is_interactive, sizeof (session->priv->is_interactive));
632 write_string (session, NULL); /* Used to be class, now we just use the environment variable */
633 write_string (session, session->priv->tty);
634 write_string (session, session->priv->remote_host_name);
635 write_string (session, session->priv->xdisplay);
636 write_xauth (session, session->priv->x_authority);
638 l_debug (session, "Started with service '%s', username '%s'", session->priv->pam_service, session->priv->username);
644 session_get_username (Session *session)
646 g_return_val_if_fail (session != NULL, NULL);
647 return session->priv->username;
651 session_get_login1_session_id (Session *session)
653 g_return_val_if_fail (session != NULL, NULL);
654 return session->priv->login1_session_id;
658 session_get_console_kit_cookie (Session *session)
660 g_return_val_if_fail (session != NULL, NULL);
661 return session->priv->console_kit_cookie;
665 session_respond (Session *session, struct pam_response *response)
667 int error = PAM_SUCCESS;
670 g_return_if_fail (session != NULL);
672 write_data (session, &error, sizeof (error));
673 for (i = 0; i < session->priv->messages_length; i++)
675 write_string (session, response[i].resp);
676 write_data (session, &response[i].resp_retcode, sizeof (response[i].resp_retcode));
679 /* Delete the old messages */
680 for (i = 0; i < session->priv->messages_length; i++)
681 g_free ((char *) session->priv->messages[i].msg);
682 g_free (session->priv->messages);
683 session->priv->messages = NULL;
684 session->priv->messages_length = 0;
688 session_respond_error (Session *session, int error)
690 g_return_if_fail (session != NULL);
691 g_return_if_fail (error != PAM_SUCCESS);
693 write_data (session, &error, sizeof (error));
697 session_get_messages_length (Session *session)
699 g_return_val_if_fail (session != NULL, 0);
700 return session->priv->messages_length;
703 const struct pam_message *
704 session_get_messages (Session *session)
706 g_return_val_if_fail (session != NULL, NULL);
707 return session->priv->messages;
711 session_get_is_authenticated (Session *session)
713 g_return_val_if_fail (session != NULL, FALSE);
714 return session->priv->authentication_complete && session->priv->authentication_result == PAM_SUCCESS;
718 session_get_authentication_result (Session *session)
720 g_return_val_if_fail (session != NULL, 0);
721 return session->priv->authentication_result;
725 session_get_authentication_result_string (Session *session)
727 g_return_val_if_fail (session != NULL, NULL);
728 return session->priv->authentication_result_string;
732 session_run (Session *session)
734 g_return_if_fail (session->priv->display_server != NULL);
735 return SESSION_GET_CLASS (session)->run (session);
739 session_real_run (Session *session)
742 gchar *command, *x_authority_filename;
745 g_return_if_fail (session != NULL);
746 g_return_if_fail (!session->priv->command_run);
747 g_return_if_fail (session_get_is_authenticated (session));
748 g_return_if_fail (session->priv->argv != NULL);
749 g_return_if_fail (session->priv->pid != 0);
751 display_server_connect_session (session->priv->display_server, session);
753 session->priv->command_run = TRUE;
755 command = g_strjoinv (" ", session->priv->argv);
756 l_debug (session, "Running command %s", command);
759 /* Create authority location */
760 if (session->priv->x_authority_use_system_location)
762 gchar *run_dir, *dir;
764 run_dir = config_get_string (config_get_instance (), "LightDM", "run-directory");
765 dir = g_build_filename (run_dir, session->priv->username, NULL);
768 if (g_mkdir_with_parents (dir, S_IRWXU) < 0)
769 l_warning (session, "Failed to set create system authority dir %s: %s", dir, strerror (errno));
772 if (chown (dir, user_get_uid (session_get_user (session)), user_get_gid (session_get_user (session))) < 0)
773 l_warning (session, "Failed to set ownership of user authority dir: %s", strerror (errno));
776 x_authority_filename = g_build_filename (dir, "xauthority", NULL);
780 x_authority_filename = g_build_filename (user_get_home_directory (session_get_user (session)), ".Xauthority", NULL);
782 /* Make sure shared user directory for this user exists */
783 if (!session->priv->remote_host_name)
785 gchar *data_dir = shared_data_manager_ensure_user_dir (shared_data_manager_get_instance (), session->priv->username);
788 session_set_env (session, "XDG_GREETER_DATA_DIR", data_dir);
793 if (session->priv->log_filename)
794 l_debug (session, "Logging to %s", session->priv->log_filename);
795 write_string (session, session->priv->log_filename);
796 write_data (session, &session->priv->log_mode, sizeof (session->priv->log_mode));
797 write_string (session, session->priv->tty);
798 write_string (session, x_authority_filename);
799 g_free (x_authority_filename);
800 write_string (session, session->priv->xdisplay);
801 write_xauth (session, session->priv->x_authority);
802 argc = g_list_length (session->priv->env);
803 write_data (session, &argc, sizeof (argc));
804 for (link = session->priv->env; link; link = link->next)
805 write_string (session, (gchar *) link->data);
806 argc = g_strv_length (session->priv->argv);
807 write_data (session, &argc, sizeof (argc));
808 for (i = 0; i < argc; i++)
809 write_string (session, session->priv->argv[i]);
811 session->priv->login1_session_id = read_string_from_child (session);
812 session->priv->console_kit_cookie = read_string_from_child (session);
816 session_lock (Session *session)
818 g_return_if_fail (session != NULL);
821 if (session->priv->login1_session_id)
822 login1_service_lock_session (login1_service_get_instance (), session->priv->login1_session_id);
823 else if (session->priv->console_kit_cookie)
824 ck_lock_session (session->priv->console_kit_cookie);
829 session_unlock (Session *session)
831 g_return_if_fail (session != NULL);
834 if (session->priv->login1_session_id)
835 login1_service_unlock_session (login1_service_get_instance (), session->priv->login1_session_id);
836 else if (session->priv->console_kit_cookie)
837 ck_unlock_session (session->priv->console_kit_cookie);
842 session_activate (Session *session)
844 g_return_if_fail (session != NULL);
847 if (session->priv->login1_session_id)
848 login1_service_activate_session (login1_service_get_instance (), session->priv->login1_session_id);
849 else if (session->priv->console_kit_cookie)
850 ck_activate_session (session->priv->console_kit_cookie);
855 session_stop (Session *session)
857 g_return_if_fail (session != NULL);
859 /* If can cleanly stop then do that */
860 if (session_get_is_authenticated (session) && !session->priv->command_run)
863 LogMode log_mode = LOG_MODE_INVALID;
865 session->priv->command_run = TRUE;
866 write_string (session, NULL); // log filename
867 write_data (session, &log_mode, sizeof (log_mode)); // log mode
868 write_string (session, NULL); // tty
869 write_string (session, NULL); // xauth filename
870 write_string (session, NULL); // xdisplay
871 write_xauth (session, NULL); // xauth
872 write_data (session, &n, sizeof (n)); // environment
873 write_data (session, &n, sizeof (n)); // command
877 if (session->priv->stopping)
879 session->priv->stopping = TRUE;
881 return SESSION_GET_CLASS (session)->stop (session);
885 session_real_stop (Session *session)
887 g_return_if_fail (session != NULL);
889 if (session->priv->pid > 0)
891 l_debug (session, "Sending SIGTERM");
892 kill (session->priv->pid, SIGTERM);
893 // FIXME: Handle timeout
896 g_signal_emit (G_OBJECT (session), signals[STOPPED], 0);
900 session_get_is_stopping (Session *session)
902 g_return_val_if_fail (session != NULL, FALSE);
903 return session->priv->stopping;
907 session_init (Session *session)
909 session->priv = G_TYPE_INSTANCE_GET_PRIVATE (session, SESSION_TYPE, SessionPrivate);
910 session->priv->log_filename = g_strdup (".xsession-errors");
911 session->priv->log_mode = LOG_MODE_BACKUP_AND_TRUNCATE;
912 session->priv->to_child_input = -1;
913 session->priv->from_child_output = -1;
917 session_finalize (GObject *object)
919 Session *self = SESSION (object);
922 g_clear_object (&self->priv->config);
923 g_clear_object (&self->priv->display_server);
925 kill (self->priv->pid, SIGKILL);
926 close (self->priv->to_child_input);
927 close (self->priv->from_child_output);
928 if (self->priv->from_child_channel)
929 g_io_channel_unref (self->priv->from_child_channel);
930 if (self->priv->from_child_watch)
931 g_source_remove (self->priv->from_child_watch);
932 if (self->priv->child_watch)
933 g_source_remove (self->priv->child_watch);
934 g_free (self->priv->username);
935 g_clear_object (&self->priv->user);
936 g_free (self->priv->pam_service);
937 for (i = 0; i < self->priv->messages_length; i++)
938 g_free ((char *) self->priv->messages[i].msg);
939 g_free (self->priv->messages);
940 g_free (self->priv->authentication_result_string);
941 g_free (self->priv->log_filename);
942 g_free (self->priv->tty);
943 g_free (self->priv->xdisplay);
944 g_clear_object (&self->priv->x_authority);
945 g_free (self->priv->remote_host_name);
946 g_free (self->priv->login1_session_id);
947 g_free (self->priv->console_kit_cookie);
948 g_list_free_full (self->priv->env, g_free);
949 g_strfreev (self->priv->argv);
951 G_OBJECT_CLASS (session_parent_class)->finalize (object);
955 session_class_init (SessionClass *klass)
957 GObjectClass *object_class = G_OBJECT_CLASS (klass);
959 klass->start = session_real_start;
960 klass->run = session_real_run;
961 klass->stop = session_real_stop;
962 object_class->finalize = session_finalize;
964 g_type_class_add_private (klass, sizeof (SessionPrivate));
966 signals[GOT_MESSAGES] =
967 g_signal_new (SESSION_SIGNAL_GOT_MESSAGES,
968 G_TYPE_FROM_CLASS (klass),
970 G_STRUCT_OFFSET (SessionClass, got_messages),
975 signals[AUTHENTICATION_COMPLETE] =
976 g_signal_new (SESSION_SIGNAL_AUTHENTICATION_COMPLETE,
977 G_TYPE_FROM_CLASS (klass),
979 G_STRUCT_OFFSET (SessionClass, authentication_complete),
985 g_signal_new (SESSION_SIGNAL_STOPPED,
986 G_TYPE_FROM_CLASS (klass),
988 G_STRUCT_OFFSET (SessionClass, stopped),
995 session_real_logprefix (Logger *self, gchar *buf, gulong buflen)
997 Session *session = SESSION (self);
998 if (session->priv->pid != 0)
999 return g_snprintf (buf, buflen, "Session pid=%d: ", session->priv->pid);
1001 return g_snprintf (buf, buflen, "Session: ");
1005 session_logger_iface_init (LoggerInterface *iface)
1007 iface->logprefix = &session_real_logprefix;