tmi2_fluffos_v2/
tmi2_fluffos_v2/bin/
tmi2_fluffos_v2/etc/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/ChangeLog.old/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/Win32/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/compat/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/compat/simuls/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/include/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/clone/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/command/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/data/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/etc/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/include/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/inherit/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/inherit/master/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/log/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/tests/compiler/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/tests/efuns/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/tests/operators/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/u/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/tmp/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/windows/
tmi2_fluffos_v2/lib/
tmi2_fluffos_v2/lib/adm/
tmi2_fluffos_v2/lib/adm/daemons/languages/
tmi2_fluffos_v2/lib/adm/daemons/network/I3/
tmi2_fluffos_v2/lib/adm/daemons/virtual/
tmi2_fluffos_v2/lib/adm/daemons/virtual/template/
tmi2_fluffos_v2/lib/adm/news/
tmi2_fluffos_v2/lib/adm/obj/
tmi2_fluffos_v2/lib/adm/obj/master/
tmi2_fluffos_v2/lib/adm/priv/
tmi2_fluffos_v2/lib/adm/shell/
tmi2_fluffos_v2/lib/adm/tmp/
tmi2_fluffos_v2/lib/cmds/
tmi2_fluffos_v2/lib/d/
tmi2_fluffos_v2/lib/d/Conf/
tmi2_fluffos_v2/lib/d/Conf/adm/
tmi2_fluffos_v2/lib/d/Conf/boards/
tmi2_fluffos_v2/lib/d/Conf/cmds/
tmi2_fluffos_v2/lib/d/Conf/data/
tmi2_fluffos_v2/lib/d/Conf/logs/
tmi2_fluffos_v2/lib/d/Conf/obj/
tmi2_fluffos_v2/lib/d/Conf/text/help/
tmi2_fluffos_v2/lib/d/Fooland/adm/
tmi2_fluffos_v2/lib/d/Fooland/data/
tmi2_fluffos_v2/lib/d/Fooland/data/attic/
tmi2_fluffos_v2/lib/d/Fooland/items/
tmi2_fluffos_v2/lib/d/TMI/
tmi2_fluffos_v2/lib/d/TMI/adm/
tmi2_fluffos_v2/lib/d/TMI/boards/
tmi2_fluffos_v2/lib/d/TMI/data/
tmi2_fluffos_v2/lib/d/TMI/rooms/
tmi2_fluffos_v2/lib/d/grid/
tmi2_fluffos_v2/lib/d/grid/adm/
tmi2_fluffos_v2/lib/d/grid/data/
tmi2_fluffos_v2/lib/d/std/
tmi2_fluffos_v2/lib/d/std/adm/
tmi2_fluffos_v2/lib/data/adm/
tmi2_fluffos_v2/lib/data/adm/daemons/
tmi2_fluffos_v2/lib/data/adm/daemons/doc_d/
tmi2_fluffos_v2/lib/data/adm/daemons/emoted/
tmi2_fluffos_v2/lib/data/adm/daemons/network/http/
tmi2_fluffos_v2/lib/data/adm/daemons/network/services/mail_q/
tmi2_fluffos_v2/lib/data/adm/daemons/network/smtp/
tmi2_fluffos_v2/lib/data/adm/daemons/news/archives/
tmi2_fluffos_v2/lib/data/attic/connection/
tmi2_fluffos_v2/lib/data/attic/user/
tmi2_fluffos_v2/lib/data/std/connection/b/
tmi2_fluffos_v2/lib/data/std/connection/l/
tmi2_fluffos_v2/lib/data/std/user/a/
tmi2_fluffos_v2/lib/data/std/user/b/
tmi2_fluffos_v2/lib/data/std/user/d/
tmi2_fluffos_v2/lib/data/std/user/f/
tmi2_fluffos_v2/lib/data/std/user/l/
tmi2_fluffos_v2/lib/data/std/user/x/
tmi2_fluffos_v2/lib/data/u/d/dm/working/doc_d/
tmi2_fluffos_v2/lib/data/u/l/leto/doc_d/
tmi2_fluffos_v2/lib/data/u/l/leto/smtp/
tmi2_fluffos_v2/lib/doc/
tmi2_fluffos_v2/lib/doc/driverdoc/applies/
tmi2_fluffos_v2/lib/doc/driverdoc/applies/interactive/
tmi2_fluffos_v2/lib/doc/driverdoc/concepts/
tmi2_fluffos_v2/lib/doc/driverdoc/driver/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/arrays/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/buffers/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/compile/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/ed/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/filesystem/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/floats/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/functions/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/general/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/mappings/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/numbers/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/parsing/
tmi2_fluffos_v2/lib/doc/driverdoc/lpc/constructs/
tmi2_fluffos_v2/lib/doc/driverdoc/lpc/preprocessor/
tmi2_fluffos_v2/lib/doc/driverdoc/lpc/types/
tmi2_fluffos_v2/lib/doc/driverdoc/platforms/
tmi2_fluffos_v2/lib/doc/mudlib/
tmi2_fluffos_v2/lib/ftp/
tmi2_fluffos_v2/lib/include/driver/
tmi2_fluffos_v2/lib/log/
tmi2_fluffos_v2/lib/log/driver/
tmi2_fluffos_v2/lib/obj/net/
tmi2_fluffos_v2/lib/obj/shells/
tmi2_fluffos_v2/lib/obj/tools/
tmi2_fluffos_v2/lib/std/adt/
tmi2_fluffos_v2/lib/std/board/
tmi2_fluffos_v2/lib/std/body/
tmi2_fluffos_v2/lib/std/fun/
tmi2_fluffos_v2/lib/std/living/
tmi2_fluffos_v2/lib/std/object/
tmi2_fluffos_v2/lib/std/shop/
tmi2_fluffos_v2/lib/std/socket/
tmi2_fluffos_v2/lib/std/user/
tmi2_fluffos_v2/lib/std/virtual/
tmi2_fluffos_v2/lib/student/
tmi2_fluffos_v2/lib/student/kalypso/
tmi2_fluffos_v2/lib/student/kalypso/armor/
tmi2_fluffos_v2/lib/student/kalypso/rooms/
tmi2_fluffos_v2/lib/student/kalypso/weapons/
tmi2_fluffos_v2/lib/u/l/leto/
tmi2_fluffos_v2/lib/u/l/leto/cmds/
tmi2_fluffos_v2/lib/www/errors/
tmi2_fluffos_v2/lib/www/gateways/
tmi2_fluffos_v2/lib/www/images/
tmi2_fluffos_v2/old/
tmi2_fluffos_v2/win32/
/*
// File     :  /cmds/std/_who.c
// Comment  :  A command to let users know who else is on this mud
//	       It has the option to see who is on other muds
//	       There was a "who" command in MUD1, but the code for
//	       this one was written from scratch for TMI and is part
//	       of the TMI-2 distribution mudlib.  If you use any of
//	       this code, please keep this header.
// 91-**-** :  Jubal @ TMI wrote it
// 92-01-02 :  Sulam @ TMI changed the title stuff
// 92-01-20 :  DocZ @ TMI modified it for time zones
// 92-02-15 :  Truilkan @ TMI modified it for players (removed wizard only info)
//	       Original TMI _who is now _people
// 92-10-10 :  Mobydick modified it to respect invisibility
// 93-02-22 :  Pallando changed [0] to <login> on aesthetic grounds
// 93-03-22 :  Watcher removed user inhabited monsters from the display
// 93-04-14 :  Watcher change the query("invisible") to a visible() check
// 93-07-13 :  Grendel added sorting alphabetically
// 93-07-26 :  Grendel added -d option, optimised
// 93-08-18 :  Grendel added @mud option, optimised
// 94-06-06 :  Leto split do_who() off from cmd_who() for the use of http.c
// 94-06-12 :  Pallando fixed a few bugs
// 94-06-14 :  Leto added the checks for this_player for the http.c
// 94-09-04 :  Beek added some code for % ^FOO% ^ support
// XX-OO-XX :  Drizzt@Tmi-2 added support for I3 rwho requests

// Bugs: wont detect netdead wizards in monster bodies (!)
//       Don't know whether to get round this by checking for connection
//       objects or not - haven't looked at connection objects
//       closely yet to figure out if it is safe

//       Could be optimised some more...
*/

