int
main(int argc, char **argv) {
    // Recovery needs to install world-readable files, so clear umask
    // set by init
    umask(0);

    time_t start = time(NULL);

    // If these fail, there's not really anywhere to complain...
    freopen(TEMPORARY_LOG_FILE, "a", stdout); setbuf(stdout, NULL);
    freopen(TEMPORARY_LOG_FILE, "a", stderr); setbuf(stderr, NULL);

    // If this binary is started with the single argument "--adbd",
    // instead of being the normal recovery binary, it turns into kind
    // of a stripped-down version of adbd that only supports the
    // 'sideload' command.  Note this must be a real argument, not
    // anything in the command file or bootloader control block; the
    // only way recovery should be run with this argument is when it
    // starts a copy of itself from the apply_from_adb() function.
    if (argc == 3 && strcmp(argv[1], "--adbd") == 0) {
        adb_main(argv[2]);
        return 0;
    }

    printf("Starting TWRP %s on %s", TW_VERSION_STR, ctime(&start));

    Device* device = make_device();
    ui = device->GetUI();

	//ui->Init();
    //ui->SetBackground(RecoveryUI::NONE);
    //load_volume_table();

	// Load default values to set DataManager constants and handle ifdefs
	DataManager_LoadDefaults();
	printf("Starting the UI...");
	gui_init();
	printf("=> Linking mtab\n");
	system("ln -s /proc/mounts /etc/mtab"); // Link mtab for mke2fs
	printf("=> Processing recovery.fstab\n");
	if (!PartitionManager.Process_Fstab("/etc/recovery.fstab", 1)) {
		LOGE("Failing out of recovery due to problem with recovery.fstab.\n");
		//return -1;
	}
	PartitionManager.Output_Partition_Logging();
	// Load up all the resources
	gui_loadResources();

    get_args(&argc, &argv);

    int previous_runs = 0;
    const char *send_intent = NULL;
    const char *update_package = NULL;
    int wipe_data = 0, wipe_cache = 0;
    bool just_exit = false;
	bool perform_backup = false;

    int arg;
    while ((arg = getopt_long(argc, argv, "", OPTIONS, NULL)) != -1) {
        switch (arg) {
        case 'p': previous_runs = atoi(optarg); break;
        case 's': send_intent = optarg; break;
        case 'u': update_package = optarg; break;
        case 'w': wipe_data = wipe_cache = 1; break;
        case 'c': wipe_cache = 1; break;
        case 't': ui->ShowText(true); break;
        case 'x': just_exit = true; break;
        case 'n': perform_backup = true; LOGI("nandroid\n"); break;
        case '?':
            LOGE("Invalid command argument\n");
            continue;
        }
    }

#ifdef HAVE_SELINUX
    struct selinux_opt seopts[] = {
      { SELABEL_OPT_PATH, "/file_contexts" }
    };

    sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1);

    if (!sehandle) {
        fprintf(stderr, "Warning: No file_contexts\n");
        ui->Print("Warning:  No file_contexts\n");
    }
#endif

    //device->StartRecovery();

    printf("Command:");
    for (arg = 0; arg < argc; arg++) {
        printf(" \"%s\"", argv[arg]);
    }
    printf("\n");

    if (update_package) {
        // For backwards compatibility on the cache partition only, if
        // we're given an old 'root' path "CACHE:foo", change it to
        // "/cache/foo".
        if (strncmp(update_package, "CACHE:", 6) == 0) {
            int len = strlen(update_package) + 10;
            char* modified_path = (char*)malloc(len);
            strlcpy(modified_path, "/cache/", len);
            strlcat(modified_path, update_package+6, len);
            printf("(replacing path \"%s\" with \"%s\")\n",
                   update_package, modified_path);
            update_package = modified_path;
        }
    }
    printf("\n");

    property_list(print_property, NULL);
    printf("\n");

	// Check for and run startup script if script exists
	TWFunc::check_and_run_script("/sbin/runatboot.sh", "boot");
	TWFunc::check_and_run_script("/sbin/postrecoveryboot.sh", "boot");

#ifdef TW_INCLUDE_INJECTTWRP
	// Back up TWRP Ramdisk if needed:
	LOGI("Backing up TWRP ramdisk...\n");
	system("injecttwrp --backup /tmp/backup_recovery_ramdisk.img");
	LOGI("Backup of TWRP ramdisk done.\n");
#endif

    int status = INSTALL_SUCCESS;

	if (perform_backup) {
		char empt[50];
		gui_console_only();
		strcpy(empt, "(Current Date)");
		DataManager_SetStrValue(TW_BACKUP_NAME, empt);
		if (OpenRecoveryScript::Backup_Command("BSDCAE") != 0)
			status = INSTALL_ERROR;
	}
	if (status == INSTALL_SUCCESS) { // Prevent other actions if backup failed
    if (update_package != NULL) {
		gui_console_only();
		if (OpenRecoveryScript::Install_Command(update_package) == 0)
			status = INSTALL_SUCCESS;
		else
			status = INSTALL_ERROR;
		/*
        status = install_package(update_package, &wipe_cache, TEMPORARY_INSTALL_FILE);
        if (status == INSTALL_SUCCESS && wipe_cache) {
            if (erase_volume("/cache")) {
                LOGE("Cache wipe (requested by package) failed.");
            }
        }
        if (status != INSTALL_SUCCESS) ui->Print("Installation aborted.\n");
		*/
    } else if (wipe_data) {
		gui_console_only();
		if (!PartitionManager.Factory_Reset()) status = INSTALL_ERROR;
		/*
        if (device->WipeData()) status = INSTALL_ERROR;
        if (erase_volume("/data")) status = INSTALL_ERROR;
        if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR;
		*/
        if (status != INSTALL_SUCCESS) ui->Print("Data wipe failed.\n");
    } else if (wipe_cache) {
		gui_console_only();
        if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR;
        if (status != INSTALL_SUCCESS) ui->Print("Cache wipe failed.\n");
    } else if (!just_exit) {
        status = INSTALL_ERROR;  // No command specified
    }
	}

    //if (status != INSTALL_SUCCESS) ui->SetBackground(RecoveryUI::ERROR);
    if (status != INSTALL_SUCCESS /*|| ui->IsTextVisible()*/) {
		finish_recovery(NULL);
		DataManager_ReadSettingsFile();
		if (PartitionManager.Mount_By_Path("/system", false) && TWFunc::Path_Exists("/system/recovery-from-boot.p")) {
			system("mv /system/recovery-from-boot.p /system/recovery-from-boot.bak");
			ui_print("Renamed stock recovery file in /system to prevent\nthe stock ROM from replacing TWRP.\n");
		}
		PartitionManager.UnMount_By_Path("/system", false);
		if (DataManager_GetIntValue(TW_IS_ENCRYPTED) == 0 && OpenRecoveryScript::check_for_script_file()) {
			gui_console_only();
			if (OpenRecoveryScript::run_script_file() != 0) {
				// There was an error, boot the recovery
				gui_start();
			} else {
				usleep(2000000); // Sleep for 2 seconds before rebooting
			}
		} else
			gui_start();
		//prompt_and_wait(device);
    }

    // Otherwise, get ready to boot the main system...
    finish_recovery(send_intent);
    ui->Print("Rebooting...\n");
#ifdef ANDROID_RB_RESTART
    android_reboot(ANDROID_RB_RESTART, 0, 0);
#else
	reboot(RB_AUTOBOOT);
#endif
    return EXIT_SUCCESS;
}