CLIte/readme-internals.txt
2023-11-27 20:37:45 +10:00

103 lines
4.6 KiB
Text

CLIte Internals:
CLite's aim is not just to create a functional unix-like terminal in a
web page, but also to have that built on top of a unix-like operating
system written in javascript and which runs in a web page.
CLIte follows the common programming methodology of creating in three
steps:
First, make it work.
Second, make it work right.
Third, make it work well.
This means that some areas are still very much a work in progress, but
are gradually being improved.
At its core, CLIte is made up of the follow parts:
The Core:
Effectively CLIte's 'kernel', this consists of functions needed to do
basic tasks, such as loading files, loading scripts, safely running
code, downloading files, rebooting the system, and system initialisation.
Most of this is either abstracted away to higher level functions, or
otherwise need never be used by user-level programs.
The Terminal:
The terminal handles user input, and displays program output. Most of
which is abstracted away to standard io calls on /dev/tty, and even
further abstracted to standard io calls on the standard input, output,
and error filedescriptors that every program has. Additionally the
term library offers some advanced functionality which is subject to
change.
The VFS: (Virtual File Sytem)
CLIte's virtual file system bares no relation to the file system of the
server it is run on (thus /etc/passwd is not the server's /etc/passwd
file!).
During system initialisation, the root filesystem is mounted by creating
the VFS, with physical server-side files then mapped into the VFS using
a plain-text config file which is stored in /dev/wfs (web file system,
for lack of a better name). The content of files are then loaded in as
needed when the VFS file is accessed.
However other files in the VFS are created dynamically as needed during
system initialisation. For instance, commands are loaded in directly
from javascript functions, which creates both the executable file in
/bin/<name> as well as the source file in /usr/src/<name>.js. Thus two
VFS files are created from each command, with many commands being held
in a single server-side file. Libraries are loaded in similarly, to
both /lib/<name>.so and /usr/src/libs/<name>.js
Additionally, configuration files in /etc, and various default devices
in /dev are also created programatically. As is the system log file
in /var/logs.
Most VFS functions are abstracted away to stdio functions.
The Process Manager:
CLIte's process manager keeps track of running programs as processes and
process groups, in a typical unix-like manner. It also wraps each
process in its own try/catch block to ensure errors are handled
correctly, and that failed processes aren't left 'hanging'.
It also manages callbacks for functions such as wait() so that processes
can monitor and act upon each other as needed.
The User Manager:
The user manager controls the user logins, and dynamically generates a
guest session as needed.
The Logger:
The Logger manages the system logs, printing them to the terminal during
system initialisation and shutdown, as well as writing them to the
system log at /var/logs
The Lifecycle of a Process:
1. fork() is called with the environment and io data passed to it.
This adds a new process to the process manager, which assigns it
a process id (pid) and also creates a file in /proc/<pid> for
storing data about the process.
Both the environment and io data are then cloned, and the new
process is called asynchronously, forking it from the current
process.
The process id of the new process is returned to the parent.
2. exec() is called, again the environment and io data is passed to it,
along with the file path and arguments for a new program.
This checks the file both exists and is executable by the current
user.
Then updated details of the program are sent to the process manager.
The current program is then overwritten with a call to the new
program.
3. The program then runs as intended, and exits normally, or fails and
is caught by a try/catch which exits the program.
4. exit() is called with an integer 'exit state':
zero for no error.
less than zero for internal error
greater than zero for the program's own use
This ends the program, and notifies the process manager that the
process has exit.
The process manager will then remove the process from the process
list, delete the process' data file in /proc/<pid>, then handle
any wait() calls that have been queued for the process exit.
Typically, this is when the shell's waitpid() on the process causes the
shell to once again show a prompt, awaiting the user's next command
input.