#! /usr/bin/env perl

use v5.36;  # builtin, say, signatures
no  warnings 'experimental';
use autodie;
use Fcntl;                # O_RDWR;
use IO::Tty 'TIOCSCTTY';
use POSIX;                # dup2, setgid, setsid, setuid
use User::pwent;          # `getpwnam` to read /etc/passwd

sub argparse( @args ){
	# checks should have been done by autologin_tty::set package
	# so only arg count check here
	# tty gets auto-appended by init(1), so arg count is +1
	unless ( @args >= 3 ){
		CORE::die 'usage: <user> <command> [command args] ... <tty>' . "\n";  }

	my $dev_tty    = '/dev/' . CORE::pop   @args;  # tty gets auto-appended by init(1)
	my $user       =           CORE::shift @args;
	my @command    =                       @args;
	
	return $dev_tty, $user, @command;  }

sub main( @args ){
	my ( $dev_tty, $user, @command ) = argparse( @args );

	my $etc_passwd = User::pwent::getpwnam $user;
	my $filehandle;
	my $filedescriptor;

	# Open the physical terminal device for read-write access without truncating it
	CORE::sysopen $filehandle, $dev_tty, Fcntl::O_RDWR;

	# Become a session leader (prereq for TIOCSCTTY)
	# If this fails, you might already be a session leader, which is okay, 
	# but you cannot be in a process group of another session.
	POSIX::setsid;

	# Set the controlling terminal
	# The third argument is ignored for TIOCSCTTY but must be present
	CORE::ioctl $filehandle, TIOCSCTTY, 0;

	# Redirect STDIN, STDOUT, STDERR to the new controlling tty
	$filedescriptor = CORE::fileno $filehandle;
	POSIX::dup2 $filedescriptor, 0;
	POSIX::dup2 $filedescriptor, 1;
	POSIX::dup2 $filedescriptor, 2;
	CORE::close $filehandle;

	POSIX::setgid $etc_passwd->gid;
	POSIX::setuid $etc_passwd->uid;

	$ENV{TERM}  = 'vt220';
	$ENV{USER}  = $user;
	$ENV{HOME}  = $etc_passwd->dir;
	$ENV{SHELL} = $etc_passwd->shell;

	CORE::chdir $ENV{HOME};

	CORE::say qq{as user "$user" exec: }, CORE::join( ' ', @command );
	CORE::exec @command;  }

main @ARGV;

