From e2ba7cd29617ae05087ad3d25c55a2eb8ce607a3 Mon Sep 17 00:00:00 2001 From: fusion32 Date: Thu, 28 May 2026 23:56:29 -0300 Subject: fix issues and warnings when compiling with glibc < 2.32 (#57, #58) This also fixes some inconsistencies such as mixing both strerror and strerrordesc_np, and possible formatting issues. --- Makefile | 6 +++--- src/common.hh | 2 ++ src/communication.cc | 10 +++++----- src/connections.cc | 6 +++--- src/main.cc | 34 ++++++++++++++++++++-------------- src/map.cc | 2 +- src/operate.cc | 2 +- src/query.cc | 2 +- src/script.cc | 18 +++++++++--------- src/sending.cc | 4 ++-- src/shm.cc | 2 +- src/threads.cc | 4 ++-- src/utils.cc | 41 +++++++++++++++++++++++++++++++++++++++++ src/writer.cc | 2 +- tools/makefile.go | 5 +++-- 15 files changed, 95 insertions(+), 45 deletions(-) diff --git a/Makefile b/Makefile index 097c430..07f598a 100644 --- a/Makefile +++ b/Makefile @@ -4,13 +4,13 @@ OUTPUTEXE = game CC = g++ CFLAGS = -m64 -fno-strict-aliasing -pedantic -Wall -Wextra -Wno-deprecated-declarations -Wno-unused-parameter -Wno-format-truncation -std=c++11 -pthread -DOS_LINUX=1 -DARCH_X64=1 -LFLAGS = -Wl,-t -lcrypto +LFLAGS = -Wl,-t -lrt -lcrypto DEBUG ?= 0 ifneq ($(DEBUG), 0) - CFLAGS += -g -Og -DENABLE_ASSERTIONS=1 + CFLAGS += -g -Og -DENABLE_ASSERTIONS=1 else - CFLAGS += -O2 + CFLAGS += -O2 endif HEADERS = $(SRCDIR)/common.hh $(SRCDIR)/communication.hh $(SRCDIR)/config.hh $(SRCDIR)/connections.hh $(SRCDIR)/containers.hh $(SRCDIR)/cr.hh $(SRCDIR)/crypto.hh $(SRCDIR)/enums.hh $(SRCDIR)/houses.hh $(SRCDIR)/info.hh $(SRCDIR)/magic.hh $(SRCDIR)/map.hh $(SRCDIR)/moveuse.hh $(SRCDIR)/objects.hh $(SRCDIR)/operate.hh $(SRCDIR)/query.hh $(SRCDIR)/reader.hh $(SRCDIR)/script.hh $(SRCDIR)/threads.hh $(SRCDIR)/writer.hh diff --git a/src/common.hh b/src/common.hh index 4206ed6..a45db1c 100644 --- a/src/common.hh +++ b/src/common.hh @@ -182,6 +182,8 @@ void error(const char *Text, ...) ATTR_PRINTF(1, 2); void print(int Level, const char *Text, ...) ATTR_PRINTF(2, 3); int random(int Min, int Max); bool FileExists(const char *FileName); +const char *GetSignalDescription(int SigNr); +const char *GetErrorDescription(int SigNr); bool isSpace(int c); bool isAlpha(int c); diff --git a/src/communication.cc b/src/communication.cc index 2de5e04..e8cf21a 100644 --- a/src/communication.cc +++ b/src/communication.cc @@ -652,7 +652,7 @@ bool CallGameThread(TConnection *Connection){ Connection->WaitingForACK = true; if(tgkill(GetGameProcessID(), GetGameThreadID(), SIGUSR1) == -1){ error("CallGameThread: Can't send SIGUSR1 to thread %d/%d: (%d) %s\n", - GetGameProcessID(), GetGameThreadID(), errno, strerrordesc_np(errno)); + GetGameProcessID(), GetGameThreadID(), errno, GetErrorDescription(errno)); SendLoginMessage(Connection, LOGIN_MESSAGE_ERROR, "The server is not online.\nPlease try again later.", -1); return false; @@ -1489,21 +1489,21 @@ bool OpenSocket(void){ Linger.l_linger = 0; if(setsockopt(TCPSocket, SOL_SOCKET, SO_LINGER, &Linger, sizeof(Linger)) == -1){ error("LaunchServer: Failed to set SO_LINGER=(0, 0): (%d) %s.\n", - errno, strerrordesc_np(errno)); + errno, GetErrorDescription(errno)); return false; } int ReuseAddr = 1; if(setsockopt(TCPSocket, SOL_SOCKET, SO_REUSEADDR, &ReuseAddr, sizeof(ReuseAddr)) == -1){ error("LaunchServer: Failed to set SO_REUSEADDR=1: (%d) %s.\n", - errno, strerrordesc_np(errno)); + errno, GetErrorDescription(errno)); return false; } int NoDelay = 1; if(setsockopt(TCPSocket, IPPROTO_TCP, TCP_NODELAY, &NoDelay, sizeof(NoDelay)) == -1){ error("LaunchServer: Failed to set TCP_NODELAY=1: (%d) %s.\n", - errno, strerrordesc_np(errno)); + errno, GetErrorDescription(errno)); return false; } @@ -1517,7 +1517,7 @@ bool OpenSocket(void){ #endif if(bind(TCPSocket, (struct sockaddr*)&ServerAddress, sizeof(ServerAddress)) == -1){ error("LaunchServer: Failed to bind to acceptor to %s:%d: (%d) %s.\n", - inet_ntoa(ServerAddress.sin_addr), GamePort, errno, strerrordesc_np(errno)); + inet_ntoa(ServerAddress.sin_addr), GamePort, errno, GetErrorDescription(errno)); return false; } diff --git a/src/connections.cc b/src/connections.cc index f1d36fb..2aee24a 100644 --- a/src/connections.cc +++ b/src/connections.cc @@ -105,7 +105,7 @@ bool TConnection::SetLoginTimer(int Timeout){ SigEvent.sigev_notify_thread_id = this->ThreadID; if(timer_create(CLOCK_MONOTONIC, &SigEvent, &this->LoginTimer) == -1){ error("TConnection::SetLoginTimer: Failed to create timer: (%d) %s\n", - errno, strerrordesc_np(errno)); + errno, GetErrorDescription(errno)); return false; } @@ -113,7 +113,7 @@ bool TConnection::SetLoginTimer(int Timeout){ TimerSpec.it_value.tv_sec = Timeout; if(timer_settime(this->LoginTimer, 0, &TimerSpec, NULL) == -1){ error("TConnection::SetLoginTimer: Failed to start timer: (%d) %s\n", - errno, strerrordesc_np(errno)); + errno, GetErrorDescription(errno)); return false; } @@ -133,7 +133,7 @@ void TConnection::StopLoginTimer(void){ if(timer_delete(this->LoginTimer) == -1){ error("TConnection::StopLoginTimer: Failed to delete timer: (%d) %s\n", - errno, strerrordesc_np(errno)); + errno, GetErrorDescription(errno)); } this->LoginTimer = 0; diff --git a/src/main.cc b/src/main.cc index ddeda8b..937c222 100644 --- a/src/main.cc +++ b/src/main.cc @@ -53,7 +53,8 @@ static void SigBlock(int SigNr){ sigaddset(&Set, SigNr); if(sigprocmask(SIG_BLOCK, &Set, NULL) == -1){ error("SigBlock: Failed to block signal %d (%s): (%d) %s\n", - SigNr, sigdescr_np(SigNr), errno, strerrordesc_np(errno)); + SigNr, GetSignalDescription(SigNr), + errno, GetErrorDescription(errno)); } } @@ -63,18 +64,18 @@ static void SigWaitAny(void){ sigsuspend(&Set); } -static void SigHupHandler(int signr){ +static void SigHupHandler(int SigNr){ // no-op (?) } -static void SigAbortHandler(int signr){ +static void SigAbortHandler(int SigNr){ print(1, "SigAbortHandler: schalte Writer-Thread ab.\n"); AbortWriter(); } -static void DefaultHandler(int signr){ +static void DefaultHandler(int SigNr){ print(1, "DefaultHandler: Beende Game-Server (SigNr. %d: %s).\n", - signr, sigdescr_np(signr)); + SigNr, GetSignalDescription(SigNr)); SigHandler(SIGINT, SIG_IGN); SigHandler(SIGQUIT, SIG_IGN); @@ -83,8 +84,8 @@ static void DefaultHandler(int signr){ SigHandler(SIGXFSZ, SIG_IGN); SigHandler(SIGPWR, SIG_IGN); - SaveMapOn = (signr == SIGQUIT) || (signr == SIGTERM) || (signr == SIGPWR); - if(signr == SIGTERM){ + SaveMapOn = (SigNr == SIGQUIT) || (SigNr == SIGTERM) || (SigNr == SIGPWR); + if(SigNr == SIGTERM){ int Hour, Minute; GetRealTime(&Hour, &Minute); RebootTime = (Hour * 60 + Minute + 6) % 1440; @@ -98,8 +99,8 @@ static void DefaultHandler(int signr){ #if 0 // TODO(fusion): This function was exported in the binary but not referenced anywhere. -static void ErrorHandler(int signr){ - error("ErrorHandler: SigNr. %d: %s\n", signr, sigdescr_np(signr)); +static void ErrorHandler(int SigNr){ + error("ErrorHandler: SigNr. %d: %s\n", SigNr, GetSignalDescription(SigNr)); EndGame(); LogoutAllPlayers(); exit(EXIT_FAILURE); @@ -151,7 +152,7 @@ static void InitTime(void){ SigEvent.sigev_notify_thread_id = gettid(); if(timer_create(CLOCK_MONOTONIC, &SigEvent, &BeatTimer) == -1){ error("InitTime: Failed to create beat timer: (%d) %s\n", - errno, strerrordesc_np(errno)); + errno, GetErrorDescription(errno)); throw "cannot create beat timer"; } @@ -161,7 +162,7 @@ static void InitTime(void){ TimerSpec.it_value = TimerSpec.it_interval; if(timer_settime(BeatTimer, 0, &TimerSpec, NULL) == -1){ error("InitTime: Failed to start beat timer: (%d) %s\n", - errno, strerrordesc_np(errno)); + errno, GetErrorDescription(errno)); throw "cannot start beat timer"; } } @@ -169,7 +170,7 @@ static void InitTime(void){ static void ExitTime(void){ if(timer_delete(BeatTimer) == -1){ error("ExitTime: Failed to delete beat timer: (%d) %s\n", - errno, strerrordesc_np(errno)); + errno, GetErrorDescription(errno)); } SigHandler(SIGALRM, SIG_IGN); @@ -448,7 +449,7 @@ static void AdvanceGame(int Delay){ SendAll(); } -static void SigUsr1Handler(int signr){ +static void SigUsr1Handler(int SigNr){ SigUsr1Counter += 1; } @@ -508,7 +509,12 @@ static bool DaemonInit(bool NoFork){ } umask(0177); - chdir(SAVEPATH); + + // NOTE(fusion): The original binary would change directories to `SAVEPATH` + // here, but because this function is called very early at startup, no config + // values would have been loaded, leaving `SAVEPATH` empty and causing this + // next call to `chdir` to always fail with ENOENT. + //chdir(SAVEPATH); int OpenMax = sysconf(_SC_OPEN_MAX); if(OpenMax < 0){ diff --git a/src/map.cc b/src/map.cc index 86b0c83..b39d25a 100644 --- a/src/map.cc +++ b/src/map.cc @@ -1713,7 +1713,7 @@ void PatchSector(int SectorX, int SectorY, int SectorZ, bool FullSector, if(rename(FileNameBak, FileName) != 0){ int ErrCode = errno; error("PatchSector: Fehler %d beim Umbenennen von %s.\n", ErrCode, FileNameBak); - error("# Fehler %d: %s.\n", ErrCode, strerror(ErrCode)); + error("# Fehler %d: %s.\n", ErrCode, GetErrorDescription(ErrCode)); throw "cannot patch ORIGMAP"; } } diff --git a/src/operate.cc b/src/operate.cc index b67b3dd..715c272 100644 --- a/src/operate.cc +++ b/src/operate.cc @@ -2406,7 +2406,7 @@ void Talk(uint32 CreatureID, int Mode, const char *Addressee, const char *Text, TConnection *Connection = GetFirstConnection(); while(Connection != NULL){ if(Connection->Live()){ - SendMessage(Connection, TALK_ADMIN_MESSAGE, Text); + SendMessage(Connection, TALK_ADMIN_MESSAGE, "%s", Text); } Connection = GetNextConnection(); diff --git a/src/query.cc b/src/query.cc index 76b31fd..086c9cc 100644 --- a/src/query.cc +++ b/src/query.cc @@ -95,7 +95,7 @@ void TQueryManagerConnection::connect(void){ int SocketFlags = fcntl(this->Socket, F_GETFL); if(SocketFlags == -1 || fcntl(this->Socket, F_SETFL, (SocketFlags | O_NONBLOCK)) == -1){ error("TQueryManagerConnection::connect: Failed to set socket as non-blocking: (%d) %s\n", - errno, strerrordesc_np(errno)); + errno, GetErrorDescription(errno)); this->disconnect(); continue; } diff --git a/src/script.cc b/src/script.cc index 75eab55..4695acc 100644 --- a/src/script.cc +++ b/src/script.cc @@ -115,7 +115,7 @@ void TReadScriptFile::open(const char *FileName){ if(this->File[Depth] == NULL){ int ErrCode = errno; ::error("TReadScriptFile::open: Kann Datei %s nicht öffnen.\n", this->Filename[Depth]); - ::error("Fehler %d: %s.\n", ErrCode, strerror(ErrCode)); + ::error("Fehler %d: %s.\n", ErrCode, GetErrorDescription(ErrCode)); throw "Cannot open script-file"; } @@ -582,7 +582,7 @@ void TWriteScriptFile::open(const char *FileName){ if(this->File == NULL){ int ErrCode = errno; ::error("TWriteScriptFile: Kann Datei %s nicht anlegen.\n", FileName); - ::error("Fehler %d: %s.\n", ErrCode, strerror(ErrCode)); + ::error("Fehler %d: %s.\n", ErrCode, GetErrorDescription(ErrCode)); throw "Cannot create script-file"; } @@ -751,7 +751,7 @@ void TReadBinaryFile::close(void){ int ErrCode = errno; ::error("TReadBinaryFile::close: Fehler beim Schließen der Datei.\n"); ::error("# Datei: %s, Fehlercode: %d (%s)\n", - this->Filename, ErrCode, strerror(ErrCode)); + this->Filename, ErrCode, GetErrorDescription(ErrCode)); } this->File = NULL; } @@ -811,7 +811,7 @@ uint8 TReadBinaryFile::readByte(void){ int Position = this->getPosition(); ::error("TReadBinaryFile::readByte: Fehler beim Lesen eines Bytes\n"); ::error("# Datei: %s, Position: %d, Rückgabewert: %d, Fehlercode: %d (%s)\n", - this->Filename, Position, Result, ErrCode, strerror(ErrCode)); + this->Filename, Position, Result, ErrCode, GetErrorDescription(ErrCode)); // NOTE(fusion): Close file and make a backup, possibly for further inspection. if(fclose(this->File) != 0){ @@ -832,7 +832,7 @@ void TReadBinaryFile::readBytes(uint8 *Buffer, int Count){ int Position = this->getPosition(); ::error("TReadBinaryFile::readBytes: Fehler beim Lesen von %d Bytes\n", Count); ::error("# Datei: %s, Position %d, Rückgabewert: %d, Fehlercode: %d (%s)\n", - this->Filename, Position, Result, ErrCode, strerror(ErrCode)); + this->Filename, Position, Result, ErrCode, GetErrorDescription(ErrCode)); // NOTE(fusion): Close file and make a backup, possibly for further inspection. if(fclose(this->File) != 0){ @@ -885,7 +885,7 @@ void TWriteBinaryFile::open(const char *FileName){ if(this->File == NULL){ int ErrCode = errno; ::error("TWriteBinaryFile::open: Kann Datei %s nicht anlegen.\n", FileName); - ::error("Fehler %d: %s.\n", ErrCode, strerror(ErrCode)); + ::error("Fehler %d: %s.\n", ErrCode, GetErrorDescription(ErrCode)); snprintf(ErrorString, sizeof(ErrorString), "Cannot create file %s.", FileName); @@ -902,7 +902,7 @@ void TWriteBinaryFile::close(void){ int ErrCode = errno; ::error("TWriteBinaryFile::close: Fehler beim Schließen der Datei.\n"); ::error("# Datei: %s, Fehlercode: %d (%s)\n", - this->Filename, ErrCode, strerror(ErrCode)); + this->Filename, ErrCode, GetErrorDescription(ErrCode)); } this->File = NULL; } @@ -928,7 +928,7 @@ void TWriteBinaryFile::writeByte(uint8 Byte){ int ErrCode = errno; ::error("TWriteBinaryFile::writeByte: Fehler beim Schreiben eines Bytes\n"); ::error("# Datei: %s, Rückgabewert: %d, Fehlercode: %d (%s)\n", - this->Filename, Result, ErrCode, strerror(ErrCode)); + this->Filename, Result, ErrCode, GetErrorDescription(ErrCode)); // NOTE(fusion): Close file and make a backup, possibly for further inspection. if(fclose(this->File) != 0){ @@ -947,7 +947,7 @@ void TWriteBinaryFile::writeBytes(const uint8 *Buffer, int Count){ int ErrCode = errno; ::error("TWriteBinaryFile::writeBytes: Fehler beim Schreiben von %d Bytes\n", Count); ::error("# Datei: %s, Rückgabewert: %d, Fehlercode: %d (%s)\n", - this->Filename, Result, ErrCode, strerror(ErrCode)); + this->Filename, Result, ErrCode, GetErrorDescription(ErrCode)); // NOTE(fusion): Close file and make a backup, possibly for further inspection. if(fclose(this->File) != 0){ diff --git a/src/sending.cc b/src/sending.cc index eb78e82..1661836 100644 --- a/src/sending.cc +++ b/src/sending.cc @@ -349,7 +349,7 @@ void SendResult(TConnection *Connection, RESULT r){ } if(Message != NULL){ - SendMessage(Connection, TALK_FAILURE_MESSAGE, Message); + SendMessage(Connection, TALK_FAILURE_MESSAGE, "%s", Message); if(r == ENTERPROTECTIONZONE || r == NOTINVITED || r == MOVENOTPOSSIBLE){ SendSnapback(Connection); } @@ -1721,7 +1721,7 @@ void BroadcastMessage(int Mode, const char *Text, ...){ TConnection *Connection = GetFirstConnection(); while(Connection != NULL){ if(Connection->Live()){ - SendMessage(Connection, Mode, Message); + SendMessage(Connection, Mode, "%s", Message); } Connection = GetNextConnection(); } diff --git a/src/shm.cc b/src/shm.cc index 98dd526..0e2153a 100644 --- a/src/shm.cc +++ b/src/shm.cc @@ -126,7 +126,7 @@ static void ErrorHandler(const char *Text){ if(SHM != NULL){ SHM->Errors += 1; if(SHM->Errors <= 0x8000){ - Log("error", Text); + Log("error", "%s", Text); if(SHM->Errors == 0x8000){ Log("error", "Zu viele Fehler. Keine weitere Protokollierung.\n"); } diff --git a/src/threads.cc b/src/threads.cc index fbced09..ba17086 100644 --- a/src/threads.cc +++ b/src/threads.cc @@ -146,10 +146,10 @@ Semaphore::~Semaphore(void){ int ErrorCode; if((ErrorCode = pthread_mutex_destroy(&this->mutex)) != 0){ error("Semaphore::~Semaphore: Kann Mutex nicht freigeben: (%d) %s.\n", - ErrorCode, strerrordesc_np(ErrorCode)); + ErrorCode, GetErrorDescription(ErrorCode)); }else if((ErrorCode = pthread_cond_destroy(&this->condition)) != 0){ error("Semaphore::~Semaphore: Kann Wartebedingung nicht freigeben: (%d) %s.\n", - ErrorCode, strerrordesc_np(ErrorCode)); + ErrorCode, GetErrorDescription(ErrorCode)); } } diff --git a/src/utils.cc b/src/utils.cc index 3937923..e7d8acd 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -1,5 +1,6 @@ #include "common.hh" +#include #include static TErrorFunction *ErrorFunction; @@ -95,6 +96,46 @@ bool FileExists(const char *FileName){ return Result; } +#if !defined(_GNU_SOURCE) || (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 32)) +# if defined(_BSD_SOURCE) || defined(_DEFAULT_SOURCE) +static const char *sigdescr_np(int SigNr){ + const char *Description = NULL; + if(SigNr >= 0 && SigNr < NSIG){ + Description = sys_siglist[SigNr]; + } + return Description; +} + +static const char *strerrordesc_np(int ErrCode){ + const char *Description = NULL; + if(ErrCode >= 0 && ErrCode < sys_nerr){ + Description = sys_errlist[ErrCode]; + } + return Description; +} +# else // defined(_BSD_SOURCE) || defined(_DEFAULT_SOURCE) +#warning "Current LIBC/GLIBC version doesn't expose error/signal description tables." +static const char *sigdescr_np(int SigNr){ return "No signal description"; } +static const char *strerrordesc_np(int ErrCode){ return "No error description"; } +# endif // defined(_BSD_SOURCE) || defined(_DEFAULT_SOURCE) +#endif //!defined(_GNU_SOURCE) || (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 32)) + +const char *GetSignalDescription(int SigNr){ + const char *Description = sigdescr_np(SigNr); + if(Description == NULL){ + Description = "Invalid signal"; + } + return Description; +} + +const char *GetErrorDescription(int ErrCode){ + const char *Description = strerrordesc_np(ErrCode); + if(Description == NULL){ + Description = "Invalid error"; + } + return Description; +} + // String Utility // ============================================================================= bool isSpace(int c){ diff --git a/src/writer.cc b/src/writer.cc index ee712ba..3b52fd6 100644 --- a/src/writer.cc +++ b/src/writer.cc @@ -921,7 +921,7 @@ void ProcessBroadcastReply(TBroadcastReplyData *Data){ return; } - BroadcastMessage(TALK_STATUS_MESSAGE, Data->Message); + BroadcastMessage(TALK_STATUS_MESSAGE, "%s", Data->Message); delete Data; } diff --git a/tools/makefile.go b/tools/makefile.go index b76efcf..333f422 100644 --- a/tools/makefile.go +++ b/tools/makefile.go @@ -30,6 +30,7 @@ var ( releaseOptions = []string{"-O2"} linkerOptions = []string{ "-Wl,-t", + "-lrt", "-lcrypto", } ) @@ -80,9 +81,9 @@ func main() { // DEBUG SWITCH fmt.Fprint(&output, "DEBUG ?= 0\n") fmt.Fprint(&output, "ifneq ($(DEBUG), 0)\n") - fmt.Fprintf(&output, "\tCFLAGS += %v\n", strings.Join(debugOptions, " ")) + fmt.Fprintf(&output, " CFLAGS += %v\n", strings.Join(debugOptions, " ")) fmt.Fprint(&output, "else\n") - fmt.Fprintf(&output, "\tCFLAGS += %v\n", strings.Join(releaseOptions, " ")) + fmt.Fprintf(&output, " CFLAGS += %v\n", strings.Join(releaseOptions, " ")) fmt.Fprint(&output, "endif\n\n") // HEADERS -- cgit v1.2.3