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

Re: [tyndur-devel] [PATCH 7/7] argv über PPB übergeben



On Wed, Dec 29 14:12, Kevin Wolf wrote:
> * libc: Die Argumente von neu gestarteten Programmen werden jetzt in
>   einem PPB statt in der Kommandozeile übergeben
> * init: Angepasst, um Programme mit PPB starten zu können
> * Pascal-RTL: argv wird jetzt aus dem PPB ausgelesen

Wäre der letzte Punkt nicht eher was für einen separaten Pätsch?

> 
> Signed-off-by: Kevin Wolf <kevin@xxxxxxxxxx>
> ---
>  src/modules/include/init.h         |    1 +
>  src/modules/init/init.c            |   76 ++++++++++++++++++++----------------
>  src/modules/init/loader.c          |    7 +++-
>  src/modules/lib/init.c             |   32 +++++++++++++--
>  src/modules/lib/param.c            |   16 ++++++++
>  src/modules/pas/lib/prt0.asm       |   17 +++++++-
>  src/modules/pas/lib/rtl/system.pas |   61 +++++++----------------------
>  7 files changed, 122 insertions(+), 88 deletions(-)
> 
> diff --git a/src/modules/include/init.h b/src/modules/include/init.h
> index eb29b3a..4bd3ebd 100644
> --- a/src/modules/include/init.h
> +++ b/src/modules/include/init.h
> @@ -44,6 +44,7 @@ char *init_service_get_name(pid_t pid);
>  
>  void init_process_exit(int result);
>  pid_t init_execute(const char* cmd);
> +pid_t init_execv(const char* file, const char* const argv[]);
>  int ppb_from_argv(const char* const argv[]);
>  
>  int cmdline_get_argc(const char* args);
> diff --git a/src/modules/init/init.c b/src/modules/init/init.c
> index 573bccd..384b151 100644
> --- a/src/modules/init/init.c
> +++ b/src/modules/init/init.c
> @@ -76,8 +76,9 @@ void rpc_dev_list(pid_t pid, uint32_t cid, size_t size, void* data);
>  
>  void load_modules(init_module_list_t* modules);
>  pid_t load_single_module(void* image, size_t image_size, char* args,
> -    pid_t parent_pid) ;
> -pid_t start_program(char* path, char* args, pid_t parent_pid);
> +    pid_t parent_pid, int ppb_shm_id);
> +static pid_t start_program(const char* path, char* args, pid_t parent_pid,
> +    int shm);
>  extern void init_sync_messages(void);
>  
>  struct service_s* get_service_by_name(const char* name);
> @@ -355,7 +356,7 @@ void load_modules(init_module_list_t* modules)
>      { 
>          //printf("Modul %d: %s\n", i, modules->modules[i].cmdline);
>          load_single_module((Elf32_Ehdr*) modules->modules[i].start,
> -            modules->modules[i].size, modules->modules[i].cmdline, 0);
> +            modules->modules[i].size, modules->modules[i].cmdline, 0, 0);
>          mem_free(modules->modules[i].start, modules->modules[i].size);
>          //msleep(50); // Damit die Meldungen nicht durcheinandergeraten
>      } 
> @@ -436,7 +437,8 @@ size_t ainflate(void* src, size_t len, void** dest_ptr)
>      return ret;
>  }
>  
> -pid_t start_program(char* path, char* args, pid_t parent_pid)
> +static pid_t start_program(const char* path, char* args, pid_t parent_pid,
> +    int shm)
>  {
>      pid_t pid;
>      FILE* f = fopen(path, "r");
> @@ -479,10 +481,13 @@ pid_t start_program(char* path, char* args, pid_t parent_pid)
>      {
>          /* Skript: Interpreter aufrufen */
>          char interpreter[256];
> -        char* new_path;
> -        char* new_args;
> +        char* interp_args;
> +        int ppb_argc, interp_argc, argc;
>          int ret;
>          size_t i;
> +        struct proc_param_block* ppb;
> +        size_t ppb_size;
> +        int new_shm;
>  
>          fgets(interpreter, 256, f);
>          fclose(f);
> @@ -496,14 +501,29 @@ pid_t start_program(char* path, char* args, pid_t parent_pid)
>              return false;
>          }
>  
> -        asprintf(&new_args, "%s%s%s",
> -            interpreter + 2,
> -            args ? " " : "",
> -            args ? args : "");
> -        new_path = strtok(interpreter + 2, " ");
> +        interp_args = interpreter + 2;
> +
> +        ppb = open_shared_memory(shm);
> +        if (ppb == NULL) {
> +            return false;
> +        }
> +        ppb_size = PAGE_SIZE; // FIXME

Was gehoert denn hier in richtig hin? Ein shm_size-Syscall?

> +
> +        ppb_argc = ppb_get_argc(ppb, ppb_size);
> +        interp_argc = cmdline_get_argc(interp_args);
> +        argc = ppb_argc + interp_argc;
> +
> +        const char* argv[argc + 1];
> +
> +        cmdline_copy_argv(interp_args, argv, interp_argc);
> +        ppb_copy_argv(ppb, ppb_size, (char**) argv + interp_argc, ppb_argc);
> +        argv[argc] = NULL;
> +
> +        new_shm = ppb_from_argv(argv);
> +        ret = start_program(argv[0], args, parent_pid, new_shm);
> +        close_shared_memory(new_shm);
> +        close_shared_memory(shm);
>  
> -        ret = start_program(new_path, new_args, parent_pid);
> -        free(new_args);
>          return ret;
>      }
>      else
> @@ -514,7 +534,7 @@ pid_t start_program(char* path, char* args, pid_t parent_pid)
>      }
>      fclose(f);
>  
> -    pid = load_single_module(buffer, buffer_size, args, parent_pid);
> +    pid = load_single_module(buffer, buffer_size, args, parent_pid, shm);
>      free(buffer);
>      return pid;
>  }
> @@ -522,33 +542,21 @@ pid_t start_program(char* path, char* args, pid_t parent_pid)
>  
>  void rpc_loadelf(pid_t pid, uint32_t correlation_id, size_t data_size, void* data)
>  {
> -    char* first_space;
>      pid_t new_pid;
> +    size_t fn_len;
> +    int shm;
>  
> -    // Wir erwarten einen Null-terminierten String
> -    if (strnlen(data, data_size) == data_size) {
> +    // Wir erwarten einen Null-terminierten String und einen Integer
> +    fn_len = strnlen(data, data_size);
> +
> +    if (data_size < fn_len + sizeof(int) + 1) {
>          rpc_send_dword_response(pid, correlation_id, 0);
>          return;
>      }
>  
> +    shm = *(int*)((uintptr_t) data + fn_len + 1);
>  
> -    first_space = strchr(data, ' ');
> -
> -    //Wenn kein leerschlag vorhanden ist, muessen keine Kommandozeilenargumente
> -    //abgetrennt werden.
> -    if (first_space == NULL) {
> -        new_pid = start_program(data, data, pid);
> -    } else {
> -        //Sonst wird erst der Name rauskopiert
> -        size_t filename_length = (uint32_t) first_space - (uint32_t) data;
> -        char* filename = malloc(filename_length + 1);
> -        memcpy(filename, data, filename_length);
> -        filename[filename_length] = '\0';
> -
> -        new_pid = start_program(filename, data, pid);
> -        
> -        free(filename);
> -    }
> +    new_pid = start_program(data, data, pid, shm);
>      rpc_send_dword_response(pid, correlation_id, new_pid);
>  }
>  
> diff --git a/src/modules/init/loader.c b/src/modules/init/loader.c
> index 3a5fdea..3f440ca 100644
> --- a/src/modules/init/loader.c
> +++ b/src/modules/init/loader.c
> @@ -99,7 +99,7 @@ bool loader_create_thread(pid_t process, vaddr_t address)
>   * Erstellt einen neuen Prozess aus einer ELF-Datei
>   */
>  pid_t load_single_module(void* image, size_t image_size, char* args,
> -    pid_t parent_pid)
> +    pid_t parent_pid, int ppb_shm_id)
>  {
>      p();
>      lock(&loader_state.lock);
> @@ -110,6 +110,11 @@ pid_t load_single_module(void* image, size_t image_size, char* args,
>          loader_state.pid = 0;
>          goto fail;
>      }
> +
> +    if (ppb_shm_id) {
> +        init_child_ppb(loader_state.pid, ppb_shm_id);
> +    }
> +
>      unblock_process(loader_state.pid);
>  
>  fail:
> diff --git a/src/modules/lib/init.c b/src/modules/lib/init.c
> index ea0a7d2..2edad3e 100644
> --- a/src/modules/lib/init.c
> +++ b/src/modules/lib/init.c
> @@ -99,9 +99,12 @@ void init_process_exit(int result)
>  }
>  
>  /**
> + * Startet einen neuen Prozess
>   *
> + * @param cmd Dateiname des zu startenden Programms
> + * @param ppb_shm_id ID des SHM, der den Process Parameter Block enthaelt
>   */
> -pid_t init_execute(const char* cmd)
> +pid_t __init_exec(const char* cmd, int ppb_shm_id)
>  {
>      pid_t pid;
>  
> @@ -161,11 +164,10 @@ pid_t init_execute(const char* cmd)
>      
>      // Ansonsten wird jetzt der ganze Befehl in einen Puffer kopiert
>      size_t abs_path_len = strlen(abs_path);
> -    size_t args_len = strlen(cmd + program_len);
> -    size_t rpc_size = abs_path_len + args_len + 1;
> +    size_t rpc_size = abs_path_len + sizeof(int) + 1;
>      char rpc_data[rpc_size];
>      strcpy(rpc_data, abs_path);
> -    strcpy(rpc_data + abs_path_len, cmd + program_len);
> +    *(int*)(rpc_data + abs_path_len + 1) = ppb_shm_id;
>      free(abs_path);
>  
>      // TODO: Relative Pfade
> @@ -215,6 +217,28 @@ void cmdline_copy_argv(char* args, const char** argv, size_t argc)
>      argv[argc] = NULL;
>  }
>  
> +pid_t init_execute(const char* args)
> +{
> +    int argc;
> +    char* s;
> +    int ret;
> +
> +    /* Zunaechst die Argumente zaehlen. */
> +    argc = cmdline_get_argc(args);
> +
> +    /* Jetzt argv anlegen und befuellen */
> +    const char* argv[argc + 1];
> +
> +    s = strdup(args);
> +    cmdline_copy_argv(s, argv, argc);
> +
> +    /* Und den Prozess starten */
> +    ret = init_execv(args, argv);
> +    free(s);
> +
> +    return ret;
> +}
> +
>  int init_dev_register(struct init_dev_desc* dev, size_t size)
>  {
>      return rpc_get_int(1, "DEV_REG ", size, (char*) dev);
> diff --git a/src/modules/lib/param.c b/src/modules/lib/param.c
> index c3a4f60..1267216 100644
> --- a/src/modules/lib/param.c
> +++ b/src/modules/lib/param.c
> @@ -193,6 +193,22 @@ int ppb_from_argv(const char* const argv[])
>      return shm;
>  }
>  
> +pid_t init_execv(const char* file, const char* const argv[])
> +{
> +    int shm;
> +    pid_t ret;
> +
> +    shm = ppb_from_argv(argv);
> +    if (shm == -1) {
> +        return -1;
> +    }
> +
> +    ret = __init_exec(file, shm);
> +    close_shared_memory(shm);
> +
> +    return ret;
> +}
> +
>  bool ppb_is_valid(struct proc_param_block* ppb, size_t ppb_size)
>  {
>      size_t offset;
> diff --git a/src/modules/pas/lib/prt0.asm b/src/modules/pas/lib/prt0.asm
> index 8aff18a..4570d62 100644
> --- a/src/modules/pas/lib/prt0.asm
> +++ b/src/modules/pas/lib/prt0.asm
> @@ -1,13 +1,24 @@
>  ; startup
>  extern PASCALMAIN
> -global _start
>  
>  section .text
>  
> +global _start
>  _start:
> +        mov [__ppb_shm_id], eax
> +        mov [__ppb_ptr], ebx
> +        mov [__ppb_size], ecx
>          call PASCALMAIN
>          hlt
> -        
> +
>  section .data
> -        
> +
>  section .bss
> +
> +global __ppb_size
> +global __ppb_ptr
> +global __ppb_shm_id
> +
> +__ppb_size:     resd 1
> +__ppb_ptr:      resd 1
> +__ppb_shm_id:   resd 1
> diff --git a/src/modules/pas/lib/rtl/system.pas b/src/modules/pas/lib/rtl/system.pas
> index 92701ea..1cc5d7b 100644
> --- a/src/modules/pas/lib/rtl/system.pas
> +++ b/src/modules/pas/lib/rtl/system.pas
> @@ -58,6 +58,11 @@ procedure DisableFlushing(var f: Text);
>  
>  implementation
>  
> +var
> +    ppb_size: integer; external name '__ppb_size';
> +    ppb_ptr: Pointer; external name '__ppb_ptr';
> +    ppb_shm_id: integer; external name '__ppb_shm_id';
> +
>  procedure InitMessaging; cdecl; external name 'init_messaging';
>  procedure InitEnvironment; cdecl; external name 'init_envvars';
>  procedure InitWaitpid; cdecl; external name 'init_waitpid';
> @@ -96,7 +101,7 @@ end;
>  { number of args }
>  function paramcount : longint;
>  begin
> -    paramcount := argc;
> +    paramcount := argc - 1;
>  end;
>  
>  { argument number l }
> @@ -105,23 +110,7 @@ var
>      p: PChar;
>  begin
>      if (l >= 0) and (l <= argc) then begin
> -        (*paramstr := StrPas(argv[l])*)
> -        p := commandline;
> -        while (l > 0) and (p^ <> #0) do begin
> -            if p^ = ' ' then begin
> -                Dec(l);
> -                while (p+1)^ = ' ' do begin
> -                    Inc(p);
> -                end;
> -            end;
> -            Inc(p);
> -        end;
> -
> -        paramstr := '';
> -        while not (p^ in [' ', #0]) do begin 
> -            paramstr := paramstr + p^;
> -            Inc(p);
> -        end;
> +        paramstr := StrPas(argv[l]);
>      end else begin
>          paramstr := '';
>      end;
> @@ -223,41 +212,21 @@ begin
>      OpenStdIO(StdErr, fmOutput, StdErrorHandle);
>  end;
>  
> +function ppb_get_argc(ppb: Pointer; size: integer): integer;
> +    cdecl; external name 'ppb_get_argc';
> +procedure ppb_copy_argv(ppb: Pointer; size: integer; argv: PPChar; argc: integer);
> +    cdecl; external name 'ppb_copy_argv';
> +
>  procedure InitParams;
>  var
>      i: integer;
>      p: PChar;
>      space: boolean;
>  begin
> -    commandline := GetCmdline();
> -
> -    p := commandline;
> -    argc := 0;
> -    space := false;
> -    while p^ <> #0 do begin
> -        if p^ = ' ' then begin
> -            space := true;
> -        end else if space then begin
> -            space := false;
> -            Inc(argc);
> -        end;
> -
> -        Inc(p);
> -    end;
> +    argc := ppb_get_argc(ppb_ptr, ppb_size);

Hier vielleicht noch etwas Fehlerbehandlung?

>  
> -    (*argv := GetMem((argc + 1) * sizeof(PChar));
> -    
> -    p := cmdline;
> -    argv^ := p;
> -    i := 1;
> -    while p^ <> #0 do begin
> -        if p^ = ' ' then begin
> -            (argv + i)^ := p;
> -            Inc(i);
> -        end;
> -
> -        Inc(p);
> -    end;*)
> +    argv := GetMem((argc + 1) * sizeof(PChar));
> +    ppb_copy_argv(ppb_ptr, ppb_size, argv, argc);
>  end;
>  
>  Begin

Weiter fällt mir auf, dass die crt0 noch den Code für ohne PPB enthält,
aber prt0 nicht. Hat das irgend einen konkreten Grund? ;-)

Sonst könnte das wohl etwa hinkommen, glaube ich.

-- 
Antoine Kaufmann
<toni@xxxxxxxxxxxxxxxx>

Attachment: pgp9_tN38mhuw.pgp
Description: PGP signature