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
18 #include <glib/gstdio.h>
22 #include "configuration.h"
26 /* Authentication for this session */
27 PAMSession *authentication;
29 /* Command to run for this session */
32 /* Cookie for the session */
35 /* TRUE if this is a greeter session */
39 G_DEFINE_TYPE (Session, session, PROCESS_TYPE);
42 session_set_authentication (Session *session, PAMSession *authentication)
44 g_return_if_fail (session != NULL);
45 session->priv->authentication = g_object_ref (authentication);
49 session_get_authentication (Session *session)
51 g_return_val_if_fail (session != NULL, NULL);
52 return session->priv->authentication;
56 session_get_user (Session *session)
58 g_return_val_if_fail (session != NULL, NULL);
59 return pam_session_get_user (session->priv->authentication);
63 session_set_is_greeter (Session *session, gboolean is_greeter)
65 g_return_if_fail (session != NULL);
66 session->priv->is_greeter = is_greeter;
70 session_get_is_greeter (Session *session)
72 g_return_val_if_fail (session != NULL, FALSE);
73 return session->priv->is_greeter;
77 session_set_command (Session *session, const gchar *command)
79 g_return_if_fail (session != NULL);
81 g_free (session->priv->command);
82 session->priv->command = g_strdup (command);
86 session_get_command (Session *session)
88 g_return_val_if_fail (session != NULL, NULL);
89 return session->priv->command;
93 session_set_cookie (Session *session, const gchar *cookie)
95 g_return_if_fail (session != NULL);
97 g_free (session->priv->cookie);
98 session->priv->cookie = g_strdup (cookie);
102 session_get_cookie (Session *session)
104 g_return_val_if_fail (session != NULL, NULL);
105 return session->priv->cookie;
109 get_absolute_command (const gchar *command)
112 gchar *absolute_binary, *absolute_command = NULL;
114 tokens = g_strsplit (command, " ", 2);
116 absolute_binary = g_find_program_in_path (tokens[0]);
120 absolute_command = g_strjoin (" ", absolute_binary, tokens[1], NULL);
122 absolute_command = g_strdup (absolute_binary);
127 return absolute_command;
131 set_env_from_authentication (Session *session, PAMSession *authentication)
135 pam_env = pam_session_get_envlist (authentication);
141 env_string = g_strjoinv (" ", pam_env);
142 g_debug ("PAM returns environment '%s'", env_string);
145 for (i = 0; pam_env[i]; i++)
147 gchar **pam_env_vars = g_strsplit (pam_env[i], "=", 2);
148 if (pam_env_vars && pam_env_vars[0] && pam_env_vars[1])
149 process_set_env (PROCESS (session), pam_env_vars[0], pam_env_vars[1]);
151 g_warning ("Can't parse PAM environment variable %s", pam_env[i]);
152 g_strfreev (pam_env_vars);
154 g_strfreev (pam_env);
159 session_real_start (Session *session)
161 //gint session_stdin, session_stdout, session_stderr;
164 gchar *absolute_command;
165 const gchar *orig_path;
166 GError *error = NULL;
168 g_return_val_if_fail (session->priv->authentication != NULL, FALSE);
169 g_return_val_if_fail (session->priv->command != NULL, FALSE);
171 absolute_command = get_absolute_command (session->priv->command);
172 if (!absolute_command)
174 g_debug ("Can't launch session %s, not found in path", session->priv->command);
178 pam_session_open (session->priv->authentication);
180 g_debug ("Launching session");
182 user = pam_session_get_user (session->priv->authentication);
183 process_set_env (PROCESS (session), "PATH", "/usr/local/bin:/usr/bin:/bin");
184 process_set_env (PROCESS (session), "USER", user_get_name (user));
185 process_set_env (PROCESS (session), "USERNAME", user_get_name (user)); // FIXME: Is this required?
186 process_set_env (PROCESS (session), "HOME", user_get_home_directory (user));
187 process_set_env (PROCESS (session), "SHELL", user_get_shell (user));
188 set_env_from_authentication (session, session->priv->authentication);
190 /* Insert our own utility directory to PATH
191 * This is to provide gdmflexiserver which provides backwards compatibility with GDM.
192 * Must be done after set_env_from_authentication because that often sets PATH.
193 * This can be removed when this is no longer required.
195 orig_path = process_get_env (PROCESS (session), "PATH");
198 gchar *path = g_strdup_printf ("%s:%s", PKGLIBEXEC_DIR, orig_path);
199 process_set_env (PROCESS (session), "PATH", path);
203 if (session->priv->cookie)
204 process_set_env (PROCESS (session), "XDG_SESSION_COOKIE", session->priv->cookie);
206 result = process_start (PROCESS (session),
208 user_get_home_directory (user),
211 g_free (absolute_command);
214 g_warning ("Failed to spawn session: %s", error->message);
215 g_clear_error (&error);
221 session_start (Session *session)
223 g_return_val_if_fail (session != NULL, FALSE);
224 return SESSION_GET_CLASS (session)->start (session);
228 session_real_stop (Session *session)
230 process_signal (PROCESS (session), SIGTERM);
234 session_stop (Session *session)
236 g_return_if_fail (session != NULL);
237 SESSION_GET_CLASS (session)->stop (session);
241 session_stopped (Process *process)
243 Session *session = SESSION (process);
245 pam_session_close (session->priv->authentication);
247 PROCESS_CLASS (session_parent_class)->stopped (process);
251 session_init (Session *session)
253 session->priv = G_TYPE_INSTANCE_GET_PRIVATE (session, SESSION_TYPE, SessionPrivate);
257 session_finalize (GObject *object)
261 self = SESSION (object);
263 if (self->priv->authentication)
264 g_object_unref (self->priv->authentication);
265 g_free (self->priv->command);
266 g_free (self->priv->cookie);
268 G_OBJECT_CLASS (session_parent_class)->finalize (object);
272 session_class_init (SessionClass *klass)
274 GObjectClass *object_class = G_OBJECT_CLASS (klass);
275 ProcessClass *process_class = PROCESS_CLASS (klass);
277 klass->start = session_real_start;
278 klass->stop = session_real_stop;
279 process_class->stopped = session_stopped;
280 object_class->finalize = session_finalize;
282 g_type_class_add_private (klass, sizeof (SessionPrivate));