Add shebang handling
This commit is contained in:
@@ -105,6 +105,13 @@ static int elf_bzero(mm_space_t space, uintptr_t vma_dst, size_t size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int binfmt_is_elf(const char *ident, size_t len) {
|
||||
if (len < 4) {
|
||||
return 0;
|
||||
}
|
||||
return !strncmp(ident, "\x7F""ELF", 4);
|
||||
}
|
||||
|
||||
int elf_load(struct process *proc, struct vfs_ioctx *ctx, struct ofile *fd, uintptr_t *entry) {
|
||||
int res;
|
||||
ssize_t bread;
|
||||
|
||||
@@ -5,3 +5,4 @@ struct process;
|
||||
struct ofile;
|
||||
|
||||
int elf_load(struct process *proc, struct vfs_ioctx *ctx, struct ofile *fd, uintptr_t *entry);
|
||||
int binfmt_is_elf(const char *guess, size_t len);
|
||||
|
||||
+42
-5
@@ -120,6 +120,7 @@ int sys_execve(const char *path, const char **argv, const char **envp) {
|
||||
_assert(thr);
|
||||
struct process *proc = thr->proc;
|
||||
_assert(proc);
|
||||
char shebang[128];
|
||||
|
||||
if (proc->thread_count > 1) {
|
||||
panic("XXX: execve() in multithreaded process\n");
|
||||
@@ -136,6 +137,47 @@ int sys_execve(const char *path, const char **argv, const char **envp) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if ((res = vfs_open(&proc->ioctx, &fd, path, O_RDONLY, 0)) != 0) {
|
||||
kerror("%s: %s\n", path, kstrerror(res));
|
||||
return res;
|
||||
}
|
||||
|
||||
if ((res = vfs_read(&proc->ioctx, &fd, shebang, sizeof(shebang))) <= 0) {
|
||||
kerror("%s: %s\n", path, kstrerror(res));
|
||||
return res;
|
||||
}
|
||||
|
||||
if (!binfmt_is_elf(shebang, res)) {
|
||||
// Try checking for shebang line
|
||||
if (shebang[0] == '#' && shebang[1] == '!') {
|
||||
char *e = strchr(shebang, '\n');
|
||||
if (!e) {
|
||||
vfs_close(&proc->ioctx, &fd);
|
||||
return -EINVAL;
|
||||
}
|
||||
*e = 0;
|
||||
|
||||
int argc;
|
||||
for (argc = 0; argv[argc]; ++argc);
|
||||
// For interpreter
|
||||
++argc;
|
||||
// Sanity check
|
||||
_assert(argc <= 32);
|
||||
const char *argv_new[argc + 1];
|
||||
argv_new[0] = shebang + 2;
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
argv_new[i] = argv[i - 1];
|
||||
}
|
||||
argv_new[argc] = NULL;
|
||||
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
kdebug("[%d]: %s\n", i, argv_new[i]);
|
||||
}
|
||||
|
||||
return sys_execve(shebang + 2, argv_new, envp);
|
||||
}
|
||||
}
|
||||
|
||||
const char *e = strrchr(path, '/');
|
||||
const char *name = e + 1;
|
||||
if (!e) {
|
||||
@@ -162,11 +204,6 @@ int sys_execve(const char *path, const char **argv, const char **envp) {
|
||||
panic("Failed to copy argp/envp to new process\n");
|
||||
}
|
||||
|
||||
if ((res = vfs_open(&proc->ioctx, &fd, path, O_RDONLY, 0)) != 0) {
|
||||
kerror("%s: %s\n", path, kstrerror(res));
|
||||
return res;
|
||||
}
|
||||
|
||||
if (proc->space == mm_kernel) {
|
||||
// Have to allocate a new PID for kernel -> userspace transition
|
||||
proc->pid = process_alloc_pid(1); //thread_alloc_pid(1);
|
||||
|
||||
Reference in New Issue
Block a user