tonarchy

tonarchy

https://git.tonybtw.com/tonarchy.git git://git.tonybtw.com/tonarchy.git

Asdf

Commit
048b0ba9de59b59007525003fde47d69912c99aa
Parent
c32000c
Author
tonybtw <tonybtw@tonybtw.com>
Date
2025-12-22 18:11:32

Diff

diff --git a/Makefile b/Makefile
index 608598a..fd65a4a 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,7 @@
 CC = gcc
 CFLAGS = -std=c23 -Wall -Wextra -O2 -Iinclude
 LDFLAGS =
+STATIC_LDFLAGS = -static
 
 SRC_DIR = src
 INC_DIR = include
@@ -10,21 +11,26 @@ TARGET = tonarchy
 SRCS = $(wildcard $(SRC_DIR)/*.c)
 OBJS = $(SRCS:$(SRC_DIR)/%.c=$(BUILD_DIR)/%.o)
 
-.PHONY: all clean install
+.PHONY: all clean install static
 
 all: $(BUILD_DIR) $(TARGET)
 
+static: $(BUILD_DIR) $(TARGET)-static
+
 $(BUILD_DIR):
 	mkdir -p $(BUILD_DIR)
 
 $(TARGET): $(OBJS)
 	$(CC) $(OBJS) -o $(TARGET) $(LDFLAGS)
 
+$(TARGET)-static: $(OBJS)
+	$(CC) $(OBJS) -o $(TARGET)-static $(STATIC_LDFLAGS)
+
 $(BUILD_DIR)/%.o: $(SRC_DIR)/%.c
 	$(CC) $(CFLAGS) -c $< -o $@
 
 clean:
-	rm -rf $(BUILD_DIR) $(TARGET)
+	rm -rf $(BUILD_DIR) $(TARGET) $(TARGET)-static
 
 install: $(TARGET)
 	install -Dm755 $(TARGET) /usr/local/bin/$(TARGET)
diff --git a/flake.nix b/flake.nix
index aef4783..ece30ec 100644
--- a/flake.nix
+++ b/flake.nix
@@ -15,17 +15,17 @@
         default = pkgs.mkShell {
           buildInputs = [
             pkgs.gcc
+            pkgs.glibc.static
             pkgs.gnumake
-            pkgs.ncurses.dev
-            pkgs.notcurses
-            pkgs.pkg-config
             pkgs.bear
+            pkgs.qemu_kvm
+            pkgs.OVMF
           ];
           shellHook = ''
             export PS1="(tonarchy-dev) $PS1"
             echo "tonarchy development environment"
             echo "Run 'make' to build"
-            echo "Run 'make -f Makefile.notcurses && ./notcurses_demo' to see notcurses demo"
+            echo "Run './vm-test [iso-path]' to test an ISO in qemu"
           '';
         };
       });
diff --git a/src/main.c b/src/main.c
index d7ed675..de24d4b 100644
--- a/src/main.c
+++ b/src/main.c
@@ -689,6 +689,307 @@ static int select_disk(char *disk_name) {
     return 1;
 }
 
+static int partition_disk(const char *disk) {
+    char cmd[1024];
+    int rows, cols;
+    get_terminal_size(&rows, &cols);
+
+    clear_screen();
+    draw_logo(cols);
+
+    int logo_start = (cols - 70) / 2;
+    printf("\033[%d;%dH\033[37mPartitioning /dev/%s...\033[0m", 10, logo_start, disk);
+    fflush(stdout);
+
+    snprintf(cmd, sizeof(cmd), "wipefs -af /dev/%s 2>&1", disk);
+    if (system(cmd) != 0) {
+        show_message("Failed to wipe disk");
+        return 0;
+    }
+
+    snprintf(cmd, sizeof(cmd), "sgdisk --zap-all /dev/%s 2>&1", disk);
+    if (system(cmd) != 0) {
+        show_message("Failed to zap disk");
+        return 0;
+    }
+
+    snprintf(cmd, sizeof(cmd),
+        "sgdisk --clear "
+        "--new=1:0:+1G --typecode=1:ef00 --change-name=1:EFI "
+        "--new=2:0:+4G --typecode=2:8200 --change-name=2:swap "
+        "--new=3:0:0 --typecode=3:8300 --change-name=3:root "
+        "/dev/%s 2>&1", disk);
+    if (system(cmd) != 0) {
+        show_message("Failed to create partitions");
+        return 0;
+    }
+
+    printf("\033[%d;%dH\033[37mFormatting partitions...\033[0m", 11, logo_start);
+    fflush(stdout);
+
+    snprintf(cmd, sizeof(cmd), "mkfs.fat -F32 /dev/%s1 2>&1", disk);
+    if (system(cmd) != 0) {
+        show_message("Failed to format EFI partition");
+        return 0;
+    }
+
+    snprintf(cmd, sizeof(cmd), "mkswap /dev/%s2 2>&1", disk);
+    if (system(cmd) != 0) {
+        show_message("Failed to format swap partition");
+        return 0;
+    }
+
+    snprintf(cmd, sizeof(cmd), "mkfs.ext4 -F /dev/%s3 2>&1", disk);
+    if (system(cmd) != 0) {
+        show_message("Failed to format root partition");
+        return 0;
+    }
+
+    printf("\033[%d;%dH\033[37mMounting partitions...\033[0m", 12, logo_start);
+    fflush(stdout);
+
+    snprintf(cmd, sizeof(cmd), "mount /dev/%s3 /mnt 2>&1", disk);
+    if (system(cmd) != 0) {
+        show_message("Failed to mount root partition");
+        return 0;
+    }
+
+    snprintf(cmd, sizeof(cmd), "mkdir -p /mnt/boot 2>&1");
+    system(cmd);
+
+    snprintf(cmd, sizeof(cmd), "mount /dev/%s1 /mnt/boot 2>&1", disk);
+    if (system(cmd) != 0) {
+        show_message("Failed to mount EFI partition");
+        return 0;
+    }
+
+    snprintf(cmd, sizeof(cmd), "swapon /dev/%s2 2>&1", disk);
+    if (system(cmd) != 0) {
+        show_message("Failed to enable swap");
+        return 0;
+    }
+
+    show_message("Disk prepared successfully!");
+    return 1;
+}
+
+static int install_packages(const char *package_list) {
+    int rows, cols;
+    get_terminal_size(&rows, &cols);
+
+    clear_screen();
+    draw_logo(cols);
+
+    int logo_start = (cols - 70) / 2;
+    printf("\033[%d;%dH\033[37mInstalling system packages...\033[0m", 10, logo_start);
+    printf("\033[%d;%dH\033[37mThis will take several minutes.\033[0m", 11, logo_start);
+    fflush(stdout);
+
+    char cmd[512];
+    snprintf(cmd, sizeof(cmd), "pacstrap -K /mnt $(cat %s)", package_list);
+
+    if (system(cmd) != 0) {
+        show_message("Failed to install packages");
+        return 0;
+    }
+
+    show_message("Packages installed successfully!");
+    return 1;
+}
+
+static int configure_system(const char *username, const char *password,
+                           const char *hostname, const char *keyboard,
+                           const char *timezone, const char *disk, int use_dm) {
+    char cmd[4096];
+    int rows, cols;
+    get_terminal_size(&rows, &cols);
+
+    clear_screen();
+    draw_logo(cols);
+
+    int logo_start = (cols - 70) / 2;
+    printf("\033[%d;%dH\033[37mConfiguring system...\033[0m", 10, logo_start);
+    printf("\033[%d;%dH\033[90m(Logging to /tmp/tonarchy-install.log)\033[0m", 11, logo_start);
+    fflush(stdout);
+
+    system("echo '=== Tonarchy Installation Log ===' > /tmp/tonarchy-install.log");
+    system("date >> /tmp/tonarchy-install.log");
+
+    if (system("genfstab -U /mnt >> /mnt/etc/fstab 2>> /tmp/tonarchy-install.log") != 0) {
+        show_message("Failed to generate fstab - check /tmp/tonarchy-install.log");
+        return 0;
+    }
+
+    snprintf(cmd, sizeof(cmd),
+        "arch-chroot /mnt /bin/bash -c '\n"
+        "ln -sf /usr/share/zoneinfo/%s /etc/localtime\n"
+        "hwclock --systohc\n"
+        "echo \"en_US.UTF-8 UTF-8\" >> /etc/locale.gen\n"
+        "locale-gen\n"
+        "echo \"LANG=en_US.UTF-8\" > /etc/locale.conf\n"
+        "echo \"KEYMAP=%s\" > /etc/vconsole.conf\n"
+        "echo \"%s\" > /etc/hostname\n"
+        "cat > /etc/hosts <<EOF\n"
+        "127.0.0.1   localhost\n"
+        "::1         localhost\n"
+        "127.0.1.1   %s.localdomain %s\n"
+        "EOF\n"
+        "useradd -m -G wheel -s /bin/bash %s\n"
+        "echo \"%s:%s\" | chpasswd\n"
+        "echo \"root:%s\" | chpasswd\n"
+        "sed -i \"s/^# %%wheel ALL=(ALL:ALL) ALL/%%wheel ALL=(ALL:ALL) ALL/\" /etc/sudoers\n"
+        "systemctl enable NetworkManager\n"
+        "%s"
+        "' >> /tmp/tonarchy-install.log 2>&1",
+        timezone, keyboard, hostname, hostname, hostname,
+        username, username, password, password,
+        use_dm ? "systemctl enable lightdm\n" : "");
+
+    system("echo '=== Running configure_system ===' >> /tmp/tonarchy-install.log");
+    if (system(cmd) != 0) {
+        show_message("Failed to configure system - check /tmp/tonarchy-install.log");
+        return 0;
+    }
+
+    show_message("System configured successfully!");
+    return 1;
+}
+
+static int install_bootloader(const char *disk) {
+    char cmd[2048];
+    int rows, cols;
+    get_terminal_size(&rows, &cols);
+
+    clear_screen();
+    draw_logo(cols);
+
+    int logo_start = (cols - 70) / 2;
+    printf("\033[%d;%dH\033[37mInstalling bootloader...\033[0m", 10, logo_start);
+    fflush(stdout);
+
+    snprintf(cmd, sizeof(cmd),
+        "arch-chroot /mnt /bin/bash -c '\n"
+        "bootctl install\n"
+        "cat > /boot/loader/loader.conf <<EOF\n"
+        "default arch.conf\n"
+        "timeout 3\n"
+        "console-mode max\n"
+        "editor no\n"
+        "EOF\n"
+        "cat > /boot/loader/entries/arch.conf <<EOF\n"
+        "title   Tonarchy\n"
+        "linux   /vmlinuz-linux\n"
+        "initrd  /initramfs-linux.img\n"
+        "options root=/dev/%s3 rw\n"
+        "EOF\n"
+        "'",
+        disk);
+
+    if (system(cmd) != 0) {
+        show_message("Failed to install bootloader");
+        return 0;
+    }
+
+    show_message("Bootloader installed successfully!");
+    return 1;
+}
+
+static int configure_cinnamon_keybinds(const char *username) {
+    char cmd[4096];
+    int rows, cols;
+    get_terminal_size(&rows, &cols);
+
+    clear_screen();
+    draw_logo(cols);
+
+    int logo_start = (cols - 70) / 2;
+    printf("\033[%d;%dH\033[37mConfiguring Cinnamon keybinds...\033[0m", 10, logo_start);
+    fflush(stdout);
+
+    snprintf(cmd, sizeof(cmd),
+        "arch-chroot /mnt sudo -u %s dbus-run-session bash -c '\n"
+        "dconf write /org/cinnamon/desktop/keybindings/custom-keybindings/custom0/binding \"[\\\"<Super>Return\\\"]\"\n"
+        "dconf write /org/cinnamon/desktop/keybindings/custom-keybindings/custom0/command \"\\\"alacritty\\\"\"\n"
+        "dconf write /org/cinnamon/desktop/keybindings/custom-keybindings/custom0/name \"\\\"Terminal\\\"\"\n"
+        "dconf write /org/cinnamon/desktop/keybindings/custom-keybindings/custom1/binding \"[\\\"<Super>b\\\"]\"\n"
+        "dconf write /org/cinnamon/desktop/keybindings/custom-keybindings/custom1/command \"\\\"firefox\\\"\"\n"
+        "dconf write /org/cinnamon/desktop/keybindings/custom-keybindings/custom1/name \"\\\"Browser\\\"\"\n"
+        "dconf write /org/cinnamon/desktop/keybindings/custom-keybindings/custom2/binding \"[\\\"<Super>e\\\"]\"\n"
+        "dconf write /org/cinnamon/desktop/keybindings/custom-keybindings/custom2/command \"\\\"nemo\\\"\"\n"
+        "dconf write /org/cinnamon/desktop/keybindings/custom-keybindings/custom2/name \"\\\"File Manager\\\"\"\n"
+        "dconf write /org/cinnamon/desktop/keybindings/custom-list \"[\\\"custom0\\\", \\\"custom1\\\", \\\"custom2\\\"]\"\n"
+        "dconf write /org/cinnamon/desktop/keybindings/wm/close \"[\\\"<Super>q\\\", \\\"<Alt>F4\\\"]\"\n"
+        "dconf write /org/cinnamon/desktop/keybindings/wm/toggle-fullscreen \"[\\\"<Super>f\\\"]\"\n"
+        "dconf write /org/cinnamon/desktop/keybindings/wm/push-tile-left \"[\\\"<Super>Left\\\"]\"\n"
+        "dconf write /org/cinnamon/desktop/keybindings/wm/push-tile-right \"[\\\"<Super>Right\\\"]\"\n"
+        "'",
+        username);
+
+    if (system(cmd) != 0) {
+        show_message("Warning: Failed to configure keybinds (can be done manually)");
+        return 1;
+    }
+
+    show_message("Cinnamon keybinds configured!");
+    return 1;
+}
+
+static int install_suckless_tools(const char *username) {
+    int rows, cols;
+    get_terminal_size(&rows, &cols);
+
+    clear_screen();
+    draw_logo(cols);
+
+    int logo_start = (cols - 70) / 2;
+    printf("\033[%d;%dH\033[37mInstalling suckless tools (dwm, st, dmenu)...\033[0m", 10, logo_start);
+    printf("\033[%d;%dH\033[37mCloning and building from source...\033[0m", 11, logo_start);
+    fflush(stdout);
+
+    // Copy wallpaper to /mnt/tmp first
+    system("cp walls/wall1.jpg /mnt/tmp/wall1.jpg 2>/dev/null");
+
+    char cmd[4096];
+    snprintf(cmd, sizeof(cmd),
+        "arch-chroot /mnt /bin/bash -c '\n"
+        "cd /home/%s\n"
+        "sudo -u %s git clone https://github.com/tonybanters/dwm\n"
+        "sudo -u %s git clone https://github.com/tonybanters/st\n"
+        "sudo -u %s git clone https://github.com/tonybanters/dmenu\n"
+        "cd dwm && make clean install\n"
+        "cd ../st && make clean install\n"
+        "cd ../dmenu && make clean install\n"
+        "cd /home/%s\n"
+        "sudo -u %s mkdir -p .config walls\n"
+        "mv /tmp/wall1.jpg /home/%s/walls/wall1.jpg 2>/dev/null || true\n"
+        "chown %s:%s /home/%s/walls/wall1.jpg 2>/dev/null || true\n"
+        "echo \"xwallpaper --zoom \\$HOME/walls/wall1.jpg &\" > /home/%s/.xinitrc\n"
+        "echo \"exec dwm\" >> /home/%s/.xinitrc\n"
+        "chown %s:%s /home/%s/.xinitrc\n"
+        "chmod +x /home/%s/.xinitrc\n"
+        "echo \"if [ -z \\$DISPLAY ] && [ \\$XDG_VTNR = 1 ]; then\" > /home/%s/.bash_profile\n"
+        "echo \"  exec startx\" >> /home/%s/.bash_profile\n"
+        "echo \"fi\" >> /home/%s/.bash_profile\n"
+        "chown %s:%s /home/%s/.bash_profile\n"
+        "mkdir -p /etc/systemd/system/getty@tty1.service.d\n"
+        "echo \"[Service]\" > /etc/systemd/system/getty@tty1.service.d/autologin.conf\n"
+        "echo \"ExecStart=\" >> /etc/systemd/system/getty@tty1.service.d/autologin.conf\n"
+        "echo \"ExecStart=-/sbin/agetty -o \\\"-p -f -- \\\\\\\\u\\\" --noclear --autologin %s %%I \\$TERM\" >> /etc/systemd/system/getty@tty1.service.d/autologin.conf\n"
+        "'",
+        username, username, username, username, username, username,
+        username, username, username, username, username, username,
+        username, username, username, username, username, username,
+        username, username, username, username, username);
+
+    if (system(cmd) != 0) {
+        show_message("Warning: Failed to install suckless tools (can be done manually)");
+        return 1;
+    }
+
+    show_message("Suckless tools installed successfully!");
+    return 1;
+}
+
 int main(void) {
     char username[256] = "";
     char password[256] = "";
@@ -702,9 +1003,9 @@ int main(void) {
     }
 
     const char *levels[] = {
-        "Beginner (We'll pick everything for you.)",
-        "Intermediate (choose desktop & tools)",
-        "Advanced (full customization)"
+        "Beginner (Cinnamon desktop - perfect for starters)",
+        "Tony-Suckless (dwm + minimal setup)",
+        "Expert (Coming soon...)"
     };
 
     int level = select_from_menu(levels, 3);
@@ -717,14 +1018,93 @@ int main(void) {
         return 1;
     }
 
-    clear_screen();
-    printf("Installation would proceed with:\n");
-    printf("Username: %s\n", username);
-    printf("Hostname: %s\n", hostname);
-    printf("Keyboard: %s\n", keyboard);
-    printf("Timezone: %s\n", timezone);
-    printf("Level: %s\n", levels[level]);
-    printf("Disk: /dev/%s\n", disk);
+    if (level == 0) {
+        if (!partition_disk(disk)) {
+            return 1;
+        }
+
+        if (!install_packages("packages/beginner.txt")) {
+            return 1;
+        }
+
+        if (!configure_system(username, password, hostname, keyboard, timezone, disk, 1)) {
+            return 1;
+        }
+
+        if (!install_bootloader(disk)) {
+            return 1;
+        }
+
+        configure_cinnamon_keybinds(username);
+
+        clear_screen();
+        int rows, cols;
+        get_terminal_size(&rows, &cols);
+        draw_logo(cols);
+
+        int logo_start = (cols - 70) / 2;
+        printf("\033[%d;%dH\033[1;32mInstallation complete!\033[0m", 10, logo_start);
+        printf("\033[%d;%dH\033[37mYou can now reboot into your new system.\033[0m", 12, logo_start);
+        printf("\033[%d;%dH\033[37mPress any key to exit...\033[0m", 14, logo_start);
+        fflush(stdout);
+
+        enable_raw_mode();
+        char c;
+        read(STDIN_FILENO, &c, 1);
+        disable_raw_mode();
+    } else if (level == 1) {
+        // Tony-Suckless mode
+        if (!partition_disk(disk)) {
+            return 1;
+        }
+
+        if (!install_packages("packages/suckless.txt")) {
+            return 1;
+        }
+
+        if (!configure_system(username, password, hostname, keyboard, timezone, disk, 0)) {
+            return 1;
+        }
+
+        if (!install_bootloader(disk)) {
+            return 1;
+        }
+
+        install_suckless_tools(username);
+
+        clear_screen();
+        int rows, cols;
+        get_terminal_size(&rows, &cols);
+        draw_logo(cols);
+
+        int logo_start = (cols - 70) / 2;
+        printf("\033[%d;%dH\033[1;32mInstallation complete!\033[0m", 10, logo_start);
+        printf("\033[%d;%dH\033[37mYou can now reboot into your new system.\033[0m", 12, logo_start);
+        printf("\033[%d;%dH\033[37mPress any key to exit...\033[0m", 14, logo_start);
+        fflush(stdout);
+
+        enable_raw_mode();
+        char c;
+        read(STDIN_FILENO, &c, 1);
+        disable_raw_mode();
+    } else {
+        // Expert mode - coming soon
+        clear_screen();
+        int rows, cols;
+        get_terminal_size(&rows, &cols);
+        draw_logo(cols);
+
+        int logo_start = (cols - 70) / 2;
+        printf("\033[%d;%dH\033[1;33mExpert mode coming soon!\033[0m", 10, logo_start);
+        printf("\033[%d;%dH\033[37mThis mode will allow full customization of your installation.\033[0m", 12, logo_start);
+        printf("\033[%d;%dH\033[37mPress any key to exit...\033[0m", 14, logo_start);
+        fflush(stdout);
+
+        enable_raw_mode();
+        char c;
+        read(STDIN_FILENO, &c, 1);
+        disable_raw_mode();
+    }
 
     return 0;
 }