Example #1
0
bool TraceManager::check_result(ITracePlugin* plugin, const char* module, const char* function,
	bool result)
{
	if (result)
		return true;

	if (!plugin)
	{
		gds__log("Trace plugin %s returned error on call %s, "
			"did not create plugin and provided no additional details on reasons of failure",
			module, function);
		return false;
	}

	const char* errorStr = plugin->trace_get_error();

	if (!errorStr)
	{
		gds__log("Trace plugin %s returned error on call %s, "
			"but provided no additional details on reasons of failure", module, function);
		return false;
	}

	gds__log("Trace plugin %s returned error on call %s.\n\tError details: %s",
		module, function, errorStr);
	return false;
}
Example #2
0
// create directory for lock files and set appropriate access rights
void createLockDirectory(const char* pathname)
{
	static bool errorLogged = false;

	DWORD attr = GetFileAttributes(pathname);
	DWORD errcode = 0;
	if (attr == INVALID_FILE_ATTRIBUTES)
	{
		errcode = GetLastError();
		if (errcode == ERROR_FILE_NOT_FOUND)
		{
			if (!CreateDirectory(pathname, NULL)) {
				errcode = GetLastError();
			}
			else
			{
				adjustLockDirectoryAccess(pathname);

				attr = GetFileAttributes(pathname);
				if (attr == INVALID_FILE_ATTRIBUTES) {
					errcode = GetLastError();
				}
			}
		}
	}

	Firebird::string err;
	if (attr == INVALID_FILE_ATTRIBUTES)
	{
		err.printf("Can't create directory \"%s\". OS errno is %d", pathname, errcode);
		if (!errorLogged)
		{
			errorLogged = true;
			gds__log(err.c_str());
		}
		Firebird::fatal_exception::raise(err.c_str());
	}

	if (!(attr & FILE_ATTRIBUTE_DIRECTORY))
	{
		err.printf("Can't create directory \"%s\". File with same name already exists", pathname);
		if (!errorLogged)
		{
			errorLogged = true;
			gds__log(err.c_str());
		}
		Firebird::fatal_exception::raise(err.c_str());
	}

	if (attr & FILE_ATTRIBUTE_READONLY)
	{
		err.printf("Can't create directory \"%s\". Readonly directory with same name already exists", pathname);
		if (!errorLogged)
		{
			errorLogged = true;
			gds__log(err.c_str());
		}
		Firebird::fatal_exception::raise(err.c_str());
	}
}
Example #3
0
void iscLogStatus(const TEXT* text, const ISC_STATUS* status_vector)
{
/**************************************
 *
 *	i s c L o g S t a t u s
 *
 **************************************
 *
 * Functional description
 *	Log error to error log.
 *
 **************************************/
	fb_assert(status_vector[1] != FB_SUCCESS);

	try
	{
		Firebird::string buffer(text ? text : "");

		TEXT temp[BUFFER_LARGE];
		while (fb_interpret(temp, sizeof(temp), &status_vector))
		{
			if (!buffer.isEmpty())
			{
				buffer += "\n\t";
			}
			buffer += temp;
		}

		gds__log("%s", buffer.c_str());
	}
	catch (const Firebird::Exception&)
	{} // no-op
}
Example #4
0
void CNTL_stop_service() //const TEXT* service) // unused param
{
/**************************************
 *
 *	C N T L _ s t o p _ s e r v i c e
 *
 **************************************
 *
 * Functional description
 *   This function is called to stop the service.
 *
 *
 **************************************/

	SC_HANDLE servicemgr_handle = OpenSCManager(NULL, NULL, GENERIC_READ);
	if (servicemgr_handle == NULL)
	{
		// return error
		int error = GetLastError();
		gds__log("SC manager error %d", error);
		return;
	}

	SC_HANDLE service_handleL =
		OpenService(servicemgr_handle, service_name->c_str(), GENERIC_READ | GENERIC_EXECUTE);

	if (service_handleL == NULL)
	{
		// return error
		int error = GetLastError();
		gds__log("open services error %d", error);
		return;
	}
	else
	{
		SERVICE_STATUS status_info;
		if (!ControlService
			(service_handleL, SERVICE_CONTROL_STOP, &status_info))
		{
			// return error
			const int error = GetLastError();
			gds__log("Control services error %d", error);
			return;
		}
	}
}
Example #5
0
pid_t UTIL_start_process(const char* process, const char* process2, char** argv, const char* prog_name)
{
/**************************************
 *
 *      U T I L _ s t a r t _ p r o c e s s
 *
 **************************************
 *
 * Functional description
 *
 *     This function is used to create the specified process,
 *
 * Returns Codes:
 *	-1		Process spawn failed.
 *	pid		Successful creation. PID is returned.
 *
 *     Note: Make sure that the argument list ends with a null
 *     and the first argument is large enough to hold the complete
 *     expanded process name. (MAXPATHLEN recommended)
 *
 **************************************/
	fb_assert(process != NULL);
	fb_assert(argv != NULL);

	// prepend Firebird home directory to the program name
	// choose correct (super/superclassic) image - to be removed in 3.0
	Firebird::PathName string = fb_utils::getPrefix(fb_utils::FB_DIR_SBIN, process);
	if (access(string.c_str(), X_OK) < 0) {
		string = fb_utils::getPrefix(fb_utils::FB_DIR_SBIN, process2);
	}
	if (prog_name) {
		gds__log("%s: guardian starting %s\n", prog_name, string.c_str());
	}

	// add place in argv for visibility to "ps"
	strcpy(argv[0], string.c_str());
#if (defined SOLARIS)
	pid_t pid = fork1();
	if (!pid)
	{
		if (execv(string.c_str(), argv) == -1) {
			//ib_fprintf(ib_stderr, "Could not create child process %s with args %s\n", string, argv);
		}
		exit(FINI_ERROR);
	}

#else

	pid_t pid = vfork();
	if (!pid)
	{
		execv(string.c_str(), argv);
		_exit(FINI_ERROR);
	}
#endif
	return (pid);
}
Example #6
0
static int wait_threads(const int, const int, void*)
{
	server_shutdown = true;

	if (!ThreadCounter::wait()) {
		gds__log("Timeout expired during remote server shutdown");
	}

	return FB_SUCCESS;
}
Example #7
0
static void raiseLimit(int resource)
{
    struct rlimit lim;
    if (getrlimit(resource, &lim) == 0)
    {
        if (lim.rlim_cur != lim.rlim_max)
        {
            lim.rlim_cur = lim.rlim_max;
            if (setrlimit(resource, &lim) != 0)
            {
                gds__log("setrlimit() failed, errno=%d", errno);
            }
        }
    }
    else
    {
        gds__log("getrlimit() failed, errno=%d", errno);
    }
}
HWND DisplayPropSheet(HWND hParentWnd, HINSTANCE hInst)
{
/******************************************************************************
 *
 *  D i s p l a y P r o p S h e e t
 *
 ******************************************************************************
 *
 *  Input:  hParentWnd - Handle to the main window of this application
 *
 *  Return: Handle to the Property sheet dialog if successful
 *          NULL if error in displaying property sheet
 *
 *  Description: This function initializes the page(s) of the property sheet,
 *               and then calls the PropertySheet() function to display it.
 *****************************************************************************/
	PROPSHEETPAGE PSPages[1];
	HINSTANCE hInstance = hInst;

	PSPages[0].dwSize = sizeof(PROPSHEETPAGE);
	PSPages[0].dwFlags = PSP_USETITLE;
	PSPages[0].hInstance = hInstance;
	PSPages[0].pszTemplate = MAKEINTRESOURCE(IDD_PROPSHEET);
	PSPages[0].pszTitle = MAKEINTRESOURCE(IDS_PROP_TITLE);
	PSPages[0].pfnDlgProc = (DLGPROC) GeneralPage;
	PSPages[0].pfnCallback = NULL;

	PROPSHEETHEADER PSHdr;
	PSHdr.dwSize = sizeof(PROPSHEETHEADER);
	PSHdr.dwFlags = PSH_PROPTITLE | PSH_PROPSHEETPAGE | PSH_USEICONID | PSH_MODELESS | PSH_NOAPPLYNOW | PSH_NOCONTEXTHELP;
	PSHdr.hwndParent = hParentWnd;
	PSHdr.hInstance = hInstance;
	PSHdr.pszIcon = MAKEINTRESOURCE(IDI_IBGUARD);
	PSHdr.pszCaption = (LPSTR) GUARDIAN_APP_LABEL;
	PSHdr.nPages = FB_NELEM(PSPages);
	PSHdr.nStartPage = 0;
	PSHdr.ppsp = (LPCPROPSHEETPAGE) & PSPages;
	PSHdr.pfnCallback = NULL;

	hPSDlg = (HWND) PropertySheet(&PSHdr);

	if (hPSDlg == 0 || hPSDlg == (HWND) -1)
	{
		gds__log("Create property sheet window failed. Error code %d", GetLastError());
		hPSDlg = NULL;
	}
	return hPSDlg;
}
Example #9
0
static THREAD_ENTRY_DECLARE xnet_connect_wait_thread(THREAD_ENTRY_PARAM)
{
/**************************************
 *
 *      x n e t _ c o n n e c t _ w a i t _ t h r e a d
 *
 **************************************
 *
 * Functional description
 *   Starts xnet server side interprocess thread
 *
 **************************************/
	ThreadCounter counter;

	ISC_STATUS_ARRAY status_vector;
	while (!server_shutdown)
	{
		fb_utils::init_status(status_vector);
		rem_port* port = XNET_connect(/*NULL,*/ NULL, status_vector, server_flag);

		if (!port)
		{
			const ISC_STATUS err = status_vector[1];
			if (err)
			{
				if (err == isc_net_server_shutdown)
					break;
				gds__log_status(0, status_vector);
			}
		}
		else if (gds__thread_start(process_connection_thread, port, THREAD_medium, 0, 0))
		{
			gds__log("XNET: can't start worker thread, connection terminated");
			port->disconnect(NULL, NULL);
		}
	}

	return 0;
}
Example #10
0
static THREAD_ENTRY_DECLARE inet_connect_wait_thread(THREAD_ENTRY_PARAM)
{
/**************************************
 *
 *      i n e t _ c o n n e c t _ w a i t _ t h r e a d
 *
 **************************************
 *
 * Functional description
 *
 **************************************/
	ThreadCounter counter;

	ISC_STATUS_ARRAY status_vector;
	while (!server_shutdown)
	{
		fb_utils::init_status(status_vector);
		rem_port* port = INET_connect(protocol_inet, NULL, status_vector, server_flag, 0);

		if (!port)
		{
			if (status_vector[1]) {
				gds__log_status(0, status_vector);
			}
			break;
		}
		if (server_flag & SRVR_multi_client)
		{
			SRVR_multi_thread(port, server_flag);
			break;
		}
		if (gds__thread_start(process_connection_thread, port, THREAD_medium, 0, 0))
		{
			gds__log("INET: can't start worker thread, connection terminated");
			port->disconnect(NULL, NULL);
		}
	}
	return 0;
}
static THREAD_ENTRY_DECLARE WINDOW_main(THREAD_ENTRY_PARAM)
{
/**************************************
 *
 *	W I N D O W _ m a i n
 *
 **************************************
 *
 * Functional description
 *
 *      This function is where the actual service code starts.
 * Do all the window init stuff, then fork off a thread for starting
 * the server.
 *
 **************************************/

	// If we're a service, don't create a window
	if (service_flag)
	{
		try
		{
			Thread::start(start_and_watch_server, 0, THREAD_medium, &watcher_thd);
		}
		catch (const Firebird::Exception&)
		{
			// error starting server thread
			char szMsgString[256];
			LoadString(hInstance_gbl, IDS_CANT_START_THREAD, szMsgString, 256);
			gds__log(szMsgString);
		}

		return 0;
	}

	// Make sure that there is only 1 instance of the guardian running
	HWND hWnd = FindWindow(GUARDIAN_CLASS_NAME, GUARDIAN_APP_NAME);
	if (hWnd)
	{
		char szMsgString[256];
		LoadString(hInstance_gbl, IDS_ALREADYSTARTED, szMsgString, 256);
		MessageBox(NULL, szMsgString, GUARDIAN_APP_LABEL, MB_OK | MB_ICONSTOP);
		gds__log(szMsgString);
		return 0;
	}

	// initialize main window
	WNDCLASS wcl;
	wcl.hInstance = hInstance_gbl;
	wcl.lpszClassName = GUARDIAN_CLASS_NAME;
	wcl.lpfnWndProc = WindowFunc;
	wcl.style = 0;
	wcl.hIcon = LoadIcon(hInstance_gbl, MAKEINTRESOURCE(IDI_IBGUARD));
	wcl.hCursor = LoadCursor(NULL, IDC_ARROW);
	wcl.lpszMenuName = NULL;
	wcl.cbClsExtra = 0;
	wcl.cbWndExtra = 0;
	wcl.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);

	if (!RegisterClass(&wcl))
	{
		char szMsgString[256];
		LoadString(hInstance_gbl, IDS_REGERROR, szMsgString, 256);
		MessageBox(NULL, szMsgString, GUARDIAN_APP_LABEL, MB_OK | MB_ICONSTOP);
		return 0;
	}

	hWnd = CreateWindowEx(0,
						  GUARDIAN_CLASS_NAME,
						  GUARDIAN_APP_NAME,
						  WS_DLGFRAME | WS_SYSMENU | WS_MINIMIZEBOX,
						  CW_USEDEFAULT,
						  CW_USEDEFAULT,
						  CW_USEDEFAULT,
						  CW_USEDEFAULT,
						  HWND_DESKTOP, NULL, hInstance_gbl, NULL);

	// Save the window handle for the thread
	hWndGbl = hWnd;

	// begin a new thread for calling the start_and_watch_server
	try
	{
		Thread::start(start_and_watch_server, 0, THREAD_medium, NULL);
	}
	catch (const Firebird::Exception&)
	{
		// error starting server thread
		char szMsgString[256];
		LoadString(hInstance_gbl, IDS_CANT_START_THREAD, szMsgString, 256);
		MessageBox(NULL, szMsgString, GUARDIAN_APP_LABEL, MB_OK | MB_ICONSTOP);
		gds__log(szMsgString);
		DestroyWindow(hWnd);
		return 0;
	}

	SendMessage(hWnd, WM_COMMAND, IDM_CANCEL, 0);
	UpdateWindow(hWnd);

	MSG message;
	while (GetMessage(&message, NULL, 0, 0))
	{
		if (hPSDlg)
		{
			// If property sheet dialog is open
			// Check if the message is property sheet dialog specific
			BOOL bPSMsg = PropSheet_IsDialogMessage(hPSDlg, &message);

			// Check if the property sheet dialog is still valid, if not destroy it
			if (!PropSheet_GetCurrentPageHwnd(hPSDlg))
			{
				DestroyWindow(hPSDlg);
				hPSDlg = NULL;
				if (swap_icons_thd)
				{
					CloseHandle(swap_icons_thd);
					swap_icons_thd = 0;
				};
			}
			if (bPSMsg)
				continue;
		}
		TranslateMessage(&message);
		DispatchMessage(&message);
	}
	return message.wParam;
}
static void write_log(int log_action, const char* buff)
{
/******************************************************************************
 *
 *  w r i t e _ l o g
 *
 ******************************************************************************
 *
 *  Description:  Writes the guardian information to either the Windows 95
 *                property sheet structure (log_entry) or to the Windows NT
 *                Event Log
 *****************************************************************************/
	const size_t BUFF_SIZE = 512;
	char tmp_buff[BUFF_SIZE];

	// Move to the end of the log_entry list
	log_info* log_temp = log_entry;
	while (log_temp->next)
		log_temp = log_temp->next;

	log_info* tmp = static_cast<log_info*>(malloc(sizeof(log_info)));
	memset(tmp, 0, sizeof(log_info));

#ifdef NOT_USED_OR_REPLACED
	time_t ltime;
	time(&ltime);
	const tm* today = localtime(&ltime);

	sprintf(tmp->log_time, "%02d:%02d", today->tm_hour, today->tm_min);
	sprintf(tmp->log_date, "%02d/%02d/%02d", today->tm_mon + 1, today->tm_mday, today->tm_year % 100);
#else
	// TMN: Fixed this after bug-report. Should it really force
	// 24hr format in e.g US, where they use AM/PM wharts?
	GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS | TIME_FORCE24HOURFORMAT, NULL, NULL,
				  tmp->log_time, sizeof(tmp->log_time));
	GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL,
				  tmp->log_date, sizeof(tmp->log_date));
