Commits

Palmer, 2E0EOL  committed 96cb40c

Entire changeset 0.0.12 -> 0.0.13

  • Participants
  • Parent commits 0da521a
  • Tags overchat-0.0.13

Comments (0)

Files changed (38)

 daily with any changes to the server and made available
 at http://www.daybologic.co.uk/overchat/ChangeLog
 
-22/12/2001 - 0.0.12-STABLE
+30/12/2001 - 0.0.13-STABLE
+----------
+DDRP: Fix: Accidental use of strcpy() not strcmp() in server_auth
+DDRP: Fix: Open files in text not binary mode (dlini)
+DDRP: Fix: dlini_int_ChopCrap() didn't know about \r's (dlini)
+DDRP: Fix: Accidental failure to free exPacket in i_ProcessIncoming (Blake)
+DDRP: Fix: Math bug in i_PacketCompiler (TX/RX)
+DDRP: Add uptime to logs every day and at shutdown
+DDRP: Fork into a background process if running on UNIX
+
+29/12/2001
+----------
+DDRP: Experimental offsets in packet receiving.
+DDRP: Fix: Math bug in RECEIVE_FROM_BUFFER (blake protocol)
+DDRP: Fix: Packet compiler gives wrong length to crack packet
+DDRP: Insignificant change to login size calculation method
+DDRP: Added number of bytes to data arrived event
+DDRP: Fix: Packet compiler to compile all available packets on a socket and not 2 bytes!
+DDRP: Fix: Login packet receiver did not update caller's offset
+DDRP: Wrote authenticator
+DDRP: Added socket info to Blake callbacks
+
+28/12/2001
+----------
+DDRP: dlini supports GetPrivateProfileString() & GetPrivateProfileInt()
+
+25/12/2001
+----------
+DDRP: Fix: (Blake protocol) i_ReceivePacket() not offsetting addresses given to subfunctions.
+DDRP: Fix: (Blake protocol) i_ReceivePacket() uninitialised error return
+
+24/12/2001 - 0.0.12-24122001-STABLE
+----------
+DDRP: Fix: Ignore old sockets sending data to TX/RX (remove detection trap)
+DDRP: Reorder operations for disconnecting a user.
+DDRP: Remove some debug info from server_core
+
+22/12/2001 - 0.0.12
 ----------
 DDRP - Added buildtimer for timed builds (current=1 min, 14 secs)
 DDRP - Fix: Accidental free of NULL pointer in blake_CrackPacket()
 
 
 # Master build rule
-all : tools memory_debugger dlini_lib blake_lib overchat cgi _clients
+all : tools memory_debugger libs blake_lib overchat cgi _clients
 	cd buildtimer ; gmake -f $(THISFILE) stop
 	@echo Build complete
 
 	&& ../blakemake/blakemake --debug --server \
 	&& gmake -f $(THISFILE) blake_lib
 
+libs : dlini_lib
+
 dlini_lib:
 	cd dlini && gmake -f $(THISFILE)
 

File Makefile.gnu

 
 
 # Master build rule
-all : tools memory_debugger dlini_lib blake_lib overchat cgi _clients
+all : tools memory_debugger libs blake_lib overchat cgi _clients
 	cd buildtimer ; gmake -f $(THISFILE) stop
 	@echo Build complete
 
 	&& ../blakemake/blakemake --debug --server \
 	&& gmake -f $(THISFILE) blake_lib
 
+libs : dlini_lib
+
 dlini_lib:
 	cd dlini && gmake -f $(THISFILE)
 

File blake/blake.h

   packets that can be processed are handled install a callback for
   every possible client code (or server code in the case of the server)
   by calling this function many times within a a setup function before
-  cracking any packets.  IsServer should not be set by clients.  The Code
+  cracking any packets.  IsServer should be set by clients.  The Code
   should be cast from an enum blakeClientCode.  The callback should be
   able to accept a void pointer.  The void pointer is in reality the
   correct structure for that type of callback and should be cast to
-  one of the structures in this file. Callbacks should report
+  one of the structures in this file.  In addition, the int Sock is the
+  socket of the relevant caller connection (user). Callbacks should report
   failure by returning zero or false.  If the installer reports an error,
   display it to the user as this is a-typical.
   A unique number corrosponding to the thread you are calling from is
   is acceptable or your own numbering system.  but don't get the two systems
   confused!
 */
-enum blakeError BLAKEAPI blake_InstallCallback(const int ThreadID, bool IsServer, WORD Code, bool (*UserCallback)(const void*));
+enum blakeError BLAKEAPI blake_InstallCallback(const int ThreadID, bool IsServer, WORD Code, bool (*UserCallback)(int, const void*));
 
 /*
   Networking

File blake/blake_cb.c

 /* Before changing any of the callbacks make sure the mutant is locked */
 static struct {
   recursiveMutant* mutantPtr;
-  bool (*suspend)(struct blakeSuspend* PBlakeSuspend);
-  bool (*resume)(struct blakeResume* PResume);
-  bool (*challenge)(struct blakeChallenge* PChallenge);
-  bool (*goterror)(struct blakeGotError* PGotError);
-  bool (*listresponse)(struct blakeListResponse* PListResponse);
-  bool (*whoisinfo)(struct blakeWhoisInfo* PWhoisInfo);
-  bool (*versioned)(struct blakeVersioned* PVersionVersioned);
-  bool (*super)(struct blakeSuper* PSuper);
-  bool (*killed)(struct blakeKilled* PKilled, const char* Message);
-  bool (*chumsignon)(struct blakeChumSignon* PChumSignon);
-  bool (*chumsignoff)(struct blakeChumSignoff* PChumSignoff);
-  bool (*chumidle)(struct blakeChumIdle* PChumIdle);
-  bool (*login)(struct blakeLogin* PLogin);
-  bool (*superrequest)(struct blakeSuperRequest* PSuperRequest);
-  bool (*addwanker)(struct blakeAddWanker* PAddWanker);
-  bool (*notwanker)(struct blakeNotWanker* PNotWanker);
-  bool (*joinchat)(struct blakeJoinChat* PJoinChat);
-  bool (*list)(struct blakeList* PList);
-  bool (*killuser)(struct blakeKillUser* PKillUser, const char* Message);
-  bool (*killchat)(struct blakeKillChat* PKillChat);
-  bool (*kick)(struct blakeKick* PKick);
-  bool (*reserved0)(struct blakeReserved0* PReserved0);
-  bool (*nonsense0)(struct blakeNonsense0* PNonsense0);
-  bool (*version)(struct blakeVersion* PVersion);
-  bool (*message)(struct blakeMessage* PMessage, const char* IMMessage);
-  bool (*chatmsg)(struct blakeChatMsg* PChatMsg, const char* ChatMessage);
-  bool (*whois)(struct blakeWhois* PWhois);
-  bool (*undocumented0)(struct blakeUndocumented0* PUndocumented0);
-  bool (*remoteshutdown)(struct blakeRemoteShutdown* PRemoteShutdown);
-  bool (*chumadd)(struct blakeChumAdd* PChumAdd);
-  bool (*chumremove)(struct blakeChumRemove* PChumRemove);
-  bool (*idle)(struct blakeIdle* PIdle);
+  bool (*suspend)(int Sock, struct blakeSuspend* PBlakeSuspend);
+  bool (*resume)(int Sock, struct blakeResume* PResume);
+  bool (*challenge)(int Sock, struct blakeChallenge* PChallenge);
+  bool (*goterror)(int Sock, struct blakeGotError* PGotError);
+  bool (*listresponse)(int Sock, struct blakeListResponse* PListResponse);
+  bool (*whoisinfo)(int Sock, struct blakeWhoisInfo* PWhoisInfo);
+  bool (*versioned)(int Sock, struct blakeVersioned* PVersionVersioned);
+  bool (*super)(int Sock, struct blakeSuper* PSuper);
+  bool (*killed)(int Sock, struct blakeKilled* PKilled, const char* Message);
+  bool (*chumsignon)(int Sock, struct blakeChumSignon* PChumSignon);
+  bool (*chumsignoff)(int Sock, struct blakeChumSignoff* PChumSignoff);
+  bool (*chumidle)(int Sock, struct blakeChumIdle* PChumIdle);
+  bool (*login)(int Sock, struct blakeLogin* PLogin);
+  bool (*superrequest)(int Sock, struct blakeSuperRequest* PSuperRequest);
+  bool (*addwanker)(int Sock, struct blakeAddWanker* PAddWanker);
+  bool (*notwanker)(int Sock, struct blakeNotWanker* PNotWanker);
+  bool (*joinchat)(int Sock, struct blakeJoinChat* PJoinChat);
+  bool (*list)(int Sock, struct blakeList* PList);
+  bool (*killuser)(int Sock, struct blakeKillUser* PKillUser, const char* Message);
+  bool (*killchat)(int Sock, struct blakeKillChat* PKillChat);
+  bool (*kick)(int Sock, struct blakeKick* PKick);
+  bool (*reserved0)(int Sock, struct blakeReserved0* PReserved0);
+  bool (*nonsense0)(int Sock, struct blakeNonsense0* PNonsense0);
+  bool (*version)(int Sock, struct blakeVersion* PVersion);
+  bool (*message)(int Sock, struct blakeMessage* PMessage, const char* IMMessage);
+  bool (*chatmsg)(int Sock, struct blakeChatMsg* PChatMsg, const char* ChatMessage);
+  bool (*whois)(int Sock, struct blakeWhois* PWhois);
+  bool (*undocumented0)(int Sock, struct blakeUndocumented0* PUndocumented0);
+  bool (*remoteshutdown)(int Sock, struct blakeRemoteShutdown* PRemoteShutdown);
+  bool (*chumadd)(int Sock, struct blakeChumAdd* PChumAdd);
+  bool (*chumremove)(int Sock, struct blakeChumRemove* PChumRemove);
+  bool (*idle)(int Sock, struct blakeIdle* PIdle);
 } callbacks;
 /*-------------------------------------------------------------------------*/
 bool blake_cb_Init()
   }
 }
 /*-------------------------------------------------------------------------*/
