示例#1
0
uint8_t bootmgr_handle_key(int key)
{
    if(sleep_mode)
    {
        bootmgr_do_sleep(0);
        return 0;
    }

    switch(bootmgr_phase)
    {
        case BOOTMGR_MAIN:
        {
            switch(key)
            {
                case KEY_VOLUMEDOWN:
                {
                   if(++bootmgr_selected == 4)
                       bootmgr_selected = 0;
                   break;
                }
                case KEY_VOLUMEUP:
                {
                   if(--bootmgr_selected == -1)
                       bootmgr_selected = 3;
                   break;
                }
                case KEY_BACK:
                    bootmgr_printf(-1, 25, WHITE, "Rebooting...");
                    bootmgr_draw();
                    __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, "recovery");
                    return 1;
                case KEY_END:
                {
                    bootmgr_do_sleep(!sleep_mode);
                    break;
                }
                case KEY_POWER:
                {
                    reboot(RB_POWER_OFF);
                    return 1;
                }
                case KEY_MENU:
                {
                    switch(bootmgr_selected)
                    {
                        case 0: bootmgr_boot_internal(); return 1;
                        case 1:
                            if(bootmgr_show_rom_list())
                                return 1;
                            break;
                        case 2: bootmgr_touch_ums();    break;
                        case 3: bootmgr_touch_misc(); break;
                    }
                    break;
                }
                case KEY_SEARCH:
                {
                    bootmgr_charger_init();
                    break;
                }
                default: break;
            }
            break;
        }
        case BOOTMGR_SD_SEL:
        {
            switch(key)
            {
                case KEY_VOLUMEDOWN:
                    bootmgr_touch_sd_down();
                    break;
                case KEY_VOLUMEUP:
                    bootmgr_touch_sd_up();
                    break;
                case KEY_MENU:
                    return bootmgr_boot_sd();
                case KEY_BACK:
                    bootmgr_touch_sd_exit();
                    break;
                default:break;
            }
            break;
        }
        case BOOTMGR_TETRIS:
        {
            tetris_key(key);
            break;
        }
        case BOOTMGR_UMS:
        {
            if(key != KEY_SEARCH)
                break;
            bootmgr_touch_exit_ums();
            break;
        }
        case BOOTMGR_CHARGER: return bootmgr_charger_key(key);
        case BOOTMGR_MISC:    return bootmgr_misc_key(key);
    }
    return 0;
}
示例#2
0
int main(int argc, char *argv[]) {
        bool need_umount, need_swapoff, need_loop_detach, need_dm_detach;
        bool in_container, use_watchdog = false;
        _cleanup_free_ char *cgroup = NULL;
        char *arguments[3];
        unsigned retries;
        int cmd, r;
        static const char* const dirs[] = {SYSTEM_SHUTDOWN_PATH, NULL};

        log_parse_environment();
        r = parse_argv(argc, argv);
        if (r < 0)
                goto error;

        /* journald will die if not gone yet. The log target defaults
         * to console, but may have been changed by command line options. */

        log_close_console(); /* force reopen of /dev/console */
        log_open();

        umask(0022);

        if (getpid() != 1) {
                log_error("Not executed by init (PID 1).");
                r = -EPERM;
                goto error;
        }

        if (streq(arg_verb, "reboot"))
                cmd = RB_AUTOBOOT;
        else if (streq(arg_verb, "poweroff"))
                cmd = RB_POWER_OFF;
        else if (streq(arg_verb, "halt"))
                cmd = RB_HALT_SYSTEM;
        else if (streq(arg_verb, "kexec"))
                cmd = LINUX_REBOOT_CMD_KEXEC;
        else if (streq(arg_verb, "exit"))
                cmd = 0; /* ignored, just checking that arg_verb is valid */
        else {
                r = -EINVAL;
                log_error("Unknown action '%s'.", arg_verb);
                goto error;
        }

        cg_get_root_path(&cgroup);

        use_watchdog = !!getenv("WATCHDOG_USEC");

        /* lock us into memory */
        mlockall(MCL_CURRENT|MCL_FUTURE);

        log_info("Sending SIGTERM to remaining processes...");
        broadcast_signal(SIGTERM, true, true);

        log_info("Sending SIGKILL to remaining processes...");
        broadcast_signal(SIGKILL, true, false);

        in_container = detect_container() > 0;

        need_umount = !in_container;
        need_swapoff = !in_container;
        need_loop_detach = !in_container;
        need_dm_detach = !in_container;

        /* Unmount all mountpoints, swaps, and loopback devices */
        for (retries = 0; retries < FINALIZE_ATTEMPTS; retries++) {
                bool changed = false;

                if (use_watchdog)
                        watchdog_ping();

                /* Let's trim the cgroup tree on each iteration so
                   that we leave an empty cgroup tree around, so that
                   container managers get a nice notify event when we
                   are down */
                if (cgroup)
                        cg_trim(SYSTEMD_CGROUP_CONTROLLER, cgroup, false);

                if (need_umount) {
                        log_info("Unmounting file systems.");
                        r = umount_all(&changed);
                        if (r == 0) {
                                need_umount = false;
                                log_info("All filesystems unmounted.");
                        } else if (r > 0)
                                log_info("Not all file systems unmounted, %d left.", r);
                        else
                                log_error_errno(r, "Failed to unmount file systems: %m");
                }

                if (need_swapoff) {
                        log_info("Deactivating swaps.");
                        r = swapoff_all(&changed);
                        if (r == 0) {
                                need_swapoff = false;
                                log_info("All swaps deactivated.");
                        } else if (r > 0)
                                log_info("Not all swaps deactivated, %d left.", r);
                        else
                                log_error_errno(r, "Failed to deactivate swaps: %m");
                }

                if (need_loop_detach) {
                        log_info("Detaching loop devices.");
                        r = loopback_detach_all(&changed);
                        if (r == 0) {
                                need_loop_detach = false;
                                log_info("All loop devices detached.");
                        } else if (r > 0)
                                log_info("Not all loop devices detached, %d left.", r);
                        else
                                log_error_errno(r, "Failed to detach loop devices: %m");
                }

                if (need_dm_detach) {
                        log_info("Detaching DM devices.");
                        r = dm_detach_all(&changed);
                        if (r == 0) {
                                need_dm_detach = false;
                                log_info("All DM devices detached.");
                        } else if (r > 0)
                                log_info("Not all DM devices detached, %d left.", r);
                        else
                                log_error_errno(r, "Failed to detach DM devices: %m");
                }

                if (!need_umount && !need_swapoff && !need_loop_detach && !need_dm_detach) {
                        if (retries > 0)
                                log_info("All filesystems, swaps, loop devices, DM devices detached.");
                        /* Yay, done */
                        goto initrd_jump;
                }

                /* If in this iteration we didn't manage to
                 * unmount/deactivate anything, we simply give up */
                if (!changed) {
                        log_info("Cannot finalize remaining%s%s%s%s continuing.",
                                 need_umount ? " file systems," : "",
                                 need_swapoff ? " swap devices," : "",
                                 need_loop_detach ? " loop devices," : "",
                                 need_dm_detach ? " DM devices," : "");
                        goto initrd_jump;
                }

                log_debug("After %u retries, couldn't finalize remaining %s%s%s%s trying again.",
                          retries + 1,
                          need_umount ? " file systems," : "",
                          need_swapoff ? " swap devices," : "",
                          need_loop_detach ? " loop devices," : "",
                          need_dm_detach ? " DM devices," : "");
        }

        log_error("Too many iterations, giving up.");

 initrd_jump:

        arguments[0] = NULL;
        arguments[1] = arg_verb;
        arguments[2] = NULL;
        execute_directories(dirs, DEFAULT_TIMEOUT_USEC, arguments);

        if (!in_container && !in_initrd() &&
            access("/run/initramfs/shutdown", X_OK) == 0) {
                r = switch_root_initramfs();
                if (r >= 0) {
                        argv[0] = (char*) "/shutdown";

                        setsid();
                        make_console_stdio();

                        log_info("Successfully changed into root pivot.\n"
                                 "Returning to initrd...");

                        execv("/shutdown", argv);
                        log_error_errno(errno, "Failed to execute shutdown binary: %m");
                } else
                        log_error_errno(r, "Failed to switch root to \"/run/initramfs\": %m");

        }

        if (need_umount || need_swapoff || need_loop_detach || need_dm_detach)
                log_error("Failed to finalize %s%s%s%s ignoring",
                          need_umount ? " file systems," : "",
                          need_swapoff ? " swap devices," : "",
                          need_loop_detach ? " loop devices," : "",
                          need_dm_detach ? " DM devices," : "");

        /* The kernel will automaticall flush ATA disks and suchlike
         * on reboot(), but the file systems need to be synce'd
         * explicitly in advance. So let's do this here, but not
         * needlessly slow down containers. */
        if (!in_container)
                sync();

        if (streq(arg_verb, "exit")) {
                if (in_container)
                        exit(arg_exit_code);
                else {
                        /* We cannot exit() on the host, fallback on another
                         * method. */
                        cmd = RB_POWER_OFF;
                }
        }

        switch (cmd) {

        case LINUX_REBOOT_CMD_KEXEC:

                if (!in_container) {
                        /* We cheat and exec kexec to avoid doing all its work */
                        pid_t pid;

                        log_info("Rebooting with kexec.");

                        pid = fork();
                        if (pid < 0)
                                log_error_errno(errno, "Failed to fork: %m");
                        else if (pid == 0) {

                                const char * const args[] = {
                                        KEXEC, "-e", NULL
                                };

                                /* Child */

                                execv(args[0], (char * const *) args);
                                _exit(EXIT_FAILURE);
                        } else
                                wait_for_terminate_and_warn("kexec", pid, true);
                }

                cmd = RB_AUTOBOOT;
                /* Fall through */

        case RB_AUTOBOOT:

                if (!in_container) {
                        _cleanup_free_ char *param = NULL;

                        if (read_one_line_file(REBOOT_PARAM_FILE, &param) >= 0) {
                                log_info("Rebooting with argument '%s'.", param);
                                syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, param);
                        }
                }

                log_info("Rebooting.");
                break;

        case RB_POWER_OFF:
                log_info("Powering off.");
                break;

        case RB_HALT_SYSTEM:
                log_info("Halting system.");
                break;

        default:
                assert_not_reached("Unknown magic");
        }

        reboot(cmd);
        if (errno == EPERM && in_container) {
                /* If we are in a container, and we lacked
                 * CAP_SYS_BOOT just exit, this will kill our
                 * container for good. */
                log_info("Exiting container.");
                exit(0);
        }

        r = log_error_errno(errno, "Failed to invoke reboot(): %m");

  error:
        log_emergency_errno(r, "Critical error while doing system shutdown: %m");
        freeze();
}
示例#3
0
文件: init.c 项目: Ga-vin/MINIX3
int main(void)
{
  pid_t pid;			/* pid of child process */
  int fd;			/* generally useful */
  int linenr;			/* loop variable */
  int check;			/* check if a new process must be spawned */
  int sn;			/* signal number */
  struct slotent *slotp;	/* slots[] pointer */
  struct ttyent *ttyp;		/* ttytab entry */
  struct sigaction sa;
  struct stat stb;

#define OPENFDS						\
  if (fstat(0, &stb) < 0) {				\
	/* Open standard input, output & error. */	\
	(void) open("/dev/null", O_RDONLY);		\
	(void) open("/dev/log", O_WRONLY);		\
	dup(1);						\
  }

  sigemptyset(&sa.sa_mask);
  sa.sa_flags = 0;

  /* Default: Ignore every signal (except those that follow). */
  sa.sa_handler = SIG_IGN;
  for (sn = 1; sn < _NSIG; sn++) {
      sigaction(sn, &sa, NULL);
  }

  /* Hangup: Reexamine /etc/ttytab for newly enabled terminal lines. */
  sa.sa_handler = onhup;
  sigaction(SIGHUP, &sa, NULL);

  /* Terminate: Stop spawning login processes, shutdown is near. */
  sa.sa_handler = onterm;
  sigaction(SIGTERM, &sa, NULL);

  /* Abort: Sent by the kernel on CTRL-ALT-DEL; shut the system down. */
  sa.sa_handler = onabrt;
  sigaction(SIGABRT, &sa, NULL);

  /* Execute the /etc/rc file. */
  if ((pid = fork()) != 0) {
	/* Parent just waits. */
	while (wait(NULL) != pid) {
		if (gotabrt) reboot(RBT_HALT);
	}
  } else {
#if ! SYS_GETKENV
	struct sysgetenv sysgetenv;
#endif
	char bootopts[16];
	static char *rc_command[] = { "sh", "/etc/rc", NULL, NULL, NULL };
	char **rcp = rc_command + 2;

	/* Get the boot options from the boot environment. */
	sysgetenv.key = "bootopts";
	sysgetenv.keylen = 8+1;
	sysgetenv.val = bootopts;
	sysgetenv.vallen = sizeof(bootopts);
	if (svrctl(PMGETPARAM, &sysgetenv) == 0) *rcp++ = bootopts;
	*rcp = "start";

	execute(rc_command);
	report(2, "sh /etc/rc");
	_exit(1);	/* impossible, we hope */
  }

  OPENFDS;

  /* Clear /etc/utmp if it exists. */
  if ((fd = open(PATH_UTMP, O_WRONLY | O_TRUNC)) >= 0) close(fd);

  /* Log system reboot. */
  wtmp(BOOT_TIME, 0, NULL, 0);

  /* Main loop. If login processes have already been started up, wait for one
   * to terminate, or for a HUP signal to arrive. Start up new login processes
   * for all ttys which don't have them. Note that wait() also returns when
   * somebody's orphan dies, in which case ignore it.  If the TERM signal is
   * sent then stop spawning processes, shutdown time is near.
   */

  check = 1;
  while (1) {
	while ((pid = waitpid(-1, NULL, check ? WNOHANG : 0)) > 0) {
		/* Search to see which line terminated. */
		for (linenr = 0; linenr < PIDSLOTS; linenr++) {
			slotp = &slots[linenr];
			if (slotp->pid == pid) {
				/* Record process exiting. */
				wtmp(DEAD_PROCESS, linenr, NULL, pid);
				slotp->pid = NO_PID;
				check = 1;
			}
		}
	}

	/* If a signal 1 (SIGHUP) is received, simply reset error counts. */
	if (gothup) {
		gothup = 0;
		for (linenr = 0; linenr < PIDSLOTS; linenr++) {
			slots[linenr].errct = 0;
		}
		check = 1;
	}

	/* Shut down on signal 6 (SIGABRT). */
	if (gotabrt) {
		gotabrt = 0;
		startup(0, &TT_REBOOT);
	}

	if (spawn && check) {
		/* See which lines need a login process started up. */
		for (linenr = 0; linenr < PIDSLOTS; linenr++) {
			slotp = &slots[linenr];
			if ((ttyp = getttyent()) == NULL) break;

			if (ttyp->ty_getty != NULL
				/* ty_getty is a string, and TTY_ON is
				 * the way to check for enabled ternimanls. */
				&& (ttyp->ty_status & TTY_ON)
				&& slotp->pid == NO_PID
				&& slotp->errct < ERRCT_DISABLE)
			{
				startup(linenr, ttyp);
			}
		}
		endttyent();
	}
	check = 0;
  }
}
示例#4
0
int
main(int argc, char **argv) {
//    while(1);
	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);
	//    printf("Starting recovery on %s", ctime(&start));