#endif

	if (log_action >= IDS_LOG_START && log_action <= IDS_LOG_TERM)
	{
		// Only Windows 95 needs this information since it goes in the property sheet
		LoadString(hInstance_gbl, log_action, tmp_buff, sizeof(tmp->log_action));
		sprintf(tmp->log_action, "%s", tmp_buff);
		tmp->next = NULL;
		log_temp->next = tmp;
	}

	if (service_flag)
	{
		// on NT
		HANDLE hLog = RegisterEventSource(NULL, service_name->c_str());
		if (!hLog)
			gds__log("Error opening Windows NT Event Log");
		else
		{
			char buffer[BUFF_SIZE];
			char* act_buff[1];
			act_buff[0] = buffer;

			LoadString(hInstance_gbl, log_action + 1, tmp_buff, sizeof(tmp_buff));
			sprintf(act_buff[0], "%s", buff);

			LPTSTR lpMsgBuf;
			FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
						  FORMAT_MESSAGE_ARGUMENT_ARRAY |
						  FORMAT_MESSAGE_FROM_STRING,
						  tmp_buff, 0, 0, (LPTSTR) &lpMsgBuf, 0,
						  reinterpret_cast<va_list*>(act_buff));

			const int len = MIN(BUFF_SIZE - 1, strlen(lpMsgBuf) - 1);
			strncpy(act_buff[0], lpMsgBuf, len);
			act_buff[0][len] = 0;
			LocalFree(lpMsgBuf);
			WORD wLogType;

			switch (log_action)
			{
			case IDS_LOG_START:
			case IDS_LOG_STOP:
				wLogType = EVENTLOG_INFORMATION_TYPE;
				break;
			default:
				wLogType = EVENTLOG_ERROR_TYPE;
			}

			if (!ReportEvent
				(hLog, wLogType, 0, log_action + 1, NULL, 1, 0,
				 const_cast<const char**>(act_buff), NULL))
			{
				FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
							  FORMAT_MESSAGE_FROM_SYSTEM |
							  FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
							  GetLastError(),
							  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),	// Default language
							  (LPTSTR) & lpMsgBuf, 0, NULL);
				gds__log("Unable to update NT Event Log.\n\tOS Message: %s", lpMsgBuf);
				LocalFree(lpMsgBuf);
			}
			DeregisterEventSource(hLog);
		}
	}

	// Write to the Firebird log
	if (*buff)
		gds__log(buff);
}
Example #13
0
static HANDLE parse_args(LPCSTR lpszArgs, USHORT* pserver_flag)
{
/**************************************
 *
 *      p a r s e _ a r g s
 *
 **************************************
 *
 * Functional description
 *      WinMain gives us a stupid command string, not
 *      a cool argv.  Parse through the string and
 *      set the options.
 * Returns
 *      a connection handle if one was passed in,
 *      INVALID_HANDLE_VALUE otherwise.
 *
 **************************************/
	bool delimited = false;

	HANDLE connection_handle = INVALID_HANDLE_VALUE;

	const TEXT* p = lpszArgs;
	while (*p)
	{
		TEXT c;
		if (*p++ == '-')
		{
			while ((*p) && (c = *p++) && (c != ' '))
			{
				switch (UPPER(c))
				{
				case 'A':
					*pserver_flag |= SRVR_non_service;
					break;

				case 'B':
					*pserver_flag |= SRVR_high_priority;
					break;

				case 'D':
					*pserver_flag |= (SRVR_debug | SRVR_non_service);
					break;

#ifndef SUPERSERVER
				case 'H':
					while (*p && *p == ' ')
						p++;
					if (*p)
					{
						TEXT buffer[32];
						char* pp = buffer;
						while (*p && *p != ' ' && (pp - buffer < sizeof(buffer) - 1))
						{
							if (*p == '@')
							{
								p++;
								*pp++ = '\0';
								connection_handle = (HANDLE) _atoi64(buffer);
								pp = buffer;
							}
							else
								*pp++ = *p++;
						}
						*pp++ = '\0';

						if (connection_handle == INVALID_HANDLE_VALUE)
						{
							connection_handle = (HANDLE) _atoi64(buffer);
						}
						else
						{
							const DWORD parent_id = atol(buffer);
							const HANDLE parent_handle = OpenProcess(PROCESS_DUP_HANDLE, FALSE, parent_id);
							if (!parent_handle)
							{
								gds__log("SERVER: OpenProcess failed. Errno = %d, parent PID = %d", GetLastError(), parent_id);
								exit(FINI_ERROR);
							}

							if (!DuplicateHandle(parent_handle, connection_handle, GetCurrentProcess(), &connection_handle,
									0, FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
							{
								gds__log("SERVER: DuplicateHandle failed. Errno = %d, parent PID = %d", GetLastError(), parent_id);
								exit(FINI_ERROR);
							}

							CloseHandle(parent_handle);
						}
					}
					break;
#endif

				case 'I':
					*pserver_flag |= SRVR_inet;
					break;

				case 'M':
					*pserver_flag |= SRVR_multi_client;
					break;

				case 'N':
					*pserver_flag |= SRVR_no_icon;
					break;

				case 'P':	// Specify a port or named pipe other than the default
					while (*p && *p == ' ')
						p++;
					if (*p)
					{
						// Assumed the buffer size for both protocols may differ
						// in the future, hence I did generic code.
						char* pi = protocol_inet;
						const char* piend = protocol_inet + sizeof(protocol_inet) - 1;
						char* pw = protocol_wnet;
						const char* pwend = protocol_wnet + sizeof(protocol_wnet) - 1;

						*pi++ = '/';
						*pw++ = '\\';
						*pw++ = '\\';
						*pw++ = '.';
						*pw++ = '@';
						while (*p && *p != ' ')
						{
							if (pi < piend)
								*pi++ = *p;
							if (pw < pwend)
								*pw++ = *p++;
						}
						*pi++ = '\0';
						*pw++ = '\0';
					}
					break;

				case 'R':
					*pserver_flag &= ~SRVR_high_priority;
					break;

				case 'S':
					delimited = false;
					while (*p && *p == ' ')
						p++;
					if (*p && *p == '"')
					{
						p++;
						delimited = true;
					}
					if (delimited)
					{
						char* pi = instance;
						const char* pend = instance + sizeof(instance) - 1;
						while (*p && *p != '"' && pi < pend) {
							*pi++ = *p++;
						}
						*pi++ = '\0';
						if (*p && *p == '"')
							p++;
					}
					else
					{
						if (*p && *p != '-')
						{
							char* pi = instance;
							const char* pend = instance + sizeof(instance) - 1;
							while (*p && *p != ' ' && pi < pend) {
								*pi++ = *p++;
							}
							*pi++ = '\0';
						}
					}
					break;

				case 'W':
					*pserver_flag |= SRVR_wnet;
					break;

				case 'X':
					*pserver_flag |= SRVR_xnet;
					break;

				case 'Z':
					// CVC: printf doesn't work because we don't have a console attached.
					//printf("Firebird remote server version %s\n",  FB_VERSION);
					MessageBox(NULL, FB_VERSION, "Firebird server version",
						MB_OK | MB_ICONINFORMATION | MB_TOPMOST | MB_DEFAULT_DESKTOP_ONLY);
					exit(FINI_OK);

				default:
					// In case of something unrecognized, just
					// continue, since we have already taken it off
					// of p.
					break;
				}
			}
		}
	}

	if ((*pserver_flag & (SRVR_inet | SRVR_wnet | SRVR_xnet)) == 0)
	{
		*pserver_flag |= SRVR_wnet;
		*pserver_flag |= SRVR_inet;
		*pserver_flag |= SRVR_xnet;
	}

	return connection_handle;
}
Example #14
0
    int FB_EXPORTED server_main( int argc, char** argv)
    {
        /**************************************
         *
         *	m a i n
         *
         **************************************
         *
         * Functional description
         *	Run the server with apollo mailboxes.
         *
         **************************************/
        RemPortPtr port;

// 01 Sept 2003, Nickolay Samofatov
// In GCC version 3.1-3.3 we need to install special error handler
// in order to get meaningful terminate() error message on stderr.
// In GCC 3.4 or later this is the default.
//#if __GNUC__ == 3 && __GNUC_MINOR__ >= 1 && __GNUC_MINOR__ < 4
//    std::set_terminate (__gnu_cxx::__verbose_terminate_handler);
//#endif

        const TEXT* const* const end = argc + argv;
        argv++;
        bool debug = false, standalone = false;
        INET_SERVER_flag = 0;
        int channel = 0;
        protocol[0] = 0;
        bool multi_client = false, multi_threaded = false;

#ifdef SUPERSERVER
        INET_SERVER_flag |= SRVR_multi_client;
        multi_client = multi_threaded = standalone = true;
#endif

        int clients = 0;
        bool done = false;

        while (argv < end)
        {
            TEXT c;
            const TEXT* p = *argv++;
            if (*p++ == '-')
                while (c = *p++)
                {
                    switch (UPPER(c))
                    {
                    case 'D':
                        INET_SERVER_flag |= SRVR_debug;
                        debug = true;
                        break;
#ifndef SUPERSERVER

                    case 'M':
                        INET_SERVER_flag |= SRVR_multi_client;
                        if (argv < end)
                        {
                            if (clients = atoi(*argv))
                                argv++;
                        }
                        multi_client = standalone = true;
                        break;

                    case 'S':
                        standalone = true;
                        break;


                    case 'I':
                        standalone = false;
                        break;

                    case 'T':
                        multi_threaded = true;
                        break;

                    case 'U':
                        multi_threaded = false;
                        break;
#endif // SUPERSERVER

                    case 'E':
                        if (ISC_set_prefix(p, *argv) == -1)
                            printf("Invalid argument Ignored\n");
                        else
                            argv++;	// do not skip next argument if this one is invalid
                        done = true;
                        break;

                    case 'P':
                        fb_utils::snprintf(protocol, sizeof(protocol), "/%s", *argv++);
                        break;

                    case 'H':
                    case '?':
                        printf("Firebird TCP/IP server options are:\n");
                        printf("  -d           : debug on\n");

#ifndef SUPERSERVER
                        // These options are not applicable to super server
                        printf("  -m           : multiclient - on\n");
                        printf("  -s           : standalone - true\n");
                        printf("  -i           : standalone - false\n");

                        printf("  -t           : multithread - true  (non pc only)\n");
                        printf("  -u           : multithread - false (pc only)\n");
#endif

                        printf("  -p<protocol> : specify protocol\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");
                        printf("  -z   : print version\n");

                        exit(FINI_OK);
                    case 'Z':
                        printf("Firebird TCP/IP server version %s\n", GDS_VERSION);
                        exit(FINI_OK);
                    }
                    if (done)
                        break;
                }
        }

        // activate paths set with -e family of switches
        ISC_set_prefix(0, 0);

#ifdef UNIX
        set_signal(SIGPIPE, signal_handler);
        set_signal(SIGUSR1, signal_handler);
        set_signal(SIGUSR2, signal_handler);
#endif

#if defined(UNIX) && defined(HAVE_SETRLIMIT) && defined(HAVE_GETRLIMIT)

#ifdef RLIMIT_NPROC
        raiseLimit(RLIMIT_NPROC);
#endif

#if !(defined(DEV_BUILD))
        if (Config::getBugcheckAbort())
#endif
        {
            // try to force core files creation
            raiseLimit(RLIMIT_CORE);

            // we need some writable directory for core file
            // on any unix /tmp seems to be the best place
            if (CHANGE_DIR(TEMP_DIR))
            {
                // error on changing the directory
                gds__log("Could not change directory to %s due to errno %d", TEMP_DIR, errno);
            }
        }

#if defined(SUPERSERVER) && (defined SOLARIS || defined HPUX || defined LINUX)
        // Increase max open files to hard limit for Unix
        // platforms which are known to have low soft limits.

        raiseLimit(RLIMIT_NOFILE);
#endif

#endif

        // Fork off a server, wait for it to die, then fork off another,
        // but give up after 100 tries

#ifndef SUPERSERVER
        if (multi_client && !debug)
        {
#ifdef UNIX
            set_signal(SIGUSR1, signal_handler);
#endif
            int child;
            for (int n = 0; n < 100; n++)
            {
                INET_SERVER_start = 0;
                if (!(child = fork()))
                    break;
                while (wait(0) != child)
                    if (INET_SERVER_start)
                    {
                        n = 0;		// reset error counter on "real" signal
                        break;
                    }
                gds__log("INET_SERVER/main: gds_inet_server restarted");
            }
#ifdef UNIX
            set_signal(SIGUSR1, SIG_DFL);
#endif
        }
#endif

        if (standalone)
        {
            if (multi_client)
            {
#ifdef SUPERSERVER

                // Remove restriction on username, for DEV builds
                // restrict only for production builds.  MOD 21-July-2002
#ifndef DEV_BUILD
                Firebird::string user_name;	// holds the user name
                // check user id
                ISC_get_user(&user_name, NULL, NULL, NULL);

                if (user_name != "root" &&
                        user_name != FIREBIRD_USER_NAME &&
                        user_name != INTERBASE_USER_NAME &&
                        user_name != INTERBASE_USER_SHORT)
                {
                    // invalid user -- bail out
                    fprintf(stderr, "%s: Invalid user (must be %s, %s, %s or root).\n",
                            "fbserver", FIREBIRD_USER_NAME,
                            INTERBASE_USER_NAME, INTERBASE_USER_SHORT);
                    exit(STARTUP_ERROR);
                }
#endif
#else
                if (setreuid(0, 0) < 0)
                    printf("Inet_server: couldn't set uid to superuser.\n");
#endif
                INET_set_clients(clients);
            }

            if (!debug)
            {
                int mask = 0; // FD_ZERO(&mask);
                mask |= 1 << 2; // FD_SET(2, &mask);
                divorce_terminal(mask);
            }
            {   // scope block
                ISC_STATUS_ARRAY status_vector;
                port = INET_connect(protocol, 0, status_vector, INET_SERVER_flag, 0);
                if (!port)
                {
                    gds__print_status(status_vector);
                    exit(STARTUP_ERROR);
                }
            } // end scope block
        }
        else
        {
            port = INET_server(channel);
            if (!port)
            {
                fprintf(stderr, "fbserver: Unable to start INET_server\n");
                exit(STARTUP_ERROR);
            }
        }

#ifdef SUPERSERVER
        // before starting the superserver stuff change directory to tmp
        if (CHANGE_DIR(TEMP_DIR))
        {
            // error on changing the directory
            gds__log("Could not change directory to %s due to errno %d", TEMP_DIR, errno);
        }

        // 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.

        {   // scope
            TEXT path[MAXPATHLEN];
            ISC_STATUS_ARRAY status;
            isc_db_handle db_handle = 0L;

            Jrd::SecurityDatabase::getPath(path);
            const char dpb[] = {isc_dpb_version1, isc_dpb_gsec_attach, 1, 1};
            isc_attach_database(status, strlen(path), path, &db_handle, sizeof dpb, dpb);
            if (status[0] == 1 && status[1] > 0)
            {
                gds__log_status(path, status);
                isc_print_status(status);
                exit(STARTUP_ERROR);
            }
            isc_detach_database(status, &db_handle);
            if (status[0] == 1 && status[1] > 0)
            {
                gds__log_status(path, status);
                isc_print_status(status);
                exit(STARTUP_ERROR);
            }
        } // end scope

        shutdownInit();
#endif

        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

        //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

        // 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;
    }
Example #15
0
// The following two functions are temporary stubs and will be
// removed as the services API takes shape.  They are used to
// test that the paths for starting services and parsing command-lines
// are followed correctly.
int test_thread(Firebird::UtilSvc* uSvc)
{
	gds__log("Starting service");
	return FINI_OK;
}
Example #16
0
int CLIB_ROUTINE main( int argc, char **argv)
{
    /**************************************
     *
     *	m a i n
     *
     **************************************
     *
     * Functional description
     *	If there is no command line, prompt for one, read it
     *	and make an artificial argc/argv.   Otherwise, pass
     *	the specified argc/argv to IBMGR_exec_line (see below).
     *
     **************************************/

    fprintf(stderr, "*** fbmgr is deprecated, will be removed soon ***\n");
    gds__log("*** fbmgr is deprecated, will be removed soon ***");

    // Let's see if we have something in environment variables
    Firebird::string user, password;
    fb_utils::readenv(ISC_USER, user);
    fb_utils::readenv(ISC_PASSWORD, password);

    Firebird::string host;
    // MMM - do not allow to change host now
    //fb_utils::readenv("ISC_HOST", host);

    TEXT msg[MSG_LEN];

    // Let's get a real user name. This info is used by
    // START server command. Because server is not running
    // we can not check the password, thus we require a
    // real user to be root or FIREBIRD_USER_NAME or
    // INTERBASE_USER_NAME or INTERBASE_USER_SHORT

    const struct passwd* pw = getpwuid(getuid());
    if (pw == NULL)
    {
        perror("getpwuid");
        SRVRMGR_msg_get(MSG_GETPWFAIL, msg);
        fprintf(OUTFILE, "%s\n", msg);
        exit(FINI_ERROR);
    }

    strcpy(ibmgr_data.real_user, pw->pw_name);

    if (!strcmp(pw->pw_name, "root") ||
            !strcmp(pw->pw_name, FIREBIRD_USER_NAME) ||
            !strcmp(pw->pw_name, INTERBASE_USER_NAME) ||
            !strcmp(pw->pw_name, INTERBASE_USER_SHORT))
    {
        strcpy(ibmgr_data.user, SYSDBA_USER_NAME);
    }
    else
        copy_str_upper(ibmgr_data.user, pw->pw_name);


    if (user.length())
        copy_str_upper(ibmgr_data.user, user.c_str());

    if (password.length())
        strcpy(ibmgr_data.password, password.c_str());
    else
        ibmgr_data.password[0] = '\0';

    if (host.length())
        strcpy(ibmgr_data.host, host.c_str());
    else
        strcpy(ibmgr_data.host, "localhost");


    // Shutdown is not in progress and we are not attached to service yet.
    // But obviously we will need attachment.

    ibmgr_data.shutdown = false;
    ibmgr_data.attached = 0;
    ibmgr_data.reattach |= (REA_HOST | REA_USER | REA_PASSWORD);

    // No pidfile by default
    ibmgr_data.pidfile[0] = 0;



    // Special case a solitary -z switch.
    // Print the version and then drop into prompt mode.

    if (argc == 2 && *argv[1] == '-' && (argv[1][1] == 'Z' || argv[1][1] == 'z'))
    {
        parse_cmd_line(argc, argv, false);
        argc--;
    }

    SSHORT ret;
    if (argc > 1)
    {
        ret = parse_cmd_line(argc, argv, true);
        if (ret == FB_SUCCESS)
        {
            ret = SRVRMGR_exec_line(&ibmgr_data);
            if (ret)
            {
                SRVRMGR_msg_get(ret, msg);
                fprintf(OUTFILE, "%s\n", msg);
            }
            // We also need to check the shutdown flag here (if operation was
            // -shut -[noat|notr]) and, depending on what we want to do, either
            // wait here on some sort of a shutdown event, or go to the prompt mode
            SRVRMGR_cleanup(&ibmgr_data);
            exit(FINI_OK);
        }
        else if (ret != ACT_PROMPT)
            exit(FINI_OK);
    }

    int local_argc;
    SCHAR* local_argv[MAXARGS];
    TEXT stuff[MAXSTUFF];

    for (;;)
    {
        if (get_line(&local_argc, local_argv, stuff))
            break;
        if (local_argc > 1)
        {
            ret = parse_cmd_line(local_argc, local_argv, false);
            if (ret == ACT_QUIT)
                break;
            if (ret == FB_SUCCESS)
            {
                ret = SRVRMGR_exec_line(&ibmgr_data);
                if (ret)
                {
                    SRVRMGR_msg_get(ret, msg);
                    fprintf(OUTFILE, "%s\n", msg);
                }
            }
        }
    }
    SRVRMGR_cleanup(&ibmgr_data);
    exit(FINI_OK);
}
Example #17
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);
	}
}
Example #18
0
bool IntlUtil::initUnicodeCollation(texttype* tt, charset* cs, const ASCII* name,
	USHORT attributes, const UCharBuffer& specificAttributes, const string& configInfo)
{
	memset(tt, 0, sizeof(*tt));

	// name comes from stack. Copy it.
	ASCII* nameCopy = FB_NEW ASCII[strlen(name) + 1];
	strcpy(nameCopy, name);
	tt->texttype_name = nameCopy;

	tt->texttype_version = TEXTTYPE_VERSION_1;
	tt->texttype_country = CC_INTL;
	tt->texttype_canonical_width = 4;	// UTF-32
	tt->texttype_fn_destroy = unicodeDestroy;
	tt->texttype_fn_compare = unicodeCompare;
	tt->texttype_fn_key_length = unicodeKeyLength;
	tt->texttype_fn_string_to_key = unicodeStrToKey;
	tt->texttype_fn_canonical = unicodeCanonical;

	IntlUtil::SpecificAttributesMap map;

	Jrd::CharSet* charSet = NULL;

	try
	{
		charSet = Jrd::CharSet::createInstance(*getDefaultMemoryPool(), 0, cs);
		IntlUtil::parseSpecificAttributes(charSet, specificAttributes.getCount(),
			specificAttributes.begin(), &map);
		delete charSet;
	}
	catch (...)
	{
		delete charSet;
		gds__log("initUnicodeCollation failed - unexpected exception caught");
		return false;
	}

	IntlUtil::SpecificAttributesMap map16;

	SpecificAttributesMap::Accessor accessor(&map);

	bool found = accessor.getFirst();

	while (found)
	{
		UCharBuffer s1, s2;
		USHORT errCode;
		ULONG errPosition;

		s1.resize(cs->charset_to_unicode.csconvert_fn_convert(
			&cs->charset_to_unicode, accessor.current()->first.length(), NULL, 0, NULL, &errCode, &errPosition));
		s1.resize(cs->charset_to_unicode.csconvert_fn_convert(
			&cs->charset_to_unicode, accessor.current()->first.length(), (UCHAR*) accessor.current()->first.c_str(),
			s1.getCapacity(), s1.begin(), &errCode, &errPosition));

		s2.resize(cs->charset_to_unicode.csconvert_fn_convert(
			&cs->charset_to_unicode, accessor.current()->second.length(), NULL, 0, NULL, &errCode, &errPosition));
		s2.resize(cs->charset_to_unicode.csconvert_fn_convert(
			&cs->charset_to_unicode, accessor.current()->second.length(), (UCHAR*) accessor.current()->second.c_str(),
			s2.getCapacity(), s2.begin(), &errCode, &errPosition));

		map16.put(string((char*) s1.begin(), s1.getCount()), string((char*) s2.begin(), s2.getCount()));

		found = accessor.getNext();
	}

	UnicodeUtil::Utf16Collation* collation =
		UnicodeUtil::Utf16Collation::create(tt, attributes, map16, configInfo);

	if (!collation)
	{
		gds__log("initUnicodeCollation failed - UnicodeUtil::Utf16Collation::create failed");
		return false;
	}

	tt->texttype_impl = FB_NEW TextTypeImpl(cs, collation);

	return true;
}
void ConfigStorage::checkFile()
{
	if (m_cfg_file >= 0)
		return;

	char* cfg_file_name = m_sharedMemory->getHeader()->cfg_file_name;

	if (!(*cfg_file_name))
	{
		fb_assert(m_sharedMemory->getHeader()->cnt_uses == 0);

		char dir[MAXPATHLEN];
		iscPrefixLock(dir, "", true);

		PathName filename = TempFile::create("fb_trace_", dir);
		filename.copyTo(cfg_file_name, sizeof(m_sharedMemory->getHeader()->cfg_file_name));
		m_cfg_file = os_utils::openCreateSharedFile(cfg_file_name, O_BINARY);
	}
	else
	{
		m_cfg_file = ::open(cfg_file_name, O_RDWR | O_BINARY);

		if (m_cfg_file < 0)
			checkFileError(cfg_file_name, "open", isc_io_open_err);
	}

	// put default (audit) trace file contents into storage
	if (m_sharedMemory->getHeader()->change_number == 0)
	{
		FILE* cfgFile = NULL;

		try
		{
			PathName configFileName(Config::getAuditTraceConfigFile());

			// remove quotes around path if present
			{ // scope
				const FB_SIZE_T pathLen = configFileName.length();
				if (pathLen > 1 && configFileName[0] == '"' &&
					configFileName[pathLen - 1] == '"')
				{
					configFileName.erase(0, 1);
					configFileName.erase(pathLen - 2, 1);
				}
			}

			if (configFileName.empty())
				return;

			if (PathUtils::isRelative(configFileName))
			{
				PathName root(Config::getRootDirectory());
				PathUtils::ensureSeparator(root);
				configFileName.insert(0, root);
			}

			cfgFile = fopen(configFileName.c_str(), "rb");
			if (!cfgFile) {
				checkFileError(configFileName.c_str(), "fopen", isc_io_open_err);
			}

			TraceSession session(*getDefaultMemoryPool());

			fseek(cfgFile, 0, SEEK_END);
			const long len = ftell(cfgFile);
			if (len)
			{
				fseek(cfgFile, 0, SEEK_SET);
				char* p = session.ses_config.getBuffer(len + 1);

				if (fread(p, 1, len, cfgFile) != size_t(len)) {
					checkFileError(configFileName.c_str(), "fread", isc_io_read_err);
				}
				p[len] = 0;
			}
			else {
				gds__log("Audit configuration file \"%s\" is empty", configFileName.c_str());
			}

			session.ses_user = SYSDBA_USER_NAME;
			session.ses_name = "Firebird Audit";
			session.ses_flags = trs_admin | trs_system;

			addSession(session);
		}
		catch(const Exception& ex)
		{
			ISC_STATUS_ARRAY temp;
			ex.stuff_exception(temp);
			iscLogStatus("Cannot open audit configuration file", temp);
		}

		if (cfgFile) {
			fclose(cfgFile);
		}
	}
}
Example #20
0
void DirectoryList::initialize(bool simple_mode)
{
	if (mode != NotInitialized)
		return;

	clear();

	PathName val = getConfigString();

	if (simple_mode) {
		mode = SimpleList;
	}
	else
	{
		if (keyword(None, val, "None", "") || keyword(Full, val, "Full", "")) {
			return;
		}
		if (! keyword(Restrict, val, "Restrict", " \t"))
		{
			gds__log("DirectoryList: unknown parameter '%s', defaulting to None", val.c_str());
			mode = None;
			return;
		}
	}

	size_t last = 0;
	PathName root = Config::getRootDirectory();
	size_t i;
	for (i = 0; i < val.length(); i++)
	{
		if (val[i] == ';')
		{
			PathName dir = "";
			if (i > last)
			{
				dir = val.substr(last, i - last);
				dir.trim();
			}
			if (PathUtils::isRelative(dir))
			{
				PathName newdir;
				PathUtils::concatPath(newdir, root, dir);
				dir = newdir;
			}
			add(ParsedPath(dir));
			last = i + 1;
		}
	}
	PathName dir = "";
	if (i > last)
	{
		dir = val.substr(last, i - last);
		dir.trim();
	}
	if (PathUtils::isRelative(dir))
	{
		PathName newdir;
		PathUtils::concatPath(newdir, root, dir);
		dir = newdir;
	}
	add(ParsedPath(dir));
}
Example #21
0
void test_cmd(USHORT /*spb_length*/, SCHAR* /*spb*/, TEXT** /*switches*/)
{
	gds__log("test_cmd called");
}
Example #22
0
bool isGlobalKernelPrefix()
{
	// The strategy of this function is as follows: use Global\ kernel namespace
	// for engine objects if we can. This can be prevented by either lack of OS support
	// for the feature (Win9X) or lack of privileges (Vista, Windows 2000/XP restricted accounts)

	const DWORD dwVersion = GetVersion();

	// Is Windows NT running?
	if (!(dwVersion & 0x80000000))
	{
		if (LOBYTE(LOWORD(dwVersion)) <= 4) // This is Windows NT 4.0 or earlier.
			return validateProductSuite("Terminal Server");

		// Is it Windows 2000 or greater? It is possible to use Global\ prefix on any
		// version of Windows from Windows 2000 and up
		// Check if we have enough privileges to create global handles.
		// If not fall back to creating local ones.
		// The API for that is the NT thing, so we have to get addresses of the
		// functions dynamically to avoid troubles on Windows 9X platforms

		DynLibHandle hmodAdvApi(LoadLibrary("advapi32.dll"));

		if (!hmodAdvApi)
		{
			gds__log("LoadLibrary failed for advapi32.dll. Error code: %lu", GetLastError());
			return false;
		}

		typedef BOOL (WINAPI *PFnOpenProcessToken) (HANDLE, DWORD, PHANDLE);
		typedef BOOL (WINAPI *PFnLookupPrivilegeValue) (LPCSTR, LPCSTR, PLUID);
		typedef BOOL (WINAPI *PFnPrivilegeCheck) (HANDLE, PPRIVILEGE_SET, LPBOOL);

		PFnOpenProcessToken pfnOpenProcessToken =
			(PFnOpenProcessToken) GetProcAddress(hmodAdvApi, "OpenProcessToken");
		PFnLookupPrivilegeValue pfnLookupPrivilegeValue =
			(PFnLookupPrivilegeValue) GetProcAddress(hmodAdvApi, "LookupPrivilegeValueA");
		PFnPrivilegeCheck pfnPrivilegeCheck =
			(PFnPrivilegeCheck) GetProcAddress(hmodAdvApi, "PrivilegeCheck");

		if (!pfnOpenProcessToken || !pfnLookupPrivilegeValue || !pfnPrivilegeCheck)
		{
			// Should never happen, really
			gds__log("Cannot access privilege management API");
			return false;
		}

		HANDLE hProcess = GetCurrentProcess();
		HANDLE hToken;
		if (pfnOpenProcessToken(hProcess, TOKEN_QUERY, &hToken) == 0)
		{
			gds__log("OpenProcessToken failed. Error code: %lu", GetLastError());
			return false;
		}

		PRIVILEGE_SET ps;
		memset(&ps, 0, sizeof(ps));
		ps.Control = PRIVILEGE_SET_ALL_NECESSARY;
		ps.PrivilegeCount = 1;
		if (pfnLookupPrivilegeValue(NULL, TEXT("SeCreateGlobalPrivilege"), &ps.Privilege[0].Luid) == 0)
		{
			// Failure here means we're running on old version of Windows 2000 or XP
			// which always allow creating global handles
			CloseHandle(hToken);
			return true;
		}

		BOOL checkResult;
		if (pfnPrivilegeCheck(hToken, &ps, &checkResult) == 0)
		{
			gds__log("PrivilegeCheck failed. Error code: %lu", GetLastError());
			CloseHandle(hToken);
			return false;
		}

		CloseHandle(hToken);

		return checkResult;
	}

	return false;
}
Example #23
0
int CLIB_ROUTINE main( int argc, char **argv)
{
/**************************************
 *
 *      m a i n
 *
 **************************************
 *
 * Functional description
 *      The main for fbguard. This process is used to start
 *      the standalone server and keep it running after an abnormal termination.
 *
 **************************************/
	USHORT option = FOREVER;	// holds FOREVER or ONETIME  or IGNORE
	bool done = true;
	bool daemon = false;
	const TEXT* prog_name = argv[0];
	const TEXT* pidfilename = 0;
	int guard_exit_code = 0;

	const TEXT* const* const end = argc + argv;
	argv++;
	while (argv < end)
	{
		const TEXT* p = *argv++;
		if (*p++ == '-')
			switch (UPPER(*p))
			{
			case 'D':
				daemon = true;
				break;
			case 'F':
				option = FOREVER;
				break;
			case 'O':
				option = ONETIME;
				break;
			case 'S':
				option = IGNORE;
				break;
			case 'P':
				pidfilename = *argv++;
				break;
			default:
				fprintf(stderr,
						"Usage: %s [-signore | -onetime | -forever (default)] [-daemon] [-pidfile filename]\n",
						prog_name);
				exit(-1);
				break;
			}

	} // while

	// check user id
	Firebird::string user_name;		// holds the user name
	ISC_get_user(&user_name, NULL, NULL, NULL);

	if (user_name != INTERBASE_USER && user_name != "root" && user_name != FIREBIRD_USER &&
		user_name != INTERBASE_USER_SHORT)
	{
		// invalid user bail out
		fprintf(stderr, "%s: Invalid user (must be %s, %s, %s or root).\n",
				   prog_name, FIREBIRD_USER, INTERBASE_USER, INTERBASE_USER_SHORT);
		exit(-2);
	}

	// get and set the umask for the current process
	const ULONG new_mask = 0007;
	const ULONG old_mask = umask(new_mask);

	// exclusive lock the file
	int fd_guard;
	if ((fd_guard = UTIL_ex_lock(GUARD_FILE)) < 0)
	{
		// could not get exclusive lock -- some other guardian is running
		if (fd_guard == -2)
			fprintf(stderr, "%s: Program is already running.\n", prog_name);
		exit(-3);
	}

	// the umask back to orignal donot want to carry this to child process
	umask(old_mask);

	// move the server name into the argument to be passed
	TEXT process_name[1024];
	process_name[0] = '\0';
	TEXT* server_args[2];
	server_args[0] = process_name;
	server_args[1] = NULL;

	shutting_down = 0;
	if (UTIL_set_handler(SIGTERM, shutdown_handler, false) < 0)
	{
		fprintf(stderr, "%s: Cannot set signal handler (error %d).\n", prog_name, errno);
		exit(-5);
	}
	if (UTIL_set_handler(SIGINT, shutdown_handler, false) < 0)
	{
		fprintf(stderr, "%s: Cannot set signal handler (error %d).\n", prog_name, errno);
		exit(-5);
	}

	// detach from controlling tty
	if (daemon && fork()) {
		exit(0);
	}
	divorce_terminal(0);

	time_t timer = 0;

	do {
		int ret_code;

		if (shutting_down)
		{
			// don't start a child
			break;
		}

		if (timer == time(0))
		{
			// don't let server restart too often - avoid log overflow
			sleep(1);
			continue;
		}
		timer = time(0);

		pid_t child_pid =
			UTIL_start_process(SUPER_SERVER_BINARY, SUPER_CLASSIC_BINARY, server_args, prog_name);
		if (child_pid == -1)
		{
			// could not fork the server
			gds__log("%s: guardian could not start server\n", prog_name/*, process_name*/);
			fprintf(stderr, "%s: Could not start server\n", prog_name/*, process_name*/);
			UTIL_ex_unlock(fd_guard);
			exit(-4);
		}

		if (pidfilename)
		{
			FILE *pf = fopen(pidfilename, "w");
			if (pf)
			{
				fprintf(pf, "%d", child_pid);
				fclose(pf);
			}
			else
			{
				gds__log("%s: guardian could not open %s for writing, error %d\n",
						 prog_name, pidfilename, errno);
			}
		}

		// wait for child to die, and evaluate exit status
		bool shutdown_child = true;
		if (!shutting_down)
		{
			ret_code = UTIL_wait_for_child(child_pid, shutting_down);
			shutdown_child = (ret_code == -2);
		}
		if (shutting_down)
		{
			if (shutdown_child)
			{
				ret_code = UTIL_shutdown_child(child_pid, 3, 1);
				if (ret_code < 0)
				{
					gds__log("%s: error while shutting down %s (%d)\n",
							 prog_name, process_name, errno);
					guard_exit_code = -6;
				}
				else if (ret_code == 1) {
					gds__log("%s: %s killed (did not terminate)\n", prog_name, process_name);
				}
				else if (ret_code == 2) {
					gds__log("%s: unable to shutdown %s\n", prog_name, process_name);
				}
				else {
					gds__log("%s: %s terminated\n", prog_name, process_name);
				}
			}
			break;
		}
		if (ret_code != NORMAL_EXIT)
		{
			// check for startup error
			if (ret_code == STARTUP_ERROR)
			{
				gds__log("%s: %s terminated due to startup error (%d)\n",
						 prog_name, process_name, ret_code);
				if (option == IGNORE)
				{
					gds__log("%s: %s terminated due to startup error (%d)\n Trying again\n",
						 prog_name, process_name, ret_code);

					done = false;	// Try it again, Sam (even if it is a startup error) FSG 8.11.2000
				}
				else
				{
					gds__log("%s: %s terminated due to startup error (%d)\n",
							 prog_name, process_name, ret_code);

					done = true;	// do not restart we have a startup problem
				}
			}
			else
			{
				gds__log("%s: %s terminated abnormally (%d)\n", prog_name, process_name, ret_code);
				if (option == FOREVER || option == IGNORE)
					done = false;
			}
		}
		else
		{
			// Normal shutdown - don't restart the server
			gds__log("%s: %s normal shutdown.\n", prog_name, process_name);
			done = true;
		}
	} while (!done);

	if (pidfilename) {
		remove(pidfilename);
	}
	UTIL_ex_unlock(fd_guard);
	exit(guard_exit_code);
} // main