Shell: detect associated TTY

This commit is contained in:
李通洲
2024-01-19 15:42:48 +08:00
committed by Carter Li
parent 9610a1ab23
commit 87813b3306
4 changed files with 40 additions and 8 deletions
+2 -1
View File
@@ -5,13 +5,14 @@
typedef struct FFShellResult
{
FFstrbuf processName;
FFstrbuf exe; //Actually arg0
FFstrbuf exe; //Actually arg0 in *nix
const char* exeName; //pointer to a char in exe
FFstrbuf exePath; //Full real path to executable file
FFstrbuf prettyName;
FFstrbuf version;
uint32_t pid;
uint32_t ppid;
int32_t tty;
} FFShellResult;
typedef struct FFTerminalResult
@@ -121,7 +121,7 @@ static void getProcessInformation(pid_t pid, FFstrbuf* processName, FFstrbuf* ex
setExeName(exe, exeName);
}
static const char* getProcessNameAndPpid(pid_t pid, char* name, pid_t* ppid)
static const char* getProcessNameAndPpid(pid_t pid, char* name, pid_t* ppid, int32_t* tty)
{
#ifdef __linux__
@@ -135,13 +135,18 @@ static const char* getProcessNameAndPpid(pid_t pid, char* name, pid_t* ppid)
*ppid = 0;
static_assert(sizeof(*ppid) == sizeof(int), "");
int tty_;
if(
sscanf(buf, "%*s (%255[^)]) %*c %d", name, ppid) != 2 || //stat (comm) state ppid
sscanf(buf, "%*s (%255[^)]) %*c %d %*d %*d %d", name, ppid, &tty_) < 2 || //stat (comm) state ppid pgrp session tty
!ffStrSet(name) ||
*ppid == 0
)
return "sscanf(stat) failed";
if (tty && (tty_ >> 8) == 0x88)
*tty = tty_ & 0xFF;
#elif defined(__APPLE__)
struct kinfo_proc proc;
@@ -154,7 +159,13 @@ static const char* getProcessNameAndPpid(pid_t pid, char* name, pid_t* ppid)
return "sysctl(KERN_PROC_PID) failed";
*ppid = (pid_t)proc.kp_eproc.e_ppid;
strncpy(name, proc.kp_proc.p_comm, MAXCOMLEN); //trancated to 16 chars
strcpy(name, proc.kp_proc.p_comm); //trancated to 16 chars
if (tty)
{
*tty = ((proc.kp_eproc.e_tdev >> 24) & 0xFF) == 0x10
? proc.kp_eproc.e_tdev & 0xFFFFFF
: -1;
}
#elif defined(__FreeBSD__)
@@ -168,7 +179,20 @@ static const char* getProcessNameAndPpid(pid_t pid, char* name, pid_t* ppid)
return "sysctl(KERN_PROC_PID) failed";
*ppid = (pid_t)proc.ki_ppid;
strncpy(name, proc.ki_comm, COMMLEN);
strcpy(name, proc.ki_comm);
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
*tty = -1;
}
else
*tty = -1;
}
#else
@@ -186,7 +210,7 @@ static pid_t getShellInfo(FFShellResult* result, pid_t pid)
pid_t ppid = 0;
while (getProcessNameAndPpid(pid, name, &ppid) == NULL)
while (getProcessNameAndPpid(pid, name, &ppid, &result->tty) == NULL)
{
//Common programs that are between terminal and own process, but are not the shell
if(
@@ -227,7 +251,7 @@ static pid_t getTerminalInfo(FFTerminalResult* result, pid_t pid)
pid_t ppid = 0;
while (getProcessNameAndPpid(pid, name, &ppid) == NULL)
while (getProcessNameAndPpid(pid, name, &ppid, NULL) == NULL)
{
//Known shells
if (
@@ -259,7 +283,7 @@ static pid_t getTerminalInfo(FFTerminalResult* result, pid_t pid)
// https://github.com/fastfetch-cli/fastfetch/discussions/501
if (ffStrEndsWith(name, " (figterm)") || ffStrEndsWith(name, " (cwterm)"))
{
if (__builtin_expect(getProcessNameAndPpid(ppid, name, &ppid) != NULL, false))
if (__builtin_expect(getProcessNameAndPpid(ppid, name, &ppid, NULL) != NULL, false))
return 0;
}
#endif
@@ -465,6 +489,7 @@ const FFShellResult* ffDetectShell()
ffStrbufInit(&result.version);
result.pid = 0;
result.ppid = 0;
result.tty = -1;
pid_t ppid = getppid();
ppid = getShellInfo(&result, ppid);
@@ -379,6 +379,7 @@ const FFShellResult* ffDetectShell(void)
ffStrbufInit(&result.version);
result.pid = 0;
result.ppid = 0;
result.tty = -1;
uint32_t ppid;
if(!getProcessInfo(0, &ppid, NULL, NULL, NULL, NULL, NULL))
+5
View File
@@ -39,6 +39,7 @@ void ffPrintShell(FFShellOptions* options)
{FF_FORMAT_ARG_TYPE_UINT, &result->pid},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->prettyName},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->exePath},
{FF_FORMAT_ARG_TYPE_INT, &result->tty},
});
}
}
@@ -97,6 +98,10 @@ void ffGenerateShellJsonResult(FF_MAYBE_UNUSED FFShellOptions* options, yyjson_m
yyjson_mut_obj_add_strbuf(doc, obj, "processName", &result->processName);
yyjson_mut_obj_add_strbuf(doc, obj, "prettyName", &result->prettyName);
yyjson_mut_obj_add_strbuf(doc, obj, "version", &result->version);
if (result->tty >= 0)
yyjson_mut_obj_add_int(doc, obj, "tty", result->tty);
else
yyjson_mut_obj_add_null(doc, obj, "tty");
}
void ffPrintShellHelpFormat(void)