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

Re: [Lost] [Patch] init_execute relative Pfade und $PATH



Am Sonntag, 23. März 2008 01.47:19 schrieb Kevin Wolf:
> Antoine Kaufmann schrieb:
> > +    strncpy(program, cmd, program_len);
> > +    program[program_len] = 0;
> > +    printf("program: '%s' ", program);
>
> Debugausgabe, und dazu noch eine englische. Schande! ;-)

Die ist schon deutsch. Ich habe nur den Namen der Variablen übernommen. *g*

> > +    // Pruefen ob es sich um einen Pfad handelt
> > +    abs_path = io_get_absolute_path(program);
> > +    f = fopen(abs_path, "r");
> > +    if (f == NULL) {
>
> Zum einen fände ich es grundsätzlich schöner, wenn die kurze Bedingung
> der then-Pfad ist, ansonsten habe ich bis zum else schon wieder
> vergessen, worum es geht.

Die fällt jetzt eh weg.

> In diesem speziellen Fall (und unten nochmal) öffnest du f ja nur zum
> prüfen, ob es das gibt. Hatten wir nicht neulich ein access() aufgenommen?

Hm stimmt...

> > +            printf("dir: '%s'  pp: '%s'\n", dir, program_path);
>
> Debugausgabe
>
> > +            // Pruefen ob die Datei existiert
> > +            f = fopen(program_path, "r");
> > +            if (f != NULL) {
> > +                // Wenn ja, wird ein Puffer alloziert und abs_path
> > gesetzt +                abs_path = malloc(strlen(program_path) + 1);
>
> Memleak. abs_path muß erst freigegeben werden.

Hat was.

> > +    // Wenn kein Programm gefunden wurde, wird abgebrochen
> > +    if (abs_path == NULL) {
> > +        return 0;
> > +    }
>
> Kann abs_path jemals NULL sein? Wenn ja, ist es so geschickt, oben fopen
> mit NULL als Dateinamen aufzurufen?

Jetzt schon.

> > === commmands.c
> > ==================================================================
> > +    if (wait == TRUE) {
> > +        while (waitpid(pid, &status, 0) != pid);
> > +    }
> > +    return status;
>
> Wenn wait == FALSE, ist status undefiniert.
Das ist so eh Bockmist. Denn damit kriegt man von shell ständig Befehl nicht 
gefunden, wenn ein Programm nicht sauber terminiert.

Hier der 2. Anlauf.


=== init.c
==================================================================
--- init.c	(/lost/trunk/src/modules/lib/init.c)	(revision 1451)
+++ init.c	(/lost/local/src/modules/lib/init.c)	(revision 1451)
@@ -38,6 +38,8 @@
 #include "string.h"
 #include "init.h"
 #include "stdlib.h"
+#include <io.h>
+#include <unistd.h>
 
 // Kindprozess eintragen
 extern void wait_child_add(pid_t pid);
@@ -88,17 +90,78 @@
 
 }
 
-
 /**
  *
  */
-
 pid_t init_execute(const char* cmd)
 {
     pid_t pid;
 
+    // Vollstaendigen Pfad des Programmes finden
+    size_t program_len = strcspn(cmd, " ");
+    char program[program_len + 1];
+    char* abs_path;
+
+    strncpy(program, cmd, program_len);
+    program[program_len] = 0;
+
+    // Pruefen ob es sich um einen Pfad handelt
+    abs_path = io_get_absolute_path(program);
+    if (access(abs_path, R_OK) != 0) {
+        // Den absoluten Pfad freigeben
+        free(abs_path);
+        abs_path = NULL;
+
+        // Es handelt sich nicht um eine Pfadangabe, dann wird jetzt PATH
+        // durchsucht.
+        const char* path = getenv("PATH");
+        if (path == NULL) {
+            return 0;
+        }
+
+        // Sonst wird jetzt eine Kopie davon angefertigt um sie auseinander zu
+        // nehmen.
+        char path_backup[strlen(path) + 1];
+        char* dir;
+        strcpy(path_backup, path);
+
+        dir = strtok(path_backup, ";");
+        while (dir != NULL) {
+            // Verzeichnis + / + Programm + \0
+            size_t dir_len = strlen(dir);
+            char program_path[dir_len + 1 + program_len + 1];
+            strcpy(program_path, dir);
+            program_path[dir_len] = '/';
+            strcpy(program_path + dir_len + 1, program);
+
+            // Pruefen ob die Datei existiert
+            if (access(program_path, R_OK) == 0) {
+                // Wenn ja, wird ein Puffer alloziert und abs_path gesetzt
+                abs_path = malloc(strlen(program_path) + 1);
+                strcpy(abs_path, program_path);
+                break;
+            }
+
+            dir = strtok(NULL, ";");
+        }
+    }
+
+    // Wenn kein Programm gefunden wurde, wird abgebrochen
+    if (abs_path == NULL) {
+        return 0;
+    }
+    
+    // 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;
+    char rpc_data[rpc_size];
+    strcpy(rpc_data, abs_path);
+    strcpy(rpc_data + abs_path_len, cmd + program_len);
+    free(abs_path);
+
     // TODO: Relative Pfade
-    pid = rpc_get_dword(1, "LOADELF ", strlen(cmd) + 1, (char*)cmd);
+    pid = rpc_get_dword(1, "LOADELF ", rpc_size, rpc_data);
 
     // Kindprozess eintragen, falls er erfolgreich gestartet wurde
     if (pid != 0) {
=== commmands.c
==================================================================
--- commmands.c	(/lost/trunk/src/modules/c/shell/commmands.c)	(revision 1451)
+++ commmands.c	(/lost/local/src/modules/c/shell/commmands.c)	(revision 1451)
@@ -67,122 +67,27 @@
 #endif
 
 
-int shell_start_path_app(const char* cmd, const char* path, bool wait)
+int shell_start_path_app(const char* cmd, bool wait)
 {
-    const char* bindir_path = path;
-    DIR* bindir = opendir(bindir_path);
-    if(bindir == NULL)
-    {
-        DEBUG_MSG1("Konnte das Applikationsverzeichnis '%s' nicht finden", 
-            bindir_path);
+    DEBUG_MSG("Starte das Programm");
+    pid_t pid = init_execute(cmd);
+
+    // Fehler ist aufgetreten
+    if (pid == 0) {
         return -1;
     }
-    struct dirent* dir_entry;
-    
-    do {
-        dir_entry = readdir(bindir);
-        if (dir_entry == NULL) {
-            break;
-        }
-        if (shell_match_command(dir_entry->d_name, cmd) == TRUE) {
-            // Hier wird nach Leerschlaegen gesucht, um festzustellen, ob dem
-            // Befehl Argumente uebegeben werden sollen.
-            char* start_opts = strchr(cmd, ' ');
-            if (start_opts != NULL) {
-                // Falls Argumente uebergeben werden sollen, wird der
-                // Leerschlag, der die Argumente vom Programmnamen trennt durch
-                // ein Nullbyte ersetzt, da das die Verarbeitung des
-                // Programmnamens erleichtert.
-                *start_opts = '\0';
-                
-                // Jetzt werden noch weitere Leerschlaege uebersprungen, da die
-                // nicht erwuenscht sind.
-                while (*(++start_opts) == ' ');
-                start_opts--;
-            }
-            
-            // Speicher fuer den neuen Pfad. Besteht aus: Dem Verzeichnis mit
-            // den Anwendungen, einem Slash, dem Anwendungsnamen und einem
-            // abschliessenden Nullbyte. Die seltsame Darstellung dient nur der
-            // besseren Lesbarkeit, und wird hoffentlich vom Compiler
-            // wegoptimiert ;-).            
-            char start_path[strlen(bindir_path) + 1 + strlen(cmd) + 1];
-            bool insert_slash = (bindir_path[strlen(bindir_path)-1] != '/');
 
-            memcpy(start_path, bindir_path, strlen(bindir_path));            
-            if (insert_slash) {
-                start_path[strlen(bindir_path)] = '/';
-                memcpy(start_path + strlen(bindir_path) + 1, 
-                    cmd, strlen(cmd) + 1);
-            } else {
-                memcpy(start_path + strlen(bindir_path), cmd, strlen(cmd) + 1);
-            }
-            
-
-            char* message;
-
-            // FIXME: Hier sollten eigentlich keine mallocs() noetig sein...
-            if (start_opts == NULL) {
-                // Wenn keine Kommandozeilenargumente an das Programm
-                // uebergeben werden sollen, muss nur der Pfad des Programms an
-                // init geschickt werden.
-                message = malloc(strlen(start_path) + 1);
-                //memcpy(message, "LOADELF ", 8);
-                memcpy((void*) ((dword)message/* + 8*/), start_path, 
-                    strlen(start_path) + 1);
-            } else {
-                // Da vorher der Leerschlag durch ein Nullbyte ersetzt wurde,
-                // wird das hier wieder korrigiert, damit die Argumente einfach
-                // kopiert werden koennen.
-                *start_opts = ' ';
-
-                message = malloc(strlen(start_path) + 1 + 
-                    strlen(start_opts));
-                
-                memcpy((void*) ((dword)message /*+ 8*/), start_path, 
-                    strlen(start_path));
-                memcpy((void*) ((dword)message /*+ 8 */+ 
-                    strlen(start_path)), start_opts, 
-                    strlen(start_opts) + 1);
-            }
-            
-            // Jetzt wird der RPC an Init geschickt. Hier sollte noch irgend
-            // was hin, um zu warten bis der Prozess beendet wurde.
-            //send_message(1, 512, 0, strlen(message) + 1, message);
-            DEBUG_MSG("Starte das Programm");
-            pid_t pid = init_execute(message);
-            
-            // Fehler ist aufgetreten
-            if (pid == 0) {
-                free(message);
-                closedir(bindir);
-                return -1;
-            }
-
-            // Wenn es gewuenscht wurde, wird jetzt gewartet, bis der Prozess
-            // beendet wird.
-            if (wait == TRUE) {
-                int status;
-                while (waitpid(pid, &status, 0) != pid);
-            }
-
-            // FIXME: s.o.
-            free(message);
-            closedir(bindir);
-            return 0;
-        }
-        
-        free(dir_entry);
-
-    } while(dir_entry != NULL);
-
-    closedir(bindir);
-    return -1;
+    // Wenn es gewuenscht wurde, wird jetzt gewartet, bis der Prozess beendet
+    // wird.
+    if (wait == TRUE) {
+        int status;
+        while (waitpid(pid, &status, 0) != pid);
+    }
+    return 0;
 }
 
 /**
- * Wird aufgerufen, wenn keiner der internen Befehle passt. Dabei wird das
- * apps-Verzeichnis durchsucht.
+ * Wird aufgerufen, wenn keiner der internen Befehle passt.
  */
 int shell_command_default(int argc, char* argv[], const char* cmd)
 {
@@ -191,26 +96,12 @@
         return 0;
     }
     
-    int result;
-    const char* path = getenv("PATH");
-
-    const char* cwd = getcwd(NULL, 0);
-    result = shell_start_path_app(cmd, cwd, TRUE);
-    free((char*) cwd);
-    
-    // FIXME: Das ist so eigentlich nicht richtig...
-    if (result == 0) {
-        return result;
-    } else {
-        result = shell_start_path_app(cmd, path, TRUE);
-        if (result == 0) {
-            return 0;
-        }
+    if (shell_start_path_app(cmd, TRUE) == 0) {
+        return 0;
     }
-    puts("Befehl wurde nicht gefunden!");
 
-    
-    return 1;
+    puts("Befehl wurde nicht gefunden!");
+    return -1;
 }
 
 /**
@@ -219,38 +110,13 @@
 int shell_command_start(int argc, char* argv[], const char* cmd)
 {
     DEBUG_MSG("start");
-    
-    char* space = strchr((char*) cmd, ' ');
-    if (space == NULL) {
-        DEBUG_MSG("space == NULL");
+ 
+    if (shell_start_path_app(cmd, TRUE) == 0) {
         return 0;
-    }
-
-    cmd = space + 1;
-
-    int result;
-    const char* path = getenv("PATH");
-    char* cwd = getcwd(NULL, 0);
+    }   
     
-    DEBUG_MSG("Starte aus dem aktuellen Verzeichnis");
-    result = shell_start_path_app(cmd, cwd, FALSE);
-    free(cwd);
-    
-    // FIXME: Das ist so eigentlich nicht richtig...
-    if (result == 0) {
-        DEBUG_MSG("result == 0");
-        return result;
-    } else {
-        DEBUG_MSG("Starte aus dem Pfad");
-        result = shell_start_path_app(cmd, path, FALSE);
-        if (result == 0) {
-            DEBUG_MSG("result == 0");
-            return result;
-        }
-    }
     puts("Befehl wurde nicht gefunden!");
-    
-    return 1;
+    return -1;
 }