summaryrefslogtreecommitdiffstats
path: root/mdk-stage1/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'mdk-stage1/init.c')
-rw-r--r--mdk-stage1/init.c340
1 files changed, 190 insertions, 150 deletions
diff --git a/mdk-stage1/init.c b/mdk-stage1/init.c
index f5a46010b..7c48f64ec 100644
--- a/mdk-stage1/init.c
+++ b/mdk-stage1/init.c
@@ -1,7 +1,7 @@
/*
- * Guillaume Cottenceau (gc@mandrakesoft.com)
+ * Guillaume Cottenceau (gc)
*
- * Copyright 2000 Mandrakesoft
+ * Copyright 2000 Mandriva
*
* This software may be freely redistributed under the terms of the GNU
* public license.
@@ -19,29 +19,54 @@
*
*/
-#ifndef INIT_HEADERS
-#include "init-libc-headers.h"
-#else
-#include INIT_HEADERS
-#endif
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/mount.h>
+#include <linux/un.h>
+#include <errno.h>
+#include <signal.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+#include <linux/unistd.h>
+#include <sys/select.h>
+#include <sys/ioctl.h>
+#include <linux/reboot.h>
+
+#include <sys/syscall.h>
+#define syslog(...) syscall(__NR_syslog, __VA_ARGS__)
+
+static unsigned int reboot_magic = LINUX_REBOOT_CMD_RESTART;
+
+static inline long reboot(unsigned int command)
+{
+ return (long) syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, command, 0);
+}
#include "config-stage1.h"
#include <linux/cdrom.h>
-#if defined(__powerpc__)
-#define TIOCSCTTY 0x540E
-#endif
+
+#define BINARY_STAGE2 "/usr/bin/runinstall2"
+
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"
-#if defined(__x86_64__) || defined(__ppc64__)
- ":/lib64:/usr/lib64:/usr/X11R6/lib64:/mnt/lib64:/mnt/usr/lib64:/mnt/usr/X11R6/lib64"
+ "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",
+ "LC_CTYPE=UTF-8",
NULL
};
@@ -81,20 +106,20 @@ void print_int_init(int fd, int i)
char buf[10];
char * chptr = buf + 9;
int j = 0;
-
+
if (i < 0)
{
write(1, "-", 1);
i = -1 * i;
}
-
+
while (i)
{
*chptr-- = '0' + (i % 10);
j++;
i = i / 10;
}
-
+
write(fd, chptr + 1, j);
}
@@ -112,7 +137,7 @@ void doklog()
fd_set readset, unixs;
int in, out, i;
int log;
- int s;
+ socklen_t s;
int sock = -1;
struct sockaddr_un sockaddr;
char buf[1024];
@@ -125,7 +150,6 @@ void doklog()
return;
}
- mkdir("/tmp", 0755);
if ((log = open("/tmp/syslog", O_WRONLY | O_CREAT | O_APPEND, 0644)) < 0) {
print_error("error opening /tmp/syslog");
sleep(5);
@@ -141,7 +165,7 @@ void doklog()
close(1);
close(2);
}
-
+
out = open("/dev/tty4", O_WRONLY, 0);
if (out < 0)
print_warning("couldn't open tty for syslog -- still using /tmp/syslog\n");
@@ -183,7 +207,7 @@ void doklog()
if (sock >= 0)
FD_SET(sock, &readset);
FD_SET(in, &readset);
-
+
i = select(20, &readset, NULL, NULL, NULL);
if (i <= 0)
continue;
@@ -198,25 +222,6 @@ void doklog()
}
}
- /* 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)) {
- i = read(readfd, buf, sizeof(buf));
- if (i > 0) {
- /* grep out the output of RPM telling that it installed/removed some packages */
- if (!strstr(buf, "mdk installed") && !strstr(buf, "mdk removed")) {
- if (out >= 0)
- write(out, buf, i);
- write(log, buf, i);
- }
- } else if (i == 0) {
- /* socket closed */
- close(readfd);
- FD_CLR(readfd, &unixs);
- }
- }
- }
-
/* the socket has moved, new stuff to do */
if (sock >= 0 && FD_ISSET(sock, &readset)) {
s = sizeof(sockaddr);
@@ -275,7 +280,9 @@ char* strcat(register char* s,register const char* t)
char *dest=s;
s+=strlen(s);
for (;;) {
- if (!(*s = *t)) break; ++s; ++t;
+ if (!(*s = *t))
+ break;
+ ++s; ++t;
}
return dest;
}
@@ -289,10 +296,9 @@ void unmount_filesystems(void)
struct filesystem fs[500];
int numfs = 0;
int i, nb;
- int disallow_eject = 0;
printf("unmounting filesystems...\n");
-
+
fd = open("/proc/mounts", O_RDONLY, 0);
if (fd < 1) {
print_error("failed to open /proc/mounts");
@@ -319,8 +325,6 @@ void unmount_filesystems(void)
*p++ = '\0';
while (*p != '\n') p++;
p++;
- if (!strcmp(fs[numfs].fs, "nfs"))
- disallow_eject = 1;
if (strcmp(fs[numfs].name, "/")
&& !strstr(fs[numfs].dev, "ram")
&& strcmp(fs[numfs].name, "/dev")
@@ -344,77 +348,20 @@ void unmount_filesystems(void)
}
}
} while (nb);
-
+
for (i = nb = 0; i < numfs; i++)
if (fs[i].mounted) {
-#ifdef MANDRAKE_MOVE
- if (!strcmp(fs[i].name, "/cdrom") || !strcmp(fs[i].name, "/image_always"))
- continue;
-#endif
printf("\tumount failed: %s\n", fs[i].name);
if (strcmp(fs[i].fs, "ext3") == 0) nb++; /* don't count not-ext3 umount failed */
}
-#ifdef MANDRAKE_MOVE
- if (!disallow_eject) {
- fd = open("/proc/fs/supermount/subfs", O_RDONLY, 0);
- if (fd > 0) {
- char devices[100][100];
- int i = 0;
- char * ptr1, * ptr2;
- size = read(fd, buf, sizeof(buf) - 1);
- buf[size] = '\0';
- close(fd);
- ptr1 = buf;
- ptr2 = buf;
- while (*ptr1 && *ptr2) {
- char * ptrf = ptr1;
- while (*ptr2 && *ptr2 != '\n')
- ptr2++;
- while (*ptrf && *ptrf != ' ')
- ptrf++;
- if (*ptrf)
- *ptrf = '\0';
- strcpy(devices[i], ptr1);
- i++;
- if (*ptr2)
- ptr2++;
- ptr1 = ptr2;
- }
- while (i >= 1) {
- i--;
- strcat(devices[i], " release force");
- fd = open("/proc/fs/supermount/subfs", O_WRONLY, 0);
- write(fd, devices[i], strlen(devices[i]));
- close(fd);
- }
- }
- fd = open("/dev/cdrom", O_RDONLY|O_NONBLOCK, 0);
- if (fd > 0) {
- ioctl(fd, CDROM_LOCKDOOR, 0);
- close(fd);
- }
- fd = open("/dev/cdrom", O_RDONLY|O_NONBLOCK, 0);
- if (fd > 0) {
- ioctl(fd, CDROMEJECT, 0);
- close(fd);
- }
- }
-#endif
-
+
if (nb) {
printf("failed to umount some filesystems\n");
select(0, NULL, NULL, NULL, NULL);
}
}
-#define BMAGIC_HARD 0x89ABCDEF
-#define BMAGIC_SOFT 0
-#define BMAGIC_REBOOT 0x01234567
-#define BMAGIC_HALT 0xCDEF0123
-#define BMAGIC_POWEROFF 0x4321FEDC
-int reboot_magic = BMAGIC_REBOOT;
-
int in_reboot(void)
{
int fd;
@@ -423,13 +370,92 @@ int in_reboot(void)
int i = read(fd, buf, sizeof(buf));
close(fd);
if (strstr(buf, "halt"))
- reboot_magic = BMAGIC_POWEROFF;
+ reboot_magic = LINUX_REBOOT_CMD_POWER_OFF;
return i > 0;
}
return 0;
}
-int exit_value_proceed = 66;
+int recursive_remove(char *file);
+int recursive_remove(char *file)
+{
+ struct stat sb;
+
+ if (lstat(file, &sb) != 0) {
+ printf("failed to stat %s: %d\n", file, errno);
+ return -1;
+ }
+
+ /* only descend into subdirectories if device is same as dir */
+ if (S_ISDIR(sb.st_mode)) {
+ char * strBuf = alloca(strlen(file) + 1024);
+ DIR * dir;
+ struct dirent * d;
+
+ if (!(dir = opendir(file))) {
+ printf("error opening %s: %d\n", file, errno);
+ return -1;
+ }
+ while ((d = readdir(dir))) {
+ if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
+ continue;
+
+ strcpy(strBuf, file);
+ strcat(strBuf, "/");
+ strcat(strBuf, d->d_name);
+
+ if (recursive_remove(strBuf) != 0) {
+ closedir(dir);
+ return -1;
+ }
+ }
+ closedir(dir);
+
+ if (rmdir(file)) {
+ printf("failed to rmdir %s: %d\n", file, errno);
+ return -1;
+ }
+ } else {
+ if (unlink(file) != 0) {
+ printf("failed to remove %s: %d\n", file, errno);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+
+int create_initial_fs_symlinks(char* symlinks)
+{
+ FILE *f;
+ char buf[5000];
+
+ if (!(f = fopen(symlinks, "rb"))) {
+ printf("Error opening symlink definitions file '%s'\n", symlinks);
+ return -1;
+ }
+ while (fgets(buf, sizeof(buf), f)) {
+ char oldpath[500], newpath[500];
+ struct stat sb;
+
+ buf[strlen(buf)-1] = '\0'; // trim \n
+ if (sscanf(buf, "%s %s", oldpath, newpath) != 2) {
+ snprintf(oldpath, sizeof(oldpath), "%s%s", STAGE2_LOCATION, buf);
+ snprintf(newpath, sizeof(newpath), "%s", buf);
+ }
+ if (lstat(newpath, &sb) == 0)
+ recursive_remove(newpath);
+ printf("Creating symlink %s -> %s\n", oldpath, newpath);
+ if (symlink(oldpath, newpath)) {
+ printf("Error creating symlink\n");
+ return -1;
+ }
+ }
+ fclose(f);
+ return 0;
+}
+
+
int exit_value_restart = 0x35;
int main(int argc, char **argv)
@@ -454,33 +480,27 @@ int main(int argc, char **argv)
printf("*** TESTING MODE *** (pid is %d)\n", getpid());
- if (!testing) {
- mkdir("/proc", 0755);
- if (mount("/proc", "/proc", "proc", 0, NULL))
- fatal_error("Unable to mount proc filesystem");
- }
-
+ // needed for ldetect:
+ if (!testing)
+ if (mount("none", "/sys/kernel/debug", "debugfs", MS_NOSUID, "mode=0755"))
+ fatal_error("Unable to mount debugfs filesystem");
+
/* ignore Control-C and keyboard stop signals */
signal(SIGINT, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
-#ifdef MANDRAKE_MOVE
- /* disallow Ctrl Alt Del to reboot */
- reboot(0xfee1dead, 672274793, BMAGIC_SOFT);
-#endif
-
if (!testing) {
fd = open("/dev/console", O_RDWR, 0);
if (fd < 0)
fatal_error("failed to open /dev/console");
-
+
dup2(fd, 0);
dup2(fd, 1);
dup2(fd, 2);
close(fd);
}
-
+
/* I set me up as session leader (probably not necessary?) */
setsid();
@@ -498,46 +518,66 @@ int main(int argc, char **argv)
if (!testing)
doklog();
- /* Go into normal init mode - keep going, and then do a orderly shutdown
- when:
-
- 1) install exits
- 2) we receive a SIGHUP
- */
-
- do {
- if (!(installpid = fork())) {
- /* child */
- char * child_argv[2];
- child_argv[0] = BINARY;
- child_argv[1] = NULL;
-
- execve(child_argv[0], child_argv, env);
- printf("error in exec of %s :-( [%d]\n", BINARY, errno);
- return 0;
- }
+ if (create_initial_fs_symlinks(STAGE2_LOCATION "/usr/share/symlinks") != 0)
+ fatal_error("Fatal error finishing initialization (could not create symlinks).");
+
+ /* kernel modules and firmware is needed by stage2, so move them to the root */
+ if (rename("/usr/lib/modules", "/modules"))
+ fatal_error("Cannot rename modules folder");
+
+ if (rename("/usr/lib/firmware", "/firmware"))
+ fatal_error("Cannot rename firmware folder");
- do {
- childpid = wait4(-1, &wait_status, 0, NULL);
- } while (childpid != installpid);
- } while (WIFEXITED(wait_status) && WEXITSTATUS(wait_status) == exit_value_restart);
+ /* Add some symlinks so stage1 is still valid on it's own - not strictly needed */
+ if (symlink("/modules", "/usr/lib/modules"))
+ fatal_error("Cannot symlink modules folder");
- /* allow Ctrl Alt Del to reboot */
- reboot(0xfee1dead, 672274793, BMAGIC_HARD);
+ if (symlink("/firmware", "/usr/lib/firmware"))
+ fatal_error("Cannot symlink firmware folder");
+
+ if (mount(STAGE2_LOCATION "/usr", "/usr", "none", MS_BIND|MS_RDONLY, NULL))
+ fatal_error("Unable to bind mount /usr filesystem from rescue or installer stage2");
+
+
+ if (access("/run/drakx/run-init", R_OK) == 0) {
+ /* This is typically used in rescue mode */
+ char * child_argv[2] = { "/sbin/init", NULL };
- if (in_reboot()) {
- // any exitcode is valid if we're in_reboot
- } else if (WIFEXITED(wait_status) && WEXITSTATUS(wait_status) == exit_value_proceed) {
kill(klog_pid, 9);
printf("proceeding, please wait...\n");
- return 0;
- } else if (!WIFEXITED(wait_status) || WEXITSTATUS(wait_status) != 0) {
+ execve(child_argv[0], child_argv, env);
+ fatal_error("failed to exec /sbin/init");
+ }
+
+ /* This is installer mode */
+ do {
+ printf("proceeding, please wait...\n");
+
+ if (!(installpid = fork())) {
+ /* child */
+ char * child_argv[2] = { BINARY_STAGE2, NULL };
+ execve(child_argv[0], child_argv, env);
+ printf("error in exec of %s :-( [%d]\n", child_argv[0], errno);
+ return 0;
+ }
+
+ do {
+ childpid = wait4(-1, &wait_status, 0, NULL);
+ } while (childpid != installpid);
+ } while (WIFEXITED(wait_status) && WEXITSTATUS(wait_status) == exit_value_restart);
+
+ /* allow Ctrl Alt Del to reboot */
+ reboot(LINUX_REBOOT_CMD_CAD_ON);
+
+ if (in_reboot()) {
+ // any exitcode is valid if we're in_reboot
+ } else if (!WIFEXITED(wait_status) || WEXITSTATUS(wait_status) != 0) {
printf("exited abnormally :-( ");
if (WIFSIGNALED(wait_status))
printf("-- received signal %d", WTERMSIG(wait_status));
printf("\n");
abnormal_termination = 1;
- }
+ }
if (!abnormal_termination) {
int i;
@@ -566,12 +606,12 @@ int main(int argc, char **argv)
sync(); sync();
if (!abnormal_termination) {
- if (reboot_magic == BMAGIC_REBOOT) {
+ if (reboot_magic == LINUX_REBOOT_CMD_RESTART) {
#ifdef DEBUG
printf("automatic reboot in 10 seconds\n");
sleep(10);
#endif
- reboot(0xfee1dead, 672274793, reboot_magic);
+ reboot(reboot_magic);
} else {
printf("you may safely poweroff your computer now\n");
}