Merge "Include libpcre if present" into android-5.0
diff --git a/gui/gui.cpp b/gui/gui.cpp
index 61e5de1..9b918f0 100644
--- a/gui/gui.cpp
+++ b/gui/gui.cpp
@@ -68,8 +68,8 @@
 pthread_mutex_t gForceRendermutex;
 static int gNoAnimation = 1;
 static int gGuiInputRunning = 0;
-static int gCmdLineRunning = 0;
 blanktimer blankTimer;
+int ors_read_fd = -1;
 
 // Needed by pages.cpp too
 int gGuiRunning = 0;
@@ -407,83 +407,97 @@
 	return NULL;
 }
 
-static void * command_thread(void *cookie)
+static void setup_ors_command()
 {
-	int read_fd;
-	FILE* orsout;
-	char command[1024], result[512];
-
-	LOGINFO("Starting command line thread\n");
+	ors_read_fd = -1;
 
 	unlink(ORS_INPUT_FILE);
 	if (mkfifo(ORS_INPUT_FILE, 06660) != 0) {
 		LOGINFO("Unable to mkfifo %s\n", ORS_INPUT_FILE);
-		return 0;
+		return;
 	}
 	unlink(ORS_OUTPUT_FILE);
 	if (mkfifo(ORS_OUTPUT_FILE, 06666) != 0) {
 		LOGINFO("Unable to mkfifo %s\n", ORS_OUTPUT_FILE);
 		unlink(ORS_INPUT_FILE);
-		return 0;
+		return;
 	}
 
-	read_fd = open(ORS_INPUT_FILE, O_RDONLY);
-	if (read_fd < 0) {
+	ors_read_fd = open(ORS_INPUT_FILE, O_RDONLY | O_NONBLOCK);
+	if (ors_read_fd < 0) {
 		LOGINFO("Unable to open %s\n", ORS_INPUT_FILE);
 		unlink(ORS_INPUT_FILE);
 		unlink(ORS_OUTPUT_FILE);
-		return 0;
 	}
+}
 
-	while (!gGuiRunning)
-		sleep(1);
+static void ors_command_read()
+{
+	FILE* orsout;
+	char command[1024], result[512];
+	int set_page_done = 0, read_ret = 0;
 
-	for (;;) {
-		while (read(read_fd, &command, sizeof(command)) > 0) {
-			command[1022] = '\n';
-			command[1023] = '\0';
-			LOGINFO("Command '%s' received\n", command);
-			orsout = fopen(ORS_OUTPUT_FILE, "w");
-			if (!orsout) {
-				close(read_fd);
-				LOGINFO("Unable to fopen %s\n", ORS_OUTPUT_FILE);
-				unlink(ORS_INPUT_FILE);
-				unlink(ORS_OUTPUT_FILE);
-				return 0;
-			}
-			if (DataManager::GetIntValue("tw_busy") != 0) {
-				strcpy(result, "Failed, operation in progress\n");
-				fprintf(orsout, "%s", result);
-				LOGINFO("Command cannot be performed, operation in progress.\n");
-			} else {
-				if (gui_console_only() == 0) {
-					LOGINFO("Console started successfully\n");
-					gui_set_FILE(orsout);
-					if (strlen(command) > 11 && strncmp(command, "runscript", 9) == 0) {
-						char* filename = command + 11;
-						if (OpenRecoveryScript::copy_script_file(filename) == 0) {
-							LOGERR("Unable to copy script file\n");
-						} else {
-							OpenRecoveryScript::run_script_file();
-						}
-					} else if (strlen(command) > 5 && strncmp(command, "get", 3) == 0) {
-						char* varname = command + 4;
-						string temp;
-						DataManager::GetValue(varname, temp);
-						gui_print("%s = %s\n", varname, temp.c_str());
-					} else if (OpenRecoveryScript::Insert_ORS_Command(command)) {
+	if ((read_ret = read(ors_read_fd, &command, sizeof(command))) > 0) {
+		command[1022] = '\n';
+		command[1023] = '\0';
+		LOGINFO("Command '%s' received\n", command);
+		orsout = fopen(ORS_OUTPUT_FILE, "w");
+		if (!orsout) {
+			close(ors_read_fd);
+			ors_read_fd = -1;
+			LOGINFO("Unable to fopen %s\n", ORS_OUTPUT_FILE);
+			unlink(ORS_INPUT_FILE);
+			unlink(ORS_OUTPUT_FILE);
+			return;
+		}
+		if (DataManager::GetIntValue("tw_busy") != 0) {
+			strcpy(result, "Failed, operation in progress\n");
+			fprintf(orsout, "%s", result);
+			LOGINFO("Command cannot be performed, operation in progress.\n");
+		} else {
+			if (gui_console_only() == 0) {
+				LOGINFO("Console started successfully\n");
+				gui_set_FILE(orsout);
+				if (strlen(command) > 11 && strncmp(command, "runscript", 9) == 0) {
+					char* filename = command + 11;
+					if (OpenRecoveryScript::copy_script_file(filename) == 0) {
+						LOGERR("Unable to copy script file\n");
+					} else {
 						OpenRecoveryScript::run_script_file();
 					}
-					gui_set_FILE(NULL);
-					gGuiConsoleTerminate = 1;
+				} else if (strlen(command) > 5 && strncmp(command, "get", 3) == 0) {
+					char* varname = command + 4;
+					string temp;
+					DataManager::GetValue(varname, temp);
+					gui_print("%s = %s\n", varname, temp.c_str());
+				} else if (strlen(command) > 9 && strncmp(command, "decrypt", 7) == 0) {
+					char* pass = command + 8;
+					gui_print("Attempting to decrypt data partition via command line.\n");
+					if (PartitionManager.Decrypt_Device(pass) == 0) {
+						set_page_done = 1;
+					}
+				} else if (OpenRecoveryScript::Insert_ORS_Command(command)) {
+					OpenRecoveryScript::run_script_file();
 				}
+				gui_set_FILE(NULL);
+				gGuiConsoleTerminate = 1;
 			}
-			fclose(orsout);
 		}
+		fclose(orsout);
+		LOGINFO("Done reading ORS command from command line\n");
+		if (set_page_done) {
+			DataManager::SetValue("tw_page_done", 1);
+		} else {
+			// The select function will return ready to read and the
+			// read function will return errno 19 no such device unless
+			// we set everything up all over again.
+			close(ors_read_fd);
+			setup_ors_command();
+		}
+	} else {
+		LOGINFO("ORS command line read returned an error: %i, %i, %s\n", read_ret, errno, strerror(errno));
 	}
-	close(read_fd);
-	LOGINFO("Command thread exiting\n");
-	return 0;
+	return;
 }
 
 // This special function will return immediately the first time, but then
@@ -521,8 +535,11 @@
 	} while (1);
 }
 
-static int runPages(void)
+static int runPages(const char *page_name, const int stop_on_page_done)
 {
+	if (page_name)
+		gui_changePage(page_name);
+
 	// Raise the curtain
 	if (gCurtain != NULL)
 	{
@@ -542,10 +559,27 @@
 	timespec start, end;
 	int32_t render_t, flip_t;
 #endif
+#ifndef TW_OEM_BUILD
+	struct timeval timeout;
+	fd_set fdset;
+	int has_data = 0;
+#endif
 
 	for (;;)
 	{
 		loopTimer();
+#ifndef TW_OEM_BUILD
+		if (ors_read_fd > 0) {
+			FD_ZERO(&fdset);
+			FD_SET(ors_read_fd, &fdset);
+			timeout.tv_sec = 0;
+			timeout.tv_usec = 1;
+			has_data = select(ors_read_fd+1, &fdset, NULL, NULL, &timeout);
+			if (has_data > 0) {
+				ors_command_read();
+			}
+		}
+#endif
 
 		if (gGuiConsoleRunning) {
 			continue;
@@ -591,64 +625,17 @@
 		}
 
 		blankTimer.checkForTimeout();
-		if (DataManager::GetIntValue("tw_gui_done") != 0)
-			break;
-	}
-
-	gGuiRunning = 0;
-	return 0;
-}
-
-static int runPage(const char *page_name)
-{
-	gui_changePage(page_name);
-
-	// Raise the curtain
-	if (gCurtain != NULL)
-	{
-		gr_surface surface;
-
-		PageManager::Render();
-		gr_get_surface(&surface);
-		curtainRaise(surface);
-		gr_free_surface(surface);
-	}
-
-	gGuiRunning = 1;
-
-	DataManager::SetValue("tw_loaded", 1);
-
-	for (;;)
-	{
-		loopTimer();
-
-		if (!gForceRender)
-		{
-			int ret;
-
-			ret = PageManager::Update();
-			if (ret > 1)
-				PageManager::Render();
-
-			if (ret > 0)
-				flip();
-		}
-		else
-		{
-			pthread_mutex_lock(&gForceRendermutex);
-			gForceRender = 0;
-			pthread_mutex_unlock(&gForceRendermutex);
-			PageManager::Render();
-			flip();
-		}
-		blankTimer.checkForTimeout();
-		if (DataManager::GetIntValue("tw_page_done") != 0)
+		if (stop_on_page_done && DataManager::GetIntValue("tw_page_done") != 0)
 		{
 			gui_changePage("main");
 			break;
 		}
+		if (DataManager::GetIntValue("tw_gui_done") != 0)
+			break;
 	}
-
+	if (ors_read_fd > 0)
+		close(ors_read_fd);
+	ors_read_fd = -1;
 	gGuiRunning = 0;
 	return 0;
 }
@@ -839,37 +826,10 @@
 
 extern "C" int gui_start(void)
 {
-	if (!gGuiInitialized)
-		return -1;
-
-	gGuiConsoleTerminate = 1;
-
-	while (gGuiConsoleRunning)
-		loopTimer();
-
-	// Set the default package
-	PageManager::SelectPackage("TWRP");
-
-	if (!gGuiInputRunning)
-	{
-		// Start by spinning off an input handler.
-		pthread_t t;
-		pthread_create(&t, NULL, input_thread, NULL);
-		gGuiInputRunning = 1;
-	}
-#ifndef TW_OEM_BUILD
-	if (!gCmdLineRunning)
-	{
-		// Start by spinning off an input handler.
-		pthread_t t;
-		pthread_create(&t, NULL, command_thread, NULL);
-		gCmdLineRunning = 1;
-	}
-#endif
-	return runPages();
+	return gui_startPage(NULL, 1, 0);
 }
 
-extern "C" int gui_startPage(const char *page_name)
+extern "C" int gui_startPage(const char *page_name, const int allow_commands, int stop_on_page_done)
 {
 	if (!gGuiInitialized)
 		return -1;
@@ -889,9 +849,20 @@
 		pthread_create(&t, NULL, input_thread, NULL);
 		gGuiInputRunning = 1;
 	}
-
+#ifndef TW_OEM_BUILD
+	if (allow_commands)
+	{
+		if (ors_read_fd < 0)
+			setup_ors_command();
+	} else {
+		if (ors_read_fd >= 0) {
+			close(ors_read_fd);
+			ors_read_fd = -1;
+		}
+	}
+#endif
 	DataManager::SetValue("tw_page_done", 0);
-	return runPage(page_name);
+	return runPages(page_name, stop_on_page_done);
 }
 
 static void * console_thread(void *cookie)
diff --git a/gui/gui.h b/gui/gui.h
index 21c460e..5b2cdec 100644
--- a/gui/gui.h
+++ b/gui/gui.h
@@ -26,7 +26,7 @@
 int gui_loadResources();
 int gui_loadCustomResources();
 int gui_start();
-int gui_startPage(const char* page_name);
+int gui_startPage(const char* page_name, const int allow_comands, int stop_on_page_done);
 void gui_print(const char *fmt, ...);
 void gui_print_color(const char *color, const char *fmt, ...);
 void gui_set_FILE(FILE* f);
diff --git a/gui/resources.cpp b/gui/resources.cpp
index 74f020b..0d32cee 100644
--- a/gui/resources.cpp
+++ b/gui/resources.cpp
@@ -256,82 +256,45 @@
 		if (!attr)
 			break;
 
+		Resource* res = NULL;
 		std::string type = attr->value();
-
 		if (type == "font")
 		{
-			FontResource* res = new FontResource(child, pZip);
-			if (res == NULL || res->GetResource() == NULL)
-			{
-				std::string res_name;
-				if (child->first_attribute("name"))
-					res_name = child->first_attribute("name")->value();
-				if (res_name.empty() && child->first_attribute("filename"))
-					res_name = child->first_attribute("filename")->value();
-
-				if (!res_name.empty()) {
-					LOGERR("Resource (%s)-(%s) failed to load\n", type.c_str(), res_name.c_str());
-				} else
-					LOGERR("Resource type (%s) failed to load\n", type.c_str());
-
-				delete res;
-			}
-			else
-			{
-				mResources.push_back((Resource*) res);
-			}
+			res = new FontResource(child, pZip);
 		}
 		else if (type == "image")
 		{
-			ImageResource* res = new ImageResource(child, pZip);
-			if (res == NULL || res->GetResource() == NULL)
-			{
-				std::string res_name;
-				if (child->first_attribute("name"))
-					res_name = child->first_attribute("name")->value();
-				if (res_name.empty() && child->first_attribute("filename"))
-					res_name = child->first_attribute("filename")->value();
-
-				if (!res_name.empty()) {
-					LOGERR("Resource (%s)-(%s) failed to load\n", type.c_str(), res_name.c_str());
-				} else
-					LOGERR("Resource type (%s) failed to load\n", type.c_str());
-
-				delete res;
-			}
-			else
-			{
-				mResources.push_back((Resource*) res);
-			}
+			res = new ImageResource(child, pZip);
 		}
 		else if (type == "animation")
 		{
-			AnimationResource* res = new AnimationResource(child, pZip);
-			if (res == NULL || res->GetResource() == NULL)
-			{
-				std::string res_name;
-				if (child->first_attribute("name"))
-					res_name = child->first_attribute("name")->value();
-				if (res_name.empty() && child->first_attribute("filename"))
-					res_name = child->first_attribute("filename")->value();
-
-				if (!res_name.empty()) {
-					LOGERR("Resource (%s)-(%s) failed to load\n", type.c_str(), res_name.c_str());
-				} else
-					LOGERR("Resource type (%s) failed to load\n", type.c_str());
-
-				delete res;
-			}
-			else
-			{
-				mResources.push_back((Resource*) res);
-			}
+			res = new AnimationResource(child, pZip);
 		}
 		else
 		{
 			LOGERR("Resource type (%s) not supported.\n", type.c_str());
 		}
 
+		if (res == NULL || res->GetResource() == NULL)
+		{
+			std::string res_name;
+			if (child->first_attribute("name"))
+				res_name = child->first_attribute("name")->value();
+			if (res_name.empty() && child->first_attribute("filename"))
+				res_name = child->first_attribute("filename")->value();
+
+			if (!res_name.empty()) {
+				LOGERR("Resource (%s)-(%s) failed to load\n", type.c_str(), res_name.c_str());
+			} else
+				LOGERR("Resource type (%s) failed to load\n", type.c_str());
+
+			delete res;
+		}
+		else
+		{
+			mResources.push_back(res);
+		}
+
 		child = child->next_sibling("resource");
 	}
 }
diff --git a/openrecoveryscript.cpp b/openrecoveryscript.cpp
index 9638393..d28f762 100644
--- a/openrecoveryscript.cpp
+++ b/openrecoveryscript.cpp
@@ -566,7 +566,7 @@
 	DataManager::SetValue("tw_complete_text1", "OpenRecoveryScript Complete");
 	DataManager::SetValue("tw_has_cancel", 0);
 	DataManager::SetValue("tw_show_reboot", 0);
-	if (gui_startPage("action_page") != 0) {
+	if (gui_startPage("action_page", 0, 1) != 0) {
 		LOGERR("Failed to load OpenRecoveryScript GUI page.\n");
 	}
 }
diff --git a/prebuilt/Android.mk b/prebuilt/Android.mk
index 305aa23..2671e1b 100644
--- a/prebuilt/Android.mk
+++ b/prebuilt/Android.mk
@@ -140,10 +140,8 @@
 ifeq ($(TARGET_USERIMAGES_USE_F2FS), true)
     ifeq ($(PLATFORM_SDK_VERSION), 21)
         RELINK_SOURCE_FILES += $(TARGET_ROOT_OUT_SBIN)/mkfs.f2fs
-        #RELINK_SOURCE_FILES += $(TARGET_ROOT_OUT_SBIN)/fibmap.f2fs
     else
         RELINK_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/mkfs.f2fs
-        RELINK_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/fibmap.f2fs
     endif
     RELINK_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/fsck.f2fs
 endif
diff --git a/twrp.cpp b/twrp.cpp
index 3489f8c..b6d3d79 100644
--- a/twrp.cpp
+++ b/twrp.cpp
@@ -276,7 +276,7 @@
 	// Offer to decrypt if the device is encrypted
 	if (DataManager::GetIntValue(TW_IS_ENCRYPTED) != 0) {
 		LOGINFO("Is encrypted, do decrypt page first\n");
-		if (gui_startPage("decrypt") != 0) {
+		if (gui_startPage("decrypt", 1, 1) != 0) {
 			LOGERR("Failed to start decrypt GUI page.\n");
 		} else {
 			// Check for and load custom theme if present
@@ -347,7 +347,7 @@
 		if (TWFunc::Path_Exists("/supersu/su") && !TWFunc::Path_Exists("/system/bin/su") && !TWFunc::Path_Exists("/system/xbin/su") && !TWFunc::Path_Exists("/system/bin/.ext/.su")) {
 			// Device doesn't have su installed
 			DataManager::SetValue("tw_busy", 1);
-			if (gui_startPage("installsu") != 0) {
+			if (gui_startPage("installsu", 1, 1) != 0) {
 				LOGERR("Failed to start SuperSU install page.\n");
 			}
 		}