~ubuntu-branches/ubuntu/warty/kdebase/warty

« back to all changes in this revision

Viewing changes to ksysguard/ksysguardd/Solaris/ProcessList.c

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones
  • Date: 2004-09-16 04:51:45 UTC
  • Revision ID: james.westby@ubuntu.com-20040916045145-9vr63kith3k1cpza
Tags: upstream-3.2.2
ImportĀ upstreamĀ versionĀ 3.2.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    KSysGuard, the KDE System Guard
 
3
   
 
4
        Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
 
5
 
 
6
        Solaris support by Torsten Kasch <tk@Genetik.Uni-Bielefeld.DE>
 
7
    
 
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.
 
11
 
 
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.
 
16
 
 
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.
 
20
 
 
21
        $Id: ProcessList.c,v 1.10 2003/09/03 15:12:11 tokoe Exp $
 
22
*/
 
23
 
 
24
#include <stdio.h>
 
25
#include <stdlib.h>
 
26
#include <unistd.h>
 
27
#include <string.h>
 
28
#include <errno.h>
 
29
#include <fcntl.h>
 
30
#include <signal.h>
 
31
#include <sys/types.h>
 
32
#include <dirent.h>
 
33
#include <pwd.h>
 
34
#include <procfs.h>
 
35
#include <sys/proc.h>
 
36
#include <sys/resource.h>
 
37
 
 
38
#include "ccont.h"
 
39
#include "../../gui/SignalIDs.h"
 
40
#include "ksysguardd.h"
 
41
 
 
42
#include "Command.h"
 
43
#include "ProcessList.h"
 
44
 
 
45
#define BUFSIZE 1024
 
46
 
 
47
typedef struct {
 
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                  */
 
63
} ProcessInfo;
 
64
 
 
65
static CONTAINER ProcessList = 0;
 
66
static unsigned ProcessCount = 0;       /*  # of processes        */
 
67
static DIR *procdir;                    /*  handle for /proc      */
 
68
 
 
69
/*
 
70
 *  lwpStateName()  --  return string representation of process state
 
71
 */
 
72
char *lwpStateName( lwpsinfo_t lwpinfo ) {
 
73
 
 
74
        char    result[8];
 
75
        int     processor;
 
76
 
 
77
        switch( (int) lwpinfo.pr_state ) {
 
78
                case SSLEEP:
 
79
                        sprintf( result, "%s", "sleep" );
 
80
                        break;
 
81
                case SRUN:
 
82
                        sprintf( result, "%s", "run" );
 
83
                        break;
 
84
                case SZOMB:
 
85
                        sprintf( result, "%s", "zombie" );
 
86
                        break;
 
87
                case SSTOP:
 
88
                        sprintf( result, "%s", "stop" );
 
89
                        break;
 
90
                case SIDL:
 
91
                        sprintf( result, "%s", "start" );
 
92
                        break;
 
93
                case SONPROC:
 
94
                        processor = (int) lwpinfo.pr_onpro;
 
95
                        sprintf( result, "%s/%d", "cpu", processor );
 
96
                        break;
 
97
                default:
 
98
                        sprintf( result, "%s", "???" );
 
99
                        break;
 
100
        }
 
101
 
 
102
        return( strdup( result ));
 
103
}
 
104
 
 
105
static void validateStr( char *string ) {
 
106
 
 
107
        char    *ptr = string;
 
108
 
 
109
        /*
 
110
         *  remove all chars that might screw up communication
 
111
         */
 
112
        while( *ptr != '\0' ) {
 
113
                if( *ptr == '\t' || *ptr == '\n' || *ptr == '\r' )
 
114
                        *ptr = ' ';
 
115
                ptr++;
 
116
        }
 
117
        /*
 
118
         *  make sure there's at least one char 
 
119
         */
 
120
        if( string[0] == '\0' )
 
121
                strcpy( string, " " );
 
122
}
 
123
 
 
124
static int processCmp( void *p1, void *p2 ) {
 
125
 
 
126
        return( ((ProcessInfo *) p1)->pid - ((ProcessInfo *) p2)->pid );
 
127
}
 
128
 
 
129
static ProcessInfo *findProcessInList( pid_t pid ) {
 
130
 
 
131
        ProcessInfo     key;
 
132
        long            index;
 
133
        
 
134
        key.pid = pid;
 
135
        if( (index = search_ctnr( ProcessList, processCmp, &key )) < 0 )
 
136
                return( NULL );
 
137
 
 
138
        return( get_ctnr( ProcessList, index ));
 
139
}
 
