This is an automated email from the git hooks/post-receive script.

guillem pushed a commit to branch main
in repository dpkg.

View the commit online:
https://git.dpkg.org/cgit/dpkg/dpkg.git/commit/?id=d6a9bb6951166a7254ab2b4f887c69c4bd4fb1a7

commit d6a9bb6951166a7254ab2b4f887c69c4bd4fb1a7
Author: Guillem Jover <[email protected]>
AuthorDate: Mon Apr 29 09:55:19 2024 +0200

    libdpkg: Add new execname module
    
    This module tries to return the executable name for a specific process
    given its PID. If it cannot gather the information either because the
    process is gone, or the port does not yet have support for it, then
    the code will return NULL.
---
 lib/dpkg/Makefile.am               |   2 +
 lib/dpkg/execname.c                | 165 +++++++++++++++++++++++++++++++++++++
 lib/dpkg/{program.h => execname.h} |  16 ++--
 lib/dpkg/libdpkg.map               |   3 +
 po/POTFILES.in                     |   1 +
 5 files changed, 180 insertions(+), 7 deletions(-)

diff --git a/lib/dpkg/Makefile.am b/lib/dpkg/Makefile.am
index 8c72cbad1..862562c8f 100644
--- a/lib/dpkg/Makefile.am
+++ b/lib/dpkg/Makefile.am
@@ -85,6 +85,7 @@ libdpkg_la_SOURCES = \
        dump.c \
        ehandle.c \
        error.c \
+       execname.c \
        fdio.c \
        file.c \
        fields.c \
@@ -155,6 +156,7 @@ pkginclude_HEADERS = \
        dpkg-db.h \
        ehandle.h \
        error.h \
+       execname.h \
        fdio.h \
        file.h \
        fsys.h \
