Ejemplo n.º 1
0
static void
wipe_data(int confirm) 
{
  if (confirm) 
  {
    char* headers[] = { "Confirm wipe of all user data?",
                        "  THIS CAN NOT BE UNDONE.",
                        "",
                        NULL };

    char* items[] = { " No",
                      " No",
                      " No",
                      " No",
                      " No",
                      " No",
                      " No",
                      " Yes -- delete all user data",   // [7]
                      " No",
                      " No",
                      " No",
                      NULL };
                      
    int chosen_item = show_interactive_menu(headers, items);
		hide_menu_selection();
    if (chosen_item != 8) 
        return;
  }

	ui_led_blink(1);
  ui_print("\n-- Wiping data...\n");
  device_wipe_data();
  erase_root("DATA:");
  erase_root("CACHE:");
  ensure_common_roots_mounted();
  ui_print("Data wipe complete.\n");
 	ui_led_toggle(0);
}
Ejemplo n.º 2
0
void run_shell_script(const char *command, int stdoutToUI, char** extra_env_variables) 
{
	char *argp[] = {PHONE_SHELL, "-c", NULL, NULL};
	
	//check it
	if (!command)
		return;
	
	//add the command
	argp[2] = (char *)command;
	fprintf(stderr, "Running Shell Script: \"%s\"\n", command);
	
	//interactive menu shared memory node
	int imenu_fd = 0;
	
	//pipes
	int script_pipefd[2];
		
	if (stdoutToUI)
	{
  	pipe(script_pipefd);
  	
  	if((imenu_fd = open(INTERACTIVE_MENU_SHM, (O_CREAT | O_RDWR),
				             666)) < 0 ) 
		{
			LOGE("Failed opening the shared memory node for interactive menu.\n");
			LOGE("Interactive menu disabled.\n");
		}
		else
		{
			ftruncate(imenu_fd, sizeof(interactive_menu_struct));
			if ((interactive_menu = ((interactive_menu_struct*) mmap(0, sizeof(interactive_menu_struct), (PROT_READ | PROT_WRITE),
                   MAP_SHARED, imenu_fd, 0))) == MAP_FAILED)
			{
				LOGE("Failed opening the shared memory node for interactive menu.\n");
				LOGE("Interactive menu disabled.\n");
				interactive_menu = NULL;
			}
			else
			{
				interactive_menu->in_trigger = 0;
				interactive_menu->out_trigger = 0;
				interactive_menu->header[0] = '\0';
				interactive_menu->items[0][0] = '\0';
			}
		}
	}

	pid_t child = fork();
	if (child == 0) 
	{
		if (stdoutToUI)
		{
			//put stdout to the pipe only
			close(script_pipefd[0]);
			dup2(script_pipefd[1], 1); 
		}
		
		if (extra_env_variables != NULL)
		{
			while (*extra_env_variables)
			{
				fprintf(stderr, "run_shell_script: child env variable %s\n", *extra_env_variables);
				putenv(*extra_env_variables);
				extra_env_variables++;
			}
		}
		
		execv(PHONE_SHELL, argp);
		fprintf(stderr, "run_shell_script: execv failed: %s\n", strerror(errno));
		_exit(1);
	}
	
	//status for the waitpid	
	int sts;
		
	if (stdoutToUI)
	{				
		char buffer[1024+1];
		
		//nonblocking mode
		int f = fcntl(script_pipefd[0], F_GETFL, 0);
  	// Set bit for non-blocking flag
  	f |= O_NONBLOCK;
  	// Change flags on fd
  	fcntl(script_pipefd[0], F_SETFL, f);
  	
								
  	while (1)
  	{
  		//maybe use signalling
  		if (interactive_menu != NULL && interactive_menu->in_trigger)
  		{
  			interactive_menu->in_trigger = 0;
  			fprintf(stderr, "run_shell_script: interactive_menu triggered\n");
  			//first print the rest, but don't bother if there is an error
  			int rv = read(script_pipefd[0], buffer, 1024);	
  			if (rv > 0)
  			{
  				buffer[rv] = 0;	
					ui_print_raw(buffer);
				}
				
				//parse the name and headers
				char* headers[3];
				char* items[20];
				
				headers[0] = interactive_menu->header;
				headers[1] = " ";
				headers[2] = NULL;
				
				int i;
				for (i = 0; interactive_menu->items[i][0] && i < 20; i++)
					items[i] = interactive_menu->items[i];
			
				items[i] = NULL;
				
				//show the menu
				ui_led_toggle(0);
				fprintf(stderr, "run_shell_script: showing interactive menu\n");
				int chosen_item = show_interactive_menu(headers, items);
        ui_led_blink(1);
        
        interactive_menu->header[0] = '\0';
				interactive_menu->items[0][0] = '\0';
        interactive_menu->out_trigger = chosen_item;   
  		}
  	
  		int rv = read(script_pipefd[0], buffer, 1024);		
  		
  		if (rv <= 0)
  		{
  			if(errno == EAGAIN)
  			{
					if (waitpid(child, &sts, WNOHANG))
					{
						//do one last check (race)
						int rv = read(script_pipefd[0], buffer, 1024);
						
						if (rv > 0)
						{
							buffer[rv] = 0;	
							ui_print_raw(buffer);
						}
						
						break;
					}
  					
  				continue;
  			}
  			
  			fprintf(stderr, "run_shell_script: there was a read error %d.\n", errno);
  			waitpid(child, &sts, 0);
  			break;
  		}
  	  		
  		//if the string is read only partially, it won't be null terminated		  		
			buffer[rv] = 0;	
			ui_print_raw(buffer);
  	}
	}
	else
		waitpid(child, &sts, 0);
		
	//check exit status
	if (WIFEXITED(sts)) 
	{
		if (WEXITSTATUS(sts) != 0) 
		{
			fprintf(stderr, "run_shell_script: child exited with status %d.\n",
			WEXITSTATUS(sts));
		}
	} 
	else if (WIFSIGNALED(sts)) 
	{
		fprintf(stderr, "run_shell_script: child terminated by signal %d.\n",
		WTERMSIG(sts));
	}

	if (stdoutToUI)
	{
		//close the pipe here after killing the process
		close(script_pipefd[1]);
		close(script_pipefd[0]);
		
		if (imenu_fd > 0)
		{
			close(imenu_fd);
			remove(INTERACTIVE_MENU_SHM);
		}
		
		interactive_menu = NULL;
	}
}
Ejemplo n.º 3
0
/**
 * @brief SD LED Toggle.
 */
