//----------------------------------------------------------------------------// // GNU GPL OS/K // // // // Desc: Kernel shell // // // // // // Copyright © 2018-2019 The OS/K Team // // // // This file is part of OS/K. // // // // OS/K 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 3 of the License, or // // any later version. // // // // OS/K 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 OS/K. If not, see . // //----------------------------------------------------------------------------// #include #include #include #include #include #include #include int shargc = 0; char **shargv = 0; int shcol = VGA_COLOR_LIGHT_GREY; static char *argvbuf = 0; void ExecuteCommand(char *cmdbuf, Command_t *cmdtable) { error_t rc; Command_t *cmd; bool found = false; if (!cmdbuf || !*cmdbuf) return; memzero(*shargv, ARG_MAX); rc = ShCmdLineToArgVec(cmdbuf, &shargc, argvbuf); if (rc) KeStartPanic("Shell: Couldn't parse command line: %d", rc); for (cmd = cmdtable; cmd->name != NULL; cmd++) { if (!strcmp(cmd->name, shargv[0])) { cmd->func(shargc, shargv, cmdbuf); found = true; break; } } assert(shargv[0] == argvbuf + ARG_MAX); if (found == false) { KernLog("err: command not found: '%.255s' (%ld)\n", shargv[0], strlen(shargv[0])); } } void ShStartShell(void) { uchar ch; error_t rc; char *cmdbuf = malloc(CMDBUFSIZE); char *bufptr = cmdbuf; argvbuf = malloc(ARG_MAX * 2); memzero(argvbuf, ARG_MAX * 2); shargv = (char **)argvbuf; KernLog("\n%Cshell> %C", VGA_COLOR_WHITE, shcol); BFlushBuf(BStdOut); while ((rc = BGetFromBuf(BStdIn, &ch)) == EOK || rc == EENDF) { // Reset BStdIn's content if (rc == EENDF) { if (!(BStdIn->flags & BF_ERR)) { *bufptr = 0; bufptr = cmdbuf; ExecuteCommand(cmdbuf, shcmdtable); memzero(cmdbuf, CMDBUFSIZE); BFlushBuf(BStdIn); KernLog("%Cshell> %C", VGA_COLOR_WHITE, shcol); BFlushBuf(BStdOut); } else break; } switch (ch) { case KEY_BS: *bufptr = 0; if (bufptr > cmdbuf) { bufptr--; } break; case KEY_BEL: if (rand() % 16 == 0) { IoDoStarWars(); } else IoDoBeep(); break; case KEY_DC1: IoScrollUp(); break; case KEY_DC2: IoScrollDown(); break; case KEY_ESC: PoShutdown(); break; default: IoSetScroll(1); IoScrollDown(); *bufptr++ = (char)ch; // End of buffer? if (bufptr != cmdbuf+CMDBUFSIZE-1) { break; // No } KernLog("\n"); // Else, fallthrough to case '\n' case '\n': while (IoGetScroll() > 0) { IoScrollDown(); } *bufptr = 0; bufptr = cmdbuf; ExecuteCommand(cmdbuf, shcmdtable); memzero(cmdbuf, CMDBUFSIZE); KernLog("%Cshell> %C", VGA_COLOR_WHITE, shcol); BFlushBuf(BStdIn); BFlushBuf(BStdOut); break; } KePauseCPU(); } KernLog("[EOI]\n"); }