Programmorder feststellen

B

BetaWolf

Grünschnabel
Wie kann ich feststellen in einem Programm feststellen wo es sich selbst befindet? Ich würde gerne einige Dinge unabhängig von wo das Programm gestartet wird aus dem Programmordner laden.
 
Code:
whereis Programmname

In die Konsole / das Terminal eingeben
 
Denke, du kannst über argv[0] feststellen, wie das Programm aufgerufen wurde. Falls ein absoluter Pfad angegeben wurde, kannst du mit dirname() den Programmordner direkt rausfinden; wenn '/' in argv[0] enthalten ist (Aufruf erfolgte über relative Pfadangabe), erstmal mit chdir in das entsprechende Verzeichnis wechseln, dort liefert dann getcwd(), wo du bist; und falls nur der Programmname selbst in argv[0] steckt, musst du über $PATH suchen, bis du das Programm findest ...

Wenn du zufällig auf Linux unterwegs sein solltest ;-), kannst du auch über das /proc-FS (-> /proc/self/exe) feststellen, welches Programm du eigentlich ausführst; der dirname() davon sollte dir das Gewünschte liefern.
 
Ah, ich hatte das anders verstanden. Dann wäre das proc-fs tatsächlich der Weg.
Der Inhalt von argv[0] ist (afair) weder vom c-std noch von POSIX garantiert. Von daher ist proc wohl der bessere Weg.
Aber dirname macht afaik keine link-resolution, sondern stupides string-parsing. readlink wäre eine Idee.
 
Hi Gott_in_schwarz,

doch, ich glaube argv ist Teil des C-Standards; siehe z.B. http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1362.pdf. Und im Gegensatz zu /proc funktioniert das auch auf Nicht-Linux-Plattformen.

Und wenn es nur darum geht, festzustellen, aus welchem Verzeichnis ein Programm aufgerufen wurde, um von dort z.B. Standardeinstellungen aus einem Konfig-File nachzuladen - so habe ich die Aufgabenstellung verstanden - wäre mir relativ egal, ob in den Namen noch irgendwelche Links enthalten sind ;-)

Grüsse
 
— The value of argc shall be nonnegative.
— argv[argc] shall be a null pointer.
— If the value of argc is greater than zero, the string pointed to by argv[0]
represents the program name; argv[0][0] shall be the null character if the
program name is not available from the host environment.
Möglichkeiten:
argc == 0:
argv[0] == NULL

oder
argc > 0:
argv[0] entweder Programmname oder ""

Also ist das nicht vom Standard abgedeckt.

Das gilt natürlich genauso fürs procfs.
Btw, dirname("/proc/self/exe", ...) ergibt "/proc/self". Ich denke mal du siehst ein wieso man für die proc-Lösung readlink und nicht (nur) dirname verwenden sollte.

Ein weiteres (ziemlich unschönes) Problem beim "argv[0]-approach" ist (was du auch bereits angesprochen hast), dass das Programm eventuell "pfadlos" aufgerufen wurde. Dann darf man lustig PATH durchsuchen.
Ich würd sagen die proc-Methode ist transparenter und, zumindest auf bestimmten unixoiden Betriebssystemen, verlässlicher.

Aber mich würde auch mal interessieren, obs da einen "portablen" Weg gibt.

edit:
Ein weiteres Problem mit argv[0] und PATH wäre die Möglichkeit, dass die binary in irgendeinem Ordner "außerhalb" der PATH-Variable liegt, aber ein Softlink in einem der PATH-Pfade vorliegt. Dann muss man PATH dursuchen und readlink (eventuell sogar mehrfach) benutzen.
Consider:
Code:
$ cd /home/user
$ cat readlink.c 
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <libgen.h>

int main(int argc, char *argv[]) {
    char buf[1024];
    char *dname;
    int len;
    if ((len = readlink("/proc/self/exe", buf, sizeof(buf)-1)) != -1) {
        buf[len] = '\0';
    }
    printf("readlink(\"/proc/self/exe\", ...)\t== %s\n", buf);
    printf("dirname(\"%s\", ...)\t== ", argv[0]);
    dname = dirname(argv[0]);
    printf("%s\n", dname);
    return EXIT_SUCCESS;
}
$ gcc readlink.c -o readlink
$ ln -s /home/user/readlink /bin/MY_READLINK
$ cd /
$ MY_READLINK 
readlink("/proc/self/exe", ...) == /home/user/readlink
dirname("MY_READLINK", ...)     == .
Und das Beispiel ist nichtmal sonderlich unwahrscheinlich.
Code:
$ ls -lah /usr/bin/cc
lrwxrwxrwx 1 root root 20 2008-01-27 02:11 /usr/bin/cc -> /etc/alternatives/cc*
$ ls -lah /etc/alternatives/cc
lrwxrwxrwx 1 root root 12 2008-01-27 02:11 /etc/alternatives/cc -> /usr/bin/gcc*
$ ls -lah /usr/bin/gcc
lrwxrwxrwx 1 root root 7 2008-01-27 02:11 /usr/bin/gcc -> gcc-4.1*

edit:
Wow, das geht sogar noch besser als ich dachte:
Code:
$ cd /home/user && mv readlink foo/
$ ln -s /home/user/foo/readlink /home/user/readlink
$ ls -lah /bin/MY_READLINK
lrwxrwxrwx 1 root root 21 2009-03-13 19:01 /bin/MY_READLINK -> /home/user/readlink*
$ ls -lah readlink
lrwxrwxrwx 1 user user 25 2009-03-13 19:56 readlink -> /home/user/foo/readlink*
$ MY_READLINK 
readlink("/proc/self/exe", ...) == /home/user/foo/readlink
dirname("MY_READLINK", ...)     == .
Also nimmt /proc/self/exe einem die Arbeit mit mehrfachen Softlinks ab.
 
Zuletzt bearbeitet:

Ähnliche Themen

Welche Distro wie RHEL (Tools & Repos)?

MangoHud Version v0.6.9: Neue Parameter für das Linux-Performance-Overlay

Versehentlich gelöschte Daten zurückholen

Kernel Kaltstart / reboot?

Samba Server mangling

Zurück
Oben