+GLOBAL CLIENT *
+Client_Search( CHAR *Nick )
+{
+ /* Client-Struktur, die den entsprechenden Nick hat, liefern.
+ * Wird keine gefunden, so wird NULL geliefert. */
+
+ CHAR search_id[CLIENT_ID_LEN], *ptr;
+ CLIENT *c = NULL;
+ UINT32 search_hash;
+
+ assert( Nick != NULL );
+
+ /* Nick kopieren und ggf. Host-Mask abschneiden */
+ strncpy( search_id, Nick, CLIENT_ID_LEN - 1 );
+ search_id[CLIENT_ID_LEN - 1] = '\0';
+ ptr = strchr( search_id, '!' );
+ if( ptr ) *ptr = '\0';
+
+ search_hash = Hash( search_id );
+
+ c = My_Clients;
+ while( c )
+ {
+ if( c->hash == search_hash )
+ {
+ /* lt. Hash-Wert: Treffer! */
+ if( strcasecmp( c->id, search_id ) == 0 ) return c;
+ }
+ c = (CLIENT *)c->next;
+ }
+ return NULL;
+} /* Client_Search */
+
+
+GLOBAL CLIENT *
+Client_GetFromToken( CLIENT *Client, INT Token )
+{
+ /* Client-Struktur, die den entsprechenden Introducer (=Client)
+ * und das gegebene Token hat, liefern. Wird keine gefunden,
+ * so wird NULL geliefert. */
+
+ CLIENT *c;
+
+ assert( Client != NULL );
+ assert( Token > 0 );
+
+ c = My_Clients;
+ while( c )
+ {
+ if(( c->type == CLIENT_SERVER ) && ( c->introducer == Client ) && ( c->token == Token )) return c;
+ c = (CLIENT *)c->next;
+ }
+ return NULL;
+} /* Client_GetFromToken */
+
+
+GLOBAL INT
+Client_Type( CLIENT *Client )
+{
+ assert( Client != NULL );
+ return Client->type;
+} /* Client_Type */
+
+
+GLOBAL CONN_ID
+Client_Conn( CLIENT *Client )
+{
+ assert( Client != NULL );
+ return Client->conn_id;
+} /* Client_Conn */
+
+
+GLOBAL CHAR *
+Client_ID( CLIENT *Client )
+{
+ assert( Client != NULL );
+
+#ifdef DEBUG
+ if( Client->type == CLIENT_USER ) assert( strlen( Client->id ) < CLIENT_NICK_LEN );
+#endif
+
+ if( Client->id[0] ) return Client->id;
+ else return "*";
+} /* Client_ID */
+
+
+GLOBAL CHAR *
+Client_Info( CLIENT *Client )
+{
+ assert( Client != NULL );
+ return Client->info;
+} /* Client_Info */
+
+
+GLOBAL CHAR *
+Client_User( CLIENT *Client )
+{
+ assert( Client != NULL );
+ if( Client->user[0] ) return Client->user;
+ else return "~";
+} /* Client_User */
+
+
+GLOBAL CHAR *
+Client_Hostname( CLIENT *Client )
+{
+ assert( Client != NULL );
+ return Client->host;
+} /* Client_Hostname */
+
+
+GLOBAL CHAR *
+Client_Password( CLIENT *Client )
+{
+ assert( Client != NULL );
+ return Client->pwd;
+} /* Client_Password */
+
+
+GLOBAL CHAR *
+Client_Modes( CLIENT *Client )
+{
+ assert( Client != NULL );
+ return Client->modes;
+} /* Client_Modes */
+
+
+GLOBAL CHAR *
+Client_Flags( CLIENT *Client )
+{
+ assert( Client != NULL );
+ return Client->flags;
+} /* Client_Flags */
+
+
+GLOBAL BOOLEAN
+Client_OperByMe( CLIENT *Client )
+{
+ assert( Client != NULL );
+ return Client->oper_by_me;
+} /* Client_OperByMe */
+
+
+GLOBAL INT
+Client_Hops( CLIENT *Client )
+{
+ assert( Client != NULL );
+ return Client->hops;
+} /* Client_Hops */
+
+
+GLOBAL INT
+Client_Token( CLIENT *Client )
+{
+ assert( Client != NULL );
+ return Client->token;
+} /* Client_Token */
+
+
+GLOBAL INT
+Client_MyToken( CLIENT *Client )
+{
+ assert( Client != NULL );
+ return Client->mytoken;
+} /* Client_MyToken */
+
+
+GLOBAL CLIENT *
+Client_NextHop( CLIENT *Client )
+{
+ CLIENT *c;
+
+ assert( Client != NULL );
+
+ c = Client;
+ while( c->introducer && ( c->introducer != c ) && ( c->introducer != This_Server )) c = c->introducer;
+ return c;
+} /* Client_NextHop */
+
+
+GLOBAL CHAR *
+Client_Mask( CLIENT *Client )
+{
+ /* Client-"ID" liefern, wie sie z.B. fuer
+ * Prefixe benoetigt wird. */
+
+ assert( Client != NULL );
+
+ if( Client->type == CLIENT_SERVER ) return Client->id;
+
+ snprintf( GetID_Buffer, GETID_LEN, "%s!%s@%s", Client->id, Client->user, Client->host );
+ return GetID_Buffer;
+} /* Client_Mask */
+
+
+GLOBAL CLIENT *
+Client_Introducer( CLIENT *Client )
+{
+ assert( Client != NULL );
+ return Client->introducer;
+} /* Client_Introducer */
+
+
+GLOBAL CLIENT *
+Client_TopServer( CLIENT *Client )
+{
+ assert( Client != NULL );
+ return Client->topserver;
+} /* Client_TopServer */
+
+
+GLOBAL BOOLEAN
+Client_HasMode( CLIENT *Client, CHAR Mode )
+{
+ assert( Client != NULL );
+ return strchr( Client->modes, Mode ) != NULL;
+} /* Client_HasMode */
+
+
+GLOBAL CHAR *
+Client_Away( CLIENT *Client )
+{
+ /* AWAY-Text liefern */
+
+ assert( Client != NULL );
+ return Client->away;
+} /* Client_Away */
+
+
+GLOBAL BOOLEAN
+Client_CheckNick( CLIENT *Client, CHAR *Nick )
+{
+ /* Nick ueberpruefen */
+
+ assert( Client != NULL );
+ assert( Nick != NULL );
+
+ /* Nick ungueltig? */
+ if( ! Client_IsValidNick( Nick ))
+ {
+ IRC_WriteStrClient( Client, ERR_ERRONEUSNICKNAME_MSG, Client_ID( Client ), Nick );
+ return FALSE;
+ }
+
+ /* Nick bereits vergeben? */
+ if( Client_Search( Nick ))
+ {
+ /* den Nick gibt es bereits */
+ IRC_WriteStrClient( Client, ERR_NICKNAMEINUSE_MSG, Client_ID( Client ), Nick );
+ return FALSE;
+ }
+
+ return TRUE;
+} /* Client_CheckNick */
+
+
+GLOBAL BOOLEAN
+Client_CheckID( CLIENT *Client, CHAR *ID )
+{
+ /* Nick ueberpruefen */
+
+ CHAR str[COMMAND_LEN];
+ CLIENT *c;
+
+ assert( Client != NULL );
+ assert( Client->conn_id > NONE );
+ assert( ID != NULL );
+
+ /* Nick zu lang? */
+ if( strlen( ID ) > CLIENT_ID_LEN )
+ {
+ IRC_WriteStrClient( Client, ERR_ERRONEUSNICKNAME_MSG, Client_ID( Client ), ID );
+ return FALSE;
+ }
+
+ /* ID bereits vergeben? */
+ c = My_Clients;
+ while( c )
+ {
+ if( strcasecmp( c->id, ID ) == 0 )
+ {
+ /* die Server-ID gibt es bereits */
+ sprintf( str, "ID \"%s\" already registered", ID );
+ if( Client->conn_id != c->conn_id ) Log( LOG_ERR, "%s (on connection %d)!", str, c->conn_id );
+ else Log( LOG_ERR, "%s (via network)!", str );
+ Conn_Close( Client->conn_id, str, str, TRUE );
+ return FALSE;
+ }
+ c = (CLIENT *)c->next;
+ }
+
+ return TRUE;
+} /* Client_CheckID */
+
+
+GLOBAL CLIENT *
+Client_First( VOID )
+{
+ /* Ersten Client liefern. */
+
+ return My_Clients;
+} /* Client_First */
+
+
+GLOBAL CLIENT *
+Client_Next( CLIENT *c )
+{
+ /* Naechsten Client liefern. Existiert keiner,
+ * so wird NULL geliefert. */
+
+ assert( c != NULL );
+ return (CLIENT *)c->next;
+} /* Client_Next */
+
+
+GLOBAL LONG
+Client_UserCount( VOID )
+{
+ return Count( CLIENT_USER );
+} /* Client_UserCount */
+
+
+GLOBAL LONG
+Client_ServiceCount( VOID )
+{
+ return Count( CLIENT_SERVICE );;
+} /* Client_ServiceCount */
+
+
+GLOBAL LONG
+Client_ServerCount( VOID )
+{
+ return Count( CLIENT_SERVER );
+} /* Client_ServerCount */
+
+
+GLOBAL LONG
+Client_MyUserCount( VOID )
+{
+ return MyCount( CLIENT_USER );
+} /* Client_MyUserCount */
+
+
+GLOBAL LONG
+Client_MyServiceCount( VOID )
+{
+ return MyCount( CLIENT_SERVICE );
+} /* Client_MyServiceCount */
+
+
+GLOBAL LONG
+Client_MyServerCount( VOID )
+{
+ CLIENT *c;
+ LONG cnt;
+
+ cnt = 0;
+ c = My_Clients;
+ while( c )
+ {
+ if(( c->type == CLIENT_SERVER ) && ( c->hops == 1 )) cnt++;
+ c = (CLIENT *)c->next;
+ }
+ return cnt;
+} /* Client_MyServerCount */
+
+
+GLOBAL LONG
+Client_OperCount( VOID )
+{
+ CLIENT *c;
+ LONG cnt;
+
+ cnt = 0;
+ c = My_Clients;
+ while( c )
+ {
+ if( c && ( c->type == CLIENT_USER ) && ( strchr( c->modes, 'o' ))) cnt++;
+ c = (CLIENT *)c->next;
+ }
+ return cnt;
+} /* Client_OperCount */
+
+
+GLOBAL LONG
+Client_UnknownCount( VOID )
+{
+ CLIENT *c;
+ LONG cnt;
+
+ cnt = 0;
+ c = My_Clients;
+ while( c )
+ {
+ if( c && ( c->type != CLIENT_USER ) && ( c->type != CLIENT_SERVICE ) && ( c->type != CLIENT_SERVER )) cnt++;
+ c = (CLIENT *)c->next;
+ }
+ return cnt;
+} /* Client_UnknownCount */
+
+
+GLOBAL BOOLEAN
+Client_IsValidNick( CHAR *Nick )
+{
+ /* Ist der Nick gueltig? */
+
+ CHAR *ptr, goodchars[20];
+
+ assert( Nick != NULL );
+
+ strcpy( goodchars, ";0123456789-" );
+
+ if( Nick[0] == '#' ) return FALSE;
+ if( strchr( goodchars, Nick[0] )) return FALSE;
+ if( strlen( Nick ) >= CLIENT_NICK_LEN ) return FALSE;
+
+ ptr = Nick;
+ while( *ptr )
+ {
+ if(( *ptr < 'A' ) && ( ! strchr( goodchars, *ptr ))) return FALSE;
+ if(( *ptr > '}' ) && ( ! strchr( goodchars, *ptr ))) return FALSE;
+ ptr++;
+ }
+
+ return TRUE;
+} /* Client_IsValidNick */
+
+
+LOCAL LONG
+Count( CLIENT_TYPE Type )
+{
+ CLIENT *c;
+ LONG cnt;
+
+ cnt = 0;
+ c = My_Clients;
+ while( c )
+ {
+ if( c->type == Type ) cnt++;
+ c = (CLIENT *)c->next;
+ }
+ return cnt;
+} /* Count */
+
+
+LOCAL LONG
+MyCount( CLIENT_TYPE Type )
+{
+ CLIENT *c;
+ LONG cnt;
+
+ cnt = 0;
+ c = My_Clients;
+ while( c )
+ {
+ if(( c->introducer == This_Server ) && ( c->type == Type )) cnt++;
+ c = (CLIENT *)c->next;
+ }
+ return cnt;
+} /* MyCount */
+
+
+LOCAL CLIENT *
+New_Client_Struct( VOID )