Argv now works in main.

This commit is contained in:
Jonas 'Sortie' Termansen 2011-11-09 23:18:26 +01:00
parent 9ba01ad3b2
commit ae599b6d67
7 changed files with 96 additions and 19 deletions

View File

@ -31,7 +31,7 @@ namespace Maxsi
namespace Process namespace Process
{ {
DEFN_SYSCALL1_VOID(SysExit, 1, int); 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_VOID(SysPrintPathFiles, 11);
DEFN_SYSCALL0(pid_t, SysFork, 12); DEFN_SYSCALL0(pid_t, SysFork, 12);
DEFN_SYSCALL0(pid_t, SysGetPID, 13); DEFN_SYSCALL0(pid_t, SysGetPID, 13);
@ -42,7 +42,7 @@ namespace Maxsi
int Execute(const char* filepath, int argc, const char** argv) 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() void PrintPathFiles()

View File

@ -33,9 +33,8 @@ _start:
call initialize_standard_library call initialize_standard_library
# Run main # Run main
# TODO: Sortix should push these values to the stack itself! push %ebx # argv
push $0x0 # argv push %eax # argc
push $0 # argc
call main call main
# Terminate the process with main's exit code. # Terminate the process with main's exit code.

View File

@ -79,7 +79,8 @@ namespace Sortix
Sound::Mute(); Sound::Mute();
const char* programname = "sh"; const char* programname = "sh";
Process::Execute(programname, regs); const char* const argv[] = { "sh" };
CurrentProcess()->Execute(programname, 1, argv, regs);
return; return;
} }

View File

@ -244,8 +244,10 @@ namespace Sortix
// TODO: Unmap any process memory segments. // 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; size_t programsize = 0;
byte* program = InitRD::Open(programname, &programsize); byte* program = InitRD::Open(programname, &programsize);
if ( !program ) { return -1; } if ( !program ) { return -1; }
@ -259,24 +261,75 @@ namespace Sortix
Panic("Couldn't create the shell process"); 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: This may be an ugly hack!
// TODO: Move this to x86/process.cpp. // 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->eip = entry;
regs->useresp = CurrentThread()->stackpos + CurrentThread()->stacksize; regs->useresp = stackpos;
regs->ebp = CurrentThread()->stackpos + CurrentThread()->stacksize; regs->ebp = stackpos;
return 0; 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! // Make a copy of argv and filename as they are going to be destroyed
return Process::Execute(programname, Syscall::InterruptRegs()); // 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() pid_t SysFork()
@ -528,7 +581,7 @@ namespace Sortix
void Process::Init() void Process::Init()
{ {
Syscall::Register(SYSCALL_EXEC, (void*) SysExecute); Syscall::Register(SYSCALL_EXEC, (void*) SysExecVE);
Syscall::Register(SYSCALL_FORK, (void*) SysFork); Syscall::Register(SYSCALL_FORK, (void*) SysFork);
Syscall::Register(SYSCALL_GETPID, (void*) SysGetPID); Syscall::Register(SYSCALL_GETPID, (void*) SysGetPID);
Syscall::Register(SYSCALL_GETPPID, (void*) SysGetParentPID); Syscall::Register(SYSCALL_GETPPID, (void*) SysGetParentPID);

View File

@ -60,7 +60,6 @@ namespace Sortix
public: public:
static void Init(); static void Init();
static int Execute(const char* programname, CPU::InterruptRegisters* regs);
private: private:
static pid_t AllocatePID(); static pid_t AllocatePID();
@ -90,6 +89,7 @@ namespace Sortix
bool sigint; bool sigint;
public: public:
int Execute(const char* programname, int argc, const char* const* argv, CPU::InterruptRegisters* regs);
void ResetAddressSpace(); void ResetAddressSpace();
public: public:

View File

@ -294,7 +294,10 @@ namespace Sortix
hacksigintpending = false; hacksigintpending = false;
Log::PrintF("^C\n"); 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() void SigIntHack()

View File

@ -57,11 +57,32 @@ void command()
return; 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. // 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. // 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); exit(127);
} }