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);}