void _unix_get_executable_name(char *output, int size)
{
#ifdef ALLEGRO_HAVE_SV_PROCFS
struct prpsinfo psinfo;
int fd;
#endif
#if defined ALLEGRO_HAVE_SV_PROCFS || defined ALLEGRO_SYS_GETEXECNAME
char *s;
#endif
char linkname[1024];
char filename[1024];
struct stat finfo;
FILE *pipe;
pid_t pid;
int len;
#ifdef ALLEGRO_HAVE_GETEXECNAME
s = getexecname();
if (s) {
if (s[0] == '/') { /* Absolute path */
do_uconvert (s, U_ASCII, output, U_CURRENT, size);
return;
}
else { /* Not an absolute path */
if (_find_executable_file(s, output, size))
return;
}
}
s = NULL;
#endif
/* We need the PID in order to query procfs */
pid = getpid();
/* Try a Linux-like procfs */
/* get symolic link to executable from proc fs */
sprintf (linkname, "/proc/%d/exe", pid);
if (stat (linkname, &finfo) == 0) {
len = readlink (linkname, filename, sizeof(filename)-1);
if (len>-1) {
filename[len] = '\0';
do_uconvert (filename, U_ASCII, output, U_CURRENT, size);
return;
}
}
/* Use System V procfs calls if available */
#ifdef ALLEGRO_HAVE_SV_PROCFS
sprintf (linkname, "/proc/%d/exe", pid);
fd = open(linkname, O_RDONLY);
if (!fd == -1) {
ioctl(fd, PIOCPSINFO, &psinfo);
close(fd);
/* Use argv[0] directly if we can */
#ifdef ALLEGRO_HAVE_PROCFS_ARGCV
if (psinfo.pr_argv && psinfo.pr_argc) {
if (_find_executable_file(psinfo.pr_argv[0], output, size))
return;
}
else
#endif
{
/* Emulate it */
/* We use the pr_psargs field to find argv[0]
* This is better than using the pr_fname field because we need
* the additional path information that may be present in argv[0]
*/
/* Skip other args */
s = strchr(psinfo.pr_psargs, ' ');
if (s) s[0] = '\0';
if (_find_executable_file(psinfo.pr_psargs, output, size))
return;
}
/* Try the pr_fname just for completeness' sake if argv[0] fails */
if (_find_executable_file(psinfo.pr_fname, output, size))
return;
}
#endif
/* Last resort: try using the output of the ps command to at least find */
/* the name of the file if not the full path */
uszprintf (linkname, sizeof(linkname), "ps -p %d", pid);
do_uconvert (linkname, U_CURRENT, filename, U_ASCII, size);
pipe = popen(filename, "r");
if (pipe) {
/* The first line of output is a header */
fgets(linkname, sizeof(linkname), pipe);
/* The information we want is in the last column; find it */
len = strlen(linkname);
while (linkname[len] != ' ' && linkname[len] != '\t')
len--;
/* The second line contains the info we want */
fgets(linkname, sizeof(linkname), pipe);
pclose(pipe);
/* Treat special cases: filename between [] and - for login shell */
if (linkname[len] == '-')
len++;
if (linkname[len] == '[' && linkname[strlen(linkname)] == ']') {
len++;
linkname[strlen(linkname)] = '\0';
}
/* Now, the filename should be in the last column */
_al_sane_strncpy (filename, linkname+len+1, strlen(linkname)-len+1);
if (_find_executable_file(filename, output, size))
return;
/* Just return the output from ps... */
do_uconvert (filename, U_ASCII, output, U_CURRENT, size);
return;
}
#ifdef ALLEGRO_WITH_MAGIC_MAIN
/* Try the captured argv[0] */
if (_find_executable_file(__crt0_argv[0], output, size))
return;
#endif
/* Give up; return empty string */
do_uconvert ("", U_ASCII, output, U_CURRENT, size);
}