library: cleanup of readproc functions
readproc still had some of the old API hanging around that was good while we were trying it out, but its time to say goodbye: readproc.h removed from public procps.h header file enum ns_type - not used - removed get_ns_name() - not defined - removed get_ns_id() - not defined - removed PROCTAB proc_t only used internal to library readproctab() and 2,3 friends not used - removed proc_data_t was used by readproctab23() - removed readtask() - not used - removed read_cmdline() - copy,renamed and made generic - remove original freeproc() - not used - removed get_proc_status - not used - removed, however there should be a new function created that does this. Given a PID return data about it instead of scanning the entire procfs. Maybe it already does. Left as internal-to-library only functions: readproc(), readeither(), look_up_our_self(), openproc(), closeproc() Updated libprocps.sym to export only what we use.
This commit is contained in:
parent
9fb09268bb
commit
887bb51016
@ -9,7 +9,7 @@ __BEGIN_DECLS
|
|||||||
#define ABBREV_TTY 2 /* remove tty */
|
#define ABBREV_TTY 2 /* remove tty */
|
||||||
#define ABBREV_PTS 4 /* remove pts/ */
|
#define ABBREV_PTS 4 /* remove pts/ */
|
||||||
|
|
||||||
extern unsigned dev_to_tty(char *__restrict ret, unsigned chop, dev_t dev_t_dev, int pid, unsigned int flags);
|
unsigned dev_to_tty(char *__restrict ret, unsigned chop, dev_t dev_t_dev, int pid, unsigned int flags);
|
||||||
|
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,20 +1,10 @@
|
|||||||
LIBPROCPS_0 {
|
LIBPROCPS_0 {
|
||||||
global:
|
global:
|
||||||
closeproc;
|
|
||||||
dev_to_tty;
|
|
||||||
escape_command;
|
escape_command;
|
||||||
escape_str;
|
escape_str;
|
||||||
escape_strlist;
|
escape_strlist;
|
||||||
escaped_copy;
|
escaped_copy;
|
||||||
fatal_proc_unmounted;
|
fatal_proc_unmounted;
|
||||||
look_up_our_self;
|
|
||||||
lookup_wchan;
|
|
||||||
openproc;
|
|
||||||
readproc;
|
|
||||||
readproctab2;
|
|
||||||
readproctab3;
|
|
||||||
readproctab;
|
|
||||||
readtask;
|
|
||||||
procps_cpu_count;
|
procps_cpu_count;
|
||||||
procps_diskstat_dev_count;
|
procps_diskstat_dev_count;
|
||||||
procps_diskstat_dev_get;
|
procps_diskstat_dev_get;
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
#include <proc/meminfo.h>
|
#include <proc/meminfo.h>
|
||||||
#include <proc/namespace.h>
|
#include <proc/namespace.h>
|
||||||
#include <proc/pids.h>
|
#include <proc/pids.h>
|
||||||
#include <proc/readproc.h>
|
|
||||||
#include <proc/readstat.h>
|
#include <proc/readstat.h>
|
||||||
#include <proc/slab.h>
|
#include <proc/slab.h>
|
||||||
#include <proc/sysinfo.h>
|
#include <proc/sysinfo.h>
|
||||||
|
237
proc/readproc.c
237
proc/readproc.c
@ -784,13 +784,6 @@ static void fill_environ_cvt (const char* directory, proc_t *restrict p) {
|
|||||||
p->environ = vectorize_this_str(dst_buffer[0] ? dst_buffer : "-");
|
p->environ = vectorize_this_str(dst_buffer[0] ? dst_buffer : "-");
|
||||||
}
|
}
|
||||||
|
|
||||||
// warning: interface may change
|
|
||||||
int read_cmdline(char *restrict const dst, unsigned sz, unsigned pid) {
|
|
||||||
char path[PROCPATHLEN];
|
|
||||||
snprintf(path, sizeof(path), "/proc/%u", pid);
|
|
||||||
return read_unvectored(dst, sz, path, "cmdline", ' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Provide the means to value proc_t.lxcname (perhaps only with "-") while
|
// Provide the means to value proc_t.lxcname (perhaps only with "-") while
|
||||||
// tracking all names already seen thus avoiding the overhead of repeating
|
// tracking all names already seen thus avoiding the overhead of repeating
|
||||||
@ -1235,61 +1228,6 @@ out:
|
|||||||
return NULL;
|
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) {
|
|
||||||
char path[PROCPATHLEN]; // must hold /proc/2000222000/task/2000222000/cmdline
|
|
||||||
proc_t *ret;
|
|
||||||
proc_t *saved_t;
|
|
||||||
|
|
||||||
saved_t = t;
|
|
||||||
if(!t) t = xcalloc(sizeof *t);
|
|
||||||
else free_acquired(t, 1);
|
|
||||||
|
|
||||||
// 1. got to fake a thread for old kernels
|
|
||||||
#ifdef QUICK_THREADS
|
|
||||||
// 2. for single-threaded processes, this is faster (but must patch up stuff that differs!)
|
|
||||||
if(task_dir_missing || p->nlwp < 2){
|
|
||||||
#else
|
|
||||||
if(task_dir_missing){
|
|
||||||
#endif
|
|
||||||
if(PT->did_fake) goto out;
|
|
||||||
PT->did_fake=1;
|
|
||||||
memcpy(t,p,sizeof(proc_t));
|
|
||||||
// use the per-task pending, not per-tgid pending
|
|
||||||
#ifdef SIGNAL_STRING
|
|
||||||
memcpy(&t->signal, &t->_sigpnd, sizeof t->signal);
|
|
||||||
#else
|
|
||||||
t->signal = t->_sigpnd;
|
|
||||||
#endif
|
|
||||||
#ifdef QUICK_THREADS
|
|
||||||
MK_THREAD(t);
|
|
||||||
#else
|
|
||||||
t->environ = NULL;
|
|
||||||
t->cmdline = vectorize_this_str("n/a");
|
|
||||||
t->cgroup = NULL;
|
|
||||||
t->supgid = NULL;
|
|
||||||
t->supgrp = NULL;
|
|
||||||
#endif
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
// readeither: return a pointer to a proc_t filled with requested info about
|
// readeither: return a pointer to a proc_t filled with requested info about
|
||||||
@ -1386,14 +1324,6 @@ void closeproc(PROCTAB* PT) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// deallocate space allocated by readproc
|
|
||||||
void freeproc(proc_t* p) {
|
|
||||||
if (p) {
|
|
||||||
free_acquired(p, 0);
|
|
||||||
free(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
void look_up_our_self(proc_t *p) {
|
void look_up_our_self(proc_t *p) {
|
||||||
@ -1407,173 +1337,6 @@ void look_up_our_self(proc_t *p) {
|
|||||||
free(ub.buf);
|
free(ub.buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Convenient wrapper around openproc and readproc to slurp in the whole process
|
|
||||||
* table subset satisfying the constraints of flags and the optional PID list.
|
|
||||||
* Free allocated memory with exit(). Access via tab[N]->member. The pointer
|
|
||||||
* list is NULL terminated.
|
|
||||||
*/
|
|
||||||
proc_t** readproctab(unsigned flags, ...) {
|
|
||||||
PROCTAB* PT = NULL;
|
|
||||||
proc_t** tab = NULL;
|
|
||||||
int n = 0;
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, flags); /* pass through args to openproc */
|
|
||||||
if (flags & PROC_UID) {
|
|
||||||
/* temporary variables to ensure that va_arg() instances
|
|
||||||
* are called in the right order
|
|
||||||
*/
|
|
||||||
uid_t* u;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
u = va_arg(ap, uid_t*);
|
|
||||||
i = va_arg(ap, int);
|
|
||||||
PT = openproc(flags, u, i);
|
|
||||||
}
|
|
||||||
else if (flags & PROC_PID)
|
|
||||||
PT = openproc(flags, va_arg(ap, void*)); /* assume ptr sizes same */
|
|
||||||
else
|
|
||||||
PT = openproc(flags);
|
|
||||||
va_end(ap);
|
|
||||||
if (!PT)
|
|
||||||
return 0;
|
|
||||||
do { /* read table: */
|
|
||||||
tab = xrealloc(tab, (n+1)*sizeof(proc_t*));/* realloc as we go, using */
|
|
||||||
tab[n] = readproc(PT, NULL); /* final null to terminate */
|
|
||||||
} while (tab[n++]); /* stop when NULL reached */
|
|
||||||
closeproc(PT);
|
|
||||||
return tab;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try again, this time with threads and selection.
|
|
||||||
proc_data_t *readproctab2(int(*want_proc)(proc_t *buf), int(*want_task)(proc_t *buf), PROCTAB *restrict const PT) {
|
|
||||||
static proc_data_t pd;
|
|
||||||
proc_t** ptab = NULL;
|
|
||||||
unsigned n_proc_alloc = 0;
|
|
||||||
unsigned n_proc = 0;
|
|
||||||
|
|
||||||
proc_t** ttab = NULL;
|
|
||||||
unsigned n_task_alloc = 0;
|
|
||||||
unsigned n_task = 0;
|
|
||||||
|
|
||||||
proc_t* data = NULL;
|
|
||||||
unsigned n_alloc = 0;
|
|
||||||
unsigned long n_used = 0;
|
|
||||||
|
|
||||||
for(;;){
|
|
||||||
proc_t *tmp;
|
|
||||||
if(n_alloc == n_used){
|
|
||||||
//proc_t *old = data;
|
|
||||||
n_alloc = n_alloc*5/4+30; // grow by over 25%
|
|
||||||
data = xrealloc(data,sizeof(proc_t)*n_alloc);
|
|
||||||
memset(data+n_used, 0, sizeof(proc_t)*(n_alloc-n_used));
|
|
||||||
}
|
|
||||||
if(n_proc_alloc == n_proc){
|
|
||||||
//proc_t **old = ptab;
|
|
||||||
n_proc_alloc = n_proc_alloc*5/4+30; // grow by over 25%
|
|
||||||
ptab = xrealloc(ptab,sizeof(proc_t*)*n_proc_alloc);
|
|
||||||
}
|
|
||||||
tmp = readproc(PT, data+n_used);
|
|
||||||
if(!tmp) break;
|
|
||||||
if(!want_proc(tmp)) continue;
|
|
||||||
ptab[n_proc++] = (proc_t*)(n_used++);
|
|
||||||
if(!( PT->flags & PROC_LOOSE_TASKS )) continue;
|
|
||||||
for(;;){
|
|
||||||
proc_t *t;
|
|
||||||
if(n_alloc == n_used){
|
|
||||||
proc_t *old = data;
|
|
||||||
n_alloc = n_alloc*5/4+30; // grow by over 25%
|
|
||||||
data = xrealloc(data,sizeof(proc_t)*n_alloc);
|
|
||||||
// have to move tmp too
|
|
||||||
tmp = data+(tmp-old);
|
|
||||||
memset(data+n_used+1, 0, sizeof(proc_t)*(n_alloc-(n_used+1)));
|
|
||||||
}
|
|
||||||
if(n_task_alloc == n_task){
|
|
||||||
//proc_t **old = ttab;
|
|
||||||
n_task_alloc = n_task_alloc*5/4+1; // grow by over 25%
|
|
||||||
ttab = xrealloc(ttab,sizeof(proc_t*)*n_task_alloc);
|
|
||||||
}
|
|
||||||
t = readtask(PT, tmp, data+n_used);
|
|
||||||
if(!t) break;
|
|
||||||
if(!want_task(t)) continue;
|
|
||||||
ttab[n_task++] = (proc_t*)(n_used++);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pd.proc = ptab;
|
|
||||||
pd.task = ttab;
|
|
||||||
pd.nproc = n_proc;
|
|
||||||
pd.ntask = n_task;
|
|
||||||
if(PT->flags & PROC_LOOSE_TASKS){
|
|
||||||
pd.tab = ttab;
|
|
||||||
pd.n = n_task;
|
|
||||||
}else{
|
|
||||||
pd.tab = ptab;
|
|
||||||
pd.n = n_proc;
|
|
||||||
}
|
|
||||||
// change array indexes to pointers
|
|
||||||
while(n_proc--) ptab[n_proc] = data+(long)(ptab[n_proc]);
|
|
||||||
while(n_task--) ttab[n_task] = data+(long)(ttab[n_task]);
|
|
||||||
|
|
||||||
return &pd;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try try yet again, this time treating processes and threads the same...
|
|
||||||
proc_data_t *readproctab3 (int(*want_task)(proc_t *buf), PROCTAB *restrict const PT) {
|
|
||||||
static proc_data_t pd;
|
|
||||||
proc_t **tab = NULL;
|
|
||||||
unsigned n_alloc = 0;
|
|
||||||
unsigned n_used = 0;
|
|
||||||
proc_t *p = NULL;
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
if (n_alloc == n_used) {
|
|
||||||
n_alloc = n_alloc*5/4+30; // grow by over 25%
|
|
||||||
tab = xrealloc(tab,sizeof(proc_t*)*n_alloc);
|
|
||||||
}
|
|
||||||
// let this next guy allocate the necessary proc_t storage
|
|
||||||
// (or recycle it) since he can't tolerate realloc relocations
|
|
||||||
if (!(p = readeither(PT,p))) break;
|
|
||||||
if (want_task(p)) {
|
|
||||||
tab[n_used++] = p;
|
|
||||||
p = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pd.tab = tab;
|
|
||||||
pd.n = n_used;
|
|
||||||
return &pd;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* get_proc_stats - lookup a single tasks information and fill out a proc_t
|
|
||||||
*
|
|
||||||
* On failure, returns NULL. On success, returns 'p' and 'p' is a valid
|
|
||||||
* and filled out proc_t structure.
|
|
||||||
*/
|
|
||||||
proc_t * get_proc_stats(pid_t pid, proc_t *p) {
|
|
||||||
struct utlbuf_s ub = { NULL, 0 };
|
|
||||||
static char path[32];
|
|
||||||
struct stat statbuf;
|
|
||||||
|
|
||||||
sprintf(path, "/proc/%d", pid);
|
|
||||||
if (stat(path, &statbuf)) {
|
|
||||||
perror("stat");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file2str(path, "stat", &ub) >= 0)
|
|
||||||
stat2proc(ub.buf, p);
|
|
||||||
if (file2str(path, "statm", &ub) >= 0)
|
|
||||||
statm2proc(ub.buf, p);
|
|
||||||
if (file2str(path, "status", &ub) >= 0)
|
|
||||||
status2proc(ub.buf, p, 0);
|
|
||||||
|
|
||||||
free(ub.buf);
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef MK_THREAD
|
#undef MK_THREAD
|
||||||
#undef IS_THREAD
|
#undef IS_THREAD
|
||||||
#undef MAX_BUFSZ
|
#undef MAX_BUFSZ
|
||||||
|
@ -10,7 +10,9 @@
|
|||||||
// in the file COPYING
|
// in the file COPYING
|
||||||
|
|
||||||
|
|
||||||
// #include <proc/pwcache.h>
|
#include <sys/types.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <proc/namespace.h>
|
#include <proc/namespace.h>
|
||||||
|
|
||||||
#define SIGNAL_STRING
|
#define SIGNAL_STRING
|
||||||
@ -31,18 +33,6 @@ __BEGIN_DECLS
|
|||||||
// neither tgid nor tid seemed correct. (in other words, FIXME)
|
// neither tgid nor tid seemed correct. (in other words, FIXME)
|
||||||
#define XXXID tid
|
#define XXXID tid
|
||||||
|
|
||||||
enum ns_type {
|
|
||||||
IPCNS = 0,
|
|
||||||
MNTNS,
|
|
||||||
NETNS,
|
|
||||||
PIDNS,
|
|
||||||
USERNS,
|
|
||||||
UTSNS,
|
|
||||||
NUM_NS // total namespaces (fencepost)
|
|
||||||
};
|
|
||||||
extern const char *get_ns_name(int id);
|
|
||||||
extern int get_ns_id(const char *name);
|
|
||||||
|
|
||||||
// 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)
|
||||||
//
|
//
|
||||||
@ -183,10 +173,6 @@ typedef struct proc_t {
|
|||||||
// from openproc(). The setup is intentionally similar to the dirent interface
|
// from openproc(). The setup is intentionally similar to the dirent interface
|
||||||
// and other system table interfaces (utmp+wtmp come to mind).
|
// and other system table interfaces (utmp+wtmp come to mind).
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#define PROCPATHLEN 64 // must hold /proc/2000222000/task/2000222000/cmdline
|
#define PROCPATHLEN 64 // must hold /proc/2000222000/task/2000222000/cmdline
|
||||||
|
|
||||||
typedef struct PROCTAB {
|
typedef struct PROCTAB {
|
||||||
@ -211,54 +197,6 @@ typedef struct PROCTAB {
|
|||||||
unsigned pathlen; // length of string in the above (w/o '\0')
|
unsigned pathlen; // length of string in the above (w/o '\0')
|
||||||
} PROCTAB;
|
} PROCTAB;
|
||||||
|
|
||||||
// Initialize a PROCTAB structure holding needed call-to-call persistent data
|
|
||||||
extern PROCTAB* openproc(unsigned flags, ... /* pid_t*|uid_t*|dev_t*|char* [, int n] */ );
|
|
||||||
|
|
||||||
typedef struct proc_data_t { // valued by: (else zero)
|
|
||||||
proc_t **tab; // readproctab2, readproctab3
|
|
||||||
proc_t **proc; // readproctab2
|
|
||||||
proc_t **task; // * readproctab2
|
|
||||||
int n; // readproctab2, readproctab3
|
|
||||||
int nproc; // readproctab2
|
|
||||||
int ntask; // * readproctab2
|
|
||||||
} proc_data_t; // * when PROC_LOOSE_TASKS set
|
|
||||||
|
|
||||||
extern proc_data_t *readproctab2(int(*want_proc)(proc_t *buf), int(*want_task)(proc_t *buf), PROCTAB *__restrict const PT);
|
|
||||||
extern proc_data_t *readproctab3(int(*want_task)(proc_t *buf), PROCTAB *__restrict const PT);
|
|
||||||
|
|
||||||
// Convenient wrapper around openproc and readproc to slurp in the whole process
|
|
||||||
// table subset satisfying the constraints of flags and the optional PID list.
|
|
||||||
// Free allocated memory with exit(). Access via tab[N]->member. The pointer
|
|
||||||
// list is NULL terminated.
|
|
||||||
extern proc_t** readproctab(unsigned flags, ... /* same as openproc */ );
|
|
||||||
|
|
||||||
// Clean-up open files, etc from the openproc()
|
|
||||||
extern void closeproc(PROCTAB* PT);
|
|
||||||
|
|
||||||
// Retrieve the next process or task matching the criteria set by the openproc().
|
|
||||||
//
|
|
||||||
// Note: When NULL is used as the readproc 'p', readtask 't' or readeither 'x'
|
|
||||||
// parameter, the library will allocate the necessary proc_t storage.
|
|
||||||
//
|
|
||||||
// Alternatively, you may provide your own reuseable buffer address
|
|
||||||
// in which case that buffer *MUST* be initialized to zero one time
|
|
||||||
// only before first use. Thereafter, the library will manage such
|
|
||||||
// a passed proc_t, freeing any additional acquired memory associated
|
|
||||||
// with the previous process or thread.
|
|
||||||
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);
|
|
||||||
extern proc_t* readeither(PROCTAB *__restrict const PT, proc_t *__restrict x);
|
|
||||||
|
|
||||||
// warning: interface may change
|
|
||||||
extern int read_cmdline(char *__restrict const dst, unsigned sz, unsigned pid);
|
|
||||||
|
|
||||||
extern void look_up_our_self(proc_t *p);
|
|
||||||
|
|
||||||
// Deallocate space allocated by readproc
|
|
||||||
extern void freeproc(proc_t* p);
|
|
||||||
|
|
||||||
// Fill out a proc_t for a single task
|
|
||||||
extern proc_t * get_proc_stats(pid_t pid, proc_t *p);
|
|
||||||
|
|
||||||
// openproc/readproctab:
|
// openproc/readproctab:
|
||||||
//
|
//
|
||||||
@ -305,5 +243,23 @@ extern proc_t * get_proc_stats(pid_t pid, proc_t *p);
|
|||||||
#define PROC_SPARE_3 0x04000000
|
#define PROC_SPARE_3 0x04000000
|
||||||
#define PROC_SPARE_4 0x08000000
|
#define PROC_SPARE_4 0x08000000
|
||||||
|
|
||||||
|
// Function definitions
|
||||||
|
// Initialize a PROCTAB structure holding needed call-to-call persistent data
|
||||||
|
PROCTAB* openproc(unsigned flags, ... /* pid_t*|uid_t*|dev_t*|char* [, int n] */ );
|
||||||
|
// Retrieve the next process or task matching the criteria set by the openproc().
|
||||||
|
//
|
||||||
|
// Note: When NULL is used as the readproc 'p' or readeither 'x'
|
||||||
|
// parameter, the library will allocate the necessary proc_t storage.
|
||||||
|
//
|
||||||
|
// Alternatively, you may provide your own reuseable buffer address
|
||||||
|
// in which case that buffer *MUST* be initialized to zero one time
|
||||||
|
// only before first use. Thereafter, the library will manage such
|
||||||
|
// a passed proc_t, freeing any additional acquired memory associated
|
||||||
|
// with the previous process or thread.
|
||||||
|
proc_t* readproc(PROCTAB *__restrict const PT, proc_t *__restrict p);
|
||||||
|
proc_t* readeither(PROCTAB *__restrict const PT, proc_t *__restrict x);
|
||||||
|
void look_up_our_self(proc_t *p);
|
||||||
|
void closeproc(PROCTAB* PT);
|
||||||
|
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user