2
KSysGuard, the KDE System Guard
4
Copyright (c) 1999-2000 Hans Petter Bieker<bieker@kde.org>
5
Copyright (c) 1999 Chris Schlaeger <cs@kde.org>
7
This program is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2 of the License, or
10
(at your option) any later version.
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.17 2004/01/10 20:29:44 leimbach Exp $
32
#include <sys/param.h>
34
#if defined(__DragonFly__)
36
#include <sys/resourcevar.h>
39
#if __FreeBSD_version > 500015
40
#include <sys/priority.h>
42
#include <sys/sysctl.h>
44
#include <sys/types.h>
49
#include "../../gui/SignalIDs.h"
51
#include "ProcessList.h"
53
#include "ksysguardd.h"
55
CONTAINER ProcessList = 0;
63
/* This flag is set for all found processes at the beginning of the
64
* process list update. Processes that do not have this flag set will
65
* be assumed dead and removed from the list. The flag is cleared after
66
* each list update. */
72
/* the parent process ID */
75
/* the real user ID */
78
/* the real group ID */
81
/* a character description of the process status */
84
/* the number of the tty the process owns */
88
* The nice level. The range should be -20 to 20. I'm not sure
89
* whether this is true for all platforms.
94
* The scheduling priority.
99
* The total amount of memory the process uses. This includes shared and
105
* The amount of physical memory the process currently uses.
110
* The amount of memory (shared/swapped/etc) the process shares with
116
* The number of 1/100 of a second the process has spend in user space.
117
* If a machine has an uptime of 1 1/2 years or longer this is not a
118
* good idea. I never thought that the stability of UNIX could get me
121
#if !defined(__DragonFly__)
122
unsigned int userTime;
128
* The number of 1/100 of a second the process has spend in system space.
129
* If a machine has an uptime of 1 1/2 years or longer this is not a
130
* good idea. I never thought that the stability of UNIX could get me
133
unsigned int sysTime;
135
/* system time as multime of 100ms */
138
/* the current CPU load (in %) from user space */
141
/* the current CPU load (in %) from system space */
144
/* the name of the process */
147
/* the command used to start the process */
150
/* the login name of the user that owns this process */
154
static unsigned ProcessCount;
157
processCmp(void* p1, void* p2)
159
return (((ProcessInfo*) p1)->pid - ((ProcessInfo*) p2)->pid);
163
findProcessInList(int pid)
169
if ((index = search_ctnr(ProcessList, processCmp, &key)) < 0)
172
return (get_ctnr(ProcessList, index));
176
updateProcess(int pid)
178
static char *statuses[] = { "idle","run","sleep","stop","zombie" };
181
struct passwd* pwent;
189
if ((ps = findProcessInList(pid)) == 0)
191
ps = (ProcessInfo*) malloc(sizeof(ProcessInfo));
194
push_ctnr(ProcessList, ps);
195
bsort_ctnr(ProcessList, processCmp);
202
mib[2] = KERN_PROC_PID;
206
if (sysctl(mib, 4, &p, &len, NULL, 0) == -1 || !len)
209
#if __FreeBSD_version >= 500015
211
ps->ppid = p.ki_ppid;
214
ps->priority = p.ki_pri.pri_user;
215
ps->niceLevel = p.ki_nice;
217
ps->pid = p.kp_proc.p_pid;
218
ps->ppid = p.kp_eproc.e_ppid;
219
ps->uid = p.kp_eproc.e_ucred.cr_uid;
220
ps->gid = p.kp_eproc.e_pgid;
221
ps->priority = p.kp_proc.p_priority;
222
ps->niceLevel = p.kp_proc.p_nice;
225
/* this isn't usertime -- it's total time (??) */
226
#if __FreeBSD_version >= 500015
227
ps->userTime = p.ki_runtime / 10000;
228
#elif __FreeBSD_version >= 300000
229
#if defined(__DragonFly__)
230
if (!getrusage(p.kp_proc.p_pid, &pru))
232
errx(1, "failed to get rusage info");
234
ps->userTime = pru.ru_utime.tv_usec / 1000; /*p_runtime / 1000*/
236
ps->userTime = p.kp_proc.p_runtime / 10000;
239
ps->userTime = p.kp_proc.p_rtime.tv_sec*100+p.kp_proc.p_rtime.tv_usec/100;
244
/* memory, process name, process uid */
245
/* find out user name with process uid */
246
pwent = getpwuid(ps->uid);
247
strncpy(ps->userName,pwent&&pwent->pw_name? pwent->pw_name:"????",sizeof(ps->userName));
248
ps->userName[sizeof(ps->userName)-1]='\0';
253
#if __FreeBSD_version >= 500015
254
ps->userLoad = 100.0 * (double) p.ki_pctcpu / fscale;
255
ps->vmSize = p.ki_size;
256
ps->vmRss = p.ki_rssize * getpagesize();
257
strlcpy(ps->name,p.ki_comm? p.ki_comm:"????",sizeof(ps->name));
258
strcpy(ps->status,(p.ki_stat>=1)&&(p.ki_stat<=5)? statuses[p.ki_stat-1]:"????");
260
ps->userLoad = 100.0 * (double) p.kp_proc.p_pctcpu / fscale;
261
ps->vmSize = p.kp_eproc.e_vm.vm_map.size;
262
ps->vmRss = p.kp_eproc.e_vm.vm_rssize * getpagesize();
263
#if defined (__DragonFly__)
264
strlcpy(ps->name,p.kp_thread.td_comm ? p.kp_thread.td_comm : "????",
267
strlcpy(ps->name,p.kp_proc.p_comm ? p.kp_proc.p_comm : "????", sizeof(ps->name));
269
strcpy(ps->status,(p.kp_proc.p_stat>=1)&&(p.kp_proc.p_stat<=5)? statuses[p.kp_proc.p_stat-1]:"????");
272
/* process command line */
273
/* do a sysctl to get the command line args. */
277
mib[2] = KERN_PROC_ARGS;
280
if ((sysctl(mib, 4, buf, &buflen, 0, 0) == -1) || !buflen)
281
strcpy(ps->cmdline, "????");
283
strncpy(ps->cmdline, buf, buflen);
289
cleanupProcessList(void)
294
/* All processes that do not have the active flag set are assumed dead
295
* and will be removed from the list. The alive flag is cleared. */
296
for (ps = first_ctnr(ProcessList); ps; ps = next_ctnr(ProcessList))
300
/* Process is still alive. Just clear flag. */
306
/* Process has probably died. We remove it from the list and
307
* destruct the data structure. i needs to be decremented so
308
* that after i++ the next list element will be inspected. */
309
free(remove_ctnr(ProcessList));
315
================================ public part ==================================
319
initProcessList(struct SensorModul* sm)
322
ProcessList = new_ctnr();
324
registerMonitor("ps", "table", printProcessList, printProcessListInfo, sm);
325
registerMonitor("pscount", "integer", printProcessCount, printProcessCountInfo, sm);
329
registerCommand("kill", killProcess);
330
registerCommand("setpriority", setPriority);
333
fscalelen = sizeof(fscale);
334
if (sysctlbyname("kern.fscale", &fscale, &fscalelen, NULL, 0) == -1)
341
exitProcessList(void)
344
removeMonitor("pscount");
351
updateProcessList(void)
356
struct kinfo_proc *p;
361
mib[2] = KERN_PROC_ALL;
362
sysctl(mib, 3, NULL, &len, NULL, 0);
364
sysctl(mib, 3, p, &len, NULL, 0);
366
for (num = 0; num < len / sizeof(struct kinfo_proc); num++)
367
#if __FreeBSD_version >= 500015
368
updateProcess(p[num].ki_pid);
370
updateProcess(p[num].kp_proc.p_pid);
373
cleanupProcessList();
379
printProcessListInfo(const char* cmd)
381
fprintf(CurrentClient, "Name\tPID\tPPID\tUID\tGID\tStatus\tUser%%\tSystem%%\tNice\tVmSize\tVmRss\tLogin\tCommand\n");
382
fprintf(CurrentClient, "s\td\td\td\td\tS\tf\tf\td\tD\tD\ts\ts\n");
386
printProcessList(const char* cmd)
390
ps = first_ctnr(ProcessList); /* skip 'kernel' entry */
391
for (ps = next_ctnr(ProcessList); ps; ps = next_ctnr(ProcessList))
393
fprintf(CurrentClient, "%s\t%ld\t%ld\t%ld\t%ld\t%s\t%.2f\t%.2f\t%d\t%d\t%d\t%s\t%s\n",
394
ps->name, (long)ps->pid, (long)ps->ppid,
395
(long)ps->uid, (long)ps->gid, ps->status,
396
ps->userLoad, ps->sysLoad, ps->niceLevel,
397
ps->vmSize / 1024, ps->vmRss / 1024, ps->userName, ps->cmdline);
402
printProcessCount(const char* cmd)
404
fprintf(CurrentClient, "%d\n", ProcessCount);
408
printProcessCountInfo(const char* cmd)
410
fprintf(CurrentClient, "Number of Processes\t1\t65535\t\n");
414
killProcess(const char* cmd)
418
sscanf(cmd, "%*s %d %d", &pid, &sig);
421
case MENU_ID_SIGABRT:
424
case MENU_ID_SIGALRM:
427
case MENU_ID_SIGCHLD:
430
case MENU_ID_SIGCONT:
445
case MENU_ID_SIGKILL:
448
case MENU_ID_SIGPIPE:
451
case MENU_ID_SIGQUIT:
454
case MENU_ID_SIGSEGV:
457
case MENU_ID_SIGSTOP:
460
case MENU_ID_SIGTERM:
463
case MENU_ID_SIGTSTP:
466
case MENU_ID_SIGTTIN:
469
case MENU_ID_SIGTTOU:
472
case MENU_ID_SIGUSR1:
475
case MENU_ID_SIGUSR2:
479
if (kill((pid_t) pid, sig))
484
fprintf(CurrentClient, "4\t%d\n", pid);
487
fprintf(CurrentClient, "3\t%d\n", pid);
490
fprintf(CurrentClient, "2\t%d\n", pid);
493
fprintf(CurrentClient, "1\t%d\n", pid); /* unknown error */
499
fprintf(CurrentClient, "0\t%d\n", pid);
503
setPriority(const char* cmd)
507
sscanf(cmd, "%*s %d %d", &pid, &prio);
508
if (setpriority(PRIO_PROCESS, pid, prio))
513
fprintf(CurrentClient, "4\n");
516
fprintf(CurrentClient, "3\n");
520
fprintf(CurrentClient, "2\n");
523
fprintf(CurrentClient, "1\n"); /* unknown error */
528
fprintf(CurrentClient, "0\n");