//	printf("............just for aibing debug \n\r");
//	while(1);
	ui_init();
	//    ui_set_background(BACKGROUND_ICON_INSTALLING);
	load_volume_table();
	get_args(&argc, &argv);

	int previous_runs = 0;
	const char *send_intent = NULL;
	const char *update_package = NULL;
	const char *encrypted_fs_mode = NULL;
	int wipe_data = 0, wipe_cache = 0;
	int toggle_secure_fs = 0;
	encrypted_fs_info encrypted_fs_data; 
	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 'e': encrypted_fs_mode = optarg; toggle_secure_fs = 1; break;
			case 't': ui_show_text(1); break;
			case '?':
				  LOGE("Invalid command argument\n");
				  continue;
		}
	}
	//reinit wipe_data and wipe_cache as it will do in clean boot;
	wipe_data = wipe_cache = 0;

	device_recovery_start();

	printf("Aibing test Command:");
	for (arg = 0; arg < argc; arg++) {
		printf(" \"%s\"", argv[arg]);
	}
	printf("\n");
	if (update_package) {
		printf("in update_package run?????\n");
		// 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 = 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("list start\n");

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

	int status = INSTALL_SUCCESS;
	int mcu_status = INSTALL_SUCCESS;
	int mpeg_status = INSTALL_SUCCESS;
	int overridekey_status = INSTALL_SUCCESS;
	int tractor_prop_status = INSTALL_SUCCESS;
	int radio_status = INSTALL_SUCCESS;
	if (toggle_secure_fs) {
		if (strcmp(encrypted_fs_mode,"on") == 0) {
			encrypted_fs_data.mode = MODE_ENCRYPTED_FS_ENABLED;
			printf("Enabling Encrypted FS.\n");
		} else if (strcmp(encrypted_fs_mode,"off") == 0) {
			encrypted_fs_data.mode = MODE_ENCRYPTED_FS_DISABLED;
			printf("Disabling Encrypted FS.\n");
		} else {
			printf("Error: invalid Encrypted FS setting.\n");
			status = INSTALL_ERROR;
		}

		// Recovery strategy: if the data partition is damaged, disable encrypted file systems.
		// This preventsthe device recycling endlessly in recovery mode.
		if ((encrypted_fs_data.mode == MODE_ENCRYPTED_FS_ENABLED) &&
				(read_encrypted_fs_info(&encrypted_fs_data))) {
			printf("Encrypted FS change aborted, resetting to disabled state.\n");
			encrypted_fs_data.mode = MODE_ENCRYPTED_FS_DISABLED;
		}

		if (status != INSTALL_ERROR) {
			if (erase_volume("/data")) {
				printf("Data wipe failed.\n");
				status = INSTALL_ERROR;
			} else if (erase_volume("/cache")) {
				printf("Cache wipe failed.\n");
				status = INSTALL_ERROR;
			} else if ((encrypted_fs_data.mode == MODE_ENCRYPTED_FS_ENABLED) &&
					(restore_encrypted_fs_info(&encrypted_fs_data))) {
				printf("Encrypted FS change aborted.\n");
				status = INSTALL_ERROR;
			} else {
				printf("Successfully updated Encrypted FS.\n");
				status = INSTALL_SUCCESS;
			}
		}
	} else if (update_package != NULL) {
		status = install_package(update_package);
		if (status != INSTALL_SUCCESS) printf("Installation aborted.\n");
	} else if (wipe_data) {
		if (device_wipe_data()) status = INSTALL_ERROR;
		if (erase_volume("/data")) status = INSTALL_ERROR;
		if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR;
		if (status != INSTALL_SUCCESS) printf("Data wipe failed.\n");
	} else if (wipe_cache) {
		if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR;
		if (status != INSTALL_SUCCESS) printf("Cache wipe failed.\n");
	} else {
		status = INSTALL_ERROR;  // No command specified
	}
	
	printf("Recovery svn version:%d, Compile Time: %s %s\n", 
			SVN_VERSION,__DATE__,  __TIME__);
	sprintf(version_buf, "Recovery svn version:%d, Compile Time: %s %s", 
			SVN_VERSION,__TIME__, __DATE__);
	
	int fd = 0;
	fd = open("/dev/recovery",O_RDWR | O_CREAT | O_TRUNC);
	if(fd < 0) {
		printf("open recovery devices error\n");
		return EXIT_SUCCESS;
	} 
	
	int recovery_mode = 0;
	ioctl(fd, RECOVERY_GET_VAL, &recovery_mode);
//	recovery_mode = UPDATE_SYSTEM;

	/*	test_functions()  */
	//remove_logo_config_file();

	if(recovery_mode == CLEAN_MODE) {
		ui_set_cleanboot_background();
		ui_set_cleanboot_system();
		clean_boot();
		while(system_cleanboot_end == 0) {
			//printf("waiting thread is end");
			usleep(50000);
		}
		sync();
		ui_set_cleanboot_succ();
		sleep(3);
		close_backlight();
		reboot(RB_AUTOBOOT);
		printf("reboot end, it should never been output\n");
	} else if (recovery_mode == UPDATE_RECOVERY){
		ui_set_prepare_background();
		sleep(1);
		burning_recovery_image();
	} else if (recovery_mode == UPDATE_SYSTEM  || recovery_mode == BACKUP_MODE){
		ui_set_burning_background(BURNING_MISC_UPDATING);
		sleep(1);
		overridekey_status = update_overridekey();
		tractor_prop_status = update_tractorprop();
		radio_status = update_radioCFG();
		mpeg_status = mpeg_update();
		update_status &= ~(0x03 << 2);
		update_status |= mpeg_status << 2;
		ui_set_burning_reflesh(update_status);
		sleep(1);
		printf("mcu_start\n");
		mcu_status = mcu_update();		
		update_status &= ~(0x03 << 4);
		update_status |= (mcu_status << 4);
		ui_set_burning_reflesh(update_status);
		sleep(1);
		if(status == INSTALL_ERROR){
			printf("++check auto Burning update.zip in data tractor...\n");
			status = device_burn_data_if_exist();
			if(status == INSTALL_SUCCESS) {
				//burning_recovery_image();
			}
			ui_set_burning_status();
			printf("--check auto Burning update.zip in data tractor: %d\n", status);	 
			update_status &= ~(0x03);
			update_status |= status;
		}
		ui_set_burning_reflesh(update_status);
		sleep(3);
/*		
		if ( (mcu_status == INSTALL_SUCCESS) ||
				(status == INSTALL_SUCCESS)  || 
				(mpeg_status == INSTALL_SUCCESS)||
				(overridekey_status == INSTALL_SUCCESS)) {
			if (set_skip() == INSTALL_ERROR) {
				ui_set_burning_background(BURNING_RESULT_FAILURE);
				sleep(3);
				mcu_reset_cpu();
				return EXIT_FAILURE;
			}
		}
*/
		printf("end \n");
		if ( (status != INSTALL_SUCCESS) && 
				(mcu_status != INSTALL_SUCCESS) &&
				(mpeg_status != INSTALL_SUCCESS) && 
				(overridekey_status != INSTALL_SUCCESS)&& 
				(radio_status != INSTALL_SUCCESS)) {
			ui_set_burning_background(BURNING_RESULT_FAILURE);
			sleep(3);
			mcu_reset_cpu();
			return EXIT_FAILURE;
		}
		sync();
		ui_set_burning_background(BURNING_RESULT_SUCCESS);
		sleep(3);
		//while mcu is burning,  the mcu need to restart and reset the main cpu. 
		if (mcu_status == INSTALL_SUCCESS) {
			mcu_reset_cpu();
		} else {
			close_backlight();
			reboot(RB_AUTOBOOT);
		}
	}while(0);
	return EXIT_SUCCESS;
}
示例#5
0
文件: poweroff.c 项目: Adam-Koza/A3
int
main()
{
	reboot(RB_POWEROFF);
	return 0;
}
示例#6
0
/*
 * Bring the system up single user.
 */
