~ubuntu-branches/ubuntu/utopic/kde-workspace/utopic-proposed

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Michał Zając
  • Date: 2011-07-09 08:31:15 UTC
  • Revision ID: james.westby@ubuntu.com-20110709083115-ohyxn6z93mily9fc
Tags: upstream-4.6.90
Import upstream version 4.6.90

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