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:
parent
be22452f3b
commit
43ed6aa0db
@ -12,7 +12,9 @@
|
||||
struct uspace_program_args;
|
||||
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_dlfcn(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
|
||||
load_image(int32 argCount, const char **args, const char **environ)
|
||||
{
|
||||
char starter[B_FILE_NAME_LENGTH];
|
||||
const char **newArgs = NULL;
|
||||
char invoker[B_FILE_NAME_LENGTH];
|
||||
char **newArgs = NULL;
|
||||
int32 envCount = 0;
|
||||
thread_id thread;
|
||||
|
||||
@ -30,26 +30,15 @@ load_image(int32 argCount, const char **args, const char **environ)
|
||||
|
||||
// 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)
|
||||
return status;
|
||||
|
||||
if (starter[0]) {
|
||||
int32 i;
|
||||
|
||||
// this is a shell script and requires special treatment
|
||||
newArgs = malloc((argCount + 2) * sizeof(void *));
|
||||
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++;
|
||||
if (invoker[0]) {
|
||||
status = __parse_invoke_line(invoker, &newArgs,
|
||||
(char * const **)&args, &argCount);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,10 +107,84 @@ clear_caches(void *address, size_t length, uint32 flags)
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
status_t
|
||||
__test_executable(const char *path, char *starter)
|
||||
static char *
|
||||
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[])
|
||||
{
|
||||
int32 argCount = 0, envCount = 0;
|
||||
char starter[B_FILE_NAME_LENGTH];
|
||||
char invoker[B_FILE_NAME_LENGTH];
|
||||
char **newArgs = NULL;
|
||||
|
||||
// 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
|
||||
{
|
||||
status_t status = __test_executable(args[0], starter);
|
||||
status_t status = __test_executable(args[0], invoker);
|
||||
if (status < B_OK) {
|
||||
errno = status;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (starter[0]) {
|
||||
int32 i;
|
||||
|
||||
// this is a shell script and requires special treatment
|
||||
newArgs = malloc((argCount + 2) * sizeof(void *));
|
||||
if (newArgs == NULL) {
|
||||
errno = B_NO_MEMORY;
|
||||
if (invoker[0]) {
|
||||
status = __parse_invoke_line(invoker, &newArgs, &args, &argCount);
|
||||
if (status < B_OK) {
|
||||
errno = status;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
path = starter;
|
||||
args = newArgs;
|
||||
argCount++;
|
||||
path = newArgs[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -206,7 +206,7 @@ open_executable(char *name, image_type type, const char *rpath)
|
||||
*/
|
||||
|
||||
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 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) {
|
||||
// test for shell scripts
|
||||
if (!strncmp(buffer, "#!", 2)) {
|
||||
status = B_OK;
|
||||
if (starter) {
|
||||
char *end;
|
||||
buffer[length - 1] = '\0';
|
||||
char *end;
|
||||
buffer[length - 1] = '\0';
|
||||
|
||||
if ((end = strchr(buffer, '\n')) != NULL)
|
||||
end[0] = '\0';
|
||||
strcpy(starter, buffer + 2);
|
||||
}
|
||||
end = strchr(buffer, '\n');
|
||||
if (end == NULL) {
|
||||
status = E2BIG;
|
||||
goto out;
|
||||
} else
|
||||
end[0] = '\0';
|
||||
|
||||
if (invoker)
|
||||
strcpy(invoker, buffer + 2);
|
||||
|
||||
status = B_OK;
|
||||
}
|
||||
} else if (status == B_OK && starter)
|
||||
starter[0] = '\0';
|
||||
} else if (status == B_OK && invoker)
|
||||
invoker[0] = '\0';
|
||||
|
||||
out:
|
||||
_kern_close(fd);
|
||||
|
Loading…
x
Reference in New Issue
Block a user