Eigenes Programmverzeichnis ermitteln



  • Hallo ich habe mir mit c++ ein kleines mini Programm geschrieben.
    dieses benötigt aber eine sqlite DB die ja beim Starten geladen werden muss.
    jetzt würde ich das gerne relative zur aktuellen position machen.

    wenn man das Googelt findet man schnell so sachen wie "get_current_dir_name()" und getcwd mein Problem ist nur, zumindest unter linux bekomme ich immer nur
    /home/benutzer zurück obwohl das Programm unter /usr/local/bin liegt
    ich möchte aber auch den Pfad nicht hard in dehn Code schreiben.

    könnt ihr mir sagen wie ich das gelöst bekomme?
    Danke im vorraus!



  • Eine Sqlitedatei in /usr/local/bin ist nicht so sinnvoll. Die ist dort für normale Benutzer nicht schreibbar.



  • okay zugegeben aber auch wenn ich es irgendwo anders hinpacke Außer natürlich direkt /home/benutzer/ habe ich ja das gleiche problem



  • Unter Unix/Linux wird in argv[0] der Pfad zum Programm entweder als absoluter Pfad oder als Pfad relativ zum aktuellen (= working directory) mitgegeben.



  • Sollte sowas nicht nach /opt ?



  • Husker schrieb:

    okay zugegeben aber auch wenn ich es irgendwo anders hinpacke Außer natürlich direkt /home/benutzer/ habe ich ja das gleiche problem

    Du solltest Daten- und Programmverzeichnis trennen. Du kannst das Datenverzeichnis als Aufrufparameter mitgeben oder eben nach $HOME/irgendwas legen.



  • leider nein es wird nur der anwendungsname zurückgegeben.



  • Swordfish schrieb:

    Sollte sowas nicht nach /opt ?

    ja ist vermuttlich ein besserer ort


  • Mod

    manni66 schrieb:

    Unter Unix/Linux wird in argv[0] der Pfad zum Programm entweder als absoluter Pfad oder als Pfad relativ zum aktuellen (= working directory) mitgegeben.

    Nein, da steht wirklich nur der Aufruf drin. Wenn der Aufruf aber nicht durch direkte Angabe der Executable erfolgte (zum Beispiel, weil die Executable im aktuellen PATH zu finden ist), dann kann man daraus auch nicht auf den Ort der Executable schließen.



  • manni66 schrieb:

    Husker schrieb:

    okay zugegeben aber auch wenn ich es irgendwo anders hinpacke Außer natürlich direkt /home/benutzer/ habe ich ja das gleiche problem

    Du solltest Daten- und Programmverzeichnis trennen. Du kannst das Datenverzeichnis als Aufrufparameter mitgeben oder eben nach $HOME/irgendwas legen.

    das würde ich lieber nicht machen wollen, es soll wie ein normaler linux befehl arbeiten, als Paramter gebe ich lediglich das mit was die anwendung braucht

    die DB ist ja FIX und es wäre auch blödsin der pfad bei jedem aufruf immer mitzugeben.



  • ist das unter c++ so schwer rauszufinden wo die Anwendung liegt?



  • Husker schrieb:

    manni66 schrieb:

    Du solltest Daten- und Programmverzeichnis trennen. Du kannst das Datenverzeichnis als Aufrufparameter mitgeben oder eben nach $HOME/irgendwas legen.

    das würde ich lieber nicht machen wollen, es soll wie ein normaler linux befehl arbeiten,

    Bei einem normalen Linux-Befehl SIND Daten- und Programmverzeichnis getrennt! Wenn Du keinen Parameter haben willst, kannst Du ja (wie schon von manni66 vorgeschlagen) $HOME/.programmname/ nehmen.



  • Husker schrieb:

    ist das unter c++ so schwer rauszufinden wo die Anwendung liegt?

    Das hat mit C oder C++ nichts zu tun, sondern ist Sache des Environments.

    https://stackoverflow.com/questions/933850/how-do-i-find-the-location-of-the-executable-in-c



  • Zur Sicherheit, ob hier nicht aneinander vorbeigeredet wird, noch einmal die Frage:

    Diese Datenbank, ist sie konstant? Also bleibt sie dauerhaft gleich? Und ist sie ebenfalls benutzerunabhängig? Dann und nur dann macht es natürlich keinen Sinn, diese in $HOME zu speichern, sondern dann wäre vermutlich eher /usr/(local/)share oder so sinnvoll.



  • Also vieleicht führe ich das doch mal etwas aus:

    das kleine Prog soll den Hersteller zu einer MacAdresse liefern

    also

    macident -ident d2:a2:ef:12:da:2a

    als ergebnis würde dann sowas bei rauskommen:

    HUWAEI LTD. ink. oder sowas

    klar könnte ich die Datenbank als aufruf Param mit geben aber da die DB sowieso immer an der gleichen Stelle liegt fände ich das quatsch, zumal es ja dann auch den Befehlt bzw. den ausruf unnötig kompliziert macht

    **macident -ident d2:a2:ef:12:da:2a -database /usr/local/macident/database/database.sqlite3
    **

    die Datenbank ist recht fix, könnte sein das ich die von zeit zu zeit mal update, aber eigentlich enthält sie nur Basisinformationen, das Benutzerverzeichnis (HOME) möchte ich eigentlich nicht benutzen da die Anwendung dann nur noch unter dem Benutzer läuft ich hätte es aber gerne MultiUser 🙂

    hätte ich jetzt tatsächlich nicht gedacht das das so ein Problem werden würde, unter anderen Sprachen wie z.b. .NET oder auch Java ist das kein Problem 🙂



  • Husker schrieb:

    hätte ich jetzt tatsächlich nicht gedacht das das so ein Problem werden würde, unter anderen Sprachen wie z.b. .NET oder auch Java ist das kein Problem

    Java Programme (.NET kenne ich nicht) werden von einem Interpreter ausgeführt. Das Problem existiert dort also nicht.

    Man muss halt mal ein bisschen googeln, dann findet man auch eine Lösung:

    #include <iostream>
    #include <array>
    #include <unistd.h>
    
    int main( int argc, char** argv )
    {
            std::array<char,1000> path = {};
    
            readlink( "/proc/self/exe", path.data(), path.size());
            std::cout << argv[0] << " " << path.data()  << "\n";
    }
    

    Die Fehlerbehandlung bleibt dem Leser überlassen 😉



  • manni66 schrieb:

    Husker schrieb:

    hätte ich jetzt tatsächlich nicht gedacht das das so ein Problem werden würde, unter anderen Sprachen wie z.b. .NET oder auch Java ist das kein Problem

    Java Programme (.NET kenne ich nicht) werden von einem Interpreter ausgeführt. Das Problem existiert dort also nicht.

    Man muss halt mal ein bisschen googeln, dann findet man auch eine Lösung:

    #include <iostream>
    #include <array>
    #include <unistd.h>
    
    int main( int argc, char** argv )
    {
            std::array<char,1000> path = {};
    
            readlink( "/proc/self/exe", path.data(), path.size());
            std::cout << argv[0] << " " << path.data()  << "\n";
    }
    

    Die Fehlerbehandlung bleibt dem Leser überlassen 😉

    über das Code Fragment bin ich auch schon gesolpert, leider bekomme ich das nicht ans laufen scheinbar hat er ein Problem mit der Deklaration

    std::array<char,1000> path = {};
    

    Type 'std::array<char,1000>' could not be resolved

    könnte natürlich ein anfänger fehler sein, allerdings habe ich sonde deklaration beim Googeln von c++ und Array nicht gefunden 😞



  • Husker schrieb:

    über das Code Fragment bin ich auch schon gesolpert, leider bekomme ich das nicht ans laufen scheinbar hat er ein Problem mit der Deklaration

    Das bezweifle ich, das Code Fragment habe ich gerade selber geschrieben.

    Husker schrieb:

    std::array<char,1000> path = {};
    

    Type 'std::array<char,1000>' could not be resolved

    Copy&paste vollständige Fehlermeldung
    Copy&paste Kommandozeile Compiler

    Man kann auch ein simples C-Array verwenden.



  • ja mag sein, aber über:

    https://www.computerbase.de/forum/showthread.php?t=1232719

    bin ich schon gestolpert, ist nicht 100% gleich aber es nutzt auch readlink

    hier das BuildLog

    `13:06:45 **** Build of configuration Release for project macident ****

    make all

    Building file: ../src/MacObject.cpp

    Invoking: Cross G++ Compiler

    g++ -O3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/MacObject.d" -MT"src/MacObject.o" -o "src/MacObject.o" "../src/MacObject.cpp"

    Finished building: ../src/MacObject.cpp

    Building file: ../src/SQLiteDatabase.cpp

    Invoking: Cross G++ Compiler

    g++ -O3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/SQLiteDatabase.d" -MT"src/SQLiteDatabase.o" -o "src/SQLiteDatabase.o" "../src/SQLiteDatabase.cpp"

    Finished building: ../src/SQLiteDatabase.cpp

    Building file: ../src/macident.cpp

    Invoking: Cross G++ Compiler

    g++ -O3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/macident.d" -MT"src/macident.o" -o "src/macident.o" "../src/macident.cpp"

    In file included from /usr/include/c++/5/array:35:0,

                 from ../src/macident.cpp:26:
    

    /usr/include/c++/5/bits/c++0x_warning.h:32:2: error: #error This file requires compiler and library support for the ISO C++ 2011 standard. This support must be enabled with the -std=c++11 or -std=gnu++11 compiler options.

    #error This file requires compiler and library support \

    ^

    ../src/macident.cpp: In function ‘int main(int, char**)’:

    ../src/macident.cpp:44:2: error: ‘array’ was not declared in this scope

    array<char,1000> path = {};

    ^

    ../src/macident.cpp:44:8: error: expected primary-expression before ‘char’

    array<char,1000> path = {};

        ^
    

    ../src/macident.cpp:46:30: error: ‘path’ was not declared in this scope

    readlink( "/proc/self/exe", path.data(), path.size());

                              ^
    

    src/subdir.mk:24: die Regel für Ziel „src/macident.o“ scheiterte

    make: *** [src/macident.o] Fehler 1

    13:06:50 Build Finished (took 5s.58ms)`



  • #error This file requires compiler and library support for the ISO C++ 2011 standard. This support must be enabled with the -std=c++11 or -std=gnu++11 compiler options.

    Entweder du schaltest C++11 oder höher ein (für das komplette Projekt) oder du benutzt C-Arrays.


Log in to reply