124139Sjoerg/* 224139Sjoerg * Top users/processes display for Unix 324139Sjoerg * Version 3 424139Sjoerg * 524139Sjoerg * This program may be freely redistributed, 624139Sjoerg * but this entire comment MUST remain intact. 724139Sjoerg * 824139Sjoerg * Copyright (c) 1984, 1989, William LeFebvre, Rice University 924139Sjoerg * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University 1066641Simp * 1166641Simp * $FreeBSD: stable/11/contrib/top/display.c 332948 2018-04-24 17:37:29Z lidl $ 1224139Sjoerg */ 1324139Sjoerg 1424139Sjoerg/* 1524139Sjoerg * This file contains the routines that display information on the screen. 1624139Sjoerg * Each section of the screen has two routines: one for initially writing 1724139Sjoerg * all constant and dynamic text, and one for only updating the text that 1824139Sjoerg * changes. The prefix "i_" is used on all the "initial" routines and the 1924139Sjoerg * prefix "u_" is used for all the "updating" routines. 2024139Sjoerg * 2124139Sjoerg * ASSUMPTIONS: 2224139Sjoerg * None of the "i_" routines use any of the termcap capabilities. 2324139Sjoerg * In this way, those routines can be safely used on terminals that 2424139Sjoerg * have minimal (or nonexistant) terminal capabilities. 2524139Sjoerg * 2624139Sjoerg * The routines are called in this order: *_loadave, i_timeofday, 2724139Sjoerg * *_procstates, *_cpustates, *_memory, *_message, *_header, 2824139Sjoerg * *_process, u_endscreen. 2924139Sjoerg */ 3024139Sjoerg 3124139Sjoerg#include "os.h" 32300395Sngie 33300395Sngie#include <sys/time.h> 34300395Sngie 35332948Slidl#include <curses.h> 3624139Sjoerg#include <ctype.h> 37332948Slidl#include <termcap.h> 3824139Sjoerg#include <time.h> 39300395Sngie#include <unistd.h> 4024139Sjoerg 4124139Sjoerg#include "screen.h" /* interface to screen package */ 4224139Sjoerg#include "layout.h" /* defines for screen position layout */ 4324139Sjoerg#include "display.h" 4424139Sjoerg#include "top.h" 4524139Sjoerg#include "top.local.h" 4624139Sjoerg#include "boolean.h" 4724139Sjoerg#include "machine.h" /* we should eliminate this!!! */ 4824139Sjoerg#include "utils.h" 4924139Sjoerg 5024139Sjoerg#ifdef DEBUG 5124139SjoergFILE *debug; 5224139Sjoerg#endif 5324139Sjoerg 5424139Sjoerg/* imported from screen.c */ 5524139Sjoergextern int overstrike; 5624139Sjoerg 5724139Sjoergstatic int lmpid = 0; 5824139Sjoergstatic int last_hi = 0; /* used in u_process and u_endscreen */ 5924139Sjoergstatic int lastline = 0; 6024139Sjoergstatic int display_width = MAX_COLS; 6124139Sjoerg 6224139Sjoerg#define lineindex(l) ((l)*display_width) 6324139Sjoerg 6424139Sjoerg 6524139Sjoerg/* things initialized by display_init and used thruout */ 6624139Sjoerg 6724139Sjoerg/* buffer of proc information lines for display updating */ 6824139Sjoergchar *screenbuf = NULL; 6924139Sjoerg 7024139Sjoergstatic char **procstate_names; 7124139Sjoergstatic char **cpustate_names; 7224139Sjoergstatic char **memory_names; 73237656Sjhbstatic char **arc_names; 74318449Sallanjudestatic char **carc_names; 7524142Sjoergstatic char **swap_names; 7624139Sjoerg 7724139Sjoergstatic int num_procstates; 7824139Sjoergstatic int num_cpustates; 7924139Sjoergstatic int num_memory; 8024142Sjoergstatic int num_swap; 8124139Sjoerg 8224139Sjoergstatic int *lprocstates; 8324139Sjoergstatic int *lcpustates; 8424139Sjoergstatic int *lmemory; 8524142Sjoergstatic int *lswap; 8624139Sjoerg 87175420Speterstatic int num_cpus; 8824139Sjoergstatic int *cpustate_columns; 8924139Sjoergstatic int cpustate_total_length; 90175420Speterstatic int cpustates_column; 9124139Sjoerg 9224139Sjoergstatic enum { OFF, ON, ERASE } header_status = ON; 9324139Sjoerg 9424139Sjoergstatic int string_count(); 9524139Sjoergstatic void summary_format(); 9624139Sjoergstatic void line_update(); 9724139Sjoerg 98175420Speterint x_lastpid = 10; 99175420Speterint y_lastpid = 0; 100175420Speterint x_loadave = 33; 101175420Speterint x_loadave_nompid = 15; 102175420Speterint y_loadave = 0; 103175420Speterint x_procstate = 0; 104175420Speterint y_procstate = 1; 105175420Speterint x_brkdn = 15; 106175420Speterint y_brkdn = 1; 107175420Speterint x_mem = 5; 108175420Speterint y_mem = 3; 109237656Sjhbint x_arc = 5; 110237656Sjhbint y_arc = 4; 111318449Sallanjudeint x_carc = 5; 112318449Sallanjudeint y_carc = 5; 113175420Speterint x_swap = 6; 114175420Speterint y_swap = 4; 115175420Speterint y_message = 5; 116175420Speterint x_header = 0; 117175420Speterint y_header = 6; 118175420Speterint x_idlecursor = 0; 119175420Speterint y_idlecursor = 5; 120175420Speterint y_procs = 7; 121175420Speter 122175420Speterint y_cpustates = 2; 123175420Speterint Header_lines = 7; 124175420Speter 12524139Sjoergint display_resize() 12624139Sjoerg 12724139Sjoerg{ 12824139Sjoerg register int lines; 12924139Sjoerg 13024139Sjoerg /* first, deallocate any previous buffer that may have been there */ 13124139Sjoerg if (screenbuf != NULL) 13224139Sjoerg { 13324139Sjoerg free(screenbuf); 13424139Sjoerg } 13524139Sjoerg 13624139Sjoerg /* calculate the current dimensions */ 13724139Sjoerg /* if operating in "dumb" mode, we only need one line */ 13824139Sjoerg lines = smart_terminal ? screen_length - Header_lines : 1; 13924139Sjoerg 140101692Sdwmalone if (lines < 0) 141101692Sdwmalone lines = 0; 14224139Sjoerg /* we don't want more than MAX_COLS columns, since the machine-dependent 14324139Sjoerg modules make static allocations based on MAX_COLS and we don't want 14424139Sjoerg to run off the end of their buffers */ 14524139Sjoerg display_width = screen_width; 14624139Sjoerg if (display_width >= MAX_COLS) 14724139Sjoerg { 14824139Sjoerg display_width = MAX_COLS - 1; 14924139Sjoerg } 15024139Sjoerg 15124139Sjoerg /* now, allocate space for the screen buffer */ 15224139Sjoerg screenbuf = (char *)malloc(lines * display_width); 15324139Sjoerg if (screenbuf == (char *)NULL) 15424139Sjoerg { 15524139Sjoerg /* oops! */ 15624139Sjoerg return(-1); 15724139Sjoerg } 15824139Sjoerg 15924139Sjoerg /* return number of lines available */ 16024139Sjoerg /* for dumb terminals, pretend like we can show any amount */ 16124139Sjoerg return(smart_terminal ? lines : Largest); 16224139Sjoerg} 16324139Sjoerg 164223936Sjhbint display_updatecpus(statics) 16524139Sjoerg 16624139Sjoergstruct statics *statics; 16724139Sjoerg 16824139Sjoerg{ 169224205Sjhb register int *lp; 17024139Sjoerg register int lines; 17124139Sjoerg register int i; 172223936Sjhb 17324139Sjoerg /* call resize to do the dirty work */ 17424139Sjoerg lines = display_resize(); 175224205Sjhb if (pcpu_stats) 176224205Sjhb num_cpus = statics->ncpus; 177224205Sjhb else 178224205Sjhb num_cpus = 1; 179175420Speter cpustates_column = 5; /* CPU: */ 180175420Speter if (num_cpus != 1) 181175420Speter cpustates_column += 2; /* CPU 0: */ 182175420Speter for (i = num_cpus; i > 9; i /= 10) 183175420Speter cpustates_column++; 18424139Sjoerg 185224205Sjhb /* fill the "last" array with all -1s, to insure correct updating */ 186224205Sjhb lp = lcpustates; 187224205Sjhb i = num_cpustates * num_cpus; 188224205Sjhb while (--i >= 0) 189224205Sjhb { 190224205Sjhb *lp++ = -1; 191224205Sjhb } 192224205Sjhb 193223936Sjhb return(lines); 194223936Sjhb} 195223936Sjhb 196223936Sjhbint display_init(statics) 197223936Sjhb 198223936Sjhbstruct statics *statics; 199223936Sjhb 200223936Sjhb{ 201223936Sjhb register int lines; 202223936Sjhb register char **pp; 203223936Sjhb register int *ip; 204223936Sjhb register int i; 205223936Sjhb 206223936Sjhb lines = display_updatecpus(statics); 207223936Sjhb 20824139Sjoerg /* only do the rest if we need to */ 20924139Sjoerg if (lines > -1) 21024139Sjoerg { 21124139Sjoerg /* save pointers and allocate space for names */ 21224139Sjoerg procstate_names = statics->procstate_names; 21324139Sjoerg num_procstates = string_count(procstate_names); 21424139Sjoerg lprocstates = (int *)malloc(num_procstates * sizeof(int)); 21524139Sjoerg 21624139Sjoerg cpustate_names = statics->cpustate_names; 21724142Sjoerg 21824142Sjoerg swap_names = statics->swap_names; 21924142Sjoerg num_swap = string_count(swap_names); 22024142Sjoerg lswap = (int *)malloc(num_swap * sizeof(int)); 22124139Sjoerg num_cpustates = string_count(cpustate_names); 222224205Sjhb lcpustates = (int *)malloc(num_cpustates * sizeof(int) * statics->ncpus); 22324139Sjoerg cpustate_columns = (int *)malloc(num_cpustates * sizeof(int)); 22424139Sjoerg 22524139Sjoerg memory_names = statics->memory_names; 22624139Sjoerg num_memory = string_count(memory_names); 22724139Sjoerg lmemory = (int *)malloc(num_memory * sizeof(int)); 22824139Sjoerg 229237656Sjhb arc_names = statics->arc_names; 230318449Sallanjude carc_names = statics->carc_names; 231237656Sjhb 23224139Sjoerg /* calculate starting columns where needed */ 23324139Sjoerg cpustate_total_length = 0; 23424139Sjoerg pp = cpustate_names; 23524139Sjoerg ip = cpustate_columns; 23624139Sjoerg while (*pp != NULL) 23724139Sjoerg { 23889758Sdwmalone *ip++ = cpustate_total_length; 23924139Sjoerg if ((i = strlen(*pp++)) > 0) 24024139Sjoerg { 24124139Sjoerg cpustate_total_length += i + 8; 24224139Sjoerg } 24324139Sjoerg } 24424139Sjoerg } 24524139Sjoerg 24624139Sjoerg /* return number of lines available */ 24724139Sjoerg return(lines); 24824139Sjoerg} 24924139Sjoerg 250300395Sngievoid 25124139Sjoergi_loadave(mpid, avenrun) 25224139Sjoerg 25324139Sjoergint mpid; 25424139Sjoergdouble *avenrun; 25524139Sjoerg 25624139Sjoerg{ 25724139Sjoerg register int i; 25824139Sjoerg 25924139Sjoerg /* i_loadave also clears the screen, since it is first */ 260332948Slidl top_clear(); 26124139Sjoerg 26224139Sjoerg /* mpid == -1 implies this system doesn't have an _mpid */ 26324139Sjoerg if (mpid != -1) 26424139Sjoerg { 26524139Sjoerg printf("last pid: %5d; ", mpid); 26624139Sjoerg } 26724139Sjoerg 26824139Sjoerg printf("load averages"); 26924139Sjoerg 27024139Sjoerg for (i = 0; i < 3; i++) 27124139Sjoerg { 27224139Sjoerg printf("%c %5.2f", 27324139Sjoerg i == 0 ? ':' : ',', 27424139Sjoerg avenrun[i]); 27524139Sjoerg } 27624139Sjoerg lmpid = mpid; 27724139Sjoerg} 27824139Sjoerg 279300395Sngievoid 28024139Sjoergu_loadave(mpid, avenrun) 28124139Sjoerg 28224139Sjoergint mpid; 28324139Sjoergdouble *avenrun; 28424139Sjoerg 28524139Sjoerg{ 28624139Sjoerg register int i; 28724139Sjoerg 28824139Sjoerg if (mpid != -1) 28924139Sjoerg { 29024139Sjoerg /* change screen only when value has really changed */ 29124139Sjoerg if (mpid != lmpid) 29224139Sjoerg { 29324139Sjoerg Move_to(x_lastpid, y_lastpid); 29424139Sjoerg printf("%5d", mpid); 29524139Sjoerg lmpid = mpid; 29624139Sjoerg } 29724139Sjoerg 29824139Sjoerg /* i remembers x coordinate to move to */ 29924139Sjoerg i = x_loadave; 30024139Sjoerg } 30124139Sjoerg else 30224139Sjoerg { 30324139Sjoerg i = x_loadave_nompid; 30424139Sjoerg } 30524139Sjoerg 30624139Sjoerg /* move into position for load averages */ 30724139Sjoerg Move_to(i, y_loadave); 30824139Sjoerg 30924139Sjoerg /* display new load averages */ 31024139Sjoerg /* we should optimize this and only display changes */ 31124139Sjoerg for (i = 0; i < 3; i++) 31224139Sjoerg { 31324139Sjoerg printf("%s%5.2f", 31424139Sjoerg i == 0 ? "" : ", ", 31524139Sjoerg avenrun[i]); 31624139Sjoerg } 31724139Sjoerg} 31824139Sjoerg 319300395Sngievoid 32024139Sjoergi_timeofday(tod) 32124139Sjoerg 32224139Sjoergtime_t *tod; 32324139Sjoerg 32424139Sjoerg{ 32524139Sjoerg /* 32624139Sjoerg * Display the current time. 32724139Sjoerg * "ctime" always returns a string that looks like this: 32824139Sjoerg * 32924139Sjoerg * Sun Sep 16 01:03:52 1973 33024139Sjoerg * 012345678901234567890123 33124139Sjoerg * 1 2 33224139Sjoerg * 33324139Sjoerg * We want indices 11 thru 18 (length 8). 33424139Sjoerg */ 33524139Sjoerg 33624139Sjoerg if (smart_terminal) 33724139Sjoerg { 33824139Sjoerg Move_to(screen_width - 8, 0); 33924139Sjoerg } 34024139Sjoerg else 34124139Sjoerg { 34224139Sjoerg fputs(" ", stdout); 34324139Sjoerg } 34424139Sjoerg#ifdef DEBUG 34524139Sjoerg { 34624139Sjoerg char *foo; 34724139Sjoerg foo = ctime(tod); 34824139Sjoerg fputs(foo, stdout); 34924139Sjoerg } 35024139Sjoerg#endif 35124139Sjoerg printf("%-8.8s\n", &(ctime(tod)[11])); 35224139Sjoerg lastline = 1; 35324139Sjoerg} 35424139Sjoerg 35524139Sjoergstatic int ltotal = 0; 35689758Sdwmalonestatic char procstates_buffer[MAX_COLS]; 35724139Sjoerg 35824139Sjoerg/* 35924139Sjoerg * *_procstates(total, brkdn, names) - print the process summary line 36024139Sjoerg * 36124139Sjoerg * Assumptions: cursor is at the beginning of the line on entry 36224139Sjoerg * lastline is valid 36324139Sjoerg */ 36424139Sjoerg 365300395Sngievoid 36624139Sjoergi_procstates(total, brkdn) 36724139Sjoerg 36824139Sjoergint total; 36924139Sjoergint *brkdn; 37024139Sjoerg 37124139Sjoerg{ 37224139Sjoerg register int i; 37324139Sjoerg 37424139Sjoerg /* write current number of processes and remember the value */ 37524139Sjoerg printf("%d processes:", total); 37624139Sjoerg ltotal = total; 37724139Sjoerg 37824139Sjoerg /* put out enough spaces to get to column 15 */ 37924139Sjoerg i = digits(total); 38024139Sjoerg while (i++ < 4) 38124139Sjoerg { 38224139Sjoerg putchar(' '); 38324139Sjoerg } 38424139Sjoerg 38524139Sjoerg /* format and print the process state summary */ 38624139Sjoerg summary_format(procstates_buffer, brkdn, procstate_names); 38724139Sjoerg fputs(procstates_buffer, stdout); 38824139Sjoerg 38924139Sjoerg /* save the numbers for next time */ 39024139Sjoerg memcpy(lprocstates, brkdn, num_procstates * sizeof(int)); 39124139Sjoerg} 39224139Sjoerg 393300395Sngievoid 39424139Sjoergu_procstates(total, brkdn) 39524139Sjoerg 39624139Sjoergint total; 39724139Sjoergint *brkdn; 39824139Sjoerg 39924139Sjoerg{ 40089758Sdwmalone static char new[MAX_COLS]; 40124139Sjoerg register int i; 40224139Sjoerg 40324139Sjoerg /* update number of processes only if it has changed */ 40424139Sjoerg if (ltotal != total) 40524139Sjoerg { 40624139Sjoerg /* move and overwrite */ 40724139Sjoerg#if (x_procstate == 0) 40824139Sjoerg Move_to(x_procstate, y_procstate); 40924139Sjoerg#else 41024139Sjoerg /* cursor is already there...no motion needed */ 41124139Sjoerg /* assert(lastline == 1); */ 41224139Sjoerg#endif 41324139Sjoerg printf("%d", total); 41424139Sjoerg 41524139Sjoerg /* if number of digits differs, rewrite the label */ 41624139Sjoerg if (digits(total) != digits(ltotal)) 41724139Sjoerg { 41824139Sjoerg fputs(" processes:", stdout); 41924139Sjoerg /* put out enough spaces to get to column 15 */ 42024139Sjoerg i = digits(total); 42124139Sjoerg while (i++ < 4) 42224139Sjoerg { 42324139Sjoerg putchar(' '); 42424139Sjoerg } 42524139Sjoerg /* cursor may end up right where we want it!!! */ 42624139Sjoerg } 42724139Sjoerg 42824139Sjoerg /* save new total */ 42924139Sjoerg ltotal = total; 43024139Sjoerg } 43124139Sjoerg 43224139Sjoerg /* see if any of the state numbers has changed */ 43324139Sjoerg if (memcmp(lprocstates, brkdn, num_procstates * sizeof(int)) != 0) 43424139Sjoerg { 43524139Sjoerg /* format and update the line */ 43624139Sjoerg summary_format(new, brkdn, procstate_names); 43724139Sjoerg line_update(procstates_buffer, new, x_brkdn, y_brkdn); 43824139Sjoerg memcpy(lprocstates, brkdn, num_procstates * sizeof(int)); 43924139Sjoerg } 44024139Sjoerg} 44124139Sjoerg 442175420Speter#ifdef no_more 44324139Sjoerg/* 44424139Sjoerg * *_cpustates(states, names) - print the cpu state percentages 44524139Sjoerg * 44624139Sjoerg * Assumptions: cursor is on the PREVIOUS line 44724139Sjoerg */ 44824139Sjoerg 44924139Sjoerg/* cpustates_tag() calculates the correct tag to use to label the line */ 45024139Sjoerg 45124139Sjoergchar *cpustates_tag() 45224139Sjoerg 45324139Sjoerg{ 45424139Sjoerg register char *use; 45524139Sjoerg 45624139Sjoerg static char *short_tag = "CPU: "; 45724139Sjoerg static char *long_tag = "CPU states: "; 45824139Sjoerg 45924139Sjoerg /* if length + strlen(long_tag) >= screen_width, then we have to 46024139Sjoerg use the shorter tag (we subtract 2 to account for ": ") */ 46124139Sjoerg if (cpustate_total_length + (int)strlen(long_tag) - 2 >= screen_width) 46224139Sjoerg { 46324139Sjoerg use = short_tag; 46424139Sjoerg } 46524139Sjoerg else 46624139Sjoerg { 46724139Sjoerg use = long_tag; 46824139Sjoerg } 46924139Sjoerg 47024139Sjoerg /* set cpustates_column accordingly then return result */ 47124139Sjoerg cpustates_column = strlen(use); 47224139Sjoerg return(use); 47324139Sjoerg} 474175420Speter#endif 47524139Sjoerg 476300395Sngievoid 47724139Sjoergi_cpustates(states) 47824139Sjoerg 479300395Sngieint *states; 48024139Sjoerg 48124139Sjoerg{ 48224139Sjoerg register int i = 0; 48324139Sjoerg register int value; 484175420Speter register char **names; 48524139Sjoerg register char *thisname; 486175420Speter int cpu; 48724139Sjoerg 488175420Speterfor (cpu = 0; cpu < num_cpus; cpu++) { 489175420Speter names = cpustate_names; 490175420Speter 49124139Sjoerg /* print tag and bump lastline */ 492175420Speter if (num_cpus == 1) 493175420Speter printf("\nCPU: "); 494218171Sjhb else { 495218171Sjhb value = printf("\nCPU %d: ", cpu); 496218171Sjhb while (value++ <= cpustates_column) 497218171Sjhb printf(" "); 498218171Sjhb } 49924139Sjoerg lastline++; 50024139Sjoerg 50124139Sjoerg /* now walk thru the names and print the line */ 50224139Sjoerg while ((thisname = *names++) != NULL) 50324139Sjoerg { 50424139Sjoerg if (*thisname != '\0') 50524139Sjoerg { 50624139Sjoerg /* retrieve the value and remember it */ 50724139Sjoerg value = *states++; 50824139Sjoerg 50924139Sjoerg /* if percentage is >= 1000, print it as 100% */ 51024139Sjoerg printf((value >= 1000 ? "%s%4.0f%% %s" : "%s%4.1f%% %s"), 511175420Speter (i++ % num_cpustates) == 0 ? "" : ", ", 51224139Sjoerg ((float)value)/10., 51324139Sjoerg thisname); 51424139Sjoerg } 51524139Sjoerg } 516175420Speter} 51724139Sjoerg 51824139Sjoerg /* copy over values into "last" array */ 519175420Speter memcpy(lcpustates, states, num_cpustates * sizeof(int) * num_cpus); 52024139Sjoerg} 52124139Sjoerg 522300395Sngievoid 52324139Sjoergu_cpustates(states) 52424139Sjoerg 525300395Sngieint *states; 52624139Sjoerg 52724139Sjoerg{ 52824139Sjoerg register int value; 529175420Speter register char **names; 53024139Sjoerg register char *thisname; 53124139Sjoerg register int *lp; 53224139Sjoerg register int *colp; 533175420Speter int cpu; 53424139Sjoerg 535175420Speterfor (cpu = 0; cpu < num_cpus; cpu++) { 536175420Speter names = cpustate_names; 537175420Speter 538175420Speter Move_to(cpustates_column, y_cpustates + cpu); 539175420Speter lastline = y_cpustates + cpu; 540175420Speter lp = lcpustates + (cpu * num_cpustates); 54124139Sjoerg colp = cpustate_columns; 54224139Sjoerg 54324139Sjoerg /* we could be much more optimal about this */ 54424139Sjoerg while ((thisname = *names++) != NULL) 54524139Sjoerg { 54624139Sjoerg if (*thisname != '\0') 54724139Sjoerg { 54824139Sjoerg /* did the value change since last time? */ 54924139Sjoerg if (*lp != *states) 55024139Sjoerg { 55124139Sjoerg /* yes, move and change */ 552175420Speter Move_to(cpustates_column + *colp, y_cpustates + cpu); 553175420Speter lastline = y_cpustates + cpu; 55424139Sjoerg 55524139Sjoerg /* retrieve value and remember it */ 55624139Sjoerg value = *states; 55724139Sjoerg 55824139Sjoerg /* if percentage is >= 1000, print it as 100% */ 55924139Sjoerg printf((value >= 1000 ? "%4.0f" : "%4.1f"), 56024139Sjoerg ((double)value)/10.); 56124139Sjoerg 56224139Sjoerg /* remember it for next time */ 56389758Sdwmalone *lp = value; 56424139Sjoerg } 56524139Sjoerg } 56624139Sjoerg 56724139Sjoerg /* increment and move on */ 56824139Sjoerg lp++; 56924139Sjoerg states++; 57024139Sjoerg colp++; 57124139Sjoerg } 57224139Sjoerg} 573175420Speter} 57424139Sjoerg 575300395Sngievoid 57624139Sjoergz_cpustates() 57724139Sjoerg 57824139Sjoerg{ 57924139Sjoerg register int i = 0; 580175420Speter register char **names; 58124139Sjoerg register char *thisname; 58224139Sjoerg register int *lp; 583218171Sjhb int cpu, value; 58424139Sjoerg 585175420Speterfor (cpu = 0; cpu < num_cpus; cpu++) { 586175420Speter names = cpustate_names; 587175420Speter 58824139Sjoerg /* show tag and bump lastline */ 589175420Speter if (num_cpus == 1) 590175420Speter printf("\nCPU: "); 591218171Sjhb else { 592218171Sjhb value = printf("\nCPU %d: ", cpu); 593218171Sjhb while (value++ <= cpustates_column) 594218171Sjhb printf(" "); 595218171Sjhb } 59624139Sjoerg lastline++; 59724139Sjoerg 59824139Sjoerg while ((thisname = *names++) != NULL) 59924139Sjoerg { 60024139Sjoerg if (*thisname != '\0') 60124139Sjoerg { 602175420Speter printf("%s %% %s", (i++ % num_cpustates) == 0 ? "" : ", ", thisname); 60324139Sjoerg } 60424139Sjoerg } 605175420Speter} 60624139Sjoerg 60724139Sjoerg /* fill the "last" array with all -1s, to insure correct updating */ 60824139Sjoerg lp = lcpustates; 609175420Speter i = num_cpustates * num_cpus; 61024139Sjoerg while (--i >= 0) 61124139Sjoerg { 61224139Sjoerg *lp++ = -1; 61324139Sjoerg } 61424139Sjoerg} 61524139Sjoerg 61624139Sjoerg/* 61724139Sjoerg * *_memory(stats) - print "Memory: " followed by the memory summary string 61824139Sjoerg * 61924139Sjoerg * Assumptions: cursor is on "lastline" 62024139Sjoerg * for i_memory ONLY: cursor is on the previous line 62124139Sjoerg */ 62224139Sjoerg 62324139Sjoergchar memory_buffer[MAX_COLS]; 62424139Sjoerg 625300395Sngievoid 62624139Sjoergi_memory(stats) 62724139Sjoerg 62824139Sjoergint *stats; 62924139Sjoerg 63024139Sjoerg{ 63124142Sjoerg fputs("\nMem: ", stdout); 63224139Sjoerg lastline++; 63324139Sjoerg 63424139Sjoerg /* format and print the memory summary */ 63524139Sjoerg summary_format(memory_buffer, stats, memory_names); 63624139Sjoerg fputs(memory_buffer, stdout); 63724139Sjoerg} 63824139Sjoerg 639300395Sngievoid 64024139Sjoergu_memory(stats) 64124139Sjoerg 64224139Sjoergint *stats; 64324139Sjoerg 64424139Sjoerg{ 64524139Sjoerg static char new[MAX_COLS]; 64624139Sjoerg 64724139Sjoerg /* format the new line */ 64824139Sjoerg summary_format(new, stats, memory_names); 64924139Sjoerg line_update(memory_buffer, new, x_mem, y_mem); 65024139Sjoerg} 65124139Sjoerg 65224139Sjoerg/* 653237656Sjhb * *_arc(stats) - print "ARC: " followed by the ARC summary string 654237656Sjhb * 655237656Sjhb * Assumptions: cursor is on "lastline" 656237656Sjhb * for i_arc ONLY: cursor is on the previous line 657237656Sjhb */ 658237656Sjhbchar arc_buffer[MAX_COLS]; 659237656Sjhb 660300395Sngievoid 661237656Sjhbi_arc(stats) 662237656Sjhb 663237656Sjhbint *stats; 664237656Sjhb 665237656Sjhb{ 666237656Sjhb if (arc_names == NULL) 667300395Sngie return; 668237656Sjhb 669237656Sjhb fputs("\nARC: ", stdout); 670237656Sjhb lastline++; 671237656Sjhb 672237656Sjhb /* format and print the memory summary */ 673237656Sjhb summary_format(arc_buffer, stats, arc_names); 674237656Sjhb fputs(arc_buffer, stdout); 675237656Sjhb} 676237656Sjhb 677300395Sngievoid 678237656Sjhbu_arc(stats) 679237656Sjhb 680237656Sjhbint *stats; 681237656Sjhb 682237656Sjhb{ 683237656Sjhb static char new[MAX_COLS]; 684237656Sjhb 685237656Sjhb if (arc_names == NULL) 686300395Sngie return; 687237656Sjhb 688237656Sjhb /* format the new line */ 689237656Sjhb summary_format(new, stats, arc_names); 690237656Sjhb line_update(arc_buffer, new, x_arc, y_arc); 691237656Sjhb} 692237656Sjhb 693318449Sallanjude 694318449Sallanjude/* 695318449Sallanjude * *_carc(stats) - print "Compressed ARC: " followed by the summary string 696318449Sallanjude * 697318449Sallanjude * Assumptions: cursor is on "lastline" 698318449Sallanjude * for i_carc ONLY: cursor is on the previous line 699318449Sallanjude */ 700318449Sallanjudechar carc_buffer[MAX_COLS]; 701318449Sallanjude 702318449Sallanjudevoid 703318449Sallanjudei_carc(stats) 704318449Sallanjude 705318449Sallanjudeint *stats; 706318449Sallanjude 707318449Sallanjude{ 708318449Sallanjude if (carc_names == NULL) 709318449Sallanjude return; 710318449Sallanjude 711318449Sallanjude fputs("\n ", stdout); 712318449Sallanjude lastline++; 713318449Sallanjude 714318449Sallanjude /* format and print the memory summary */ 715318449Sallanjude summary_format(carc_buffer, stats, carc_names); 716318449Sallanjude fputs(carc_buffer, stdout); 717318449Sallanjude} 718318449Sallanjude 719318449Sallanjudevoid 720318449Sallanjudeu_carc(stats) 721318449Sallanjude 722318449Sallanjudeint *stats; 723318449Sallanjude 724318449Sallanjude{ 725318449Sallanjude static char new[MAX_COLS]; 726318449Sallanjude 727318449Sallanjude if (carc_names == NULL) 728318449Sallanjude return; 729318449Sallanjude 730318449Sallanjude /* format the new line */ 731318449Sallanjude summary_format(new, stats, carc_names); 732318449Sallanjude line_update(carc_buffer, new, x_carc, y_carc); 733318449Sallanjude} 734237656Sjhb 735237656Sjhb/* 73624142Sjoerg * *_swap(stats) - print "Swap: " followed by the swap summary string 73724142Sjoerg * 73824142Sjoerg * Assumptions: cursor is on "lastline" 73924142Sjoerg * for i_swap ONLY: cursor is on the previous line 74024142Sjoerg */ 74124142Sjoerg 74224142Sjoergchar swap_buffer[MAX_COLS]; 74324142Sjoerg 744300395Sngievoid 74524142Sjoergi_swap(stats) 74624142Sjoerg 74724142Sjoergint *stats; 74824142Sjoerg 74924142Sjoerg{ 75024142Sjoerg fputs("\nSwap: ", stdout); 75124142Sjoerg lastline++; 75224142Sjoerg 75324142Sjoerg /* format and print the swap summary */ 75424142Sjoerg summary_format(swap_buffer, stats, swap_names); 75524142Sjoerg fputs(swap_buffer, stdout); 75624142Sjoerg} 75724142Sjoerg 758300395Sngievoid 75924142Sjoergu_swap(stats) 76024142Sjoerg 76124142Sjoergint *stats; 76224142Sjoerg 76324142Sjoerg{ 76424142Sjoerg static char new[MAX_COLS]; 76524142Sjoerg 76624142Sjoerg /* format the new line */ 76724142Sjoerg summary_format(new, stats, swap_names); 76824142Sjoerg line_update(swap_buffer, new, x_swap, y_swap); 76924142Sjoerg} 77024142Sjoerg 77124142Sjoerg/* 77224139Sjoerg * *_message() - print the next pending message line, or erase the one 77324139Sjoerg * that is there. 77424139Sjoerg * 77524139Sjoerg * Note that u_message is (currently) the same as i_message. 77624139Sjoerg * 77724139Sjoerg * Assumptions: lastline is consistent 77824139Sjoerg */ 77924139Sjoerg 78024139Sjoerg/* 78124139Sjoerg * i_message is funny because it gets its message asynchronously (with 78224139Sjoerg * respect to screen updates). 78324139Sjoerg */ 78424139Sjoerg 78524139Sjoergstatic char next_msg[MAX_COLS + 5]; 78624139Sjoergstatic int msglen = 0; 78724139Sjoerg/* Invariant: msglen is always the length of the message currently displayed 78824139Sjoerg on the screen (even when next_msg doesn't contain that message). */ 78924139Sjoerg 790300395Sngievoid 79124139Sjoergi_message() 79224139Sjoerg 79324139Sjoerg{ 79424139Sjoerg while (lastline < y_message) 79524139Sjoerg { 79624139Sjoerg fputc('\n', stdout); 79724139Sjoerg lastline++; 79824139Sjoerg } 79924139Sjoerg if (next_msg[0] != '\0') 80024139Sjoerg { 801332948Slidl top_standout(next_msg); 80224139Sjoerg msglen = strlen(next_msg); 80324139Sjoerg next_msg[0] = '\0'; 80424139Sjoerg } 80524139Sjoerg else if (msglen > 0) 80624139Sjoerg { 80724139Sjoerg (void) clear_eol(msglen); 80824139Sjoerg msglen = 0; 80924139Sjoerg } 81024139Sjoerg} 81124139Sjoerg 812300395Sngievoid 81324139Sjoergu_message() 81424139Sjoerg 81524139Sjoerg{ 81624139Sjoerg i_message(); 81724139Sjoerg} 81824139Sjoerg 81924139Sjoergstatic int header_length; 82024139Sjoerg 82124139Sjoerg/* 822146344Skeramida * Trim a header string to the current display width and return a newly 823146344Skeramida * allocated area with the trimmed header. 824146344Skeramida */ 825146344Skeramida 826146344Skeramidachar * 827146344Skeramidatrim_header(text) 828146344Skeramida 829146344Skeramidachar *text; 830146344Skeramida 831146344Skeramida{ 832146344Skeramida char *s; 833146344Skeramida int width; 834146344Skeramida 835146344Skeramida s = NULL; 836223342Sdelphij width = display_width; 837146344Skeramida header_length = strlen(text); 838146344Skeramida if (header_length >= width) { 839146344Skeramida s = malloc((width + 1) * sizeof(char)); 840146344Skeramida if (s == NULL) 841146344Skeramida return (NULL); 842146344Skeramida strncpy(s, text, width); 843146344Skeramida s[width] = '\0'; 844146344Skeramida } 845146344Skeramida return (s); 846146344Skeramida} 847146344Skeramida 848146344Skeramida/* 84924139Sjoerg * *_header(text) - print the header for the process area 85024139Sjoerg * 85124139Sjoerg * Assumptions: cursor is on the previous line and lastline is consistent 85224139Sjoerg */ 85324139Sjoerg 854300395Sngievoid 85524139Sjoergi_header(text) 85624139Sjoerg 85724139Sjoergchar *text; 85824139Sjoerg 85924139Sjoerg{ 860146344Skeramida char *s; 861146344Skeramida 862146344Skeramida s = trim_header(text); 863146344Skeramida if (s != NULL) 864146344Skeramida text = s; 865146344Skeramida 86624139Sjoerg if (header_status == ON) 86724139Sjoerg { 86824139Sjoerg putchar('\n'); 869223342Sdelphij fputs(text, stdout); 87024139Sjoerg lastline++; 87124139Sjoerg } 87224139Sjoerg else if (header_status == ERASE) 87324139Sjoerg { 87424139Sjoerg header_status = OFF; 87524139Sjoerg } 876146344Skeramida free(s); 87724139Sjoerg} 87824139Sjoerg 87924139Sjoerg/*ARGSUSED*/ 880300395Sngievoid 88124139Sjoergu_header(text) 88224139Sjoerg 883300395Sngiechar *text __unused; /* ignored */ 88424139Sjoerg 88524139Sjoerg{ 886146344Skeramida 88724139Sjoerg if (header_status == ERASE) 88824139Sjoerg { 88924139Sjoerg putchar('\n'); 89024139Sjoerg lastline++; 89124139Sjoerg clear_eol(header_length); 89224139Sjoerg header_status = OFF; 89324139Sjoerg } 89424139Sjoerg} 89524139Sjoerg 89624139Sjoerg/* 89724139Sjoerg * *_process(line, thisline) - print one process line 89824139Sjoerg * 89924139Sjoerg * Assumptions: lastline is consistent 90024139Sjoerg */ 90124139Sjoerg 902300395Sngievoid 90324139Sjoergi_process(line, thisline) 90424139Sjoerg 90524139Sjoergint line; 90624139Sjoergchar *thisline; 90724139Sjoerg 90824139Sjoerg{ 90924139Sjoerg register char *p; 91024139Sjoerg register char *base; 91124139Sjoerg 91224139Sjoerg /* make sure we are on the correct line */ 91324139Sjoerg while (lastline < y_procs + line) 91424139Sjoerg { 91524139Sjoerg putchar('\n'); 91624139Sjoerg lastline++; 91724139Sjoerg } 91824139Sjoerg 91924139Sjoerg /* truncate the line to conform to our current screen width */ 92024139Sjoerg thisline[display_width] = '\0'; 92124139Sjoerg 92224139Sjoerg /* write the line out */ 92324139Sjoerg fputs(thisline, stdout); 92424139Sjoerg 92524139Sjoerg /* copy it in to our buffer */ 92624139Sjoerg base = smart_terminal ? screenbuf + lineindex(line) : screenbuf; 92724139Sjoerg p = strecpy(base, thisline); 92824139Sjoerg 92924139Sjoerg /* zero fill the rest of it */ 93024139Sjoerg memzero(p, display_width - (p - base)); 93124139Sjoerg} 93224139Sjoerg 933300395Sngievoid 93424139Sjoergu_process(line, newline) 93524139Sjoerg 93624139Sjoergint line; 93724139Sjoergchar *newline; 93824139Sjoerg 93924139Sjoerg{ 94024139Sjoerg register char *optr; 94124139Sjoerg register int screen_line = line + Header_lines; 94224139Sjoerg register char *bufferline; 94324139Sjoerg 94424139Sjoerg /* remember a pointer to the current line in the screen buffer */ 94524139Sjoerg bufferline = &screenbuf[lineindex(line)]; 94624139Sjoerg 94724139Sjoerg /* truncate the line to conform to our current screen width */ 94824139Sjoerg newline[display_width] = '\0'; 94924139Sjoerg 95024139Sjoerg /* is line higher than we went on the last display? */ 95124139Sjoerg if (line >= last_hi) 95224139Sjoerg { 95324139Sjoerg /* yes, just ignore screenbuf and write it out directly */ 95424139Sjoerg /* get positioned on the correct line */ 95524139Sjoerg if (screen_line - lastline == 1) 95624139Sjoerg { 95724139Sjoerg putchar('\n'); 95824139Sjoerg lastline++; 95924139Sjoerg } 96024139Sjoerg else 96124139Sjoerg { 96224139Sjoerg Move_to(0, screen_line); 96324139Sjoerg lastline = screen_line; 96424139Sjoerg } 96524139Sjoerg 96624139Sjoerg /* now write the line */ 96724139Sjoerg fputs(newline, stdout); 96824139Sjoerg 96924139Sjoerg /* copy it in to the buffer */ 97024139Sjoerg optr = strecpy(bufferline, newline); 97124139Sjoerg 97224139Sjoerg /* zero fill the rest of it */ 97324139Sjoerg memzero(optr, display_width - (optr - bufferline)); 97424139Sjoerg } 97524139Sjoerg else 97624139Sjoerg { 97724139Sjoerg line_update(bufferline, newline, 0, line + Header_lines); 97824139Sjoerg } 97924139Sjoerg} 98024139Sjoerg 981300395Sngievoid 98224139Sjoergu_endscreen(hi) 98324139Sjoerg 984300395Sngieint hi; 98524139Sjoerg 98624139Sjoerg{ 98724139Sjoerg register int screen_line = hi + Header_lines; 98824139Sjoerg register int i; 98924139Sjoerg 99024139Sjoerg if (smart_terminal) 99124139Sjoerg { 99224139Sjoerg if (hi < last_hi) 99324139Sjoerg { 99424139Sjoerg /* need to blank the remainder of the screen */ 99524139Sjoerg /* but only if there is any screen left below this line */ 99624139Sjoerg if (lastline + 1 < screen_length) 99724139Sjoerg { 99824139Sjoerg /* efficiently move to the end of currently displayed info */ 99924139Sjoerg if (screen_line - lastline < 5) 100024139Sjoerg { 100124139Sjoerg while (lastline < screen_line) 100224139Sjoerg { 100324139Sjoerg putchar('\n'); 100424139Sjoerg lastline++; 100524139Sjoerg } 100624139Sjoerg } 100724139Sjoerg else 100824139Sjoerg { 100924139Sjoerg Move_to(0, screen_line); 101024139Sjoerg lastline = screen_line; 101124139Sjoerg } 101224139Sjoerg 101324139Sjoerg if (clear_to_end) 101424139Sjoerg { 101524139Sjoerg /* we can do this the easy way */ 101624139Sjoerg putcap(clear_to_end); 101724139Sjoerg } 101824139Sjoerg else 101924139Sjoerg { 102024139Sjoerg /* use clear_eol on each line */ 102124139Sjoerg i = hi; 102224139Sjoerg while ((void) clear_eol(strlen(&screenbuf[lineindex(i++)])), i < last_hi) 102324139Sjoerg { 102424139Sjoerg putchar('\n'); 102524139Sjoerg } 102624139Sjoerg } 102724139Sjoerg } 102824139Sjoerg } 102924139Sjoerg last_hi = hi; 103024139Sjoerg 103124139Sjoerg /* move the cursor to a pleasant place */ 103224139Sjoerg Move_to(x_idlecursor, y_idlecursor); 103324139Sjoerg lastline = y_idlecursor; 103424139Sjoerg } 103524139Sjoerg else 103624139Sjoerg { 103724139Sjoerg /* separate this display from the next with some vertical room */ 103824139Sjoerg fputs("\n\n", stdout); 103924139Sjoerg } 104024139Sjoerg} 104124139Sjoerg 1042300395Sngievoid 104324139Sjoergdisplay_header(t) 104424139Sjoerg 104524139Sjoergint t; 104624139Sjoerg 104724139Sjoerg{ 104824139Sjoerg if (t) 104924139Sjoerg { 105024139Sjoerg header_status = ON; 105124139Sjoerg } 105224139Sjoerg else if (header_status == ON) 105324139Sjoerg { 105424139Sjoerg header_status = ERASE; 105524139Sjoerg } 105624139Sjoerg} 105724139Sjoerg 105824139Sjoerg/*VARARGS2*/ 1059300395Sngievoid 106024139Sjoergnew_message(type, msgfmt, a1, a2, a3) 106124139Sjoerg 106224139Sjoergint type; 106324139Sjoergchar *msgfmt; 106424139Sjoergcaddr_t a1, a2, a3; 106524139Sjoerg 106624139Sjoerg{ 106724139Sjoerg register int i; 106824139Sjoerg 106924139Sjoerg /* first, format the message */ 107066641Simp (void) snprintf(next_msg, sizeof(next_msg), msgfmt, a1, a2, a3); 107124139Sjoerg 107224139Sjoerg if (msglen > 0) 107324139Sjoerg { 107424139Sjoerg /* message there already -- can we clear it? */ 107524139Sjoerg if (!overstrike) 107624139Sjoerg { 107724139Sjoerg /* yes -- write it and clear to end */ 107824139Sjoerg i = strlen(next_msg); 107924139Sjoerg if ((type & MT_delayed) == 0) 108024139Sjoerg { 1081332948Slidl type & MT_standout ? top_standout(next_msg) : 108224139Sjoerg fputs(next_msg, stdout); 108324139Sjoerg (void) clear_eol(msglen - i); 108424139Sjoerg msglen = i; 108524139Sjoerg next_msg[0] = '\0'; 108624139Sjoerg } 108724139Sjoerg } 108824139Sjoerg } 108924139Sjoerg else 109024139Sjoerg { 109124139Sjoerg if ((type & MT_delayed) == 0) 109224139Sjoerg { 1093332948Slidl type & MT_standout ? top_standout(next_msg) : fputs(next_msg, stdout); 109424139Sjoerg msglen = strlen(next_msg); 109524139Sjoerg next_msg[0] = '\0'; 109624139Sjoerg } 109724139Sjoerg } 109824139Sjoerg} 109924139Sjoerg 1100300395Sngievoid 110124139Sjoergclear_message() 110224139Sjoerg 110324139Sjoerg{ 110424139Sjoerg if (clear_eol(msglen) == 1) 110524139Sjoerg { 110624139Sjoerg putchar('\r'); 110724139Sjoerg } 110824139Sjoerg} 110924139Sjoerg 1110300395Sngieint 111124139Sjoergreadline(buffer, size, numeric) 111224139Sjoerg 111324139Sjoergchar *buffer; 111424139Sjoergint size; 111524139Sjoergint numeric; 111624139Sjoerg 111724139Sjoerg{ 111824139Sjoerg register char *ptr = buffer; 111924139Sjoerg register char ch; 112024139Sjoerg register char cnt = 0; 112124139Sjoerg register char maxcnt = 0; 112224139Sjoerg 112324139Sjoerg /* allow room for null terminator */ 112424139Sjoerg size -= 1; 112524139Sjoerg 112624139Sjoerg /* read loop */ 112724139Sjoerg while ((fflush(stdout), read(0, ptr, 1) > 0)) 112824139Sjoerg { 112924139Sjoerg /* newline means we are done */ 113024142Sjoerg if ((ch = *ptr) == '\n' || ch == '\r') 113124139Sjoerg { 113224139Sjoerg break; 113324139Sjoerg } 113424139Sjoerg 113524139Sjoerg /* handle special editing characters */ 113624139Sjoerg if (ch == ch_kill) 113724139Sjoerg { 113824139Sjoerg /* kill line -- account for overstriking */ 113924139Sjoerg if (overstrike) 114024139Sjoerg { 114124139Sjoerg msglen += maxcnt; 114224139Sjoerg } 114324139Sjoerg 114424139Sjoerg /* return null string */ 114524139Sjoerg *buffer = '\0'; 114624139Sjoerg putchar('\r'); 114724139Sjoerg return(-1); 114824139Sjoerg } 114924139Sjoerg else if (ch == ch_erase) 115024139Sjoerg { 115124139Sjoerg /* erase previous character */ 115224139Sjoerg if (cnt <= 0) 115324139Sjoerg { 115424139Sjoerg /* none to erase! */ 115524139Sjoerg putchar('\7'); 115624139Sjoerg } 115724139Sjoerg else 115824139Sjoerg { 115924139Sjoerg fputs("\b \b", stdout); 116024139Sjoerg ptr--; 116124139Sjoerg cnt--; 116224139Sjoerg } 116324139Sjoerg } 116424139Sjoerg /* check for character validity and buffer overflow */ 116524139Sjoerg else if (cnt == size || (numeric && !isdigit(ch)) || 116624139Sjoerg !isprint(ch)) 116724139Sjoerg { 116824139Sjoerg /* not legal */ 116924139Sjoerg putchar('\7'); 117024139Sjoerg } 117124139Sjoerg else 117224139Sjoerg { 117324139Sjoerg /* echo it and store it in the buffer */ 117424139Sjoerg putchar(ch); 117524139Sjoerg ptr++; 117624139Sjoerg cnt++; 117724139Sjoerg if (cnt > maxcnt) 117824139Sjoerg { 117924139Sjoerg maxcnt = cnt; 118024139Sjoerg } 118124139Sjoerg } 118224139Sjoerg } 118324139Sjoerg 118424139Sjoerg /* all done -- null terminate the string */ 118524139Sjoerg *ptr = '\0'; 118624139Sjoerg 118724139Sjoerg /* account for the extra characters in the message area */ 118824139Sjoerg /* (if terminal overstrikes, remember the furthest they went) */ 118924139Sjoerg msglen += overstrike ? maxcnt : cnt; 119024139Sjoerg 119124139Sjoerg /* return either inputted number or string length */ 119224139Sjoerg putchar('\r'); 119324139Sjoerg return(cnt == 0 ? -1 : numeric ? atoi(buffer) : cnt); 119424139Sjoerg} 119524139Sjoerg 119624139Sjoerg/* internal support routines */ 119724139Sjoerg 119824139Sjoergstatic int string_count(pp) 119924139Sjoerg 120024139Sjoergregister char **pp; 120124139Sjoerg 120224139Sjoerg{ 120324139Sjoerg register int cnt; 120424139Sjoerg 120524139Sjoerg cnt = 0; 120624139Sjoerg while (*pp++ != NULL) 120724139Sjoerg { 120824139Sjoerg cnt++; 120924139Sjoerg } 121024139Sjoerg return(cnt); 121124139Sjoerg} 121224139Sjoerg 121324139Sjoergstatic void summary_format(str, numbers, names) 121424139Sjoerg 121524139Sjoergchar *str; 121624139Sjoergint *numbers; 121724139Sjoergregister char **names; 121824139Sjoerg 121924139Sjoerg{ 122024139Sjoerg register char *p; 122124139Sjoerg register int num; 122224139Sjoerg register char *thisname; 122324139Sjoerg register int useM = No; 1224318449Sallanjude char rbuf[6]; 122524139Sjoerg 122624139Sjoerg /* format each number followed by its string */ 122724139Sjoerg p = str; 122824139Sjoerg while ((thisname = *names++) != NULL) 122924139Sjoerg { 123024139Sjoerg /* get the number to format */ 123124139Sjoerg num = *numbers++; 123224139Sjoerg 123324139Sjoerg /* display only non-zero numbers */ 123424139Sjoerg if (num > 0) 123524139Sjoerg { 123624139Sjoerg /* is this number in kilobytes? */ 123724139Sjoerg if (thisname[0] == 'K') 123824139Sjoerg { 123924139Sjoerg /* yes: format it as a memory value */ 124024139Sjoerg p = strecpy(p, format_k(num)); 124124139Sjoerg 124224139Sjoerg /* skip over the K, since it was included by format_k */ 124324139Sjoerg p = strecpy(p, thisname+1); 124424139Sjoerg } 1245318449Sallanjude /* is this number a ratio? */ 1246318449Sallanjude else if (thisname[0] == ':') 1247318449Sallanjude { 1248318449Sallanjude (void) snprintf(rbuf, sizeof(rbuf), "%.2f", 1249318449Sallanjude (float)*(numbers - 2) / (float)num); 1250318449Sallanjude p = strecpy(p, rbuf); 1251318449Sallanjude p = strecpy(p, thisname); 1252318449Sallanjude } 125324139Sjoerg else 125424139Sjoerg { 125524139Sjoerg p = strecpy(p, itoa(num)); 125624139Sjoerg p = strecpy(p, thisname); 125724139Sjoerg } 125824139Sjoerg } 125924139Sjoerg 126024139Sjoerg /* ignore negative numbers, but display corresponding string */ 126124139Sjoerg else if (num < 0) 126224139Sjoerg { 126324139Sjoerg p = strecpy(p, thisname); 126424139Sjoerg } 126524139Sjoerg } 126624139Sjoerg 126724139Sjoerg /* if the last two characters in the string are ", ", delete them */ 126824139Sjoerg p -= 2; 126924139Sjoerg if (p >= str && p[0] == ',' && p[1] == ' ') 127024139Sjoerg { 127124139Sjoerg *p = '\0'; 127224139Sjoerg } 127324139Sjoerg} 127424139Sjoerg 127524139Sjoergstatic void line_update(old, new, start, line) 127624139Sjoerg 127724139Sjoergregister char *old; 127824139Sjoergregister char *new; 127924139Sjoergint start; 128024139Sjoergint line; 128124139Sjoerg 128224139Sjoerg{ 128324139Sjoerg register int ch; 128424139Sjoerg register int diff; 128524139Sjoerg register int newcol = start + 1; 128624139Sjoerg register int lastcol = start; 128724139Sjoerg char cursor_on_line = No; 128824139Sjoerg char *current; 128924139Sjoerg 129024139Sjoerg /* compare the two strings and only rewrite what has changed */ 129124139Sjoerg current = old; 129224139Sjoerg#ifdef DEBUG 129324139Sjoerg fprintf(debug, "line_update, starting at %d\n", start); 129424139Sjoerg fputs(old, debug); 129524139Sjoerg fputc('\n', debug); 129624139Sjoerg fputs(new, debug); 129724139Sjoerg fputs("\n-\n", debug); 129824139Sjoerg#endif 129924139Sjoerg 130024139Sjoerg /* start things off on the right foot */ 130124139Sjoerg /* this is to make sure the invariants get set up right */ 130224139Sjoerg if ((ch = *new++) != *old) 130324139Sjoerg { 130424139Sjoerg if (line - lastline == 1 && start == 0) 130524139Sjoerg { 130624139Sjoerg putchar('\n'); 130724139Sjoerg } 130824139Sjoerg else 130924139Sjoerg { 131024139Sjoerg Move_to(start, line); 131124139Sjoerg } 131224139Sjoerg cursor_on_line = Yes; 131324139Sjoerg putchar(ch); 131424139Sjoerg *old = ch; 131524139Sjoerg lastcol = 1; 131624139Sjoerg } 131724139Sjoerg old++; 131824139Sjoerg 131924139Sjoerg /* 132024139Sjoerg * main loop -- check each character. If the old and new aren't the 132124139Sjoerg * same, then update the display. When the distance from the 132224139Sjoerg * current cursor position to the new change is small enough, 132324139Sjoerg * the characters that belong there are written to move the 132424139Sjoerg * cursor over. 132524139Sjoerg * 132624139Sjoerg * Invariants: 132724139Sjoerg * lastcol is the column where the cursor currently is sitting 132824139Sjoerg * (always one beyond the end of the last mismatch). 132924139Sjoerg */ 133024139Sjoerg do /* yes, a do...while */ 133124139Sjoerg { 133224139Sjoerg if ((ch = *new++) != *old) 133324139Sjoerg { 133424139Sjoerg /* new character is different from old */ 133524139Sjoerg /* make sure the cursor is on top of this character */ 133624139Sjoerg diff = newcol - lastcol; 133724139Sjoerg if (diff > 0) 133824139Sjoerg { 133924139Sjoerg /* some motion is required--figure out which is shorter */ 134024139Sjoerg if (diff < 6 && cursor_on_line) 134124139Sjoerg { 134224139Sjoerg /* overwrite old stuff--get it out of the old buffer */ 134324139Sjoerg printf("%.*s", diff, ¤t[lastcol-start]); 134424139Sjoerg } 134524139Sjoerg else 134624139Sjoerg { 134724139Sjoerg /* use cursor addressing */ 134824139Sjoerg Move_to(newcol, line); 134924139Sjoerg cursor_on_line = Yes; 135024139Sjoerg } 135124139Sjoerg /* remember where the cursor is */ 135224139Sjoerg lastcol = newcol + 1; 135324139Sjoerg } 135424139Sjoerg else 135524139Sjoerg { 135624139Sjoerg /* already there, update position */ 135724139Sjoerg lastcol++; 135824139Sjoerg } 135924139Sjoerg 136024139Sjoerg /* write what we need to */ 136124139Sjoerg if (ch == '\0') 136224139Sjoerg { 136324139Sjoerg /* at the end--terminate with a clear-to-end-of-line */ 136424139Sjoerg (void) clear_eol(strlen(old)); 136524139Sjoerg } 136624139Sjoerg else 136724139Sjoerg { 136824139Sjoerg /* write the new character */ 136924139Sjoerg putchar(ch); 137024139Sjoerg } 137124139Sjoerg /* put the new character in the screen buffer */ 137224139Sjoerg *old = ch; 137324139Sjoerg } 137424139Sjoerg 137524139Sjoerg /* update working column and screen buffer pointer */ 137624139Sjoerg newcol++; 137724139Sjoerg old++; 137824139Sjoerg 137924139Sjoerg } while (ch != '\0'); 138024139Sjoerg 138124139Sjoerg /* zero out the rest of the line buffer -- MUST BE DONE! */ 138224139Sjoerg diff = display_width - newcol; 138324139Sjoerg if (diff > 0) 138424139Sjoerg { 138524139Sjoerg memzero(old, diff); 138624139Sjoerg } 138724139Sjoerg 138824139Sjoerg /* remember where the current line is */ 138924139Sjoerg if (cursor_on_line) 139024139Sjoerg { 139124139Sjoerg lastline = line; 139224139Sjoerg } 139324139Sjoerg} 139424139Sjoerg 139524139Sjoerg/* 139624139Sjoerg * printable(str) - make the string pointed to by "str" into one that is 139724139Sjoerg * printable (i.e.: all ascii), by converting all non-printable 139824139Sjoerg * characters into '?'. Replacements are done in place and a pointer 139924139Sjoerg * to the original buffer is returned. 140024139Sjoerg */ 140124139Sjoerg 140224139Sjoergchar *printable(str) 140324139Sjoerg 140424139Sjoergchar *str; 140524139Sjoerg 140624139Sjoerg{ 140724139Sjoerg register char *ptr; 140824139Sjoerg register char ch; 140924139Sjoerg 141024139Sjoerg ptr = str; 141124139Sjoerg while ((ch = *ptr) != '\0') 141224139Sjoerg { 141324139Sjoerg if (!isprint(ch)) 141424139Sjoerg { 141524139Sjoerg *ptr = '?'; 141624139Sjoerg } 141724139Sjoerg ptr++; 141824139Sjoerg } 141924139Sjoerg return(str); 142024139Sjoerg} 142142447Sobrien 1422300395Sngievoid 142342447Sobrieni_uptime(bt, tod) 142442447Sobrien 142542447Sobrienstruct timeval* bt; 142642447Sobrientime_t *tod; 142742447Sobrien 142842447Sobrien{ 142942447Sobrien time_t uptime; 143042447Sobrien int days, hrs, mins, secs; 143142447Sobrien 143242447Sobrien if (bt->tv_sec != -1) { 143342447Sobrien uptime = *tod - bt->tv_sec; 143442447Sobrien days = uptime / 86400; 143542447Sobrien uptime %= 86400; 143642447Sobrien hrs = uptime / 3600; 143742447Sobrien uptime %= 3600; 143842447Sobrien mins = uptime / 60; 143942447Sobrien secs = uptime % 60; 144042447Sobrien 144142447Sobrien /* 144242447Sobrien * Display the uptime. 144342447Sobrien */ 144442447Sobrien 144542447Sobrien if (smart_terminal) 144642447Sobrien { 144742447Sobrien Move_to((screen_width - 24) - (days > 9 ? 1 : 0), 0); 144842447Sobrien } 144942447Sobrien else 145042447Sobrien { 145142447Sobrien fputs(" ", stdout); 145242447Sobrien } 145342447Sobrien printf(" up %d+%02d:%02d:%02d", days, hrs, mins, secs); 145442447Sobrien } 145542447Sobrien} 1456