summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/show-users.pl132
1 files changed, 78 insertions, 54 deletions
diff --git a/scripts/show-users.pl b/scripts/show-users.pl
index d47a535..8bd0825 100644
--- a/scripts/show-users.pl
+++ b/scripts/show-users.pl
@@ -21,8 +21,8 @@
# **** End License ****
use lib "/opt/vyatta/share/perl5";
-use Term::ANSIColor;
use Vyatta::Config;
+use IO::Seekable;
use strict;
use warnings;
@@ -33,74 +33,98 @@ sub usage {
exit 1;
}
-my %pw;
-setpwent();
-while ( my ($u, $p) = getpwent()) {
- $pw{$u} = $p;
+use constant {
+ VYATTA => 0x1,
+ OTHER => 0x2,
+ LOCKED => 0x4,
+};
+
+my %filters = (
+ 'vyatta' => VYATTA,
+ 'other' => OTHER,
+ 'locked' => OTHER|LOCKED,
+ 'all' => VYATTA|OTHER|LOCKED,
+);
+
+my $filter = 0;
+for (@ARGV) {
+ my $mask = $filters{$_};
+ unless ($mask) {
+ warn "Unknown type $_\n";
+ usage();
+ }
+ $filter |= $mask;
}
-endpwent();
+# Default is everything but locked accounts
+$filter |= VYATTA|OTHER if ($filter == 0);
+# Read list of Vyatta users
my $cfg = new Vyatta::Config;
$cfg->setLevel('system login user');
$cfg->{_active_dir_base} = '/opt/vyatta/config/active/';
my %vuser = map { $_ => 1 } $cfg->listOrigNodes();
-sub locked {
- return grep { length($pw{$_}) == 1 } @_;
-}
+# Setup to access lastlog
+open (my $lastlog, '<', "/var/log/lastlog")
+ or die "can't open /var/log/lastlog:$!";
+# Magic values based on binary format of last log
+# See /usr/include/bits/utm.h
+my $typedef = 'L Z32 Z256';
+my $reclen = length(pack($typedef));
+
+sub lastlog {
+ my $uid = shift;
+
+ sysseek($lastlog, $uid * $reclen, SEEK_SET)
+ or die "seek failed: $!";
+
+ my ($rec, $line, $host, $time);
+ if (sysread($lastlog, $rec, $reclen) == $reclen) {
+ my ($time, $line, $host) = unpack($typedef, $rec);
+ return scalar(localtime($time)), $line, $host
+ if ($time != 0);
+ }
-sub nopasswd {
- return grep { length($pw{$_}) == 0 } @_;
+ return ("never logged in", "", "");
}
-sub all {
- return @_;
-}
-sub vyatta {
- return grep { $vuser{$_} } @_;
-}
-
-sub other {
- return grep { length($pw{$_}) > 1 && ! defined($vuser{$_}) } @_;
-}
+# Walk password file
+# Note: this only works as root
+my %users;
+setpwent();
+while ( my ($u, $p, $uid) = getpwent()) {
+ my $l = length($p);
+ my $status;
+ my $flag = 0;
+
+ my $type = defined($vuser{$u}) ? 'vyatta' : 'other';
+ if ($type eq 'vyatta') {
+ $flag |= VYATTA;
+ } elsif ($l != 1) {
+ $flag |= OTHER;
+ }
-sub login_color {
- my $u = shift;
- my $p = $pw{$u};
- my $c;
-
- if (length($p) == 0) {
- $c = 'blink red'; # open no password!
- } elsif ($vuser{$u}) {
- $c = 'green'; # vyatta user
- } elsif (length($p) == 1) {
- $c = 'blue'; # locked account
- } else {
- $c = 'yellow'; # non vyatta account
+ # only works as root, otherwise shadow file is inaccessible
+ if ($l == 0) {
+ $type .= '!';
+ } if ($l == 1) {
+ $flag |= LOCKED;
+ $type .= '-';
}
- return color($c) . $u . color('reset');
-}
-# show non-locked accounts in color
-sub colorize {
- return map { login_color($_) } grep { length($pw{$_}) != 1 } @_;
+ next if (($flag & $filter) == 0);
+
+ my ($time, $line, $host) = lastlog($uid);
+ # fields to printf
+ $users{$u} = [ $type, $line, $host, $time ];
}
+endpwent();
+close $lastlog;
-my %filters = (
- 'all' => \&all,
- 'vyatta' => \&vyatta,
- 'locked' => \&locked,
- 'open' => \&nopasswd,
- 'other' => \&other,
- 'color' => \&colorize,
-);
+my $fmt = "%-15s %-7s %-8s %-19s %s\n";
+printf $fmt, "Username","Type","Tty", "From","Last login";
-for (@ARGV) {
- my $func = $filters{$_};
- unless ($func) {
- warn "Unknown type $_\n";
- usage();
- }
- print join("\n", sort($func->(keys %pw))), "\n";
+foreach my $u (sort keys %users) {
+ printf $fmt, $u, @{$users{$u}};
}