diff options
Diffstat (limited to 'gl/getprogname.c')
-rw-r--r-- | gl/getprogname.c | 302 |
1 files changed, 302 insertions, 0 deletions
diff --git a/gl/getprogname.c b/gl/getprogname.c new file mode 100644 index 00000000..9a802811 --- /dev/null +++ b/gl/getprogname.c | |||
@@ -0,0 +1,302 @@ | |||
1 | /* Program name management. | ||
2 | Copyright (C) 2016-2021 Free Software Foundation, Inc. | ||
3 | |||
4 | This program is free software: you can redistribute it and/or modify | ||
5 | it under the terms of the GNU Lesser General Public License as published by | ||
6 | the Free Software Foundation; either version 2.1 of the License, or | ||
7 | (at your option) any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU Lesser General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Lesser General Public License | ||
15 | along with this program. If not, see <https://www.gnu.org/licenses/>. */ | ||
16 | |||
17 | #include <config.h> | ||
18 | |||
19 | /* Specification. */ | ||
20 | #include "getprogname.h" | ||
21 | |||
22 | #include <errno.h> /* get program_invocation_name declaration */ | ||
23 | #include <stdlib.h> /* get __argv declaration */ | ||
24 | |||
25 | #ifdef _AIX | ||
26 | # include <unistd.h> | ||
27 | # include <procinfo.h> | ||
28 | # include <string.h> | ||
29 | #endif | ||
30 | |||
31 | #ifdef __MVS__ | ||
32 | # ifndef _OPEN_SYS | ||
33 | # define _OPEN_SYS | ||
34 | # endif | ||
35 | # include <string.h> | ||
36 | # include <sys/ps.h> | ||
37 | #endif | ||
38 | |||
39 | #ifdef __hpux | ||
40 | # include <unistd.h> | ||
41 | # include <sys/param.h> | ||
42 | # include <sys/pstat.h> | ||
43 | # include <string.h> | ||
44 | #endif | ||
45 | |||
46 | #if defined __sgi || defined __osf__ | ||
47 | # include <string.h> | ||
48 | # include <unistd.h> | ||
49 | # include <stdio.h> | ||
50 | # include <fcntl.h> | ||
51 | # include <sys/procfs.h> | ||
52 | #endif | ||
53 | |||
54 | #if defined __SCO_VERSION__ || defined __sysv5__ | ||
55 | # include <fcntl.h> | ||
56 | # include <stdlib.h> | ||
57 | # include <string.h> | ||
58 | #endif | ||
59 | |||
60 | #include "basename-lgpl.h" | ||
61 | |||
62 | #ifndef HAVE_GETPROGNAME /* not Mac OS X, FreeBSD, NetBSD, OpenBSD >= 5.4, Cygwin */ | ||
63 | char const * | ||
64 | getprogname (void) | ||
65 | { | ||
66 | # if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME /* glibc, BeOS */ | ||
67 | /* https://www.gnu.org/software/libc/manual/html_node/Error-Messages.html */ | ||
68 | return program_invocation_short_name; | ||
69 | # elif HAVE_DECL_PROGRAM_INVOCATION_NAME /* glibc, BeOS */ | ||
70 | /* https://www.gnu.org/software/libc/manual/html_node/Error-Messages.html */ | ||
71 | return last_component (program_invocation_name); | ||
72 | # elif HAVE_GETEXECNAME /* Solaris */ | ||
73 | /* https://docs.oracle.com/cd/E19253-01/816-5168/6mbb3hrb1/index.html */ | ||
74 | const char *p = getexecname (); | ||
75 | if (!p) | ||
76 | p = "?"; | ||
77 | return last_component (p); | ||
78 | # elif HAVE_DECL___ARGV /* mingw, MSVC */ | ||
79 | /* https://docs.microsoft.com/en-us/cpp/c-runtime-library/argc-argv-wargv */ | ||
80 | const char *p = __argv && __argv[0] ? __argv[0] : "?"; | ||
81 | return last_component (p); | ||
82 | # elif HAVE_VAR___PROGNAME /* OpenBSD, Android, QNX */ | ||
83 | /* https://man.openbsd.org/style.9 */ | ||
84 | /* http://www.qnx.de/developers/docs/6.5.0/index.jsp?topic=%2Fcom.qnx.doc.neutrino_lib_ref%2Fp%2F__progname.html */ | ||
85 | /* Be careful to declare this only when we absolutely need it | ||
86 | (OpenBSD 5.1), rather than when it's available. Otherwise, | ||
87 | its mere declaration makes program_invocation_short_name | ||
88 | malfunction (have zero length) with Fedora 25's glibc. */ | ||
89 | extern char *__progname; | ||
90 | const char *p = __progname; | ||
91 | # if defined __ANDROID__ | ||
92 | return last_component (p); | ||
93 | # else | ||
94 | return p && p[0] ? p : "?"; | ||
95 | # endif | ||
96 | # elif _AIX /* AIX */ | ||
97 | /* Idea by Bastien ROUCARIÈS, | ||
98 | https://lists.gnu.org/r/bug-gnulib/2010-12/msg00095.html | ||
99 | Reference: https://www.ibm.com/support/knowledgecenter/en/ssw_aix_61/com.ibm.aix.basetrf1/getprocs.htm | ||
100 | */ | ||
101 | static char *p; | ||
102 | static int first = 1; | ||
103 | if (first) | ||
104 | { | ||
105 | first = 0; | ||
106 | pid_t pid = getpid (); | ||
107 | struct procentry64 procs; | ||
108 | p = (0 < getprocs64 (&procs, sizeof procs, NULL, 0, &pid, 1) | ||
109 | ? strdup (procs.pi_comm) | ||
110 | : NULL); | ||
111 | if (!p) | ||
112 | p = "?"; | ||
113 | } | ||
114 | return p; | ||
115 | # elif defined __hpux | ||
116 | static char *p; | ||
117 | static int first = 1; | ||
118 | if (first) | ||
119 | { | ||
120 | first = 0; | ||
121 | pid_t pid = getpid (); | ||
122 | struct pst_status status; | ||
123 | if (pstat_getproc (&status, sizeof status, 0, pid) > 0) | ||
124 | { | ||
125 | char *ucomm = status.pst_ucomm; | ||
126 | char *cmd = status.pst_cmd; | ||
127 | if (strlen (ucomm) < PST_UCOMMLEN - 1) | ||
128 | p = ucomm; | ||
129 | else | ||
130 | { | ||
131 | /* ucomm is truncated to length PST_UCOMMLEN - 1. | ||
132 | Look at cmd instead. */ | ||
133 | char *space = strchr (cmd, ' '); | ||
134 | if (space != NULL) | ||
135 | *space = '\0'; | ||
136 | p = strrchr (cmd, '/'); | ||
137 | if (p != NULL) | ||
138 | p++; | ||
139 | else | ||
140 | p = cmd; | ||
141 | if (strlen (p) > PST_UCOMMLEN - 1 | ||
142 | && memcmp (p, ucomm, PST_UCOMMLEN - 1) == 0) | ||
143 | /* p is less truncated than ucomm. */ | ||
144 | ; | ||
145 | else | ||
146 | p = ucomm; | ||
147 | } | ||
148 | p = strdup (p); | ||
149 | } | ||
150 | else | ||
151 | { | ||
152 | # if !defined __LP64__ | ||
153 | /* Support for 32-bit programs running in 64-bit HP-UX. | ||
154 | The documented way to do this is to use the same source code | ||
155 | as above, but in a compilation unit where '#define _PSTAT64 1' | ||
156 | is in effect. I prefer a single compilation unit; the struct | ||
157 | size and the offsets are not going to change. */ | ||
158 | char status64[1216]; | ||
159 | if (__pstat_getproc64 (status64, sizeof status64, 0, pid) > 0) | ||
160 | { | ||
161 | char *ucomm = status64 + 288; | ||
162 | char *cmd = status64 + 168; | ||
163 | if (strlen (ucomm) < PST_UCOMMLEN - 1) | ||
164 | p = ucomm; | ||
165 | else | ||
166 | { | ||
167 | /* ucomm is truncated to length PST_UCOMMLEN - 1. | ||
168 | Look at cmd instead. */ | ||
169 | char *space = strchr (cmd, ' '); | ||
170 | if (space != NULL) | ||
171 | *space = '\0'; | ||
172 | p = strrchr (cmd, '/'); | ||
173 | if (p != NULL) | ||
174 | p++; | ||
175 | else | ||
176 | p = cmd; | ||
177 | if (strlen (p) > PST_UCOMMLEN - 1 | ||
178 | && memcmp (p, ucomm, PST_UCOMMLEN - 1) == 0) | ||
179 | /* p is less truncated than ucomm. */ | ||
180 | ; | ||
181 | else | ||
182 | p = ucomm; | ||
183 | } | ||
184 | p = strdup (p); | ||
185 | } | ||
186 | else | ||
187 | # endif | ||
188 | p = NULL; | ||
189 | } | ||
190 | if (!p) | ||
191 | p = "?"; | ||
192 | } | ||
193 | return p; | ||
194 | # elif __MVS__ /* z/OS */ | ||
195 | /* https://www.ibm.com/support/knowledgecenter/SSLTBW_2.1.0/com.ibm.zos.v2r1.bpxbd00/rtwgetp.htm */ | ||
196 | static char *p = "?"; | ||
197 | static int first = 1; | ||
198 | if (first) | ||
199 | { | ||
200 | pid_t pid = getpid (); | ||
201 | int token; | ||
202 | W_PSPROC buf; | ||
203 | first = 0; | ||
204 | memset (&buf, 0, sizeof(buf)); | ||
205 | buf.ps_cmdptr = (char *) malloc (buf.ps_cmdlen = PS_CMDBLEN_LONG); | ||
206 | buf.ps_conttyptr = (char *) malloc (buf.ps_conttylen = PS_CONTTYBLEN); | ||
207 | buf.ps_pathptr = (char *) malloc (buf.ps_pathlen = PS_PATHBLEN); | ||
208 | if (buf.ps_cmdptr && buf.ps_conttyptr && buf.ps_pathptr) | ||
209 | { | ||
210 | for (token = 0; token >= 0; | ||
211 | token = w_getpsent (token, &buf, sizeof(buf))) | ||
212 | { | ||
213 | if (token > 0 && buf.ps_pid == pid) | ||
214 | { | ||
215 | char *s = strdup (last_component (buf.ps_pathptr)); | ||
216 | if (s) | ||
217 | p = s; | ||
218 | break; | ||
219 | } | ||
220 | } | ||
221 | } | ||
222 | free (buf.ps_cmdptr); | ||
223 | free (buf.ps_conttyptr); | ||
224 | free (buf.ps_pathptr); | ||
225 | } | ||
226 | return p; | ||
227 | # elif defined __sgi || defined __osf__ /* IRIX or Tru64 */ | ||
228 | char filename[50]; | ||
229 | int fd; | ||
230 | |||
231 | # if defined __sgi | ||
232 | sprintf (filename, "/proc/pinfo/%d", (int) getpid ()); | ||
233 | # else | ||
234 | sprintf (filename, "/proc/%d", (int) getpid ()); | ||
235 | # endif | ||
236 | fd = open (filename, O_RDONLY | O_CLOEXEC); | ||
237 | if (0 <= fd) | ||
238 | { | ||
239 | prpsinfo_t buf; | ||
240 | int ioctl_ok = 0 <= ioctl (fd, PIOCPSINFO, &buf); | ||
241 | close (fd); | ||
242 | if (ioctl_ok) | ||
243 | { | ||
244 | char *name = buf.pr_fname; | ||
245 | size_t namesize = sizeof buf.pr_fname; | ||
246 | /* It may not be NUL-terminated. */ | ||
247 | char *namenul = memchr (name, '\0', namesize); | ||
248 | size_t namelen = namenul ? namenul - name : namesize; | ||
249 | char *namecopy = malloc (namelen + 1); | ||
250 | if (namecopy) | ||
251 | { | ||
252 | namecopy[namelen] = '\0'; | ||
253 | return memcpy (namecopy, name, namelen); | ||
254 | } | ||
255 | } | ||
256 | } | ||
257 | return NULL; | ||
258 | # elif defined __SCO_VERSION__ || defined __sysv5__ /* SCO OpenServer6/UnixWare */ | ||
259 | char buf[80]; | ||
260 | int fd; | ||
261 | sprintf (buf, "/proc/%d/cmdline", getpid()); | ||
262 | fd = open (buf, O_RDONLY); | ||
263 | if (0 <= fd) | ||
264 | { | ||
265 | size_t n = read (fd, buf, 79); | ||
266 | if (n > 0) | ||
267 | { | ||
268 | buf[n] = '\0'; /* Guarantee null-termination */ | ||
269 | char *progname; | ||
270 | progname = strrchr (buf, '/'); | ||
271 | if (progname) | ||
272 | { | ||
273 | progname = progname + 1; /* Skip the '/' */ | ||
274 | } | ||
275 | else | ||
276 | { | ||
277 | progname = buf; | ||
278 | } | ||
279 | char *ret; | ||
280 | ret = malloc (strlen (progname) + 1); | ||
281 | if (ret) | ||
282 | { | ||
283 | strcpy (ret, progname); | ||
284 | return ret; | ||
285 | } | ||
286 | } | ||
287 | close (fd); | ||
288 | } | ||
289 | return "?"; | ||
290 | # else | ||
291 | # error "getprogname module not ported to this OS" | ||
292 | # endif | ||
293 | } | ||
294 | |||
295 | #endif | ||
296 | |||
297 | /* | ||
298 | * Hey Emacs! | ||
299 | * Local Variables: | ||
300 | * coding: utf-8 | ||
301 | * End: | ||
302 | */ | ||