$NetBSD: patch-daemon_gdm-session-record_c,v 1.1 2021/04/16 13:57:52 cirnatdan Exp $ $OpenBSD: patch-daemon_gdm-session-record_c,v 1.11 2019/11/02 15:34:07 ajacoutot Exp $ https://bugzilla.gnome.org/show_bug.cgi?id=722482 Index: daemon/gdm-session-record.c --- daemon/gdm-session-record.c.orig 2020-05-04 20:11:25.000000000 +0000 +++ daemon/gdm-session-record.c @@ -33,6 +33,16 @@ #include #endif +#if defined(HAVE_UTIL_H) +#include +#endif + +#if defined(HAVE_GETTTYENT) +#include /* open(2) */ +#include +static int fd = -1; +#endif + #include #include #include @@ -43,6 +53,9 @@ #define GDM_BAD_SESSION_RECORDS_FILE "/var/log/btmp" #endif +static void write_utmp_login_manually (struct utmp *ut); +static void write_utmp_logout_manually (char *); + #if !defined(GDM_NEW_SESSION_RECORDS_FILE) # if defined(WTMPX_FILE) # define GDM_NEW_SESSION_RECORDS_FILE WTMPX_FILE @@ -168,6 +181,84 @@ record_set_line (UTMP *u, g_debug ("using ut_line %.*s", (int) sizeof (u->ut_line), u->ut_line); } +static void +write_utmp_login_manually (struct utmp *ut) +{ +#if defined(HAVE_GETTTYENT) && defined(HAVE_UTMP_H) + UTMP ubuf; + int topslot = -1; + + g_debug ("Adding new utmp record"); + + /* + * First, loop through /etc/ttys, if needed, to initialize the + * top of the tty slots, since gdm has no tty. + */ + if (topslot < 0) { + topslot = 0; + while (getttyent () != (struct ttyent *) NULL) + topslot++; + } + if ((topslot < 0) || ((fd < 0) && + (fd = open (_PATH_UTMP, O_RDWR|O_CREAT, 0644)) < 0)) + return; + + /* + * Now find a slot that's not in use... + */ + (void) lseek (fd, (off_t) (topslot * sizeof (struct utmp)), SEEK_SET); + + while (1) { + if (read (fd, &ubuf, sizeof (struct utmp)) == + sizeof (struct utmp)) { + if (!ubuf.ut_name[0]) { + (void) lseek (fd, -(off_t) sizeof (struct utmp), + SEEK_CUR); + break; + } + topslot++; + } else { + (void) lseek (fd, (off_t) (topslot * + sizeof (struct utmp)), SEEK_SET); + break; + } + } + + (void) write (fd, ut, sizeof (struct utmp)); +#endif +} + +static void +write_utmp_logout_manually (char *line) +{ +#if defined(HAVE_GETTTYENT) && defined(HAVE_UTMP_H) && !defined(HAVE_GETUTXENT) + int rval = 1; + struct timeval tv; + UTMP ut; + + g_debug ("Removing utmp record"); + + if (fd >= 0) { + (void) lseek (fd, 0, SEEK_SET); + while (read (fd, &ut, sizeof (struct utmp)) == sizeof (struct utmp)) { + if (!ut.ut_name[0] || + strncmp (ut.ut_line, line, UT_LINESIZE)) + continue; + bzero (ut.ut_name, UT_NAMESIZE); + bzero (ut.ut_host, UT_HOSTSIZE); + gettimeofday (&tv, NULL); + ut.ut_time = tv.tv_sec; + (void) lseek (fd, -(off_t) sizeof (struct utmp), SEEK_CUR); + (void) write (fd, &ut, sizeof (struct utmp)); + rval = 0; + } + } + + if (rval != 0) + g_debug ("Failed to remove utmp record"); +#endif +} + void gdm_session_record_login (GPid session_pid, const char *user_name, @@ -214,8 +305,9 @@ gdm_session_record_login (GPid setutxent(); pututxline (&session_record); endutxent(); -#elif defined(HAVE_LOGIN) - login (&session_record); +#else + if (strcmp (session_record.ut_name, "(unknown)") != 0) + write_utmp_login_manually (&session_record); #endif } @@ -259,8 +351,8 @@ gdm_session_record_logout (GPid setutxent(); pututxline (&session_record); endutxent(); -#elif defined(HAVE_LOGOUT) - logout (session_record.ut_line); +#else + write_utmp_logout_manually (session_record.ut_line); #endif }