From 88eec2dc00f951913a1992a064ccefc7cff95e96 Mon Sep 17 00:00:00 2001 From: Christian Goettsche Date: Wed, 21 Oct 2020 13:56:26 +0200 Subject: FreeBSD: rework tty process column --- freebsd/FreeBSDProcess.c | 16 ++++++++- freebsd/FreeBSDProcess.h | 5 +++ freebsd/FreeBSDProcessList.c | 79 +++++++++++++++++++++++++++++++++++++++++++- freebsd/FreeBSDProcessList.h | 2 ++ 4 files changed, 100 insertions(+), 2 deletions(-) (limited to 'freebsd') diff --git a/freebsd/FreeBSDProcess.c b/freebsd/FreeBSDProcess.c index ea3f693d..616a7196 100644 --- a/freebsd/FreeBSDProcess.c +++ b/freebsd/FreeBSDProcess.c @@ -17,6 +17,8 @@ in the source distribution for its full text. #include +const char* const nodevStr = "nodev"; + const ProcessClass FreeBSDProcess_class = { .super = { .extends = Class(Process), @@ -35,7 +37,7 @@ ProcessFieldData Process_fields[] = { [PPID] = { .name = "PPID", .title = " PPID ", .description = "Parent process ID", .flags = 0, }, [PGRP] = { .name = "PGRP", .title = " PGRP ", .description = "Process group ID", .flags = 0, }, [SESSION] = { .name = "SESSION", .title = " SID ", .description = "Process's session ID", .flags = 0, }, - [TTY_NR] = { .name = "TTY_NR", .title = " TTY ", .description = "Controlling terminal", .flags = 0, }, + [TTY_NR] = { .name = "TTY_NR", .title = " TTY ", .description = "Controlling terminal", .flags = PROCESS_FLAG_FREEBSD_TTY, }, [TPGID] = { .name = "TPGID", .title = " TPGID ", .description = "Process ID of the fg process group of the controlling terminal", .flags = 0, }, [MINFLT] = { .name = "MINFLT", .title = " MINFLT ", .description = "Number of minor faults which have not required loading a memory page from disk", .flags = 0, }, [MAJFLT] = { .name = "MAJFLT", .title = " MAJFLT ", .description = "Number of major faults which have required loading a memory page from disk", .flags = 0, }, @@ -99,6 +101,16 @@ void FreeBSDProcess_writeField(const Process* this, RichString* str, ProcessFiel } break; } + case TTY_NR: + if (fp->ttyPath) { + if (fp->ttyPath == nodevStr) + attr = CRT_colors[PROCESS_SHADOW]; + xSnprintf(buffer, n, "%-8s", fp->ttyPath); + } else { + attr = CRT_colors[PROCESS_SHADOW]; + xSnprintf(buffer, n, "? "); + } + break; default: Process_writeField(this, str, field); return; @@ -122,6 +134,8 @@ long FreeBSDProcess_compare(const void* v1, const void* v2) { return (p1->jid - p2->jid); case JAIL: return strcmp(p1->jname ? p1->jname : "", p2->jname ? p2->jname : ""); + case TTY_NR: + return strcmp(p1->ttyPath ? p1->ttyPath : "", p2->ttyPath ? p2->ttyPath : ""); default: return Process_compare(v1, v2); } diff --git a/freebsd/FreeBSDProcess.h b/freebsd/FreeBSDProcess.h index aa769d65..d6873d09 100644 --- a/freebsd/FreeBSDProcess.h +++ b/freebsd/FreeBSDProcess.h @@ -15,6 +15,10 @@ in the source distribution for its full text. #include "Settings.h" +#define PROCESS_FLAG_FREEBSD_TTY 0x0100 + +extern const char* const nodevStr; + typedef enum FreeBSDProcessFields_ { // Add platform-specific fields here, with ids >= 100 JID = 100, @@ -27,6 +31,7 @@ typedef struct FreeBSDProcess_ { int kernel; int jid; char* jname; + const char* ttyPath; } FreeBSDProcess; #define Process_isKernelThread(_process) (_process->kernel == 1) diff --git a/freebsd/FreeBSDProcessList.c b/freebsd/FreeBSDProcessList.c index ef06f9b4..69b4aba2 100644 --- a/freebsd/FreeBSDProcessList.c +++ b/freebsd/FreeBSDProcessList.c @@ -8,6 +8,7 @@ in the source distribution for its full text. #include "FreeBSDProcessList.h" #include +#include #include #include #include @@ -16,8 +17,10 @@ in the source distribution for its full text. #include #include #include +#include #include #include +#include #include "CRT.h" #include "FreeBSDProcess.h" @@ -138,11 +141,16 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, ui errx(1, "kvm_open: %s", errbuf); } + fpl->ttys = Hashtable_new(20, true); + return pl; } void ProcessList_delete(ProcessList* this) { const FreeBSDProcessList* fpl = (FreeBSDProcessList*) this; + + Hashtable_delete(fpl->ttys); + if (fpl->kd) kvm_close(fpl->kd); free(fpl->cp_time_o); @@ -311,6 +319,70 @@ static inline void FreeBSDProcessList_scanMemoryInfo(ProcessList* pl) { pl->sharedMem = 0; // currently unused } +static void FreeBSDProcessList_scanTTYs(ProcessList* pl) { + FreeBSDProcessList* fpl = (FreeBSDProcessList*) pl; + + // scan /dev/tty* + { + DIR* dirPtr = opendir("/dev"); + if (!dirPtr) + return; + + int dirFd = dirfd(dirPtr); + if (dirFd < 0) + goto err1; + + const struct dirent* entry; + while ((entry = readdir(dirPtr))) { + if (!String_startsWith(entry->d_name, "tty")) + continue; + + struct stat info; + if (fstatat(dirFd, entry->d_name, &info, 0) < 0) + continue; + + if (!S_ISCHR(info.st_mode)) + continue; + + if (!Hashtable_get(fpl->ttys, info.st_rdev)) + Hashtable_put(fpl->ttys, info.st_rdev, xStrdup(entry->d_name)); + } + +err1: + closedir(dirPtr); + } + + // scan /dev/pts/* + { + DIR* dirPtr = opendir("/dev/pts"); + if (!dirPtr) + return; + + int dirFd = dirfd(dirPtr); + if (dirFd < 0) + goto err2; + + const struct dirent* entry; + while ((entry = readdir(dirPtr))) { + struct stat info; + if (fstatat(dirFd, entry->d_name, &info, 0) < 0) + continue; + + if (!S_ISCHR(info.st_mode)) + continue; + + if (!Hashtable_get(fpl->ttys, info.st_rdev)) { + char* path; + xAsprintf(&path, "pts/%s", entry->d_name); + Hashtable_put(fpl->ttys, info.st_rdev, path); + } + } + +err2: + closedir(dirPtr); + } +} + char* FreeBSDProcessList_readProcessName(kvm_t* kd, struct kinfo_proc* kproc, int* basenameEnd) { char** argv = kvm_getargv(kd, kproc, 0); if (!argv) { @@ -394,6 +466,9 @@ void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) { if (pauseProcessUpdate) return; + if (settings->flags & PROCESS_FLAG_FREEBSD_TTY) + FreeBSDProcessList_scanTTYs(super); + int count = 0; struct kinfo_proc* kprocs = kvm_getprocs(fpl->kd, KERN_PROC_PROC, 0, &count); @@ -417,7 +492,6 @@ void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) { proc->tpgid = kproc->ki_tpgid; proc->tgid = kproc->ki_pid; proc->session = kproc->ki_sid; - proc->tty_nr = kproc->ki_tdev; proc->pgrp = kproc->ki_pgid; proc->st_uid = kproc->ki_uid; proc->starttime_ctime = kproc->ki_start.tv_sec; @@ -490,6 +564,9 @@ void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) { default: proc->state = '?'; } + if (settings->flags & PROCESS_FLAG_FREEBSD_TTY) + fp->ttyPath = (kproc->ki_tdev == NODEV) ? nodevStr : Hashtable_get(fpl->ttys, kproc->ki_tdev); + if (Process_isKernelThread(fp)) { super->kernelThreads++; } diff --git a/freebsd/FreeBSDProcessList.h b/freebsd/FreeBSDProcessList.h index 5fa49924..81980415 100644 --- a/freebsd/FreeBSDProcessList.h +++ b/freebsd/FreeBSDProcessList.h @@ -46,6 +46,8 @@ typedef struct FreeBSDProcessList_ { CPUData* cpus; + Hashtable* ttys; + unsigned long *cp_time_o; unsigned long *cp_time_n; -- cgit v1.2.3