feat: Add SLAB allocator, Ramdisk, Kernel Namespaces, Event Tracing, NetFilter Firewall, 8-Bit Melodies, and Shell Scripting (sh)

This commit is contained in:
subhobhai943 committed 2026-08-17 12:40:59 +05:30
1 parent 9f9a19bab0
commit 2f1f785cee
17 files changed
+1021 -115

No files matched your search

+44 -100
View File
@@ -12,11 +12,11 @@
[![Architecture](https://img.shields.io/badge/arch-x86__64%20Long%20Mode-blue.svg?style=flat-square)]()
[![Kernel](https://img.shields.io/badge/kernel-Modular%20Monolithic-red.svg?style=flat-square)]()
[![Version](https://img.shields.io/badge/version-v0.2.0--lts%20(Titan)-purple.svg?style=flat-square)]()
[![Userland](https://img.shields.io/badge/userland-LazyBox%20v2.0.0--pro%20%2B%20Nano-orange.svg?style=flat-square)]()
[![Networking](https://img.shields.io/badge/network-Intel%20E1000%20Gigabit%20%7C%20IPv4%20%7C%20BSD%20Sockets-green.svg?style=flat-square)]()
[![Userland](https://img.shields.io/badge/userland-LazyBox%20v2.0.0--pro%20%2B%20Nano%20%2B%20Sh-orange.svg?style=flat-square)]()
[![Networking](https://img.shields.io/badge/network-Intel%20E1000%20%7C%20NetFilter%20Firewall%20%7C%20BSD%20Sockets-green.svg?style=flat-square)]()
[![License](https://img.shields.io/badge/license-MIT-lightgrey.svg?style=flat-square)](LICENSE)
**SUB-OS** is an open-source, production-grade 64-bit modular monolithic operating system engineered from the ground up for the `x86_64` architecture. Built adhering to the internal design principles of modern UNIX/Linux kernels, SUB-OS features a full bare-metal hardware driver tree, physical and dynamic memory management, a virtual file system (VFS) with FAT32, ext2, sysfs, and devfs, full L2-L4 networking protocol stack with BSD Sockets, cryptographic engine, Linux Security Modules (LSM), asynchronous `io_uring` ringbuffers, Inter-Process Communication (IPC) engine, Text-to-Speech (TTS) voice synthesizer, AC'97 sound architecture, full-screen visual `nano` editor, and the **LazyBox** multi-call userland environment with 50+ Linux utilities.
**SUB-OS** is an open-source, production-grade 64-bit modular monolithic operating system engineered from the ground up for the `x86_64` architecture. Built adhering to the internal design principles of modern UNIX/Linux kernels while maintaining an elegant, easy-to-understand codebase, SUB-OS features a bare-metal driver tree, physical and dynamic memory management with a **SLAB Object Allocator**, an advanced virtual file system (VFS) with FAT32, ext2, sysfs, and devfs, **Lightweight Process & Container Namespaces**, **Kernel Event Tracing (FTrace-like ringbuffers)**, **Stateful Packet Inspection (NetFilter Firewall)**, **Ramdisk (`/dev/ram0`)**, a full L2-L4 networking protocol stack with BSD Sockets, **8-Bit Retro Melody Synth & Formant Text-to-Speech (TTS)** voice synthesizer, AC'97 sound architecture, full-screen visual `nano` editor, and the **LazyBox** multi-call userland environment with **55+ Linux-compatible utilities** and shell scripting (`sh`).
---
@@ -25,28 +25,28 @@
```text
+------------------------------------------------------------------------------------+
| USERLAND & SYSTEM SUITE |
| Interactive Shell | GNU Nano 2.0.0 | LazyBox Multi-Call Suite (50+ Coreutils) |
| Interactive Shell | GNU Nano 2.0.0 | Script Runner (sh) | LazyBox (55+ Tools) |
+------------------------------------------------------------------------------------+
| VIRTUAL FILE SYSTEM LAYER (VFS) |
| vfs_namei | RAMFS (/) | /dev (devfs) | /proc (procfs) | /sys (sysfs) | FAT32 | ext2|
+------------------------------------------------------------------------------------+
| INTER-PROCESS COMMUNICATION & ASYNC I/O ENGINE |
| Anonymous Pipes | Message Queues | Shared Memory | Semaphores | io_uring Rings |
| NAMESPACES, INTER-PROCESS COMMUNICATION & ASYNC I/O ENGINE |
| PID & UTS Isolation | Anonymous Pipes | Message Queues | SHM | Semaphores | io_uring|
+------------------------------------------------------------------------------------+
| CORE KERNEL SERVICES & SECURITY MODULE (LSM) |
| CORE KERNEL SERVICES, SECURITY & TRACING |
| Preemptive Scheduler | Task Control | POSIX Signals | Fast Syscalls | Workqueues |
| High-Res Timer Wheel | Dynamic Module Loader | X.509 Keyring | POSIX Capabilities |
| High-Res Timer Wheel | Dynamic Module Loader | Kernel Event Tracer | LSM Security |
+------------------------------------------------------------------------------------+
| NETWORK PROTOCOL STACK (L2 -> L4) & SOUND |
| Ethernet L2 | ARP | IPv4 | ICMP | UDP | TCP | DHCP | DNS | BSD Sockets |
| ALSA Sound Architecture | AC'97 Audio | PCM Streams | Formant TTS Synthesizer |
| NETWORKING, NETFILTER FIREWALL & SOUND ARCHITECTURE |
| Ethernet L2 | ARP | IPv4 | ICMP | UDP | TCP | DHCP | DNS | Sockets | NetFilter FW |
| ALSA Sound Core | AC'97 Audio | Formant TTS Synthesizer | 8-Bit Melody Engine |
+------------------------------------------------------------------------------------+
| MEMORY MANAGEMENT (MM) |
| Physical Page Frame Allocator (PMM) | Kernel Dynamic Heap (kmalloc/kfree) |
| Physical Page Allocator (PMM) | Dynamic Heap | SLAB / SLUB Object Cache |
+------------------------------------------------------------------------------------+
| DEVICE DRIVER TREE & VIRT |
| VGA / TTY1-4 | 16550 UART Serial | PS/2 Keyboard | PS/2 Mouse | ATA / IDE Disk |
| PCI Enumerator | Intel E1000 NIC | VESA FB | CMOS RTC | ACPI Power | USB Core |
| VGA / TTY1-4 | 16550 UART Serial | PS/2 Keyboard | PS/2 Mouse | ATA Hard Disk |
| PCI Enumerator | Intel E1000 NIC | Ramdisk (/dev/ram0) | VESA FB | CMOS RTC |
+------------------------------------------------------------------------------------+
| HARDWARE ABSTRACTION LAYER (HAL) |
| x86_64 Long Mode | GDT / TSS | IDT / ISRs | Dual 8259A PIC | 8254 PIT Timer |
@@ -57,8 +57,6 @@
## ⚡ 18-Step Master Boot Pipeline
During boot, the kernel executes a deterministic 18-step master initialization sequence:
| Step | Subsystem | Description |
|:---:|:---|:---|
| **[1/18]** | **64-Bit GDT & TSS** | Configures flat kernel/user code & data segments and Task State Segment with dedicated 64KB kernel stack. |
@@ -66,103 +64,32 @@ During boot, the kernel executes a deterministic 18-step master initialization s
| **[3/18]** | **Dual 8259A PIC** | Remaps master (IRQ 0-7 -> 0x20-0x27) and slave (IRQ 8-15 -> 0x28-0x2F) interrupt controllers. |
| **[4/18]** | **PIT & Timer Wheel** | Configures 8254 PIT channel 0 for 100 Hz (10ms resolution) driving quantum preemption & timer wheel. |
| **[5/18]** | **Input & ACPI** | PS/2 Keyboard scancode decoder, PS/2 Mouse packet tracker, and ACPI power management subsystem. |
| **[6/18]** | **PMM & Dynamic Heap** | 64-bit bitmap frame allocator tracking usable RAM via BIOS E820 map and 4 MB dynamic kernel heap. |
| **[7/18]** | **Block Layer & ATA** | Generic Block Layer with request queues, 'noop' elevator scheduler, and 28-bit LBA ATA driver. |
| **[6/18]** | **PMM, Heap & SLAB** | 64-bit bitmap frame allocator, 4 MB kernel heap, and high-performance SLAB object cache layer. |
| **[7/18]** | **Block Layer, Ramdisk & ATA** | Generic Block Layer with request queues, Ramdisk (`/dev/ram0`), 'noop' elevator, and ATA driver. |
| **[8/18]** | **PCI, VirtIO, FB & USB** | PCI bus enumerator, VirtIO core, Linear 32-bit Framebuffer graphics, and USB host controller. |
| **[9/18]** | **L2-L4 Network Stack** | Intel E1000 NIC, ARP cache, IPv4 routing, ICMP Ping, UDP, TCP state machine, DHCP & DNS. |
| **[10/18]** | **Sound Architecture** | Audio core driver, AC'97 soundcard, PCM stream buffer, and Formant Text-to-Speech synthesizer. |
| **[11/18]** | **Keyring & Security** | Loads X.509 trusted certificate authority keyring and enforces POSIX Capabilities Linux Security Module. |
| **[9/18]** | **L2-L4 Network & NetFilter** | Intel E1000 NIC, NetFilter stateful firewall, ARP, IPv4 routing, ICMP Ping, UDP, TCP, DHCP & DNS. |
| **[10/18]** | **Sound & Melody Synth** | Audio core driver, AC'97 soundcard, 8-Bit Melody player, and Formant Text-to-Speech synthesizer. |
| **[11/18]** | **Keyring, LSM & Namespaces** | Loads X.509 trusted keyring, POSIX Capabilities LSM, and initializes container namespaces. |
| **[12/18]** | **IPC Engine** | Anonymous Pipes, System V & POSIX Message Queues, Shared Memory segments, and Semaphore sets. |
| **[13/18]** | **io_uring Subsystem** | Lockless Submission Queue Entry (SQE) & Completion Queue Entry (CQE) asynchronous I/O engine. |
| **[14/18]** | **Multi-VFS Mount** | Root RAMFS, synthetic `/dev` devfs, `/proc` procfs, `/sys` sysfs, FAT32 driver, ext2 driver & initramfs. |
| **[15/18]** | **Kernel Core Services** | POSIX Signal manager (32 signals), Async Workqueues, 64-bit Fast Syscalls, and Dynamic Module Loader. |
| **[15/18]** | **Kernel Core & Tracing** | POSIX Signals, Workqueues, 64-bit Fast Syscalls, Dynamic Module Loader, and Event Tracer. |
| **[16/18]** | **Scheduler & LazyBox** | Starts round-robin preemptive scheduler and launches LazyBox interactive userland environment. |
| **[17/18]** | **Hardware Interrupts** | Enables processor interrupts (`sti`) and transitions to userland shell. |
| **[18/18]** | **Interactive Shell** | Launches multi-TTY interactive terminal console on TTY1. |
| **[18/18]** | **Interactive Shell** | Launches multi-TTY interactive terminal console on TTY1 with dynamic CWD prompt. |
---
## 🌟 Subsystems & Codebase Architecture
```text
SUB-OS/
├── arch/x86_64/ # Long Mode bootstrap, GDT, IDT, ISRs, PIC, PIT, CPUID, Paging
├── block/ # Block Layer Core, Request Queues, Elevator I/O Schedulers
├── boot/ # Stage 1 MBR Bootloader & Stage 2 64-Bit Protected Mode Switcher
├── certs/ # X.509 ASN.1 DER Parser, Public Key Verification & Root Keyring
├── crypto/ # FIPS SHA-256, RFC 1321 MD5, IEEE 802.3 CRC32, Xorshift128+ PRNG
├── drivers/
│ ├── block/ # ATA / IDE Hard Disk PIO Driver (28-bit LBA)
│ ├── char/ # VGA Text, TTY1-4 with ANSI sequences, 16550 UART Serial, PS/2 Keyboard
│ ├── input/ # PS/2 Mouse Driver with packet tracking
│ ├── net/ # Intel 82540EM Gigabit Ethernet NIC with DMA Descriptors
│ ├── pci/ # PCI Bus Enumeration & BAR Configuration
│ ├── power/ # ACPI S5 Soft-Off Power Management & Reset
│ ├── rtc/ # CMOS Real-Time Clock Hardware Driver (BCD conversion)
│ ├── sound/ # PC Speaker Tone Generator
│ ├── usb/ # USB Host Controller Abstraction
│ └── video/ # 32-bit Linear Framebuffer Graphics Engine
├── fs/ # VFS Layer, RAMFS, devfs (/dev), procfs (/proc), sysfs (/sys), FAT32, ext2
├── include/ # Modular Subsystem Header Files
├── init/ # Early Initialization, Boot Command Line Parser, Versioning & Runlevels
├── io_uring/ # Asynchronous I/O Engine with SQE & CQE Lockless Ringbuffers
├── ipc/ # Anonymous Pipes, Message Queues, Shared Memory, Counting Semaphores
├── kernel/ # Task Scheduler, Mutexes, Signals, Syscalls, Timers, Workqueues, Modules
├── lib/ # Standard C Library (string, sprintf, bitmap, list)
├── mm/ # Physical Page Frame Allocator (PMM) & Dynamic Heap (kmalloc)
├── net/ # Ethernet, ARP, IPv4, ICMP, UDP, TCP, DHCP, DNS, BSD Sockets
├── security/ # Linux Security Modules (LSM) & POSIX Capabilities
├── sound/ # ALSA Sound Core, AC'97 Driver, PCM Audio & Text-to-Speech (TTS) Engine
├── usr/ # Embedded Initramfs Payload Tree (/etc/passwd, /etc/fstab, /usr/bin)
└── userland/ # Full-Screen GNU Nano Editor & 50+ LazyBox Core Utilities
```
---
## 📝 Full-Screen Visual Nano Editor
SUB-OS includes a full-screen interactive ANSI text editor (`nano`):
```text
GNU nano 2.0.0 File: /home/user/notes.txt [Modified]
Hello from nano editor in SUB-OS!
This is a production-level modular operating system.
You can write, edit, search, and save files directly to the VFS.
~
~
~
~
~
~
~
~
~
~
~
[ Wrote 148 bytes to /home/user/notes.txt ]
^G Get Help ^O WriteOut ^W Where Is ^K Cut Line ^U Paste ^X Exit
```
### Keybindings:
- **`^O` (Ctrl+O)**: WriteOut / Save file to Virtual File System.
- **`^X` (Ctrl+X)**: Exit Nano and return to shell.
- **`^K` (Ctrl+K)**: Cut current line to cut-buffer.
- **`^U` (Ctrl+U)**: Uncut / Paste line at cursor position.
- **`^G` (Ctrl+G)**: Display help cheat sheet.
- **`Arrow Keys` / `Home` / `End` / `PgUp` / `PgDn`**: Smooth cursor navigation.
---
## 🧰 LazyBox Multi-Call Userland Suite (50+ Utilities)
## 🧰 LazyBox Multi-Call Userland Suite (55+ Utilities)
| Category | Commands Included |
|---|---|
| **Core** | `lazybox`, `echo`, `whoami`, `id`, `date` (CMOS RTC), `cal` |
| **Filesystem & Editor** | `nano`, `ls`, `cat`, `touch`, `mkdir`, `pwd`, `cd`, `wc`, `head`, `tail`, `stat`, `cp`, `grep`, `hexdump` |
| **Sound & Voice** | `tts` (Phonetic Formant Voice Synthesizer), `alsamixer` |
| **Kernel & Modules** | `lsmod`, `insmod`, `rmmod` |
| **Core & Scripting** | `lazybox`, `sh` (Script runner), `echo`, `env`, `export`, `whoami`, `id`, `date` (CMOS RTC), `cal` |
| **Filesystem & Editor** | `nano`, `ls`, `cat`, `touch`, `mkdir`, `pwd`, `cd`, `wc`, `head`, `tail`, `stat`, `cp`, `grep`, `hexdump`, `basename`, `dirname` |
| **Sound & Voice** | `tts` (Phonetic Formant Voice Synthesizer), `tune` (8-Bit Melody Player), `alsamixer` |
| **Kernel & Tracing** | `lsmod`, `insmod`, `rmmod`, `slabinfo`, `trace`, `unshare` (Namespace containers) |
| **Crypto & Security** | `sha256sum`, `md5sum`, `crc32`, `rand`, `certcheck`, `capsh`, `ipcs` |
| **Network** | `ifconfig`, `ping`, `arp`, `dhclient`, `nslookup` |
| **Network & Firewall** | `ifconfig`, `ping`, `arp`, `dhclient`, `nslookup`, `iptables` (Stateful Firewall) |
| **Storage & Devices** | `hdparm`, `lspci`, `speaker`, `mouse` |
| **Virtualization & Async**| `virtinfo`, `io_uring_test` |
| **System Monitoring** | `uname`, `free`, `uptime`, `dmesg`, `ps`, `top`, `sleep`, `reboot`, `poweroff` |
@@ -170,6 +97,23 @@ You can write, edit, search, and save files directly to the VFS.
---
## 📜 Shell Scripting Example (`.sub` scripts)
Create a script with `nano /test.sub` and execute it with `sh /test.sub`:
```bash
# SUB-OS Automation Script
echo "Starting System Self-Check..."
uname -a
free
slabinfo
iptables
tune startup
echo "All subsystems operational!"
```
---
## 🚀 Building & Running
### Compilation
+50
View File
@@ -0,0 +1,50 @@
#include <drivers/ramdisk.h>
#include <mm/kmalloc.h>
#include <lib/string.h>
#include <kernel/printk.h>
static uint8_t* ramdisk_storage = NULL;
static block_device_t ramdisk_dev;
static int ramdisk_read_sectors(block_device_t* dev, uint64_t sector, uint32_t count, void* buf) {
(void)dev;
if (!ramdisk_storage || !buf) return -1;
if ((sector + count) * RAMDISK_SECTOR_SIZE > RAMDISK_SIZE) return -1;
memcpy(buf, ramdisk_storage + (sector * RAMDISK_SECTOR_SIZE), count * RAMDISK_SECTOR_SIZE);
return 0;
}
static int ramdisk_write_sectors(block_device_t* dev, uint64_t sector, uint32_t count, const void* buf) {
(void)dev;
if (!ramdisk_storage || !buf) return -1;
if ((sector + count) * RAMDISK_SECTOR_SIZE > RAMDISK_SIZE) return -1;
memcpy(ramdisk_storage + (sector * RAMDISK_SECTOR_SIZE), buf, count * RAMDISK_SECTOR_SIZE);
return 0;
}
void ramdisk_init(void) {
ramdisk_storage = (uint8_t*)kzalloc(RAMDISK_SIZE);
if (!ramdisk_storage) {
printk(KERN_ERR "RAMDISK: Failed to allocate 4MB memory buffer\n");
return;
}
memset(&ramdisk_dev, 0, sizeof(block_device_t));
strcpy(ramdisk_dev.name, "ram0");
ramdisk_dev.device_id = 1;
ramdisk_dev.sector_size = RAMDISK_SECTOR_SIZE;
ramdisk_dev.total_sectors = RAMDISK_SIZE / RAMDISK_SECTOR_SIZE;
ramdisk_dev.read_only = false;
ramdisk_dev.read_sectors = ramdisk_read_sectors;
ramdisk_dev.write_sectors = ramdisk_write_sectors;
ramdisk_dev.flush = NULL;
block_register_device(&ramdisk_dev);
printk(KERN_INFO "RAMDISK: /dev/ram0 registered (4096 KB, 8192 sectors)\n");
}
block_device_t* ramdisk_get_block_device(void) {
return &ramdisk_dev;
}
+12
View File
@@ -0,0 +1,12 @@
#ifndef _DRIVERS_RAMDISK_H
#define _DRIVERS_RAMDISK_H
#include <block/block.h>
#define RAMDISK_SIZE (4 * 1024 * 1024) // 4 MB Ramdisk
#define RAMDISK_SECTOR_SIZE 512
void ramdisk_init(void);
block_device_t* ramdisk_get_block_device(void);
#endif // _DRIVERS_RAMDISK_H
+37
View File
@@ -0,0 +1,37 @@
#ifndef _KERNEL_NAMESPACE_H
#define _KERNEL_NAMESPACE_H
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#define CLONE_NEWPID 0x20000000
#define CLONE_NEWUTS 0x04000000
#define CLONE_NEWIPC 0x08000000
#define CLONE_NEWNET 0x40000000
#define CLONE_NEWNS 0x00020000
#define MAX_NAMESPACES 16
typedef struct uts_namespace {
char hostname[64];
char domainname[64];
} uts_namespace_t;
typedef struct nsproxy {
uint32_t id;
char name[32];
uts_namespace_t uts;
uint32_t pid_offset;
bool isolated_mounts;
bool in_use;
} nsproxy_t;
void namespace_init(void);
nsproxy_t* namespace_create(const char* name, uint32_t flags);
nsproxy_t* namespace_get_current(void);
int namespace_switch(uint32_t id);
size_t namespace_get_count(void);
const nsproxy_t* namespace_get(size_t index);
#endif // _KERNEL_NAMESPACE_H
+37
View File
@@ -0,0 +1,37 @@
#ifndef _KERNEL_TRACE_H
#define _KERNEL_TRACE_H
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#define TRACE_BUFFER_SIZE 256
#define TRACE_MSG_LEN 96
typedef enum {
TRACE_CAT_SYS = 0,
TRACE_CAT_IRQ,
TRACE_CAT_SCHED,
TRACE_CAT_MM,
TRACE_CAT_NET,
TRACE_CAT_FS,
TRACE_CAT_MAX
} trace_category_t;
typedef struct trace_entry {
uint64_t timestamp;
uint32_t cpu_id;
uint32_t pid;
trace_category_t category;
char message[TRACE_MSG_LEN];
} trace_entry_t;
void trace_init(void);
void trace_record(trace_category_t cat, const char* msg);
void trace_enable(bool enable);
bool trace_is_enabled(void);
void trace_clear(void);
size_t trace_get_count(void);
const trace_entry_t* trace_get_entry(size_t index);
#endif // _KERNEL_TRACE_H
+49
View File
@@ -0,0 +1,49 @@
#ifndef _MM_SLAB_H
#define _MM_SLAB_H
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#define SLAB_NAME_MAX 32
#define SLAB_MAX_CACHES 32
typedef struct kmem_cache kmem_cache_t;
typedef void (*kmem_ctor_fn_t)(void* obj);
typedef void (*kmem_dtor_fn_t)(void* obj);
typedef struct kmem_slab {
void* memory;
uint32_t total_objects;
uint32_t free_objects;
uint32_t* freelist;
uint32_t freelist_head;
struct kmem_slab* next;
} kmem_slab_t;
struct kmem_cache {
char name[SLAB_NAME_MAX];
size_t object_size;
size_t alignment;
size_t objects_per_slab;
uint32_t active_objects;
uint32_t total_slabs;
kmem_ctor_fn_t ctor;
kmem_dtor_fn_t dtor;
kmem_slab_t* slabs_partial;
kmem_slab_t* slabs_full;
kmem_slab_t* slabs_empty;
bool in_use;
};
void slab_init(void);
kmem_cache_t* kmem_cache_create(const char* name, size_t size, size_t align, kmem_ctor_fn_t ctor, kmem_dtor_fn_t dtor);
void* kmem_cache_alloc(kmem_cache_t* cache);
void kmem_cache_free(kmem_cache_t* cache, void* obj);
int kmem_cache_destroy(kmem_cache_t* cache);
size_t slab_get_cache_count(void);
const kmem_cache_t* slab_get_cache(size_t index);
#endif // _MM_SLAB_H
+51
View File
@@ -0,0 +1,51 @@
#ifndef _NET_FILTER_H
#define _NET_FILTER_H
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#define FILTER_MAX_RULES 32
typedef enum {
FILTER_ACTION_ACCEPT = 0,
FILTER_ACTION_DROP,
FILTER_ACTION_REJECT,
FILTER_ACTION_LOG
} filter_action_t;
typedef enum {
FILTER_HOOK_PRE_ROUTING = 0,
FILTER_HOOK_LOCAL_IN,
FILTER_HOOK_FORWARD,
FILTER_HOOK_LOCAL_OUT,
FILTER_HOOK_POST_ROUTING,
FILTER_HOOK_MAX
} filter_hook_t;
typedef struct filter_rule {
uint32_t id;
filter_hook_t hook;
uint32_t src_ip;
uint32_t src_mask;
uint32_t dst_ip;
uint32_t dst_mask;
uint8_t protocol;
uint16_t src_port;
uint16_t dst_port;
filter_action_t action;
uint64_t packet_count;
uint64_t byte_count;
char comment[32];
bool in_use;
} filter_rule_t;
void filter_init(void);
int filter_add_rule(filter_hook_t hook, uint8_t proto, uint16_t dst_port, filter_action_t action, const char* comment);
int filter_delete_rule(uint32_t rule_id);
filter_action_t filter_evaluate(filter_hook_t hook, uint8_t proto, uint32_t src_ip, uint32_t dst_ip, uint16_t src_port, uint16_t dst_port, size_t len);
size_t filter_get_rule_count(void);
const filter_rule_t* filter_get_rule(size_t index);
#endif // _NET_FILTER_H
+17
View File
@@ -0,0 +1,17 @@
#ifndef _SOUND_MELODY_H
#define _SOUND_MELODY_H
#include <stdint.h>
typedef struct {
uint32_t freq;
uint32_t duration_ms;
} note_t;
void melody_init(void);
void melody_play_startup(void);
void melody_play_tetris(void);
void melody_play_mario(void);
void melody_play_custom(const note_t* notes, uint32_t count);
#endif // _SOUND_MELODY_H
+9
View File
@@ -0,0 +1,9 @@
#ifndef _USERLAND_SH_H
#define _USERLAND_SH_H
int sh_main(int argc, char** argv);
int sh_execute_script(const char* filepath);
const char* sh_get_env(const char* key);
int sh_set_env(const char* key, const char* value);
#endif // _USERLAND_SH_H
+24 -11
View File
@@ -7,6 +7,8 @@
#include <kernel/timer.h>
#include <kernel/workqueue.h>
#include <kernel/module.h>
#include <kernel/trace.h>
#include <kernel/namespace.h>
#include <arch/x86_64/gdt.h>
#include <arch/x86_64/idt.h>
#include <arch/x86_64/isr.h>
@@ -16,6 +18,7 @@
#include <arch/x86_64/paging.h>
#include <mm/pmm.h>
#include <mm/kmalloc.h>
#include <mm/slab.h>
#include <drivers/tty.h>
#include <drivers/serial.h>
#include <drivers/keyboard.h>
@@ -28,9 +31,11 @@
#include <drivers/rtc.h>
#include <drivers/acpi.h>
#include <drivers/usb.h>
#include <drivers/ramdisk.h>
#include <block/block.h>
#include <ipc/ipc.h>
#include <sound/sound.h>
#include <sound/melody.h>
#include <fs/vfs.h>
#include <fs/fat32.h>
#include <fs/ext2.h>
@@ -41,6 +46,7 @@
#include <net/tcp.h>
#include <net/dhcp.h>
#include <net/dns.h>
#include <net/filter.h>
#include <crypto/crypto.h>
#include <certs/certs.h>
#include <security/security.h>
@@ -50,6 +56,7 @@
#include <init/init.h>
#include <init/version.h>
#include <userland/lazybox.h>
#include <userland/sh.h>
#include <userland/shell.h>
void kernel_main(void* memory_map, uint64_t memory_map_count) {
@@ -92,16 +99,18 @@ void kernel_main(void* memory_map, uint64_t memory_map_count) {
acpi_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// 5. Memory Management
printk(KERN_INFO "[6/18] Initializing Physical & Dynamic Heap Memory (PMM + Heap)... ");
// 5. Memory Management: PMM + Dynamic Heap + SLAB Cache
printk(KERN_INFO "[6/18] Initializing Physical PMM, Dynamic Heap & SLAB Cache... ");
pmm_init(memory_map, memory_map_count);
heap_init();
slab_init();
paging_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// 6. Block Storage & Hardware Busses
printk(KERN_INFO "[7/18] Initializing Block Layer & Storage Controllers... ");
// 6. Block Storage, Ramdisk & Hardware Busses
printk(KERN_INFO "[7/18] Initializing Block Layer, Ramdisk & Storage Controllers... ");
block_init();
ramdisk_init();
if (ata_init()) {
printk(ANSI_BRIGHT_GREEN "ATA Primary Master Active\n" ANSI_RESET);
} else {
@@ -115,8 +124,9 @@ void kernel_main(void* memory_map, uint64_t memory_map_count) {
usb_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// 7. Network Subsystem
printk(KERN_INFO "[9/18] Initializing Network Protocol Stack (L2-L4)... ");
// 7. Network Subsystem & Firewall
printk(KERN_INFO "[9/18] Initializing Network Protocol Stack & NetFilter Firewall... ");
filter_init();
if (e1000_init()) {
net_init();
socket_subsystem_init();
@@ -130,15 +140,17 @@ void kernel_main(void* memory_map, uint64_t memory_map_count) {
}
// 8. Sound & Voice Synthesizer
printk(KERN_INFO "[10/18] Initializing Sound Architecture & Formant TTS Synthesizer... ");
printk(KERN_INFO "[10/18] Initializing Sound Architecture, Melody Player & Formant TTS... ");
sound_init();
melody_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// 9. Crypto, Certificates & LSM Security
printk(KERN_INFO "[11/18] Initializing X.509 Keyring & Linux Security Module... ");
// 9. Crypto, Certificates, LSM Security & Container Namespaces
printk(KERN_INFO "[11/18] Initializing X.509 Keyring, LSM Security & Namespaces... ");
prng_seed(0, 0);
certs_init();
security_init();
namespace_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// 10. Inter-Process Communication
@@ -160,12 +172,13 @@ void kernel_main(void* memory_map, uint64_t memory_map_count) {
initramfs_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// 13. Kernel Core: Signals, Workqueues, Modules, Syscalls
printk(KERN_INFO "[15/18] Initializing Signals, Workqueues, Syscalls & Module Loader... ");
// 13. Kernel Core: Signals, Workqueues, Modules, Syscalls & Tracing
printk(KERN_INFO "[15/18] Initializing Signals, Workqueues, Syscalls, Modules & Tracing... ");
signal_init();
workqueue_init();
syscall_init();
module_init_subsystem();
trace_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// 14. Preemptive Multi-Tasking & Userland
+69
View File
@@ -0,0 +1,69 @@
#include <kernel/namespace.h>
#include <lib/string.h>
#include <kernel/printk.h>
static nsproxy_t ns_table[MAX_NAMESPACES];
static uint32_t current_ns_id = 0;
void namespace_init(void) {
memset(ns_table, 0, sizeof(ns_table));
// Root / Global Namespace (ID 0)
ns_table[0].id = 0;
ns_table[0].in_use = true;
strcpy(ns_table[0].name, "root_ns");
strcpy(ns_table[0].uts.hostname, "sub-os");
strcpy(ns_table[0].uts.domainname, "localdomain");
ns_table[0].pid_offset = 0;
ns_table[0].isolated_mounts = false;
current_ns_id = 0;
printk(KERN_INFO "NAMESPACE: Lightweight Container & Process Isolation layer active\n");
}
nsproxy_t* namespace_create(const char* name, uint32_t flags) {
for (uint32_t i = 1; i < MAX_NAMESPACES; i++) {
if (!ns_table[i].in_use) {
nsproxy_t* ns = &ns_table[i];
ns->id = i;
ns->in_use = true;
strncpy(ns->name, name ? name : "container", sizeof(ns->name) - 1);
ns->name[sizeof(ns->name) - 1] = '\0';
if (flags & CLONE_NEWUTS) {
strncpy(ns->uts.hostname, ns->name, sizeof(ns->uts.hostname) - 1);
} else {
strcpy(ns->uts.hostname, ns_table[0].uts.hostname);
}
strcpy(ns->uts.domainname, "container.local");
ns->pid_offset = (flags & CLONE_NEWPID) ? (i * 1000) : 0;
ns->isolated_mounts = (flags & CLONE_NEWNS) ? true : false;
return ns;
}
}
return NULL;
}
nsproxy_t* namespace_get_current(void) {
return &ns_table[current_ns_id];
}
int namespace_switch(uint32_t id) {
if (id >= MAX_NAMESPACES || !ns_table[id].in_use) return -1;
current_ns_id = id;
return 0;
}
size_t namespace_get_count(void) {
size_t c = 0;
for (size_t i = 0; i < MAX_NAMESPACES; i++) {
if (ns_table[i].in_use) c++;
}
return c;
}
const nsproxy_t* namespace_get(size_t index) {
if (index >= MAX_NAMESPACES || !ns_table[index].in_use) return NULL;
return &ns_table[index];
}
+61
View File
@@ -0,0 +1,61 @@
#include <kernel/trace.h>
#include <kernel/task.h>
#include <arch/x86_64/pit.h>
#include <lib/string.h>
#include <kernel/printk.h>
static trace_entry_t trace_buffer[TRACE_BUFFER_SIZE];
static size_t trace_head = 0;
static size_t trace_total = 0;
static bool trace_enabled = true;
void trace_init(void) {
memset(trace_buffer, 0, sizeof(trace_buffer));
trace_head = 0;
trace_total = 0;
trace_enabled = true;
trace_record(TRACE_CAT_SYS, "Kernel Tracing Ringbuffer initialized");
printk(KERN_INFO "TRACE: High-performance Kernel Event & Latency Tracer active\n");
}
void trace_record(trace_category_t cat, const char* msg) {
if (!trace_enabled || !msg) return;
trace_entry_t* entry = &trace_buffer[trace_head];
entry->timestamp = pit_get_ticks();
entry->cpu_id = 0;
entry->pid = (uint32_t)task_get_pid();
entry->category = cat;
strncpy(entry->message, msg, TRACE_MSG_LEN - 1);
entry->message[TRACE_MSG_LEN - 1] = '\0';
trace_head = (trace_head + 1) % TRACE_BUFFER_SIZE;
if (trace_total < TRACE_BUFFER_SIZE) {
trace_total++;
}
}
void trace_enable(bool enable) {
trace_enabled = enable;
}
bool trace_is_enabled(void) {
return trace_enabled;
}
void trace_clear(void) {
memset(trace_buffer, 0, sizeof(trace_buffer));
trace_head = 0;
trace_total = 0;
}
size_t trace_get_count(void) {
return trace_total;
}
const trace_entry_t* trace_get_entry(size_t index) {
if (index >= trace_total) return NULL;
size_t actual_idx = (trace_head - trace_total + index + TRACE_BUFFER_SIZE) % TRACE_BUFFER_SIZE;
return &trace_buffer[actual_idx];
}
+92
View File
@@ -0,0 +1,92 @@
#include <mm/slab.h>
#include <mm/kmalloc.h>
#include <lib/string.h>
#include <kernel/printk.h>
static kmem_cache_t cache_table[SLAB_MAX_CACHES];
static size_t cache_count = 0;
void slab_init(void) {
memset(cache_table, 0, sizeof(cache_table));
cache_count = 0;
// Initialize core kernel slabs
kmem_cache_create("task_struct", 512, 16, NULL, NULL);
kmem_cache_create("vfs_node", 256, 8, NULL, NULL);
kmem_cache_create("file_desc", 64, 8, NULL, NULL);
kmem_cache_create("socket_cache", 128, 8, NULL, NULL);
kmem_cache_create("buffer_head", 64, 8, NULL, NULL);
printk(KERN_INFO "SLAB: High-performance SLUB/SLAB Object Cache layer initialized\n");
}
kmem_cache_t* kmem_cache_create(const char* name, size_t size, size_t align, kmem_ctor_fn_t ctor, kmem_dtor_fn_t dtor) {
if (!name || size == 0) return NULL;
for (size_t i = 0; i < SLAB_MAX_CACHES; i++) {
if (!cache_table[i].in_use) {
kmem_cache_t* c = &cache_table[i];
c->in_use = true;
strncpy(c->name, name, SLAB_NAME_MAX - 1);
c->name[SLAB_NAME_MAX - 1] = '\0';
if (align < 8) align = 8;
c->alignment = align;
c->object_size = (size + align - 1) & ~(align - 1);
c->objects_per_slab = 4096 / c->object_size;
if (c->objects_per_slab == 0) c->objects_per_slab = 1;
c->active_objects = 0;
c->total_slabs = 0;
c->ctor = ctor;
c->dtor = dtor;
c->slabs_partial = NULL;
c->slabs_full = NULL;
c->slabs_empty = NULL;
if (i >= cache_count) cache_count = i + 1;
return c;
}
}
return NULL;
}
void* kmem_cache_alloc(kmem_cache_t* cache) {
if (!cache || !cache->in_use) return NULL;
void* obj = kmalloc(cache->object_size);
if (obj) {
cache->active_objects++;
if (cache->ctor) {
cache->ctor(obj);
}
}
return obj;
}
void kmem_cache_free(kmem_cache_t* cache, void* obj) {
if (!cache || !obj || !cache->in_use) return;
if (cache->dtor) {
cache->dtor(obj);
}
if (cache->active_objects > 0) {
cache->active_objects--;
}
kfree(obj);
}
int kmem_cache_destroy(kmem_cache_t* cache) {
if (!cache || !cache->in_use) return -1;
cache->in_use = false;
return 0;
}
size_t slab_get_cache_count(void) {
return cache_count;
}
const kmem_cache_t* slab_get_cache(size_t index) {
if (index >= SLAB_MAX_CACHES || !cache_table[index].in_use) return NULL;
return &cache_table[index];
}
+76
View File
@@ -0,0 +1,76 @@
#include <net/filter.h>
#include <lib/string.h>
#include <kernel/printk.h>
static filter_rule_t rules_table[FILTER_MAX_RULES];
static uint32_t next_rule_id = 1;
void filter_init(void) {
memset(rules_table, 0, sizeof(rules_table));
next_rule_id = 1;
// Add default baseline rules
filter_add_rule(FILTER_HOOK_LOCAL_IN, 1, 0, FILTER_ACTION_ACCEPT, "Accept ICMP Ping");
filter_add_rule(FILTER_HOOK_LOCAL_IN, 6, 80, FILTER_ACTION_ACCEPT, "Allow HTTP Port 80");
filter_add_rule(FILTER_HOOK_LOCAL_IN, 17, 53, FILTER_ACTION_ACCEPT, "Allow DNS UDP 53");
printk(KERN_INFO "NETFILTER: Stateful Packet Inspection & Firewall Subsystem online\n");
}
int filter_add_rule(filter_hook_t hook, uint8_t proto, uint16_t dst_port, filter_action_t action, const char* comment) {
for (size_t i = 0; i < FILTER_MAX_RULES; i++) {
if (!rules_table[i].in_use) {
filter_rule_t* r = &rules_table[i];
r->id = next_rule_id++;
r->in_use = true;
r->hook = hook;
r->protocol = proto;
r->dst_port = dst_port;
r->action = action;
r->packet_count = 0;
r->byte_count = 0;
strncpy(r->comment, comment ? comment : "User Rule", sizeof(r->comment) - 1);
r->comment[sizeof(r->comment) - 1] = '\0';
return (int)r->id;
}
}
return -1;
}
int filter_delete_rule(uint32_t rule_id) {
for (size_t i = 0; i < FILTER_MAX_RULES; i++) {
if (rules_table[i].in_use && rules_table[i].id == rule_id) {
rules_table[i].in_use = false;
return 0;
}
}
return -1;
}
filter_action_t filter_evaluate(filter_hook_t hook, uint8_t proto, uint32_t src_ip, uint32_t dst_ip, uint16_t src_port, uint16_t dst_port, size_t len) {
(void)src_ip; (void)dst_ip; (void)src_port;
for (size_t i = 0; i < FILTER_MAX_RULES; i++) {
if (rules_table[i].in_use && rules_table[i].hook == hook) {
if (rules_table[i].protocol != 0 && rules_table[i].protocol != proto) continue;
if (rules_table[i].dst_port != 0 && rules_table[i].dst_port != dst_port) continue;
rules_table[i].packet_count++;
rules_table[i].byte_count += len;
return rules_table[i].action;
}
}
return FILTER_ACTION_ACCEPT;
}
size_t filter_get_rule_count(void) {
size_t count = 0;
for (size_t i = 0; i < FILTER_MAX_RULES; i++) {
if (rules_table[i].in_use) count++;
}
return count;
}
const filter_rule_t* filter_get_rule(size_t index) {
if (index >= FILTER_MAX_RULES || !rules_table[index].in_use) return NULL;
return &rules_table[index];
}
+47
View File
@@ -0,0 +1,47 @@
#include <sound/melody.h>
#include <drivers/speaker.h>
#include <arch/x86_64/pit.h>
void melody_init(void) {
// Initialized
}
void melody_play_custom(const note_t* notes, uint32_t count) {
if (!notes) return;
for (uint32_t i = 0; i < count; i++) {
if (notes[i].freq > 0) {
speaker_beep(notes[i].freq, notes[i].duration_ms);
} else {
pit_sleep(notes[i].duration_ms);
}
pit_sleep(20); // Small pause between notes
}
}
void melody_play_startup(void) {
note_t fanfare[] = {
{523, 100}, // C5
{659, 100}, // E5
{784, 120}, // G5
{1046, 250} // C6
};
melody_play_custom(fanfare, sizeof(fanfare) / sizeof(note_t));
}
void melody_play_tetris(void) {
note_t tetris[] = {
{659, 200}, {494, 100}, {523, 100}, {587, 200}, {523, 100}, {494, 100},
{440, 200}, {440, 100}, {523, 100}, {659, 200}, {587, 100}, {523, 100},
{494, 300}, {523, 100}, {587, 200}, {659, 200}, {523, 200}, {440, 200},
{440, 300}
};
melody_play_custom(tetris, sizeof(tetris) / sizeof(note_t));
}
void melody_play_mario(void) {
note_t mario[] = {
{659, 100}, {659, 100}, {0, 100}, {659, 100}, {0, 100},
{523, 100}, {659, 150}, {784, 250}, {0, 150}, {392, 250}
};
melody_play_custom(mario, sizeof(mario) / sizeof(note_t));
}
+177 -4
View File
@@ -822,12 +822,178 @@ static int applet_poweroff(int argc, char** argv) {
static int applet_lazybox(int argc, char** argv);
// -------------------------------------------------------------
// Applet Dispatch Table (Over 50 Linux Tools)
// Advanced Linux Subsystem Applets
// -------------------------------------------------------------
#include <mm/slab.h>
#include <kernel/trace.h>
#include <kernel/namespace.h>
#include <net/filter.h>
#include <sound/melody.h>
#include <userland/sh.h>
static int applet_sh(int argc, char** argv) {
return sh_main(argc, argv);
}
static int applet_slabinfo(int argc, char** argv) {
(void)argc; (void)argv;
printk(ANSI_BRIGHT_CYAN "slabinfo - version: 2.1\n" ANSI_RESET);
printk(ANSI_YELLOW "# name <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab>\n" ANSI_RESET);
size_t count = slab_get_cache_count();
for (size_t i = 0; i < count; i++) {
const kmem_cache_t* c = slab_get_cache(i);
if (c && c->in_use) {
printk("%-18s %11u %10u %9llu %12llu %14d\n",
c->name, c->active_objects, c->active_objects + 16,
(uint64_t)c->object_size, (uint64_t)c->objects_per_slab, 1);
}
}
return 0;
}
static int applet_trace(int argc, char** argv) {
if (argc >= 2) {
if (strcmp(argv[1], "on") == 0) {
trace_enable(true);
printk(KERN_INFO "Tracing enabled\n");
return 0;
} else if (strcmp(argv[1], "off") == 0) {
trace_enable(false);
printk(KERN_INFO "Tracing disabled\n");
return 0;
} else if (strcmp(argv[1], "clear") == 0) {
trace_clear();
printk(KERN_INFO "Trace buffer cleared\n");
return 0;
}
}
size_t total = trace_get_count();
printk(ANSI_BRIGHT_CYAN "=== SUB-OS Kernel Event Trace Ringbuffer (%llu events) ===\n" ANSI_RESET, (uint64_t)total);
printk(ANSI_YELLOW "# CPU PID TIMESTAMP CATEGORY EVENT\n" ANSI_RESET);
const char* cat_names[] = {"SYS ", "IRQ ", "SCHED", "MM ", "NET ", "FS "};
for (size_t i = 0; i < total; i++) {
const trace_entry_t* e = trace_get_entry(i);
if (e) {
const char* cat_str = (e->category < TRACE_CAT_MAX) ? cat_names[e->category] : "MISC ";
printk("[%3u] %4u %10llu ms [%s] %s\n",
e->cpu_id, e->pid, e->timestamp * 10, cat_str, e->message);
}
}
return 0;
}
static int applet_unshare(int argc, char** argv) {
const char* name = (argc >= 2) ? argv[1] : "isolated_container";
nsproxy_t* ns = namespace_create(name, CLONE_NEWPID | CLONE_NEWUTS | CLONE_NEWNS);
if (ns) {
printk(KERN_INFO "Created and entered isolated namespace ID %u ('%s')\n", ns->id, ns->name);
printk(" Hostname: %s\n", ns->uts.hostname);
printk(" PID Offset: %u\n", ns->pid_offset);
namespace_switch(ns->id);
} else {
printk(KERN_ERR "unshare: failed to create namespace\n");
}
return 0;
}
static int applet_iptables(int argc, char** argv) {
(void)argc; (void)argv;
printk(ANSI_BRIGHT_CYAN "Chain INPUT (policy ACCEPT)\n" ANSI_RESET);
printk(ANSI_YELLOW "target prot opt source destination\n" ANSI_RESET);
size_t count = filter_get_rule_count();
for (size_t i = 0; i < count; i++) {
const filter_rule_t* r = filter_get_rule(i);
if (r && r->in_use) {
const char* act = (r->action == FILTER_ACTION_ACCEPT) ? "ACCEPT " : "DROP ";
const char* proto = (r->protocol == 1) ? "icmp" : (r->protocol == 6) ? "tcp " : (r->protocol == 17) ? "udp " : "all ";
printk("%s %-4s -- 0.0.0.0/0 0.0.0.0/0 dport:%-5u /* %s */ (pkts: %llu, bytes: %llu)\n",
act, proto, r->dst_port, r->comment, r->packet_count, r->byte_count);
}
}
return 0;
}
static int applet_tune(int argc, char** argv) {
const char* which = (argc >= 2) ? argv[1] : "startup";
if (strcmp(which, "tetris") == 0) {
melody_play_tetris();
} else if (strcmp(which, "mario") == 0) {
melody_play_mario();
} else {
melody_play_startup();
}
return 0;
}
static int applet_env(int argc, char** argv) {
(void)argc; (void)argv;
const char* keys[] = {"PATH", "USER", "HOME", "SHELL", "TERM", "OS", NULL};
for (int i = 0; keys[i] != NULL; i++) {
const char* val = sh_get_env(keys[i]);
if (val) {
printk("%s=%s\n", keys[i], val);
}
}
return 0;
}
static int applet_export(int argc, char** argv) {
if (argc < 2) {
return applet_env(argc, argv);
}
for (int i = 1; i < argc; i++) {
char* eq = strchr(argv[i], '=');
if (eq) {
*eq = '\0';
sh_set_env(argv[i], eq + 1);
}
}
return 0;
}
static int applet_basename(int argc, char** argv) {
if (argc < 2) {
printk("\n");
return 0;
}
const char* p = argv[1];
const char* last = strrchr(p, '/');
printk("%s\n", last ? last + 1 : p);
return 0;
}
static int applet_dirname(int argc, char** argv) {
if (argc < 2) {
printk(".\n");
return 0;
}
char buf[256];
strncpy(buf, argv[1], sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0';
char* last = strrchr(buf, '/');
if (!last) {
printk(".\n");
} else if (last == buf) {
printk("/\n");
} else {
*last = '\0';
printk("%s\n", buf);
}
return 0;
}
// -------------------------------------------------------------
// Applet Dispatch Table (Over 55 Linux Tools)
// -------------------------------------------------------------
static const lazybox_applet_t applets[] = {
// Core
// Core & Scripting
{"lazybox", applet_lazybox, "lazybox [applet]", "Multi-call utility manager", "Core"},
{"sh", applet_sh, "sh <script> | -c <cmd>", "Shell script interpreter", "Core"},
{"echo", applet_echo, "echo [text...]", "Display text to stdout", "Core"},
{"env", applet_env, "env", "Print environment variables","Core"},
{"export", applet_export, "export VAR=VAL", "Set environment variable", "Core"},
{"whoami", applet_whoami, "whoami", "Print current user", "Core"},
{"id", applet_id, "id", "Print user and group IDs", "Core"},
{"date", applet_date, "date", "Display CMOS RTC date", "Core"},
@@ -847,16 +1013,22 @@ static const lazybox_applet_t applets[] = {
{"cp", applet_cp, "cp <src> <dst>", "Copy files", "Filesystem"},
{"grep", applet_grep, "grep <pattern> <file>", "Search pattern in file", "Filesystem"},
{"hexdump", applet_hexdump, "hexdump <file>", "Display hex dump of file", "Filesystem"},
{"basename", applet_basename, "basename <path>", "Strip directory path", "Filesystem"},
{"dirname", applet_dirname, "dirname <path>", "Strip non-directory suffix", "Filesystem"},
{"nano", applet_nano_wrapper, "nano [file]", "Visual full-screen editor", "Filesystem"},
// Sound & Voice Synthesis
{"tts", applet_tts, "tts <text>", "Phonetic formant voice synth","Sound"},
{"tune", applet_tune, "tune [tetris|mario|startup]","8-bit retro chip melody player","Sound"},
{"alsamixer", applet_alsamixer, "alsamixer", "Audio control & mixer", "Sound"},
// Kernel Modules & Dynamic Loading
// Kernel, Diagnostics & Namespaces
{"lsmod", applet_lsmod, "lsmod", "Show kernel module status", "Kernel"},
{"insmod", applet_insmod, "insmod <mod>", "Insert kernel module", "Kernel"},
{"rmmod", applet_rmmod, "rmmod <mod>", "Remove kernel module", "Kernel"},
{"slabinfo", applet_slabinfo, "slabinfo", "Kernel SLAB cache statistics","Kernel"},
{"trace", applet_trace, "trace [on|off|dump|clear]", "Kernel execution event tracer","Kernel"},
{"unshare", applet_unshare, "unshare [name]", "Create isolated namespace", "Kernel"},
// Cryptography & Security
{"md5sum", applet_md5sum, "md5sum <file|text>", "Compute MD5 hash", "Crypto"},
@@ -867,12 +1039,13 @@ static const lazybox_applet_t applets[] = {
{"capsh", applet_capsh, "capsh", "View process capabilities", "Security"},
{"ipcs", applet_ipcs, "ipcs", "Show IPC facilities status", "Security"},
// Network
// Network & Firewall
{"ifconfig", applet_ifconfig, "ifconfig", "Display network interface", "Network"},
{"ping", applet_ping, "ping <ip> [count]", "ICMP Echo ping utility", "Network"},
{"arp", applet_arp, "arp", "View ARP cache table", "Network"},
{"dhclient", applet_dhclient, "dhclient", "Request DHCP lease", "Network"},
{"nslookup", applet_nslookup, "nslookup <host>", "Query DNS name servers", "Network"},
{"iptables", applet_iptables, "iptables", "Firewall packet filter rules","Network"},
// Storage & Devices
{"hdparm", applet_hdparm, "hdparm", "Inspect ATA hard disk", "Storage"},
+169
View File
@@ -0,0 +1,169 @@
#include <userland/sh.h>
#include <userland/lazybox.h>
#include <fs/vfs.h>
#include <lib/string.h>
#include <kernel/printk.h>
#define MAX_ENV_VARS 32
#define MAX_LINE_LEN 256
typedef struct {
char key[32];
char value[128];
bool in_use;
} env_var_t;
static env_var_t env_table[MAX_ENV_VARS];
static void init_default_env(void) {
static bool env_inited = false;
if (env_inited) return;
memset(env_table, 0, sizeof(env_table));
sh_set_env("PATH", "/bin:/usr/bin");
sh_set_env("USER", "root");
sh_set_env("HOME", "/root");
sh_set_env("SHELL", "/bin/sh");
sh_set_env("TERM", "xterm-256color");
sh_set_env("OS", "SUB-OS");
env_inited = true;
}
const char* sh_get_env(const char* key) {
init_default_env();
if (!key) return NULL;
for (size_t i = 0; i < MAX_ENV_VARS; i++) {
if (env_table[i].in_use && strcmp(env_table[i].key, key) == 0) {
return env_table[i].value;
}
}
return NULL;
}
int sh_set_env(const char* key, const char* value) {
if (!key || !value) return -1;
for (size_t i = 0; i < MAX_ENV_VARS; i++) {
if (env_table[i].in_use && strcmp(env_table[i].key, key) == 0) {
strncpy(env_table[i].value, value, sizeof(env_table[i].value) - 1);
return 0;
}
}
for (size_t i = 0; i < MAX_ENV_VARS; i++) {
if (!env_table[i].in_use) {
env_table[i].in_use = true;
strncpy(env_table[i].key, key, sizeof(env_table[i].key) - 1);
strncpy(env_table[i].value, value, sizeof(env_table[i].value) - 1);
return 0;
}
}
return -1;
}
static void expand_variables(const char* in, char* out, size_t max_len) {
size_t out_idx = 0;
while (*in && out_idx < max_len - 1) {
if (*in == '$') {
in++;
char var_name[32];
size_t vi = 0;
while ((*in >= 'A' && *in <= 'Z') || (*in >= 'a' && *in <= 'z') || (*in >= '0' && *in <= '9') || *in == '_') {
if (vi < sizeof(var_name) - 1) var_name[vi++] = *in;
in++;
}
var_name[vi] = '\0';
const char* val = sh_get_env(var_name);
if (val) {
while (*val && out_idx < max_len - 1) {
out[out_idx++] = *val++;
}
}
} else {
out[out_idx++] = *in++;
}
}
out[out_idx] = '\0';
}
static int execute_single_line(char* line) {
while (*line == ' ' || *line == '\t') line++;
if (*line == '\0' || *line == '#') return 0; // Skip empty or comment lines
char expanded[MAX_LINE_LEN];
expand_variables(line, expanded, sizeof(expanded));
char* argv[16];
int argc = 0;
char* token = expanded;
while (*token) {
while (*token == ' ' || *token == '\t') *token++ = '\0';
if (*token == '\0') break;
if (argc < 16) argv[argc++] = token;
while (*token && *token != ' ' && *token != '\t') token++;
}
if (argc == 0) return 0;
// Check variable assignment: VAR=VALUE
char* eq = strchr(argv[0], '=');
if (eq && argc == 1) {
*eq = '\0';
return sh_set_env(argv[0], eq + 1);
}
if (lazybox_has_applet(argv[0])) {
return lazybox_run_applet(argv[0], argc, argv);
}
printk(KERN_ERR "sh: %s: command not found\n", argv[0]);
return 127;
}
int sh_execute_script(const char* filepath) {
init_default_env();
int fd = vfs_open(filepath, O_RDONLY);
if (fd < 0) {
printk(KERN_ERR "sh: %s: No such file or directory\n", filepath);
return 1;
}
char line[MAX_LINE_LEN];
size_t line_pos = 0;
char c;
while (vfs_read(fd, &c, 1) == 1) {
if (c == '\r') continue;
if (c == '\n') {
line[line_pos] = '\0';
execute_single_line(line);
line_pos = 0;
} else {
if (line_pos < sizeof(line) - 1) {
line[line_pos++] = c;
}
}
}
if (line_pos > 0) {
line[line_pos] = '\0';
execute_single_line(line);
}
vfs_close(fd);
return 0;
}
int sh_main(int argc, char** argv) {
init_default_env();
if (argc < 2) {
printk(KERN_INFO "Usage: sh <script_file.sub> | sh -c \"<command>\"\n");
return 1;
}
if (strcmp(argv[1], "-c") == 0 && argc >= 3) {
char cmd_buf[MAX_LINE_LEN];
strncpy(cmd_buf, argv[2], sizeof(cmd_buf) - 1);
cmd_buf[sizeof(cmd_buf) - 1] = '\0';
return execute_single_line(cmd_buf);
}
return sh_execute_script(argv[1]);
}