2
KSysGuard, the KDE System Guard
4
Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
6
Solaris support by Torsten Kasch <tk@Genetik.Uni-Bielefeld.DE>
8
This program is free software; you can redistribute it and/or
9
modify it under the terms of version 2 of the GNU General Public
10
License as published by the Free Software Foundation.
12
This program is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
GNU General Public License for more details.
17
You should have received a copy of the GNU General Public License
18
along with this program; if not, write to the Free Software
19
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
$Id: ProcessList.c,v 1.10 2003/09/03 15:12:11 tokoe Exp $
31
#include <sys/types.h>
36
#include <sys/resource.h>
39
#include "../../gui/SignalIDs.h"
40
#include "ksysguardd.h"
43
#include "ProcessList.h"
48
int alive; /* for "garbage collection" */
49
pid_t pid; /* process ID */
50
pid_t ppid; /* parent process ID */
51
uid_t uid; /* process owner (real UID) */
52
gid_t gid; /* process group (real GID) */
53
char *userName; /* process owner (name) */
54
int nThreads; /* # of threads in this process */
55
int Prio; /* scheduling priority */
56
size_t Size; /* total size of process image */
57
size_t RSSize; /* resident set size */
58
char *State; /* process state */
59
int Time; /* CPU time for the process */
60
double Load; /* CPU load in % */
61
char *Command; /* command name */
62
char *CmdLine; /* command line */
65
static CONTAINER ProcessList = 0;
66
static unsigned ProcessCount = 0; /* # of processes */
67
static DIR *procdir; /* handle for /proc */
70
* lwpStateName() -- return string representation of process state
72
char *lwpStateName( lwpsinfo_t lwpinfo ) {
77
switch( (int) lwpinfo.pr_state ) {
79
sprintf( result, "%s", "sleep" );
82
sprintf( result, "%s", "run" );
85
sprintf( result, "%s", "zombie" );
88
sprintf( result, "%s", "stop" );
91
sprintf( result, "%s", "start" );
94
processor = (int) lwpinfo.pr_onpro;
95
sprintf( result, "%s/%d", "cpu", processor );
98
sprintf( result, "%s", "???" );
102
return( strdup( result ));
105
static void validateStr( char *string ) {
110
* remove all chars that might screw up communication
112
while( *ptr != '\0' ) {
113
if( *ptr == '\t' || *ptr == '\n' || *ptr == '\r' )
118
* make sure there's at least one char
120
if( string[0] == '\0' )
121
strcpy( string, " " );
124
static int processCmp( void *p1, void *p2 ) {
126
return( ((ProcessInfo *) p1)->pid - ((ProcessInfo *) p2)->pid );
129
static ProcessInfo *findProcessInList( pid_t pid ) {
135
if( (index = search_ctnr( ProcessList, processCmp, &key )) < 0 )
138
return( get_ctnr( ProcessList, index ));
141
static int updateProcess( pid_t pid ) {
149
if( (ps = findProcessInList( pid )) == NULL ) {
150
if( (ps = (ProcessInfo *) malloc( sizeof( ProcessInfo )))
152
print_error( "cannot malloc()\n" );
162
push_ctnr( ProcessList, ps );
163
bsort_ctnr( ProcessList, processCmp );
166
snprintf( buf, BUFSIZE - 1, "%s/%ld/psinfo", PROCDIR, pid );
167
if( (fd = open( buf, O_RDONLY )) < 0 ) {
171
if( read( fd, &psinfo, sizeof( psinfo_t )) != sizeof( psinfo_t )) {
177
ps->ppid = psinfo.pr_ppid;
178
ps->uid = psinfo.pr_uid;
179
ps->gid = psinfo.pr_gid;
181
pw = getpwuid( psinfo.pr_uid );
182
if( ps->userName != NULL )
183
free( ps->userName );
184
ps->userName = strdup( pw->pw_name );
186
if( ps->State != NULL )
188
ps->State = lwpStateName( psinfo.pr_lwp );
191
* the following data is invalid for zombies, so...
193
if( (ps->nThreads = psinfo.pr_nlwp ) != 0 ) {
194
ps->Prio = psinfo.pr_lwp.pr_pri;
195
ps->Time = psinfo.pr_lwp.pr_time.tv_sec * 100
196
+ psinfo.pr_lwp.pr_time.tv_nsec * 10000000;
197
ps->Load = (double) psinfo.pr_lwp.pr_pctcpu
198
/ (double) 0x8000 * 100.0;
205
ps->Size = psinfo.pr_size;
206
ps->RSSize = psinfo.pr_rssize;
208
if( ps->Command != NULL )
210
ps->Command = strdup( psinfo.pr_fname );
211
if( ps->CmdLine != NULL )
213
ps->CmdLine = strdup( psinfo.pr_psargs );
215
validateStr( ps->Command );
216
validateStr( ps->CmdLine );
223
static void cleanupProcessList( void ) {
228
for( ps = first_ctnr( ProcessList ); ps; ps = next_ctnr( ProcessList )) {
233
free( remove_ctnr( ProcessList ));
238
void initProcessList( struct SensorModul* sm ) {
240
if( (procdir = opendir( PROCDIR )) == NULL ) {
241
print_error( "cannot open \"%s\" for reading\n", PROCDIR );
245
ProcessList = new_ctnr();
248
* register the supported monitors & commands
250
registerMonitor( "pscount", "integer",
251
printProcessCount, printProcessCountInfo, sm );
252
registerMonitor( "ps", "table",
253
printProcessList, printProcessListInfo, sm );
255
registerCommand( "kill", killProcess );
256
registerCommand( "setpriority", setPriority );
259
void exitProcessList( void ) {
261
destr_ctnr( ProcessList, free );
264
int updateProcessList( void ) {
268
rewinddir( procdir );
269
while( (de = readdir( procdir )) != NULL ) {
273
if( de->d_name[0] == '.' )
277
* fetch the process info and insert it into the info table
279
updateProcess( (pid_t) atol( de->d_name ));
281
cleanupProcessList();
286
void printProcessListInfo( const char *cmd ) {
287
fprintf(CurrentClient, "Name\tPID\tPPID\tGID\tStatus\tUser\tThreads"
288
"\tSize\tResident\t%% CPU\tPriority\tCommand\n" );
289
fprintf(CurrentClient, "s\td\td\td\ts\ts\td\tD\tD\tf\td\ts\n" );
292
void printProcessList( const char *cmd ) {
296
for( ps = first_ctnr( ProcessList ); ps; ps = next_ctnr( ProcessList )) {
297
fprintf(CurrentClient,
298
"%s\t%ld\t%ld\t%ld\t%s\t%s\t%d\t%d\t%d\t%.2f\t%d\t%s\n",
313
fprintf(CurrentClient, "\n");
316
void printProcessCount( const char *cmd ) {
317
fprintf(CurrentClient, "%d\n", ProcessCount );
320
void printProcessCountInfo( const char *cmd ) {
321
fprintf(CurrentClient, "Number of Processes\t0\t0\t\n" );
324
void killProcess( const char *cmd ) {
328
sscanf( cmd, "%*s %d %d", &pid, &sig );
331
case MENU_ID_SIGABRT:
334
case MENU_ID_SIGALRM:
337
case MENU_ID_SIGCHLD:
340
case MENU_ID_SIGCONT:
355
case MENU_ID_SIGKILL:
358
case MENU_ID_SIGPIPE:
361
case MENU_ID_SIGQUIT:
364
case MENU_ID_SIGSEGV:
367
case MENU_ID_SIGSTOP:
370
case MENU_ID_SIGTERM:
373
case MENU_ID_SIGTSTP:
376
case MENU_ID_SIGTTIN:
379
case MENU_ID_SIGTTOU:
382
case MENU_ID_SIGUSR1:
385
case MENU_ID_SIGUSR2:
389
if( kill( (pid_t) pid, sig )) {
392
fprintf(CurrentClient, "4\n" );
395
fprintf(CurrentClient, "3\n" );
398
fprintf(CurrentClient, "2\n" );
401
fprintf(CurrentClient, "1\n" ); /* unknown error */
405
fprintf(CurrentClient, "0\n");
408
void setPriority( const char *cmd ) {
411
sscanf( cmd, "%*s %d %d", &pid, &prio );
412
if( setpriority( PRIO_PROCESS, pid, prio )) {
415
fprintf(CurrentClient, "4\n" );
418
fprintf(CurrentClient, "3\n" );
422
fprintf(CurrentClient, "2\n" );
425
fprintf(CurrentClient, "1\n" ); /* unknown error */
429
fprintf(CurrentClient, "0\n");