From 6053a358dd187fd56bdd1753fbc6b8285c35cd98 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Mon, 13 May 2019 14:43:35 +0200 Subject: Add reboot/kexec/poweroff via RPC --- src/main.c | 102 ++++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 60 insertions(+), 42 deletions(-) (limited to 'src/main.c') diff --git a/src/main.c b/src/main.c index f9960f5..032aa27 100644 --- a/src/main.c +++ b/src/main.c @@ -25,13 +25,6 @@ static time_t lastActivity; static struct user *users; // List of reboot and shutdown times -enum Shutdown { - REBOOT = 0, - POWEROFF, - KEXEC, - SUSPEND, - SHUTDOWN_ENUM_END, -}; static const char *shutdownActions[SHUTDOWN_ENUM_END] = { [REBOOT] = "reboot", [POWEROFF] = "poweroff", @@ -39,11 +32,6 @@ static const char *shutdownActions[SHUTDOWN_ENUM_END] = { [SUSPEND] = "suspend", }; #define TABMAX (20) -struct time { - int hour; - int minute; - enum Shutdown action; -}; static struct { time_t deadline; // MONOTONIC; 0 = none, or last one was disarmed and time elapsed past deadline enum Shutdown action; @@ -63,6 +51,8 @@ static struct { int gracePeriod; } config; +static time_t combineTime( const time_t now, const struct time * time ); + static void getXAuthority( struct user *user ); static bool parseCmdline( int argc, char **argv ); @@ -216,37 +206,22 @@ int main( int argc, char **argv ) nextAction.deadline = 0; } const time_t NOW = time( NULL ); - struct tm tmNOW; - if ( localtime_r( &NOW, &tmNOW ) != NULL ) { - struct tm dtime; - time_t deadline; - int delta; - for ( idx = 0; idx < config.shutdowns; ++idx ) { - dtime = tmNOW; - dtime.tm_hour = config.shutdown[idx].hour; - dtime.tm_min = config.shutdown[idx].minute; - dtime.tm_sec = 0; - deadline = mktime( &dtime ); - if ( deadline + 6 < NOW ) { - // Try again tomorrow - dtime.tm_mday++; - deadline = mktime( &dtime ); - } - if ( deadline == -1 ) { - perror( "Cannot convert shutdown entry to time_t via mktime" ); - continue; - } - delta = deadline - NOW; - if ( delta >= -6 && ( nextAction.deadline == 0 || ( nextAction.deadline - monoNOW - 3 ) > delta ) ) { - // Engage - nextAction.deadline = monoNOW + ( delta < 0 ? 0 : delta ); - nextAction.disarmed = false; - nextAction.action = config.shutdown[idx].action; - if ( delta < 300 ) { - printf( "Scheduling reboot/poweroff in %d seconds\n", delta ); - } - CAP_SLEEP( delta ); + time_t deadline; + int delta; + for ( idx = 0; idx < config.shutdowns; ++idx ) { + deadline = combineTime( NOW, &config.shutdown[idx] ); + if ( deadline == 0 ) + continue; + delta = deadline - NOW; + if ( delta >= -6 && ( nextAction.deadline == 0 || ( nextAction.deadline - monoNOW - 3 ) > delta ) ) { + // Engage + nextAction.deadline = monoNOW + ( delta < 0 ? 0 : delta ); + nextAction.disarmed = false; + nextAction.action = config.shutdown[idx].action; + if ( delta < 300 ) { + printf( "Scheduling reboot/poweroff in %d seconds\n", delta ); } + CAP_SLEEP( delta ); } } } @@ -324,6 +299,32 @@ int main( int argc, char **argv ) return 0; } +static time_t combineTime( const time_t now, const struct time * time ) +{ + struct tm dtime; + if ( localtime_r( &now, &dtime ) == NULL ) + return 0; + time_t result; + dtime.tm_hour = time->hour; + dtime.tm_min = time->minute; + dtime.tm_sec = 0; + result = mktime( &dtime ); + if ( result + 6 < now ) { + // Try again tomorrow + dtime.tm_mday++; + result = mktime( &dtime ); + } + if ( result == -1 ) { + perror( "Cannot convert struct tm to time_t via mktime" ); + return 0; + } + if ( result < now ) { + fprintf( stderr, "combineTime: Even +1 day seems in the past!?\n" ); + return 0; + } + return result; +} + /** * This doesn't really use any clever logic but rather assumes that * it will be $HOME/.Xauthority @@ -359,6 +360,7 @@ static struct option long_options[] = { { "dpms-timeout", required_argument, NULL, 'dpms' }, { "grace-period", required_argument, NULL, 'gp' }, { "cmd", required_argument, NULL, 'cmd' }, + { "send", required_argument, NULL, 'send' }, { "test", no_argument, NULL, 't' }, { NULL, 0, NULL, 0 } }; @@ -435,6 +437,8 @@ static bool parseCmdline( int argc, char **argv ) case 'cmd': config.shutdownCommand = strdup( optarg ); break; + case 'send': + exit( !rpc_send( optarg ) ); default: fprintf( stderr, "Unhandled command line option %d, aborting\n", ch ); return false; @@ -496,3 +500,17 @@ struct user* main_getUser( const char *terminal ) return NULL; } +void main_queueAction( enum Shutdown action, int delta ) +{ + if ( delta < 0 || action < 0 || action >= SHUTDOWN_ENUM_END ) + return; + time_t monoNOW = now(); + if ( nextAction.deadline == 0 || ( nextAction.deadline - monoNOW - 3 ) > delta ) { + // Engage + nextAction.deadline = monoNOW + delta; + nextAction.disarmed = false; + nextAction.action = action; + printf( "RPC: Scheduling reboot/poweroff in %d seconds\n", delta ); + } +} + -- cgit v1.2.3-55-g7522