library/src/command_control_interface/BP-CommandControlInterfacePty.cc
// process a branch in the command tree.  Processing is relative to buffers present (or soon to be present
// in the session.
process a branch in the command tree.  Processing is relative to buffers present (or soon to be present
in the session.
process a branch in the command tree . Processing is relative to buffers present ( or soon to be present in the session .
BP_ERROR_T BP_CCProcessCommandTreePty(P_BP_CC_SESSION session, P_BP_CC_DECISION_BRANCH execute_branch)
{
	if (!session)
		return ERR_FAILURE;
	if (!execute_branch)
		return ERR_FAILURE;
	fd_set rfd;
	BP_ZERO_STACK(rfd);
	fd_set wfd;
	BP_ZERO_STACK(wfd);
	fd_set efd;
	BP_ZERO_STACK(efd);
	timeval tv;
	BP_ZERO_STACK(tv);
	if (execute_branch->try_this)
	{
		FD_ZERO(&rfd);
		FD_ZERO(&wfd);
		FD_ZERO(&efd);
		FD_SET(session->fds->forkpty_master, &rfd);
		if(session->display_writes_to_app_stdin)
		{
			BP_printfVTColor("%s", BP_COLOR_CODE_FG_RED, BP_COLOR_CODE_BG_GREEN, execute_branch->try_this);
		}
		if(BP_FDWrite(session->fds->forkpty_master, execute_branch->try_this, execute_branch->try_buff_size) == -1)
		{
			return ERR_FAILURE;
		}
	}
	BP_BOOL expect_failed_due_to_bad_app_read = BP_FALSE;
	char  *read_from_app_buff = NULL;
	size_t read_from_app_buff_n = 0;
	if(execute_branch->expect_this)
	{
		printf("\n I MIGHT VOMIT");
		size_t data_write_index = 0;
		int stdout_read_size = 0;
		int stderr_read_size = 0;
		size_t std_err_index = 0;
		size_t check_iter = 0;
		char read_char_buff [BP_KILOBYTE+1];
		for(;;)
		{
			if(stdout_read_size)
				BP_ZERO_STACK(read_char_buff);
			FD_ZERO(&rfd);
			FD_ZERO(&wfd);
			FD_ZERO(&efd);
			FD_SET(session->fds->forkpty_master, &rfd);
			tv.tv_sec  = session->select_child_stdout_timeout_sec;
			tv.tv_usec = session->select_child_stdout_timeout_usec;
			int select_val = select
			(
					session->fds->forkpty_master + 1,
					&rfd,
					&wfd,
					&efd,
					&tv
			);
			if(select_val == -1)
				break;
			if(select_val == 0)
				break;
			if (FD_ISSET(session->fds->forkpty_master, &rfd))
			{
				stdout_read_size = read(session->fds->forkpty_master, &read_char_buff[0], BP_KILOBYTE);
				if ( stdout_read_size != -1)
				{
					read_from_app_buff = (char *) bprealloc
					(
							read_from_app_buff,
							read_from_app_buff_n + stdout_read_size + 1
					);
					memcpy(&read_from_app_buff[read_from_app_buff_n], &read_char_buff, stdout_read_size);
					read_from_app_buff_n += stdout_read_size;
				}
				else
				{
					break;
				}
			}
		}
	}
	%
	%
	BP_BOOL expect_checks_passed_ok = BP_TRUE;
	if(execute_branch->expect_this)
	{
		if(read_from_app_buff)
		{
			if(session->display_reads_from_app_stdout)
			{
				BP_printfVTColor("\n%s", BP_COLOR_CODE_FG_WHITE, BP_COLOR_CODE_BG_BLUE, read_from_app_buff);
				BP_RESET_TERMINAL_COLOR;
			}
			if(execute_branch->expect_this)
			{
				if(execute_branch->expect_match_policy == BP_CC_MATCH_BUFF_POLICY_MEM_SEARCH)
				{
					if(expect_checks_passed_ok)
					if(read_from_app_buff_n < execute_branch->expect_buff_size)
						expect_checks_passed_ok = BP_FALSE;
					if(expect_checks_passed_ok)
					if(!memmem(read_from_app_buff, read_from_app_buff_n, execute_branch->expect_this, execute_branch->expect_buff_size))
						expect_checks_passed_ok = BP_FALSE;
				}
				else if(execute_branch->expect_match_policy == BP_CC_MATCH_BUFF_POLICY_MEM_EXACT)
				{
					if(expect_checks_passed_ok)
					if(read_from_app_buff_n != execute_branch->expect_buff_size)
						expect_checks_passed_ok = BP_FALSE;
					if(expect_checks_passed_ok)
					if(memcmp(read_from_app_buff, execute_branch->expect_this, read_from_app_buff_n) != 0)
						expect_checks_passed_ok = BP_FALSE;
				}
				else
				if(execute_branch->expect_match_policy == BP_CC_MATCH_BUFF_POLICY_PCRE_SEARCH)
				{
					BP_ZERO_STACK(execute_branch->match_info);
					if(expect_checks_passed_ok)
					if
					(
						BP_MatchRegularExpressionPCRE
						(
							(char *) read_from_app_buff,
							read_from_app_buff_n,
							execute_branch->expect_this,
							0,
							1024,
							&execute_branch->match_info,
							BP_TRUE
						) != ERR_SUCCESS
					)
					{
						expect_checks_passed_ok = BP_FALSE;
						BP_DestroyRegexpMatchInfo(&execute_branch->match_info);
					}
				}
				if(expect_checks_passed_ok)
				{
					if(execute_branch->matched_text)
						tq_free(session->m, execute_branch->matched_text);
					execute_branch->matched_text      = read_from_app_buff;
					execute_branch->matched_text_size = read_from_app_buff_n;
					session->last_expect_match_success_branch = execute_branch;
				}
			}
		}
		if(!expect_checks_passed_ok)
		{
			if(read_from_app_buff)
				tq_free(session->m, read_from_app_buff);
			printf("\n [!!] Expect check failed for: %s", execute_branch->expect_this);
			session->last_expect_match_failed_branch = execute_branch;
			return ERR_FAILURE;
		}
	}
	%
	%
	if(expect_failed_due_to_bad_app_read)
	{
		 before exiting
		session->last_expect_match_failed_branch = execute_branch;
		return ERR_FAILURE;
	}
	if(execute_branch->yes && expect_checks_passed_ok)
	{
		return BP_CCProcessCommandTreePty(session, execute_branch->yes);
	}
	else if(execute_branch->no && !expect_checks_passed_ok)
	{
		return BP_CCProcessCommandTreePty(session, execute_branch->no);
	}
	return ERR_SUCCESS;
}
BP_ERROR_T BP_CCProcessCommandTreePty ( P_BP_CC_SESSION session , P_BP_CC_DECISION_BRANCH execute_branch ) { if ( ! session ) return ERR_FAILURE ; if ( ! execute_branch ) return ERR_FAILURE ; fd_set rfd ; BP_ZERO_STACK ( rfd ) ; fd_set wfd ; BP_ZERO_STACK ( wfd ) ; fd_set efd ; BP_ZERO_STACK ( efd ) ; timeval tv ; BP_ZERO_STACK ( tv ) ; if ( execute_branch -> try_this ) { FD_ZERO ( & rfd ) ; FD_ZERO ( & wfd ) ; FD_ZERO ( & efd ) ; FD_SET ( session -> fds -> forkpty_master , & rfd ) ; if ( session -> display_writes_to_app_stdin ) { BP_printfVTColor ( " " , BP_COLOR_CODE_FG_RED , BP_COLOR_CODE_BG_GREEN , execute_branch -> try_this ) ; } if ( BP_FDWrite ( session -> fds -> forkpty_master , execute_branch -> try_this , execute_branch -> try_buff_size ) == -1 ) { return ERR_FAILURE ; } } BP_BOOL expect_failed_due_to_bad_app_read = BP_FALSE ; char * read_from_app_buff = NULL ; size_t read_from_app_buff_n = 0 ; if ( execute_branch -> expect_this ) { printf ( " \n " ) ; size_t data_write_index = 0 ; int stdout_read_size = 0 ; int stderr_read_size = 0 ; size_t std_err_index = 0 ; size_t check_iter = 0 ; char read_char_buff [ BP_KILOBYTE + 1 ] ; for ( ; ; ) { if ( stdout_read_size ) BP_ZERO_STACK ( read_char_buff ) ; FD_ZERO ( & rfd ) ; FD_ZERO ( & wfd ) ; FD_ZERO ( & efd ) ; FD_SET ( session -> fds -> forkpty_master , & rfd ) ; tv . tv_sec = session -> select_child_stdout_timeout_sec ; tv . tv_usec = session -> select_child_stdout_timeout_usec ; int select_val = select ( session -> fds -> forkpty_master + 1 , & rfd , & wfd , & efd , & tv ) ; if ( select_val == -1 ) break ; if ( select_val == 0 ) break ; if ( FD_ISSET ( session -> fds -> forkpty_master , & rfd ) ) { stdout_read_size = read ( session -> fds -> forkpty_master , & read_char_buff [ 0 ] , BP_KILOBYTE ) ; if ( stdout_read_size != -1 ) { read_from_app_buff = ( char * ) bprealloc ( read_from_app_buff , read_from_app_buff_n + stdout_read_size + 1 ) ; memcpy ( & read_from_app_buff [ read_from_app_buff_n ] , & read_char_buff , stdout_read_size ) ; read_from_app_buff_n += stdout_read_size ; } else { break ; } } } } BP_BOOL expect_checks_passed_ok = BP_TRUE ; if ( execute_branch -> expect_this ) { if ( read_from_app_buff ) { if ( session -> display_reads_from_app_stdout ) { BP_printfVTColor ( " \n " , BP_COLOR_CODE_FG_WHITE , BP_COLOR_CODE_BG_BLUE , read_from_app_buff ) ; BP_RESET_TERMINAL_COLOR ; } if ( execute_branch -> expect_this ) { if ( execute_branch -> expect_match_policy == BP_CC_MATCH_BUFF_POLICY_MEM_SEARCH ) { if ( expect_checks_passed_ok ) if ( read_from_app_buff_n < execute_branch -> expect_buff_size ) expect_checks_passed_ok = BP_FALSE ; if ( expect_checks_passed_ok ) if ( ! memmem ( read_from_app_buff , read_from_app_buff_n , execute_branch -> expect_this , execute_branch -> expect_buff_size ) ) expect_checks_passed_ok = BP_FALSE ; } else if ( execute_branch -> expect_match_policy == BP_CC_MATCH_BUFF_POLICY_MEM_EXACT ) { if ( expect_checks_passed_ok ) if ( read_from_app_buff_n != execute_branch -> expect_buff_size ) expect_checks_passed_ok = BP_FALSE ; if ( expect_checks_passed_ok ) if ( memcmp ( read_from_app_buff , execute_branch -> expect_this , read_from_app_buff_n ) != 0 ) expect_checks_passed_ok = BP_FALSE ; } else if ( execute_branch -> expect_match_policy == BP_CC_MATCH_BUFF_POLICY_PCRE_SEARCH ) { BP_ZERO_STACK ( execute_branch -> match_info ) ; if ( expect_checks_passed_ok ) if ( BP_MatchRegularExpressionPCRE ( ( char * ) read_from_app_buff , read_from_app_buff_n , execute_branch -> expect_this , 0 , 1024 , & execute_branch -> match_info , BP_TRUE ) != ERR_SUCCESS ) { expect_checks_passed_ok = BP_FALSE ; BP_DestroyRegexpMatchInfo ( & execute_branch -> match_info ) ; } } if ( expect_checks_passed_ok ) { if ( execute_branch -> matched_text ) tq_free ( session -> m , execute_branch -> matched_text ) ; execute_branch -> matched_text = read_from_app_buff ; execute_branch -> matched_text_size = read_from_app_buff_n ; session -> last_expect_match_success_branch = execute_branch ; } } } if ( ! expect_checks_passed_ok ) { if ( read_from_app_buff ) tq_free ( session -> m , read_from_app_buff ) ; printf ( " \n " , execute_branch -> expect_this ) ; session -> last_expect_match_failed_branch = execute_branch ; return ERR_FAILURE ; } } if ( expect_failed_due_to_bad_app_read ) { session -> last_expect_match_failed_branch = execute_branch ; return ERR_FAILURE ; } if ( execute_branch -> yes && expect_checks_passed_ok ) { return BP_CCProcessCommandTreePty ( session , execute_branch -> yes ) ; } else if ( execute_branch -> no && ! expect_checks_passed_ok ) { return BP_CCProcessCommandTreePty ( session , execute_branch -> no ) ; } return ERR_SUCCESS ; }
process a branch in the command tree.
process a branch in the command tree .
// ensure we have a session and execute_branch // read fd set // write fdset // error fdset // timeval for polling // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%% Run "Try" By Writing To Process STDIN %%%%%%%%%%%%%%%%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // run the try command // set fds before write // perform substitutions // write try command to fd // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%% Run "Expect" By Reading Child Process STDOUT %%%%%%%%%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // this is set to true if the application read failed // buffer read from app // if we're expecting data, attempt to read data // data write index // declare stdout/stderr read sizes // set standard err index // size check iter // create stack read buffer (1kb) // main read loop for expect // zero the read and write buffers on loop // zero all the file descriptor sets // set master // note: this makes it keyboard interactive // FD_SET(STDIN_FILENO, &rfd); // set polling timeouts // select on fds // if we can no longer select, break the loop // if we have no fds to read from, break loop // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%% Read From Application %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // Check for data to receive; the received // data includes also the data previously sent // on the same master descriptor (line 90). // attempt to read a kilobyte // printf("\n Got read size?: %i", stdout_read_size); // perform reallocation based on current size + read size // copy in read data at read position // increment the read size by the size of the data read from stdout /*
					// since we get a bad read, check if the process exited, if the process exited
					// it's not actually a bad read (bug fixed on 07/2016)

					// if the pid is not running (checked here with kill), and we got a -1 on read, something
					// has gone wrong and we can no longer trust our results.
					if(kill(session->fds->pid, 0) == 0)
					{
						printf("\n Fudge you, you fudge: %i - %s", session->fds->pid, read_from_app_buff);
						expect_failed_due_to_bad_app_read = BP_TRUE;
					}
					*/ // set expect failure // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%% Run Expect Match Checks  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // Create expect checks indicator.  This is initialized to true, and only // set to false if one or more checks in the cascading if/else below fails. // run the "expect" branch // display the read buffer // display reads if set // If we're expecting some data back from the application, go ahead and run expect checks. /* run memmem to search buffer */ // run length check disqualifier first // run search disqualifier next /* run memcmp to exact-match buffer */ // run length check disqualifier first // run memcmp disqualifier next /* run PCRE to search buffer */ // zero out our match info before use // attempt to match pcre on our buffer // set expect checks flag to false/fail // destroy the regexp match info if we've failed match // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%% After Match Checks Complete/Store Buffers %%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // ensure checks passed ok before setting buffers // destroy matched buffer if necessary before re-assigning // set buffers directly (since they've been tq allocated // set the last success branch // if the expect checks failed, exit here // Destroy the application read buffer if we haven't attached it to // an execution branch. // display check failed message // set last failed branch // return indicating failure // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%% Recurse Decision Tree %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // run the yes execute tree if there is one // set last failed branch before exiting // Branch to yes if we've passed our checks.  Branch to no if we failed our checks. // return ERR_SUCCESS after recursion bottoms.