toaruos/kernel/core/shell.c
2011-04-14 15:27:03 -05:00

272 lines
8.1 KiB
C

/*
* vim:tabstop=4
* vim:noexpandtab
*
* ToAruOS Kernel Debugger Shell
*
* Part of the ToAruOS Kernel, under the NCSA license
*
* Copyright 2011 Kevin Lange
*
* (Preliminary documentation based on intended future use; currently,
* this is just a file system explorer)
*
* This is a kernel debugging shell that allows basic, sh-like operation
* of the system while it is in use, without other tasks running in the
* background. While the debug shell is running, the tasker is disabled
* and the kernel will remainin on its current task, allowing users to
* display registry and memory information relavent to the current task.
*
*/
#include <system.h>
#include <fs.h>
#include <multiboot.h>
void
start_shell() {
/* Current working directory */
char path[1024] = {'/', '\0'};
/* File system node for the working directory */
fs_node_t * node = fs_root;
char * username = "kernel";
char * hostname = "toaru";
while (1) {
/* Read buffer */
char buffer[1024];
int size;
/* Print the prompt */
uint16_t month, day, hours, minutes, seconds;
get_date(&month, &day);
get_time(&hours, &minutes, &seconds);
kprintf("\033[1m[\033[1;33m%s \033[1;32m%s \033[1;31m%d/%d \033[1;34m%d:%d:%d\033[0m \033[0m%s\033[1m]\033[0m\n\033[1;32m$\033[0m ",
username, hostname, month, day, hours, minutes, seconds, path);
/* Read commands */
size = kgets((char *)&buffer, 1023);
if (size < 1) {
continue;
} else {
/*
* Tokenize the command
*/
char * pch;
char * cmd;
char * save;
pch = strtok_r(buffer," ",&save);
cmd = pch;
if (!cmd) { continue; }
char * argv[1024]; /* Command tokens (space-separated elements) */
int tokenid = 0;
while (pch != NULL) {
argv[tokenid] = (char *)pch;
++tokenid;
pch = strtok_r(NULL," ",&save);
}
argv[tokenid] = NULL;
/*
* Execute the command
*/
if (!strcmp(cmd, "cd")) {
/*
* Change Directory
*/
if (tokenid < 2) {
kprintf("cd: argument expected\n");
continue;
} else {
char * filename = malloc(sizeof(char) * 1024);
if (argv[1][0] == '/') {
memcpy(filename, argv[1], strlen(argv[1]) + 1);
} else {
memcpy(filename, path, strlen(path));
if (!strcmp(path,"/")) {
memcpy((void *)((uintptr_t)filename + strlen(path)),argv[1],strlen(argv[1])+1);
} else {
filename[strlen(path)] = '/';
memcpy((void *)((uintptr_t)filename + strlen(path) + 1),argv[1],strlen(argv[1])+1);
}
}
fs_node_t * chd = kopen(filename, 0);
if (chd) {
if ((chd->flags & FS_DIRECTORY) == 0) {
kprintf("cd: %s is not a directory\n", filename);
continue;
}
node = chd;
memcpy(path, filename, strlen(filename));
path[strlen(filename)] = '\0';
} else {
kprintf("cd: could not change directory\n");
}
}
} else if (!strcmp(cmd, "cat")) {
/*
* Read and print content of file
*/
if (tokenid < 2) {
kprintf("cat: argument expected\n");
continue;
} else {
char * filename = malloc(sizeof(char) * 1024);
if (argv[1][0] == '/') {
memcpy(filename, argv[1], strlen(argv[1]) + 1);
} else {
memcpy(filename, path, strlen(path));
if (!strcmp(path,"/")) {
memcpy((void *)((uintptr_t)filename + strlen(path)),argv[1],strlen(argv[1])+1);
} else {
filename[strlen(path)] = '/';
memcpy((void *)((uintptr_t)filename + strlen(path) + 1),argv[1],strlen(argv[1])+1);
}
}
fs_node_t * file = kopen(filename,0);
free(filename);
if (!file) {
kprintf("cat: could not open file `%s`\n", argv[1]);
continue;
}
char *bufferb = malloc(file->length + 200);
size_t bytes_read = read_fs(file, 0, file->length, (uint8_t *)bufferb);
size_t i = 0;
for (i = 0; i < bytes_read; ++i) {
ansi_put(bufferb[i]);
}
free(bufferb);
close_fs(file);
}
} else if (!strcmp(cmd, "ls")) {
/*
* List the files in the current working directory
*/
struct dirent * entry = NULL;
int i = 0;
entry = readdir_fs(node, i);
while (entry != NULL) {
kprintf("%s\n", entry->name);
free(entry);
i++;
entry = readdir_fs(node, i);
}
} else if (!strcmp(cmd, "info")) {
kprintf("Flags: 0x%x\n", node->flags);
} else if (!strcmp(cmd, "help")) {
kprintf("\033[1;34m");
kprintf(" - ToAruOS Kernel Debug Shell - \n");
kprintf("\033[0m");
kprintf(" This is the ToAruOS kernel debugging environment.\n");
kprintf(" From here, you have access to the virtual file system layer and \n");
kprintf(" can read files, list files in directories, dump memory, registers,\n");
kprintf(" and a few other things.\n");
} else if (!strcmp(cmd, "out")) {
if (tokenid < 3) {
kprintf("Need a port and a character (both as numbers, please) to write...\n");
} else {
int port;
port = atoi(argv[1]);
int val;
val = atoi(argv[2]);
kprintf("Writing %d (%c) to port %d\n", val, (unsigned char)val, port);
outportb((short)port, (unsigned char)val);
}
} else if (!strcmp(cmd, "serial")) {
if (tokenid < 2) {
kprintf("Need some arguments.\n");
} else {
int i = 1;
for (i = 1; i < tokenid; ++i) {
int j = 0;
for (j = 0; j < strlen(argv[i]); ++j) {
serial_send(argv[i][j]);
writech(argv[i][j]);
}
writech(' ');
}
serial_send('\n');
writech('\n');
}
} else if (!strcmp(cmd, "clear")) {
cls();
} else if (!strcmp(cmd, "crash")) {
kprintf("Going to dereference some invalid pointers.\n");
int i = 0xFFFFFFFF;
int j = *(int *)i;
j = 0xDEADBEEF;
} else if (!strcmp(cmd, "exit")) {
kprintf("Good byte.\n");
break;
} else if (!strcmp(cmd, "cpu-detect")) {
detect_cpu();
} else if (!strcmp(cmd, "scroll")) {
bochs_scroll();
} else if (!strcmp(cmd, "logo")) {
if (tokenid < 2) {
bochs_draw_logo("/bs.bmp");
} else {
bochs_draw_logo(argv[1]);
}
} else if (!strcmp(cmd, "line")) {
if (tokenid < 5) {
bochs_draw_line(0,1024,0,768, 0xFFFFFF);
} else {
bochs_draw_line(atoi(argv[1]),atoi(argv[2]),atoi(argv[3]),atoi(argv[4]),0xFFFFFF);
}
} else if (!strcmp(cmd, "exec")) {
if (tokenid < 2) {
continue;
}
int ret = exec(argv[1],tokenid - 1, &argv[1]);
kprintf("Returned %d\n", ret);
} else if (!strcmp(cmd, "boredom")) {
int x = 30;
if (tokenid > 1) {
x = atoi(argv[1]);
}
for (int derp = 0; derp < x; ++derp) {
int x0 = krand() % 1024;
int x1 = krand() % 1024;
int y0 = krand() % 768;
int y1 = krand() % 768;
bochs_draw_line(x0,x1,y0,y1, krand() % 0xFFFFFF);
}
} else if (!strcmp(cmd, "test-scroll")) {
bochs_set_y_offset(12 * 20);
} else if (!strcmp(cmd, "reset-keyboard")) {
/* Reset the shift/alt/ctrl statuses, in case they get messed up */
set_kbd(0,0,0);
} else if (!strcmp(cmd, "test-ansi")) {
ansi_print("This is a \033[32mtest\033[0m of the \033[33mANSI\033[0m driver.\n");
ansi_print("This is a \033[32;1mte\033[34mst\033[0m of \033[1mthe \033[33mANSI\033[0m driver.\n");
} else if (!strcmp(cmd, "multiboot")) {
dump_multiboot(mboot_ptr);
} else {
/* Alright, here we go */
char * filename = malloc(sizeof(char) * 1024);
if (argv[0][0] == '/') {
memcpy(filename, argv[0], strlen(argv[0]) + 1);
} else {
memcpy(filename, path, strlen(path));
if (!strcmp(path,"/")) {
memcpy((void *)((uintptr_t)filename + strlen(path)),argv[0],strlen(argv[0])+1);
} else {
filename[strlen(path)] = '/';
memcpy((void *)((uintptr_t)filename + strlen(path) + 1),argv[0],strlen(argv[0])+1);
}
}
fs_node_t * chd = kopen(filename, 0);
if (!chd) {
/* Alright, let's try this... */
char * search_path = "/bin/";
memcpy(filename, search_path, strlen(search_path));
memcpy((void*)((uintptr_t)filename + strlen(search_path)),argv[0],strlen(argv[0])+1);
chd = kopen(filename, 0);
}
if (!chd) {
kprintf("Unrecognized command: %s\n", cmd);
} else {
close_fs(chd);
exec(filename, tokenid, argv);
}
}
}
}
}