static state_func_t
single_user(void)
{
	pid_t pid, wpid;
	int status;
	sigset_t mask;
	const char *shell;
	char *argv[2];
#ifdef SECURE
	struct ttyent *typ;
	struct passwd *pp;
	static const char banner[] =
		"Enter root password, or ^D to go multi-user\n";
	char *clear, *password;
#endif
#ifdef DEBUGSHELL
	char altshell[128];
#endif

	if (Reboot) {
		/* Instead of going single user, let's reboot the machine */
		sync();
		alarm(2);
		pause();
		reboot(howto);
		_exit(0);
	}

	shell = get_shell();

	if ((pid = fork()) == 0) {
		/*
		 * Start the single user session.
		 */
		setctty(_PATH_CONSOLE);

#ifdef SECURE
		/*
		 * Check the root password.
		 * We don't care if the console is 'on' by default;
		 * it's the only tty that can be 'off' and 'secure'.
		 */
		typ = getttynam("console");
		pp = getpwnam("root");
		if (typ && (typ->ty_status & TTY_SECURE) == 0 &&
		    pp && *pp->pw_passwd) {
			write_stderr(banner);
			for (;;) {
				clear = getpass("Password:"******"single-user login failed\n");
			}
		}
		endttyent();
		endpwent();
#endif /* SECURE */

#ifdef DEBUGSHELL
		{
			char *cp = altshell;
			int num;

#define	SHREQUEST "Enter full pathname of shell or RETURN for "
			write_stderr(SHREQUEST);
			write_stderr(shell);
			write_stderr(": ");
			while ((num = read(STDIN_FILENO, cp, 1)) != -1 &&
			    num != 0 && *cp != '\n' && cp < &altshell[127])
				cp++;
			*cp = '\0';
			if (altshell[0] != '\0')
				shell = altshell;
		}
#endif /* DEBUGSHELL */

		/*
		 * Unblock signals.
		 * We catch all the interesting ones,
		 * and those are reset to SIG_DFL on exec.
		 */
		sigemptyset(&mask);
		sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0);

		/*
		 * Fire off a shell.
		 * If the default one doesn't work, try the Bourne shell.
		 */

		char name[] = "-sh";

		argv[0] = name;
		argv[1] = 0;
		execv(shell, argv);
		emergency("can't exec %s for single user: %m", shell);
		execv(_PATH_BSHELL, argv);
		emergency("can't exec %s for single user: %m", _PATH_BSHELL);
		sleep(STALL_TIMEOUT);
		_exit(1);
	}

	if (pid == -1) {
		/*
		 * We are seriously hosed.  Do our best.
		 */
		emergency("can't fork single-user shell, trying again");
		while (waitpid(-1, (int *) 0, WNOHANG) > 0)
			continue;
		return (state_func_t) single_user;
	}

	requested_transition = 0;
	do {
		if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1)
			collect_child(wpid);
		if (wpid == -1) {
			if (errno == EINTR)
				continue;
			warning("wait for single-user shell failed: %m; restarting");
			return (state_func_t) single_user;
		}
		if (wpid == pid && WIFSTOPPED(status)) {
			warning("init: shell stopped, restarting\n");
			kill(pid, SIGCONT);
			wpid = -1;
		}
	} while (wpid != pid && !requested_transition);

	if (requested_transition)
		return (state_func_t) requested_transition;

	if (!WIFEXITED(status)) {
		if (WTERMSIG(status) == SIGKILL) {
			/*
			 *  reboot(8) killed shell?
			 */
			warning("single user shell terminated.");
			sleep(STALL_TIMEOUT);
			_exit(0);
		} else {
			warning("single user shell terminated, restarting");
			return (state_func_t) single_user;
		}
	}

	runcom_mode = FASTBOOT;
	return (state_func_t) runcom;
}
示例#7
0
/* Process menu context 
 * Return 0 to select, <0 to raise error, >0 to continue
 */
int process_ctx_menu(struct params_t *params, int action) {
	static int rc;
	static int menu_action;
	static kx_menu *menu;
	menu = params->menu;

#ifdef USE_NUMKEYS
	/* Some hacks to allow menu items selection by keys 0-9 */
	if ((action >= A_KEY0) && (action <= A_KEY9)) {
		rc = action - A_KEY0;
		if (-1 == menu_item_select_by_no(menu, rc)) {
			/* There is no item with such number - do nothing */
			return 1;
		} else {
			action = A_SELECT;
		}
	}
#endif

	menu_action = (A_SELECT == action ? menu->current->current->id : action);
	rc = 1;

	switch (menu_action) {
	case A_UP:
		menu_item_select(menu, -1);
		break;
	case A_DOWN:
		menu_item_select(menu, 1);
		break;
	case A_SUBMENU:
		menu->current = menu->current->current->submenu;
		break;
	case A_PARENTMENU:
		menu->current = menu->current->parent;
		break;

	case A_REBOOT:
#ifdef USE_FBMENU
		gui_show_msg(params->gui, "Rebooting...");
#endif
#ifdef USE_TEXTUI
		tui_show_msg(params->tui, "Rebooting...");
#endif
#ifdef USE_HOST_DEBUG
		sleep(1);
#else
		sync();
		/* if ( -1 == reboot(LINUX_REBOOT_CMD_RESTART) ) { */
		if ( -1 == reboot(RB_AUTOBOOT) ) {
			log_msg(lg, "Can't initiate reboot: %s", ERRMSG);
		}
#endif
		break;
	case A_SHUTDOWN:
#ifdef USE_FBMENU
		gui_show_msg(params->gui, "Shutting down...");
#endif
#ifdef USE_TEXTUI
		tui_show_msg(params->tui, "Shutting down...");
#endif
#ifdef USE_HOST_DEBUG
		sleep(1);
#else
		sync();
		/* if ( -1 == reboot(LINUX_REBOOT_CMD_POWER_OFF) ) { */
		if ( -1 == reboot(RB_POWER_OFF) ) {
			log_msg(lg, "Can't initiate shutdown: %s", ERRMSG);
		}
#endif
		break;

	case A_RESCAN:
#ifdef USE_FBMENU
		gui_show_msg(params->gui, "Rescanning devices.\nPlease wait...");
#endif
#ifdef USE_TEXTUI
		tui_show_msg(params->tui, "Rescanning devices.\nPlease wait...");
#endif
		if (-1 == do_rescan(params)) {
			log_msg(lg, "Rescan failed");
			return -1;
		}
		menu = params->menu;
		break;

	case A_DEBUG:
		params->context = KX_CTX_TEXTVIEW;
		break;

	case A_EXIT:
		if (initmode) break;	// don't exit if we are init
	case A_ERROR:
		rc = -1;
		break;

#ifdef USE_TIMEOUT
	case A_TIMEOUT:		// timeout was reached - boot 1st kernel if exists
		if (menu->current->count > 1) {
			menu_item_select(menu, 0);	/* choose first item */
			menu_item_select(menu, 1);	/* and switch to next item */
			rc = 0;
		}
		break;
#endif

	default:
		if (menu_action >= A_DEVICES) rc = 0;
		break;
	}

	return rc;
}
示例#8
0
/* Get characters from keyboard */
char *keyb_get(void)
{
	uchar_t dt;
	static uchar_t extended = 0, lock_state = 0;
	static uint_t shift_state = 0;
	static uchar_t capchar[2];

	dt = bus_inb(0x60);
		
	capchar[0] = 0;
	capchar[1] = 0;
	
	/* Key is released */
	if (dt & 0x80) {
		dt &= 0x7f;
		switch (scan_codes[dt].type) {
		case KB_NUM:
			shift_state &= ~KB_NUM;
			break;
		case KB_CAPS:
			shift_state &= ~KB_CAPS;
			break;
		case KB_SCROLL:
			shift_state &= ~KB_SCROLL;
			break;
		case KB_SHIFT:
			shift_state &= ~KB_SHIFT;
			break;
		case KB_ALT:
			if (extended)
				shift_state &= ~KB_ALTGR;
			else
				shift_state &= ~KB_ALT;
			break;
		case KB_CTL:
			shift_state &= ~KB_CTL;
			break;
		}
	}
	
	/* Key is pressed */
	else {
		switch (scan_codes[dt].type) {

		/* Locking keys - Caps, Scroll, Num */
		case KB_NUM:
			if (shift_state & KB_NUM)
				break;
			shift_state |= KB_NUM;
			lock_state ^= KB_NUM;
			/*async_update();*/
			break;
		case KB_CAPS:
			if (shift_state & KB_CAPS)
				break;
			shift_state |= KB_CAPS;
			lock_state ^= KB_CAPS;
			/*async_update();*/
			break;
		case KB_SCROLL:
			if (shift_state & KB_SCROLL)
				break;
			shift_state |= KB_SCROLL;
			lock_state ^= KB_SCROLL;
			/*async_update();*/
			break;

		/* Special no locking keys */
		case KB_SHIFT:
			shift_state |= KB_SHIFT;
			break;
		case KB_ALT:
			if (extended)
				shift_state |= KB_ALTGR;
			else
				shift_state |= KB_ALT;
			break;
		case KB_CTL:
			shift_state |= KB_CTL;
			break;
		
		/* Regular ASCII */
		case KB_ASCII:
			
			/* Control is pressed */
			if (shift_state & KB_CTL)
				capchar[0] = scan_codes[dt].ctl[0];
			
			/* Right alt and right alt with shift */
			else if (shift_state & KB_ALTGR) {
				if (shift_state & KB_SHIFT)
					capchar[0] = scan_codes[dt].shift_altgr[0];
				else
					capchar[0] = scan_codes[dt].altgr[0];
						
			/* Shift */
			} else {
				if (shift_state & KB_SHIFT)
					capchar[0] = scan_codes[dt].shift[0];
				
				/* Only key without special keys */
				else
					capchar[0] = scan_codes[dt].unshift[0];
			}
			
			/* If CAPS is active capitalize letters */
			if ((lock_state & KB_CAPS) && capchar[0] >= 'a' && capchar[0] <= 'z') {
				capchar[0] -= ('a' - 'A');
			}
			
			/* Left ALT */
			capchar[0] |= (shift_state & KB_ALT);
			extended = 0;
			return capchar;
		
		/* Key without meaning */	
		case KB_NONE:
			break;
			
		/* Function key */	
		case KB_FUNC: {
			char *more_chars;
			if (shift_state & KB_SHIFT)
				more_chars = scan_codes[dt].shift;
			else if (shift_state & KB_CTL)
				more_chars = scan_codes[dt].ctl;
			else
				more_chars = scan_codes[dt].unshift;
			extended = 0;
			return more_chars;
		}
		
		/* Keypad */
		case KB_KP: {
			char *more_chars;
			
			/* Reboot sequence */
			if ((shift_state & KB_ALT) && (shift_state & KB_CTL) && (dt == 83)) {
				std_printf("Rebooting ...\n");
				reboot();
				return capchar;
			}
			
			if (shift_state & (KB_SHIFT | KB_CTL) || (lock_state & KB_NUM) == 0 || extended)
				more_chars = scan_codes[dt].shift;
			else
				more_chars = scan_codes[dt].unshift;
			extended = 0;
			return more_chars;
		}
		}
	}

	extended = 0;
	return capchar;
}
示例#9
0
/* Remounting filesystems read-only is difficult when there are files
 * opened for writing or pending deletes on the filesystem.  There is
 * no way to force the remount with the mount(2) syscall.  The magic sysrq
 * 'u' command does an emergency remount read-only on all writable filesystems
 * that have a block device (i.e. not tmpfs filesystems) by calling
 * emergency_remount(), which knows how to force the remount to read-only.
 * Unfortunately, that is asynchronous, and just schedules the work and
 * returns.  The best way to determine if it is done is to read /proc/mounts
 * repeatedly until there are no more writable filesystems mounted on
 * block devices.
 */
