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

« back to all changes in this revision

Viewing changes to ksysguard/ksysguardd/Irix/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
        Irix support by Carsten Kroll <ckroll@pinnaclesys.com>
 
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
#include <stdio.h>
 
24
#include <stdlib.h>
 
25
#include <unistd.h>
 
26
#include <string.h>
 
27
#include <errno.h>
 
28
#include <fcntl.h>
 
29
#include <signal.h>
 
30
#include <sys/types.h>
 
31
#include <dirent.h>
 
32
#include <pwd.h>
 
33
#include <sys/resource.h>
 
34
#include <sys/procfs.h>
 
35
#include <sys/statfs.h>
 
36
#include <sys/sysmp.h>
 
37
#include <sys/sysinfo.h>
 
38
 
 
39
#include "ccont.h"
 
40
#include "../../gui/SignalIDs.h"
 
41
#include "ksysguardd.h"
 
42
 
 
43
#include "Command.h"
 
44
#include "ProcessList.h"
 
45
 
 
46
#define BUFSIZE 1024
 
47
#define KDEINITLEN strlen("kdeinit: ")
 
48
 
 
49
typedef struct {
 
50
        int     alive;          /*  for "garbage collection"            */
 
51
        pid_t   pid;            /*  process ID                          */
 
52
        pid_t   ppid;           /*  parent process ID                   */
 
53
        uid_t   uid;            /*  process owner (real UID)            */
 
54
        gid_t   gid;            /*  process group (real GID)            */
 
55
        char    *userName;      /*  process owner (name)                */
 
56
        int     nThreads;       /*  # of threads in this process        */
 
57
        int     Prio;           /*  scheduling priority                 */
 
58
        size_t  Size;           /*  total size of process image         */
 
59
        size_t  RSSize;         /*  resident set size                   */
 
60
        char    State[8];       /*  process state                       */
 
61
        double  Time;           /*  CPU time for the process in 100ms   */
 
62
        double  Load;           /*  CPU load in %                       */
 
63
        char    Command[PRCOMSIZ];/*  command name                      */
 
64
        char    CmdLine[PRARGSZ];/*  command line                       */
 
65
        double  centStamp;      /*  timestamp for CPU load              */
 
66
} ProcessInfo;
 
67
 
 
68
static CONTAINER ProcessList = 0;
 
69
static unsigned ProcessCount = 0;       /*  # of processes        */
 
70
static DIR *procdir;                    /*  handle for /proc      */
 
71
static int pagesz;
 
72
 
 
73
#define KBYTES 1024
 
74
 
 
75
/*
 
76
 *  lwpStateName()  --  return string representation of process state
 
77
 */
 
