diff options
Diffstat (limited to 'mdk-stage1/rescue-gui.c')
| -rw-r--r-- | mdk-stage1/rescue-gui.c | 301 |
1 files changed, 301 insertions, 0 deletions
diff --git a/mdk-stage1/rescue-gui.c b/mdk-stage1/rescue-gui.c new file mode 100644 index 000000000..c7aae6126 --- /dev/null +++ b/mdk-stage1/rescue-gui.c @@ -0,0 +1,301 @@ +/* + * Guillaume Cottenceau (gc) + * + * Copyright 2001 Mandriva + * + * + * This software may be freely redistributed under the terms of the GNU + * public license. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include <stdlib.h> +#define _USE_BSD +#include <sys/types.h> +#include <sys/time.h> +#include <sys/resource.h> +#include <sys/wait.h> +#include <unistd.h> +#include <string.h> +#include <stdio.h> +#include <sys/mount.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <linux/unistd.h> +#include <sys/select.h> +#include <linux/reboot.h> + +#include "config-stage1.h" +#include "frontend.h" +#include "utils.h" +#include "params.h" + +#include <sys/syscall.h> + +static inline long reboot(void) +{ + return (long) syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART, 0); +} + +#if defined(__i386__) || defined(__x86_64__) +#define ENABLE_RESCUE_MS_BOOT 1 +#endif + +char * env[] = { + "PATH=/usr/bin:/bin:/sbin:/usr/sbin:/mnt/sbin:/mnt/usr/sbin:/mnt/bin:/mnt/usr/bin", + "LD_LIBRARY_PATH=/lib:/usr/lib:/mnt/lib:/mnt/usr/lib" +#if defined(__x86_64__) + ":/lib64:/usr/lib64:/mnt/lib64:/mnt/usr/lib64" +#endif + , + "HOME=/", + "TERM=linux", + "TERMINFO=/etc/terminfo", + NULL +}; + +/* pause() already exists and causes the invoking process to sleep + until a signal is received */ +static void PAUSE(void) { + unsigned char t; + fflush(stdout); + read(0, &t, 1); +} + + +/* ------ UUURGH this is duplicated from `init.c', don't edit here........ */ +void fatal_error(char *msg) +{ + printf("FATAL ERROR IN RESCUE: %s\n\nI can't recover from this.\nYou may reboot your system.\n", msg); + while (1); +} + +#define LOOP_CLR_FD 0x4C01 +void del_loop(char *device) +{ + int fd; + if ((fd = open(device, O_RDONLY, 0)) < 0) { + printf("del_loop open failed\n"); + return; + } + + if (ioctl(fd, LOOP_CLR_FD, 0) < 0) { + printf("del_loop ioctl failed"); + return; + } + + close(fd); +} +struct filesystem { char * dev; char * name; char * fs; int mounted; }; +void unmount_filesystems(void) +{ + int fd, size; + char buf[65535]; /* this should be big enough */ + char *p; + struct filesystem fs[500]; + int numfs = 0; + int i, nb; + + printf("unmounting filesystems...\n"); + + fd = open("/proc/mounts", O_RDONLY, 0); + if (fd < 1) { + printf("ERROR: failed to open /proc/mounts"); + sleep(2); + return; + } + + size = read(fd, buf, sizeof(buf) - 1); + buf[size] = '\0'; + + close(fd); + + p = buf; + while (*p) { + fs[numfs].mounted = 1; + fs[numfs].dev = p; + while (*p != ' ') p++; + *p++ = '\0'; + fs[numfs].name = p; + while (*p != ' ') p++; + *p++ = '\0'; + fs[numfs].fs = p; + while (*p != ' ') p++; + *p++ = '\0'; + while (*p != '\n') p++; + p++; + if (strcmp(fs[numfs].name, "/") != 0) numfs++; /* skip if root, no need to take initrd root in account */ + } + + /* Pixel's ultra-optimized sorting algorithm: + multiple passes trying to umount everything until nothing moves + anymore (a.k.a holy shotgun method) */ + do { + nb = 0; + for (i = 0; i < numfs; i++) { + /*printf("trying with %s\n", fs[i].name);*/ + if (fs[i].mounted && umount(fs[i].name) == 0) { + if (strncmp(fs[i].dev + sizeof("/dev/") - 1, "loop", + sizeof("loop") - 1) == 0) + del_loop(fs[i].dev); + + printf("\t%s\n", fs[i].name); + fs[i].mounted = 0; + nb++; + } + } + } while (nb); + + for (i = nb = 0; i < numfs; i++) + if (fs[i].mounted) { + printf("\t%s umount failed\n", fs[i].name); + if (strcmp(fs[i].fs, "ext4") == 0) nb++; /* don't count not-ext4 umount failed */ + } + + if (nb) { + printf("failed to umount some filesystems\n"); + while (1); + } +} +/* ------ UUURGH -- end */ + + +/* ------ UUURGH -- this is dirrrrrttttyyyyyy */ +void probe_that_type(void) {} + + +int main(int argc __attribute__ ((unused)), char **argv __attribute__ ((unused))) +{ + enum return_type results; + + char install_bootloader[] = "Re-install Boot Loader"; +#if ENABLE_RESCUE_MS_BOOT + char restore_ms_boot[] = "Restore Windows Boot Loader"; +#endif + char mount_parts[] = "Mount your partitions under /mnt"; + char go_to_console[] = "Go to console"; + char reboot_[] = "Reboot"; + char doc[] = "Doc: what's addressed by this Rescue?"; + + char upgrade[] = "Upgrade to New Version"; + char rootpass[] = "Reset Root Password"; + char userpass[] = "Reset User Password"; + char factory[] = "Reset to Factory Defaults"; + char backup[] = "Backup User Files"; + char restore[] = "Restore User Files from Backup"; + char badblocks[] = "Test Key for Badblocks"; + + char * actions_default[] = { install_bootloader, +#if ENABLE_RESCUE_MS_BOOT + restore_ms_boot, +#endif + mount_parts, go_to_console, reboot_, doc, NULL }; + char * actions_flash_rescue[] = { rootpass, userpass, factory, backup, restore, + badblocks, go_to_console, reboot_, NULL }; + char * actions_flash_upgrade[] = { upgrade, go_to_console, reboot_, NULL }; + + + char * flash_mode; + char ** actions; + char * choice; + + process_cmdline(); + flash_mode = get_param_valued("flash"); + actions = !flash_mode ? + actions_default : + streq(flash_mode, "upgrade") ? actions_flash_upgrade : actions_flash_rescue; + + init_frontend("Welcome to " DISTRIB_NAME " Rescue (" DISTRIB_VERSION ") " __DATE__ " " __TIME__); + + do { + int pid; + char * binary = NULL; + + choice = ""; + results = ask_from_list("Please choose the desired action.", actions, &choice); + + if (ptr_begins_static_str(choice, install_bootloader)) { + binary = "/usr/bin/install_bootloader"; + } +#if ENABLE_RESCUE_MS_BOOT + if (ptr_begins_static_str(choice, restore_ms_boot)) { + binary = "/usr/bin/restore_ms_boot"; + } +#endif + if (ptr_begins_static_str(choice, mount_parts)) { + binary = "/usr/bin/guessmounts"; + } + if (ptr_begins_static_str(choice, reboot_)) { + finish_frontend(); + sync(); sync(); + sleep(2); + unmount_filesystems(); + sync(); sync(); + printf("rebooting system\n"); + sleep(2); + reboot(); + } + if (ptr_begins_static_str(choice, doc)) { + binary = "/usr/bin/rescue-doc"; + } + + /* Mandriva Flash entries */ + if (ptr_begins_static_str(choice, rootpass)) { + binary = "/usr/bin/reset_rootpass"; + } + if (ptr_begins_static_str(choice, userpass)) { + binary = "/usr/bin/reset_userpass"; + } + if (ptr_begins_static_str(choice, factory)) { + binary = "/usr/bin/clear_systemloop"; + } + if (ptr_begins_static_str(choice, backup)) { + binary = "/usr/bin/backup_systemloop"; + } + if (ptr_begins_static_str(choice, restore)) { + binary = "/usr/bin/restore_systemloop"; + } + if (ptr_begins_static_str(choice, badblocks)) { + binary = "/usr/bin/test_badblocks"; + } + if (ptr_begins_static_str(choice, upgrade)) { + binary = "/usr/bin/upgrade"; + } + + if (binary) { + int wait_status; + suspend_to_console(); + if (!(pid = fork())) { + + char * child_argv[2]; + child_argv[0] = binary; + child_argv[1] = NULL; + + execve(child_argv[0], child_argv, env); + printf("Can't execute binary (%s)\n<press Enter>\n", binary); + PAUSE(); + + return 33; + } + while (wait4(-1, &wait_status, 0, NULL) != pid) {}; + printf("<press Enter to return to Rescue menu>"); + PAUSE(); + resume_from_suspend(); + if (!WIFEXITED(wait_status) || WEXITSTATUS(wait_status) != 0) { + error_message("Program exited abnormally (return code %d).", WEXITSTATUS(wait_status)); + if (WIFSIGNALED(wait_status)) + error_message("(received signal %d)", WTERMSIG(wait_status)); + } + } + + } while (results == RETURN_OK && !ptr_begins_static_str(choice, go_to_console)); + + finish_frontend(); + printf("Bye.\n"); + + return 0; +} |