void ui_led_sd_toggle( void )
{
	ui_led_toggle( &ui_led_sd );
}
Ejemplo n.º 4
0
static void
prompt_and_wait()
{
	char* menu_files[MAX_MENU_LEVEL] = { NULL };
	char* menu_scripts[MAX_MENU_LEVEL] = { NULL };
	int menu_sel[MAX_MENU_LEVEL] = { 0 };
	unsigned int menu_level = 0;  
	int menu_result;
  
  //always ensure if mountings are good
  ensure_common_roots_mounted();
  
	//initialize the recovery -> either call the script for initalization, or switch to full version
#if !OPEN_RCVR_VERSION_LITE
	run_shell_script("/bin/init_recovery.sh "OPEN_RECOVERY_PHONE_SWITCH, 1, NULL);
#endif 

  menu_files[0] = malloc(strlen(MAIN_MENU_FILE)+1);
  strcpy(menu_files[0], MAIN_MENU_FILE);
  ui_led_blink(1);
  create_menu(menu_files[0], menu_scripts[0]);
  ui_led_toggle(0);
  int title_length;  
	char** headers;
	headers = prepend_title(MENU_HEADERS, &title_length);
	int override_initial_selection = -1;	
	
	int call_finish_in_loop = 1;
			
  for (;;) {  

		if (call_finish_in_loop)
		{
			finish_recovery(NULL);
			call_finish_in_loop = 0;
		}

		int menu_item;		
		
		if (override_initial_selection != -1)
		{
			menu_item = get_menu_selection(headers, MENU_ITEMS, MENU_ITEMS_SELECTABLE, title_length, override_initial_selection, 0);
			override_initial_selection = -1;
		}
		else
    	menu_item = get_menu_selection(headers, MENU_ITEMS, MENU_ITEMS_SELECTABLE, title_length, 0, 0);

    // Parse open recovery commands
    int chosen_item = select_action(menu_item);
    chosen_item = device_perform_action(chosen_item);

		//if tag, menu, or scripted menu -> don't hide menu
		//do it here explicitly, it would be a mess in the switch
		if (chosen_item != ITEM_TAG && chosen_item != ITEM_NEW_MENU 
		    && chosen_item != ITEM_NEW_MENU_SCRIPTED)
			hide_menu_selection();

		fprintf(stderr, "Menu: %d, %d, %s\n", menu_item, chosen_item, MENU_ITEMS_TARGET[menu_item]);

    switch (chosen_item) {
    	case ITEM_REBOOT:
       	return;

      case ITEM_WIPE_DATA:
        wipe_data(ui_text_visible());

        if (!ui_text_visible()) 
        	return;
        	
        ui_set_background(BACKGROUND_ICON_ERROR);
        break;

      case ITEM_WIPE_CACHE:
        ui_print("\n-- Wiping cache...\n");
				ui_led_blink(1);
        erase_root("CACHE:");
        ensure_common_roots_mounted();
				ui_led_toggle(0);
        ui_print("Cache wipe complete.\n");
        if (!ui_text_visible()) 
        	return;
        ui_set_background(BACKGROUND_ICON_ERROR);
        break;

      case ITEM_APPLY_SDCARD:
      
      	//HACK for "error: a label can only be part of a statement and a declaration is not a statement"
      	//the rule is retarted, the follwing "dummy" statement is cut in optimization
      	override_initial_selection=override_initial_selection; 
      
      	//confirm it	
      	char* confirm_headers[] = { "Confirm installing update package?",
      															 MENU_ITEMS[menu_item],
      															 "",
      															 NULL
      														};
      	char* confirm_items[] = { "Yes", "No", NULL };
      	int confirm_item = show_interactive_menu(confirm_headers, confirm_items);
      	
      	if (confirm_item == 1) //YES!
      	{      	
		      ui_print("\n-- Install from sdcard...\n");
		      ui_led_blink(1);
		      ensure_common_roots_unmounted();
		      ensure_root_path_mounted("SDCARD:");
		      set_sdcard_update_bootloader_message();
		      call_finish_in_loop = 1;
		      int status = install_package(MENU_ITEMS_TARGET[menu_item]);
		      ensure_common_roots_mounted();
		      if (status != INSTALL_SUCCESS) 
		      {
						ui_set_background(BACKGROUND_ICON_ERROR);
						ui_print("Installation aborted.\n");
		      } 
		      else if (!ui_text_visible()) 
	          return;  // reboot if logs aren't visible
		      else 
		      {
		        if (firmware_update_pending()) 
		        {
	        		ui_set_background(BACKGROUND_ICON_ERROR);
	            ui_print("\nReboot via menu to complete\n"
	                     "installation.\n");
		        } 
		        else 
		        {
	        		ui_set_background(BACKGROUND_ICON_ERROR);
	            ui_print("\nInstall from sdcard complete.\n");
		        }
		      }
		      
		      create_menu(menu_files[menu_level], menu_scripts[menu_level]);
		      free(headers);
		      headers = prepend_title(MENU_HEADERS, &title_length);
		      ui_led_toggle(0);
		    }
        
        override_initial_selection = menu_item;											
 				break; 

      case ITEM_SHELL_SCRIPT:
        ui_print("\n-- Shell script...\n");
        ui_print("%s\n", MENU_ITEMS_TARGET[menu_item]);
				ui_led_blink(1);
				ensure_common_roots_mounted();
				
				run_shell_script(MENU_ITEMS_TARGET[menu_item], 1, NULL);
				create_menu(menu_files[menu_level], menu_scripts[menu_level]);
				free(headers);
				headers = prepend_title(MENU_HEADERS, &title_length);
				
				ui_led_toggle(0);
        ui_print("Done.\n");
				
				override_initial_selection = menu_item;											
 				break; 
				
			case ITEM_TAG:
			
				if (MENU_ITEMS_TAG[menu_item] == 0x00)
				{
					int tag_fd = creat(MENU_ITEMS_TARGET[menu_item], 0644);
					if (tag_fd < 0)
						LOGE("Failed to set the tag.\n");
					else
					{
						MENU_ITEMS_TAG[menu_item] = 0x01;
						MENU_ITEMS[menu_item][1] = 'X';
						close(tag_fd);
					}					 
				}
				else if (MENU_ITEMS_TAG[menu_item] == 0x01) //just a little check if 0xFF aint there if bug is present
				{
					remove(MENU_ITEMS_TARGET[menu_item]);
					MENU_ITEMS_TAG[menu_item] = 0x00;
					MENU_ITEMS[menu_item][1] = ' '; 
				}
			
				override_initial_selection = menu_item;											
 				break; 

      case ITEM_NEW_MENU:
				if (menu_level + 1 >= MAX_MENU_LEVEL)
				{
					//too much menus, ignore
					break;
				}
							
				ui_led_blink(1);
				if (!strcmp(MENU_ITEMS_TARGET[menu_item], ".."))
				{
					if (menu_level)
					{
						free(menu_files[menu_level]);
						menu_files[menu_level] = NULL;
						
						if (menu_scripts[menu_level])
						{
							free(menu_scripts[menu_level]);
							menu_scripts[menu_level] = NULL;
						}
						
						menu_sel[menu_level] = 0;
						menu_level--;
						override_initial_selection = menu_sel[menu_level];
					}
				}
				else
				{
					menu_sel[menu_level] = menu_item;
					menu_level++;
					menu_files[menu_level] = malloc(strlen(MENU_ITEMS_TARGET[menu_item]) + 1);
					strcpy(menu_files[menu_level], MENU_ITEMS_TARGET[menu_item]);				
				}
					
				ensure_common_roots_mounted();	
				menu_result = create_menu(menu_files[menu_level], menu_scripts[menu_level]);
				
				//if fail, remove the new menu
				if (menu_result && menu_level)
				{
					free(menu_files[menu_level]);
					menu_files[menu_level] = NULL;
					
					if (menu_scripts[menu_level])
					{
						free(menu_scripts[menu_level]);
						menu_scripts[menu_level] = NULL;
					}
					
					menu_level--;
				}
				
				free(headers);
				headers = prepend_title(MENU_HEADERS, &title_length);
				ui_led_toggle(0);
				break;
			
			case ITEM_NEW_MENU_SCRIPTED:
			
				if (menu_level + 1 >= MAX_MENU_LEVEL)
				{
					//too much menus, ignore
					break;
				}
			
				ui_led_blink(1);
				char cmdBuff[MAX_LINE_LENGTH];
				strcpy(cmdBuff, MENU_ITEMS_TARGET[menu_item]);
				char* ptr;
										
				//menufile:script
				ptr = strtok(cmdBuff, ":");
				if (ptr != NULL)
				{
					menu_sel[menu_level] = menu_item;
					menu_level++;
					menu_files[menu_level] = malloc(strlen(ptr) + 1);
					strcpy(menu_files[menu_level], ptr);						
					
					ptr = strtok(NULL, "");
					if (ptr != NULL)
					{
						if (ptr[0] == '/' || (ptr[0] == '\"' && ptr[1] == '/'))
						{
							menu_scripts[menu_level] = malloc(strlen(ptr) + 1);
							strcpy(menu_scripts[menu_level], ptr);					
						}
						else
						{
							menu_scripts[menu_level] = malloc(strlen(CUSTOM_SHELL_SCRIPT_PATH) + strlen(ptr) + 2);
						
							if (ptr[0] == '\"')
								sprintf(menu_scripts[menu_level], "\"%s/%s", CUSTOM_SHELL_SCRIPT_PATH, ptr+1);
							else
								sprintf(menu_scripts[menu_level], "%s/%s", CUSTOM_SHELL_SCRIPT_PATH, ptr);

						}
					}
					
					ensure_common_roots_mounted();
					menu_result = create_menu(menu_files[menu_level], menu_scripts[menu_level]);
					
					//if fail, remove the new menu
					if (menu_result && menu_level)
					{
						free(menu_files[menu_level]);
						menu_files[menu_level] = NULL;
						
						if (menu_scripts[menu_level])
						{
							free(menu_scripts[menu_level]);
							menu_scripts[menu_level] = NULL;
						}
						
						menu_level--;
					}
					
					free(headers);
					headers = prepend_title(MENU_HEADERS, &title_length);
				}
					
				ui_led_toggle(0);
				break;
			
			case ITEM_CONSOLE:
#if OPEN_RECOVERY_HAVE_CONSOLE
				ensure_common_roots_mounted();
				
				ui_print("Opening console...\n");
				int console_error = run_console(NULL);
				
				if (console_error)
					if (console_error == CONSOLE_FORCE_QUIT)
						ui_print("Console was forcibly closed.\n");
					else if (console_error == CONSOLE_FAILED_START)
						ui_print("Console failed to start.\n");
					else
					{
						ui_print("Closing console...\n"); //don't bother printing error to UI
						fprintf(stderr, "Console closed with error %d.\n", console_error);
					}		
				else
					ui_print("Closing console...\n");
					
				create_menu(menu_files[menu_level], menu_scripts[menu_level]);
				free(headers);
				headers = prepend_title(MENU_HEADERS, &title_length);
#else
				LOGE("This phone doesn't support console.\n");
#endif
				override_initial_selection = menu_item;											
 				break; 
			
			case ITEM_ERROR:
				LOGE("Unknown command: %s.\n", MENU_ITEMS_ACTION[menu_item]);
				break;
    }
  }
}