140
 
 
141
static int updateProcess( pid_t pid ) {
 
142
 
 
143
        ProcessInfo     *ps;
 
144
        int             fd;
 
145
        char            buf[BUFSIZE];
 
146
        psinfo_t        psinfo;
 
147
        struct passwd   *pw;
 
148
 
 
149
        if( (ps = findProcessInList( pid )) == NULL ) {
 
150
                if( (ps = (ProcessInfo *) malloc( sizeof( ProcessInfo )))
 
151
                                == NULL ) {
 
152
                        print_error( "cannot malloc()\n" );
 
153
                        return( -1 );
 
154
                }
 
155
                ps->pid = pid;
 
156
                ps->userName = NULL;
 
157
                ps->State = NULL;
 
158
                ps->Command = NULL;
 
159
                ps->CmdLine = NULL;
 
160
                ps->alive = 0;
 
161
 
 
162
                push_ctnr( ProcessList, ps );
 
163
                bsort_ctnr( ProcessList, processCmp );
 
164
        }
 
165
 
 
166
        snprintf( buf, BUFSIZE - 1, "%s/%ld/psinfo", PROCDIR, pid );
 
167
        if( (fd = open( buf, O_RDONLY )) < 0 ) {
 
168
                return( -1 );
 
169
        }
 
170
 
 
171
        if( read( fd, &psinfo, sizeof( psinfo_t )) != sizeof( psinfo_t )) {
 
172
                close( fd );
 
173
                return( -1 );
 
174
        }
 
175
        close( fd );
 
176
 
 
177
        ps->ppid = psinfo.pr_ppid;
 
178
        ps->uid = psinfo.pr_uid;
 
179
        ps->gid = psinfo.pr_gid;
 
180
 
 
181
        pw = getpwuid( psinfo.pr_uid );
 
182
        if( ps->userName != NULL )
 
183
                free( ps->userName );
 
184
        ps->userName = strdup( pw->pw_name );
 
185
 
 
186
        if( ps->State != NULL )
 
187
                free( ps->State );
 
188
        ps->State = lwpStateName( psinfo.pr_lwp );
 
189
 
 
190
        /*
 
191
         * the following data is invalid for zombies, so...
 
192
         */
 
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;
 
199
        } else {
 
200
                ps->Prio = 0;
 
201
                ps->Time = 0;
 
202
                ps->Load = 0.0;
 
203
        }
 
204
 
 
205
        ps->Size = psinfo.pr_size;
 
206
        ps->RSSize = psinfo.pr_rssize;
 
207
 
 
208
        if( ps->Command != NULL )
 
209
                free( ps->Command );
 
210
        ps->Command = strdup( psinfo.pr_fname );
 
211
        if( ps->CmdLine != NULL )
 
212
                free( ps->CmdLine );
 
213
        ps->CmdLine = strdup( psinfo.pr_psargs );
 
214
 
 
215
        validateStr( ps->Command );
 
216
        validateStr( ps->CmdLine );
 
217
 
 
218
        ps->alive = 1;
 
219
 
 
220
        return( 0 );
 
221
}
 
222
 
 
223
static void cleanupProcessList( void ) {
 
224
 
 
225
        ProcessInfo *ps;
 
226
 
 
227
        ProcessCount = 0;
 
228
        for( ps = first_ctnr( ProcessList ); ps; ps = next_ctnr( ProcessList )) {
 
229
                if( ps->alive ) {
 
230
                        ps->alive = 0;
 
231
                        ProcessCount++;
 
232
                } else {
 
233
                        free( remove_ctnr( ProcessList ));
 
234
                }
 
235
        }
 
236
}
 
237
 
 
238
void initProcessList( struct SensorModul* sm ) {
 
239
 
 
240
        if( (procdir = opendir( PROCDIR )) == NULL ) {
 
241
                print_error( "cannot open \"%s\" for reading\n", PROCDIR );
 
242
                return;
 
243
        }
 
244
 
 
245
        ProcessList = new_ctnr();
 
246
 
 
247
        /*
 
248
         *  register the supported monitors & commands
 
249
         */
 
250
        registerMonitor( "pscount", "integer",
 
251
                                printProcessCount, printProcessCountInfo, sm );
 
252
        registerMonitor( "ps", "table",
 
253
                                printProcessList, printProcessListInfo, sm );
 
254
 
 
255
        registerCommand( "kill", killProcess );
 
256
        registerCommand( "setpriority", setPriority );
 
257
}
 
258
 
 
259
void exitProcessList( void ) {
 
260
 
 
261
        destr_ctnr( ProcessList, free );
 
262
}
 
263
 
 
264
int updateProcessList( void ) {
 
265
 
 
266
        struct dirent   *de;
 
267
 
 
268
        rewinddir( procdir );
 
269
        while( (de = readdir( procdir )) != NULL ) {
 
270
                /*
 
271
                 *  skip '.' and '..'
 
272
                 */
 
273
                if( de->d_name[0] == '.' )
 
274
                        continue;
 
275
 
 
276
                /*
 
277
                 *  fetch the process info and insert it into the info table
 
278
                 */
 
279
                updateProcess( (pid_t) atol( de->d_name ));
 
280
        }
 
281
        cleanupProcessList();
 
282
 
 
283
        return( 0 );
 
284
}
 
285
 
 
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" );
 
290
}
 
