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()94 getexecpath()
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