feat: refine symbolic link support.
[lunaix-os.git] / lunaix-os / kernel / loader / exec.c
index 3c40f6cd227b21e77e52c4c523b7f8de8fd72c8b..6a18ffca11d91bdbeec592bd7b84689266473f11 100644 (file)
@@ -7,12 +7,18 @@
 #include <lunaix/spike.h>
 #include <lunaix/status.h>
 #include <lunaix/syscall.h>
 #include <lunaix/spike.h>
 #include <lunaix/status.h>
 #include <lunaix/syscall.h>
+#include <lunaix/syscall_utils.h>
 
 #include <klibc/string.h>
 
 size_t
 exec_str_size(const char** str_arr, size_t* length)
 {
 
 #include <klibc/string.h>
 
 size_t
 exec_str_size(const char** str_arr, size_t* length)
 {
+    if (!str_arr) {
+        *length = 0;
+        return 0;
+    }
+
     const char* chr = *str_arr;
     size_t sz = 0, len = 0;
 
     const char* chr = *str_arr;
     size_t sz = 0, len = 0;
 
@@ -20,11 +26,11 @@ exec_str_size(const char** str_arr, size_t* length)
         sz += strlen(chr);
         len++;
 
         sz += strlen(chr);
         len++;
 
-        chr = *(str_arr + sz);
+        chr = *(str_arr++);
     }
 
     *length = len;
     }
 
     *length = len;
-    return sz + 1;
+    return sz + sizeof(char*);
 }
 
 void
 }
 
 void
@@ -42,10 +48,10 @@ __exec_remap_heap(struct ld_param* param, struct proc_mm* pvms)
 
     struct mmap_param map_param = { .pvms = pvms,
                                     .vms_mnt = param->vms_mnt,
 
     struct mmap_param map_param = { .pvms = pvms,
                                     .vms_mnt = param->vms_mnt,
-                                    .flags = MAP_ANON | MAP_PRIVATE | MAP_FIXED,
+                                    .flags = MAP_ANON | MAP_PRIVATE,
                                     .type = REGION_TYPE_HEAP,
                                     .proct = PROT_READ | PROT_WRITE,
                                     .type = REGION_TYPE_HEAP,
                                     .proct = PROT_READ | PROT_WRITE,
-                                    .mlen = DEFAULT_HEAP_PAGES * PG_SIZE };
+                                    .mlen = PG_SIZE };
     int status = 0;
     struct mm_region* heap;
     if ((status = mem_map(NULL, &heap, param->info.end, NULL, &map_param))) {
     int status = 0;
     struct mm_region* heap;
     if ((status = mem_map(NULL, &heap, param->info.end, NULL, &map_param))) {
@@ -55,13 +61,15 @@ __exec_remap_heap(struct ld_param* param, struct proc_mm* pvms)
 
     heap->region_copied = __heap_copied;
     mm_index((void**)&pvms->heap, heap);
 
     heap->region_copied = __heap_copied;
     mm_index((void**)&pvms->heap, heap);
+
+    return status;
 }
 
 int
 }
 
 int