static void remount_ro(void)
{
    int fd, cnt = 0;

    /* Trigger the remount of the filesystems as read-only,
     * which also marks them clean.
     */
    fd = open("/proc/sysrq-trigger", O_WRONLY);
    if (fd < 0) {
        return;
    }
    write(fd, "u", 1);
    close(fd);


    /* Now poll /proc/mounts till it's done */
#ifdef STE_HARDWARE
    while (!remount_ro_done() && (cnt < 50)) {
#else
    while (!remount_ro_done() && (cnt < 3600)) {
#endif
        usleep(100000);
        cnt++;
    }

    return;
}


int android_reboot(int cmd, int flags, char *arg)
{
    int ret = 0;
    int reason = -1;

#ifdef RECOVERY_PRE_COMMAND
    if (cmd == (int) ANDROID_RB_RESTART2) {
        if (arg && strlen(arg) > 0) {
            char cmd[PATH_MAX];
            sprintf(cmd, RECOVERY_PRE_COMMAND " %s", arg);
            system(cmd);
        }
    }
#endif

    sync();
    remount_ro();

    switch (cmd) {
        case ANDROID_RB_RESTART:
            reason = RB_AUTOBOOT;
            break;

        case ANDROID_RB_POWEROFF:
            ret = reboot(RB_POWER_OFF);
            return ret;

        case ANDROID_RB_RESTART2:
            // REBOOT_MAGIC
            break;

        default:
            return -1;
    }

#ifdef RECOVERY_PRE_COMMAND_CLEAR_REASON
    reason = RB_AUTOBOOT;
#endif

    if (reason != -1)
        ret = reboot(reason);
    else
        ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
                           LINUX_REBOOT_CMD_RESTART2, arg);

    return ret;
}
示例#10
0
void bootloader(void)
{
    BKPInit();
    BKPWrite(STAY_IN_BOOTLOADER_MAGIC);
    reboot();
}
示例#11
0
文件: halt.c 项目: Obarun/obarun-boot
int main(int argc, char *argv[]) {
  int do_sync = 1;
  int do_force = 0;
  int opt;
  action_type action = NOOP;

  if (strcmp(__progname, "halt") == 0)
    action = HALT;
  else if (strcmp(__progname, "reboot") == 0)
    action = REBOOT;
  else if (strcmp(__progname, "poweroff") == 0)
    action = POWEROFF;
  else
    warnx("no default behavior, needs to be called as halt/reboot/poweroff.");

  while ((opt = getopt(argc, argv, "dfhinw")) != -1)
    switch (opt) {
    case 'n':
      do_sync = 0;
      break;
    case 'w':
      action = NOOP;
      do_sync = 0;
      break;
    case 'd':
    case 'h':
    case 'i':
      /* silently ignored.  */
      break;
    case 'f':
      do_force = 1;
      break;
    default:
      errx(1, "Usage: %s [-n] [-f]", __progname);
    }

  if (do_sync)
    sync();

  switch (action) {
  case HALT:
    if (do_force)
      reboot(RB_HALT_SYSTEM);
    else
      execl("/usr/bin/runit-init", "init", "0", (char*)0);
    err(1, "halt failed");
    break;
  case POWEROFF:
    if (do_force)
      reboot(RB_POWER_OFF);
    else
      execl("/usr/bin/runit-init", "init", "0", (char*)0);
    err(1, "poweroff failed");
    break;
  case REBOOT:
    if (do_force)
      reboot(RB_AUTOBOOT);
    else
      execl("/usr/bin/runit-init", "init", "6", (char*)0);
    err(1, "reboot failed");
    break;
  case NOOP:
    break;
  }

  return 0;
}
示例#12
0
void ProcessServer::onReceive( dword client, byte message, const InStream & input )
{
	//LOG_STATUS( "ProcessServer","onReceive, client = %u (%s), message = 0x%x", client, clientAddress(client), message );

	switch( message )
	{
	case ProcessClient::SERVER_LOGIN:
		{
			dword job;
			input >> job;
			CharString uid;
			input >> uid;
			CharString md5;
			input >> md5;

			bool result = false;

			MetaClient::Profile profile;
			if ( m_MetaClient.loginByProxy( uid, md5, profile ) > 0 )
			{
				LOG_STATUS( "ProcessServer", CharString().format("Login %s, client %u (%s)", profile.name.cstr(), client, clientAddress(client)) );
				result = (profile.flags & (MetaClient::ADMINISTRATOR|MetaClient::SERVER)) != 0;
			}
			else
				LOG_STATUS( "ProcessServer", CharString().format("Login failed, client %u (%s)", client, clientAddress(client)) );

			AutoLock lock( &m_Lock );

			m_ClientValid[ client ] = result;
			send( client, ProcessClient::CLIENT_JOB_DONE ) << job << result;
		}
		break;
	case ProcessClient::SERVER_SESSION_LOGIN:
		{
			dword job;
			input >> job;
			dword sessionId;
			input >> sessionId;

			bool result = false;

			MetaClient::Profile profile;
			if ( m_MetaClient.loginByProxy( sessionId, profile ) > 0 )
			{
				LOG_STATUS( "ProcessServer", CharString().format("Login %s, client %u (%s)", profile.name.cstr(), client, clientAddress(client)) );
				result = (profile.flags & MetaClient::ADMINISTRATOR) != 0;
			}
			else
				LOG_STATUS( "ProcessServer", CharString().format("Login failed, client %u (%s)", client, clientAddress(client)) );

			AutoLock lock( &m_Lock );

			m_ClientValid[ client ] = result;
			send( client, ProcessClient::CLIENT_JOB_DONE ) << job << result;
		}
		break;
	case ProcessClient::SERVER_SEND_PROCESS_LIST:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;

			// send process list to the server
			AutoLock lock( &m_Lock );
			send( client, ProcessClient::CLIENT_RECV_PROCESS_LIST ) << job << m_ProcessList;
		}
		break;
	case ProcessClient::SERVER_SEND_CONFIG:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;
			dword processId;
			input >> processId;

			CharString config;
			CharString configFile;

			if ( processId != 0 )
			{
				Process proc;
				if ( findProcess( processId, proc ) )
					configFile = proc.config;
			}
			else
				configFile = m_Context.config;

			LOG_STATUS( "ProcessServer", CharString().format("Send Config, client %u (%s), configFile = %s", 
				client, clientAddress(client), configFile.cstr()) );

			// attempt to load the configuration file
			char * pConfig = FileDisk::loadTextFile( configFile );
			if ( pConfig != NULL )
			{
				config = pConfig;
				delete [] pConfig;
			}

			send( client, ProcessClient::CLIENT_RECV_CONFIG ) << job << config;
		}
		break;
	case ProcessClient::SERVER_RECV_CONFIG:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;
			dword processId;
			input >> processId;
			CharString config;
			input >> config;

			bool jobDone = false;

			CharString configFile;
			if ( processId != 0 )
			{
				Process proc;
				if ( findProcess( processId, proc ) )
					configFile = proc.config;
			}
			else
				configFile = m_Context.config;

			LOG_STATUS( "ProcessServer", "Recv Config, client %u (%s), configFile = %s", 
				client, clientAddress(client), configFile.cstr() );

			// save the new file
			jobDone = FileDisk::saveTextFile( configFile, CharString( config ) );

			send( client, ProcessClient::CLIENT_JOB_DONE ) << job << jobDone;
		}
		break;
	case ProcessClient::SERVER_SEND_LOG:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;
			dword processId;
			input >> processId;

			CharString log;
			CharString logFile;
			if ( processId != 0 )
			{
				// send log of one of our processes
				Process proc;
				if ( findProcess( processId, proc ) )
					logFile = proc.log;
			}
			else
				logFile = m_Context.logFile;

			FileDisk file;
			if ( file.open( logFile ) )
			{
				dword size = file.size();
				if ( size > MAX_LOG_SIZE )
				{
					file.setPosition( size - MAX_LOG_SIZE );
					size = MAX_LOG_SIZE;
				}

				char * pLog = new char[ size + 1];
				pLog[ size ] = 0;

				file.read( pLog, size );
				file.close();

				// save to string
				log = pLog;
				// release allocated memory
				delete [] pLog;
			}
			else
				log = "Failed to open log file!";


			send( client, ProcessClient::CLIENT_RECV_LOG ) << job << log;
		}
		break;
	case ProcessClient::SERVER_ADD_PROCESS:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;
			Process proc;
			input >> proc;

			AutoLock lock( &m_Lock );

			proc.processId = m_NextProcessId++;
			m_ProcessList.push( proc );

			LOG_STATUS( "ProcessServer", "Add Process, client = %u (%s), processId = %u, name = %s, exec = %s", 
				client, clientAddress(client), proc.processId, proc.name.cstr(), proc.executable.cstr() );

			saveProcessList();
			send( client, ProcessClient::CLIENT_JOB_DONE ) << job << true;
		}
		break;
	case ProcessClient::SERVER_SET_PROCESS:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;
			Process proc;
			input >> proc;

			bool jobDone = false;

			AutoLock lock( &m_Lock );

			int pi = findProcess( proc.processId );
			if ( pi >= 0 )
			{
				m_ProcessList[pi] = proc;
				jobDone = true;

				LOG_STATUS( "ProcessServer", "Set Process, client = %u (%s), processId = %u, name = %s, exec = %s", 
					client, clientAddress(client), proc.processId, proc.name.cstr(), proc.executable.cstr() );

				saveProcessList();
			}

			send( client, ProcessClient::CLIENT_JOB_DONE ) << job << jobDone;
		}
		break;
	case ProcessClient::SERVER_DEL_PROCESS:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;
			dword processId;
			input >> processId;

			bool jobDone = false;

			AutoLock lock( &m_Lock );

			int pi = findProcess( processId );
			if ( pi >= 0 )
			{
				LOG_STATUS( "ProcessServer", "Delete Process, name = %s, client = %u (%s), processId = %u", 
					m_ProcessList[pi].name.cstr(), client, clientAddress(client), processId );

				// stop the actual process if any
				if ( m_ProcessInfo.find( processId ).valid() )
				{
					::Process::stop( m_ProcessInfo[ processId ].m_pHandle );
					m_ProcessInfo.remove( processId );
				}

				// remove from the list
				m_ProcessList.remove( pi );
				jobDone = true;

				saveProcessList();
			}

			send( client, ProcessClient::CLIENT_JOB_DONE ) << job << jobDone;
		}
		break;
	case ProcessClient::SERVER_STOP_PROCESS:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;
			dword processId;
			input >> processId;

			bool jobDone = false;

			AutoLock lock( &m_Lock );

			int pi = findProcess( processId );
			if ( pi >= 0 )
			{
				m_ProcessList[ pi ].flags |= ProcessClient::PF_DISABLED;
				jobDone = true;

				LOG_STATUS( "ProcessServer", "Stop Process, name = %s, client = %u (%s), processId = %u", 
					m_ProcessList[pi].name.cstr(), client, clientAddress(client), processId );

				saveProcessList();
			}

			send( client, ProcessClient::CLIENT_JOB_DONE ) << job << jobDone;
		}
		break;
	case ProcessClient::SERVER_START_PROCESS:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;
			dword processId;
			input >> processId;

			bool jobDone = false;

			AutoLock lock( &m_Lock );

			int pi = findProcess( processId );
			if ( pi >= 0 )
			{
				m_ProcessList[ pi ].flags &= ~ProcessClient::PF_DISABLED;
				jobDone = true;

				LOG_STATUS( "ProcessServer", "Start Process, name = %s, client = %u (%s), processId = %u", 
					m_ProcessList[pi].name.cstr(), client, clientAddress(client), processId );
				saveProcessList();
			}

			send( client, ProcessClient::CLIENT_JOB_DONE ) << job << jobDone;
		}
		break;
	case ProcessClient::SERVER_RESTART_PROCESS:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;
			dword processId;
			input >> processId;

			bool jobDone = false;

			AutoLock lock( &m_Lock );

			Process proc;
			if ( findProcess( processId, proc ) )
			{
				if ( m_ProcessInfo.find( processId ).valid() )
				{
					jobDone = stopProcess( processId );

					LOG_STATUS( "ProcessServer", "Restart Process, name = %s, client = %u (%s), processId = %u,", 
						proc.name.cstr(), client, clientAddress(client), processId );
				}
			}

			send( client, ProcessClient::CLIENT_JOB_DONE ) << job << jobDone;
		}
		break;
	case ProcessClient::SERVER_SEND_STATUS:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;

			AutoLock lock( &m_Lock );

			ProcessClient::Status status;
			status.processGroup = m_Context.processGroup;
			status.networkGroup = m_Context.networkGroup;
			status.cpuUsage = cpuUsage();
			status.memoryUsage = memoryUsage();	
			status.processCount = 0;

			for(int i=0;i<m_ProcessList.size();i++)
				if ( (m_ProcessList[i].flags & ProcessClient::PF_RUNNING) != 0 )
					status.processCount++;

			send( client, ProcessClient::CLIENT_RECV_STATUS ) << job << status;
		}
		break;
	case ProcessClient::SERVER_STOP_ALL:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;

			bool jobDone = false;

			AutoLock lock( &m_Lock );
			for(int i=0;i<m_ProcessList.size();i++)
				m_ProcessList[i].flags |= ProcessClient::PF_DISABLED;
			saveProcessList();

			jobDone = true;

			LOG_STATUS( "ProcessServer", CharString().format("Stop All, client = %u (%s)", client, clientAddress(client)) );
			send( client, ProcessClient::CLIENT_JOB_DONE ) << job << jobDone;
		}
		break;
	case ProcessClient::SERVER_START_ALL:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;

			bool jobDone = false;

			AutoLock lock( &m_Lock );
			for(int i=0;i<m_ProcessList.size();i++)
				m_ProcessList[i].flags &= ~ProcessClient::PF_DISABLED;
			saveProcessList();

			jobDone = true;
			LOG_STATUS( "ProcessServer", CharString().format("Start All, client = %u (%s)", client, clientAddress(client)) );
			send( client, ProcessClient::CLIENT_JOB_DONE ) << job << jobDone;
		}
		break;
	case ProcessClient::SERVER_RESTART_ALL:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;

			bool jobDone = false;

			AutoLock lock( &m_Lock );
			for(int i=0;i<m_ProcessList.size();i++)
				stopProcess( m_ProcessList[i].processId );

			jobDone = true;
			LOG_STATUS( "ProcessServer", CharString().format("Restart All, client = %u (%s)", client, clientAddress(client)) );
			send( client, ProcessClient::CLIENT_JOB_DONE ) << job << jobDone;
		}
		break;
	case ProcessClient::SERVER_REBOOT:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;

			bool jobDone = reboot();
			if ( jobDone )
				LOG_STATUS( "ProcessServer", CharString().format("Server Rebooting, client = %u (%s)", client, clientAddress(client)) );

			send( client, ProcessClient::CLIENT_JOB_DONE ) << job << jobDone;
		}
		break;
	case ProcessClient::SERVER_EXIT:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;

			// signal all running processes to stop
			bool jobDone = shutdown();
			if ( jobDone )
				LOG_STATUS( "ProcessServer", CharString().format("Server Exiting, client = %u (%s)", client, clientAddress(client)) );

			send( client, ProcessClient::CLIENT_JOB_DONE ) << job << jobDone;
		}
		break;
	case ProcessClient::SERVER_TERMINATE_PROCESS:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;
			dword processId;
			input >> processId;

			bool jobDone = false;

			AutoLock lock( &m_Lock );

			Process proc;
			if ( findProcess( processId, proc ) )
			{
				// just terminate the process
				if ( m_ProcessInfo.find( processId ).valid() )
				{
					::Process::stop( m_ProcessInfo[ processId ].m_pHandle );
					jobDone = true;

					LOG_STATUS( "ProcessServer", "Terminated Process, name = %s, client = %u (%s), processId = %u,", 
						proc.name.cstr(), client, clientAddress(client), processId );
				}
			}

			send( client, ProcessClient::CLIENT_JOB_DONE ) << job << jobDone;
		}
		break;
	case ProcessClient::SERVER_OPEN_LOG:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;
			dword processId;
			input >> processId;

			CharString logFile;
			if ( processId != 0 )
			{
				// send log of one of our processes
				Process proc;
				if ( findProcess( processId, proc ) )
					logFile = proc.log;
			}
			else
				logFile = m_Context.logFile;

			dword logId = m_NextLogId++;

			AutoLock lock( &m_Lock );

			FileDisk & file = m_LogFile[ logId ];
			if ( file.open( logFile ) )
			{
				LOG_STATUS( "ProcessServer", "Open Log, logFile = %s, logId = %u, clientId = %u", logFile.cstr(), logId, client );

				m_ActiveLog.push( logId );
				m_LogClient[ logId ] = client;
				m_ClientLog[ client ].push( logId );
			}
			else
			{
				LOG_STATUS( "ProcessServer", "Open Log Failed, logFile = %s, clientId = %u", logFile.cstr(), client );

				// failed to open file
				m_LogFile.remove( logId );
				// set id to 0 for error
				logId = 0;
			}

			send( client, ProcessClient::CLIENT_RECV_LOG_ID ) << job << logId;
		}
		break;
	case ProcessClient::SERVER_CLOSE_LOG:
		if ( validateClient( client ) )
		{
			dword logId;
			input >> logId;

			AutoLock lock( &m_Lock );

			LOG_STATUS( "ProcessServer", CharString().format("Close Log, logId = %u, client = %u", logId, client) );

			m_ActiveLog.removeSearch( logId );
			m_LogFile.remove( logId );
			m_LogClient.remove( logId );
			m_ClientLog[ client ].removeSearch( logId );
		}
		break;
	case ProcessClient::SERVER_SEARCH_LOGS:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;
			ProcessClient::SearchLogRequest req;
			input >> req;

			LOG_STATUS( "ProcessServer", CharString().format("Search Log, clientId = %u", client) );

			CharString result;
			if( req.filemask.find('/') >= 0 || req.filemask.find('\\') >= 0 )
			{	// this should never happen, unless the user has a hacked client
				LOG_STATUS( "ProcessServer", CharString().format("Search Log, invalid filemask received from clientId = %u", client) );
				result = "Failed";
			}
			else
			{
				result = searchLogFiles( req.filemask, req.searchString, req.isRegExp, req.searchLevel, req.resolveClientId );
			}

			send( client, ProcessClient::CLIENT_RECV_SEARCHRESULT ) << job << result;
		}
		break;
	case ProcessClient::PING:
		send( client, ProcessClient::PONG );
		break;
	case ProcessClient::PONG:
		break;
	default:
		{
			LOG_ERROR( "ProcessServer", CharString().format("Bad Message, client = %u (%s), message = %d", client, clientAddress(client), message) );
			removeClient( client );
		}
		break;
	}
}
示例#13
0
	void RawControl::checkCan()
	{
		if(arm->GetP()!=ARM_P)
			reboot(0x04);
		
	}
