From 87813b3306f1f018f93d26c33368447939ded602 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 19 Jan 2024 15:42:48 +0800 Subject: [PATCH] Shell: detect associated TTY --- src/detection/terminalshell/terminalshell.h | 3 +- .../terminalshell/terminalshell_linux.c | 39 +++++++++++++++---- .../terminalshell/terminalshell_windows.c | 1 + src/modules/shell/shell.c | 5 +++ 4 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/detection/terminalshell/terminalshell.h b/src/detection/terminalshell/terminalshell.h index 0ba1cb227..235a29f60 100644 --- a/src/detection/terminalshell/terminalshell.h +++ b/src/detection/terminalshell/terminalshell.h @@ -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 diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c index 89afe0ebc..c83dffde4 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -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); diff --git a/src/detection/terminalshell/terminalshell_windows.c b/src/detection/terminalshell/terminalshell_windows.c index d6821ede6..67b91a677 100644 --- a/src/detection/terminalshell/terminalshell_windows.c +++ b/src/detection/terminalshell/terminalshell_windows.c @@ -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)) diff --git a/src/modules/shell/shell.c b/src/modules/shell/shell.c index a0792d5c2..c3e4fcc1a 100644 --- a/src/modules/shell/shell.c +++ b/src/modules/shell/shell.c @@ -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)