mirror of https://github.com/xzeldon/htop.git
Rework TTY column
* Rename internal identifier from TTY_NR to just TTY * Unify column header on platforms * Use devname(3) on BSD derivate to show the actual terminal, simplifies current FreeBSD implementation. * Use 'unsigned long int' as id type, to fit dev_t on Linux. Only on Solaris the terminal path is not yet resolved.
This commit is contained in:
parent
36880cd61c
commit
9a8221568a
16
Macros.h
16
Macros.h
|
@ -4,27 +4,31 @@
|
||||||
#include <assert.h> // IWYU pragma: keep
|
#include <assert.h> // IWYU pragma: keep
|
||||||
|
|
||||||
#ifndef MINIMUM
|
#ifndef MINIMUM
|
||||||
#define MINIMUM(a, b) ((a) < (b) ? (a) : (b))
|
#define MINIMUM(a, b) ((a) < (b) ? (a) : (b))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MAXIMUM
|
#ifndef MAXIMUM
|
||||||
#define MAXIMUM(a, b) ((a) > (b) ? (a) : (b))
|
#define MAXIMUM(a, b) ((a) > (b) ? (a) : (b))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CLAMP
|
#ifndef CLAMP
|
||||||
#define CLAMP(x, low, high) (assert((low) <= (high)), ((x) > (high)) ? (high) : MAXIMUM(x, low))
|
#define CLAMP(x, low, high) (assert((low) <= (high)), ((x) > (high)) ? (high) : MAXIMUM(x, low))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef ARRAYSIZE
|
#ifndef ARRAYSIZE
|
||||||
#define ARRAYSIZE(x) (sizeof(x) / sizeof((x)[0]))
|
#define ARRAYSIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef SPACESHIP_NUMBER
|
#ifndef SPACESHIP_NUMBER
|
||||||
#define SPACESHIP_NUMBER(a, b) (((a) > (b)) - ((a) < (b)))
|
#define SPACESHIP_NUMBER(a, b) (((a) > (b)) - ((a) < (b)))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef SPACESHIP_NULLSTR
|
#ifndef SPACESHIP_NULLSTR
|
||||||
#define SPACESHIP_NULLSTR(a, b) strcmp((a) ? (a) : "", (b) ? (b) : "")
|
#define SPACESHIP_NULLSTR(a, b) strcmp((a) ? (a) : "", (b) ? (b) : "")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SPACESHIP_DEFAULTSTR
|
||||||
|
#define SPACESHIP_DEFAULTSTR(a, b, s) strcmp((a) ? (a) : (s), (b) ? (b) : (s))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __GNUC__ // defined by GCC and Clang
|
#ifdef __GNUC__ // defined by GCC and Clang
|
||||||
|
|
18
Process.c
18
Process.c
|
@ -378,17 +378,15 @@ void Process_writeField(const Process* this, RichString* str, ProcessField field
|
||||||
xSnprintf(buffer, n, "%*d ", Process_pidDigits, this->tgid);
|
xSnprintf(buffer, n, "%*d ", Process_pidDigits, this->tgid);
|
||||||
break;
|
break;
|
||||||
case TPGID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, this->tpgid); break;
|
case TPGID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, this->tpgid); break;
|
||||||
case TTY_NR: {
|
case TTY:
|
||||||
unsigned int major = major(this->tty_nr);
|
if (!this->tty_name) {
|
||||||
unsigned int minor = minor(this->tty_nr);
|
|
||||||
if (major == 0 && minor == 0) {
|
|
||||||
attr = CRT_colors[PROCESS_SHADOW];
|
attr = CRT_colors[PROCESS_SHADOW];
|
||||||
xSnprintf(buffer, n, "(none) ");
|
xSnprintf(buffer, n, "(no tty) ");
|
||||||
} else {
|
} else {
|
||||||
xSnprintf(buffer, n, "%3u:%3u ", major, minor);
|
const char* name = String_startsWith(this->tty_name, "/dev/") ? (this->tty_name + strlen("/dev/")) : this->tty_name;
|
||||||
|
xSnprintf(buffer, n, "%-8s ", name);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case USER:
|
case USER:
|
||||||
if (Process_getuid != this->st_uid)
|
if (Process_getuid != this->st_uid)
|
||||||
attr = CRT_colors[PROCESS_SHADOW];
|
attr = CRT_colors[PROCESS_SHADOW];
|
||||||
|
@ -435,6 +433,7 @@ void Process_display(const Object* cast, RichString* out) {
|
||||||
void Process_done(Process* this) {
|
void Process_done(Process* this) {
|
||||||
assert (this != NULL);
|
assert (this != NULL);
|
||||||
free(this->comm);
|
free(this->comm);
|
||||||
|
free(this->tty_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* Process_getCommandStr(const Process* p) {
|
static const char* Process_getCommandStr(const Process* p) {
|
||||||
|
@ -612,8 +611,9 @@ int Process_compareByKey_Base(const Process* p1, const Process* p2, ProcessField
|
||||||
return SPACESHIP_NUMBER(p1->tgid, p2->tgid);
|
return SPACESHIP_NUMBER(p1->tgid, p2->tgid);
|
||||||
case TPGID:
|
case TPGID:
|
||||||
return SPACESHIP_NUMBER(p1->tpgid, p2->tpgid);
|
return SPACESHIP_NUMBER(p1->tpgid, p2->tpgid);
|
||||||
case TTY_NR:
|
case TTY:
|
||||||
return SPACESHIP_NUMBER(p1->tty_nr, p2->tty_nr);
|
/* Order no tty last */
|
||||||
|
return SPACESHIP_DEFAULTSTR(p1->tty_name, p2->tty_name, "\x7F");
|
||||||
case USER:
|
case USER:
|
||||||
return SPACESHIP_NULLSTR(p1->user, p2->user);
|
return SPACESHIP_NULLSTR(p1->user, p2->user);
|
||||||
default:
|
default:
|
||||||
|
|
12
Process.h
12
Process.h
|
@ -28,7 +28,7 @@ typedef enum ProcessField_ {
|
||||||
PPID = 4,
|
PPID = 4,
|
||||||
PGRP = 5,
|
PGRP = 5,
|
||||||
SESSION = 6,
|
SESSION = 6,
|
||||||
TTY_NR = 7,
|
TTY = 7,
|
||||||
TPGID = 8,
|
TPGID = 8,
|
||||||
MINFLT = 10,
|
MINFLT = 10,
|
||||||
MAJFLT = 12,
|
MAJFLT = 12,
|
||||||
|
@ -84,11 +84,11 @@ typedef struct Process_ {
|
||||||
/* Foreground group identifier of the controlling terminal */
|
/* Foreground group identifier of the controlling terminal */
|
||||||
int tpgid;
|
int tpgid;
|
||||||
|
|
||||||
/*
|
/* Controlling terminal identifier of the process */
|
||||||
* Controlling terminal of the process.
|
unsigned long int tty_nr;
|
||||||
* The minor device number is contained in the combination of bits 31 to 20 and 7 to 0; the major device number is in bits 15 to 8.
|
|
||||||
* */
|
/* Controlling terminal name of the process */
|
||||||
unsigned int tty_nr;
|
char* tty_name;
|
||||||
|
|
||||||
/* User identifier */
|
/* User identifier */
|
||||||
uid_t st_uid;
|
uid_t st_uid;
|
||||||
|
|
|
@ -26,7 +26,7 @@ const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = {
|
||||||
[PPID] = { .name = "PPID", .title = "PPID", .description = "Parent process ID", .flags = 0, .pidColumn = true, },
|
[PPID] = { .name = "PPID", .title = "PPID", .description = "Parent process ID", .flags = 0, .pidColumn = true, },
|
||||||
[PGRP] = { .name = "PGRP", .title = "PGRP", .description = "Process group ID", .flags = 0, .pidColumn = true, },
|
[PGRP] = { .name = "PGRP", .title = "PGRP", .description = "Process group ID", .flags = 0, .pidColumn = true, },
|
||||||
[SESSION] = { .name = "SESSION", .title = "SID", .description = "Process's session ID", .flags = 0, .pidColumn = true, },
|
[SESSION] = { .name = "SESSION", .title = "SID", .description = "Process's session ID", .flags = 0, .pidColumn = true, },
|
||||||
[TTY_NR] = { .name = "TTY_NR", .title = " TTY ", .description = "Controlling terminal", .flags = 0, },
|
[TTY] = { .name = "TTY", .title = "TTY ", .description = "Controlling terminal", .flags = 0, },
|
||||||
[TPGID] = { .name = "TPGID", .title = "TPGID", .description = "Process ID of the fg process group of the controlling terminal", .flags = 0, .pidColumn = true, },
|
[TPGID] = { .name = "TPGID", .title = "TPGID", .description = "Process ID of the fg process group of the controlling terminal", .flags = 0, .pidColumn = true, },
|
||||||
[MINFLT] = { .name = "MINFLT", .title = " MINFLT ", .description = "Number of minor faults which have not required loading a memory page from disk", .flags = 0, .defaultSortDesc = true, },
|
[MINFLT] = { .name = "MINFLT", .title = " MINFLT ", .description = "Number of minor faults which have not required loading a memory page from disk", .flags = 0, .defaultSortDesc = true, },
|
||||||
[MAJFLT] = { .name = "MAJFLT", .title = " MAJFLT ", .description = "Number of major faults which have required loading a memory page from disk", .flags = 0, .defaultSortDesc = true, },
|
[MAJFLT] = { .name = "MAJFLT", .title = " MAJFLT ", .description = "Number of major faults which have required loading a memory page from disk", .flags = 0, .defaultSortDesc = true, },
|
||||||
|
@ -272,11 +272,17 @@ void DarwinProcess_setFromKInfoProc(Process* proc, const struct kinfo_proc* ps,
|
||||||
proc->tpgid = ps->kp_eproc.e_tpgid;
|
proc->tpgid = ps->kp_eproc.e_tpgid;
|
||||||
proc->tgid = proc->pid;
|
proc->tgid = proc->pid;
|
||||||
proc->st_uid = ps->kp_eproc.e_ucred.cr_uid;
|
proc->st_uid = ps->kp_eproc.e_ucred.cr_uid;
|
||||||
/* e_tdev = (major << 24) | (minor & 0xffffff) */
|
|
||||||
/* e_tdev == -1 for "no device" */
|
|
||||||
proc->tty_nr = ps->kp_eproc.e_tdev & 0xff; /* TODO tty_nr is unsigned */
|
|
||||||
dp->translated = ps->kp_proc.p_flag & P_TRANSLATED;
|
dp->translated = ps->kp_proc.p_flag & P_TRANSLATED;
|
||||||
|
|
||||||
|
proc->tty_nr = ps->kp_eproc.e_tdev;
|
||||||
|
const char* name = (ps->kp_eproc.e_tdev != NODEV) ? devname(ps->kp_eproc.e_tdev, S_IFCHR) : NULL;
|
||||||
|
if (!name) {
|
||||||
|
free(proc->tty_name);
|
||||||
|
proc->tty_name = NULL;
|
||||||
|
} else {
|
||||||
|
free_and_xStrdup(&proc->tty_name, name);
|
||||||
|
}
|
||||||
|
|
||||||
proc->starttime_ctime = ep->p_starttime.tv_sec;
|
proc->starttime_ctime = ep->p_starttime.tv_sec;
|
||||||
Process_fillStarttimeBuffer(proc);
|
Process_fillStarttimeBuffer(proc);
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = {
|
||||||
[PPID] = { .name = "PPID", .title = "PPID", .description = "Parent process ID", .flags = 0, .pidColumn = true, },
|
[PPID] = { .name = "PPID", .title = "PPID", .description = "Parent process ID", .flags = 0, .pidColumn = true, },
|
||||||
[PGRP] = { .name = "PGRP", .title = "PGRP", .description = "Process group ID", .flags = 0, .pidColumn = true, },
|
[PGRP] = { .name = "PGRP", .title = "PGRP", .description = "Process group ID", .flags = 0, .pidColumn = true, },
|
||||||
[SESSION] = { .name = "SESSION", .title = "SID", .description = "Process's session ID", .flags = 0, .pidColumn = true, },
|
[SESSION] = { .name = "SESSION", .title = "SID", .description = "Process's session ID", .flags = 0, .pidColumn = true, },
|
||||||
[TTY_NR] = { .name = "TTY_NR", .title = " TTY ", .description = "Controlling terminal", .flags = 0, },
|
[TTY] = { .name = "TTY", .title = "TTY ", .description = "Controlling terminal", .flags = 0, },
|
||||||
[TPGID] = { .name = "TPGID", .title = "TPGID", .description = "Process ID of the fg process group of the controlling terminal", .flags = 0, .pidColumn = true, },
|
[TPGID] = { .name = "TPGID", .title = "TPGID", .description = "Process ID of the fg process group of the controlling terminal", .flags = 0, .pidColumn = true, },
|
||||||
[MINFLT] = { .name = "MINFLT", .title = " MINFLT ", .description = "Number of minor faults which have not required loading a memory page from disk", .flags = 0, .defaultSortDesc = true, },
|
[MINFLT] = { .name = "MINFLT", .title = " MINFLT ", .description = "Number of minor faults which have not required loading a memory page from disk", .flags = 0, .defaultSortDesc = true, },
|
||||||
[MAJFLT] = { .name = "MAJFLT", .title = " MAJFLT ", .description = "Number of major faults which have required loading a memory page from disk", .flags = 0, .defaultSortDesc = true, },
|
[MAJFLT] = { .name = "MAJFLT", .title = " MAJFLT ", .description = "Number of major faults which have required loading a memory page from disk", .flags = 0, .defaultSortDesc = true, },
|
||||||
|
|
|
@ -396,12 +396,20 @@ void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) {
|
||||||
proc->tgid = kproc->kp_pid; // thread group id
|
proc->tgid = kproc->kp_pid; // thread group id
|
||||||
proc->pgrp = kproc->kp_pgid; // process group id
|
proc->pgrp = kproc->kp_pgid; // process group id
|
||||||
proc->session = kproc->kp_sid;
|
proc->session = kproc->kp_sid;
|
||||||
proc->tty_nr = kproc->kp_tdev; // control terminal device number
|
|
||||||
proc->st_uid = kproc->kp_uid; // user ID
|
proc->st_uid = kproc->kp_uid; // user ID
|
||||||
proc->processor = kproc->kp_lwp.kl_origcpu;
|
proc->processor = kproc->kp_lwp.kl_origcpu;
|
||||||
proc->starttime_ctime = kproc->kp_start.tv_sec;
|
proc->starttime_ctime = kproc->kp_start.tv_sec;
|
||||||
proc->user = UsersTable_getRef(super->usersTable, proc->st_uid);
|
proc->user = UsersTable_getRef(super->usersTable, proc->st_uid);
|
||||||
|
|
||||||
|
proc->tty_nr = kproc->kp_tdev; // control terminal device number
|
||||||
|
const char* name = (kproc->kp_tdev != NODEV) ? devname(kproc->kp_tdev, S_IFCHR) : NULL;
|
||||||
|
if (!name) {
|
||||||
|
free(proc->tty_name);
|
||||||
|
proc->tty_name = NULL;
|
||||||
|
} else {
|
||||||
|
free_and_xStrdup(&proc->tty_name, name);
|
||||||
|
}
|
||||||
|
|
||||||
ProcessList_add(super, proc);
|
ProcessList_add(super, proc);
|
||||||
proc->comm = DragonFlyBSDProcessList_readProcessName(dfpl->kd, kproc, &proc->basenameOffset);
|
proc->comm = DragonFlyBSDProcessList_readProcessName(dfpl->kd, kproc, &proc->basenameOffset);
|
||||||
dfp->jname = DragonFlyBSDProcessList_readJailName(dfpl, kproc->kp_jailid);
|
dfp->jname = DragonFlyBSDProcessList_readJailName(dfpl, kproc->kp_jailid);
|
||||||
|
|
|
@ -26,7 +26,7 @@ const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = {
|
||||||
[PPID] = { .name = "PPID", .title = "PPID", .description = "Parent process ID", .flags = 0, .pidColumn = true, },
|
[PPID] = { .name = "PPID", .title = "PPID", .description = "Parent process ID", .flags = 0, .pidColumn = true, },
|
||||||
[PGRP] = { .name = "PGRP", .title = "PGRP", .description = "Process group ID", .flags = 0, .pidColumn = true, },
|
[PGRP] = { .name = "PGRP", .title = "PGRP", .description = "Process group ID", .flags = 0, .pidColumn = true, },
|
||||||
[SESSION] = { .name = "SESSION", .title = "SID", .description = "Process's session ID", .flags = 0, .pidColumn = true, },
|
[SESSION] = { .name = "SESSION", .title = "SID", .description = "Process's session ID", .flags = 0, .pidColumn = true, },
|
||||||
[TTY_NR] = { .name = "TTY_NR", .title = " TTY ", .description = "Controlling terminal", .flags = PROCESS_FLAG_FREEBSD_TTY, },
|
[TTY] = { .name = "TTY", .title = "TTY ", .description = "Controlling terminal", .flags = 0, },
|
||||||
[TPGID] = { .name = "TPGID", .title = "TPGID", .description = "Process ID of the fg process group of the controlling terminal", .flags = 0, .pidColumn = true, },
|
[TPGID] = { .name = "TPGID", .title = "TPGID", .description = "Process ID of the fg process group of the controlling terminal", .flags = 0, .pidColumn = true, },
|
||||||
[MAJFLT] = { .name = "MAJFLT", .title = " MAJFLT ", .description = "Number of copy-on-write faults", .flags = 0, .defaultSortDesc = true, },
|
[MAJFLT] = { .name = "MAJFLT", .title = " MAJFLT ", .description = "Number of copy-on-write faults", .flags = 0, .defaultSortDesc = true, },
|
||||||
[PRIORITY] = { .name = "PRIORITY", .title = "PRI ", .description = "Kernel's internal priority for the process", .flags = 0, },
|
[PRIORITY] = { .name = "PRIORITY", .title = "PRI ", .description = "Kernel's internal priority for the process", .flags = 0, },
|
||||||
|
@ -74,16 +74,6 @@ static void FreeBSDProcess_writeField(const Process* this, RichString* str, Proc
|
||||||
case JAIL:
|
case JAIL:
|
||||||
Process_printLeftAlignedField(str, attr, fp->jname ? fp->jname : "N/A", 11);
|
Process_printLeftAlignedField(str, attr, fp->jname ? fp->jname : "N/A", 11);
|
||||||
return;
|
return;
|
||||||
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:
|
default:
|
||||||
Process_writeField(this, str, field);
|
Process_writeField(this, str, field);
|
||||||
return;
|
return;
|
||||||
|
@ -101,8 +91,6 @@ static int FreeBSDProcess_compareByKey(const Process* v1, const Process* v2, Pro
|
||||||
return SPACESHIP_NUMBER(p1->jid, p2->jid);
|
return SPACESHIP_NUMBER(p1->jid, p2->jid);
|
||||||
case JAIL:
|
case JAIL:
|
||||||
return SPACESHIP_NULLSTR(p1->jname, p2->jname);
|
return SPACESHIP_NULLSTR(p1->jname, p2->jname);
|
||||||
case TTY_NR:
|
|
||||||
return SPACESHIP_NULLSTR(p1->ttyPath, p2->ttyPath);
|
|
||||||
default:
|
default:
|
||||||
return Process_compareByKey_Base(v1, v2, key);
|
return Process_compareByKey_Base(v1, v2, key);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,16 +14,11 @@ in the source distribution for its full text.
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
|
|
||||||
|
|
||||||
#define PROCESS_FLAG_FREEBSD_TTY 0x0100
|
|
||||||
|
|
||||||
extern const char* const nodevStr;
|
|
||||||
|
|
||||||
typedef struct FreeBSDProcess_ {
|
typedef struct FreeBSDProcess_ {
|
||||||
Process super;
|
Process super;
|
||||||
bool isKernelThread;
|
bool isKernelThread;
|
||||||
int jid;
|
int jid;
|
||||||
char* jname;
|
char* jname;
|
||||||
const char* ttyPath;
|
|
||||||
} FreeBSDProcess;
|
} FreeBSDProcess;
|
||||||
|
|
||||||
static inline bool Process_isKernelThread(const Process* this) {
|
static inline bool Process_isKernelThread(const Process* this) {
|
||||||
|
|
|
@ -10,7 +10,6 @@ in the source distribution for its full text.
|
||||||
#include "FreeBSDProcessList.h"
|
#include "FreeBSDProcessList.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <dirent.h>
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -22,7 +21,6 @@ in the source distribution for its full text.
|
||||||
#include <sys/priority.h>
|
#include <sys/priority.h>
|
||||||
#include <sys/proc.h>
|
#include <sys/proc.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
@ -148,16 +146,12 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, ui
|
||||||
CRT_fatalError("kvm_openfiles() failed");
|
CRT_fatalError("kvm_openfiles() failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
fpl->ttys = Hashtable_new(20, true);
|
|
||||||
|
|
||||||
return pl;
|
return pl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessList_delete(ProcessList* this) {
|
void ProcessList_delete(ProcessList* this) {
|
||||||
const FreeBSDProcessList* fpl = (FreeBSDProcessList*) this;
|
const FreeBSDProcessList* fpl = (FreeBSDProcessList*) this;
|
||||||
|
|
||||||
Hashtable_delete(fpl->ttys);
|
|
||||||
|
|
||||||
if (fpl->kd) {
|
if (fpl->kd) {
|
||||||
kvm_close(fpl->kd);
|
kvm_close(fpl->kd);
|
||||||
}
|
}
|
||||||
|
@ -383,70 +377,6 @@ static inline void FreeBSDProcessList_scanMemoryInfo(ProcessList* pl) {
|
||||||
pl->usedSwap *= pageSizeKb;
|
pl->usedSwap *= pageSizeKb;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 (Compat_fstatat(dirFd, "/dev", 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 (Compat_fstatat(dirFd, "/dev/pts", 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static char* FreeBSDProcessList_readProcessName(kvm_t* kd, const struct kinfo_proc* kproc, int* basenameEnd) {
|
static char* FreeBSDProcessList_readProcessName(kvm_t* kd, const struct kinfo_proc* kproc, int* basenameEnd) {
|
||||||
char** argv = kvm_getargv(kd, kproc, 0);
|
char** argv = kvm_getargv(kd, kproc, 0);
|
||||||
if (!argv) {
|
if (!argv) {
|
||||||
|
@ -512,10 +442,6 @@ void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings->flags & PROCESS_FLAG_FREEBSD_TTY) {
|
|
||||||
FreeBSDProcessList_scanTTYs(super);
|
|
||||||
}
|
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
const struct kinfo_proc* kprocs = kvm_getprocs(fpl->kd, KERN_PROC_PROC, 0, &count);
|
const struct kinfo_proc* kprocs = kvm_getprocs(fpl->kd, KERN_PROC_PROC, 0, &count);
|
||||||
|
|
||||||
|
@ -543,6 +469,15 @@ void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) {
|
||||||
ProcessList_add(super, proc);
|
ProcessList_add(super, proc);
|
||||||
proc->comm = FreeBSDProcessList_readProcessName(fpl->kd, kproc, &proc->basenameOffset);
|
proc->comm = FreeBSDProcessList_readProcessName(fpl->kd, kproc, &proc->basenameOffset);
|
||||||
fp->jname = FreeBSDProcessList_readJailName(kproc);
|
fp->jname = FreeBSDProcessList_readJailName(kproc);
|
||||||
|
|
||||||
|
proc->tty_nr = kproc->ki_tdev;
|
||||||
|
const char* name = (kproc->ki_tdev != NODEV) ? devname(kproc->ki_tdev, S_IFCHR) : NULL;
|
||||||
|
if (!name) {
|
||||||
|
free(proc->tty_name);
|
||||||
|
proc->tty_name = NULL;
|
||||||
|
} else {
|
||||||
|
free_and_xStrdup(&proc->tty_name, name);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (fp->jid != kproc->ki_jid) {
|
if (fp->jid != kproc->ki_jid) {
|
||||||
// process can enter jail anytime
|
// process can enter jail anytime
|
||||||
|
@ -603,10 +538,6 @@ void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) {
|
||||||
default: proc->state = '?';
|
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(proc))
|
if (Process_isKernelThread(proc))
|
||||||
super->kernelThreads++;
|
super->kernelThreads++;
|
||||||
|
|
||||||
|
|
|
@ -39,8 +39,6 @@ typedef struct FreeBSDProcessList_ {
|
||||||
|
|
||||||
CPUData* cpus;
|
CPUData* cpus;
|
||||||
|
|
||||||
Hashtable* ttys;
|
|
||||||
|
|
||||||
unsigned long* cp_time_o;
|
unsigned long* cp_time_o;
|
||||||
unsigned long* cp_time_n;
|
unsigned long* cp_time_n;
|
||||||
|
|
||||||
|
|
|
@ -288,7 +288,7 @@ The process's group ID.
|
||||||
.B SESSION (SID)
|
.B SESSION (SID)
|
||||||
The process's session ID.
|
The process's session ID.
|
||||||
.TP
|
.TP
|
||||||
.B TTY_NR (TTY)
|
.B TTY
|
||||||
The controlling terminal of the process.
|
The controlling terminal of the process.
|
||||||
.TP
|
.TP
|
||||||
.B TPGID
|
.B TPGID
|
||||||
|
|
|
@ -38,7 +38,7 @@ const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = {
|
||||||
[PPID] = { .name = "PPID", .title = "PPID", .description = "Parent process ID", .flags = 0, .pidColumn = true, },
|
[PPID] = { .name = "PPID", .title = "PPID", .description = "Parent process ID", .flags = 0, .pidColumn = true, },
|
||||||
[PGRP] = { .name = "PGRP", .title = "PGRP", .description = "Process group ID", .flags = 0, .pidColumn = true, },
|
[PGRP] = { .name = "PGRP", .title = "PGRP", .description = "Process group ID", .flags = 0, .pidColumn = true, },
|
||||||
[SESSION] = { .name = "SESSION", .title = "SID", .description = "Process's session ID", .flags = 0, .pidColumn = true, },
|
[SESSION] = { .name = "SESSION", .title = "SID", .description = "Process's session ID", .flags = 0, .pidColumn = true, },
|
||||||
[TTY_NR] = { .name = "TTY_NR", .title = "TTY ", .description = "Controlling terminal", .flags = 0, },
|
[TTY] = { .name = "TTY", .title = "TTY ", .description = "Controlling terminal", .flags = 0, },
|
||||||
[TPGID] = { .name = "TPGID", .title = "TPGID", .description = "Process ID of the fg process group of the controlling terminal", .flags = 0, .pidColumn = true, },
|
[TPGID] = { .name = "TPGID", .title = "TPGID", .description = "Process ID of the fg process group of the controlling terminal", .flags = 0, .pidColumn = true, },
|
||||||
[MINFLT] = { .name = "MINFLT", .title = " MINFLT ", .description = "Number of minor faults which have not required loading a memory page from disk", .flags = 0, .defaultSortDesc = true, },
|
[MINFLT] = { .name = "MINFLT", .title = " MINFLT ", .description = "Number of minor faults which have not required loading a memory page from disk", .flags = 0, .defaultSortDesc = true, },
|
||||||
[CMINFLT] = { .name = "CMINFLT", .title = " CMINFLT ", .description = "Children processes' minor faults", .flags = 0, .defaultSortDesc = true, },
|
[CMINFLT] = { .name = "CMINFLT", .title = " CMINFLT ", .description = "Children processes' minor faults", .flags = 0, .defaultSortDesc = true, },
|
||||||
|
@ -129,7 +129,6 @@ void Process_delete(Object* cast) {
|
||||||
#endif
|
#endif
|
||||||
free(this->cwd);
|
free(this->cwd);
|
||||||
free(this->secattr);
|
free(this->secattr);
|
||||||
free(this->ttyDevice);
|
|
||||||
free(this->procExe);
|
free(this->procExe);
|
||||||
free(this->procComm);
|
free(this->procComm);
|
||||||
free(this->mergedCommand.str);
|
free(this->mergedCommand.str);
|
||||||
|
@ -610,14 +609,6 @@ static void LinuxProcess_writeField(const Process* this, RichString* str, Proces
|
||||||
int attr = CRT_colors[DEFAULT_COLOR];
|
int attr = CRT_colors[DEFAULT_COLOR];
|
||||||
size_t n = sizeof(buffer) - 1;
|
size_t n = sizeof(buffer) - 1;
|
||||||
switch (field) {
|
switch (field) {
|
||||||
case TTY_NR:
|
|
||||||
if (lp->ttyDevice) {
|
|
||||||
xSnprintf(buffer, n, "%-8s ", lp->ttyDevice + 5 /* skip "/dev/" */);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Process_writeField(this, str, field);
|
|
||||||
return;
|
|
||||||
case CMINFLT: Process_colorNumber(str, lp->cminflt, coloring); return;
|
case CMINFLT: Process_colorNumber(str, lp->cminflt, coloring); return;
|
||||||
case CMAJFLT: Process_colorNumber(str, lp->cmajflt, coloring); return;
|
case CMAJFLT: Process_colorNumber(str, lp->cmajflt, coloring); return;
|
||||||
case M_DRS: Process_humanNumber(str, lp->m_drs * pageSizeKB, coloring); return;
|
case M_DRS: Process_humanNumber(str, lp->m_drs * pageSizeKB, coloring); return;
|
||||||
|
|
|
@ -117,7 +117,6 @@ typedef struct LinuxProcess_ {
|
||||||
#endif
|
#endif
|
||||||
char* cgroup;
|
char* cgroup;
|
||||||
unsigned int oom;
|
unsigned int oom;
|
||||||
char* ttyDevice;
|
|
||||||
#ifdef HAVE_DELAYACCT
|
#ifdef HAVE_DELAYACCT
|
||||||
unsigned long long int delay_read_time;
|
unsigned long long int delay_read_time;
|
||||||
unsigned long long cpu_delay_total;
|
unsigned long long cpu_delay_total;
|
||||||
|
|
|
@ -1196,7 +1196,7 @@ static bool LinuxProcessList_readCmdlineFile(Process* process, openat_arg_t proc
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char* LinuxProcessList_updateTtyDevice(TtyDriver* ttyDrivers, unsigned int tty_nr) {
|
static char* LinuxProcessList_updateTtyDevice(TtyDriver* ttyDrivers, unsigned long int tty_nr) {
|
||||||
unsigned int maj = major(tty_nr);
|
unsigned int maj = major(tty_nr);
|
||||||
unsigned int min = minor(tty_nr);
|
unsigned int min = minor(tty_nr);
|
||||||
|
|
||||||
|
@ -1363,13 +1363,13 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_
|
||||||
|
|
||||||
char command[MAX_NAME + 1];
|
char command[MAX_NAME + 1];
|
||||||
unsigned long long int lasttimes = (lp->utime + lp->stime);
|
unsigned long long int lasttimes = (lp->utime + lp->stime);
|
||||||
unsigned int tty_nr = proc->tty_nr;
|
unsigned long int tty_nr = proc->tty_nr;
|
||||||
if (! LinuxProcessList_readStatFile(proc, procFd, command, sizeof(command)))
|
if (! LinuxProcessList_readStatFile(proc, procFd, command, sizeof(command)))
|
||||||
goto errorReadingProcess;
|
goto errorReadingProcess;
|
||||||
|
|
||||||
if (tty_nr != proc->tty_nr && this->ttyDrivers) {
|
if (tty_nr != proc->tty_nr && this->ttyDrivers) {
|
||||||
free(lp->ttyDevice);
|
free(proc->tty_name);
|
||||||
lp->ttyDevice = LinuxProcessList_updateTtyDevice(this->ttyDrivers, proc->tty_nr);
|
proc->tty_name = LinuxProcessList_updateTtyDevice(this->ttyDrivers, proc->tty_nr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings->flags & PROCESS_FLAG_LINUX_IOPRIO) {
|
if (settings->flags & PROCESS_FLAG_LINUX_IOPRIO) {
|
||||||
|
|
|
@ -63,9 +63,9 @@ const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = {
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.pidColumn = true,
|
.pidColumn = true,
|
||||||
},
|
},
|
||||||
[TTY_NR] = {
|
[TTY] = {
|
||||||
.name = "TTY_NR",
|
.name = "TTY",
|
||||||
.title = " TTY ",
|
.title = "TTY ",
|
||||||
.description = "Controlling terminal",
|
.description = "Controlling terminal",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
},
|
},
|
||||||
|
|
|
@ -225,7 +225,6 @@ static void OpenBSDProcessList_scanProcs(OpenBSDProcessList* this) {
|
||||||
proc->tpgid = kproc->p_tpgid;
|
proc->tpgid = kproc->p_tpgid;
|
||||||
proc->tgid = kproc->p_pid;
|
proc->tgid = kproc->p_pid;
|
||||||
proc->session = kproc->p_sid;
|
proc->session = kproc->p_sid;
|
||||||
proc->tty_nr = kproc->p_tdev;
|
|
||||||
proc->pgrp = kproc->p__pgid;
|
proc->pgrp = kproc->p__pgid;
|
||||||
proc->st_uid = kproc->p_uid;
|
proc->st_uid = kproc->p_uid;
|
||||||
proc->starttime_ctime = kproc->p_ustart_sec;
|
proc->starttime_ctime = kproc->p_ustart_sec;
|
||||||
|
@ -233,6 +232,15 @@ static void OpenBSDProcessList_scanProcs(OpenBSDProcessList* this) {
|
||||||
proc->user = UsersTable_getRef(this->super.usersTable, proc->st_uid);
|
proc->user = UsersTable_getRef(this->super.usersTable, proc->st_uid);
|
||||||
ProcessList_add(&this->super, proc);
|
ProcessList_add(&this->super, proc);
|
||||||
proc->comm = OpenBSDProcessList_readProcessName(this->kd, kproc, &proc->basenameOffset);
|
proc->comm = OpenBSDProcessList_readProcessName(this->kd, kproc, &proc->basenameOffset);
|
||||||
|
|
||||||
|
proc->tty_nr = kproc->p_tdev;
|
||||||
|
const char* name = ((dev_t)kproc->p_tdev != NODEV) ? devname(kproc->p_tdev, S_IFCHR) : NULL;
|
||||||
|
if (!name || String_eq(name, "??")) {
|
||||||
|
free(proc->tty_name);
|
||||||
|
proc->tty_name = NULL;
|
||||||
|
} else {
|
||||||
|
free_and_xStrdup(&proc->tty_name, name);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (settings->updateProcessNames) {
|
if (settings->updateProcessNames) {
|
||||||
free(proc->comm);
|
free(proc->comm);
|
||||||
|
|
|
@ -28,7 +28,7 @@ const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = {
|
||||||
[PPID] = { .name = "PPID", .title = "PPID", .description = "Parent process ID", .flags = 0, .pidColumn = true, },
|
[PPID] = { .name = "PPID", .title = "PPID", .description = "Parent process ID", .flags = 0, .pidColumn = true, },
|
||||||
[PGRP] = { .name = "PGRP", .title = "PGRP", .description = "Process group ID", .flags = 0, .pidColumn = true, },
|
[PGRP] = { .name = "PGRP", .title = "PGRP", .description = "Process group ID", .flags = 0, .pidColumn = true, },
|
||||||
[SESSION] = { .name = "SESSION", .title = "SID", .description = "Process's session ID", .flags = 0, .pidColumn = true, },
|
[SESSION] = { .name = "SESSION", .title = "SID", .description = "Process's session ID", .flags = 0, .pidColumn = true, },
|
||||||
[TTY_NR] = { .name = "TTY_NR", .title = " TTY ", .description = "Controlling terminal", .flags = 0, },
|
[TTY] = { .name = "TTY", .title = "TTY ", .description = "Controlling terminal", .flags = 0, },
|
||||||
[TPGID] = { .name = "TPGID", .title = "TPGID", .description = "Process ID of the fg process group of the controlling terminal", .flags = 0, .pidColumn = true, },
|
[TPGID] = { .name = "TPGID", .title = "TPGID", .description = "Process ID of the fg process group of the controlling terminal", .flags = 0, .pidColumn = true, },
|
||||||
[MINFLT] = { .name = "MINFLT", .title = " MINFLT ", .description = "Number of minor faults which have not required loading a memory page from disk", .flags = 0, .defaultSortDesc = true, },
|
[MINFLT] = { .name = "MINFLT", .title = " MINFLT ", .description = "Number of minor faults which have not required loading a memory page from disk", .flags = 0, .defaultSortDesc = true, },
|
||||||
[MAJFLT] = { .name = "MAJFLT", .title = " MAJFLT ", .description = "Number of major faults which have required loading a memory page from disk", .flags = 0, .defaultSortDesc = true, },
|
[MAJFLT] = { .name = "MAJFLT", .title = " MAJFLT ", .description = "Number of major faults which have required loading a memory page from disk", .flags = 0, .defaultSortDesc = true, },
|
||||||
|
|
|
@ -23,7 +23,7 @@ const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = {
|
||||||
[PPID] = { .name = "PPID", .title = "PPID", .description = "Parent process ID", .flags = 0, .pidColumn = true, },
|
[PPID] = { .name = "PPID", .title = "PPID", .description = "Parent process ID", .flags = 0, .pidColumn = true, },
|
||||||
[PGRP] = { .name = "PGRP", .title = "PGRP", .description = "Process group ID", .flags = 0, .pidColumn = true, },
|
[PGRP] = { .name = "PGRP", .title = "PGRP", .description = "Process group ID", .flags = 0, .pidColumn = true, },
|
||||||
[SESSION] = { .name = "SESSION", .title = "SID", .description = "Process's session ID", .flags = 0, .pidColumn = true, },
|
[SESSION] = { .name = "SESSION", .title = "SID", .description = "Process's session ID", .flags = 0, .pidColumn = true, },
|
||||||
[TTY_NR] = { .name = "TTY_NR", .title = " TTY ", .description = "Controlling terminal", .flags = 0, },
|
[TTY] = { .name = "TTY", .title = "TTY ", .description = "Controlling terminal", .flags = 0, },
|
||||||
[TPGID] = { .name = "TPGID", .title = "TPGID", .description = "Process ID of the fg process group of the controlling terminal", .flags = 0, .pidColumn = true, },
|
[TPGID] = { .name = "TPGID", .title = "TPGID", .description = "Process ID of the fg process group of the controlling terminal", .flags = 0, .pidColumn = true, },
|
||||||
[MINFLT] = { .name = "MINFLT", .title = " MINFLT ", .description = "Number of minor faults which have not required loading a memory page from disk", .flags = 0, .defaultSortDesc = true,},
|
[MINFLT] = { .name = "MINFLT", .title = " MINFLT ", .description = "Number of minor faults which have not required loading a memory page from disk", .flags = 0, .defaultSortDesc = true,},
|
||||||
[MAJFLT] = { .name = "MAJFLT", .title = " MAJFLT ", .description = "Number of major faults which have required loading a memory page from disk", .flags = 0, .defaultSortDesc = true, },
|
[MAJFLT] = { .name = "MAJFLT", .title = " MAJFLT ", .description = "Number of major faults which have required loading a memory page from disk", .flags = 0, .defaultSortDesc = true, },
|
||||||
|
|
|
@ -54,6 +54,7 @@ void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) {
|
||||||
proc->pgrp = 0;
|
proc->pgrp = 0;
|
||||||
proc->session = 0;
|
proc->session = 0;
|
||||||
proc->tty_nr = 0;
|
proc->tty_nr = 0;
|
||||||
|
proc->tty_name = NULL;
|
||||||
proc->tpgid = 0;
|
proc->tpgid = 0;
|
||||||
proc->st_uid = 0;
|
proc->st_uid = 0;
|
||||||
proc->processor = 0;
|
proc->processor = 0;
|
||||||
|
|
Loading…
Reference in New Issue