diff --git a/lib/dpkg/execname.c b/lib/dpkg/execname.c
new file mode 100644
index 000000000..3f6b14d1b
--- /dev/null
+++ b/lib/dpkg/execname.c
@@ -0,0 +1,165 @@
+/*
+ * libdpkg - Debian packaging suite library routines
+ * execname.c - executable name handling functions
+ *
+ * Copyright © 2024 Guillem Jover <[email protected]>
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <compat.h>
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_SYS_SYSCTL_H
+#include <sys/sysctl.h>
+#endif
+#if defined(_AIX) && defined(HAVE_SYS_PROCFS_H)
+#include <sys/procfs.h>
+#endif
+
+#include <limits.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#if defined(__APPLE__) && defined(__MACH__)
+#include <libproc.h>
+#endif
+
+#include <dpkg/dpkg.h>
+#include <dpkg/file.h>
+#include <dpkg/execname.h>
+
+#if defined(_AIX) && defined(HAVE_STRUCT_PSINFO)
+static bool
+proc_get_psinfo(pid_t pid, struct psinfo *psinfo)
+{
+       char filename[64];
+       FILE *fp;
+
+       sprintf(filename, "/proc/%d/psinfo", pid);
+       fp = fopen(filename, "r");
+       if (!fp)
+               return false;
+       if (fread(psinfo, sizeof(*psinfo), 1, fp) == 0) {
+               fclose(fp);
+               return false;
+       }
+       if (ferror(fp)) {
+               fclose(fp);
+               return false;
+       }
+
+       fclose(fp);
+
+       return true;
+}
+#endif
+
+/**
+ * Get the executable name for a PID.
+ *
+ * Tries to obtain the executable name or process name for a specific PID,
+ * if the executable name cannot be obtained then it will return NULL.
+ *
+ * @return A pointer to an allocated string with the executable name, or NULL.
+ */
+char *
+dpkg_get_pid_execname(pid_t pid)
+{
+       const char *execname = NULL;
+#if defined(__linux__)
+       char lname[32];
+       char lcontents[_POSIX_PATH_MAX + 1];
+       int nread;
+
+       sprintf(lname, "/proc/%d/exe", pid);
+       nread = readlink(lname, lcontents, sizeof(lcontents) - 1);
+       if (nread == -1)
+               return NULL;
+
+       lcontents[nread] = '\0';
+       execname = lcontents;
+#elif defined(__GNU__)
+       struct proc_stat *ps;
+       const char *filename;
+
+       ps = get_proc_stat(pid, PSTAT_ARGS);
+       if (ps == NULL)
+               return NULL;
+
+       /* On old Hurd systems we have to use the argv[0] value, because
+        * there is nothing better. */
+       execname = proc_stat_args(ps);
+
+#ifdef PSTAT_EXE
+       /* On new Hurd systems we can use the correct value, as long
+        * as it's not NULL nor empty, as it was the case on the first
+        * implementation. */
+       if (proc_stat_set_flags(ps, PSTAT_EXE) == 0 &&
+           proc_stat_flags(ps) & PSTAT_EXE &&
+           proc_stat_exe(ps) != NULL &&
+           proc_stat_exe(ps)[0] != '\0')
+               execname = proc_stat_exe(ps);
+#endif
+#elif defined(__sun)
+       char filename[64];
+       struct varbuf vb = VARBUF_INIT;
+
+       sprintf(filename, "/proc/%d/execname", pid);
+       if (file_slurp(filename, &vb, NULL) < 0)
+               return NULL;
+
+       return varbuf_detach(&vb);
+#elif defined(__APPLE__) && defined(__MACH__)
+       char pathname[_POSIX_PATH_MAX];
+
+       if (proc_pidpath(pid, pathname, sizeof(pathname)) < 0)
+               return NULL;
+
+       execname = pathname;
+#elif defined(_AIX) && defined(HAVE_STRUCT_PSINFO)
+       char filename[64];
+       struct psinfo psi;
+
+       sprintf(filename, "/proc/%d/psinfo", pid);
+       if (!proc_get_psinfo(pid, &psi))
+               return NULL;
+
+       execname = psi.pr_fname;
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+       int error, mib[4];
+       size_t len;
+       char pathname[PATH_MAX];
+
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_PROC;
+       mib[2] = KERN_PROC_PATHNAME;
+       mib[3] = pid;
+       len = sizeof(pathname);
+
+       error = sysctl(mib, 4, pathname, &len, NULL, 0);
+       if (error != 0 && errno != ESRCH)
+               return NULL;
+       if (len == 0)
+               pathname[0] = '\0';
+       execname = pathname;
+#endif
+
+       return m_strdup(execname);
+}
diff --git a/lib/dpkg/program.h b/lib/dpkg/execname.h
similarity index 74%
copy from lib/dpkg/program.h
copy to lib/dpkg/execname.h
index e4fe4f4a0..f82efc340 100644
--- a/lib/dpkg/program.h
+++ b/lib/dpkg/execname.h
@@ -1,8 +1,8 @@
 /*
  * libdpkg - Debian packaging suite library routines
- * program.h - dpkg-based program support
+ * execname.h - executable name handling functions
  *
- * Copyright © 2013 Guillem Jover <[email protected]>
+ * Copyright © 2024 Guillem Jover <[email protected]>
  *
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,21 +18,23 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
-#ifndef LIBDPKG_PROGRAM_H
-#define LIBDPKG_PROGRAM_H
+#ifndef LIBDPKG_EXECNAME_H
+#define LIBDPKG_EXECNAME_H
+
+#include <sys/types.h>
 
 #include <dpkg/macros.h>
 
 DPKG_BEGIN_DECLS
 
 /**
- * @defgroup program Program support
+ * @defgroup execname Executable name handling
  * @ingroup dpkg-public
  * @{
  */
 
-void dpkg_program_init(const char *progname);
-void dpkg_program_done(void);
+char *
+dpkg_get_pid_execname(pid_t pid);
 
 /** @} */
 
diff --git a/lib/dpkg/libdpkg.map b/lib/dpkg/libdpkg.map
index c2b0048e6..3b29ad44a 100644
--- a/lib/dpkg/libdpkg.map
+++ b/lib/dpkg/libdpkg.map
@@ -30,6 +30,9 @@ global:
        dpkg_ar_normalize_name;
        dpkg_ar_member_is_illegal;
 
+       # Process information
+       dpkg_get_pid_execname;
+
 local:
        *;
 };
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 9507e0e18..38e83b593 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -26,6 +26,7 @@ lib/dpkg/dir.c
 lib/dpkg/dump.c
 lib/dpkg/ehandle.c
 lib/dpkg/error.c
+lib/dpkg/execname.c
 lib/dpkg/fdio.c
 lib/dpkg/fields.c
 lib/dpkg/file.c

-- 
Dpkg.Org's dpkg

Reply via email to