/* Copyright (C) 2008 Emmanuel Varoquaux
This file is part of XOS.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see . */
#include "usr.h"
#include
#include
#define SHELL_FILENAME "/bin/xsh"
static int file_exists(const char *path)
{
int fd;
if ((fd = open(path, O_READ)) != -1) {
close(fd);
return 1;
}
else
return 0;
}
static int setup()
{
/* montage des systemes de fichiers systeme */
if (mount(NULL, "/", "rootfs") == -1)
goto error;
if (mount(NULL, "/dev", "devfs") == -1)
goto error_umount_rootfs;
if (mount(NULL, "/proc", "procfs") == -1)
goto error_umount_devfs;
/* creation des descripteurs de fichiers sur la console */
if (open("/dev/console", O_READ) == -1)
goto error_umount_procfs;
if (open("/dev/console", O_WRITE) == -1)
goto error_close_0;
if (open("/dev/console", O_READ | O_WRITE) == -1)
goto error_close_1;
/* affichage de messages d'information */
printf("root file system mounted on /.\n");
printf("dev file system mounted on /dev.\n");
printf("proc file system mounted on /proc.\n");
/* montage des systemes de fichiers des peripheriques de stockage */
if (file_exists("/dev/fd")) {
if (mount("/dev/fd", "/floppy", "vfat") == -1)
perror("init: failed to mount file system vfat on floppy drive");
else
printf("File system vfat on floppy drive mounted on /floppy.\n");
}
if (mount(NULL, "/home", "ramfs") == -1)
perror("init: failed to mount file system ramfs");
else
printf("File system ramfs mounted on /home.\n");
return 1;
error_close_1:
close(1);
error_close_0:
close(0);
error_umount_procfs:
umount("/proc");
error_umount_devfs:
umount("/dev");
error_umount_rootfs:
umount("/");
error:
return 0;
}
static void killall()
{
printf("Sending all processes the TERM signal...\n");
kill(-1, SIGTERM);
sleep(1);
printf("Sending all processes the KILL signal...\n");
kill(-1, SIGKILL);
}
static void shutdown()
{
printf("Shutting down...\n");
/* demontage des systemes de fichiers des peripheriques de stockage */
umount("/home");
umount("/floppy");
/* destruction des descripteurs de fichiers sur la console */
close(2);
close(1);
close(0);
/* demontage des systemes de fichiers systeme */
umount("/proc");
umount("/dev");
umount("/");
}
void _start_init()
{
static char shell_filename[] = SHELL_FILENAME;
static char *const shell_argv[] = {shell_filename, NULL};
static char *const shell_envp[] = {NULL};
int pid, pgid;
if (!setup())
goto end;
if ((pid = fork()) == -1) {
perror("init: failed to fork");
goto shutdown;
}
if (!pid) {
setpgid(0, 0);
pgid = getpgid();
ioctl(0, TSETPGID, &pgid);
if (chdir("/home") == -1)
perror("init: chdir /home");
exec(shell_filename, shell_argv, shell_envp);
perror("init: failed to run " SHELL_FILENAME);
exit(EXIT_FAILURE);
}
wait(pid, NULL, 0);
killall();
shutdown:
shutdown();
end:
reboot(RB_HALT);
exit(EXIT_FAILURE);
}