Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options

who for NT/2K

by idnopheq (Chaplain)
on Apr 23, 2001 at 14:55 UTC ( #74680=sourcecode: print w/replies, xml ) Need Help??
Category: NT Admin
Author/Contact Info idnopheq
Description: who - who is on the system

The who utility can list the user's name and login time for each current system user.

#!/usr/local/bin/perl -w

use strict;
use Win32::NetAdmin;
use Win32API::Net;
use vars qw ( @WhoList %UserInfo $UserName %Option );
use Getopt::Std;
use Win32::EventLog;

my ($VERSION) = '$Revision: 1.0 $' =~ /([.\d]+)/;

my $warnings = 0;

# Print a usuage message on a unknown option.

$SIG {__WARN__} = sub {
    if (substr ($_ [0], 0, 14) eq "Unknown option") {die "Usage"};
    require File::Basename;
    $0 = File::Basename::basename ($0);
    $warnings = 1;
    warn "$0: @_";

$SIG {__DIE__} = sub {
    require File::Basename;
    $0 = File::Basename::basename ($0);
    if (substr ($_ [0], 0,  5) eq "Usage") {
        die <<EOF;
$0 (NT Perl bin utils) $VERSION
$0 [ -H | -b | -B ] [ -h ]
    die "$0: @_";

# Get the options.

getopts ( 
    );                    # -h, -H, -B & -b take no option

die "Usage" if ( $Option{'h'} || scalar keys %Option > 1 );

my $Server = "";
my $Level = "11";
my @Month = (

LastReboot()  if $Option{'b'};
EventID6005() if $Option{'B'};

Win32::NetAdmin::LoggedOnUsers (
  or die "$^E\n";

printf "%s%30s\n", "USER", "LOGIN-TIME" if $Option{'H'};

foreach $UserName ( @WhoList ) {

sub UserGetInfo {
    my $LastLogon;
    my $Length;
    my $UserNameLength = length $UserName;
    if ( Win32API::Net::UserGetInfo (
                    ) ) {
    my (
       ) = localtime ( $UserInfo{lastLogon} );
    $Length = 27 - $UserNameLength;
    printf "%s%${Length}s %2d %2d:%2d\n",
    else {
    $Length = 31 - $UserNameLength;
    printf "%s%${Length}s\n", $UserName, "unknown";

sub LastReboot {
    my $Reboot = time - ( Win32::GetTickCount() / 1000 );
    my (
       ) = localtime ( $Reboot );
    printf "%22s %4s %2d %2d:%2d\n", "system boot", $Month[$mon], $mda
+y, $hour, $min;

sub EventID6005 {
    my (
    Win32::EventLog::Open($EventLog , "System", "") 
    or die ("EventLog Open() failed");
      or die ("EventLog GetOldest() failed");
      or die ("EventLog GetNumber() failed");

    $EventLog->Read (
    for my $i (0 .. $First+$Count-1) {
    $EventLog->Read (
      or die ("EventLog Read() failed at event $i");
    %Data = %{$Event};
    $Data{"EventID"} = $Data{"EventID"} & 0xffff;
    next unless $Data{"EventID"} == 6005;
    my (
       ) = localtime ( $Data{"TimeGenerated"} );
    printf "%22s %4s %2d %2d:%2d\n", "system boot", $Month[$mon], $mda
+y, $hour, $min;


=head1 NAME

B<who> - who is on the system


B<who> [ -H | -b | -B ]


The who utility can list the user's name and login time for each curre
+nt system user.

The general format for output is:

name time



=item name

user's login name.

=item time

time since user's login.


=head2 OPTIONS

The following options are supported:

=over 4

=item -b

Indicate the approximate time and date of the last reboot.

=item -B

Indicate a more exact but slower to acquire time and date of the last 

=item -H

Output column headings above the regular output.

=item -h

Display syntax.


=head1 EXAMPLE

Below is an example of the output B<who> provides without options:

C:\> who
shoehorn                unknown
Administrator           Jun 22  9:39

Below is an example of the output of B<who -H>:

C:\> who -H
USER                    LOGIN-TIME
shoehorn                unknown
Administrator           Jun 22  9:39

Below is an example of the output of B<who -b> and B<who -B>:

C:\> who -b
           system boot  Jun 21 15:29


The working of B<who> is not influenced by any environment variables.

=head1 BUGS

B<who> isn't as nice as I would like, but Win32 isn't Unix, now is it?
+  This I<really> doesn't like Samba domain controllers, which is whi 
+I added the 'unknown' entry in the output.

The B<-b> option returns an approximate uptime.  It uses the Win32::Ge
+tTickCount() function, an imprecise mechanism.  A better was to derri
+ve the last boot is to query the event log for the most recent 6005 o
+r 6009 event and grab that time.  If log files are large, this can be
+ time consuming.

B<printf> does not seem to want to pad numbers with '0's.


It does not make sense to talk about standards in a B<who> manual page


    Revision 1.0  2000/06/22 07:14:57  idnopheq
    Initial revision

=head1 AUTHOR

The Perl implementation of B<who> was written by Dexter Coffin, I<idno>.


This program is copyright by Dexter Coffin 2000.

This program is free and open software. You may use, copy, modify, dis
and sell this program (and any modified variants) in any way you wish,
provided you do not restrict others from doing the same.

=head1 SEE ALSO

=for html
<a href="uptime.html">uptime</a>, <a href="users.html">users</a><p>


Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: sourcecode [id://74680]
[Corion]: Yesterday I've been mulling over how to best generate HTTP requests from permutations of values but I haven't found a nice API for passing in the "template" of the HTTP request yet. I guess I'll have to do a SoPW for that
[Corion]: The API itself will basically be my $iter = generate_http_requ ests(method => 'GET', url => '/settings/:name', headers => ???, get_params => ['foo','bar']), but I'm not sure how to parametrize values in the headers and how to specify lists of ...
[choroba]: On the other hand, lots of options to receive the requests :-)
[Corion]: ... values to be used. For example, I think for headers, one would want to have various kinds of Content-Encoding headers, but for the get_parameters one would have various kinds of Bobby Tables
[choroba]: What about [metadoc:// Algorithm::Loops]?
[Corion]: choroba: Yeah, but handing off the request to Dancer,Plack, Mojolicious,LWP is easy once I have the data filled into some structure ;))
[choroba]: Algorithm::Loops
[Corion]: choroba: I'm using that to generate the permutations, but I don't know how the user can pass the intended values to my function in a sane way
[Corion]: I have a prototype that permutes the get_parameters, but the values used for the get parameters should be different from the values used for the headers and potentially for parts of the URL
[Corion]: But yes, in general, my approach will be "split the URL into another set of parameters, generate an array of allowed values for each parameter and then NestedLoops() over the set"

How do I use this? | Other CB clients
Other Users?
Others chanting in the Monastery: (9)
As of 2017-01-17 08:16 GMT
Find Nodes?
    Voting Booth?
    Do you watch meteor showers?

    Results (152 votes). Check out past polls.