/* 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); }