#!/usr/bin/perl
use BSD::Resource;

# (c) 2000 aoe@mars: chrootsh doesn't take arguments and exits
# if you don't have a valid  account in prison. 

# arbitrary defaults
$newroot="/home/prison";
$ENV{PATH}="/bin:/usr/bin:/sbin:/usr/sbin";
$ENV{ENV}="";

# make it even warmer and cozier
setrlimit(&RLIMIT_CPU,2,3);
setrlimit(&RLIMIT_FSIZE,1024*1024,1024*2048);
setrlimit(&RLIMIT_DATA,1024*1024,1024*2048);
setrlimit(&RLIMIT_STACK,1024*1024,1024*2048);
setrlimit(&RLIMIT_CORE,0,0);
setrlimit(&RLIMIT_RSS,1024*1024,1024*2048);
setrlimit(&RLIMIT_MEMLOCK,1024*1024,1024*2048);
setrlimit(&RLIMIT_NPROC,30,32);
setrlimit(&RLIMIT_NOFILE,32,64);
setrlimit(&RLIMIT_AS,1024*1024*20,1024*2048*40);

setpriority(&PRIO_USER,0,5) || die "priority";

# my home is my castle
chdir ("$newroot") || die "error in chdir $newroot";
chroot($newroot) || die "error in chroot $newroot";

# /proc is needed for arp, but nothing else
chmod 0500, "/proc";
chown 1,1,"/proc";

# make it comfortable
@_=getpwuid($<);
$home=$_[7];
$shell=$_[8];
$ENV{SHELL}=$shell;
$ENV{HOME}=$home;

# show our real self
$)=$( || die "gid";
if ($> != $< || $< != 0) {
  $>=$< || die "uid";
}

chdir("$home");

# either exec a command, or a login shell using the default shell
# in the prison
if (@ARGV >= 0) {
  for (@ARGV) {
    push @newargv,$_;
  }
} else {
  @newargv=("-");
}

if ($< == 0) {
  exec ("execcap","CAP_SYS_BOOT=eip","$shell")|| die "setting caps";
}

exec ("$shell",@newargv) || die "execing $shell";
