[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