From 43028a40d5d68bb3bf5e6e0dc7a7a5888e64a706 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Fri, 18 Oct 2019 16:48:22 +0200 Subject: Add feature to clean up user processes after logout --- src/main.c | 36 ++++++++++++++++++++++++++++++++---- src/userlist.c | 11 ++++++----- src/userlist.h | 2 +- 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/src/main.c b/src/main.c index 9ca1da9..68ae274 100644 --- a/src/main.c +++ b/src/main.c @@ -52,6 +52,7 @@ static struct { int dpmsTimeout; int gracePeriod; int minIdle; + bool killUserProcesses; } config; static time_t combineTime( const time_t now, const struct time * time ); @@ -62,6 +63,8 @@ static bool parseCmdline( int argc, char **argv ); static void execShutdown( enum Shutdown action ); +static void userLoggedOut(struct user* usr); + int main( int argc, char **argv ) { int idx; @@ -80,7 +83,7 @@ int main( int argc, char **argv ) startWall = time( NULL ); startMono = now(); // Calculate shortest possible sleep time without delaying any timeout related actions - int defaultSleep = 900; + int defaultSleep = 120; if ( config.logoutTimeout > 0 && config.logoutTimeout < defaultSleep ) { defaultSleep = config.logoutTimeout; } @@ -100,8 +103,13 @@ int main( int argc, char **argv ) userCount = count; for ( idx = 0; idx < count; ++idx ) { struct user * const usr = &users[idx]; - if ( !usr->mark ) { - fprintf( stderr, "This will never happen \\o/\n" ); + if ( !usr->online ) { + if ( !usr->lastOnline ) { + fprintf( stderr, "This will never happen \\o/\n" ); + continue; + } + // User was logged in, but isn't anymore + userLoggedOut(usr); continue; } const time_t NOW = time( NULL ); @@ -384,6 +392,7 @@ static struct option long_options[] = { { "min-idle", required_argument, NULL, 'min' }, { "cmd", required_argument, NULL, 'cmd' }, { "send", required_argument, NULL, 'send' }, + { "kill-user-processes", no_argument, NULL, 'kill' }, { "test", no_argument, NULL, 't' }, { NULL, 0, NULL, 0 } }; @@ -422,6 +431,7 @@ static bool parseCmdline( int argc, char **argv ) config.gracePeriod = -1; config.shutdownCommand = NULL; config.minIdle = 0; + config.killUserProcesses = false; while ( ( ch = getopt_long( argc, argv, "", long_options, NULL ) ) != -1 ) { switch ( ch ) { case 'pot': @@ -466,6 +476,10 @@ static bool parseCmdline( int argc, char **argv ) break; case 'send': exit( !rpc_send( optarg ) ); + break; + case 'kill': + config.killUserProcesses = true; + break; default: fprintf( stderr, "Unhandled command line option %d, aborting\n", ch ); return false; @@ -518,7 +532,7 @@ void main_getStatus( const char **nextString, time_t *deadline ) struct user* main_getUser( const char *terminal ) { - for ( int i = 0; i < USERS && users[i].mark; ++i ) { + for ( int i = 0; i < userCount; ++i ) { if ( strcmp( users[i].device, terminal ) == 0 || strcmp( users[i].display, terminal ) == 0 ) { return &users[i]; @@ -565,4 +579,18 @@ void main_warnAll( const char *message ) } } +static void userLoggedOut(struct user* usr) +{ + if ( !config.killUserProcesses ) + return; + for ( int i = 0; i < userCount; ++i ) { + if (users[i].online && strcmp(users[i].user, usr->user) == 0) + return; // Still an active session + } + struct passwd *u = getpwnam( usr->user ); + if ( u == NULL || u->pw_uid < 1000 ) + return; // Ignore system users + printf( "Killing remaining processes of %s\n", usr->user ); + run( true, "pkill", "-u", usr->user, (char*)NULL ); +} diff --git a/src/userlist.c b/src/userlist.c index fffe772..d4dde86 100644 --- a/src/userlist.c +++ b/src/userlist.c @@ -52,7 +52,8 @@ int getUserList( struct user *outbuf, int size ) if ( outbuf[i].user[0] != '\0' ) { deadzone = i + 1; } - outbuf[i].mark = false; + outbuf[i].lastOnline = outbuf[i].online; + outbuf[i].online = false; } struct utmp buffer[100]; ssize_t len = read( fh, buffer, sizeof(buffer) ); @@ -114,7 +115,7 @@ int getUserList( struct user *outbuf, int size ) getSessionData( &outbuf[use] ); outbuf[use].loginctlFails++; } - outbuf[use].mark = true; + outbuf[use].online = true; // Reset offset if timestamp changed // but ONLY if this isn't a known X session if ( outbuf[use].display[0] == '\0' ) { @@ -128,11 +129,11 @@ int getUserList( struct user *outbuf, int size ) close( fh ); // Compact for ( int i = 0; i < deadzone; ++i ) { - if ( outbuf[i].mark ) - continue; // In use + if ( outbuf[i].online || outbuf[i].lastOnline ) + continue; // In use, or just finished do { deadzone--; - if ( outbuf[deadzone].mark ) { + if ( outbuf[deadzone].online || outbuf[deadzone].lastOnline ) { outbuf[i] = outbuf[deadzone]; outbuf[deadzone].user[0] = '\0'; break; diff --git a/src/userlist.h b/src/userlist.h index 189b0c2..f9ae458 100644 --- a/src/userlist.h +++ b/src/userlist.h @@ -19,7 +19,7 @@ struct user { int lastActivityOffset; int lockTimeOffset; int loginctlFails; - bool mark; + bool online, lastOnline; bool isLocked; char user[STRLEN]; char device[STRLEN]; -- cgit v1.2.3-55-g7522