En realidad, no es una respuesta, sino solo una nota para tener en cuenta.
Como pudimos ver, el problema de encontrar la ubicación del ejecutable en ejecución es bastante complicado y específico de la plataforma en Linux y Unix. Uno debería pensar dos veces antes de hacer eso.
Si necesita la ubicación de su ejecutable para descubrir algunos archivos de configuración o de recursos, tal vez debería seguir la forma Unix de colocar archivos en el sistema:poner configuraciones en /etc
o /usr/local/etc
o en el directorio de inicio del usuario actual, y /usr/share
es un buen lugar para colocar sus archivos de recursos.
Use la función GetModuleFileName() si está usando Windows.
Tenga en cuenta que los siguientes comentarios son solo para Unix.
La respuesta pedante a esta pregunta es que no existe un general manera de responder correctamente a esta pregunta en todos los casos. Como ha descubierto, argv[0] puede establecerse en cualquier cosa mediante el proceso principal y, por lo tanto, no necesita tener ninguna relación con el nombre real del programa o su ubicación en el sistema de archivos.
Sin embargo, la siguiente heurística suele funcionar:
- Si argv[0] es una ruta absoluta, asuma que es la ruta completa al ejecutable.
- Si argv[0] es una ruta relativa, es decir, contiene un
/
, determine el directorio de trabajo actual con getcwd() y luego agréguele argv[0]. - Si argv[0] es una palabra sencilla, busque $PATH buscando argv[0] y agregue argv[0] al directorio en el que lo encuentre.
Tenga en cuenta que todos estos pueden ser eludidos por el proceso que invocó el programa en cuestión. Finalmente, puede usar técnicas específicas de Linux, como las mencionadas por emg-2. Probablemente existen técnicas equivalentes en otros sistemas operativos.
Incluso suponiendo que los pasos anteriores le den un nombre de ruta válido, es posible que aún no tenga el nombre de ruta que realmente desea (ya que sospecho que lo que realmente desea hacer es encontrar un archivo de configuración en alguna parte). La presencia de enlaces duros significa que puede tener la siguiente situación:
-- assume /app/bin/foo is the actual program
$ mkdir /some/where/else
$ ln /app/bin/foo /some/where/else/foo # create a hard link to foo
$ /some/where/else/foo
Ahora, el enfoque anterior (incluyendo, sospecho, /proc/$pid/exe) dará /some/where/else/foo
como el verdadero camino al programa. Y, de hecho, es a camino real al programa, pero no el que querías. Tenga en cuenta que este problema no ocurre con los enlaces simbólicos que son mucho más comunes en la práctica que los enlaces físicos.
A pesar de que, en principio, este enfoque no es fiable, en la práctica funciona bastante bien para la mayoría de los propósitos.
Para resumir:
-
En Unixes con
/proc
manera realmente directa y confiable es:-
readlink("/proc/self/exe", buf, bufsize)
(Linux) -
readlink("/proc/curproc/file", buf, bufsize)
(FreeBSD) -
readlink("/proc/self/path/a.out", buf, bufsize)
(Solaris)
-
-
En Unixes sin
/proc
(es decir, si lo anterior falla):-
Si argv[0] comienza con "/" (ruta absoluta), esta es la ruta.
-
De lo contrario, si argv[0] contiene "/" (ruta relativa), agréguelo a cwd (suponiendo que aún no se haya cambiado).
-
De lo contrario, busque directorios en
$PATH
para ejecutableargv[0]
.
Posteriormente, puede ser razonable verificar si el ejecutable no es realmente un enlace simbólico. Si lo es, resuélvalo en relación con el directorio de enlaces simbólicos.
Este paso no es necesario en el método /proc (al menos para Linux). Allí, el enlace simbólico proc apunta directamente al ejecutable.
Tenga en cuenta que depende del proceso de llamada establecer
argv[0]
correctamente. Es correcto la mayoría de las veces, sin embargo, hay ocasiones en las que no se puede confiar en el proceso de llamada (por ejemplo, setuid ejecutable). -
-
En Windows:usa
GetModuleFileName(NULL, buf, bufsize)