summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mdk-stage1/automatic.c22
-rw-r--r--mdk-stage1/automatic.h1
-rw-r--r--mdk-stage1/init.c15
-rw-r--r--mdk-stage1/modules.c2
-rw-r--r--mdk-stage1/network.c10
-rw-r--r--mdk-stage1/probing.c50
-rw-r--r--mdk-stage1/probing.h3
-rw-r--r--mdk-stage1/stage1.c71
-rw-r--r--mdk-stage1/stage1.h1
-rw-r--r--mdk-stage1/tools.c83
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;
}