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