EVIL_PROC_HACK
This commit is contained in:
parent
d611d4e66f
commit
8b04273f89
4
NEWS
4
NEWS
@ -1,3 +1,7 @@
|
|||||||
|
procps-3.1.12 --> procps-3.1.13
|
||||||
|
|
||||||
|
no seLinux for now (new kernel interface)
|
||||||
|
|
||||||
procps-3.1.11 --> procps-3.1.12
|
procps-3.1.11 --> procps-3.1.12
|
||||||
|
|
||||||
ps: explicit width ("ps -o pid,wchan:42,args")
|
ps: explicit width ("ps -o pid,wchan:42,args")
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
_3_1_5 {
|
_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; ps_readproc; look_up_our_self; escape_command;
|
readproc; 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;
|
||||||
|
301
proc/readproc.c
301
proc/readproc.c
@ -31,6 +31,7 @@
|
|||||||
#include <fs_secure.h>
|
#include <fs_secure.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// sometimes it's easier to do this manually, w/o gcc helping
|
||||||
#ifdef PROF
|
#ifdef PROF
|
||||||
extern void __cyg_profile_func_enter(void*,void*);
|
extern void __cyg_profile_func_enter(void*,void*);
|
||||||
#define ENTER(x) __cyg_profile_func_enter((void*)x,(void*)x)
|
#define ENTER(x) __cyg_profile_func_enter((void*)x,(void*)x)
|
||||||
@ -40,52 +41,6 @@ extern void __cyg_profile_func_enter(void*,void*);
|
|||||||
#define LEAVE(x)
|
#define LEAVE(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* initiate a process table scan
|
|
||||||
*/
|
|
||||||
PROCTAB* openproc(int flags, ...) {
|
|
||||||
va_list ap;
|
|
||||||
PROCTAB* PT = xmalloc(sizeof(PROCTAB));
|
|
||||||
|
|
||||||
if (flags & PROC_PID)
|
|
||||||
PT->procfs = NULL;
|
|
||||||
else if (!(PT->procfs = opendir("/proc")))
|
|
||||||
return NULL;
|
|
||||||
PT->flags = flags;
|
|
||||||
va_start(ap, flags); /* Init args list */
|
|
||||||
if (flags & PROC_PID)
|
|
||||||
PT->pids = va_arg(ap, pid_t*);
|
|
||||||
else if (flags & PROC_UID) {
|
|
||||||
PT->uids = va_arg(ap, uid_t*);
|
|
||||||
PT->nuid = va_arg(ap, int);
|
|
||||||
}
|
|
||||||
va_end(ap); /* Clean up args list */
|
|
||||||
return PT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* terminate a process table scan
|
|
||||||
*/
|
|
||||||
void closeproc(PROCTAB* PT) {
|
|
||||||
if (PT){
|
|
||||||
if (PT->procfs) closedir(PT->procfs);
|
|
||||||
free(PT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* deallocate the space allocated by readproc if the passed rbuf was NULL
|
|
||||||
*/
|
|
||||||
void freeproc(proc_t* p) {
|
|
||||||
if (!p) /* in case p is NULL */
|
|
||||||
return;
|
|
||||||
/* ptrs are after strings to avoid copying memory when building them. */
|
|
||||||
/* so free is called on the address of the address of strvec[0]. */
|
|
||||||
if (p->cmdline)
|
|
||||||
free((void*)*p->cmdline);
|
|
||||||
if (p->environ)
|
|
||||||
free((void*)*p->environ);
|
|
||||||
free(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
typedef struct status_table_struct {
|
typedef struct status_table_struct {
|
||||||
@ -505,66 +460,23 @@ int read_cmdline(char *restrict const dst, unsigned sz, unsigned pid){
|
|||||||
i < n && l[i] == x; \
|
i < n && l[i] == x; \
|
||||||
} )
|
} )
|
||||||
|
|
||||||
/* readproc: return a pointer to a proc_t filled with requested info about the
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
* next process available matching the restriction set. If no more such
|
// This reads process info from /proc in the traditional way, for one process.
|
||||||
* processes are available, return a null pointer (boolean false). Use the
|
// The pid (tgid? tid?) is already in p, and a path to it in path, with some
|
||||||
* passed buffer instead of allocating space if it is non-NULL. */
|
// room to spare.
|
||||||
|
static proc_t* simple_readproc(PROCTAB *restrict const PT, proc_t *restrict const p, char *restrict const path) {
|
||||||
|
static struct stat sb; // stat() buffer
|
||||||
|
static char sbuf[1024]; // buffer for stat,statm
|
||||||
|
unsigned flags = PT->flags;
|
||||||
|
|
||||||
/* This is optimized so that if a PID list is given, only those files are
|
|
||||||
* searched for in /proc. If other lists are given in addition to the PID list,
|
|
||||||
* the same logic can follow through as for the no-PID list case. This is
|
|
||||||
* fairly complex, but it does try to not to do any unnecessary work.
|
|
||||||
*/
|
|
||||||
proc_t* readproc(PROCTAB* PT, proc_t* p) {
|
|
||||||
static struct direct *ent; /* dirent handle */
|
|
||||||
static struct stat sb; /* stat buffer */
|
|
||||||
static char path[32], sbuf[1024]; /* bufs for stat,statm */
|
|
||||||
#ifdef FLASK_LINUX
|
|
||||||
security_id_t secsid;
|
|
||||||
#endif
|
|
||||||
pid_t pid; // saved until we have a proc_t allocated for sure
|
|
||||||
|
|
||||||
/* loop until a proc matching restrictions is found or no more processes */
|
|
||||||
/* I know this could be a while loop -- this way is easier to indent ;-) */
|
|
||||||
next_proc: /* get next PID for consideration */
|
|
||||||
|
|
||||||
/*printf("PT->flags is 0x%08x\n", PT->flags);*/
|
|
||||||
#define flags (PT->flags)
|
|
||||||
|
|
||||||
if (flags & PROC_PID) {
|
|
||||||
pid = *(PT->pids)++;
|
|
||||||
if (unlikely(!pid)) return NULL;
|
|
||||||
snprintf(path, sizeof path, "/proc/%d", pid);
|
|
||||||
} else { /* get next numeric /proc ent */
|
|
||||||
for (;;) {
|
|
||||||
ent = readdir(PT->procfs);
|
|
||||||
if(unlikely(unlikely(!ent) || unlikely(!ent->d_name))) return NULL;
|
|
||||||
if(likely( likely(*ent->d_name > '0') && likely(*ent->d_name <= '9') )) break;
|
|
||||||
}
|
|
||||||
pid = strtoul(ent->d_name, NULL, 10);
|
|
||||||
memcpy(path, "/proc/", 6);
|
|
||||||
strcpy(path+6, ent->d_name); // trust /proc to not contain evil top-level entries
|
|
||||||
// snprintf(path, sizeof path, "/proc/%s", ent->d_name);
|
|
||||||
}
|
|
||||||
#ifdef FLASK_LINUX
|
|
||||||
if ( stat_secure(path, &sb, &secsid) == -1 ) /* no such dirent (anymore) */
|
|
||||||
#else
|
|
||||||
if (unlikely(stat(path, &sb) == -1)) /* no such dirent (anymore) */
|
if (unlikely(stat(path, &sb) == -1)) /* no such dirent (anymore) */
|
||||||
#endif
|
|
||||||
goto next_proc;
|
goto next_proc;
|
||||||
|
|
||||||
if ((flags & PROC_UID) && !XinLN(uid_t, sb.st_uid, PT->uids, PT->nuid))
|
if ((flags & PROC_UID) && !XinLN(uid_t, sb.st_uid, PT->uids, PT->nuid))
|
||||||
goto next_proc; /* not one of the requested uids */
|
goto next_proc; /* not one of the requested uids */
|
||||||
|
|
||||||
if (!p)
|
|
||||||
p = xcalloc(p, sizeof *p); /* passed buf or alloced mem */
|
|
||||||
|
|
||||||
p->euid = sb.st_uid; /* need a way to get real uid */
|
p->euid = sb.st_uid; /* need a way to get real uid */
|
||||||
p->egid = sb.st_gid; /* need a way to get real gid */
|
p->egid = sb.st_gid; /* need a way to get real gid */
|
||||||
#ifdef FLASK_LINUX
|
|
||||||
p->secsid = secsid;
|
|
||||||
#endif
|
|
||||||
p->pid = pid;
|
|
||||||
|
|
||||||
if (flags & PROC_FILLSTAT) { /* read, parse /proc/#/stat */
|
if (flags & PROC_FILLSTAT) { /* read, parse /proc/#/stat */
|
||||||
if (unlikely( file2str(path, "stat", sbuf, sizeof sbuf) == -1 ))
|
if (unlikely( file2str(path, "stat", sbuf, sizeof sbuf) == -1 ))
|
||||||
@ -614,10 +526,54 @@ next_proc: /* get next PID for consideration */
|
|||||||
p->environ = NULL;
|
p->environ = NULL;
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
|
next_proc:
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
#undef flags
|
|
||||||
|
|
||||||
/* ps_readproc: return a pointer to a proc_t filled with requested info about the
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// This finds processes in /proc in the traditional way.
|
||||||
|
// Return non-zero on success.
|
||||||
|
static int simple_nextpid(PROCTAB *restrict const PT, proc_t *restrict const p, char *restrict const path) {
|
||||||
|
static struct direct *ent; /* dirent handle */
|
||||||
|
for (;;) {
|
||||||
|
ent = readdir(PT->procfs);
|
||||||
|
if(unlikely(unlikely(!ent) || unlikely(!ent->d_name))) return 0;
|
||||||
|
if(likely( likely(*ent->d_name > '0') && likely(*ent->d_name <= '9') )) break;
|
||||||
|
}
|
||||||
|
p->pid = strtoul(ent->d_name, NULL, 10);
|
||||||
|
memcpy(path, "/proc/", 6);
|
||||||
|
strcpy(path+6, ent->d_name); // trust /proc to not contain evil top-level entries
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PROCPATHLEN 64 // must hold /proc/2000222000/task/2000222000/cmdline
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// This "finds" processes in a list that was given to openproc().
|
||||||
|
// Return non-zero on success. (pid was handy)
|
||||||
|
static int listed_nextpid(PROCTAB *restrict const PT, proc_t *restrict const p, char *restrict const path) {
|
||||||
|
pid_t pid = *(PT->pids)++;
|
||||||
|
if(likely( pid )){
|
||||||
|
snprintf(path, PROCPATHLEN, "/proc/%d", pid);
|
||||||
|
p->pid = pid;
|
||||||
|
}
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// This "finds" processes by guessing every possible one of them.
|
||||||
|
// 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) {
|
||||||
|
pid_t pid = --PT->u;
|
||||||
|
if(likely( pid )){
|
||||||
|
snprintf(path, PROCPATHLEN, "/proc/%d", pid);
|
||||||
|
p->pid = pid;
|
||||||
|
}
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/* readproc: return a pointer to a proc_t filled with requested info about the
|
||||||
* next process available matching the restriction set. If no more such
|
* next process available matching the restriction set. If no more such
|
||||||
* processes are available, return a null pointer (boolean false). Use the
|
* processes are available, return a null pointer (boolean false). Use the
|
||||||
* passed buffer instead of allocating space if it is non-NULL. */
|
* passed buffer instead of allocating space if it is non-NULL. */
|
||||||
@ -627,99 +583,86 @@ next_proc: /* get next PID for consideration */
|
|||||||
* the same logic can follow through as for the no-PID list case. This is
|
* the same logic can follow through as for the no-PID list case. This is
|
||||||
* 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* ps_readproc(PROCTAB* PT, proc_t* p) {
|
proc_t* readproc(PROCTAB *restrict const PT, proc_t *restrict p) {
|
||||||
static struct direct *ent; /* dirent handle */
|
static char path[PROCPATHLEN]; // must hold /proc/2000222000/task/2000222000/cmdline
|
||||||
static struct stat sb; /* stat buffer */
|
proc_t *ret;
|
||||||
static char path[32], sbuf[1024]; /* bufs for stat,statm */
|
proc_t *saved_p;
|
||||||
#ifdef FLASK_LINUX
|
|
||||||
security_id_t secsid;
|
|
||||||
#endif
|
|
||||||
pid_t pid; // saved until we have a proc_t allocated for sure
|
|
||||||
|
|
||||||
/* loop until a proc matching restrictions is found or no more processes */
|
saved_p = p;
|
||||||
/* I know this could be a while loop -- this way is easier to indent ;-) */
|
if(!p) p = xcalloc(p, sizeof *p); /* passed buf or alloced mem */
|
||||||
next_proc: /* get next PID for consideration */
|
|
||||||
|
|
||||||
/*printf("PT->flags is 0x%08x\n", PT->flags);*/
|
|
||||||
#define flags (PT->flags)
|
|
||||||
|
|
||||||
for(;;){
|
for(;;){
|
||||||
ent = readdir(PT->procfs);
|
// fills in the path and the p->pid
|
||||||
if(unlikely(unlikely(!ent) || unlikely(!ent->d_name))) return NULL;
|
if (unlikely(! PT->finder(PT,p,path) )) goto out;
|
||||||
if(likely( likely(*ent->d_name > '0') && likely(*ent->d_name <= '9') )) break;
|
|
||||||
}
|
|
||||||
pid = strtoul(ent->d_name, NULL, 10);
|
|
||||||
memcpy(path, "/proc/", 6);
|
|
||||||
strcpy(path+6, ent->d_name); // trust /proc to not contain evil top-level entries
|
|
||||||
// snprintf(path, sizeof path, "/proc/%s", ent->d_name);
|
|
||||||
|
|
||||||
#ifdef FLASK_LINUX
|
// go read the process data
|
||||||
if (stat_secure(path, &sb, &secsid) == -1) /* no such dirent (anymore) */
|
ret = PT->reader(PT,p,path);
|
||||||
#else
|
if(ret) return ret;
|
||||||
if (stat(path, &sb) == -1) /* no such dirent (anymore) */
|
|
||||||
#endif
|
|
||||||
goto next_proc;
|
|
||||||
|
|
||||||
if (!p)
|
|
||||||
p = xcalloc(p, sizeof *p); /* passed buf or alloced mem */
|
|
||||||
|
|
||||||
p->euid = sb.st_uid; /* need a way to get real uid */
|
|
||||||
p->egid = sb.st_gid; /* need a way to get real gid */
|
|
||||||
#ifdef FLASK_LINUX
|
|
||||||
p->secsid = secsid;
|
|
||||||
#endif
|
|
||||||
p->pid = pid;
|
|
||||||
|
|
||||||
if ((file2str(path, "stat", sbuf, sizeof sbuf)) == -1)
|
|
||||||
goto next_proc; /* error reading /proc/#/stat */
|
|
||||||
stat2proc(sbuf, p); /* parse /proc/#/stat */
|
|
||||||
|
|
||||||
if (flags & PROC_FILLMEM) { /* read, parse /proc/#/statm */
|
|
||||||
if ((file2str(path, "statm", sbuf, sizeof sbuf)) != -1 )
|
|
||||||
statm2proc(sbuf, p); /* ignore statm errors here */
|
|
||||||
} /* statm fields just zero */
|
|
||||||
|
|
||||||
/* if (flags & PROC_FILLSTATUS) { */ /* read, parse /proc/#/status */
|
|
||||||
if ((file2str(path, "status", sbuf, sizeof sbuf)) != -1 ){
|
|
||||||
status2proc(sbuf, p);
|
|
||||||
}
|
|
||||||
/* }*/
|
|
||||||
|
|
||||||
/* some number->text resolving which is time consuming */
|
|
||||||
if (flags & PROC_FILLUSR){
|
|
||||||
strncpy(p->euser, user_from_uid(p->euid), sizeof p->euser);
|
|
||||||
/* if(flags & PROC_FILLSTATUS) { */
|
|
||||||
strncpy(p->ruser, user_from_uid(p->ruid), sizeof p->ruser);
|
|
||||||
strncpy(p->suser, user_from_uid(p->suid), sizeof p->suser);
|
|
||||||
strncpy(p->fuser, user_from_uid(p->fuid), sizeof p->fuser);
|
|
||||||
/* }*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* some number->text resolving which is time consuming */
|
out:
|
||||||
if (flags & PROC_FILLGRP){
|
if(!saved_p) free(p);
|
||||||
strncpy(p->egroup, group_from_gid(p->egid), sizeof p->egroup);
|
return NULL;
|
||||||
/* if(flags & PROC_FILLSTATUS) { */
|
|
||||||
strncpy(p->rgroup, group_from_gid(p->rgid), sizeof p->rgroup);
|
|
||||||
strncpy(p->sgroup, group_from_gid(p->sgid), sizeof p->sgroup);
|
|
||||||
strncpy(p->fgroup, group_from_gid(p->fgid), sizeof p->fgroup);
|
|
||||||
/* }*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((flags & PROC_FILLCOM) || (flags & PROC_FILLARG)) /* read+parse /proc/#/cmdline */
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
p->cmdline = file2strvec(path, "cmdline");
|
|
||||||
else
|
|
||||||
p->cmdline = NULL;
|
|
||||||
|
|
||||||
if (flags & PROC_FILLENV) /* read+parse /proc/#/environ */
|
// initiate a process table scan
|
||||||
p->environ = file2strvec(path, "environ");
|
PROCTAB* openproc(int flags, ...) {
|
||||||
else
|
va_list ap;
|
||||||
p->environ = NULL;
|
PROCTAB* PT = xmalloc(sizeof(PROCTAB));
|
||||||
|
|
||||||
return p;
|
PT->reader = simple_readproc;
|
||||||
|
if (flags & PROC_PID){
|
||||||
|
PT->procfs = NULL;
|
||||||
|
PT->finder = listed_nextpid;
|
||||||
|
}else{
|
||||||
|
PT->procfs = opendir("/proc");
|
||||||
|
if(!PT->procfs) return NULL;
|
||||||
|
PT->finder = simple_nextpid;
|
||||||
|
}
|
||||||
|
PT->flags = flags;
|
||||||
|
|
||||||
|
if(getenv("EVIL_PROC_HACK")){
|
||||||
|
PT->finder = stupid_nextpid;
|
||||||
|
PT->u = 10000;
|
||||||
|
}
|
||||||
|
|
||||||
|
va_start(ap, flags); /* Init args list */
|
||||||
|
if (flags & PROC_PID)
|
||||||
|
PT->pids = va_arg(ap, pid_t*);
|
||||||
|
else if (flags & PROC_UID) {
|
||||||
|
PT->uids = va_arg(ap, uid_t*);
|
||||||
|
PT->nuid = va_arg(ap, int);
|
||||||
|
}
|
||||||
|
va_end(ap); /* Clean up args list */
|
||||||
|
|
||||||
|
return PT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// terminate a process table scan
|
||||||
|
void closeproc(PROCTAB* PT) {
|
||||||
|
if (PT){
|
||||||
|
if (PT->procfs) closedir(PT->procfs);
|
||||||
|
free(PT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// deallocate the space allocated by readproc if the passed rbuf was NULL
|
||||||
|
void freeproc(proc_t* p) {
|
||||||
|
if (!p) /* in case p is NULL */
|
||||||
|
return;
|
||||||
|
/* ptrs are after strings to avoid copying memory when building them. */
|
||||||
|
/* so free is called on the address of the address of strvec[0]. */
|
||||||
|
if (p->cmdline)
|
||||||
|
free((void*)*p->cmdline);
|
||||||
|
if (p->environ)
|
||||||
|
free((void*)*p->environ);
|
||||||
|
free(p);
|
||||||
}
|
}
|
||||||
#undef flags
|
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
void look_up_our_self(proc_t *p) {
|
void look_up_our_self(proc_t *p) {
|
||||||
char sbuf[1024];
|
char sbuf[1024];
|
||||||
|
|
||||||
|
@ -150,17 +150,18 @@ typedef struct proc_t {
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
typedef struct PROCTAB {
|
typedef struct PROCTAB {
|
||||||
DIR* procfs;
|
DIR* procfs;
|
||||||
int flags;
|
int(*finder)(struct PROCTAB *restrict const, proc_t *restrict const, char *restrict const);
|
||||||
|
proc_t*(*reader)(struct PROCTAB *restrict const, proc_t *restrict const, char *restrict const);
|
||||||
|
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 */
|
||||||
int nuid; /* cannot really sentinel-terminate unsigned short[] */
|
int nuid; /* cannot really sentinel-terminate unsigned short[] */
|
||||||
#ifdef FLASK_LINUX
|
int i; // generic
|
||||||
security_id_t* sids; /* SIDs of the procs */
|
unsigned u; // generic
|
||||||
#endif
|
void * vp; // generic
|
||||||
} PROCTAB;
|
} PROCTAB;
|
||||||
|
|
||||||
/* initialize a PROCTAB structure holding needed call-to-call persistent data
|
// initialize a PROCTAB structure holding needed call-to-call persistent data
|
||||||
*/
|
|
||||||
extern PROCTAB* openproc(int flags, ... /* pid_t*|uid_t*|dev_t*|char* [, int n] */ );
|
extern PROCTAB* openproc(int flags, ... /* pid_t*|uid_t*|dev_t*|char* [, int n] */ );
|
||||||
|
|
||||||
|
|
||||||
@ -171,14 +172,11 @@ extern PROCTAB* openproc(int flags, ... /* pid_t*|uid_t*|dev_t*|char* [, int n]
|
|||||||
*/
|
*/
|
||||||
extern proc_t** readproctab(int flags, ... /* same as openproc */ );
|
extern proc_t** readproctab(int flags, ... /* same as openproc */ );
|
||||||
|
|
||||||
/* clean-up open files, etc from the openproc()
|
// clean-up open files, etc from the 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* PT, proc_t* return_buf);
|
|
||||||
extern proc_t* ps_readproc(PROCTAB* PT, proc_t* return_buf);
|
|
||||||
|
|
||||||
// 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);
|
||||||
|
@ -71,6 +71,8 @@
|
|||||||
|
|
||||||
/******************* PS DEFINE *******************/
|
/******************* PS DEFINE *******************/
|
||||||
|
|
||||||
|
#define needs_for_select (PROC_FILLSTAT | PROC_FILLSTATUS)
|
||||||
|
|
||||||
/* 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
|
||||||
|
10
ps/display.c
10
ps/display.c
@ -242,13 +242,13 @@ static void compute_needs(void){
|
|||||||
static void simple_spew(void){
|
static void simple_spew(void){
|
||||||
proc_t buf;
|
proc_t buf;
|
||||||
PROCTAB* ptp;
|
PROCTAB* ptp;
|
||||||
ptp = openproc(needs_for_format | needs_for_sort);
|
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");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
memset(&buf, '#', sizeof(proc_t));
|
memset(&buf, '#', sizeof(proc_t));
|
||||||
while(ps_readproc(ptp,&buf)){
|
while(readproc(ptp,&buf)){
|
||||||
if(want_this_proc(&buf)) show_one_proc(&buf);
|
if(want_this_proc(&buf)) show_one_proc(&buf);
|
||||||
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
|
||||||
@ -381,16 +381,16 @@ 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 */
|
||||||
ptp = openproc(needs_for_format | needs_for_sort);
|
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");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
while((retbuf = ps_readproc(ptp,retbuf))){
|
while((retbuf = readproc(ptp,retbuf))){
|
||||||
if(want_this_proc(retbuf)){
|
if(want_this_proc(retbuf)){
|
||||||
fill_pcpu(retbuf); // in case we might sort by %cpu
|
fill_pcpu(retbuf); // in case we might sort by %cpu
|
||||||
processes[n++] = retbuf;
|
processes[n++] = retbuf;
|
||||||
retbuf = NULL; /* NULL asks ps_readproc to allocate */
|
retbuf = NULL; // NULL asks readproc to allocate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(retbuf) free(retbuf);
|
if(retbuf) free(retbuf);
|
||||||
|
Loading…
Reference in New Issue
Block a user