summaryrefslogtreecommitdiffstats
path: root/ksysguard/ksysguardd/Irix/ProcessList.c
diff options
context:
space:
mode:
Diffstat (limited to 'ksysguard/ksysguardd/Irix/ProcessList.c')
-rw-r--r--ksysguard/ksysguardd/Irix/ProcessList.c462
1 files changed, 462 insertions, 0 deletions
diff --git a/ksysguard/ksysguardd/Irix/ProcessList.c b/ksysguard/ksysguardd/Irix/ProcessList.c
new file mode 100644
index 000000000..523d87d26
--- /dev/null
+++ b/ksysguard/ksysguardd/Irix/ProcessList.c
@@ -0,0 +1,462 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
+
+ Irix support by Carsten Kroll <ckroll@pinnaclesys.com>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <pwd.h>
+#include <sys/resource.h>
+#include <sys/procfs.h>
+#include <sys/statfs.h>
+#include <sys/sysmp.h>
+#include <sys/sysinfo.h>
+
+#include "ccont.h"
+#include "../../gui/SignalIDs.h"
+#include "ksysguardd.h"
+
+#include "Command.h"
+#include "ProcessList.h"
+
+#define BUFSIZE 1024
+#define KDEINITLEN strlen("kdeinit: ")
+
+typedef struct {
+ int alive; /* for "garbage collection" */
+ pid_t pid; /* process ID */
+ pid_t ppid; /* parent process ID */
+ uid_t uid; /* process owner (real UID) */
+ gid_t gid; /* process group (real GID) */
+ char *userName; /* process owner (name) */
+ int nThreads; /* # of threads in this process */
+ int Prio; /* scheduling priority */
+ size_t Size; /* total size of process image */
+ size_t RSSize; /* resident set size */
+ char State[8]; /* process state */
+ double Time; /* CPU time for the process in 100ms */
+ double Load; /* CPU load in % */
+ char Command[PRCOMSIZ];/* command name */
+ char CmdLine[PRARGSZ];/* command line */
+ double centStamp; /* timestamp for CPU load */
+} ProcessInfo;
+
+static CONTAINER ProcessList = 0;
+static unsigned ProcessCount = 0; /* # of processes */
+static DIR *procdir; /* handle for /proc */
+static int pagesz;
+
+#define KBYTES 1024
+
+/*
+ * lwpStateName() -- return string representation of process state
+ */
+char *lwpStateName( prpsinfo_t lwpinfo ) {
+
+ static char result[8];
+
+ switch( lwpinfo.pr_sname ) {
+ case 'S':
+ sprintf( result, "%s", "sleep" );
+ break;
+ case 'R':
+ sprintf( result, "%s", "run" );
+ break;
+ case 'Z':
+ sprintf( result, "%s", "zombie" );
+ break;
+ case 'T':
+ sprintf( result, "%s", "stop" );
+ break;
+ case 'I':
+ sprintf( result, "%s", "start" );
+ break;
+ case 'X':
+ sprintf( result, "%s", "wmem" );
+ case '0':
+ sprintf( result, "%s/%d", "cpu", (int) lwpinfo.pr_sonproc );
+ break;
+ default:
+ sprintf( result, "%s", "???" );
+ break;
+ }
+
+ return( result );
+}
+
+static void validateStr( char *string ) {
+
+ char *ptr = string;
+
+ /*
+ * remove all chars that might screw up communication
+ */
+ while( *ptr != '\0' ) {
+ if( *ptr == '\t' || *ptr == '\n' || *ptr == '\r' )
+ *ptr = ' ';
+ ptr++;
+ }
+ /*
+ * make sure there's at least one char
+ */
+ if( string[0] == '\0' )
+ strcpy( string, " " );
+}
+
+static int processCmp( void *p1, void *p2 ) {
+
+ return( ((ProcessInfo *) p1)->pid - ((ProcessInfo *) p2)->pid );
+}
+
+static ProcessInfo *findProcessInList( pid_t pid ) {
+
+ ProcessInfo key;
+ long index;
+
+ key.pid = pid;
+ if( (index = search_ctnr( ProcessList, processCmp, &key )) < 0 )
+ return( NULL );
+
+ return( get_ctnr( ProcessList, index ));
+}
+
+static int updateProcess( pid_t pid ) {
+ ProcessInfo *ps;
+ int fd;
+ char buf[BUFSIZE];
+ prpsinfo_t psinfo;
+ struct passwd *pw;
+ register double newCentStamp,timeDiff, usDiff,usTime;
+ struct timeval tv;
+
+ if( (ps = findProcessInList( pid )) == NULL ) {
+ if( (ps = (ProcessInfo *) malloc( sizeof( ProcessInfo )))
+ == NULL ) {
+ print_error( "cannot malloc()\n" );
+ return( -1 );
+ }
+ ps->pid = pid;
+ ps->userName = NULL;
+ ps->alive = 0;
+
+ gettimeofday(&tv, 0);
+ ps->centStamp = (double)tv.tv_sec * 100.0 + (double)tv.tv_usec / 10000.0;
+
+ push_ctnr( ProcessList, ps );
+ bsort_ctnr( ProcessList, processCmp );
+ }
+
+ sprintf( buf, "%s/pinfo/%ld", PROCDIR, pid );
+ if( (fd = open( buf, O_RDONLY )) < 0 ) {
+ /* process terminated */
+ return( -1 );
+ }
+
+
+
+ if( ioctl(fd,PIOCPSINFO,&psinfo) < 0) {
+ print_error( "cannot read psinfo from \"%s\"\n", buf );
+ close( fd );
+ return( -1 );
+ }
+ close( fd );
+
+ ps->ppid = psinfo.pr_ppid;
+ ps->uid = psinfo.pr_uid;
+ ps->gid = psinfo.pr_gid;
+
+ pw = getpwuid( psinfo.pr_uid );
+ if( ps->userName != NULL )
+ free( ps->userName );
+ ps->userName = strdup( pw->pw_name );
+
+ strncpy (ps->State,lwpStateName( psinfo ),8);
+ ps->State[7]='\0';
+
+
+ ps->Prio = psinfo.pr_pri;
+
+ gettimeofday(&tv, 0);
+ newCentStamp = (double)tv.tv_sec * 100.0 + (double) tv.tv_usec / 10000.0;
+ usTime = (double) psinfo.pr_time.tv_sec * 100.0 + (double)psinfo.pr_time.tv_nsec / 10000000.0;
+
+ timeDiff = newCentStamp - ps->centStamp;
+ usDiff = usTime - ps->Time;
+
+ if ((timeDiff > 0.0) && (usDiff >= 0.0))
+ {
+ ps->Load = (usDiff / timeDiff) * 100.0;
+ /* During startup we get bigger loads since the time diff
+ * cannot be correct. So we force it to 0. */
+ ps->Load = (ps->Load > 100.0) ? 0.0 : ps->Load;
+ }
+ else
+ ps->Load = 0.0;
+
+ ps->centStamp = newCentStamp;
+ ps->Time = usTime;
+
+ ps->Size = (psinfo.pr_size * pagesz)/KBYTES;
+ ps->RSSize = (psinfo.pr_rssize * pagesz)/KBYTES;
+
+ strncpy(ps->Command,psinfo.pr_fname,PRCOMSIZ);
+ ps->Command[PRCOMSIZ-1]='\0';
+
+ strncpy(ps->CmdLine,psinfo.pr_psargs,PRARGSZ);
+ ps->CmdLine[PRARGSZ-1]='\0';
+
+ validateStr( ps->Command );
+ validateStr( ps->CmdLine );
+
+ ps->alive = 1;
+ return( 0 );
+}
+
+static void cleanupProcessList( void ) {
+
+ ProcessInfo *ps;
+
+ ProcessCount = 0;
+ for( ps = first_ctnr( ProcessList ); ps; ps = next_ctnr( ProcessList )) {
+ if( ps->alive ) {
+ ps->alive = 0;
+ ProcessCount++;
+ } else {
+ free( remove_ctnr( ProcessList ));
+ }
+ }
+}
+
+void initProcessList( struct SensorModul* sm ) {
+
+ if( (procdir = opendir( PROCDIR )) == NULL ) {
+ print_error( "cannot open \"%s\" for reading\n", PROCDIR );
+ return;
+ }
+ pagesz=getpagesize();
+ ProcessList = new_ctnr();
+ updateProcessList();
+
+ /*
+ * register the supported monitors & commands
+ */
+ registerMonitor( "pscount", "integer",
+ printProcessCount, printProcessCountInfo, sm );
+ registerMonitor( "ps", "table",
+ printProcessList, printProcessListInfo, sm );
+
+ if (!RunAsDaemon)
+ {
+ registerCommand("kill", killProcess);
+ registerCommand("setpriority", setPriority);
+ }
+}
+
+void exitProcessList( void ) {
+
+ removeMonitor("ps");
+ removeMonitor("pscount");
+
+ if (!RunAsDaemon)
+ {
+ removeCommand("kill");
+ removeCommand("setpriority");
+ }
+
+ destr_ctnr( ProcessList, free );
+}
+
+int updateProcessList( void ) {
+
+ struct dirent *de;
+ struct statfs sf;
+
+ statfs("/proc/pinfo",&sf,sizeof(sf),0);
+ ProcessCount = sf.f_files;
+
+ rewinddir( procdir );
+ while( (de = readdir( procdir )) != NULL ) {
+ /*
+ * skip '.' and '..'
+ */
+ if( de->d_name[0] == '.' )
+ continue;
+
+ /*
+ * fetch the process info and insert it into the info table
+ */
+ updateProcess( (pid_t) atol( de->d_name ));
+ }
+ cleanupProcessList();
+
+ return( 0 );
+}
+
+void printProcessListInfo( const char *cmd ) {
+ fprintf(CurrentClient, "Name\tPID\tPPID\tGID\tStatus\tUser"
+ "\tSize\tResident\t%% CPU\tPriority\tCommand\n" );
+ fprintf(CurrentClient, "s\td\td\td\ts\ts\tD\tD\tf\td\ts\n" );
+}
+
+void printProcessList( const char *cmd ) {
+
+ ProcessInfo *ps;
+
+ for( ps = first_ctnr( ProcessList ); ps; ps = next_ctnr( ProcessList )) {
+ fprintf(CurrentClient,
+ "%s\t%ld\t%ld\t%ld\t%s\t%s\t%d\t%d\t%.2f\t%d\t%s\n",
+ ps->Command,
+ (long) ps->pid,
+ (long) ps->ppid,
+ (long) ps->gid,
+ ps->State,
+ ps->userName,
+ ps->Size,
+ ps->RSSize,
+ ps->Load,
+ ps->Prio,
+ ps->CmdLine);
+ }
+
+ fprintf(CurrentClient, "\n");
+}
+
+void printProcessCount( const char *cmd ) {
+ fprintf(CurrentClient, "%d\n", ProcessCount );
+}
+
+void printProcessCountInfo( const char *cmd ) {
+ fprintf(CurrentClient, "Number of Processes\t0\t0\t\n" );
+}
+
+void killProcess( const char *cmd ) {
+
+ int sig, pid;
+
+ sscanf( cmd, "%*s %d %d", &pid, &sig );
+
+ switch( sig ) {
+ case MENU_ID_SIGABRT:
+ sig = SIGABRT;
+ break;
+ case MENU_ID_SIGALRM:
+ sig = SIGALRM;
+ break;
+ case MENU_ID_SIGCHLD:
+ sig = SIGCHLD;
+ break;
+ case MENU_ID_SIGCONT:
+ sig = SIGCONT;
+ break;
+ case MENU_ID_SIGFPE:
+ sig = SIGFPE;
+ break;
+ case MENU_ID_SIGHUP:
+ sig = SIGHUP;
+ break;
+ case MENU_ID_SIGILL:
+ sig = SIGILL;
+ break;
+ case MENU_ID_SIGINT:
+ sig = SIGINT;
+ break;
+ case MENU_ID_SIGKILL:
+ sig = SIGKILL;
+ break;
+ case MENU_ID_SIGPIPE:
+ sig = SIGPIPE;
+ break;
+ case MENU_ID_SIGQUIT:
+ sig = SIGQUIT;
+ break;
+ case MENU_ID_SIGSEGV:
+ sig = SIGSEGV;
+ break;
+ case MENU_ID_SIGSTOP:
+ sig = SIGSTOP;
+ break;
+ case MENU_ID_SIGTERM:
+ sig = SIGTERM;
+ break;
+ case MENU_ID_SIGTSTP:
+ sig = SIGTSTP;
+ break;
+ case MENU_ID_SIGTTIN:
+ sig = SIGTTIN;
+ break;
+ case MENU_ID_SIGTTOU:
+ sig = SIGTTOU;
+ break;
+ case MENU_ID_SIGUSR1:
+ sig = SIGUSR1;
+ break;
+ case MENU_ID_SIGUSR2:
+ sig = SIGUSR2;
+ break;
+ }
+ if( kill( (pid_t) pid, sig )) {
+ switch( errno ) {
+ case EINVAL:
+ fprintf(CurrentClient, "4\n" );
+ break;
+ case ESRCH:
+ fprintf(CurrentClient, "3\n" );
+ break;
+ case EPERM:
+ fprintf(CurrentClient, "2\n" );
+ break;
+ default:
+ fprintf(CurrentClient, "1\n" ); /* unknown error */
+ break;
+ }
+ } else
+ fprintf(CurrentClient, "0\n");
+}
+
+void setPriority( const char *cmd ) {
+ int pid, prio;
+
+ sscanf( cmd, "%*s %d %d", &pid, &prio );
+ if( setpriority( PRIO_PROCESS, pid, prio )) {
+ switch( errno ) {
+ case EINVAL:
+ fprintf(CurrentClient, "4\n" );
+ break;
+ case ESRCH:
+ fprintf(CurrentClient, "3\n" );
+ break;
+ case EPERM:
+ case EACCES:
+ fprintf(CurrentClient, "2\n" );
+ break;
+ default:
+ fprintf(CurrentClient, "1\n" ); /* unknown error */
+ break;
+ }
+ } else
+ fprintf(CurrentClient, "0\n");
+}