acheng@uiucdcs.UUCP (09/21/83)
#N:uiucdcs:12600015:000:15356 uiucdcs!acheng Sep 20 09:04:00 1983 *************FORWARDED NOTE****************** I didn't realize there might be a demand for screen-oriented versions of vmstat(1). I just looked at chris@umcp (hope I got that right) program vmpic; unfortunately I can't use it yet, because I haven't done anything about the window library. I have been using my own hacked-up version of vmstat, which uses plain old curses and runs on 4.1bsd. The source follows. Hack it as you wish. All I ask is you not sell it. Cheers, Vahe Sarkissian UUCP : {ihnss!ihnp4}!inuxc!iuvax!vahe CSnet : Vahe @ Indiana The source is bracketed between the two lines of all percent marks. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #include <curses.h> #include <signal.h> #include <sys/param.h> #include <sys/vm.h> #include <sys/dk.h> #include <nlist.h> #include <sys/buf.h> #include <sys/ubavar.h> #include <sys/mbavar.h> /* vmshow - show vm statistics with screen-oriented output. * This program is a hacked up version of vmstat(1). It uses * the "curses" package. * To compile: * * cc -O -s -n vmshow.c -o vmshow -ljobs -lcurses -ltermlib * * The defined string MYNAME should be the name of the machine * the program is running on. It can be set to anything you like. * Vahe Sarkissian, IUCS, July 29, 1983. */ #define MYNAME " I U V A X " struct nlist mynl[] = { #define X_CPTIME 0 { "_cp_time" }, #define X_RATE 1 { "_rate" }, #define X_TOTAL 2 { "_total" }, #define X_DEFICIT 3 { "_deficit" }, #define X_FORKSTAT 4 { "_forkstat" }, #define X_SUM 5 { "_sum" }, #define X_FIRSTFREE 6 { "_firstfree" }, #define X_MAXFREE 7 { "_maxfree" }, #define X_BOOTIME 8 { "_bootime" }, #define X_DKXFER 9 { "_dk_xfer" }, #define X_MBDINIT 10 { "_mbdinit" }, #define X_UBDINIT 11 { "_ubdinit" }, #define X_REC 12 { "_rectime" }, #define X_PGIN 13 { "_pgintime" }, #define X_HZ 14 { "_hz" }, { 0 }, }; char dr_name[DK_NDRIVE][10]; char dr_unit[DK_NDRIVE]; double stat1(); /* save these for later.... int firstfree, maxfree; */ int hz; struct { long time[CPUSTATES]; long xfer[DK_NDRIVE]; struct vmmeter Rate; struct vmtotal Total; struct vmmeter Sum; } s, s1; #define rate s.Rate #define total s.Total #define sum s.Sum int deficit; double etime; int mf; main(argc, argv) char **argv; { time_t now; extern char *ctime(); char timestr[26]; register i; int iter = 1; int nintv; time_t bootime; long t; int cleanup(); sigset(SIGINT,cleanup); sigset(SIGHUP,cleanup); sigset(SIGQUIT,cleanup); nlist("/vmunix", mynl); if(mynl[0].n_type == 0) { printf("no /vmunix namelist\n"); exit(1); } mf = open("/dev/kmem", 0); if(mf < 0) { printf("cannot open /dev/kmem\n"); exit(1); } if(argc > 1) iter = atoi(argv[1]); /* These may come in handy in the future.... lseek(mf, (long)mynl[X_FIRSTFREE].n_value, 0); read(mf, &firstfree, sizeof firstfree); lseek(mf, (long)mynl[X_MAXFREE].n_value, 0); read(mf, &maxfree, sizeof maxfree); */ lseek(mf, (long)mynl[X_BOOTIME].n_value, 0); read(mf, &bootime, sizeof bootime); lseek(mf, (long)mynl[X_HZ].n_value, 0); read(mf, &hz, sizeof hz); for (i = 0; i < DK_NDRIVE; i++) { strcpy(dr_name[i], "xx"); dr_unit[i] = i; } read_names(); time(&now); nintv = now - bootime; if (nintv <= 0 || nintv > 60*60*24*365*10) { printf("Time makes no sense... namelist must be wrong.\n"); exit(1); } set_display(); loop: /* This begins an infinite loop. It's not written in the form for(;;) because you run out of crt if you indent...*/ lseek(mf, (long)mynl[X_CPTIME].n_value, 0); read(mf, s.time, sizeof s.time); lseek(mf, (long)mynl[X_DKXFER].n_value, 0); read(mf, s.xfer, sizeof s.xfer); if (nintv != 1) { lseek(mf, (long)mynl[X_SUM].n_value, 0); read(mf, &rate, sizeof rate); } else { lseek(mf, (long)mynl[X_RATE].n_value, 0); read(mf, &rate, sizeof rate); } lseek(mf, (long)mynl[X_TOTAL].n_value, 0); read(mf, &total, sizeof total); lseek(mf, (long)mynl[X_DEFICIT].n_value, 0); read(mf, &deficit, sizeof deficit); lseek(mf, (long)mynl[X_SUM].n_value, 0); read(mf, &sum, sizeof sum); etime = 0; for (i=0; i < DK_NDRIVE; i++) { t = s.xfer[i]; s.xfer[i] -= s1.xfer[i]; s1.xfer[i] = t; } for (i=0; i < CPUSTATES; i++) { t = s.time[i]; s.time[i] -= s1.time[i]; s1.time[i] = t; etime += s.time[i]; } if(etime == 0.) etime = 1.; time(&now); strncpy(timestr,ctime(&now),sizeof timestr); timestr[19] = '\0'; mvaddstr(1,11,×tr[11]); mvprintw(1,73,"%3d",sum.v_rev); mvprintw(4,14,"%3d",total.t_rq); mvprintw(5,14,"%3d",total.t_dw+total.t_pw); mvprintw(6,14,"%3d",total.t_sw); mvprintw(4,42,"%6d",total.t_avm/2); mvprintw(5,42,"%6d",total.t_free/2); mvprintw(10,21,"%3d",(rate.v_pgrec - (rate.v_xsfrec+rate.v_xifrec))/nintv); mvprintw(11,21,"%3d",(rate.v_xsfrec+rate.v_xifrec)/nintv); mvprintw(10,35,"%3d",rate.v_pgpgin/2/nintv); mvprintw(11,35,"%3d",rate.v_pgpgout/2/nintv); mvprintw(10,50,"%3d",rate.v_scan/nintv); mvprintw(11,50,"%3d",rate.v_dfree/2/nintv); mvprintw(10,68,"%3d",deficit/2); etime /= 60.; for(i=0; i<DK_NDRIVE; i++) mvprintw(15,(9*i+21),"%3.0f",s.xfer[i]/etime); mvprintw(17,30,"%3d",(rate.v_intr/nintv)-hz); mvprintw(17,68,"%3d",rate.v_pdma/nintv); mvprintw(18,30,"%3d",rate.v_syscall/nintv); mvprintw(18,68,"%3d",rate.v_trap/nintv); mvprintw(4,68,"%3d",rate.v_swtch/nintv); for(i=0; i<CPUSTATES; i++) { float f = stat1(i); if (i == 0) { /* US+NI */ i++; f += stat1(i); } mvprintw(4+i,68,"%3.0f",f); } mvprintw(21,30,"%4d",rate.v_pswpin/nintv); mvprintw(22,30,"%4d",rate.v_pswpout/nintv); mvprintw(21,68,"%4d",rate.v_swpin/nintv); mvprintw(22,68,"%4d",rate.v_swpout/nintv); move(0,0); refresh(); nintv = 1; sleep(iter); goto loop; /*NOTREACHED*/ } double stat1(row) { double t; register i; t = 0; for(i=0; i<CPUSTATES; i++) t += s.time[i]; if(t == 0.) t = 1.; return(s.time[row]*100./t); } set_display() { int column,i; initscr(); nonl(); clear(); mvaddstr(1,5,"Time:"); standout(); mvaddstr(0,(40-strlen(MYNAME)/2),MYNAME); standend(); mvaddstr(1,60,"Clock Revs:"); mvaddstr(3,5,"Procs:"); mvaddstr(3,34,"Virtual Mem:"); mvaddstr(3,60,"CPU:"); mvaddstr(4,5,"running:"); mvaddstr(4,34,"active:"); mvaddstr(4,60,"ctxsw :"); mvaddstr(5,5,"blocked:"); mvaddstr(5,34,"free :"); mvaddstr(5,60,"user :"); mvaddstr(6,5,"waiting:"); mvaddstr(6,60,"system:"); mvaddstr(7,60,"idle :"); mvaddstr(9,5,"Paging:"); mvaddstr(9,41,"(daemon)"); mvaddstr(10,10,"reclaims :"); mvaddstr(10,27,"pgins :"); mvaddstr(10,41,"scanned:"); mvaddstr(10,57,"deficit :"); mvaddstr(11,10,"free list:"); mvaddstr(11,27,"pgouts:"); mvaddstr(11,41,"freed :"); mvaddstr(13,5,"Faults:"); mvaddstr(14,10,"disk:"); column = 21; for(i = 0; i < DK_NDRIVE; i++) { mvprintw(14,column,"%2s%d",dr_name[i],dr_unit[i]); column += 9; } mvaddstr(17,10,"device interrupts :"); mvaddstr(17,39,"pseudo-dma dz interrupts :"); mvaddstr(18,10,"system calls :"); mvaddstr(18,39,"traps :"); mvaddstr(20,5,"Swap:"); mvaddstr(21,10,"pages swapped in :"); mvaddstr(21,39,"number of swapins :"); mvaddstr(22,10,"pages swapped out :"); mvaddstr(22,39,"number of swapouts :"); refresh(); } /* * Read the drive names out of kmem. * ARGH ARGH ARGH ARGH !!!!!!!!!!!! */ #define steal(where, var) lseek(mf, where, 0); read(mf, &var, sizeof var); read_names() { struct mba_device mdev; register struct mba_device *mp; struct mba_driver mdrv; short two_char; char *cp = (char *) &two_char; struct uba_device udev, *up; struct uba_driver udrv; mp = (struct mba_device *) mynl[X_MBDINIT].n_value; up = (struct uba_device *) mynl[X_UBDINIT].n_value; if (up == 0) { fprintf(stderr, "iostat: Disk init info not in namelist\n"); exit(1); } if (mp) for (;;) { steal(mp++, mdev); if (mdev.mi_driver == 0) break; if (mdev.mi_dk < 0 || mdev.mi_alive == 0) continue; steal(mdev.mi_driver, mdrv); steal(mdrv.md_dname, two_char); sprintf(dr_name[mdev.mi_dk], "%c%c", cp[0], cp[1]); dr_unit[mdev.mi_dk] = mdev.mi_unit; } for (;;) { steal(up++, udev); if (udev.ui_driver == 0) break; if (udev.ui_dk < 0 || udev.ui_alive == 0) continue; steal(udev.ui_driver, udrv); steal(udrv.ud_dname, two_char); sprintf(dr_name[udev.ui_dk], "%c%c", cp[0], cp[1]); dr_unit[udev.ui_dk] = udev.ui_unit; } } cleanup() { sigignore(SIGINT); sigignore(SIGHUP); sigignore(SIGQUIT); mvcur(0,COLS-1,LINES-1,0); endwin(); exit(0); } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% N:sri-unix:-9900:0 Prolog library: helper.pl pereira:0 1983:8:15:0:52 001:9978 % File: Mec:Helper.Pl Author: R.A.O'Keefe Updated: 12 October 82 % Modified for TOPS-20 Fernando Pereira % This file contains two utilities: % try_hard_to_see(FileName, DeviceDefaults, ExtensionDefaults) % -- tries all the Extension and Device defaults (varying the % -- extensions first) until it succeeds in 'see'ing the file, % -- and fails if the file cannot be found. % give_help(Area, Topic) % -- looks for an assertion help_file(Area, FileName, Delimiter) % -- which you must supply. It then tries hard to open the file % -- with default extensions "", "HLP", and "PL" and with device % -- defaults "DSK", "MEC", "UTIL", and "PLL". If the file can't % -- be found, or if there is no help_file assertion, it gives an % -- apology. Otherwise it searches the file for the sequence % -- Delimiter Topic ".", e.g. #help. % It defines append, but its definition is the same as that in UTIL. %----------------------------------------------------------------------% :- public try_hard_to_see/3. :- public append/3. :- mode try_hard_to_see(+, +, +), expand_file(+, +, +, -), parse_file(-, -, -, -, ?, ?), file_component(-, ?, ?), letter_or_digit(+, -), normalise_file_component(+, +, -), supply_file_default(+, +, +, -), supply_file_default(+, +, -), pack_file_title(+, +, +, +, -), append(+, +, -). try_hard_to_see(Title, DeviceDefaults, ExtensionDefaults) :- nofileerrors, expand_file(Title, DeviceDefaults, ExtensionDefaults, FullTitle), see(FullTitle), !, fileerrors. try_hard_to_see(Title, _, _) :- fileerrors, write('** Can''t see '), writeq(Title), nl, fail. expand_file(Title, DeviceDefaults, ExtensionDefaults, FullTitle) :- atomic(Title), name(Title, TitleName), !, expand_file(TitleName, DeviceDefaults, ExtensionDefaults, FullTitle). expand_file(Title, DeviceDefaults, ExtensionDefaults, FullTitle) :- parse_file(Device, Directory, FileName, Extension, Title, []), normalise_file_component(Directory, 99999, TryDirectory), normalise_file_component(FileName, 99999, TryFileName), !, supply_file_default(Device, DeviceDefaults, 99999, TryDevice), supply_file_default(Extension, ExtensionDefaults, 99999, TryExtension), pack_file_title(TryDevice, TryDirectory, TryFileName, TryExtension, TryTitle), name(FullTitle, TryTitle). parse_file(Device, Directory, FileName, Extension) --> ( file_component(Device), ":" | { Device = "" } ), !, ( "<", file_component(Directory), ">" | { Directory = "" } ), !, file_component(FileName), ( ".", file_component(Extension) | { Extension = "" } ), !. file_component([LetDig|Rest]) --> [Char], { letter_or_digit(Char, LetDig) | [Char] = "-", LetDig = Char }, !, file_component(Rest). file_component([]) --> []. letter_or_digit(C, C) :- C >= "0", C =< "9", !. letter_or_digit(C, C) :- C >= "a", C =< "z", !. letter_or_digit(C, D) :- C >= "A", C =< "Z", D is C+("a"-"A"). normalise_file_component([], _, []) :- !. normalise_file_component(Default, Length, TryThis) :- atomic(Default), name(Default, DefaultName), !, normalise_file_component(DefaultName, Length, TryThis). normalise_file_component(_, 0, []) :- !. normalise_file_component([C|Rest], Length, [LetDig|More]) :- letter_or_digit(C, LetDig), !, Left is Length-1, normalise_file_component(Rest, Left, More). normalise_file_component([_|Rest], Length, TryThis) :- normalise_file_component(Rest, Length, TryThis). supply_file_default(Given, _, Length, TryThis) :- normalise_file_component(Given, Length, TryThis). supply_file_default([], Defaults, Length, TryThis) :- supply_file_default(Defaults, Length, TryThis). supply_file_default([Default|_], Length, TryThis) :- normalise_file_component(Default, Length, TryThis). supply_file_default([_|Defaults], Length, TryThis) :- !, supply_file_default(Defaults, Length, TryThis). pack_file_title([], [], FileName, Extension, Title) :- !, append(FileName, [46|Extension], Title). % 46 is "." pack_file_title([], Directory, FileName, Extension, Title) :- !, pack_file_title([], [], FileName, Extension, Tail), append([60|Directory],[62|Tail],Title). % 60 is "<" % 62 is ">" pack_file_title(Device, Directory, FileName, Extension, Title) :- pack_file_title([], Directory, FileName, Extension, Tail), append(Device, [58|Tail], Title). % 58 is ":" append([Head|Tail], List, [Head|More]) :- append(Tail, List, More). append([], List, List). %----------------------------------------------------------------------% :- public give_help/0, give_help/1, give_help/2. :- mode give_help, % list of areas. give_help(+), % list of topics in an area. give_help(+, +), % help on a specific topic. find_help(+, +), % find and type a topic of list read_after_delimiter(+), % find "#" or return end_of_file find_help(+, +, +), % check a list of topics among(+, +), % member on commas instead of dots type_until_delimiter(+). % display body of a Note. give_help :- write('Help is available in the following areas:'), nl, help_file(Area, _, _), <aeera au in b- ,ptt'en2 L)i