-exec_loadto(struct ld_param* param,
-            struct v_file* executable,
-            const char** argv,
-            const char** envp)
+exec_load(struct ld_param* param,
+          struct v_file* executable,
+          const char** argv,
+          const char** envp)
 {
     int errno = 0;
 
 {
     int errno = 0;
 
@@ -88,7 +96,6 @@ exec_loadto(struct ld_param* param,
                                    .mlen = MAX_VAR_PAGES * PG_SIZE };
 
     void* mapped;
                                    .mlen = MAX_VAR_PAGES * PG_SIZE };
 
     void* mapped;
-    isr_param* intr_ctx = &param->proc->intr_ctx;
 
     if ((errno = __exec_remap_heap(param, pvms))) {
         goto done;
 
     if ((errno = __exec_remap_heap(param, pvms))) {
         goto done;
@@ -103,39 +110,39 @@ exec_loadto(struct ld_param* param,
 
         // make some handy infos available to user space
         ptr_t arg_start = mapped + sizeof(struct usr_exec_param);
 
         // make some handy infos available to user space
         ptr_t arg_start = mapped + sizeof(struct usr_exec_param);
-        memcpy(arg_start, (void*)argv, sz_argv);
-        memcpy(arg_start + sz_argv, (void*)envp, sz_envp);
-
-        struct usr_exec_param* param = mapped;
-        *param = (struct usr_exec_param){ .argc = argv_len,
-                                          .argv = arg_start,
-                                          .envc = envp_len,
-                                          .envp = arg_start + sz_argv,
-                                          .info = param->info };
+        if (argv)
+            memcpy(arg_start, (void*)argv, sz_argv);
+        if (envp)
+            memcpy(arg_start + sz_argv, (void*)envp, sz_envp);
+
         ptr_t* ustack = (ptr_t*)USTACK_TOP;
         ptr_t* ustack = (ptr_t*)USTACK_TOP;
+        struct usr_exec_param* exec_param = (struct usr_exec_param*)mapped;
+
         ustack[-1] = (ptr_t)mapped;
         ustack[-1] = (ptr_t)mapped;
-        intr_ctx->esp = &ustack[-1];
+        param->info.stack_top = &ustack[-1];
+
+        *exec_param = (struct usr_exec_param){ .argc = argv_len,
+                                               .argv = arg_start,
+                                               .envc = envp_len,
+                                               .envp = arg_start + sz_argv,
+                                               .info = param->info };
     } else {
         // TODO need to find a way to inject argv and envp remotely
     } else {
         // TODO need to find a way to inject argv and envp remotely
+        //      this is for the support of kernel level implementation of
+        //      posix_spawn
         fail("not implemented");
     }
 
         fail("not implemented");
     }
 
-    intr_ctx->eip = param->info.ehdr_out.e_entry;
-    // we will jump to new entry point (_u_start) upon syscall's
-    // return so execve 'will not return' from the perspective of it's invoker
-
+    param->info.entry = param->info.ehdr_out.e_entry;
 done:
     return errno;
 }
 
 done:
     return errno;
 }
 
-__DEFINE_LXSYSCALL3(int,
-                    execve,
-                    const char*,
-                    filename,
-                    const char*,
-                    argv[],
-                    const char*,
-                    envp[])
+int
+exec_load_byname(struct ld_param* param,
+                 const char* filename,
+                 const char** argv,
+                 const char** envp)
 {
     int errno = 0;
     struct v_dnode* dnode;
 {
     int errno = 0;
     struct v_dnode* dnode;
@@ -149,20 +156,44 @@ __DEFINE_LXSYSCALL3(int,
         goto done;
     }
 
         goto done;
     }
 
+    if ((errno = exec_load(param, file, argv, envp))) {
+        vfs_pclose(file, __current->pid);
+    }
+
+done:
+    return errno;
+}
+
+__DEFINE_LXSYSCALL3(int,
+                    execve,
+                    const char*,
+                    filename,
+                    const char*,
+                    argv[],
+                    const char*,
+                    envp[])
+{
+    int errno = 0;
     struct ld_param ldparam;
     ld_create_param(&ldparam, __current, VMS_SELF);
 
     struct ld_param ldparam;
     ld_create_param(&ldparam, __current, VMS_SELF);
 
-    if ((errno = exec_loadto(&ldparam, file, argv, envp))) {
-        vfs_pclose(file, __current->pid);
-
+    if ((errno = exec_load_byname(&ldparam, filename, argv, envp))) {
         if ((ldparam.status & LD_STAT_FKUP)) {
             // we fucked up our address space.
             terminate_proc(11451);
             schedule();
             fail("should not reach");
         }
         if ((ldparam.status & LD_STAT_FKUP)) {
             // we fucked up our address space.
             terminate_proc(11451);
             schedule();
             fail("should not reach");
         }
+        goto done;
     }
 
     }
 
+    volatile struct exec_param* execp = __current->intr_ctx.execp;
+    execp->esp = ldparam.info.stack_top;
+    execp->eip = ldparam.info.entry;
+
+    // we will jump to new entry point (_u_start) upon syscall's
+    // return so execve 'will not return' from the perspective of it's invoker
+
 done:
 done:
-    return errno;
+    return DO_STATUS(errno);
 }
\ No newline at end of file
 }
\ No newline at end of file