diff options
-rw-r--r-- | mdk-stage1/automatic.c | 22 | ||||
-rw-r--r-- | mdk-stage1/automatic.h | 1 | ||||
-rw-r--r-- | mdk-stage1/init.c | 15 | ||||
-rw-r--r-- | mdk-stage1/modules.c | 2 | ||||
-rw-r--r-- | mdk-stage1/network.c | 10 | ||||
-rw-r--r-- | mdk-stage1/probing.c | 50 | ||||
-rw-r--r-- | mdk-stage1/probing.h | 3 | ||||
-rw-r--r-- | mdk-stage1/stage1.c | 71 | ||||
-rw-r--r-- | mdk-stage1/stage1.h | 1 | ||||
-rw-r--r-- | mdk-stage1/tools.c | 83 |
10 files changed, 214 insertions, 44 deletions
diff --git a/mdk-stage1/automatic.c b/mdk-stage1/automatic.c index b92cc9e40..57ae1f3a6 100644 --- a/mdk-stage1/automatic.c +++ b/mdk-stage1/automatic.c @@ -105,6 +105,28 @@ enum return_type ask_from_list_auto(char *msg, char ** elems, char ** choice, ch } } +enum return_type ask_from_list_comments_auto(char *msg, char ** elems, char ** elems_comments, char ** choice, char * auto_param, char ** elems_auto) +{ + if (!IS_AUTOMATIC) + return ask_from_list_comments(msg, elems, elems_comments, choice); + else { + char ** sav_elems = elems; + char * tmp = get_auto_value(auto_param); + while (elems && *elems) { + if (!strcmp(tmp, *elems_auto)) { + *choice = *elems; + log_message("AUTOMATIC: parameter %s for %s means returning %s", tmp, auto_param, *elems); + return RETURN_OK; + } + elems++; + elems_auto++; + } + unset_param(MODE_AUTOMATIC); /* we are in a fallback mode */ + return ask_from_list_comments(msg, sav_elems, elems_comments, choice); + } +} + + enum return_type ask_from_entries_auto(char *msg, char ** questions, char *** answers, int entry_size, char ** questions_auto) { if (!IS_AUTOMATIC) diff --git a/mdk-stage1/automatic.h b/mdk-stage1/automatic.h index 507876072..f51b1d749 100644 --- a/mdk-stage1/automatic.h +++ b/mdk-stage1/automatic.h @@ -26,6 +26,7 @@ void grab_automatic_params(char * line); enum return_type ask_from_list_auto(char *msg, char ** elems, char ** choice, char * auto_param, char ** elems_auto); +enum return_type ask_from_list_comments_auto(char *msg, char ** elems, char ** elems_comments, char ** choice, char * auto_param, char ** elems_auto); enum return_type ask_from_entries_auto(char *msg, char ** questions, char *** answers, int entry_size, char ** questions_auto); #endif diff --git a/mdk-stage1/init.c b/mdk-stage1/init.c index fb33c7480..fc48c68f2 100644 --- a/mdk-stage1/init.c +++ b/mdk-stage1/init.c @@ -311,17 +311,6 @@ void unmount_filesystems(void) } } -int is_rescue() -{ - int fd, size; - char buf[512]; - if ((fd = open("/proc/cmdline", O_RDONLY, 0)) == -1) - fatal_error("could not open /proc/cmdline"); - size = read(fd, buf, sizeof(buf)); - buf[size-1] = 0; - close(fd); - return (strstr(buf, "rescue") != NULL); -} int main(int argc, char **argv) { @@ -420,13 +409,13 @@ int main(int argc, char **argv) end_stage2 = 1; } - if (!WIFEXITED(wait_status) || WEXITSTATUS(wait_status)) { + if (!WIFEXITED(wait_status) || (WEXITSTATUS(wait_status) != 0 && WEXITSTATUS(wait_status) != 1)) { printf("install exited abnormally :-( "); if (WIFSIGNALED(wait_status)) printf("-- received signal %d", WTERMSIG(wait_status)); printf("\n"); abnormal_termination = 1; - } else if (is_rescue()) { + } else if (WIFEXITED(wait_status) && WEXITSTATUS(wait_status) == 1) { kill(klog_pid, 9); printf("exiting stage1-initializer -- giving hand to rescue\n"); return 0; diff --git a/mdk-stage1/modules.c b/mdk-stage1/modules.c index 3f9647a35..fe55ff15f 100644 --- a/mdk-stage1/modules.c +++ b/mdk-stage1/modules.c @@ -267,6 +267,8 @@ int my_insmod(const char * mod_name, enum driver_type type, char * options) sprintf(alias, "alias %s %s", *new_net_devices, mod_name); add_modules_conf(alias); log_message("NET: %s", alias); + net_discovered_interface(*new_net_devices); + already_present: new_net_devices++; } diff --git a/mdk-stage1/network.c b/mdk-stage1/network.c index 84eee2c8e..f961df17f 100644 --- a/mdk-stage1/network.c +++ b/mdk-stage1/network.c @@ -502,6 +502,7 @@ static enum return_type bringup_networking(struct interface_info * intf) static char * interface_select(void) { char ** interfaces, ** ptr; + char * descriptions[50]; char * choice; int i, count = 0; enum return_type results; @@ -525,7 +526,14 @@ static char * interface_select(void) if (count == 1) return *interfaces; - results = ask_from_list_auto("Please choose the NET device to use for the installation.", interfaces, &choice, "interface", interfaces); + i = 0; + while (interfaces[i]) { + descriptions[i] = get_net_intf_description(interfaces[i]); + i++; + } + + results = ask_from_list_comments_auto("Please choose the NET device to use for the installation.", + interfaces, descriptions, &choice, "interface", interfaces); if (results != RETURN_OK) return NULL; diff --git a/mdk-stage1/probing.c b/mdk-stage1/probing.c index 88b406b8a..bddeb438d 100644 --- a/mdk-stage1/probing.c +++ b/mdk-stage1/probing.c @@ -64,6 +64,53 @@ static void warning_insmod_failed(void) error_message("Warning, installation of driver failed."); } +#ifndef DISABLE_NETWORK +struct net_description_elem +{ + char * intf_name; + char * intf_description; +}; +static struct net_description_elem net_descriptions[50]; +static int net_descr_number = 0; +static char * intf_descr_for_discover = NULL; +static char * net_intf_too_early_name[50]; /* for modules providing more than one net intf */ +static int net_intf_too_early_number = 0; +static int net_intf_too_early_ptr = 0; + +void prepare_intf_descr(const char * intf_descr) +{ + intf_descr_for_discover = strdup(intf_descr); +} + +void net_discovered_interface(char * intf_name) +{ + if (!intf_descr_for_discover) { + net_intf_too_early_name[net_intf_too_early_number++] = strdup(intf_name); + return; + } + if (!intf_name) { + if (net_intf_too_early_ptr >= net_intf_too_early_number) { + log_message("NET: was expecting another network interface (broken net module?)"); + return; + } + net_descriptions[net_descr_number].intf_name = net_intf_too_early_name[net_intf_too_early_ptr++]; + } + else + net_descriptions[net_descr_number].intf_name = strdup(intf_name); + net_descriptions[net_descr_number].intf_description = strdup(intf_descr_for_discover); + intf_descr_for_discover = NULL; + net_descr_number++; +} + +char * get_net_intf_description(char * intf_name) +{ + int i; + for (i = 0; i < net_descr_number ; i++) + if (!strcmp(net_descriptions[i].intf_name, intf_name)) + return net_descriptions[i].intf_description; + return strdup("unknown"); +} +#endif static void probe_that_type(enum driver_type type) { @@ -126,8 +173,11 @@ static void probe_that_type(enum driver_type type) if (type == NETWORK_DEVICES) { /* insmod is quick, let's use the info message */ info_message("Found %s", pcidb[i].name); + prepare_intf_descr(pcidb[i].name); if (my_insmod(pcidb[i].module, NETWORK_DEVICES, NULL)) warning_insmod_failed(); + if (intf_descr_for_discover) /* for modules providing more than one net intf */ + net_discovered_interface(NULL); } #endif } diff --git a/mdk-stage1/probing.h b/mdk-stage1/probing.h index ecafa0e0a..ea618b7b1 100644 --- a/mdk-stage1/probing.h +++ b/mdk-stage1/probing.h @@ -28,6 +28,9 @@ enum driver_type { SCSI_ADAPTERS, NETWORK_DEVICES, ANY_DRIVER_TYPE }; void get_medias(enum media_type media, char *** names, char *** models); char ** get_net_devices(void); +void net_discovered_interface(char * intf_name); +char * get_net_intf_description(char * intf_name); +void prepare_intf_descr(const char * intf_descr); #endif diff --git a/mdk-stage1/stage1.c b/mdk-stage1/stage1.c index 2332c8c2d..ae07e9463 100644 --- a/mdk-stage1/stage1.c +++ b/mdk-stage1/stage1.c @@ -28,6 +28,7 @@ #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h> +#include <signal.h> #include <stdlib.h> #include <stdio.h> @@ -75,13 +76,11 @@ void fatal_error(char *msg) } - /* spawns a shell on console #2 */ static void spawn_shell(void) { #ifdef SPAWN_SHELL int fd; - pid_t pid; char * shell_name = "/sbin/sash"; log_message("spawning a shell"); @@ -97,7 +96,7 @@ static void spawn_shell(void) return; } - if (!(pid = fork())) { + if (!fork()) { dup2(fd, 0); dup2(fd, 1); dup2(fd, 2); @@ -117,6 +116,65 @@ static void spawn_shell(void) } +char * interactive_fifo = "/tmp/stage1-fifo"; +static pid_t interactive_pid = 0; + +/* spawns my small interactive on console #6 */ +static void spawn_interactive(void) +{ +#ifdef SPAWN_INTERACTIVE + int fd; + char * dev = "/dev/tty6"; + + log_message("spawning my interactive on %s", dev); + + if (!IS_TESTING) { + fd = open(dev, O_RDWR); + if (fd == -1) { + log_message("cannot open %s -- no interactive", dev); + return; + } + + if (mkfifo(interactive_fifo, O_RDWR)) { + log_message("cannot create fifo -- no interactive"); + return; + } + + if (!(interactive_pid = fork())) { + int fif_out; + + 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"); + + fif_out = open(interactive_fifo, O_WRONLY); + printf("Please enter your command (availables: [+,-] [rescue,expert]).\n"); + + while (1) { + char s[50]; + int i = 0; + printf("? "); + fflush(stdout); + read(0, &(s[i++]), 1); + fcntl(0, F_SETFL, O_NONBLOCK); + while (read(0, &(s[i++]), 1) > 0 && i < sizeof(s)); + fcntl(0, F_SETFL, 0); + write(fif_out, s, i-2); + printf("Ok.\n"); + } + } + + close(fd); + } +#endif +} + + static void expert_third_party_modules(void) { enum return_type results; @@ -271,6 +329,8 @@ int main(int argc, char **argv, char **env) if (getpid() > 50) set_param(MODE_TESTING); + spawn_interactive(); + open_log(); log_message("welcome to the " DISTRIB_NAME " install (stage1, version " VERSION " built " __DATE__ " " __TIME__")"); process_cmdline(); @@ -297,6 +357,9 @@ int main(int argc, char **argv, char **env) fatal_error("symlink to " STAGE2_LOCATION " failed"); } + if (interactive_pid != 0) + kill(interactive_pid, 9); + if (IS_RESCUE) { int fd = open("/proc/sys/kernel/real-root-dev", O_RDWR); #ifdef __sparc__ @@ -305,7 +368,7 @@ int main(int argc, char **argv, char **env) write(fd, "0x103", sizeof("0x103")); /* ram3 */ #endif close(fd); - return 0; + return 1; } if (IS_TESTING) diff --git a/mdk-stage1/stage1.h b/mdk-stage1/stage1.h index 736fa6924..b99a8fa65 100644 --- a/mdk-stage1/stage1.h +++ b/mdk-stage1/stage1.h @@ -31,6 +31,7 @@ enum return_type { RETURN_OK, RETURN_BACK, RETURN_ERROR }; extern char * method_name; +extern char * interactive_fifo; #define MODE_TESTING (1 << 0) #define MODE_EXPERT (1 << 1) diff --git a/mdk-stage1/tools.c b/mdk-stage1/tools.c index 84c53a2d6..9acabdb5f 100644 --- a/mdk-stage1/tools.c +++ b/mdk-stage1/tools.c @@ -39,13 +39,13 @@ #include "tools.h" -static struct param_elem * params; +static struct param_elem params[50]; +static int param_number = 0; void process_cmdline(void) { char buf[512]; - int fd, size, i, p; - struct param_elem tmp_params[50]; + int fd, size, i; log_message("opening /proc/cmdline... "); @@ -58,7 +58,7 @@ void process_cmdline(void) log_message("\t%s", buf); - i = 0; p = 0; + i = 0; while (buf[i] != '\0') { char *name, *value = NULL; int j = i; @@ -80,8 +80,9 @@ void process_cmdline(void) value[i-k] = '\0'; } - tmp_params[p].name = name; - tmp_params[p].value = value; + params[param_number].name = name; + params[param_number].value = value; + param_number++; if (!strcmp(name, "expert")) set_param(MODE_EXPERT); if (!strcmp(name, "rescue")) set_param(MODE_RESCUE); if (!strcmp(name, "special_stage2")) set_param(MODE_SPECIAL_STAGE2); @@ -89,24 +90,12 @@ void process_cmdline(void) set_param(MODE_AUTOMATIC); grab_automatic_params(value); } - p++; if (buf[i] == '\0') break; i++; } - if (IS_RESCUE) { - tmp_params[p].name = "special_stage2"; - tmp_params[p].value = "rescue"; - p++; - set_param(MODE_SPECIAL_STAGE2); - } - - tmp_params[p++].name = NULL; - - params = memdup(tmp_params, sizeof(struct param_elem) * p); - - log_message("\tgot %d args", p-1); + log_message("\tgot %d args", param_number); } @@ -114,29 +103,71 @@ int stage1_mode = 0; int get_param(int i) { +#ifdef SPAWN_INTERACTIVE + static int fd = 0; + char buf[5000]; + char * ptr; + int nb; + + if (fd <= 0) { + fd = open(interactive_fifo, O_RDONLY); + if (fd == -1) + return (stage1_mode & i); + fcntl(fd, F_SETFL, O_NONBLOCK); + } + + if (fd > 0) { + if ((nb = read(fd, buf, sizeof(buf))) > 0) { + buf[nb] = '\0'; + ptr = buf; + while ((ptr = strstr(ptr, "+ "))) { + if (!strncmp(ptr+2, "expert", 6)) set_param(MODE_EXPERT); + if (!strncmp(ptr+2, "rescue", 6)) set_param(MODE_RESCUE); + ptr++; + } + ptr = buf; + while ((ptr = strstr(ptr, "- "))) { + if (!strncmp(ptr+2, "expert", 6)) unset_param(MODE_EXPERT); + if (!strncmp(ptr+2, "rescue", 6)) unset_param(MODE_RESCUE); + ptr++; + } + } + } +#endif + return (stage1_mode & i); } char * get_param_valued(char *param_name) { - struct param_elem * ptr = params; - - while (ptr->name) { - if (!strcmp(ptr->name, param_name)) - return ptr->value; - ptr++; - } + int i; + for (i = 0; i < param_number ; i++) + if (!strcmp(params[i].name, param_name)) + return params[i].value; return NULL; } +void set_param_valued(char *param_name, char *param_value) +{ + params[param_number].name = param_name; + params[param_number].value = param_value; + param_number++; +} + void set_param(int i) { + log_message("setting param %d", i); stage1_mode |= i; + if (i == MODE_RESCUE) { + set_param_valued("special_stage2", "rescue"); + set_param(MODE_SPECIAL_STAGE2); + } } void unset_param(int i) { + log_message("unsetting param %d", i); stage1_mode &= ~i; } |