diff options
Diffstat (limited to 'pkgs/tmux-lift/lift.c')
| -rw-r--r-- | pkgs/tmux-lift/lift.c | 139 |
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 } ); +} |
