rendered paste body/*
* This file is part of Popcorn.
* Copyright (C) 2007 Mike Smith.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <lib/types.hpp>
#include <lib/String.hpp>
#include <VConsole.hpp>
#include <Keyboard.hpp>
#include <Timer.hpp>
#include <Panic.hpp>
#include <lib/Assert.hpp>
#include <lib/Alloc.hpp>
#include <Tasks.hpp>
#include <DebugConsole.hpp>
#include <lib/LinkedList.hpp>
#include <Power.hpp>
namespace KShell
{
typedef struct
{
const char *name;
const char *text;
} help_t;
help_t help[] =
{
{ "help", "Show this help menu" },
{ "echo <text>", "Print text to the screen" },
{ "halt", "Halt the CPU" },
{ "reboot", "Restart your computer" },
{ "uptime", "Show how long Popcorn has been running" },
{ "syscall", "Test system calls (should print 'A' to screen)" },
{ "crash", "Crash the computer in a way of your choice" },
{ "kitty", "Show the obligatory ASCII Art Kitty" },
{ "tasks", "List currently running tasks" },
{ "exit", "Exit KShell" }
};
char cmdbuf[1024];
void getcmd()
{
String::memset(cmdbuf, 0, 1024);
int i = 0;
while (i < 1024)
{
uint_16 key = cout.getchar();
if (key & 0xF000)
{
cdebug << "[kshell] non-printing key pressed\n";
}
else if (key == '\b')
{
if (i)
{
cmdbuf[--i] = 0;
cout << '\b';
}
}
else if (key == '\n')
{
cout << "\n";
return;
}
else if (Keyboard::is_ctrl_on() && key == 'c')
{
// ^C pressed, clear buffer and return
String::memset(cmdbuf, 0, 1024);
cout << "\n";
return;
}
else if (Keyboard::is_ctrl_on() && key == 'l')
{
// ^L: Clear screen
String::memset(cmdbuf, 0, 1024);
cout.clear();
return;
}
else
{
cout << (char)key;
cmdbuf[i++] = (char)key;
}
}
}
void prompt()
{
cout.set_fg(WHITE);
cout << ">";
cout.set_fg(GRAY);
cout << ">";
cout.set_fg(DARKGRAY);
cout << "> ";
cout.set_fg(GRAY);
}
int main(int argc, char *argv[])
{
cout << "Welcome to KShell! Type 'help' and press enter for avaliable commands.\n";
while (1)
{
prompt();
getcmd();
if (String::strlen(cmdbuf) != 0)
{
char *tokptr;
char *cmd = String::strtok_r(cmdbuf, " ", &tokptr);
if (String::strcmp(cmd, "help") == 0 || String::strcmp(cmd, "?") == 0)
{
int num = sizeof(help) / sizeof(help[0]);
for (int i = 0; i < num; i++)
{
cout.set_fg(LIGHTCYAN);
cout << help[i].name;
cout.set_fg(CYAN);
cout << ": ";
cout.set_fg(GRAY);
cout << help[i].text << "\n";
}
}
else if (String::strcmp(cmd, "echo") == 0)
{
char *tok;
while ((tok = String::strtok_r(NULL, " ", &tokptr)))
cout << tok << " ";
cout << "\n";
}
else if (String::strcmp(cmd, "halt") == 0)
{
Power::halt();
}
else if (String::strcmp(cmd, "reboot") == 0)
{
Power::reboot();
}
else if (String::strcmp(cmd, "uptime") == 0)
{
cout.flags(dec);
cout << "Current Uptime: " << Timer::getuptime() / 1000 << " seconds\n";
}
else if (String::strcmp(cmd, "syscall") == 0)
{
asm volatile
(
"mov $0, %%eax;"
"mov $0x41, %%ebx;"
"int $0x7B;"
::: "%eax", "%ebx"
);
}
else if (String::strcmp(cmd, "vcprint") == 0)
{
cout.print("This is a test\n");
cout.print("%%d: %d %%x: %x %%b: %b %%c: %c %%s: %s\n", 123, 123, 123, 'a', "asdf");
cout.print("%%08x: %08x\n", 123);
}
else if (String::strcmp(cmd, "crash") == 0)
{
cout << " 0. Cancel\n";
cout << " 1. Write to unmapped memory\n";
cout << " 2. Divide by 0\n";
cout << " 3. Execute a UD2 instruction\n";
cout << " 4. Assert false\n";
cout << " 5. Trigger a Burnt Popcorn\n";
cout << " 6. Print a null pointer to cout\n";
cout << "Please enter your choice: ";
char c = cout.getchar();
cout << c << "\n";
int zero = 0;
int choice = c - '0';
switch (choice)
{
case 0:
break;
case 1:
*(char *)(0xFFFFFFFF) = 'a';
break;
case 2:
cout << 10 / zero;
break;
case 3:
asm volatile ("ud2");
break;
case 4:
assert(false);
break;
case 5:
panic("foo");
break;
case 6:
cout << (char *)0 << "\n";
break;
default:
cout << "Invalid choice\n";
break;
}
}
else if (String::strcmp(cmd, "kitty") == 0)
{
cout << " _______ \n";
cout << " (_Meow!_)\n";
cout << " | / \n";
cout << " /|_ |/ \n";
cout << " ,' .\\ \n";
cout << " ,--' _,' \n";
cout << " / / \n";
cout << " ( -. | \n";
cout << " | ) | \n";
cout << " (`-. `--.) \n";
cout << " `._)----' \n\n";
}
else if (String::strcmp(cmd, "tasks") == 0)
{
//Tasks::list_tasks();
}
else if (String::strcmp(cmd, "exit") == 0)
{
//Tasks::process_end(1);
while (1);
}
else
{
cout << "Unknown command " << cmd << "\n";
}
}
}
}
}