Add PATH variable.
This commit is contained in:
parent
f29abd73ec
commit
15c48f4efc
|
@ -1,6 +1,6 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012.
|
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013.
|
||||||
|
|
||||||
This file is part of the Sortix C Library.
|
This file is part of the Sortix C Library.
|
||||||
|
|
||||||
|
@ -22,31 +22,79 @@
|
||||||
|
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#if defined(PLATFORM_X86)
|
// TODO: Move this to some generic environment interface!
|
||||||
#define CPUTYPE_STR "i486-sortix"
|
static const char* LookupEnvironment(const char* name, char* const* envp)
|
||||||
#elif defined(PLATFORM_X64)
|
{
|
||||||
#define CPUTYPE_STR "x86_64-sortix"
|
size_t equalpos = strcspn(name, "=");
|
||||||
#else
|
if ( name[equalpos] == '=' )
|
||||||
#error No cputype environmental variable provided here.
|
return NULL;
|
||||||
#endif
|
size_t namelen = equalpos;
|
||||||
|
for ( size_t i = 0; envp[i]; i++ )
|
||||||
|
{
|
||||||
|
if ( strncmp(name, envp[i], namelen) )
|
||||||
|
continue;
|
||||||
|
if ( envp[i][namelen] != '=' )
|
||||||
|
continue;
|
||||||
|
return envp[i] + namelen + 1;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// Note that the only PATH variable in Sortix is the one used here.
|
// TODO: Provide an interface that allows user-space to find out which command
|
||||||
|
// would have been executed (according to PATH) had execvpe been called now.
|
||||||
|
// This is of value to programs such as which(1), instead of repeating much of
|
||||||
|
// this logic there.
|
||||||
extern "C" int execvpe(const char* filename, char* const* argv,
|
extern "C" int execvpe(const char* filename, char* const* argv,
|
||||||
char* const* envp)
|
char* const* envp)
|
||||||
{
|
{
|
||||||
if ( strchr(filename, '/') )
|
const char* path = LookupEnvironment("PATH", envp);
|
||||||
|
// TODO: Should there be a default PATH value?
|
||||||
|
if ( strchr(filename, '/') || !path )
|
||||||
return execve(filename, argv, envp);
|
return execve(filename, argv, envp);
|
||||||
size_t filenamelen = strlen(filename);
|
|
||||||
const char* PATH = "/" CPUTYPE_STR "/bin";
|
// Search each directory in the PATH variable for a suitable file.
|
||||||
size_t pathlen = strlen(PATH);
|
size_t filename_len = strlen(filename);
|
||||||
char* pathname = (char*) malloc(filenamelen + 1 + pathlen + 1);
|
while ( *path )
|
||||||
if ( !pathname ) { return -1; }
|
{
|
||||||
stpcpy(stpcpy(stpcpy(pathname, PATH), "/"), filename);
|
size_t len = strcspn(path, ":");
|
||||||
int result = execve(pathname, argv, envp);
|
if ( !len )
|
||||||
free(pathname);
|
{
|
||||||
return result;
|
// Sortix doesn't support that the empty string means current
|
||||||
|
// directory. While it does inductively make sense, the common
|
||||||
|
// kernel interfaces such as openat doesn't accept it and software
|
||||||
|
// often just prefix their directories and a colon to PATH without
|
||||||
|
// regard to whether it's already empty. S
|
||||||
|
path++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the full path to the file if it is in the directory.
|
||||||
|
size_t fullpath_len = len + 1 + filename_len + 1;
|
||||||
|
char* fullpath = (char*) malloc(fullpath_len * sizeof(char));
|
||||||
|
if ( !fullpath )
|
||||||
|
return -1;
|
||||||
|
stpcpy(stpcpy(stpncpy(fullpath, path, len), "/"), filename);
|
||||||
|
if ( (path += len + 1)[0] == ':' )
|
||||||
|
path++;
|
||||||
|
|
||||||
|
execve(fullpath, argv, envp);
|
||||||
|
free(fullpath);
|
||||||
|
|
||||||
|
// TODO: There may be some security concerns here as to whether to
|
||||||
|
// continue or abort execution. For instance, if a directory in the
|
||||||
|
// start of the PATH has permissions set up too restrictively, then
|
||||||
|
// it would never look in the later directories (and you can't execute
|
||||||
|
// anything without absolute paths). And other situations.
|
||||||
|
if ( errno == EACCES )
|
||||||
|
return -1;
|
||||||
|
if ( errno == ENOENT )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,6 +79,15 @@ int main(int /*argc*/, char* /*argv*/[])
|
||||||
// we are running.
|
// we are running.
|
||||||
setenv("objtype", getenv("cputype"), 0);
|
setenv("objtype", getenv("cputype"), 0);
|
||||||
|
|
||||||
|
// Set up the PATH variable.
|
||||||
|
const char* prefix = "/";
|
||||||
|
const char* cputype = getenv("cputype");
|
||||||
|
const char* suffix = "/bin";
|
||||||
|
char* path = new char[strlen(prefix) + strlen(cputype) + strlen(suffix) + 1];
|
||||||
|
stpcpy(stpcpy(stpcpy(path, prefix), cputype), suffix);
|
||||||
|
setenv("PATH", path, 0);
|
||||||
|
delete[] path;
|
||||||
|
|
||||||
// Make sure that we have a /tmp directory.
|
// Make sure that we have a /tmp directory.
|
||||||
mkdir("/tmp", 01777);
|
mkdir("/tmp", 01777);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue