[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[tyndur-devel] [PATCH 6/7] libc/Pascal-RTL: stdio mit lio_dup() und PPB übergeben



* libc/Pascal-RTL: Anstatt beim console-Service nach dem Dateinamen für
  die Standardein- und -ausgabe zu fragen und diese dann neu zu öffnen,
  werden jetzt LIO-Streams übergeben und im PPB eingetragen.

Signed-off-by: Kevin Wolf <kevin@xxxxxxxxxx>
---
 src/modules/c/getterm/main.c       |   1 +
 src/modules/include/init.h         |   5 ++
 src/modules/include/lostio.h       |   1 +
 src/modules/include/syscall.h      |   1 +
 src/modules/init/loader.c          |  11 ++++
 src/modules/lib/crt0.c             |  10 +++
 src/modules/lib/param.c            | 128 +++++++++++++++++++++++++++++++++++++
 src/modules/lib/stdlibc/file.c     |  11 ++++
 src/modules/lib/stdlibc/stdio.c    | 103 +++++++++++++++--------------
 src/modules/pas/lib/rtl/system.pas |  41 ++++++------
 10 files changed, 243 insertions(+), 69 deletions(-)

diff --git a/src/modules/c/getterm/main.c b/src/modules/c/getterm/main.c
index 92d755b..ade145c 100644
--- a/src/modules/c/getterm/main.c
+++ b/src/modules/c/getterm/main.c
@@ -134,6 +134,7 @@ int main(int argc, char* argv[])
     console_set_handle(STDERR, argv[3]);
 
     // Lokale Ein- und Ausgabehandles auch anpassen
+    stdin = stdout = stderr = NULL;
     stdio_init();
 
     do {
diff --git a/src/modules/include/init.h b/src/modules/include/init.h
index 2de8092..07d7972 100644
--- a/src/modules/include/init.h
+++ b/src/modules/include/init.h
@@ -31,6 +31,7 @@
 #include <types.h>
 #include <stdio.h>
 #include <stdbool.h>
+#include <syscall.h>
 
 #define INIT_PID 1
 
@@ -55,6 +56,10 @@ int ppb_get_argc(struct proc_param_block* ppb, size_t ppb_size);
 void ppb_copy_argv(struct proc_param_block* ppb, size_t ppb_size,
     char** argv, int argc);
 int ppb_extract_env(struct proc_param_block* ppb, size_t ppb_size);
+int ppb_forward_streams(struct proc_param_block* ppb, size_t ppb_size,
+                        pid_t from, pid_t to);
+int ppb_get_streams(lio_stream_t* streams, struct proc_param_block* ppb,
+                    size_t ppb_size, pid_t from, int num);
 
 
 #ifdef _USE_START_
diff --git a/src/modules/include/lostio.h b/src/modules/include/lostio.h
index b1c56d5..3b79469 100644
--- a/src/modules/include/lostio.h
+++ b/src/modules/include/lostio.h
@@ -409,6 +409,7 @@ int lio_request_translated_blocks(struct lio_resource* res, uint64_t offset,
 /* Interne Funktionen */
 int __iores_fileno(io_resource_t* io_res);
 struct lostio_internal_file* __create_file_from_iores(io_resource_t* io_res);
+struct lostio_internal_file* __create_file_from_lio_stream(lio_stream_t s);
 
 #endif
 
diff --git a/src/modules/include/syscall.h b/src/modules/include/syscall.h
index 5a493bb..017d157 100644
--- a/src/modules/include/syscall.h
+++ b/src/modules/include/syscall.h
@@ -61,6 +61,7 @@ void* get_phys_addr(void* address);
 uint32_t create_shared_memory(uint32_t size);
 void *open_shared_memory(uint32_t id);
 void close_shared_memory(uint32_t id);
+ssize_t shared_memory_size(uint32_t id);
 
 bool request_ports(uint32_t port, uint32_t length);
 bool release_ports(uint32_t port, uint32_t length);
diff --git a/src/modules/init/loader.c b/src/modules/init/loader.c
index 3f440ca..58649e2 100644
--- a/src/modules/init/loader.c
+++ b/src/modules/init/loader.c
@@ -37,6 +37,7 @@
 #include <syscall.h>
 #include <loader.h>
 #include <lock.h>
+#include <init.h>
 
 static struct {
     pid_t   pid;
@@ -112,6 +113,16 @@ pid_t load_single_module(void* image, size_t image_size, char* args,
     }
 
     if (ppb_shm_id) {
+        void *ppb = open_shared_memory(ppb_shm_id);
+        ssize_t ppb_size = shared_memory_size(ppb_shm_id);
+
+        if (!ppb || ppb_size < 0) {
+            goto fail;
+        }
+
+        ppb_forward_streams(ppb, ppb_size, parent_pid, loader_state.pid);
+        close_shared_memory(ppb_shm_id);
+
         init_child_ppb(loader_state.pid, ppb_shm_id);
     }
 
diff --git a/src/modules/lib/crt0.c b/src/modules/lib/crt0.c
index fa4e2da..94cfa5e 100644
--- a/src/modules/lib/crt0.c
+++ b/src/modules/lib/crt0.c
@@ -32,6 +32,7 @@
 #include <init.h>
 #include <string.h>
 #include <stdio.h>
+#include <lostio.h>
 
 //Sollte anders geloest werden
 extern int main(int argc, char* argv[]);
@@ -79,6 +80,15 @@ static void __attribute__((used))
     init_envvars(ppb, ppb_size);
     init_waitpid();
 #ifndef _NO_STDIO_
+    if (ppb_shm_id) {
+        lio_stream_t streams[3];
+        int ret = ppb_get_streams(streams, ppb, ppb_size, 1, 3);
+        if (ret == 3) {
+            stdin = streams[0] ? __create_file_from_lio_stream(streams[0]) : NULL;
+            stdout = streams[1] ? __create_file_from_lio_stream(streams[1]) : NULL;
+            stderr = streams[2] ? __create_file_from_lio_stream(streams[2]) : NULL;
+        }
+    }
     stdio_init();
 #endif
 
diff --git a/src/modules/lib/param.c b/src/modules/lib/param.c
index a79be5b..f03dc53 100644
--- a/src/modules/lib/param.c
+++ b/src/modules/lib/param.c
@@ -28,15 +28,19 @@
 
 #include <stdlib.h>
 #include <string.h>
+#include <stdio.h>
 #include <errno.h>
+#include <assert.h>
 
 #include <syscall.h>
+#include <lostio.h>
 #include <page.h>
 #include <env.h>
 
 enum ppb_entry_type {
     PPB_CMDLINE_ARG = 1,
     PPB_ENV_VAR,
+    PPB_STREAM,
 };
 
 struct ppb_entry {
@@ -171,6 +175,42 @@ static int ppb_builder_finish(struct ppb_builder* b)
     return shm;
 }
 
+static int ppb_add_cloned_stdio(struct ppb_builder* b,
+                                lio_stream_t *remote, int num)
+{
+    FILE* stdio[] = { stdin, stdout, stderr };
+    int i;
+
+    assert(num <= 3);
+    for (i = 0; i < num; i++) {
+        lio_stream_t orig, copy;
+        int ret;
+
+        orig = file_get_stream(stdio[i]);
+        if (orig < 0) {
+            continue;
+        }
+
+        copy = lio_dup(orig, -1);
+        if (copy < 0) {
+            return copy;
+        }
+
+        remote[i] = lio_pass_fd(copy, 1);
+        if (remote[i] < 0) {
+            lio_close(copy);
+            return remote[i];
+        }
+
+        ret = ppb_add_entry(b, PPB_STREAM, &remote[i], sizeof(remote[i]));
+        if (ret < 0) {
+            return ret;
+        }
+    }
+
+    return 0;
+}
+
 static int ppb_add_cloned_env(struct ppb_builder* b)
 {
     int i, cnt;
@@ -222,6 +262,11 @@ int ppb_from_argv(const char* const argv[])
     const char* const* p;
     int ret;
 
+    /* Muss hier deklariert werden statt in ppb_add_cloned_stdio(), sonst ist
+     * der Pointer nicht mehr gültig, wenn er in ppb_builder_finish() benutzt
+     * wird. */
+    lio_stream_t remote_streams[3];
+
     b = ppb_builder_init();
     if (b == NULL) {
         errno = ENOMEM;
@@ -240,6 +285,12 @@ int ppb_from_argv(const char* const argv[])
         return -1;
     }
 
+    ret = ppb_add_cloned_stdio(b, remote_streams, 3);
+    if (ret < 0) {
+        errno = -ret;
+        return -1;
+    }
+
     shm = ppb_builder_finish(b);
     if (shm < 0) {
         errno = -shm;
@@ -363,3 +414,80 @@ int ppb_extract_env(struct proc_param_block* ppb, size_t ppb_size)
 
     return 0;
 }
+
+int ppb_forward_streams(struct proc_param_block* ppb, size_t ppb_size,
+                        pid_t from, pid_t to)
+{
+    int i;
+
+    if (!ppb_is_valid(ppb, ppb_size)) {
+        return -EINVAL;
+    }
+
+    for (i = 0; i < ppb->num; i++) {
+        lio_stream_t s, remote;
+
+        if (ppb->entries[i].type != PPB_STREAM) {
+            continue;
+        }
+
+        if (ppb->entries[i].len != sizeof(lio_stream_t)) {
+            return -EFAULT;
+        }
+
+        s = *(lio_stream_t*)(((char*) ppb) + ppb->entries[i].value);
+
+        if (lio_stream_origin(s) != from) {
+            return -EBADF;
+        }
+
+        remote = lio_pass_fd(s, to);
+        if (remote < 0) {
+            return remote;
+        }
+
+        *(lio_stream_t*)(((char*) ppb) + ppb->entries[i].value) = remote;
+    }
+
+    return 0;
+}
+
+int ppb_get_streams(lio_stream_t* streams, struct proc_param_block* ppb,
+                    size_t ppb_size, pid_t from, int num)
+{
+    int i;
+    int found = 0;
+
+    if (!ppb_is_valid(ppb, ppb_size)) {
+        return -EINVAL;
+    }
+
+    for (i = 0; i < ppb->num; i++) {
+        lio_stream_t s;
+
+        if (ppb->entries[i].type != PPB_STREAM) {
+            continue;
+        }
+
+        if (ppb->entries[i].len != sizeof(lio_stream_t)) {
+            return -EFAULT;
+        }
+
+        s = *(lio_stream_t*)(((char*) ppb) + ppb->entries[i].value);
+
+        if (lio_stream_origin(s) != from) {
+            return -EBADF;
+        }
+
+        if (found < num) {
+            streams[found++] = s;
+        } else {
+            lio_close(s);
+        }
+    }
+    while (found < num) {
+        streams[found++] = 0;
+    }
+
+    return found;
+}
diff --git a/src/modules/lib/stdlibc/file.c b/src/modules/lib/stdlibc/file.c
index b0935bc..513f75b 100644
--- a/src/modules/lib/stdlibc/file.c
+++ b/src/modules/lib/stdlibc/file.c
@@ -73,6 +73,17 @@ FILE* __create_file_from_iores(io_resource_t* io_res)
     return int_res;
 }
 
+FILE* __create_file_from_lio_stream(lio_stream_t s)
+{
+    io_resource_t* iores = malloc(sizeof(*iores));
+    *iores = (io_resource_t) {
+        .lio2_stream    =   s,
+        .lio2_res       =   1, /* XXX Hässlich, aber wird nur auf > 0 geprüft */
+        .flags          =   IO_RES_FLAG_READAHEAD,
+    };
+    return __create_file_from_iores(iores);
+}
+
 /**
  * Datei oeffnen
  *
diff --git a/src/modules/lib/stdlibc/stdio.c b/src/modules/lib/stdlibc/stdio.c
index e6a1955..7e0766f 100644
--- a/src/modules/lib/stdlibc/stdio.c
+++ b/src/modules/lib/stdlibc/stdio.c
@@ -51,71 +51,80 @@ void stdio_init(void)
     
 
     // stdin aktualisieren
-    path_file = fopen("console:/stdin",  "r");
-    if (path_file == NULL) {
-        // Kein stdin
-        stdin = NULL;
-    } else {
-        // Pfad einlesen
-        size = fread(path, 1, 128, path_file);
-        path[size] = 0;
-
-        // Falls stdin schon geoeffnet wurde, wird freopen benutzt, damit siche
-        // nichts durcheinander kommt
-        if (stdin) {
-            freopen(path, "rs", stdin);
+    if (!stdin) {
+        path_file = fopen("console:/stdin",  "r");
+        if (path_file == NULL) {
+            // Kein stdin
+            stdin = NULL;
         } else {
-            stdin  = fopen(path,  "rs");
+            // Pfad einlesen
+            size = fread(path, 1, 128, path_file);
+            path[size] = 0;
+
+            // Falls stdin schon geoeffnet wurde, wird freopen benutzt, damit siche
+            // nichts durcheinander kommt
+            if (stdin) {
+                freopen(path, "rs", stdin);
+            } else {
+                stdin  = fopen(path,  "rs");
+            }
+            fclose(path_file);
         }
-        fclose(path_file);
-
+    }
+    if (stdin) {
         // stdin muss nicht gepuffert sein
         setvbuf(stdin, NULL, _IONBF, 0);
     }
 
     // stdout aktualisieren
-    path_file = fopen("console:/stdout",  "r");
-    if (path_file == NULL) {
-        // Kein stdin
-        stdout = NULL;
-    } else {
-        // Pfad einlesen
-        size = fread(path, 1, 128, path_file);
-        path[size] = 0;
-
-        // Siehe oben bei stdin
-        if (stdout) {
-            freopen(path, "a", stdout);
+    if (!stdout) {
+        path_file = fopen("console:/stdout",  "r");
+        if (path_file == NULL) {
+            // Kein stdin
+            stdout = NULL;
         } else {
-            stdout = fopen(path,  "a");
+            // Pfad einlesen
+            size = fread(path, 1, 128, path_file);
+            path[size] = 0;
+
+            // Siehe oben bei stdin
+            if (stdout) {
+                freopen(path, "a", stdout);
+            } else {
+                stdout = fopen(path,  "a");
+            }
+            fclose(path_file);
         }
-        fclose(path_file);
-
+    }
+    if (stdout) {
         // Zeilenpuffer fuer stdout aktivieren
         setvbuf(stdout, stdout_buf, _IOLBF, sizeof(stdout_buf));
     }
 
     // stderr
-    path_file = fopen("console:/stderr",  "r");
-    if (path_file == NULL) {
-        // Kein stdin
-        stderr = NULL;
-    } else {
-        // Pfad einlesen
-        size = fread(path, 1, 128, path_file);
-        path[size] = 0;
-
-        // Siehe oben bei stdin
-        if (stderr) {
-            freopen(path, "a", stderr);
+    if (!stderr) {
+        path_file = fopen("console:/stderr",  "r");
+        if (path_file == NULL) {
+            // Kein stdin
+            stderr = NULL;
         } else {
-            stderr = fopen(path,  "a");
-        }
+            // Pfad einlesen
+            size = fread(path, 1, 128, path_file);
+            path[size] = 0;
+
+            // Siehe oben bei stdin
+            if (stderr) {
+                freopen(path, "a", stderr);
+            } else {
+                stderr = fopen(path,  "a");
+            }
 
+            fclose(path_file);
+        }
+    }
+    if (stderr) {
         // stderr soll ungepuffert sein
         setvbuf(stderr, NULL, _IONBF, 0);
-
-        fclose(path_file);
     }
 }
 
diff --git a/src/modules/pas/lib/rtl/system.pas b/src/modules/pas/lib/rtl/system.pas
index c9501c5..378dbd8 100644
--- a/src/modules/pas/lib/rtl/system.pas
+++ b/src/modules/pas/lib/rtl/system.pas
@@ -164,6 +164,11 @@ begin
 end;
 *)
 
+function ppb_get_streams(streams: PInt64; ppb: Pointer;
+                         size, pid, num: integer): integer;
+    cdecl; external name 'ppb_get_streams';
+function file_from_lio(stream: Int64): PDWord;
+    cdecl; external name '__create_file_from_lio_stream';
 procedure c_stdio_init(); cdecl; external name 'stdio_init';
 function c_setvbuf(f: Pointer; buf: Pointer; mode: integer; size: TSize):
     integer; cdecl; external name 'setvbuf';
@@ -174,30 +179,22 @@ var
     c_stderr: ^dword; external name 'stderr';
 
 procedure SysInitStdIO;
-(*
 var
-    filename: String;
-    c_stdin, c_stdout, c_stderr: text;
-*)    
+    streams: Array [0..2] of Int64;
+    ret: integer;
 begin
-(*
-    TextRec(c_stdin).mode := fmClosed;
-    TextRec(c_stdout).mode := fmClosed;
-    TextRec(c_stderr).mode := fmClosed;
-    
-    filename := GetRealStdIO('console:/stdin') + #0;
-    Do_Open(c_stdin,  @filename[1], 0);
-
-    filename := GetRealStdIO('console:/stdout') + #0;
-    Do_Open(c_stdout, @filename[1], 0);
-    
-    filename := GetRealStdIO('console:/stderr') + #0;
-    Do_Open(c_stderr, @filename[1], 0);
-
-    StdInputHandle  := TextRec(c_stdin).handle;
-    StdOutputHandle := TextRec(c_stdout).handle;
-    StdErrorHandle  := TextRec(c_stderr).handle;
-*)    
+    ret := ppb_get_streams(@streams[0], ppb_ptr, ppb_size, 1, 3);
+    if ret = 3 then begin
+        if streams[0] <> 0 then begin
+            c_stdin := file_from_lio(streams[0]);
+        end;
+        if streams[1] <> 0 then begin
+            c_stdout := file_from_lio(streams[1]);
+        end;
+        if streams[2] <> 0 then begin
+            c_stderr := file_from_lio(streams[2]);
+        end;
+    end;
 
     c_stdio_init();
 
-- 
2.1.4