This commit is contained in:
albert 2003-02-17 00:57:15 +00:00
parent f082411c7d
commit 4a54e25aca
5 changed files with 257 additions and 99 deletions

1
NEWS
View File

@ -1,5 +1,6 @@
procps-3.1.5 --> procps-3.1.6
handle the 2.5.61 kernel
top: memory leak fixed
ps: new --ppid option selects by PPID
watch: new --no-title option #179862

View File

@ -14,19 +14,22 @@ LIBOBJ := $(LIBSRC:.c=.o)
#ALL += proc/lib$(NAME).a
#INSTALL += $(usr/lib)/lib$(NAME).a # plus $(usr/include)$(NAME) gunk
FPIC := -fpic
ifeq ($(SHARED),1)
ALL += proc/$(SONAME)
INSTALL += $(lib)/$(SONAME)
FPIC := -fpic
LIBFLAGS := -DSHARED=1 $(FPIC)
LIBPROC := proc/$(SONAME)
else
ALL += proc/lib$(NAME).a
LIBFLAGS := -DSHARED=0
LIBPROC := proc/lib$(NAME).a
endif
# Separate rule for this directory, to use -fpic or -fPIC
$(filter-out proc/version.o,$(LIBOBJ)): proc/%.o: proc/%.c
$(CC) -c $(CFLAGS) $(FPIC) $< -o $@
$(CC) -c $(CFLAGS) $(LIBFLAGS) $< -o $@
LIB_X := COPYING module.mk library.map
TARFILES += $(LIBSRC) $(LIBHDR) $(addprefix proc/,$(LIB_X))
@ -71,4 +74,4 @@ $(lib)/$(SONAME) : proc/$(SONAME)
proc/version.o: proc/version.c proc/version.h
$(CC) $(CFLAGS) $(FPIC) -DVERSION=\"$(VERSION)\" -DSUBVERSION=\"$(SUBVERSION)\" -DMINORVERSION=\"$(MINORVERSION)\" -c -o $@ $<
$(CC) $(CFLAGS) $(LIBFLAGS) -DVERSION=\"$(VERSION)\" -DSUBVERSION=\"$(SUBVERSION)\" -DMINORVERSION=\"$(MINORVERSION)\" -c -o $@ $<

View File

@ -64,6 +64,11 @@
#define expected(x,y) (x)
#endif
#if SHARED==1 && (__GNUC__ > 2 || __GNUC_MINOR__ >= 96)
#define LABEL_OFFSET
#endif
// marks old junk, to warn non-procps library users
#if ( __GNUC__ == 3 && __GNUC_MINOR__ > 0 ) || __GNUC__ > 3
#define OBSOLETE __attribute__((deprecated))

View File

