/* * Guillaume Cottenceau (gc@mandrakesoft.com) * * Copyright 2000 MandrakeSoft * * View the homepage: http://us.mandrakesoft.com/~gc/html/stage1.html * * * 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. * */ /* * Portions from Erik Troan (ewt@redhat.com) * * Copyright 1996 Red Hat Software * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "stage1.h" #include "log.h" #include "probing.h" #include "frontend.h" #include "modules.h" #include "tools.h" #include "automatic.h" #include "mount.h" #include "insmod.h" #ifndef DISABLE_CDROM #include "cdrom.h" #endif #ifndef DISABLE_NETWORK #include "network.h" #endif #ifndef DISABLE_DISK #include "disk.h" #endif #ifdef SPAWN_SPLASH #include "init.h" #endif extern char *env[]; /************************************************************ * globals */ char version[128] = DISTRIB_NAME; char * method_name; void fatal_error(char *msg) { printf("FATAL ERROR IN STAGE1: %s\n\nI can't recover from this.\nYou may reboot your system.\n", msg); while (1); } /************************************************************ * special frontend functs * (the principle is to not pollute frontend code with stage1-specific stuff) */ void stg1_error_message(char *msg, ...) { va_list args; va_start(args, msg); log_message("unsetting automatic"); unset_param(MODE_AUTOMATIC); verror_message(msg, args); va_end(args); } void stg1_info_message(char *msg, ...) { va_list args; va_start(args, msg); if (IS_AUTOMATIC) { vlog_message(msg, args); return; } vinfo_message(msg, args); va_end(args); } /************************************************************ * spawns a shell on console #2 */ static pid_t shell_pid = 0; static void spawn_shell(void) { #ifdef SPAWN_SHELL int fd; int i; int timeout=60; char * shell_name[] = { "/bin/sh", NULL }; log_message("spawning a shell"); if (!IS_TESTING) { for(i=0; i < timeout; i++ ) { fd = open("/dev/tty2", O_RDWR); if(fd > -1) break; fprintf(stderr,"\rwaiting for /dev/tty2: %d",i); sleep(1); } if (fd == -1) { log_message("cannot open /dev/tty2 -- no shell will be provided"); return; } else if (access(shell_name[0], X_OK)) { log_message("cannot open shell - %s doesn't exist", shell_name[0]); return; } if (!(shell_pid = fork())) { dup2(fd, 0); dup2(fd, 1); dup2(fd, 2); close(fd); setsid(); if (ioctl(0, TIOCSCTTY, NULL)) log_perror("could not set new controlling tty"); execve(shell_name[0], shell_name, env); log_message("execve of %s failed: %s", shell_name[0], strerror(errno)); exit(-1); } close(fd); } #endif } static void spawn_splash(void) { #ifdef SPAWN_SPLASH if (!IS_SPLASH) return; struct stat pst; if (stat("/bin/plymouth", &pst)) return; char * splash_name[] = { "/sbin/plymouthd", "plymouthd", "--tty=/dev/tty5", NULL }; log_message("spawning a splash screen"); if(spawn(splash_name)) sleep(1); char * av[] = { "/bin/plymouth", "plymouth", "show-splash", NULL }; log_message( "%s: %s\n", av[0], av[2] ); spawn(av); return; #endif } /************************************************************ */ static void expert_third_party_modules(void) { enum return_type results; char * floppy_mount_location = "/tmp/floppy"; char ** modules; char final_name[500]; char * choice; int rc; char * questions[] = { "Options", NULL }; static char ** answers = NULL; results = ask_yes_no("If you want to insert third-party kernel modules, insert " "a Linux (ext2fs) formatted floppy containing the modules and confirm. Otherwise, select \"no\".");; if (results != RETURN_OK) return; my_insmod("floppy", NULL); if (my_mount("/dev/fd0", floppy_mount_location, "ext2", 0) == -1) { stg1_error_message("I can't find a Linux ext2 floppy in first floppy drive."); return expert_third_party_modules(); } modules = list_directory(floppy_mount_location); if (!modules || !*modules) { stg1_error_message("No modules found on floppy disk."); umount(floppy_mount_location); return expert_third_party_modules(); } results = ask_from_list("Which driver would you like to insmod?", modules, &choice); if (results != RETURN_OK) { umount(floppy_mount_location); return; } sprintf(final_name, "%s/%s", floppy_mount_location, choice); results = ask_from_entries("Please enter the options:", questions, &answers, 24, NULL); if (results != RETURN_OK) { umount(floppy_mount_location); return expert_third_party_modules(); } rc = insmod_call(final_name, answers[0]); umount(floppy_mount_location); if (rc) { log_message("\tfailed"); stg1_error_message("Insmod failed."); } return expert_third_party_modules(); } /************************************************************ */ static enum return_type method_select_and_prepare(void) { enum return_type results; char * choice; char * means[10], * means_auto[10]; int i; #ifndef DISABLE_DISK char * disk_install = "Hard disk"; char * disk_install_auto = "disk"; #endif #ifndef DISABLE_CDROM char * cdrom_install = "CDROM drive"; char * cdrom_install_auto = "cdrom"; #endif #ifndef DISABLE_NETWORK char * network_nfs_install = "NFS server"; char * network_nfs_install_auto = "nfs"; char * network_ftp_install = "FTP server"; char * network_ftp_install_auto = "ftp"; char * network_http_install = "HTTP server"; char * network_http_install_auto = "http"; #endif i = 0; #ifndef DISABLE_NETWORK means[i] = network_nfs_install; means_auto[i++] = network_nfs_install_auto; means[i] = network_ftp_install; means_auto[i++] = network_ftp_install_auto; means[i] = network_http_install; means_auto[i++] = network_http_install_auto; #endif #ifndef DISABLE_CDROM means[i] = cdrom_install; means_auto[i++] = cdrom_install_auto; #endif #ifndef DISABLE_DISK means[i] = disk_install; means_auto[i++] = disk_install_auto; #endif means[i] = NULL; update_splash("method_select"); #ifndef DISABLE_NETWORK /* if requested by auto "network" param, bring networking up, regardless of method */ net_prepare(); #endif results = ask_from_list_auto("Please choose the installation method.", means, &choice, "method", means_auto); if (results != RETURN_OK) return method_select_and_prepare(); results = RETURN_ERROR; #ifndef DISABLE_CDROM if (!strcmp(choice, cdrom_install)) results = cdrom_prepare(); #endif #ifndef DISABLE_DISK if (!strcmp(choice, disk_install)) results = disk_prepare(); #endif #ifndef DISABLE_NETWORK if (!strcmp(choice, network_nfs_install)) results = nfs_prepare(); if (!strcmp(choice, network_ftp_install)) results = ftp_prepare(); if (!strcmp(choice, network_http_install)) results = http_prepare(); #endif if (results != RETURN_OK) return method_select_and_prepare(); return RETURN_OK; } void getversion() { FILE *f; char *c; if (!(f = fopen(VERSION_FILE, "r"))) return; if (fgets(version, sizeof(version), f)) { c = strrchr(version, '\n'); if (c) *c = 0; } fclose(f); } void stage1() { enum return_type ret; char buf[128]; char *init; open_log(); getversion(); log_message("welcome to the %s install (alt-stage1, built " __DATE__ " " __TIME__")", version); process_cmdline(); handle_env(env); spawn_shell(); spawn_splash(); update_splash("welcome"); snprintf(buf, sizeof(buf), "Welcome to %s", version); init_frontend(buf); update_splash("init_frontend"); init = get_param_valued("init"); if (init) add_to_env("INIT", init); ret = method_select_and_prepare(); finish_frontend(); update_splash("finish_frontend"); close_log(); if (ret != RETURN_OK) fatal_error("could not select an installation method"); /* all went good */ if (shell_pid != 0) kill(shell_pid, 9); pass_env(4); exit(0); }