The "shebang" handler is supposed to parse arguments, too - we now do that.
Also, when the line is too long, E2BIG is returned. Thanks to Korli who pointed me to this: http://homepages.cwi.nl/~aeb/std/shebang/ git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13114 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -12,7 +12,9 @@
|
|||||||
struct uspace_program_args;
|
struct uspace_program_args;
|
||||||
struct real_time_data;
|
struct real_time_data;
|
||||||
|
|
||||||
status_t __test_executable(const char *path, char *starter);
|
status_t __parse_invoke_line(char *invoker, char ***_newArgs,
|
||||||
|
char * const **_oldArgs, int32 *_argCount);
|
||||||
|
status_t __test_executable(const char *path, char *invoker);
|
||||||
void __init_image(const struct uspace_program_args *args);
|
void __init_image(const struct uspace_program_args *args);
|
||||||
void __init_dlfcn(const struct uspace_program_args *args);
|
void __init_dlfcn(const struct uspace_program_args *args);
|
||||||
void __init_env(const struct uspace_program_args *args);
|
void __init_env(const struct uspace_program_args *args);
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ static struct rld_export const *sRuntimeLinker;
|
|||||||
thread_id
|
thread_id
|
||||||
load_image(int32 argCount, const char **args, const char **environ)
|
load_image(int32 argCount, const char **args, const char **environ)
|
||||||
{
|
{
|
||||||
char starter[B_FILE_NAME_LENGTH];
|
char invoker[B_FILE_NAME_LENGTH];
|
||||||
const char **newArgs = NULL;
|
char **newArgs = NULL;
|
||||||
int32 envCount = 0;
|
int32 envCount = 0;
|
||||||
thread_id thread;
|
thread_id thread;
|
||||||
|
|
||||||
@@ -30,26 +30,15 @@ load_image(int32 argCount, const char **args, const char **environ)
|
|||||||
|
|
||||||
// test validity of executable + support for scripts
|
// test validity of executable + support for scripts
|
||||||
{
|
{
|
||||||
status_t status = __test_executable(args[0], starter);
|
status_t status = __test_executable(args[0], invoker);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
if (starter[0]) {
|
if (invoker[0]) {
|
||||||
int32 i;
|
status = __parse_invoke_line(invoker, &newArgs,
|
||||||
|
(char * const **)&args, &argCount);
|
||||||
// this is a shell script and requires special treatment
|
if (status < B_OK)
|
||||||
newArgs = malloc((argCount + 2) * sizeof(void *));
|
return status;
|
||||||
if (newArgs == NULL)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
|
|
||||||
// copy args and have "starter" as new app
|
|
||||||
newArgs[0] = starter;
|
|
||||||
for (i = 0; i < argCount; i++)
|
|
||||||
newArgs[i + 1] = args[i];
|
|
||||||
newArgs[i + 1] = NULL;
|
|
||||||
|
|
||||||
args = newArgs;
|
|
||||||
argCount++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,10 +107,84 @@ clear_caches(void *address, size_t length, uint32 flags)
|
|||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
status_t
|
static char *
|
||||||
__test_executable(const char *path, char *starter)
|
next_argument(char **_start, bool separate)
|
||||||
{
|
{
|
||||||
return sRuntimeLinker->test_executable(path, geteuid(), getegid(), starter);
|
char *line = *_start;
|
||||||
|
char quote = 0;
|
||||||
|
int32 i;
|
||||||
|
|
||||||
|
// eliminate leading spaces
|
||||||
|
while (line[0] == ' ')
|
||||||
|
line++;
|
||||||
|
|
||||||
|
if (line[0] == '"' || line[0] == '\'') {
|
||||||
|
quote = line[0];
|
||||||
|
line++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!line[0])
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (i = 0;; i++) {
|
||||||
|
if (line[i] == '\\' && line[i + 1] != '\0')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((!quote && line[i] == ' ') || line[i] == quote || line[i] == '\0') {
|
||||||
|
// argument separator!
|
||||||
|
if (separate)
|
||||||
|
line[i] = '\0';
|
||||||
|
*_start = &line[i + 1];
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
__parse_invoke_line(char *invoker, char ***_newArgs,
|
||||||
|
char * const **_oldArgs, int32 *_argCount)
|
||||||
|
{
|
||||||
|
int32 i, count = 0;
|
||||||
|
char *arg = invoker;
|
||||||
|
char **newArgs;
|
||||||
|
|
||||||
|
// count arguments in the line
|
||||||
|
|
||||||
|
while (next_argument(&arg, false)) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is a shell script and requires special treatment
|
||||||
|
newArgs = malloc((*_argCount + count + 1) * sizeof(void *));
|
||||||
|
if (newArgs == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
// copy invoker and old arguments and to newArgs
|
||||||
|
|
||||||
|
for (i = 0; (arg = next_argument(&invoker, true)) != NULL; i++) {
|
||||||
|
newArgs[i] = arg;
|
||||||
|
}
|
||||||
|
for (i = 0; i < *_argCount; i++) {
|
||||||
|
newArgs[i + count] = (char *)(*_oldArgs)[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
newArgs[i + count] = NULL;
|
||||||
|
|
||||||
|
*_newArgs = newArgs;
|
||||||
|
*_oldArgs = (char * const *)newArgs;
|
||||||
|
*_argCount += count;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
__test_executable(const char *path, char *invoker)
|
||||||
|
{
|
||||||
|
return sRuntimeLinker->test_executable(path, geteuid(), getegid(), invoker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ int
|
|||||||
execve(const char *path, char * const args[], char * const environment[])
|
execve(const char *path, char * const args[], char * const environment[])
|
||||||
{
|
{
|
||||||
int32 argCount = 0, envCount = 0;
|
int32 argCount = 0, envCount = 0;
|
||||||
char starter[B_FILE_NAME_LENGTH];
|
char invoker[B_FILE_NAME_LENGTH];
|
||||||
char **newArgs = NULL;
|
char **newArgs = NULL;
|
||||||
|
|
||||||
// count argument/environment list entries here, we don't want
|
// count argument/environment list entries here, we don't want
|
||||||
@@ -72,31 +72,20 @@ execve(const char *path, char * const args[], char * const environment[])
|
|||||||
|
|
||||||
// test validity of executable + support for scripts
|
// test validity of executable + support for scripts
|
||||||
{
|
{
|
||||||
status_t status = __test_executable(args[0], starter);
|
status_t status = __test_executable(args[0], invoker);
|
||||||
if (status < B_OK) {
|
if (status < B_OK) {
|
||||||
errno = status;
|
errno = status;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (starter[0]) {
|
if (invoker[0]) {
|
||||||
int32 i;
|
status = __parse_invoke_line(invoker, &newArgs, &args, &argCount);
|
||||||
|
if (status < B_OK) {
|
||||||
// this is a shell script and requires special treatment
|
errno = status;
|
||||||
newArgs = malloc((argCount + 2) * sizeof(void *));
|
|
||||||
if (newArgs == NULL) {
|
|
||||||
errno = B_NO_MEMORY;
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy args and have "starter" as new app
|
path = newArgs[0];
|
||||||
newArgs[0] = starter;
|
|
||||||
for (i = 0; i < argCount; i++)
|
|
||||||
newArgs[i + 1] = args[i];
|
|
||||||
newArgs[i + 1] = NULL;
|
|
||||||
|
|
||||||
path = starter;
|
|
||||||
args = newArgs;
|
|
||||||
argCount++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -206,7 +206,7 @@ open_executable(char *name, image_type type, const char *rpath)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
test_executable(const char *name, uid_t user, gid_t group, char *starter)
|
test_executable(const char *name, uid_t user, gid_t group, char *invoker)
|
||||||
{
|
{
|
||||||
char path[B_PATH_NAME_LENGTH];
|
char path[B_PATH_NAME_LENGTH];
|
||||||
char buffer[B_FILE_NAME_LENGTH];
|
char buffer[B_FILE_NAME_LENGTH];
|
||||||
@@ -251,18 +251,23 @@ test_executable(const char *name, uid_t user, gid_t group, char *starter)
|
|||||||
if (status == B_NOT_AN_EXECUTABLE) {
|
if (status == B_NOT_AN_EXECUTABLE) {
|
||||||
// test for shell scripts
|
// test for shell scripts
|
||||||
if (!strncmp(buffer, "#!", 2)) {
|
if (!strncmp(buffer, "#!", 2)) {
|
||||||
status = B_OK;
|
char *end;
|
||||||
if (starter) {
|
buffer[length - 1] = '\0';
|
||||||
char *end;
|
|
||||||
buffer[length - 1] = '\0';
|
|
||||||
|
|
||||||
if ((end = strchr(buffer, '\n')) != NULL)
|
end = strchr(buffer, '\n');
|
||||||
end[0] = '\0';
|
if (end == NULL) {
|
||||||
strcpy(starter, buffer + 2);
|
status = E2BIG;
|
||||||
}
|
goto out;
|
||||||
|
} else
|
||||||
|
end[0] = '\0';
|
||||||
|
|
||||||
|
if (invoker)
|
||||||
|
strcpy(invoker, buffer + 2);
|
||||||
|
|
||||||
|
status = B_OK;
|
||||||
}
|
}
|
||||||
} else if (status == B_OK && starter)
|
} else if (status == B_OK && invoker)
|
||||||
starter[0] = '\0';
|
invoker[0] = '\0';
|
||||||
|
|
||||||
out:
|
out:
|
||||||
_kern_close(fd);
|
_kern_close(fd);
|
||||||
|
|||||||
Reference in New Issue
Block a user