console_setup.proxy.in 3.39 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
#!/usr/bin/perl -wT
use English;

#
# usage: console_setup node1 pid1 node2 pid2 ...
#
# This script runs on plastic where the tip lines are and the capture
# processes are running. Since plastic does not have access to the DB
# we invoke this from paper in nalloc/nfree, giving it a list of node/pid
# pairs to set. Only use can run this script.
#
my $TB		= "/usr/testbed/bin";
my $TIPLOGDIR   = "/var/log/tiplogs";
my $TIPDEVDIR   = "/dev/tip";
my $TBPID	= "flux";
my $dbg		= 1;
my %nodepid     = ();

# un-taint path
$ENV{'PATH'} = '/bin:/usr/bin:/usr/local/bin';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};

sub usage {
    die("Usage: console_setup node project_id [node pid node pid ...]\n".
	"Enables project members to access consoles logs of nodes.\n".
	"This script must be run as root, typically from paper.\n");
}

if ( $#ARGV < 1) {
    usage();
}

while ($#ARGV >= 0) {
    if ($#ARGV < 1) {
	usage();
    }
    
    $node = shift;
    $pid  = shift;

    # untaint the args.
    if ($node =~ /^([-\@\w.]+)$/) {
	$node = $1;
    }
    if ($pid =~ /^([-\@\w.]+)$/) {
	$pid = $1;
    }
    
    $nodepid{$node} = $pid;
}

#
# This script must be run as root, typically from paper.
#
if ($UID != 0) {
    die("Must be run as root.");
}

if (! chdir($TIPLOGDIR)) {
    die("Could not chdir to $TIPLOGDIR: $!\n");
}

#
# Well, do it.
# 
foreach my $node ( keys %nodepid ) {
    $pid = $nodepid{$node};

    #
    # Find out the current group setting for the file. 
    #
    $filename = "${node}.run";
    if (! -e $filename) {
	die("Console log $filename for $node does not exist!");
    }
    # This is silly! Is there a better way to do this?
    (undef,undef,undef,undef,undef,$gid) = stat($filename);

    #
    # If the file is already in the correct group skip it since there no point
    # in rolling the file. Inconvenient for the user to have the log keep
    # rolling.
    #
    if (getgrgid($gid) eq $pid) {
	next;
    }

    unlink($filename) or
	die("Could not unlink run file $filename");

    #
    # Now send a USR1 signal to the capture process so that it opens
    # a new run file.
    #
    $procid = `cat ${node}.pid`;
    $procid =~ s/\n//;
    # untaint
    if ($procid =~ /^([-\@\w.]+)$/) {
	$procid = $1;
    }
    kill('USR1', $procid) or
	die("Could not signal(USR1) process $procid for log $filename");
    # Give capture the chance to react.
    sleep(1);

    #
    # If the file does not exist, touch it. We have this problem with
    # capture getting blocked.
    #
    if (! -e $filename) {
	system("touch $filename");
    }
    
    #
    # The new log should exist now. Set its group, and just to be safe
    # set its mode too. 
    #
    $gid = getgrnam($pid);
    chown(0, $gid, $filename) or
	die("Could not chown(0, $gid) $filename: $!");
    chmod(0640, $filename) or
	die("Could not chmod(0640) $filename: $!");

    #
    # Now send a USR2 signal to the capture process so that it closes down
    # any tip thats attached to it.
    #
    kill('USR2', $procid) or
	die("Could not signal(USR2) process $procid for log $filename");

    #
    # Set the mode and group for the tty that tip is going to use. This
    # allows the user to access the tip line using a non-setuid version
    # of tip.
    #
    $tipdevname = "$TIPDEVDIR/$node";
    chown(0, $gid, $tipdevname) or
	die("Could not chown(0, $gid) $tipdevname: $!");
    chmod(0660, $tipdevname) or
	die("Could not chmod(0660) $tipdevname: $!");
}

exit 0;