Exemple #1
0
int CLIB_ROUTINE main(int argc, char* argv[])
{
/**************************************
 *
 *	m a i n
 *
 **************************************
 *
 * Functional description
 *	Invoke real gsec main function
 *
 **************************************/
#ifdef HAVE_LOCALE_H
	// Pick up the system locale to allow SYSTEM<->UTF8 conversions
	setlocale(LC_CTYPE, "");
#endif

	int exitCode = 1;

	try
	{
		Firebird::AutoPtr<Firebird::UtilSvc> uSvc(Firebird::UtilSvc::createStandalone(argc, argv));
		exitCode = gsec(uSvc);
 	}
	catch (const Firebird::Exception& ex)
 	{
 		Firebird::StaticStatusVector st;
		ex.stuffException(st);
		isc_print_status(st.begin());
 	}

	fb_shutdown(0, fb_shutrsn_app_stopped);
	return exitCode;
}
Exemple #2
0
//____________________________________________________________
//
//	An error returned has been trapped.  If the user specified
//	a status vector, return a status code.  Otherwise print the
//	error code(s) and abort.
//
static ISC_STATUS error(const Firebird::Exception& ex)
{
	Firebird::StaticStatusVector v;
	ex.stuffException(v);
	makePermanentVector(v.begin());

	if (UDSQL_error->dsql_user_status)
	{
		fb_utils::copyStatus(UDSQL_error->dsql_user_status, ISC_STATUS_LENGTH, v.begin(), v.getCount());
		return UDSQL_error->dsql_user_status[1];
	}

	fb_utils::copyStatus(UDSQL_error->dsql_status, ISC_STATUS_LENGTH, v.begin(), v.getCount());
	gds__print_status(UDSQL_error->dsql_status);
	exit(UDSQL_error->dsql_status[1]);

	return 0; // suppress compiler warning
}
Exemple #3
0
void iscLogException(const char* text, const Firebird::Exception& e)
{
/**************************************
 *
 *	i s c L o g E x c e p t i o n
 *
 **************************************
 *
 * Functional description
 *	Add record about an exception to firebird.log
 *
 **************************************/
	Firebird::StaticStatusVector s;
	e.stuffException(s);
	iscLogStatus(text, s.begin());
}
Exemple #4
0
int CLIB_ROUTINE main(int argc, char* argv[])
{
/**************************************
 *
 *	m a i n
 *
 **************************************
 *
 * Functional description
 *	Invoke real trace main function
 *
 **************************************/
#ifdef HAVE_LOCALE_H
	// Pick up the system locale to allow SYSTEM<->UTF8 conversions
	setlocale(LC_CTYPE, "");
#endif

#ifdef WIN_NT
	int binout = fileno(stdout);
	_setmode(binout, _O_BINARY);
#endif

	atexit(&atexit_fb_shutdown);

	AutoPtr<UtilSvc> uSvc(UtilSvc::createStandalone(argc, argv));
	try
	{
		TraceSvcUtil traceUtil;

 		fbtrace(uSvc, &traceUtil);
	}
	catch (const Firebird::Exception& ex)
	{
 		Firebird::StaticStatusVector temp;

		ex.stuffException(temp);
		isc_print_status(temp.begin());

		return FINI_ERROR;
	}

	return FINI_OK;
}
Exemple #5
0
int main(int ac, char** av)
{
#ifdef HAVE_LOCALE_H
	// Pick up the system locale to allow SYSTEM<->UTF8 conversions
	setlocale(LC_CTYPE, "");
#endif

	if (ac < 2 || (ac == 2 && strcmp(av[1], "-?") == 0))
	{
		usage(ac == 2);
		return 1;
	}

	if (ac == 2 && (strcmp(av[1], "-z") == 0 || strcmp(av[1], "-Z") == 0))
	{
		printMessage(51, SafeArg() << FB_VERSION);
		return 0;
	}

	os_utils::CtrlCHandler ctrlCHandler;
	atexit(&atexit_fb_shutdown);

	ISC_STATUS_ARRAY status;

	try {
		const int maxbuf = 16384;
		av++;

		const char* name = *av;
		if (name)
		{
			av++;
		}

		ClumpletWriter spbAtt(ClumpletWriter::spbList, maxbuf);
		while (populateSpbFromSwitches(av, spbAtt, attSwitch, 0))
			;

		ClumpletWriter spbStart(ClumpletWriter::SpbStart, maxbuf);
		ClumpletWriter spbItems(ClumpletWriter::SpbReceiveItems, 256);
		// single action per one utility run, it may populate info items also
		populateSpbFromSwitches(av, spbStart, actionSwitch, &spbItems);

		if (spbStart.getBufferLength() == 0)
		{
			while (populateSpbFromSwitches(av, spbItems, infSwitch, 0))
				;
		}

		// Here we are over with av parse, look - may be unknown switch left
		if (*av)
		{
			if (strcmp(av[0], "-z") == 0 || strcmp(av[0], "-Z") == 0)
			{
				printMessage(51, SafeArg() << FB_VERSION);
				++av;
			}
		}

		if (*av)
		{
			status_exception::raise(Arg::Gds(isc_fbsvcmgr_switch_unknown) << Arg::Str(*av));
		}

		isc_svc_handle svc_handle = 0;
		if (isc_service_attach(status, 0, name, &svc_handle,
					static_cast<USHORT>(spbAtt.getBufferLength()),
					reinterpret_cast<const char*>(spbAtt.getBuffer())))
		{
			isc_print_status(status);
			return 1;
		}

		if (spbStart.getBufferLength() > 0)
		{
			if (isc_service_start(status, &svc_handle, 0,
					static_cast<USHORT>(spbStart.getBufferLength()),
					reinterpret_cast<const char*>(spbStart.getBuffer())))
			{
				isc_print_status(status);
				isc_service_detach(status, &svc_handle);
				return 1;
			}
		}

		if (spbItems.getBufferLength() > 0)
		{
			if (fb_utils::isRunningCheck(spbItems.getBuffer(), spbItems.getBufferLength()))
			{
				// running service may request stdin data
				spbItems.insertTag(isc_info_svc_stdin);
			}

			// use one second timeout to poll service
			char send[16];
			char* p = send;
			*p++ = isc_info_svc_timeout;
			ADD_SPB_LENGTH(p, 4);
			ADD_SPB_NUMERIC(p, 1);
			*p++ = isc_info_end;

			char results[maxbuf];
			UserPrint uPrint;
			ULONG stdinRequest = 0;
			Array<char> stdinBuffer;
			do
			{
				char* sendBlock = send;
				USHORT sendSize = p - send;
				if (stdinRequest)
				{
					--sendSize;
					FB_SIZE_T len = sendSize;
					len += (1 + 2 + stdinRequest);
					if (len > MAX_USHORT - 1)
					{
						len = MAX_USHORT - 1;
						stdinRequest = len - (1 + 2) - sendSize;
					}
					sendBlock = stdinBuffer.getBuffer(len + 1);
					memcpy(sendBlock, send, sendSize);

					static int binIn = -1;
					if (binIn == -1)
					{
#ifdef WIN_NT
						binIn = fileno(stdin);
						_setmode(binIn, _O_BINARY);
#else
						binIn = 0;
#endif
					}

					int n = read(binIn, &sendBlock[sendSize + 1 + 2], stdinRequest);
					if (n < 0)
					{
						perror("stdin");
						break;
					}

					stdinRequest = n;
					sendBlock[sendSize] = isc_info_svc_line;
					sendBlock[sendSize + 1] = stdinRequest;
					sendBlock[sendSize + 2] = stdinRequest >> 8;
					sendBlock[sendSize + 1 + 2 + stdinRequest] = isc_info_end;
					sendSize += (1 + 2 + stdinRequest + 1);

					stdinRequest = 0;
				}

				if (isc_service_query(status, &svc_handle, 0, sendSize, sendBlock,
						static_cast<USHORT>(spbItems.getBufferLength()),
						reinterpret_cast<const char*>(spbItems.getBuffer()),
						sizeof(results), results))
				{
					if (!ctrlCHandler.getTerminated())
						isc_print_status(status);
					isc_service_detach(status, &svc_handle);
					return 1;
				}
			} while (printInfo(results, sizeof(results), uPrint, stdinRequest) && !ctrlCHandler.getTerminated());
		}

		if (isc_service_detach(status, &svc_handle))
		{
			if (!ctrlCHandler.getTerminated())
				isc_print_status(status);
			return 1;
		}
		return 0;
	}
	catch (const Exception& e)
	{
 		Firebird::StaticStatusVector st;
		e.stuffException(st);
		isc_print_status(st.begin());
	}
	return 2;
}
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);
	}
}
Exemple #7
0
void iscLogStatus(const TEXT* text, const Firebird::IStatus* status)
{
	Firebird::StaticStatusVector tmp;
	tmp.mergeStatus(status);
	iscLogStatus(text, tmp.begin());
}