#include <writef.h>
#include <mudlib.h>
#include <net/daemons.h>
#include <net/macros.h>
#include <net/ftpd_base.h>

#define SYNTAX "Usage: who [ @<mud> | -d | -f ]\n"

inherit "/adm/daemons/timezone";
inherit DAEMON;

string do_who( string args );
string divide;

create()
{
    int i;
    
    ::create();
    for( divide = "", i = 0; i < 78; i++ )
	divide += "_";
    divide += "\n";
}

// sort array doesn't allow the optional argument the way filter array
// does, so we have to make it global
// This mapping is used so we don't have to do player->query("name")
// several zillion times in the sort function
mapping names;

int cmd_who( string arg )
{
    write( do_who( arg ) );
    return 1;
}

string ansi_kludge(string f1, string f2) {
    // Remember % ^FOO% ^ takes up no space
    string *tmp = explode(f1, "%^");
    int i,n;

    n = (sizeof(tmp)+1)/2;
    for (i=0; i<n; i++) tmp[i] = tmp[2*i];
    tmp = tmp[0..n-1];
    n = strlen(implode(tmp,""));
    return sprintf("%s%"+(65-n)+"s %4s\n", f1, "", f2);
}

string do_who( string arg )
{
    mixed *list;
    string lines, zone_name, str;
    int i, time_zone;
    int dead;
    string mud;
    
    names = ([]);
    // check args
    if( arg && arg != "" )
    {
	// linkdead option
	if( arg == "-d" )
	{
	    this_player()-> block_attack( 2 );
	    list = filter_array( children( USER ), "deadp", this_object() );
	    list = filter_array( list, "filter_users", this_object() );
	    if( !sizeof( list ) )
		return sprintf(
		  "%sThere are no linkdead users at this time\n%s",
		  divide, divide );
	    list = sort_array( list, "sort_users", this_object() );
	    write( divide + "  Linkdead users\n" + divide );
	    i = sizeof( list );
	    while( i-- )
		write( capitalize( geteuid( list[i] ) ) + "\n" );
	    write( divide );
	    return "";
	} else
	    if( arg == "-f" )
	    {
		this_player()-> block_attack( 2 );
		if (find_object(FTP_D) &&
		      catch( list = (mapping *)FTP_D->query_connections() ) )
		    return "";
		if( !sizeof( list ) )
		{
		    write( divide + "There are no FTP users at this time.\n"
		      + divide );
		    return "";
		}
		list = sort_array( list, "sort_users_in_mapping",
		  this_object() );
		write( divide + "  FTP users\n" + divide );
		i = sizeof( list );
		if( adminp(geteuid( previous_object() )) )
		    while( i-- )
		    {
			write( sprintf( "%-16s %s\n", ( list[i][USER_NAME] ),
			  ( list[i][USER_SITE] ) ) );
		    }
		else
		    while( i-- )
		    {
			write( ( list[i][USER_NAME] ) + "\n" );
		    }
		write( divide );
		return "";
	    // rwho option
	    } else if( sscanf( arg, "@%s", mud ) == 1 ) {
		return "/adm/daemons/network/I3/who"->send_who_req(mud, this_player()->query("name"));
	    } else {
		// bad option
		notify_fail( SYNTAX );
		return "";
	    }
    }
    
    if( this_player() ) this_player()-> block_attack( 2 );
    lines = divide;
    
    list = filter_array( users(), "filter_users", this_object() );
    list = sort_array( list, "sort_users", this_object() );
    
    if( !sizeof( list ) )
    {
	return( divide +
	  "\tLooks like no one is logged on. Strange beans, huh?\n" + divide );
    }
    
    if( sizeof( list ) > 1 )
	lines += "\t\t   There are " + sizeof( list ) +
	  " users connected.\n";
    else // (Buddha claims this message ;-)
	lines += "\t\tHow lonely!  You're the only one here.\n";
    
    if( this_player() )
	zone_name = (string)this_player()-> getenv( "TZONE" );
    else
	zone_name = "GMT";
    
    if( !time_zone = query_tzone( zone_name ) )
    {
	lines += "\t\tMud time is " + ctime( time() ) + "\n" +
	  "\t\t[Those contained in brackets are editing.]\n";
    } else {
	lines += "\t\t" + zone_name + " time is " + ctime( time_zone ) + "\n";
    }
    lines += divide +
      "Name                                                              Idle\n"
    + divide;
    
    i = sizeof( list );
    while( i-- )
    {
	string field1, field2;
	mixed val;
	
	if( !list[i] ) continue;
	if( (int)list[i]-> query( "npc" ) )
	    field1 = "(" + capitalize( (string)list[i]-> link_data( "name" ) ) +
	      " is inhabiting " +
	      (string)list[i]-> query( "short" ) + ")";
	else field1 = (string)list[i]-> query( "short" );
	
	if( in_edit( list[i] ) || in_input( list[i] ) )
	    field1 = "[" + field1 + "]";
	if( !field1 ) field1 = "(null)";
	if( field1 == "[0]" ) field1 = "<login>";
	
	val = query_idle( list[i] );
	if( val >= 3600 )
	    field2 = val/3600 + "h";
	else if( val >= 60 )
	    field2 = val/60 + "m";
	else field2 = "";
//	      lines += writef(field1,65,QUIET|TRUNC_RIGHT) + " "+
//		       writef(field2,4,QUIET|JFY_RIGHT) + "\n";
//	lines += sprintf( "%-:65s %4s\n", field1, field2 );
    lines += ansi_kludge( field1, field2 );
    }
    lines += divide;
    return( lines );
}

