static cell AMX_NATIVE_CALL set_native_filter(AMX *amx, cell *params) { Handler *pHandler = (Handler *)amx->userdata[UD_HANDLER]; if (!pHandler) { Debugger::GenericMessage(amx, AMX_ERR_NOTFOUND); AMXXLOG_Error("[AMXX] Plugin not initialized correctly."); return 0; } if (!pHandler->IsNativeFiltering()) { //we can only initialize this during PRENIT if (! (amx->flags & AMX_FLAG_PRENIT) ) return 0; } int len; char *func = get_amxstring(amx, params[1], 0, len); int err = pHandler->SetNativeFilter(func); if (err != AMX_ERR_NONE) { Debugger::GenericMessage(amx, AMX_ERR_NOTFOUND); AMXXLOG_Error("[AMXX] Function not found: %s", function); return 0; } return 1; }
bool CGameConfig::EnterFile(const char *file, char *error, size_t maxlength) { build_pathname_r(m_CurrentPath, sizeof(m_CurrentPath), "%s/gamedata/%s", get_localinfo("amxx_datadir", "addons/amxmodx/data"), file); m_IgnoreLevel = 0; m_ShouldBeReadingDefault = true; m_ParseState = PSTATE_NONE; SMCError err; SMCStates state = { 0, 0 }; if ((err = textparsers->ParseSMCFile(m_CurrentPath, this, &state, error, maxlength)) != SMCError_Okay) { const char *msg = textparsers->GetSMCErrorString(err); AMXXLOG_Error("Error parsing gameconfig file \"%s\":", m_CurrentPath); AMXXLOG_Error("Error %d on line %d, col %d: %s", err, state.line, state.col, msg ? msg : "Unknown error"); if (m_ParseState == PSTATE_GAMEDEFS_CUSTOM) { m_CustomHandler->ReadSMC_ParseEnd(true, true); m_CustomHandler = nullptr; m_CustomLevel = 0; } return false; } return true; }
void Debugger::GenericMessage(AMX *amx, int err) { static char buffer[512]; buffer[0] = '\0'; Debugger::FmtGenericMsg(amx, err, buffer, sizeof(buffer)-1); if (buffer[0] != '\0') AMXXLOG_Error("[AMXX] %s", buffer); }
static cell AMX_NATIVE_CALL set_error_filter(AMX *amx, cell *params) { int len; char *function = get_amxstring(amx, params[1], 0, len); Handler *pHandler = (Handler *)amx->userdata[UD_HANDLER]; if (!pHandler) { Debugger::GenericMessage(amx, AMX_ERR_NOTFOUND); AMXXLOG_Error("[AMXX] Plugin not initialized correctly."); return 0; } int err = pHandler->SetErrorHandler(function); if (err != AMX_ERR_NONE) { Debugger::GenericMessage(amx, AMX_ERR_NOTFOUND); AMXXLOG_Error("[AMXX] Function not found: %s", function); return 0; } return 1; }
void Debugger::DisplayTrace(const char *message) { if (message != NULL) AMXXLOG_Error("%s", message); char buffer[512]; int length = FormatError(buffer, sizeof(buffer)-1); const char *filename = _GetFilename(); const char *version = _GetVersion(); AMXXLOG_Error("[AMXX] Displaying debug trace (plugin \"%s\", version \"%s\")", filename, version); if (length != -1) // Don't show blank line if AMX_ERR_NONE is set since there is no error message. { AMXXLOG_Error("[AMXX] %s", buffer); } int count = 0; long lLine; const char *file, *function; trace_info_t *pTrace = GetTraceStart(); while (pTrace) { GetTraceInfo(pTrace, lLine, function, file); AMXXLOG_Error( "[AMXX] [%d] %s::%s (line %d)", count, file, function, (int)(lLine + 1) ); count++; pTrace = GetNextTrace(pTrace); } }
SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *name) { if (m_IgnoreLevel) { m_IgnoreLevel++; return SMCResult_Continue; } switch (m_ParseState) { case PSTATE_NONE: { if (strcmp(name, "Games") == 0) { m_ParseState = PSTATE_GAMES; } else { m_IgnoreLevel++; } break; } case PSTATE_GAMES: { if (strcmp(name, "*") == 0 || strcmp(name, "#default") == 0 || DoesGameMatch(name)) { m_ShouldBeReadingDefault = true; strncopy(m_Game, name, sizeof(m_Game)); m_Class[0] = '\0'; m_MatchedClasses = false; m_ParseState = PSTATE_GAMEDEFS; } else { m_IgnoreLevel++; } break; } case PSTATE_GAMEDEFS: case PSTATE_GAMEDEFS_CLASSES_CLASS: { if (strcmp(name, "Classes") == 0) { if (!m_Class[0]) { m_ParseState = PSTATE_GAMEDEFS_CLASSES; m_MatchedClasses = true; } else { ++m_IgnoreLevel; } break; } else if (strcmp(name, "Offsets") == 0) { m_ParseState = PSTATE_GAMEDEFS_OFFSETS; } else if (strcmp(name, "Keys") == 0) { m_ParseState = PSTATE_GAMEDEFS_KEYS; } else if (strcmp(name, "#supported") == 0 && strcmp(m_Game, "#default") == 0) { m_ParseState = PSTATE_GAMEDEFS_SUPPORTED; m_ShouldBeReadingDefault = false; m_HadGame = false; m_MatchedGame = false; m_HadEngine = false; m_MatchedEngine = false; } else if (strcmp(name, "Signatures") == 0) { m_ParseState = PSTATE_GAMEDEFS_SIGNATURES; } else if (strcmp(name, "Addresses") == 0) { m_ParseState = PSTATE_GAMEDEFS_ADDRESSES; } else { if (ConfigManager.m_customHandlers.retrieve(name, &m_CustomHandler)) { m_CustomLevel = 0; m_ParseState = PSTATE_GAMEDEFS_CUSTOM; m_CustomHandler->ReadSMC_ParseStart(); break; } ++m_IgnoreLevel; } break; } case PSTATE_GAMEDEFS_CLASSES: { strncopy(m_Class, name, sizeof(m_Class)); m_ParseState = PSTATE_GAMEDEFS_CLASSES_CLASS; break; } case PSTATE_GAMEDEFS_OFFSETS: { strncopy(m_Offset, name, sizeof(m_Offset)); TempType.reset(); m_ParseState = PSTATE_GAMEDEFS_OFFSETS_OFFSET; m_MatchedPlatform = false; m_FoundOffset = false; break; } case PSTATE_GAMEDEFS_SIGNATURES: { strncopy(m_Offset, name, sizeof(m_Offset)); TempSig.Reset(); m_ParseState = PSTATE_GAMEDEFS_SIGNATURES_SIG; m_MatchedPlatform = false; break; } case PSTATE_GAMEDEFS_CUSTOM: { ++m_CustomLevel; return m_CustomHandler->ReadSMC_NewSection(states, name); break; } case PSTATE_GAMEDEFS_ADDRESSES: { m_Address[0] = '\0'; m_AddressSignature[0] = '\0'; m_AddressReadCount = 0; strncopy(m_Address, name, sizeof(m_Address)); m_ParseState = PSTATE_GAMEDEFS_ADDRESSES_ADDRESS; break; } case PSTATE_GAMEDEFS_ADDRESSES_ADDRESS: { if (g_LibSys.DoesPlatformMatch(name)) { m_ParseState = PSTATE_GAMEDEFS_ADDRESSES_ADDRESS_READ; } else { if (strcmp(name, PLATFORM_LINUX_NAME) != 0 && strcmp(name, PLATFORM_WINDOWNS_NAME) != 0 && strcmp(name, PLATFORM_MAC_NAME) != 0) { AMXXLOG_Error("Error while parsing Address section for \"%s\" (%s):", m_Address, m_CurrentPath); AMXXLOG_Error("Unrecognized platform \"%s\"", name); } m_IgnoreLevel = 1; } break; } default: { m_IgnoreLevel++; break; } } return SMCResult_Continue; }
bool CGameConfig::Reparse(char *error, size_t maxlength) { m_Offsets.clear(); m_OffsetsByClass.clear(); m_Keys.clear(); m_Addresses.clear(); char path[PLATFORM_MAX_PATH]; const char *dataDir = get_localinfo("amxx_datadir", "addons/amxmodx/data"); build_pathname_r(path, sizeof(path), "%s/gamedata/%s/master.games.txt", dataDir, m_File); if (!g_LibSys.PathExists(path)) { // Single config file without master g_LibSys.PathFormat(path, sizeof(path), "%s.txt", m_File); if (!EnterFile(path, error, maxlength)) { return false; } // Allow customizations of default gamedata files build_pathname_r(path, sizeof(path), "%s/gamedata/custom/%s.txt", dataDir, m_File); if (g_LibSys.PathExists(path)) { g_LibSys.PathFormat(path, sizeof(path), "custom/%s.txt", m_File); auto success = EnterFile(path, error, maxlength); if (success) { AMXXLOG_Log("[AMXX] Parsed custom gamedata override file: %s", path); } return success; } return true; } SMCError err; SMCStates state = { 0, 0 }; ke::Vector<ke::AString> fileList; MasterReader.m_FileList = &fileList; err = textparsers->ParseSMCFile(path, &MasterReader, &state, error, maxlength); if (err != SMCError_Okay) { const char *msg = textparsers->GetSMCErrorString(err); AMXXLOG_Error("Error parsing master gameconf file \"%s\":", path); AMXXLOG_Error("Error %d on line %d, col %d: %s", err, state.line, state.col, msg ? msg : "Unknown error"); return false; } for (size_t i = 0; i < fileList.length(); ++i) { g_LibSys.PathFormat(path, sizeof(path), "%s/%s", m_File, fileList[i].chars()); if (!EnterFile(path, error, maxlength)) { return false; } } build_pathname_r(path, sizeof(path), "%s/gamedata/%s/custom", dataDir, m_File); CDirectory *customDir = g_LibSys.OpenDirectory(path); if (!customDir) { return true; } while (customDir->MoreFiles()) { if (!customDir->IsEntryFile()) { customDir->NextEntry(); continue; } const char *currentFile = customDir->GetEntryName(); size_t length = strlen(currentFile); if (length > 4 && strcmp(¤tFile[length - 4], ".txt") != 0) { customDir->NextEntry(); continue; } g_LibSys.PathFormat(path, sizeof(path), "%s/custom/%s", m_File, currentFile); if (!EnterFile(path, error, maxlength)) { g_LibSys.CloseDirectory(customDir); return false; } AMXXLOG_Log("[AMXX] Parsed custom gamedata override file: %s", path); customDir->NextEntry(); } g_LibSys.CloseDirectory(customDir); return true; }
SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states) { if (m_IgnoreLevel) { m_IgnoreLevel--; return SMCResult_Continue; } if (m_CustomLevel) { m_CustomLevel--; m_CustomHandler->ReadSMC_LeavingSection(states); return SMCResult_Continue; } switch (m_ParseState) { case PSTATE_GAMES: { m_ParseState = PSTATE_NONE; break; } case PSTATE_GAMEDEFS: { m_ParseState = PSTATE_GAMES; break; } case PSTATE_GAMEDEFS_CLASSES: { m_MatchedClasses = false; m_ParseState = PSTATE_GAMEDEFS; break; } case PSTATE_GAMEDEFS_CLASSES_CLASS: { m_ParseState = PSTATE_GAMEDEFS_CLASSES; m_Class[0] = '\0'; break; } case PSTATE_GAMEDEFS_CUSTOM: { m_ParseState = PSTATE_GAMEDEFS; m_CustomHandler->ReadSMC_ParseEnd(false, false); break; } case PSTATE_GAMEDEFS_KEYS: { m_ParseState = m_MatchedClasses ? PSTATE_GAMEDEFS_CLASSES_CLASS : PSTATE_GAMEDEFS; break; } case PSTATE_GAMEDEFS_OFFSETS: { m_ParseState = m_MatchedClasses ? PSTATE_GAMEDEFS_CLASSES_CLASS : PSTATE_GAMEDEFS; break; } case PSTATE_GAMEDEFS_OFFSETS_OFFSET: { if (m_FoundOffset) { if (m_Class[0]) { auto ic = m_OffsetsByClass.findForAdd(m_Class); if (ic.found()) { ic->value->list.replace(m_Offset, TempType); } else if (m_OffsetsByClass.add(ic, m_Class)) { ic->value = new OffsetClass; ic->value->list.insert(m_Offset, TempType); } } else { m_Offsets.replace(m_Offset, TempType); } } m_ParseState = PSTATE_GAMEDEFS_OFFSETS; break; } case PSTATE_GAMEDEFS_SUPPORTED: { if (!m_ShouldBeReadingDefault) { m_IgnoreLevel = 1; m_ParseState = PSTATE_GAMES; } else { m_ParseState = PSTATE_GAMEDEFS; } break; } case PSTATE_GAMEDEFS_SIGNATURES: { m_ParseState = m_MatchedClasses ? PSTATE_GAMEDEFS_CLASSES_CLASS : PSTATE_GAMEDEFS; break; } case PSTATE_GAMEDEFS_SIGNATURES_SIG: { if (TempSig.library[0] == '\0') { strncopy(TempSig.library, "server", sizeof(TempSig.library)); } void *addressInBase = nullptr; if (strcmp(TempSig.library, "server") == 0) { addressInBase = reinterpret_cast<void*>(MDLL_Spawn); } else if (strcmp(TempSig.library, "engine") == 0) { addressInBase = reinterpret_cast<void*>(gpGlobals); } void *finalAddress = nullptr; if (!addressInBase) { AMXXLOG_Error("Unrecognized library \"%s\" (gameconf \"%s\")", TempSig.library, m_CurrentPath); } else if (TempSig.signature[0]) { if (TempSig.signature[0] == '@') { #if defined PLATFORM_WINDOWS MEMORY_BASIC_INFORMATION mem; if (VirtualQuery(addressInBase, &mem, sizeof(mem))) { finalAddress = g_MemUtils.ResolveSymbol(mem.AllocationBase, &TempSig.signature[1]); } else { AMXXLOG_Error("Unable to find library \"%s\" in memory (gameconf \"%s\")", TempSig.library, m_File); } #elif defined PLATFORM_POSIX Dl_info info; if (dladdr(addressInBase, &info) != 0) { void *handle = dlopen(info.dli_fname, RTLD_NOW); if (handle) { finalAddress = g_MemUtils.ResolveSymbol(handle, &TempSig.signature[1]); dlclose(handle); } else { AMXXLOG_Error("Unable to load library \"%s\" (gameconf \"%s\")", TempSig.library, m_File); } } else { AMXXLOG_Error("Unable to find library \"%s\" in memory (gameconf \"%s\")", TempSig.library, m_File); } #endif } if (!finalAddress) { finalAddress = g_MemUtils.DecodeAndFindPattern(addressInBase, TempSig.signature); } m_Sigs.replace(m_Offset, finalAddress); } m_ParseState = PSTATE_GAMEDEFS_SIGNATURES; break; } case PSTATE_GAMEDEFS_ADDRESSES: { m_ParseState = m_MatchedClasses ? PSTATE_GAMEDEFS_CLASSES_CLASS : PSTATE_GAMEDEFS; break; } case PSTATE_GAMEDEFS_ADDRESSES_ADDRESS: { m_ParseState = PSTATE_GAMEDEFS_ADDRESSES; if (m_Address[0] != '\0' && m_AddressSignature[0] != '\0') { AddressConf addrConf(m_AddressSignature, sizeof(m_AddressSignature), m_AddressReadCount, m_AddressRead); m_Addresses.replace(m_Address, addrConf); } break; } case PSTATE_GAMEDEFS_ADDRESSES_ADDRESS_READ: { m_ParseState = PSTATE_GAMEDEFS_ADDRESSES_ADDRESS; break; } } return SMCResult_Continue; }
SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value) { if (m_IgnoreLevel) { return SMCResult_Continue; } switch (m_ParseState) { case PSTATE_GAMEDEFS_OFFSETS_OFFSET: { if (!strcmp(key, "type")) { auto type = FieldType::FIELD_NONE; if (!strcmp(value, "stringint")) { type = FieldType::FIELD_STRINGINT; } else if (!strcmp(value, "stringptr")) { type = FieldType::FIELD_STRINGPTR; } else if (!strcmp(value, "string")) { type = FieldType::FIELD_STRING; } else if (!strcmp(value, "classptr")) { type = FieldType::FIELD_CLASSPTR; } else if (!strcmp(value, "class")) { type = FieldType::FIELD_CLASS; } else if (!strcmp(value, "ehandle")) { type = FieldType::FIELD_EHANDLE; } else if (!strcmp(value, "edict")) { type = FieldType::FIELD_EDICT; } else if (!strcmp(value, "entvars")) { type = FieldType::FIELD_ENTVARS; } else if (!strcmp(value, "vector")) { type = FieldType::FIELD_VECTOR; } else if (!strcmp(value, "pointer")) { type = FieldType::FIELD_POINTER; } else if (!strcmp(value, "integer")) { type = FieldType::FIELD_INTEGER; } else if (!strcmp(value, "function")) { type = FieldType::FIELD_FUNCTION; } else if (!strcmp(value, "boolean")) { type = FieldType::FIELD_BOOLEAN; } else if (!strcmp(value, "short")) { type = FieldType::FIELD_SHORT; } else if (!strcmp(value, "character")) { type = FieldType::FIELD_CHARACTER; } else if (!strcmp(value, "float")) { type = FieldType::FIELD_FLOAT; } TempType.fieldType = type; } else if (!strcmp(key, "size")) { TempType.fieldSize = ke::Max<int>(0, atoi(value)); } else if (!strcmp(key, "unsigned")) { TempType.fieldUnsigned = !!atoi(value); } else if (g_LibSys.IsPlatformCompatible(key, &m_MatchedPlatform)) { m_FoundOffset = true; TempType.fieldOffset = atoi(value); } break; } case PSTATE_GAMEDEFS_KEYS: { ke::AString vstr(value); m_Keys.replace(key, ke::Move(vstr)); break; } case PSTATE_GAMEDEFS_SUPPORTED: { if (strcmp(key, "game") == 0) { m_HadGame = true; if (DoesGameMatch(value)) { m_MatchedGame = true; } if ((!m_HadEngine && m_MatchedGame) || (m_MatchedEngine && m_MatchedGame)) { m_ShouldBeReadingDefault = true; } } else if (strcmp(key, "engine") == 0) { m_HadEngine = true; if (DoesEngineMatch(value)) { m_MatchedEngine = true; } if ((!m_HadGame && m_MatchedEngine) || (m_MatchedGame && m_MatchedEngine)) { m_ShouldBeReadingDefault = true; } } break; } case PSTATE_GAMEDEFS_SIGNATURES_SIG: { if (g_LibSys.IsPlatformCompatible(key, &m_MatchedPlatform)) { strncopy(TempSig.signature, value, sizeof(TempSig.signature)); } else if (strcmp(key, "library") == 0) { strncopy(TempSig.library, value, sizeof(TempSig.library)); } break; } case PSTATE_GAMEDEFS_ADDRESSES_ADDRESS: case PSTATE_GAMEDEFS_ADDRESSES_ADDRESS_READ: { if (strcmp(key, "read") == 0) { int limit = sizeof(m_AddressRead) / sizeof(m_AddressRead[0]); if (m_AddressReadCount < limit) { m_AddressRead[m_AddressReadCount] = atoi(value); m_AddressReadCount++; } else { AMXXLOG_Error("[SM] Error parsing Address \"%s\", does not support more than %d read offsets (gameconf \"%s\")", m_Address, limit, m_CurrentPath); } } else if (strcmp(key, "signature") == 0) { strncopy(m_AddressSignature, value, sizeof(m_AddressSignature)); } break; } case PSTATE_GAMEDEFS_CUSTOM: { return m_CustomHandler->ReadSMC_KeyValue(states, key, value); } } return SMCResult_Continue; }
int CPluginMngr::loadPluginsFromFile(const char* filename, bool warn) { char file[PLATFORM_MAX_PATH]; FILE *fp = fopen(build_pathname_r(file, sizeof(file), "%s", filename), "rt"); if (!fp) { if (warn) { AMXXLOG_Error("[AMXX] Plugins list not found (file \"%s\")", filename); } return 1; } // Find now folder char pluginName[256], error[256], debug[256]; int debugFlag = 0; const char *pluginsDir = get_localinfo("amxx_pluginsdir", "addons/amxmodx/plugins"); char line[512]; List<ke::AString *>::iterator block_iter; while (!feof(fp)) { pluginName[0] = '\0'; debug[0] = '\0'; debugFlag = 0; line[0] = '\0'; fgets(line, sizeof(line), fp); /** quick hack */ char *ptr = line; while (*ptr) { if (*ptr == ';') { *ptr = '\0'; } else { ptr++; } } sscanf(line, "%s %s", pluginName, debug); if (!isalnum(*pluginName)) { continue; } if (isalnum(*debug) && !strcmp(debug, "debug")) { debugFlag = 1; } bool skip = false; for (block_iter = m_BlockList.begin(); block_iter != m_BlockList.end(); block_iter++) { if ((*block_iter)->compare(pluginName) == 0) { skip = true; break; } } if (skip || !strcmp(debug, "disabled")) { continue; } if (findPlugin(pluginName) != NULL) { continue; } CPlugin* plugin = loadPlugin(pluginsDir, pluginName, error, sizeof(error), debugFlag); if (plugin->getStatusCode() == ps_bad_load) { char errorMsg[255]; sprintf(errorMsg, "%s (plugin \"%s\")", error, pluginName); plugin->setError(errorMsg); AMXXLOG_Error("[AMXX] %s", plugin->getError()); } else { cell addr; if (amx_FindPubVar(plugin->getAMX(), "MaxClients", &addr) != AMX_ERR_NOTFOUND) { *get_amxaddr(plugin->getAMX(), addr) = gpGlobals->maxClients; } if (amx_FindPubVar(plugin->getAMX(), "MapName", &addr) != AMX_ERR_NOTFOUND) { set_amxstring(plugin->getAMX(), addr, STRING(gpGlobals->mapname), MAX_MAPNAME_LENGTH - 1); } if (amx_FindPubVar(plugin->getAMX(), "NULL_STRING", &addr) != AMX_ERR_NOTFOUND) { plugin->m_pNullStringOfs = get_amxaddr(plugin->getAMX(), addr); } if (amx_FindPubVar(plugin->getAMX(), "NULL_VECTOR", &addr) != AMX_ERR_NOTFOUND) { plugin->m_pNullVectorOfs = get_amxaddr(plugin->getAMX(), addr); } } } fclose(fp); return pCounter; }
const char *translate(AMX *amx, const char *lang, const char *key) { auto pLangName = lang; int status; if (!pLangName || !isalpha(pLangName[0])) { pLangName = amxmodx_language->string; } auto def = g_langMngr.GetDef(pLangName, key, status); if (!amx_mldebug) { amx_mldebug = CVAR_GET_POINTER("amx_mldebug"); } auto debug = (amx_mldebug && amx_mldebug->string && (amx_mldebug->string[0] != '\0')); if (debug) { int debug_status; auto validlang = true; auto testlang = amx_mldebug->string; if (!g_langMngr.LangExists(testlang)) { AMXXLOG_Error("[AMXX] \"%s\" is an invalid debug language", testlang); validlang = false; } g_langMngr.GetDef(testlang, key, debug_status); if (validlang && debug_status == ERR_BADKEY) { AMXXLOG_Error("[AMXX] Language key \"%s\" not found for language \"%s\", check \"%s\"", key, testlang, GetFileName(amx)); } } if (!def) { if (debug && status == ERR_BADLANG) { ke::AString langName(pLangName); auto &err = BadLang_Table.AltFindOrInsert(ke::Move(langName)); if (err.last + 120.0f < gpGlobals->time) { AMXXLOG_Error("[AMXX] Language \"%s\" not found", pLangName); err.last = gpGlobals->time; } } if (strcmp(pLangName, amxmodx_language->string) != 0) { def = g_langMngr.GetDef(amxmodx_language->string, key, status); } if (!def && (strcmp(pLangName, "en") != 0 && strcmp(amxmodx_language->string, "en") != 0)) { def = g_langMngr.GetDef("en", key, status); } } return def; }
SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value) { if (m_IgnoreLevel) { return SMCResult_Continue; } switch (m_ParseState) { case PSTATE_GAMEDEFS_OFFSETS_OFFSET: { if (g_LibSys.IsPlatformCompatible(key, &m_MatchedPlatform)) { if (m_Class[0]) { auto ic = m_OffsetsByClass.findForAdd(m_Class); if (ic.found()) { ic->value->list.replace(m_Offset, atoi(value)); } else if (m_OffsetsByClass.add(ic, m_Class)) { ic->value = new OffsetClass; ic->value->list.insert(m_Offset, atoi(value)); } } else { m_Offsets.replace(m_Offset, atoi(value)); } } break; } case PSTATE_GAMEDEFS_KEYS: { ke::AString vstr(value); m_Keys.replace(key, ke::Move(vstr)); break; } case PSTATE_GAMEDEFS_SUPPORTED: { if (strcmp(key, "game") == 0) { m_HadGame = true; if (DoesGameMatch(value)) { m_MatchedGame = true; } if ((!m_HadEngine && m_MatchedGame) || (m_MatchedEngine && m_MatchedGame)) { m_ShouldBeReadingDefault = true; } } else if (strcmp(key, "engine") == 0) { m_HadEngine = true; if (DoesEngineMatch(value)) { m_MatchedEngine = true; } if ((!m_HadGame && m_MatchedEngine) || (m_MatchedGame && m_MatchedEngine)) { m_ShouldBeReadingDefault = true; } } break; } case PSTATE_GAMEDEFS_SIGNATURES_SIG: { if (g_LibSys.IsPlatformCompatible(key, &m_MatchedPlatform)) { strncopy(TempSig.signature, value, sizeof(TempSig.signature)); } else if (strcmp(key, "library") == 0) { strncopy(TempSig.library, value, sizeof(TempSig.library)); } break; } case PSTATE_GAMEDEFS_ADDRESSES_ADDRESS: case PSTATE_GAMEDEFS_ADDRESSES_ADDRESS_READ: { if (strcmp(key, "read") == 0) { int limit = sizeof(m_AddressRead) / sizeof(m_AddressRead[0]); if (m_AddressReadCount < limit) { m_AddressRead[m_AddressReadCount] = atoi(value); m_AddressReadCount++; } else { AMXXLOG_Error("[SM] Error parsing Address \"%s\", does not support more than %d read offsets (gameconf \"%s\")", m_Address, limit, m_CurrentPath); } } else if (strcmp(key, "signature") == 0) { strncopy(m_AddressSignature, value, sizeof(m_AddressSignature)); } break; } case PSTATE_GAMEDEFS_CUSTOM: { return m_CustomHandler->ReadSMC_KeyValue(states, key, value); } } return SMCResult_Continue; }
int CPluginMngr::loadPluginsFromFile(const char* filename, bool warn) { char file[256]; FILE *fp = fopen(build_pathname_r(file, sizeof(file) - 1, "%s", filename), "rt"); if (!fp) { if (warn) { AMXXLOG_Error("[AMXX] Plugins list not found (file \"%s\")", filename); } return 1; } // Find now folder char pluginName[256], error[256], debug[256]; int debugFlag = 0; const char *pluginsDir = get_localinfo("amxx_pluginsdir", "addons/amxmodx/plugins"); String line; List<String *>::iterator block_iter; while (!feof(fp)) { pluginName[0] = '\0'; debug[0] = '\0'; debugFlag = 0; line.clear(); line._fread(fp); /** quick hack */ char *ptr = const_cast<char *>(line.c_str()); while (*ptr) { if (*ptr == ';') { *ptr = '\0'; } else { ptr++; } } sscanf(line.c_str(), "%s %s", pluginName, debug); if (!isalnum(*pluginName)) { continue; } if (isalnum(*debug) && !strcmp(debug, "debug")) { debugFlag = 1; } bool skip = false; for (block_iter = m_BlockList.begin(); block_iter != m_BlockList.end(); block_iter++) { if ((*block_iter)->compare(pluginName) == 0) { skip = true; break; } } if (skip || !strcmp(debug, "disabled")) { continue; } if (findPlugin(pluginName) != NULL) { continue; } CPlugin* plugin = loadPlugin(pluginsDir, pluginName, error, debugFlag); if (plugin->getStatusCode() == ps_bad_load) { char errorMsg[255]; sprintf(errorMsg, "%s (plugin \"%s\")", error, pluginName); plugin->setError(errorMsg); AMXXLOG_Error("[AMXX] %s", plugin->getError()); } } fclose(fp); return pCounter; }
int CPluginMngr::loadPluginsFromDir(const char* dir, bool debug ){ char pluginName[ 256 ], error[ 256 ], dirFull[ 256 ]; char * ext = 0; #if defined WIN32 build_pathname_r( dirFull , sizeof( dirFull ) , "%s\\*" , dir ); _finddata_t fd; intptr_t handle = _findfirst( dirFull , &fd); if (handle < 0){ return 0; } while (!_findnext(handle, &fd)){ if ( !strcmp ( fd.name , ".") || !strcmp ( fd.name , "..") ){ continue; } ext = strrchr( fd.name, '.' ); if( !ext || strcmp( ext , ".amxx" ) ){ continue; } *ext = '\0'; strncpy( pluginName , fd.name , ext - ( fd.name ) ); pluginName[ ext - ( fd.name ) ] = '\0'; if ( findPlugin( pluginName ) != NULL ){ continue; } CPlugin* plugin = loadPlugin( dir, fd.name, error, debug , pluginName ); if (plugin->getStatusCode() == ps_bad_load){ char errorMsg[255]; sprintf(errorMsg, "%s (plugin \"%s\")", error, pluginName); plugin->setError(errorMsg); AMXXLOG_Error("[AMXX] %s", plugin->getError()); } } _findclose(handle); #elif defined(__linux__) || defined(__APPLE__) build_pathname_r( dirFull , sizeof( dirFull ) , "%s" , dir ); struct dirent *ep; DIR *dp; if (( dp = opendir( dirFull ) ) == NULL ){ return 0; } while ( ( ep = readdir( dp )) != NULL ){ if ( !strcmp ( ep -> d_name , ".") || !strcmp ( ep -> d_name , "..") ){ continue; } ext = strrchr( ep -> d_name, '.' ); if( !ext || strcmp( ext , ".amxx" ) ){ continue; } strncpy( pluginName , ep -> d_name , ext - ( ep -> d_name ) ); pluginName[ ext - ( ep -> d_name ) ] = '\0'; if ( findPlugin( pluginName ) != NULL ){ continue; } CPlugin* plugin = loadPlugin( dir, ep -> d_name, error, debug , pluginName ); if (plugin->getStatusCode() == ps_bad_load){ char errorMsg[255]; sprintf(errorMsg, "%s (plugin \"%s\")", error, pluginName); plugin->setError(errorMsg); AMXXLOG_Error("[AMXX] %s", plugin->getError()); } } closedir (dp); #endif return pCounter; }
int Handler::HandleError(const char *msg) { if (m_iErrFunc <= 0) return 0; m_Handling = true; m_pTrace = NULL; m_FmtCache.clear(); Debugger *pDebugger = (Debugger *)m_pAmx->userdata[UD_DEBUGGER]; int error = m_pAmx->error; static char _buffer[512]; if (pDebugger) { pDebugger->SetTracedError(error); m_pTrace = pDebugger->GetTraceStart(); pDebugger->FormatError(_buffer, sizeof(_buffer)-1); m_FmtCache.assign(_buffer); pDebugger->BeginExec(); } else { Debugger::FmtGenericMsg(m_pAmx, error, _buffer, sizeof(_buffer)-1); m_FmtCache.assign(_buffer); } SetErrorMsg(msg); cell hea_addr, *phys_addr, result; amx_PushString(m_pAmx, &hea_addr, &phys_addr, msg, 0, 0); amx_Push(m_pAmx, pDebugger ? 1 : 0); amx_Push(m_pAmx, error); int err = amx_Exec(m_pAmx, &result, m_iErrFunc); if (err != AMX_ERR_NONE) { //handle this manually. if (pDebugger) { pDebugger->SetTracedError(err); pDebugger->DisplayTrace(msg); } else { if (GetLastMsg()) AMXXLOG_Error("%s", GetLastMsg()); Debugger::GenericMessage(m_pAmx, err); } AMXXLOG_Error("[AMXX] NOTE: Runtime failures in an error filter are not good!"); } if (pDebugger) pDebugger->EndExec(); amx_Release(m_pAmx, hea_addr); m_Handling = false; m_pTrace = NULL; m_FmtCache.clear(); if (err != AMX_ERR_NONE || !result) return 0; return result; }
int Handler::HandleNative(const char *native, int index, int trap) { if (!IsNativeFiltering()) return 0; /** * Our handler here is a bit different from HandleError(). * For one, there is no current error in pDebugger, so we * don't have to save some states. */ m_InNativeFilter = true; Debugger *pDebugger = (Debugger *)m_pAmx->userdata[UD_DEBUGGER]; if (pDebugger && trap) pDebugger->BeginExec(); else if (pDebugger && !trap) DisableDebugHandler(m_pAmx); cell hea_addr, *phys_addr, retval; if (!trap) m_pAmx->flags |= AMX_FLAG_PRENIT; amx_Push(m_pAmx, trap); amx_Push(m_pAmx, index); amx_PushString(m_pAmx, &hea_addr, &phys_addr, native, 0, 0); int err = amx_Exec(m_pAmx, &retval, m_iNatFunc); if (err != AMX_ERR_NONE) { //LogError() took care of something for us. if (err == -1) { m_InNativeFilter = false; amx_Release(m_pAmx, hea_addr); return 1; } if (!trap) { AMXXLOG_Error("[AMXX] Runtime failure %d occurred in native filter. Aborting plugin load.", err); return 0; } //handle this manually. //we need to push this through an error filter, same as executeForwards! if (pDebugger && pDebugger->ErrorExists()) { //don't display, it was already handled. } else if (err != -1) { LogError(m_pAmx, err, NULL); } AMXXLOG_Error("[AMXX] NOTE: Runtime failures in native filters are not good!"); retval = 0; } if (!trap) m_pAmx->flags &= ~AMX_FLAG_PRENIT; if (pDebugger && trap) pDebugger->EndExec(); else if (pDebugger && !trap) EnableDebugHandler(m_pAmx, pDebugger); amx_Release(m_pAmx, hea_addr); m_InNativeFilter = false; return (int)retval; }