By default, Bugzilla does not search the list of RESOLVED bugs.
You can force it to do so by putting the upper-case word ALL in front of your search query, e.g.: ALL tdelibs
We recommend searching for bugs this way, as you may discover that your bug has already been resolved and fixed in a later release. View | Details | Raw Unified | Return to bug 2110
Collapse All | Expand All

(-)ksysguard/ksysguardd/OpenBSD/ProcessList.c.orig (+500 lines)
Line 0 Link Here
1
/*
2
    KSysGuard, the KDE System Guard
3
4
	Copyright (c) 1999-2000 Hans Petter Bieker<bieker@kde.org>
5
	Copyright (c) 1999 Chris Schlaeger <cs@kde.org>
6
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.
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 <config.h>
24
25
#include <ctype.h>
26
#include <dirent.h>
27
#include <pwd.h>
28
#include <stdio.h>
29
#include <stdlib.h>
30
#include <string.h>
31
#include <sys/param.h>
32
#include <sys/sysctl.h>
33
#include <sys/time.h>
34
#include <sys/types.h>
35
#include <sys/user.h>
36
#include <unistd.h>
37
#include <signal.h>
38
39
#include "../../gui/SignalIDs.h"
40
#include "Command.h"
41
#include "ProcessList.h"
42
#include "ccont.h"
43
#include "ksysguardd.h"
44
45
CONTAINER ProcessList = 0;
46
47
#define BUFSIZE 1024
48
49
typedef struct
50
{
51
	/* This flag is set for all found processes at the beginning of the
52
	 * process list update. Processes that do not have this flag set will
53
	 * be assumed dead and removed from the list. The flag is cleared after
54
	 * each list update. */
55
	int alive;
56
57
	/* the process ID */
58
	pid_t pid;
59
60
	/* the parent process ID */
61
	pid_t ppid;
62
63
	/* the real user ID */
64
	uid_t uid;
65
66
	/* the real group ID */
67
	gid_t gid;
68
69
	/* a character description of the process status */
70
	char status[16];
71
72
	/* the number of the tty the process owns */
73
	int ttyNo;
74
75
	/*
76
	 * The nice level. The range should be -20 to 20. I'm not sure
77
	 * whether this is true for all platforms.
78
	 */
79
	int niceLevel;
80
81
	/*
82
	 * The scheduling priority.
83
	 */
84
	int priority;
85
86
	/*
87
	 * The total amount of memory the process uses. This includes shared and
88
	 * swapped memory.
89
	 */
90
	unsigned int vmSize;
91
92
	/*
93
	 * The amount of physical memory the process currently uses.
94
	 */
95
	unsigned int vmRss;
96
97
	/*
98
	 * The amount of memory (shared/swapped/etc) the process shares with
99
	 * other processes.
100
	 */
101
	unsigned int vmLib;
102
103
	/*
104
	 * The number of 1/100 of a second the process has spend in user space.
105
	 * If a machine has an uptime of 1 1/2 years or longer this is not a
106
	 * good idea. I never thought that the stability of UNIX could get me
107
	 * into trouble! ;)
108
	 */
109
	unsigned int userTime;
110
111
	/*
112
	 * The number of 1/100 of a second the process has spend in system space.
113
	 * If a machine has an uptime of 1 1/2 years or longer this is not a
114
	 * good idea. I never thought that the stability of UNIX could get me
115
	 * into trouble! ;)
116
	 */
117
	unsigned int sysTime;
118
119
	/* system time as multime of 100ms */
120
	int centStamp;
121
122
	/* the current CPU load (in %) from user space */
123
	double userLoad;
124
125
	/* the current CPU load (in %) from system space */
126
	double sysLoad;
127
128
	/* the name of the process */
129
	char name[64];
130
131
	/* the command used to start the process */
132
	char cmdline[256];
133
134
	/* the login name of the user that owns this process */
135
 	char userName[32];
136
} ProcessInfo;
137
138
static unsigned ProcessCount;
139
140
static int
141
processCmp(void* p1, void* p2)
142
{
143
	return (((ProcessInfo*) p1)->pid - ((ProcessInfo*) p2)->pid);
144
}
145
146
static ProcessInfo*
147
findProcessInList(int pid)
148
{
149
	ProcessInfo key;
150
	long index;
151
152
	key.pid = pid;
153
	if ((index = search_ctnr(ProcessList, processCmp, &key)) < 0)
154
		return (0);
155
156
	return (get_ctnr(ProcessList, index));
157
}
158
159
static void
160
fillProcessCmdline(char *cmdline, struct kinfo_proc *p, size_t maxlen)
161
{
162
	int mib[4];
163
	int ret = -1;
164
	static char *argbuf = NULL;
165
	static size_t arglen = 0;
166
167
	strlcpy(cmdline, p->p_comm, maxlen);
168
169
	if (!argbuf) {
170
		arglen = 1024;
171
		argbuf = malloc(arglen);
172
	}
173
	mib[0] = CTL_KERN;
174
	mib[1] = KERN_PROC_ARGS;
175
	mib[2] = p->p_pid;
176
	mib[3] = KERN_PROC_ARGV;
177
178
	while (argbuf) {
179
		ret = sysctl(mib, 4, argbuf, &arglen, NULL, 0);
180
		if (ret == -1 && errno == ENOMEM) {
181
			char *n;
182
			n = realloc(argbuf, arglen * 2);
183
			if (n != 0) {
184
				argbuf = n;
185
				arglen *= 2;
186
				continue;
187
			}
188
		}
189
		break;
190
	}
191
192
	if (ret != 1) {
193
		char **argv;
194
		int argc;
195
196
		argv = (char **)argbuf;
197
		if (argv[0] != NULL)
198
			strlcpy(cmdline, argv[0], maxlen);
199
		for (argc = 1; argv[argc] != NULL; argc++) {
200
			strlcat(cmdline, " ", maxlen);
201
			strlcat(cmdline, argv[argc], maxlen);
202
		}
203
	} else {
204
		strlcpy(cmdline, p->p_comm, maxlen);
205
	} 
206
}
207
208
static int
209
updateProcess(struct kinfo_proc *p)
210
{
211
	static char *statuses[] = { "idle","run","sleep","stop","zombie" };
212
	
213
	ProcessInfo* ps;
214
	struct passwd* pwent;
215
	pid_t pid = p->p_pid;
216
217
	if ((ps = findProcessInList(pid)) == 0)
218
	{
219
		ps = (ProcessInfo*) malloc(sizeof(ProcessInfo));
220
		ps->pid = pid;
221
		ps->centStamp = 0;
222
		push_ctnr(ProcessList, ps);
223
		bsort_ctnr(ProcessList, processCmp);
224
	} 
225
226
	ps->alive = 1;
227
228
        ps->pid       = p->p_pid;
229
        ps->ppid      = p->p_ppid;
230
        ps->uid       = p->p_uid;
231
        ps->gid       = p->p_gid;
232
        ps->priority  = p->p_priority;
233
        ps->niceLevel = p->p_nice;
234
235
        /* this isn't usertime -- it's total time (??) */
236
	ps->userTime = p->p_uutime_sec*100+p->p_uutime_usec/100;
237
        ps->sysTime  = 0;
238
        ps->sysLoad  = 0;
239
240
        /* memory, process name, process uid */
241
	/* find out user name with process uid */
242
	pwent = getpwuid(ps->uid);
243
	strlcpy(ps->userName,pwent&&pwent->pw_name? pwent->pw_name:"????",sizeof(ps->userName));
244
	ps->userName[sizeof(ps->userName)-1]='\0';
245
246
        ps->userLoad = p->p_pctcpu / 100;
247
	ps->vmSize   = (p->p_vm_tsize +
248
			p->p_vm_dsize +
249
			p->p_vm_ssize) * getpagesize();
250
	ps->vmRss    = p->p_vm_rssize * getpagesize();
251
	strlcpy(ps->name,p->p_comm ? p->p_comm : "????", sizeof(ps->name));
252
	strlcpy(ps->status,(p->p_stat>=1)&&(p->p_stat<=5)? statuses[p->p_stat-1]:"????", sizeof(ps->status));
253
254
	fillProcessCmdline(ps->cmdline, p, sizeof(ps->cmdline));
255
        /* process command line */
256
257
	return (0);
258
}
259
260
static void
261
cleanupProcessList(void)
262
{
263
	ProcessInfo* ps;
264
265
	ProcessCount = 0;
266
	/* All processes that do not have the active flag set are assumed dead
267
	 * and will be removed from the list. The alive flag is cleared. */
268
	for (ps = first_ctnr(ProcessList); ps; ps = next_ctnr(ProcessList))
269
	{
270
		if (ps->alive)
271
		{
272
			/* Process is still alive. Just clear flag. */
273
			ps->alive = 0;
274
			ProcessCount++;
275
		}
276
		else
277
		{
278
			/* Process has probably died. We remove it from the list and
279
			 * destruct the data structure. i needs to be decremented so
280
			 * that after i++ the next list element will be inspected. */
281
			free(remove_ctnr(ProcessList));
282
		}
283
	}
284
}
285
286
/*
287
================================ public part ==================================
288
*/
289
290
void
291
initProcessList(struct SensorModul* sm)
292
{
293
	ProcessList = new_ctnr();
294
295
	registerMonitor("ps", "table", printProcessList, printProcessListInfo, sm);
296
	registerMonitor("pscount", "integer", printProcessCount, printProcessCountInfo, sm);
297
298
	if (!RunAsDaemon)
299
	{
300
		registerCommand("kill", killProcess);
301
		registerCommand("setpriority", setPriority);
302
	}
303
304
	updateProcessList();
305
}
306
307
void
308
exitProcessList(void)
309
{
310
	removeMonitor("ps");
311
	removeMonitor("pscount");
312
313
	if (ProcessList)
314
		free (ProcessList);
315
}
316
317
int
318
updateProcessList(void)
319
{
320
        int mib[6];
321
        size_t len;
322
        size_t num;
323
        struct kinfo_proc *p;
324
325
326
        mib[0] = CTL_KERN;
327
        mib[1] = KERN_PROC;
328
        mib[2] = KERN_PROC_ALL;
329
	mib[3] = 0;
330
	mib[4] = sizeof(struct kinfo_proc);
331
	mib[5] = 0;
332
        if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1)
333
		return 0;
334
	len = 5 * len / 4;
335
	p = malloc(len);
336
	if (!p)
337
		return 0;
338
	mib[5] = len/ sizeof(struct kinfo_proc);
339
        if (sysctl(mib, 6, p, &len, NULL, 0) == -1)
340
		return 0;
341
342
	for (num = 0; num < len / sizeof(struct kinfo_proc); num++)
343
		updateProcess(&p[num]);
344
	free(p);
345
	cleanupProcessList();
346
347
	return (0);
348
}
349
350
void
351
printProcessListInfo(const char* cmd)
352
{
353
	fprintf(CurrentClient, "Name\tPID\tPPID\tUID\tGID\tStatus\tUser%%\tSystem%%\tNice\tVmSize\tVmRss\tLogin\tCommand\n");
354
	fprintf(CurrentClient, "s\td\td\td\td\tS\tf\tf\td\tD\tD\ts\ts\n");
355
}
356
357
void
358
printProcessList(const char* cmd)
359
{
360
	ProcessInfo* ps;
361
362
	for (ps = first_ctnr(ProcessList); ps; ps = next_ctnr(ProcessList))
363
	{
364
		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",
365
			   ps->name, (long)ps->pid, (long)ps->ppid,
366
			   (long)ps->uid, (long)ps->gid, ps->status,
367
			   ps->userLoad, ps->sysLoad, ps->niceLevel,
368
			   ps->vmSize / 1024, ps->vmRss / 1024, ps->userName, ps->cmdline);
369
	}
