Files
MontaukOS/programs/src/shell/builtins.cpp
T

149 lines
4.8 KiB
C++

/*
* builtins.cpp
* Shell builtin commands: help, ls, cd, man
* Copyright (c) 2025-2026 Daniel Hammer
*/
#include "shell.h"
static void print_ls_entry(const char* entry) {
int len = slen(entry);
bool hadTrailingSlash = len > 0 && entry[len - 1] == '/';
while (len > 0 && entry[len - 1] == '/') len--;
int base = 0;
for (int i = 0; i < len; i++) {
if (entry[i] == '/') base = i + 1;
}
for (int i = base; i < len; i++) montauk::putchar(entry[i]);
if (hadTrailingSlash) montauk::putchar('/');
}
// ---- help ----
void cmd_help() {
montauk::print("Shell builtins:\n");
montauk::print(" help Show this help message\n");
montauk::print(" ls [dir] List files in directory\n");
montauk::print(" cd [dir] Change working directory\n");
montauk::print(" pwd Print working directory\n");
montauk::print(" echo [-n] ... Print arguments\n");
montauk::print(" set [VAR=val] Show or set shell variables\n");
montauk::print(" unset VAR Remove a shell variable\n");
montauk::print(" true / false Return success / failure\n");
montauk::print(" N: Switch to drive N (e.g. 1:)\n");
montauk::print(" exit Exit the shell\n");
montauk::print("\n");
montauk::print("Syntax:\n");
montauk::print(" VAR=value Set a shell variable\n");
montauk::print(" $VAR ${VAR} Variable expansion\n");
montauk::print(" ~ Expands to home directory\n");
montauk::print(" cmd1 ; cmd2 Run commands sequentially\n");
montauk::print(" cmd1 && cmd2 Run cmd2 if cmd1 succeeds\n");
montauk::print(" cmd1 || cmd2 Run cmd2 if cmd1 fails\n");
montauk::print(" # comment Comment (ignored)\n");
montauk::print("\n");
montauk::print("Built-in variables:\n");
montauk::print(" $USER $HOME $PWD $?\n");
montauk::print("\n");
montauk::print("System commands:\n");
montauk::print(" man <topic> View manual pages\n");
montauk::print(" cat <file> Display file contents\n");
montauk::print(" edit [file] Text editor\n");
montauk::print(" whoami Print current username\n");
montauk::print(" info Show system information\n");
montauk::print(" date Show current date and time\n");
montauk::print(" uptime Show uptime\n");
montauk::print(" clear Clear the screen\n");
montauk::print(" fontscale [n] Set terminal font scale (1-8)\n");
montauk::print(" reset Reboot the system\n");
montauk::print(" shutdown Shut down the system\n");
montauk::print("\n");
montauk::print("Network commands:\n");
montauk::print(" ping <ip> Send ICMP echo requests\n");
montauk::print(" nslookup DNS lookup\n");
montauk::print(" ifconfig Show/set network configuration\n");
montauk::print(" tcpconnect Connect to a TCP server\n");
montauk::print(" irc IRC client\n");
montauk::print(" dhcp DHCP client\n");
montauk::print(" fetch <url> HTTP client\n");
montauk::print(" httpd HTTP server\n");
}
// ---- ls ----
void cmd_ls(const char* arg) {
arg = skip_spaces(arg);
char path[128];
if (*arg) scopy(path, arg, sizeof(path));
else scopy(path, ".", sizeof(path));
const char* entries[64];
int count = montauk::readdir(path, entries, 64);
if (count <= 0) {
montauk::print("(empty)\n");
return;
}
for (int i = 0; i < count; i++) {
montauk::print(" ");
print_ls_entry(entries[i]);
montauk::putchar('\n');
}
}
// ---- cd ----
bool switch_drive(int drive) {
char path[8];
build_drive_path(drive, "", path, sizeof(path));
if (montauk::chdir(path) < 0) return false;
sync_cwd();
return true;
}
int cmd_cd(const char* arg) {
arg = skip_spaces(arg);
char target[128];
if (*arg == '\0') {
if (session_home[0]) scopy(target, session_home, sizeof(target));
else scopy(target, "/", sizeof(target));
} else {
scopy(target, arg, sizeof(target));
}
if (montauk::chdir(target) < 0) {
montauk::print("cd: no such directory: ");
montauk::print(target);
montauk::putchar('\n');
return 1;
}
sync_cwd();
return 0;
}
// ---- man ----
int cmd_man(const char* arg) {
arg = skip_spaces(arg);
if (*arg == '\0') {
montauk::print("Usage: man <topic>\n");
montauk::print(" man <section> <topic>\n");
montauk::print("Try: man intro\n");
return 1;
}
int pid = montauk::spawn("0:/os/man.elf", arg);
if (pid < 0) {
montauk::print("Error: failed to start man viewer\n");
return 1;
}
montauk::waitpid(pid);
return 0;
}