diff --git a/include/ex/argv.h b/include/ex/argv.h index 14541b7..a651f34 100644 --- a/include/ex/argv.h +++ b/include/ex/argv.h @@ -240,7 +240,7 @@ size_t KalComputeArgVecSize(const char **argv); // error_t KalCmdLineToArgVecEx(const char *cmdLine, int *argcPtr, - char **argv, + char *bufptr, bool doEscaping); // @@ -248,7 +248,7 @@ error_t KalCmdLineToArgVecEx(const char *cmdLine, // error_t KalCmdLineToArgVec(const char *cmdLine, int *argcPtr, - char **argv); + char *bufptr); // // Argument vector to command line diff --git a/kaleid/extras/argv.c b/kaleid/extras/argv.c index 6f58753..ae818bf 100644 --- a/kaleid/extras/argv.c +++ b/kaleid/extras/argv.c @@ -56,25 +56,17 @@ size_t KalComputeArgVecSize(const char *argv[]) // // Converts command line to an argument vector // -// This function assumes that argv[0] is a pointer -// to a ARG_MAX-wide buffer, which will be filled -// with strings in succession; the address of the nth -// string will be stored in argv[n-1] -// -// Technically ARG_MAX is the maximum number of bytes -// in both the buffer *and* argv, i.e. (argc + 1) * sizeof(char *) -// bytes are reserved for the argv[i] pointers, so in fact less than -// ARG_MAX bytes are available -// -// That available space, however, remains strictly higher than 4KB, -// which is the POSIX minimum; the current ARG_MAX guarantees 16KB available +// This function assumes that *argv is a (ARG_MAX * 2)-wide buffer, +// whose second half will be filled with strings in succession; +// with the address of the nth string stored in the first half, +// specifically at argv[n-1] // // TODO long escape sequences // get program command line if cmdLine == NULL // error_t KalCmdLineToArgVecEx(const char *cmdLine, int *argcPtr, - char **argv, + char *bufptr, bool doEscaping) { int argc = 0; @@ -83,11 +75,17 @@ error_t KalCmdLineToArgVecEx(const char *cmdLine, bool escaping = false; size_t written = 0; error_t retcode = EOK; - - assert_always(argv && *argv && cmdLine); + bool maxreached = false; // An ARG_MAX-wide buffer - char *buffer = *argv; + char **argv = (char **)bufptr; + + assert(argv && cmdLine); + + // Another ARG_MAX-wide buffer + char *buffer = *argv + ARG_MAX; + + argv[0] = buffer; // Null-terminate current argv slot // and save the start of next string @@ -111,12 +109,15 @@ error_t KalCmdLineToArgVecEx(const char *cmdLine, for (; *cmdLine; cmdLine++) { // Make sure we don't go beyond ARG_MAX bytes - if (written >= ARG_MAX - (1 + sizeof(char *))) { - // Sanity check - assert(written == ARG_MAX - (1 + sizeof(char *))); + maxreached = written >= ARG_MAX - 1; + maxreached = maxreached || argc >= (int)(ARG_MAX/sizeof(char *) - 1); - // All we have left is one byte for the null-terminator of the current slot - // and sizeof(char *) bytes for the NULL at the end of argv + if (maxreached) { + // Sanity check + assert(written == ARG_MAX - 1); + + // All we have left is one byte for the null-terminator + // (or argv maxed out) *buffer = 0; // Did we write anything in this slot? @@ -193,6 +194,9 @@ error_t KalCmdLineToArgVecEx(const char *cmdLine, *buffer++ = *cmdLine; } + // Ensures that the last string is null-terminated + *buffer = 0; + // Ensures that argv[argc] == NULL argv[++argc] = NULL; @@ -211,7 +215,7 @@ error_t KalCmdLineToArgVecEx(const char *cmdLine, error_t KalCmdLineToArgVec(const char *cmdLine, int *argcPtr, - char **argv) + char *bufptr) { - return KalCmdLineToArgVecEx(cmdLine, argcPtr, argv, false); + return KalCmdLineToArgVecEx(cmdLine, argcPtr, bufptr, false); } diff --git a/kaleid/kernel/init/init.c b/kaleid/kernel/init/init.c index 9af0beb..c2058d5 100644 --- a/kaleid/kernel/init/init.c +++ b/kaleid/kernel/init/init.c @@ -41,7 +41,7 @@ noreturn void BtStartKern(multiboot_info_t *mbInfo, uint mbMagic, void *codeSeg) IoEnableCursor(); IoUpdateCursor(0, 0); - KernLog("%c%c%c OS/K\n\n", 219, 219, 219); //grrr + KernLog("%c%c%c OS/K\n\n", 219, 219, 219); // Sanity checks BtDoSanityChecks(mbMagic); @@ -54,6 +54,8 @@ noreturn void BtStartKern(multiboot_info_t *mbInfo, uint mbMagic, void *codeSeg) // Interrupts launching KeSetupIDT(); KeEnableIRQs(); + + //KalCmdLineToArgVec("test 1 2 3 4 5\n", &buf, ); // Start drivers KeEnableRTC(); diff --git a/kaleid/kernel/sh/shell.c b/kaleid/kernel/sh/shell.c index 840b3be..6b82927 100644 --- a/kaleid/kernel/sh/shell.c +++ b/kaleid/kernel/sh/shell.c @@ -38,7 +38,7 @@ void ExecuteCommand(char *cmdbuf) return; memzero(*shargv, ARG_MAX); - rc = KalCmdLineToArgVec(cmdbuf, &shargc, shargv); + rc = KalCmdLineToArgVec(cmdbuf, &shargc, argv0); if (rc) KeStartPanic("Shell: Couldn't parse command line: %d", rc); for (cmd = cmdtable; cmd->name != NULL; cmd++) { @@ -63,9 +63,9 @@ void KeStartShell(void) char *cmdbuf = malloc(CMDBUFSIZE); char *bufptr = cmdbuf; - argv0 = malloc(ARG_MAX); - memzero(argv0, ARG_MAX); - shargv = &argv0; + argv0 = malloc(ARG_MAX * 2); + memzero(argv0, ARG_MAX * 2); + shargv = (char **)argv0; KernLog("\nshell> "); BFlushBuf(BStdOut);