2 * libdpkg - Debian packaging suite library routines
3 * execname.c - executable name handling functions
5 * Copyright © 2024 Guillem Jover <guillem@debian.org>
7 * This is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
24 #ifdef HAVE_SYS_PARAM_H
25 #include <sys/param.h>
27 #ifdef HAVE_SYS_SYSCTL_H
28 #include <sys/sysctl.h>
30 #if defined(_AIX) && defined(HAVE_SYS_PROCFS_H)
31 #include <sys/procfs.h>
45 #if defined(__APPLE__) && defined(__MACH__)
49 #include <dpkg/dpkg.h>
51 #include <dpkg/file.h>
53 #include <dpkg/execname.h>
55 #if defined(_AIX) && defined(HAVE_STRUCT_PSINFO)
57 proc_get_psinfo(pid_t pid
, struct psinfo
*psinfo
)
62 sprintf(filename
, "/proc/%d/psinfo", pid
);
63 fp
= fopen(filename
, "r");
66 if (fread(psinfo
, sizeof(*psinfo
), 1, fp
) == 0) {
82 * Get the executable name for a PID.
84 * Tries to obtain the executable name or process name for a specific PID,
85 * if the executable name cannot be obtained then it will return NULL.
87 * @return A pointer to an allocated string with the executable name, or NULL.
90 dpkg_get_pid_execname(pid_t pid
)
92 char *execname
= NULL
;
93 #if defined(__linux__)
95 char lcontents
[_POSIX_PATH_MAX
+ 1];
98 sprintf(lname
, "/proc/%d/exe", pid
);
99 nread
= readlink(lname
, lcontents
, sizeof(lcontents
) - 1);
103 lcontents
[nread
] = '\0';
104 execname
= lcontents
;
105 #elif defined(__GNU__)
106 struct ps_context
*pc
;
107 struct proc_stat
*ps
;
113 err
= ps_context_create(getproc(), &pc
);
117 err
= ps_context_find_proc_stat(pc
, pid
, &ps
);
121 /* On old Hurd systems we have to use the argv[0] value, because
122 * there is nothing better. */
123 if (proc_stat_set_flags(ps
, PSTAT_ARGS
) == 0 &&
124 (proc_stat_flags(ps
) & PSTAT_ARGS
))
125 execname
= proc_stat_args(ps
);
128 /* On new Hurd systems we can use the correct value, as long
129 * as it's not NULL nor empty, as it was the case on the first
131 if (proc_stat_set_flags(ps
, PSTAT_EXE
) == 0 &&
132 proc_stat_flags(ps
) & PSTAT_EXE
&&
133 proc_stat_exe(ps
) != NULL
&&
134 proc_stat_exe(ps
)[0] != '\0')
135 execname
= proc_stat_exe(ps
);
141 struct varbuf vb
= VARBUF_INIT
;
143 sprintf(filename
, "/proc/%d/execname", pid
);
144 if (file_slurp(filename
, &vb
, NULL
) < 0)
147 return varbuf_detach(&vb
);
148 #elif defined(__APPLE__) && defined(__MACH__)
149 char pathname
[_POSIX_PATH_MAX
];
151 if (proc_pidpath(pid
, pathname
, sizeof(pathname
)) < 0)
155 #elif defined(_AIX) && defined(HAVE_STRUCT_PSINFO)
159 sprintf(filename
, "/proc/%d/psinfo", pid
);
160 if (!proc_get_psinfo(pid
, &psi
))
163 execname
= psi
.pr_fname
;
164 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
167 char pathname
[PATH_MAX
];
171 mib
[2] = KERN_PROC_PATHNAME
;
173 len
= sizeof(pathname
);
175 error
= sysctl(mib
, 4, pathname
, &len
, NULL
, 0);
176 if (error
!= 0 && errno
!= ESRCH
)
185 return m_strdup(execname
);