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     :  _call.c
// Syntax   :  int cmd_call( string a );
// Purpose  :  allow wizards to call functions in objects
// 92-06-00 :  Douglas Reay (aka Pallando @ many muds) wrote a bin based wizard
//             tool for Ephemeral Dale lpmud (LPC2)
// 92-10-00 :  Pallando wrote a basic multi-reference tracer for this
// 93-01-02 :  Pallando changed refs to be stored on player not in daemon
//             This file is now part of the TMI-II mudlib distribution.
//             Please retain this header if you use any of this code.
// 93-03-19 :  Pallando changed refs over to get_objects()
// 93-07-17 :  Robocoder switched call_other to arrays, ie ({ func, args... })
// 93-08-20 :  Grendel allowed admins to call with any euid
// 93-08-23 :  Pallando changed it to inherit REF_D
// 93-10-22 : Mobydick added the ADMIN_ONLY define.
*/
#include <daemons.h>
#include <mudlib.h>
#include <logs.h>
#include <uid.h>

#define NO_USER_CALLS 1

inherit DAEMON;
inherit REF_D;

#define SYNTAX "Syntax: call [-<uid>] <object>;<function>;<arg>;<arg>\n"
#define FUNC_LIST ({ "query_skills", "query_nicknames", "query_aliases" })
#define TAB "\t"

static
string * do_call( object ob, string func, mixed args );

int cmd_call( string a )
{
  string str, *exp_a;
  mixed objs, funcs, args, tmp, ret, rets;
  object ob;
  int i, s, fi, fs;

  if( !a ) { notify_fail( SYNTAX ); return 0; }

#ifdef ADMIN_ONLY
  if (!adminp(geteuid(this_player()))) {
    write ("Sorry, this command can only be used by admins.\n") ;
    return 1 ;
  }
#endif


#ifdef EVAL_CALL_LOG

    seteuid(ROOT_UID);
    if (!adminp(geteuid(this_player())))
        log_file(EVAL_CALL_LOG, "************\n" +
             extract(ctime(time()), 4, 15) +
            " [" + geteuid(this_player()) + "] call'd: " + a + "\n");
#endif

  // do this first in case something bombs out below
  seteuid( geteuid( previous_object() ) );

  if(a[0] == '-')
  {
    if(a[1] == '-')
      a = a[2..<1];
    else if (geteuid(previous_object())
	     && adminp(geteuid(previous_object()))
	     && previous_object() == this_player()
	     && this_player() == this_player(1))
    {
      i = strsrch(a, ' ');
      if(i != -1)
      {
	seteuid(a[1..(i-1)]);
	a = a[(i+1)..<1];
      } else {
	notify_fail("call: seteuid: bad euid\n");
	return 0;
      }
    } else {
      notify_fail("call: seteuid: permission denied\n");
      return 0;
    }
  }

  exp_a = explode( a, ";" );
  s = sizeof( exp_a );
  objs = exp_a[0];
  if( s > 1 ) funcs = exp_a[1];
  else funcs = FUNC_LIST;
  if( s == 3 ) args = ({ exp_a[2] });
  if( s > 3 ) args = exp_a[2..(s-1)];

  objs = resolv_ref( objs );
  if( objs == "users" ) objs = users();
  if( !pointerp( objs ) ) objs = ({ objs });
  tmp = ({ });
  s = sizeof( objs );
  for( i = 0 ; i < s ; i++ )
  {
    if( stringp( objs[i] ) ) ob = get_objects( objs[i],0,1 );
    else if( objectp( objs[i] ) ) ob = objs[i];
    if( !ob ) write( wrap( "Can't identify " + identify( objs[i] ) +
      " as an object." ) );
    else tmp += ({ ob });
  }
  if( !sizeof( tmp ) ) return 1;
  objs = tmp;

  funcs = resolv_ref( funcs );
  if( !pointerp( funcs ) ) funcs = ({ funcs });
  tmp = ({ });
  s = sizeof( funcs );
  for( i = 0 ; i < s ; i ++ )
  {
    if( stringp( funcs[i] ) ) tmp += ({ funcs[i] });
    else write( wrap( "Can't identify " + identify( funcs[i] )+
      " as a string." ) );
  }
  if( !sizeof( tmp ) ) return 1;
  funcs = tmp;

  if( pointerp( args ) && ( s = sizeof( args ) ) )
    for( i = 0 ; i < s ; i++ )
      args[i] = resolv_ref( resolv_str( args[i] ) );

  rets = ({ });
  s = sizeof( objs );
  fs = sizeof( funcs );
  for( i = 0 ; i < s ; i++ )
  {
    str = identify( objs[i] );
    for( fi = 0 ; fi < fs ; fi++ )
    {
      ret = do_call( objs[i], funcs[fi], args );
      if( ret[0] ) rets += ({ ret[0] });
      if( fs == 1 ) str = wrap( str + ret[1] );
      else str += (fi?"":"\n") + wrap( ret[1] );
    }
    write( str );
  }
  switch( sizeof( rets ) )
  {
    case 0: rets = 0; break;
    case 1: rets = rets[0];
  }
  set_ref( "default", rets );

  return 1;
}

static
string *do_call( object ob, string func, mixed args )
{
  mixed ret, err;
  int i, s;
  string str;
  object shad;

  if( !function_exists( func, ob ) )
  {
    for( shad = shadow( ob, 0 ) ; shad ; shad = shadow( shad, 0 ) )
      if( function_exists( func, shad ) ) { ob = shad; break; }
    if( ob != shad ) return ({ 0, "- does not contain " + func + "()" });
  }
  str = "-> " + func;
  if( pointerp( args ) && ( s = sizeof( args ) ) )
  {
    str += "( ";
    for( i = 0 ; i < s ; i++ )
    {
      if( i ) str += ", ";
      str += identify( args[i] );
    }
    str += " )";
  } else str += "()";
    
#ifdef NO_USER_CALLS
  if (!adminp(getuid(this_player()))) {
    if (userp(ob) && getuid(ob)!=getuid(this_player())) {
	return ({ 0, str+" = Illegal operation." }) ;
    }
  }
#endif
  if (!s) {
      err = catch(
        ret = call_other(ob, func)
      );
  } else {
      err = catch(
        ret = call_other(ob, ({ func }) + args)
      );
  }
  if( err ) return ({ 0, str + TAB + "= ERR(" + identify( err ) + ")" });
  return ({ ret, str + TAB + "= " + identify( ret ) });
}

int help()
{
  write( SYNTAX +
    "Effect: Calls the function <function> in object <object>,\n"+
    "passing as many arguments <arg> as you give.\n"+ 
    "If no function is specified a dump of the object is given.\n"+
    "<object> and <function> can be arrays (eg \"users\")\n"+
    "Any of them can be references (qv help refs)\n"+
  "" );
  return 1;
}