2015-07-18 1 views
1

Я пробовал:Как получить исполняемый путь на OpenBSD?

char *path = realpath(getenv("_"), NULL); 
*(strrchr(path, '/')+1) = '\0'; 

Это работает, но если мой исполняемый файл вызывается родительским процессом, то путь родительского процесса показан.

У меня много googled, но я не смог найти подходящего рабочего решения.

/proc не является вариантом.

+0

Вы пробовали [SYSCTL?] (Http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man3/sysctl.3?query=sysctl&sec=3) –

+0

@BlueMoon : Да, я пытался получить 'kinfo_proc' через' sysctl() ', но' kinfo_proc-> p_comm' содержит только исполняемое имя (то есть: 'a.out'). – Thomas

ответ

1

После некоторого экспериментирования, я думаю, что у меня есть рабочее решение ...

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

#include <limits.h> 
#include <unistd.h> 
#include <sys/sysctl.h> 
#include <sys/stat.h> 

const char *getExecutablePath(char *epath) { 
    int mib[4]; 
    char **argv; 
    size_t len; 
    const char *comm; 
    int ok = 0; 

    mib[0] = CTL_KERN; 
    mib[1] = KERN_PROC_ARGS; 
    mib[2] = getpid(); 
    mib[3] = KERN_PROC_ARGV; 

    if (sysctl(mib, 4, NULL, &len, NULL, 0) < 0) 
    abort(); 

    if (!(argv = malloc(len))) 
    abort(); 

    if (sysctl(mib, 4, argv, &len, NULL, 0) < 0) 
    abort(); 

    comm = argv[0]; 

    if (*comm == '/' || *comm == '.') { 
    if (realpath(comm, epath)) 
     ok = 1; 
    } else { 
    char *sp; 
    char *xpath = strdup(getenv("PATH")); 
    char *path = strtok_r(xpath, ":", &sp); 
    struct stat st; 

    if (!xpath) 
     abort(); 

    while (path) { 
     snprintf(epath, PATH_MAX, "%s/%s", path, comm); 

     if (!stat(epath, &st) && (st.st_mode & S_IXUSR)) { 
     ok = 1; 
     break; 
     } 

     path = strtok_r(NULL, ":", &sp); 
    } 

    free(xpath); 
    } 

    if (ok) 
    *strrchr(epath, '/') = '\0'; 

    free(argv); 
    return ok ? epath : NULL; 
} 

int main(void) { 
    char path[PATH_MAX]; 

    if (getExecutablePath(path)) 
    puts(path); 

    return 0; 
} 
0

К сожалению, нет никакого способа, чтобы получить полный путь к исполняемому файлу в OpenBSD.

Первый аргумент по соглашению указывает на имя файла, а не на полный путь, и вы не можете быть уверены, что родительский процесс будет следовать этому соглашению.

Эта команда, называемая exe, иллюстрирует это.

#include <stdio.h> 
#include <fcntl.h> 
#include <limits.h> 
#include <stdlib.h> 
#include <sys/wait.h> 

int exe(const char * path, const char * fakepath) 
{ 
    pid_t pid = vfork() ; 
    if(pid == 0) 
    { 
     /* Child process */ 
     int fd ; 
     const int TO = getdtablesize() ; 
     for(fd = 0 ; fd <= TO ; fd++) 
     { 
      close(fd); 
     } 
     open("/dev/tty", O_RDONLY) ; 
     open("/dev/tty", O_WRONLY) ; 
     open("/dev/tty", O_WRONLY) ; 
     const char *arguments[2] = { fakepath, NULL } ; 
     execvp(path, (char**)arguments) ; 
     perror("exe") ; 
     exit(1) ; 
    } 
    else if(pid > 0) 
    { 
     /* Parent process */ 
     int status = 0 ; 
     if(waitpid(pid, &status, 0) != -1) 
     { 
      if(WIFEXITED(status)) 
      { 
       return WEXITSTATUS(status) ; 
      } 
      else 
      { 
       printf("exe: child process failed\n") ; 
       return 1 ; 
      } 
     } 
    } 
    perror("exe") ; 
    return 1 ; 
} 

int main(int argc, char * argv[]) 
{ 
    if(argc != 3) 
    { 
     printf("Usage: exe program /fake/first/program/argument\n") ; 
     return 1 ; 
    } 
    return exe(argv[1], argv[2]) ; 
} 

Теперь вы можете выполнить программу прохождения arbitraty первого аргумента, как это:

exe program /fake/first/program/argument 

пользователя спросил Тео де Raadt осуществить то, что необходимо, чтобы быть в состоянии получить полный путь исполняемый файл в этом thread

Я думаю, мы могли бы придерживаться «путь» в качестве вспомогательного значения вектора и имеют ld.so делать в Realpath() вызов, если используется $ ORIGIN? Было бы так, что или имеют ядро ​​хранят весь путь в течение всего процесса для получения с помощью sysctl(). Сейчас он сохраняет только последний компонент (разрешенного) исходного пути в p_comm.

И он ответил:

Дороговато для такой небольшой потребности.

+0

BSD отстой. Нам нужен почти всегда доступ к узлу каталогов исполняемого файла, так что мы можем использовать вызовы openat для загрузки exe-файлов. Тогда каталог с запущенной программой может перемещаться во время выполнения. – Lothar