Removes the "-unix" element and with it any trademark exposure to The
Open Group.
The split follows the ecosystem layout: SchOS is the system, and the
kernel has its own name. Kernel-identity strings are the only places
that take SchIFT -- uname(2) sysname, /proc/version, and the two licence
sentences that say "kernel" outright. That is what every Unix does here:
`uname -s` on Linux reports the kernel, not the distribution. Everything
a user reads as the product -- panic screen, boot menu, error prefixes,
docs, LICENSE, NOTICE -- is SchOS.
schunix.img is schos.img, the logo assets and the musl TLS patch are
renamed, and __SCHUNIX__ is __SCHOS__ (the define and the patch that
consumes it moved together).
Two things the rename broke, both found by the bootcheck suite:
- shmtest wrote "SCHUNIX-MMAP-OK" with a hardcoded length of 15 and
compared it back by hand-counted offsets (m[3]=='U', m[14]=='K').
The shorter marker left the write running two bytes past the literal
and the compare reading past the data, failing a file-backed mmap
that was working correctly. Now written and compared through one
constant with sizeof.
- bootcheck asserted a 31-byte file after appending to
"hello-from-schunix"; the shorter string makes it 29.
Both are the same mistake: a string literal whose length is written out
somewhere else. Full suite green -- base, Tty, Ps, Sock, Fb, Usb, Evdev.
124 lines
4.5 KiB
C
124 lines
4.5 KiB
C
// SPDX-License-Identifier: Apache-2.0
|
|
// SchOS — minimal init (PID 1)
|
|
|
|
#include "types.h"
|
|
#include "user.h"
|
|
#include "fcntl.h"
|
|
|
|
static void
|
|
xputs(int fd, const char *s)
|
|
{
|
|
int n = 0;
|
|
while (s[n]) n++;
|
|
write(fd, (void *)s, n);
|
|
}
|
|
|
|
int
|
|
main(void)
|
|
{
|
|
if (getpid() != 1)
|
|
exit();
|
|
|
|
// Open console as fd 0; dup to fd 1 (stdout) and fd 2 (stderr).
|
|
if (open("console", O_RDWR) < 0) {
|
|
mknod("console", 1, 1);
|
|
open("console", O_RDWR);
|
|
}
|
|
dup(0);
|
|
dup(0);
|
|
|
|
// --- /dev ------------------------------------------------------------
|
|
// Minor numbers under major 1 follow Linux's mem-major layout where it
|
|
// costs nothing (null=2, zero=5, full=7, random=8, urandom=9).
|
|
// /dev/hole (was minor 4) is gone: it backed an abandoned experiment and
|
|
// nothing has referenced it since.
|
|
mkdir("/dev");
|
|
mknod("/dev/console", 1, 1);
|
|
mknod("/dev/null", 1, 2);
|
|
mknod("/dev/keyboard", 1, 3);
|
|
mknod("/dev/zero", 1, 5);
|
|
mknod("/dev/full", 1, 7);
|
|
mknod("/dev/random", 1, 8);
|
|
mknod("/dev/urandom", 1, 9);
|
|
mknod("/dev/fb0", 2, 0);
|
|
mknod("/dev/mouse", 3, 1);
|
|
mknod("/dev/tty", 1, 1); // alias for console — must pass TCGETS ioctl
|
|
mknod("/dev/ttyS0", 4, 64);
|
|
mknod("/dev/stdin", 1, 1);
|
|
mknod("/dev/stdout", 1, 1);
|
|
mknod("/dev/stderr", 1, 1);
|
|
|
|
// Raw input events, Linux evdev layout (kernel/dev/input.c). /dev/keyboard
|
|
// and /dev/mouse above are the old character-and-position interfaces; these
|
|
// are the ones with key releases and button transitions, which is what a
|
|
// game or a compositor needs and what neither of the others can express.
|
|
mkdir("/dev/input");
|
|
mknod("/dev/input/event0", 7, 0); // keyboard
|
|
mknod("/dev/input/event1", 7, 1); // mouse
|
|
|
|
// --- /proc -----------------------------------------------------------
|
|
// Synthesised status files, major 6 (kernel/dev/procfs.c). These are the
|
|
// global ones; per-process /proc/<pid>/ directories need synthetic
|
|
// directory support in the filesystem, which does not exist yet.
|
|
mkdir("/proc");
|
|
// /proc is a real filesystem now (kernel/fs/procfs.c), not a handful of
|
|
// mknod'd nodes: it has to be, because one directory per process cannot be
|
|
// created ahead of time. This is what makes `ps` and `top` work.
|
|
//
|
|
// The mknod'd global files below still happen, and are simply covered by
|
|
// the mount. They stay for now so that a failure here degrades to the old
|
|
// behaviour instead of losing /proc entirely.
|
|
mount("proc", "/proc", "proc", 0, 0);
|
|
mknod("/proc/meminfo", 6, 1);
|
|
mknod("/proc/uptime", 6, 2);
|
|
mknod("/proc/cpuinfo", 6, 3);
|
|
mknod("/proc/version", 6, 4);
|
|
mknod("/proc/stat", 6, 5);
|
|
mknod("/proc/loadavg", 6, 6);
|
|
mknod("/proc/mounts", 6, 7);
|
|
mknod("/proc/filesystems", 6, 8);
|
|
// SchFS volume summary: label, generation, free space, and the root
|
|
// directory. Reachable whether or not the volume is mounted into the
|
|
// namespace, which is what makes it useful when a mount has gone wrong.
|
|
mknod("/proc/schfs", 6, 9);
|
|
// Write 'c' here to crash on purpose. The crash screen is otherwise the
|
|
// one part of the system that can only be seen by having a bug.
|
|
mknod("/proc/sysrq", 6, 10);
|
|
mknod("/proc/pci", 6, 11);
|
|
mknod("/proc/interrupts", 6, 12);
|
|
|
|
mkdir("/sys");
|
|
|
|
xputs(1, "\nSchOS\n");
|
|
xputs(1, "init: ready (pid 1)\n");
|
|
|
|
for (;;) {
|
|
int pid = fork();
|
|
if (pid < 0) {
|
|
xputs(2, "init: fork failed\n");
|
|
sleep(100);
|
|
continue;
|
|
}
|
|
|
|
if (pid == 0) {
|
|
// exec.c auto-enables Linux ABI for musl binaries (entry >= 0x100000).
|
|
// Do NOT call enable_linux_abi() here — it corrupts SchOS syscall
|
|
// numbers for the exec/exit calls that follow in this child.
|
|
// Standardized naming: the shell is always /bin/sh, regardless of
|
|
// which implementation backs it (dash, mksh, etc.) — no ksh/mksh/
|
|
// other aliases are looked up here.
|
|
static char *argv[] = { "sh", 0 };
|
|
exec("/bin/sh", argv);
|
|
xputs(2, "init: no shell found; place sh in /bin\n");
|
|
exit();
|
|
}
|
|
|
|
// Reap zombies; the loop restarts the shell when it exits.
|
|
int wpid;
|
|
while ((wpid = wait()) >= 0 && wpid != pid)
|
|
;
|
|
// Brief pause before restarting so we don't spin on a missing shell.
|
|
sleep(100);
|
|
}
|
|
return 0;
|
|
}
|