/* * 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 #include #include #include #include #include #include #include #include #include #include #include namespace KShell { typedef struct { const char *name; const char *text; } help_t; help_t help[] = { { "help", "Show this help menu" }, { "echo ", "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"; } } } } }