2021-04-18 15:19:21 +02:00
|
|
|
#include "fastfetch.h"
|
2022-07-25 14:48:59 +02:00
|
|
|
#include "common/processing.h"
|
2023-01-28 12:40:12 +01:00
|
|
|
#include "common/io/io.h"
|
2024-05-28 22:34:41 +08:00
|
|
|
#include "util/stringUtils.h"
|
2024-05-28 23:46:13 +08:00
|
|
|
#include "util/mallocHelper.h"
|
2021-04-18 15:19:21 +02:00
|
|
|
|
2022-06-18 14:25:31 +02:00
|
|
|
#include <stdlib.h>
|
2021-04-18 15:19:21 +02:00
|
|
|
#include <unistd.h>
|
2023-07-10 16:14:04 +08:00
|
|
|
#include <signal.h>
|
2023-07-11 11:10:10 +08:00
|
|
|
#include <poll.h>
|
2023-07-11 20:28:59 +08:00
|
|
|
#include <fcntl.h>
|
|
|
|
|
#include <errno.h>
|
2023-07-15 08:25:57 +08:00
|
|
|
#include <sys/wait.h>
|
2025-07-18 13:27:17 +08:00
|
|
|
|
|
|
|
|
#if !(__ANDROID__ || __OpenBSD__)
|
|
|
|
|
#include <spawn.h>
|
|
|
|
|
#endif
|
2023-07-11 20:28:59 +08:00
|
|
|
|
2024-05-28 22:34:41 +08:00
|
|
|
#if defined(__FreeBSD__) || defined(__APPLE__)
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <sys/user.h>
|
|
|
|
|
#include <sys/sysctl.h>
|
|
|
|
|
#endif
|
2024-06-17 14:44:34 +08:00
|
|
|
#if defined(__APPLE__)
|
2024-05-28 23:46:13 +08:00
|
|
|
#include <libproc.h>
|
2024-06-17 14:44:34 +08:00
|
|
|
#elif defined(__sun)
|
|
|
|
|
#include <procfs.h>
|
2024-10-04 15:58:17 +08:00
|
|
|
#elif defined(__OpenBSD__)
|
2024-10-27 11:43:36 +08:00
|
|
|
#include <sys/param.h>
|
|
|
|
|
#include <sys/sysctl.h>
|
|
|
|
|
#include <kvm.h>
|
|
|
|
|
#elif defined(__NetBSD__)
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <sys/sysctl.h>
|
2025-02-12 00:44:41 +08:00
|
|
|
#elif defined(__HAIKU__)
|
|
|
|
|
#include <OS.h>
|
2025-02-13 22:39:45 +00:00
|
|
|
#include <image.h>
|
2024-05-28 23:46:13 +08:00
|
|
|
#endif
|
2024-05-28 22:34:41 +08:00
|
|
|
|
2025-07-09 21:27:19 +08:00
|
|
|
#ifndef environ
|
|
|
|
|
extern char** environ;
|
|
|
|
|
#endif
|
|
|
|
|
|
2023-12-04 15:10:58 +08:00
|
|
|
enum { FF_PIPE_BUFSIZ = 8192 };
|
2021-04-18 15:19:21 +02:00
|
|
|
|
2025-02-05 15:36:09 +08:00
|
|
|
static inline int ffPipe2(int* fds, int flags)
|
2023-11-29 19:28:28 +09:00
|
|
|
{
|
2025-02-05 15:36:09 +08:00
|
|
|
#ifndef FF_HAVE_PIPE2
|
2023-11-29 19:28:28 +09:00
|
|
|
if(pipe(fds) == -1)
|
|
|
|
|
return -1;
|
|
|
|
|
fcntl(fds[0], F_SETFL, fcntl(fds[0], F_GETFL) | flags);
|
|
|
|
|
fcntl(fds[1], F_SETFL, fcntl(fds[1], F_GETFL) | flags);
|
|
|
|
|
return 0;
|
|
|
|
|
#else
|
|
|
|
|
return pipe2(fds, flags);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-15 10:15:39 +08:00
|
|
|
|
|
|
|
|
// Not thread-safe
|
2023-07-10 21:02:13 +08:00
|
|
|
const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool useStdErr)
|
2023-07-10 09:36:33 +08:00
|
|
|
{
|
|
|
|
|
int pipes[2];
|
2023-11-29 19:28:28 +09:00
|
|
|
const int timeout = instance.config.general.processingTimeout;
|
2023-07-10 09:36:33 +08:00
|
|
|
|
2023-11-29 19:28:28 +09:00
|
|
|
if(ffPipe2(pipes, O_CLOEXEC) == -1)
|
2023-07-10 09:36:33 +08:00
|
|
|
return "pipe() failed";
|
|
|
|
|
|
2025-07-18 10:37:52 +08:00
|
|
|
pid_t childPid = -1;
|
|
|
|
|
int nullFile = ffGetNullFD();
|
|
|
|
|
|
|
|
|
|
#if !(__ANDROID__ || __OpenBSD__)
|
|
|
|
|
|
|
|
|
|
// NetBSD / Darwin: native syscall
|
|
|
|
|
// Linux (glibc): clone3-execve
|
|
|
|
|
// FreeBSD: vfork-execve
|
|
|
|
|
// illumos: vforkx-execve
|
|
|
|
|
// OpenBSD / Android (bionic): fork-execve
|
|
|
|
|
|
2025-07-09 21:27:19 +08:00
|
|
|
posix_spawn_file_actions_t file_actions;
|
|
|
|
|
posix_spawn_file_actions_init(&file_actions);
|
|
|
|
|
posix_spawn_file_actions_adddup2(&file_actions, pipes[1], useStdErr ? STDERR_FILENO : STDOUT_FILENO);
|
2025-07-18 10:37:52 +08:00
|
|
|
posix_spawn_file_actions_adddup2(&file_actions, nullFile, useStdErr ? STDOUT_FILENO : STDERR_FILENO);
|
2023-07-10 09:36:33 +08:00
|
|
|
|
2025-07-15 10:15:39 +08:00
|
|
|
static char* oldLang = NULL;
|
|
|
|
|
static int langIndex = -1;
|
|
|
|
|
|
|
|
|
|
if (langIndex >= 0)
|
|
|
|
|
{
|
|
|
|
|
// Found before
|
|
|
|
|
if (oldLang) // oldLang was set only if it needed to be changed
|
|
|
|
|
{
|
|
|
|
|
if (environ[langIndex] != oldLang)
|
|
|
|
|
{
|
|
|
|
|
// environ is changed outside of this function
|
|
|
|
|
langIndex = -1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
environ[langIndex] = (char*) "LANG=C.UTF-8";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (langIndex < 0)
|
2023-07-10 09:36:33 +08:00
|
|
|
{
|
2025-07-15 10:15:39 +08:00
|
|
|
for (int i = 0; environ[i] != NULL; i++)
|
2025-07-09 21:27:19 +08:00
|
|
|
{
|
2025-07-15 10:15:39 +08:00
|
|
|
if (ffStrStartsWith(environ[i], "LANG="))
|
|
|
|
|
{
|
|
|
|
|
langIndex = i;
|
|
|
|
|
const char* langValue = environ[i] + 5; // Skip "LANG="
|
|
|
|
|
if (ffStrEqualsIgnCase(langValue, "C") ||
|
|
|
|
|
ffStrStartsWithIgnCase(environ[i], "C.") ||
|
|
|
|
|
ffStrEqualsIgnCase(langValue, "en_US") ||
|
|
|
|
|
ffStrStartsWithIgnCase(langValue, "en_US."))
|
|
|
|
|
break; // No need to change LANG
|
|
|
|
|
oldLang = environ[i];
|
|
|
|
|
environ[i] = (char*) "LANG=C.UTF-8"; // Set LANG to C.UTF-8 for consistent output
|
|
|
|
|
break;
|
|
|
|
|
}
|
2025-07-09 21:27:19 +08:00
|
|
|
}
|
2023-07-10 09:36:33 +08:00
|
|
|
}
|
|
|
|
|
|
2025-07-09 21:27:19 +08:00
|
|
|
int ret = posix_spawnp(&childPid, argv[0], &file_actions, NULL, argv, environ);
|
|
|
|
|
|
|
|
|
|
if (oldLang)
|
|
|
|
|
environ[langIndex] = oldLang;
|
|
|
|
|
|
|
|
|
|
posix_spawn_file_actions_destroy(&file_actions);
|
|
|
|
|
|
|
|
|
|
if (ret != 0)
|
|
|
|
|
{
|
|
|
|
|
close(pipes[0]);
|
2025-07-18 10:37:52 +08:00
|
|
|
close(pipes[1]);
|
2025-07-09 21:27:19 +08:00
|
|
|
return "posix_spawnp() failed";
|
|
|
|
|
}
|
2023-07-10 09:36:33 +08:00
|
|
|
|
2025-07-18 10:37:52 +08:00
|
|
|
#else
|
|
|
|
|
|
|
|
|
|
// https://github.com/termux/termux-packages/issues/25369
|
|
|
|
|
childPid = fork();
|
|
|
|
|
if(childPid == -1)
|
|
|
|
|
{
|
|
|
|
|
close(pipes[0]);
|
|
|
|
|
close(pipes[1]);
|
|
|
|
|
return "fork() failed";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(childPid == 0)
|
|
|
|
|
{
|
|
|
|
|
//Child
|
|
|
|
|
dup2(pipes[1], useStdErr ? STDERR_FILENO : STDOUT_FILENO);
|
|
|
|
|
dup2(nullFile, useStdErr ? STDOUT_FILENO : STDERR_FILENO);
|
|
|
|
|
putenv("LANG=C.UTF-8");
|
|
|
|
|
execvp(argv[0], argv);
|
|
|
|
|
_exit(127);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
close(pipes[1]);
|
|
|
|
|
|
2023-07-10 09:36:33 +08:00
|
|
|
int FF_AUTO_CLOSE_FD childPipeFd = pipes[0];
|
2023-11-29 19:28:28 +09:00
|
|
|
char str[FF_PIPE_BUFSIZ];
|
2023-07-11 20:28:59 +08:00
|
|
|
|
2023-11-29 19:28:28 +09:00
|
|
|
while(1)
|
2023-07-11 11:10:10 +08:00
|
|
|
{
|
2023-07-11 20:28:59 +08:00
|
|
|
if (timeout >= 0)
|
2023-07-11 11:10:10 +08:00
|
|
|
{
|
2023-07-11 20:28:59 +08:00
|
|
|
struct pollfd pollfd = { childPipeFd, POLLIN, 0 };
|
2025-07-09 21:27:19 +08:00
|
|
|
int pollret = poll(&pollfd, 1, timeout);
|
|
|
|
|
if (pollret == 0)
|
2023-07-11 20:28:59 +08:00
|
|
|
{
|
|
|
|
|
kill(childPid, SIGTERM);
|
2024-01-18 14:54:14 +08:00
|
|
|
waitpid(childPid, NULL, 0);
|
2024-04-30 10:33:21 +08:00
|
|
|
return "poll(&pollfd, 1, timeout) timeout (try increasing --processing-timeout)";
|
2023-07-11 20:28:59 +08:00
|
|
|
}
|
2025-07-09 21:27:19 +08:00
|
|
|
else if (pollret < 0)
|
2024-12-02 15:54:59 +08:00
|
|
|
{
|
2025-07-09 21:27:19 +08:00
|
|
|
if (errno == EINTR)
|
|
|
|
|
{
|
|
|
|
|
// The child process has been terminated. See `chldSignalHandler` in `common/init.c`
|
|
|
|
|
if (waitpid(childPid, NULL, WNOHANG) == childPid)
|
|
|
|
|
{
|
|
|
|
|
// Read remaining data from the pipe
|
|
|
|
|
fcntl(childPipeFd, F_SETFL, O_CLOEXEC | O_NONBLOCK);
|
|
|
|
|
childPid = -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
2024-12-02 15:54:59 +08:00
|
|
|
{
|
2025-07-09 21:27:19 +08:00
|
|
|
kill(childPid, SIGTERM);
|
|
|
|
|
waitpid(childPid, NULL, 0);
|
|
|
|
|
return "poll(&pollfd, 1, timeout) error";
|
2024-12-02 15:54:59 +08:00
|
|
|
}
|
|
|
|
|
}
|
2023-07-11 20:28:59 +08:00
|
|
|
else if (pollfd.revents & POLLERR)
|
|
|
|
|
{
|
|
|
|
|
kill(childPid, SIGTERM);
|
2024-01-18 14:54:14 +08:00
|
|
|
waitpid(childPid, NULL, 0);
|
2023-07-11 20:28:59 +08:00
|
|
|
return "poll(&pollfd, 1, timeout) error";
|
|
|
|
|
}
|
2023-07-11 11:10:10 +08:00
|
|
|
}
|
2023-07-11 20:28:59 +08:00
|
|
|
|
2023-11-29 19:28:28 +09:00
|
|
|
ssize_t nRead = read(childPipeFd, str, FF_PIPE_BUFSIZ);
|
|
|
|
|
if (nRead > 0)
|
|
|
|
|
ffStrbufAppendNS(buffer, (uint32_t) nRead, str);
|
|
|
|
|
else if (nRead == 0)
|
2024-01-18 14:54:14 +08:00
|
|
|
{
|
|
|
|
|
int stat_loc = 0;
|
2024-12-02 15:54:59 +08:00
|
|
|
if (childPid > 0 && waitpid(childPid, &stat_loc, 0) == childPid)
|
2024-01-18 14:54:14 +08:00
|
|
|
{
|
|
|
|
|
if (!WIFEXITED(stat_loc))
|
|
|
|
|
return "child process exited abnormally";
|
|
|
|
|
if (WEXITSTATUS(stat_loc) == 127)
|
|
|
|
|
return "command was not found";
|
|
|
|
|
// We only handle 127 as an error. See `getTerminalVersionUrxvt` in `terminalshell.c`
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2024-12-02 15:54:59 +08:00
|
|
|
return NULL;
|
2024-01-18 14:54:14 +08:00
|
|
|
}
|
2023-11-29 19:28:28 +09:00
|
|
|
else if (nRead < 0)
|
2024-12-02 15:54:59 +08:00
|
|
|
{
|
|
|
|
|
if (errno == EAGAIN)
|
|
|
|
|
return NULL;
|
|
|
|
|
else
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-11-29 19:28:28 +09:00
|
|
|
};
|
2023-07-10 09:36:33 +08:00
|
|
|
|
2023-11-29 19:28:28 +09:00
|
|
|
return "read(childPipeFd, str, FF_PIPE_BUFSIZ) failed";
|
2023-07-10 09:36:33 +08:00
|
|
|
}
|
2024-05-28 22:34:41 +08:00
|
|
|
|
|
|
|
|
void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, const char** exeName, FFstrbuf* exePath)
|
|
|
|
|
{
|
|
|
|
|
assert(processName->length > 0);
|
|
|
|
|
ffStrbufClear(exe);
|
|
|
|
|
|
|
|
|
|
#ifdef __linux__
|
|
|
|
|
|
|
|
|
|
char filePath[64];
|
|
|
|
|
snprintf(filePath, sizeof(filePath), "/proc/%d/cmdline", (int)pid);
|
|
|
|
|
|
2024-05-28 23:46:13 +08:00
|
|
|
if(ffReadFileBuffer(filePath, exe))
|
2024-05-28 22:34:41 +08:00
|
|
|
{
|
|
|
|
|
ffStrbufRecalculateLength(exe); //Trim the arguments
|
2024-05-28 23:46:13 +08:00
|
|
|
ffStrbufTrimRightSpace(exe);
|
2024-05-28 22:34:41 +08:00
|
|
|
ffStrbufTrimLeft(exe, '-'); //Login shells start with a dash
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-28 23:46:13 +08:00
|
|
|
if (exePath)
|
2024-05-28 22:34:41 +08:00
|
|
|
{
|
2024-05-28 23:46:13 +08:00
|
|
|
snprintf(filePath, sizeof(filePath), "/proc/%d/exe", (int)pid);
|
2024-10-14 11:35:29 +08:00
|
|
|
char buf[PATH_MAX];
|
|
|
|
|
ssize_t length = readlink(filePath, buf, PATH_MAX - 1);
|
2024-05-28 23:46:13 +08:00
|
|
|
if (length > 0) // doesn't contain trailing NUL
|
|
|
|
|
{
|
2024-10-14 11:35:29 +08:00
|
|
|
buf[length] = '\0';
|
2024-11-13 10:46:30 +08:00
|
|
|
ffStrbufEnsureFixedLengthFree(exePath, (uint32_t)length);
|
2024-10-14 11:35:29 +08:00
|
|
|
ffStrbufAppendNS(exePath, (uint32_t)length, buf);
|
2024-05-28 23:46:13 +08:00
|
|
|
}
|
2024-05-28 22:34:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#elif defined(__APPLE__)
|
|
|
|
|
|
|
|
|
|
size_t len = 0;
|
|
|
|
|
int mibs[] = { CTL_KERN, KERN_PROCARGS2, pid };
|
2024-10-18 16:15:48 +08:00
|
|
|
if (sysctl(mibs, ARRAY_SIZE(mibs), NULL, &len, NULL, 0) == 0)
|
2024-05-28 23:46:13 +08:00
|
|
|
{// try get arg0
|
2024-05-28 22:34:41 +08:00
|
|
|
//don't know why if don't let len longer, proArgs2 and len will change during the following sysctl() in old MacOS version.
|
|
|
|
|
len++;
|
|
|
|
|
FF_AUTO_FREE char* const procArgs2 = malloc(len);
|
2024-10-18 16:15:48 +08:00
|
|
|
if (sysctl(mibs, ARRAY_SIZE(mibs), procArgs2, &len, NULL, 0) == 0)
|
2024-05-28 22:34:41 +08:00
|
|
|
{
|
|
|
|
|
// https://gist.github.com/nonowarn/770696#file-getargv-c-L46
|
|
|
|
|
uint32_t argc = *(uint32_t*) procArgs2;
|
|
|
|
|
const char* realExePath = procArgs2 + sizeof(argc);
|
|
|
|
|
|
|
|
|
|
const char* arg0 = memchr(realExePath, '\0', len - (size_t) (realExePath - procArgs2));
|
2024-05-28 23:46:13 +08:00
|
|
|
if (exePath)
|
|
|
|
|
ffStrbufSetNS(exePath, (uint32_t) (arg0 - realExePath), realExePath);
|
2024-05-28 22:34:41 +08:00
|
|
|
|
|
|
|
|
do arg0++; while (*arg0 == '\0');
|
|
|
|
|
assert(arg0 < procArgs2 + len);
|
2024-05-30 09:27:35 +08:00
|
|
|
|
2024-05-30 09:58:06 +08:00
|
|
|
if (argc > 1)
|
2024-05-30 09:27:35 +08:00
|
|
|
{
|
|
|
|
|
// #977
|
2024-05-30 09:58:06 +08:00
|
|
|
const char* p = strrchr(arg0, '/');
|
2024-05-30 09:27:35 +08:00
|
|
|
if (p)
|
|
|
|
|
p++;
|
2024-05-30 09:58:06 +08:00
|
|
|
else
|
|
|
|
|
p = arg0;
|
|
|
|
|
if (ffStrStartsWithIgnCase(p, "python")) // /opt/homebrew/Cellar/python@3.12/3.12.3/Frameworks/Python.framework/Versions/3.12/Resources/Python.app/Contents/MacOS/Python /Users/carter/.local/bin/xonsh
|
|
|
|
|
arg0 = p + strlen(p) + 1;
|
2024-05-30 09:27:35 +08:00
|
|
|
}
|
|
|
|
|
|
2024-05-28 22:34:41 +08:00
|
|
|
if (*arg0 == '-') arg0++; // Login shells
|
|
|
|
|
|
|
|
|
|
ffStrbufSetS(exe, arg0);
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-05-28 23:46:13 +08:00
|
|
|
else
|
|
|
|
|
{
|
2024-11-13 10:46:30 +08:00
|
|
|
char buf[PROC_PIDPATHINFO_MAXSIZE];
|
|
|
|
|
int length = proc_pidpath(pid, buf, ARRAY_SIZE(buf));
|
2024-05-28 23:46:13 +08:00
|
|
|
if (length > 0)
|
|
|
|
|
{
|
2024-11-13 10:46:30 +08:00
|
|
|
ffStrbufEnsureFixedLengthFree(exe, (uint32_t) length);
|
|
|
|
|
ffStrbufAppendNS(exe, (uint32_t) length, buf);
|
2024-05-28 23:46:13 +08:00
|
|
|
if (exePath)
|
|
|
|
|
ffStrbufSet(exePath, exe);
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-05-28 22:34:41 +08:00
|
|
|
|
2024-10-27 11:43:36 +08:00
|
|
|
#elif defined(__FreeBSD__) || defined(__NetBSD__)
|
2024-05-28 22:34:41 +08:00
|
|
|
|
|
|
|
|
size_t size = ARG_MAX;
|
|
|
|
|
FF_AUTO_FREE char* args = malloc(size);
|
|
|
|
|
|
|
|
|
|
static_assert(ARG_MAX > PATH_MAX, "");
|
|
|
|
|
|
2024-05-28 23:46:13 +08:00
|
|
|
if(exePath && sysctl(
|
2024-10-27 11:43:36 +08:00
|
|
|
(int[]){CTL_KERN,
|
|
|
|
|
#if __FreeBSD__
|
2024-10-31 00:25:40 +08:00
|
|
|
KERN_PROC, KERN_PROC_PATHNAME, pid
|
2024-10-27 11:43:36 +08:00
|
|
|
#else
|
2024-10-31 00:25:40 +08:00
|
|
|
KERN_PROC_ARGS, pid, KERN_PROC_PATHNAME
|
2024-10-27 11:43:36 +08:00
|
|
|
#endif
|
2024-10-31 00:25:40 +08:00
|
|
|
}, 4,
|
2024-05-28 22:34:41 +08:00
|
|
|
args, &size,
|
|
|
|
|
NULL, 0
|
|
|
|
|
) == 0)
|
|
|
|
|
ffStrbufSetNS(exePath, (uint32_t) (size - 1), args);
|
|
|
|
|
|
|
|
|
|
size = ARG_MAX;
|
|
|
|
|
if(sysctl(
|
2024-10-27 11:43:36 +08:00
|
|
|
(int[]){CTL_KERN,
|
|
|
|
|
#if __FreeBSD__
|
2024-10-31 00:25:40 +08:00
|
|
|
KERN_PROC, KERN_PROC_ARGS, pid
|
2024-10-27 11:43:36 +08:00
|
|
|
#else
|
2024-10-31 00:25:40 +08:00
|
|
|
KERN_PROC_ARGS, pid, KERN_PROC_ARGV,
|
2024-10-27 11:43:36 +08:00
|
|
|
#endif
|
2024-10-31 00:25:40 +08:00
|
|
|
}, 4,
|
2024-05-28 22:34:41 +08:00
|
|
|
args, &size,
|
|
|
|
|
NULL, 0
|
|
|
|
|
) == 0)
|
|
|
|
|
{
|
|
|
|
|
char* arg0 = args;
|
|
|
|
|
size_t arg0Len = strlen(args);
|
|
|
|
|
if (size > arg0Len + 1)
|
|
|
|
|
{
|
|
|
|
|
char* p = (char*) memrchr(args, '/', arg0Len);
|
|
|
|
|
if (p)
|
|
|
|
|
p++;
|
2024-05-30 09:58:06 +08:00
|
|
|
else
|
|
|
|
|
p = arg0;
|
|
|
|
|
if (ffStrStartsWith(p, "python")) // /usr/local/bin/python3.9 /home/carter/.local/bin/xonsh
|
|
|
|
|
{
|
|
|
|
|
arg0 += arg0Len + 1;
|
2024-05-28 22:34:41 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (arg0[0] == '-') arg0++;
|
|
|
|
|
ffStrbufSetS(exe, arg0);
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-17 14:44:34 +08:00
|
|
|
#elif defined(__sun)
|
|
|
|
|
|
2024-10-14 11:35:29 +08:00
|
|
|
char filePath[128];
|
2024-06-17 14:44:34 +08:00
|
|
|
snprintf(filePath, sizeof(filePath), "/proc/%d/psinfo", (int) pid);
|
|
|
|
|
psinfo_t proc;
|
|
|
|
|
if (ffReadFileData(filePath, sizeof(proc), &proc) == sizeof(proc))
|
|
|
|
|
{
|
2025-06-22 12:12:49 +08:00
|
|
|
const char* args = proc.pr_psargs;
|
|
|
|
|
if (args[0] == '-') ++args;
|
|
|
|
|
const char* end = strchr(args, ' ');
|
|
|
|
|
ffStrbufSetNS(exe, end ? (uint32_t) (end - args) : (uint32_t) strlen(args), args);
|
2024-06-17 14:44:34 +08:00
|
|
|
}
|
|
|
|
|
|
2024-06-17 15:18:02 +08:00
|
|
|
if (exePath)
|
2024-06-17 14:44:34 +08:00
|
|
|
{
|
2024-06-17 15:18:02 +08:00
|
|
|
snprintf(filePath, sizeof(filePath), "/proc/%d/path/a.out", (int) pid);
|
2024-10-14 11:35:29 +08:00
|
|
|
char buf[PATH_MAX];
|
|
|
|
|
ssize_t length = readlink(filePath, buf, PATH_MAX - 1);
|
2024-06-17 15:18:02 +08:00
|
|
|
if (length > 0) // doesn't contain trailing NUL
|
|
|
|
|
{
|
2024-10-14 11:35:29 +08:00
|
|
|
buf[length] = '\0';
|
2024-11-13 10:46:30 +08:00
|
|
|
ffStrbufEnsureFixedLengthFree(exePath, (uint32_t)length);
|
2024-10-14 11:35:29 +08:00
|
|
|
ffStrbufAppendNS(exePath, (uint32_t)length, buf);
|
2024-06-17 15:18:02 +08:00
|
|
|
}
|
2024-06-17 14:44:34 +08:00
|
|
|
}
|
|
|
|
|
|
2024-10-04 15:58:17 +08:00
|
|
|
#elif defined(__OpenBSD__)
|
|
|
|
|
|
|
|
|
|
kvm_t* kd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, NULL);
|
|
|
|
|
int count = 0;
|
|
|
|
|
const struct kinfo_proc* proc = kvm_getprocs(kd, KERN_PROC_PID, pid, sizeof(struct kinfo_proc), &count);
|
|
|
|
|
if (proc)
|
|
|
|
|
{
|
|
|
|
|
char** argv = kvm_getargv(kd, proc, 0);
|
2025-02-05 16:10:42 +08:00
|
|
|
if (argv)
|
|
|
|
|
{
|
|
|
|
|
const char* arg0 = argv[0];
|
|
|
|
|
if (arg0[0] == '-') arg0++;
|
|
|
|
|
ffStrbufSetS(exe, arg0);
|
|
|
|
|
}
|
2024-10-04 15:58:17 +08:00
|
|
|
}
|
|
|
|
|
kvm_close(kd);
|
|
|
|
|
|
2025-02-13 22:39:45 +00:00
|
|
|
#elif defined(__HAIKU__)
|
|
|
|
|
|
2025-02-18 19:49:40 +08:00
|
|
|
image_info info;
|
|
|
|
|
int32 cookie = 0;
|
2025-02-17 21:22:12 +08:00
|
|
|
|
2025-02-18 19:49:40 +08:00
|
|
|
while (get_next_image_info(pid, &cookie, &info) == B_OK)
|
2025-02-13 22:39:45 +00:00
|
|
|
{
|
2025-02-18 19:49:40 +08:00
|
|
|
if (info.type != B_APP_IMAGE) continue;
|
|
|
|
|
ffStrbufSetS(exe, info.name);
|
2025-02-13 22:39:45 +00:00
|
|
|
|
2025-02-18 19:49:40 +08:00
|
|
|
if (exePath)
|
|
|
|
|
ffStrbufSet(exePath, exe);
|
|
|
|
|
break;
|
2025-02-13 22:39:45 +00:00
|
|
|
}
|
|
|
|
|
|
2024-05-28 22:34:41 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if(exe->length == 0)
|
|
|
|
|
ffStrbufSet(exe, processName);
|
|
|
|
|
|
|
|
|
|
assert(exe->length > 0);
|
|
|
|
|
uint32_t lastSlashIndex = ffStrbufLastIndexC(exe, '/');
|
|
|
|
|
if(lastSlashIndex < exe->length)
|
|
|
|
|
*exeName = exe->chars + lastSlashIndex + 1;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-28 23:46:13 +08:00
|
|
|
const char* ffProcessGetBasicInfoLinux(pid_t pid, FFstrbuf* name, pid_t* ppid, int32_t* tty)
|
2024-05-28 22:34:41 +08:00
|
|
|
{
|
|
|
|
|
if (pid <= 0)
|
|
|
|
|
return "Invalid pid";
|
|
|
|
|
|
|
|
|
|
#ifdef __linux__
|
|
|
|
|
|
2024-05-28 23:46:13 +08:00
|
|
|
char procFilePath[64];
|
|
|
|
|
if (ppid)
|
|
|
|
|
{
|
|
|
|
|
snprintf(procFilePath, sizeof(procFilePath), "/proc/%d/stat", (int)pid);
|
|
|
|
|
char buf[PROC_FILE_BUFFSIZ];
|
|
|
|
|
ssize_t nRead = ffReadFileData(procFilePath, sizeof(buf) - 1, buf);
|
2024-05-29 16:24:18 +08:00
|
|
|
if(nRead <= 8)
|
2024-05-28 23:46:13 +08:00
|
|
|
return "ffReadFileData(/proc/pid/stat, PROC_FILE_BUFFSIZ-1, buf) failed";
|
|
|
|
|
buf[nRead] = '\0';
|
|
|
|
|
|
|
|
|
|
*ppid = 0;
|
|
|
|
|
static_assert(sizeof(*ppid) == sizeof(int), "");
|
|
|
|
|
|
|
|
|
|
ffStrbufEnsureFixedLengthFree(name, 255);
|
|
|
|
|
int tty_;
|
|
|
|
|
if(
|
|
|
|
|
sscanf(buf, "%*s (%255[^)]) %*c %d %*d %*d %d", name->chars, ppid, &tty_) < 2 || //stat (comm) state ppid pgrp session tty
|
|
|
|
|
name->chars[0] == '\0'
|
|
|
|
|
)
|
|
|
|
|
return "sscanf(stat) failed";
|
|
|
|
|
|
|
|
|
|
ffStrbufRecalculateLength(name);
|
|
|
|
|
if (tty)
|
|
|
|
|
*tty = tty_ & 0xFF;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
snprintf(procFilePath, sizeof(procFilePath), "/proc/%d/comm", (int)pid);
|
|
|
|
|
ssize_t nRead = ffReadFileBuffer(procFilePath, name);
|
2024-05-29 16:24:18 +08:00
|
|
|
if(nRead <= 0)
|
2024-05-28 23:46:13 +08:00
|
|
|
return "ffReadFileBuffer(/proc/pid/comm, name) failed";
|
|
|
|
|
ffStrbufTrimRightSpace(name);
|
|
|
|
|
}
|
2024-05-28 22:34:41 +08:00
|
|
|
|
|
|
|
|
#elif defined(__APPLE__)
|
|
|
|
|
|
|
|
|
|
struct kinfo_proc proc;
|
|
|
|
|
size_t size = sizeof(proc);
|
|
|
|
|
if(sysctl(
|
|
|
|
|
(int[]){CTL_KERN, KERN_PROC, KERN_PROC_PID, pid}, 4,
|
|
|
|
|
&proc, &size,
|
|
|
|
|
NULL, 0
|
|
|
|
|
))
|
|
|
|
|
return "sysctl(KERN_PROC_PID) failed";
|
|
|
|
|
|
2024-05-28 23:46:13 +08:00
|
|
|
ffStrbufSetS(name, proc.kp_proc.p_comm); //trancated to 16 chars
|
|
|
|
|
if (ppid)
|
|
|
|
|
*ppid = (pid_t)proc.kp_eproc.e_ppid;
|
2024-05-28 22:34:41 +08:00
|
|
|
if (tty)
|
|
|
|
|
{
|
|
|
|
|
*tty = ((proc.kp_eproc.e_tdev >> 24) & 0xFF) == 0x10
|
|
|
|
|
? proc.kp_eproc.e_tdev & 0xFFFFFF
|
|
|
|
|
: -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#elif defined(__FreeBSD__)
|
|
|
|
|
|
2024-11-03 08:35:11 +08:00
|
|
|
#ifdef __DragonFly__
|
|
|
|
|
#define ki_comm kp_comm
|
|
|
|
|
#define ki_ppid kp_ppid
|
|
|
|
|
#define ki_tdev kp_tdev
|
|
|
|
|
#define ki_flag kp_flags
|
|
|
|
|
#endif
|
|
|
|
|
|
2024-05-28 22:34:41 +08:00
|
|
|
struct kinfo_proc proc;
|
|
|
|
|
size_t size = sizeof(proc);
|
|
|
|
|
if(sysctl(
|
|
|
|
|
(int[]){CTL_KERN, KERN_PROC, KERN_PROC_PID, pid}, 4,
|
|
|
|
|
&proc, &size,
|
|
|
|
|
NULL, 0
|
|
|
|
|
))
|
|
|
|
|
return "sysctl(KERN_PROC_PID) failed";
|
|
|
|
|
|
2024-05-28 23:46:13 +08:00
|
|
|
ffStrbufSetS(name, proc.ki_comm);
|
|
|
|
|
if (ppid)
|
|
|
|
|
*ppid = (pid_t)proc.ki_ppid;
|
2024-05-28 22:34:41 +08:00
|
|
|
if (tty)
|
|
|
|
|
{
|
|
|
|
|
if (proc.ki_tdev != NODEV && proc.ki_flag & P_CONTROLT)
|
|
|
|
|
{
|
|
|
|
|
const char* ttyName = devname(proc.ki_tdev, S_IFCHR);
|
|
|
|
|
if (ffStrStartsWith(ttyName, "pts/"))
|
|
|
|
|
*tty = (int32_t) strtol(ttyName + strlen("pts/"), NULL, 10);
|
|
|
|
|
else
|
2024-10-27 11:43:36 +08:00
|
|
|
*tty = -1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
*tty = -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#elif defined(__NetBSD__)
|
|
|
|
|
|
|
|
|
|
struct kinfo_proc2 proc;
|
|
|
|
|
size_t size = sizeof(proc);
|
|
|
|
|
if(sysctl(
|
2024-10-31 00:25:40 +08:00
|
|
|
(int[]){CTL_KERN, KERN_PROC2, KERN_PROC_PID, pid, sizeof(proc), 1}, 6,
|
2024-10-27 11:43:36 +08:00
|
|
|
&proc, &size,
|
|
|
|
|
NULL, 0
|
2024-10-31 00:25:40 +08:00
|
|
|
) != 0)
|
2024-10-27 11:43:36 +08:00
|
|
|
return "sysctl(KERN_PROC_PID) failed";
|
|
|
|
|
|
|
|
|
|
ffStrbufSetS(name, proc.p_comm);
|
|
|
|
|
if (ppid)
|
|
|
|
|
*ppid = (pid_t)proc.p_ppid;
|
|
|
|
|
if (tty)
|
|
|
|
|
{
|
|
|
|
|
if (proc.p_flag & P_CONTROLT)
|
|
|
|
|
{
|
|
|
|
|
const char* ttyName = devname(proc.p_tdev, S_IFCHR);
|
|
|
|
|
if (ffStrStartsWith(ttyName, "pts/"))
|
|
|
|
|
*tty = (int32_t) strtol(ttyName + strlen("pts/"), NULL, 10);
|
|
|
|
|
else
|
2024-05-28 22:34:41 +08:00
|
|
|
*tty = -1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
*tty = -1;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-17 13:35:26 +08:00
|
|
|
#elif defined(__sun)
|
2024-06-17 14:44:34 +08:00
|
|
|
char path[128];
|
|
|
|
|
snprintf(path, sizeof(path), "/proc/%d/psinfo", (int) pid);
|
|
|
|
|
psinfo_t proc;
|
|
|
|
|
if (ffReadFileData(path, sizeof(proc), &proc) != sizeof(proc))
|
|
|
|
|
return "ffReadFileData(psinfo) failed";
|
2024-06-17 13:35:26 +08:00
|
|
|
|
2024-06-17 14:44:34 +08:00
|
|
|
ffStrbufSetS(name, proc.pr_fname);
|
2024-06-17 13:35:26 +08:00
|
|
|
if (ppid)
|
2024-06-17 14:44:34 +08:00
|
|
|
*ppid = proc.pr_ppid;
|
2024-06-17 13:35:26 +08:00
|
|
|
if (tty)
|
2024-06-17 14:44:34 +08:00
|
|
|
*tty = (int) proc.pr_ttydev;
|
2024-06-17 13:35:26 +08:00
|
|
|
|
2024-10-04 15:58:17 +08:00
|
|
|
#elif defined(__OpenBSD__)
|
|
|
|
|
|
|
|
|
|
kvm_t* kd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, NULL);
|
|
|
|
|
int count = 0;
|
|
|
|
|
const struct kinfo_proc* proc = kvm_getprocs(kd, KERN_PROC_PID, pid, sizeof(struct kinfo_proc), &count);
|
|
|
|
|
if (proc)
|
|
|
|
|
{
|
|
|
|
|
ffStrbufSetS(name, proc->p_comm);
|
|
|
|
|
if (ppid)
|
|
|
|
|
*ppid = proc->p_ppid;
|
|
|
|
|
if (tty)
|
|
|
|
|
*tty = (int) proc->p_tdev;
|
|
|
|
|
}
|
|
|
|
|
kvm_close(kd);
|
|
|
|
|
if (!proc)
|
|
|
|
|
return "kvm_getprocs() failed";
|
|
|
|
|
|
2025-02-12 00:44:41 +08:00
|
|
|
#elif defined(__HAIKU__)
|
|
|
|
|
|
|
|
|
|
team_info info;
|
|
|
|
|
if (get_team_info(pid, &info) == B_OK)
|
|
|
|
|
{
|
|
|
|
|
ffStrbufSetS(name, info.name);
|
|
|
|
|
if (ppid)
|
|
|
|
|
*ppid = info.parent;
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-13 22:39:45 +00:00
|
|
|
FF_UNUSED(tty);
|
|
|
|
|
|
2024-05-28 22:34:41 +08:00
|
|
|
#else
|
|
|
|
|
|
|
|
|
|
return "Unsupported platform";
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|