-bool blake_cb_Call(const struct blakePacket* BlakePacketPtr, const int ThreadID)
+bool blake_cb_Call(int Sock, const struct blakePacket* BlakePacketPtr, const int ThreadID)
 {
   bool status = false;
   blake_Trace("in blake_cb_Call");
           if ( callbacks.suspend ) {
             struct blakeSuspend suspend;
             memcpy(&suspend, &BlakePacketPtr->info._suspend, sizeof(suspend));
-            status = callbacks.suspend(&suspend);
+            status = callbacks.suspend(Sock, &suspend);
           }
           break;
         }
           if ( callbacks.resume ) {
             struct blakeResume resume;
             memcpy(&resume, &BlakePacketPtr->info._resume, sizeof(resume));
-            status = callbacks.resume(&resume);
+            status = callbacks.resume(Sock, &resume);
           }
           break;
         }
           if ( callbacks.challenge ) {
             struct blakeChallenge challenge;
             memcpy(&challenge, &BlakePacketPtr->info._challenge, sizeof(challenge));
-            status = callbacks.challenge(&challenge);
+            status = callbacks.challenge(Sock, &challenge);
             printf("status after bscchallenge callback is %d\n", status);
           }
           break;
           if ( callbacks.goterror ) {
             struct blakeGotError gotError;
             memcpy(&gotError, &BlakePacketPtr->info._goterror, sizeof(gotError));
-            status = callbacks.goterror(&gotError);
+            status = callbacks.goterror(Sock, &gotError);
           }
           break;
         }
           if ( callbacks.listresponse ) {
             struct blakeListResponse lr;
             memcpy(&lr, &BlakePacketPtr->info._listresponse, sizeof(lr));
-            status = callbacks.listresponse(&lr);
+            status = callbacks.listresponse(Sock, &lr);
           }
           break;
         }
           if ( callbacks.login ) {
             struct blakeLogin login;
             memcpy(&login, &BlakePacketPtr->info._login, sizeof(login));
-            status = callbacks.login(&login);
+            status = callbacks.login(Sock, &login);
           }
           break;
         }
   return status;
 }
 /*-------------------------------------------------------------------------*/
