1 /* vi: set et sw=4 ts=4 cino=t0,(0: */
2 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
4 * This file is part of tlm (Tizen Login Manager)
6 * Copyright (C) 2013-2014 Intel Corporation.
8 * Contact: Amarnath Valluri <amarnath.valluri@linux.intel.com>
9 * Jussi Laako <jussi.laako@linux.intel.com>
10 * Imran Zaman <imran.zaman@intel.com>
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
38 #include <sys/types.h>
41 #include <sys/ioctl.h>
43 #include <sys/socket.h>
48 #include <glib/gstdio.h>
50 #include "tlm-session.h"
51 #include "tlm-auth-session.h"
52 #include "common/tlm-log.h"
53 #include "common/tlm-utils.h"
54 #include "common/tlm-error.h"
55 #include "common/tlm-config-general.h"
56 #include "common/tlm-config-seat.h"
58 G_DEFINE_TYPE (TlmSession, tlm_session, G_TYPE_OBJECT);
60 #define TLM_SESSION_PRIV(obj) \
61 G_TYPE_INSTANCE_GET_PRIVATE ((obj), TLM_TYPE_SESSION, TlmSessionPrivate)
64 #define KDSKBMUTE 0x4B51
76 static GParamSpec *pspecs[N_PROPERTIES];
80 SIG_SESSION_TERMINATED,
85 static guint signals[SIG_MAX];
87 struct _TlmSessionPrivate
94 struct termios stdin_state, stdout_state, stderr_state;
99 TlmAuthSession *auth_session;
102 guint child_watch_id;
104 gchar *xdg_runtime_dir;
105 gboolean setup_runtime_dir;
106 gboolean can_emit_signal;
107 gboolean is_child_up;
108 gboolean session_pause;
112 _clear_session (TlmSession *session)
114 tlm_session_reset_tty (session);
115 if (session->priv->setup_runtime_dir)
116 tlm_utils_delete_dir (session->priv->xdg_runtime_dir);
118 if (session->priv->timer_id) {
119 g_source_remove (session->priv->timer_id);
120 session->priv->timer_id = 0;
123 if (session->priv->child_watch_id) {
124 g_source_remove (session->priv->child_watch_id);
125 session->priv->child_watch_id = 0;
128 if (session->priv->auth_session)
129 g_clear_object (&session->priv->auth_session);
131 if (session->priv->env_hash) {
132 g_hash_table_unref (session->priv->env_hash);
133 session->priv->env_hash = NULL;
135 g_clear_string (&session->priv->seat_id);
136 g_clear_string (&session->priv->service);
137 g_clear_string (&session->priv->username);
138 g_clear_string (&session->priv->sessionid);
139 g_clear_string (&session->priv->xdg_runtime_dir);
143 tlm_session_dispose (GObject *self)
145 TlmSession *session = TLM_SESSION(self);
146 TlmSessionPrivate *priv = session->priv;
147 DBG("disposing session: %s", priv->service);
148 priv->can_emit_signal = FALSE;
150 tlm_session_terminate (session);
151 while (priv->is_child_up)
152 g_main_context_iteration(NULL, TRUE);
154 g_clear_object (&session->priv->config);
156 G_OBJECT_CLASS (tlm_session_parent_class)->dispose (self);
160 tlm_session_finalize (GObject *self)
162 //TlmSession *session = TLM_SESSION(self);
163 G_OBJECT_CLASS (tlm_session_parent_class)->finalize (self);
167 _session_set_property (GObject *obj,
172 TlmSession *session = TLM_SESSION(obj);
173 TlmSessionPrivate *priv = TLM_SESSION_PRIV (session);
175 switch (property_id) {
177 priv->config = g_value_dup_object (value);
180 g_free (priv->seat_id);
181 priv->seat_id = g_value_dup_string (value);
184 priv->service = g_value_dup_string (value);
187 priv->username = g_value_dup_string (value);
189 case PROP_ENVIRONMENT:
190 priv->env_hash = (GHashTable *) g_value_get_pointer (value);
192 g_hash_table_ref (priv->env_hash);
195 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec);
200 _session_get_property (GObject *obj,
205 TlmSession *session = TLM_SESSION(obj);
206 TlmSessionPrivate *priv = TLM_SESSION_PRIV (session);
208 switch (property_id) {
210 g_value_set_object (value, priv->config);
213 g_value_set_string (value, priv->seat_id);
216 g_value_set_string (value, priv->service);
219 g_value_set_string (value, priv->username);
221 case PROP_ENVIRONMENT:
222 g_value_set_pointer (value, priv->env_hash);
225 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec);
230 tlm_session_class_init (TlmSessionClass *klass)
232 GObjectClass *g_klass = G_OBJECT_CLASS (klass);
234 g_type_class_add_private (klass, sizeof (TlmSessionPrivate));
236 g_klass->dispose = tlm_session_dispose ;
237 g_klass->finalize = tlm_session_finalize;
238 g_klass->set_property = _session_set_property;
239 g_klass->get_property = _session_get_property;
241 pspecs[PROP_CONFIG] =
242 g_param_spec_object ("config",
244 "Configuration object",
247 G_PARAM_STATIC_STRINGS);
249 g_param_spec_string ("seat",
253 G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS);
254 pspecs[PROP_SERVICE] =
255 g_param_spec_string ("service",
256 "authentication service",
259 G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS);
260 pspecs[PROP_USERNAME] =
261 g_param_spec_string ("username",
263 "Unix user name of user to login",
265 G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS);
266 pspecs[PROP_ENVIRONMENT] =
267 g_param_spec_pointer ("environment",
268 "environment variables",
269 "Environment variables for the session",
270 G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS);
272 g_object_class_install_properties (g_klass, N_PROPERTIES, pspecs);
274 signals[SIG_SESSION_CREATED] = g_signal_new ("session-created",
275 TLM_TYPE_SESSION, G_SIGNAL_RUN_LAST,
276 0, NULL, NULL, NULL, G_TYPE_NONE,
279 signals[SIG_SESSION_TERMINATED] = g_signal_new ("session-terminated",
280 TLM_TYPE_SESSION, G_SIGNAL_RUN_LAST,
281 0, NULL, NULL, NULL, G_TYPE_NONE,
284 signals[SIG_AUTHENTICATED] = g_signal_new ("authenticated",
285 TLM_TYPE_SESSION, G_SIGNAL_RUN_LAST,
286 0, NULL, NULL, NULL, G_TYPE_NONE,
289 signals[SIG_SESSION_ERROR] = g_signal_new ("session-error",
290 TLM_TYPE_SESSION, G_SIGNAL_RUN_LAST,
291 0, NULL, NULL, NULL, G_TYPE_NONE,
297 tlm_session_init (TlmSession *session)
299 TlmSessionPrivate *priv = TLM_SESSION_PRIV (session);
301 priv->service = NULL;
302 priv->env_hash = NULL;
303 priv->auth_session = NULL;
304 priv->sessionid = NULL;
305 priv->child_watch_id = 0;
306 priv->is_child_up = FALSE;
307 priv->can_emit_signal = TRUE;
308 priv->config = tlm_config_new ();
310 session->priv = priv;
312 struct stat tty_stat;
314 if (fstat (0, &tty_stat) == 0) {
315 priv->tty_uid = tty_stat.st_uid;
316 priv->tty_gid = tty_stat.st_gid;
322 if (tcgetattr (0, &priv->stdin_state) ||
323 tcgetattr (1, &priv->stdout_state) ||
324 tcgetattr (2, &priv->stderr_state))
325 WARN ("Failed to retrieve initial terminal state");
329 _setenv_to_session (const gchar *key, const gchar *val,
330 TlmSessionPrivate *user_data)
332 TlmSessionPrivate *priv = (TlmSessionPrivate *) user_data;
333 if (priv->session_pause)
334 tlm_auth_session_set_env (priv->auth_session,
336 (const gchar *) val);
338 setenv ((const char *) key, (const char *) val, 1);
342 _set_terminal (TlmSessionPrivate *priv)
348 gchar *tty_dev = NULL;
349 struct stat tty_stat;
351 DBG ("VTNR is %u", priv->vtnr);
352 if (priv->vtnr > 0) {
353 tty_dev = g_strdup_printf ("/dev/tty%u", priv->vtnr);
355 tty_dev = g_strdup (ttyname (0));
357 DBG ("trying to setup TTY '%s'", tty_dev);
363 if (access (tty_dev, R_OK|W_OK)) {
364 WARN ("TTY not accessible: %s", strerror(errno));
368 if (lstat (tty_dev, &tty_stat)) {
369 WARN ("lstat() failed: %s", strerror(errno));
373 if (tty_stat.st_nlink > 1 ||
374 !S_ISCHR (tty_stat.st_mode) ||
375 strncmp (tty_dev, "/dev/", 5)) {
376 WARN ("Invalid TTY");
381 tty_fd = open (tty_dev, O_RDWR | O_NONBLOCK);
383 WARN ("open() failed: %s", strerror(errno));
387 if (!isatty (tty_fd)) {
389 WARN ("isatty() failed");
393 if (ioctl (tty_fd, TIOCSCTTY, 1))
394 WARN ("ioctl(TIOCSCTTY) failed: %s", strerror(errno));
395 tty_pgid = getpgid (getpid ());
396 if (ioctl (tty_fd, TIOCSPGRP, &tty_pgid)) {
397 WARN ("ioctl(TIOCSPGRP) failed: %s", strerror(errno));
400 /* TODO: unset the mode on session cleanup */
401 if (ioctl(tty_fd, KDSKBMUTE, 1) &&
402 ioctl(tty_fd, KDSKBMODE, K_OFF)) {
403 WARN ("ioctl(KDSKBMODE) failed: %s", strerror(errno));
406 /*if (tcsetpgrp (tty_fd, getpgrp ()))
407 WARN ("tcsetpgrp() failed: %s", strerror(errno));*/
409 // close all old handles
410 for (i = 0; i < tty_fd; i++)
423 _set_environment (TlmSessionPrivate *priv)
425 gchar **envlist = tlm_auth_session_get_envlist(priv->auth_session);
426 const gchar *home_dir = NULL, *shell = NULL;
430 for (env = envlist; *env != NULL; ++env) {
431 DBG ("ENV : %s", *env);
438 const gchar *path = tlm_config_get_string (priv->config,
440 TLM_CONFIG_GENERAL_SESSION_PATH);
442 path = "/usr/local/bin:/usr/bin:/bin";
443 _setenv_to_session ("PATH", path, priv);
445 _setenv_to_session ("USER", priv->username, priv);
446 _setenv_to_session ("LOGNAME", priv->username, priv);
447 home_dir = tlm_user_get_home_dir (priv->username);
448 if (home_dir) _setenv_to_session ("HOME", home_dir, priv);
449 shell = tlm_user_get_shell (priv->username);
450 if (shell) _setenv_to_session ("SHELL", shell, priv);
452 if (!tlm_config_has_key (priv->config,
454 TLM_CONFIG_GENERAL_NSEATS))
455 _setenv_to_session ("XDG_SEAT", priv->seat_id, priv);
457 const gchar *xdg_data_dirs =
458 tlm_config_get_string (priv->config,
460 TLM_CONFIG_GENERAL_DATA_DIRS);
462 xdg_data_dirs = "/usr/share:/usr/local/share";
463 _setenv_to_session ("XDG_DATA_DIRS", xdg_data_dirs, priv);
465 if (priv->xdg_runtime_dir)
466 _setenv_to_session ("XDG_RUNTIME_DIR", priv->xdg_runtime_dir, priv);
469 g_hash_table_foreach (priv->env_hash,
470 (GHFunc) _setenv_to_session,
482 g_spawn_close_pid (pid);
484 TlmSession *session = TLM_SESSION (data);
486 DBG ("Sessiond(%p) with pid (%d) closed with status %d", session, pid,
489 session->priv->child_pid = 0;
490 session->priv->is_child_up = FALSE;
491 _clear_session (session);
492 if (session->priv->can_emit_signal)
493 g_signal_emit (session, signals[SIG_SESSION_TERMINATED], 0);
501 guint rtdir_perm = 0700;
502 const gchar *pattern = "('.*?'|\".*?\"|\\S+)";
503 const gchar *rtdir_perm_str;
505 const char *shell = NULL;
506 const char *env_shell = NULL;
509 gchar **args_iter = NULL;
510 TlmSessionPrivate *priv = session->priv;
511 gchar **temp_strv = NULL;
513 priv = session->priv;
515 priv->username = g_strdup (tlm_auth_session_get_username (
516 priv->auth_session));
517 DBG ("session ID : %s", priv->sessionid);
519 if (tlm_config_has_key (priv->config,
521 TLM_CONFIG_GENERAL_SETUP_RUNTIME_DIR)) {
522 priv->setup_runtime_dir = tlm_config_get_boolean (priv->config,
524 TLM_CONFIG_GENERAL_SETUP_RUNTIME_DIR,
527 priv->setup_runtime_dir = tlm_config_get_boolean (priv->config,
529 TLM_CONFIG_GENERAL_SETUP_RUNTIME_DIR,
532 rtdir_perm_str = tlm_config_get_string (priv->config,
534 TLM_CONFIG_GENERAL_RUNTIME_MODE);
536 rtdir_perm_str = tlm_config_get_string (priv->config,
538 TLM_CONFIG_GENERAL_RUNTIME_MODE);
539 uid_str = g_strdup_printf ("%u", tlm_user_get_uid (priv->username));
540 priv->xdg_runtime_dir = g_build_filename ("/run/user",
544 if (priv->setup_runtime_dir) {
545 tlm_utils_delete_dir (priv->xdg_runtime_dir);
546 if (g_mkdir_with_parents ("/run/user", 0755))
547 WARN ("g_mkdir_with_parents(\"/run/user\") failed");
549 sscanf(rtdir_perm_str, "%o", &rtdir_perm);
550 DBG ("setting up XDG_RUNTIME_DIR=%s mode=%o",
551 priv->xdg_runtime_dir, rtdir_perm);
552 if (g_mkdir (priv->xdg_runtime_dir, rtdir_perm))
553 WARN ("g_mkdir(\"%s\") failed", priv->xdg_runtime_dir);
554 if (chown (priv->xdg_runtime_dir,
555 tlm_user_get_uid (priv->username),
556 tlm_user_get_gid (priv->username)))
557 WARN ("chown(\"%s\"): %s", priv->xdg_runtime_dir, strerror(errno));
558 if (chmod (priv->xdg_runtime_dir, rtdir_perm))
559 WARN ("chmod(\"%s\"): %s", priv->xdg_runtime_dir, strerror(errno));
561 DBG ("not setting up XDG_RUNTIME_DIR");
564 priv->child_pid = fork ();
565 if (priv->child_pid) {
566 DBG ("establish handler for the child pid %u", priv->child_pid);
567 session->priv->child_watch_id = g_child_watch_add (priv->child_pid,
568 (GChildWatchFunc)_on_child_down_cb, session);
569 session->priv->is_child_up = TRUE;
573 /* ==================================
574 * this is child process here onwards
575 * ================================== */
579 //close all open descriptors other than stdin, stdout, stderr
580 open_max = sysconf (_SC_OPEN_MAX);
581 for (fd = 3; fd < open_max; fd++) {
582 if (fcntl (fd, F_SETFD, FD_CLOEXEC) < -1) {
583 WARN ("Failed to close desriptor '%d', error: %s",
584 fd, strerror(errno));
588 uid_t target_uid = tlm_user_get_uid (priv->username);
589 gid_t target_gid = tlm_user_get_gid (priv->username);
591 if (fchown (0, target_uid, -1)) {
592 WARN ("Changing TTY access rights failed");
595 /*if (getppid() == 1) {
596 if (setsid () == (pid_t) -1)
597 WARN ("setsid() failed: %s", strerror (errno));
600 WARN ("setpgrp() failed: %s", strerror (errno));
603 DBG ("old pgid=%u", getpgrp ());
604 if (setsid () == (pid_t) -1)
605 WARN ("setsid() failed: %s", strerror (errno));
606 DBG ("new pgid=%u", getpgrp());
608 gboolean setup_terminal;
609 if (tlm_config_has_key (priv->config,
611 TLM_CONFIG_GENERAL_SETUP_TERMINAL)) {
612 setup_terminal = tlm_config_get_boolean (priv->config,
614 TLM_CONFIG_GENERAL_SETUP_TERMINAL,
617 setup_terminal = tlm_config_get_boolean (priv->config,
619 TLM_CONFIG_GENERAL_SETUP_TERMINAL,
622 if (setup_terminal) {
623 /* usually terminal settings are handled by PAM */
624 _set_terminal (priv);
627 if (initgroups (priv->username, target_gid))
628 WARN ("initgroups() failed: %s", strerror(errno));
629 if (setregid (target_gid, target_gid))
630 WARN ("setregid() failed: %s", strerror(errno));
631 if (setreuid (target_uid, target_uid))
632 WARN ("setreuid() failed: %s", strerror(errno));
634 int grouplist_len = NGROUPS_MAX;
635 gid_t grouplist[NGROUPS_MAX];
636 grouplist_len = getgroups (grouplist_len, grouplist);
637 DBG ("group membership:");
638 for (i = 0; i < grouplist_len; i++)
639 DBG ("\t%s", getgrgid (grouplist[i])->gr_name);
641 DBG (" state:\n\truid=%d, euid=%d, rgid=%d, egid=%d (%s)",
642 getuid(), geteuid(), getgid(), getegid(), priv->username);
643 _set_environment (priv);
646 home = getenv("HOME");
648 DBG ("changing directory to : %s", home);
649 if (chdir (home) < 0)
650 WARN ("Failed to change directroy : %s", strerror (errno));
651 } else WARN ("Could not get home directory");
653 shell = tlm_config_get_string (priv->config,
655 TLM_CONFIG_GENERAL_SESSION_CMD);
657 shell = tlm_config_get_string (priv->config,
659 TLM_CONFIG_GENERAL_SESSION_CMD);
661 DBG ("Session command : %s", shell);
662 temp_strv = g_regex_split_simple (pattern,
665 G_REGEX_MATCH_NOTEMPTY);
671 args = g_new0 (gchar *, g_strv_length (temp_strv));
672 for (temp_iter = temp_strv, args_iter = args;
676 gchar *item = g_strstrip (*temp_iter);
678 item_len = strlen (item);
682 if ((item[0] == '\"' && item[item_len - 1] == '\"') ||
683 (item[0] == '\'' && item[item_len - 1] == '\'')) {
684 item[item_len - 1] = '\0';
685 memmove (item, item + 1, item_len - 1);
687 *args_iter = g_strcompress (item);
690 g_strfreev (temp_strv);
691 } else if ((env_shell = getenv("SHELL"))){
692 /* use shell if no override configured */
693 args = g_new0 (gchar *, 2);
694 args[0] = g_strdup (env_shell);
696 /* in case shell is not defined, fall back to systemd --user */
697 args = g_new0 (gchar *, 3);
698 args[0] = g_strdup ("systemd");
699 args[1] = g_strdup ("--user");
704 while (args_iter && *args_iter) {
705 DBG ("\targv[%d]: %s", i, *args_iter);
708 execvp (args[0], args);
709 /* we reach here only in case of error */
711 DBG ("execl(): %s", strerror(errno));
719 return g_object_new (TLM_TYPE_SESSION, NULL);
723 tlm_session_start (TlmSession *session,
724 const gchar *seat_id, const gchar *service,
725 const gchar *username, const gchar *password,
726 GHashTable *environment)
728 GError *error = NULL;
729 g_return_val_if_fail (session && TLM_IS_SESSION(session), FALSE);
730 TlmSessionPrivate *priv = TLM_SESSION_PRIV(session);
731 const gchar *session_type;
733 if (!seat_id || !service || !username) {
734 error = TLM_GET_ERROR_FOR_ID (TLM_ERROR_SESSION_CREATION_FAILURE,
735 "Unable to create PAM sesssion as input data is invalid "
736 "seatid(%p) service(%p) username(%p)", seat_id, service,
738 g_signal_emit (session, signals[SIG_SESSION_ERROR], 0, error);
739 g_error_free (error);
743 g_object_set (G_OBJECT (session), "seat", seat_id, "service", service,
744 "username", username, "environment", environment, NULL);
746 priv->vtnr = tlm_config_get_uint (priv->config,
748 TLM_CONFIG_SEAT_VTNR,
750 gchar *tty_name = priv->vtnr > 0 ?
751 g_strdup_printf ("tty%u", priv->vtnr) : NULL;
752 priv->auth_session = tlm_auth_session_new (priv->service, priv->username,
756 if (!priv->auth_session) {
757 error = TLM_GET_ERROR_FOR_ID (TLM_ERROR_SESSION_CREATION_FAILURE,
758 "Unable to create PAM sesssion");
759 g_signal_emit (session, signals[SIG_SESSION_ERROR], 0, error);
760 g_error_free (error);
764 session_type = tlm_config_get_string (priv->config,
766 TLM_CONFIG_GENERAL_SESSION_TYPE);
768 session_type = tlm_config_get_string (priv->config,
770 TLM_CONFIG_GENERAL_SESSION_TYPE);
771 if (!tlm_config_has_key (priv->config,
773 TLM_CONFIG_GENERAL_NSEATS))
774 tlm_auth_session_putenv (priv->auth_session,
778 tlm_auth_session_putenv (priv->auth_session,
781 tlm_auth_session_putenv (priv->auth_session,
785 if (priv->vtnr > 0) {
786 gchar *vtnr_str = g_strdup_printf("%u", priv->vtnr);
787 tlm_auth_session_putenv (priv->auth_session,
793 if (!tlm_auth_session_authenticate (priv->auth_session, &error)) {
795 //consistant error message flow
796 GError *err = TLM_GET_ERROR_FOR_ID (
797 TLM_ERROR_SESSION_CREATION_FAILURE,
798 "%d:%s", error->code, error->message);
799 g_error_free (error);
802 error = TLM_GET_ERROR_FOR_ID (TLM_ERROR_SESSION_CREATION_FAILURE,
803 "Unable to authenticate PAM sesssion");
805 g_signal_emit (session, signals[SIG_SESSION_ERROR], 0, error);
806 g_error_free (error);
809 g_signal_emit (session, signals[SIG_AUTHENTICATED], 0);
811 priv->session_pause = tlm_config_get_boolean (priv->config,
813 TLM_CONFIG_GENERAL_PAUSE_SESSION,
815 if (priv->session_pause) {
816 _set_environment (priv);
820 if (!tlm_auth_session_open (priv->auth_session, &error)) {
822 error = TLM_GET_ERROR_FOR_ID (TLM_ERROR_SESSION_CREATION_FAILURE,
823 "Unable to open PAM sesssion");
825 g_signal_emit (session, signals[SIG_SESSION_ERROR], 0, error);
826 g_error_free (error);
829 priv->sessionid = g_strdup (tlm_auth_session_get_sessionid (
830 priv->auth_session));
831 tlm_utils_log_utmp_entry (priv->username);
832 if (!priv->session_pause)
833 _exec_user_session (session);
834 g_signal_emit (session, signals[SIG_SESSION_CREATED], 0,
835 priv->sessionid ? priv->sessionid : "");
840 _terminate_timeout (gpointer user_data)
842 TlmSession *session = TLM_SESSION(user_data);
843 TlmSessionPrivate *priv = TLM_SESSION_PRIV(session);
845 switch (priv->last_sig)
848 DBG ("child %u didn't respond to SIGHUP, sending SIGTERM",
850 if (killpg (getpgid (priv->child_pid), SIGTERM))
851 WARN ("killpg(%u, SIGTERM): %s",
852 getpgid (priv->child_pid),
854 priv->last_sig = SIGTERM;
855 return G_SOURCE_CONTINUE;
857 DBG ("child %u didn't respond to SIGTERM, sending SIGKILL",
859 if (killpg (getpgid (priv->child_pid), SIGKILL))
860 WARN ("killpg(%u, SIGKILL): %s",
861 getpgid (priv->child_pid),
863 priv->last_sig = SIGKILL;
864 return G_SOURCE_CONTINUE;
866 DBG ("child %u didn't respond to SIGKILL, process is stuck in kernel",
869 _clear_session (session);
870 if (session->priv->can_emit_signal) {
871 GError *error = TLM_GET_ERROR_FOR_ID (
872 TLM_ERROR_SESSION_TERMINATION_FAILURE,
873 "Unable to terminate session - process is stuck"
875 g_signal_emit (session, signals[SIG_SESSION_ERROR], 0, error);
876 g_error_free (error);
878 return G_SOURCE_REMOVE;
880 WARN ("%d has unknown signaling state %d",
884 return G_SOURCE_REMOVE;
888 tlm_session_terminate (TlmSession *session)
890 g_return_if_fail (session && TLM_IS_SESSION(session));
891 TlmSessionPrivate *priv = TLM_SESSION_PRIV(session);
893 DBG ("Session Terminate");
895 if (!priv->is_child_up) {
896 DBG ("no child process is running - closing pam session");
897 _clear_session (session);
898 if (session->priv->can_emit_signal)
899 g_signal_emit (session, signals[SIG_SESSION_TERMINATED], 0);
903 if (killpg (getpgid (priv->child_pid), SIGHUP) < 0)
904 WARN ("kill(%u, SIGHUP): %s",
905 getpgid (priv->child_pid),
907 priv->last_sig = SIGHUP;
908 priv->timer_id = g_timeout_add_seconds (
909 tlm_config_get_uint (priv->config, TLM_CONFIG_GENERAL,
910 TLM_CONFIG_GENERAL_TERMINATE_TIMEOUT, 3),
916 tlm_session_reset_tty (TlmSession *session)
918 TlmSessionPrivate *priv = TLM_SESSION_PRIV(session);
920 if (fchown (0, priv->tty_uid, priv->tty_gid))
921 WARN ("Changing TTY access rights failed");
922 if (tcflush (0, TCIOFLUSH) ||
923 tcflush (1, TCIOFLUSH) ||
924 tcflush (2, TCIOFLUSH))
925 WARN ("Flushing stdio failed");
926 pid_t pgid = getpgid (getpid ());
927 if (tcsetpgrp (0, pgid) || tcsetpgrp (1, pgid) || tcsetpgrp (2, pgid))
928 WARN ("Change TTY controlling process failed");
929 if (tcsetattr (0, TCSANOW, &priv->stdin_state) ||
930 tcsetattr (1, TCSANOW, &priv->stdout_state) ||
931 tcsetattr (2, TCSANOW, &priv->stderr_state))
932 WARN ("Restoring TTY settings failed");