Monday May 08, 2006
Finding the canonical path to an executable
Below is a coding example of how an executable can determine the
canonical path to itself on the file system. Compiler drivers,
like cc, CC, f95 need to do this in order to exec the component
executables that compile a program. For example, the compiler
front-end, an optimizer, and a linker.
% cat findself.c
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#ifndef MAXPATHLEN
#define MAXPATHLEN 1024
#endif
/* find_run_directory - find executable file in PATH
* PARAMETERS:
* cmd filename as typed by user
* cwd where to return working directory
* dir where to return program's directory
* run where to return final resolution name
* RETURNS:
* returns zero for success,
* -1 for error (with errno set properly).
*/
int
find_run_directory (char *cmd, char *cwd, char *dir, char **run)
{
char *s;
if (!cmd || !*cmd || !cwd || !dir) {
errno = EINVAL; /*
stupid arguments! */
return -1;
}
if (*cwd != '/')
if (getcwd (cwd, MAXPATHLEN - 1) == NULL )
return -1; /*
cant get working directory */
if (strchr (cmd, '/') != NULL) {
if (realpath(cmd, dir) == NULL) {
int lerrno = errno;
if (chdir((const char *)cwd) == NULL)
errno = lerrno;
return -1;
}
} else {
#ifdef __linux__
/* getexecname() not available on Linux */
if (readlink("/proc/self/exe", dir, MAXPATHLEN) == -1) {
#else
if (realpath(getexecname(), dir) == NULL) {
#endif
int lerrno = errno;
if (chdir((const char *)cwd) == NULL)
errno = lerrno;
return -1;
}
}
s = strrchr (dir, '/');
*s++ = 0;
if (run) /* user wants resolution name */
*run = s;
return 0;
}
char current_working_directory[MAXPATHLEN];
char run_directory[MAXPATHLEN];
char * run_exec_name = NULL;
int
main(int argc, char **argv)
{
if ( !find_run_directory (argv[0],
current_working_directory,
run_directory, &run_exec_name) ) {
(void)printf("argv[0] = %s\n"
"cwd = %s\n"
"run_dir = %s\n"
"run_exec = %s\n",
argv[0],
current_working_directory,
run_directory,
run_exec_name);
} else {
(void) printf("%s\n", "Unaable to find run directory.");
}
exit (0);
}
% cc findself.c -O -o prod/bin/findself
% ls
bin findself.c prod
% ls bin
findself
% ls -laF bin
total 6
drwxr-xr-x
2 me
staff 512 Mar 5 10:37 ./
drwxr-xr-x
4 me
staff 512 Mar 5 10:37
../
lrwxrwxrwx
1 me
staff 20 Mar 5
10:37 findself -> ../prod/bin/findself*
% ls -laF prod/bin
total 22
drwxr-xr-x
2 me
staff 512 Mar 5 10:37 ./
drwxr-xr-x
3 me
staff 512 Mar 5 10:37
../
-rwxr-xr-x
1 me
staff 8992 Mar 5 10:37
findself*
% bin/findself
argv[0] = bin/findself
cwd = /home/me/blog
run_dir = /home/me/blog/prod/bin
run_exec = findself
% prod/bin/findself
argv[0] = prod/bin/findself
cwd = /home/me/blog
run_dir = /home/me/blog/prod/bin
run_exec = findself
% setenv PATH /home/me/bin:${PATH}
% findself
argv[0] = findself
cwd = /home/me/blog
run_dir = /home/me/blog/prod/bin
run_exec = findself
%
( May 08 2006, 06:36:27 PM PDT )
Permalink
Comments [0]