1 /* @(#)getexecpath.c 1.3 20/07/27 Copyright 2006-2020 J. Schilling */ 2 /* 3 * Copyright (c) 2006-2020 J. Schilling 4 */ 5 /* 6 * The contents of this file are subject to the terms of the 7 * Common Development and Distribution License, Version 1.0 only 8 * (the "License"). You may not use this file except in compliance 9 * with the License. 10 * 11 * See the file CDDL.Schily.txt in this distribution for details. 12 * A copy of the CDDL is also available via the Internet at 13 * http://www.opensource.org/licenses/cddl1.txt 14 * 15 * When distributing Covered Code, include this CDDL HEADER in each 16 * file and include the License file CDDL.Schily.txt from this distribution. 17 */ 18 19 #include <schily/mconfig.h> 20 #include <schily/types.h> 21 #include <schily/unistd.h> 22 #include <schily/stdlib.h> 23 #include <schily/string.h> 24 #include <schily/standard.h> 25 #include <schily/schily.h> 26 27 #if (defined(sun) || defined(__sun) || defined(__sun__)) && defined(__SVR4) 28 #define PATH_IMPL 29 #define METHOD_SYMLINK 30 #define SYMLINK_PATH "/proc/self/path/a.out" /* Solaris 10 -> ... */ 31 #endif 32 33 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 34 #define PATH_IMPL 35 #define METHOD_SYMLINK 36 #define SYMLINK_PATH "/proc/curproc/file" /* /proc may nor be mounted */ 37 #endif 38 39 #if defined(__linux__) || defined(__linux)|| defined(linux) 40 #define PATH_IMPL 41 #define METHOD_SYMLINK 42 #define SYMLINK_PATH "/proc/self/exe" 43 #endif 44 45 #if defined(HAVE_PROC_PIDPATH) /* Mac OS X */ 46 #ifdef HAVE_LIBPROC_H 47 #include <libproc.h> 48 #endif 49 #define PATH_IMPL 50 #define METHOD_PROC_PIDPATH 51 #endif 52 53 #if defined(HAVE_SYS_AUXV_H) 54 /* 55 * Methods based on the ELF Aux Vector give the best results. 56 */ 57 #include <sys/auxv.h> 58 59 #ifdef HAVE_GETEXECNAME /* Solaris */ 60 #define PATH_IMPL 61 #define METHOD_GETEXECNAME 62 #undef METHOD_SYMLINK 63 #undef METHOD_PROC_PIDPATH 64 #else 65 #if defined(HAVE_GETAUXVAL) && defined(AT_EXECFN) /* Linux */ 66 #define PATH_IMPL 67 #define METHOD_GETAUXVAL 68 #undef METHOD_SYMLINK 69 #undef METHOD_PROC_PIDPATH 70 #else 71 #if defined(HAVE_ELF_AUX_INFO) && defined(AT_EXECPATH) /* FreeBSD */ 72 #define PATH_IMPL 73 #define METHOD_ELF_AUX_INFO 74 #undef METHOD_SYMLINK 75 #undef METHOD_PROC_PIDPATH 76 #else 77 /* 78 * No Solution yet 79 */ 80 #endif 81 #endif 82 #endif 83 84 #endif /* HAVE_SYS_AUXV_H */ 85 86 87 88 /* 89 * TODO: AIX: /proc/$$/object/a.out -> plain file, match via st_dev/st_ino 90 */ 91 92 93 EXPORT char * getexecpath()94getexecpath() 95 { 96 #ifdef PATH_IMPL 97 #ifdef METHOD_GETEXECNAME /* Solaris */ 98 const char *en = getexecname(); 99 100 if (en == NULL) 101 return (NULL); 102 return (strdup(en)); 103 #endif 104 #ifdef METHOD_GETAUXVAL /* Linux */ 105 char *en = (char *)getauxval(AT_EXECFN); 106 107 if (en == NULL) 108 return (NULL); 109 return (strdup(en)); 110 #endif 111 #ifdef METHOD_ELF_AUX_INFO /* FreeBSD */ 112 char buf[1024]; 113 int ret; 114 115 ret = elf_aux_info(AT_EXECPATH, buf, sizeof (buf)); 116 if (ret != 0) 117 return (NULL); 118 return (strdup(buf)); 119 #endif 120 #ifdef METHOD_SYMLINK 121 char buf[1024]; 122 ssize_t len; 123 124 len = readlink(SYMLINK_PATH, buf, sizeof (buf)-1); 125 if (len == -1) 126 return (NULL); 127 buf[len] = '\0'; 128 return (strdup(buf)); 129 #endif 130 #ifdef METHOD_PROC_PIDPATH /* Mac OS X */ 131 char buf[1024]; 132 int len; 133 134 len = proc_pidpath(getpid(), buf, sizeof (buf)); 135 if (len == -1) 136 return (NULL); 137 return (strdup(buf)); 138 #endif 139 #else 140 return (NULL); 141 #endif 142 } 143