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
{
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()

View File

@ -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.

View File

@ -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;
}

View File

@ -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);

View File

@ -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:

View File

@ -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()

View File

@ -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);
}