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:                   channels.c  (A daemon)
//      Author:                 Inspiral@Tabor, et al
//      Created:                93-05-10
//      Purpose:                To efficiently handle player communication.
//
// REVISON HISTORY:
// 930725  - Fixed problem with creating spurious channels!    -- Inspiral
// 930801  - Added scan_config()                               -- Inspiral
// 930803  - Reformatted data structure to use
//           more arrays than mappings                         -- Inspiral
// 930811  - Removed all reliances on query() and set() lfuns. -- Inspiral
// 930818  - Added log(), tell_user(), secure()                -- Inspiral
// 930826  - fixed bug in del user                             -- Pallando
// 931004  - added emotes                                      -- Rust
// 940322  - Rewritten to be faster, and to index users by object 
//                                                             -- Inspiral
// 940911  - Added missing prototpye                           -- Leto
// 950408  - Fixed minor bug with adminp                       -- Pallando
// 950422  - Added restrictions on Intermud for guest          -- Leto

#include <channels.h>

#define RESTRICTED_GUEST

int register_channel( string chan, object user, int state );
int log( string log_mesg );

mapping channels; // contains all our channel stats
mapping alias;  // a rude alias mechanism



// Begin tell_user()
int tell_user( object user, string mesg ) {
    tell_object( user, wrap( sprintf( "CHANNELS:\t%s\n", mesg ) ) );
    return 1;
}
// End tell_user()

// Begin create_channel()
static
varargs
int create_channel( string chan ) {
    if( channels[chan] ) return 1;
    
    channels[chan] = ([ ]);
    channels[chan]["vis"] = ({  });
    return 1;
}
// End of create_channel()


// Begin delete_channel()
static int kill_user( object user, string chan ) {
  if( undefinedp( channels[chan] ) ) return 0;
   channels[chan]["vis"] -= ({ user });
  return 1;
}

static varargs
int delete_channel( string chan ) {
    if( undefinedp( channels[chan] ) ) 
        return 0;
    
    map_delete( channels, chan );
    return 1;
}
// End of delete_channel()


// Beginning of add_user()
static
varargs
int add_user(string chan, object user) {
    string *toggle_list;
    string priv;
    
    if( !chan || !user ) return 0;
    
    if( !pointerp( toggle_list = ( string * ) user-> query( "channels" ) ) ) {
        user-> set( "channels", ({  }) );
        toggle_list = ({  });
    }
    
// chan doesn't exist...do we have permission to create it?
    if( undefinedp( channels[chan] ) ) {
#ifdef NO_NEW_CHANNELS
        return 0;
#endif
       create_channel( chan, user );
   } 
    
    if( !undefinedp( priv = channels[chan]["priv"] ) ) 
        if( !member_group( geteuid( user ), priv ) ) 
            if(!adminp(user))return 0;
    
    if( member_array( chan, toggle_list ) ==  - 1 ) 
        user -> add( "channels", ({ chan }) ); 
    
   channels[chan]["vis"] =
	uniq_array( channels[chan]["vis"] + ({ user }) );
    return 1;
}
// End of add_user()


static
int kill_users( mixed chan ) {
  int i;

  if( !chan ) chan = keys( channels );
  else chan = ({ chan });
 
  i = sizeof( chan );
  while( i-- )
      channels[chan[i]]["vis"] -= ({ 0 });

  return 1;
}


// Beginning of initialize_user()
varargs int initialize_user( object whom ) {
    int i, j;
    object *list;
    string *current_list;
    
    if( !whom || !living( whom ) ) list = users();
    else list = ({ whom });  // We have one user.
    
    i = sizeof( list );
    
    while( i-- ) {
        current_list = ( string * ) list[i] -> query( "channels" );
        
        if( !pointerp( current_list ) ) {
            list[i]-> set( "channels", ({  }) );
            current_list = ({  });
        }
        
        j = sizeof( current_list );
        
	while( j-- )
          register_channel( current_list[j], list[i], ADD );
        
    }
    return 1;
}
// End of initialize_user()



