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