Beispiel #1
0
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);
	}
}
Beispiel #2
0
// Prints the whole chain of arguments, according to format and in the specified stream.
int MsgPrint(BaseStream& out_stream, const char* format, const SafeArg& arg, bool userFormatting)
{
	int out_bytes = 0;
	for (const char* iter = format; true; ++iter)
	{
		switch (*iter)
		{
		case 0:
			return out_bytes;

		case '@':
			switch (iter[1])
			{
			case 0:
				if (userFormatting)
					out_bytes += out_stream.write("@", 1);
				else
					out_bytes += out_stream.write("@(EOF)", 6);
				return out_bytes;
			case '@':
				out_bytes += out_stream.write(iter, 1);
				break;
			default:
				{
					const int pos = iter[1] - '0';
					if (pos > 0 && static_cast<size_t>(pos) <= arg.m_count)
						out_bytes += MsgPrintHelper(out_stream, arg.m_arguments[pos - 1]);
					else
					{
						if (userFormatting)
						{
							out_bytes += out_stream.write("@", 1);
							out_bytes += out_stream.write(iter + 1, 1);
						}
						else if (pos >= 0 && pos <= 9)
						{
							// Show the missing or out of range param number.
							out_bytes += MsgPrint(out_stream,
								"<Missing arg #@1 - possibly status vector overflow>",
								SafeArg() << pos);
						}
						else // Something not a number following @, invalid.
							out_bytes += out_stream.write("(error)", 7);
					}
				}
			}
			++iter;
			break;

		case '\\':
			switch (iter[1])
			{
			case 0:
				out_bytes += out_stream.write("\\(EOF)", 6);
				return out_bytes;
			case 'n':
				out_bytes += out_stream.write("\n", 1);
				break;
			case 't':
				out_bytes += out_stream.write("\t", 1);
				break;
			default:
				out_bytes += out_stream.write(iter, 2); // iter[0] and iter[1]
			}
			++iter;
			break;

		default:
			{
				const char* iter2 = iter;
				// Take into account the previous cases: 0, @ and backslash.
				while (iter2[1] && iter2[1] != '@' && iter2[1] != '\\')
					++iter2;

				out_bytes += out_stream.write(iter, iter2 - iter + 1);
				iter = iter2;
			}
			break;
		}
	}

	return 0;
}