diff --git a/Dockerfile b/Dockerfile index 9d27f84..d5e44f1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,9 +23,9 @@ FROM alpine:3.19 COPY scripts/docker-install-packages.sh /tmp/ RUN /tmp/docker-install-packages.sh -# Alpine Linux includes BusyBox by default -# BusyBox provides: shell (sh), networking (udhcpc, ip, ping, wget), and core utilities -# This is verified by the test.sh script which shows BusyBox version and available applets +# SparkOS Philosophy: No CLI tools, GUI-only experience +# The init system is completely self-contained with no external dependencies +# All functionality is provided through direct system calls in C # Create minimal rootfs structure COPY scripts/docker-setup-rootfs.sh /tmp/ diff --git a/rootfs/README.txt b/rootfs/README.txt index a96ef10..d9a3e99 100644 --- a/rootfs/README.txt +++ b/rootfs/README.txt @@ -1,43 +1,41 @@ SparkOS Root Filesystem ======================= -This is the root filesystem for SparkOS, a minimal Linux distribution. +This is the root filesystem for SparkOS, a GUI-only Linux distribution. -Minimal System Packages: - - Linux Kernel (with networking support) - - SparkOS Init System (custom) - - Busybox (shell, utilities, networking) - - Git (for installing spark CLI) - - Sudo (privilege elevation) +SparkOS Philosophy: + - GUI-Only: No CLI tools, no shell, no Unix utilities + - Network-First: Networking integrated into Qt6 GUI + - Direct Kernel Interface: Qt6 communicates directly with Linux kernel + - No Unix Baggage: No users, groups, passwords, or authentication + +Minimal System: + - Linux Kernel (with networking and framebuffer support) + - SparkOS Init System (completely self-contained, no dependencies) + - Qt6 GUI Application (all user interaction) Directory Structure: - /bin, /sbin - Essential binaries - /etc - Configuration files + /sbin - Init binary only + /etc - Minimal configuration files /proc, /sys, /dev - Kernel interfaces /tmp - Temporary files - /usr - User programs - /var - Variable data + /usr - Qt6 GUI application and libraries + /var - Variable data (overlay mount) /root - Root home directory - /home/spark - Default user home directory - -Default User: - Username: spark (UID 1000) - Home: /home/spark - Sudo: Full access without password - Scripts: ~/clone-sparkos.sh for installing spark CLI Network Configuration: - /etc/network/interfaces - Wired network (DHCP) - /etc/resolv.conf - DNS configuration (8.8.8.8, 1.1.1.1) - /sbin/init-network - Network initialization script + - Managed entirely through Qt6 GUI + - Init brings up interfaces via direct ioctl calls + - DHCP and network management handled by Qt6 NetworkManager + - /etc/resolv.conf provides fallback DNS servers -Bootstrap Process: - 1. System boots as 'spark' user with wired networking (DHCP) - 2. Run ~/clone-sparkos.sh to install spark CLI - 3. Use spark CLI to configure WiFi and system - 4. Install additional packages via spark CLI - 5. Use 'sudo' for any root-level operations +Boot Process: + 1. Linux kernel loads + 2. Init (PID 1) mounts filesystems + 3. Init brings up network interfaces + 4. Init spawns Qt6 GUI application + 5. All user interaction through GUI -Note: This is a minimal system. You'll need to populate /bin and /usr/bin -with actual binaries (busybox, git, sudo) from a proper Linux system -or by cross-compiling. +Note: This is a minimal, GUI-only system. + No shell, no CLI tools, no busybox. + All functionality is provided through the Qt6 GUI application. diff --git a/scripts/setup_rootfs.sh b/scripts/setup_rootfs.sh index 6cb034a..8a936c6 100755 --- a/scripts/setup_rootfs.sh +++ b/scripts/setup_rootfs.sh @@ -1,8 +1,7 @@ #!/bin/bash # SparkOS Setup Script -# Sets up a minimal rootfs with busybox and essential utilities +# Sets up a minimal rootfs for GUI-only SparkOS # Note: This script runs on the host system and uses bash for ${BASH_SOURCE} -# The target system uses busybox sh instead. set -e @@ -16,16 +15,12 @@ echo "" # Create directory structure echo "Creating directory structure..." -mkdir -p "$ROOTFS_DIR"/{bin,sbin,etc,proc,sys,dev,tmp,usr/{bin,sbin,lib,lib64},var,root,home} -mkdir -p "$ROOTFS_DIR/etc"/{init.d,network} +mkdir -p "$ROOTFS_DIR"/{sbin,etc,proc,sys,dev,tmp,usr/{bin,sbin,lib,lib64},var,root} mkdir -p "$ROOTFS_DIR/var"/{log,run} -mkdir -p "$ROOTFS_DIR/home/spark" -mkdir -p "$ROOTFS_DIR/etc/sudoers.d" # Set permissions chmod 1777 "$ROOTFS_DIR/tmp" chmod 700 "$ROOTFS_DIR/root" -chmod 755 "$ROOTFS_DIR/home/spark" # Create basic config files echo "Creating configuration files..." @@ -40,19 +35,6 @@ cat > "$ROOTFS_DIR/etc/hosts" << 'EOF' ::1 localhost ip6-localhost ip6-loopback EOF -# /etc/passwd -cat > "$ROOTFS_DIR/etc/passwd" << 'EOF' -root:x:0:0:root:/root:/bin/sh -spark:x:1000:1000:SparkOS User:/home/spark:/bin/sh -EOF - -# /etc/group -cat > "$ROOTFS_DIR/etc/group" << 'EOF' -root:x:0: -spark:x:1000: -sudo:x:27:spark -EOF - # /etc/fstab cat > "$ROOTFS_DIR/etc/fstab" << 'EOF' # @@ -62,320 +44,77 @@ devtmpfs /dev devtmpfs defaults 0 0 tmpfs /tmp tmpfs defaults 0 0 EOF -# /etc/resolv.conf - DNS configuration +# /etc/resolv.conf - DNS configuration (managed by Qt6 GUI) cat > "$ROOTFS_DIR/etc/resolv.conf" << 'EOF' # SparkOS DNS Configuration -# Fallback to public DNS servers for reliability +# Managed by Qt6 GUI NetworkManager +# Fallback to public DNS servers nameserver 8.8.8.8 nameserver 8.8.4.4 nameserver 1.1.1.1 nameserver 1.0.0.1 EOF -# /etc/sudoers - Sudo configuration -cat > "$ROOTFS_DIR/etc/sudoers" << 'EOF' -# SparkOS Sudoers Configuration -# Allow spark user to run any command without password - -# Default settings -Defaults env_reset -Defaults secure_path="/bin:/sbin:/usr/bin:/usr/sbin" - -# Root can run anything -root ALL=(ALL:ALL) ALL - -# Spark user can run anything without password -spark ALL=(ALL:ALL) NOPASSWD: ALL - -# Include sudoers.d directory -@includedir /etc/sudoers.d -EOF - -chmod 0440 "$ROOTFS_DIR/etc/sudoers" - -# /etc/network/interfaces - Wired network configuration -cat > "$ROOTFS_DIR/etc/network/interfaces" << 'EOF' -# SparkOS Network Configuration -# Wired networking only for bootstrapping - -# Loopback interface -auto lo -iface lo inet loopback - -# Primary wired interface (DHCP) -auto eth0 -iface eth0 inet dhcp -EOF - -# /etc/profile -cat > "$ROOTFS_DIR/etc/profile" << 'EOF' -# SparkOS System Profile - -export PATH=/bin:/sbin:/usr/bin:/usr/sbin -export PS1='SparkOS:\w\$ ' -export TERM=linux - -# Set HOME based on user -if [ "$(id -u)" = "0" ]; then - export HOME=/root -else - export HOME=/home/$(whoami) -fi - -# Welcome message -echo "Welcome to SparkOS!" -echo "Type 'help' for available commands" -echo "" -EOF - -# Create .profile for root (busybox uses .profile instead of .bashrc) -cat > "$ROOTFS_DIR/root/.profile" << 'EOF' -# SparkOS Root Shell Configuration - -# Set prompt -PS1='SparkOS:\w# ' - -# Aliases -alias ll='ls -lah' -alias ..='cd ..' - -# Environment -export EDITOR=vi -export PAGER=less -EOF - -# Create .profile for spark user -cat > "$ROOTFS_DIR/home/spark/.profile" << 'EOF' -# SparkOS User Shell Configuration - -# Set prompt -PS1='SparkOS:\w\$ ' - -# Aliases -alias ll='ls -lah' -alias ..='cd ..' - -# Environment -export EDITOR=vi -export PAGER=less -EOF - -# Create clone-sparkos.sh script for spark user -cat > "$ROOTFS_DIR/home/spark/clone-sparkos.sh" << 'EOF' -#!/bin/sh -# SparkOS CLI Installation Script -# This script clones the SparkOS CLI repository - -echo "SparkOS CLI Installation" -echo "========================" -echo "" - -SPARK_REPO="https://github.com/johndoe6345789/spark-cli.git" -INSTALL_DIR="$HOME/spark-cli" - -echo "This script will clone the SparkOS CLI to: $INSTALL_DIR" -echo "" - -# Check if git is available -if ! command -v git >/dev/null 2>&1; then - echo "Error: git is not installed" - echo "Please install git to continue" - exit 1 -fi - -# Check if directory already exists -if [ -d "$INSTALL_DIR" ]; then - echo "Warning: $INSTALL_DIR already exists" - echo -n "Do you want to remove it and re-clone? (y/N): " - read answer - if [ "$answer" = "y" ] || [ "$answer" = "Y" ]; then - rm -rf "$INSTALL_DIR" - else - echo "Installation cancelled" - exit 0 - fi -fi - -# Clone the repository -echo "Cloning spark CLI repository..." -if git clone "$SPARK_REPO" "$INSTALL_DIR"; then - echo "" - echo "SparkOS CLI cloned successfully!" - echo "" - echo "Next steps:" - echo " 1. cd $INSTALL_DIR" - echo " 2. Follow the installation instructions in the repository" - echo "" -else - echo "" - echo "Error: Failed to clone repository" - echo "Please check your network connection and try again" - exit 1 -fi -EOF - -chmod +x "$ROOTFS_DIR/home/spark/clone-sparkos.sh" - -# Create a simple help script -cat > "$ROOTFS_DIR/bin/sparkos-help" << 'EOF' -#!/bin/sh -cat << 'HELP' -SparkOS - Minimal Linux Distribution -==================================== - -Default Packages: - - Kernel (Linux) - - Init system (custom) - - Busybox (shell and utilities) - - Git (for installing spark CLI) - - Sudo (privilege elevation) - -Default User: - Username: spark - Home: /home/spark - Privileges: Full sudo access (no password required) - - To run commands as root: sudo - To become root: sudo -i - -Available commands: - ls, cd, pwd - Navigate filesystem - cat, less - View files - mkdir, rm, cp - File operations - mount, umount - Mount filesystems - ip, ifconfig - Network configuration - ping, wget - Network testing - git - Version control - sudo - Run commands as root - poweroff, reboot - System control - help - Show this help - -Network: - Wired networking (eth0) configured via DHCP - DNS: 8.8.8.8, 1.1.1.1 (Google and Cloudflare) - To check network: ping 8.8.8.8 - To test DNS: ping google.com - -Next Steps: - 1. Install spark CLI: ~/clone-sparkos.sh - 2. Use spark CLI to configure WiFi and system - 3. Install additional packages as needed - -For more information: https://github.com/johndoe6345789/SparkOS -HELP -EOF - -chmod +x "$ROOTFS_DIR/bin/sparkos-help" -ln -sf sparkos-help "$ROOTFS_DIR/bin/help" - -# Create network initialization script -cat > "$ROOTFS_DIR/sbin/init-network" << 'EOF' -#!/bin/sh -# SparkOS Network Initialization -# Brings up wired networking for system bootstrap - -echo "Initializing network..." - -# Bring up loopback -ip link set lo up 2>/dev/null || ifconfig lo up 2>/dev/null - -# Bring up primary wired interface with DHCP -# Try eth0 first, then other common interface names -for iface in eth0 enp0s3 enp0s8 ens33; do - if ip link show "$iface" >/dev/null 2>&1; then - echo "Bringing up $iface..." - - # Bring up the interface - if ip link set "$iface" up 2>/dev/null || ifconfig "$iface" up 2>/dev/null; then - # Try to get IP via DHCP using busybox udhcpc - if command -v udhcpc >/dev/null 2>&1; then - # Run udhcpc in background, it will daemonize itself - udhcpc -i "$iface" -b -t 5 2>/dev/null - fi - else - echo "Warning: Failed to bring up $iface" - fi - break - fi -done - -echo "Network initialization complete" -EOF - -chmod +x "$ROOTFS_DIR/sbin/init-network" - # Create README cat > "$ROOTFS_DIR/README.txt" << 'EOF' SparkOS Root Filesystem ======================= -This is the root filesystem for SparkOS, a minimal Linux distribution. +This is the root filesystem for SparkOS, a GUI-only Linux distribution. -Minimal System Packages: - - Linux Kernel (with networking support) - - SparkOS Init System (custom) - - Busybox (shell, utilities, networking) - - Git (for installing spark CLI) - - Sudo (privilege elevation) +SparkOS Philosophy: + - GUI-Only: No CLI tools, no shell, no Unix utilities + - Network-First: Networking integrated into Qt6 GUI + - Direct Kernel Interface: Qt6 communicates directly with Linux kernel + - No Unix Baggage: No users, groups, passwords, or authentication + +Minimal System: + - Linux Kernel (with networking and framebuffer support) + - SparkOS Init System (completely self-contained, no dependencies) + - Qt6 GUI Application (all user interaction) Directory Structure: - /bin, /sbin - Essential binaries - /etc - Configuration files + /sbin - Init binary only + /etc - Minimal configuration files /proc, /sys, /dev - Kernel interfaces /tmp - Temporary files - /usr - User programs - /var - Variable data + /usr - Qt6 GUI application and libraries + /var - Variable data (overlay mount) /root - Root home directory - /home/spark - Default user home directory - -Default User: - Username: spark (UID 1000) - Home: /home/spark - Sudo: Full access without password - Scripts: ~/clone-sparkos.sh for installing spark CLI Network Configuration: - /etc/network/interfaces - Wired network (DHCP) - /etc/resolv.conf - DNS configuration (8.8.8.8, 1.1.1.1) - /sbin/init-network - Network initialization script + - Managed entirely through Qt6 GUI + - Init brings up interfaces via direct ioctl calls + - DHCP and network management handled by Qt6 NetworkManager + - /etc/resolv.conf provides fallback DNS servers -Bootstrap Process: - 1. System boots as 'spark' user with wired networking (DHCP) - 2. Run ~/clone-sparkos.sh to install spark CLI - 3. Use spark CLI to configure WiFi and system - 4. Install additional packages via spark CLI - 5. Use 'sudo' for any root-level operations +Boot Process: + 1. Linux kernel loads + 2. Init (PID 1) mounts filesystems + 3. Init brings up network interfaces + 4. Init spawns Qt6 GUI application + 5. All user interaction through GUI -Note: This is a minimal system. You'll need to populate /bin and /usr/bin -with actual binaries (busybox, git, sudo) from a proper Linux system -or by cross-compiling. +Note: This is a minimal, GUI-only system. + No shell, no CLI tools, no busybox. + All functionality is provided through the Qt6 GUI application. EOF echo "" echo "Root filesystem structure created at: $ROOTFS_DIR" echo "" -echo "User configuration:" -echo " - Default user: spark (UID 1000)" -echo " - Home directory: /home/spark" -echo " - Sudo access: Enabled (no password required)" -echo " - Clone script: /home/spark/clone-sparkos.sh" -echo "" -echo "Network configuration:" -echo " - Wired networking (DHCP) configured for eth0" -echo " - DNS: 8.8.8.8, 1.1.1.1, 8.8.4.4, 1.0.0.1" -echo " - Network init script: /sbin/init-network" +echo "SparkOS Configuration:" +echo " - Architecture: GUI-only, no CLI" +echo " - Init: Self-contained, no external dependencies" +echo " - Network: Direct C implementation via ioctl" +echo " - User Experience: Pure Qt6 GUI" echo "" echo "Next steps:" echo " 1. Build init: make init" echo " 2. Install init: make install" -echo " 3. Copy busybox, git, and sudo binaries to rootfs/bin/" -echo " 4. Create busybox symlinks" -echo " 5. Create bootable image: sudo make image" +echo " 3. Build Qt6 GUI: make gui" +echo " 4. Create bootable image: sudo make image" echo "" -echo "Minimum required binaries:" -echo " - busybox (provides shell, networking, utilities)" -echo " - git (for installing spark CLI)" -echo " - sudo (for privilege elevation)" -echo "" -echo "Note: Busybox should be compiled with networking support" -echo " (CONFIG_UDHCPC, CONFIG_IFCONFIG, CONFIG_IP, CONFIG_PING, CONFIG_WGET)" +echo "Philosophy:" +echo " No busybox, no shell, no CLI tools" +echo " Everything is GUI-driven through Qt6" diff --git a/scripts/test.sh b/scripts/test.sh index d457293..4ed84aa 100644 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -3,48 +3,6 @@ echo "SparkOS Docker Test Environment" echo "================================" echo "" -# Verify BusyBox is present and working -echo "Verifying BusyBox..." -echo "-------------------" -if command -v busybox >/dev/null 2>&1; then - echo "✓ BusyBox is installed" - echo "" - echo "BusyBox version:" - # Store version for reuse in summary - BUSYBOX_VERSION=$(busybox | head -n 1) - echo "$BUSYBOX_VERSION" - echo "" - echo "BusyBox location:" - which busybox - ls -lh "$(which busybox)" - echo "" - echo "Shell (/bin/sh) is BusyBox:" - ls -lh /bin/sh - if [ -L /bin/sh ]; then - echo " → /bin/sh is a symlink to: \"$(readlink /bin/sh)\"" - fi - echo "" - echo "Available BusyBox applets (sample):" - # Store applet list once to avoid redundant executions - APPLET_LIST=$(busybox --list) - echo "$APPLET_LIST" | head -n 20 - echo " ... and $(echo "$APPLET_LIST" | wc -l) total applets" - echo "" - echo "Networking applets (required for SparkOS):" - for cmd in udhcpc ip ifconfig ping wget; do - if echo "$APPLET_LIST" | grep -q "^${cmd}$"; then - echo " ✓ $cmd" - else - echo " ✗ $cmd (NOT FOUND)" - fi - done -else - echo "✗ BusyBox not found!" - echo " SparkOS requires BusyBox for shell and utilities" - exit 1 -fi - -echo "" echo "Verifying SparkOS init binary..." echo "--------------------------------" if [ -f /sparkos/rootfs/sbin/init ]; then @@ -75,10 +33,13 @@ echo "✓ SparkOS is ready for testing!" echo "================================" echo "" echo "Summary:" -echo " - BusyBox: $BUSYBOX_VERSION" -echo " - Init: Custom SparkOS init system" -echo " - Shell: BusyBox sh (/bin/sh)" -echo " - Networking: BusyBox udhcpc, ip, ping, wget" +echo " - Init: Custom SparkOS init system (no external dependencies)" +echo " - Architecture: GUI-only, no CLI/shell" +echo " - Network: Direct C implementation via ioctl" +echo " - Philosophy: Pure GUI experience, network-first" +echo "" +echo "Note: SparkOS has no CLI tools (no busybox, no shell)" +echo " All functionality is provided through the Qt6 GUI" echo "" echo "To test the init system:" -echo " docker run --rm /sparkos/rootfs/sbin/init --help" \ No newline at end of file +echo " docker run --rm /sparkos/rootfs/sbin/init" \ No newline at end of file diff --git a/src/init.c b/src/init.c index 62baff8..eb0a353 100644 --- a/src/init.c +++ b/src/init.c @@ -1,6 +1,11 @@ /* * SparkOS Init - Minimal init system for SparkOS * This is the first process that runs after the kernel boots + * + * SparkOS Philosophy: GUI-only, no CLI, network-first + * - No shell spawning or CLI utilities + * - Direct boot to Qt6 GUI + * - Network initialization via direct C system calls */ #include @@ -8,9 +13,16 @@ #include #include #include +#include +#include +#include +#include +#include +#include #include #include #include +#include static void signal_handler(int sig) { if (sig == SIGCHLD) { @@ -33,7 +45,7 @@ static void spawn_gui() { char *argv[] = {"/usr/bin/sparkos-gui", NULL}; char *envp[] = { "HOME=/root", - "PATH=/bin:/sbin:/usr/bin:/usr/sbin", + "PATH=/usr/bin:/usr/sbin", "QT_QPA_PLATFORM=linuxfb:fb=/dev/fb0", "QT_QPA_FB_FORCE_FULLSCREEN=1", "QT_QPA_FONTDIR=/usr/share/fonts", @@ -51,39 +63,122 @@ static void spawn_gui() { waitpid(pid, &status, 0); } -static void spawn_shell() { - pid_t pid = fork(); +/* + * Initialize network interface directly via ioctl + * No dependency on busybox or CLI tools + */ +static int init_network_interface(const char *ifname) { + int sock; + struct ifreq ifr; - if (pid < 0) { - perror("fork failed"); - return; + // Create socket for ioctl operations + sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) { + perror("socket creation failed"); + return -1; } - if (pid == 0) { - // Child process - exec shell as root (fallback only) - - char *argv[] = {"/bin/sh", "-l", NULL}; - char *envp[] = { - "HOME=/root", - "PATH=/bin:/sbin:/usr/bin:/usr/sbin", - "TERM=linux", - "PS1=SparkOS# ", - NULL - }; - - execve("/bin/sh", argv, envp); - - perror("failed to exec shell"); - exit(1); + // Prepare interface request structure + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1); + + // Get current flags + if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) { + close(sock); + return -1; // Interface doesn't exist } - // Parent process - wait for shell to exit - int status; - waitpid(pid, &status, 0); + // Bring interface up + ifr.ifr_flags |= IFF_UP | IFF_RUNNING; + if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) { + perror("failed to bring up interface"); + close(sock); + return -1; + } + + close(sock); + printf("Network interface %s brought up successfully\n", ifname); + return 0; +} + +/* + * Initialize networking without external dependencies + * Brings up loopback and first available ethernet interface + */ +static void init_network() { + const char *interfaces[] = {"lo", "eth0", "enp0s3", "enp0s8", "ens33", NULL}; + int i; + int eth_initialized = 0; + + printf("Initializing network interfaces...\n"); + + // Bring up loopback + if (init_network_interface("lo") == 0) { + printf("Loopback interface initialized\n"); + } + + // Try to bring up first available ethernet interface + for (i = 1; interfaces[i] != NULL && !eth_initialized; i++) { + if (init_network_interface(interfaces[i]) == 0) { + printf("Primary network interface %s initialized\n", interfaces[i]); + printf("Note: DHCP configuration should be handled by Qt6 GUI\n"); + eth_initialized = 1; + } + } + + if (!eth_initialized) { + fprintf(stderr, "Warning: No ethernet interface found or initialized\n"); + fprintf(stderr, "Network configuration will be available through GUI\n"); + } +} + +/* + * Mount filesystem using direct mount() system call + * No dependency on mount binary + */ +static int mount_fs(const char *source, const char *target, const char *fstype, unsigned long flags) { + if (mount(source, target, fstype, flags, NULL) < 0) { + return -1; + } + return 0; +} + +/* + * Create directory recursively + * No dependency on mkdir binary + */ +static int mkdir_p(const char *path) { + char tmp[256]; + char *p = NULL; + size_t len; + + snprintf(tmp, sizeof(tmp), "%s", path); + len = strlen(tmp); + if (tmp[len - 1] == '/') + tmp[len - 1] = 0; + + for (p = tmp + 1; *p; p++) { + if (*p == '/') { + *p = 0; + if (mkdir(tmp, 0755) < 0 && errno != EEXIST) { + return -1; + } + *p = '/'; + } + } + + if (mkdir(tmp, 0755) < 0 && errno != EEXIST) { + return -1; + } + + return 0; } int main(int argc, char *argv[]) { printf("SparkOS Init System Starting...\n"); + printf("================================\n"); + printf("Philosophy: GUI-Only, No CLI, Network-First\n"); + printf("================================\n\n"); // Make sure we're PID 1 if (getpid() != 1) { @@ -94,18 +189,18 @@ int main(int argc, char *argv[]) { // Set up signal handlers signal(SIGCHLD, signal_handler); - // Mount essential filesystems + // Mount essential filesystems using direct system calls printf("Mounting essential filesystems...\n"); - if (system("mount -t proc proc /proc 2>/dev/null") != 0) { + if (mount_fs("proc", "/proc", "proc", 0) != 0) { fprintf(stderr, "Warning: Failed to mount /proc\n"); } - if (system("mount -t sysfs sys /sys 2>/dev/null") != 0) { + if (mount_fs("sysfs", "/sys", "sysfs", 0) != 0) { fprintf(stderr, "Warning: Failed to mount /sys\n"); } - if (system("mount -t devtmpfs dev /dev 2>/dev/null") != 0) { + if (mount_fs("devtmpfs", "/dev", "devtmpfs", 0) != 0) { fprintf(stderr, "Warning: Failed to mount /dev\n"); } - if (system("mount -t tmpfs tmpfs /tmp 2>/dev/null") != 0) { + if (mount_fs("tmpfs", "/tmp", "tmpfs", 0) != 0) { fprintf(stderr, "Warning: Failed to mount /tmp\n"); } @@ -113,37 +208,38 @@ int main(int argc, char *argv[]) { printf("Setting up overlay filesystem for writable layer...\n"); // Create overlay directories in tmpfs - if (system("mkdir -p /tmp/overlay/var-upper /tmp/overlay/var-work 2>/dev/null") != 0) { + if (mkdir_p("/tmp/overlay/var-upper") != 0 || mkdir_p("/tmp/overlay/var-work") != 0) { fprintf(stderr, "Warning: Failed to create overlay directories for /var\n"); } // Mount overlay on /var for logs and runtime data - if (system("mount -t overlay overlay -o lowerdir=/var,upperdir=/tmp/overlay/var-upper,workdir=/tmp/overlay/var-work /var 2>/dev/null") != 0) { + char overlay_opts[256]; + snprintf(overlay_opts, sizeof(overlay_opts), + "lowerdir=/var,upperdir=/tmp/overlay/var-upper,workdir=/tmp/overlay/var-work"); + if (mount("overlay", "/var", "overlay", 0, overlay_opts) != 0) { fprintf(stderr, "Warning: Failed to mount overlay on /var - system may be read-only\n"); } else { printf("Overlay filesystem mounted on /var (base OS is immutable)\n"); } // Mount tmpfs on /run for runtime data - if (system("mkdir -p /run 2>/dev/null") == 0) { - if (system("mount -t tmpfs tmpfs /run 2>/dev/null") != 0) { + if (mkdir_p("/run") == 0) { + if (mount_fs("tmpfs", "/run", "tmpfs", 0) != 0) { fprintf(stderr, "Warning: Failed to mount /run\n"); } } - // Initialize network (wired only for bootstrap) - printf("Initializing wired network...\n"); - if (system("/sbin/init-network 2>/dev/null") != 0) { - fprintf(stderr, "Warning: Network initialization failed - check network interface availability\n"); - } + // Initialize network interfaces + init_network(); - printf("Starting Qt6 GUI application...\n"); + printf("\nStarting Qt6 GUI application...\n"); printf("Welcome to SparkOS!\n"); printf("===================\n"); printf("Base OS: Read-only (immutable)\n"); printf("Writable: /tmp, /var (overlay), /run\n"); printf("Mode: Qt6 GUI (Network-First Architecture)\n"); - printf("No Users/Authentication - Direct Boot to GUI\n\n"); + printf("No Users/Authentication - Direct Boot to GUI\n"); + printf("No CLI/Shell - Pure GUI Experience\n\n"); // Main loop - keep respawning GUI application while (1) {