示例#14
0
static long
conswrite(Chan *c, void *va, long n, vlong off)
{
	char buf[256];
	long l, bp;
	char *a;
	Mach *mp;
	int id, fd;
	Chan *swc;
	ulong offset;
	Cmdbuf *cb;
	Cmdtab *ct;

	a = va;
	offset = off;

	switch((ulong)c->qid.path){
	case Qcons:
		/*
		 * Can't page fault in putstrn, so copy the data locally.
		 */
		l = n;
		while(l > 0){
			bp = l;
			if(bp > sizeof buf)
				bp = sizeof buf;
			memmove(buf, a, bp);
			putstrn0(buf, bp, 1);
			a += bp;
			l -= bp;
		}
		break;

	case Qconsctl:
		error(Egreg);

	case Qtime:
		if(!iseve())
			error(Eperm);
		return writetime(a, n);

	case Qbintime:
		if(!iseve())
			error(Eperm);
		return writebintime(a, n);

	case Qhostowner:
		return hostownerwrite(a, n);

	case Qhostdomain:
		return hostdomainwrite(a, n);

	case Quser:
		return userwrite(a, n);

	case Qnull:
		break;

	case Qconfig:
		error(Eperm);
		break;

	case Qreboot:
		if(!iseve())
			error(Eperm);
		cb = parsecmd(a, n);

		if(waserror()) {
			free(cb);
			nexterror();
		}
		ct = lookupcmd(cb, rebootmsg, nelem(rebootmsg));
		switch(ct->index) {
		case CMhalt:
			reboot(nil, 0, 0);
			break;
		case CMreboot:
			rebootcmd(cb->nf-1, cb->f+1);
			break;
		case CMpanic:
			*(ulong*)0=0;
			panic("/dev/reboot");
		case CMrdb:
			if(consdebug == nil)
				consdebug = rdb;
			consdebug();
			break;
		}
		poperror();
		free(cb);
		break;

	case Qsysstat:
		for(id = 0; id < 32; id++) {
			if(active.machs & (1<<id)) {
				mp = MACHP(id);
				mp->cs = 0;
				mp->intr = 0;
				mp->syscall = 0;
				mp->pfault = 0;
				mp->tlbfault = 0;
				mp->tlbpurge = 0;
			}
		}
		break;

	case Qswap:
		if(n >= sizeof buf)
			error(Egreg);
		memmove(buf, va, n);	/* so we can NUL-terminate */
		buf[n] = 0;
		/* start a pager if not already started */
		if(strncmp(buf, "start", 5) == 0){
			kickpager();
			break;
		}
		if(!iseve())
			error(Eperm);
		if(buf[0]<'0' || '9'<buf[0])
			error(Ebadarg);
		fd = strtoul(buf, 0, 0);
		swc = fdtochan(fd, -1, 1, 1);
		setswapchan(swc);
		break;

	case Qsysname:
		if(offset != 0)
			error(Ebadarg);
		if(n <= 0 || n >= sizeof buf)
			error(Ebadarg);
		strncpy(buf, a, n);
		buf[n] = 0;
		if(buf[n-1] == '\n')
			buf[n-1] = 0;
		kstrdup(&sysname, buf);
		break;
	
	case Qmordor:
		error("one does not simply write into mordor");
		return 0;

	default:
		print("conswrite: %#llux\n", c->qid.path);
		error(Egreg);
	}
	return n;
}
示例#15
0
int
main(int argc, char **argv)
{
    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);
    fprintf(stderr, "Starting recovery on %s", ctime(&start));

    ui_init();
    ui_print("Android system recovery utility\n");
    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;

    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 '?':
            LOGE("Invalid command argument\n");
            continue;
        }
    }

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

    property_list(print_property, NULL);
    fprintf(stderr, "\n");

#if TEST_AMEND
    test_amend();
