diff --git a/libmaxsi/process.cpp b/libmaxsi/process.cpp index a7f3954b..b7792d22 100644 --- a/libmaxsi/process.cpp +++ b/libmaxsi/process.cpp @@ -31,7 +31,7 @@ namespace Maxsi namespace Process { DEFN_SYSCALL1_VOID(SysExit, 1, int); - DEFN_SYSCALL3(int, SysExecute, 10, const char*, int, const char**); + DEFN_SYSCALL4(int, SysExecVE, 10, const char*, int, char* const*, char* const*); DEFN_SYSCALL0_VOID(SysPrintPathFiles, 11); DEFN_SYSCALL0(pid_t, SysFork, 12); DEFN_SYSCALL0(pid_t, SysGetPID, 13); @@ -42,7 +42,7 @@ namespace Maxsi int Execute(const char* filepath, int argc, const char** argv) { - return SysExecute(filepath, argc, argv); + return SysExecVE(filepath, argc, (char* const*) argv, NULL); } void PrintPathFiles() diff --git a/libmaxsi/x86/start.s b/libmaxsi/x86/start.s index 8eef55c4..bf396595 100644 --- a/libmaxsi/x86/start.s +++ b/libmaxsi/x86/start.s @@ -33,9 +33,8 @@ _start: call initialize_standard_library # Run main - # TODO: Sortix should push these values to the stack itself! - push $0x0 # argv - push $0 # argc + push %ebx # argv + push %eax # argc call main # Terminate the process with main's exit code. diff --git a/sortix/interrupt.cpp b/sortix/interrupt.cpp index c1423e71..700a4d0f 100644 --- a/sortix/interrupt.cpp +++ b/sortix/interrupt.cpp @@ -79,7 +79,8 @@ namespace Sortix Sound::Mute(); const char* programname = "sh"; - Process::Execute(programname, regs); + const char* const argv[] = { "sh" }; + CurrentProcess()->Execute(programname, 1, argv, regs); return; } diff --git a/sortix/process.cpp b/sortix/process.cpp index b8f80a66..4b5a182a 100644 --- a/sortix/process.cpp +++ b/sortix/process.cpp @@ -244,8 +244,10 @@ namespace Sortix // TODO: Unmap any process memory segments. } - int Process::Execute(const char* programname, CPU::InterruptRegisters* regs) + int Process::Execute(const char* programname, int argc, const char* const* argv, CPU::InterruptRegisters* regs) { + ASSERT(CurrentProcess() == this); + size_t programsize = 0; byte* program = InitRD::Open(programname, &programsize); if ( !program ) { return -1; } @@ -259,24 +261,75 @@ namespace Sortix Panic("Couldn't create the shell process"); } - return Execute("sh", regs); + const char* const SHARGV[]= { "sh" }; + return Execute("sh", 1, SHARGV, regs); } // TODO: This may be an ugly hack! // TODO: Move this to x86/process.cpp. + + // Alright, move argv onto the new stack! First figure out exactly how + // big argv actually is. + addr_t stackpos = CurrentThread()->stackpos + CurrentThread()->stacksize; + addr_t argvpos = stackpos - sizeof(char*) * argc; + char** stackargv = (char**) argvpos; + regs->eax = argc; + regs->ebx = argvpos; + + size_t argvsize = 0; + for ( int i = 0; i < argc; i++ ) + { + size_t len = String::Length(argv[i]) + 1; + argvsize += len; + char* dest = ((char*) argvpos) - argvsize; + stackargv[i] = dest; + Maxsi::Memory::Copy(dest, argv[i], len); + } + + stackpos = argvpos - argvsize; + regs->eip = entry; - regs->useresp = CurrentThread()->stackpos + CurrentThread()->stacksize; - regs->ebp = CurrentThread()->stackpos + CurrentThread()->stacksize; + regs->useresp = stackpos; + regs->ebp = stackpos; return 0; } - int SysExecute(const char* programname) + int SysExecVE(const char* filename, int argc, char* const argv[], char* const /*envp*/[]) { - // TODO: Validate that filepath is a user-space readable string! + // TODO: Validate that all the pointer-y parameters are SAFE! - // This is a hacky way to set up the thread! - return Process::Execute(programname, Syscall::InterruptRegs()); + // Make a copy of argv and filename as they are going to be destroyed + // when the address space is reset. + filename = String::Clone(filename); + if ( !filename ) { return -1; /* TODO: errno */ } + + char** newargv = new char*[argc]; + if ( !newargv ) { delete[] filename; return -1; /* TODO: errno */ } + + for ( int i = 0; i < argc; i++ ) + { + newargv[i] = String::Clone(argv[i]); + if ( !newargv[i] ) + { + while ( i ) { delete[] newargv[--i]; } + + return -1; /* TODO: errno */ + } + } + + argv = newargv; + + CPU::InterruptRegisters* regs = Syscall::InterruptRegs(); + Process* process = CurrentProcess(); + int result = process->Execute(filename, argc, argv, regs); + Syscall::AsIs(); + + for ( int i = 0; i < argc; i++ ) { delete[] argv[i]; } + delete[] argv; + delete[] filename; + + return result; } pid_t SysFork() @@ -528,7 +581,7 @@ namespace Sortix void Process::Init() { - Syscall::Register(SYSCALL_EXEC, (void*) SysExecute); + Syscall::Register(SYSCALL_EXEC, (void*) SysExecVE); Syscall::Register(SYSCALL_FORK, (void*) SysFork); Syscall::Register(SYSCALL_GETPID, (void*) SysGetPID); Syscall::Register(SYSCALL_GETPPID, (void*) SysGetParentPID); diff --git a/sortix/process.h b/sortix/process.h index 7084e777..ee4145ba 100644 --- a/sortix/process.h +++ b/sortix/process.h @@ -60,7 +60,6 @@ namespace Sortix public: static void Init(); - static int Execute(const char* programname, CPU::InterruptRegisters* regs); private: static pid_t AllocatePID(); @@ -90,6 +89,7 @@ namespace Sortix bool sigint; public: + int Execute(const char* programname, int argc, const char* const* argv, CPU::InterruptRegisters* regs); void ResetAddressSpace(); public: diff --git a/sortix/scheduler.cpp b/sortix/scheduler.cpp index 2bf34b90..1e398df3 100644 --- a/sortix/scheduler.cpp +++ b/sortix/scheduler.cpp @@ -294,7 +294,10 @@ namespace Sortix hacksigintpending = false; Log::PrintF("^C\n"); - Process::Execute("sh", regs); + const char* programname = "sh"; + const char* const argv[] = { "sh" }; + CurrentProcess()->Execute(programname, 1, argv, regs); + return; } void SigIntHack() diff --git a/utils/mxsh.cpp b/utils/mxsh.cpp index e6775902..1e8a8cff 100644 --- a/utils/mxsh.cpp +++ b/utils/mxsh.cpp @@ -57,11 +57,32 @@ void command() return; } + int argc = 0; + const char* argv[256]; + argv[argc++] = command; + + bool lastwasspace = false; + for ( size_t i = 0; i <= commandused; i++ ) + { + switch ( command[i] ) + { + case ' ': + case '\t': + case '\n': + command[i] = 0; + lastwasspace = true; + break; + default: + if ( lastwasspace ) { argv[argc++] = command + i; } + lastwasspace = false; + } + } + // Replace the current process with another process image. - Process::Execute(command, 0, NULL); + Process::Execute(argv[0], argc, argv); // This is clever. This only happens if the program didn't change. - printf("%s: command not found\n", command); + printf("%s: command not found\n", argv[0]); exit(127); }