291
 
 
292
void printProcessList( const char *cmd ) {
 
293
 
 
294
        ProcessInfo *ps;
 
295
 
 
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",
 
299
                        ps->Command,
 
300
                        (long) ps->pid,
 
301
                        (long) ps->ppid,
 
302
                        (long) ps->gid,
 
303
                        ps->State,
 
304
                        ps->userName,
 
305
                        ps->nThreads,
 
306
                        ps->Size,
 
307
                        ps->RSSize,
 
308
                        ps->Load,
 
309
                        ps->Prio,
 
310
                        ps->CmdLine);
 
311
        }
 
312
 
 
313
        fprintf(CurrentClient, "\n");
 
314
}
 
315
 
 
316
void printProcessCount( const char *cmd ) {
 
317
        fprintf(CurrentClient, "%d\n", ProcessCount );
 
318
}
 
319
 
 
320
void printProcessCountInfo( const char *cmd ) {
 
321
        fprintf(CurrentClient, "Number of Processes\t0\t0\t\n" );
 
322
}
 
323
 
 
324
void killProcess( const char *cmd ) {
 
325
 
 
326
        int sig, pid;
 
327
 
 
328
        sscanf( cmd, "%*s %d %d", &pid, &sig );
 
329
 
 
330
        switch( sig ) {
 
331
                case MENU_ID_SIGABRT:
 
332
                        sig = SIGABRT;
 
333
                        break;
 
334
                case MENU_ID_SIGALRM:
 
335
                        sig = SIGALRM;
 
336
                        break;
 
337
                case MENU_ID_SIGCHLD:
 
338
                        sig = SIGCHLD;
 
339
                        break;
 
340
                case MENU_ID_SIGCONT:
 
341
                        sig = SIGCONT;
 
342
                        break;
 
343
                case MENU_ID_SIGFPE:
 
344
                        sig = SIGFPE;
 
345
                        break;
 
346
                case MENU_ID_SIGHUP:
 
347
                        sig = SIGHUP;
 
348
                        break;
 
349
                case MENU_ID_SIGILL:
 
350
                        sig = SIGILL;
 
351
                        break;
 
352
                case MENU_ID_SIGINT:
 
353
                        sig = SIGINT;
 
354
                        break;
 
355
                case MENU_ID_SIGKILL:
 
356
                        sig = SIGKILL;
 
357
                        break;
 
358
                case MENU_ID_SIGPIPE:
 
359
                        sig = SIGPIPE;
 
360
                        break;
 
361
                case MENU_ID_SIGQUIT:
 
362
                        sig = SIGQUIT;
 
363
                        break;
 
364
                case MENU_ID_SIGSEGV:
 
365
                        sig = SIGSEGV;
 
366
                        break;
 
367
                case MENU_ID_SIGSTOP:
 
368
                        sig = SIGSTOP;
 
369
                        break;
 
370
                case MENU_ID_SIGTERM:
 
371
                        sig = SIGTERM;
 
372
                        break;
 
373
                case MENU_ID_SIGTSTP:
 
374
                        sig = SIGTSTP;
 
375
                        break;
 
376
                case MENU_ID_SIGTTIN:
 
377
                        sig = SIGTTIN;
 
378
                        break;
 
379
                case MENU_ID_SIGTTOU:
 
380
                        sig = SIGTTOU;
 
381
                        break;
 
382
                case MENU_ID_SIGUSR1:
 
383
                        sig = SIGUSR1;
 
384
                        break;
 
385
                case MENU_ID_SIGUSR2:
 
386
                        sig = SIGUSR2;
 
387
                        break;
 
388
        }
 
389
        if( kill( (pid_t) pid, sig )) {
 
390
                switch( errno ) {
 
391
                        case EINVAL:
 
392
                                fprintf(CurrentClient, "4\n" );
 
393
                                break;
 
394
                        case ESRCH:
 
395
                                fprintf(CurrentClient, "3\n" );
 
396
                                break;
 
397
                        case EPERM:
 
398
                                fprintf(CurrentClient, "2\n" );
 
399
                                break;
 
400
                        default:
 
401
                                fprintf(CurrentClient, "1\n" ); /* unknown error */
 
402
                                break;
 
403
                }
 
404
        } else
 
405
                fprintf(CurrentClient, "0\n");
 
406
}
 
407
 
 
408
void setPriority( const char *cmd ) {
 
409
        int pid, prio;
 
410
 
 
411
        sscanf( cmd, "%*s %d %d", &pid, &prio );
 
412
        if( setpriority( PRIO_PROCESS, pid, prio )) {
 
413
                switch( errno ) {
 
414
                        case EINVAL:
 
415
                                fprintf(CurrentClient, "4\n" );
 
416
                                break;
 
417
                        case ESRCH:
 
418
                                fprintf(CurrentClient, "3\n" );
 
419
                                break;
 
420
                        case EPERM:
 
421
                        case EACCES:
 
422
                                fprintf(CurrentClient, "2\n" );
 
423
                                break;
 
424
                        default:
 
425
                                fprintf(CurrentClient, "1\n" ); /* unknown error */
 
426
                                break;
 
427
                }
 
428
        } else
 
429
                fprintf(CurrentClient, "0\n");
 
430
}