diff options
Diffstat (limited to 'ksysguard/ksysguardd/Irix/ProcessList.c')
-rw-r--r-- | ksysguard/ksysguardd/Irix/ProcessList.c | 462 |
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"); +} |