// Beginning of parse_channel()
varargs int parse_channel( string chan, string mesg, string name, int emote ) {
    int i;
    string *ignore;
     object *list, foo_ob;
    string ext_ob, err, plural;
    
    if( alias[chan] ) chan = alias[chan];
    if( undefinedp( channels[chan] ) ) return 0;
    kill_users( chan );
    if( undefinedp( ( list = channels[chan]["vis"] ) ) ) return 0;
    
    i = sizeof( list );  // Optimize is.
    
// Channel format is wrong in the daemon..Attempt a fix, but log.
    if( !pointerp( list ) ) {
        channels[chan]["vis"] = ({  });
        initialize_user();  // Shall we reconfigure?
        return log( sprintf( "parse_channel: channel %s "
          "is not a pointer!  Fixing.", identify( chan ) ) );
    }
    
// Is the name flag not given? or, is name not even in the list?
    if( this_player() )
        if( member_array( this_player(), list ) ==  - 1 ) return 0;
    
    if( this_player() && !name ) 
        name = (string) this_player() -> query( "cap_name" );

    if( !mesg || mesg == "" )
       return tell_user( this_player(), "Cannot broadcast blank messages!" );
    
    if( undefinedp( ( plural = channels[chan]["plural"] ) ) )
        plural = pluralize_verb( chan );
    
    while( i-- ) {
       if( mesg[0..5] == ":emote" ) {
          mesg = mesg[7..<1];
          emote = 1;
       }

     if( objectp( list[i] ) && list[i]  != this_player() ) {
         ignore = (string *) list[i] -> query( "ignore" );
         if( !pointerp( ignore ) ) ignore = ({ });
         if( member_array( lower_case( name ), ignore ) != -1 ) continue;
            
         if( list[i]-> getenv( "add_newline" ) ) 
		tell_object( list[i], "\n" );
     if( emote )
            message( "channels",
              iwrap(capitalize(chan)+": "+name+" "+mesg), list[i]);
            else
            message( "channels",
              iwrap( name + " " + plural + ": " + mesg ), list[i] );
            continue;
        }
        
        if( list[i] == this_player() )
         if( emote )
            message( "channels",
              iwrap(capitalize(chan)+": "+name+" "+mesg), list[i]);
        else
            message( "channels",
              iwrap( "You " + chan + ": " + mesg ), list[i] );
   } // while() 

// Do we have an apply to an external object?
    chan = lower_case( chan );
    if( !undefinedp( ( ext_ob = channels[chan]["object"] ) ) ) {
// format of object flag:  alias#object
        sscanf( ext_ob, "%s#%s", chan, ext_ob );
        
#ifdef RESTRICTED_GUEST
if (this_player() && getuid(this_player()) == "guest") {
  notify_fail("Due to abuse, guest isn't allowed on the Intermud.\n");
    return 0;
}
#endif RESTRICTED_GUEST
// Attempt the apply, log all errors
        foo_ob = find_object_or_load(ext_ob);
        if( err = catch( foo_ob->
          daemon_apply( this_player(), chan, mesg, emote ) ) )
            log( sprintf( "parse_channel:\tError in %s:\n%s",
              ext_ob, err ) );
    }
    
    return 1;
}
// End of parse_channel()


// Begin of display_channel()
varargs mixed display_channel( string chan, object viewer ) {
    mixed list;
    
    if( !chan || chan == "" ) list = keys( channels );
    else {
        if( undefinedp( list = channels[chan] ) )
            return sprintf( "There is no such channel:  %s.",
              identify( chan ) );
        list = channels[chan]["vis"];
    }
    
    if( !pointerp( list ) || !sizeof( list ) ) {
        channels[chan]["vis"] = ({  });
        return sprintf( "CHANNELS:\tNo Users Subscribed to %s",
          identify( chan ) );
    }
    if( chan && chan != "" )
    list = filter_array( list, "flush_list", this_object(), viewer );
    list = map_array( list, "get_cap", this_object() );
    
    list = ( implode( list, "   " ) + "   <End>" );
    return list;
}
// End of display_channel()


// Begin scan_config()
static
int scan_config() {
    string *list, *split_line;
    string line;
    int i, j;
    
    list = update_file( CHANNELS_CONFIG );
    i = sizeof( list );
    
// Once through the i for each non-"#" line in config file
    while( i-- ) {
        line = list[i];
        if( line ) {
            split_line = explode( line, ":" );
            j = sizeof( split_line );
            
            channels[split_line[0]] = allocate_mapping( 6 );
            channels[split_line[0]]["vis"] = ({  });
            
	    while( j-- ) {
                if( ( split_line[j] != "X" ) &&
                  ( CHANNELS_INFO[j] != "" ) )
                    channels[split_line[0]][CHANNELS_INFO[j]] =
                      split_line[j];
            } // while (j)
            
        }  // IF (LINE)
    } // while (i)
    
    return 1;
}


// Begin log()
int log( string log_mesg ) {
    if( !log_mesg || log_mesg == "" ) return 0; ;
    
    log_file( CHANNELS_LOG, sprintf( "%s %O - %s\n",
      intl_date_stamp( 1 ), previous_object(), log_mesg ) );
    return 0;
}
// End of log()


mixed q() { return copy( channels );  }
mixed a() { return copy( alias );  }

// Begin process_alias()
void process_alias() {
    int i;
    string *list;
    string temp1;
    
    list = keys( channels );
    i = sizeof( list );
    
    while( i-- ) {
        if( !undefinedp( temp1 = channels[list[i]]["object"] ) )
            if( sscanf( temp1, "%s#%*s", temp1 ) == 2 )
                alias += ([ temp1 : list[i] ]);
    }
}

// Begin get_cap()
string get_cap( object ob ) { 
   return (string) ob -> query( "cap_name" );
}
// End get_cap()

// Begin flush_list()
int flush_list( object user, object viewer ) {
    return (objectp(user) && visible(user, viewer) && interactive(user));
}
// end flush_list()
// Begin create()
void create() {
    channels = allocate_mapping( 20 );
    alias = allocate_mapping( 20 );
    
    seteuid( getuid() );
    scan_config();
    process_alias();
    call_out( "initialize_user", 2 );
}
// End of create()

// Begin register_channel()
varargs
int register_channel( string chan, object user, int state) {
    int ret;
    
    if( nullp( state ) ) {
            notify_fail(  "register_channel:  no state given!" );
        return 0;
    }
    
    switch( state ) {
        case DEL: ret = delete_channel( chan, user ); break;
        case CRE: ret = create_channel( chan, user, state ); break;
        case ADD: ret = add_user( chan, user ); break;
        case KIL: ret = kill_user( user, chan );
        break;
        default: ret = 0; break;
    }
    return ret;
}
// End of register_channel()