summaryrefslogtreecommitdiff
path: root/pkgs/tmux-lift/lift.c
diff options
context:
space:
mode:
authorAlejandro Soto <alejandro@34project.org>2022-03-05 00:40:32 -0600
committerAlejandro Soto <alejandro@34project.org>2022-03-05 00:40:32 -0600
commit5dc85e72a002efce36b440a98b17a6c80234a142 (patch)
tree11f0d3af31b88c079d1598a5842dc47d9e024aa9 /pkgs/tmux-lift/lift.c
parent743a205dd9bff31e0ed63ebba8dd3327614ac188 (diff)
Restructure flake source hierarchy
Diffstat (limited to 'pkgs/tmux-lift/lift.c')
-rw-r--r--pkgs/tmux-lift/lift.c139
1 files changed, 139 insertions, 0 deletions
diff --git a/pkgs/tmux-lift/lift.c b/pkgs/tmux-lift/lift.c
new file mode 100644
index 0000000..71d959b
--- /dev/null
+++ b/pkgs/tmux-lift/lift.c
@@ -0,0 +1,139 @@
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+
+#include "lift.h"
+
+
+#define STAGES 2
+
+
+#define FAIL_PAUSE 0x01
+#define FAIL_EXIT 0x02
+
+
+unsigned failures = 0;
+const char* program_name;
+
+
+void fail
+(
+ const char* source,
+ int mode,
+ const char* format,
+ ...
+)
+{
+ va_list args;
+ va_start( args, format );
+
+ perror( source );
+ if( format != NULL )
+ {
+ fputs( program_name, stderr );
+ fputs( ": ", stderr );
+ vfprintf( stderr, format, args );
+ fputc( '\n', stderr );
+ }
+
+ va_end( args );
+
+ ++failures;
+ if( failures == STAGES || ( mode & FAIL_PAUSE ) )
+ {
+ pause();
+ }
+
+ if( failures == STAGES || ( mode & FAIL_EXIT ) )
+ {
+ exit( EXIT_FAILURE );
+ }
+}
+
+
+void checked_take_foreground()
+{
+ signal( SIGTTOU, SIG_IGN );
+ if( tcsetpgrp( 0, getpgrp() ) < 0 )
+ {
+ fail( "tcsetpgrp()", FAIL_EXIT, NULL );
+ }
+
+ signal( SIGTTOU, SIG_DFL );
+}
+
+
+void checked_exec
+(
+ char *const* command_line
+)
+{
+ execvp( command_line[ 0 ], command_line );
+ fail( "execvp()", FAIL_EXIT, "unable to execute %s", command_line[ 0 ] );
+}
+
+
+int main
+(
+ int argc,
+ char *const argv[]
+)
+{
+ program_name = argv[ 0 ];
+
+ struct passwd* passwd = getpwuid( getuid() );
+ if( passwd == NULL )
+ {
+ fail( "getpwuid()", FAIL_PAUSE | FAIL_EXIT, NULL );
+ }
+
+ pid_t pid = fork();
+ if( pid < 0 )
+ {
+ fail( "fork()", 0, NULL );
+ } else if( pid == 0 )
+ {
+ if( setpgid( 0, 0 ) < 0 )
+ {
+ fail( "setpgid()", FAIL_EXIT, NULL );
+ }
+
+ checked_take_foreground();
+
+ char formatted_pid[ 16 ];
+ snprintf( formatted_pid, sizeof formatted_pid, "%d", getpid() );
+
+ setenv( LIFT_PID_ENV, formatted_pid, 1 );
+ checked_exec( argc > 1 ? &argv[ 1 ] : (char *const[]){ DEFAULT_PATH, NULL } );
+ } else
+ {
+ int status;
+ pid_t res = wait( &status );
+
+ checked_take_foreground();
+ if( res < 0 )
+ {
+ fail( "wait()", FAIL_PAUSE | FAIL_EXIT, NULL );
+ }
+
+ if( WIFEXITED( status ) )
+ {
+ if( status == 0 )
+ {
+ return 0;
+ }
+
+ fprintf( stderr, "Session unlifted by exit code %d\n", WEXITSTATUS( status ) );
+ } else if( WIFSIGNALED( status ) )
+ {
+ fprintf( stderr, "Session unlifted by %s\n", strsignal( WTERMSIG( status ) ) );
+ }
+ }
+
+ checked_exec( (char *const[]){ passwd->pw_shell, NULL } );
+}