@ -31,6 +31,15 @@
#include <fs_secure.h>
#endif
#ifdef PROF
extern void __cyg_profile_func_enter(void*,void*);
#define ENTER(x) __cyg_profile_func_enter((void*)x,(void*)x)
#define LEAVE(x) __cyg_profile_func_exit((void*)x,(void*)x)
#else
#define ENTER(x)
#define LEAVE(x)
#endif
/* initiate a process table scan
*/
PROCTAB* openproc(int flags, ...) {
@ -77,103 +86,237 @@ void freeproc(proc_t* p) {
}
// 2.5.xx looks like:
//
// "State:\t%s\n"
// "Tgid:\t%d\n"
// "Pid:\t%d\n"
// "PPid:\t%d\n"
// "TracerPid:\t%d\n"
///////////////////////////////////////////////////////////////////////////
static void status2proc(const char *S, proc_t *restrict P){
char* tmp;
unsigned i;
// The cmd is escaped, with \\ and \n for backslash and newline.
// It certainly may contain "VmSize:" and similar crap.
if(unlikely(strncmp("Name:\t",S,6))) fprintf(stderr, "Internal error!\n");
S += 6;
i = 0;
while(i < sizeof P->cmd - 1){
int c = *S++;
if(unlikely(c=='\n')) break;
if(unlikely(c=='\0')) return; // should never happen
if(unlikely(c=='\\')){
c = *S++;
if(c=='\n') break; // should never happen
if(!c) break; // should never happen
if(c=='n') c='\n'; // else we assume it is '\\'
}
P->cmd[i++] = c;
}
P->cmd[i] = '\0';
tmp = strstr (S,"State:\t");
if(likely(tmp)) P->state = tmp[7];
else fprintf(stderr, "Internal error!\n");
tmp = strstr (S,"PPid:");
if(likely(tmp)) sscanf (tmp,
"PPid:\t%d\n",
&P->ppid
);
else fprintf(stderr, "Internal error!\n");
tmp = strstr (S,"Uid:");
if(likely(tmp)) sscanf (tmp,
"Uid:\t%d\t%d\t%d\t%d",
&P->ruid, &P->euid, &P->suid, &P->fuid
);
else fprintf(stderr, "Internal error!\n");
tmp = strstr (S,"Gid:");
if(likely(tmp)) sscanf (tmp,
"Gid:\t%d\t%d\t%d\t%d",
&P->rgid, &P->egid, &P->sgid, &P->fgid
);
else fprintf(stderr, "Internal error!\n");
tmp = strstr (S,"VmSize:");
if(likely(tmp)) sscanf (tmp,
"VmSize: %lu kB\n"
"VmLck: %lu kB\n"
"VmRSS: %lu kB\n"
"VmData: %lu kB\n"
"VmStk: %lu kB\n"
"VmExe: %lu kB\n"
"VmLib: %lu kB\n",
&P->vm_size, &P->vm_lock, &P->vm_rss, &P->vm_data,
&P->vm_stack, &P->vm_exe, &P->vm_lib
);
else /* looks like an annoying kernel thread */
{
P->vm_size = 0;
P->vm_lock = 0;
P->vm_rss = 0;
P->vm_data = 0;
P->vm_stack = 0;
P->vm_exe = 0;
P->vm_lib = 0;
}
// 2.1 SigPnd SigBlk SigIgn SigCat ("SigCat")
// other SigPnd SigBlk SigIgn SigCgt
// 2.5+ SigPnd ShdPnd SigBlk SigIgn SigCgt
tmp = strstr (S,"SigPnd:");
if(likely(tmp)) sscanf (tmp,
#ifdef SIGNAL_STRING
"SigPnd: %s SigBlk: %s SigIgn: %s %*s %s",
P->signal, P->blocked, P->sigignore, P->sigcatch
typedef struct status_table_struct {
unsigned char name[6]; // /proc/*/status field name
short len; // name length
#ifdef LABEL_OFFSET
long offset; // jump address offset
#else
"SigPnd: %Lx SigBlk: %Lx SigIgn: %Lx %*s %Lx",
&P->signal, &P->blocked, &P->sigignore, &P->sigcatch
void *addr;
#endif
);
else fprintf(stderr, "Internal error!\n");
} status_table_struct;
#ifdef LABEL_OFFSET
#define F(x) {#x, sizeof(#x)-1, (int)(&&case_##x-&&base)},
#else
#define F(x) {#x, sizeof(#x)-1, &&case_##x},
#endif
#define NUL {"", 0, 0},
// Derived from:
// gperf -7 --language=ANSI-C --key-positions=1,3,4 -C -n -c sml.gperf
static void status2proc(char *S, proc_t *restrict P){
static const unsigned char asso[] = {
56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 15, 56, 56, 56, 56, 56,
56, 56, 25, 30, 15, 3, 56, 5, 56, 3, 56, 56, 3, 56, 10, 56,
18, 56, 13, 0, 30, 25, 0, 56, 56, 56, 56, 56, 56, 56, 56, 56,
56, 30, 56, 8, 0, 0, 56, 25, 56, 5, 56, 56, 56, 0, 56, 56,
56, 56, 56, 56, 0, 56, 56, 56, 0, 56, 56, 56, 56, 56, 56, 56
};
static const status_table_struct table[] = {
F(VmStk)
NUL
NUL
F(VmExe)
NUL
F(VmSize)
NUL
NUL
F(VmLib)
NUL
F(Name)
F(VmLck)
NUL
F(VmRSS)
NUL
NUL
NUL
NUL
F(ShdPnd)
NUL
F(Gid)
NUL
NUL
F(PPid)
NUL
NUL
NUL
NUL
F(SigIgn)
NUL
F(State)
NUL
NUL
F(Pid)
NUL
F(Tgid)
NUL
NUL
NUL
NUL
F(Uid)
NUL
NUL
F(SigPnd)
NUL
F(VmData)
NUL
NUL
NUL
NUL
F(SigBlk)
NUL
NUL
NUL
NUL
F(SigCgt)
NUL
NUL
NUL
NUL
NUL
NUL
NUL
NUL
};
#undef F
#undef NUL
ENTER(0x220);
P->vm_size = 0;
P->vm_lock = 0;
P->vm_rss = 0;
P->vm_data = 0;
P->vm_stack= 0;
P->vm_exe = 0;
P->vm_lib = 0;
goto base;
for(;;){
char *colon;
status_table_struct entry;
// advance to next line
S = strchr(S, '\n');
if(unlikely(!S)) break; // if no newline
S++;
// examine a field name (hash and compare)
base:
if(unlikely(!*S)) break;
entry = table[63 & (asso[S[3]] + asso[S[2]] + asso[S[0]])];
colon = strchr(S, ':');
if(unlikely(!colon)) break;
if(unlikely(colon[1]!='\t')) break;
if(unlikely(colon-S != entry.len)) continue;
if(unlikely(memcmp(entry.name,S,colon-S))) continue;
S = colon+2; // past the '\t'
#ifdef LABEL_OFFSET
goto *(&&base + entry.offset);
#else
goto *entry.addr;
#endif
case_Gid:
P->rgid = strtol(S,&S,10);
P->egid = strtol(S,&S,10);
P->sgid = strtol(S,&S,10);
P->fgid = strtol(S,&S,10);
continue;
case_Name:{
int i = 0;
while(i < sizeof P->cmd - 1){
int c = *S++;
if(unlikely(c=='\n')) break;
if(unlikely(c=='\0')) return; // should never happen
if(unlikely(c=='\\')){
c = *S++;
if(c=='\n') break; // should never happen
if(!c) break; // should never happen
if(c=='n') c='\n'; // else we assume it is '\\'
}
P->cmd[i++] = c;
}
P->cmd[i] = '\0';
continue;
}
case_PPid:
P->ppid = strtol(S,&S,10);
continue;
case_Pid:
P->pid = strtol(S,&S,10);
continue;
case_ShdPnd:
memcpy(P->signal, S, 16);
P->signal[16] = '\0';
continue;
case_SigBlk:
memcpy(P->blocked, S, 16);
P->blocked[16] = '\0';
continue;
case_SigCgt:
memcpy(P->sigcatch, S, 16);
P->sigcatch[16] = '\0';
continue;
case_SigIgn:
memcpy(P->sigignore, S, 16);
P->sigignore[16] = '\0';
continue;
case_SigPnd:
memcpy(P->signal, S, 16);
P->signal[16] = '\0';
continue;
case_State:
P->state = *S;
continue;
case_Tgid:
P->tgid = strtol(S,&S,10);
continue;
case_Uid:
P->ruid = strtol(S,&S,10);
P->euid = strtol(S,&S,10);
P->suid = strtol(S,&S,10);
P->fuid = strtol(S,&S,10);
continue;
case_VmData:
P->vm_data = strtol(S,&S,10);
continue;
case_VmExe:
P->vm_exe = strtol(S,&S,10);
continue;
case_VmLck:
P->vm_lock = strtol(S,&S,10);
continue;
case_VmLib:
P->vm_lib = strtol(S,&S,10);
continue;
case_VmRSS:
P->vm_rss = strtol(S,&S,10);
continue;
case_VmSize:
P->vm_size = strtol(S,&S,10);
continue;
case_VmStk:
P->vm_stack = strtol(S,&S,10);
continue;
}
LEAVE(0x220);
}
///////////////////////////////////////////////////////////////////////
// Reads /proc/*/stat files, being careful not to trip over processes with
// names like ":-) 1 2 3 4 5 6".
@ -181,6 +324,8 @@ static void stat2proc(const char* S, proc_t *restrict P) {
unsigned num;
char* tmp;
ENTER(0x160);
/* fill in default values for older kernels */
P->exit_signal = SIGCHLD;
P->processor = 0;
@ -225,8 +370,11 @@ static void stat2proc(const char* S, proc_t *restrict P) {
/* -- Linux 2.2.8 to 2.5.17 end here -- */
&P->rtprio, &P->sched /* both added to 2.5.18 */
);
LEAVE(0x160);
}
/////////////////////////////////////////////////////////////////////////
static void statm2proc(const char* s, proc_t *restrict P) {
int num;
num = sscanf(s, "%ld %ld %ld %ld %ld %ld %ld",
@ -243,9 +391,9 @@ static int file2str(const char *directory, const char *what, char *ret, int cap)
fd = open(filename, O_RDONLY, 0);
if(unlikely(fd==-1)) return -1;
num_read = read(fd, ret, cap - 1);
if(unlikely(num_read<=0)) num_read = -1;
else ret[num_read] = 0;
close(fd);
if(unlikely(num_read<=0)) return -1;
ret[num_read] = '\0';
return num_read;
}
@ -329,8 +477,8 @@ int read_cmdline(char *restrict const dst, unsigned sz, unsigned pid){
dst[n] = '\0';
i=n;
while(i--){
int c = dst[i];
if(c<' ' || c>'~') dst[i]=' ';
int c = dst[i];
if(c<' ' || c>'~') dst[i]=' ';
}
}
return n;

View File

@ -133,6 +133,7 @@ typedef struct proc_t {
session, /* session id */
tty, /* full device number of controlling terminal */
tpgid, /* terminal process group id */
tgid, /* thread group ID */
exit_signal, /* might not be SIGCHLD */
processor; /* current (or most recent?) CPU */
#ifdef FLASK_LINUX