Created
August 8, 2013 04:25
-
-
Save fumiyas/6181427 to your computer and use it in GitHub Desktop.
runuser(1) clone to emulate Red Hat Linux
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl | |
## | |
## runuser(1) clone to emulate Red Hat Linux | |
## Copyright (c) 2008-2009 SATOH Fumiyasu @ OSS Technology Corp. | |
## <http://www.osstech.co.jp> | |
## | |
## License: GNU General Public License version 2 or later | |
## Date: 2009-03-12, since 2008-06-13 | |
## | |
use strict; | |
use warnings; | |
use English qw(-no_match_vars); | |
use Getopt::Long; | |
use constant true => 1; | |
use constant false => undef; | |
sub pinfo { | |
chomp(my $m = join('', @_)); | |
print STDERR "$0: INFO: $m\n"; | |
} | |
sub pwarn { | |
chomp(my $m = join('', @_)); | |
print STDERR "$0: WARNING: $m\n"; | |
} | |
sub perr { | |
chomp(my $m = join('', @_)); | |
print STDERR "$0: ERROR: $m\n"; | |
} | |
sub pdie { | |
perr(@_); | |
exit(1); | |
} | |
my $group = undef; | |
my $shell = undef; | |
my $login_shell_f = false; | |
my $preserve_env_f = false; | |
my $not_implemented = sub { pdie "$_[0] option not implemented"; }; | |
my $cmd_usage = "Usage: $0 [OPTIONS] [-] [USER [ARG] ...]"; | |
{ | |
## Trap warning messages from Getopt::Long | |
local($SIG{'__WARN__'}) = sub { | |
my ($msg) = shift(@_); | |
pwarn $msg; | |
}; | |
## I don't like default behavior. | |
Getopt::Long::Configure('bundling'); | |
Getopt::Long::Configure('no_ignore_case'); | |
Getopt::Long::Configure('no_auto_abbrev'); | |
GetOptions( | |
'l|login' => \$login_shell_f, | |
'g|group=s' => \$group, | |
'G|groups=s' => $not_implemented, | |
'c|command=s' => $not_implemented, | |
'f|fast' => $not_implemented, | |
'm|p|preserve-environment' =>\$preserve_env_f, | |
's|shell=s' => \$shell, | |
) || exit(1); | |
} | |
my $login = @ARGV ? shift(@ARGV) : 'root'; | |
my @argv = @ARGV; | |
my @pwent = getpwnam($login); | |
@pwent || pdie "User does not exist: $login"; | |
my $uid = $pwent[2]; | |
my $gid = defined($group) ? getgrnam($group) : $pwent[3]; | |
defined($gid) || pdie "Group does not exist: $group"; | |
defined($shell) || ($shell = $pwent[8] || '/bin/sh'); | |
my $argv0 = $shell; | |
$argv0 =~ s#.*/#-# if ($login_shell_f); | |
unless ($preserve_env_f) { | |
for my $env_name (keys %ENV) { | |
next if ($env_name =~ /^(LANG|LC_\w+|PATH)$/); | |
delete($ENV{$env_name}); | |
} | |
$ENV{'LOGNAME'} = $ENV{'USER'} = $login; | |
$ENV{'HOME'} = $pwent[7]; | |
$ENV{'SHELL'} = $shell; | |
} | |
$EGID = "$gid $gid"; | |
$ERRNO && pdie "Cannot change effective GID: $gid: $!"; | |
$GID = $gid; | |
$ERRNO && pdie "Cannot change real GID: $gid: $!"; | |
$EUID = $uid; | |
$ERRNO && pdie "Cannot change effective UID: $uid: $!"; | |
$UID = $uid; | |
$ERRNO && pdie "Cannot change real UID: $uid: $!"; | |
unless (exec {$shell} $argv0, @argv) { | |
pdie "Cannot execute command: $shell: $!"; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment