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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
29
#include <sys/param.h>
30
#include <sys/sysctl.h>
32
#include <sys/types.h>
37
#include "../../gui/SignalIDs.h"
39
#include "ProcessList.h"
41
#include "ksysguardd.h"
43
CONTAINER ProcessList = 0;
49
/* This flag is set for all found processes at the beginning of the
50
* process list update. Processes that do not have this flag set will
51
* be assumed dead and removed from the list. The flag is cleared after
52
* each list update. */
58
/* the parent process ID */
61
/* the real user ID */
64
/* the real group ID */
67
/* a character description of the process status */
70
/* the number of the tty the process owns */
74
* The nice level. The range should be -20 to 20. I'm not sure
75
* whether this is true for all platforms.
80
* The scheduling priority.
85
* The total amount of memory the process uses. This includes shared and
91
* The amount of physical memory the process currently uses.
96
* The amount of memory (shared/swapped/etc) the process shares with
102
* The number of 1/100 of a second the process has spend in user space.
103
* If a machine has an uptime of 1 1/2 years or longer this is not a
104
* good idea. I never thought that the stability of UNIX could get me
107
unsigned int userTime;
110
* The number of 1/100 of a second the process has spend in system space.
111
* If a machine has an uptime of 1 1/2 years or longer this is not a
112
* good idea. I never thought that the stability of UNIX could get me
115
unsigned int sysTime;
117
/* system time as multime of 100ms */
120
/* the current CPU load (in %) from user space */
123
/* the current CPU load (in %) from system space */
126
/* the name of the process */
129
/* the command used to start the process */
132
/* the login name of the user that owns this process */
136
static unsigned ProcessCount;
139
processCmp(void* p1, void* p2)
141
return (((ProcessInfo*) p1)->pid - ((ProcessInfo*) p2)->pid);
145
findProcessInList(int pid)
151
if ((index = search_ctnr(ProcessList, processCmp, &key)) < 0)
154
return (get_ctnr(ProcessList, index));
158
fillProcessCmdline(char *cmdline, struct kinfo_proc2 *p, size_t maxlen)
162
static char *argbuf = NULL;
163
static size_t arglen = 0;
165
strlcpy(cmdline, p->p_comm, maxlen);
169
argbuf = malloc(arglen);
172
mib[1] = KERN_PROC_ARGS;
174
mib[3] = KERN_PROC_ARGV;
177
ret = sysctl(mib, 4, argbuf, &arglen, NULL, 0);
178
if (ret == -1 && errno == ENOMEM) {
180
n = realloc(argbuf, arglen * 2);
194
argv = (char **)argbuf;
196
strlcpy(cmdline, argv[0], maxlen);
197
for (argc = 1; argv[argc] != NULL; argc++) {
198
strlcat(cmdline, " ", maxlen);
199
strlcat(cmdline, argv[argc], maxlen);
202
strlcpy(cmdline, p->p_comm, maxlen);
207
updateProcess(struct kinfo_proc2 *p)
209
static const char * const statuses[] = { "idle","run","sleep","stop","zombie" };
212
struct passwd* pwent;
213
pid_t pid = p->p_pid;
215
if ((ps = findProcessInList(pid)) == 0)
217
ps = (ProcessInfo*) malloc(sizeof(ProcessInfo));
220
push_ctnr(ProcessList, ps);
221
bsort_ctnr(ProcessList, processCmp);
227
ps->ppid = p->p_ppid;
230
ps->priority = p->p_priority;
231
ps->niceLevel = p->p_nice;
233
/* this isn't usertime -- it's total time (??) */
234
ps->userTime = p->p_uutime_sec*100+p->p_uutime_usec/100;
238
/* memory, process name, process uid */
239
/* find out user name with process uid */
240
pwent = getpwuid(ps->uid);
241
strlcpy(ps->userName,pwent&&pwent->pw_name? pwent->pw_name:"????",sizeof(ps->userName));
242
ps->userName[sizeof(ps->userName)-1]='\0';
244
ps->userLoad = p->p_pctcpu / 100;
245
ps->vmSize = (p->p_vm_tsize +
247
p->p_vm_ssize) * getpagesize();
248
ps->vmRss = p->p_vm_rssize * getpagesize();
249
strlcpy(ps->name,p->p_comm ? p->p_comm : "????", sizeof(ps->name));
250
strlcpy(ps->status,(p->p_stat>=1)&&(p->p_stat<=5)? statuses[p->p_stat-1]:"????", sizeof(ps->status));
252
fillProcessCmdline(ps->cmdline, p, sizeof(ps->cmdline));
253
/* process command line */
259
cleanupProcessList(void)
264
/* All processes that do not have the active flag set are assumed dead
265
* and will be removed from the list. The alive flag is cleared. */
266
for (ps = first_ctnr(ProcessList); ps; ps = next_ctnr(ProcessList))
270
/* Process is still alive. Just clear flag. */
276
/* Process has probably died. We remove it from the list and
277
* destruct the data structure. */
278
free(remove_ctnr(ProcessList));
284
================================ public part ==================================
288
initProcessList(struct SensorModul* sm)
290
ProcessList = new_ctnr();
292
registerMonitor("ps", "table", printProcessList, printProcessListInfo, sm);
293
registerMonitor("pscount", "integer", printProcessCount, printProcessCountInfo, sm);
297
registerCommand("kill", killProcess);
298
registerCommand("setpriority", setPriority);
305
exitProcessList(void)
308
removeMonitor("pscount");
315
updateProcessList(void)
320
struct kinfo_proc2 *p;
325
mib[2] = KERN_PROC_ALL;
327
mib[4] = sizeof(struct kinfo_proc2);
329
if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1)
335
mib[5] = len/ sizeof(struct kinfo_proc2);
336
if (sysctl(mib, 6, p, &len, NULL, 0) == -1)
339
for (num = 0; num < len / sizeof(struct kinfo_proc2); num++)
340
updateProcess(&p[num]);
342
cleanupProcessList();
348
printProcessListInfo(const char* cmd)
350
fprintf(CurrentClient, "Name\tPID\tPPID\tUID\tGID\tStatus\tUser%%\tSystem%%\tNice\tVmSize\tVmRss\tLogin\tCommand\n");
351
fprintf(CurrentClient, "s\td\td\td\td\tS\tf\tf\td\tD\tD\ts\ts\n");
355
printProcessList(const char* cmd)
359
for (ps = first_ctnr(ProcessList); ps; ps = next_ctnr(ProcessList))
361
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",
362
ps->name, (long)ps->pid, (long)ps->ppid,
363
(long)ps->uid, (long)ps->gid, ps->status,
364
ps->userLoad, ps->sysLoad, ps->niceLevel,
365
ps->vmSize / 1024, ps->vmRss / 1024, ps->userName, ps->cmdline);
370
printProcessCount(const char* cmd)
372
fprintf(CurrentClient, "%d\n", ProcessCount);
376
printProcessCountInfo(const char* cmd)
378
fprintf(CurrentClient, "Number of Processes\t1\t65535\t\n");
382
killProcess(const char* cmd)
386
sscanf(cmd, "%*s %d %d", &pid, &sig);
389
case MENU_ID_SIGABRT:
392
case MENU_ID_SIGALRM:
395
case MENU_ID_SIGCHLD:
398
case MENU_ID_SIGCONT:
413
case MENU_ID_SIGKILL:
416
case MENU_ID_SIGPIPE:
419
case MENU_ID_SIGQUIT:
422
case MENU_ID_SIGSEGV:
425
case MENU_ID_SIGSTOP:
428
case MENU_ID_SIGTERM:
431
case MENU_ID_SIGTSTP:
434
case MENU_ID_SIGTTIN:
437
case MENU_ID_SIGTTOU:
440
case MENU_ID_SIGUSR1:
443
case MENU_ID_SIGUSR2:
447
if (kill((pid_t) pid, sig))
452
fprintf(CurrentClient, "4\t%d\n", pid);
455
fprintf(CurrentClient, "3\t%d\n", pid);
458
fprintf(CurrentClient, "2\t%d\n", pid);
461
fprintf(CurrentClient, "1\t%d\n", pid); /* unknown error */
467
fprintf(CurrentClient, "0\t%d\n", pid);
471
setPriority(const char* cmd)
475
sscanf(cmd, "%*s %d %d", &pid, &prio);
476
if (setpriority(PRIO_PROCESS, pid, prio))
481
fprintf(CurrentClient, "4\n");
484
fprintf(CurrentClient, "3\n");
488
fprintf(CurrentClient, "2\n");
491
fprintf(CurrentClient, "1\n"); /* unknown error */
496
fprintf(CurrentClient, "0\n");