コード例 #1
0
static void execute_abort( qli_nod* node)
{
/**************************************
 *
 *	e x e c u t e _ a b o r t
 *
 **************************************
 *
 * Functional description
 *	Abort a statement.
 *
 **************************************/
	if (node->nod_count)
	{
	    const TEXT* ptr = NULL;
		Firebird::VaryStr<80> temp;
		const USHORT l =
			MOVQ_get_string(EVAL_value(node->nod_arg[0]), &ptr, &temp, sizeof(temp));

		UCHAR msg[128];
		MOVQ_terminate(ptr, (SCHAR*) msg, l, sizeof(msg));
		ERRQ_error(40, SafeArg() << msg);
		// Msg40 Request terminated by statement: %s
	}

	IBERROR(41);				// Msg41 Request terminated by statement
}
コード例 #2
0
ファイル: command.cpp プロジェクト: andrewleech/firebird
void CMD_rename_proc( qli_syntax* node)
{
/**************************************
 *
 *	C M D _ r e n a m e _ p r o c
 *
 **************************************
 *
 * Functional description
 *	Rename a procedure in the named database,
 *	or the most recently readied database.
 *
 **************************************/
	qli_proc* old_proc = (qli_proc*) node->syn_arg[0];
	qli_proc* new_proc = (qli_proc*) node->syn_arg[1];

	qli_dbb* database = old_proc->qpr_database;
	if (!database)
		database = QLI_databases;

	if (new_proc->qpr_database && (new_proc->qpr_database != database))
		IBERROR(84);			// Msg84 Procedures can not be renamed across databases. Try COPY
	const qli_name* old_name = old_proc->qpr_name;
	const qli_name* new_name = new_proc->qpr_name;

	if (PRO_rename_procedure(database, old_name->nam_string, new_name->nam_string))
	{
		return;
	}

	ERRQ_error(85, SafeArg() << old_name->nam_string << database->dbb_symbol->sym_string);
	// Msg85 Procedure %s not found in database %s
}
コード例 #3
0
ファイル: tdr.cpp プロジェクト: ariska-net/firebird
static bool reconnect(FB_API_HANDLE handle, SLONG number, const TEXT* name, SINT64 switches)
{
    ISC_STATUS_ARRAY status_vector;

    const SLONG id = gds__vax_integer(reinterpret_cast<const UCHAR*>(&number), 4);
    FB_API_HANDLE transaction = 0;
    if (isc_reconnect_transaction(status_vector, &handle, &transaction,
                                  sizeof(id), reinterpret_cast<const char*>(&id)))
    {
        ALICE_print(90, SafeArg() << name);
        // msg 90: failed to reconnect to a transaction in database %s
        ALICE_print_status(true, status_vector);
        return true;
    }

    if (!(switches & (sw_commit | sw_rollback)))
    {
        ALICE_print(91, SafeArg() << number);
        // msg 91: Transaction %ld:
        switches = ask();
        if (switches == ~SINT64(0))
        {
            ALICE_print(84);
            // msg 84: unexpected end of input
            return true;
        }
    }

    if (switches & sw_commit)
        isc_commit_transaction(status_vector, &transaction);
    else if (switches & sw_rollback)
        isc_rollback_transaction(status_vector, &transaction);
    else
        return false;

    if (status_vector[1])
    {
        ALICE_print_status(true, status_vector);
        return true;
    }

    return false;
}
コード例 #4
0
ファイル: command.cpp プロジェクト: andrewleech/firebird
void CMD_extract( qli_syntax* node)
{
/**************************************
 *
 *	C M D _ e x t r a c t
 *
 **************************************
 *
 * Functional description
 *	Extract a series of procedures.
 *
 **************************************/
	FILE* file = (FILE*) EXEC_open_output((qli_nod*) node->syn_arg[1]);

	qli_syntax* list = node->syn_arg[0];
	if (list)
	{
		qli_syntax** ptr = list->syn_arg;
		for (const qli_syntax* const* const end = ptr + list->syn_count; ptr < end; ptr++)
		{
			qli_proc* proc = (qli_proc*) *ptr;
			qli_dbb* database = proc->qpr_database;
			if (!database)
				database = QLI_databases;

			const qli_name* name = proc->qpr_name;
			FB_API_HANDLE blob = PRO_fetch_procedure(database, name->nam_string);
			if (!blob)
			{
				ERRQ_msg_put(89, SafeArg() << name->nam_string << database->dbb_symbol->sym_string);
				// Msg89 Procedure %s not found in database %s
				continue;
			}
			dump_procedure(database, file, name->nam_string, name->nam_length, blob);
		}
	}
	else
	{
		CMD_check_ready();
		for (qli_dbb* database = QLI_databases; database; database = database->dbb_next)
		{
			PRO_scan(database, extract_procedure, file);
		}
	}

#ifdef WIN_NT
	if (((qli_nod*) node->syn_arg[1])->nod_arg[e_out_pipe])
		_pclose(file);
	else
#endif
		fclose(file);
}
コード例 #5
0
ファイル: dtr.cpp プロジェクト: mp-lee/core
static bool yes_no(USHORT number, const TEXT* arg1)
{
/**************************************
 *
 *	y e s _ n o
 *
 **************************************
 *
 * Functional description
 *	Put out a prompt that expects a yes/no
 *	answer, and keep trying until we get an
 *	acceptable answer (e.g. y, Yes, N, etc.)
 *
 **************************************/
	TEXT prompt[256];

	ERRQ_msg_format(number, sizeof(prompt), prompt, SafeArg() << arg1);

	if (!yes_no_loaded)
	{
		yes_no_loaded = true;
		// Msg498 NO
		if (!ERRQ_msg_get(498, answer_table[0].answer, sizeof(answer_table[0].answer)))
			strcpy(answer_table[0].answer, "NO");	// default if msg_get fails

		// Msg497 YES
		if (!ERRQ_msg_get(497, answer_table[1].answer, sizeof(answer_table[1].answer)))
			strcpy(answer_table[1].answer, "YES");
	}

	TEXT buffer[256];
	while (true)
	{
		buffer[0] = 0;
		if (!LEX_get_line(prompt, buffer, sizeof(buffer)))
			return true;
		for (const answer_t* response = answer_table; *response->answer != '\0'; response++)
		{
			const TEXT* p = buffer;
			while (*p == ' ')
				p++;
			if (*p == EOF)
				return true;
			for (const TEXT* q = response->answer; *p && UPPER(*p) == *q++; p++)
				;
			if (!*p || *p == '\n')
				return response->value;
		}
	}
}
コード例 #6
0
ファイル: err.cpp プロジェクト: Alexpux/firebird
void ERRQ_print_error(USHORT number, const char* str)
{
/**************************************
 *
 *	E R R Q _ p r i n t _ e r r o r
 *
 **************************************
 *
 * Functional description
 *	An error has occurred.  Put out an error message and
 *	unwind.
 *
 **************************************/

	ERRQ_error(number, SafeArg() << str);
}
コード例 #7
0
ファイル: err.cpp プロジェクト: Alexpux/firebird
void ERRQ_msg_put(USHORT number, const char* str)
{
/**************************************
 *
 *	E R R Q _ m s g _ p u t
 *
 **************************************
 *
 * Functional description
 *	Retrieve a message from the error file, format it, and print it
 * It's same outcome as ERRQ_msg_partial but with a newline at the end.
 *
 **************************************/

	fb_msg_format(0, QLI_MSG_FAC, number, sizeof(ERRQ_message), ERRQ_message, SafeArg() << str);
	printf("%s\n", ERRQ_message);
}
コード例 #8
0
ファイル: err.cpp プロジェクト: Alexpux/firebird
void ERRQ_error(USHORT number, const char* str)
{
/**************************************
 *
 *	E R R Q _ e r r o r
 *
 **************************************
 *
 * Functional description
 *	An error has occurred.  Put out an error message and
 *	unwind.  If this was called before the unwind path
 *	was established, don't unwind just print error and exit.
 *
 **************************************/

	ERRQ_error(number, SafeArg() << str);
}
コード例 #9
0
ファイル: err.cpp プロジェクト: Alexpux/firebird
void ERRQ_bugcheck( USHORT number)
{
/**************************************
 *
 *	E R R Q _ b u g c h e c k
 *
 **************************************
 *
 * Functional description
 *	Somebody has screwed up.  Bugcheck.
 *
 **************************************/
	TEXT s[256];

	ERRQ_msg_format(number, sizeof(s), s);
	ERRQ_error(9, SafeArg() << s);	// Msg9 INTERNAL: %s
}
コード例 #10
0
ファイル: tdr.cpp プロジェクト: ariska-net/firebird
bool TDR_attach_database(ISC_STATUS* status_vector, tdr* trans, const TEXT* pathname)
{
    AliceGlobals* tdgbl = AliceGlobals::getSpecific();

    if (tdgbl->ALICE_data.ua_debug)
        ALICE_print(68, SafeArg() << pathname); // msg 68: ATTACH_DATABASE: attempted attach of %s

    Firebird::ClumpletWriter dpb(Firebird::ClumpletReader::Tagged, MAX_DPB_SIZE, isc_dpb_version1);
    dpb.insertTag(isc_dpb_no_garbage_collect);
    dpb.insertTag(isc_dpb_gfix_attach);
    tdgbl->uSvc->fillDpb(dpb);
    if (tdgbl->ALICE_data.ua_user) {
        dpb.insertString(isc_dpb_user_name, tdgbl->ALICE_data.ua_user, fb_strlen(tdgbl->ALICE_data.ua_user));
    }
    if (tdgbl->ALICE_data.ua_password)
    {
        dpb.insertString(tdgbl->uSvc->isService() ? isc_dpb_password_enc : isc_dpb_password,
                         tdgbl->ALICE_data.ua_password, fb_strlen(tdgbl->ALICE_data.ua_password));
    }

    trans->tdr_db_handle = 0;

    isc_attach_database(status_vector, 0, pathname,
                        &trans->tdr_db_handle, dpb.getBufferLength(),
                        reinterpret_cast<const char*>(dpb.getBuffer()));

    if (status_vector[1])
    {
        if (tdgbl->ALICE_data.ua_debug)
        {
            ALICE_print(69);	// msg 69:  failed
            ALICE_print_status(false, status_vector);
        }
        return false;
    }

    MET_set_capabilities(status_vector, trans);

    if (tdgbl->ALICE_data.ua_debug)
        ALICE_print(70);	// msg 70:  succeeded

    return true;
}
コード例 #11
0
ファイル: err.cpp プロジェクト: Alexpux/firebird
void ERRQ_syntax( USHORT number)
{
/**************************************
 *
 *	E R R Q _ s y n t a x
 *
 **************************************
 *
 * Functional description
 *	Syntax error has occurred.  Give some hint of what went
 *	wrong.
 *
 **************************************/
	TEXT s[256];

	ERRQ_msg_format(number, sizeof(s), s);
	ERRQ_error(13, SafeArg() << s << QLI_token->tok_string);
	// Msg13 expected %s, encountered %s
}
コード例 #12
0
ファイル: err.cpp プロジェクト: Alexpux/firebird
void ERRQ_error_format(USHORT number, const SafeArg& arg)
{
/**************************************
 *
 *	E R R Q _ e r r o r _ f o r m a t
 *
 **************************************
 *
 * Functional description
 *	Retrieve a message from the error file and format it
 *      in the standard qli error format, put it where
 *      ERRQ_pending expects to find it.
 **************************************/
	TEXT s[256];

	fb_msg_format(0, QLI_MSG_FAC, number, sizeof(s), s, arg);
	fb_msg_format(0, QLI_MSG_FAC, 12, sizeof(ERRQ_message), ERRQ_message, SafeArg() << s);
	// Msg12 ** QLI error: %s **
	QLI_error = ERRQ_message;
	QLI_skip_line = true;
}
コード例 #13
0
ファイル: command.cpp プロジェクト: andrewleech/firebird
void CMD_delete_proc( qli_syntax* node)
{
/**************************************
 *
 *	C M D _ d e l e t e _ p r o c
 *
 **************************************
 *
 * Functional description
 *	Delete a procedure in the named database
 *	or in the most recently readied database.
 *
 **************************************/
	qli_proc* proc = (qli_proc*) node->syn_arg[0];

	if (!proc->qpr_database)
		proc->qpr_database = QLI_databases;

	if (PRO_delete_procedure(proc->qpr_database, proc->qpr_name->nam_string))
		return;

	ERRQ_msg_put(88, SafeArg() << proc->qpr_name->nam_string <<	// Msg88 Procedure %s not found in database %s
				 proc->qpr_database->dbb_symbol->sym_string);
}
コード例 #14
0
ファイル: alice.cpp プロジェクト: ASSmodeus/dsploit
int alice(Firebird::UtilSvc* uSvc)
{
	AliceGlobals gblInstance(uSvc);
	AliceGlobals* tdgbl = &gblInstance;
	AliceGlobals::putSpecific(tdgbl);
	int exit_code = FINI_ERROR;

	try {

//  Perform some special handling when run as a Firebird service.  The
//  first switch can be "-svc" (lower case!) or it can be "-svc_re" followed
//  by 3 file descriptors to use in re-directing stdin, stdout, and stderr.

	tdgbl->ALICE_data.ua_user = NULL;
	tdgbl->ALICE_data.ua_password = NULL;
#ifdef TRUSTED_AUTH
	tdgbl->ALICE_data.ua_trusted = false;
#endif
	tdgbl->ALICE_data.ua_tr_user = NULL;
	tdgbl->ALICE_data.ua_tr_role = false;

//  Start by parsing switches

	bool error = false, help = false;
	SINT64 flags = 0;
	tdgbl->ALICE_data.ua_shutdown_delay = 0;
	const TEXT* database = NULL;
	TEXT	string[512];

	const char** argv = uSvc->argv.begin();
	int argc = uSvc->argv.getCount();
	++argv;

	// tested outside the loop
	const in_sw_tab_t* table = alice_in_sw_table;

	while (--argc > 0)
	{
		if ((*argv)[0] != '-')
		{
			if (database)
			{
				ALICE_error(1, SafeArg() << database);
				// msg 1: "data base file name (%s) already given",
			}
			database = *argv++;

			continue;
		}

		ALICE_down_case(*argv++, string, sizeof(string));
		if (!string[1]) {
			continue;
		}
		if (strcmp(string, "-?") == 0)
		{
			error = help = true;
			break;
		}

		for (table = alice_in_sw_table; true; ++table)
		{
			const TEXT* p = (TEXT*) table->in_sw_name;
			if (!p)
			{
				ALICE_print(2, SafeArg() << (*--argv));	// msg 2: invalid switch %s
				error = true;
				break;
			}

			TEXT* q = &string[1];
			while (*q && *p++ == *q)
			{
				q++;
			}
			if (!*q && (q - &string[1] >= table->in_sw_min_length))
			{
				break;
			}
		}
		if (error) {
			break;
		}
		if (*table->in_sw_name == 'x') {
			tdgbl->ALICE_data.ua_debug++;
		}
        if (table->in_sw_value & sw_trusted_svc)
        {
			uSvc->checkService();
			if (--argc <= 0) {
				ALICE_error(13);	// msg 13: user name required
			}
			tdgbl->ALICE_data.ua_tr_user = *argv++;
			continue;
		}
        if (table->in_sw_value & sw_trusted_role)
        {
			uSvc->checkService();
			tdgbl->ALICE_data.ua_tr_role = true;
			continue;
		}
#ifdef TRUSTED_AUTH
        if (table->in_sw_value & sw_trusted_auth)
        {
			tdgbl->ALICE_data.ua_trusted = true;
			continue;
		}
#endif
		if (table->in_sw_value == sw_z) {
			ALICE_print(3, SafeArg() << GDS_VERSION);	// msg 3: gfix version %s
		}
		if ((table->in_sw_incompatibilities & flags) ||
			(table->in_sw_requires && !(table->in_sw_requires & flags)))
		{
			ALICE_print(4);	// msg 4: incompatible switch combination
			error = true;
			break;
		}
		flags |= table->in_sw_value;

		if ((table->in_sw_value & (sw_shut | sw_online)) && (argc > 1))
		{
			ALICE_down_case(*argv, string, sizeof(string));
			bool found = true;
			if (strcmp(string, "normal") == 0)
				tdgbl->ALICE_data.ua_shutdown_mode = SHUT_NORMAL;
			else if (strcmp(string, "multi") == 0)
				tdgbl->ALICE_data.ua_shutdown_mode = SHUT_MULTI;
			else if (strcmp(string, "single") == 0)
				tdgbl->ALICE_data.ua_shutdown_mode = SHUT_SINGLE;
			else if (strcmp(string, "full") == 0)
				tdgbl->ALICE_data.ua_shutdown_mode = SHUT_FULL;
			else
				found = false;
			// Consume argument only if we identified mode
			// Let's hope that database with names of modes above are unusual
			if (found)
			{
				argv++;
				argc--;
			}
		}

#ifdef DEV_BUILD
		/*
		if (table->in_sw_value & sw_begin_log)
		{
			if (--argc <= 0) {
				ALICE_error(5);	// msg 5: replay log pathname required
			}
			fb_utils::copy_terminate(tdgbl->ALICE_data.ua_log_file, *argv++, sizeof(tdgbl->ALICE_data.ua_log_file));
		}
		*/
#endif

		if (table->in_sw_value & sw_buffers)
		{
			if (--argc <= 0) {
				ALICE_error(6);	// msg 6: number of page buffers for cache required
			}
			ALICE_down_case(*argv++, string, sizeof(string));
			if ((!(tdgbl->ALICE_data.ua_page_buffers = atoi(string))) && (strcmp(string, "0")))
			{
				ALICE_error(7);	// msg 7: numeric value required
			}
			if (tdgbl->ALICE_data.ua_page_buffers < 0) {
				ALICE_error(114);	// msg 114: positive or zero numeric value required
			}
		}

		if (table->in_sw_value & sw_housekeeping)
		{
			if (--argc <= 0) {
				ALICE_error(9);	// msg 9: number of transactions per sweep required
			}
			ALICE_down_case(*argv++, string, sizeof(string));
			if ((!(tdgbl->ALICE_data.ua_sweep_interval = atoi(string))) && (strcmp(string, "0")))
			{
				ALICE_error(7);	// msg 7: numeric value required
			}
			if (tdgbl->ALICE_data.ua_sweep_interval < 0) {
				ALICE_error(114);	// msg 114: positive or zero numeric value required
			}
		}

		if (table->in_sw_value & sw_set_db_dialect)
		{
			if (--argc <= 0) {
				ALICE_error(113);	// msg 113: dialect number required
			}

			ALICE_down_case(*argv++, string, sizeof(string));

			if ((!(tdgbl->ALICE_data.ua_db_SQL_dialect = atoi(string))) && (strcmp(string, "0")))
			{
				ALICE_error(7);	// msg 7: numeric value required
			}

			// JMB: Removed because tdgbl->ALICE_data.ua_db_SQL_dialect is
			//		an unsigned number.  Therefore this check is useless.
			// if (tdgbl->ALICE_data.ua_db_SQL_dialect < 0)
			// {
			//	ALICE_error(114);	// msg 114: positive or zero numeric value required
			// }
		}

		if (table->in_sw_value & (sw_commit | sw_rollback | sw_two_phase))
		{
			if (--argc <= 0) {
				ALICE_error(10);	// msg 10: transaction number or "all" required
			}
			ALICE_down_case(*argv++, string, sizeof(string));
			if (!(tdgbl->ALICE_data.ua_transaction = atoi(string)))
			{
				if (strcmp(string, "all")) {
					ALICE_error(10);	// msg 10: transaction number or "all" required
				}
				else {
					flags |= sw_list;
				}
			}
		}

		if (table->in_sw_value & sw_write)
		{
			if (--argc <= 0) {
				ALICE_error(11);	// msg 11: "sync" or "async" required
			}
			ALICE_down_case(*argv++, string, sizeof(string));
			if (!strcmp(string, ALICE_SW_SYNC)) {
				tdgbl->ALICE_data.ua_force = true;
			}
			else if (!strcmp(string, ALICE_SW_ASYNC)) {
				tdgbl->ALICE_data.ua_force = false;
			}
			else {
				ALICE_error(11);	// msg 11: "sync" or "async" required
			}
		}

		if (table->in_sw_value & sw_no_reserve)
		{
			if (--argc <= 0) {
				ALICE_error(12);	// msg 12: "full" or "reserve" required
			}
			ALICE_down_case(*argv++, string, sizeof(string));
			if (!strcmp(string, "full")) {
				tdgbl->ALICE_data.ua_no_reserve = true;
			}
			else if (!strcmp(string, "reserve")) {
				tdgbl->ALICE_data.ua_no_reserve = false;
			}
			else {
				ALICE_error(12);	// msg 12: "full" or "reserve" required
			}
		}

		if (table->in_sw_value & sw_user)
		{
			if (--argc <= 0) {
				ALICE_error(13);	// msg 13: user name required
			}
			tdgbl->ALICE_data.ua_user = *argv++;
		}

		if (table->in_sw_value & sw_password)
		{
			if (--argc <= 0) {
				ALICE_error(14);	// msg 14: password required
			}
			uSvc->hidePasswd(uSvc->argv, argv - uSvc->argv.begin());
			tdgbl->ALICE_data.ua_password = *argv++;
		}

		if (table->in_sw_value & sw_fetch_password)
		{
			if (--argc <= 0) {
				ALICE_error(14);	// msg 14: password required
			}
			switch (fb_utils::fetchPassword(*argv, tdgbl->ALICE_data.ua_password))
			{
			case fb_utils::FETCH_PASS_OK:
				break;
			case fb_utils::FETCH_PASS_FILE_OPEN_ERROR:
				ALICE_error(116, MsgFormat::SafeArg() << *argv << errno);
				// error @2 opening password file @1
				break;
			case fb_utils::FETCH_PASS_FILE_READ_ERROR:
				ALICE_error(117, MsgFormat::SafeArg() << *argv << errno);
				// error @2 reading password file @1
				break;
			case fb_utils::FETCH_PASS_FILE_EMPTY:
				ALICE_error(118, MsgFormat::SafeArg() << *argv);
				// password file @1 is empty
				break;
			}
			++argv;
		}

		if (table->in_sw_value & sw_disable)
		{
			if (--argc <= 0) {
				ALICE_error(15);	// msg 15: subsystem name
			}
			ALICE_down_case(*argv++, string, sizeof(string));
			if (strcmp(string, "wal")) {
				ALICE_error(16);	// msg 16: "wal" required
			}
		}

		if (table->in_sw_value & (sw_attach | sw_force | sw_tran | sw_cache))
		{
			if (--argc <= 0) {
				ALICE_error(17);	// msg 17: number of seconds required
			}
			ALICE_down_case(*argv++, string, sizeof(string));
			if ((!(tdgbl->ALICE_data.ua_shutdown_delay = atoi(string))) && (strcmp(string, "0")))
			{
				ALICE_error(7);	// msg 7: numeric value required
			}
			if (tdgbl->ALICE_data.ua_shutdown_delay < 0 ||
				tdgbl->ALICE_data.ua_shutdown_delay > 32767)
			{
				ALICE_error(18);	// msg 18: numeric value between 0 and 32767 inclusive required
			}
		}

		if (table->in_sw_value & sw_mode)
		{
			if (--argc <= 0) {
				ALICE_error(110);	// msg 110: "read_only" or "read_write" required
			}
			ALICE_down_case(*argv++, string, sizeof(string));
			if (!strcmp(string, ALICE_SW_MODE_RO)) {
				tdgbl->ALICE_data.ua_read_only = true;
			}
			else if (!strcmp(string, ALICE_SW_MODE_RW)) {
				tdgbl->ALICE_data.ua_read_only = false;
			}
			else {
				ALICE_error(110);	// msg 110: "read_only" or "read_write" required
			}
		}

	}

//  put this here since to put it above overly complicates the parsing
//  can't use tbl_requires since it only looks backwards on command line
	if ((flags & sw_shut) && !(flags & ((sw_attach | sw_force | sw_tran | sw_cache))))
	{
		ALICE_error(19);	// msg 19: must specify type of shutdown
	}

//  catch the case where -z is only command line option
//  flags is unset since sw_z == 0
	if (!flags && !error && table->in_sw_value == sw_z) {
		ALICE_exit(FINI_OK, tdgbl);
	}

	if (!flags || !(flags & ~(sw_user | sw_password | sw_fetch_password |
								sw_trusted_auth | sw_trusted_svc | sw_trusted_role)))
	{
		if (!help && !uSvc->isService())
		{
			ALICE_print(20);	// msg 20: please retry, specifying an option
		}
		error = true;
	}

	if (error)
	{
		if (uSvc->isService())
		{
			uSvc->setServiceStatus(ALICE_MSG_FAC, 20, MsgFormat::SafeArg());
		}
		else
		{
			if (help)
				ALICE_print(120); // usage: gfix [options] <database>
			ALICE_print(21);	// msg 21: plausible options are:
			for (table = alice_in_sw_table; table->in_sw_name; table++)
			{
				if (table->in_sw_msg)
					ALICE_print(table->in_sw_msg);
			}
			ALICE_print(22);	// msg 22: \n    qualifiers show the major option in parenthesis
		}
		ALICE_exit(FINI_ERROR, tdgbl);
	}

	if (!database) {
		ALICE_error(23);	// msg 23: please retry, giving a database name
	}

	//  generate the database parameter block for the attach,
	//  based on the various flags

	USHORT ret;

	if (flags & (sw_list | sw_commit | sw_rollback | sw_two_phase))
	{
		ret = EXE_two_phase(database, flags);
	}
	else
	{
		ret = EXE_action(database, flags);

		const SLONG* ua_val_errors = tdgbl->ALICE_data.ua_val_errors;

		if (!ua_val_errors[VAL_INVALID_DB_VERSION])
		{
			bool any_error = false;

			for (int i = 0; i < MAX_VAL_ERRORS; ++i)
			{
				if (ua_val_errors[i])
				{
					any_error = true;
					break;
				}
			}

			if (any_error)
			{
				ALICE_print(24);	// msg 24: Summary of validation errors\n

				for (int i = 0; i < MAX_VAL_ERRORS; ++i)
				{
					if (ua_val_errors[i]) {
						ALICE_print(val_err_table[i], SafeArg() << ua_val_errors[i]);
					}
				}
			}
		}
	}

	if (ret == FINI_ERROR)
	{
		ALICE_print_status(true, tdgbl->status);
		ALICE_exit(FINI_ERROR, tdgbl);
	}

	ALICE_exit(FINI_OK, tdgbl);

	}	// try

	catch (const Firebird::LongJump&)
	{
		// All "calls" to ALICE_exit(), normal and error exits, wind up here
		exit_code = tdgbl->exit_code;
	}

	catch (const Firebird::Exception& e)
	{
		// Non-alice exception was caught
		e.stuff_exception(tdgbl->status_vector);
		ALICE_print_status(true, tdgbl->status_vector);
		exit_code = FINI_ERROR;
	}

	AliceGlobals::restoreSpecific();

#if defined(DEBUG_GDS_ALLOC)
	if (!uSvc->isService())
	{
		gds_alloc_report(0, __FILE__, __LINE__);
	}
#endif

	if ((exit_code != FINI_OK) && uSvc->isService())
	{
		uSvc->initStatus();
		uSvc->setServiceStatus(tdgbl->status);
	}
	tdgbl->uSvc->started();

	return exit_code;
}
コード例 #15
0
ファイル: lex.cpp プロジェクト: narolez571/firebird
qli_tok* LEX_token()
{
/**************************************
 *
 *	L E X _ t o k e n
 *
 **************************************
 *
 * Functional description
 *	Parse and return the next token.
 *
 **************************************/
	qli_tok* token = QLI_token;
	TEXT* p = token->tok_string;

	// Get next significant byte.  If it's the last EOL of a blob, throw it away

	SSHORT c;

	for (;;)
	{
		c = skip_white();
		if (c != '\n' || QLI_line->line_type != line_blob)
			break;
		qli_line* prior = QLI_line;
		next_line(true);
		if (prior == QLI_line)
			break;
	}

	// If we hit end of file, make up a phoney token

	if (!QLI_line)
	{
		const TEXT* q = eof_string;
		while (*p++ = *q++);
		token->tok_type = tok_eof;
		token->tok_keyword = KW_none;
		return NULL;
	}

	*p++ = c;
	QLI_token->tok_position = QLI_line->line_position + QLI_line->line_ptr - QLI_line->line_data - 1;

	// On end of file, generate furious but phone end of line tokens

	char char_class = classes(c);

	if (char_class & CHR_letter)
	{
		for (c = nextchar(true); classes(c) & CHR_ident; c = nextchar(true))
			*p++ = c;
		retchar();
		token->tok_type = tok_ident;
	}
	else if (((char_class & CHR_digit) || c == '.') && scan_number(c, &p))
		token->tok_type = tok_number;
	else if (char_class & CHR_quote)
	{
		token->tok_type = tok_quoted;
		while (true)
		{
			const SSHORT next = nextchar(false);
			if (!next || next == '\n')
			{
				retchar();
				IBERROR(63);	// Msg 63 unterminated quoted string
				break;
			}
			*p++ = next;
			if ((p - token->tok_string) >= MAXSYMLEN)
				ERRQ_msg_put(470, SafeArg() << MAXSYMLEN);	// Msg 470 literal too long

			// If there are 2 quotes in a row, interpret 2nd as a literal

			if (next == c)
			{
				const SSHORT peek = nextchar(false);
				retchar();
				if (peek != c)
					break;
				nextchar(false);
			}
		}
	}
	else if (c == '\n')
	{
	    // end of line, signal it properly with a phoney token.
		token->tok_type = tok_eol;
		--p;
		const TEXT* q = eol_string;
		while (*q)
			*p++ = *q++;
	}
	else
	{
		token->tok_type = tok_punct;
		*p++ = nextchar(true);
		if (!HSH_lookup(token->tok_string, 2))
		{
			retchar();
			--p;
		}
	}

	token->tok_length = p - token->tok_string;
	*p = '\0';

	if (token->tok_string[0] == '$' && trans_limit < TRANS_LIMIT)
	{
		Firebird::string s;
		if (fb_utils::readenv(token->tok_string + 1, s))
		{
			LEX_push_string(s.c_str());
			++trans_limit;
			token = LEX_token();
			--trans_limit;
			return token;
		}
	}

    qli_symbol* symbol = HSH_lookup(token->tok_string, token->tok_length);
	token->tok_symbol = symbol;
	if (symbol && symbol->sym_type == SYM_keyword)
		token->tok_keyword = (kwwords) symbol->sym_keyword;
	else
		token->tok_keyword = KW_none;

	if (sw_trace)
		puts(token->tok_string);

	return token;
}
コード例 #16
0
ファイル: tdr.cpp プロジェクト: ariska-net/firebird
static void reattach_database(tdr* trans)
{
    ISC_STATUS_ARRAY status_vector;
    char buffer[1024];
    // sizeof(buffer) - 1 => leave space for the terminator.
    const char* const end = buffer + sizeof(buffer) - 1;
    AliceGlobals* tdgbl = AliceGlobals::getSpecific();

    ISC_get_host(buffer, sizeof(buffer));

    if (trans->tdr_fullpath)
    {
        // if this is being run from the same host,
        // try to reconnect using the same pathname

        if (!strcmp(buffer, reinterpret_cast<const char*>(trans->tdr_host_site->str_data)))
        {
            if (TDR_attach_database(status_vector, trans,
                                    reinterpret_cast<char*>(trans->tdr_fullpath->str_data)))
            {
                return;
            }
        }
        else if (trans->tdr_host_site)
        {
            //  try going through the previous host with all available
            //  protocols, using chaining to try the same method of
            //  attachment originally used from that host
            char* p = buffer;
            const UCHAR* q = trans->tdr_host_site->str_data;
            while (*q && p < end)
                *p++ = *q++;
            *p++ = ':';
            q = trans->tdr_fullpath->str_data;
            while (*q && p < end)
                *p++ = *q++;
            *p = 0;
            if (TDR_attach_database(status_vector, trans, buffer))
            {
                return;
            }
        }

        // attaching using the old method didn't work;
        // try attaching to the remote node directly

        if (trans->tdr_remote_site)
        {
            char* p = buffer;
            const UCHAR* q = trans->tdr_remote_site->str_data;
            while (*q && p < end)
                *p++ = *q++;
            *p++ = ':';
            q = reinterpret_cast<const UCHAR*>(trans->tdr_filename);
            while (*q && p < end)
                *p++ = *q++;
            *p = 0;
            if (TDR_attach_database (status_vector, trans, buffer))
            {
                return;
            }
        }

    }
    // we have failed to reattach; notify the user
    // and let them try to succeed where we have failed

    ALICE_print(86, SafeArg() << trans->tdr_id);
    // msg 86: Could not reattach to database for transaction %ld.
    ALICE_print(87, SafeArg() << (trans->tdr_fullpath ? (char*)(trans->tdr_fullpath->str_data) : "is unknown"));
    // msg 87: Original path: %s

    if (tdgbl->uSvc->isService())
    {
        ALICE_exit(FINI_ERROR, tdgbl);
    }

    for (;;)
    {
        ALICE_print(88);	// msg 88: Enter a valid path:
        char* p = buffer;
        while (p < end && (*p = getchar()) != '\n' && !feof(stdin) && !ferror(stdin))
            ++p;
        *p = 0;
        if (!buffer[0])
            break;
        p = buffer;
        while (*p == ' ')
            ++p;
        if (TDR_attach_database(status_vector, trans, p))
        {
            const size_t p_len = strlen(p);
            alice_str* string = FB_NEW_RPT(*tdgbl->getDefaultPool(), p_len + 1) alice_str;
            strcpy(reinterpret_cast<char*>(string->str_data), p);
            string->str_length = static_cast<USHORT>(p_len);
            trans->tdr_fullpath = string;
            trans->tdr_filename = (TEXT *) string->str_data;
            return;
        }
        ALICE_print(89);	// msg 89: Attach unsuccessful.
    }
}
コード例 #17
0
ファイル: tdr.cpp プロジェクト: ariska-net/firebird
USHORT TDR_analyze(const tdr* trans)
{
    if (trans == NULL)
        return TRA_none;

    // if the tdr for the first transaction is missing,
    // we can assume it was committed

    USHORT advice = TRA_none;
    USHORT state = trans->tdr_state;
    if (state == TRA_none)
        state = TRA_commit;
    else if (state == TRA_unknown)
        advice = TRA_unknown;

    for (trans = trans->tdr_next; trans; trans = trans->tdr_next)
    {
        switch (trans->tdr_state)
        {
        // an explicitly committed transaction necessitates a check for the
        // perverse case of a rollback, otherwise a commit if at all possible

        case TRA_commit:
            if (state == TRA_rollback)
            {
                ALICE_print(105);
                // msg 105: Warning: Multidatabase transaction is in inconsistent state for recovery.
                ALICE_print(106, SafeArg() << trans->tdr_id);
                // msg 106: Transaction %ld was committed, but prior ones were rolled back.
                return 0;
            }
            else
                advice = TRA_commit;
            break;

        // a prepared transaction requires a commit if there are missing
        // records up to now, otherwise only do something if somebody else
        // already has

        case TRA_limbo:
            switch (state)
            {
            case TRA_none:
            case TRA_commit:
                advice = TRA_commit;
                break;
            case TRA_rollback:
                advice = TRA_rollback;
                break;
            }
            break;

        // an explicitly rolled back transaction requires a rollback unless a
        // transaction has committed or is assumed committed

        case TRA_rollback:
            if ((state == TRA_commit) || (state == TRA_none))
            {
                ALICE_print(105);
                // msg 105: Warning: Multidatabase transaction is in inconsistent state for recovery.
                ALICE_print(107, SafeArg() << trans->tdr_id);
                // msg 107: Transaction %ld was rolled back, but prior ones were committed.

                return 0;
            }
            advice = TRA_rollback;
            break;

        // a missing TDR indicates a committed transaction if a limbo one hasn't
        // been found yet, otherwise it implies that the transaction wasn't
        // prepared

        case TRA_none:
            if (state == TRA_commit)
                advice = TRA_commit;
            else if (state == TRA_limbo)
                advice = TRA_rollback;
            break;

        // specifically advise TRA_unknown to prevent assumption that all are
        // in limbo

        case TRA_unknown:
            if (!advice)
                advice = TRA_unknown;
            break;

        default:
            ALICE_print(67, SafeArg() << trans->tdr_state);
            // msg 67: Transaction state %d not in valid range.
            return 0;
        }
    }

    return advice;
}
コード例 #18
0
ファイル: tdr.cpp プロジェクト: ariska-net/firebird
static void print_description(const tdr* trans)
{
    AliceGlobals* tdgbl = AliceGlobals::getSpecific();

    if (!trans)
    {
        return;
    }

    if (!tdgbl->uSvc->isService())
    {
        ALICE_print(92);	// msg 92:   Multidatabase transaction:
    }

    bool prepared_seen = false;
    for (const tdr* ptr = trans; ptr; ptr = ptr->tdr_next)
    {
        if (ptr->tdr_host_site)
        {
            const char* pszHostSize = reinterpret_cast<const char*>(ptr->tdr_host_site->str_data);

            if (!tdgbl->uSvc->isService())
            {
                // msg 93: Host Site: %s
                ALICE_print(93, SafeArg() << pszHostSize);
            }
            tdgbl->uSvc->putLine(isc_spb_tra_host_site, pszHostSize);
        }

        if (ptr->tdr_id)
        {
            if (!tdgbl->uSvc->isService())
            {
                // msg 94: Transaction %ld
                ALICE_print(94, SafeArg() << ptr->tdr_id);
            }
            tdgbl->uSvc->putSLong(isc_spb_tra_id, ptr->tdr_id);
        }

        switch (ptr->tdr_state)
        {
        case TRA_limbo:
            if (!tdgbl->uSvc->isService())
            {
                ALICE_print(95);	// msg 95: has been prepared.
            }
            tdgbl->uSvc->putChar(isc_spb_tra_state, isc_spb_tra_state_limbo);
            prepared_seen = true;
            break;

        case TRA_commit:
            if (!tdgbl->uSvc->isService())
            {
                ALICE_print(96);	// msg 96: has been committed.
            }
            tdgbl->uSvc->putChar(isc_spb_tra_state, isc_spb_tra_state_commit);
            break;

        case TRA_rollback:
            if (!tdgbl->uSvc->isService())
            {
                ALICE_print(97);	// msg 97: has been rolled back.
            }
            tdgbl->uSvc->putChar(isc_spb_tra_state, isc_spb_tra_state_rollback);
            break;

        case TRA_unknown:
            if (!tdgbl->uSvc->isService())
            {
                ALICE_print(98);	// msg 98: is not available.
            }
            tdgbl->uSvc->putChar(isc_spb_tra_state, isc_spb_tra_state_unknown);
            break;

        default:
            if (!tdgbl->uSvc->isService())
            {
                // msg 99: is not found, assumed not prepared.
                // msg 100: is not found, assumed to be committed.
                ALICE_print(prepared_seen ? 99 : 100);
            }
            break;
        }

        if (ptr->tdr_remote_site)
        {
            const char* pszRemoteSite = reinterpret_cast<const char*>(ptr->tdr_remote_site->str_data);

            if (!tdgbl->uSvc->isService())
            {
                // msg 101: Remote Site: %s
                ALICE_print(101, SafeArg() << pszRemoteSite);
            }
            tdgbl->uSvc->putLine(isc_spb_tra_remote_site, pszRemoteSite);
        }

        if (ptr->tdr_fullpath)
        {
            const char* pszFullpath = reinterpret_cast<const char*>(ptr->tdr_fullpath->str_data);

            if (!tdgbl->uSvc->isService())
            {
                // msg 102: Database Path: %s
                ALICE_print(102, SafeArg() << pszFullpath);
            }
            tdgbl->uSvc->putLine(isc_spb_tra_db_path, pszFullpath);
        }
    }

    // let the user know what the suggested action is

    switch (TDR_analyze(trans))
    {
    case TRA_commit:
        if (!tdgbl->uSvc->isService())
        {
            // msg 103: Automated recovery would commit this transaction.
            ALICE_print(103);
        }
        tdgbl->uSvc->putChar(isc_spb_tra_advise, isc_spb_tra_advise_commit);
        break;

    case TRA_rollback:
        if (!tdgbl->uSvc->isService())
        {
            // msg 104: Automated recovery would rollback this transaction.
            ALICE_print(104);
        }
        tdgbl->uSvc->putChar(isc_spb_tra_advise, isc_spb_tra_advise_rollback);
        break;

    default:
        tdgbl->uSvc->putChar(isc_spb_tra_advise, isc_spb_tra_advise_unknown);
        break;
    }
}
コード例 #19
0
ファイル: tdr.cpp プロジェクト: ariska-net/firebird
bool TDR_reconnect_multiple(FB_API_HANDLE handle, SLONG id, const TEXT* name, SINT64 switches)
{
    ISC_STATUS_ARRAY status_vector;

    // get the state of all the associated transactions

    tdr* trans = MET_get_transaction(status_vector, handle, id);
    if (!trans)
        return reconnect(handle, id, name, switches);

    reattach_databases(trans);
    TDR_get_states(trans);

    // analyze what to do with them; if the advice contradicts the user's
    // desire, make them confirm it; otherwise go with the flow.

    const USHORT advice = TDR_analyze(trans);

    if (!advice)
    {
        print_description(trans);
        switches = ask();
    }
    else
    {
        switch (advice)
        {
        case TRA_rollback:
            if (switches & sw_commit)
            {
                ALICE_print(74, SafeArg() << trans->tdr_id);
                // msg 74: A commit of transaction %ld will violate two-phase commit.
                print_description(trans);
                switches = ask();
            }
            else if (switches & sw_rollback)
                switches |= sw_rollback;
            else if (switches & sw_two_phase)
                switches |= sw_rollback;
            else if (switches & sw_prompt)
            {
                ALICE_print(75, SafeArg() << trans->tdr_id);
                // msg 75: A rollback of transaction %ld is needed to preserve two-phase commit.
                print_description(trans);
                switches = ask();
            }
            break;

        case TRA_commit:
            if (switches & sw_rollback)
            {
                ALICE_print(76, SafeArg() << trans->tdr_id);
                // msg 76: Transaction %ld has already been partially committed.
                ALICE_print(77);
                // msg 77: A rollback of this transaction will violate two-phase commit.
                print_description(trans);
                switches = ask();
            }
            else if (switches & sw_commit)
                switches |= sw_commit;
            else if (switches & sw_two_phase)
                switches |= sw_commit;
            else if (switches & sw_prompt)
            {
                ALICE_print(78, SafeArg() << trans->tdr_id);
                // msg 78: Transaction %ld has been partially committed.
                ALICE_print(79);
                // msg 79: A commit is necessary to preserve the two-phase commit.
                print_description(trans);
                switches = ask();
            }
            break;

        case TRA_unknown:
            ALICE_print(80);
            // msg 80: Insufficient information is available to determine
            ALICE_print(81, SafeArg() << trans->tdr_id);
            // msg 81: a proper action for transaction %ld.
            print_description(trans);
            switches = ask();
            break;

        default:
            if (!(switches & (sw_commit | sw_rollback)))
            {
                ALICE_print(82, SafeArg() << trans->tdr_id);
                // msg 82: Transaction %ld: All subtransactions have been prepared.
                ALICE_print(83);
                // msg 83: Either commit or rollback is possible.
                print_description(trans);
                switches = ask();
            }
        }
    }

    bool error = false;
    if (switches != ULONG(~0))
    {
        // now do the required operation with all the subtransactions

        if (switches & (sw_commit | sw_rollback))
        {
            for (tdr* ptr = trans; ptr; ptr = ptr->tdr_next)
            {
                if (ptr->tdr_state == TRA_limbo)
                {
                    reconnect(ptr->tdr_db_handle, ptr->tdr_id, ptr->tdr_filename, switches);
                }
            }
        }
    }
    else
    {
        ALICE_print(84);	// msg 84: unexpected end of input
        error = true;
    }

    // shutdown all the databases for cleanliness' sake

    TDR_shutdown_databases(trans);

    return error;
}
コード例 #20
0
ファイル: tdr.cpp プロジェクト: ariska-net/firebird
void TDR_list_limbo(FB_API_HANDLE handle, const TEXT* name, const SINT64 switches)
{
    UCHAR buffer[1024];
    ISC_STATUS_ARRAY status_vector;
    AliceGlobals* tdgbl = AliceGlobals::getSpecific();

    if (isc_database_info(status_vector, &handle, sizeof(limbo_info),
                          reinterpret_cast<const char*>(limbo_info),
                          sizeof(buffer),
                          reinterpret_cast<char*>(buffer)))
    {
        ALICE_print_status(true, status_vector);
        return;
    }

    SLONG id;
    tdr* trans;
    UCHAR* ptr = buffer;
    bool flag = true;

    while (flag)
    {
        const USHORT item = *ptr++;
        const USHORT length = (USHORT) gds__vax_integer(ptr, 2);
        ptr += 2;
        switch (item)
        {
        case isc_info_limbo:
            id = gds__vax_integer(ptr, length);
            if (switches & (sw_commit | sw_rollback | sw_two_phase | sw_prompt))
            {
                TDR_reconnect_multiple(handle, id, name, switches);
                ptr += length;
                break;
            }
            if (!tdgbl->uSvc->isService())
            {
                ALICE_print(71, SafeArg() << id);
                // msg 71: Transaction %d is in limbo.
            }
            if (trans = MET_get_transaction(status_vector, handle, id))
            {
                tdgbl->uSvc->putSLong(isc_spb_multi_tra_id, id);
                reattach_databases(trans);
                TDR_get_states(trans);
                TDR_shutdown_databases(trans);
                print_description(trans);
            }
            else
            {
                tdgbl->uSvc->putSLong(isc_spb_single_tra_id, id);
            }
            ptr += length;
            break;

        case isc_info_truncated:
            if (!tdgbl->uSvc->isService())
            {
                ALICE_print(72);
                // msg 72: More limbo transactions than fit.  Try again
                // And how it's going to retry with a bigger buffer if the buffer is fixed size?
            }
        // fall through

        case isc_info_end:
            flag = false;
            break;

        default:
            if (!tdgbl->uSvc->isService())
            {
                ALICE_print(73, SafeArg() << item);
                // msg 73: Unrecognized info item %d
            }
        }
    }
}
コード例 #21
0
ファイル: dtr.cpp プロジェクト: mp-lee/core
int CLIB_ROUTINE main(int argc, char** argv)
{
/**************************************
 *
 *	m a i n
 *
 **************************************
 *
 * Functional description
 *	Top level routine.
 *
 **************************************/

	// Look at options, if any

	Firebird::PathName startup_file = STARTUP_FILE;

#ifdef UNIX
	// If a Unix system, get home directory from environment
	SCHAR home_directory[MAXPATHLEN];
	if (!fb_utils::readenv("HOME", startup_file))
		startup_file = ".qli_startup";
	else
		startup_file.append("/.qli_startup");
#endif

#ifdef HAVE_LOCALE_H
	// Pick up the system locale to allow SYSTEM<->UTF8 conversions
	setlocale(LC_CTYPE, "");
#endif
	atexit(&atexit_fb_shutdown);

	const TEXT* application_file = NULL;
	ALLQ_init();
	LEX_init();
	bool version_flag = false;
	bool banner_flag = true;
	sw_buffers = 0;
	strcpy(QLI_prompt_string, "QLI> ");
	strcpy(QLI_cont_string, "CON> ");
	// Let's define the default number of columns on a machine by machine basis
	QLI_columns = 80;
#ifdef TRUSTED_AUTH
	QLI_trusted = false;
#endif
	QLI_nodb_triggers = false;
	QLI_lines = 60;
	QLI_name_columns = 0;
	QLI_prompt = QLI_prompt_string;
	QLI_matching_language = 0;
	QLI_default_user[0] = 0;
	QLI_default_password[0] = 0;
	QLI_charset[0] = 0;
	QLI_quit_flag = false;
	bool help_flag = false;

#ifdef DEV_BUILD
	QLI_hex_output = false;
#endif

	SLONG debug_value; // aparently unneeded, see usage below.

	const Switches switches(qli_in_sw_table, FB_NELEM(qli_in_sw_table), false, true);

	const TEXT* const* const arg_end = argv + argc;
	argv++;
	while (argv < arg_end)
	{
		const TEXT* const p = *argv++;
		if (*p != '-')
		{
			banner_flag = false;
			LEX_pop_line();
			LEX_push_string(p);
			continue;
		}
		if (!p[1])
			continue;

		const Switches::in_sw_tab_t* option = switches.findSwitch(p);
		const int in_sw = option ? option->in_sw : IN_SW_QLI_0;

		switch (in_sw)
		{
		case IN_SW_QLI_APP_SCRIPT:
			if (argv >= arg_end)
			{
				ERRQ_msg_put(23);	// Msg23 Please retry, supplying an application script file name
				exit(FINI_ERROR);
			}

			application_file = *argv++;
			break;

		case IN_SW_QLI_BUFFERS:
			if (argv < arg_end && **argv != '-')
				sw_buffers = atoi(*argv++);
			break;

		case IN_SW_QLI_EXIT:
			QLI_quit_flag = true;
			break;

		case IN_SW_QLI_FETCH_PASSWORD:
			{
				if (argv >= arg_end || **argv == '-')
					break;
				const char* pwd = NULL;
				if (fb_utils::fetchPassword(*argv++, pwd) != fb_utils::FETCH_PASS_OK)
					break;
				fb_utils::copy_terminate(QLI_default_password, pwd, sizeof(QLI_default_password));
			}
			break;

		case IN_SW_QLI_INITIAL_SCRIPT:
			if (argv >= arg_end || **argv == '-')
				startup_file = "";
			else
				startup_file = *argv++;
			break;

#ifdef TRUSTED_AUTH
		case IN_SW_QLI_TRUSTED_AUTH:
			QLI_trusted = true;
			break;
#endif

		case IN_SW_QLI_NOBANNER:
			banner_flag = false;
			break;

		case IN_SW_QLI_NODBTRIGGERS:
			QLI_nodb_triggers = true;
			break;

		case IN_SW_QLI_PASSWORD:
			if (argv >= arg_end || **argv == '-')
				break;
			fb_utils::copy_terminate(QLI_default_password, fb_utils::get_passwd(*argv++),
				sizeof(QLI_default_password));
			break;

		case IN_SW_QLI_TRACE:
			sw_trace = true;
			break;

		case IN_SW_QLI_USER:
			if (argv >= arg_end || **argv == '-')
				break;
			fb_utils::copy_terminate(QLI_default_user, *argv++, sizeof(QLI_default_user));
			break;

		case IN_SW_QLI_VERIFY:
			sw_verify = true;
			break;

		case IN_SW_QLI_X:
			debug_value = 1;
			isc_set_debug(debug_value);
			break;

		// This switch's name is arbitrary; since it is an internal
		// mechanism it can be changed at will
		case IN_SW_QLI_Y:
			QLI_trace = true;
			break;

		case IN_SW_QLI_Z:
			version_flag = true;
			break;

		case IN_SW_QLI_HELP:
			help_flag = true;
			break;

		default:
			ERRQ_msg_put(529, SafeArg() << p);
			// Msg469 qli: ignoring unknown switch %c
			break;
		}
	}

	enable_signals();

	if (help_flag)
	{
		usage(switches);
		HELP_fini();
		MET_shutdown();
		LEX_fini();
		ALLQ_fini();
		return FINI_OK;
	}

	if (banner_flag)
		ERRQ_msg_put(24);	// Msg24 Welcome to QLI Query Language Interpreter

	if (version_flag)
		ERRQ_msg_put(25, SafeArg() << FB_VERSION);	// Msg25 qli version %s

	if (application_file)
		LEX_push_file(application_file, true);
	else
		QLI_quit_flag = false;		// Silently ignore -E switch when no script is given

	if (startup_file.length())
		LEX_push_file(startup_file.c_str(), false);

#if defined(_MSC_VER) && _MSC_VER >= 1400
	_set_output_format(_TWO_DIGIT_EXPONENT);
#endif

	for (bool got_started = false; !got_started;)
	{
		got_started = true;
		try {
			PAR_token();
		}
		catch (const Firebird::Exception&)
		{
			// try again
			got_started = false;
			ERRQ_pending();
		}
	}
	QLI_error = NULL;

	// Loop until end of file or forced exit

	bool flush_flag = false;
	while (QLI_line)
	{
		qli_plb* temp = QLI_default_pool = ALLQ_pool();
		flush_flag = process_statement(flush_flag);
		ERRQ_pending();
		ALLQ_rlpool(temp);
	}

	HELP_fini();
	MET_shutdown();
	LEX_fini();
	ALLQ_fini();
#ifdef DEBUG_GDS_ALLOC
	// Report any memory leaks noticed.
	// We don't particularly care about QLI specific memory leaks, so all
	// QLI allocations have been marked as "don't report".  However, much
	// of the test-base uses QLI so having a report when QLI finishes
	// could find leaks within the engine.

	gds_alloc_report(0 ALLOC_ARGS);
#endif
	return (FINI_OK);
}
コード例 #22
0
ファイル: dtr.cpp プロジェクト: mp-lee/core
static bool process_statement(bool flush_flag)
{
/**************************************
 *
 *	p r o c e s s _ s t a t e m e n t
 *
 **************************************
 *
 * Functional description
 *	Parse, compile, and execute a single statement.  If an input flush
 *	is required, return true (or status), otherwise return false.
 *
 **************************************/

	// Clear database active flags in preparation for a new statement

	QLI_abort = false;

	for (qli_dbb* dbb = QLI_databases; dbb; dbb = dbb->dbb_next)
		dbb->dbb_flags &= ~DBB_active;

	// If the last statement wrote out anything to the terminal, skip a line

	if (QLI_skip_line)
	{
		printf("\n");
		QLI_skip_line = false;
	}

	// Enable signal handling for the next statement.  Each signal will
	// be caught at least once, then reset to allow the user to really
	// kill the process

	enable_signals();

	// Enable error unwinding and enable the unwinding environment

	try {

		// Set up the appropriate prompt and get the first significant token.  If
		// we don't get one, we're at end of file

		QLI_prompt = QLI_prompt_string;

		// This needs to be done after setting QLI_prompt to prevent
		// and infinite loop in LEX/next_line.
		// If there was a prior syntax error, flush the token stream

		if (flush_flag)
			LEX_flush();

		while (QLI_token->tok_keyword == KW_SEMI)
			LEX_token();

		PAR_real();

		if (!QLI_line)
			return false;

		EXEC_poll_abort();

		// Mark the current token as starting the statement.  This is allows
		// the EDIT command to find the last statement

		LEX_mark_statement();

		// Change the prompt string to the continuation prompt, and parse
		// the next statement

		QLI_prompt = QLI_cont_string;

		qli_syntax* syntax_tree = PARQ_parse();
		if (!syntax_tree)
			return false;

		EXEC_poll_abort();

		// If the statement was EXIT, force end of file on command input

		if (syntax_tree->syn_type == nod_exit)
		{
			QLI_line = NULL;
			return false;
		}

		// If the statement was quit, ask the user if he want to rollback

		if (syntax_tree->syn_type == nod_quit)
		{
			QLI_line = NULL;
			for (qli_dbb* dbb = QLI_databases; dbb; dbb = dbb->dbb_next)
			{
				if ((dbb->dbb_transaction) && (dbb->dbb_flags & DBB_updates))
				{
					// Msg460 Do you want to rollback updates for <dbb>?
					if (yes_no(460, dbb->dbb_symbol->sym_string))
						MET_transaction(nod_rollback, dbb);
					else
						MET_transaction(nod_commit, dbb);
				}
			}
			return false;
		}

		// Expand the statement.  It will return NULL if the statement was
		// a command.  An error will be unwound

		qli_nod* expanded_tree = EXP_expand(syntax_tree);
		if (!expanded_tree)
			return false;

		// Compile the statement

		qli_nod* execution_tree = CMPQ_compile(expanded_tree);
		if (!execution_tree)
			return false;

		// Generate any BLR needed to support the request

		if (!GEN_generate(execution_tree))
			return false;

		if (QLI_statistics)
		{
			for (qli_dbb* dbb = QLI_databases; dbb; dbb = dbb->dbb_next)
			{
				if (dbb->dbb_flags & DBB_active)
				{
					if (!dbb->dbb_statistics)
					{
						dbb->dbb_statistics = (int*) gds__alloc((SLONG) sizeof(PERF64));
#ifdef DEBUG_GDS_ALLOC
						// We don't care about QLI specific memory leaks for V4.0
						gds_alloc_flag_unfreed((void *) dbb->dbb_statistics);	// QLI: don't care
#endif
					}
					perf64_get_info(&dbb->dbb_handle, (perf64*) dbb->dbb_statistics);
				}
			}
		}

		// Execute the request, for better or worse

		EXEC_top(execution_tree);

		if (QLI_statistics)
		{
			PERF64 statistics;
			TEXT buffer[512], report[256];
			for (qli_dbb* dbb = QLI_databases; dbb; dbb = dbb->dbb_next)
			{
				report[0] = 0;
				if (dbb->dbb_flags & DBB_active)
				{
					ERRQ_msg_get(505, report, sizeof(report));
					// Msg505 "    reads = !r writes = !w fetches = !f marks = !m\n"
					FB_SIZE_T used_len = fb_strlen(report);
					ERRQ_msg_get(506, report + used_len, sizeof(report) - used_len);
					// Msg506 "    elapsed = !e cpu = !u system = !s mem = !x, buffers = !b"
					perf64_get_info(&dbb->dbb_handle, &statistics);
					perf64_format((perf64*) dbb->dbb_statistics, &statistics, report, buffer, 0);
					ERRQ_msg_put(26, SafeArg() << dbb->dbb_filename << buffer);
					// Msg26 Statistics for database %s %s
					QLI_skip_line = true;
				}
			}
		}

		// Release resources associated with the request

		GEN_release();

		return false;

	}	// try
	catch (const Firebird::Exception&)
	{
		GEN_release();
		return true;
	}
}