#endif

    RecoveryCommandContext ctx = { NULL };
    if (register_update_commands(&ctx)) {
        LOGE("Can't install update commands\n");
    }

    int status = INSTALL_SUCCESS;

    if (update_package != NULL) {
        status = install_package(update_package);
        if (status != INSTALL_SUCCESS) ui_print("Installation aborted.\n");
    } else if (wipe_data || wipe_cache) {
        if (wipe_data && erase_root("DATA:")) status = INSTALL_ERROR;
        if (wipe_cache && erase_root("CACHE:")) status = INSTALL_ERROR;
        if (status != INSTALL_SUCCESS) ui_print("Data wipe failed.\n");
    } else {
        status = INSTALL_ERROR;  // No command specified
    }

    if (status != INSTALL_SUCCESS) ui_set_background(BACKGROUND_ICON_ERROR);
    if (status != INSTALL_SUCCESS || ui_text_visible()) prompt_and_wait();

    // If there is a radio image pending, reboot now to install it.
    maybe_install_firmware_update(send_intent);

    // Otherwise, get ready to boot the main system...
    finish_recovery(send_intent);
    ui_print("Rebooting...\n");
    sync();
    reboot(RB_AUTOBOOT);
    return EXIT_SUCCESS;
}
示例#16
0
文件: luascript.c 项目: emlyn/chdk
/*
result = reboot(["filename"])
returns false on failure, does not return on success
see lib/armutil/reboot.c for details
*/
static int luaCB_reboot( lua_State* L )
{
    lua_pushboolean(L, reboot(luaL_optstring( L, 1, NULL )));
    return 1;
}
示例#17
0
int main(int argc, char *argv[])
{
	int rc = 0;

	struct udev *udev;

	struct sigaction act;
	sigset_t mask;
	struct udev_monitor *kernel_monitor = NULL;
	fd_set readfds;

	const char *filter_subsys    = "block";
	/* const char *filter_devtype   = "partition"; */
    const char *filter_action1   = "remove";
    const char *filter_action2   = "change";
    const char *filter_devsuffix;

    int kexec = 0;

	udev = udev_new();
	if (udev == NULL)
		goto out2;

	if (argc != 2 && argc != 3)
		goto out2;
	filter_devsuffix = argv[1];

    if (argc == 3 && !strcmp(argv[2], "kexec"))
        kexec = 1;

	/* set signal handlers */
	memset(&act, 0x00, sizeof(struct sigaction));
	act.sa_handler = sig_handler;
	sigemptyset(&act.sa_mask);
	act.sa_flags = SA_RESTART;
	sigaction(SIGINT, &act, NULL);
	sigaction(SIGTERM, &act, NULL);
	sigemptyset(&mask);
	sigaddset(&mask, SIGINT);
	sigaddset(&mask, SIGTERM);
	sigprocmask(SIG_UNBLOCK, &mask, NULL);

	kernel_monitor = udev_monitor_new_from_netlink(udev, "kernel");
	if (kernel_monitor == NULL) {
		fprintf(stderr, "error: unable to create netlink socket\n");
		rc = 3;
		goto out;
	}

	if (udev_monitor_filter_add_match_subsystem_devtype(kernel_monitor, filter_subsys, NULL /* filter_devtype */) < 0)
		fprintf(stderr, "error: unable to apply subsystem filter '%s:%s'\n", filter_subsys, "NULL" /* filter_devtype */);

	if (udev_monitor_enable_receiving(kernel_monitor) < 0) {
		fprintf(stderr, "error: unable to subscribe to kernel events\n");
		rc = 4;
		goto out;
	}

    /* lock process memory */
    if (mlockall(MCL_CURRENT) != 0)
        fprintf(stderr, "warning: failed to lock process memory: %s\n", strerror(errno));

	while (!udev_exit) {
		int fdcount;

		FD_ZERO(&readfds);
		if (kernel_monitor != NULL)
			FD_SET(udev_monitor_get_fd(kernel_monitor), &readfds);

		fdcount = select(udev_monitor_get_fd(kernel_monitor)+1,
				 &readfds, NULL, NULL, NULL);
		if (fdcount < 0) {
			if (errno != EINTR)
				fprintf(stderr, "error receiving uevent message: %s\n", strerror(errno));
			continue;
		}

		if ((kernel_monitor != NULL) && FD_ISSET(udev_monitor_get_fd(kernel_monitor), &readfds)) {
			struct udev_device *device;

			device = udev_monitor_receive_device(kernel_monitor);
			if (device == NULL)
				continue;
			if (print_device(device, filter_action1, filter_action2, filter_devsuffix))
                udev_exit = 1;

			udev_device_unref(device);
		}
	}

out:
	udev_monitor_unref(kernel_monitor);

out2:
	udev_unref(udev);

    if (udev_exit == 2)
        rc = 1;

    if (rc == 0 && kexec) {
        reboot(LINUX_REBOOT_CMD_KEXEC);

        fprintf(stderr, "error: failed to reboot via kexec: %s\n", strerror(errno));
        rc = 1;
    }

	return rc;
}
示例#18
0
文件: bluebox.c 项目: johandc/bluebox
static void do_control_request(int direction)
{
	switch (USB_ControlRequest.bRequest) {
	case REQUEST_REGISTER:
		do_register(direction, USB_ControlRequest.wValue);
		break;
	case REQUEST_FREQUENCY:
		do_frequency(direction, USB_ControlRequest.wValue);
		break;
	case REQUEST_RXTX_MODE:
		do_rxtx_mode(direction, USB_ControlRequest.wValue);
		break;
	case REQUEST_MODINDEX:
		do_modindex(direction, USB_ControlRequest.wValue);
		break;
	case REQUEST_CSMA_RSSI:
		do_csma_rssi(direction, USB_ControlRequest.wValue);
		break;
	case REQUEST_POWER:
		do_power(direction, USB_ControlRequest.wValue);
		break;
	case REQUEST_AFC:
		do_acf(direction, USB_ControlRequest.wValue);
		break;
	case REQUEST_IFBW:
		do_ifbw(direction, USB_ControlRequest.wValue);
		break;
	case REQUEST_TRAINING:	
		do_training(direction, USB_ControlRequest.wValue);
		break;
	case REQUEST_SYNCWORD:	
		do_syncword(direction, USB_ControlRequest.wValue);
		break;
	case REQUEST_BITRATE:
		do_bitrate(direction, USB_ControlRequest.wValue);
		break;
	case REQUEST_TX:
		do_tx(direction, USB_ControlRequest.wValue);
		break;
	case REQUEST_RX:
		do_rx(direction, USB_ControlRequest.wValue);
		break;
	case REQUEST_TX_FREQUENCY:
		do_tx_frequency(direction, USB_ControlRequest.wValue);
		break;
	case REQUEST_RX_FREQUENCY:
		do_rx_frequency(direction, USB_ControlRequest.wValue);
		break;
	case REQUEST_SERIALNUMBER:
		do_serialnumber(direction, USB_ControlRequest.wValue);
		break;
	case REQUEST_FWREVISION:
		do_fw_revision(direction, USB_ControlRequest.wValue);
		break;
	case REQUEST_RESET:
		reboot();
		break;
	case REQUEST_DFU:
		jump_to_bootloader();
		break;
	}
}
示例#19
0
void reboot_device(unsigned reboot_reason)
{
	reboot(reboot_reason);
}
示例#20
0
int main(int argc, char *argv[])
{
	int c, force = 0;
	struct option long_options[] = {
		{"help",     0, NULL, 'h'},
		{"force",    0, NULL, 'f'},
		{"halt",     0, NULL, 'H'},
		{"poweroff", 0, NULL, 'p'},
		{"reboot",   0, NULL, 'r'},
		{NULL, 0, NULL, 0}
	};

	/* Initial command taken from program name */
	progname(argv[0]);
	translate();

	while ((c = getopt_long(argc, argv, "h?fHpr", long_options, NULL)) != EOF) {
		switch(c) {
		case 'h':
		case '?':
			return usage(0);

		case 'f':
			force = 1;
			break;

		case 'H':
			cmd = CMD_HALT;
			break;

		case 'p':
			cmd = CMD_POWEROFF;
			break;

		case 'r':
			cmd = CMD_REBOOT;
			break;

		default:
			return usage(1);
		}
	}

	/* Check for any overrides */
	translate();

	if (force) {
		switch (cmd) {
		case CMD_REBOOT:
			c = reboot(RB_AUTOBOOT);
			break;

		case CMD_HALT:
			c = reboot(RB_HALT_SYSTEM);
			break;

		case CMD_POWEROFF:
			c = reboot(RB_POWER_OFF);
			break;

		case CMD_SUSPEND:
			c = reboot(RB_SW_SUSPEND);
			break;

		case CMD_UNKNOWN:
			errx(1, "Invalid command");
			break;
		}

		if (c)
			warn("Failed forced %s", msg);
		else
			return 0;
	}

	switch (cmd) {
	case CMD_REBOOT:
		c = kill(1, SIGTERM);
		break;

	case CMD_HALT:
		c = kill(1, SIGUSR1);
		break;

	case CMD_POWEROFF:
		c = kill(1, SIGUSR2);
		break;

	case CMD_SUSPEND:
	case CMD_UNKNOWN:
		errx(1, "Invalid command");
		break;
	}

	if (c)
		err(1, "Failed signalling init to %s", msg);
	else
		sleep(2);

	return 0;
}
示例#21
0
void main (){
reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
LINUX_REBOOT_CMD_RESTART2,"recovery");
}
示例#22
0
int halt_main(int argc UNUSED_PARAM, char **argv)
{
	static const int magic[] = {
		RB_HALT_SYSTEM,
		RB_POWER_OFF,
		RB_AUTOBOOT
	};
	static const smallint signals[] = { SIGUSR1, SIGUSR2, SIGTERM };

	int delay = 0;
	int which, flags, rc;

	/* Figure out which applet we're running */
	for (which = 0; "hpr"[which] != applet_name[0]; which++)
		continue;

	/* Parse and handle arguments */
	opt_complementary = "d+"; /* -d N */
	/* We support -w even if !ENABLE_FEATURE_WTMP,
	 * in order to not break scripts.
	 * -i (shut down network interfaces) is ignored.
	 */
	flags = getopt32(argv, "d:nfwi", &delay);

	sleep(delay);

	write_wtmp();

	if (flags & 8) /* -w */
		return EXIT_SUCCESS;

	if (!(flags & 2)) /* no -n */
		sync();

	/* Perform action. */
	rc = 1;
	if (!(flags & 4)) { /* no -f */
//TODO: I tend to think that signalling linuxrc is wrong
// pity original author didn't comment on it...
		if (ENABLE_FEATURE_INITRD) {
			/* talk to linuxrc */
			/* bbox init/linuxrc assumed */
			pid_t *pidlist = find_pid_by_name("linuxrc");
			if (pidlist[0] > 0)
				rc = kill(pidlist[0], signals[which]);
			if (ENABLE_FEATURE_CLEAN_UP)
				free(pidlist);
		}
		if (rc) {
			/* talk to init */
			if (!ENABLE_FEATURE_CALL_TELINIT) {
				/* bbox init assumed */
				rc = kill(1, signals[which]);
			} else {
				/* SysV style init assumed */
				/* runlevels:
				 * 0 == shutdown
				 * 6 == reboot */
				rc = execlp(CONFIG_TELINIT_PATH,
						CONFIG_TELINIT_PATH,
						which == 2 ? "6" : "0",
						(char *)NULL
				);
			}
		}
	} else {
		rc = reboot(magic[which]);
	}

	if (rc)
		bb_perror_nomsg_and_die();
	return rc;
}
示例#23
0
void burning_recovery_image()
{
	char* copy = NULL;
	int result = 0;
	int mcu_fd;
	int mode = 2;
	FILE *fp = fopen_path(RECOVERY_FILE, "r");
	if(fp == NULL){
		//LOGE("cant find the RECOVERY_FILE:%s\n", RECOVERY_FILE);
		goto done;
	}
	check_and_fclose(fp,RECOVERY_FILE);
	if (RECOVERY_FILE) {
		result = install_recovery(RECOVERY_FILE);
	} else {
		result = INSTALL_ERROR;
	}
done:
	mcu_fd = open( mcu_dev, O_RDWR | O_CREAT | O_TRUNC );
	if (mcu_fd < 0) {
		LOGE("open mcu dev error\n");
		result= INSTALL_ERROR;
	} else {
		ioctl(mcu_fd, MCU_SET_UPDATE_FLAG, &mode);
	}
	close(mcu_fd);
//	set_recovery();
	sync();
	sleep(3);
	close_backlight();
	reboot(RB_AUTOBOOT);
#if 0
	FILE *fin = NULL, *fout = NULL;
	char *inputfile = "/firmware/recovery.img";
	char *outfile = "/dev/block/mmcblk0p5";
	printf("time start \n\r");
	fin = fopen(inputfile, "rb");
	if (!fin) {
		printf("can't open input file:%s\n",inputfile);
		return ;
	}
	fout = fopen(outfile, "wb");
	if (!fout) {
		printf("can't open output file:%s\n",outfile);
		return ;
	}	
	while (!feof(fin)) {
		char *buffer[4096];
		int n = fread(buffer, 1, 4096, fin);
		if (n < 0) {
			printf("fread error:%s \n", inputfile);
			return ;
		}
		int r = fwrite(buffer, 1, 4096, fout);
		if (r < 0) {
			printf("fwrite error:%s \n", outfile);
			return ;
		}
	}
	fclose(fin);
	fclose(fout);
	sync();
	sprintf(buf_cmd, "/system/bin/busybox rm -rf /firmware/recovery.img");
	system(buf_cmd);
	printf("%s	rt=%d	\n\r",buf_cmd, rt_cmd);
	sync();	
	printf("time end \n\r");
#endif
}
示例#24
0
int
main(int argc, char *argv[])
{
	struct passwd *pw;
	int ch, howto, i, fd, kflag, lflag, nflag, qflag, pflag, sverrno;
	u_int pageins;
	char *kernel = NULL, *p;
	const char *user;

	if (strstr((p = strrchr(*argv, '/')) ? p + 1 : *argv, "halt")) {
		dohalt = 1;
		howto = RB_HALT;
	} else
		howto = 0;
	kflag = lflag = nflag = qflag = 0;
	while ((ch = getopt(argc, argv, "dk:lnpq")) != -1)
		switch(ch) {
		case 'd':
			howto |= RB_DUMP;
			break;
		case 'k':
			kflag = 1;
			kernel = optarg;
			break;
		case 'l':
			lflag = 1;
			break;
		case 'n':
			nflag = 1;
			howto |= RB_NOSYNC;
			break;
		case 'p':
			pflag = 1;
			howto |= (RB_POWEROFF | RB_HALT);
			break;
		case 'q':
			qflag = 1;
			break;
		case '?':
		default:
			usage();
		}
	argc -= optind;
	argv += optind;

	if ((howto & (RB_DUMP | RB_HALT)) == (RB_DUMP | RB_HALT))
		errx(1, "cannot dump (-d) when halting; must reboot instead");
	if (geteuid()) {
		errno = EPERM;
		err(1, NULL);
	}

	if (qflag) {
		reboot(howto);
		err(1, NULL);
	}

	if (kflag) {
		fd = open("/boot/nextboot.conf",
			  O_WRONLY | O_CREAT | O_TRUNC, 0444);
		if (fd != -1) {
			write(fd, "kernel=\"", 8L);
			write(fd, kernel, strlen(kernel));
			write(fd, "\"\n", 2);
			close(fd);
		}
	}

	/* Log the reboot. */
	if (!lflag)  {
		if ((user = getlogin()) == NULL)
			user = (pw = getpwuid(getuid())) ?
			    pw->pw_name : "???";
		if (dohalt) {
			openlog("halt", 0, LOG_AUTH | LOG_CONS);
			syslog(LOG_CRIT, "halted by %s", user);
		} else {
			openlog("reboot", 0, LOG_AUTH | LOG_CONS);
			syslog(LOG_CRIT, "rebooted by %s", user);
		}
	}
	logwtmp("~", "shutdown", "");

	/*
	 * Do a sync early on, so disks start transfers while we're off
	 * killing processes.  Don't worry about writes done before the
	 * processes die, the reboot system call syncs the disks.
	 */
	if (!nflag)
		sync();

	/* Just stop init -- if we fail, we'll restart it. */
	if (kill(1, SIGTSTP) == -1)
		err(1, "SIGTSTP init");

	/* Ignore the SIGHUP we get when our parent shell dies. */
	signal(SIGHUP, SIG_IGN);

	/* Send a SIGTERM first, a chance to save the buffers. */
	if (kill(-1, SIGTERM) == -1)
		err(1, "SIGTERM processes");

	/*
	 * After the processes receive the signal, start the rest of the
	 * buffers on their way.  Wait 5 seconds between the SIGTERM and
	 * the SIGKILL to give everybody a chance. If there is a lot of
	 * paging activity then wait longer, up to a maximum of approx
	 * 60 seconds.
	 */
	sleep(2);
	for (i = 0; i < 20; i++) {
		pageins = get_pageins();
		if (!nflag)
			sync();
		sleep(3);
		if (get_pageins() == pageins)
			break;
	}

	for (i = 1;; ++i) {
		if (kill(-1, SIGKILL) == -1) {
			if (errno == ESRCH)
				break;
			goto restart;
		}
		if (i > 5) {
			fprintf(stderr,
			    "WARNING: some process(es) wouldn't die\n");
			break;
		}
		sleep(2 * i);
	}

	reboot(howto);
	/* FALLTHROUGH */

restart:
	sverrno = errno;
	errx(1, "%s%s", kill(1, SIGHUP) == -1 ? "(can't restart init): " : "",
	    strerror(sverrno));
	/* NOTREACHED */
}
示例#25
0
static void ficl_reboot(ficlVm *vm)
{
  void reboot(int);

  reboot(0);
}
示例#26
0
void BootMaker::exitRestart() {
    reboot();
}
示例#27
0
/* Once we get here, we should be * safe to do whatever we want;
* heavyweights like malloc and CString are OK. (Don't crash!) */
static void child_process()
{
    /* 1. Read the CrashData. */
    CrashData crash;
    if( !child_read(3, &crash, sizeof(CrashData)) )
	return;

    /* 2. Read info. */
    int size;
    if( !child_read(3, &size, sizeof(size)) )
	return;
    char *Info = new char [size];
    if( !child_read(3, Info, size) )
	return;

    /* 3. Read AdditionalLog. */
    if( !child_read(3, &size, sizeof(size)) )
	return;

    char *AdditionalLog = new char [size];
    if( !child_read(3, AdditionalLog, size) )
	return;

    /* 4. Read RecentLogs. */
    int cnt = 0;
    if( !child_read(3, &cnt, sizeof(cnt)) )
	return;
    char *Recent[1024];
    for( int i = 0; i < cnt; ++i )
    {
        if( !child_read(3, &size, sizeof(size)) )
		return;
        Recent[i] = new char [size];
        if( !child_read(3, Recent[i], size) )
		return;
    }

    /* 5. Read CHECKPOINTs. */
    if( !child_read(3, &size, sizeof(size)) )
	return;

    char *temp = new char [size];
    if( !child_read(3, temp, size) )
	return;

    CStringArray Checkpoints;
    split(temp, "$$", Checkpoints);
    delete [] temp;

    /* 6. Read the crashed thread's name. */
    if( !child_read(3, &size, sizeof(size)) )
	return;
    temp = new char [size];
    if( !child_read(3, temp, size) )
	return;
    const CString CrashedThread(temp);
    delete[] temp;

    /* Wait for the child to either finish cleaning up or die.  XXX:
        * This should time out, in case something deadlocks. */

    char x;
    int ret = read(3, &x, sizeof(x));
    if( ret > 0 )
    {
        fprintf( stderr, "Unexpected child read() result: %i\n", ret );
        /* keep going */
    } else if( (ret == -1 && errno != EPIPE) || ret != 0 )
    {
        /* We expect an EOF or EPIPE.  What happened? */
        fprintf(stderr, "Unexpected child read() result: %i (%s)\n", ret, strerror(errno));
        /* keep going */
    }

	// We don't need the file/ext, but they're required args.
	CString sPath, sDir, sFile, sExt;

	sPath = g_pCrashHandlerArgv0;
	splitpath( sPath, sDir, sFile, sExt );

	CString sCrashInfoPath = sDir + "stats";
	
	time_t seconds;
	seconds = time( NULL );

#ifdef ITG_ARCADE	
	sCrashInfoPath = ssprintf( "/stats/crashinfo-%ld.txt" , seconds ); // Timestamped!
#else
	sCrashInfoPath = ssprintf( "Data/crashinfo-%ld.txt" , seconds );
#endif

	FILE *CrashDump = fopen( sCrashInfoPath, "w+" );
	if(CrashDump == NULL)
	{
		fprintf( stderr, "Couldn't open " + sCrashInfoPath + ": %s\n", strerror(errno) );
		exit(1);
	}

    fprintf(CrashDump, "%s crash report", ProductInfo::GetFullVersion().c_str() );
#if defined(HAVE_VERSION_INFO)
    fprintf(CrashDump, " (build %u)", ProductInfo::GetBuildRevision().c_str() );
#endif
    fprintf(CrashDump, "\n");
    fprintf(CrashDump, "--------------------------------------\n");
    fprintf(CrashDump, "\n");

    CString reason;
    switch( crash.type )
    {
    case CrashData::SIGNAL:
    {
	CString Signal = SignalName( crash.signal );

#if !defined(DARWIN)
	reason = ssprintf( "%s - %s", Signal.c_str(), SignalCodeName(crash.signal, crash.si.si_code) );
#else
	reason = Signal;
#endif
	/* Linux puts the PID that sent the signal in si_addr for SI_USER. */
	if( crash.si.si_code == SI_USER )
		reason += ssprintf( " from pid %li", (long) crash.si.si_addr );
	else switch( crash.signal )
	{
	case SIGILL:
	case SIGFPE:
	case SIGSEGV:
	case SIGBUS:
		reason += ssprintf( " at 0x%0*lx", int(sizeof(void*)*2), (unsigned long) crash.si.si_addr );
	}
	break;
    }
    case CrashData::FORCE_CRASH:
	crash.reason[ sizeof(crash.reason)-1] = 0;
	reason = crash.reason;
	break;
    }

    fprintf( CrashDump, "Crash reason: %s\n", reason.c_str() );
    fprintf( CrashDump, "Crashed thread: %s\n\n", CrashedThread.c_str() );

    fprintf(CrashDump, "Checkpoints:\n");
    for (unsigned i=0; i<Checkpoints.size(); ++i)
        fprintf(CrashDump, Checkpoints[i]);
    fprintf(CrashDump, "\n");

    for( int i = 0; i < CrashData::MAX_BACKTRACE_THREADS; ++i )
    {
	    if( !crash.BacktracePointers[i][0] )
		    break;
	    fprintf( CrashDump, "Thread: %s\n", crash.m_ThreadName[i] );
	    output_stack_trace( CrashDump, crash.BacktracePointers[i] );
	    fprintf(CrashDump, "\n");
    }

    fprintf(CrashDump, "Static log:\n");
    fprintf(CrashDump, "%s", Info);
    fprintf(CrashDump, "%s", AdditionalLog);
    fprintf(CrashDump, "\nPartial log:\n");
    for( int i = 0; i < cnt; ++i )
        fprintf(CrashDump, "%s\n", Recent[i] );
    fprintf(CrashDump, "\n");
    fprintf(CrashDump, "-- End of report\n");
    fclose(CrashDump);

#if defined(DARWIN)
    InformUserOfCrash( sCrashInfoPath );

    /* Forcibly kill our parent. */
    kill( getppid(), SIGKILL );
#else
    /* stdout may have been inadvertently closed by the crash in the parent;
     * write to /dev/tty instead. */
    FILE *tty = fopen( "/dev/tty", "w" );
    if( tty == NULL )
        tty = stderr;

	fprintf(tty,
		"\n"
		+ ProductInfo::GetName()
		+ " has crashed.  Debug information has been output to\n"
		"\n"
		"    " + sCrashInfoPath + "\n"
		"\n"
		"Please report a bug at:\n"
		"\n"
		"    " + ProductInfo::GetCrashReportURL() + "\n"
		"\n"
	);

#endif

#ifdef ITG_ARCADE
	struct stat ncr;
	if ( stat("/tmp/no-crash-reboot", &ncr) != 0 )
	{
		sync();
		sleep(5);
		reboot(RB_AUTOBOOT);
	}
#endif
}
示例#28
0
static void
tengine_stonith_notify(stonith_t * st, stonith_event_t * st_event)
{
    if(te_client_id == NULL) {
        te_client_id = crm_strdup_printf("%s.%d", crm_system_name, getpid());
    }

    if (st_event == NULL) {
        crm_err("Notify data not found");
        return;
    }

    crmd_notify_fencing_op(st_event);

    if (st_event->result == pcmk_ok && safe_str_eq("on", st_event->action)) {
        crm_notice("%s was successfully unfenced by %s (at the request of %s)",
                   st_event->target, st_event->executioner ? st_event->executioner : "<anyone>", st_event->origin);
                /* TODO: Hook up st_event->device */
        return;

    } else if (safe_str_eq("on", st_event->action)) {
        crm_err("Unfencing of %s by %s failed: %s (%d)",
                st_event->target, st_event->executioner ? st_event->executioner : "<anyone>",
                pcmk_strerror(st_event->result), st_event->result);
        return;

    } else if (st_event->result == pcmk_ok && crm_str_eq(st_event->target, fsa_our_uname, TRUE)) {
        crm_crit("We were allegedly just fenced by %s for %s!",
                 st_event->executioner ? st_event->executioner : "<anyone>", st_event->origin); /* Dumps blackbox if enabled */

        qb_log_fini(); /* Try to get the above log message to disk - somehow */

        /* Get out ASAP and do not come back up.
         *
         * Triggering a reboot is also not the worst idea either since
         * the rest of the cluster thinks we're safely down
         */

#ifdef RB_HALT_SYSTEM
        reboot(RB_HALT_SYSTEM);
#endif

        /*
         * If reboot() fails or is not supported, coming back up will
         * probably lead to a situation where the other nodes set our
         * status to 'lost' because of the fencing callback and will
         * discard subsequent election votes with:
         *
         * Election 87 (current: 5171, owner: 103): Processed vote from east-03 (Peer is not part of our cluster)
         *
         * So just stay dead, something is seriously messed up anyway.
         *
         */
        exit(100); /* None of our wrappers since we already called qb_log_fini() */
        return;
    }

    if (st_event->result == pcmk_ok &&
        safe_str_eq(st_event->operation, T_STONITH_NOTIFY_FENCE)) {
        st_fail_count_reset(st_event->target);
    }

    crm_notice("Peer %s was%s terminated (%s) by %s for %s: %s (ref=%s) by client %s",
               st_event->target, st_event->result == pcmk_ok ? "" : " not",
               st_event->action,
               st_event->executioner ? st_event->executioner : "<anyone>",
               st_event->origin, pcmk_strerror(st_event->result), st_event->id,
               st_event->client_origin ? st_event->client_origin : "<unknown>");

#if SUPPORT_CMAN
    if (st_event->result == pcmk_ok && is_cman_cluster()) {
        int local_rc = 0;
        int confirm = 0;
        char *target_copy = strdup(st_event->target);

        /* In case fenced hasn't noticed yet
         *
         * Any fencing that has been inititated will be completed by way of the fence_pcmk redirect
         */
        local_rc = fenced_external(target_copy);
        if (local_rc != 0) {
            crm_err("Could not notify CMAN that '%s' is now fenced: %d", st_event->target,
                    local_rc);
        } else {
            crm_notice("Notified CMAN that '%s' is now fenced", st_event->target);
        }

        /* In case fenced is already trying to shoot it */
        confirm = open("/var/run/cluster/fenced_override", O_NONBLOCK|O_WRONLY);
        if (confirm >= 0) {
            int ignore = 0;
            int len = strlen(target_copy);

            errno = 0;
            local_rc = write(confirm, target_copy, len);
            ignore = write(confirm, "\n", 1);

            if(ignore < 0 && errno == EBADF) {
                crm_trace("CMAN not expecting %s to be fenced (yet)", st_event->target);

            } else if (local_rc < len) {
                crm_perror(LOG_ERR, "Confirmation of CMAN fencing event for '%s' failed: %d", st_event->target, local_rc);

            } else {
                fsync(confirm);
                crm_notice("Confirmed CMAN fencing event for '%s'", st_event->target);
            }
            close(confirm);
        }
        free(target_copy);
    }
#endif

    if (st_event->result == pcmk_ok) {
        crm_node_t *peer = crm_find_peer_full(0, st_event->target, CRM_GET_PEER_ANY);
        const char *uuid = NULL;
        gboolean we_are_executioner = safe_str_eq(st_event->executioner, fsa_our_uname);

        if (peer == NULL) {
            return;
        }

        uuid = crm_peer_uuid(peer);

        crm_trace("target=%s dc=%s", st_event->target, fsa_our_dc);
        if(AM_I_DC) {
            /* The DC always sends updates */
            send_stonith_update(NULL, st_event->target, uuid);

            if (st_event->client_origin && safe_str_neq(st_event->client_origin, te_client_id)) {

                /* Abort the current transition graph if it wasn't us
                 * that invoked stonith to fence someone
                 */
                crm_info("External fencing operation from %s fenced %s", st_event->client_origin, st_event->target);
                abort_transition(INFINITY, tg_restart, "External Fencing Operation", NULL);
            }

            /* Assume it was our leader if we dont currently have one */
        } else if (((fsa_our_dc == NULL) || safe_str_eq(fsa_our_dc, st_event->target))
            && !is_set(peer->flags, crm_remote_node)) {

            crm_notice("Target %s our leader %s (recorded: %s)",
                       fsa_our_dc ? "was" : "may have been", st_event->target,
                       fsa_our_dc ? fsa_our_dc : "<unset>");

            /* Given the CIB resyncing that occurs around elections,
             * have one node update the CIB now and, if the new DC is different,
             * have them do so too after the election
             */
            if (we_are_executioner) {
                send_stonith_update(NULL, st_event->target, uuid);
            }
            add_stonith_cleanup(st_event->target);
        }

        /* If the target is a remote node, and we host its connection,
         * immediately fail all monitors so it can be recovered quickly.
         * The connection won't necessarily drop when a remote node is fenced,
         * so the failure might not otherwise be detected until the next poke.
         */
        if (is_set(peer->flags, crm_remote_node)) {
            remote_ra_fail(st_event->target);
        }

        crmd_peer_down(peer, TRUE);
     }
}
示例#29
0
int
main(int argc, char **argv) {
	if (strstr(argv[0], "recovery") == NULL)
	{
	    if (strstr(argv[0], "flash_image") != NULL)
	        return flash_image_main(argc, argv);
	    if (strstr(argv[0], "dump_image") != NULL)
	        return dump_image_main(argc, argv);
	    if (strstr(argv[0], "erase_image") != NULL)
	        return erase_image_main(argc, argv);
	    if (strstr(argv[0], "mkyaffs2image") != NULL)
	        return mkyaffs2image_main(argc, argv);
	    if (strstr(argv[0], "unyaffs") != NULL)
	        return unyaffs_main(argc, argv);
        if (strstr(argv[0], "amend"))
            return amend_main(argc, argv);
        if (strstr(argv[0], "nandroid"))
            return nandroid_main(argc, argv);
        if (strstr(argv[0], "reboot"))
            return reboot_main(argc, argv);
        if (strstr(argv[0], "setprop"))
            return setprop_main(argc, argv);
		return busybox_driver(argc, argv);
	}
    __system("/sbin/postrecoveryboot.sh");
    create_fstab();
    
    int is_user_initiated_recovery = 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);
    fprintf(stderr, "Starting recovery on %s", ctime(&start));

    ui_init();
    ui_print(EXPAND(RECOVERY_VERSION)"\n");
