+ start = time( NULL );
+ while(( time( NULL ) - start < Timeout ) && ( ! NGIRCd_Quit ))
+ {
+ Check_Connections( );
+
+ /* Timeout initialisieren */
+ tv.tv_sec = 0;
+ tv.tv_usec = 50000;
+
+ /* noch volle Lese-Buffer suchen */
+ for( i = 0; i < MAX_CONNECTIONS; i++ )
+ {
+ if(( My_Connections[i].sock >= 0 ) && ( My_Connections[i].rdatalen > 0 ))
+ {
+ /* Kann aus dem Buffer noch ein Befehl extrahiert werden? */
+ Handle_Buffer( i );
+ }
+ }
+
+ /* noch volle Schreib-Puffer suchen */
+ FD_ZERO( &write_sockets );
+ for( i = 0; i < MAX_CONNECTIONS; i++ )
+ {
+ if(( My_Connections[i].sock >= 0 ) && ( My_Connections[i].wdatalen > 0 ))
+ {
+ /* Socket der Verbindung in Set aufnehmen */
+ FD_SET( My_Connections[i].sock, &write_sockets );
+ }
+ }
+
+ read_sockets = My_Sockets;
+ if( select( My_Max_Fd + 1, &read_sockets, &write_sockets, NULL, &tv ) == -1 )
+ {
+ if( errno != EINTR ) Log( LOG_ALERT, "select(): %s!", strerror( errno ));
+ return;
+ }
+
+ /* Koennen Daten geschrieben werden? */
+ for( i = 0; i < My_Max_Fd + 1; i++ )
+ {
+ if( FD_ISSET( i, &write_sockets )) Handle_Write( Socket2Index( i ));
+ }
+
+ /* Daten zum Lesen vorhanden? */
+ for( i = 0; i < My_Max_Fd + 1; i++ )
+ {
+ if( FD_ISSET( i, &read_sockets )) Handle_Read( i );
+ }
+ }
+} /* Conn_Handler */
+
+
+GLOBAL BOOLEAN Conn_WriteStr( CONN_ID Idx, CHAR *Format, ... )
+{
+ /* String in Socket schreiben. CR+LF wird von dieser Funktion
+ * automatisch angehaengt. Im Fehlerfall wird dir Verbindung
+ * getrennt und FALSE geliefert. */
+
+ CHAR buffer[MAX_CMDLEN];
+ BOOLEAN ok;
+ va_list ap;
+
+ va_start( ap, Format );
+ if( vsnprintf( buffer, MAX_CMDLEN - 2, Format, ap ) == MAX_CMDLEN - 2 )
+ {
+ Log( LOG_ALERT, "String too long to send (connection %d)!", Idx );
+ Conn_Close( Idx, "Server error: String too long to send!" );
+ return FALSE;
+ }
+
+#ifdef SNIFFER
+ Log( LOG_DEBUG, " -> connection %d: '%s'.", Idx, buffer );
+#endif
+
+ strcat( buffer, "\r\n" );
+ ok = Conn_Write( Idx, buffer, strlen( buffer ));
+
+ va_end( ap );
+ return ok;
+} /* Conn_WriteStr */
+
+
+GLOBAL BOOLEAN Conn_Write( CONN_ID Idx, CHAR *Data, INT Len )
+{
+ /* Daten in Socket schreiben. Bei "fatalen" Fehlern wird
+ * der Client disconnectiert und FALSE geliefert. */
+
+ assert( Idx >= 0 );
+ assert( My_Connections[Idx].sock >= 0 );
+ assert( Data != NULL );
+ assert( Len > 0 );
+
+ /* pruefen, ob Daten im Schreibpuffer sind. Wenn ja, zunaechst
+ * pruefen, ob diese gesendet werden koennen */
+ if( My_Connections[Idx].wdatalen > 0 )
+ {
+ if( ! Try_Write( Idx )) return FALSE;
+ }
+
+ /* pruefen, ob im Schreibpuffer genuegend Platz ist */
+ if( WRITEBUFFER_LEN - My_Connections[Idx].wdatalen - Len <= 0 )
+ {
+ /* der Puffer ist dummerweise voll ... */
+ Log( LOG_NOTICE, "Write buffer overflow (connection %d)!", Idx );
+ Conn_Close( Idx, NULL );
+ return FALSE;
+ }
+
+ /* Daten in Puffer kopieren */
+ memcpy( My_Connections[Idx].wbuf + My_Connections[Idx].wdatalen, Data, Len );
+ My_Connections[Idx].wdatalen += Len;
+
+ /* pruefen, on Daten vorhanden sind und geschrieben werden koennen */
+ if( My_Connections[Idx].wdatalen > 0 )
+ {
+ if( ! Try_Write( Idx )) return FALSE;
+ }
+
+ return TRUE;
+} /* Conn_Write */
+
+
+GLOBAL VOID Conn_Close( CONN_ID Idx, CHAR *Msg )
+{
+ /* Verbindung schliessen */
+
+ assert( Idx >= 0 );
+ assert( My_Connections[Idx].sock >= 0 );
+
+ if( Msg ) Conn_WriteStr( Idx, "ERROR :%s", Msg );
+
+ if( close( My_Connections[Idx].sock ) != 0 )