78
char *lwpStateName( prpsinfo_t lwpinfo ) {
 
79
 
 
80
        static char result[8];
 
81
 
 
82
        switch( lwpinfo.pr_sname ) {
 
83
                case 'S':
 
84
                        sprintf( result, "%s", "sleep" );
 
85
                        break;
 
86
                case 'R':
 
87
                        sprintf( result, "%s", "run" );
 
88
                        break;
 
89
                case 'Z':
 
90
                        sprintf( result, "%s", "zombie" );
 
91
                        break;
 
92
                case 'T':
 
93
                        sprintf( result, "%s", "stop" );
 
94
                        break;
 
95
                case 'I':
 
96
                        sprintf( result, "%s", "start" );
 
97
                        break;
 
98
                case 'X':
 
99
                        sprintf( result, "%s", "wmem" );
 
100
                case '0':
 
101
                        sprintf( result, "%s/%d", "cpu", (int) lwpinfo.pr_sonproc );
 
102
                        break;
 
103
                default:
 
104
                        sprintf( result, "%s", "???" );
 
105
                        break;
 
106
        }
 
107
 
 
108
        return( 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
        ProcessInfo     *ps;
 
149
        int             fd;
 
150
        char            buf[BUFSIZE];
 
151
        prpsinfo_t      psinfo;
 
152
        struct passwd   *pw;
 
153
        register double newCentStamp,timeDiff, usDiff,usTime;
 
154
        struct timeval tv;
 
155
 
 
156
        if( (ps = findProcessInList( pid )) == NULL ) {
 
157
                if( (ps = (ProcessInfo *) malloc( sizeof( ProcessInfo )))
 
158
                                == NULL ) {
 
159
                        print_error( "cannot malloc()\n" );
 
160
                        return( -1 );
 
161
                }
 
162
                ps->pid = pid;
 
163
                ps->userName = NULL;
 
164
                ps->alive = 0;
 
165
 
 
166
                gettimeofday(&tv, 0);
 
167
                ps->centStamp = (double)tv.tv_sec * 100.0 + (double)tv.tv_usec / 10000.0;
 
168
 
 
169
                push_ctnr( ProcessList, ps );
 
170
                bsort_ctnr( ProcessList, processCmp );
 
171
        }
 
172
 
 
173
        sprintf( buf, "%s/pinfo/%ld", PROCDIR, pid );
 
174
        if( (fd = open( buf, O_RDONLY )) < 0 ) {
 
175
                /* process terminated */
 
176
                return( -1 );
 
177
        }
 
178
 
 
179
 
 
180
 
 
181
        if( ioctl(fd,PIOCPSINFO,&psinfo) < 0) {
 
182
                print_error( "cannot read psinfo from \"%s\"\n", buf );
 
183
                close( fd );
 
184
                return( -1 );
 
185
        }
 
186
        close( fd );
 
187
 
 
188
        ps->ppid = psinfo.pr_ppid;
 
189
        ps->uid = psinfo.pr_uid;
 
190
        ps->gid = psinfo.pr_gid;
 
191
 
 
192
        pw = getpwuid( psinfo.pr_uid );
 
193
        if( ps->userName != NULL )
 
194
                free( ps->userName );
 
195
        ps->userName = strdup( pw->pw_name );
 
196
 
 
197
        strncpy (ps->State,lwpStateName( psinfo ),8);
 
198
        ps->State[7]='\0';
 
199
 
 
200
 
 
201
        ps->Prio = psinfo.pr_pri;
 
202
 
 
203
        gettimeofday(&tv, 0);
 
204
        newCentStamp = (double)tv.tv_sec * 100.0 + (double) tv.tv_usec / 10000.0;
 
205
        usTime = (double) psinfo.pr_time.tv_sec * 100.0 + (double)psinfo.pr_time.tv_nsec / 10000000.0;
 
206
 
 
207
        timeDiff = newCentStamp - ps->centStamp;
 
208
        usDiff = usTime - ps->Time;
 
209
 
 
210
        if ((timeDiff > 0.0) && (usDiff >= 0.0))
 
211
        {
 
212
                ps->Load = (usDiff / timeDiff) * 100.0;
 
213
                /* During startup we get bigger loads since the time diff
 
214
                * cannot be correct. So we force it to 0. */
 
215
                ps->Load = (ps->Load > 100.0) ? 0.0 : ps->Load;
 
216
        }
 
217
        else
 
218
                ps->Load = 0.0;
 
219
 
 
220
        ps->centStamp = newCentStamp;
 
221
        ps->Time = usTime;
 
222
 
 
223
        ps->Size = (psinfo.pr_size * pagesz)/KBYTES;
 
224
        ps->RSSize = (psinfo.pr_rssize * pagesz)/KBYTES;
 
225
 
 
226
        strncpy(ps->Command,psinfo.pr_fname,PRCOMSIZ);
 
227
        ps->Command[PRCOMSIZ-1]='\0';
 
228
 
 
229
        strncpy(ps->CmdLine,psinfo.pr_psargs,PRARGSZ);
 
230
        ps->CmdLine[PRARGSZ-1]='\0';
 
231
 
 
232
        validateStr( ps->Command );
 
233
        validateStr( ps->CmdLine );
 
234
 
 
235
        ps->alive = 1;
 
236
        return( 0 );
 
237
}
 
238
 
 
239
static void cleanupProcessList( void ) {
 
240
 
 
241
        ProcessInfo *ps;
 
242
 
 
243
        ProcessCount = 0;
 
244
        for( ps = first_ctnr( ProcessList ); ps; ps = next_ctnr( ProcessList )) {
 
245
                if( ps->alive ) {
 
246
                        /* Process is still alive. Just clear flag. */
 
247
                        ps->alive = 0;
 
248
                        ProcessCount++;
 
249
                } else {
 
250
                        /* Process has probably died. We remove it from the list and
 
251
                         * destruct the data structure. */
 
252
                        free( remove_ctnr( ProcessList ));
 
253
                }
 
254
        }
 
255
}
 
256
 
 
257
void initProcessList( struct SensorModul* sm ) {
 
258
 
 
259
        if( (procdir = opendir( PROCDIR )) == NULL ) {
 
260
                print_error( "cannot open \"%s\" for reading\n", PROCDIR );
 
261
                return;
 
262
        }
 
263
        pagesz=getpagesize();
 
264
        ProcessList = new_ctnr();
 
265
        updateProcessList();
 
266
 
 
267
        /*
 
268
         *  register the supported monitors & commands
 
269
         */
 
270
        registerMonitor( "pscount", "integer",
 
271
                                printProcessCount, printProcessCountInfo, sm );
 
272
        registerMonitor( "ps", "table",
 
273
                                printProcessList, printProcessListInfo, sm );
 
274
 
 
275
        if (!RunAsDaemon)
 
276
        {
 
277
                registerCommand("kill", killProcess);
 
278
                registerCommand("setpriority", setPriority);
 
279
        }
 
280
}
 
281
 
 
282
void exitProcessList( void ) {
 
283
 
 
284
        removeMonitor("ps");
 
285
        removeMonitor("pscount");
 
286
 
 
287
        if (!RunAsDaemon)
 
288
        {
 
289
                removeCommand("kill");
 
290
                removeCommand("setpriority");
 
291
        }
 
292
 
 
293
        destr_ctnr( ProcessList, free );
 
294
}
 
295
 
 
296
int updateProcessList( void ) {
 
297
 
 
298
        struct dirent   *de;
 
299
        struct statfs sf;
 
300
 
 
301
        statfs("/proc/pinfo",&sf,sizeof(sf),0);
 
302
        ProcessCount = sf.f_files;
 
303
 
 
304
        rewinddir( procdir );
 
305
        while( (de = readdir( procdir )) != NULL ) {
 
306
                /*
 
307
                 *  skip '.' and '..'
 
308
                 */
 
309
                if( de->d_name[0] == '.' )
 
310
                        continue;
 
311
 
 
312
                /*
 
313
                 *  fetch the process info and insert it into the info table
 
314
                 */
 
315
                updateProcess( (pid_t) atol( de->d_name ));
 
316
        }
 
317
        cleanupProcessList();
 
318
 
 
319
        return( 0 );
 
320
}
 
321
 
 
322
void printProcessListInfo( const char *cmd ) {
 
323
        fprintf(CurrentClient, "Name\tPID\tPPID\tGID\tStatus\tUser"
 
324
                "\tSize\tResident\t%% CPU\tPriority\tCommand\n" );
 
325
        fprintf(CurrentClient, "s\td\td\td\ts\ts\tD\tD\tf\td\ts\n" );
 
326
}
 
327
 
 
328
void printProcessList( const char *cmd ) {
 
329
 
 
330
        ProcessInfo *ps;
 
331
 
 
332
        for( ps = first_ctnr( ProcessList ); ps; ps = next_ctnr( ProcessList )) {
 
333
                fprintf(CurrentClient,
 
334
                        "%s\t%ld\t%ld\t%ld\t%s\t%s\t%d\t%d\t%.2f\t%d\t%s\n",
 
335
                        ps->Command,
 
336
                        (long) ps->pid,
 
337
                        (long) ps->ppid,
 
338
                        (long) ps->gid,
 
339
                        ps->State,
 
340
                        ps->userName,
 
341
                        ps->Size,
 
342
                        ps->RSSize,
 
343
                        ps->Load,
 
344
                        ps->Prio,
 
345
                        ps->CmdLine);
 
346
        }
 
347
 
 
348
        fprintf(CurrentClient, "\n");
 
349
}
 
350
 
 
351
void printProcessCount( const char *cmd ) {
 
352
        fprintf(CurrentClient, "%d\n", ProcessCount );
 
353
}
 
354
 
 
355
void printProcessCountInfo( const char *cmd ) {
 
356
        fprintf(CurrentClient, "Number of Processes\t0\t0\t\n" );
 
357
}
 
358
 
 
359
void killProcess( const char *cmd ) {
 
360
 
 
361
        int sig, pid;
 
362
 
 
363
        sscanf( cmd, "%*s %d %d", &pid, &sig );
 
364
 
 
365
        switch( sig ) {
 
366
                case MENU_ID_SIGABRT:
 
367
                        sig = SIGABRT;
 
368
                        break;
 
369
                case MENU_ID_SIGALRM:
 
370
                        sig = SIGALRM;
 
371
                        break;
 
372
                case MENU_ID_SIGCHLD:
 
373
                        sig = SIGCHLD;
 
374
                        break;
 
375
                case MENU_ID_SIGCONT:
 
376
                        sig = SIGCONT;
 
377
                        break;
 
378
                case MENU_ID_SIGFPE:
 
379
                        sig = SIGFPE;
 
380
                        break;
 
381
                case MENU_ID_SIGHUP:
 
382
                        sig = SIGHUP;
 
383
                        break;
 
384
                case MENU_ID_SIGILL:
 
385
                        sig = SIGILL;
 
386
                        break;
 
387
                case MENU_ID_SIGINT:
 
388
                        sig = SIGINT;
 
389
                        break;
 
390
                case MENU_ID_SIGKILL:
 
391
                        sig = SIGKILL;
 
392
                        break;
 
393
                case MENU_ID_SIGPIPE:
 
394
                        sig = SIGPIPE;
 
395
                        break;
 
396
                case MENU_ID_SIGQUIT:
 
397
                        sig = SIGQUIT;
 
398
                        break;
 
399
                case MENU_ID_SIGSEGV:
 
400
                        sig = SIGSEGV;
 
401
                        break;
 
402
                case MENU_ID_SIGSTOP:
 
403
                        sig = SIGSTOP;
 
404
                        break;
 
405
                case MENU_ID_SIGTERM:
 
406
                        sig = SIGTERM;
 
407
                        break;
 
408
                case MENU_ID_SIGTSTP:
 
409
                        sig = SIGTSTP;
 
410
                        break;
 
411
                case MENU_ID_SIGTTIN:
 
412
                        sig = SIGTTIN;
 
413
                        break;
 
414
                case MENU_ID_SIGTTOU:
 
415
                        sig = SIGTTOU;
 
416
                        break;
 
417
                case MENU_ID_SIGUSR1:
 
418
                        sig = SIGUSR1;
 
419
                        break;
 
420
                case MENU_ID_SIGUSR2:
 
421
                        sig = SIGUSR2;
 
422
                        break;
 
423
        }
 
424
        if( kill( (pid_t) pid, sig )) {
 
425
                switch( errno ) {
 
426
                        case EINVAL:
 
427
                                fprintf(CurrentClient, "4\n" );
 
428
                                break;
 
429
                        case ESRCH:
 
430
                                fprintf(CurrentClient, "3\n" );
 
431
                                break;
 
432
                        case EPERM:
 
433
                                fprintf(CurrentClient, "2\n" );
 
434
                                break;
 
435
                        default:
 
436
                                fprintf(CurrentClient, "1\n" ); /* unknown error */
 
437
                                break;
 
438
                }
 
439
        } else
 
440
                fprintf(CurrentClient, "0\n");
 
441
}
 
442
 
 
443
void setPriority( const char *cmd ) {
 
444
        int pid, prio;
 
445
 
 
446
        sscanf( cmd, "%*s %d %d", &pid, &prio );
 
447
        if( setpriority( PRIO_PROCESS, pid, prio )) {
 
448
                switch( errno ) {
 
449
                        case EINVAL:
 
450
                                fprintf(CurrentClient, "4\n" );
 
451
                                break;
 
452
                        case ESRCH:
 
453
                                fprintf(CurrentClient, "3\n" );
 
454
                                break;
 
455
                        case EPERM:
 
456
                        case EACCES:
 
457
                                fprintf(CurrentClient, "2\n" );
 
458
                                break;
 
459
                        default:
 
460
                                fprintf(CurrentClient, "1\n" ); /* unknown error */
 
461
                                break;
 
462
                }
 
463
        } else
 
464
                fprintf(CurrentClient, "0\n");
 
465
}