void TraceManager::load_plugins() { // Initialize all trace needs to false trace_needs = 0; if (init_factories) return; MutexLockGuard guard(init_factories_mtx, FB_FUNCTION); if (init_factories) return; init_factories = true; factories = FB_NEW(*getDefaultMemoryPool()) TraceManager::Factories(*getDefaultMemoryPool()); for (GetPlugins<ITraceFactory> traceItr(IPluginManager::Trace); traceItr.hasData(); traceItr.next()) { FactoryInfo info; info.factory = traceItr.plugin(); info.factory->addRef(); string name(traceItr.name()); name.copyTo(info.name, sizeof(info.name)); factories->add(info); } }
Switches::Switches(const in_sw_tab_t* table, size_t count, bool copy, bool minLength) : m_base(table), m_count(count), m_copy(copy), m_minLength(minLength), m_table(0), m_opLengths(0) { fb_assert(table && count > 1); // the last element is a terminator if (!table || count < 2) complain("Switches: invalid arguments for constructor"); if (m_copy) { m_table = FB_NEW(*getDefaultMemoryPool()) in_sw_tab_t[m_count]; for (size_t iter = 0; iter < m_count; ++iter) m_table[iter] = m_base[iter]; } m_opLengths = FB_NEW(*getDefaultMemoryPool()) size_t[m_count]; for (size_t iter = 0; iter < m_count; ++iter) { if (m_base[iter].in_sw_name) { m_opLengths[iter] = strlen(m_base[iter].in_sw_name); fb_assert(m_opLengths[iter] > 0); fb_assert(!m_minLength || m_opLengths[iter] >= m_base[iter].in_sw_min_length); } else m_opLengths[iter] = 0; } }
ModuleLoader::Module* ModuleLoader::loadModule(ISC_STATUS* status, const Firebird::PathName& modPath) { void* module = dlopen(modPath.nullStr(), FB_RTLD_MODE); if (module == NULL) { if (status) { status[0] = isc_arg_gds; status[1] = isc_random; status[2] = isc_arg_string; status[3] = (ISC_STATUS) dlerror(); status[4] = isc_arg_end; } return 0; } #ifdef DEBUG_THREAD_IN_UNLOADED_LIBRARY Firebird::string command; command.printf("echo +++ %s +++ >>/tmp/fbmaps;date >> /tmp/fbmaps;cat /proc/%d/maps >>/tmp/fbmaps", modPath.c_str(), getpid()); system(command.c_str()); #endif return FB_NEW_POOL(*getDefaultMemoryPool()) DlfcnModule(*getDefaultMemoryPool(), modPath, module); }
ServerAuth::ServerAuth(const char* fName, int fLen, const Firebird::ClumpletWriter& pb, ServerAuth::Part2* p2, P_OP op) : fileName(*getDefaultMemoryPool()), clumplet(*getDefaultMemoryPool()), part2(p2), operation(op) { fileName.assign(fName, fLen); size_t pbLen = pb.getBufferLength(); if (pbLen) { memcpy(clumplet.getBuffer(pbLen), pb.getBuffer(), pbLen); } authSspi = FB_NEW(*getDefaultMemoryPool()) AuthSspi; }
// Transform ICU-VERSION attribute (given by the user) in COLL-VERSION (to be stored). bool IntlUtil::setupIcuAttributes(charset* cs, const string& specificAttributes, const string& configInfo, string& newSpecificAttributes) { AutoPtr<Jrd::CharSet> charSet(Jrd::CharSet::createInstance(*getDefaultMemoryPool(), 0, cs)); IntlUtil::SpecificAttributesMap map; if (!IntlUtil::parseSpecificAttributes(charSet, specificAttributes.length(), (const UCHAR*) specificAttributes.begin(), &map)) { return false; } string icuVersion; map.get("ICU-VERSION", icuVersion); string collVersion; if (!UnicodeUtil::getCollVersion(icuVersion, configInfo, collVersion)) return false; map.remove("ICU-VERSION"); map.remove("COLL-VERSION"); if (collVersion.hasData()) map.put("COLL-VERSION", collVersion); newSpecificAttributes = IntlUtil::generateSpecificAttributes(charSet, map); return true; }
void TraceSvcUtil::startSession(TraceSession& session, bool /*interactive*/) { m_stop = false; HalfStaticArray<UCHAR, 1024> buff(*getDefaultMemoryPool()); UCHAR* p = NULL; long len = 0; FILE* file = NULL; try { const char* fileName = session.ses_config.c_str(); file = fopen(fileName, "rb"); if (!file) { (Arg::Gds(isc_io_error) << Arg::Str("fopen") << Arg::Str(fileName) << Arg::Gds(isc_io_open_err) << Arg::OsError()).raise(); } fseek(file, 0, SEEK_END); len = ftell(file); if (len == 0) { (Arg::Gds(isc_io_error) << Arg::Str("fread") << Arg::Str(fileName) << Arg::Gds(isc_io_read_err) << Arg::OsError()).raise(); } fseek(file, 0, SEEK_SET); p = buff.getBuffer(len); if (fread(p, 1, len, file) != size_t(len)) { (Arg::Gds(isc_io_error) << Arg::Str("fread") << Arg::Str(fileName) << Arg::Gds(isc_io_read_err) << Arg::OsError()).raise(); } fclose(file); } catch (const Exception&) { if (file) fclose(file); throw; } ClumpletWriter spb(ClumpletWriter::SpbStart, MAXBUF); spb.insertTag(isc_action_svc_trace_start); spb.insertBytes(isc_spb_trc_cfg, p, len); if (session.ses_name.hasData()) { spb.insertBytes(isc_spb_trc_name, reinterpret_cast<const UCHAR*> (session.ses_name.c_str()), session.ses_name.length()); } runService(spb.getBufferLength(), spb.getBuffer()); }
Config::Config(const ConfigFile& file) : notifyDatabase(*getDefaultMemoryPool()) { // Array to save string temporarily // Will be finally saved by loadValues() in the end of ctor Firebird::ObjectsArray<ConfigFile::String> tempStrings(getPool()); // Iterate through the known configuration entries for (unsigned int i = 0; i < MAX_CONFIG_KEY; i++) { values[i] = entries[i].default_value; if (entries[i].data_type == TYPE_STRING && values[i]) { ConfigFile::String expand((const char*)values[i]); if (file.macroParse(expand, NULL) && expand != (const char*) values[i]) { ConfigFile::String& saved(tempStrings.add()); saved = expand; values[i] = (ConfigValue) saved.c_str(); } } } loadValues(file); }
TraceManager::TraceManager(const char* in_filename) : attachment(NULL), service(NULL), filename(in_filename), trace_sessions(*getDefaultMemoryPool()) { init(); }
AuthSspi::AuthSspi() : hasContext(false), ctName(*getDefaultMemoryPool()), wheel(false) { TimeStamp timeOut; hasCredentials = initEntries() && (fAcquireCredentialsHandle(0, "NTLM", SECPKG_CRED_BOTH, 0, 0, 0, 0, &secHndl, &timeOut) == SEC_E_OK); }
StatusVector::ImplStatusVector::ImplStatusVector(const Exception& ex) throw() : Base::ImplBase(0, 0), m_status_vector(*getDefaultMemoryPool()) { clear(); assign(ex); }
MemoryPool* MemoryPool::createPool(MemoryPool* parentPool, MemoryStats& stats) { if (!parentPool) { parentPool = getDefaultMemoryPool(); } return FB_NEW(*parentPool) MemoryPool(*parentPool, stats); }
THREAD_ENTRY_DECLARE swap_icons(THREAD_ENTRY_PARAM param) { /****************************************************************************** * * S w a p I c o n s * ****************************************************************************** * * Description: Animates the icon if the server restarted *****************************************************************************/ Firebird::ContextPoolHolder threadContext(getDefaultMemoryPool()); HWND hWnd = static_cast<HWND>(param); HINSTANCE hInstance = (HINSTANCE) GetWindowLongPtr(hWnd, GWLP_HINSTANCE); HICON hIconNormal = (HICON) LoadImage(hInstance, MAKEINTRESOURCE(IDI_IBGUARD), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR); HICON hIconAlert = (HICON) LoadImage(hInstance, MAKEINTRESOURCE(IDI_IBGUARDALRT), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR); NOTIFYICONDATA nidNormal; nidNormal.cbSize = sizeof(NOTIFYICONDATA); nidNormal.hWnd = hWnd; nidNormal.uID = IDI_IBGUARD; nidNormal.uFlags = NIF_ICON; nidNormal.hIcon = hIconNormal; NOTIFYICONDATA nidAlert; nidAlert.cbSize = sizeof(NOTIFYICONDATA); nidAlert.hWnd = hWnd; nidAlert.uID = IDI_IBGUARD; nidAlert.uFlags = NIF_ICON; nidAlert.hIcon = hIconAlert; // Animate until the property sheet is displayed. Once the property sheet is // displayed, stop animating the icon while (!hPSDlg) { if (!Shell_NotifyIcon(NIM_MODIFY, &nidAlert)) SetClassLongPtr(hWnd, GCLP_HICON, (LONG_PTR) hIconAlert); Sleep(500); if (!Shell_NotifyIcon(NIM_MODIFY, &nidNormal)) SetClassLongPtr(hWnd, GCLP_HICON, (LONG_PTR) hIconNormal); Sleep(500); } // Make sure that the icon is normal if (!Shell_NotifyIcon(NIM_MODIFY, &nidNormal)) SetClassLongPtr(hWnd, GCLP_HICON, (LONG_PTR) hIconNormal); if (hIconNormal) DestroyIcon(hIconNormal); if (hIconAlert) DestroyIcon(hIconAlert); return 0; }
void TraceManager::update_sessions() { SortedArray<ULONG> liveSessions(*getDefaultMemoryPool()); { // scope ConfigStorage* storage = getStorage(); StorageGuard guard(storage); storage->restart(); TraceSession session(*getDefaultMemoryPool()); while (storage->getNextSession(session)) { if ((session.ses_flags & trs_active) && !(session.ses_flags & trs_log_full)) { update_session(session); liveSessions.add(session.ses_id); } } changeNumber = storage->getChangeNumber(); } // remove sessions not present in storage FB_SIZE_T i = 0; while (i < trace_sessions.getCount()) { FB_SIZE_T pos; if (liveSessions.find(trace_sessions[i].ses_id, pos)) { i++; } else { trace_sessions[i].plugin->release(); trace_sessions.remove(i); } } // nothing to trace, clear needs if (trace_sessions.getCount() == 0) { trace_needs = 0; } }
void PortsCleanup::registerPort(rem_port* port) { Firebird::MutexLockGuard guard(m_mutex, FB_FUNCTION); if (!m_ports) { Firebird::MemoryPool& pool = *getDefaultMemoryPool(); m_ports = FB_NEW_POOL (pool) PortsArray(pool); } m_ports->add(port); }
Config::Config(const ConfigFile& file, const Config& base) : notifyDatabase(*getDefaultMemoryPool()) { // Iterate through the known configuration entries for (unsigned int i = 0; i < MAX_CONFIG_KEY; i++) { values[i] = base.values[i]; } loadValues(file); }
StatusVector::ImplStatusVector::ImplStatusVector(const ISC_STATUS* s) throw() : Base::ImplBase(0, 0), m_status_vector(*getDefaultMemoryPool()) { fb_assert(s); clear(); // special case - empty initialized status vector, no warnings if (s[0] != isc_arg_gds || s[1] != 0 || s[2] != 0) append(s); }
StatusVector::ImplStatusVector::ImplStatusVector(const IStatus* s) throw() : Base::ImplBase(0, 0), m_status_vector(*getDefaultMemoryPool()) { fb_assert(s); clear(); if (s->getState() & IStatus::STATE_ERRORS) append(s->getErrors()); if (s->getState() & IStatus::STATE_WARNINGS) append(s->getWarnings()); }
ModuleLoader::Module* ModuleLoader::loadModule(const Firebird::PathName& modPath) { void* module = dlopen(modPath.c_str(), FB_RTLD_MODE); if (module == NULL) { #ifdef DEBUG_LOADER fprintf(stderr, "load error: %s: %s\n", modPath.c_str(), dlerror()); #endif // DEBUG_LOADER return 0; } return FB_NEW_POOL(*getDefaultMemoryPool()) DlfcnModule(module); }
PublicHandle::PublicHandle() : RefPtr<ExistenceMutex>(FB_NEW(*getDefaultMemoryPool()) ExistenceMutex) { WriteLockGuard guard(sync); if (handles->exist(this)) { fb_assert(false); } else { handles->add(this); } }
PathName TempFile::create(CheckStatusWrapper* status, const PathName& prefix, const PathName& directory) { PathName filename; try { TempFile file(*getDefaultMemoryPool(), prefix, directory, false); filename = file.getName(); } catch (const Exception& ex) { if (status) { ex.stuffException(status); } } return filename; }
ModuleLoader::Module* ModuleLoader::loadModule(const Firebird::PathName& modPath) { void* module = dlopen(modPath.nullStr(), FB_RTLD_MODE); if (module == NULL) { #ifdef DEV_BUILD // gds__log("loadModule failed loading %s: %s", modPath.c_str(), dlerror()); #endif return 0; } #ifdef DEBUG_THREAD_IN_UNLOADED_LIBRARY Firebird::string command; command.printf("echo +++ %s +++ >>/tmp/fbmaps;date >> /tmp/fbmaps;cat /proc/%d/maps >>/tmp/fbmaps", modPath.c_str(), getpid()); system(command.c_str()); #endif return FB_NEW_POOL(*getDefaultMemoryPool()) DlfcnModule(module); }
rem_str* REMOTE_make_string(const SCHAR* input) { /************************************** * * R E M O T E _ m a k e _ s t r i n g * ************************************** * * Functional description * Copy a given string to a permanent location, returning * address of new string. * **************************************/ const USHORT length = static_cast<USHORT>(strlen(input)); rem_str* string = FB_NEW_RPT(*getDefaultMemoryPool(), length) rem_str; #ifdef DEBUG_REMOTE_MEMORY printf("REMOTE_make_string allocate string %x\n", string); #endif strcpy(string->str_data, input); string->str_length = length; return string; }
void fbtrace(UtilSvc* uSvc, TraceSvcIntf* traceSvc) { const char* const* end = uSvc->argv.end(); bool version = false, help = false; // search for "action" switch, set NULL into recognized argv const Switches actSwitches(trace_action_in_sw_table, FB_NELEM(trace_action_in_sw_table), false, true); const Switches::in_sw_tab_t* action_sw = NULL; const char** argv = uSvc->argv.begin(); for (++argv; argv < end; argv++) { if (!uSvc->isService() && strcmp(argv[0], "-?") == 0) { help = true; *argv = NULL; break; } const Switches::in_sw_tab_t* sw = actSwitches.findSwitch(*argv); if (sw) { if (sw->in_sw == IN_SW_TRACE_VERSION) { version = true; *argv = NULL; continue; } if (action_sw) usage(uSvc, isc_trace_conflict_acts, action_sw->in_sw_name, sw->in_sw_name); else action_sw = sw; *argv = NULL; } } if (version) { printMsg(1, SafeArg() << FB_VERSION); if (!action_sw) exit(FINI_OK); } if (!action_sw) { if (help) usage(uSvc, 0); else usage(uSvc, isc_trace_act_notfound); } // search for action's parameters, set NULL into recognized argv const Switches optSwitches(trace_option_in_sw_table, FB_NELEM(trace_option_in_sw_table), false, true); TraceSession session(*getDefaultMemoryPool()); argv = uSvc->argv.begin(); for (++argv; argv < end; argv++) { if (!*argv) continue; const Switches::in_sw_tab_t* sw = optSwitches.findSwitch(*argv); if (!sw) continue; *argv = NULL; switch (sw->in_sw) { case IN_SW_TRACE_CONFIG: switch (action_sw->in_sw) { case IN_SW_TRACE_STOP: case IN_SW_TRACE_SUSPEND: case IN_SW_TRACE_RESUME: case IN_SW_TRACE_LIST: usage(uSvc, isc_trace_param_act_notcompat, sw->in_sw_name, action_sw->in_sw_name); break; } if (!session.ses_config.empty()) usage(uSvc, isc_trace_switch_once, sw->in_sw_name); argv++; if (argv < end && *argv) session.ses_config = *argv; else usage(uSvc, isc_trace_param_val_miss, sw->in_sw_name); break; case IN_SW_TRACE_NAME: switch (action_sw->in_sw) { case IN_SW_TRACE_STOP: case IN_SW_TRACE_SUSPEND: case IN_SW_TRACE_RESUME: case IN_SW_TRACE_LIST: usage(uSvc, isc_trace_param_act_notcompat, sw->in_sw_name, action_sw->in_sw_name); break; } if (!session.ses_name.empty()) usage(uSvc, isc_trace_switch_once, sw->in_sw_name); argv++; if (argv < end && *argv) session.ses_name = *argv; else usage(uSvc, isc_trace_param_val_miss, sw->in_sw_name); break; case IN_SW_TRACE_ID: switch (action_sw->in_sw) { case IN_SW_TRACE_START: case IN_SW_TRACE_LIST: usage(uSvc, isc_trace_param_act_notcompat, sw->in_sw_name, action_sw->in_sw_name); break; } if (session.ses_id) usage(uSvc, isc_trace_switch_once, sw->in_sw_name); argv++; if (argv < end && *argv) { session.ses_id = atol(*argv); if (!session.ses_id) usage(uSvc, isc_trace_param_invalid, *argv, sw->in_sw_name); } else usage(uSvc, isc_trace_param_val_miss, sw->in_sw_name); break; default: fb_assert(false); } *argv = NULL; } // search for authentication parameters const Switches authSwitches(trace_auth_in_sw_table, FB_NELEM(trace_auth_in_sw_table), false, true); string svc_name, user, pwd; bool adminRole = false; argv = uSvc->argv.begin(); for (++argv; argv < end; argv++) { if (!*argv) continue; const Switches::in_sw_tab_t* sw = authSwitches.findSwitch(*argv); if (!sw) { usage(uSvc, isc_trace_switch_unknown, *argv); } switch (sw->in_sw) { case IN_SW_TRACE_USERNAME: if (!user.empty()) usage(uSvc, isc_trace_switch_once, sw->in_sw_name); argv++; if (argv < end && *argv) user = *argv; else usage(uSvc, isc_trace_param_val_miss, sw->in_sw_name); break; case IN_SW_TRACE_PASSWORD: if (!pwd.empty()) usage(uSvc, isc_trace_switch_once, sw->in_sw_name); argv++; if (argv < end && *argv) pwd = *argv; else usage(uSvc, isc_trace_param_val_miss, sw->in_sw_name); break; case IN_SW_TRACE_FETCH_PWD: if (uSvc->isService()) usage(uSvc, isc_trace_switch_user_only, sw->in_sw_name); if (!pwd.empty()) usage(uSvc, isc_trace_switch_once, sw->in_sw_name); argv++; if (argv < end && *argv) { const PathName fileName(*argv); const char *s = NULL; switch (fb_utils::fetchPassword(fileName, s)) { case fb_utils::FETCH_PASS_OK: pwd = s; break; case fb_utils::FETCH_PASS_FILE_OPEN_ERROR: (Arg::Gds(isc_io_error) << Arg::Str("open") << Arg::Str(fileName) << Arg::Gds(isc_io_open_err) << Arg::OsError()).raise(); break; case fb_utils::FETCH_PASS_FILE_READ_ERROR: case fb_utils::FETCH_PASS_FILE_EMPTY: (Arg::Gds(isc_io_error) << Arg::Str("read") << Arg::Str(fileName) << Arg::Gds(isc_io_read_err) << Arg::OsError()).raise(); break; } } else usage(uSvc, isc_trace_param_val_miss, sw->in_sw_name); break; case IN_SW_TRACE_TRUSTED_AUTH: if (uSvc->isService()) usage(uSvc, isc_trace_switch_user_only, sw->in_sw_name); adminRole = true; break; case IN_SW_TRACE_SERVICE_NAME: if (uSvc->isService()) continue; if (!svc_name.empty()) usage(uSvc, isc_trace_switch_once, sw->in_sw_name); argv++; if (argv < end && *argv) svc_name = *argv; else usage(uSvc, isc_trace_param_val_miss, sw->in_sw_name); break; default: fb_assert(false); } } // validate missed action's parameters and perform action if (!uSvc->isService() && svc_name.isEmpty()) { usage(uSvc, isc_trace_mandatory_switch_miss, "SERVICE"); } if (!session.ses_id) { switch (action_sw->in_sw) { case IN_SW_TRACE_STOP: case IN_SW_TRACE_SUSPEND: case IN_SW_TRACE_RESUME: usage(uSvc, isc_trace_switch_param_miss, "ID", action_sw->in_sw_name); break; } } if (session.ses_config.empty()) { if (action_sw->in_sw == IN_SW_TRACE_START) { usage(uSvc, isc_trace_switch_param_miss, "CONFIG", action_sw->in_sw_name); } } AuthReader::AuthBlock authBlock; const unsigned char* bytes; unsigned int authBlockSize = uSvc->getAuthBlock(&bytes); if (authBlockSize) { authBlock.add(bytes, authBlockSize); pwd = ""; user = ""; adminRole = false; } traceSvc->setAttachInfo(svc_name, user, pwd, authBlock, adminRole); switch (action_sw->in_sw) { case IN_SW_TRACE_START: traceSvc->startSession(session, true); break; case IN_SW_TRACE_STOP: traceSvc->stopSession(session.ses_id); break; case IN_SW_TRACE_SUSPEND: traceSvc->setActive(session.ses_id, false); break; case IN_SW_TRACE_RESUME: traceSvc->setActive(session.ses_id, true); break; case IN_SW_TRACE_LIST: traceSvc->listSessions(); break; default: fb_assert(false); } }
void Config::setRootDirectoryFromCommandLine(const Firebird::PathName& newRoot) { delete rootFromCommandLine; rootFromCommandLine = FB_NEW(*getDefaultMemoryPool()) Firebird::PathName(*getDefaultMemoryPool(), newRoot); }
WriterImplementation::WriterImplementation() : current(*getDefaultMemoryPool(), ClumpletReader::WideUnTagged, MAX_DPB_SIZE), result(*getDefaultMemoryPool(), ClumpletReader::WideUnTagged, MAX_DPB_SIZE), method(*getDefaultMemoryPool()), sequence(0) { }
int CLIB_ROUTINE main( int argc, char** argv) { /************************************** * * m a i n * ************************************** * * Functional description * Run the server with apollo mailboxes. * **************************************/ try { RemPortPtr port; // We should support 3 modes: // 1. Standalone single-process listener (like SS). // 2. Standalone listener, forking on each packet accepted (look -s switch in CS). // 3. Process spawned by (x)inetd (like CS). bool classic = false; bool standaloneClassic = false; bool super = false; // It's very easy to detect that we are spawned - just check fd 0 to be a socket. const int channel = 0; struct stat stat0; if (fstat(channel, &stat0) == 0 && S_ISSOCK(stat0.st_mode)) { // classic server mode classic = true; } const TEXT* const* const end = argc + argv; argv++; bool debug = false; USHORT INET_SERVER_flag = 0; protocol[0] = 0; bool done = false; while (argv < end) { TEXT c; const TEXT* p = *argv++; if (*p++ == '-') { while (c = *p++) { switch (UPPER(c)) { case 'D': debug = true; break; case 'E': if (argv < end) { if (ISC_set_prefix(p, *argv) == -1) printf("Invalid argument Ignored\n"); else argv++; // do not skip next argument if this one is invalid } else { printf("Missing argument, switch -E ignored\n"); } done = true; break; case 'P': if (argv < end) { if (!classic) { fb_utils::snprintf(protocol, sizeof(protocol), "/%s", *argv++); } else { gds__log("Switch -P ignored in CS mode\n"); } } else { printf("Missing argument, switch -P ignored\n"); } break; case 'H': case '?': printf("Firebird TCP/IP server options are:\n"); printf(" -d : debug on\n"); printf(" -p <port> : specify port to listen on\n"); printf(" -z : print version and exit\n"); printf(" -h|? : print this help\n"); printf("\n"); printf(" (The following -e options used to be -h options)\n"); printf(" -e <firebird_root_dir> : set firebird_root path\n"); printf(" -el <firebird_lock_dir> : set runtime firebird_lock dir\n"); printf(" -em <firebird_msg_dir> : set firebird_msg dir path\n"); exit(FINI_OK); case 'Z': printf("Firebird TCP/IP server version %s\n", FB_VERSION); exit(FINI_OK); default: printf("Unknown switch '%c', ignored\n", c); break; } if (done) break; } } } if (Config::getServerMode() == MODE_CLASSIC) { if (!classic) standaloneClassic = true; } else { if (classic) { gds__log("Server misconfigured - to start it from (x)inetd add ServerMode=Classic to firebird.conf"); Firebird::Syslog::Record(Firebird::Syslog::Error, "Server misconfigured - add ServerMode=Classic to firebird.conf"); exit(STARTUP_ERROR); } INET_SERVER_flag |= SRVR_multi_client; super = true; } { // scope Firebird::MasterInterfacePtr master; master->serverMode(super ? 1 : 0); } if (debug) { INET_SERVER_flag |= SRVR_debug; } // activate paths set with -e family of switches ISC_set_prefix(0, 0); // ignore some signals set_signal(SIGPIPE, signal_handler); set_signal(SIGUSR1, signal_handler); set_signal(SIGUSR2, signal_handler); // First of all change directory to tmp if (chdir(TEMP_DIR)) { // error on changing the directory gds__log("Could not change directory to %s due to errno %d", TEMP_DIR, errno); } #ifdef FB_RAISE_LIMITS #ifdef RLIMIT_NPROC raiseLimit(RLIMIT_NPROC); #endif #if !(defined(DEV_BUILD)) if (Config::getBugcheckAbort()) #endif { // try to force core files creation raiseLimit(RLIMIT_CORE); } #if (defined SOLARIS || defined HPUX || defined LINUX) if (super) { // Increase max open files to hard limit for Unix // platforms which are known to have low soft limits. raiseLimit(RLIMIT_NOFILE); } #endif // Unix platforms #endif // FB_RAISE_LIMITS #ifdef HAVE_LOCALE_H // Pick up the system locale to allow SYSTEM<->UTF8 conversions inside the engine setlocale(LC_CTYPE, ""); #endif if (!(debug || classic)) { int mask = 0; // FD_ZERO(&mask); mask |= 1 << 2; // FD_SET(2, &mask); divorce_terminal(mask); } // check firebird.conf presence - must be for server if (Config::missFirebirdConf()) { Firebird::Syslog::Record(Firebird::Syslog::Error, "Missing master config file firebird.conf"); exit(STARTUP_ERROR); } if (super || standaloneClassic) { try { port = INET_connect(protocol, 0, INET_SERVER_flag, 0, NULL); } catch (const Firebird::Exception& ex) { iscLogException("startup:INET_connect:", ex); Firebird::StaticStatusVector st; ex.stuffException(st); gds__print_status(st.begin()); exit(STARTUP_ERROR); } } if (classic) { port = INET_server(channel); if (!port) { gds__log("Unable to start INET_server"); Firebird::Syslog::Record(Firebird::Syslog::Error, "Unable to start INET_server"); exit(STARTUP_ERROR); } } { // scope for interface ptr Firebird::PluginManagerInterfacePtr pi; Auth::registerSrpServer(pi); } if (super) { // Server tries to attach to security2.fdb to make sure everything is OK // This code fixes bug# 8429 + all other bug of that kind - from // now on the server exits if it cannot attach to the database // (wrong or no license, not enough memory, etc. ISC_STATUS_ARRAY status; isc_db_handle db_handle = 0L; const Firebird::RefPtr<Config> defConf(Config::getDefaultConfig()); const char* path = defConf->getSecurityDatabase(); const char dpb[] = {isc_dpb_version1, isc_dpb_sec_attach, 1, 1, isc_dpb_address_path, 0}; isc_attach_database(status, strlen(path), path, &db_handle, sizeof dpb, dpb); if (status[0] == 1 && status[1] > 0) { logSecurityDatabaseError(path, status); } isc_detach_database(status, &db_handle); if (status[0] == 1 && status[1] > 0) { logSecurityDatabaseError(path, status); } } // end scope fb_shutdown_callback(NULL, closePort, fb_shut_exit, port); SRVR_multi_thread(port, INET_SERVER_flag); #ifdef DEBUG_GDS_ALLOC // In Debug mode - this will report all server-side memory leaks due to remote access Firebird::PathName name = fb_utils::getPrefix( Firebird::IConfigManager::DIR_LOG, "memdebug.log"); FILE* file = os_utils::fopen(name.c_str(), "w+t"); if (file) { fprintf(file, "Global memory pool allocated objects\n"); getDefaultMemoryPool()->print_contents(file); fclose(file); } #endif // perform atexit shutdown here when all globals in embedded library are active // also sync with possibly already running shutdown in dedicated thread fb_shutdown(10000, fb_shutrsn_exit_called); return FINI_OK; } catch (const Firebird::Exception& ex) { Firebird::StaticStatusVector st; ex.stuffException(st); char s[100]; const ISC_STATUS* status = st.begin(); fb_interpret(s, sizeof(s), &status); iscLogException("Firebird startup error:", ex); Firebird::Syslog::Record(Firebird::Syslog::Error, "Firebird startup error"); Firebird::Syslog::Record(Firebird::Syslog::Error, s); exit(STARTUP_ERROR); } }
THREAD_ENTRY_DECLARE start_and_watch_server(THREAD_ENTRY_PARAM) { /************************************** * * s t a r t _ a n d _ w a t c h _ s e r v e r * ************************************** * * Functional description * * This function is where the server process is created and * the thread waits for this process to exit. * **************************************/ Firebird::ContextPoolHolder threadContext(getDefaultMemoryPool()); HANDLE procHandle = NULL; bool done = true; const UINT error_mode = SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX | SEM_NOALIGNMENTFAULTEXCEPT; SC_HANDLE hScManager = 0, hService = 0; // get the guardian startup information const short option = Config::getGuardianOption(); char prefix_buffer[MAXPATHLEN]; GetModuleFileName(NULL, prefix_buffer, sizeof(prefix_buffer)); Firebird::PathName path = prefix_buffer; path = path.substr(0, path.rfind(PathUtils::dir_sep) + 1) + FBSERVER; path = "\"" + path + "\""; Firebird::PathName prog_name = path + " -a -n"; // if the guardian is set to FOREVER then set the error mode UINT old_error_mode = 0; if (option == START_FOREVER) old_error_mode = SetErrorMode(error_mode); // Spawn the new process do { SERVICE_STATUS ServiceStatus; char out_buf[1024]; BOOL success; int error = 0; if (service_flag) { if (hService) { while ((QueryServiceStatus(hService, &ServiceStatus) == TRUE) && (ServiceStatus.dwCurrentState != SERVICE_STOPPED)) { Sleep(500); } } procHandle = CreateMutex(NULL, FALSE, mutex_name->c_str()); // start as a service. If the service can not be found or // fails to start, close the handle to the mutex and set // success = FALSE if (!hScManager) hScManager = OpenSCManager(NULL, NULL, GENERIC_READ); if (!hService) { hService = OpenService(hScManager, remote_name->c_str(), GENERIC_READ | GENERIC_EXECUTE); } success = StartService(hService, 0, NULL); if (success != TRUE) error = GetLastError(); // if the server is already running, then inform it that it should // open the guardian mutex so that it may be governed. if (!error || error == ERROR_SERVICE_ALREADY_RUNNING) { // Make sure that it is actually ready to receive commands. // If we were the one who started it, then it will need a few // seconds to get ready. while ((QueryServiceStatus(hService, &ServiceStatus) == TRUE) && (ServiceStatus.dwCurrentState != SERVICE_RUNNING)) { Sleep(500); } ControlService(hService, SERVICE_CREATE_GUARDIAN_MUTEX, &ServiceStatus); success = TRUE; } } else { HWND hTmpWnd = FindWindow(szClassName, szWindowName); if (hTmpWnd == NULL) { STARTUPINFO si; SECURITY_ATTRIBUTES sa; PROCESS_INFORMATION pi; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; success = CreateProcess(NULL, const_cast<char*>(prog_name.c_str()), &sa, NULL, FALSE, 0, NULL, NULL, &si, &pi); if (success != TRUE) error = GetLastError(); procHandle = pi.hProcess; // TMN: 04 Aug 2000 - closed the handle that previously leaked. CloseHandle(pi.hThread); } else { SendMessage(hTmpWnd, WM_COMMAND, (WPARAM) IDM_GUARDED, 0); DWORD server_pid; GetWindowThreadProcessId(hTmpWnd, &server_pid); procHandle = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION, FALSE, server_pid); if (procHandle == NULL) { error = GetLastError(); success = FALSE; } else { success = TRUE; } } } if (success != TRUE) { // error creating new process char szMsgString[256]; LoadString(hInstance_gbl, IDS_CANT_START_THREAD, szMsgString, 256); sprintf(out_buf, "%s : %s errno : %d", path.c_str(), szMsgString, error); write_log(IDS_CANT_START_THREAD, out_buf); if (service_flag) { SERVICE_STATUS status_info; // wait a second to get the mutex handle (just in case) and // then close it WaitForSingleObject(procHandle, 1000); CloseHandle(procHandle); hService = OpenService(hScManager, remote_name->c_str(), GENERIC_READ | GENERIC_EXECUTE); ControlService(hService, SERVICE_CONTROL_STOP, &status_info); CloseServiceHandle(hScManager); CloseServiceHandle(hService); CNTL_stop_service(); //service_name->c_str()); } else { MessageBox(NULL, out_buf, NULL, MB_OK | MB_ICONSTOP); PostMessage(hWndGbl, WM_CLOSE, 0, 0); } return 0; } else { char szMsgString[256]; LoadString(hInstance_gbl, IDS_STARTING_GUARD, szMsgString, 256); sprintf(out_buf, "%s: %s\n", szMsgString, path.c_str()); write_log(IDS_LOG_START, out_buf); } // wait for process to terminate DWORD exit_status; if (service_flag) { while (WaitForSingleObject(procHandle, 500) == WAIT_OBJECT_0) { ReleaseMutex(procHandle); Sleep(100); } const int ret_val = WaitForSingleObject(procHandle, INFINITE); if (ret_val == WAIT_ABANDONED) exit_status = CRASHED; else if (ret_val == WAIT_OBJECT_0) exit_status = NORMAL_EXIT; CloseHandle(procHandle); } else { while (WaitForSingleObject(procHandle, INFINITE) == WAIT_FAILED) ; GetExitCodeProcess(procHandle, &exit_status); CloseHandle(procHandle); } if (exit_status != NORMAL_EXIT) { // check for startup error if (exit_status == STARTUP_ERROR) { char szMsgString[256]; LoadString(hInstance_gbl, IDS_STARTUP_ERROR, szMsgString, 256); sprintf(out_buf, "%s: %s (%lu)\n", path.c_str(), szMsgString, exit_status); write_log(IDS_STARTUP_ERROR, out_buf); done = true; } else { char szMsgString[256]; LoadString(hInstance_gbl, IDS_ABNORMAL_TERM, szMsgString, 256); sprintf(out_buf, "%s: %s (%lu)\n", path.c_str(), szMsgString, exit_status); write_log(IDS_LOG_TERM, out_buf); // switch the icons if the server restarted if (!service_flag) PostMessage(hWndGbl, WM_SWITCHICONS, 0, 0); if (option == START_FOREVER) done = false; } } else { // Normal shutdown - ie: via ibmgr - don't restart the server char szMsgString[256]; LoadString(hInstance_gbl, IDS_NORMAL_TERM, szMsgString, 256); sprintf(out_buf, "%s: %s\n", path.c_str(), szMsgString); write_log(IDS_LOG_STOP, out_buf); done = true; } if (option == START_ONCE) done = true; } while (!done); // If on WINNT if (service_flag) { CloseServiceHandle(hScManager); CloseServiceHandle(hService); CNTL_stop_service(); //(service_name->c_str()); } else PostMessage(hWndGbl, WM_CLOSE, 0, 0); return 0; }
int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE /*hPrevInst*/, LPSTR lpszArgs, int nWndMode) { /************************************** * * W i n M a i n * ************************************** * * Functional description * Run the server with NT named * pipes and/or TCP/IP sockets. * **************************************/ hInst = hThisInst; // We want server to crash without waiting for feedback from the user try { if (!Config::getBugcheckAbort()) SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); } catch (Firebird::fatal_exception& e) { MessageBox(NULL, e.what(), "Firebird server failure", MB_OK | MB_ICONHAND | MB_SYSTEMMODAL | MB_DEFAULT_DESKTOP_ONLY); return STARTUP_ERROR; // see /jrd/common.h } catch (Firebird::status_exception& e) { TEXT buffer[BUFFER_LARGE]; const ISC_STATUS* vector = e.value(); if (! (vector && fb_interpret(buffer, sizeof(buffer), &vector))) { strcpy(buffer, "Unknown internal failure"); } MessageBox(NULL, buffer, "Firebird server failure", MB_OK | MB_ICONHAND | MB_SYSTEMMODAL | MB_DEFAULT_DESKTOP_ONLY); return STARTUP_ERROR; // see /jrd/common.h } #ifdef SUPERSERVER server_flag = SRVR_multi_client; #else server_flag = 0; #endif #ifdef SUPERSERVER SetProcessAffinityMask(GetCurrentProcess(), static_cast<DWORD>(Config::getCpuAffinityMask())); #endif protocol_inet[0] = 0; protocol_wnet[0] = 0; strcpy(instance, FB_DEFAULT_INSTANCE); const HANDLE connection_handle = parse_args(lpszArgs, &server_flag); #ifdef SUPERSERVER // get priority class from the config file int priority = Config::getProcessPriorityLevel(); // override it, if necessary if (server_flag & SRVR_high_priority) { priority = 1; } // set priority class if (priority > 0) { SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); } else if (priority < 0) { SetPriorityClass(GetCurrentProcess(), IDLE_PRIORITY_CLASS); } #endif TEXT mutex_name[MAXPATHLEN]; fb_utils::snprintf(mutex_name, sizeof(mutex_name), SERVER_MUTEX, instance); fb_utils::prefix_kernel_object_name(mutex_name, sizeof(mutex_name)); CreateMutex(ISC_get_security_desc(), FALSE, mutex_name); // Initialize the service ISC_signal_init(); Firebird::FpeControl::maskAll(); int nReturnValue = 0; ISC_STATUS_ARRAY status_vector; fb_utils::init_status(status_vector); fb_shutdown_callback(0, wait_threads, fb_shut_finish, NULL); if (connection_handle != INVALID_HANDLE_VALUE) { rem_port* port = 0; if (server_flag & SRVR_inet) { port = INET_reconnect((SOCKET) connection_handle, status_vector); if (port) { SRVR_multi_thread(port, server_flag); port = NULL; } } else if (server_flag & SRVR_wnet) port = WNET_reconnect(connection_handle, status_vector); else if (server_flag & SRVR_xnet) port = XNET_reconnect((ULONG) connection_handle, status_vector); if (port) { service_connection(port); } else if (status_vector[1]) gds__log_status(0, status_vector); fb_shutdown(5 * 1000 /*5 seconds*/, fb_shutrsn_no_connection); } else if (!(server_flag & SRVR_non_service)) { Firebird::string service_name; service_name.printf(REMOTE_SERVICE, instance); CNTL_init(start_connections_thread, instance); const SERVICE_TABLE_ENTRY service_table[] = { {const_cast<char*>(service_name.c_str()), CNTL_main_thread}, {NULL, NULL} }; // BRS There is a error in MinGW (3.1.0) headers // the parameter of StartServiceCtrlDispatcher is declared const in msvc headers #if defined(MINGW) if (!StartServiceCtrlDispatcher(const_cast<SERVICE_TABLE_ENTRY*>(service_table))) { #else if (!StartServiceCtrlDispatcher(service_table)) { #endif if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) { CNTL_shutdown_service("StartServiceCtrlDispatcher failed"); } server_flag |= SRVR_non_service; } } else { start_connections_thread(0); nReturnValue = WINDOW_main(hThisInst, nWndMode, server_flag); } #ifdef DEBUG_GDS_ALLOC // In Debug mode - this will report all server-side memory leaks // due to remote access //gds_alloc_report(0, __FILE__, __LINE__); Firebird::PathName name = fb_utils::getPrefix(fb_utils::FB_DIR_LOG, "memdebug.log"); FILE* file = fopen(name.c_str(), "w+t"); if (file) { fprintf(file, "Global memory pool allocated objects\n"); getDefaultMemoryPool()->print_contents(file); fclose(file); } #endif return nReturnValue; } THREAD_ENTRY_DECLARE process_connection_thread(THREAD_ENTRY_PARAM arg) { /************************************** * * p r o c e s s _ c o n n e c t i o n _ t h r e a d * ************************************** * * Functional description * **************************************/ ThreadCounter counter; service_connection((rem_port*) arg); return 0; }
SLONG ISC_set_prefix(const TEXT* sw, const TEXT* path) { /************************************** * * i s c _ s e t _ p r e f i x * ************************************** * * Functional description * Parse the 'E' argument further for 'EL' 'EM' or 'E' * **************************************/ /* * We can't call gds__get_prefix() at once when switch is found. * gds__get_prefix() invokes GDS_init_prefix(), which in turn causes * config file to be loaded. And in case when -el or -em is given * before -e, this leads to use of wrong firebird.conf. * To avoid it accumulate values for switches locally, * and finally when called with sw==0, use them in correct order. */ static struct ESwitches { Firebird::PathName prefix, lockPrefix, msgPrefix; explicit ESwitches(MemoryPool& p) : prefix(p), lockPrefix(p), msgPrefix(p) { } }* eSw = 0; if (! sw) { if (eSw) { setPrefixIfNotEmpty(eSw->prefix, IB_PREFIX_TYPE); setPrefixIfNotEmpty(eSw->lockPrefix, IB_PREFIX_LOCK_TYPE); setPrefixIfNotEmpty(eSw->msgPrefix, IB_PREFIX_MSG_TYPE); delete eSw; eSw = 0; } return 0; } if ((!path) || (path[0] <= ' ')) { return -1; } if (! eSw) { eSw = FB_NEW(*getDefaultMemoryPool()) ESwitches(*getDefaultMemoryPool()); } switch (UPPER(*sw)) { case '\0': eSw->prefix = path; break; case 'L': eSw->lockPrefix = path; break; case 'M': eSw->msgPrefix = path; break; default: return -1; } return 0; }
BlrFromMessage::BlrFromMessage(IMessageMetadata* metadata, unsigned aDialect) : BlrWriter(*getDefaultMemoryPool()), expectedMessageLength(0), dialect(aDialect) { buildBlr(metadata); }