summaryrefslogtreecommitdiffstats
path: root/mdk-stage1
diff options
context:
space:
mode:
Diffstat (limited to 'mdk-stage1')
-rw-r--r--mdk-stage1/Makefile23
-rw-r--r--mdk-stage1/cdrom.c93
-rw-r--r--mdk-stage1/cdrom.h29
-rw-r--r--mdk-stage1/disk.c91
-rw-r--r--mdk-stage1/disk.h27
-rw-r--r--mdk-stage1/frontend.h34
-rw-r--r--mdk-stage1/init.c198
-rw-r--r--mdk-stage1/log.c48
-rw-r--r--mdk-stage1/log.h8
-rw-r--r--mdk-stage1/mar/Makefile13
-rw-r--r--mdk-stage1/mar/mar-extract-only.c43
-rw-r--r--mdk-stage1/mar/mar-extract-only.h6
-rw-r--r--mdk-stage1/mar/mar-frontend.c18
-rw-r--r--mdk-stage1/mar/mar.h3
-rw-r--r--mdk-stage1/minilibc.c16
-rw-r--r--mdk-stage1/minilibc.h4
-rw-r--r--mdk-stage1/modules.c203
-rw-r--r--mdk-stage1/modules.h33
-rw-r--r--mdk-stage1/network.c46
-rw-r--r--mdk-stage1/network.h30
-rw-r--r--mdk-stage1/newt-frontend.c149
-rw-r--r--mdk-stage1/probing.c301
-rw-r--r--mdk-stage1/probing.h44
-rw-r--r--mdk-stage1/stage1.c180
-rw-r--r--mdk-stage1/stage1.h61
-rw-r--r--mdk-stage1/tools.c71
-rw-r--r--mdk-stage1/tools.h30
27 files changed, 1575 insertions, 227 deletions
diff --git a/mdk-stage1/Makefile b/mdk-stage1/Makefile
index a1b2fc68f..beefda163 100644
--- a/mdk-stage1/Makefile
+++ b/mdk-stage1/Makefile
@@ -29,7 +29,7 @@ ARCH := $(patsubst sparc%,sparc,$(ARCH))
#- We can leave "-g" forever since stripping will remove everything
CFLAGS = -Os -g -Wall -Werror -fomit-frame-pointer
INCLUDES = -I.
-DEFS = -D_GNU_SOURCE=1 -DVERSION=\"$(VERSION)\" -DUSE_LOGDEV -DSPAWN_SHELL
+DEFS = -D_GNU_SOURCE=1 -DVERSION=\"$(VERSION)\"
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CFLAGS)
@@ -41,12 +41,12 @@ INITOBJS = $(subst .c,.o,$(INITSRC))
#- stage1 itself (minus stage1.c)
-STAGE1SRC = log.c #cdrom.c devices.c
+STAGE1SRC = log.c tools.c modules.c probing.c newt-frontend.c cdrom.c disk.c network.c
-STAGE1OBJS = $(subst .c,.o,$(STAGE1SRC))
+STAGE1OBJS = $(subst .c,.o,$(STAGE1SRC)) insmod-busybox/libinsmod.a mar/libmar.a /usr/lib/libnewt.a /usr/lib/libslang.a /usr/lib/libz.a
-ALLSRC = $(INITSRC) $(STAGE1SRC)
+ALLSRC = $(INITSRC) $(STAGE1SRC) stage1.c
ifeq (i386, $(ARCH))
@@ -81,13 +81,12 @@ BINS = init stage1-network
#BINS += stage1-all
#endif
-DIRS = mar
+DIRS = mar insmod-busybox
all: dirs $(BINS)
dirs:
- @echo -e "*** BUILDING in all directories\n"
@for n in . $(DIRS); do \
[ "$$n" = "." ] || make -C $$n ;\
done
@@ -95,20 +94,24 @@ dirs:
init: $(INITOBJS)
$(CC) $(LDFLAGS_INIT) -o $@ $(INITOBJS)
+ strip -s $@
-stage1-network: $(STAGE1OBJS) stage1-network.o $(NETOBJS)
- $(CC) $(LDFLAGS_STAGE1) -o $@ $(STAGE1OBJS) stage1-network.o $(NETOBJS)
+stage1-network: stage1-network.o $(STAGE1OBJS) $(NETOBJS)
+ $(CC) $(LDFLAGS_STAGE1) -o $@ $^
+ strip -s $@
+stage1-network-diet: $(STAGE1OBJS) stage1-network.o $(NETOBJS)
+ gcc -nostdlib -o $@ ../../../tmp/dietlibc/start.o $^ ../../../tmp/dietlibc/dietlibc.a
+ strip -s $@
.c.o:
$(COMPILE) -c $<
stage1-network.o: stage1.c
- $(COMPILE) -DNETWORK_INSTALL -o $@ -c $<
+ $(COMPILE) -c $< -o $@
clean:
- @echo -e "*** CLEANING in all directories\n"
@for n in $(DIRS); do \
(cd $$n; make clean) \
done
diff --git a/mdk-stage1/cdrom.c b/mdk-stage1/cdrom.c
new file mode 100644
index 000000000..e794dc9f5
--- /dev/null
+++ b/mdk-stage1/cdrom.c
@@ -0,0 +1,93 @@
+/*
+ * Guillaume Cottenceau (gc@mandrakesoft.com)
+ *
+ * Copyright 2000 MandrakeSoft
+ *
+ * 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 <stdlib.h>
+#include <unistd.h>
+#include "stage1.h"
+#include "frontend.h"
+#include "modules.h"
+#include "probing.h"
+#include "log.h"
+
+#include "cdrom.h"
+
+static enum return_type try_with_device(char *dev_name)
+{
+ log_message("with dev %s", dev_name);
+
+ error_message("Should be trying with sucking device.");
+
+ return RETURN_OK;
+}
+
+enum return_type cdrom_prepare(void)
+{
+ char ** medias, ** ptr, ** medias_models;
+ char * choice;
+ int i, count = 0;
+ enum return_type results;
+
+ my_insmod("ide-cd");
+ my_insmod("sr_mod");
+ my_insmod("isofs");
+
+ medias = get_medias(CDROM, QUERY_NAME);
+
+ ptr = medias;
+ while (ptr && *ptr) {
+ log_message("found CDROM %s", *ptr);
+ count++;
+ ptr++;
+ }
+
+ if (count == 0) {
+ error_message("No CDROM device found.");
+ i = ask_scsi_insmod();
+ if (i == RETURN_BACK)
+ return RETURN_BACK;
+ return cdrom_prepare();
+ }
+
+ if (count == 1) {
+ results = try_with_device(*medias);
+ if (results == RETURN_OK)
+ return RETURN_OK;
+ i = ask_scsi_insmod();
+ if (i == RETURN_BACK)
+ return RETURN_BACK;
+ return cdrom_prepare();
+ }
+
+ medias_models = get_medias(CDROM, QUERY_MODEL);
+
+ results = ask_from_list_comments("Please choose the CDROM drive to use for the installation.", medias, medias_models, &choice);
+
+ if (results != RETURN_OK)
+ return results;
+
+ results = try_with_device(choice);
+ if (results == RETURN_OK)
+ return RETURN_OK;
+ i = ask_scsi_insmod();
+ if (i == RETURN_BACK)
+ return RETURN_BACK;
+ return cdrom_prepare();
+}
diff --git a/mdk-stage1/cdrom.h b/mdk-stage1/cdrom.h
new file mode 100644
index 000000000..639487eed
--- /dev/null
+++ b/mdk-stage1/cdrom.h
@@ -0,0 +1,29 @@
+/*
+ * Guillaume Cottenceau (gc@mandrakesoft.com)
+ *
+ * Copyright 2000 MandrakeSoft
+ *
+ * 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
+ *
+ */
+
+#ifndef _CDROM_H_
+#define _CDROM_H_
+
+#include "stage1.h"
+
+enum return_type cdrom_prepare(void);
+
+#endif
diff --git a/mdk-stage1/disk.c b/mdk-stage1/disk.c
new file mode 100644
index 000000000..e64782471
--- /dev/null
+++ b/mdk-stage1/disk.c
@@ -0,0 +1,91 @@
+/*
+ * Guillaume Cottenceau (gc@mandrakesoft.com)
+ *
+ * Copyright 2000 MandrakeSoft
+ *
+ * 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 <stdlib.h>
+#include <unistd.h>
+#include "stage1.h"
+#include "frontend.h"
+#include "modules.h"
+#include "probing.h"
+#include "log.h"
+
+#include "disk.h"
+
+static enum return_type try_with_device(char *dev_name)
+{
+
+ return RETURN_OK;
+}
+
+enum return_type disk_prepare(void)
+{
+ char ** medias, ** ptr, ** medias_models;
+ char * choice;
+ int i, count = 0;
+ enum return_type results;
+
+ my_insmod("sd_mod");
+ my_insmod("vfat");
+ my_insmod("reiserfs");
+
+ medias = get_medias(DISK, QUERY_NAME);
+
+ /* TODO partition check */
+ ptr = medias;
+ while (ptr && *ptr) {
+ log_message("found DISK %s", *ptr);
+ count++;
+ ptr++;
+ }
+
+ if (count == 0) {
+ error_message("No DISK drive found.");
+ i = ask_scsi_insmod();
+ if (i == RETURN_BACK)
+ return RETURN_BACK;
+ return disk_prepare();
+ }
+
+ if (count == 1) {
+ results = try_with_device(*medias);
+ if (results == RETURN_OK)
+ return RETURN_OK;
+ i = ask_scsi_insmod();
+ if (i == RETURN_BACK)
+ return RETURN_BACK;
+ return disk_prepare();
+ }
+
+ medias_models = get_medias(DISK, QUERY_MODEL);
+
+ results = ask_from_list_comments("Please choose the DISK drive to use for the installation.", medias, medias_models, &choice);
+
+ if (results != RETURN_OK)
+ return results;
+
+ results = try_with_device(choice);
+ if (results == RETURN_OK)
+ return RETURN_OK;
+ i = ask_scsi_insmod();
+ if (i == RETURN_BACK)
+ return RETURN_BACK;
+ return disk_prepare();
+}
diff --git a/mdk-stage1/disk.h b/mdk-stage1/disk.h
new file mode 100644
index 000000000..54213cf68
--- /dev/null
+++ b/mdk-stage1/disk.h
@@ -0,0 +1,27 @@
+/*
+ * Guillaume Cottenceau (gc@mandrakesoft.com)
+ *
+ * Copyright 2000 MandrakeSoft
+ *
+ * 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
+ *
+ */
+
+#ifndef _DISK_H_
+#define _DISK_H_
+
+enum return_type disk_prepare(void);
+
+#endif
diff --git a/mdk-stage1/frontend.h b/mdk-stage1/frontend.h
new file mode 100644
index 000000000..27b858a51
--- /dev/null
+++ b/mdk-stage1/frontend.h
@@ -0,0 +1,34 @@
+/*
+ * Guillaume Cottenceau (gc@mandrakesoft.com)
+ *
+ * Copyright 2000 MandrakeSoft
+ *
+ * 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.
+ *
+ */
+
+/*
+ * Each different frontend must implement all functions defined here
+ */
+
+
+#ifndef _FRONTEND_H_
+#define _FRONTEND_H_
+
+#include "stage1.h"
+
+void init_frontend(void);
+void finish_frontend(void);
+void error_message(char *msg);
+void wait_message(char *msg, ...);
+void remove_wait_message(void);
+
+enum return_type ask_from_list(char *msg, char ** elems, char ** choice);
+enum return_type ask_from_list_comments(char *msg, char ** elems, char ** elems_comments, char ** choice);
+
+#endif
diff --git a/mdk-stage1/init.c b/mdk-stage1/init.c
index 7a0363c3f..3783bc8c7 100644
--- a/mdk-stage1/init.c
+++ b/mdk-stage1/init.c
@@ -34,12 +34,12 @@
#define ENV_DEBUG 4
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:/usr/X11R6/lib:/mnt/usr/X11R6/lib",
- "HOME=/",
- "TERMINFO=/etc/linux-terminfo",
- NULL
+ "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:/usr/X11R6/lib:/mnt/usr/X11R6/lib",
+ "HOME=/",
+ "TERM=linux",
+ "TERMINFO=/etc/terminfo",
+ NULL
};
@@ -73,7 +73,11 @@ void print_warning(char *msg)
}
-void doklog(char * fn)
+/* fork to:
+ * (1) watch /proc/kmsg and copy the stuff to /dev/tty4
+ * (2) listens to /dev/log and copy also this stuff (log from programs)
+ */
+void doklog()
{
fd_set readset, unixs;
int in, out, i;
@@ -86,28 +90,24 @@ void doklog(char * fn)
/* open kernel message logger */
in = open("/proc/kmsg", O_RDONLY,0);
- if (in < 0)
- {
+ if (in < 0) {
print_error("could not open /proc/kmsg");
return;
}
-
- out = open(fn, O_WRONLY, 0);
+
+ out = open("/dev/tty4", O_WRONLY, 0);
if (out < 0)
print_warning("couldn't open tty for syslog -- still using /tmp/syslog\n");
-
+
log = open("/tmp/syslog", O_WRONLY | O_CREAT, 0644);
- if (log < 0)
- {
+ if (log < 0) {
print_error("error opening /tmp/syslog");
sleep(5);
return;
}
- /* if we get this far, we should be in good shape */
- if (fork())
- {
+ if (fork()) {
/* parent */
close(in);
close(out);
@@ -116,7 +116,7 @@ void doklog(char * fn)
return;
}
- printf("logging process forked.\n");
+ printf("kernel logging process forked.\n");
close(0);
close(1);
@@ -124,39 +124,38 @@ void doklog(char * fn)
dup2(1, log);
-#if defined(USE_LOGDEV)
/* now open the syslog socket */
sockaddr.sun_family = AF_UNIX;
- strcpy(sockaddr.sun_path, "/dev/log");
+ strncpy(sockaddr.sun_path, "/dev/log", UNIX_PATH_MAX);
sock = socket(AF_UNIX, SOCK_STREAM, 0);
- if (sock < 0)
- {
+ if (sock < 0) {
printf("error creating socket: %d\n", errno);
sleep(5);
}
- printf("got socket\n");
- if (bind(sock, (struct sockaddr *) &sockaddr, sizeof(sockaddr.sun_family) +
- strlen(sockaddr.sun_path)))
- {
- printf("bind error: %d\n", errno);
+ print_str(log, "] got socket\n");
+ if (bind(sock, (struct sockaddr *) &sockaddr, sizeof(sockaddr.sun_family) + strlen(sockaddr.sun_path))) {
+ print_str(log, "] bind error: ");
+ print_int(log, errno);
+ print_str(log, "\n");
sleep(5);
}
- printf("bound socket\n");
+ print_str(log, "] bound socket\n");
chmod("/dev/log", 0666);
- if (listen(sock, 5))
- {
- printf("listen error: %d\n", errno);
+ if (listen(sock, 5)) {
+ print_str(log, "] listen error: ");
+ print_int(log, errno);
+ print_str(log, "\n");
sleep(5);
}
-#endif
+ /* disable on-console syslog output */
syslog(8, NULL, 1);
+ print_str(log, "] kernel/system logger ok\n");
FD_ZERO(&unixs);
- while (1)
- {
+ while (1) {
memcpy(&readset, &unixs, sizeof(unixs));
if (sock >= 0) FD_SET(sock, &readset);
@@ -164,59 +163,53 @@ void doklog(char * fn)
i = select(20, &readset, NULL, NULL, NULL);
if (i <= 0) continue;
-
- if (FD_ISSET(in, &readset))
- {
+
+ /* has /proc/kmsg things to tell us? */
+ if (FD_ISSET(in, &readset)) {
i = read(in, buf, sizeof(buf));
- if (i > 0)
- {
+ if (i > 0) {
if (out >= 0) write(out, buf, i);
write(log, buf, i);
}
}
-
- for (readfd = 0; readfd < 20; ++readfd)
- {
- if (FD_ISSET(readfd, &readset) && FD_ISSET(readfd, &unixs))
- {
+
+ /* examine some fd's in the hope to find some syslog outputs from programs */
+ for (readfd = 0; readfd < 20; ++readfd) {
+ if (FD_ISSET(readfd, &readset) && FD_ISSET(readfd, &unixs)) {
+ print_str(log, "] one fd moves: ");
+ print_int(log, readfd);
+ print_str(log, "\n");
i = read(readfd, buf, sizeof(buf));
- if (i > 0)
- {
- if (out >= 0)
- {
+ if (i > 0) {
+ if (out >= 0) {
write(out, buf, i);
- write(out, "\n", 1);
+ write(out, "\n", 1);
}
-
+
write(log, buf, i);
write(log, "\n", 1);
+ } else if (i == 0) {
+ /* socket closed */
+ close(readfd);
+ FD_CLR(readfd, &unixs);
}
- else
- if (i == 0)
- {
- /* socket closed */
- close(readfd);
- FD_CLR(readfd, &unixs);
- }
}
}
- if (sock >= 0 && FD_ISSET(sock, &readset))
- {
+ /* the socket has moved, new stuff to do */
+ if (sock >= 0 && FD_ISSET(sock, &readset)) {
+ print_str(log, "] syslog socket moved\n");
s = sizeof(sockaddr);
readfd = accept(sock, (struct sockaddr *) &sockaddr, &s);
- if (readfd < 0)
- {
- char * msg_error = "error in accept\n";
+ if (readfd < 0) {
+ char * msg_error = "] error in accept\n";
if (out >= 0) write(out, msg_error, strlen(msg_error));
write(log, msg_error, strlen(msg_error));
close(sock);
sock = -1;
}
else
- {
FD_SET(readfd, &unixs);
- }
}
}
}
@@ -225,14 +218,12 @@ void doklog(char * fn)
void del_loop(char *device)
{
int fd;
- if ((fd = open(device, O_RDONLY, 0)) < 0)
- {
+ if ((fd = open(device, O_RDONLY, 0)) < 0) {
printf("del_loop open failed\n");
return;
}
- if (ioctl(fd, LOOP_CLR_FD, 0) < 0)
- {
+ if (ioctl(fd, LOOP_CLR_FD, 0) < 0) {
printf("del_loop ioctl failed");
return;
}
@@ -248,6 +239,7 @@ struct filesystem
int mounted;
};
+/* attempt to unmount all filesystems in /proc/mounts */
void unmount_filesystems(void)
{
int fd, size;
@@ -260,8 +252,7 @@ void unmount_filesystems(void)
printf("unmounting filesystems...\n");
fd = open("/proc/mounts", O_RDONLY, 0);
- if (fd < 1)
- {
+ if (fd < 1) {
print_error("failed to open /proc/mounts");
sleep(2);
return;
@@ -273,8 +264,7 @@ void unmount_filesystems(void)
close(fd);
p = buf;
- while (*p)
- {
+ while (*p) {
fs[numfs].mounted = 1;
fs[numfs].dev = p;
while (*p != ' ') p++;
@@ -293,14 +283,11 @@ void unmount_filesystems(void)
/* Pixel's ultra-optimized sorting algorithm:
multiple passes trying to umount everything until nothing moves
anymore (a.k.a holy shotgun method) */
- do
- {
+ do {
nb = 0;
- for (i = 0; i < numfs; i++)
- {
+ for (i = 0; i < numfs; i++) {
/*printf("trying with %s\n", fs[i].name);*/
- if (fs[i].mounted && umount(fs[i].name) == 0)
- {
+ 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);
@@ -311,16 +298,14 @@ void unmount_filesystems(void)
}
}
} while (nb);
-
+
for (i = nb = 0; i < numfs; i++)
- if (fs[i].mounted)
- {
+ if (fs[i].mounted) {
printf("\t%s umount failed\n", fs[i].name);
if (strcmp(fs[i].fs, "ext2") == 0) nb++; /* don't count not-ext2 umount failed */
}
- if (nb)
- {
+ if (nb) {
printf("failed to umount some filesystems\n");
while (1);
}
@@ -338,8 +323,7 @@ void disable_swap(void)
printf("disabling swap...\n");
fd = open("/proc/swaps", O_RDONLY, 0);
- if (fd < 0)
- {
+ if (fd < 0) {
print_warning("failed to open /proc/swaps");
return;
}
@@ -347,16 +331,14 @@ void disable_swap(void)
/* read all data at once */
i = read(fd, buf, sizeof(buf) - 1);
close(fd);
- if (i < 0)
- {
+ if (i < 0) {
print_warning("failed to read /proc/swaps");
return;
}
buf[i] = '\0';
start = buf;
- while (*start)
- {
+ while (*start) {
/* move to next line */
while (*start != '\n' && *start) start++;
if (!*start) return;
@@ -394,8 +376,7 @@ int main(int argc, char **argv)
/* getpid() != 1 should work, by linuxrc tends to get a larger pid */
testing = (getpid() > 50);
- if (!testing)
- {
+ if (!testing) {
/* turn off screen blanking */
printf("\033[9;0]");
printf("\033[8]");
@@ -408,8 +389,7 @@ int main(int argc, char **argv)
printf("VERSION: %s\n", VERSION);
- if (!testing)
- {
+ if (!testing) {
printf("mounting /proc filesystem... ");
if (mount("/proc", "/proc", "proc", 0, NULL))
fatal_error("Unable to mount proc filesystem");
@@ -422,8 +402,7 @@ int main(int argc, char **argv)
signal(SIGTSTP, SIG_IGN);
- if (!testing)
- {
+ if (!testing) {
fd = open("/dev/tty1", O_RDWR, 0);
if (fd < 0)
/* try with devfs */
@@ -444,8 +423,7 @@ int main(int argc, char **argv)
if (ioctl(0, TIOCSCTTY, NULL))
print_error("could not set new controlling tty");
- if (!testing)
- {
+ if (!testing) {
char * my_hostname = "localhost.localdomain";
sethostname(my_hostname, strlen(my_hostname));
/* the default domainname (as of 2.0.35) is "(none)", which confuses
@@ -454,19 +432,19 @@ int main(int argc, char **argv)
}
if (!testing)
- doklog("/dev/tty4");
+ doklog();
/* Go into normal init mode - keep going, and then do a orderly shutdown
when:
- 1) /bin/install exits
+ 1) install exits
2) we receive a SIGHUP
*/
-
+
+ printf("Remember what Warly said: drink white part of an egg each morning builds a man!\n");
printf("running stage1...\n");
- if (!(installpid = fork()))
- {
+ if (!(installpid = fork())) {
/* child */
char * child_argv[2];
child_argv[0] = "/sbin/stage1";
@@ -478,20 +456,16 @@ int main(int argc, char **argv)
exit(0);
}
- while (!end_stage2)
- {
+ while (!end_stage2) {
childpid = wait4(-1, &wait_status, 0, NULL);
if (childpid == installpid)
end_stage2 = 1;
}
- if (!WIFEXITED(wait_status) || WEXITSTATUS(wait_status))
- {
+ if (!WIFEXITED(wait_status) || WEXITSTATUS(wait_status)) {
printf("install exited abnormally :-( ");
if (WIFSIGNALED(wait_status))
- {
printf("-- received signal %d", WTERMSIG(wait_status));
- }
printf("\n");
abnormal_termination = 1;
}
@@ -516,15 +490,13 @@ int main(int argc, char **argv)
disable_swap();
unmount_filesystems();
- if (!abnormal_termination)
- {
+ if (!abnormal_termination) {
printf("rebooting system\n");
sleep(2);
+ printf("**temp** should be rebooting\n"); while(1);
reboot(0xfee1dead, 672274793, 0x1234567);
- }
- else
- {
+ } else {
printf("you may safely reboot your system\n");
while (1);
}
diff --git a/mdk-stage1/log.c b/mdk-stage1/log.c
index 27e77bf02..7536d0a08 100644
--- a/mdk-stage1/log.c
+++ b/mdk-stage1/log.c
@@ -19,26 +19,29 @@
*
*/
-
+#include <stdlib.h>
+#include <unistd.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
#include "log.h"
static FILE * logfile = NULL;
-
-void do_log_message(const char * s, va_list args)
+void vlog_message_nobs(const char * s, va_list args)
{
- if (!logfile) return;
-
fprintf(logfile, "* ");
vfprintf(logfile, s, args);
+}
+
+void vlog_message(const char * s, va_list args)
+{
+ vlog_message_nobs(s, args);
fprintf(logfile, "\n");
-
fflush(logfile);
}
@@ -46,25 +49,34 @@ void do_log_message(const char * s, va_list args)
void log_message(const char * s, ...)
{
va_list args;
-
+
+ if (!logfile) {
+ fprintf(stderr, "Log is not open!\n");
+ return;
+ }
+
va_start(args, s);
- do_log_message(s, args);
+ vlog_message(s, args);
va_end(args);
return;
}
+void log_perror(char *msg)
+{
+ log_message("%s %s", strerror(errno), msg);
+}
+
void open_log(int testing)
{
- if (!testing)
- {
- logfile = fopen("/dev/tty3", "w");
- if (!logfile)
- logfile = fopen("/tmp/install.log", "a");
- }
- else
- logfile = fopen("debug.log", "w");
+ if (!testing) {
+ logfile = fopen("/dev/tty3", "w");
+ if (!logfile)
+ logfile = fopen("/tmp/install.log", "a");
+ }
+ else
+ logfile = fopen("debug.log", "w");
}
void close_log(void)
diff --git a/mdk-stage1/log.h b/mdk-stage1/log.h
index 61daa41be..9be73e83c 100644
--- a/mdk-stage1/log.h
+++ b/mdk-stage1/log.h
@@ -23,12 +23,12 @@
#ifndef _LOG_H_
#define _LOG_H_
-#include <stdio.h>
-
-extern FILE * log;
-extern int logfd;
+#include <stdarg.h>
void log_message(const char * s, ...);
+void vlog_message(const char * s, va_list args);
+void vlog_message_nobs(const char * s, va_list args);
+void log_perror(char *msg);
void open_log(int useLocal);
void close_log(void);
diff --git a/mdk-stage1/mar/Makefile b/mdk-stage1/mar/Makefile
index c35f50f02..e7f6977ce 100644
--- a/mdk-stage1/mar/Makefile
+++ b/mdk-stage1/mar/Makefile
@@ -18,7 +18,7 @@
#*****************************************************************************
-all: mar
+all: libmar.a mar
clean:
rm -f *.o mar
@@ -26,11 +26,18 @@ clean:
FLAGS = -Wall -Werror -Os -fomit-frame-pointer -c
-mar: mar-frontend.o mar-extract-only.o
- gcc -o mar mar-frontend.o mar-extract-only.o -lz
+mar: mar-frontend.o mar-extract-only-standalone.o
+ gcc -o mar mar-frontend.o mar-extract-only-standalone.o -lz
+
+libmar.a: mar-extract-only.o
+ ar -cru $@ $^
+ ranlib $@
mar-frontend.o: mar-frontend.c mar.h mar-extract-only.h
gcc $(FLAGS) mar-frontend.c
mar-extract-only.o: mar-extract-only.c mar-extract-only.h mar.h
gcc $(FLAGS) mar-extract-only.c
+
+mar-extract-only-standalone.o: mar-extract-only.c mar-extract-only.h mar.h
+ gcc $(FLAGS) -o $@ -D_STANDALONE_ mar-extract-only.c
diff --git a/mdk-stage1/mar/mar-extract-only.c b/mdk-stage1/mar/mar-extract-only.c
index 3627e84bb..b1079880e 100644
--- a/mdk-stage1/mar/mar-extract-only.c
+++ b/mdk-stage1/mar/mar-extract-only.c
@@ -26,15 +26,34 @@
#include "mar.h"
-
+#ifdef _STANDALONE_
void
gzerr(gzFile f) /* decrease code size */
{
fprintf(stderr, gzerror(f, &gz_errnum));
}
+void
+log_perror(char *msg)
+{
+ perror(msg);
+}
+void
+log_message(char *msg)
+{
+ fprintf(stderr, msg);
+}
+#else /* _STANDALONE_ */
+#include "../log.h"
+void
+gzerr(gzFile f) /* decrease code size */
+{
+ log_message(gzerror(f, &gz_errnum));
+}
+#endif /* _STANDALONE_ */
+
int
-calc_integrity(struct mar_stream *s)
+mar_calc_integrity(struct mar_stream *s)
{
char buf[4096];
int current_crc = 0;
@@ -51,20 +70,18 @@ calc_integrity(struct mar_stream *s)
gzerr(s->mar_gzfile);
return -1;
}
- DEBUG_MAR(printf("D: mar::calc_integrity more-bytes-to-handle-for-crc %d\n", bytes););
while (bytes > 0)
{
bytes--;
current_crc += buf[bytes];
}
}
- DEBUG_MAR(printf("D: mar::calc_integrity computed-crc %d\n", current_crc););
return current_crc;
}
int
-extract_file(struct mar_stream *s, char *filename, char *dest_dir)
+mar_extract_file(struct mar_stream *s, char *filename, char *dest_dir)
{
struct mar_element * elem = s->first_element;
while (elem)
@@ -80,13 +97,13 @@ extract_file(struct mar_stream *s, char *filename, char *dest_dir)
fd = creat(dest_file, 00660);
if (fd == -1)
{
- perror(dest_file);
+ log_perror(dest_file);
return -1;
}
buf = (char *) alloca(elem->file_length);
if (!buf)
{
- perror(dest_file);
+ log_perror(dest_file);
return -1;
}
if (gzseek(s->mar_gzfile, elem->data_offset, SEEK_SET) != elem->data_offset)
@@ -101,7 +118,7 @@ extract_file(struct mar_stream *s, char *filename, char *dest_dir)
}
if (write(fd, buf, elem->file_length) != elem->file_length)
{
- perror(dest_file);
+ log_perror(dest_file);
return -1;
}
close(fd); /* do not check return value for code size */
@@ -114,7 +131,7 @@ extract_file(struct mar_stream *s, char *filename, char *dest_dir)
int
-open_marfile(char *filename, struct mar_stream *s)
+mar_open_file(char *filename, struct mar_stream *s)
{
int end_filetable = 0;
struct mar_element * previous_element = NULL;
@@ -123,7 +140,7 @@ open_marfile(char *filename, struct mar_stream *s)
s->mar_gzfile = gzopen(filename, "rb");
if (!s->mar_gzfile)
{
- perror(filename);
+ log_perror(filename);
return -1;
}
@@ -134,11 +151,10 @@ open_marfile(char *filename, struct mar_stream *s)
return -1;
}
- DEBUG_MAR(printf("D: mar::open_marfile crc-in-marfile %d\n", s->crc32););
/* verify integrity */
- if (s->crc32 != calc_integrity(s))
+ if (s->crc32 != mar_calc_integrity(s))
{
- fprintf(stderr, "E: mar::open_marfile CRC check failed\n");
+ log_message("E: mar::open_marfile CRC check failed");
return -1;
}
else
@@ -167,7 +183,6 @@ open_marfile(char *filename, struct mar_stream *s)
{
struct mar_element * e = (struct mar_element *) malloc(sizeof(struct mar_element));
e->filename = strdup(buf);
- DEBUG_MAR(printf("D: mar::open_marfile processing-file %s\n", e->filename););
/* read file_length */
if (gzread(s->mar_gzfile, &(e->file_length), sizeof(int)) != sizeof(int))
{
diff --git a/mdk-stage1/mar/mar-extract-only.h b/mdk-stage1/mar/mar-extract-only.h
index f5db6c183..e8a88e96e 100644
--- a/mdk-stage1/mar/mar-extract-only.h
+++ b/mdk-stage1/mar/mar-extract-only.h
@@ -28,8 +28,8 @@
#include "mar.h"
-int open_marfile(char *filename, struct mar_stream *s);
-int extract_file(struct mar_stream *s, char *filename, char *dest_dir);
-int calc_integrity(struct mar_stream *s);
+int mar_open_file(char *filename, struct mar_stream *s);
+int mar_extract_file(struct mar_stream *s, char *filename, char *dest_dir);
+int mar_calc_integrity(struct mar_stream *s);
#endif
diff --git a/mdk-stage1/mar/mar-frontend.c b/mdk-stage1/mar/mar-frontend.c
index 55550d8a1..79a83a1c3 100644
--- a/mdk-stage1/mar/mar-frontend.c
+++ b/mdk-stage1/mar/mar-frontend.c
@@ -28,7 +28,7 @@
#include "mar-extract-only.h"
void
-list_files(struct mar_stream *s)
+mar_list_files(struct mar_stream *s)
{
struct mar_element * elem = s->first_element;
printf("%-20s%8s\n", "FILENAME", "LENGTH");
@@ -58,7 +58,7 @@ file_size(char *filename)
/* ``files'' is a NULL-terminated array of char* */
int
-create_marfile(char *dest_file, char **files)
+mar_create_file(char *dest_file, char **files)
{
int filenum = 0;
int current_offset_filetable;
@@ -179,27 +179,23 @@ main(int argc, char **argv)
if (strcmp(argv[1], "-l") == 0)
{
struct mar_stream s;
- if (open_marfile(argv[2], &s) != 0)
+ if (mar_open_file(argv[2], &s) != 0)
{
fprintf(stderr, "E: open-marfile-failed\n");
exit(-1);
}
- list_files(&s);
- if (s.crc32 == calc_integrity(&s))
- printf("CRC OK\n");
- else
- printf("CRC FAILED!\n");
+ mar_list_files(&s);
exit(0);
}
if ((strcmp(argv[1], "-x") == 0) && argc >= 4)
{
struct mar_stream s;
int i = 3;
- if (open_marfile(argv[2], &s) != 0)
+ if (mar_open_file(argv[2], &s) != 0)
exit(-1);
while (i < argc)
{
- int res = extract_file(&s, argv[i], "./");
+ int res = mar_extract_file(&s, argv[i], "./");
if (res == 1)
fprintf(stderr, "W: file-not-found-in-archive %s\n", argv[i]);
if (res == -1)
@@ -220,7 +216,7 @@ main(int argc, char **argv)
files[argc-3] = NULL;
{
int results;
- results = create_marfile(argv[2], files);
+ results = mar_create_file(argv[2], files);
if (results != 0)
fprintf(stderr, "E: create-marfile-failed\n");
exit(results);
diff --git a/mdk-stage1/mar/mar.h b/mdk-stage1/mar/mar.h
index bd731770b..e9633ab92 100644
--- a/mdk-stage1/mar/mar.h
+++ b/mdk-stage1/mar/mar.h
@@ -27,7 +27,6 @@
#ifndef MAR_H
#define MAR_H
-#if 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -36,8 +35,6 @@
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
-#endif
-//#include <minilibc.h>
#include <zlib.h>
diff --git a/mdk-stage1/minilibc.c b/mdk-stage1/minilibc.c
index e7c374105..c98d87e24 100644
--- a/mdk-stage1/minilibc.c
+++ b/mdk-stage1/minilibc.c
@@ -188,7 +188,7 @@ char * strchr(char * str, int ch)
return NULL;
}
-void print_int(int i)
+void print_int(int fd, int i)
{
char buf[10];
char * chptr = buf + 9;
@@ -207,12 +207,12 @@ void print_int(int i)
i = i / 10;
}
- write(1, chptr + 1, j);
+ write(fd, chptr + 1, j);
}
-void print_str(char * string)
+void print_str(int fd, char * string)
{
- write(1, string, strlen(string));
+ write(fd, string, strlen(string));
}
/* Minimum printf which handles only characters, %d's and %s's */
@@ -235,18 +235,18 @@ void printf(char * fmt, ...)
if (*chptr == '%')
{
*chptr++ = '\0';
- print_str(start);
+ print_str(1, start);
switch (*chptr++)
{
case 's':
strarg = va_arg(args, char *);
- print_str(strarg);
+ print_str(1, strarg);
break;
case 'd':
numarg = va_arg(args, int);
- print_int(numarg);
+ print_int(1, numarg);
break;
}
@@ -254,7 +254,7 @@ void printf(char * fmt, ...)
}
else
{
- print_str(start);
+ print_str(1, start);
start = NULL;
}
}
diff --git a/mdk-stage1/minilibc.h b/mdk-stage1/minilibc.h
index 824ac5d6e..e6743a854 100644
--- a/mdk-stage1/minilibc.h
+++ b/mdk-stage1/minilibc.h
@@ -136,7 +136,7 @@ int strncmp(const char * a, const char * b, int len);
char * strchr(char * str, int ch);
char * strncpy(char * dst, const char * src, int len);
-void print_str(char * string);
-void print_int(int i);
+void print_str(int fd, char * string);
+void print_int(int fd, int i);
/* Minimum printf which handles only characters, %d's and %s's */
void printf(char * fmt, ...);
diff --git a/mdk-stage1/modules.c b/mdk-stage1/modules.c
new file mode 100644
index 000000000..cdf50d9eb
--- /dev/null
+++ b/mdk-stage1/modules.c
@@ -0,0 +1,203 @@
+/*
+ * Guillaume Cottenceau (gc@mandrakesoft.com)
+ *
+ * Copyright 2000 MandrakeSoft
+ *
+ * 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.
+ *
+ */
+
+/*
+ * (1) calculate dependencies
+ * (2) unarchive relevant modules
+ * (3) insmod them
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include "insmod-busybox/insmod.h"
+#include "stage1.h"
+#include "log.h"
+#include "mar/mar-extract-only.h"
+#include "frontend.h"
+
+#include "modules.h"
+
+static struct module_deps_elem * modules_deps = NULL;
+
+
+/* unarchive and insmod given module
+ * WARNING: module must not contain the trailing ".o"
+ */
+int insmod_archived_file(char * mod_name)
+{
+ char * archive_name = "/modules/modules.mar";
+ char module_name[50];
+ char final_name[50] = "/tmp/";
+ static struct mar_stream s = { 0, NULL, NULL };
+ int i;
+
+ /* don't consume too much memory */
+ if (s.first_element == NULL) {
+ if (mar_open_file(archive_name, &s) != 0) {
+ log_message("open marfile failed");
+ return -1;
+ }
+ }
+
+ strncpy(module_name, mod_name, sizeof(module_name));
+ strncat(module_name, ".o", sizeof(module_name));
+ i = mar_extract_file(&s, module_name, "/tmp/");
+ if (i == 1) {
+ log_message("file-not-found-in-archive %s", module_name);
+ return -1;
+ }
+ if (i != 0)
+ return -1;
+
+ strncat(final_name, mod_name, sizeof(final_name));
+ strncat(final_name, ".o", sizeof(final_name));
+
+ return insmod_call(final_name);
+}
+
+
+
+int load_modules_dependencies(void)
+{
+ char * deps_file = "/modules/modules.dep";
+ char * buf, * ptr, * start, * end;
+ struct stat s;
+ int fd, line, i;
+
+ log_message("loading modules dependencies");
+
+ if (IS_TESTING)
+ return 0;
+
+ fd = open(deps_file, O_RDONLY);
+ if (fd == -1) {
+ log_perror(deps_file);
+ return -1;
+ }
+
+ fstat(fd, &s);
+ buf = alloca(s.st_size + 1);
+ if (read(fd, buf, s.st_size) != s.st_size) {
+ log_perror(deps_file);
+ return -1;
+ }
+ buf[s.st_size] = '\0';
+ close(fd);
+
+ ptr = buf;
+ line = 0;
+ while (ptr) {
+ line++;
+ ptr = strchr(ptr + 1, '\n');
+ }
+
+ modules_deps = malloc(sizeof(*modules_deps) * (line+1));
+
+ start = buf;
+ line = 0;
+ while (start < (buf+s.st_size) && *start) {
+ char * tmp_deps[50];
+
+ end = strchr(start, '\n');
+ *end = '\0';
+
+ ptr = strchr(start, ':');
+ if (!ptr) {
+ start = end + 1;
+ continue;
+ }
+ *ptr = '\0';
+ ptr++;
+
+ while (*ptr && (*ptr == ' ')) ptr++;
+ if (!*ptr) {
+ start = end + 1;
+ continue;
+ }
+
+ /* sort of a good line */
+ modules_deps[line].name = strdup(start);
+
+ start = ptr;
+ i = 0;
+ while (start && *start) {
+ ptr = strchr(start, ' ');
+ if (ptr) *ptr = '\0';
+ tmp_deps[i] = strdup(start);
+ if (ptr)
+ start = ptr + 1;
+ else
+ start = NULL;
+ i++;
+ while (start && *start && *start == ' ')
+ start++;
+ }
+ tmp_deps[i] = NULL;
+
+ modules_deps[line].deps = (char **) malloc(sizeof(char *) * (i+1));
+ memcpy(modules_deps[line].deps, tmp_deps, sizeof(char *) * (i+1));
+
+ line++;
+ start = end + 1;
+ }
+ modules_deps[line].name = NULL;
+
+ return 0;
+}
+
+
+int insmod_with_deps(char * mod_name)
+{
+ struct module_deps_elem * dep;
+
+ dep = modules_deps;
+ while (dep && dep->name && strcmp(dep->name, mod_name)) dep++;
+
+ if (dep && dep->name && dep->deps) {
+ char ** one_dep;
+ one_dep = dep->deps;
+ while (*one_dep) {
+ /* here, we can fail but we don't care, if the error is
+ * important, the desired module will fail also */
+ insmod_with_deps(*one_dep);
+ one_dep++;
+ }
+ }
+
+ log_message("needs %s", mod_name);
+ return insmod_archived_file(mod_name);
+}
+
+
+int my_insmod(char * mod_name)
+{
+ int i;
+ log_message("have to insmod %s", mod_name);
+
+ if (IS_TESTING)
+ return 0;
+
+ i = insmod_with_deps(mod_name);
+ if (i == 0)
+ log_message("\tsucceeded %s.", mod_name);
+ return i;
+
+}
+
+
+enum return_type ask_scsi_insmod(void)
+{
+ error_message("Try to load a SCSI module");
+ return RETURN_OK;
+}
diff --git a/mdk-stage1/modules.h b/mdk-stage1/modules.h
new file mode 100644
index 000000000..cf7eadebe
--- /dev/null
+++ b/mdk-stage1/modules.h
@@ -0,0 +1,33 @@
+/*
+ * Guillaume Cottenceau (gc@mandrakesoft.com)
+ *
+ * Copyright 2000 MandrakeSoft
+ *
+ * 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.
+ *
+ */
+
+#ifndef _MODULES_H_
+#define _MODULES_H_
+
+#include "stage1.h"
+
+int load_modules_dependencies(void);
+int my_insmod(char * mod_name);
+
+enum return_type ask_scsi_insmod(void);
+
+
+struct module_deps_elem {
+ char * name;
+ char ** deps;
+};
+
+
+
+#endif
diff --git a/mdk-stage1/network.c b/mdk-stage1/network.c
new file mode 100644
index 000000000..e6d0c6c4e
--- /dev/null
+++ b/mdk-stage1/network.c
@@ -0,0 +1,46 @@
+/*
+ * Guillaume Cottenceau (gc@mandrakesoft.com)
+ *
+ * Copyright 2000 MandrakeSoft
+ *
+ * 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 <stdlib.h>
+#include <unistd.h>
+#include "stage1.h"
+#include "frontend.h"
+#include "modules.h"
+#include "probing.h"
+#include "log.h"
+
+#include "network.h"
+
+
+enum return_type nfs_prepare(void)
+{
+ return RETURN_ERROR;
+}
+
+enum return_type ftp_prepare(void)
+{
+ return RETURN_ERROR;
+}
+
+enum return_type http_prepare(void)
+{
+ return RETURN_ERROR;
+}
diff --git a/mdk-stage1/network.h b/mdk-stage1/network.h
new file mode 100644
index 000000000..bc7e19104
--- /dev/null
+++ b/mdk-stage1/network.h
@@ -0,0 +1,30 @@
+/*
+ * Guillaume Cottenceau (gc@mandrakesoft.com)
+ *
+ * Copyright 2000 MandrakeSoft
+ *
+ * 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
+ *
+ */
+
+#ifndef _NETWORK_H_
+#define _NETWORK_H_
+
+enum return_type nfs_prepare(void);
+enum return_type ftp_prepare(void);
+enum return_type http_prepare(void);
+
+
+#endif
diff --git a/mdk-stage1/newt-frontend.c b/mdk-stage1/newt-frontend.c
new file mode 100644
index 000000000..2c7e5434b
--- /dev/null
+++ b/mdk-stage1/newt-frontend.c
@@ -0,0 +1,149 @@
+/*
+ * Guillaume Cottenceau (gc@mandrakesoft.com)
+ *
+ * Copyright 2000 MandrakeSoft
+ *
+ * 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
+ *
+ */
+
+
+/*
+ * Each different frontend must implement all functions defined in frontend.h
+ */
+
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include "stage1.h"
+#include "log.h"
+#include "newt.h"
+
+#include "frontend.h"
+
+
+void init_frontend(void)
+{
+ newtInit();
+ newtCls();
+
+ newtDrawRootText(0, 0, "Welcome to Linux-Mandrake (" VERSION ") " __DATE__ " " __TIME__);
+
+ newtPushHelpLine(" <Tab>/<Alt-Tab> between elements, <Space>/<Enter> selects");
+}
+
+
+void finish_frontend(void)
+{
+ newtFinished();
+}
+
+
+void error_message(char *msg)
+{
+ newtWinMessage("Error", "Ok", msg);
+}
+
+void wait_message(char *msg, ...)
+{
+ int width = 36;
+ int height = 3;
+ char * title = "Please wait...";
+ newtComponent t, f;
+ char * buf = NULL;
+ int size = 0;
+ int i = 0;
+ va_list args;
+
+ va_start(args, msg);
+
+ do {
+ size += 1000;
+ if (buf) free(buf);
+ buf = malloc(size);
+ i = vsnprintf(buf, size, msg, args);
+ } while (i == size);
+
+ va_end(args);
+
+ newtCenteredWindow(width, height, title);
+
+ t = newtTextbox(1, 1, width - 2, height - 2, NEWT_TEXTBOX_WRAP);
+ newtTextboxSetText(t, buf);
+ f = newtForm(NULL, NULL, 0);
+
+ free(buf);
+
+ newtFormAddComponent(f, t);
+
+ newtDrawForm(f);
+ newtRefresh();
+ newtFormDestroy(f);
+}
+
+void remove_wait_message(void)
+{
+ newtPopWindow();
+}
+
+
+enum return_type ask_from_list_comments(char *msg, char ** elems, char ** elems_comments, char ** choice)
+{
+ char * items[50];
+ int answer = 0, rc;
+ char ** sav_elems = elems;
+ int i;
+
+ i = 0;
+ while (elems && *elems) {
+ items[i] = malloc(sizeof(char) * (strlen(*elems) + strlen(*elems_comments) + 3));
+ strcpy(items[i], *elems);
+ strcat(items[i], " (");
+ strcat(items[i], *elems_comments);
+ strcat(items[i], ")");
+ i++;
+ elems++;
+ elems_comments++;
+ }
+ items[i] = NULL;
+
+ rc = newtWinMenu("Please choose...", msg, 52, 5, 5, 7, items, &answer, "Ok", "Cancel", NULL);
+
+ if (rc == 2)
+ return RETURN_BACK;
+
+ *choice = strdup(sav_elems[answer]);
+
+ return RETURN_OK;
+}
+
+
+enum return_type ask_from_list(char *msg, char ** elems, char ** choice)
+{
+ int answer = 0, rc;
+
+ rc = newtWinMenu("Please choose...", msg, 52, 5, 5, 7, elems, &answer, "Ok", "Cancel", NULL);
+
+ if (rc == 2)
+ return RETURN_BACK;
+
+ *choice = strdup(elems[answer]);
+
+ return RETURN_OK;
+}
+
diff --git a/mdk-stage1/probing.c b/mdk-stage1/probing.c
new file mode 100644
index 000000000..29ffdcd7c
--- /dev/null
+++ b/mdk-stage1/probing.c
@@ -0,0 +1,301 @@
+/*
+ * Guillaume Cottenceau (gc@mandrakesoft.com)
+ *
+ * Copyright 2000 MandrakeSoft
+ *
+ * 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
+ *
+ */
+
+
+/*
+ * This contains stuff related to probing:
+ * (1) PCI devices
+ * (2) IDE media
+ * (3) SCSI media
+ */
+
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "log.h"
+#include "frontend.h"
+#include "modules.h"
+
+#include "probing.h"
+
+
+static void pci_probing(enum driver_type type)
+{
+ if (IS_EXPERT) {
+ error_message("You should be asked if you have some SCSI.");
+ } else {
+ wait_message("Installing SCSI module...");
+ my_insmod("advansys");
+ remove_wait_message();
+ }
+}
+
+
+static struct media_info * medias = NULL;
+
+static void find_media(void)
+{
+ char b[50];
+ char buf[500];
+ struct media_info tmp[50];
+ int count;
+ int fd;
+
+ if (medias)
+ return;
+
+ /* ----------------------------------------------- */
+ log_message("looking for ide media");
+
+ count = 0;
+ strcpy(b, "/proc/ide/hda");
+ for (; b[12] <= 'm'; b[12]++) {
+ int i;
+
+ /* first, test if file exists (will tell if attached medium exists) */
+ b[13] = '\0';
+ if (access(b, R_OK))
+ continue;
+
+ tmp[count].name = strdup("hda");
+ tmp[count].name[2] = b[12];
+
+ /* media type */
+ strcpy(b + 13, "/media");
+ fd = open(b, O_RDONLY);
+ if (fd == -1) {
+ log_message("failed to open %s for reading", b);
+ continue;
+ }
+
+ i = read(fd, buf, sizeof(buf));
+ if (i == -1) {
+ log_message("failed to read %s", b);
+ continue;
+ }
+ buf[i] = '\0';
+ close(fd);
+
+ if (!strncmp(buf, "disk", strlen("disk")))
+ tmp[count].type = DISK;
+ else if (!strncmp(buf, "cdrom", strlen("cdrom")))
+ tmp[count].type = CDROM;
+ else if (!strncmp(buf, "tape", strlen("tape")))
+ tmp[count].type = TAPE;
+ else if (!strncmp(buf, "floppy", strlen("floppy")))
+ tmp[count].type = FLOPPY;
+ else
+ tmp[count].type = UNKNOWN_MEDIA;
+
+ /* media model */
+ strcpy(b + 13, "/model");
+ fd = open(b, O_RDONLY);
+ if (fd == -1) {
+ log_message("failed to open %s for reading", b);
+ continue;
+ }
+
+ i = read(fd, buf, sizeof(buf));
+ if (i <= 0) {
+ log_message("failed to read %s", b);
+ tmp[count].model = strdup("(none)");
+ }
+ else {
+ buf[i-1] = '\0'; /* eat the \n */
+ tmp[count].model = strdup(buf);
+ }
+
+ tmp[count].bus = IDE;
+ count++;
+ }
+
+ log_message("found %d IDE media", count);
+
+
+ /* ----------------------------------------------- */
+ log_message("looking for scsi media");
+
+ pci_probing(SCSI_ADAPTERS);
+
+ fd = open("/proc/scsi/scsi", O_RDONLY);
+ if (fd != -1) {
+ enum { SCSI_TOP, SCSI_HOST, SCSI_VENDOR, SCSI_TYPE } state = SCSI_TOP;
+ char * start, * chptr, * next, * end;
+
+ int i = read(fd, &buf, sizeof(buf));
+ if (i < 1) {
+ close(fd);
+ goto end_scsi;
+ }
+ close(fd);
+ buf[i] = '\0';
+
+ if (!strncmp(buf, "Attached devices: none", strlen("Attached devices: none")))
+ goto end_scsi;
+
+ start = buf;
+ while (*start) {
+ char tmp_model[50];
+ char tmp_name[10];
+ char scsi_disk_count = 'a';
+ char scsi_cdrom_count = '0';
+ char scsi_tape_count = '0';
+
+ chptr = start;
+ while (*chptr != '\n') chptr++;
+ *chptr = '\0';
+ next = chptr + 1;
+
+ switch (state) {
+ case SCSI_TOP:
+ if (strncmp(start, "Attached devices: ", strlen("Attached devices: ")))
+ goto end_scsi;
+ state = SCSI_HOST;
+ break;
+
+ case SCSI_HOST:
+ if (strncmp(start, "Host: ", strlen("Host: ")))
+ goto end_scsi;
+ state = SCSI_VENDOR;
+ break;
+
+ case SCSI_VENDOR:
+ if (strncmp(start, " Vendor: ", strlen(" Vendor: ")))
+ goto end_scsi;
+
+ /* (1) Grab Vendor info */
+ start += 10;
+ end = chptr = strstr(start, "Model:");
+ if (!chptr)
+ goto end_scsi;
+
+ chptr--;
+ while (*chptr == ' ')
+ chptr--;
+ if (*chptr == ':') {
+ chptr++;
+ *(chptr + 1) = '\0';
+ strcpy(tmp_model,"(unknown)");
+ } else {
+ *(chptr + 1) = '\0';
+ strcpy(tmp_model, start);
+ }
+
+ /* (2) Grab Model info */
+ start = end;
+ start += 7;
+
+ chptr = strstr(start, "Rev:");
+ if (!chptr)
+ goto end_scsi;
+
+ chptr--;
+ while (*chptr == ' ') chptr--;
+ *(chptr + 1) = '\0';
+
+ strcat(tmp_model, ", ");
+ strcat(tmp_model, start);
+
+ tmp[count].model = strdup(tmp_model);
+
+ state = SCSI_TYPE;
+
+ break;
+
+ case SCSI_TYPE:
+ if (strncmp(" Type:", start, 7))
+ goto end_scsi;
+ *tmp_name = '\0';
+
+ if (strstr(start, "Direct-Access")) {
+ sprintf(tmp_name, "sd%c", scsi_disk_count++);
+ tmp[count].type = DISK;
+ } else if (strstr(start, "Sequential-Access")) {
+ sprintf(tmp_name, "st%c", scsi_tape_count++);
+ tmp[count].type = TAPE;
+ } else if (strstr(start, "CD-ROM")) {
+ sprintf(tmp_name, "scd%c", scsi_cdrom_count++);
+ tmp[count].type = CDROM;
+ }
+
+ if (*tmp_name) {
+ tmp[count].name = strdup(tmp_name);
+ tmp[count].bus = SCSI;
+ count++;
+ }
+
+ state = SCSI_HOST;
+ }
+
+ start = next;
+ }
+
+ end_scsi:
+ }
+
+ log_message("adding SCSI totals %d media", count);
+
+
+ /* ----------------------------------------------- */
+ tmp[count].name = NULL;
+ count++;
+
+ medias = (struct media_info *) malloc(sizeof(struct media_info) * count);
+ memcpy(medias, tmp, sizeof(struct media_info) * count);
+}
+
+
+/* Finds by media */
+char ** get_medias(enum media_type media, enum media_query_type qtype)
+{
+ struct media_info * m;
+ char * tmp[50];
+ char ** answer;
+ int count;
+
+ find_media();
+
+ m = medias;
+
+ count = 0;
+ while (m && m->name) {
+ if (m->type == media) {
+ if (qtype == QUERY_NAME)
+ tmp[count] = m->name;
+ else
+ tmp[count] = m->model;
+ count++;
+ }
+ m++;
+ }
+ tmp[count] = NULL;
+ count++;
+
+ answer = (char **) malloc(sizeof(char *) * count);
+ memcpy(answer, tmp, sizeof(char *) * count);
+
+ return answer;
+}
diff --git a/mdk-stage1/probing.h b/mdk-stage1/probing.h
new file mode 100644
index 000000000..ee221f01b
--- /dev/null
+++ b/mdk-stage1/probing.h
@@ -0,0 +1,44 @@
+/*
+ * Guillaume Cottenceau (gc@mandrakesoft.com)
+ *
+ * Copyright 2000 MandrakeSoft
+ *
+ * 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
+ *
+ */
+
+#ifndef _PROBING_H_
+#define _PROBING_H_
+
+enum media_type { DISK, FLOPPY, CDROM, TAPE, UNKNOWN_MEDIA };
+
+enum bus_type { IDE, SCSI };
+
+struct media_info {
+ char * name;
+ char * model;
+ enum media_type type;
+ enum bus_type bus;
+};
+
+enum media_query_type { QUERY_NAME, QUERY_MODEL };
+
+enum driver_type { SCSI_ADAPTERS, NETWORK_DEVICES };
+
+
+char ** get_medias(enum media_type media, enum media_query_type qtype);
+
+
+#endif
diff --git a/mdk-stage1/stage1.c b/mdk-stage1/stage1.c
index 16b848a9c..16d896f3b 100644
--- a/mdk-stage1/stage1.c
+++ b/mdk-stage1/stage1.c
@@ -19,6 +19,7 @@
*
*/
+#include <sys/mount.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
@@ -29,11 +30,24 @@
#include <stdio.h>
#include <string.h>
#include <errno.h>
+#include <ctype.h>
+
+#include "stage1.h"
#include "log.h"
+#include "probing.h"
+#include "frontend.h"
+#include "modules.h"
+
+#include "cdrom.h"
+#include "network.h"
+#include "disk.h"
+
+/* globals */
-int testing;
+int stage1_mode = 0;
+struct cmdline_elem params[500];
void fatal_error(char *msg)
@@ -42,26 +56,63 @@ void fatal_error(char *msg)
while (1);
}
+
void process_cmdline(void)
{
- char buf[512];
- int fd;
- int size;
-
-
- log_message("opening /proc/cmdline... ");
-
- if ((fd = open("/proc/cmdline", O_RDONLY, 0)) < 0) fatal_error("could not open /proc/cmdline");
+ char buf[512];
+ int fd, size, i, p;
+
+ log_message("opening /proc/cmdline... ");
+
+ 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);
+
+ log_message("\t%s", buf);
+
+ i = 0; p = 0;
+ while (buf[i] != 0) {
+ char *name, *value = NULL;
+ int j = i;
+ while (buf[i] != ' ' && buf[i] != '=' && buf[i] != 0)
+ i++;
+ if (i == j) {
+ i++;
+ continue;
+ }
+ name = (char *) malloc(i-j + 1);
+ memcpy(name, &buf[j], i-j);
+ name[i-j] = 0;
+
+ if (buf[i] == '=') {
+ int k = i+1;
+ i++;
+ while (buf[i] != ' ' && buf[i] != 0)
+ i++;
+ value = (char *) malloc(i-k + 1);
+ memcpy(value, &buf[k], i-k);
+ value[i-k] = 0;
+ }
- size = read(fd, buf, sizeof(buf) - 1);
- buf[size] = '\0';
- close(fd);
+ params[p].name = name;
+ params[p].value = value;
+ p++;
+ i++;
+ if (!strcmp(name, "expert")) stage1_mode |= MODE_EXPERT;
+ if (!strcmp(name, "text")) stage1_mode |= MODE_TEXT;
+ if (!strcmp(name, "rescue")) stage1_mode |= MODE_RESCUE;
+ if (!strcmp(name, "pcmcia")) stage1_mode |= MODE_PCMCIA;
+ if (!strcmp(name, "cdrom")) stage1_mode |= MODE_CDROM;
+ }
+ params[p].name = NULL;
- log_message("\t%s", buf);
+ log_message("\tgot %d args", p);
}
-#ifdef SPAWN_SHELL
/* spawns a shell on console #2 */
void spawn_shell(void)
{
@@ -69,23 +120,20 @@ void spawn_shell(void)
int fd;
char * shell_name = "/sbin/sash";
- if (!testing)
- {
+ log_message("spawning a shell..");
+
+ if (!IS_TESTING) {
fd = open("/dev/tty2", O_RDWR);
- if (fd < 0)
- {
+ if (fd == -1) {
log_message("cannot open /dev/tty2 -- no shell will be provided");
return;
}
- else
- if (access(shell_name, X_OK))
- {
- log_message("cannot open shell - /usr/bin/sh doesn't exist");
- return;
- }
+ else if (access(shell_name, X_OK)) {
+ log_message("cannot open shell - %s doesn't exist", shell_name);
+ return;
+ }
- if (!(pid = fork()))
- {
+ if (!(pid = fork())) {
dup2(fd, 0);
dup2(fd, 1);
dup2(fd, 2);
@@ -94,36 +142,92 @@ void spawn_shell(void)
setsid();
if (ioctl(0, TIOCSCTTY, NULL))
perror("could not set new controlling tty");
-
+
execl(shell_name, shell_name, NULL);
log_message("execl of %s failed: %s", shell_name, strerror(errno));
}
close(fd);
}
- else
- log_message("I should be spawning a shell");
}
+
+enum return_type method_select_and_prepare(void)
+{
+ char * disk_install = "Hard disk";
+ char * cdrom_install = "CDROM drive";
+ char * network_nfs_install = "NFS server";
+ char * network_ftp_install = "FTP server";
+ char * network_http_install = "HTTP server";
+ enum return_type results;
+ char * choice;
+ char * means[10];
+ int i;
+
+ i = 0;
+#ifndef DISABLE_NETWORK
+ means[i] = network_nfs_install; i++;
+ means[i] = network_ftp_install; i++;
+ means[i] = network_http_install; i++;
+#endif
+#ifndef DISABLE_DISK
+ means[i] = disk_install; i++;
+#endif
+#ifndef DISABLE_CDROM
+ means[i] = cdrom_install; i++;
#endif
+ means[i] = NULL;
+ results = ask_from_list("Please choose the mean of installation.", means, &choice);
+
+ if (results != RETURN_OK)
+ return results;
+
+ if (!strcmp(choice, cdrom_install))
+ return cdrom_prepare();
+ else if (!strcmp(choice, disk_install))
+ return disk_prepare();
+ else if (!strcmp(choice, network_nfs_install))
+ return nfs_prepare();
+ else if (!strcmp(choice, network_ftp_install))
+ return ftp_prepare();
+ else if (!strcmp(choice, network_http_install))
+ return http_prepare();
+
+ return RETURN_ERROR;
+}
-int
-main(int argc, char **argv)
+
+int main(int argc, char **argv)
{
- /* getpid() != 1 should work, by linuxrc tends to get a larger pid */
- testing = (getpid() > 50);
+ enum return_type ret;
+
+ if (getpid() > 50)
+ stage1_mode |= MODE_TESTING;
- open_log(testing);
+ open_log(IS_TESTING);
log_message("welcome to the Linux-Mandrake install (stage1, version " VERSION " built " __DATE__ " " __TIME__")");
process_cmdline();
spawn_shell();
+ if (load_modules_dependencies())
+ fatal_error("could not open and parse modules dependencies");
-
- printf("Temporary end of stage1 binary -- entering an infinite loop\n");
- log_message("Temporary end of stage1 binary -- entering an infinite loop");
- while(1);
+ init_frontend();
+
+ if (IS_CDROM)
+ ret = cdrom_prepare();
+ else
+ ret = method_select_and_prepare();
+
+ while (ret == RETURN_BACK)
+ ret = method_select_and_prepare();
+
+ finish_frontend();
+ close_log();
+
+ if (ret == RETURN_ERROR)
+ fatal_error("could not select an installation method");
return 0;
}
diff --git a/mdk-stage1/stage1.h b/mdk-stage1/stage1.h
new file mode 100644
index 000000000..108fe14aa
--- /dev/null
+++ b/mdk-stage1/stage1.h
@@ -0,0 +1,61 @@
+/*
+ * Guillaume Cottenceau (gc@mandrakesoft.com)
+ *
+ * Copyright 2000 MandrakeSoft
+ *
+ * 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
+ *
+ */
+
+#ifndef _STAGE1_H_
+#define _STAGE1_H_
+
+
+/* Some global stuff */
+
+struct cmdline_elem
+{
+ char * name;
+ char * value;
+};
+
+extern struct cmdline_elem params[500];
+
+
+enum return_type { RETURN_OK, RETURN_BACK, RETURN_ERROR };
+
+extern int stage1_mode;
+
+#define MODE_TESTING (1 << 0)
+#define MODE_EXPERT (1 << 1)
+#define MODE_TEXT (1 << 2)
+#define MODE_RESCUE (1 << 3)
+#define MODE_KICKSTART (1 << 4)
+#define MODE_PCMCIA (1 << 5)
+#define MODE_CDROM (1 << 6)
+
+#define IS_TESTING ((stage1_mode) & MODE_TESTING)
+#define IS_EXPERT ((stage1_mode) & MODE_EXPERT)
+#define IS_TEXT ((stage1_mode) & MODE_TEXT)
+#define IS_RESCUE ((stage1_mode) & MODE_RESCUE)
+#define IS_KICKSTART ((stage1_mode) & MODE_KICKSTART)
+#define IS_PCMCIA ((stage1_mode) & MODE_PCMCIA)
+#define IS_CDROM ((stage1_mode) & MODE_CDROM)
+
+
+void fatal_error(char *msg);
+
+
+#endif
diff --git a/mdk-stage1/tools.c b/mdk-stage1/tools.c
new file mode 100644
index 000000000..e07fcd347
--- /dev/null
+++ b/mdk-stage1/tools.c
@@ -0,0 +1,71 @@
+/*
+ * Guillaume Cottenceau (gc@mandrakesoft.com)
+ *
+ * Copyright 2000 MandrakeSoft
+ *
+ * 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 <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <ctype.h>
+#include "stage1.h"
+#include "log.h"
+
+#include "tools.h"
+
+int total_memory(void)
+{
+ int fd;
+ int i;
+ char buf[4096];
+ char * memtotal_tag = "MemTotal:";
+ int memtotal = 0;
+
+ fd = open("/proc/meminfo", O_RDONLY);
+ if (fd == -1)
+ fatal_error("could not open /proc/meminfo");
+
+ i = read(fd, buf, sizeof(buf));
+ if (i < 0)
+ fatal_error("could not read /proc/meminfo");
+
+ close(fd);
+ buf[i] = 0;
+
+ i = 0;
+ while (buf[i] != 0 && strncmp(&buf[i], memtotal_tag, strlen(memtotal_tag)))
+ i++;
+
+ while (buf[i] != 0 && buf[i] != '\n' && !isdigit(buf[i]))
+ i++;
+
+ if (buf[i] == 0 || buf[i] == '\n')
+ fatal_error("could not read MemTotal");
+
+ while (buf[i] != 0 && isdigit(buf[i])) {
+ memtotal = (memtotal * 10) + (buf[i] - '0');
+ i++;
+ }
+
+ log_message("%s %d kB", memtotal_tag, memtotal);
+
+ return memtotal;
+}
diff --git a/mdk-stage1/tools.h b/mdk-stage1/tools.h
new file mode 100644
index 000000000..21d09ec86
--- /dev/null
+++ b/mdk-stage1/tools.h
@@ -0,0 +1,30 @@
+/*
+ * Guillaume Cottenceau (gc@mandrakesoft.com)
+ *
+ * Copyright 2000 MandrakeSoft
+ *
+ * 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
+ *
+ */
+
+#ifndef _TOOLS_H_
+#define _TOOLS_H_
+
+
+/* returns value of MemTotal tag from /proc/meminfo */
+int total_memory(void);
+
+
+#endif