// note this returns the list in REVERSE order - this is a speed
// optimisation, instead of doing for(i=0;i<sizeof(foo);i++)
// we can do i=sizeof(foo); while(i--)
int sort_users( object u1, object u2 )
{
    // use the names mapping for speed
    return strcmp( names[u2], names[u1] );
}

int sort_users_in_mapping( mapping u1, mapping u2 )
{
    return strcmp( u1[USER_NAME], u2[USER_NAME] );
}

int filter_users( object who )
{
    if( (int)who-> query( "npc" ) && !wizardp( this_player() ) ) return 0;
    if( !who-> query( "name" ) ) return 0;
    if( visible( who, this_player() ) )
    {
	// build up the names mapping
	names[who] = (string)who-> query( "name" );
	return 1;
    }
    return 0;
}

// used by linkdead option
int deadp( object who )
{
    if( !geteuid( who ) )
	return 0;
    return (int)who-> query_linkdead();
}

int help()
{
    write( SYNTAX + "\n" + @HELP
The who command will give you a list of all user's presently logged
onto the MUD, and whether or not they are idle at this time.
The "@<mud>" options requests a list of users at the remote mud.
This is usually shorter than the finger output, though that depends
on the remote mud.
The "-d" option gives a list of linkdead users.
The "-f" options lists all current FTP users.
HELP
    );
    
    return 1;
}

/* EOF */