File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / rsync / support / lsh
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 00:32:36 2021 UTC (3 years, 3 months ago) by misho
Branches: rsync, MAIN
CVS tags: v3_2_3, HEAD
rsync 3.2.3

    1: #!/usr/bin/env perl
    2: # This is a "local shell" command that works like a remote shell but only for
    3: # the local host.  See the usage message for more details.
    4: 
    5: use strict;
    6: use warnings;
    7: use Getopt::Long;
    8: use English '-no_match_vars';
    9: 
   10: &Getopt::Long::Configure('bundling');
   11: &Getopt::Long::Configure('require_order');
   12: GetOptions(
   13:     'l=s' => \( my $login_name ),
   14:     '1|2|4|6|A|a|C|f|g|k|M|N|n|q|s|T|t|V|v|X|x|Y' => sub { }, # Ignore
   15:     'b|c|D|e|F|i|L|m|O|o|p|R|S|w=s' => sub { }, # Ignore
   16:     'no-cd' => \( my $no_chdir ),
   17:     'sudo' => \( my $use_sudo ),
   18: ) or &usage;
   19: &usage unless @ARGV > 1;
   20: 
   21: my $host = shift;
   22: if ($host =~ s/^([^@]+)\@//) {
   23:     $login_name = $1;
   24: }
   25: if ($host eq 'lh') {
   26:     $no_chdir = 1;
   27: } elsif ($host ne 'localhost') {
   28:     die "lsh: unable to connect to host $host\n";
   29: }
   30: 
   31: my ($home_dir, @cmd);
   32: if ($login_name) {
   33:     my ($uid, $gid);
   34:     if ($login_name =~ /\D/) {
   35: 	$uid = getpwnam($login_name);
   36: 	die "Unknown user: $login_name\n" unless defined $uid;
   37:     } else {
   38: 	$uid = $login_name;
   39:     }
   40:     ($login_name, $gid, $home_dir) = (getpwuid($uid))[0,3,7];
   41:     if ($use_sudo) {
   42: 	unshift @ARGV, "cd '$home_dir' &&" unless $no_chdir;
   43: 	unshift @cmd, qw( sudo -H -u ), $login_name;
   44: 	$no_chdir = 1;
   45:     } else {
   46: 	my $groups = "$gid $gid";
   47: 	while (my ($grgid, $grmembers) = (getgrent)[2,3]) {
   48: 	    if ($grgid != $gid && $grmembers =~ /(^|\s)\Q$login_name\E(\s|$)/o) {
   49: 		$groups .= " $grgid";
   50: 	    }
   51: 	}
   52: 
   53: 	my ($ruid, $euid) = ($UID, $EUID);
   54: 	$GID = $EGID = $groups;
   55: 	$UID = $EUID = $uid;
   56: 	die "Cannot set ruid: $! (use --sudo?)\n" if $UID == $ruid && $ruid != $uid;
   57: 	die "Cannot set euid: $! (use --sudo?)\n" if $EUID == $euid && $euid != $uid;
   58: 
   59: 	$ENV{USER} = $ENV{USERNAME} = $login_name;
   60: 	$ENV{HOME} = $home_dir;
   61:     }
   62: } else {
   63:     $home_dir = (getpwuid($UID))[7];
   64: }
   65: 
   66: unless ($no_chdir) {
   67:     chdir $home_dir or die "Unable to chdir to $home_dir: $!\n";
   68: }
   69: 
   70: push @cmd, '/bin/sh', '-c', "@ARGV";
   71: exec @cmd;
   72: die "Failed to exec: $!\n";
   73: 
   74: sub usage
   75: {
   76:     die <<EOT;
   77: Usage: lsh [-l USER] [--sudo] [--no-cd] localhost COMMAND [...]
   78: 
   79: This is a "local shell" command that works like a remote shell but only for the
   80: local host.  This is useful for rsync testing or for running a local copy where
   81: the sender and the receiver need to use different options (e.g. --fake-super).
   82: If the -l option is used, we try to become the USER, either directly (when
   83: root) or by using "sudo -H -u USER" (requires --sudo option).
   84: 
   85: Note that if you pass hostname "lh" instead of "localhost" that the --no-cd
   86: option is implied.  The default is to "cd \$HOME" to simulate ssh behavior.
   87: EOT
   88: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>