370
}
371
372
void
373
printProcessCount(const char* cmd)
374
{
375
	fprintf(CurrentClient, "%d\n", ProcessCount);
376
}
377
378
void
379
printProcessCountInfo(const char* cmd)
380
{
381
	fprintf(CurrentClient, "Number of Processes\t1\t65535\t\n");
382
}
383
384
void
385
killProcess(const char* cmd)
386
{
387
	int sig, pid;
388
389
	sscanf(cmd, "%*s %d %d", &pid, &sig);
390
	switch(sig)
391
	{
392
	case MENU_ID_SIGABRT:
393
		sig = SIGABRT;
394
		break;
395
	case MENU_ID_SIGALRM:
396
		sig = SIGALRM;
397
		break;
398
	case MENU_ID_SIGCHLD:
399
		sig = SIGCHLD;
400
		break;
401
	case MENU_ID_SIGCONT:
402
		sig = SIGCONT;
403
		break;
404
	case MENU_ID_SIGFPE:
405
		sig = SIGFPE;
406
		break;
407
	case MENU_ID_SIGHUP:
408
		sig = SIGHUP;
409
		break;
410
	case MENU_ID_SIGILL:
411
		sig = SIGILL;
412
		break;
413
	case MENU_ID_SIGINT:
414
		sig = SIGINT;
415
		break;
416
	case MENU_ID_SIGKILL:
417
		sig = SIGKILL;
418
		break;
419
	case MENU_ID_SIGPIPE:
420
		sig = SIGPIPE;
421
		break;
422
	case MENU_ID_SIGQUIT:
423
		sig = SIGQUIT;
424
		break;
425
	case MENU_ID_SIGSEGV:
426
		sig = SIGSEGV;
427
		break;
428
	case MENU_ID_SIGSTOP:
429
		sig = SIGSTOP;
430
		break;
431
	case MENU_ID_SIGTERM:
432
		sig = SIGTERM;
433
		break;
434
	case MENU_ID_SIGTSTP:
435
		sig = SIGTSTP;
436
		break;
437
	case MENU_ID_SIGTTIN:
438
		sig = SIGTTIN;
439
		break;
440
	case MENU_ID_SIGTTOU:
441
		sig = SIGTTOU;
442
		break;
443
	case MENU_ID_SIGUSR1:
444
		sig = SIGUSR1;
445
		break;
446
	case MENU_ID_SIGUSR2:
447
		sig = SIGUSR2;
448
		break;
449
	}
450
	if (kill((pid_t) pid, sig))
451
	{
452
		switch(errno)
453
		{
454
		case EINVAL:
455
			fprintf(CurrentClient, "4\t%d\n", pid);
456
			break;
457
		case ESRCH:
458
			fprintf(CurrentClient, "3\t%d\n", pid);
459
			break;
460
		case EPERM:
461
			fprintf(CurrentClient, "2\t%d\n", pid);
462
			break;
463
		default:
464
			fprintf(CurrentClient, "1\t%d\n", pid);	/* unknown error */
465
			break;
466
		}
467
468
	}
469
	else
470
		fprintf(CurrentClient, "0\t%d\n", pid);
471
}
472
473
void
474
setPriority(const char* cmd)
475
{
476
	int pid, prio;
477
478
	sscanf(cmd, "%*s %d %d", &pid, &prio);
479
	if (setpriority(PRIO_PROCESS, pid, prio))
480
	{
481
		switch(errno)
482
		{
483
		case EINVAL:
484
			fprintf(CurrentClient, "4\n");
485
			break;
486
		case ESRCH:
487
			fprintf(CurrentClient, "3\n");
488
			break;
489
		case EPERM:
490
		case EACCES:
491
			fprintf(CurrentClient, "2\n");
492
			break;
493
		default:
494
			fprintf(CurrentClient, "1\n");	/* unknown error */
495
			break;
496
		}
497
	}
498
	else
499
		fprintf(CurrentClient, "0\n");
500
}

Return to bug 2110