147 lines
3.5 KiB
C++
147 lines
3.5 KiB
C++
/*
|
|
* shell.h
|
|
* Shared declarations for the MontaukOS interactive shell
|
|
* Copyright (c) 2025-2026 Daniel Hammer
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <montauk/syscall.h>
|
|
#include <montauk/string.h>
|
|
#include <montauk/heap.h>
|
|
#include <montauk/config.h>
|
|
|
|
using montauk::slen;
|
|
using montauk::streq;
|
|
using montauk::starts_with;
|
|
using montauk::skip_spaces;
|
|
|
|
// ---- Inline string helpers ----
|
|
|
|
inline void scopy(char* dst, const char* src, int maxLen) {
|
|
int i = 0;
|
|
while (src[i] && i < maxLen - 1) { dst[i] = src[i]; i++; }
|
|
dst[i] = '\0';
|
|
}
|
|
|
|
inline void scat(char* dst, const char* src, int maxLen) {
|
|
int dLen = slen(dst);
|
|
int i = 0;
|
|
while (src[i] && dLen + i < maxLen - 1) {
|
|
dst[dLen + i] = src[i];
|
|
i++;
|
|
}
|
|
dst[dLen + i] = '\0';
|
|
}
|
|
|
|
inline void int_to_str(int n, char* buf, int sz) {
|
|
if (n == 0) { buf[0] = '0'; buf[1] = '\0'; return; }
|
|
bool neg = false;
|
|
unsigned int u;
|
|
if (n < 0) { neg = true; u = (unsigned)(-n); } else { u = (unsigned)n; }
|
|
char tmp[12];
|
|
int i = 0;
|
|
while (u > 0) { tmp[i++] = '0' + u % 10; u /= 10; }
|
|
int o = 0;
|
|
if (neg && o < sz - 1) buf[o++] = '-';
|
|
while (i > 0 && o < sz - 1) buf[o++] = tmp[--i];
|
|
buf[o] = '\0';
|
|
}
|
|
|
|
// ---- Shared state (defined in main.cpp) ----
|
|
|
|
extern char cwd[128];
|
|
extern int current_drive;
|
|
extern int last_exit;
|
|
extern char session_user[32];
|
|
extern char session_home[64];
|
|
|
|
// ---- Inline path helpers ----
|
|
|
|
inline void build_drive_path(int drive, const char* dir, char* out, int outMax) {
|
|
int i = 0;
|
|
if (drive >= 10) { out[i++] = '0' + drive / 10; }
|
|
out[i++] = '0' + drive % 10;
|
|
out[i++] = ':'; out[i++] = '/';
|
|
if (dir && dir[0]) {
|
|
int j = 0;
|
|
while (dir[j] && i < outMax - 1) out[i++] = dir[j++];
|
|
}
|
|
out[i] = '\0';
|
|
}
|
|
|
|
inline void build_dir_path(const char* dir, char* out, int outMax) {
|
|
build_drive_path(current_drive, dir, out, outMax);
|
|
}
|
|
|
|
inline int parse_drive_prefix(const char* s) {
|
|
if (s[0] < '0' || s[0] > '9') return -1;
|
|
int n = s[0] - '0';
|
|
if (s[1] >= '0' && s[1] <= '9') {
|
|
n = n * 10 + (s[1] - '0');
|
|
if (s[2] != ':') return -1;
|
|
} else if (s[1] == ':') {
|
|
// single digit drive
|
|
} else {
|
|
return -1;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
inline int drive_prefix_len(const char* s) {
|
|
if (s[1] >= '0' && s[1] <= '9') return 3;
|
|
return 2;
|
|
}
|
|
|
|
inline bool has_drive_prefix(const char* s) {
|
|
return parse_drive_prefix(s) >= 0;
|
|
}
|
|
|
|
// ---- Variables (vars.cpp) ----
|
|
|
|
void var_set(const char* name, const char* value);
|
|
void var_unset(const char* name);
|
|
const char* var_get(const char* name);
|
|
bool is_var_char(char c);
|
|
void expand_vars(const char* in, char* out, int outMax);
|
|
void expand_tilde(const char* in, char* out, int outMax);
|
|
void strip_comment(char* line);
|
|
int var_user_count();
|
|
const char* var_user_name(int idx);
|
|
const char* var_user_value(int idx);
|
|
|
|
// ---- Session (main.cpp) ----
|
|
|
|
void read_session();
|
|
void sync_cwd();
|
|
|
|
// ---- Builtins (builtins.cpp) ----
|
|
|
|
void cmd_help();
|
|
void cmd_ls(const char* arg);
|
|
int cmd_cd(const char* arg);
|
|
int cmd_man(const char* arg);
|
|
bool switch_drive(int drive);
|
|
|
|
// ---- External execution (exec.cpp) ----
|
|
|
|
int exec_external(const char* cmd, const char* args);
|
|
|
|
// ---- Tab completion (tabcompletion.cpp) ----
|
|
|
|
int get_completions(char* string, char** array, int arrayMax, char* cwd = nullptr, int volume_number = 0);
|
|
|
|
// ---- Shell builtins ----
|
|
|
|
constexpr const char* shell_builtins[] = {
|
|
"help",
|
|
"ls",
|
|
"cd",
|
|
"pwd",
|
|
"echo",
|
|
"set",
|
|
"unset",
|
|
"true",
|
|
"false",
|
|
"exit"
|
|
}; |