#!/usr/bin/perl # # vwho - Wrapper for who # # based on vps by Enrico Scholz =head1 NAME vwho - show who is logged on all vserver guests =head1 DESCRIPTION B runs L on every running vserver guest system and merges the answers. Based on B by Enrico Scholz =cut if ($ARGV[0] eq "--help") { exec("who @ARGV"); exit; } foreach (@ARGV) { $headers = 1, last if (/^-H$/ || /^--heading$/); } $lockdir = "/var/run/vservers"; get_server_names(); $context=get_context("self"); if ($context == -1) { print "Can not find my security context. Is this a ctx kernel?\n"; exit; } if ($context != 0) { print "not in context 0\n"; exit; } open WHO, "who @ARGV|" or print STDERR "failed to exec who: $!\n", goto VSERVER; while () { if ($headers && /(USER|NAME)\s+LINE\s+(LOGIN-)?TIME\s+(COMMENT|FROM)/) { s/^/VSERVER /; } else { s/^/MAIN /; } print; } close WHO; VSERVER: foreach my $ctx (values %name) { open WHO, "/usr/sbin/vserver $ctx exec who @ARGV|" or print STDERR "failed to switch context to vserver $name{$ctx}\n", next VSERVER; while () { next if ($headers && /(USER|NAME)\s+LINE\s+(LOGIN-)?TIME\s+(COMMENT|FROM)/); s/^/sprintf('%-15s ', $ctx)/e; print; } close WHO; } exit; sub get_context { my $pid = $_[0]; $pid =~ s/ //g; open STATUS, "/proc/$pid/status"; while () { chomp; if (/s_context: (\d+)/) { close STATUS; return $1; } } close STATUS; return -1; } sub getcontextname { if (exists $name{$_[0]}) { return $name{$_[0]}; } if ($_[0] == 1) { return "ALL_PROCS"; } elsif ($_[0] == 0) { return "MAIN"; } return "UNKNOWN"; } sub get_server_names { opendir LOCKDIR, "$lockdir"; while ($file=readdir(LOCKDIR)) { if (-f "$lockdir/$file") { open FILE, "$lockdir/$file"; $file =~ s/(.+)\.ctx/$1/; while () { if (/S_CONTEXT=(\d+)/) { $name{$1} = $file; } } } } } # vim: ts=4 sw=4 expandtab syn=perl