-enum blakeError BLAKEAPI blake_InstallCallback(const int ThreadID, bool IsServer, WORD Code, bool (*UserCallback)(const void*))
+enum blakeError BLAKEAPI blake_InstallCallback(const int ThreadID, bool IsServer, WORD Code, bool (*UserCallback)(int, const void*))
 {
   enum blakeError ret = blakeSuccess;
-
   blake_cb_AquireLock(ThreadID);
   if ( IsServer ) {
     switch ( (enum blakeServerCodes)Code ) {
       case bscsuspend : {
-        callbacks.suspend = (bool (*)(struct blakeSuspend*))UserCallback;
+        callbacks.suspend = (bool (*)(int Sock, struct blakeSuspend*))UserCallback;
         break;
       }
       case bscresume : {
-        callbacks.resume = (bool (*)(struct blakeResume*))UserCallback;
+        callbacks.resume = (bool (*)(int Sock, struct blakeResume*))UserCallback;
         break;
       }
       case bscchallenge : {
-        callbacks.challenge = (bool (*)(struct blakeChallenge*))UserCallback;
+        callbacks.challenge = (bool (*)(int Sock, struct blakeChallenge*))UserCallback;
         break;
       }
       case bscgoterror : {
-        callbacks.goterror = (bool (*)(struct blakeGotError*))UserCallback;
+        callbacks.goterror = (bool (*)(int Sock, struct blakeGotError*))UserCallback;
         break;
       }
       case bsclist_response : {}
   else { /* Client code */
     switch ( (enum blakeClientCodes)Code ) {
       case bcclogin : {
-        /*callbacks.login = (bool (*cb)(blakeLogin*))UserCallback;*/
+        callbacks.login = (bool (*)(int Sock, struct blakeLogin*))UserCallback;
         break;
       }
       case bccsuper_request : {}
       case bccnonsense0 : {}
       case bccversion : {}
       case bccmessage : {
-        callbacks.message = (bool (*)(struct blakeMessage*, const char* IMMessage))UserCallback;
+        callbacks.message = (bool (*)(int Sock, struct blakeMessage*, const char* IMMessage))UserCallback;
         break;
       }
       case bccchatmsg : {
-        callbacks.chatmsg = (bool (*)(struct blakeChatMsg*, const char* ChatMessage))UserCallback;
+        callbacks.chatmsg = (bool (*)(int Sock, struct blakeChatMsg*, const char* ChatMessage))UserCallback;
         break;
       }
       case bccwhois : {}

File blake/blake_cb.h

 void blake_cb_ReleaseLock(const int ThreadID); /* Make sure to call this afterwards */
 /* NOTE: All functions are self locking with a recursive mutant only use the explicit locks for extended locking */
 void blake_cb_Reset(const int ThreadID); /* Clear all callbacks out */
-bool blake_cb_Call(const struct blakePacket* BlakePacketPtr, const int ThreadID); /* Call the appropriate callback, result is from callback, check IsInstalled first and be sure to lock for the duration of both calls */
+bool blake_cb_Call(int Sock, const struct blakePacket* BlakePacketPtr, const int ThreadID); /* Call the appropriate callback, result is from callback, check IsInstalled first and be sure to lock for the duration of both calls */
 bool blake_cb_IsInstalled(bool IsServer, WORD Code, const int ThreadID);
 
 #ifdef __cplusplus

File blake/blake_protocol.c

 
 /* Used by packet receiver(s) reading from user buffers */
 #define RECEIVE_FROM_BUFFER(element) \
-          if ( (sizeof((element))+offset) >= BuffSizeIn ) { \
+          if ( (sizeof((element))+offset) > BuffSizeIn ) { \
             if ( exPacketPointer ) \
               free(exPacketPointer); \
             err = blakeBufferTooSmall; \
 
     /* Read length of packet */
     RECEIVE_FROM_BUFFER(PPacketOut->len)
-    if ( !ret ) return ret;
+    if ( !ret ) goto ret;
 
     PPacketOut->len = (blake_word16_t)network_NetToHostShort((unsigned short int)PPacketOut->len);
 
     /* Read server/client indicator */
     RECEIVE_FROM_BUFFER(PPacketOut->server)
-    if ( !ret ) return ret;
+    if ( !ret ) goto ret;
 
     /* Read server or client code */
     RECEIVE_FROM_BUFFER(enumSwapper)
-    if ( !ret ) return ret;
+    if ( !ret ) goto ret;
 
     enumSwapper = (blake_word16_t)network_NetToHostShort((unsigned short int)enumSwapper);
     if ( PPacketOut->server ) /* Code will be a server code */
     if ( PPacketOut->server ) {
       switch ( PPacketOut->code.serverCode ) {
         case bscsuspend : {
-          err = i_ReceiveSuspend(BuffRawIn, BuffSizeIn, &PPacketOut->info._suspend, &offset);
+          err = i_ReceiveSuspend(BuffRawIn + offset, BuffSizeIn, &PPacketOut->info._suspend, &offset);
           break;
         }
         case bscresume : {
-          err = i_ReceiveResume(BuffRawIn, BuffSizeIn, &PPacketOut->info._resume, &offset);
+          err = i_ReceiveResume(BuffRawIn + offset, BuffSizeIn, &PPacketOut->info._resume, &offset);
           break;
         }
         case bscchallenge : {
-          err = i_ReceiveChallenge(BuffRawIn, BuffSizeIn, &PPacketOut->info._challenge, &offset);
+          err = i_ReceiveChallenge(BuffRawIn + offset, BuffSizeIn, &PPacketOut->info._challenge, &offset);
           break;
         }
         case bscgoterror : {
-          err = i_ReceiveGotError(BuffRawIn, BuffSizeIn, &PPacketOut->info._goterror, &offset);
+          err = i_ReceiveGotError(BuffRawIn + offset, BuffSizeIn, &PPacketOut->info._goterror, &offset);
           break;
         }
         case bsclist_response : {
-          err = i_ReceiveListResponse(BuffRawIn, BuffSizeIn, &PPacketOut->info._listresponse, &offset);
+          err = i_ReceiveListResponse(BuffRawIn + offset, BuffSizeIn, &PPacketOut->info._listresponse, &offset);
           break;
         }
         case bscwhois_info : {
-          err = i_ReceiveWhoisInfo(BuffRawIn, BuffSizeIn, &PPacketOut->info._whoisinfo, &offset);
+          err = i_ReceiveWhoisInfo(BuffRawIn + offset, BuffSizeIn, &PPacketOut->info._whoisinfo, &offset);
           break;
         }
         case bscversioned : {
-          err = i_ReceiveVersioned(BuffRawIn, BuffSizeIn, &PPacketOut->info._versioned, &offset);
+          err = i_ReceiveVersioned(BuffRawIn + offset, BuffSizeIn, &PPacketOut->info._versioned, &offset);
           break;
         }
         case bscsuper : {
-          err = i_ReceiveSuper(BuffRawIn, BuffSizeIn, &PPacketOut->info._super, &offset);
+          err = i_ReceiveSuper(BuffRawIn + offset, BuffSizeIn, &PPacketOut->info._super, &offset);
           break;
         }
         case bsckilled : {
-          err = i_ReceiveKilled(BuffRawIn, BuffSizeIn, &PPacketOut->info._killed, &offset);
+          err = i_ReceiveKilled(BuffRawIn + offset, BuffSizeIn, &PPacketOut->info._killed, &offset);
           break;
         }
         case bscchum_signon : {
-          err = i_ReceiveChumSignon(BuffRawIn, BuffSizeIn, &PPacketOut->info._chumsignon, &offset);
+          err = i_ReceiveChumSignon(BuffRawIn + offset, BuffSizeIn, &PPacketOut->info._chumsignon, &offset);
           break;
         }
         case bscchum_signoff : {
-          err = i_ReceiveChumSignoff(BuffRawIn, BuffSizeIn, &PPacketOut->info._chumsignoff, &offset);
+          err = i_ReceiveChumSignoff(BuffRawIn + offset, BuffSizeIn, &PPacketOut->info._chumsignoff, &offset);
           break;
         }
         case bscchum_idle : {
-          err = i_ReceiveChumIdle(BuffRawIn, BuffSizeIn, &PPacketOut->info._chumidle, &offset);
+          err = i_ReceiveChumIdle(BuffRawIn + offset, BuffSizeIn, &PPacketOut->info._chumidle, &offset);
           break;
         }
         default : {
     else { /* Must be a client code then */
       switch ( PPacketOut->code.clientCode ) {
         case bcclogin : {
-          err = i_ReceiveLogin(BuffRawIn, BuffSizeIn, &PPacketOut->info._login, &offset);
+          err = i_ReceiveLogin(BuffRawIn + offset, BuffSizeIn, &PPacketOut->info._login, &offset);
           break;
         }
         case bccsuper_request : {
-          err = i_ReceiveSuperRequest(BuffRawIn, BuffSizeIn, &PPacketOut->info._superrequest, &offset);
+          err = i_ReceiveSuperRequest(BuffRawIn + offset, BuffSizeIn, &PPacketOut->info._superrequest, &offset);
           break;
         }
         case bccadd_wanker : {
-          err = i_ReceiveAddWanker(BuffRawIn, BuffSizeIn, &PPacketOut->info._addwanker, &offset);
+          err = i_ReceiveAddWanker(BuffRawIn + offset, BuffSizeIn, &PPacketOut->info._addwanker, &offset);
           break;
         }
         case bccnot_wanker : {
-          err = i_ReceiveNotWanker(BuffRawIn, BuffSizeIn, &PPacketOut->info._notwanker, &offset);
+          err = i_ReceiveNotWanker(BuffRawIn + offset, BuffSizeIn, &PPacketOut->info._notwanker, &offset);
           break;
         }
         case bccjoin_chat : {
-          err = i_ReceiveJoinChat(BuffRawIn, BuffSizeIn, &PPacketOut->info._joinchat, &offset);
+          err = i_ReceiveJoinChat(BuffRawIn + offset, BuffSizeIn, &PPacketOut->info._joinchat, &offset);
           break;
         }
         case bcclist : {
-          err = i_ReceiveList(BuffRawIn, BuffSizeIn, &PPacketOut->info._list, &offset);
+          err = i_ReceiveList(BuffRawIn + offset, BuffSizeIn, &PPacketOut->info._list, &offset);
           break;
         }
         case bcckilluser : {
-          err = i_ReceiveKillUser(BuffRawIn, BuffSizeIn, &PPacketOut->info._killuser, &offset);
+          err = i_ReceiveKillUser(BuffRawIn + offset, BuffSizeIn, &PPacketOut->info._killuser, &offset);
           break;
         }
         case bcckillchat : {
-          err = i_ReceiveKillChat(BuffRawIn, BuffSizeIn, &PPacketOut->info._killchat, &offset);
+          err = i_ReceiveKillChat(BuffRawIn + offset, BuffSizeIn, &PPacketOut->info._killchat, &offset);
           break;
         }
         case bcckick : {
-          err = i_ReceiveKick(BuffRawIn, BuffSizeIn, &PPacketOut->info._kick, &offset);
+          err = i_ReceiveKick(BuffRawIn + offset, BuffSizeIn, &PPacketOut->info._kick, &offset);
           break;
         }
         case bccreserved0 : {
-          err = i_ReceiveReserved0(BuffRawIn, BuffSizeIn, &PPacketOut->info._reserved0, &offset);
+          err = i_ReceiveReserved0(BuffRawIn + offset, BuffSizeIn, &PPacketOut->info._reserved0, &offset);
           break;
         }
         case bccnonsense0 : {
-          err = i_ReceiveNonsense0(BuffRawIn, BuffSizeIn, &PPacketOut->info._nonsense0, &offset);
+          err = i_ReceiveNonsense0(BuffRawIn + offset, BuffSizeIn, &PPacketOut->info._nonsense0, &offset);
           break;
         }
         case bccversion : {
-          err = i_ReceiveVersion(BuffRawIn, BuffSizeIn, &PPacketOut->info._version, &offset);
+          err = i_ReceiveVersion(BuffRawIn + offset, BuffSizeIn, &PPacketOut->info._version, &offset);
           break;
         }
         case bccmessage : {
-          err = i_ReceiveMessage(BuffRawIn, BuffSizeIn, &PPacketOut->info._message, &offset);
+          err = i_ReceiveMessage(BuffRawIn + offset, BuffSizeIn, &PPacketOut->info._message, &offset);
           break;
         }
         case bccchatmsg : {
-          err = i_ReceiveChatMsg(BuffRawIn, BuffSizeIn, &PPacketOut->info._chatmsg, &offset);
+          err = i_ReceiveChatMsg(BuffRawIn + offset, BuffSizeIn, &PPacketOut->info._chatmsg, &offset);
           break;
         }
         case bccwhois : {
-          err = i_ReceiveWhois(BuffRawIn, BuffSizeIn, &PPacketOut->info._whois, &offset);
+          err = i_ReceiveWhois(BuffRawIn + offset, BuffSizeIn, &PPacketOut->info._whois, &offset);
           break;
         }
         case bccundocumented0 : {
-          err = i_ReceiveUndocumented0(BuffRawIn, BuffSizeIn, &PPacketOut->info._undocumented0, &offset);
+          err = i_ReceiveUndocumented0(BuffRawIn + offset, BuffSizeIn, &PPacketOut->info._undocumented0, &offset);
           break;
         }
         case bccremoteshutdown : {
-          err = i_ReceiveRemoteShutdown(BuffRawIn, BuffSizeIn, &PPacketOut->info._remoteshutdown, &offset);
+          err = i_ReceiveRemoteShutdown(BuffRawIn + offset, BuffSizeIn, &PPacketOut->info._remoteshutdown, &offset);
           break;
         }
         case bccchum_add : {
-          err = i_ReceiveChumAdd(BuffRawIn, BuffSizeIn, &PPacketOut->info._chumadd, &offset);
+          err = i_ReceiveChumAdd(BuffRawIn + offset, BuffSizeIn, &PPacketOut->info._chumadd, &offset);
           break;
         }
         case bccchum_remove : {
-          err = i_ReceiveChumRemove(BuffRawIn, BuffSizeIn, &PPacketOut->info._chumremove, &offset);
+          err = i_ReceiveChumRemove(BuffRawIn + offset, BuffSizeIn, &PPacketOut->info._chumremove, &offset);
           break;
         }
         case bccidle : {
-          err = i_ReceiveIdle(BuffRawIn, BuffSizeIn, &PPacketOut->info._idle, &offset);
+          err = i_ReceiveIdle(BuffRawIn + offset, BuffSizeIn, &PPacketOut->info._idle, &offset);
           break;
         }
         default : {
 
     /* Allocate the extended packet on behalf of the caller */
     RECEIVE_FROM_BUFFER(PPacketOut->extendedPacketLength)
-    if ( !ret ) return ret;
+    if ( !ret ) goto ret;
 
     if ( PPacketOut->extendedPacketLength ) {
       PPacketOut->extendedPacketLength = (blake_word16_t)network_NetToHostShort((unsigned short int)PPacketOut->extendedPacketLength);
         if ( exPacketPointer )
           free(exPacketPointer);
         err = blakeBufferTooSmall;
-        return NULL;
       }
       memcpy(exPacket, BuffRawIn + offset, PPacketOut->extendedPacketLength);
       /*offset += sizeof((element));  <- Redundant */
   else
     err = blakeInvalidParam;
 
+ret:
   if ( PErrorOut ) /* Caller allowed for an error return */
     *PErrorOut = err;
 
   if ( !ret ) return err;
   ChallengeOut->reserved = network_NetToHostShort(ChallengeOut->reserved);
 
+  assert(PCurrOffset);
+  *PCurrOffset = (*PCurrOffset) + offset;
   return err;
 }
 /*-------------------------------------------------------------------------*/
   if ( !ret ) return err;
   RECEIVE_FROM_BUFFER(LoginOut->language);
   
+  assert(PCurrOffset);
+  *PCurrOffset = (*PCurrOffset) + offset; 
   return err;
 }
 /*-------------------------------------------------------------------------*/
   queueptr = &_buffers.incoming.queue;
 
   while ( queueptr->Count(queueptr) ) {
-    int socket;
+    int Socket;
     struct blakePacket packet;
-    void* exPacket;
+    void* exPacket = NULL;
     size_t exPacketSize;
-    exPacketSize = queueptr->Top(queueptr, &socket, &packet, NULL); /* First call just to get the size of the expacket */
-    exPacket = dpcrtlmm_Alloc(_blockarray, exPacketSize);
+    exPacketSize = queueptr->Top(queueptr, &Socket, &packet, NULL); /* First call just to get the size of the expacket */
+    if ( exPacketSize ) {
+      exPacket = dpcrtlmm_Alloc(_blockarray, exPacketSize);
 
-    if ( exPacket )
-      queueptr->Top(queueptr, &socket, &packet, exPacket);
-    else {
-      packet.extendedPacketLength = 0; /* Pretend it never existed */
-      i_LogMsg("Warning, extended packet was discarded due to lack of memory");
+      if ( exPacket )
+        queueptr->Top(queueptr, &Socket, &packet, exPacket);
+      else {
+        packet.extendedPacketLength = 0; /* Pretend it never existed */
+       i_LogMsg("Warning, extended packet was discarded due to lack of memory");
+      }
     }
 
     /* Execute user-callbacks for the packet */
     blake_cb_AquireLock(0); /* FIXME */
     if ( blake_cb_IsInstalled(packet.server, (WORD)((packet.server) ? (packet.code.serverCode) : (packet.code.clientCode)), 0) ) { /* FIXME */
       blake_Trace("Calling user callback");
-      if ( blake_cb_Call(&packet, 0) ) /* FIXME */
+      if ( blake_cb_Call(Socket, &packet, 0) ) /* FIXME */
         blake_Trace("User callback reports success");
       else
         blake_Trace("User callback reports failure");
       
     queueptr->Pop(queueptr); /* Whoops, I forgot to do this ;) (21/12/2001) - DDRP */
     blake_cb_ReleaseLock(0); /* FIXME */
+    
+    if ( exPacket )
+      dpcrtlmm_Free(_blockarray, exPacket);
   }
 
   blake_UnlockMutant(_buffers.incoming.lock);
   enum blakeError err;
   BYTE* exPacket = NULL;
 
-  puts("In blake_CrackPacket()");
+  printf("(DEBUG)In blake_CrackPacket(Socket=%d, PacketBuffer=%p, BufferLength=%u\n)", Socket, PacketBuffer, BufferLength);
   if ( !PacketBuffer || !BufferLength ) return blakeInvalidParam; /* Protection */
   i_InitPacket(&packet);
   /* Now let's officially receive from the buffer */
           break;
         }
         case bscchallenge : {
-          /*sz += (blake_word16_t)sizeof(PPacket->info._challenge);*/
-          sz += (32+16) / 8;
+          sz += sizeof(PPacket->info._challenge.secs);
+          sz += sizeof(PPacket->info._challenge.reserved);
           break;
         }
         case bscgoterror : {
     else { /* Client code */
       switch ( PPacket->code.clientCode ) {
         case bcclogin : {
-          sz += (blake_word16_t)sizeof(PPacket->info._login);
+          sz += sizeof(PPacket->info._login.username);
+          sz += sizeof(PPacket->info._login.password);
+          sz += sizeof(PPacket->info._login.language);
           break;
         }
         case bccsuper_request : {

File blake/blakedb.c

     return index;
   if ( !blake_NickTest(NickName, NULL, NULL) ) return index;
 
-  if ( !ReadHandleData(DBHandle, &node) )
+  if ( !ReadHandleData(DBHandle, &node) ) /* Test object handle */
     return index; /* Bad object */
 
   for (;;) {

File buildtimer/Makefile

 
 patchedbuildtimer.c : buildtimer.c buildtimer.diff
 	@echo "==> Applying patch for buildtimer <=="
-	@cp buildtimer.c patchedbuildtimer.c
-	@patch patchedbuildtimer.c buildtimer.diff 2> /dev/null
+	cp buildtimer.c patchedbuildtimer.c
+	patch patchedbuildtimer.c buildtimer.diff
 
 clean:
 	@echo "==> Cleaning buildtimer <=="

File buildtimer/Makefile.gnu

 
 patchedbuildtimer.c : buildtimer.c buildtimer.diff
 	@echo "==> Applying patch for buildtimer <=="
-	@cp buildtimer.c patchedbuildtimer.c
-	@patch patchedbuildtimer.c buildtimer.diff 2> /dev/null
+	cp buildtimer.c patchedbuildtimer.c
+	patch patchedbuildtimer.c buildtimer.diff
 
 clean:
 	@echo "==> Cleaning buildtimer <=="

File clients/oclogin/ChangeLog

+0.0.4
+-----
+DDRP: Fix: Lies to blake_CrackPacket() about complete packet length!
+
+0.0.3
+-----
+DDRP: Fix: Forgot to free dynamic server name
+DDRP: Now we'll use a non-blocking socket

File clients/oclogin/oclogin.c

 */
 
 #include "overchat_config.h" /* Entire project configuration */
+#include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <limits.h>
 static int _localSocket = -1;
 static const char* UserName;
 static const char* Password;
+static char* DynServerName;
 
 static void InstallSignals(void);
 static void SigHandler(int SigNo);
 static void Begin(void);
 static void Error(const char* Msg);
 static const char* ServerName(const char* NewName);
+static void FreeServerName(void);
 static void BlakeError(enum blakeError ErrorNumber);
 static void OK(void);
 static void BrokenPipeCallback(int Socket);
 static void DataReader(int S);
 static void DataWriter(int Socket, const void* RawData, size_t RawDataSize);
-static bool GotChallenge(const void* Unknown);
+static bool GotChallenge(int Sock, const void* Unknown);
 
 #define GetServerName() \
           ServerName(NULL)
 #define SetServerName(newname) \
           ServerName((newname))
 
-int mymain(int argc, char* argv[]);
+/*int mymain(int argc, char* argv[]);*/
 /*-------------------------------------------------------------------------*/
+#if 0
 int main()
 {
+  /*
+    This is for debugging because I don't know how to set arguments in the
+    debugger
+  */
+  
   char* strings[] = {
     "oclogin",
     "DDRP",
     "blah",
-    "localhost"
+    SERVERNAME
   };
 
   return mymain(4, strings);
 }
+#endif
 /*-------------------------------------------------------------------------*/
-int mymain(int argc, char* argv[])
+int main(int argc, char* argv[])
 {
   InstallSignals();
   Title();
   }
 
   Begin();
+  FreeServerName();
   return EXIT_SUCCESS;
 }
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 static void Title()
 {
-  printf("Overchat - oclogin console login 0.0.2 (built from tree %u)\n"
+  printf("Overchat - oclogin console login 0.0.3 (built from tree %u)\n"
          "(C)2001 Daybo Logic, all rights reserved. - Overlord@DayboLogic.co.uk\n\n", OVERCHAT_VERBUILD
   );
 }
     goto cleanup;
   }
 
-  /*network_MakeNonBlocking(_localSocket);*/
+  network_MakeNonBlocking(_localSocket);
   blake_InstallCallback(0, true, (WORD)bscchallenge, GotChallenge);
   if ( !EventLoop() )
     Error("Couldn\'t initialise the event loop");
 /*-------------------------------------------------------------------------*/
 static const char* ServerName(const char* NewName)
 {
-  static char* dynServerName;
   static const char defServerName[] = "overchat"; /* DNS */
 
   if ( NewName ) { /* Setting a new name? */
-    if ( dynServerName )
-      free(dynServerName);
-    dynServerName = (char*)malloc( strlen(NewName) + 1 );
-    if ( dynServerName )
-      strcpy(dynServerName, NewName);
+    FreeServerName();
+    DynServerName = (char*)malloc( strlen(NewName) + 1 );
+    if ( DynServerName )
+      strcpy(DynServerName, NewName);
   }
 
-  if ( !dynServerName ) /* No user specified name */
+  if ( !DynServerName ) /* No user specified name */
     return defServerName; /* Give default */
 
-  return dynServerName;
+  return DynServerName;
+}
+/*-------------------------------------------------------------------------*/
+static void FreeServerName()
+{
+  if ( DynServerName )
+    free(DynServerName);
 }
 /*-------------------------------------------------------------------------*/
 static void BlakeError(enum blakeError ErrorNumber)
       }
       else { /* Looks like the whole packet has been read */
         /* Pass to the Blake cracker */
-        enum blakeError err = blake_CrackPacket(S, buff, expectSz);
+        enum blakeError err = blake_CrackPacket(S, buff, expectSz+2);
         /* Reset variables for next packet */
         marker = 0;
         expectSz = 0;
   network_Write(Socket, RawData, RawDataSize);
 }
 /*-------------------------------------------------------------------------*/
-static bool GotChallenge(const void* Unknown)
+static bool GotChallenge(int Sock, const void* Unknown)
 {
+  assert(Sock == _localSocket);
+  
   /* Try to login */
   if ( blake_Login(_localSocket, UserName, Password, 0) ) {
     blake_Trace("Sent login information");

File clients/oclogin/oclogin.h

 #define __INC_OCLOGIN_H
 #include "cheader.h"
 /*-------------------------------------------------------------------------*/
-#define SERVERNAME "overchat"
+#define SERVERNAME "localhost"
 #define SERVERPORT (3277)
 #define EVENTQUEUESIZE (1024)
 

File dlini/Makefile

+#  $dlini/Makefile.gnu
+#  October 2001
+#
+#  Daybo Logic INI Support library for non-Windows systems.
+#  (C) Copyright 2001 Daybo Logic.
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 2 of the License, or
+#  (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#  Daybo Logic,
+#  13 Forest Close,
+#  Newport, Isle of Wight,
+#  England.
+#  UK
+#  PO30 5SF
+#
+#  +44 1983 520085
+#  David Duncan Ross Palmer <Overlord@DayboLogic.co.uk>
+#  http://www.daybologic.co.uk/dev/dlini
+#
+#
+# Makefile for GNU Make.
+
+CC=gcc -c -g -pedantic -Wall -D__UNIX__
+LINK=gcc -g -pedantic -Wall -D__UNIX__
+ANSI=-ansi
+RM=rm -rf
+LIB=libdlini.a
+
+OBJECTS=dlini_getint.o \
+        dlini_getsection.o \
+        dlini_getsectionnames.o \
+        dlini_getstring.o \
+        dlini_getstruct.o \
+        dlini_internal.o \
+        dlini_writesection.o \
+        dlini_writestring.o \
+        dlini_writestruct.o
+
+#-------------------------------------------------------------------
+all : dlini sample runsample
+
+dlini : $(LIB)
+
+$(LIB) : $(OBJECTS)
+	ar cru $(LIB) $(OBJECTS)
+	ranlib $(LIB)
+
+# General C building rule
+.c.obj : dlini.h
+	$(CC) $(ANSI) $<
+
+# Exceptions to the rule which need a different build
+dlini_internal.o : dlini_internal.c dlini.h
+	$(CC) -odlini_internal.o dlini_internal.c
+
+# Building of the sample program
+sample : sample.c $(LIB) dlini.h
+	$(LINK) $(ANSI) -osample sample.c $(LIB)
+
+runsample:
+	./sample
+#-------------------------------------------------------------------
+clean:
+	-$(RM) $(OBJECTS)
+	-$(RM) $(LIB)
+	-$(RM) *.bak
+	-$(RM) *~
+	-$(RM) sample

File dlini/Makefile.gnu

 # Makefile for GNU Make.
 
 CC=gcc -c -g -pedantic -Wall -D__UNIX__
+LINK=gcc -g -pedantic -Wall -D__UNIX__
 ANSI=-ansi
 RM=rm -rf
 LIB=libdlini.a
         dlini_writestruct.o
 
 #-------------------------------------------------------------------
-all : dlini
+all : dlini sample runsample
 
 dlini : $(LIB)
 
 # Exceptions to the rule which need a different build
 dlini_internal.o : dlini_internal.c dlini.h
 	$(CC) -odlini_internal.o dlini_internal.c
+
+# Building of the sample program
+sample : sample.c $(LIB) dlini.h
+	$(LINK) $(ANSI) -osample sample.c $(LIB)
+
+runsample:
+	./sample
 #-------------------------------------------------------------------
 clean:
 	-$(RM) $(OBJECTS)
 	-$(RM) $(LIB)
 	-$(RM) *.bak
 	-$(RM) *~
+	-$(RM) sample

File dlini/dlini.h

 
 /* Private boolean type */
 enum dlini_bool_t {
-  dliniTrue,
-  dliniFalse
+  dliniFalse = 0,
+  dliniTrue = 1
 };
 
 #ifdef DLINI_SOURCE
+  #define DLINI_LINEBUFFER (3001)
+
   /* List internal support function here, prefix with dlini_int_ */
+  enum dlini_bool_t dlini_int_FindSection(FILE* FHandle, const char* SectionString);
   void dlini_int_GoToLine(FILE* FHandle, unsigned int LineNumber);
   unsigned int dlini_int_GetKeyNames(FILE* FHandle, const char* SectionName, char* OutputBuffer, unsigned int BuffMaxChars);
   char* dlini_int_CreateResolvedSectionName(const char* SectionName);
   FILE* dlini_int_Open(const char* Filename, enum dlini_bool_t Write);
   void dlini_int_Close(FILE* FHandle);
   const char* dlini_int_ResolveFileName(const char* FileName);
+  char* dlini_int_ChopComment(char* LineString);
+  char* dlini_int_ChopCrap(char* LineString);
+  enum dlini_bool_t dlini_int_FindKey(FILE* FHandle, const char* KeyName);
+  unsigned int dlini_int_ReadValue(FILE* FHandle, char* lpReturnedString, unsigned int nSize);
+  unsigned int dlini_int_StringToPositiveInteger(const char* NumberAsString);
+  
+  /*
+    The following three functions are from DDRP's ANSI replacement set
+    but I do not like interlibrary dependencies and they can become very
+    messy quickly.  So they have been copied across with different names.
+  */
+  int dlini_int_stricmp(const char* s1, const char* s2);
+  char* dlini_int_strlwr(char* s);
+  char* dlini_int_strupr(char* s);
 #endif /*DLINI_SOURCE*/
 
 unsigned int dlini_GetPrivateProfileInt(

File dlini/dlini_getint.c

 unsigned int dlini_GetPrivateProfileInt(
     const char* lpAppName,	/* address of section name */
     const char* lpKeyName,	/* address of key name */
-    int nDefault,	         /* return value if key name is not found */
-    const char* lpFileName /* address of initialization filename */
+    int nDefault,	        /* return value if key name is not found */
+    const char* lpFileName      /* address of initialization filename */
 )
 {
+  FILE* fileHandle;
+  unsigned int ret = (unsigned int)nDefault;
+  char* resolvedSectionName;
+  char lpReturnedString[DLINI_LINEBUFFER];
+  unsigned int nSize = (sizeof(lpReturnedString)/sizeof(lpReturnedString[0])) - 1;
+  
+  if ( !lpAppName || !lpKeyName ) /* Whoever the caller is, is in the wrong! */
+    return ret;
+    
+  fileHandle = dlini_int_Open(dlini_int_ResolveFileName(lpFileName), dliniFalse);
+  if ( !fileHandle ) return ret;
+  
+  resolvedSectionName = dlini_int_CreateResolvedSectionName(lpAppName);
+  if ( resolvedSectionName ) {
+    if ( dlini_int_FindSection(fileHandle, resolvedSectionName) ) {
+      if ( dlini_int_FindKey(fileHandle, lpKeyName) ) {
+        if ( dlini_int_ReadValue(fileHandle, lpReturnedString, nSize) )
+          ret = dlini_int_StringToPositiveInteger(lpReturnedString);
+      }
+    }
+    dlini_int_DestroyResolvedSectionName(resolvedSectionName);
+  }
+
+endsub:
+  if ( fileHandle )
+    dlini_int_Close(fileHandle);
+  return ret;
 }
 /*-------------------------------------------------------------------------*/

File dlini/dlini_getstring.c

 )
 {
   FILE* fileHandle;
-  unsigned int ret; /* Return value */
+  unsigned int ret = 0U; /* Return value */
+  char* resolvedSectionName;
 
   if ( !lpAppName ) /* Caller wants all section names */
     return dlini_GetPrivateProfileSectionNames(lpReturnedString, nSize, lpFileName);
     ret = dlini_int_GetKeyNames(fileHandle, lpAppName, lpReturnedString, nSize);
     goto endsub;
   }
+  
+  resolvedSectionName = dlini_int_CreateResolvedSectionName(lpAppName);
+  if ( resolvedSectionName ) {
+    if ( dlini_int_FindSection(fileHandle, resolvedSectionName) ) {
+      if ( dlini_int_FindKey(fileHandle, lpKeyName) ) {
+        ret = dlini_int_ReadValue(fileHandle, lpReturnedString, nSize );
+      }
+    }
+    dlini_int_DestroyResolvedSectionName(resolvedSectionName);
+  }
 
 endsub:
   if ( fileHandle )

File dlini/dlini_internal.c

 /*
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % This module provides support to other INI functions only. %
-   % The function in here should not be used by users.         %
+   % The functions in here should not be used by users.        %
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 */
 
 #include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stddef.h>
 #include "dlini.h"
 /*-------------------------------------------------------------------------*/
+static enum dlini_bool_t SeekToKeysValue(FILE* FHandle);
+/*-------------------------------------------------------------------------*/
+enum dlini_bool_t dlini_int_FindSection(FILE* FHandle, const char* SectionString)
+{
+  char lineBuff[DLINI_LINEBUFFER];
+  char* s;
+  
+  rewind(FHandle);
+  do {
+    s = fgets(lineBuff, sizeof(lineBuff)/sizeof(lineBuff[0]), FHandle);
+    if ( s ) {
+      dlini_int_ChopCrap(dlini_int_ChopComment(s));
+      if ( dlini_int_stricmp(s, SectionString) == 0 ) /* Found a match */
+        return dliniTrue;
+    }
+  } while ( s );
+  rewind(FHandle);
+  return dliniFalse;
+}
+/*-------------------------------------------------------------------------*/
 void dlini_int_GoToLine(FILE* FHandle, unsigned int LineNumber)
 {
   rewind(FHandle);
   if ( ptr ) {
     ptr[0] = '[';
     strcpy(ptr+1, SectionName);
-    ptr[sz-1] = ']';
+    strcat(ptr, "]");
   }
 
   return ptr;
 # endif /*__UNIX__*/
 
   if ( fd != -1 ) { /* If no error */
-    fsp = fdopen(fd, ( (Write==dliniTrue) ? ("r+b") : ("rb") ));
+    fsp = fdopen(fd, ( (Write==dliniTrue) ? ("r+t") : ("rt") ));
     if ( !fsp )
       close(fd);
   }
   return defFileName;
 }
 /*-------------------------------------------------------------------------*/
+char* dlini_int_ChopComment(char* LineString)
+{
+  char* comment = strchr(LineString, ';');
+  if ( comment )
+    comment[0] = '\0'; /* Terminate at beginning of comment */
+    
+  return LineString;
+}
 /*-------------------------------------------------------------------------*/
+char* dlini_int_ChopCrap(char* LineString)
+{
+  size_t pos = strlen(LineString);
+  if ( pos-- ) {
+    do {
+      if ( LineString[pos] == '\n' || LineString[pos] == ' ' || LineString[pos] == '\r' ) /* Crap! */
+        LineString[pos] = '\0';
+    } while ( pos-- );
+  }
+  return LineString;
+}
 /*-------------------------------------------------------------------------*/
+enum dlini_bool_t dlini_int_FindKey(FILE* FHandle, const char* KeyName)
+{
+  char lineBuff[DLINI_LINEBUFFER];
+  char* s;
+  
+  do {
+    char* keyoff; /* Offset of key into string (must be zero) */
+    s = fgets(lineBuff, sizeof(lineBuff)/sizeof(lineBuff[0]), FHandle);
+    if ( !s ) break; /* EOF */
+    keyoff = strstr(s, KeyName);
+    if ( keyoff ) {
+      if ( keyoff == lineBuff ) /* Key at beginning of line, perfect */
+        return SeekToKeysValue(FHandle);
+    }
+  } while ( s );
+  
+  return dliniFalse;
+}
 /*-------------------------------------------------------------------------*/
+unsigned int dlini_int_ReadValue(FILE* FHandle, char* lpReturnedString, unsigned int nSize)
+{
+  memset(lpReturnedString, 0, nSize+1);
+  fgets(lpReturnedString, nSize, FHandle);
+  dlini_int_ChopCrap(dlini_int_ChopComment(lpReturnedString));
+  return strlen(lpReturnedString);
+}
 /*-------------------------------------------------------------------------*/
+int dlini_int_stricmp(const char* s1, const char* s2)
+{
+  char* copyS1;
+  char* copyS2; /* Copies of both */
+  int ret; /* Return value */
+  
+  copyS1 = (char*)malloc( strlen(s1) + 1 );
+  strcpy(copyS1, s1); /* Make copy of comparison one */
+  copyS2 = (char*)malloc( strlen(s2) + 1 );
+  strcpy(copyS2, s2); /* Make copy of comparison two */
+  
+  dlini_int_strupr(copyS1);
+  dlini_int_strupr(copyS2); /* Convert both to uppercase which provides a way to ignore the case */
+  
+  ret = strcmp(copyS1, copyS2); /* Do comparison and save result */
+  
+  /* Cleanup and return */
+  free(copyS1); free(copyS2);
+  return ret;
+}
 /*-------------------------------------------------------------------------*/
+char* dlini_int_strlwr(char* s)
+{
+  unsigned int index = 0U;
+  
+  if ( !s ) return s; /* Get out before damage is done */
+  while ( s[index] != '\0' ) {
+    s[index] = (char)tolower( (int)(s[index]) );
+    index++;
+  };
+  return s;
+}
+/*-------------------------------------------------------------------------*/
+char* dlini_int_strupr(char* s)
+{
+  unsigned int index = 0U;
+  
+  if ( !s ) return s; /* Get out before damage is done */
+  while ( s[index] != '\0' ) {
+    s[index] = (char)toupper( (int)(s[index]) );
+    index++;
+  };
+  return s;
+}
+/*-------------------------------------------------------------------------*/
+static enum dlini_bool_t SeekToKeysValue(FILE* FHandle)
+{
+  unsigned int i = 2;
+  int c;
+  
+  while ( i ) {
+    long int oldPos = ftell(FHandle);
+    
+    fseek(FHandle, -1, SEEK_CUR); /* Go back one byte */
+    
+    if ( ftell(FHandle) != (oldPos - 1) )
+      return dliniFalse;
+      
+    c = getc(FHandle);
+    if ( c == '\n' )
+      i--;
+      
+    ungetc(c, FHandle);
+  }
+  /* We are now at the start of the line we want.  Seek forward until we
+  discover the '=', when we do, we're in front of it ready for whoever
+  wants to read or write the value */
+  
+  do {
+    c = fgetc(FHandle);
+    if ( c == '=' ) break;
+    if ( c == EOF ) return dliniFalse;
+  } while ( c != EOF ); /* Condiction is of no consequence */
+  
+  return dliniTrue;
+}
+/*-------------------------------------------------------------------------*/
+unsigned int dlini_int_StringToPositiveInteger(const char* StringAsNumber)
+{
+  int number = atoi(StringAsNumber);
+  if ( number < 0 ) number = 0; /* Microsoft rules, negatives are illegal */
+  return number;
+}
+/*-------------------------------------------------------------------------*/

File dlini/sample.c

+/*
+  $dlini/sample.c
+  December 2001
+
+  Daybo Logic INI Support library for non-Windows systems.
+  Library sample/test program.
+  (C) Copyright 2001 Daybo Logic.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+  Daybo Logic,
+  13 Forest Close,
+  Newport, Isle of Wight,
+  England.
+  UK
+  PO30 5SF
+
+  +44 1983 520085
+  David Duncan Ross Palmer <Overlord@DayboLogic.co.uk>
+  http://www.daybologic.co.uk/dev/dlini
+*/
+
+/*
+   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+   % This program is meant for debugging and developing dlini  %
+   % It has no useful purpose and is not built in with the lib %
+   % file.                                                     %
+   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "dlini.h"
+/*-------------------------------------------------------------------------*/
+#define TEST1(name) \
+          static enum dlini_bool_t name##(void)
+#define TEST2(name) \
+          static enum dlini_bool_t name##()
+#define INIFILE "sample.ini"
+
+TEST1(ReadHouses);
+TEST1(WriteHouses);
+TEST1(ReadFishInTheSea);
+TEST1(WriteFishInTheSea);
+TEST1(NoSpaceSection);
+
+static void Title(void);
+/*-------------------------------------------------------------------------*/
+int main()
+{
+  unsigned int i;
+
+  enum dlini_bool_t (*Tests[])(void) = {
+    ReadHouses,
+    WriteHouses,
+    ReadFishInTheSea,
+    WriteFishInTheSea,
+    NoSpaceSection
+  };
+    
+  Title();
+  for ( i = 0U; i < sizeof(Tests)/sizeof(Tests[0]); i++ ) {
+    if ( Tests[i] ) {
+      if ( Tests[i]() ) {
+        printf("Test %u succeeded\n", i);
+      }
+      else {
+        printf("Test %u failed.  Contact DLini\'s maintainer\n", i);
+        return EXIT_FAILURE; /* Break the build process */
+      }
+    }
+    else
+      puts("Warning Missing handler in tests loop");
+  }
+  return EXIT_SUCCESS;
+}
+/*-------------------------------------------------------------------------*/
+TEST2(ReadHouses)
+{
+  const char houses[] = "houses";
+  const char eight[] = "eight";
+  char buff[256];
+  unsigned int n; /* Number of characters read */
+
+  n = GetPrivateProfileString("last_section", houses, "none", buff, (sizeof(buff)/sizeof(buff[0]))-1, INIFILE);
+  if ( n == strlen(eight) ) {
+    if ( strcmp(buff, eight) == 0 )
+      return dliniTrue;
+  }
+
+  return dliniFalse;
+}
+/*-------------------------------------------------------------------------*/
+TEST2(WriteHouses)
+{
+  return dliniTrue;
+}
+/*-------------------------------------------------------------------------*/
+TEST2(ReadFishInTheSea)
+{
+  const char key[] = "fish_in_the_sea";
+  const char section[] = "section_two";
+  const unsigned int expected = 55809;
+  unsigned int real;
+  
+  real = GetPrivateProfileInt(section, key, 0, INIFILE);
+  
+  if ( !real ) {
+    puts("GetPrivateProfileInt() returned zero!");
+    return dliniFalse;
+  }
+  if ( real != expected ) {
+    puts("GetPrivateProfileInt() returned an unexpected nonzero");
+    return dliniFalse;
+  }
+  
+  return dliniTrue; /* Yeah! */
+}
+/*-------------------------------------------------------------------------*/
+TEST2(WriteFishInTheSea)
+{
+  return dliniTrue;
+}
+/*-------------------------------------------------------------------------*/
+TEST2(NoSpaceSection)
+{
+  const char section[] = "no_space_section";
+  const char key[] = "value";
+  const char valueDefault[] = "nonsense";
+  const char expected[] = "overlord";
+  char buff[256];
+  size_t nSize = ( sizeof(buff)/sizeof(buff[0]) ) - 1;
+  unsigned int n;
+  
+  n = GetPrivateProfileString(section, key, valueDefault, buff, nSize, INIFILE);
+  if ( n == strlen(expected) ) {
+    if ( strcmp(buff, expected) == 0 )
+      return dliniTrue;
+  }
+  
+  return dliniFalse;
+}
+/*-------------------------------------------------------------------------*/
+static void Title()
+{
+  puts("libdlini is supplied under the GNU General Public Licence");
+  puts("This program will test it's functionallity");
+  puts("(C)2001-2002 Daybo Logic.  Overlord@DayboLogic.co.uk\n");
+}
+/*-------------------------------------------------------------------------*/

File dlini/sample.ini

+; The information contained in this file has no useful
+; purpose.  It is merely here to help debug and develop
+; dlini.  It represents a typical ini file.
+
+[section_one]
+hrm=yes
+maybe=no
+pammy_anderson=yes_please!
+
+[section_two]
+fish_in_the_sea=55809
+programmers=14    ; Comment after a line
+computers=5
+[no_space_section]
+value=overlord
+
+[last_section] ; Comment after a section name
+beans=5
+; Comment in a section
+houses=eight
+name=david duncan ross palmer
+name_with_correct_case=David Duncan Ross Palmer

File dpcrtlmm/stev1306

Binary file added.
+Signals installed
+DPCRTLMM started
+(TRACE)"server.c" L117 - Blake initialised
+(TRACE)"server.c" L124 - Threads manager initialised
+(TRACE)"server.c" L131 - DeadMan started
+(TRACE)"server.c" L138 - Logging/messaging started
+(TRACE)"server.c" L144 - Heart started
+(TRACE)"server.c" L155 - TX/RX buffer manager initialised
+OverChat Server V0.0.13 by David Duncan Ross Palmer <Overlord@DayboLogic.co.uk>
+(C)Copyright 2001 Daybo Logic, all rights reserved.  http://www.daybologic.co.uk
+Server build 392, built 21:14:45 on Dec 30 2001
+
+overchatd::server.c, L309 (3C2F8498): Connection error: Cannot bind the network socket
+
+The server ran for less than a second, before manual shutdown.
+
+DPCRTLMM: "Warning! dpcrtlmm.c, L167: Shutdown(): The array 0x0x80e4050 was not freed, any blocks unfreed in the array will be listed"
+DPCRTLMM: "Warning! dpcrtlmm.c, L189: 1 arrays were not freed"

File src/Makefile

      server_signals$(O) \
      server_threads$(O) \
      server_version$(O) \
-     server_txrx$(O)
+     server_txrx$(O) \
+     server_auth$(O)
 
 LIBS=../libblake.a \
      ../dpcrtlmm/libdpcrtlmm.a \
 server_threads.o : server_threads.c server_pththreads.c server_ntthreads.c server_posixthreads.c
 	$(CC) -I/usr/local/include/pth -oserver_threads.o server_threads.c   # Ack!  Find an automated way
 
-server_event.o : server_event.c server_event.h
+server_event.o : server_event.c server_event.h server.h
 	$(CC) -oserver_event.o server_event.c
 
+server.o : server.c server.h
+	$(CC) -D__UNIX__ -oserver.o server.c
+
 # Rules to clean the local space up
 clean:
 	-rm -f $(OBJS) ../overchatd DDRPlogin DDRPlogin.o core DDRPlogin.core

File src/Makefile.gnu

      server_signals$(O) \
      server_threads$(O) \
      server_version$(O) \
-     server_txrx$(O)
+     server_txrx$(O) \
+     server_auth$(O)
 
 LIBS=../libblake.a \
      ../dpcrtlmm/libdpcrtlmm.a \
 server_threads.o : server_threads.c server_pththreads.c server_ntthreads.c server_posixthreads.c
 	$(CC) -I/usr/local/include/pth -oserver_threads.o server_threads.c   # Ack!  Find an automated way
 
-server_event.o : server_event.c server_event.h
+server_event.o : server_event.c server_event.h server.h
 	$(CC) -oserver_event.o server_event.c
 
+server.o : server.c server.h
+	$(CC) -D__UNIX__ -oserver.o server.c
+
 # Rules to clean the local space up
 clean:
 	-rm -f $(OBJS) ../overchatd DDRPlogin DDRPlogin.o core DDRPlogin.core

File src/overchatd.log

-
-overchatd (3BF15EB3): OverChat server (0.0.9 (build 132)- 17:18:02 Nov 13 2001) started
-overchatd (3BF15EC5): i_DeleteAll() called from server_globalid.c line 267
-
-overchatd (3BF2791F): OverChat server (0.0.9 (build 132)- 17:18:02 Nov 13 2001) started
-overchatd (3BF27939): i_DeleteAll() called from server_globalid.c line 267
-
-overchatd (3BF27995): OverChat server (0.0.9 (build 132)- 17:18:02 Nov 13 2001) started
-overchatd (3BF279A2): i_DeleteAll() called from server_globalid.c line 267

File src/server.c

 #include <time.h>
 #include <signal.h>
 #include <limits.h>
+#ifdef __UNIX__
+# include <unistd.h> /* For fork() */
+#endif /*__UNIX__*/
+
 #ifdef HDRSTOP
 # pragma hdrstop
 #endif /*HDRSTOP*/
 static bool GlobalConstruct(void); /* Call from server_main only, if it fails return an error to the OS */
 static void GlobalDestruct(void); /* Do not call directly, called by atexit() */
 static void Title(void);
-static void UptimePrinter(void);
+static bool Daemonize(void);
 static void SocketDescCollector(int SocketDesc);
-static void LocalBlakeErrorPrinter(enum blakeError BlakeErrorNumber); /* These are everywhere, I need to localize them */
+static void InstallBlakePacketCallbacks(void);
 
 /* Pointer table, always call these to confuse disassemblers, never call functions directly */
 static bool (*_GlobalConstruct)(void) = GlobalConstruct;
 static void (*_GlobalDestruct)(void) = GlobalDestruct;
 static void (*_Title)(void) = Title;
-static void (*_UptimePrinter)(void) = UptimePrinter;
+static bool (*_Daemonize)(void) = Daemonize;
 
 /* Data */
 static S_CORE_VTABLE* list;
   int ret = EXIT_SUCCESS;
   int sock3277;
 
+  if ( !Daemonize() ) return ret; /* We failed... or a daemon is running now */
   if ( !_GlobalConstruct() ) /* Initialise server global objects */
     return EXIT_FAILURE;
 
     if ( err == blakeSuccess ) {
       network_InstallBrokenPipeCallback(server_BrokenPipeCollector);
       network_InstallCC(sock3277, SocketDescCollector);
+      InstallBlakePacketCallbacks();
       EventLoop();
     }
     else
-      LocalBlakeErrorPrinter(err);
+      server_PrintBlakeError(err);
   }
   else {
     _server_message(true, "Can\'t aquire a master socket\n");
 exitMain:
 
   /* Cleanup */
-  _UptimePrinter();
+  /*dpcrtlmm_Dump(stdout);*/   /* Too messy for releases! ;-) */
+  core_LogUptime();  /* So we know how long things were cool for */
   _GlobalDestruct(); /* Destroy server global objects */
   return ret;
 }
   _server_message(false, msg);
 }
 /*-------------------------------------------------------------------------*/
-static void UptimePrinter()
+static bool Daemonize()
 {
-  unsigned short years = 0, days = 0, hours = 0, mins = 0, secs = 0;
-  unsigned int uptime;
+  bool ret;
   
-  printf("\nThe server ran for ");
-  uptime = core_Uptime();
-  
-  if ( uptime ) {
-    years = uptime / OVERCHAT_YEAR;
-    uptime -= OVERCHAT_YEAR * years;
-    
-    days = uptime / OVERCHAT_DAY;
-    uptime -= OVERCHAT_DAY * days;
-    
-    hours = uptime / OVERCHAT_HOUR;
-    uptime -= OVERCHAT_HOUR * hours;
-    
-    mins = uptime / OVERCHAT_MINUTE;
-    uptime -= OVERCHAT_MINUTE * mins;
-    
-    secs = uptime; /* Remainder must be secs */
-    
-    if ( years ) {
-      printf("%u year", years);
-      DO_S(years);
+  #ifdef __UNIX__
+  switch ( fork() ) {
+    case -1 : {
+      fputs("overchatd: Error, cannot create daemon!", stderr);
+      ret = false;
+      break;
     }
-    if ( days ) {
-      printf("%u day", days);
-      DO_S(days);
+    case 0 : { /* We are the daemon child (the living being!) */
+      ret = true; /* Carry on running */
+      break;
     }
-    if ( hours ) {
-      printf("%u hour", hours);
-      DO_S(hours);
-    }
-    if ( mins ) {
-      printf("%u minute", mins);
-      DO_S(mins);
-    }
-    if ( secs ) {
-      printf("%u second", secs);
-      DO_S(secs);
+    default : {
+      /* Child has been created.  Program should exit now */
+      ret = false;
     }
   }
-  else /* No time! */
-    printf("less than a second, ");
-    
-  puts("before manual shutdown.\n");
-  return;
+  #else
+  /* Not UNIX */
+  ret = true; /* Run as non-daemon */
+  #endif
+  
+  return ret;
 }
 /*-------------------------------------------------------------------------*/
 void server_BrokenPipeCollector(int SocketDesc)
   list->Broken(SocketDesc);
 }
 /*-------------------------------------------------------------------------*/
+void server_Auth(int Sock, const char* Nick)
+{
+  list->AuthenticationUpdate(Sock, Nick); /* FIXME: Can currently log in multiple times */
+}
+/*-------------------------------------------------------------------------*/
+void server_Kill(int Sock)
+{
+  list->RemoveUserBySocketDesc(Sock);
+}
+/*-------------------------------------------------------------------------*/
 static void SocketDescCollector(int SocketDesc)
 {
   if ( !list->AddUser(NULL, SocketDesc) ) {
   return;
 }
 /*-------------------------------------------------------------------------*/
-static void LocalBlakeErrorPrinter(enum blakeError BlakeErrorNumber)
+void server_PrintBlakeError(enum blakeError BlakeErrorNumber)
 {
   int len = blake_GetErrorMessage(BlakeErrorNumber, NULL, 0, 0);
   if ( len ) {
   }
 }
 /*-------------------------------------------------------------------------*/
+static void InstallBlakePacketCallbacks()
+{
+  enum blakeError err;
+  
+  err = blake_InstallCallback(0, false, (WORD)bcclogin, blakecallback_Authenticator);
+  if ( err != blakeSuccess )
+    server_PrintBlakeError(err);
+
+  /* FIXME: 0 is meant to be a thread ID, use the right function */    
+  return;
+}
+/*-------------------------------------------------------------------------*/

File src/server.h

 #include "server_event.h" /* Event loop control */
 #include "server_deadman.h" /* For control of the DeadMan debugger */
 #include "server_txrx.h" /* Network level buffers for connection */
+#include "server_auth.h" /* Authenticator */
 /*-------------------------------------------------------------------------*/
 #include "cheader.h"
 
 void server_BrokenPipeCollector(int SocketDesc);
+void server_Auth(int Sock, const char* Nick); /* Add an authenticated user */
+void server_Kill(int Sock); /* Manually kill a user! */
+void server_PrintBlakeError(enum blakeError ErrorNumber);
 
 #include "cheader.h"
 /*-------------------------------------------------------------------------*/

File src/server_auth.c

+/*
+  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+  %                                                                      %
+  %  OverChat client login authenticator.                                %
+  %  Written by David Duncan Ross Palmer <Overlord@DayboLogic.co.uk>     %
+  %  (C) Copyright 2001, 2001 Daybo Logic, all rights reserved.          %
+  %  Source code to the OverChat server is provided to those signing     %
+  %  a non-disclosure agreement under special circumstances.             %
+  %  This module is installed as a callback in Blake for when the server %
+  %  received a login packet from a client.  When it does it attempts    %
+  %  to look the user up in the database and determine whether the login %
+  %  is justified.  If it is, the user is validated and the server core  %
+  %  is updated with a nickname and other information so that the user   %
+  %  is not disconnected and may communicate with other users on the     %
+  %  system, if it is not justified, the user will be killed straight    %
+  %  away.                                                               %
+  %                                                                      %
+  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+*/
+
+#include "overchat_config.h" /* Project configuration */
+#include <assert.h>
+#include <limits.h>
+#include <stddef.h>
+#include <time.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef HDRSTOP
+# pragma hdrstop
+#endif /*HDRSTOP*/
+
+#include "ddrptype.h"
+#include "server.h"
+/*-------------------------------------------------------------------------*/
+static bool AuthUser(const char* Nick, const char* Pass);
+/*-------------------------------------------------------------------------*/
+bool blakecallback_Authenticator(int Sock, const void* BlakeLoginRaw)
+{
+  struct blakeLogin* login;
+  bool validated; /* Do not confuse with return value */
+  
+  assert(BlakeLoginRaw);
+  if ( !BlakeLoginRaw ) return false;
+  
+  login = (struct blakeLogin*)BlakeLoginRaw;
+  
+  validated = AuthUser(login->username, login->password);
+
+  /* FIXME: Check the specifications on the packet, is it possible that they
+  may not be terminated?  Try to login with hude nicks to test */  
+  if ( validated ) {
+    server_Auth(Sock, login->username);
+  }
+  else { /* Invalid username or password */
+    server_Kill(Sock);
+  }
+  return true;
+}
+/*-------------------------------------------------------------------------*/
+static bool AuthUser(const char* Nick, const char* Pass)
+{
+  bool authed = false;
+  
+  if ( Nick && Pass ) {
+    BLAKE_DATABASE_HANDLE dbHandle;
+    enum blakeError err;
+    unsigned int userIndex;
+    struct blakedb_User userData;
+    
+    err = blakedb_CreateDBHandle(OVERCHAT_REGUSERS, &dbHandle);
+    if ( err != blakeSuccess ) {
+      server_PrintBlakeError(err);
+      return false;
+    }
+    blakedb_LockDatabase(dbHandle);
+    userIndex = blakedb_GetUserIndex(dbHandle, Nick);
+    err = blakedb_GetUserData(dbHandle, userIndex, &userData, sizeof(userData));
+    if ( err != blakeSuccess ) {
+      server_PrintBlakeError(err);
+    }
+    else {
+      if ( userData.TimeOf.Creation ) { /* User exists */
+        if ( strcmp(userData.Password, Pass) == 0 ) /* Pass correct */
+          authed = true;
+      }
+    }
+    blakedb_UnlockDatabase(dbHandle);
+    
+    blakedb_DestroyDBHandle(dbHandle);
+  }
+  
+  return authed;
+}
+/*-------------------------------------------------------------------------*/

File src/server_auth.h

+/*
+  OverChat's server authentication header
+*/
+
+#ifndef __INC_AUTH_H
+#define __INC_AUTH_H
+/*-------------------------------------------------------------------------*/
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+bool blakecallback_Authenticator(int Sock, const void* BlakeLoginRaw);
+
+#ifdef __cplusplus
+  }
+#endif
+/*-------------------------------------------------------------------------*/
+#endif /*!__INC_AUTH_H*/

File src/server_core.c

   1.7 - Cleanup of poor locking practice
   1.8 - All broken flag related stuff deleted and new function i_Broken() for internal broken-ness trapping
   1.9 - GlobalID has now been renamed server_core.  Added uptime counter.
+  2.0 - Change order of socket related cleanup to prevent a trap in TX/RX
+  2.1 - Added e_AuthenticationUpdate()
+  2.2 - Add a heartbeat hook to log uptime at 24-hour intervals
 */
 #include "overchat_config.h"
 #include <stddef.h>
 #endif
 #include "ddrptype.h"
 #include "server.h"
-#include "server_core.h"
 #include "dpcrtlmm.h" /* My memory management library */
 #include "ddrpansi.h" /* Replacements for non portable thing which I beleive ANSI should have specified */
-
+/*-------------------------------------------------------------------------------*/
+/* Used by core_LogUptime() */
+#define DO_S(timefactor) \
+          if ((timefactor) > 1) sprintf(msgbuff+strlen(msgbuff), "s"); \
+          sprintf(msgbuff+strlen(msgbuff), ", ")
+/*-------------------------------------------------------------------------------*/
 /* Internal protected data */
 static S_CORE_NODE* Base = NULL; /* Base node of core linked list */
 static unsigned int Count = 0U; /* Our cached count prevents unneccersary crawls */
 static void i_StartedTrap(void); /* No useful purpose, see content */
 static void i_CleanNode(S_CORE_NODE* node);
 static void i_InitNode(S_CORE_NODE* node);
-static void i_DeleteAll(const char* File, const unsigned int Line);
+static void i_DeleteAll(void);
 static void i_DeleteNode(S_CORE_NODE* PNode);
 static void i_AppendNode(S_CORE_NODE* PNode); /* Appends a pre-allocated node onto the end of the list */
 static S_CORE_NODE* i_GetEndNode(void); /* NULL if no nodes... could well be Base */
 static void i_Challenge(S_CORE_NODE* PNode); /* Send the challenge packet to a user */
 static void i_AuthorisedScan(void); /* Don't call, runs every five seconds automatically */
 static bool i_RemoveUserBySocketDesc(const int SocketDesc);
+static bool i_AuthenticationUpdate(int SocketDesc, const char* Nick);
 static void i_Broken(const int SocketDesc);
+static void i_24Hours(void); /* Don't call this, it runs automatically every day */
 
 /* Thread safe locking controls */
 static void createmutex(void);
 static bool e_RemoveUserByNick(const char* Nick);
 static bool e_RemoveAllUsers(const char* File, const unsigned int Line);
 static bool e_AddUser(const char* Nick, int SocketDesc);
+static bool e_AuthenticationUpdate(int SocketDesc, const char* Nick);
 static void e_Broken(const int SocketDesc);
 /*------Internal bodies-----------------------------------------------------*/
 static void i_VTableInit(S_CORE_VTABLE* PTable)
   PTable->RemoveUserByNick = e_RemoveUserByNick;
   PTable->RemoveAllUsers = e_RemoveAllUsers;
   PTable->AddUser = e_AddUser;
+  PTable->AuthenticationUpdate = e_AuthenticationUpdate;
   PTable->Broken = e_Broken;
 }
 /*--------------------------------------------------------------------------*/
   memset(node, 0, sizeof(S_CORE_NODE));
 }
 /*-------------------------------------------------------------------------*/
-static void i_DeleteAll(const char* File, const unsigned int Line)
+static void i_DeleteAll()
 {
-  char msgbuff[MSG_BUFF_SIZE];
-  sprintf(msgbuff, "i_DeleteAll() called from %s line %u", File, Line);
-  _server_message(true, msgbuff);
-
   if (Base) {
     S_CORE_NODE* node = Base;
 
   assert(Base);
   assert(PNode);
 
-  server_txrx_DelConn(PNode->socketDesc); /* Clear up TX/RX buffers */
   network_InstallIncomingCallback(PNode->socketDesc, NULL); /* Uninstall incoming data callback */
   network_CloseSocket(PNode->socketDesc); /* Kill the connection */
+  server_txrx_DelConn(PNode->socketDesc); /* Clear up TX/RX buffers */
   
   if ( Base == PNode )
   {
     return;
   }
   _server_UnregBeatHook(i_AuthorisedScan); /* Stop the timer function */
-  i_DeleteAll(__FILE__, __LINE__);
+  _server_UnregBeatHook(i_24Hours); /* Stop the daily stuff */
+  i_DeleteAll();
   /* Final resets incase we're restarted */
   Started = false;
   unlock();
   return true;
 }
 /*-------------------------------------------------------------------------*/
+static bool e_AuthenticationUpdate(int SocketDesc, const char* Nick)
+{
+  bool ret;
+  
+  lock();
+  ret = i_AuthenticationUpdate(SocketDesc, Nick);
+  unlock();
+  
+  return ret;
+}
+/*-------------------------------------------------------------------------*/
+static bool i_AuthenticationUpdate(int SocketDesc, const char* Nick)
+{
+  S_CORE_NODE* userNode;
+  bool ret = false;
+  char displayString[256 + OVERCHAT_NICK_LIMIT];
+  size_t maxDS = sizeof(displayString)-1;
+  
+  userNode = i_NodeFromSocketDesc(SocketDesc);
+  if ( userNode ) {
+    userNode->nick = dpcrtlmm_Alloc(blkarray, strlen(Nick) + 1);
+    if ( userNode->nick ) {
+      ret = true;
+      strcpy(userNode->nick, Nick);
+      userNode->clearance = 1; /* FIXME: This will prevent kill but it not a real clearance */
+      /* FIXME: User's language has not been set, it will default to English */
+      
+      /* Write some stuff to the logs */
+      displayString[0] = '\0'; /* Prepare string */
+      strncat(displayString, "Nick \"", maxDS);
+      strncat(displayString, Nick, maxDS);
+      strncat(displayString, "\" has authenticated.", maxDS);
+      _server_message(true, displayString);
+    }
+  }
+  return ret;
+}
+/*-------------------------------------------------------------------------*/
 static bool e_RemoveAllUsers(const char* File, const unsigned int Line)
 {
   /* Debug crap */
   /* We're just a thread-safe wrapper around i_DeleteAll() */
   i_StartedTrap();
   lock();
-  i_DeleteAll(__FILE__, __LINE__);
+  i_DeleteAll();
   unlock();
   return true;
 }
   
   return;
 }
+/*-------------------------------------------------------------------------*/
+static void i_24Hours()
+{
+  core_LogUptime();
+}
 /*---Public bodies---------------------------------------------------------*/
 S_CORE_VTABLE* core_Setup()
 {
   if (Started) /* An illegal attempt! */
   {
-    _server_message(0, "globalid: Privelledges for list mods are already awarded.\n");
+    _server_message(false, "core: Privelleges for list mods are already awarded.\n");
     return NULL;
   }
   if ( !i_Dynamics(true) ) return NULL;
   Started = true;
   i_VTableInit(&vtab);
   _server_RegBeatHook(i_AuthorisedScan, 10); /* Register our little detective */
+  _server_RegBeatHook(i_24Hours, OVERCHAT_DAY); /* Register a daily activity */
   createmutex();
   time(&startTime); /* Record the time the server started */
   return &vtab;
   return startTime;
 }
 /*-------------------------------------------------------------------------*/
+void core_LogUptime()
+{
+  unsigned short years = 0, days = 0, hours = 0, mins = 0, secs = 0;
+  unsigned int uptime;
+  char msgbuff[512];
+  
+  sprintf(msgbuff, "Uptime: ");
+  uptime = core_Uptime();
+  
+  if ( uptime ) {
+    years = uptime / OVERCHAT_YEAR;
+    uptime -= OVERCHAT_YEAR * years;
+    
+    days = uptime / OVERCHAT_DAY;
+    uptime -= OVERCHAT_DAY * days;
+    
+    hours = uptime / OVERCHAT_HOUR;
+    uptime -= OVERCHAT_HOUR * hours;
+