#ifdef BOARD_GOAPK_DEFY
    ui_print(EXPAND(RECOVERY_VERSION_GOAPK)"\n");
    ui_print(EXPAND(RECOVERY_VERSION_QUN)"\n");
#endif
    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;

    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 '?':
            LOGE("Invalid command argument\n");
            continue;
        }
    }

    device_recovery_start();

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

    property_list(print_property, NULL);
    fprintf(stderr, "\n");

    int status = INSTALL_SUCCESS;
    
    RecoveryCommandContext ctx = { NULL };
    if (register_update_commands(&ctx)) {
        LOGE("Can't install update commands\n");
    }

    if (update_package != NULL) {
        if (wipe_data && erase_root("DATA:")) status = INSTALL_ERROR;
        status = install_package(update_package);
        if (status != INSTALL_SUCCESS) ui_print("Installation aborted.\n");
    } else if (wipe_data) {
        if (device_wipe_data()) status = INSTALL_ERROR;
        if (erase_root("DATA:")) status = INSTALL_ERROR;
        if (wipe_cache && erase_root("CACHE:")) status = INSTALL_ERROR;
        if (status != INSTALL_SUCCESS) ui_print("Data wipe failed.\n");
    } else if (wipe_cache) {
        if (wipe_cache && erase_root("CACHE:")) status = INSTALL_ERROR;
        if (status != INSTALL_SUCCESS) ui_print("Cache wipe failed.\n");
    } else {
        LOGI("Checking for extendedcommand...\n");
        status = INSTALL_ERROR;  // No command specified
        // we are starting up in user initiated recovery here
        // let's set up some default options
        signature_check_enabled = 0;
        script_assert_enabled = 0;
        is_user_initiated_recovery = 1;
        ui_set_show_text(1);
        
        if (extendedcommand_file_exists()) {
            LOGI("Running extendedcommand...\n");
            int ret;
            if (0 == (ret = run_and_remove_extendedcommand())) {
                status = INSTALL_SUCCESS;
                ui_set_show_text(0);
            }
            else {
                handle_failure(ret);
            }
        } else {
            LOGI("Skipping execution of extendedcommand, file not found...\n");
        }
    }

    if (status != INSTALL_SUCCESS && !is_user_initiated_recovery) ui_set_background(BACKGROUND_ICON_ERROR);
    if (status != INSTALL_SUCCESS || ui_text_visible()) prompt_and_wait();

