View of xos/kernel/init.c


XOS | Parent Directory | View | Download

/* 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 <http://www.gnu.org/licenses/>. */
 
#include "usr.h"
 
#include <consts.h>
#include <stddef.h>
 
#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);
}