Преглед изворни кода

feat(environ): pass envs between procs

greatbridf пре 2 година
родитељ
комит
e9937eddbd

+ 2 - 0
gblibc/include/stdlib.h

@@ -27,6 +27,8 @@ int rand(void);
 int rand_r(unsigned int* seedp);
 void srand(unsigned int seed);
 
+int setenv(const char* name, const char* value, int overwrite);
+
 #ifdef __cplusplus
 }
 #endif

+ 1 - 0
gblibc/include/string.h

@@ -22,6 +22,7 @@ void* memset(void* dst, int c, size_t n);
 char* strerror(int errnum);
 
 int strcmp(const char* s1, const char* s2);
+int strncmp(const char* s1, const char* s2, size_t n);
 int strcasecmp(const char* s1, const char* s2);
 int strncasecmp(const char* s1, const char* s2, size_t n);
 size_t strlen(const char* str);

+ 2 - 0
gblibc/include/unistd.h

@@ -49,6 +49,8 @@ void* sbrk(ssize_t increment);
 
 int isatty(int fd);
 
+extern char** environ;
+
 #ifdef __cplusplus
 }
 #endif

+ 5 - 0
gblibc/private-include/priv-vars.h

@@ -2,6 +2,7 @@
 #define __GBLIBC_PRIV_VARS_H_
 
 #include <list.h>
+#include <stdint.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -15,6 +16,7 @@ extern "C" {
 void** __start_brk_location(void);
 void** __curr_brk_location(void);
 list_head* __io_files_location(void);
+size_t* __environ_size_location(void);
 
 #undef start_brk
 #define start_brk (*__start_brk_location())
@@ -24,6 +26,9 @@ list_head* __io_files_location(void);
 #undef iofiles
 #define iofiles (*__io_files_location())
 
+#undef environ_size
+#define environ_size (*__environ_size_location())
+
 #ifdef __cplusplus
 }
 #endif

+ 6 - 2
gblibc/src/crt0.s

@@ -13,15 +13,19 @@ _start:
     andl $0xfffffff0, %esp
 
     pushl %ebx
-    pushl $0
-
     movl %esp, %ebp
 
+    leal (%ebx, %eax, 4), %ebx
+    addl $8, %ebx
+    pushl %ebx
+
     pushl %ecx
     pushl %eax
 
     call __init_gblibc
 
+    subl $4, %ebp
+
     call main
 
     movl %eax, %edi  # code

+ 27 - 1
gblibc/src/init.c

@@ -1,3 +1,4 @@
+#include <assert.h>
 #include <priv-vars.h>
 #include <stdlib.h>
 #include <syscall.h>
@@ -16,11 +17,36 @@ list_head* __io_files_location(void)
     return &__io_files;
 }
 
-void __init_gblibc(void)
+size_t* __environ_size_location(void)
 {
+    static size_t __environ_size;
+    return &__environ_size;
+}
+
+void __init_gblibc(int argc, char** argv, char** envp)
+{
+    (void)argc, (void)argv;
     // initialize program break position
     start_brk = curr_brk = (void*)syscall1(SYS_brk, (uint32_t)NULL);
 
+    // save environ vector
+    environ_size = 4;
+    environ = malloc(environ_size * sizeof(char*));
+    assert(environ);
+
+    while (*envp) {
+        char* eqp = strchr(*envp, '=');
+        if (!eqp || eqp == *envp)
+            goto next;
+
+        *eqp = 0;
+        char* value = eqp + 1;
+        setenv(*envp, value, 1);
+
+    next:;
+        ++envp;
+    }
+
     // stdout, stdin, stderr objects
     list_node* node = NULL;
 

+ 34 - 0
gblibc/src/stdlib.c

@@ -1,6 +1,7 @@
 #include <alloca.h>
 #include <priv-vars.h>
 #include <stdint.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <syscall.h>
 #include <unistd.h>
@@ -208,3 +209,36 @@ void* bsearch(const void* key, const void* base, size_t num, size_t size, compar
     
     return bsearch(key, base, mid, size, cmp);
 }
+
+int setenv(const char* name, const char* value, int overwrite)
+{
+    size_t i = 0;
+    for (; environ[i]; ++i) {
+        char* eqpos = strchr(environ[i], '=');
+        if (strncmp(name, environ[i], eqpos - environ[i]) == 0) {
+            if (overwrite)
+                goto fill_p;
+            return 0;
+        }
+    }
+
+    if (i + 2 == environ_size) {
+        environ_size *= 2;
+        char** newarr = malloc(environ_size * sizeof(char*));
+        if (!newarr)
+            return -1;
+        
+        memcpy(newarr, environ, sizeof(char*) * environ_size / 2);
+        free(environ);
+        environ = newarr;
+    }
+    environ[i + 1] = NULL;
+
+fill_p:;
+    char* newenv = NULL;
+    if (asprintf(&newenv, "%s=%s", name, value) < 0)
+        return -1;
+
+    environ[i] = newenv;
+    return 0;
+}

+ 10 - 2
gblibc/src/string.c

@@ -135,16 +135,24 @@ char* stpncpy(char* restrict dst, const char* restrict src, size_t n)
     return dst + len;
 }
 
-int strcmp(const char* s1, const char* s2)
+int strncmp(const char* s1, const char* s2, size_t n)
 {
+    if (n == 0)
+        return 0;
+
     int c;
-    while ((c = *s1 - *s2) == 0 && *s1) {
+    while (n-- && (c = *s1 - *s2) == 0 && *s1) {
         ++s1;
         ++s2;
     }
     return c;
 }
 
+int strcmp(const char* s1, const char* s2)
+{
+    return strncmp(s1, s2, __SIZE_MAX__);
+}
+
 int strncasecmp(const char* s1, const char* s2, size_t n)
 {
     if (n == 0)

+ 2 - 0
gblibc/src/unistd.c

@@ -250,3 +250,5 @@ int isatty(int fd)
 {
     return tcgetpgrp(fd) != -1;
 }
+
+char** environ;

+ 1 - 1
src/kernel/process.cpp

@@ -285,7 +285,7 @@ void NORETURN _kernel_init(void)
     current_thread->attr.system = 0;
 
     const char* argv[] = { "/mnt/init", "/mnt/sh", nullptr };
-    const char* envp[] = { nullptr };
+    const char* envp[] = { "LANG=C", "HOME=/", nullptr };
 
     types::elf::elf32_load_data d;
     auto* dent = fs::vfs_open("/mnt/init");

+ 1 - 2
user-space-program/init.c

@@ -37,7 +37,6 @@ _run_sh:;
         }
 
         char* shell_argv[128] = {};
-        char* envp[1] = { NULL };
 
         if (argc < 2)
             shell_argv[0] = "/bin/sh";
@@ -47,7 +46,7 @@ _run_sh:;
         for (int i = 2; i < argc; ++i)
             shell_argv[i - 1] = argv[i];
         
-        execve(shell_argv[0], shell_argv, envp);
+        execve(shell_argv[0], shell_argv, environ);
 
         print("[init] unable to run sh, exiting...\n");
         return -1;

+ 1 - 2
user-space-program/sh.c

@@ -79,8 +79,7 @@ runcmd(struct cmd *cmd)
     ecmd = (struct execcmd*)cmd;
     if(ecmd->argv[0] == 0)
       _exit(-1);
-    char* const envp[1] = { NULL };
-    execve(ecmd->argv[0], ecmd->argv, envp);
+    execve(ecmd->argv[0], ecmd->argv, environ);
     printf("exec %s failed\n", ecmd->argv[0]);
     break;