ttyload-0.5/004075500143120000022000000000001106407046600135545ustar00lindesusers00000400000417ttyload-0.5/BUGS010064400143120000022000000013030724571147500142410ustar00lindesusers00000400000417This code is still in relative infancy, despite the chronological age of some of it... As such, I suspect the potential is pretty high that there are a number of bugs in it. There are also a number of features which I'd like to be in it, but which currently are not... I suppose I could call those bugs too, maybe, but instead I'll reference them in a different list, presented in the file named TODO. And currently, while I've got plenty of things I want to see changed, there's not much that I can really call a "bug", per se... But here's something that's at least borderline on being one: - actually detect, rather than hard-coding, the number of rows and columns on the tty this is being run on. ttyload-0.5/Jamfile010064400143120000022000000016001033402722700150340ustar00lindesusers00000400000417# where to find headers (note: we still depend on Makefile to make # arch/thisarch -- for the moment): HDRS = . arch/thisarch arch/default ; EXEMODE = 755 ; # get our version information (hmm, maybe this would be cleaner if I # made a version.h from Version? I'd have to figure out how to do that # in Jam, too, of course) # CCFLAGS = -DVERSION="\\\"`cat Version`\\\"" ; ObjectCcFlags ttyload.c archtest.c : -DVERSION="\\\"`cat Version`\\\"" ; ARCH_SOURCES = arch/thisarch/getload.c arch/thisarch/terminfo.c ; # Alas, this doesn't work: # SoftLink arch/thisarch : arch/`uname -s | sed -e 's/ /-/g'` ; # main program: Main ttyload : ttyload.c $(ARCH_SOURCES) ; # XXX note: this re-builds the .o versions of $(ARCH_SOURCES), even # though they're already built for ttyload. I don't grok why, or how to # fix it. sigh. # archtest program: Main archtest : archtest.c $(ARCH_SOURCES) ; ttyload-0.5/LICENSE010064400143120000022000000023271106406272600145620ustar00lindesusers00000400000417The following license and related info applies to ttyload and all of the supporting components: * ttyload * Copyright 1996-2008 by David Lindes, All rights reserved. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. It is requested, without requirement, that any enhancements to this software be submitted back to the author, whose contact information can be found at the official web page for this software: http://www.daveltd.com/src/util/ttyload/ (Note: the above is a modified version of the "ISC License", as extracted from http://en.wikipedia.org/wiki/ISC_license 2008-09-16.) ttyload-0.5/Makefile010064400143120000022000000037771031036375300152240ustar00lindesusers00000400000417# Makefile for ttyload # Copyright 2001 by David Lindes, All Rights Reserved # see the "LICENSE" file for licensing info. # change this if you want to use 'make install' and have it go # somewhere else: INSTALLDIR = /usr/local/bin ARCH = `uname -s | sed -e 's/ /-/g'` LDFLAGS = `./ldflags` OBJS = arch/${ARCH}/getload.o \ arch/${ARCH}/terminfo.o \ ${NULL} # this is what I use most places... CC=gcc -pedantic -Wall # for the things in the sub-directory: INCLUDES = -I$${PWD:-.} \ -I$${PWD:-.}/arch/${ARCH} \ -I$${PWD:-.}/arch/default # Debugging compiles? DEBUG = -g VERSION = -DVERSION='"'`cat Version`'"' CFLAGS = $(INCLUDES) $(OTHER_FLAGS) $(DEBUG) $(VERSION) # most people won't want loader, so don't bother building it: # PROGRAMS = archbuild loader PROGRAMS = archbuild default: $(PROGRAMS) test: $(PROGRAMS) ./ttyload -i 1 # which architechtures are just symlinks? ARCHLINKS_FREEBSD = \ arch/Darwin \ arch/Isilon-OneFS \ ${NULL} ARCHLINKS_THISARCH = \ arch/thisarch \ ${NULL} ARCHLINKS = \ $(ARCHLINKS_FREEBSD) \ $(ARCHLINKS_THISARCH) \ ${NULL} # Some architechtures mimic eachother: $(ARCHLINKS_FREEBSD): ln -s FreeBSD $@ $(ARCHLINKS_THISARCH): ln -s ${ARCH} $@ archlinks: $(ARCHLINKS) archbuild: archlinks make archtest ttyload ARCH=$(ARCH) ttyload.c: ttyload.h Version touch ttyload.c # have to be explicit here, for some make systems, like .c.o below: ttyload: $(OBJS) ttyload.o $(CC) $(LDFLAGS) -o $@ $(OBJS) ttyload.o archtest: $(OBJS) archtest.o $(CC) $(LDFLAGS) -o $@ $(OBJS) archtest.o clean: rm -f *.o $(OBJS) core a.out clobber: clean rm -f loader ttyload archtest $(ARCHLINKS) # install, gently. not much to it: install: $(PROGRAMS) /bin/cp ttyload ${INSTALLDIR}/ttyload # because different systems' make have different behaviors on how they # deal with building stuff in subdirectories, and because I don't feel # like descending into the subdirectories to make a single object file, # I'll force the .c.o rule to what I'm expecting: .c.o: $(CC) $(CFLAGS) -o $@ -c $< ttyload-0.5/NOEXPORT010064400143120000022000000000241106407037400147440ustar00lindesusers00000400000417exportit .cvsignore ttyload-0.5/README010064400143120000022000000141301106406272700144310ustar00lindesusers00000400000417**************** * INTRODUCTION * **************** Hi there, This is ttyload. It was originally inspired several years ago when I (David Lindes, the original author) found myself with a desire to track load averages over time on a UNIX(ish) machine that I didn't have a way to run xload on (or any X application actually -- it didn't have the libraries installed, and it was not a reasonable choice to change that for that machine)... I figured this concept might come in handy in a variety of other situations, such as when logged in on a non-graphical console, or logging in remotely without an ability to forward X, etc... So, I wrote it. Now, when I originally wrote it, I was pretty inexperienced, so, while I new about curses, and that it would be nice to have this utility written with it, I didn't feel up to figuring it out and making that go, so I just used the fact that I happened to know a few ANSI escape sequences, and faked it as best I could at that time. Since then, I've found that, indeed, this functionality does have times when it's useful... And I know of no other utilities that perform quite this task. For a while, I only needed it on one platform, and so I simply recompiled it from time to time as I moved from one machine to another. But, eventually, I stopped having such a homogeneous environment, and wanted it for other platforms. And different platforms required different methods of getting data about the load averages... For a while, I didn't feel quite enough of a desire to have it elsewhere to make it work. But eventually I was convinced, through both my own desire and some urging from my friend Vern, to dust off the code and make it work again... So that's what I did. In doing so, I tried to make any purely new code be written in ways that would allow easy expansion of things onto new platforms, and generally to do things cleanly. But at the same time, the only feature I wanted to add was the ability to run it elsewhere, so, as it happens, there is still quite a bit of a primitive flavor to this program. But it did manage to get built on Linux, and now even a couple of others, so now I'm going ahead and making it available to the world... Please consider ttyload as "beta" (or maybe even only "alpha") quality software, and assume no guarantees whatsoever, thanks. For info on how to provide whatever feedback, or to get future versions as they become available, point your browser towards: http://www.daveltd.com/src/util/ttyload/ Thanks, David Lindes **************** * PLATFORMS... * **************** ttyload has been shown to run on systems running, at least: - Linux (at least some configs of it -- I'm using a SuSE 6.x box to build it on, with a 2.2.x kernel) - IRIX 6.5 (and possibly other versions?) - FreeBSD (some version or other, I'm not familiar with their numbering system... 4.4, I think.) - Solaris 2.x and later (at least 2.6 and 8) - Isilon OneFS Feel free, if you like, to submit patches to add more platforms (or other versions of existing platforms), and please let me know also if it runs unmodified on any other platforms. **************** * INSTALLATION * **************** to build ttyload, in theory all you need to is type 'make'. If you want to also install it, 'make install' should do the trick, which will copy it to /usr/local/bin (or another directory if you edit the INSTALLDIR setting in the Makefile or do 'make install INSTALLDIR=whatever'). **************** * RUN-TIME FOO * **************** After building, you can run ttyload with './ttyload' (or just 'ttyload' if either '.' is in your $PATH, or you did the make install into a directory that is), which will start up ttyload. What you see is basically a screen with three graphs on it. One is for the 1-minute load average, one for the 5min, and one for the 15min. Assuming you have color support, these will be red, green, and blue, respectively, and if they overlap, RGB addition will be done on them... Red + Green == Yellow, etc. See the Legend in the lower-left hand corner for the cheat-sheet. (Note: all my color naming is assuming your terminal is "reasonably standard" -- and no, I don't know exactly what "reasonably standard" means, so don't ask. ;-) To exit, type (hold down the "control" or "ctrl" key, and then simultaneously press the "c" key), or whatever you have 'stty intr' set to. If and when I have a curses mode, presumably 'q' and/or '' will work too. **************** * OTHER THINGS * **************** - ttyload -h gives you usage info. - the 'loader' program is generally something you don't want to run. In case you're curious, it's a "load bomb" which is specifically designed to increase your load average, but in a relatively limited way. This was done so that testing and screen shots and whatnot would be easier, and I don't expect folks to run it normally, but I figured I'd provide it anyway, just in case you're having a "Spinal Tap" moment or something. ;-) - there's a todo list on the web page, if you're thinking of a feature you want to see added, check there first before requesting it. - Please see the LICENSE file for information on what you're allowed to do with ttyload, etc. It's not under the GPL or some other license because I'm not entirely happy with most of those licenses. I eventually hope to put it under the GratuityWare Public License (GWPL, see http://www.gratuityware.org/), but that doesn't exist yet, because I haven't written it yet, so, that's yet to come. - Despite the lack of existence as yet of the GWPL, I do consider ttyload to be GratuityWare. This means that there will never be a required fee for using it, but donations are encouraged. See the web site (listed above at the end of the INTRODUCTION section) for a link that will allow you to do that. Or send me e-mail if you don't want to use the available method(s), but do want to contribute, and we can work something out. - Send any other feedback (comments, requests, bug reports, etc.) to me at (yes, '/' is valid in an e-mail address! If your mailer can't hack it, though, you can substitute '-' for it, if you must). ttyload-0.5/TODO010064400143120000022000000004140734257062100142420ustar00lindesusers00000400000417Lots of stuff todo... here are a few big items: - convert to using curses (or similar, perhaps) - make the clock stamps cleaner when using large -i values - write a man page Also, see http://www.daveltd.com/src/util/ttyload/ for other stuff that may be on my list. ttyload-0.5/Version010064400143120000022000000000041106406272700151140ustar00lindesusers000004000004170.5 ttyload-0.5/archtest.c010064400143120000022000000010411030743033700155220ustar00lindesusers00000400000417/* * archtest.c -- simple harness to the arch-specific stuff, so * that we can test those things in relative isolation. */ #include "ttyload.h" #include int rows = -1, cols = -1; int main(int argc, char *argv[]) { load_list loads; gettermsize(); printf("termsize: %d rows, %d cols\n", rows, cols); getload(&loads); printf("Load averages %g, %g, %g\n", (loads.one_minute / 1024.0), (loads.five_minute / 1024.0), (loads.fifteen_minute / 1024.0)); printf("Version: %s\n", VERSION); return(0); } ttyload-0.5/ldflags010075500143120000022000000001660734153761700151270ustar00lindesusers00000400000417#!/bin/sh case `uname -s` in SunOS) echo "-lkstat";; *) # most stuff doesn't need anything special ;; esac ttyload-0.5/loader.c010064400143120000022000000022310734154173000151610ustar00lindesusers00000400000417/* * loader.c -- a time-limited, max-load-limited load bomb * * In general, you don't want to run this. * * Copyright 2001, David Lindes, All Rights Reserved. */ #include #include #include #include int main(int argc, char *argv[]) { int ttl, /* how long to load things */ forks; /* how many jobs to run at once */ time_t start; /* when we started */ pid_t pid; /* return value for fork() */ /* for now, set these purely by hand... later, I'll * make 'em be based on argv. */ ttl = 90; forks = 11; /* this one goes to 11. ;-) */ for(/*pre-initted*/; --forks > 0 ;) { if((pid = fork()) != 0) { /* check to see if the fork actually failed: */ if(pid < 0) { perror("fork failed"); exit(1); } /* otherwise, we're a child... */ break; /* don't continue this loop as child. */ } } printf("Bomb running for %d seconds\n", ttl); start = time(NULL); while(time(NULL) < (start + ttl)) { ; /* do nothing, tight loop is intentional. */ } printf("Bomb ending at %ld, started %ld\n", time(NULL), start); exit(0); } ttyload-0.5/ttyload.1010064400143120000022000000051341106406566400153220ustar00lindesusers00000400000417.TH "ttyload" "1" "2001-08-24" "" "" .SH "NAME" ttyload \- a tty-based xload equivalent .SH "SYNOPSIS" .PP ttyload [options] .PP .SH "DESCRIPTION" .PP ttyload is a "tty" based load monitoring tool\&. Not entirely unlike xload, it plots a graph of a system's "load average" data\&. Unlike xload, it uses 3 line graphs to plot things, instead of a single fill graph, so that it can show you not only the 1-minute load average, but also the 5-minute and 15-minute averages\&. Also unlike xload, it uses a basic terminal (tty) to display the information, instead of an X window\&. ANSI escape sequences are used (optionally) for colorization and screen manipulation\&. .PP A few of the main features of ttyload are: .PP .IP o graphs load averages (all 3 numbers) over time .IP o uses ANSI escape sequences to colorize graphs .IP o works without requiring X11 libraries, in a Terminal window .IP o automatically determines screen size by default .PP \" .SH "GENERAL" \" .PP \" See DESCRIPTION\&. \" .PP .SH "USAGE" .PP The easiest way to use ttyload is just to invoke the command, with no additional options\&. .PP Additional options are described below\&. .PP To quit ttyload, enter the terminal's interrupt character (typically control-C)\&. .PP \" .SH "EXAMPLES" \" .PP \" Here are some examples of how I use ttyload\&. \" .PP \" No examples written\&. \" .RE .PP .SH "OPTIONS" .PP ttyload uses standard getopt() style options processing\&. Available options are: .PP .DS .PP .IP "\fB-h\fP" Display a brief usage statement ("help")\&. .IP "\fB-v\fP" show version info, then exit .IP "\fB-m\fP" monochrome mode (no ANSI escapes) .IP "\fB-c \fP" Sets the number of columns wide to make the display .IP "\fB-r \fP" Sets the number of rows high to make the display (these two options combine to override the default behavior of auto-determining screen size) .IP "\fB-i \fP" Alter the number of seconds in the interval between refreshes\&. The default is 4, and the minimum is 1, which is silently clamped\&. .DE .PP .PP .SH "SEE ALSO" .PP getopt(3) .PP .PP .SH "VERSION" This man page is current for version 0\&.5 of ttyload .PP .SH "THANKS" .PP Thanks to several my friends for testing things out on various platforms, or lending me accounts on their machines upon which to do porting\&. .PP .SH "AUTHOR" .PP ttyload was written by David Lindes\&. Please send any feedback, including bug reports and patches, to me\&. My contact information (as well as updates and other information) can be found on the ttyload web page at: http://www\&.daveltd\&.com/src/util/ttyload/ .PP ttyload-0.5/ttyload.c010064400143120000022000000310011106406572500153720ustar00lindesusers00000400000417/* * ttyload * * tty equivalent to xload * * Copyright 1996 by David Lindes * all right reserved. * * Version information: $Id: ttyload.c,v 1.25 2008/09/17 02:30:45 lindes Exp $ * */ #include #include #include #include #include #include #include #include #include #include #include "ttyload.h" #define HEIGHTPAD 7 /* 2 lines above; * 4 lines + cursor line below */ #define WIDTHPAD 14 #define CLOCKWIDTH 7 #define HOSTLENGTH 30 #define MINHOSTPAD 20 #define MINROWS (HEIGHTPAD + 6) #define MINCOLS (WIDTHPAD + 6) char *c="$Id: ttyload.c,v 1.25 2008/09/17 02:30:45 lindes Exp $"; char strbuf[BUFSIZ], *optstring = "i:hvmr:c:", *usage = "Usage: %s []\n" "\n" " Available options:\n" " -h -- show this help, then exit\n" " -v -- show version info, then exit\n" " -m -- monochrome mode (no ANSI escapes)\n" " -c cols -- how many cols wide is the screen?\n" " -r rows -- how many rows high is the screen?\n" " (these two options override the default\n" " behavior of auto-determining screen size)\n" " -i secs\n" " Alter the number of seconds in " "the interval between refreshes.\n" " The default is 4, and the minimum " "is 1, which is silently clamped.\n\n" " (Note: use ctrl-C to quit)\n\n" " For updates and other info, see http://" "www.daveltd.com/src/util/ttyload/\n" " Donations appreciated.\n" ""; int clockpad, clocks; clock_info *theclocks; /* version ID, passed in by the Makefile: */ char *version = VERSION; char *color_loadstrings[] = { " ", /* blank */ "\033[31m*\033[m", /* one minute average */ "\033[32m*\033[m", /* five minute average */ "\033[33m*\033[m", /* one & five, together */ "\033[34m*\033[m", /* fifteen minute average */ "\033[35m*\033[m", /* one & fifteen, together */ "\033[36m*\033[m", /* five & fifteen, together */ "\033[37m*\033[m" /* one, five & fifteen, together */ }; /* same stuff, same order: */ char *mono_loadstrings[] = { " ", "1", "2", "3", "4", "5", "6", "7" }; /* by default, use color: */ char **loadstrings = color_loadstrings; /* The following two variables should probably be assigned using some sort of real logic, rather than these hard-coded defaults, but the defaults work for now... */ int rows = 40, cols = 80, intsecs = 4, debug = 3, theclock = 0, height, width; int compute_height(load_t, load_t, int); void showloads(load_list *); void clear_screen(); void home_screen(); void cycle_load_list(load_list*, load_list, int); void initialize_load_list(load_list *list, int size); int main(argc, argv, envp) int argc; char *argv[], *envp[]; { load_list *loadavgs, newload; int c, i, errflag=0, versflag=0; char *basename; char hostname[HOSTLENGTH + 1]; time_t thetime; struct tm *thetimetm; /* set up the basename variable, used for Usage, etc. */ basename = (char *)strrchr(*argv, '/'); if(!basename) basename = *argv; else basename++; /* go past the '/' */ gettermsize(); /* sets our globals: rows, cols */ while((c = getopt(argc, argv, optstring)) != EOF) { switch(c) { /* timing interval: */ case 'i': intsecs = atoi(optarg); break; /* display mode selection: */ case 'm': loadstrings = mono_loadstrings; break; /* height/width stuff... error checking done later. */ case 'r': rows = atoi(optarg); break; case 'c': cols = atoi(optarg); break; /* help and such, plus default: */ case 'v': versflag++; break; case 'h': default: errflag++; break; /* redundant */ } } /* version info requested, show it: */ if(versflag) fprintf(stderr, "%s version %s\n", basename, version); /* error, show usage: */ if(errflag) fprintf(stderr, usage, basename); /* for either, we exit: */ if(errflag || versflag) exit(1); if(gethostname(hostname, HOSTLENGTH)) { perror("NOTICE: couldn't determine hostname"); strcpy(hostname, "localhost"); sleep(2); } /* do space-padding of hostname out to MINHOSTPAD chars: */ for(i = 0; i < (MINHOSTPAD); i++) { if(hostname[i] == '\0') { hostname[i] = ' '; hostname[i + 1] = '\0'; } } if(rows < MINROWS) { fprintf(stderr, "Sorry, %s requires at least %d rows to run.\n", basename, MINROWS); exit(1); } if(cols < MINCOLS) { fprintf(stderr, "Sorry, %s requires at least %d cols to run.\n", basename, MINCOLS); exit(1); } intsecs = MAX(1, intsecs); /* must be positive */ height = rows - HEIGHTPAD - 1; width = cols - WIDTHPAD; clocks = MAX(width/intsecs, width/CLOCKWIDTH); clockpad = (width / clocks) - CLOCKWIDTH; loadavgs = (load_list *)calloc(width, sizeof(load_list)); theclocks = (clock_info *)calloc(clocks, sizeof(clock_info)); initialize_load_list(loadavgs, width); if(!loadavgs) { perror("calloc for loadavgs failed"); exit(1); } if(!theclocks) { perror("calloc for clocks failed"); exit(1); } /* run getload one time before clear_screen, in case it * errors out or something... not that I've seen it do that, * but there's code there for checking stuff. */ getload(&loadavgs[0]); for(i=0;itm_sec) / intsecs) == 0) { if(!strftime(strbuf, 7, "^%H:%M", thetimetm)) { /* This should never happen, I hope... */ perror("strftime failed"); exit(1); } theclocks[theclock].pos = i; strcpy(theclocks[theclock].clock, strbuf); theclock++; theclock %= clocks; if(theclock >= clocks) { /* Hopefully, I'll get this to the point where it well never happen... As I first write it, I'm fairly certain it will, but that should be fixable... */ fprintf(stderr, "Internal error: too many clocks!"); exit(1); } /* as a temporary cleanup functionality after * changing from clear_screen on every iteration to * home_screen on all but the first, but since it's * nice to occasionally actually clear (at least * until we're actually using curses or the like, * when we can put that activity on SIGWINCH and * ctrl-L command, or the like), I'm using the * enclosing if() condition as a "good" time to do * that: */ clear_screen(); } if(!strftime(strbuf, 9, "%H:%M:%S", thetimetm)) { /* This should never happen, I hope... */ perror("strftime failed"); exit(1); } home_screen(); printf("%s %.2f, %.2f, %.2f %s ttyload, v%s\n\n", hostname, (loadavgs[i].one_minute / 1024.), (loadavgs[i].five_minute / 1024.), (loadavgs[i].fifteen_minute / 1024.), strbuf + 1, version); if(debug > 3) printf("Load averages: %f, %f, %f\n", loadavgs[i].one_minute / 1024., loadavgs[i].five_minute / 1024., loadavgs[i].fifteen_minute / 1024.); showloads(loadavgs); if(i == (width - 1)) { if(debug > 4) { printf("CYCLING LOAD LIST...\n"); sleep(3); } getload(&newload); cycle_load_list(loadavgs, newload, width); i--; } } return(0); /* not that we get here... right? */ } void showloads(loadavgs) load_list *loadavgs; { load_list min = {LONG_MAX-1, LONG_MAX-1, LONG_MAX-1, 0, 0, 0}, max = {0, 0, 0, 0, 0, 0}; load_t lmin, lmax; float omin, omax; int i, j, k; if(debug>3) { printf("Starting with min set: %ld, %ld, %ld\n", min.one_minute, min.five_minute, min.fifteen_minute); printf("Starting with first set: %ld, %ld, %ld\n", loadavgs[0].one_minute, loadavgs[0].five_minute, loadavgs[0].fifteen_minute); sleep(1); } for(i=0;i9) { printf("Checking for min/max at %d...\n", i); printf("Comparing, for example, %ld <=> %ld\n", min.one_minute, loadavgs[i].one_minute); } min.one_minute = MIN(min.one_minute, loadavgs[i].one_minute); min.five_minute = MIN(min.five_minute, loadavgs[i].five_minute); min.fifteen_minute = MIN(min.fifteen_minute, loadavgs[i].fifteen_minute); max.one_minute = MAX(max.one_minute, loadavgs[i].one_minute); max.five_minute = MAX(max.five_minute, loadavgs[i].five_minute); max.fifteen_minute = MAX(max.fifteen_minute, loadavgs[i].fifteen_minute); } if(debug>3) { printf("Continuing with min set: %ld,%ld,%ld\n", min.one_minute, min.five_minute, min.fifteen_minute ); printf("Continuing with first set: %ld,%ld,%ld\n", loadavgs[0].one_minute, loadavgs[0].five_minute, loadavgs[0].fifteen_minute); sleep(1); printf("MIN Load averages: %f, %f, %f\n", min.one_minute / 1024., min.five_minute / 1024., min.fifteen_minute / 1024.); printf("MAX Load averages: %f, %f, %f\n", max.one_minute / 1024., max.five_minute / 1024., max.fifteen_minute / 1024.); } lmin=MIN(min.one_minute, MIN(min.five_minute, min.fifteen_minute)); lmax=MAX(max.one_minute, MAX(max.five_minute, max.fifteen_minute)); if(debug > 3) printf("Overall MIN, MAX: %f, %f\n", lmin/1024., lmax/1024.); omin = (int)(lmin / 1024); lmin = 1024 * omin; if((lmax / 1024.) < .25) { omax = .25; } else if((lmax / 1024.) < .5) { omax = .5; } else { omax = (int)(lmax / 1024) + 1; } lmax = 1024 * omax; if(debug > 3) { printf("Boundaries: %g, %g... ", omin, omax); printf("Long Boundaries: %ld, %ld\n", lmin, lmax); } for(i=0;i 3) { printf("Load averages: %f, %f, %f -- ", loadavgs[i].one_minute / 1024., loadavgs[i].five_minute / 1024., loadavgs[i].fifteen_minute / 1024.); printf("Heights: %d, %d, %d\n", loadavgs[i].height1, loadavgs[i].height5, loadavgs[i].height15); } } for(j = 0; j <= height; j++) { printf("%6.2f ", (((omax)*(height-j)) / (height)) ); for(i=0;i 0) { strncpy( &strbuf[9+theclocks[i].pos], theclocks[i].clock, 6); } } /* make sure the string still terminates in the same place: */ strbuf[cols -1] = '\0'; printf("%s\n Legend:\n" " 1 min: %s, 5 min: %s, 15 min: %s\n" " 1&5 same: %s, 1&15: %s, 5&15: %s, all: %s\n", strbuf, loadstrings[1], loadstrings[2], loadstrings[4], loadstrings[3], loadstrings[5], loadstrings[6], loadstrings[7]); } int compute_height(thisload, maxload, height) load_t thisload, maxload; int height; { /* if thisload is negative (done by initialization), return * something impossible, so we don't draw bogus data: */ if(thisload < 0) return(height + 1); /* this is a reversal of what you might think... the X axis * is really on the top of the graph, so larger heights sit * lower. the 'height -' part is implicitly done elsewhere. * (but not really ever actually done) */ return(/* height- */ ( height * ( (maxload - thisload) / (float)maxload ) ) ); } void clear_screen() { printf("\033[H\033[2J"); } void home_screen() { printf("\033[H"); } void cycle_load_list(loadavgs, newload, width) load_list *loadavgs, newload; int width; { /* This function will eventually have code to clear locations on the screen that change. */ int i; for(i=0;i<(width-1);i++) { loadavgs[i] = loadavgs[i+1]; } loadavgs[i] = newload; for(i=0;i(b))?(a):(b)) #define ONE 01; #define FIVE 02; #define FIFTEEN 04; typedef long load_t; typedef struct load_list { load_t one_minute; load_t five_minute; load_t fifteen_minute; int height1; int height5; int height15; int numloads; } load_list; typedef struct clock_info { int pos; char clock[6]; } clock_info; /* functions in arch-specific files: */ extern void getload(load_list *); extern void gettermsize(); ttyload-0.5/arch/004075500143120000022000000000001106407046500144705ustar00lindesusers00000400000417ttyload-0.5/arch/.README010064400143120000022000000025160724566133400154360ustar00lindesusers00000400000417Here's an example of what a platform-specific getload.c might look like, in skeleton form: /* to get data types and such: */ #include "ttyload.h" /* general headers that are likely to be used on most systems: */ #include /* for perror */ #include /* for exit() */ /* and here's the core function: */ void getload(load_list *loadavgs) { /* to store data from the load average retrieval routine: */ sometype theload[3]; /* to store the return value of same: */ int ret; if((ret = someroutineforgettingload(theload)) < 0) { perror("thatroutineIcalled() failed"); exit(1); } /* so the caller can know how we did with getting the load, and * report on problems there: */ loadavgs->numloads = ret; /* and these all should be in integer form as one 1024'th of the * actual load average... On most platforms, you'll probably have * to do this math (but some may not require it, depending on how * the routine for getting the load average actually works): */ loadavgs->one_minute = theload[0] * 1024; loadavgs->five_minute = theload[1] * 1024; loadavgs->fifteen_minute = theload[2] * 1024; /* no need to "return()" anything, because we exit() on fatal * errors, and return information about our success level beyond * that with numloads. */ } ttyload-0.5/arch/FreeBSD/004075500143120000022000000000001106407046300157005ustar00lindesusers00000400000417ttyload-0.5/arch/FreeBSD/getload.c010064400143120000022000000021440734135776200174760ustar00lindesusers00000400000417/* * ttyload/arch/FreeBSD/getload.c -- getload() implimentation for the * FreeBSD platform. * * Copyright 2001, David Lindes. All rights reserved. */ #include "ttyload.h" #include /* for perror */ #include /* for exit(), and, on FreeBSD, * getloadavg(), too. */ #include /* for sleep() */ void getload(load_list *loadavgs) { double theload[3]; int ret; if((ret = getloadavg(theload, 3)) < 0) { perror("getloadavg() failed"); exit(1); } /* so the caller _can_ (maybe not _will_) know how we did */ loadavgs->numloads = ret; loadavgs->one_minute = theload[0] * 1024; loadavgs->five_minute = theload[1] * 1024; loadavgs->fifteen_minute = theload[2] * 1024; switch(ret) { case 2: fprintf(stderr, "15 minute Load average is unreliable.\n"); sleep(5); break; case 1: fprintf(stderr, "5 and 15 minute load averages are unreliable.\n"); sleep(5); break; case 0: fprintf(stderr, "Sorry, couldn't get any load " "averages. This is, therefore, pointless.\n"); exit(1); } } ttyload-0.5/arch/FreeBSD/terminfo.c010064400143120000022000000010750734257135500177010ustar00lindesusers00000400000417/* * arch/Linux/terminfo.c -- routines for getting terminal * information on Linux machines. * * Copyright 2001, David Lindes. All rights reserved. */ #include /* for ioctl() */ /* globals */ extern int rows; extern int cols; void gettermsize() { struct winsize info; /* try to get data via IOCTL: */ if (ioctl(1 /* stdout */, TIOCGWINSZ, &info) != -1) { /* if successful, and the data seems sane, set the * program's globals: */ if(info.ws_col > 0) cols = info.ws_col; if(info.ws_row > 0) rows = info.ws_row; } } ttyload-0.5/arch/IRIX/004075500143120000022000000000001106407046400152425ustar00lindesusers00000400000417ttyload-0.5/arch/IRIX/getload.c010064400143120000022000000016700734164555400170410ustar00lindesusers00000400000417/* * ttyload/arch/IRIX/getload.c -- getload() implimentation for the * IRIX platform. * * Copyright 1996-2001, David Lindes. All rights reserved. */ #include "ttyload.h" #include /* for perror() */ #include /* for exit() */ #include /* sys/syget.h needs this */ #include /* for sysget() */ void getload(load_list *loadavgs) { sgt_cookie_t cookie; SGT_COOKIE_INIT(&cookie); SGT_COOKIE_SET_KSYM(&cookie, "avenrun"); /* since IRIX uses an integer data type for this stuff, which is * 1024 times the floating-point equiv, we don't need to do any * conversions, because that's what load_list uses (since ttyload * was originally written for IRIX in the first place). */ if(sysget(SGT_KSYM, (char*)loadavgs, 3 * sizeof(load_t), SGT_READ | SGT_SUM, &cookie) != (3 * sizeof(load_t))) { perror("Couldn't read load data, sysget failed"); exit(1); } } ttyload-0.5/arch/IRIX/terminfo.c010064400143120000022000000010750734257064300172410ustar00lindesusers00000400000417/* * arch/Linux/terminfo.c -- routines for getting terminal * information on Linux machines. * * Copyright 2001, David Lindes. All rights reserved. */ #include /* for ioctl() */ /* globals */ extern int rows; extern int cols; void gettermsize() { struct winsize info; /* try to get data via IOCTL: */ if (ioctl(1 /* stdout */, TIOCGWINSZ, &info) != -1) { /* if successful, and the data seems sane, set the * program's globals: */ if(info.ws_col > 0) cols = info.ws_col; if(info.ws_row > 0) rows = info.ws_row; } } ttyload-0.5/arch/Linux/004075500143120000022000000000001106407046400155665ustar00lindesusers00000400000417ttyload-0.5/arch/Linux/getload.c010064400143120000022000000030260730223257100173460ustar00lindesusers00000400000417#define LOADFILE "/proc/loadavg" /* What the contents of the proc file look like, as an example: * 0.00 0.00 0.00 1/59 10941 */ #include "ttyload.h" #include /* for perror */ #include /* for exit() */ #include /* for sleep() */ void getload(load_list *loadavgs) { float theload[3]; FILE *loadfile; int ret; /* just for sanity: */ if(!loadavgs) { fprintf(stderr, "getload called without loadavgs pointer.\n"); exit(2); } if(!(loadfile = fopen(LOADFILE, "r"))) { perror("Open of " LOADFILE " failed"); exit(1); } ret = fscanf(loadfile, "%f %f %f ", &(theload[0]), &(theload[1]), &(theload[2])); if(fclose(loadfile) != 0) { perror("Close of " LOADFILE " failed?!"); exit(1); } /* so the caller _can_ (maybe not _will_) know how we did */ loadavgs->numloads = ret; loadavgs->one_minute = theload[0] * 1024; loadavgs->five_minute = theload[1] * 1024; loadavgs->fifteen_minute = theload[2] * 1024; /* a little warning thing... should probably be re-written * for the Linux/fscanf stuff, this is a hold-over from the * solaris stuff. */ switch(ret) { case 2: fprintf(stderr, "15 minute Load average is unreliable.\n"); sleep(5); break; case 1: fprintf(stderr, "5 and 15 minute load averages are unreliable.\n"); sleep(5); break; case 0: fprintf(stderr, "Sorry, couldn't get any load " "averages. This is, therefore, pointless.\n"); exit(1); } } ttyload-0.5/arch/Linux/terminfo.c010064400143120000022000000010750734257034300175620ustar00lindesusers00000400000417/* * arch/Linux/terminfo.c -- routines for getting terminal * information on Linux machines. * * Copyright 2001, David Lindes. All rights reserved. */ #include /* for ioctl() */ /* globals */ extern int rows; extern int cols; void gettermsize() { struct winsize info; /* try to get data via IOCTL: */ if (ioctl(1 /* stdout */, TIOCGWINSZ, &info) != -1) { /* if successful, and the data seems sane, set the * program's globals: */ if(info.ws_col > 0) cols = info.ws_col; if(info.ws_row > 0) rows = info.ws_row; } } ttyload-0.5/arch/SunOS/004075500143120000022000000000001106407046500154775ustar00lindesusers00000400000417ttyload-0.5/arch/SunOS/getload.c010064400143120000022000000040650734154012500172620ustar00lindesusers00000400000417#include "ttyload.h" #include /* for perror */ #include /* for exit() */ #include /* for the various kstat stuff */ void getload(load_list *loadavgs) { static kstat_ctl_t *kc; /* kstat control */ static kstat_t *ksrec; /* the kstat record */ kstat_named_t *info; /* our pointer to the info */ if(!kc) /* initialize, first time only */ { if(!(kc = kstat_open())) { perror("kstat_open failed"); exit(1); } /* find the record where the load averages are stored * (It seems like it's safe to only do this once) */ if(!(ksrec = kstat_lookup(kc, "unix", 0, "system_misc"))) { perror("ksatat_lookup failed"); exit(1); } } /* read in the latest data into the buffer space that ksrec * keeps for us. */ if(kstat_read(kc, ksrec, NULL) == -1) { perror("kstat_read failed"); exit(1); } /* need a pointer with a type we can dig into: */ for(info = (kstat_named_t*)ksrec->ks_data, loadavgs->numloads = 0; (char*)info < ((char*)ksrec->ks_data + ksrec->ks_data_size); info++) { /* DEBUG: printf("info->name = %s\n", info->name); */ /* in theory, the loop will take us through all three of * these, in order... I depend on that being true: */ if(strcmp(info->name, "avenrun_1min") == 0) { /* Note: Sun stores this data as the float value * * 256; we use 1024 as the multiplier, so multiply * by 4 to make up the difference: */ loadavgs->one_minute = info->value.ul * 4; loadavgs->numloads++; } else if(strcmp(info->name, "avenrun_5min") == 0) { loadavgs->five_minute = info->value.ul * 4; loadavgs->numloads++; } else if(strcmp(info->name, "avenrun_15min") == 0) { loadavgs->fifteen_minute = info->value.ul * 4; loadavgs->numloads++; } } /* hopefully, this never happens: */ if(loadavgs->numloads != 3) { fprintf(stderr, "Woah, kstat walking didn't get us the " "number of load average data points we were expecting; " "got %d instead of 3.\n", loadavgs->numloads); exit(1); } } ttyload-0.5/arch/SunOS/terminfo.c010064400143120000022000000016320736734422400174750ustar00lindesusers00000400000417/* * arch/SunOS/terminfo.c -- routines for getting terminal * information on Solaris (SunOS) machines. * * Copyright 2001, David Lindes. All rights reserved. */ #include /* for ioctl() */ #include /* for TIOCGWINSZ */ #define _KMEMUSER /* something needs this in order * for strsubr.h to be happy */ #include /* sys/strsubr.h needs this */ #include /* sys/strsubr.h needs this */ #include /* sys/ptem.h needs this */ #include /* for struct winsize */ /* globals */ extern int rows; extern int cols; void gettermsize() { struct winsize info; /* try to get data via IOCTL: */ if (ioctl(1 /* stdout */, TIOCGWINSZ, &info) != -1) { /* if successful, and the data seems sane, set the * program's globals: */ if(info.ws_col > 0) cols = info.ws_col; if(info.ws_row > 0) rows = info.ws_row; } } l.h> /* sys/strsubr.h needs this */ #include /* sys/ptem.h needs this */ #include