ps thread support
This commit is contained in:
parent
4456afd68a
commit
c462dcfad5
6
Makefile
6
Makefile
@ -18,9 +18,9 @@
|
|||||||
|
|
||||||
VERSION := 3
|
VERSION := 3
|
||||||
SUBVERSION := 1
|
SUBVERSION := 1
|
||||||
MINORVERSION := 12
|
MINORVERSION := 13
|
||||||
TARVERSION := 3.1.12
|
TARVERSION := 3.1.13
|
||||||
LIBVERSION := 3.1.12
|
LIBVERSION := 3.1.13
|
||||||
|
|
||||||
############ vars
|
############ vars
|
||||||
|
|
||||||
|
1
NEWS
1
NEWS
@ -1,5 +1,6 @@
|
|||||||
procps-3.1.12 --> procps-3.1.13
|
procps-3.1.12 --> procps-3.1.13
|
||||||
|
|
||||||
|
ps: can display NPTL threads w/ kernel patch
|
||||||
no seLinux for now (new kernel interface)
|
no seLinux for now (new kernel interface)
|
||||||
|
|
||||||
procps-3.1.11 --> procps-3.1.12
|
procps-3.1.11 --> procps-3.1.12
|
||||||
|
16
pgrep.c
16
pgrep.c
@ -375,7 +375,7 @@ select_procs (void)
|
|||||||
while (readproc (ptp, &task)) {
|
while (readproc (ptp, &task)) {
|
||||||
int match = 1;
|
int match = 1;
|
||||||
|
|
||||||
if (task.pid == myself)
|
if (task.XXXID == myself)
|
||||||
continue;
|
continue;
|
||||||
else if (opt_newest && task.start_time < saved_start_time)
|
else if (opt_newest && task.start_time < saved_start_time)
|
||||||
match = 0;
|
match = 0;
|
||||||
@ -399,7 +399,7 @@ select_procs (void)
|
|||||||
} else {
|
} else {
|
||||||
char tty[256];
|
char tty[256];
|
||||||
dev_to_tty (tty, sizeof(tty) - 1,
|
dev_to_tty (tty, sizeof(tty) - 1,
|
||||||
task.tty, task.pid, ABBREV_DEV);
|
task.tty, task.XXXID, ABBREV_DEV);
|
||||||
match = match_strlist (tty, opt_term);
|
match = match_strlist (tty, opt_term);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -433,26 +433,26 @@ select_procs (void)
|
|||||||
if (match ^ opt_negate) { /* Exclusive OR is neat */
|
if (match ^ opt_negate) { /* Exclusive OR is neat */
|
||||||
if (opt_newest) {
|
if (opt_newest) {
|
||||||
if (saved_start_time == task.start_time &&
|
if (saved_start_time == task.start_time &&
|
||||||
saved_pid > task.pid)
|
saved_pid > task.XXXID)
|
||||||
continue;
|
continue;
|
||||||
saved_start_time = task.start_time;
|
saved_start_time = task.start_time;
|
||||||
saved_pid = task.pid;
|
saved_pid = task.XXXID;
|
||||||
matches = 0;
|
matches = 0;
|
||||||
}
|
}
|
||||||
if (opt_oldest) {
|
if (opt_oldest) {
|
||||||
if (saved_start_time == task.start_time &&
|
if (saved_start_time == task.start_time &&
|
||||||
saved_pid < task.pid)
|
saved_pid < task.XXXID)
|
||||||
continue;
|
continue;
|
||||||
saved_start_time = task.start_time;
|
saved_start_time = task.start_time;
|
||||||
saved_pid = task.pid;
|
saved_pid = task.XXXID;
|
||||||
matches = 0;
|
matches = 0;
|
||||||
}
|
}
|
||||||
if (opt_long) {
|
if (opt_long) {
|
||||||
char buff[5096]; // FIXME
|
char buff[5096]; // FIXME
|
||||||
sprintf (buff, "%d %s", task.pid, cmd);
|
sprintf (buff, "%d %s", task.XXXID, cmd);
|
||||||
list[++matches].str = strdup (buff);
|
list[++matches].str = strdup (buff);
|
||||||
} else {
|
} else {
|
||||||
list[++matches].num = task.pid;
|
list[++matches].num = task.XXXID;
|
||||||
}
|
}
|
||||||
if (matches == size) {
|
if (matches == size) {
|
||||||
size *= 2;
|
size *= 2;
|
||||||
|
@ -2,7 +2,7 @@ _3_1_12 {
|
|||||||
global:
|
global:
|
||||||
__cyg_profile_func_enter; __cyg_profile_func_exit; main;
|
__cyg_profile_func_enter; __cyg_profile_func_exit; main;
|
||||||
|
|
||||||
readproc; readproctab; look_up_our_self; escape_command;
|
readproc; readtask; readproctab; look_up_our_self; escape_command;
|
||||||
escape_str; escape_strlist;
|
escape_str; escape_strlist;
|
||||||
openproc; closeproc;
|
openproc; closeproc;
|
||||||
tty_to_dev; dev_to_tty; open_psdb_message; open_psdb; wchan;
|
tty_to_dev; dev_to_tty; open_psdb_message; open_psdb; wchan;
|
||||||
|
210
proc/readproc.c
210
proc/readproc.c
@ -41,6 +41,8 @@ extern void __cyg_profile_func_enter(void*,void*);
|
|||||||
#define LEAVE(x)
|
#define LEAVE(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static int task_dir_missing;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
typedef struct status_table_struct {
|
typedef struct status_table_struct {
|
||||||
@ -211,7 +213,7 @@ ENTER(0x220);
|
|||||||
P->ppid = strtol(S,&S,10);
|
P->ppid = strtol(S,&S,10);
|
||||||
continue;
|
continue;
|
||||||
case_Pid:
|
case_Pid:
|
||||||
P->pid = strtol(S,&S,10);
|
P->tid = strtol(S,&S,10);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case_ShdPnd:
|
case_ShdPnd:
|
||||||
@ -464,9 +466,10 @@ int read_cmdline(char *restrict const dst, unsigned sz, unsigned pid){
|
|||||||
// This reads process info from /proc in the traditional way, for one process.
|
// This reads process info from /proc in the traditional way, for one process.
|
||||||
// The pid (tgid? tid?) is already in p, and a path to it in path, with some
|
// The pid (tgid? tid?) is already in p, and a path to it in path, with some
|
||||||
// room to spare.
|
// room to spare.
|
||||||
static proc_t* simple_readproc(PROCTAB *restrict const PT, proc_t *restrict const p, char *restrict const path) {
|
static proc_t* simple_readproc(PROCTAB *restrict const PT, proc_t *restrict const p) {
|
||||||
static struct stat sb; // stat() buffer
|
static struct stat sb; // stat() buffer
|
||||||
static char sbuf[1024]; // buffer for stat,statm
|
static char sbuf[1024]; // buffer for stat,statm
|
||||||
|
char *restrict const path = PT->path;
|
||||||
unsigned flags = PT->flags;
|
unsigned flags = PT->flags;
|
||||||
|
|
||||||
if (unlikely(stat(path, &sb) == -1)) /* no such dirent (anymore) */
|
if (unlikely(stat(path, &sb) == -1)) /* no such dirent (anymore) */
|
||||||
@ -530,40 +533,144 @@ next_proc:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// This reads /proc/*/task/* data, for one task.
|
||||||
|
// p is the POSIX process (task group summary) (not needed by THIS implementation)
|
||||||
|
// t is the POSIX thread (task group member, generally not the leader)
|
||||||
|
// path is a path to the task, with some room to spare.
|
||||||
|
static proc_t* simple_readtask(PROCTAB *restrict const PT, const proc_t *restrict const p, proc_t *restrict const t, char *restrict const path) {
|
||||||
|
static struct stat sb; // stat() buffer
|
||||||
|
static char sbuf[1024]; // buffer for stat,statm
|
||||||
|
unsigned flags = PT->flags;
|
||||||
|
|
||||||
|
if (unlikely(stat(path, &sb) == -1)) /* no such dirent (anymore) */
|
||||||
|
goto next_task;
|
||||||
|
|
||||||
|
// if ((flags & PROC_UID) && !XinLN(uid_t, sb.st_uid, PT->uids, PT->nuid))
|
||||||
|
// goto next_task; /* not one of the requested uids */
|
||||||
|
|
||||||
|
t->euid = sb.st_uid; /* need a way to get real uid */
|
||||||
|
t->egid = sb.st_gid; /* need a way to get real gid */
|
||||||
|
|
||||||
|
if (flags & PROC_FILLSTAT) { /* read, parse /proc/#/stat */
|
||||||
|
if (unlikely( file2str(path, "stat", sbuf, sizeof sbuf) == -1 ))
|
||||||
|
goto next_task; /* error reading /proc/#/stat */
|
||||||
|
stat2proc(sbuf, t); /* parse /proc/#/stat */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlikely(flags & PROC_FILLMEM)) { /* read, parse /proc/#/statm */
|
||||||
|
if (likely( file2str(path, "statm", sbuf, sizeof sbuf) != -1 ))
|
||||||
|
statm2proc(sbuf, t); /* ignore statm errors here */
|
||||||
|
} /* statm fields just zero */
|
||||||
|
|
||||||
|
if (flags & PROC_FILLSTATUS) { /* read, parse /proc/#/status */
|
||||||
|
if (likely( file2str(path, "status", sbuf, sizeof sbuf) != -1 )){
|
||||||
|
status2proc(sbuf, t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* some number->text resolving which is time consuming */
|
||||||
|
if (flags & PROC_FILLUSR){
|
||||||
|
strncpy(t->euser, user_from_uid(t->euid), sizeof t->euser);
|
||||||
|
if(flags & PROC_FILLSTATUS) {
|
||||||
|
strncpy(t->ruser, user_from_uid(t->ruid), sizeof t->ruser);
|
||||||
|
strncpy(t->suser, user_from_uid(t->suid), sizeof t->suser);
|
||||||
|
strncpy(t->fuser, user_from_uid(t->fuid), sizeof t->fuser);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* some number->text resolving which is time consuming */
|
||||||
|
if (flags & PROC_FILLGRP){
|
||||||
|
strncpy(t->egroup, group_from_gid(t->egid), sizeof t->egroup);
|
||||||
|
if(flags & PROC_FILLSTATUS) {
|
||||||
|
strncpy(t->rgroup, group_from_gid(t->rgid), sizeof t->rgroup);
|
||||||
|
strncpy(t->sgroup, group_from_gid(t->sgid), sizeof t->sgroup);
|
||||||
|
strncpy(t->fgroup, group_from_gid(t->fgid), sizeof t->fgroup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if ((flags & PROC_FILLCOM) || (flags & PROC_FILLARG)) /* read+parse /proc/#/cmdline */
|
||||||
|
t->cmdline = file2strvec(path, "cmdline");
|
||||||
|
else
|
||||||
|
t->cmdline = NULL;
|
||||||
|
|
||||||
|
if (unlikely(flags & PROC_FILLENV)) /* read+parse /proc/#/environ */
|
||||||
|
t->environ = file2strvec(path, "environ");
|
||||||
|
else
|
||||||
|
t->environ = NULL;
|
||||||
|
#else
|
||||||
|
t->cmdline = p->cmdline; // better not free these until done with all threads!
|
||||||
|
t->environ = p->environ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return t;
|
||||||
|
next_task:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
// This finds processes in /proc in the traditional way.
|
// This finds processes in /proc in the traditional way.
|
||||||
// Return non-zero on success.
|
// Return non-zero on success.
|
||||||
static int simple_nextpid(PROCTAB *restrict const PT, proc_t *restrict const p, char *restrict const path) {
|
static int simple_nextpid(PROCTAB *restrict const PT, proc_t *restrict const p) {
|
||||||
static struct direct *ent; /* dirent handle */
|
static struct direct *ent; /* dirent handle */
|
||||||
|
char *restrict const path = PT->path;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
ent = readdir(PT->procfs);
|
ent = readdir(PT->procfs);
|
||||||
if(unlikely(unlikely(!ent) || unlikely(!ent->d_name))) return 0;
|
if(unlikely(unlikely(!ent) || unlikely(!ent->d_name))) return 0;
|
||||||
if(likely( likely(*ent->d_name > '0') && likely(*ent->d_name <= '9') )) break;
|
if(likely( likely(*ent->d_name > '0') && likely(*ent->d_name <= '9') )) break;
|
||||||
}
|
}
|
||||||
p->pid = strtoul(ent->d_name, NULL, 10);
|
p->tgid = strtoul(ent->d_name, NULL, 10);
|
||||||
|
p->tid = p->tgid;
|
||||||
memcpy(path, "/proc/", 6);
|
memcpy(path, "/proc/", 6);
|
||||||
strcpy(path+6, ent->d_name); // trust /proc to not contain evil top-level entries
|
strcpy(path+6, ent->d_name); // trust /proc to not contain evil top-level entries
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PROCPATHLEN 64 // must hold /proc/2000222000/task/2000222000/cmdline
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// This finds tasks in /proc/*/task/ in the traditional way.
|
||||||
|
// Return non-zero on success.
|
||||||
|
static int simple_nexttid(PROCTAB *restrict const PT, const proc_t *restrict const p, proc_t *restrict const t, char *restrict const path) {
|
||||||
|
static struct direct *ent; /* dirent handle */
|
||||||
|
(void)p;
|
||||||
|
if(!PT->taskdir){
|
||||||
|
// use "path" as some tmp space
|
||||||
|
snprintf(path, PROCPATHLEN, "%s/task", PT->path);
|
||||||
|
PT->taskdir = opendir(path);
|
||||||
|
if(!PT->taskdir) return 0;
|
||||||
|
}
|
||||||
|
for (;;) {
|
||||||
|
ent = readdir(PT->taskdir);
|
||||||
|
if(unlikely(unlikely(!ent) || unlikely(!ent->d_name))) return 0;
|
||||||
|
if(likely( likely(*ent->d_name > '0') && likely(*ent->d_name <= '9') )) break;
|
||||||
|
}
|
||||||
|
t->tid = strtoul(ent->d_name, NULL, 10);
|
||||||
|
t->tgid = p->tgid;
|
||||||
|
t->ppid = p->ppid; // cover for kernel behavior? we want both actually...?
|
||||||
|
snprintf(path, PROCPATHLEN, "%s/task/%s", PT->path, ent->d_name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
// This "finds" processes in a list that was given to openproc().
|
// This "finds" processes in a list that was given to openproc().
|
||||||
// Return non-zero on success. (pid was handy)
|
// Return non-zero on success. (tgid was handy)
|
||||||
static int listed_nextpid(PROCTAB *restrict const PT, proc_t *restrict const p, char *restrict const path) {
|
static int listed_nextpid(PROCTAB *restrict const PT, proc_t *restrict const p) {
|
||||||
pid_t pid = *(PT->pids)++;
|
char *restrict const path = PT->path;
|
||||||
if(likely( pid )){
|
pid_t tgid = *(PT->pids)++;
|
||||||
snprintf(path, PROCPATHLEN, "/proc/%d", pid);
|
if(likely( tgid )){
|
||||||
p->pid = pid;
|
snprintf(path, PROCPATHLEN, "/proc/%d", tgid);
|
||||||
|
p->tgid = tgid;
|
||||||
|
p->tid = tgid; // they match for leaders
|
||||||
}
|
}
|
||||||
return pid;
|
return tgid;
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
// This "finds" processes by guessing every possible one of them!
|
// This "finds" processes by guessing every possible one of them!
|
||||||
// Return non-zero on success. (pid was handy)
|
// Return non-zero on success. (pid was handy)
|
||||||
static int stupid_nextpid(PROCTAB *restrict const PT, proc_t *restrict const p, char *restrict const path) {
|
#if 0
|
||||||
|
static int stupid_nextpid(PROCTAB *restrict const PT, proc_t *restrict const p) {
|
||||||
|
char *restrict const path = PT->path;
|
||||||
pid_t pid = --PT->u;
|
pid_t pid = --PT->u;
|
||||||
if(likely( pid )){
|
if(likely( pid )){
|
||||||
snprintf(path, PROCPATHLEN, "/proc/%d", pid);
|
snprintf(path, PROCPATHLEN, "/proc/%d", pid);
|
||||||
@ -571,15 +678,16 @@ static int stupid_nextpid(PROCTAB *restrict const PT, proc_t *restrict const p,
|
|||||||
}
|
}
|
||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
// This reads process info from proc_t structs already attached to a PROCTAB.
|
// This reads process info from proc_t structs already attached to a PROCTAB.
|
||||||
// Yeah, we don't retain any pointer for freeing the memory later. Oh well.
|
// Yeah, we don't retain any pointer for freeing the memory later. Oh well.
|
||||||
// This code is for development only.
|
// This code is for development only.
|
||||||
static proc_t* predone_readproc(PROCTAB *restrict const PT, proc_t *restrict const p, char *restrict const path) {
|
#if 0
|
||||||
|
static proc_t* predone_readproc(PROCTAB *restrict const PT, proc_t *restrict const p) {
|
||||||
proc_t *tmp;
|
proc_t *tmp;
|
||||||
proc_t *ret = NULL;
|
proc_t *ret = NULL;
|
||||||
(void)path;
|
|
||||||
for(;;){
|
for(;;){
|
||||||
tmp = PT->vp;
|
tmp = PT->vp;
|
||||||
if(!tmp) _exit(49); // can't happen
|
if(!tmp) _exit(49); // can't happen
|
||||||
@ -598,15 +706,17 @@ static proc_t* predone_readproc(PROCTAB *restrict const PT, proc_t *restrict con
|
|||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
// This "finds" processes by pulling them off of a list.
|
// This "finds" processes by pulling them off of a list.
|
||||||
// Return non-zero on success.
|
// Return non-zero on success.
|
||||||
static int predone_nextpid(PROCTAB *restrict const PT, proc_t *restrict const p, char *restrict const path) {
|
#if 0
|
||||||
|
static int predone_nextpid(PROCTAB *restrict const PT, proc_t *restrict const p) {
|
||||||
(void)p;
|
(void)p;
|
||||||
(void)path;
|
|
||||||
return !!PT->vp;
|
return !!PT->vp;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
/* readproc: return a pointer to a proc_t filled with requested info about the
|
/* readproc: return a pointer to a proc_t filled with requested info about the
|
||||||
@ -620,29 +730,70 @@ static int predone_nextpid(PROCTAB *restrict const PT, proc_t *restrict const p,
|
|||||||
* fairly complex, but it does try to not to do any unnecessary work.
|
* fairly complex, but it does try to not to do any unnecessary work.
|
||||||
*/
|
*/
|
||||||
proc_t* readproc(PROCTAB *restrict const PT, proc_t *restrict p) {
|
proc_t* readproc(PROCTAB *restrict const PT, proc_t *restrict p) {
|
||||||
static char path[PROCPATHLEN]; // must hold /proc/2000222000/task/2000222000/cmdline
|
|
||||||
proc_t *ret;
|
proc_t *ret;
|
||||||
proc_t *saved_p;
|
proc_t *saved_p;
|
||||||
|
|
||||||
|
if (PT->did_fake) PT->did_fake=0;
|
||||||
|
if (PT->taskdir) {
|
||||||
|
closedir(PT->taskdir);
|
||||||
|
PT->taskdir = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
saved_p = p;
|
saved_p = p;
|
||||||
if(!p) p = xcalloc(p, sizeof *p); /* passed buf or alloced mem */
|
if(!p) p = xcalloc(p, sizeof *p); /* passed buf or alloced mem */
|
||||||
|
|
||||||
for(;;){
|
for(;;){
|
||||||
// fills in the path and the p->pid
|
// fills in the path, plus p->tid and p->tgid
|
||||||
if (unlikely(! PT->finder(PT,p,path) )) goto out;
|
if (unlikely(! PT->finder(PT,p) )) goto out;
|
||||||
|
|
||||||
// go read the process data
|
// go read the process data
|
||||||
ret = PT->reader(PT,p,path);
|
ret = PT->reader(PT,p);
|
||||||
if(ret) return ret;
|
if(ret) return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if(!saved_p) free(p);
|
if(!saved_p) free(p);
|
||||||
|
// FIXME: maybe set tid to -1 here, for "-" in display?
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// readtask: return a pointer to a proc_t filled with requested info about the
|
||||||
|
// next task available. If no more such tasks are available, return a null
|
||||||
|
// pointer (boolean false). Use the passed buffer instead of allocating
|
||||||
|
// space if it is non-NULL.
|
||||||
|
proc_t* readtask(PROCTAB *restrict const PT, const proc_t *restrict const p, proc_t *restrict t) {
|
||||||
|
static char path[PROCPATHLEN]; // must hold /proc/2000222000/task/2000222000/cmdline
|
||||||
|
proc_t *ret;
|
||||||
|
proc_t *saved_t;
|
||||||
|
|
||||||
|
saved_t = t;
|
||||||
|
if(!t) t = xcalloc(t, sizeof *t); /* passed buf or alloced mem */
|
||||||
|
|
||||||
|
if(task_dir_missing){ // got to fake a thread for old kernels
|
||||||
|
if(PT->did_fake) goto out;
|
||||||
|
PT->did_fake=1;
|
||||||
|
memcpy(t,p,sizeof(proc_t));
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(;;){
|
||||||
|
// fills in the path, plus t->tid and t->tgid
|
||||||
|
if (unlikely(! PT->taskfinder(PT,p,t,path) )) goto out; // simple_nexttid
|
||||||
|
|
||||||
|
// go read the task data
|
||||||
|
ret = PT->taskreader(PT,p,t,path); // simple_readtask
|
||||||
|
if(ret) return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
if(!saved_t) free(t);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#if 0
|
||||||
static void evil_grouping_hack(PROCTAB* PT){
|
static void evil_grouping_hack(PROCTAB* PT){
|
||||||
proc_t *tp;
|
proc_t *tp;
|
||||||
// first we read them
|
// first we read them
|
||||||
@ -676,13 +827,23 @@ static void evil_grouping_hack(PROCTAB* PT){
|
|||||||
PT->finder = predone_nextpid;
|
PT->finder = predone_nextpid;
|
||||||
PT->reader = predone_readproc;
|
PT->reader = predone_readproc;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// initiate a process table scan
|
// initiate a process table scan
|
||||||
PROCTAB* openproc(int flags, ...) {
|
PROCTAB* openproc(int flags, ...) {
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
struct stat sbuf;
|
||||||
|
static int did_stat;
|
||||||
PROCTAB* PT = xmalloc(sizeof(PROCTAB));
|
PROCTAB* PT = xmalloc(sizeof(PROCTAB));
|
||||||
|
|
||||||
|
if(!did_stat){
|
||||||
|
task_dir_missing = stat("/proc/self/task", &sbuf);
|
||||||
|
did_stat = 1;
|
||||||
|
}
|
||||||
|
PT->taskdir = NULL;
|
||||||
|
PT->taskfinder = simple_nexttid;
|
||||||
|
PT->taskreader = simple_readtask;
|
||||||
|
|
||||||
PT->reader = simple_readproc;
|
PT->reader = simple_readproc;
|
||||||
if (flags & PROC_PID){
|
if (flags & PROC_PID){
|
||||||
PT->procfs = NULL;
|
PT->procfs = NULL;
|
||||||
@ -694,10 +855,12 @@ PROCTAB* openproc(int flags, ...) {
|
|||||||
}
|
}
|
||||||
PT->flags = flags;
|
PT->flags = flags;
|
||||||
|
|
||||||
|
#if 0
|
||||||
if(getenv("EVIL_FINDER_HACK")){ // for development only
|
if(getenv("EVIL_FINDER_HACK")){ // for development only
|
||||||
PT->finder = stupid_nextpid;
|
PT->finder = stupid_nextpid;
|
||||||
PT->u = 10000;
|
PT->u = 10000;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
va_start(ap, flags); /* Init args list */
|
va_start(ap, flags); /* Init args list */
|
||||||
if (flags & PROC_PID)
|
if (flags & PROC_PID)
|
||||||
@ -708,7 +871,9 @@ PROCTAB* openproc(int flags, ...) {
|
|||||||
}
|
}
|
||||||
va_end(ap); /* Clean up args list */
|
va_end(ap); /* Clean up args list */
|
||||||
|
|
||||||
|
#if 0
|
||||||
if(getenv("EVIL_GROUPING_HACK")) evil_grouping_hack(PT);
|
if(getenv("EVIL_GROUPING_HACK")) evil_grouping_hack(PT);
|
||||||
|
#endif
|
||||||
|
|
||||||
return PT;
|
return PT;
|
||||||
}
|
}
|
||||||
@ -717,6 +882,7 @@ PROCTAB* openproc(int flags, ...) {
|
|||||||
void closeproc(PROCTAB* PT) {
|
void closeproc(PROCTAB* PT) {
|
||||||
if (PT){
|
if (PT){
|
||||||
if (PT->procfs) closedir(PT->procfs);
|
if (PT->procfs) closedir(PT->procfs);
|
||||||
|
if (PT->taskdir) closedir(PT->taskdir);
|
||||||
free(PT);
|
free(PT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,11 @@ EXTERN_C_BEGIN
|
|||||||
lu start_time, vsize, wchan, nswap, cnswap,
|
lu start_time, vsize, wchan, nswap, cnswap,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// This is to help document a transition from pid to tgid/tid caused
|
||||||
|
// by the introduction of thread support. It is used in cases where
|
||||||
|
// neither tgid nor tid seemed correct. (in other words, FIXME)
|
||||||
|
#define XXXID tid
|
||||||
|
|
||||||
/* Basic data structure which holds all information we can get about a process.
|
/* Basic data structure which holds all information we can get about a process.
|
||||||
* (unless otherwise specified, fields are read from /proc/#/stat)
|
* (unless otherwise specified, fields are read from /proc/#/stat)
|
||||||
*
|
*
|
||||||
@ -34,7 +39,7 @@ EXTERN_C_BEGIN
|
|||||||
typedef struct proc_t {
|
typedef struct proc_t {
|
||||||
// 1st 16 bytes
|
// 1st 16 bytes
|
||||||
int
|
int
|
||||||
pid, /* process id */
|
tid, /* process id */
|
||||||
ppid; /* pid of parent process */
|
ppid; /* pid of parent process */
|
||||||
unsigned
|
unsigned
|
||||||
pcpu; /* %CPU usage (is not filled in by readproc!!!) */
|
pcpu; /* %CPU usage (is not filled in by readproc!!!) */
|
||||||
@ -144,10 +149,17 @@ typedef struct proc_t {
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#define PROCPATHLEN 64 // must hold /proc/2000222000/task/2000222000/cmdline
|
||||||
|
|
||||||
typedef struct PROCTAB {
|
typedef struct PROCTAB {
|
||||||
DIR* procfs;
|
DIR* procfs;
|
||||||
int(*finder)(struct PROCTAB *restrict const, proc_t *restrict const, char *restrict const);
|
DIR* taskdir; // for threads
|
||||||
proc_t*(*reader)(struct PROCTAB *restrict const, proc_t *restrict const, char *restrict const);
|
int did_fake; // used when taskdir is missing
|
||||||
|
int(*finder)(struct PROCTAB *restrict const, proc_t *restrict const);
|
||||||
|
proc_t*(*reader)(struct PROCTAB *restrict const, proc_t *restrict const);
|
||||||
|
int(*taskfinder)(struct PROCTAB *restrict const, const proc_t *restrict const, proc_t *restrict const, char *restrict const);
|
||||||
|
proc_t*(*taskreader)(struct PROCTAB *restrict const, const proc_t *restrict const, proc_t *restrict const, char *restrict const);
|
||||||
unsigned flags;
|
unsigned flags;
|
||||||
pid_t* pids; /* pids of the procs */
|
pid_t* pids; /* pids of the procs */
|
||||||
uid_t* uids; /* uids of procs */
|
uid_t* uids; /* uids of procs */
|
||||||
@ -155,6 +167,8 @@ typedef struct PROCTAB {
|
|||||||
int i; // generic
|
int i; // generic
|
||||||
unsigned u; // generic
|
unsigned u; // generic
|
||||||
void * vp; // generic
|
void * vp; // generic
|
||||||
|
char path[PROCPATHLEN]; // must hold /proc/2000222000/task/2000222000/cmdline
|
||||||
|
unsigned pathlen; // length of string in the above (w/o '\0')
|
||||||
} PROCTAB;
|
} PROCTAB;
|
||||||
|
|
||||||
// initialize a PROCTAB structure holding needed call-to-call persistent data
|
// initialize a PROCTAB structure holding needed call-to-call persistent data
|
||||||
@ -172,7 +186,8 @@ extern proc_t** readproctab(int flags, ... /* same as openproc */ );
|
|||||||
extern void closeproc(PROCTAB* PT);
|
extern void closeproc(PROCTAB* PT);
|
||||||
|
|
||||||
// retrieve the next process matching the criteria set by the openproc()
|
// retrieve the next process matching the criteria set by the openproc()
|
||||||
extern proc_t* readproc(PROCTAB *restrict const PT, proc_t *restrict const return_buf);
|
extern proc_t* readproc(PROCTAB *restrict const PT, proc_t *restrict p);
|
||||||
|
extern proc_t* readtask(PROCTAB *restrict const PT, const proc_t *restrict const p, proc_t *restrict t);
|
||||||
|
|
||||||
// warning: interface may change
|
// warning: interface may change
|
||||||
extern int read_cmdline(char *restrict const dst, unsigned sz, unsigned pid);
|
extern int read_cmdline(char *restrict const dst, unsigned sz, unsigned pid);
|
||||||
@ -207,8 +222,6 @@ extern void freeproc(proc_t* p);
|
|||||||
#define PROC_FILLWCHAN 0x0080 /* look up WCHAN name */
|
#define PROC_FILLWCHAN 0x0080 /* look up WCHAN name */
|
||||||
#define PROC_FILLARG 0x0100 /* alloc and fill in `cmdline' */
|
#define PROC_FILLARG 0x0100 /* alloc and fill in `cmdline' */
|
||||||
|
|
||||||
#define PROC_FILLANY 0x0000 /* either stat or status will do */
|
|
||||||
|
|
||||||
/* Obsolete, consider only processes with one of the passed: */
|
/* Obsolete, consider only processes with one of the passed: */
|
||||||
#define PROC_PID 0x1000 /* process id numbers ( 0 terminated) */
|
#define PROC_PID 0x1000 /* process id numbers ( 0 terminated) */
|
||||||
#define PROC_UID 0x4000 /* user id numbers ( length needed ) */
|
#define PROC_UID 0x4000 /* user id numbers ( length needed ) */
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
Begin4
|
Begin4
|
||||||
Title: procps
|
Title: procps
|
||||||
Version: 3.1.12
|
Version: 3.1.13
|
||||||
Entered-date: 2003-08-10
|
Entered-date: 2003-09-17
|
||||||
Description: Linux system utilities
|
Description: Linux system utilities
|
||||||
Keywords: procps /proc libproc sysctl pmap ps uptime tload
|
Keywords: procps /proc libproc sysctl pmap ps uptime tload
|
||||||
free w top vmstat watch skill snice kill pgrep pkill
|
free w top vmstat watch skill snice kill pgrep pkill
|
||||||
Author: Albert Cahalan, Michael K. Johnson, Jim Warner, etc.
|
Author: Albert Cahalan, Michael K. Johnson, Jim Warner, etc.
|
||||||
Maintained-by: various <procps-feedback@lists.sf.net>
|
Maintained-by: various <procps-feedback@lists.sf.net>
|
||||||
Primary-site: http://procps.sf.net/
|
Primary-site: http://procps.sf.net/
|
||||||
242kB procps-3.1.12.tar.gz
|
242kB procps-3.1.13.tar.gz
|
||||||
Alternate-site: http://www.debian.org/Packages/unstable/base/procps.html
|
Alternate-site: http://www.debian.org/Packages/unstable/base/procps.html
|
||||||
242kB procps-3.1.12.tar.gz
|
242kB procps-3.1.13.tar.gz
|
||||||
Copying-policy: mixed
|
Copying-policy: mixed
|
||||||
End
|
End
|
||||||
|
@ -3,7 +3,7 @@ Summary: System and process monitoring utilities
|
|||||||
Name: procps
|
Name: procps
|
||||||
%define major_version 3
|
%define major_version 3
|
||||||
%define minor_version 1
|
%define minor_version 1
|
||||||
%define revision 12
|
%define revision 13
|
||||||
%define version %{major_version}.%{minor_version}.%{revision}
|
%define version %{major_version}.%{minor_version}.%{revision}
|
||||||
Version: %{version}
|
Version: %{version}
|
||||||
Release: 1
|
Release: 1
|
||||||
|
@ -73,6 +73,10 @@
|
|||||||
|
|
||||||
#define needs_for_select (PROC_FILLSTAT | PROC_FILLSTATUS)
|
#define needs_for_select (PROC_FILLSTAT | PROC_FILLSTATUS)
|
||||||
|
|
||||||
|
/* thread_flags */
|
||||||
|
#define TF_show_proc 0x0001 // show the summary line
|
||||||
|
#define TF_show_task 0x0002 // show the per-thread lines
|
||||||
|
|
||||||
/* personality control flags */
|
/* personality control flags */
|
||||||
#define PER_BROKEN_o 0x0001
|
#define PER_BROKEN_o 0x0001
|
||||||
#define PER_BSD_h 0x0002
|
#define PER_BSD_h 0x0002
|
||||||
@ -270,6 +274,7 @@ extern const char *sysv_f_format;
|
|||||||
extern const char *sysv_fl_format;
|
extern const char *sysv_fl_format;
|
||||||
extern const char *sysv_j_format;
|
extern const char *sysv_j_format;
|
||||||
extern const char *sysv_l_format;
|
extern const char *sysv_l_format;
|
||||||
|
extern unsigned thread_flags;
|
||||||
extern int unix_f_option;
|
extern int unix_f_option;
|
||||||
extern int user_is_number;
|
extern int user_is_number;
|
||||||
extern int wchan_is_number;
|
extern int wchan_is_number;
|
||||||
|
27
ps/display.c
27
ps/display.c
@ -81,12 +81,12 @@ void hex_dump(void *vp){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void show_pid(char *s, int n, sel_union *data){
|
static void show_tgid(char *s, int n, sel_union *data){
|
||||||
printf("%s ", s);
|
printf("%s ", s);
|
||||||
while(--n){
|
while(--n){
|
||||||
printf("%d,", data[n].pid);
|
printf("%d,", data[n].tgid);
|
||||||
}
|
}
|
||||||
printf("%d\n", data[0].pid);
|
printf("%d\n", data[0].tgid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void show_uid(char *s, int n, sel_union *data){
|
static void show_uid(char *s, int n, sel_union *data){
|
||||||
@ -247,9 +247,18 @@ static void simple_spew(void){
|
|||||||
fprintf(stderr, "Error: can not access /proc.\n");
|
fprintf(stderr, "Error: can not access /proc.\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
if(!thread_flags) thread_flags=TF_show_proc;
|
||||||
memset(&buf, '#', sizeof(proc_t));
|
memset(&buf, '#', sizeof(proc_t));
|
||||||
while(readproc(ptp,&buf)){
|
while(readproc(ptp,&buf)){
|
||||||
if(want_this_proc(&buf)) show_one_proc(&buf);
|
if(want_this_proc(&buf)){
|
||||||
|
if(thread_flags & TF_show_proc) show_one_proc(&buf);
|
||||||
|
if(thread_flags & TF_show_task){
|
||||||
|
proc_t buf2;
|
||||||
|
// must still have the process allocated
|
||||||
|
while(readtask(ptp,&buf,&buf2)) show_one_proc(&buf2);
|
||||||
|
// must not attempt to free cmdline and environ
|
||||||
|
}
|
||||||
|
}
|
||||||
if(buf.cmdline) free((void*)*buf.cmdline); // ought to reuse
|
if(buf.cmdline) free((void*)*buf.cmdline); // ought to reuse
|
||||||
if(buf.environ) free((void*)*buf.environ); // ought to reuse
|
if(buf.environ) free((void*)*buf.environ); // ought to reuse
|
||||||
// memset(&buf, '#', sizeof(proc_t));
|
// memset(&buf, '#', sizeof(proc_t));
|
||||||
@ -331,7 +340,7 @@ static void show_tree(const int self, const int n, const int level, const int ha
|
|||||||
// if(processes[self]->environ) free((void*)*processes[self]->environ);
|
// if(processes[self]->environ) free((void*)*processes[self]->environ);
|
||||||
for(;;){ /* look for children */
|
for(;;){ /* look for children */
|
||||||
if(i >= n) return; /* no children */
|
if(i >= n) return; /* no children */
|
||||||
if(processes[i]->ppid == processes[self]->pid) break;
|
if(processes[i]->ppid == processes[self]->XXXID) break;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if(level){
|
if(level){
|
||||||
@ -344,7 +353,7 @@ static void show_tree(const int self, const int n, const int level, const int ha
|
|||||||
int self_pid;
|
int self_pid;
|
||||||
int more_children = 1;
|
int more_children = 1;
|
||||||
if(i >= n) break; /* over the edge */
|
if(i >= n) break; /* over the edge */
|
||||||
self_pid=processes[self]->pid;
|
self_pid=processes[self]->XXXID;
|
||||||
if(i+1 >= n)
|
if(i+1 >= n)
|
||||||
more_children = 0;
|
more_children = 0;
|
||||||
else
|
else
|
||||||
@ -367,7 +376,7 @@ static void show_forest(const int n){
|
|||||||
while(i--){ /* cover whole array looking for trees */
|
while(i--){ /* cover whole array looking for trees */
|
||||||
j = n;
|
j = n;
|
||||||
while(j--){ /* search for parent: if none, i is a tree! */
|
while(j--){ /* search for parent: if none, i is a tree! */
|
||||||
if(processes[j]->pid == processes[i]->ppid) goto not_root;
|
if(processes[j]->XXXID == processes[i]->ppid) goto not_root;
|
||||||
}
|
}
|
||||||
show_tree(i,n,0,0);
|
show_tree(i,n,0,0);
|
||||||
not_root:
|
not_root:
|
||||||
@ -381,6 +390,10 @@ static void fancy_spew(void){
|
|||||||
proc_t *retbuf = NULL;
|
proc_t *retbuf = NULL;
|
||||||
PROCTAB *restrict ptp;
|
PROCTAB *restrict ptp;
|
||||||
int n = 0; /* number of processes & index into array */
|
int n = 0; /* number of processes & index into array */
|
||||||
|
if(thread_flags){
|
||||||
|
fprintf(stderr, "can't have threads with sorting or forest output\n");
|
||||||
|
exit(49);
|
||||||
|
}
|
||||||
ptp = openproc(needs_for_format | needs_for_sort | needs_for_select);
|
ptp = openproc(needs_for_format | needs_for_sort | needs_for_select);
|
||||||
if(!ptp) {
|
if(!ptp) {
|
||||||
fprintf(stderr, "Error: can not access /proc.\n");
|
fprintf(stderr, "Error: can not access /proc.\n");
|
||||||
|
@ -73,6 +73,7 @@ const char *sysv_f_format = (const char *)0xdeadbeef;
|
|||||||
const char *sysv_fl_format = (const char *)0xdeadbeef;
|
const char *sysv_fl_format = (const char *)0xdeadbeef;
|
||||||
const char *sysv_j_format = (const char *)0xdeadbeef;
|
const char *sysv_j_format = (const char *)0xdeadbeef;
|
||||||
const char *sysv_l_format = (const char *)0xdeadbeef;
|
const char *sysv_l_format = (const char *)0xdeadbeef;
|
||||||
|
unsigned thread_flags = 0xffffffff;
|
||||||
int unix_f_option = -1;
|
int unix_f_option = -1;
|
||||||
int user_is_number = -1;
|
int user_is_number = -1;
|
||||||
int wchan_is_number = -1;
|
int wchan_is_number = -1;
|
||||||
@ -343,6 +344,7 @@ void reset_global(void){
|
|||||||
selection_list = NULL;
|
selection_list = NULL;
|
||||||
simple_select = 0;
|
simple_select = 0;
|
||||||
sort_list = NULL;
|
sort_list = NULL;
|
||||||
|
thread_flags = 0;
|
||||||
unix_f_option = 0;
|
unix_f_option = 0;
|
||||||
user_is_number = 0;
|
user_is_number = 0;
|
||||||
wchan_is_number = 0;
|
wchan_is_number = 0;
|
||||||
|
23
ps/output.c
23
ps/output.c
@ -201,7 +201,8 @@ CMP_INT(suid)
|
|||||||
CMP_INT(sgid)
|
CMP_INT(sgid)
|
||||||
CMP_INT(fuid)
|
CMP_INT(fuid)
|
||||||
CMP_INT(fgid)
|
CMP_INT(fgid)
|
||||||
CMP_SMALL(pid)
|
CMP_SMALL(tid)
|
||||||
|
CMP_SMALL(tgid)
|
||||||
CMP_SMALL(ppid)
|
CMP_SMALL(ppid)
|
||||||
CMP_SMALL(pgrp)
|
CMP_SMALL(pgrp)
|
||||||
CMP_SMALL(session)
|
CMP_SMALL(session)
|
||||||
@ -457,7 +458,7 @@ static int pr_pgid(char *restrict const outbuf, const proc_t *restrict const pp)
|
|||||||
return snprintf(outbuf, COLWID, "%u", pp->pgrp);
|
return snprintf(outbuf, COLWID, "%u", pp->pgrp);
|
||||||
}
|
}
|
||||||
static int pr_pid(char *restrict const outbuf, const proc_t *restrict const pp){
|
static int pr_pid(char *restrict const outbuf, const proc_t *restrict const pp){
|
||||||
return snprintf(outbuf, COLWID, "%u", pp->pid);
|
return snprintf(outbuf, COLWID, "%u", pp->tgid);
|
||||||
}
|
}
|
||||||
static int pr_ppid(char *restrict const outbuf, const proc_t *restrict const pp){
|
static int pr_ppid(char *restrict const outbuf, const proc_t *restrict const pp){
|
||||||
return snprintf(outbuf, COLWID, "%u", pp->ppid);
|
return snprintf(outbuf, COLWID, "%u", pp->ppid);
|
||||||
@ -561,20 +562,20 @@ static int pr_wchan(char *restrict const outbuf, const proc_t *restrict const pp
|
|||||||
*/
|
*/
|
||||||
if(!(pp->wchan & 0xffffff)) return snprintf(outbuf, COLWID, "%s", "-");
|
if(!(pp->wchan & 0xffffff)) return snprintf(outbuf, COLWID, "%s", "-");
|
||||||
if(wchan_is_number) return snprintf(outbuf, COLWID, "%x", (unsigned)(pp->wchan) & 0xffffffu);
|
if(wchan_is_number) return snprintf(outbuf, COLWID, "%x", (unsigned)(pp->wchan) & 0xffffffu);
|
||||||
return snprintf(outbuf, COLWID, "%s", wchan(pp->wchan, pp->pid));
|
return snprintf(outbuf, COLWID, "%s", wchan(pp->wchan, pp->XXXID));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Terrible trunctuation, like BSD crap uses: I999 J999 K999 */
|
/* Terrible trunctuation, like BSD crap uses: I999 J999 K999 */
|
||||||
/* FIXME: disambiguate /dev/tty69 and /dev/pts/69. */
|
/* FIXME: disambiguate /dev/tty69 and /dev/pts/69. */
|
||||||
static int pr_tty4(char *restrict const outbuf, const proc_t *restrict const pp){
|
static int pr_tty4(char *restrict const outbuf, const proc_t *restrict const pp){
|
||||||
/* snprintf(outbuf, COLWID, "%02x:%02x", pp->tty>>8, pp->tty&0xff); */
|
/* snprintf(outbuf, COLWID, "%02x:%02x", pp->tty>>8, pp->tty&0xff); */
|
||||||
return dev_to_tty(outbuf, 4, pp->tty, pp->pid, ABBREV_DEV|ABBREV_TTY|ABBREV_PTS);
|
return dev_to_tty(outbuf, 4, pp->tty, pp->XXXID, ABBREV_DEV|ABBREV_TTY|ABBREV_PTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unix98: format is unspecified, but must match that used by who(1). */
|
/* Unix98: format is unspecified, but must match that used by who(1). */
|
||||||
static int pr_tty8(char *restrict const outbuf, const proc_t *restrict const pp){
|
static int pr_tty8(char *restrict const outbuf, const proc_t *restrict const pp){
|
||||||
/* snprintf(outbuf, COLWID, "%02x:%02x", pp->tty>>8, pp->tty&0xff); */
|
/* snprintf(outbuf, COLWID, "%02x:%02x", pp->tty>>8, pp->tty&0xff); */
|
||||||
return dev_to_tty(outbuf, PAGE_SIZE-1, pp->tty, pp->pid, ABBREV_DEV);
|
return dev_to_tty(outbuf, PAGE_SIZE-1, pp->tty, pp->XXXID, ABBREV_DEV);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@ -767,7 +768,7 @@ static int pr_wname(char *restrict const outbuf, const proc_t *restrict const pp
|
|||||||
* more than one thread waiting in the kernel.
|
* more than one thread waiting in the kernel.
|
||||||
*/
|
*/
|
||||||
if(!(pp->wchan & 0xffffff)) return snprintf(outbuf, COLWID, "%s", "-");
|
if(!(pp->wchan & 0xffffff)) return snprintf(outbuf, COLWID, "%s", "-");
|
||||||
return snprintf(outbuf, COLWID, "%s", wchan(pp->wchan, pp->pid));
|
return snprintf(outbuf, COLWID, "%s", wchan(pp->wchan, pp->XXXID));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pr_nwchan(char *restrict const outbuf, const proc_t *restrict const pp){
|
static int pr_nwchan(char *restrict const outbuf, const proc_t *restrict const pp){
|
||||||
@ -937,7 +938,7 @@ static int pr_suser(char *restrict const outbuf, const proc_t *restrict const pp
|
|||||||
|
|
||||||
|
|
||||||
static int pr_thread(char *restrict const outbuf, const proc_t *restrict const pp){ /* TID tid LWP lwp SPID spid */
|
static int pr_thread(char *restrict const outbuf, const proc_t *restrict const pp){ /* TID tid LWP lwp SPID spid */
|
||||||
return snprintf(outbuf, COLWID, "%u", pp->pid); /* for now... FIXME */
|
return snprintf(outbuf, COLWID, "%u", pp->tid);
|
||||||
}
|
}
|
||||||
static int pr_nlwp(char *restrict const outbuf, const proc_t *restrict const pp){ /* THCNT thcount NLWP nlwp */
|
static int pr_nlwp(char *restrict const outbuf, const proc_t *restrict const pp){ /* THCNT thcount NLWP nlwp */
|
||||||
(void)pp; // FIXME
|
(void)pp; // FIXME
|
||||||
@ -1215,7 +1216,7 @@ static const format_struct format_array[] = {
|
|||||||
{"lstart", "STARTED", pr_lstart, sr_nop, 24, 0, XXX, RIGHT},
|
{"lstart", "STARTED", pr_lstart, sr_nop, 24, 0, XXX, RIGHT},
|
||||||
{"luid", "LUID", pr_nop, sr_nop, 5, 0, LNX, RIGHT}, /* login ID */
|
{"luid", "LUID", pr_nop, sr_nop, 5, 0, LNX, RIGHT}, /* login ID */
|
||||||
{"luser", "LUSER", pr_nop, sr_nop, 8, USR, LNX, USER}, /* login USER */
|
{"luser", "LUSER", pr_nop, sr_nop, 8, USR, LNX, USER}, /* login USER */
|
||||||
{"lwp", "LWP", pr_thread, sr_nop, 5, 0, SUN, PIDMAX|RIGHT},
|
{"lwp", "LWP", pr_thread, sr_tid, 5, 0, SUN, PIDMAX|RIGHT},
|
||||||
{"m_drs", "DRS", pr_drs, sr_drs, 5, MEM, LNx, RIGHT},
|
{"m_drs", "DRS", pr_drs, sr_drs, 5, MEM, LNx, RIGHT},
|
||||||
{"m_dt", "DT", pr_nop, sr_dt, 4, MEM, LNx, RIGHT},
|
{"m_dt", "DT", pr_nop, sr_dt, 4, MEM, LNx, RIGHT},
|
||||||
{"m_lrs", "LRS", pr_nop, sr_lrs, 5, MEM, LNx, RIGHT},
|
{"m_lrs", "LRS", pr_nop, sr_lrs, 5, MEM, LNx, RIGHT},
|
||||||
@ -1250,7 +1251,7 @@ static const format_struct format_array[] = {
|
|||||||
{"pending", "PENDING", pr_sig, sr_nop, 9, 0, BSD, SIGNAL}, /*sig*/
|
{"pending", "PENDING", pr_sig, sr_nop, 9, 0, BSD, SIGNAL}, /*sig*/
|
||||||
{"pgid", "PGID", pr_pgid, sr_pgrp, 5, 0, U98, PIDMAX|RIGHT},
|
{"pgid", "PGID", pr_pgid, sr_pgrp, 5, 0, U98, PIDMAX|RIGHT},
|
||||||
{"pgrp", "PGRP", pr_pgid, sr_pgrp, 5, 0, LNX, PIDMAX|RIGHT},
|
{"pgrp", "PGRP", pr_pgid, sr_pgrp, 5, 0, LNX, PIDMAX|RIGHT},
|
||||||
{"pid", "PID", pr_pid, sr_pid, 5, 0, U98, PIDMAX|RIGHT},
|
{"pid", "PID", pr_pid, sr_tgid, 5, 0, U98, PIDMAX|RIGHT},
|
||||||
{"pmem", "%MEM", pr_pmem, sr_nop, 4, 0, XXX, RIGHT}, /*%mem*/
|
{"pmem", "%MEM", pr_pmem, sr_nop, 4, 0, XXX, RIGHT}, /*%mem*/
|
||||||
{"poip", "-", pr_nop, sr_nop, 1, 0, BSD, RIGHT},
|
{"poip", "-", pr_nop, sr_nop, 1, 0, BSD, RIGHT},
|
||||||
{"policy", "POL", pr_class, sr_sched, 3, 0, DEC, LEFT},
|
{"policy", "POL", pr_class, sr_sched, 3, 0, DEC, LEFT},
|
||||||
@ -1296,7 +1297,7 @@ static const format_struct format_array[] = {
|
|||||||
{"sigmask", "BLOCKED", pr_sigmask, sr_nop, 9, 0, XXX, SIGNAL}, /*blocked*/
|
{"sigmask", "BLOCKED", pr_sigmask, sr_nop, 9, 0, XXX, SIGNAL}, /*blocked*/
|
||||||
{"size", "SZ", pr_swapable, sr_swapable, 1, 0, SCO, RIGHT},
|
{"size", "SZ", pr_swapable, sr_swapable, 1, 0, SCO, RIGHT},
|
||||||
{"sl", "SL", pr_nop, sr_nop, 3, 0, XXX, RIGHT},
|
{"sl", "SL", pr_nop, sr_nop, 3, 0, XXX, RIGHT},
|
||||||
{"spid", "SPID", pr_thread, sr_nop, 5, 0, SGI, PIDMAX|RIGHT},
|
{"spid", "SPID", pr_thread, sr_tid, 5, 0, SGI, PIDMAX|RIGHT},
|
||||||
{"stackp", "STACKP", pr_stackp, sr_nop, 8, 0, LNX, RIGHT}, /*start_stack*/
|
{"stackp", "STACKP", pr_stackp, sr_nop, 8, 0, LNX, RIGHT}, /*start_stack*/
|
||||||
{"start", "STARTED", pr_start, sr_nop, 8, 0, XXX, RIGHT},
|
{"start", "STARTED", pr_start, sr_nop, 8, 0, XXX, RIGHT},
|
||||||
{"start_code", "S_CODE", pr_nop, sr_start_code, 8, 0, LNx, RIGHT},
|
{"start_code", "S_CODE", pr_nop, sr_start_code, 8, 0, LNx, RIGHT},
|
||||||
@ -1316,7 +1317,7 @@ static const format_struct format_array[] = {
|
|||||||
{"sz", "SZ", pr_sz, sr_nop, 5, 0, HPU, RIGHT},
|
{"sz", "SZ", pr_sz, sr_nop, 5, 0, HPU, RIGHT},
|
||||||
{"tdev", "TDEV", pr_nop, sr_nop, 4, 0, XXX, RIGHT},
|
{"tdev", "TDEV", pr_nop, sr_nop, 4, 0, XXX, RIGHT},
|
||||||
{"thcount", "THCNT", pr_nlwp, sr_nop, 5, 0, AIX, RIGHT},
|
{"thcount", "THCNT", pr_nlwp, sr_nop, 5, 0, AIX, RIGHT},
|
||||||
{"tid", "TID", pr_thread, sr_nop, 5, 0, AIX, PIDMAX|RIGHT},
|
{"tid", "TID", pr_thread, sr_tid, 5, 0, AIX, PIDMAX|RIGHT},
|
||||||
{"time", "TIME", pr_time, sr_nop, 8, 0, U98, CUMUL|RIGHT}, /*cputime*/ /* was 6 wide */
|
{"time", "TIME", pr_time, sr_nop, 8, 0, U98, CUMUL|RIGHT}, /*cputime*/ /* was 6 wide */
|
||||||
{"timeout", "TMOUT", pr_timeout, sr_timeout, 5, 0, LNX, RIGHT},
|
{"timeout", "TMOUT", pr_timeout, sr_timeout, 5, 0, LNX, RIGHT},
|
||||||
{"tmout", "TMOUT", pr_timeout, sr_timeout, 5, 0, LNX, RIGHT},
|
{"tmout", "TMOUT", pr_timeout, sr_timeout, 5, 0, LNX, RIGHT},
|
||||||
|
22
ps/parser.c
22
ps/parser.c
@ -264,6 +264,7 @@ static const char *parse_sysv_option(void){
|
|||||||
* SCO UnixWare uses -L too.
|
* SCO UnixWare uses -L too.
|
||||||
*/
|
*/
|
||||||
trace("-L Print LWP (thread) info.\n");
|
trace("-L Print LWP (thread) info.\n");
|
||||||
|
thread_flags |= TF_show_task;
|
||||||
format_modifiers |= FM_L;
|
format_modifiers |= FM_L;
|
||||||
break;
|
break;
|
||||||
case 'M': /* someday, maybe, we will have MAC like SGI's Irix */
|
case 'M': /* someday, maybe, we will have MAC like SGI's Irix */
|
||||||
@ -298,6 +299,7 @@ static const char *parse_sysv_option(void){
|
|||||||
* Also, testing shows PID==SPID for all normal processes.
|
* Also, testing shows PID==SPID for all normal processes.
|
||||||
*/
|
*/
|
||||||
trace("-T adds strange SPID column (old sproc() threads?)\n");
|
trace("-T adds strange SPID column (old sproc() threads?)\n");
|
||||||
|
thread_flags |= TF_show_task;
|
||||||
format_modifiers |= FM_T;
|
format_modifiers |= FM_T;
|
||||||
break;
|
break;
|
||||||
case 'U': /* end */
|
case 'U': /* end */
|
||||||
@ -367,7 +369,8 @@ static const char *parse_sysv_option(void){
|
|||||||
case 'm':
|
case 'm':
|
||||||
trace("-m shows threads.\n");
|
trace("-m shows threads.\n");
|
||||||
/* note that AIX shows 2 lines for a normal process */
|
/* note that AIX shows 2 lines for a normal process */
|
||||||
/* not implemented -- silently ignore the option */
|
thread_flags |= TF_show_proc;
|
||||||
|
thread_flags |= TF_show_task;
|
||||||
break;
|
break;
|
||||||
case 'n': /* end */
|
case 'n': /* end */
|
||||||
trace("-n sets namelist file.\n");
|
trace("-n sets namelist file.\n");
|
||||||
@ -494,6 +497,11 @@ static const char *parse_bsd_option(void){
|
|||||||
return "Option C is reserved.";
|
return "Option C is reserved.";
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
case 'H': // The FreeBSD way (NetBSD:s OpenBSD:k FreeBSD:H -- NIH???)
|
||||||
|
trace("H Print LWP (thread) info.\n"); // was: Use /vmcore as c-dumpfile\n");
|
||||||
|
thread_flags |= TF_show_task; // FIXME: determine if TF_show_proc is needed
|
||||||
|
//format_modifiers |= FM_L; // FIXME: determine if we need something like this
|
||||||
|
break;
|
||||||
case 'L': /* single */
|
case 'L': /* single */
|
||||||
trace("L List all format specifiers\n");
|
trace("L List all format specifiers\n");
|
||||||
exclusive("L");
|
exclusive("L");
|
||||||
@ -587,12 +595,11 @@ static const char *parse_bsd_option(void){
|
|||||||
trace("j job control format\n");
|
trace("j job control format\n");
|
||||||
format_flags |= FF_Bj;
|
format_flags |= FF_Bj;
|
||||||
break;
|
break;
|
||||||
#if 0
|
case 'k': // The OpenBSD way (NetBSD:s OpenBSD:k FreeBSD:H -- NIH???)
|
||||||
case 'k':
|
trace("k Print LWP (thread) info.\n"); // was: Use /vmcore as c-dumpfile\n");
|
||||||
trace("k N/A Use /vmcore as c-dumpfile\n");
|
thread_flags |= TF_show_task; // FIXME: determine if TF_show_proc is needed
|
||||||
return "Obsolete k option not supported.";
|
//format_modifiers |= FM_L; // FIXME: determine if we need something like this
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
case 'l':
|
case 'l':
|
||||||
trace("l Display long format\n");
|
trace("l Display long format\n");
|
||||||
format_flags |= FF_Bl;
|
format_flags |= FF_Bl;
|
||||||
@ -607,7 +614,8 @@ static const char *parse_bsd_option(void){
|
|||||||
defer_sf_option("pmem", SF_B_m);
|
defer_sf_option("pmem", SF_B_m);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* not implemented -- silently ignore the option */
|
thread_flags |= TF_show_proc;
|
||||||
|
thread_flags |= TF_show_task;
|
||||||
break;
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
trace("n Numeric output for WCHAN, and USER replaced by UID\n");
|
trace("n Numeric output for WCHAN, and USER replaced by UID\n");
|
||||||
|
@ -17,8 +17,8 @@
|
|||||||
#include "../proc/readproc.h"
|
#include "../proc/readproc.h"
|
||||||
#include "../proc/procps.h"
|
#include "../proc/procps.h"
|
||||||
|
|
||||||
#define session_leader(p) ((p)->session == (p)->pid)
|
#define session_leader(p) ((p)->session == (p)->tgid)
|
||||||
#define process_group_leader(p) ((p)->pgid == (p)->pid)
|
#define process_group_leader(p) ((p)->pgid == (p)->tgid)
|
||||||
#define without_a_tty(p) ((unsigned short)((p)->tty) == (unsigned short)0)
|
#define without_a_tty(p) ((unsigned short)((p)->tty) == (unsigned short)0)
|
||||||
#define some_other_user(p) ((p)->euid != cached_euid)
|
#define some_other_user(p) ((p)->euid != cached_euid)
|
||||||
#define running(p) (((p)->state=='R')||((p)->state=='D'))
|
#define running(p) (((p)->state=='R')||((p)->state=='D'))
|
||||||
@ -101,7 +101,7 @@ static int proc_was_listed(proc_t *buf){
|
|||||||
break; case SEL_FGID: return_if_match(fgid,gid);
|
break; case SEL_FGID: return_if_match(fgid,gid);
|
||||||
|
|
||||||
break; case SEL_PGRP: return_if_match(pgrp,pid);
|
break; case SEL_PGRP: return_if_match(pgrp,pid);
|
||||||
break; case SEL_PID : return_if_match(pid,pid);
|
break; case SEL_PID : return_if_match(tgid,pid);
|
||||||
break; case SEL_PPID: return_if_match(ppid,ppid);
|
break; case SEL_PPID: return_if_match(ppid,ppid);
|
||||||
break; case SEL_TTY : return_if_match(tty,tty);
|
break; case SEL_TTY : return_if_match(tty,tty);
|
||||||
break; case SEL_SESS: return_if_match(session,pid);
|
break; case SEL_SESS: return_if_match(session,pid);
|
||||||
|
20
top.c
20
top.c
@ -175,7 +175,7 @@ static int Frame_srtflg, // the subject window's sort direction
|
|||||||
* 2 columns each.
|
* 2 columns each.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SCB_NUMx(P_PID, pid)
|
SCB_NUMx(P_PID, XXXID)
|
||||||
SCB_NUMx(P_PPD, ppid)
|
SCB_NUMx(P_PPD, ppid)
|
||||||
SCB_STRx(P_URR, ruser)
|
SCB_STRx(P_URR, ruser)
|
||||||
SCB_NUMx(P_UID, euid)
|
SCB_NUMx(P_UID, euid)
|
||||||
@ -976,7 +976,7 @@ static void prochlp (proc_t *this)
|
|||||||
/* calculate time in this process; the sum of user time (utime) and
|
/* calculate time in this process; the sum of user time (utime) and
|
||||||
system time (stime) -- but PLEASE dont waste time and effort on
|
system time (stime) -- but PLEASE dont waste time and effort on
|
||||||
calcs and saves that go unused, like the old top! */
|
calcs and saves that go unused, like the old top! */
|
||||||
hist_new[Frame_maxtask].pid = this->pid;
|
hist_new[Frame_maxtask].pid = this->tid;
|
||||||
hist_new[Frame_maxtask].tics = tics = (this->utime + this->stime);
|
hist_new[Frame_maxtask].tics = tics = (this->utime + this->stime);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@ -987,9 +987,9 @@ static void prochlp (proc_t *this)
|
|||||||
// find matching entry from previous frame and make ticks elapsed
|
// find matching entry from previous frame and make ticks elapsed
|
||||||
while (lo <= hi) {
|
while (lo <= hi) {
|
||||||
i = (lo + hi) / 2;
|
i = (lo + hi) / 2;
|
||||||
if (this->pid < hist_sav[i].pid)
|
if (this->tid < hist_sav[i].pid)
|
||||||
hi = i - 1;
|
hi = i - 1;
|
||||||
else if (likely(this->pid > hist_sav[i].pid))
|
else if (likely(this->tid > hist_sav[i].pid))
|
||||||
lo = i + 1;
|
lo = i + 1;
|
||||||
else {
|
else {
|
||||||
tics -= hist_sav[i].tics;
|
tics -= hist_sav[i].tics;
|
||||||
@ -1001,7 +1001,7 @@ static void prochlp (proc_t *this)
|
|||||||
{
|
{
|
||||||
HST_t tmp;
|
HST_t tmp;
|
||||||
const HST_t *ptr;
|
const HST_t *ptr;
|
||||||
tmp.pid = this->pid;
|
tmp.pid = this->tid;
|
||||||
ptr = bsearch(&tmp, hist_sav, maxt_sav, sizeof tmp, sort_HST_t);
|
ptr = bsearch(&tmp, hist_sav, maxt_sav, sizeof tmp, sort_HST_t);
|
||||||
if(ptr) tics -= ptr->tics;
|
if(ptr) tics -= ptr->tics;
|
||||||
}
|
}
|
||||||
@ -1066,7 +1066,7 @@ static proc_t **procs_refresh (proc_t **table, int flags)
|
|||||||
savmax = curmax + 1;
|
savmax = curmax + 1;
|
||||||
}
|
}
|
||||||
// this frame's end, but not necessarily end of allocated space
|
// this frame's end, but not necessarily end of allocated space
|
||||||
table[curmax]->pid = -1;
|
table[curmax]->tid = -1;
|
||||||
return table;
|
return table;
|
||||||
|
|
||||||
#undef PTRsz
|
#undef PTRsz
|
||||||
@ -2974,7 +2974,7 @@ static void task_show (const WIN_t *q, const proc_t *p)
|
|||||||
MKCOL((int)p->nice);
|
MKCOL((int)p->nice);
|
||||||
break;
|
break;
|
||||||
case P_PID:
|
case P_PID:
|
||||||
MKCOL((unsigned)p->pid);
|
MKCOL((unsigned)p->XXXID);
|
||||||
break;
|
break;
|
||||||
case P_PPD:
|
case P_PPD:
|
||||||
MKCOL((unsigned)p->ppid);
|
MKCOL((unsigned)p->ppid);
|
||||||
@ -3012,7 +3012,7 @@ static void task_show (const WIN_t *q, const proc_t *p)
|
|||||||
break;
|
break;
|
||||||
case P_TTY:
|
case P_TTY:
|
||||||
{ char tmp[TNYBUFSIZ];
|
{ char tmp[TNYBUFSIZ];
|
||||||
dev_to_tty(tmp, (int)w, p->tty, p->pid, ABBREV_DEV);
|
dev_to_tty(tmp, (int)w, p->tty, p->XXXID, ABBREV_DEV);
|
||||||
MKCOL(tmp);
|
MKCOL(tmp);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -3037,7 +3037,7 @@ static void task_show (const WIN_t *q, const proc_t *p)
|
|||||||
#endif
|
#endif
|
||||||
MKCOL((long)p->wchan);
|
MKCOL((long)p->wchan);
|
||||||
} else {
|
} else {
|
||||||
MKCOL(wchan(p->wchan, p->pid));
|
MKCOL(wchan(p->wchan, p->XXXID));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -3094,7 +3094,7 @@ static void window_show (proc_t **ppt, WIN_t *q, int *lscr)
|
|||||||
lwin = 1;
|
lwin = 1;
|
||||||
i = 0;
|
i = 0;
|
||||||
|
|
||||||
while ( -1 != ppt[i]->pid && *lscr < Max_lines && (!q->winlines || (lwin <= q->winlines)) ) {
|
while ( -1 != ppt[i]->tid && *lscr < Max_lines && (!q->winlines || (lwin <= q->winlines)) ) {
|
||||||
if ((CHKw(q, Show_IDLEPS) || ('S' != ppt[i]->state && 'Z' != ppt[i]->state))
|
if ((CHKw(q, Show_IDLEPS) || ('S' != ppt[i]->state && 'Z' != ppt[i]->state))
|
||||||
&& good_uid(ppt[i]) ) {
|
&& good_uid(ppt[i]) ) {
|
||||||
/*
|
/*
|
||||||
|
4
w.c
4
w.c
@ -146,7 +146,7 @@ static const proc_t *getproc(const utmp_t *restrict const u, const char *restric
|
|||||||
*found_utpid = 0;
|
*found_utpid = 0;
|
||||||
for(; *pptr; pptr++) {
|
for(; *pptr; pptr++) {
|
||||||
const proc_t *restrict const tmp = *pptr;
|
const proc_t *restrict const tmp = *pptr;
|
||||||
if(unlikely(tmp->pid == u->ut_pid)) {
|
if(unlikely(tmp->tgid == u->ut_pid)) {
|
||||||
*found_utpid = 1;
|
*found_utpid = 1;
|
||||||
best = tmp;
|
best = tmp;
|
||||||
}
|
}
|
||||||
@ -158,7 +158,7 @@ static const proc_t *getproc(const utmp_t *restrict const u, const char *restric
|
|||||||
secondbest = tmp;
|
secondbest = tmp;
|
||||||
}
|
}
|
||||||
if(!ignoreuser && uid != tmp->euid && uid != tmp->ruid) continue;
|
if(!ignoreuser && uid != tmp->euid && uid != tmp->ruid) continue;
|
||||||
if(tmp->pid != tmp->tpgid) continue;
|
if(tmp->tgid != tmp->tpgid) continue;
|
||||||
if(best && tmp->start_time <= best->start_time) continue;
|
if(best && tmp->start_time <= best->start_time) continue;
|
||||||
best = tmp;
|
best = tmp;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user