#ifndef BOARD_HAS_NO_MISC_PARTITION
    // If there is a radio image pending, reboot now to install it.
    maybe_install_firmware_update(send_intent);
#endif

    // Otherwise, get ready to boot the main system...
    finish_recovery(send_intent);
    ui_print("Rebooting...\n");
    sync();
    reboot(RB_AUTOBOOT);
    return EXIT_SUCCESS;
}
示例#30
0
int clear_flash_entry(struct ftm_param *param, void *priv)
{
    char *ptr;
    int chosen;
    bool exit = false;
    struct nand_info *flash = (struct nand_info *)priv;
    struct textview *tv = &flash->tv;
    struct itemview *iv;
    struct timeval tv1, tv2;

    flash->erase_result = false;
    
    LOGD(TAG "%s\n", __FUNCTION__);

    init_text(&flash->title, param->name, COLOR_YELLOW);
    init_text(&flash->text, &flash->info[0], COLOR_YELLOW);

    clear_flash_update_info(flash, flash->info);

    flash->exit_clr_thd = false;  

#if 0
    if (!flash->iv) 
    {
        iv = ui_new_itemview();
        if (!iv) 
        {
            LOGD(TAG "No memory");
            return -1;
        }
        flash->iv = iv;
    }
#endif
    ui_init_textview(tv, flash_key_handler, (void*)flash);
#if 0    
    iv = flash->iv;
    iv->set_title(iv, &flash->title);
    iv->set_items(iv, clear_flash_items, 0);
    iv->set_text(iv, &flash->text);
#endif
    tv->set_title(tv, &flash->title);
    tv->set_text(tv, &flash->text);
    
    pthread_create(&flash->update_thd, NULL, clear_flash_update_thread, priv);
#if 0    
    do
    {
        chosen = iv->run(iv, &exit);
        switch (chosen)
        {
        case ITEM_PASS:
        case ITEM_FAIL:
              if (chosen == ITEM_PASS)
              {
                flash->mod->test_result = FTM_TEST_PASS;
              } else if (chosen == ITEM_FAIL)
              {
                flash->mod->test_result = FTM_TEST_FAIL;
            }           
            exit = true;
            break;
        }
        
        if (exit)
        {
            flash->exit_clr_thd = true;
            break;
        }        
    }
    while (1);
#endif
    LOGD(TAG "Start the NAND flash erase operations !\n");

    gettimeofday(&tv1, NULL);
    flash->teststart = tv1.tv_sec * 1000000 + tv1.tv_usec;
    
    flash->erase_result = format_root_device(DATA_PARTITION);
    
    gettimeofday(&tv2, NULL);
    flash->testend = tv2.tv_sec * 1000000 + tv2.tv_usec;
    
    LOGD(TAG "Finish the NAND flash erase operations !\n");
    
    flash->exit_clr_thd = true;
    
    pthread_join(flash->update_thd, NULL); 

    sync();
    reboot(RB_AUTOBOOT); 

    return 0;
}