gmemusage-0.2/ 40755 765 765 0 6457474434 11430 5ustar rajurajugmemusage-0.2/Makefile100644 765 765 3013 6457165631 13156 0ustar rajuraju# # Makefile for gmemusage-0.2 # # User-settable options # Define BELL_ON_UNKNOWN_KEYPRESS to have gmemusage beep whenever an unknown # key (including modifiers) is pressed. # # BELL_ON_UNKNOWN_KEYPRESS = -DBELL_ON_UNKNOWN_KEYPRESS # # Define USE_PASTELS to have gmemusage use pastel colors instead of the # default red, green, blue for it's stack. # USE_PASTELS = -DPASTEL_COLORS # # Define this for freeing the double-buffer pixmap after each draw_window() # SAVE_XSERVER_MEMORY = -DSAVE_XSERVER_MEMORY # # Change these variables as necessary # CC = gcc OPTIM = -O2 # change to -g for debugging LIBX11DIR = -L /usr/X11R6/lib PREFIX = /usr/local # # You shouldn't need to modify anything below this line # OPTIONS = $(BELL_ON_UNKNOWN_KEYPRESS) $(USE_PASTELS) $(SAVE_XSERVER_MEMORY) CFLAGS = $(OPTIM) -Wall $(OPTIONS) LDFLAGS = $(OPTIM) LIBX11 = $(LIBX11DIR) -lX11 LIBS = $(LIBX11) BINDIR = $(PREFIX)/bin MANDIR = $(PREFIX)/man/man1 OBJS = gmemusage.o hash.o proc.o resource.o gmemusage: $(OBJS) $(CC) -o $@ $(LDFLAGS) $(OBJS) $(LIBX11) gmemusage.o: gmemusage.c memusage.xbm common.h defaults.h resource.o: resource.c defaults.h common.h proc.o: proc.c common.h hash.o: hash.c common.h proctest: proctest.o hash.o $(CC) $(LDFLAGS) -o $@ proctest.o hash.o proctest.o: proc.c common.h $(CC) $(CFLAGS) -DDEBUG -o proctest.o -c proc.c install: gmemusage install -m 0755 -o bin -g bin gmemusage $(BINDIR)/gmemusage install -m 0644 -o bin -g bin gmemusage.1 $(MANDIR)/gmemusage.1 clean: rm -f *.o \#* *~ *.orig x proctest gmemusage core gmemusage-0.2/README100644 765 765 2272 6457474434 12410 0ustar rajurajuGmemusage is modelled after the program of the same name on Silicon Graphics' graphics workstations. In a nutshell, gmemusage graphically displays the contents of memory on a running system, broken up by individual processes. To compile the program: make You can set OPTIM to the value appropriate to your C compiler to get optimization or debugging symbols, e.g. make OPTIM=-O2 To install: make install You can set PREFIX to a directory under which the program and the manual entry will be installed (by default /usr/local), e.g. make PREFIX=/home/raju install Please see the comments at the top of the Makefile and edit other options as you desire. Gmemusage is copyright (C) 1997 by Raju Mathur aka OldMonk. The canonical site is: http://reality.sgi.com/raju/software.html Soda, Reiki, CDs of '70s rock and flames to: raju@sgi.com Please read the file COPYING in this directory for copyright information. Please see the file TODO in this directory for a bug- and wish-list. Gmemusage was compiled and tested on Linux dontpanic 2.0.31 #13 Sun Oct 19 01:13:27 IST 1997 i486 with the following libraries libX11.so.6 => /usr/X11R6/lib/libX11.so.6.1 libc.so.5 => /lib/libc.so.5.4.38 gmemusage-0.2/TODO100644 765 765 4002 6457163300 12174 0ustar rajurajuHere's the wish list: - Make the stack clickable so that clicing on a process will display some details about the process. - Allow user to switch between core and (core + swap) views. Shouldn't be too difficult -- the infrastructure is already in place as far as I can make out. Make a command-line option for the same. - Make a help screen (key "h"). - Fix unbalanced drawables (currently the graphics and text seem to prefer to hang around at the bottom of the window). - Make a better icon/pixmap :) Update: I've been sent a pixmap but have not incorporated it yet since it'll probably necessitate my learning how to use libXpm. Some time soon... - The speed delay due to opening and reading files in /proc seems to be minimal on my 486/66. However the process does take up a fair amount of CPU when it's scanning /proc. Maybe I can find out some way of getting these values from the kernel directly. - sum(RSS) for all procs works out to more than physical memory when memory is nearly or completely full. Leave this one for Linus to fix :-) Update: Apparently Linus is not to blame, it was my understanding of the memory values which was faulty. I am not compensating for shared memory (especially libraries) and hence the values which you see are pretty approximate. Is there someplace on the web which discusses process memory usage vis-a-vis the values found in /proc/process-id? - Get a decent color combination for the bars, labels and background. R G B is easy but not particularly beautiful. There's also a new pastel color scheme (define USE_PASTELS in the Makefile) though the contrast in the colors in that could be better. - I have reports of gmemusage behaving erratically on systems with 128Mb of RAM. I forgot to stock up on those this quarter, so any inputs will help. The problem is currently under investigation. - SPARCLinux gmemusage doesn't seem to read the installed system RAM correctly. Does stat(/proc/kcore) on SPARCS return something different on SPARCS? gmemusage-0.2/common.h100644 765 765 1367 6457157475 13200 0ustar rajuraju/* * common.h * common definitions for gmemusage * * Copyright (C) 1997 by Raju Mathur (raju@sgi.com) * * See file COPYING (included in this distribution) for copyright information. */ #define kernelname "linux" #define freename "free" struct ProcInfo { char procname [14] ; int totMem , totRSS , nProcs ; } ; /* * Defined in hash.c */ extern void addProc ( char *procName , int Mem , int RSS ) ; extern void ClearProcs ( void ) ; extern struct ProcInfo *NextProc ( void ) ; extern struct ProcInfo *AllProcs ( int *nprocs ) ; /* * Defined in proc.c */ extern void makeProcs ( void ) ; extern int sysmem , kernelmem , freemem , buffermem ; /* * Defined in gmemusage.c */ extern char progname [] , *version ; gmemusage-0.2/defaults.h100644 765 765 1024 6457157475 13505 0ustar rajuraju/* * defaults.h * Setup X defaults for the gmemusage program */ #define MaxColors 9 #define ThreshholdDelta 10 #define DefaultBorder 10 /* * Defined in gmemusage.c */ extern char progname [] ; /* * Defined in resource.c */ extern char *dGeometry , *dDisplay , *dFont , *dForeground , *dBackground , *dColor[MaxColors] ; extern int dnColors , dUpdate , dThreshhold ; extern void GetInitialResources ( int *argc , char **argv ) , GetResources ( Display *display , int argc , char **argv ) ; gmemusage-0.2/gmemusage.1100644 765 765 6156 6457166277 13574 0ustar rajuraju.\" gmemusage.1 0.2 990114; Copyright (C) 1997, 1998 - Raju Mathur .TH gmemusage 1 "14 January 1998" "Silicon Graphics" .SH NAME gmemusage \- graphically display memory used by running processes. .SH SYNOPSIS .B gmemusage [ .BI options ] .SH DESCRIPTION .B Gmemusage is modelled after the program of the same name on Silicon Graphics' workstations. .B Gmemusage graphically displays the contents of memory on a running system, broken up by individual processes. The display is a stacked bar graph with the height of an area representing the RSS size of the corresponding process. In addition, the process name, number of processes with that name and the size (in kilobytes) are shown. .sp Processes which take up less memory than a (user-specifiable) threshhold are merged into a single area on the graph. Multiple processes with the same name are merged into a single area. .sp While running, .B gmemusage accepts the following keys: .TP 5 Q or q Exit the program. .TP 5 Up Arrow Increase the minimum threshhold by 10 kb. .TP 5 Down Arrow Decrease the minimum threshhold by 10 kb. .TP 0 Other keys are (not-so-silently!) ignored. .SH OPTIONS .B Gmemusage accepts the following command-line options (defaults in brackets): .TP 5 .BI \-name \ resourcename Class name to use for resources (Gmemusage) .TP 5 .BI \-display \ display X server to contact ($DISPLAY environment variable) .TP 5 .BI \-geometry \ geometry Initial window geometry (320x400) .TP 5 .BI \-font \ font Use font .I font for drawing text (fixed) .TP 5 .BI \-background \ color Color to use for window background (grey4) .TP 5 .BI \-update \ seconds Update interval (5 seconds) .TP 5 .BI \-threshhold \ kb Threshhold below which small processes are merged (400 kb) .TP 5 .BI \-ncolors \ #colors How many different colors to use (3) .TP 5 .BI \-color1 \ color Name of first color (red/maroon) .TP 5 .BI \-color2 \ color Name of second color (green/OliveDrab) .TP 5 .BI \-color3 \ color Name of third color (blue/SlateBlue) .TP 5 .BI \-color[4-9] \ color Names of remaining colors (undefined) .TP 5 .BI \-help Print a short help message. .SH RESOURCES .B Gmemusage understands the following X resources. See the OPTIONS section for details of what they do. .sp .RS .B "name (\fPclass \fBName)" .RE .RS .B "display (\fPclass \fBDisplay)" .RE .RS .B "geometry (\fPclass \fBGeometry)" .RE .RS .B "font (\fPclass \fBFont)" .RE .RS .B "background (\fPclass \fBBackground)" .RE .RS .B "update (\fPclass \fBInterval)" .RE .RS .B "threshhold (\fPclass \fBThreshhold)" .RE .RS .B "ncolors (\fPclass \fBNColors)" .RE .RS .B "color1 (\fPclass \fBColor)" .RE .RS .B "color2 (\fPclass \fBColor)" .RE .RS .B "color3 (\fPclass \fBColor)" .RE .RS .B "color[4-9] (\fPclass \fBColor)" .RE .SH BUGS See the TODO file which comes with the distribution. .SH SEE ALSO top(1), ps(1), xosview(1). .SH VERSION .B Gmemusage version 0.2, 1998/01/14 .SH AUTHOR Raju Mathur (raju@sgi.com) aka OldMonk. .SH SITE The canonical site for .B gmemusage is: .sp .RS .B http://reality.sgi.com/raju/software .RE .SH COPYRIGHT .B Gmemusage is copyright (C) 1997, 1998 by Raju Mathur. See the file COPYING in the source directory for copyright information. gmemusage-0.2/gmemusage.c100644 765 765 50251 6457165513 13661 0ustar rajuraju/* * gmemusage.c * main file for gmemusage * * Copyright (C) 1997, 1998 by Raju Mathur (raju@sgi.com) * Some portions based on O'Reilly and Associates' Xlib Programming tutorial * examples. * * See file COPYING (included in this distribution) for copyright information. * * Xemacs configuration for this indentation: * (add-hook 'c-mode-common-hook * '(lambda () * (c-set-style "ellemtel") * (c-set-offset 'topmost-intro-cont '+) * (c-set-offset 'topmost-intro '-) * (c-set-offset 'case-label '*) * (c-set-offset 'statement-case-intro '*))) * * Version 0.2, 980114 */ #include #include #include #include #include #include "memusage.xbm" #include #include #include #include #include #include "common.h" #include "defaults.h" #define BITMAPDEPTH 1 #define TOO_SMALL 0 #define BIG_ENOUGH 1 /* * I hate these file-wide variables, but since draw_window is going to be * called from a signal, we can't pass it any args. */ static Display *display ; static int screen_num ; char progname [128] , /* other functions need to access this one */ *version = "0.1" ; /* and this one */ static Window win ; #ifndef SAVE_XSERVER_MEMORY static Pixmap pxm; #endif static int window_width , window_height ; static int nColors ; static int Threshhold = -1 ; static XColor Foreground , Background ; static XFontStruct *font_info ; static int Exposed = 0 ; /* * Is this the right way to have (e.g.) 16 colors? 16 different GC's with * a different foreground? */ static GC gc [MaxColors] ; static GC blackGC; /* * Protos. */ void getGCs ( Window win , Colormap cmap ) ; #if 0 void place_text ( Window win , GC gc , XFontStruct *font_info , unsigned int win_width , unsigned int win_height ) ; void place_graphics ( Window win , GC gc , unsigned int window_width , unsigned int window_height ) ; #endif void draw_window ( void ) ; void TooSmall ( Window win , GC gc , XFontStruct *font_into ) ; void main ( int argc , char **argv ) { int default_height , default_width , default_x , default_y ; int x = 0 , y = 0 , width , height ; unsigned int border_width = 4 , display_width , display_height ; char *window_name = "gmemusage" , *icon_name = "gmemusage" ; Pixmap icon_pixmap ; XSizeHints *size_hints ; XEvent report ; int screen_num ; Screen *screen_ptr ; XWMHints *wm_hints ; XClassHint *class_hints ; XTextProperty windowName , iconName ; Colormap cmap ; /* * Remove leading dir.../ from argv[0] and store in progname */ if ( strrchr ( argv [0] , '/' ) ) { strcpy ( progname , strrchr ( argv [0] , '/' ) + 1 ) ; } else { strcpy ( progname , argv [0] ) ; } /* * Allocate necessaru X structures for later use. Apparently this needs to * be done before any other X stuff. */ if ( !( size_hints = XAllocSizeHints () ) ) { fprintf ( stderr , "%s: failure allocating SizeHints\n" , progname ) ; exit ( 1 ) ; } if ( !( wm_hints = XAllocWMHints () ) ) { fprintf ( stderr , "%s: failure allocating WMHints\n" , progname ) ; exit ( 1 ) ; } if ( !( class_hints = XAllocClassHint () ) ) { fprintf ( stderr , "%s: failure allocating ClassHints\n" , progname ) ; exit ( 1 ) ; } /* * Figure out resources from the command-line and screen resources. */ GetInitialResources ( &argc , argv ) ; if ( ( display = XOpenDisplay ( dDisplay ) ) == NULL ) { (void) fprintf ( stderr , "%s: cannot connect to X server %s\n" , progname , XDisplayName ( dDisplay ) ) ; exit ( 1 ) ; } GetResources ( display , argc , argv ) ; XParseGeometry ( dGeometry , &default_x , &default_y , &default_width , &default_height ) ; screen_num = DefaultScreen ( display ) ; screen_ptr = DefaultScreenOfDisplay ( display ) ; display_width = DisplayWidth ( display , screen_num ) ; display_height = DisplayHeight ( display , screen_num ) ; /* * Get foreground and background colors for the window */ cmap = DefaultColormap ( display , DefaultScreen ( display ) ) ; if (!XParseColor ( display , cmap , dForeground , &Foreground ) ) { fprintf ( stderr , "%s: Cannot parse color %s\n" , progname , dForeground ) ; Foreground . pixel = BlackPixel ( display , screen_num ) ; } else { XAllocColor ( display , cmap , &Foreground ) ; } if (!XParseColor ( display , cmap , dBackground , &Background ) ) { fprintf ( stderr , "%s: Cannot parse color %s\n" , progname , dBackground ) ; Background . pixel = WhitePixel ( display , screen_num ) ; } else { XAllocColor ( display , cmap , &Background ) ; } width = default_width ; height = default_height ; win = XCreateSimpleWindow ( display , RootWindow ( display , screen_num ) , x , y , width , height , border_width , Foreground . pixel , Background . pixel ) ; #ifndef SAVE_XSERVER_MEMORY pxm = XCreatePixmap ( display , win , width , height , DefaultDepth ( display , screen_num ) ); #endif icon_pixmap = XCreateBitmapFromData ( display , win , memusage_bits , memusage_width , memusage_height ) ; size_hints -> flags = PPosition | PSize | PMinSize ; size_hints -> min_width = default_width ; size_hints -> min_height = default_height ; if ( XStringListToTextProperty (&window_name , 1 , &windowName ) == 0 ) { fprintf ( stderr , "%s: struct allocation for windowName failed\n" , progname ) ; exit ( 1 ) ; } if ( XStringListToTextProperty ( &icon_name , 1 , &iconName ) == 0 ) { fprintf ( stderr , "%s: struct allocation for iconName failed\n" , progname ) ; exit ( 1 ) ; } wm_hints -> initial_state = NormalState ; wm_hints -> input = True ; wm_hints -> icon_pixmap = icon_pixmap ; wm_hints -> flags = StateHint | IconPixmapHint | InputHint ; class_hints -> res_name = progname ; class_hints -> res_class = "BasicWin" ; XSetWMProperties ( display , win , &windowName , &iconName , argv , argc , size_hints , wm_hints , class_hints ) ; XSelectInput ( display , win , ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask ) ; getGCs ( win , cmap ) ; XMapWindow ( display , win ) ; while ( 1 ) { XNextEvent ( display , &report ) ; switch ( report . type ) { char keybuf [10] ; KeySym keysym ; int count ; XComposeStatus composestatus ; case Expose: if ( report . xexpose . count != 0 ) { break ; } #if 0 printf("Expose %d %d %d %d\n",report.xexpose.x,report.xexpose.y,report.xexpose.width,report.xexpose.height); #endif #if 0 if ( window_size == TOO_SMALL ) { TooSmall ( win , gc , font_info ) ; } else #endif { Exposed = 1 ; draw_window () ; } break ; case ConfigureNotify: window_width = report . xconfigure . width ; window_height = report . xconfigure . height ; #ifndef SAVE_XSERVER_MEMORY XFreePixmap ( display , pxm ); pxm = XCreatePixmap ( display , win , window_width , window_height , DefaultDepth ( display , screen_num ) ); #endif #if 0 if ( window_width < size_hints -> min_width || window_height < size_hints -> min_height ) { window_size = TOO_SMALL ; } else { window_size = BIG_ENOUGH ; } #endif break ; case ButtonPress: /* ignore buttons for now */ XBell ( display , 10 ) ; break ; case KeyPress: count = XLookupString ( &report . xkey , keybuf , sizeof ( keybuf ) , &keysym , &composestatus ) ; if ( ( keysym >= XK_KP_Space && keysym <= XK_KP_9 ) || ( keysym >= XK_space && keysym <= XK_asciitilde ) ) { register int i ; for ( i = 0 ; keybuf [i] ; i++ ) { switch ( keybuf [i] ) { register int j ; case 'q': case 'Q': XUnloadFont ( display , font_info -> fid ) ; for ( j = 0 ; j < nColors ; j++ ) { XFreeGC ( display , gc [j] ) ; } XCloseDisplay ( display ) ; exit ( 0 ) ; default: XBell ( display , 10 ) ; break ; } } } else { switch ( keysym ) { case XK_Up: Threshhold += ThreshholdDelta ; break ; case XK_Down: Threshhold -= ThreshholdDelta ; if ( Threshhold < ThreshholdDelta ) { XBell ( display , 0 ) ; Threshhold = ThreshholdDelta ; } break ; default: #ifdef BELL_ON_UNKNOWN_KEYPRESS XBell ( display , 10 ) ; #endif break ; } } break ; default: #if 0 fprintf ( stderr , "%s: Unknown event: %d\n" , progname , report . type ) ; #endif break ; } } exit ( 0 ) ; } /* * Do all the drawing. */ void draw_window ( void ) { int pcWidth , pcHeight , pixelWidth , pixelHeight ; #ifdef SAVE_XSERVER_MEMORY Pixmap pxm; #endif struct XProcInfo { struct ProcInfo *pi ; int pixelHeight , base , midpoint ; } ; register int i ; static int nprocs ; static int oldThreshhold ; int oldnprocs ; register struct XProcInfo *this ; static struct ProcInfo *pi ; static struct XProcInfo *xpi , *oldxpi ; int alarmsecs ; static int done = 0 ; int basex , basey ; #if 0 int temp1 ; #endif GC *thisGC ; int thxpi = -1 ; struct ProcInfo thProc ; int labelNumber = 0 , nLabels = 0 ; int longestLabel = 0 ; /* * No alarms while we're here. */ (void) signal ( SIGALRM , SIG_IGN ) ; /* * See if we're being called due to an alarm, and schedule the next alarm. * If the alarm is pending, we can reuse the old data rather than calling * AllProcs again. */ if ( alarmsecs = alarm ( dUpdate ) && done ) { /* * if the alarm didn't go off, we don't need to recalc everything. */ #if 0 printf("called from expose\n"); #endif alarm ( alarmsecs ) ; } else { /* * Get the process info */ #if 0 printf("called from alarm\n"); #endif oldxpi = xpi ; oldnprocs = nprocs ; makeProcs () ; pi = AllProcs ( &nprocs ) ; done = 1 ; } /* * Calculate width of memory bars as percentage and in pixels. */ pcWidth = 40 ; pixelWidth = window_width * pcWidth / 100.0 ; pcHeight = 90 ; pixelHeight = window_height * pcHeight / 100.0 ; basex = DefaultBorder ; basey = window_height - ( window_height - pixelHeight ) / 2 - 1 ; if ( Threshhold < 0 ) { Threshhold = dThreshhold ; } #if 0 printf("pcw %d, pw %d, pch %d, ph %d, base %d\n",pcWidth,pixelWidth,pcHeight,pixelHeight,basey); #endif /* * Go through the array: allocate the ProcInfo pointer, calculate height, * base, midpoint for each rectangle. */ if ( ( xpi = calloc ( nprocs , sizeof ( struct XProcInfo ) ) ) == NULL ) { fprintf ( stderr , "%s: calloc struct XProcInfo failed" , progname ) ; perror ( "" ) ; exit ( 1 ) ; } this = xpi ; /* * First get the sum of processes less than the threshhold size */ for ( i = 0 ; i < nprocs ; i++ ) { if ( pi [i] . totRSS < Threshhold && strcmp ( pi [i] . procname , kernelname ) && strcmp ( pi [i] . procname , freename ) ) { if ( thxpi < 0 ) { thxpi = i ; sprintf ( thProc . procname , "< %d" , Threshhold ) ; thProc . totRSS = pi [i] . totRSS ; thProc . totMem = 0 ; thProc . nProcs = pi [i] . nProcs ; this [i] . pi = &thProc ; } else { this [thxpi] . pi -> nProcs += pi [i] . nProcs ; this [thxpi] . pi -> totRSS += pi [i] . totRSS ; } } } #if 0 temp1=0; printf("%d %s %d\n",thxpi,this[thxpi].pi->procname,this[thxpi].pi->totRSS); #endif /* * Now calculate percentages and sizes for the remaining (large-enough) * processes. */ for ( i = 0 ; i < nprocs ; i++ ) { if ( i != thxpi ) { if ( pi [i] . totRSS < Threshhold ) { this [i] . pi = NULL ; continue ; } else { this [i] . pi = &pi [i] ; } } nLabels++ ; #if 0 temp1+=pi[i].totRSS; printf("%s %d %d %d\n",this[i].pi->procname,this[i].pi->totMem,this[i].pi->totRSS,temp1); #endif this [i] . pixelHeight = this [i] . pi -> totRSS * pixelHeight / sysmem ; basey -= this [i] . pixelHeight ; this [i] . base = basey ; this [i] . midpoint = basey + this [i] . pixelHeight / 2 ; if ( strlen ( this [i] . pi -> procname ) > longestLabel ) { longestLabel = strlen ( this [i] . pi -> procname ) ; } } #if 0 /* Needs much more work */ /* * Check if the new values have changed at all from the previous values. * If not, just deallocate and return without redrawing. */ if ( oldThreshhold == Threshhold && oldnprocs == nprocs && !memcmp ( xpi , oldxpi , sizeof ( struct XProcInfo ) * nprocs ) && !Exposed ) { free ( oldxpi ) ; return ; } #endif /* * Make the boxes. */ #if 0 XClearArea ( display , win , 0 , 0 , 0 , 0 , False ) ; #else #ifdef SAVE_XSERVER_MEMORY pxm = XCreatePixmap ( display , win , window_width , window_height , DefaultDepth ( display , screen_num ) ); #endif XFillRectangle ( display , pxm , blackGC , 0 , 0 , window_width , window_height ) ; #endif #if 0 printf("%d %d\n",window_height,window_width); #endif labelNumber = 0 ; for ( i = 0 ; i < nprocs ; i++ ) { if ( !this [i] . pi ) { continue ; } thisGC = &gc [labelNumber % nColors] ; #if 0 printf("%d %d %d %d\n",basex,this[i].base,pixelWidth,this[i].pixelHeight); #endif XFillRectangle ( display , pxm , *thisGC , basex , this [i] . base , pixelWidth , this [i] . pixelHeight ) ; labelNumber++ ; } /* * Make the lines and the text. */ { int lineSpace = window_height / nLabels , longestLabelWidth , textXoffset , fontHeight ; char buf [128] , nprocbuf [10] ; /* procname (nnn) : nnnnnK */ memset ( buf , 'W' , longestLabel + 6 + 2 + 7 ) ; longestLabelWidth = XTextWidth ( font_info , buf , longestLabel + 6 + 2 + 7 ) ; textXoffset = window_width - DefaultBorder - longestLabelWidth ; fontHeight = font_info -> ascent + font_info -> descent ; labelNumber = 0 ; for ( i = 0 ; i < nprocs ; i++ ) { if ( !this [i] . pi ) { continue ; } thisGC = &gc [labelNumber % nColors] ; XDrawLine ( display , pxm , *thisGC , DefaultBorder + pixelWidth , this [i] . midpoint , textXoffset - 2 , window_height - (labelNumber * lineSpace ) - lineSpace / 2 ) ; if ( this [i] . pi -> nProcs > 1 ) { sprintf ( nprocbuf , "(%d)" , this [i] . pi -> nProcs ) ; } else { nprocbuf [0] = '\0' ; } sprintf ( buf , "%-*s %6s : %5dK" , longestLabel , this [i] . pi -> procname , nprocbuf , this [i] . pi -> totRSS ) ; #if 0 if ( strcmp ( this [i] . pi -> procname , kernelname ) && strcmp ( this [i] . pi -> procname , freename ) ) { sprintf ( buf , "%s (%d)" , this [i] . pi -> procname , this [i] . pi -> nProcs ) ; } else { strcpy ( buf , this [i] . pi -> procname ) ; } #endif XDrawString ( display , pxm , *thisGC , textXoffset , window_height - ( labelNumber * lineSpace ) - ( lineSpace - fontHeight ) / 2 - 2 , buf , strlen ( buf ) ) ; labelNumber++ ; } } XCopyArea ( display , pxm , win , blackGC, 0 , 0 , window_width, window_height, 0 , 0 ); #ifdef SAVE_XSERVER_MEMORY XFreePixmap ( display , pxm ); #endif XFlush ( display ) ; /* * Save and clear some of the values. */ oldThreshhold = Threshhold ; Exposed = 0 ; if ( oldxpi ) { free ( oldxpi ) ; oldxpi = NULL ; } /* * We can accept alarms again */ (void) signal ( SIGALRM , draw_window ) ; return ; } void getGCs ( Window win , Colormap cmap ) { unsigned long valuemask = 0 ; XGCValues values ; unsigned int line_width = 0 ; /* fastest server-dependent line */ int line_style = LineSolid , cap_style = CapRound , join_style = JoinRound ; XColor rgb ; register int i ; if ( ( font_info = XLoadQueryFont ( display , dFont ) ) == NULL ) { fprintf ( stderr , "%s: cannot load font %s\n" , progname , dFont ) ; exit ( 1 ) ; } nColors = dnColors ; for ( i = 0 ; i < nColors ; i++ ) { if ( dColor [i] [0] && !XParseColor ( display , cmap , dColor [i] , &rgb ) ) { fprintf ( stderr , "%s: Cannot parse color %s\n" , progname , dColor [i] ) ; rgb . pixel = BlackPixel ( display , screen_num ) ; } else { XAllocColor ( display , cmap , &rgb ) ; } gc [i] = XCreateGC ( display , win , valuemask , &values ) ; XSetForeground ( display , gc [i] , rgb . pixel ) ; XSetFont ( display , gc [i] , font_info -> fid ) ; XSetLineAttributes ( display , gc [i] , line_width , line_style , cap_style , join_style ) ; } valuemask |= GCPlaneMask; values.plane_mask = AllPlanes; blackGC = XCreateGC ( display , win , valuemask , &values ) ; XSetForeground ( display , blackGC , BlackPixel ( display , screen_num ) ) ; return ; } #if 0 void place_text ( Window win , GC gc , XFontStruct *font_info , unsigned int win_width , unsigned int win_height ) { char *string1 = "Hi! I'm a window, who are you?" , *string2 = "To terminate program: press any key" , *string3 = "or button while in this window." , *string4 = "Screen Dimensions" ; int len1 , len2 , len3 , len4 , width1 , width2 , width3 ; char cd_height[50] , cd_width [50] , cd_depth [50] ; int font_height , initial_y_offset , x_offset ; len1 = strlen ( string1 ) ; len2 = strlen ( string2 ) ; len3 = strlen ( string3 ) ; width1 = XTextWidth ( font_info , string1 , len1 ) ; width2 = XTextWidth ( font_info , string2 , len2 ) ; width3 = XTextWidth ( font_info , string3 , len3 ) ; font_height = font_info -> ascent + font_info -> descent ; XDrawString ( display , win , gc , ( win_width - width1 ) / 2 , font_height , string1 , len1 ) ; XDrawString ( display , win , gc , ( win_width - width2 ) / 2 , win_height - 2 * font_height , string2 , len2 ) ; XDrawString ( display , win , gc , ( win_width - width3 ) / 2 , win_height - 3 * font_height , string3 , len3 ) ; sprintf ( cd_height , " Height - %d pixels" , DisplayHeight ( display , screen_num ) ) ; sprintf ( cd_width , " Width - %d pixels" , DisplayWidth ( display , screen_num ) ) ; sprintf ( cd_depth , " Depth - %d planes" , DefaultDepth ( display , screen_num ) ) ; len4 = strlen ( string4 ) ; len1 = strlen ( cd_height ) ; len2 = strlen ( cd_width ) ; len3 = strlen ( cd_depth ) ; initial_y_offset = win_height / 2 - font_height - font_info -> descent ; x_offset = win_width / 4 ; XDrawString ( display , win , gc , x_offset , initial_y_offset , string4 , len4 ) ; XDrawString ( display , win , gc , x_offset , initial_y_offset + font_height , cd_height , len1 ) ; XDrawString ( display , win , gc , x_offset , initial_y_offset + 2 * font_height , cd_width , len2 ) ; XDrawString ( display , win , gc , x_offset , initial_y_offset + 3 * font_height , cd_depth , len3 ) ; } void place_graphics ( Window win , GC gc , unsigned int window_width , unsigned int window_height ) { int x , y , width , height ; height = window_height / 2 ; width = 3 * window_width / 4 ; x = window_width / 2 - width / 2 ; y = window_height / 2 - height / 2 ; XDrawRectangle ( display , win , gc , x , y , width , height ) ; } void TooSmall ( Window win , GC gc , XFontStruct *font_info ) { char *string1 = "Too Small" ; int x_offset , y_offset ; y_offset = font_info -> ascent + 2 ; x_offset = 2 ; XDrawString ( display , win , gc , x_offset , y_offset , string1 , strlen ( string1 ) ) ; } #endif gmemusage-0.2/hash.c100644 765 765 6031 6457165441 12607 0ustar rajuraju/* * hash.c * Process hashing functions for gmemusage. * * Copyright (C) 1997, 1998 by Raju Mathur (raju@sgi.com) * * See file COPYING (included in this distribution) for copyright information. */ #include #include #include "common.h" /* { */ const int minProcs = 16 ; static struct ProcInfo *procs = NULL ; static struct ProcInfo *nextproc = NULL ; static int nProcs = 0 ; static int lastallocated ; /* } */ /* * Find a process with matching name in the process array. * Currently using linear search, enhance to any method you * choose. Hash may not be a bad idea. */ struct ProcInfo *LookupProc ( char *name ) { register struct ProcInfo *pi ; for ( pi = procs ; pi - procs < nProcs ; pi++ ) { if ( !strcmp ( pi -> procname , name ) ) { return ( pi ) ; } } return NULL ; } /* * Update existing process entry, or add a process to the * process array. */ void addProc ( char *procname , int mem , int rss ) { register struct ProcInfo *thisproc ; /* * is the array empty? */ if ( !procs ) { lastallocated = minProcs ; if ( ( procs = calloc ( minProcs , sizeof ( struct ProcInfo ) ) ) == NULL ) { fprintf ( stderr , "%s: cannot alloc %d processes" , progname , minProcs ) ; perror ( "" ) ; exit ( 1 ) ; } /* printf("allocated %d procs\n",lastallocated); */ thisproc = nextproc = procs ; strcpy ( thisproc -> procname , procname ) ; thisproc -> totMem = mem ; thisproc -> totRSS = rss ; thisproc -> nProcs = 1 ; nProcs = 1 ; } /* * if a process with that name doesn't already exist in the * array, make a new entry. Allocate more space if necessary. */ else if ( !( thisproc = LookupProc ( procname ) ) ) { if ( nProcs == lastallocated ) /* no more space */ { lastallocated *= 2 ; if ( ( procs = realloc ( procs , lastallocated * sizeof ( struct ProcInfo) ) ) == NULL ) { fprintf ( stderr , "%s: cannot alloc %d processes" , progname , lastallocated ) ; perror ( "" ) ; exit ( 1 ) ; } /* printf("allocated %d procs\n",lastallocated); */ } thisproc = procs + nProcs ; strcpy ( thisproc -> procname , procname ) ; thisproc -> totMem = mem ; thisproc -> totRSS = rss ; thisproc -> nProcs = 1 ; nProcs++ ; } else { thisproc -> totMem += mem ; thisproc -> totRSS += rss ; thisproc -> nProcs++ ; } } /* * Return the next process linearly from the process * array, or NULL if no more. */ struct ProcInfo *NextProc ( void ) { if ( nextproc - procs == nProcs ) { return NULL ; } else { return nextproc++ ; } } struct ProcInfo *AllProcs ( int *n ) { *n = nProcs ; return procs ; } /* * Clear out and deallocate the process list and * associated variables. */ void ClearProcs ( void ) { if ( procs ) { free ( procs ) ; procs = NULL ; lastallocated = nProcs = 0 ; nextproc = NULL ; } } gmemusage-0.2/memusage.xbm100644 765 765 1567 6457157476 14055 0ustar rajuraju#define memusage_width 32 #define memusage_height 32 static unsigned char memusage_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x7f, 0x00, 0x00, 0x1c, 0x7f, 0xf8, 0xff, 0x03, 0x00, 0x08, 0x00, 0x71, 0x7f, 0xf8, 0xff, 0x0f, 0x7f, 0xf8, 0xff, 0x01, 0x00, 0x08, 0x00, 0x7f, 0x7f, 0x08, 0x00, 0x01, 0x7f, 0xf8, 0xff, 0x01, 0x00, 0xf8, 0xff, 0x7f, 0x7f, 0xf8, 0xff, 0x01, 0x7f, 0x08, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x71, 0x7f, 0x08, 0x00, 0x01, 0x7f, 0xf8, 0xff, 0x01, 0x00, 0xf8, 0xff, 0x7f, 0x7f, 0xf8, 0xff, 0x01, 0x7f, 0xf8, 0xff, 0x01, 0x00, 0xf8, 0xff, 0x79, 0x7f, 0x08, 0x00, 0x07, 0x7f, 0xf8, 0xff, 0x01, 0x00, 0xf8, 0xff, 0x7f, 0x7f, 0xf8, 0xff, 0x01, 0x7f, 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x7f, 0x7f, 0xf8, 0xff, 0x01, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; gmemusage-0.2/proc.c100644 765 765 14154 6457165427 12660 0ustar rajuraju/* * proc.c: * interface to process table entry in /proc * * Copyright (C) 1997, 1998 by Raju Mathur (raju@sgi.com) * * See file COPYING (included in this distribution) for copyright information. */ #include #include #include #include #include #include "common.h" /* * memory (in Kbytes) */ int sysmem = 0 , kernelmem = 0 , freemem = 0 , buffermem = 0 ; /* * Set values for various memory usages */ static void SetMemInfo ( void ) { struct stat s ; char buf [128] ; FILE *meminfo ; int totalmem ; const char *MemLine = "Mem:" ; const int MemLineLen = strlen ( MemLine ) ; /* * Cheap way to get amount of installed mem in the computer -- get size of * /proc/kcore. */ if ( stat ( "/proc/kcore" , &s ) < 0 ) { fprintf ( stderr , "%s: cannot stat /proc/kcore" , progname ) ; perror ( "" ) ; exit ( 1 ) ; } sysmem = s . st_size ; /* in Kilobytes */ /* * Read /proc/meminfo to get usable memory and buffers. Presumably buffers * should be considered a part of the kernel memory. */ if ( ( meminfo = fopen ( "/proc/meminfo" , "r" ) ) == NULL ) { fprintf ( stderr , "%s: cannot open /proc/meminfo" , progname ) ; perror ( "" ) ; exit ( 1 ) ; } while ( fgets ( buf , sizeof ( buf ) , meminfo ) ) { if ( !strncmp ( buf , MemLine , MemLineLen ) ) { /* Mem: total used free shared buffers cached */ sscanf ( buf , "%*s %d %*d %d %*d %d" , &totalmem , &freemem , &buffermem ) ; break ; } } sysmem /= 1024 ; totalmem /= 1024 ; freemem /= 1024 ; buffermem /= 1024 ; kernelmem = sysmem - totalmem ; fclose ( meminfo ) ; return ; } /* * Read /proc to get info about processes. * As a side effect :-) also set variables related to main memory. */ void makeProcs ( void ) { DIR *proc ; struct dirent *procdir ; FILE *StatusFile ; char buf [128] ; char procName [14] ; int procSize , procRSS , procData , procStk , procExe ; const char *NameLine = "Name:" , *VmSizeLine = "VmSize:" , *VmRSSLine = "VmRSS" , *VmDataLine = "VmData" , *VmStkLine = "VmStk" , *VmExeLine = "VmExe" ; const int NameLineLen = strlen ( NameLine ) , VmSizeLineLen = strlen ( VmSizeLine ) , VmDataLineLen = strlen ( VmDataLine ) , VmStkLineLen = strlen ( VmStkLine ) , VmExeLineLen = strlen ( VmExeLine ) , VmRSSLineLen = strlen ( VmRSSLine ) ; if ( ( proc = opendir ( "/proc" ) ) == NULL ) { fprintf ( stderr , "%s: unable to open /proc" , progname ) ; perror ( "" ) ; exit ( 1 ) ; } ClearProcs () ; /* * Get memory info */ SetMemInfo () ; /* * Make sure that the first process is the kernel. We'll be slightly off, * but the alternatives (adding this after the rest of the process list * has been made) are too terrible to contemplate. */ addProc ( kernelname , kernelmem + buffermem , kernelmem + buffermem ) ; /* * NASTY HACK! * Some screwy feature (or my screwy understanding of /proc) causes the * sum(RSS) for all the procs + kernel + buffers + freemem to become > system * memory. Hence we recalculate system memory based on the actual figures * we get from sum(RSS)+kernel+buffers+freemem */ sysmem = 0 ; while ( procdir = readdir ( proc ) ) { if ( !index ( "1234567890" , procdir -> d_name [0] ) ) { continue ; } sprintf ( buf , "/proc/%s/status" , procdir -> d_name ) ; if ( ( StatusFile = fopen ( buf , "r" ) ) == NULL ) { fprintf ( stderr , "%s: cannot open %s for reading" , progname , buf ) ; perror ( "" ) ; continue ; } procRSS = procSize = procData = procStk = procExe = 0 ; while ( fgets ( buf , sizeof ( buf ) , StatusFile ) ) { /* * I hate sscanf's, but am too lazy to replace them with a more elegant, * more efficient method right now. Don't you just love TODO lists? */ if ( !strncmp ( buf , NameLine , NameLineLen ) ) { /* Name: procName */ sscanf ( buf , "%*s %s" , procName ) ; } else if ( !strncmp ( buf , VmSizeLine , VmSizeLineLen ) ) { /* VmSize: procSize kB */ sscanf ( buf , "%*s %d" , &procSize ) ; } else if ( !strncmp ( buf , VmRSSLine , VmRSSLineLen ) ) { /* VmRSS: procRSS kB */ sscanf ( buf , "%*s %d" , &procRSS ) ; } else if ( !strncmp ( buf , VmDataLine , VmDataLineLen ) ) { /* VmData: procData kB */ sscanf ( buf , "%*s %d" , &procData ) ; } else if ( !strncmp ( buf , VmStkLine , VmStkLineLen ) ) { /* VmStk: procStk kB */ sscanf ( buf , "%*s %d" , &procStk ) ; } else if ( !strncmp ( buf , VmExeLine , VmExeLineLen ) ) { /* VmExe: procExe kB */ sscanf ( buf , "%*s %d" , &procExe ) ; } } fclose ( StatusFile ) ; addProc ( procName , procSize , procData + procStk + procExe ) ; sysmem += procData + procStk + procExe ; } closedir ( proc ) ; sysmem += kernelmem + buffermem + freemem ; addProc ( freename , freemem , freemem ) ; return ; } /* makeProcs */ #ifdef DEBUG void printProcs ( void ) { struct ProcInfo *pi , *procs ; int nprocs , nprocs2 , totmem ; register int i ; printf ( "%-20s%8s%8s%8s\n" , "Name" , "Memory" , "RSS" , "Number" ) ; totmem = nprocs2 = 0 ; procs = AllProcs ( &nprocs ) ; for ( i = 0 ; i < nprocs ; i++ ) { pi = &procs[i] ; printf ( "%-20s%8d%8d%8d\n" , pi -> procname , pi -> totMem , pi -> totRSS , pi -> nProcs ) ; nprocs2 += pi -> nProcs ; if ( strcmp ( pi -> procname , kernelname ) ) { totmem += pi -> totRSS ; } } printf ( "%d procs\n" , nprocs ) ; printf ( "Mem: %d procs, %d total, %d kernel, %d buffers, %d free\n" , totmem , sysmem , kernelmem , buffermem , freemem ) ; } char *progname ; void main ( int argc , char **argv ) { register int i = 0 ; progname = *argv ; while ( 1 ) { makeProcs () ; printProcs () ; printf ( "\n" ) ; sleep ( 5 ) ; } } #endif /* DEBUG */ gmemusage-0.2/resource.c100644 765 765 24222 6457165415 13536 0ustar rajuraju/* * resource.c * Manage resources for gmemusage * * Copyright (C) 1997, 1998 by Raju Mathur. * Lots of code and ideas shamelessly stolen from xlockmore-3.0/resource.c * * See file COPYING (included in this distribution) for copyright information. */ #include #include #include #include #include #include #include #include #include "common.h" #include "defaults.h" /* * Built-in defaults */ #define DEF_FONT "fixed" #define DEF_GEOMETRY "320x400" #define DEF_NCOLORS "3" #ifdef PASTEL_COLORS #define DEF_COLOR1 "maroon" #define DEF_COLOR2 "OliveDrab" #define DEF_COLOR3 "SlateBlue" #else #define DEF_COLOR1 "red" #define DEF_COLOR2 "green" #define DEF_COLOR3 "blue" #endif #define DEF_COLOR4 "" #define DEF_COLOR5 "" #define DEF_COLOR6 "" #define DEF_COLOR7 "" #define DEF_COLOR8 "" #define DEF_COLOR9 "" #define DEF_FOREGROUND "black" #define DEF_BACKGROUND "grey4" #define DEF_UPDATE "5" #define DEF_THRESHHOLD "400" #define DEF_CLASSNAME "Gmemusage" static XrmOptionDescRec optionTable [] = { { "-geometry" , ".geometry" , XrmoptionSepArg , (caddr_t) NULL } , { "-ncolors" , ".ncolors" , XrmoptionSepArg , (caddr_t) NULL } , { "-color1" , ".color1" , XrmoptionSepArg , (caddr_t) NULL } , { "-color2" , ".color2" , XrmoptionSepArg , (caddr_t) NULL } , { "-color3" , ".color3" , XrmoptionSepArg , (caddr_t) NULL } , { "-color4" , ".color4" , XrmoptionSepArg , (caddr_t) NULL } , { "-color5" , ".color5" , XrmoptionSepArg , (caddr_t) NULL } , { "-color6" , ".color6" , XrmoptionSepArg , (caddr_t) NULL } , { "-color7" , ".color7" , XrmoptionSepArg , (caddr_t) NULL } , { "-color8" , ".color8" , XrmoptionSepArg , (caddr_t) NULL } , { "-color9" , ".color9" , XrmoptionSepArg , (caddr_t) NULL } , { "-font" , ".font" , XrmoptionSepArg , (caddr_t) NULL } , { "-foreground" , ".foreground" , XrmoptionSepArg , (caddr_t) NULL } , { "-background" , ".background" , XrmoptionSepArg , (caddr_t) NULL } , { "-update" , ".update" , XrmoptionSepArg , (caddr_t) NULL } , { "-threshhold" , ".threshhold" , XrmoptionSepArg , (caddr_t) NULL } , } ; const int optionEntries = sizeof ( optionTable ) / sizeof ( optionTable [0] ) ; static XrmOptionDescRec displayTable [] = { { "-display" , ".display" , XrmoptionSepArg , (caddr_t) NULL } } ; const int displayEntries = sizeof ( displayTable ) / sizeof ( displayTable [0] ) ; static XrmOptionDescRec nameTable [] = { { "-name" , ".name" , XrmoptionSepArg , (caddr_t) NULL } } ; const int nameEntries = sizeof ( nameTable ) / sizeof ( nameTable [0] ) ; /* * Variables holding default values */ static char *dName ; char *dGeometry , *dDisplay , *dFont , *dForeground , *dBackground , *dColor [MaxColors] ; int dnColors , dUpdate , dThreshhold ; #define t_String 0 #define t_Int 1 typedef struct { caddr_t *var; char *name; char *class; char *def; int type; } argtype; /* * Warning! If you change anything here do also modify the Help function * accordingly. */ static argtype optionVars[] = { { (caddr_t *) &dFont , "font" , "Font" , DEF_FONT , t_String } , { (caddr_t *) &dGeometry , "geometry" , "Geometry" , DEF_GEOMETRY , t_String } , { (caddr_t *) &dnColors , "ncolors" , "NColors" , DEF_NCOLORS , t_Int } , { (caddr_t *) &dColor [0] , "color1" , "Color" , DEF_COLOR1 , t_String } , { (caddr_t *) &dColor [1] , "color2" , "Color" , DEF_COLOR2 , t_String } , { (caddr_t *) &dColor [2] , "color3" , "Color" , DEF_COLOR3 , t_String } , { (caddr_t *) &dColor [3] , "color4" , "Color" , DEF_COLOR4 , t_String } , { (caddr_t *) &dColor [4] , "color5" , "Color" , DEF_COLOR5 , t_String } , { (caddr_t *) &dColor [5] , "color6" , "Color" , DEF_COLOR6 , t_String } , { (caddr_t *) &dColor [6] , "color7" , "Color" , DEF_COLOR7 , t_String } , { (caddr_t *) &dColor [7] , "color8" , "Color" , DEF_COLOR8 , t_String } , { (caddr_t *) &dColor [8] , "color9" , "Color" , DEF_COLOR9 , t_String } , { (caddr_t *) &dForeground , "foreground" , "Foreground" , DEF_FOREGROUND , t_String } , { (caddr_t *) &dBackground , "background" , "Background" , DEF_BACKGROUND , t_String } , { (caddr_t *) &dUpdate , "update" , "Interval" , DEF_UPDATE , t_Int } , { (caddr_t *) &dThreshhold , "threshhold" , "Threshhold" , DEF_THRESHHOLD , t_Int } , } ; const int nVars = sizeof ( optionVars ) / sizeof ( optionVars [0] ) ; /* * Print out the help message. This'll need to be kept up-to-date as and when * commandline options change. */ static void Help ( void ) { fprintf ( stderr , "gmemusage ver %s by Raju (OldMonk) Mathur\n" "Usage: %s [options]\n" "where options (defaults/resources in brackets) are:\n" " -name resourcename Class name to use for resources (%s) (name)\n" " -display display X server to contact ($DISPLAY) (display)\n" " -geometry geometry Initial window geometry (%s) (geometry)\n" " -font font Text font (%s) (font)\n" " -background color Color to use for window background (%s) (background)\n" " -update seconds Update interval (%s) (update)\n" " -threshhold kb Threshhold to merge small processes (%s) (threshhold)\n" " -ncolors ncolors How many colors to use (%s) (ncolors)\n" " -color1 color color 1 (%s) (color1)\n" " -color2 color color 2 (%s) (color2)\n" " -color3 color color 3 (%s) (color3)\n" " -color[4-9] color colors 4 to 9 (undefined) (color4-color9)\n" " -help Print this message\n" , version , progname , DEF_CLASSNAME , DEF_GEOMETRY , DEF_FONT , DEF_BACKGROUND , DEF_UPDATE , DEF_THRESHHOLD , DEF_NCOLORS , DEF_COLOR1 , DEF_COLOR2 , DEF_COLOR3 ) ; } /* * Begin shameless thefts mentioned earlier. All I did was (1) remove the * extra cases for t_Float and t_Bool and (2) hit ESC C-q at the opening * brace in Xemacs for this function. */ static void GetResource ( XrmDatabase database , char *parentname , char *parentclass , char *name , char *class , int valueType , char *def , caddr_t *valuep ) { char *type; XrmValue value; char *string; char buffer[1024]; char fullname[1024]; char fullclass[1024]; int len; (void) sprintf(fullname, "%s.%s", parentname, name); (void) sprintf(fullclass, "%s.%s", parentclass, class); if (XrmGetResource(database, fullname, fullclass, &type, &value)) { string = value.addr; len = value.size; } else { string = def; len = strlen(string); } (void) strncpy(buffer, string, sizeof(buffer)); buffer[sizeof(buffer) - 1] = '\0'; switch (valueType) { case t_String: { char *s = (char *) malloc(len + 1); if (s == (char *) NULL) { fprintf ( stderr ,"%s: GetResource - couldn't allocate memory" , progname ) ; perror ( "" ) ; exit ( 1 ) ; } (void) strncpy(s, string, len); s[len] = '\0'; *((char **) valuep) = s; } break; case t_Int: *((int *) valuep) = atoi(buffer); break; } } static XrmDatabase optionDB = NULL , serverDB = NULL , mergedDB = NULL ; /* * External interface to resources. Again, shamelessly stolen from * xlockmore-3.0 source. I don't want to do what xlockmore does: open the * display within the GetResource, so we'll break that function up into * two seperate pieces: the first one will get the "name" and "display" * resources, return ot the parent which will then open the display * and then call the second one which will get the rest of the resources. */ void GetInitialResources ( int *argc , char **argv ) { XrmDatabase nameDB = NULL , displayDB = NULL ; XrmInitialize () ; /* * Get -name if we need to look for resources under another name. */ XrmParseCommand ( &nameDB , nameTable , nameEntries , progname , argc , argv ) ; GetResource ( nameDB , progname , "*" , "name" , "Name" , t_String , DEF_CLASSNAME , &dName ) ; XrmParseCommand ( &displayDB , displayTable , displayEntries , progname , argc , argv ) ; dDisplay = getenv ( "DISPLAY" ) ; if ( !dDisplay ) { dDisplay = "" ; } GetResource ( displayDB , progname , dName , "display" , "Display" , t_String , dDisplay , &dDisplay ) ; #if 0 printf("name %s, display %s\n",dName,dDisplay); #endif XrmMergeDatabases ( nameDB , &mergedDB ) ; XrmMergeDatabases ( displayDB , &mergedDB ) ; return ; } /* * Now get the rest of the resources. This function will be called after the * display has been opened by the application. I'm not going to look in * ~/.Xdefaults or ~/.Xresources (presumably rdb has already set those values * in the display RDB) and not in .../app-defaults/... since we are not looking * at an app-default file for the app yet. * * So finally the databases we are left with are: * - Server resources (presumably from rdb(1)) * - cmdline resources * - environment (for DISPLAY) */ void GetResources ( Display *display , int argc , char **argv ) { char *serverString ; register int i ; serverString = XResourceManagerString ( display ) ; if ( serverString ) { serverDB = XrmGetStringDatabase ( serverString ) ; (void) XrmMergeDatabases ( serverDB , &mergedDB ) ; } XrmParseCommand ( &optionDB , optionTable , optionEntries , progname , &argc , argv ) ; /* * Now there shouldn't be any arguments left at all. If there are any, * they're errors and we should flag them. */ if ( argc > 1 ) /* argv[0] still remains, presumably */ { if ( strcmp ( argv [1] , "-help" ) ) { fprintf ( stderr , "%s: unknown option %s\n" , progname , argv [1] ) ; } Help () ; exit ( 1 ) ; } XrmMergeDatabases ( optionDB , &mergedDB ) ; for ( i = 0 ; i < nVars ; i++ ) { GetResource ( mergedDB , progname , dName , optionVars [i] . name , optionVars [i] . class , optionVars [i] . type , optionVars [i] . def , optionVars [i] . var ) ; } XrmDestroyDatabase ( mergedDB ) ; return ; } gmemusage-0.2/testmem.pl100755 765 765 3027 6457157476 13551 0ustar rajuraju#!/usr/bin/perl -w # # an SGI gmemusage(1)-like interface to the process table. # # Excluded processes # @ExcludedProcesses = ( "/proc/0" , "/proc/2" , "/proc/3" ) ; %ProcSize = {} ; %ProcRSS = {} ; %nProc = {} ; $TotProcs = 0 ; $ls = "/bin/ls" ; # # Determine if a value is present in an array. # sub in { $val = shift @_ ; foreach $i ( @_ ) { return 1 if $val eq $i ; } return 0 ; } # # Extract info about running processes. # sub GetInfo { %ProcSize = {} ; %ProcRSS = {} ; $TotProcs = 0 ; %nProc = {} ; foreach $proc ( `$ls -d /proc/[0-9]*` ) { chop $proc ; if ( in ( $proc , @ExcludedProcesses ) ) { next ; } $TotProcs++ ; open ( PROC , "$proc/status" ) or next ; while ( ) { if ( /^Name:\s(.*)$/ ) { $ProcName = $1 ; # Do this to avoid unnecessary warnings from perl. can remove # later once we zap the -w . if ( ! defined $ProcSize { $ProcName } ) { $ProcSize { $ProcName } = $ProcRSS { $ProcName } = 0 ; } } if ( /^VmSize:\s*(.*)\s*kB/ ) { $ProcSize = $1 ; } if ( /^VmRSS:\s*(.*)\s*kB/ ) { $ProcRSS = $1 ; } } close PROC ; $ProcSize { $ProcName } += $ProcSize ; $ProcRSS { $ProcName } += $ProcRSS ; $nProc { $ProcName }++ ; } } # # Main() # while ( 1 ) { printf "%-20s%10s%10s%10s\n" , "Name" , "nProcs" , "totSize" , "totRSS" ; GetInfo ; foreach $i ( keys %nProc ) { printf ( "%-20s%10d%10d%10d\n" , $i , $nProc { $i } , $ProcSize { $i } , $ProcRSS { $i } ) ; } sleep 5 ; } exit 0 ; gmemusage-0.2/ChangeLog100644 765 765 1761 6457474221 13276 0ustar rajurajuWed Jan 14 21:54:49 1998 Raju Mathur * Misc: Changed version to "0.2 980114". Added 1998 to copyright year. * CREDITS : There's a CREDITS file now, so send your patches in and become famous! * Makefile: Added definitions for following variables: BELL_ON_UNKNOWN_KEYPRESS USE_PASTELS SAVE_XSERVER_MEMORY OPTIONS (agglomerate (sp?) of the above) Default optimization flag is now -O2. * resource.c: Added a new pastel color scheme for the bars in the stack. Look at the define for USE_PASTELS in Makefile. * gmemusage.c : Applied patch to use pixmaps for drawing. Now the flicker when the window updates is gone. Thanks to Yenya (Jan "Yenya" Kasprzak ) for this one. Save server memory (and get a slight performance impact) by defining SAVE_XSERVER_MEMORY in the Makefile. (main): Allow Bell to be switched off on unknown keypress. Look at the define for BELL_ON_UNKNOWN_KEYPRESS in the Makefile. * TODO: Updated TODO list gmemusage-0.2/gmemusage-0.2.lsm100644 765 765 1733 6457474347 14520 0ustar rajurajuBegin3 Title: gmemusage Version: 0.2 Entered-date: Jan 14, 1998 Description: Gmemusage is a graphical program modelled after the Silicon Graphics Inc. program of the same name. Gmemusage displays a window with a stacked bar. Areas on the bar correspond to individual processes running on the system and are updated periodically. Multiple copies of the same program (actually, programs with the same name) are merged into one area on the stack. Sizes of areas in the stack correspond to resident sizes of the processes. Keywords: process memory Author: Raju Mathur (raju@sgi.com) Maintained-by: Raju Mathur (raju@sgi.com) Primary-site: http://reality.sgi.com/raju/software.html Alternate-site: sunsite.unc.edu:pub/Linux/system/status Original-site: http://reality.sgi.com/raju/software.html Platform: Linux Copying-policy: GPL End gmemusage-0.2/CREDITS100644 765 765 211 6457165213 12507 0ustar rajurajuN: Raju Mathur E: raju@sgi.com D: Primary author N: Jan "Yenya" Kasprzak E: kas@fi.muni.cz D: Pixmap patch to get rid of update flicker