display.c revision 146344
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: head/contrib/top/display.c 146344 2005-05-18 13:48:33Z keramida $ 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" 3224139Sjoerg#include <ctype.h> 3324139Sjoerg#include <time.h> 3441943Sobrien#include <sys/time.h> 3524139Sjoerg 3624139Sjoerg#include "screen.h" /* interface to screen package */ 3724139Sjoerg#include "layout.h" /* defines for screen position layout */ 3824139Sjoerg#include "display.h" 3924139Sjoerg#include "top.h" 4024139Sjoerg#include "top.local.h" 4124139Sjoerg#include "boolean.h" 4224139Sjoerg#include "machine.h" /* we should eliminate this!!! */ 4324139Sjoerg#include "utils.h" 4424139Sjoerg 4524139Sjoerg#ifdef DEBUG 4624139SjoergFILE *debug; 4724139Sjoerg#endif 4824139Sjoerg 4924139Sjoerg/* imported from screen.c */ 5024139Sjoergextern int overstrike; 5124139Sjoerg 5224139Sjoergstatic int lmpid = 0; 5324139Sjoergstatic int last_hi = 0; /* used in u_process and u_endscreen */ 5424139Sjoergstatic int lastline = 0; 5524139Sjoergstatic int display_width = MAX_COLS; 5624139Sjoerg 5724139Sjoerg#define lineindex(l) ((l)*display_width) 5824139Sjoerg 5924139Sjoergchar *printable(); 6024139Sjoerg 6124139Sjoerg/* things initialized by display_init and used thruout */ 6224139Sjoerg 6324139Sjoerg/* buffer of proc information lines for display updating */ 6424139Sjoergchar *screenbuf = NULL; 6524139Sjoerg 6624139Sjoergstatic char **procstate_names; 6724139Sjoergstatic char **cpustate_names; 6824139Sjoergstatic char **memory_names; 6924142Sjoergstatic char **swap_names; 7024139Sjoerg 7124139Sjoergstatic int num_procstates; 7224139Sjoergstatic int num_cpustates; 7324139Sjoergstatic int num_memory; 7424142Sjoergstatic int num_swap; 7524139Sjoerg 7624139Sjoergstatic int *lprocstates; 7724139Sjoergstatic int *lcpustates; 7824139Sjoergstatic int *lmemory; 7924142Sjoergstatic int *lswap; 8024139Sjoerg 8124139Sjoergstatic int *cpustate_columns; 8224139Sjoergstatic int cpustate_total_length; 8324139Sjoerg 8424139Sjoergstatic enum { OFF, ON, ERASE } header_status = ON; 8524139Sjoerg 8624139Sjoergstatic int string_count(); 8724139Sjoergstatic void summary_format(); 8824139Sjoergstatic void line_update(); 8924139Sjoerg 9024139Sjoergint display_resize() 9124139Sjoerg 9224139Sjoerg{ 9324139Sjoerg register int lines; 9424139Sjoerg 9524139Sjoerg /* first, deallocate any previous buffer that may have been there */ 9624139Sjoerg if (screenbuf != NULL) 9724139Sjoerg { 9824139Sjoerg free(screenbuf); 9924139Sjoerg } 10024139Sjoerg 10124139Sjoerg /* calculate the current dimensions */ 10224139Sjoerg /* if operating in "dumb" mode, we only need one line */ 10324139Sjoerg lines = smart_terminal ? screen_length - Header_lines : 1; 10424139Sjoerg 105101692Sdwmalone if (lines < 0) 106101692Sdwmalone lines = 0; 10724139Sjoerg /* we don't want more than MAX_COLS columns, since the machine-dependent 10824139Sjoerg modules make static allocations based on MAX_COLS and we don't want 10924139Sjoerg to run off the end of their buffers */ 11024139Sjoerg display_width = screen_width; 11124139Sjoerg if (display_width >= MAX_COLS) 11224139Sjoerg { 11324139Sjoerg display_width = MAX_COLS - 1; 11424139Sjoerg } 11524139Sjoerg 11624139Sjoerg /* now, allocate space for the screen buffer */ 11724139Sjoerg screenbuf = (char *)malloc(lines * display_width); 11824139Sjoerg if (screenbuf == (char *)NULL) 11924139Sjoerg { 12024139Sjoerg /* oops! */ 12124139Sjoerg return(-1); 12224139Sjoerg } 12324139Sjoerg 12424139Sjoerg /* return number of lines available */ 12524139Sjoerg /* for dumb terminals, pretend like we can show any amount */ 12624139Sjoerg return(smart_terminal ? lines : Largest); 12724139Sjoerg} 12824139Sjoerg 12924139Sjoergint display_init(statics) 13024139Sjoerg 13124139Sjoergstruct statics *statics; 13224139Sjoerg 13324139Sjoerg{ 13424139Sjoerg register int lines; 13524139Sjoerg register char **pp; 13624139Sjoerg register int *ip; 13724139Sjoerg register int i; 13824139Sjoerg 13924139Sjoerg /* call resize to do the dirty work */ 14024139Sjoerg lines = display_resize(); 14124139Sjoerg 14224139Sjoerg /* only do the rest if we need to */ 14324139Sjoerg if (lines > -1) 14424139Sjoerg { 14524139Sjoerg /* save pointers and allocate space for names */ 14624139Sjoerg procstate_names = statics->procstate_names; 14724139Sjoerg num_procstates = string_count(procstate_names); 14824139Sjoerg lprocstates = (int *)malloc(num_procstates * sizeof(int)); 14924139Sjoerg 15024139Sjoerg cpustate_names = statics->cpustate_names; 15124142Sjoerg 15224142Sjoerg swap_names = statics->swap_names; 15324142Sjoerg num_swap = string_count(swap_names); 15424142Sjoerg lswap = (int *)malloc(num_swap * sizeof(int)); 15524139Sjoerg num_cpustates = string_count(cpustate_names); 15624139Sjoerg lcpustates = (int *)malloc(num_cpustates * sizeof(int)); 15724139Sjoerg cpustate_columns = (int *)malloc(num_cpustates * sizeof(int)); 15824139Sjoerg 15924139Sjoerg memory_names = statics->memory_names; 16024139Sjoerg num_memory = string_count(memory_names); 16124139Sjoerg lmemory = (int *)malloc(num_memory * sizeof(int)); 16224139Sjoerg 16324139Sjoerg /* calculate starting columns where needed */ 16424139Sjoerg cpustate_total_length = 0; 16524139Sjoerg pp = cpustate_names; 16624139Sjoerg ip = cpustate_columns; 16724139Sjoerg while (*pp != NULL) 16824139Sjoerg { 16989758Sdwmalone *ip++ = cpustate_total_length; 17024139Sjoerg if ((i = strlen(*pp++)) > 0) 17124139Sjoerg { 17224139Sjoerg cpustate_total_length += i + 8; 17324139Sjoerg } 17424139Sjoerg } 17524139Sjoerg } 17624139Sjoerg 17724139Sjoerg /* return number of lines available */ 17824139Sjoerg return(lines); 17924139Sjoerg} 18024139Sjoerg 18124139Sjoergi_loadave(mpid, avenrun) 18224139Sjoerg 18324139Sjoergint mpid; 18424139Sjoergdouble *avenrun; 18524139Sjoerg 18624139Sjoerg{ 18724139Sjoerg register int i; 18824139Sjoerg 18924139Sjoerg /* i_loadave also clears the screen, since it is first */ 19024139Sjoerg clear(); 19124139Sjoerg 19224139Sjoerg /* mpid == -1 implies this system doesn't have an _mpid */ 19324139Sjoerg if (mpid != -1) 19424139Sjoerg { 19524139Sjoerg printf("last pid: %5d; ", mpid); 19624139Sjoerg } 19724139Sjoerg 19824139Sjoerg printf("load averages"); 19924139Sjoerg 20024139Sjoerg for (i = 0; i < 3; i++) 20124139Sjoerg { 20224139Sjoerg printf("%c %5.2f", 20324139Sjoerg i == 0 ? ':' : ',', 20424139Sjoerg avenrun[i]); 20524139Sjoerg } 20624139Sjoerg lmpid = mpid; 20724139Sjoerg} 20824139Sjoerg 20924139Sjoergu_loadave(mpid, avenrun) 21024139Sjoerg 21124139Sjoergint mpid; 21224139Sjoergdouble *avenrun; 21324139Sjoerg 21424139Sjoerg{ 21524139Sjoerg register int i; 21624139Sjoerg 21724139Sjoerg if (mpid != -1) 21824139Sjoerg { 21924139Sjoerg /* change screen only when value has really changed */ 22024139Sjoerg if (mpid != lmpid) 22124139Sjoerg { 22224139Sjoerg Move_to(x_lastpid, y_lastpid); 22324139Sjoerg printf("%5d", mpid); 22424139Sjoerg lmpid = mpid; 22524139Sjoerg } 22624139Sjoerg 22724139Sjoerg /* i remembers x coordinate to move to */ 22824139Sjoerg i = x_loadave; 22924139Sjoerg } 23024139Sjoerg else 23124139Sjoerg { 23224139Sjoerg i = x_loadave_nompid; 23324139Sjoerg } 23424139Sjoerg 23524139Sjoerg /* move into position for load averages */ 23624139Sjoerg Move_to(i, y_loadave); 23724139Sjoerg 23824139Sjoerg /* display new load averages */ 23924139Sjoerg /* we should optimize this and only display changes */ 24024139Sjoerg for (i = 0; i < 3; i++) 24124139Sjoerg { 24224139Sjoerg printf("%s%5.2f", 24324139Sjoerg i == 0 ? "" : ", ", 24424139Sjoerg avenrun[i]); 24524139Sjoerg } 24624139Sjoerg} 24724139Sjoerg 24824139Sjoergi_timeofday(tod) 24924139Sjoerg 25024139Sjoergtime_t *tod; 25124139Sjoerg 25224139Sjoerg{ 25324139Sjoerg /* 25424139Sjoerg * Display the current time. 25524139Sjoerg * "ctime" always returns a string that looks like this: 25624139Sjoerg * 25724139Sjoerg * Sun Sep 16 01:03:52 1973 25824139Sjoerg * 012345678901234567890123 25924139Sjoerg * 1 2 26024139Sjoerg * 26124139Sjoerg * We want indices 11 thru 18 (length 8). 26224139Sjoerg */ 26324139Sjoerg 26424139Sjoerg if (smart_terminal) 26524139Sjoerg { 26624139Sjoerg Move_to(screen_width - 8, 0); 26724139Sjoerg } 26824139Sjoerg else 26924139Sjoerg { 27024139Sjoerg fputs(" ", stdout); 27124139Sjoerg } 27224139Sjoerg#ifdef DEBUG 27324139Sjoerg { 27424139Sjoerg char *foo; 27524139Sjoerg foo = ctime(tod); 27624139Sjoerg fputs(foo, stdout); 27724139Sjoerg } 27824139Sjoerg#endif 27924139Sjoerg printf("%-8.8s\n", &(ctime(tod)[11])); 28024139Sjoerg lastline = 1; 28124139Sjoerg} 28224139Sjoerg 28324139Sjoergstatic int ltotal = 0; 28489758Sdwmalonestatic char procstates_buffer[MAX_COLS]; 28524139Sjoerg 28624139Sjoerg/* 28724139Sjoerg * *_procstates(total, brkdn, names) - print the process summary line 28824139Sjoerg * 28924139Sjoerg * Assumptions: cursor is at the beginning of the line on entry 29024139Sjoerg * lastline is valid 29124139Sjoerg */ 29224139Sjoerg 29324139Sjoergi_procstates(total, brkdn) 29424139Sjoerg 29524139Sjoergint total; 29624139Sjoergint *brkdn; 29724139Sjoerg 29824139Sjoerg{ 29924139Sjoerg register int i; 30024139Sjoerg 30124139Sjoerg /* write current number of processes and remember the value */ 30224139Sjoerg printf("%d processes:", total); 30324139Sjoerg ltotal = total; 30424139Sjoerg 30524139Sjoerg /* put out enough spaces to get to column 15 */ 30624139Sjoerg i = digits(total); 30724139Sjoerg while (i++ < 4) 30824139Sjoerg { 30924139Sjoerg putchar(' '); 31024139Sjoerg } 31124139Sjoerg 31224139Sjoerg /* format and print the process state summary */ 31324139Sjoerg summary_format(procstates_buffer, brkdn, procstate_names); 31424139Sjoerg fputs(procstates_buffer, stdout); 31524139Sjoerg 31624139Sjoerg /* save the numbers for next time */ 31724139Sjoerg memcpy(lprocstates, brkdn, num_procstates * sizeof(int)); 31824139Sjoerg} 31924139Sjoerg 32024139Sjoergu_procstates(total, brkdn) 32124139Sjoerg 32224139Sjoergint total; 32324139Sjoergint *brkdn; 32424139Sjoerg 32524139Sjoerg{ 32689758Sdwmalone static char new[MAX_COLS]; 32724139Sjoerg register int i; 32824139Sjoerg 32924139Sjoerg /* update number of processes only if it has changed */ 33024139Sjoerg if (ltotal != total) 33124139Sjoerg { 33224139Sjoerg /* move and overwrite */ 33324139Sjoerg#if (x_procstate == 0) 33424139Sjoerg Move_to(x_procstate, y_procstate); 33524139Sjoerg#else 33624139Sjoerg /* cursor is already there...no motion needed */ 33724139Sjoerg /* assert(lastline == 1); */ 33824139Sjoerg#endif 33924139Sjoerg printf("%d", total); 34024139Sjoerg 34124139Sjoerg /* if number of digits differs, rewrite the label */ 34224139Sjoerg if (digits(total) != digits(ltotal)) 34324139Sjoerg { 34424139Sjoerg fputs(" processes:", stdout); 34524139Sjoerg /* put out enough spaces to get to column 15 */ 34624139Sjoerg i = digits(total); 34724139Sjoerg while (i++ < 4) 34824139Sjoerg { 34924139Sjoerg putchar(' '); 35024139Sjoerg } 35124139Sjoerg /* cursor may end up right where we want it!!! */ 35224139Sjoerg } 35324139Sjoerg 35424139Sjoerg /* save new total */ 35524139Sjoerg ltotal = total; 35624139Sjoerg } 35724139Sjoerg 35824139Sjoerg /* see if any of the state numbers has changed */ 35924139Sjoerg if (memcmp(lprocstates, brkdn, num_procstates * sizeof(int)) != 0) 36024139Sjoerg { 36124139Sjoerg /* format and update the line */ 36224139Sjoerg summary_format(new, brkdn, procstate_names); 36324139Sjoerg line_update(procstates_buffer, new, x_brkdn, y_brkdn); 36424139Sjoerg memcpy(lprocstates, brkdn, num_procstates * sizeof(int)); 36524139Sjoerg } 36624139Sjoerg} 36724139Sjoerg 36824139Sjoerg/* 36924139Sjoerg * *_cpustates(states, names) - print the cpu state percentages 37024139Sjoerg * 37124139Sjoerg * Assumptions: cursor is on the PREVIOUS line 37224139Sjoerg */ 37324139Sjoerg 37424139Sjoergstatic int cpustates_column; 37524139Sjoerg 37624139Sjoerg/* cpustates_tag() calculates the correct tag to use to label the line */ 37724139Sjoerg 37824139Sjoergchar *cpustates_tag() 37924139Sjoerg 38024139Sjoerg{ 38124139Sjoerg register char *use; 38224139Sjoerg 38324139Sjoerg static char *short_tag = "CPU: "; 38424139Sjoerg static char *long_tag = "CPU states: "; 38524139Sjoerg 38624139Sjoerg /* if length + strlen(long_tag) >= screen_width, then we have to 38724139Sjoerg use the shorter tag (we subtract 2 to account for ": ") */ 38824139Sjoerg if (cpustate_total_length + (int)strlen(long_tag) - 2 >= screen_width) 38924139Sjoerg { 39024139Sjoerg use = short_tag; 39124139Sjoerg } 39224139Sjoerg else 39324139Sjoerg { 39424139Sjoerg use = long_tag; 39524139Sjoerg } 39624139Sjoerg 39724139Sjoerg /* set cpustates_column accordingly then return result */ 39824139Sjoerg cpustates_column = strlen(use); 39924139Sjoerg return(use); 40024139Sjoerg} 40124139Sjoerg 40224139Sjoergi_cpustates(states) 40324139Sjoerg 40424139Sjoergregister int *states; 40524139Sjoerg 40624139Sjoerg{ 40724139Sjoerg register int i = 0; 40824139Sjoerg register int value; 40924139Sjoerg register char **names = cpustate_names; 41024139Sjoerg register char *thisname; 41124139Sjoerg 41224139Sjoerg /* print tag and bump lastline */ 41324139Sjoerg printf("\n%s", cpustates_tag()); 41424139Sjoerg lastline++; 41524139Sjoerg 41624139Sjoerg /* now walk thru the names and print the line */ 41724139Sjoerg while ((thisname = *names++) != NULL) 41824139Sjoerg { 41924139Sjoerg if (*thisname != '\0') 42024139Sjoerg { 42124139Sjoerg /* retrieve the value and remember it */ 42224139Sjoerg value = *states++; 42324139Sjoerg 42424139Sjoerg /* if percentage is >= 1000, print it as 100% */ 42524139Sjoerg printf((value >= 1000 ? "%s%4.0f%% %s" : "%s%4.1f%% %s"), 42624139Sjoerg i++ == 0 ? "" : ", ", 42724139Sjoerg ((float)value)/10., 42824139Sjoerg thisname); 42924139Sjoerg } 43024139Sjoerg } 43124139Sjoerg 43224139Sjoerg /* copy over values into "last" array */ 43324139Sjoerg memcpy(lcpustates, states, num_cpustates * sizeof(int)); 43424139Sjoerg} 43524139Sjoerg 43624139Sjoergu_cpustates(states) 43724139Sjoerg 43824139Sjoergregister int *states; 43924139Sjoerg 44024139Sjoerg{ 44124139Sjoerg register int value; 44224139Sjoerg register char **names = cpustate_names; 44324139Sjoerg register char *thisname; 44424139Sjoerg register int *lp; 44524139Sjoerg register int *colp; 44624139Sjoerg 44724139Sjoerg Move_to(cpustates_column, y_cpustates); 44824139Sjoerg lastline = y_cpustates; 44924139Sjoerg lp = lcpustates; 45024139Sjoerg colp = cpustate_columns; 45124139Sjoerg 45224139Sjoerg /* we could be much more optimal about this */ 45324139Sjoerg while ((thisname = *names++) != NULL) 45424139Sjoerg { 45524139Sjoerg if (*thisname != '\0') 45624139Sjoerg { 45724139Sjoerg /* did the value change since last time? */ 45824139Sjoerg if (*lp != *states) 45924139Sjoerg { 46024139Sjoerg /* yes, move and change */ 46124139Sjoerg Move_to(cpustates_column + *colp, y_cpustates); 46224139Sjoerg lastline = y_cpustates; 46324139Sjoerg 46424139Sjoerg /* retrieve value and remember it */ 46524139Sjoerg value = *states; 46624139Sjoerg 46724139Sjoerg /* if percentage is >= 1000, print it as 100% */ 46824139Sjoerg printf((value >= 1000 ? "%4.0f" : "%4.1f"), 46924139Sjoerg ((double)value)/10.); 47024139Sjoerg 47124139Sjoerg /* remember it for next time */ 47289758Sdwmalone *lp = value; 47324139Sjoerg } 47424139Sjoerg } 47524139Sjoerg 47624139Sjoerg /* increment and move on */ 47724139Sjoerg lp++; 47824139Sjoerg states++; 47924139Sjoerg colp++; 48024139Sjoerg } 48124139Sjoerg} 48224139Sjoerg 48324139Sjoergz_cpustates() 48424139Sjoerg 48524139Sjoerg{ 48624139Sjoerg register int i = 0; 48724139Sjoerg register char **names = cpustate_names; 48824139Sjoerg register char *thisname; 48924139Sjoerg register int *lp; 49024139Sjoerg 49124139Sjoerg /* show tag and bump lastline */ 49224139Sjoerg printf("\n%s", cpustates_tag()); 49324139Sjoerg lastline++; 49424139Sjoerg 49524139Sjoerg while ((thisname = *names++) != NULL) 49624139Sjoerg { 49724139Sjoerg if (*thisname != '\0') 49824139Sjoerg { 49924139Sjoerg printf("%s %% %s", i++ == 0 ? "" : ", ", thisname); 50024139Sjoerg } 50124139Sjoerg } 50224139Sjoerg 50324139Sjoerg /* fill the "last" array with all -1s, to insure correct updating */ 50424139Sjoerg lp = lcpustates; 50524139Sjoerg i = num_cpustates; 50624139Sjoerg while (--i >= 0) 50724139Sjoerg { 50824139Sjoerg *lp++ = -1; 50924139Sjoerg } 51024139Sjoerg} 51124139Sjoerg 51224139Sjoerg/* 51324139Sjoerg * *_memory(stats) - print "Memory: " followed by the memory summary string 51424139Sjoerg * 51524139Sjoerg * Assumptions: cursor is on "lastline" 51624139Sjoerg * for i_memory ONLY: cursor is on the previous line 51724139Sjoerg */ 51824139Sjoerg 51924139Sjoergchar memory_buffer[MAX_COLS]; 52024139Sjoerg 52124139Sjoergi_memory(stats) 52224139Sjoerg 52324139Sjoergint *stats; 52424139Sjoerg 52524139Sjoerg{ 52624142Sjoerg fputs("\nMem: ", stdout); 52724139Sjoerg lastline++; 52824139Sjoerg 52924139Sjoerg /* format and print the memory summary */ 53024139Sjoerg summary_format(memory_buffer, stats, memory_names); 53124139Sjoerg fputs(memory_buffer, stdout); 53224139Sjoerg} 53324139Sjoerg 53424139Sjoergu_memory(stats) 53524139Sjoerg 53624139Sjoergint *stats; 53724139Sjoerg 53824139Sjoerg{ 53924139Sjoerg static char new[MAX_COLS]; 54024139Sjoerg 54124139Sjoerg /* format the new line */ 54224139Sjoerg summary_format(new, stats, memory_names); 54324139Sjoerg line_update(memory_buffer, new, x_mem, y_mem); 54424139Sjoerg} 54524139Sjoerg 54624139Sjoerg/* 54724142Sjoerg * *_swap(stats) - print "Swap: " followed by the swap summary string 54824142Sjoerg * 54924142Sjoerg * Assumptions: cursor is on "lastline" 55024142Sjoerg * for i_swap ONLY: cursor is on the previous line 55124142Sjoerg */ 55224142Sjoerg 55324142Sjoergchar swap_buffer[MAX_COLS]; 55424142Sjoerg 55524142Sjoergi_swap(stats) 55624142Sjoerg 55724142Sjoergint *stats; 55824142Sjoerg 55924142Sjoerg{ 56024142Sjoerg fputs("\nSwap: ", stdout); 56124142Sjoerg lastline++; 56224142Sjoerg 56324142Sjoerg /* format and print the swap summary */ 56424142Sjoerg summary_format(swap_buffer, stats, swap_names); 56524142Sjoerg fputs(swap_buffer, stdout); 56624142Sjoerg} 56724142Sjoerg 56824142Sjoergu_swap(stats) 56924142Sjoerg 57024142Sjoergint *stats; 57124142Sjoerg 57224142Sjoerg{ 57324142Sjoerg static char new[MAX_COLS]; 57424142Sjoerg 57524142Sjoerg /* format the new line */ 57624142Sjoerg summary_format(new, stats, swap_names); 57724142Sjoerg line_update(swap_buffer, new, x_swap, y_swap); 57824142Sjoerg} 57924142Sjoerg 58024142Sjoerg/* 58124139Sjoerg * *_message() - print the next pending message line, or erase the one 58224139Sjoerg * that is there. 58324139Sjoerg * 58424139Sjoerg * Note that u_message is (currently) the same as i_message. 58524139Sjoerg * 58624139Sjoerg * Assumptions: lastline is consistent 58724139Sjoerg */ 58824139Sjoerg 58924139Sjoerg/* 59024139Sjoerg * i_message is funny because it gets its message asynchronously (with 59124139Sjoerg * respect to screen updates). 59224139Sjoerg */ 59324139Sjoerg 59424139Sjoergstatic char next_msg[MAX_COLS + 5]; 59524139Sjoergstatic int msglen = 0; 59624139Sjoerg/* Invariant: msglen is always the length of the message currently displayed 59724139Sjoerg on the screen (even when next_msg doesn't contain that message). */ 59824139Sjoerg 59924139Sjoergi_message() 60024139Sjoerg 60124139Sjoerg{ 60224139Sjoerg while (lastline < y_message) 60324139Sjoerg { 60424139Sjoerg fputc('\n', stdout); 60524139Sjoerg lastline++; 60624139Sjoerg } 60724139Sjoerg if (next_msg[0] != '\0') 60824139Sjoerg { 60924139Sjoerg standout(next_msg); 61024139Sjoerg msglen = strlen(next_msg); 61124139Sjoerg next_msg[0] = '\0'; 61224139Sjoerg } 61324139Sjoerg else if (msglen > 0) 61424139Sjoerg { 61524139Sjoerg (void) clear_eol(msglen); 61624139Sjoerg msglen = 0; 61724139Sjoerg } 61824139Sjoerg} 61924139Sjoerg 62024139Sjoergu_message() 62124139Sjoerg 62224139Sjoerg{ 62324139Sjoerg i_message(); 62424139Sjoerg} 62524139Sjoerg 62624139Sjoergstatic int header_length; 62724139Sjoerg 62824139Sjoerg/* 629146344Skeramida * Trim a header string to the current display width and return a newly 630146344Skeramida * allocated area with the trimmed header. 631146344Skeramida */ 632146344Skeramida 633146344Skeramidachar * 634146344Skeramidatrim_header(text) 635146344Skeramida 636146344Skeramidachar *text; 637146344Skeramida 638146344Skeramida{ 639146344Skeramida char *s; 640146344Skeramida int width; 641146344Skeramida 642146344Skeramida s = NULL; 643146344Skeramida width = display_width; 644146344Skeramida header_length = strlen(text); 645146344Skeramida if (header_length >= width) { 646146344Skeramida s = malloc((width + 1) * sizeof(char)); 647146344Skeramida if (s == NULL) 648146344Skeramida return (NULL); 649146344Skeramida strncpy(s, text, width); 650146344Skeramida s[width] = '\0'; 651146344Skeramida } 652146344Skeramida return (s); 653146344Skeramida} 654146344Skeramida 655146344Skeramida/* 65624139Sjoerg * *_header(text) - print the header for the process area 65724139Sjoerg * 65824139Sjoerg * Assumptions: cursor is on the previous line and lastline is consistent 65924139Sjoerg */ 66024139Sjoerg 66124139Sjoergi_header(text) 66224139Sjoerg 66324139Sjoergchar *text; 66424139Sjoerg 66524139Sjoerg{ 666146344Skeramida char *s; 667146344Skeramida 668146344Skeramida s = trim_header(text); 669146344Skeramida if (s != NULL) 670146344Skeramida text = s; 671146344Skeramida 67224139Sjoerg if (header_status == ON) 67324139Sjoerg { 67424139Sjoerg putchar('\n'); 67524139Sjoerg fputs(text, stdout); 67624139Sjoerg lastline++; 67724139Sjoerg } 67824139Sjoerg else if (header_status == ERASE) 67924139Sjoerg { 68024139Sjoerg header_status = OFF; 68124139Sjoerg } 682146344Skeramida free(s); 68324139Sjoerg} 68424139Sjoerg 68524139Sjoerg/*ARGSUSED*/ 68624139Sjoergu_header(text) 68724139Sjoerg 68824139Sjoergchar *text; /* ignored */ 68924139Sjoerg 69024139Sjoerg{ 691146344Skeramida char *s; 692146344Skeramida 693146344Skeramida s = trim_header(text); 694146344Skeramida if (s != NULL) 695146344Skeramida text = s; 696146344Skeramida 69724139Sjoerg if (header_status == ERASE) 69824139Sjoerg { 69924139Sjoerg putchar('\n'); 70024139Sjoerg lastline++; 70124139Sjoerg clear_eol(header_length); 70224139Sjoerg header_status = OFF; 70324139Sjoerg } 704146344Skeramida free(s); 70524139Sjoerg} 70624139Sjoerg 70724139Sjoerg/* 70824139Sjoerg * *_process(line, thisline) - print one process line 70924139Sjoerg * 71024139Sjoerg * Assumptions: lastline is consistent 71124139Sjoerg */ 71224139Sjoerg 71324139Sjoergi_process(line, thisline) 71424139Sjoerg 71524139Sjoergint line; 71624139Sjoergchar *thisline; 71724139Sjoerg 71824139Sjoerg{ 71924139Sjoerg register char *p; 72024139Sjoerg register char *base; 72124139Sjoerg 72224139Sjoerg /* make sure we are on the correct line */ 72324139Sjoerg while (lastline < y_procs + line) 72424139Sjoerg { 72524139Sjoerg putchar('\n'); 72624139Sjoerg lastline++; 72724139Sjoerg } 72824139Sjoerg 72924139Sjoerg /* truncate the line to conform to our current screen width */ 73024139Sjoerg thisline[display_width] = '\0'; 73124139Sjoerg 73224139Sjoerg /* write the line out */ 73324139Sjoerg fputs(thisline, stdout); 73424139Sjoerg 73524139Sjoerg /* copy it in to our buffer */ 73624139Sjoerg base = smart_terminal ? screenbuf + lineindex(line) : screenbuf; 73724139Sjoerg p = strecpy(base, thisline); 73824139Sjoerg 73924139Sjoerg /* zero fill the rest of it */ 74024139Sjoerg memzero(p, display_width - (p - base)); 74124139Sjoerg} 74224139Sjoerg 74324139Sjoergu_process(line, newline) 74424139Sjoerg 74524139Sjoergint line; 74624139Sjoergchar *newline; 74724139Sjoerg 74824139Sjoerg{ 74924139Sjoerg register char *optr; 75024139Sjoerg register int screen_line = line + Header_lines; 75124139Sjoerg register char *bufferline; 75224139Sjoerg 75324139Sjoerg /* remember a pointer to the current line in the screen buffer */ 75424139Sjoerg bufferline = &screenbuf[lineindex(line)]; 75524139Sjoerg 75624139Sjoerg /* truncate the line to conform to our current screen width */ 75724139Sjoerg newline[display_width] = '\0'; 75824139Sjoerg 75924139Sjoerg /* is line higher than we went on the last display? */ 76024139Sjoerg if (line >= last_hi) 76124139Sjoerg { 76224139Sjoerg /* yes, just ignore screenbuf and write it out directly */ 76324139Sjoerg /* get positioned on the correct line */ 76424139Sjoerg if (screen_line - lastline == 1) 76524139Sjoerg { 76624139Sjoerg putchar('\n'); 76724139Sjoerg lastline++; 76824139Sjoerg } 76924139Sjoerg else 77024139Sjoerg { 77124139Sjoerg Move_to(0, screen_line); 77224139Sjoerg lastline = screen_line; 77324139Sjoerg } 77424139Sjoerg 77524139Sjoerg /* now write the line */ 77624139Sjoerg fputs(newline, stdout); 77724139Sjoerg 77824139Sjoerg /* copy it in to the buffer */ 77924139Sjoerg optr = strecpy(bufferline, newline); 78024139Sjoerg 78124139Sjoerg /* zero fill the rest of it */ 78224139Sjoerg memzero(optr, display_width - (optr - bufferline)); 78324139Sjoerg } 78424139Sjoerg else 78524139Sjoerg { 78624139Sjoerg line_update(bufferline, newline, 0, line + Header_lines); 78724139Sjoerg } 78824139Sjoerg} 78924139Sjoerg 79024139Sjoergu_endscreen(hi) 79124139Sjoerg 79224139Sjoergregister int hi; 79324139Sjoerg 79424139Sjoerg{ 79524139Sjoerg register int screen_line = hi + Header_lines; 79624139Sjoerg register int i; 79724139Sjoerg 79824139Sjoerg if (smart_terminal) 79924139Sjoerg { 80024139Sjoerg if (hi < last_hi) 80124139Sjoerg { 80224139Sjoerg /* need to blank the remainder of the screen */ 80324139Sjoerg /* but only if there is any screen left below this line */ 80424139Sjoerg if (lastline + 1 < screen_length) 80524139Sjoerg { 80624139Sjoerg /* efficiently move to the end of currently displayed info */ 80724139Sjoerg if (screen_line - lastline < 5) 80824139Sjoerg { 80924139Sjoerg while (lastline < screen_line) 81024139Sjoerg { 81124139Sjoerg putchar('\n'); 81224139Sjoerg lastline++; 81324139Sjoerg } 81424139Sjoerg } 81524139Sjoerg else 81624139Sjoerg { 81724139Sjoerg Move_to(0, screen_line); 81824139Sjoerg lastline = screen_line; 81924139Sjoerg } 82024139Sjoerg 82124139Sjoerg if (clear_to_end) 82224139Sjoerg { 82324139Sjoerg /* we can do this the easy way */ 82424139Sjoerg putcap(clear_to_end); 82524139Sjoerg } 82624139Sjoerg else 82724139Sjoerg { 82824139Sjoerg /* use clear_eol on each line */ 82924139Sjoerg i = hi; 83024139Sjoerg while ((void) clear_eol(strlen(&screenbuf[lineindex(i++)])), i < last_hi) 83124139Sjoerg { 83224139Sjoerg putchar('\n'); 83324139Sjoerg } 83424139Sjoerg } 83524139Sjoerg } 83624139Sjoerg } 83724139Sjoerg last_hi = hi; 83824139Sjoerg 83924139Sjoerg /* move the cursor to a pleasant place */ 84024139Sjoerg Move_to(x_idlecursor, y_idlecursor); 84124139Sjoerg lastline = y_idlecursor; 84224139Sjoerg } 84324139Sjoerg else 84424139Sjoerg { 84524139Sjoerg /* separate this display from the next with some vertical room */ 84624139Sjoerg fputs("\n\n", stdout); 84724139Sjoerg } 84824139Sjoerg} 84924139Sjoerg 85024139Sjoergdisplay_header(t) 85124139Sjoerg 85224139Sjoergint t; 85324139Sjoerg 85424139Sjoerg{ 85524139Sjoerg if (t) 85624139Sjoerg { 85724139Sjoerg header_status = ON; 85824139Sjoerg } 85924139Sjoerg else if (header_status == ON) 86024139Sjoerg { 86124139Sjoerg header_status = ERASE; 86224139Sjoerg } 86324139Sjoerg} 86424139Sjoerg 86524139Sjoerg/*VARARGS2*/ 86624139Sjoergnew_message(type, msgfmt, a1, a2, a3) 86724139Sjoerg 86824139Sjoergint type; 86924139Sjoergchar *msgfmt; 87024139Sjoergcaddr_t a1, a2, a3; 87124139Sjoerg 87224139Sjoerg{ 87324139Sjoerg register int i; 87424139Sjoerg 87524139Sjoerg /* first, format the message */ 87666641Simp (void) snprintf(next_msg, sizeof(next_msg), msgfmt, a1, a2, a3); 87724139Sjoerg 87824139Sjoerg if (msglen > 0) 87924139Sjoerg { 88024139Sjoerg /* message there already -- can we clear it? */ 88124139Sjoerg if (!overstrike) 88224139Sjoerg { 88324139Sjoerg /* yes -- write it and clear to end */ 88424139Sjoerg i = strlen(next_msg); 88524139Sjoerg if ((type & MT_delayed) == 0) 88624139Sjoerg { 88724139Sjoerg type & MT_standout ? standout(next_msg) : 88824139Sjoerg fputs(next_msg, stdout); 88924139Sjoerg (void) clear_eol(msglen - i); 89024139Sjoerg msglen = i; 89124139Sjoerg next_msg[0] = '\0'; 89224139Sjoerg } 89324139Sjoerg } 89424139Sjoerg } 89524139Sjoerg else 89624139Sjoerg { 89724139Sjoerg if ((type & MT_delayed) == 0) 89824139Sjoerg { 89924139Sjoerg type & MT_standout ? standout(next_msg) : fputs(next_msg, stdout); 90024139Sjoerg msglen = strlen(next_msg); 90124139Sjoerg next_msg[0] = '\0'; 90224139Sjoerg } 90324139Sjoerg } 90424139Sjoerg} 90524139Sjoerg 90624139Sjoergclear_message() 90724139Sjoerg 90824139Sjoerg{ 90924139Sjoerg if (clear_eol(msglen) == 1) 91024139Sjoerg { 91124139Sjoerg putchar('\r'); 91224139Sjoerg } 91324139Sjoerg} 91424139Sjoerg 91524139Sjoergreadline(buffer, size, numeric) 91624139Sjoerg 91724139Sjoergchar *buffer; 91824139Sjoergint size; 91924139Sjoergint numeric; 92024139Sjoerg 92124139Sjoerg{ 92224139Sjoerg register char *ptr = buffer; 92324139Sjoerg register char ch; 92424139Sjoerg register char cnt = 0; 92524139Sjoerg register char maxcnt = 0; 92624139Sjoerg 92724139Sjoerg /* allow room for null terminator */ 92824139Sjoerg size -= 1; 92924139Sjoerg 93024139Sjoerg /* read loop */ 93124139Sjoerg while ((fflush(stdout), read(0, ptr, 1) > 0)) 93224139Sjoerg { 93324139Sjoerg /* newline means we are done */ 93424142Sjoerg if ((ch = *ptr) == '\n' || ch == '\r') 93524139Sjoerg { 93624139Sjoerg break; 93724139Sjoerg } 93824139Sjoerg 93924139Sjoerg /* handle special editing characters */ 94024139Sjoerg if (ch == ch_kill) 94124139Sjoerg { 94224139Sjoerg /* kill line -- account for overstriking */ 94324139Sjoerg if (overstrike) 94424139Sjoerg { 94524139Sjoerg msglen += maxcnt; 94624139Sjoerg } 94724139Sjoerg 94824139Sjoerg /* return null string */ 94924139Sjoerg *buffer = '\0'; 95024139Sjoerg putchar('\r'); 95124139Sjoerg return(-1); 95224139Sjoerg } 95324139Sjoerg else if (ch == ch_erase) 95424139Sjoerg { 95524139Sjoerg /* erase previous character */ 95624139Sjoerg if (cnt <= 0) 95724139Sjoerg { 95824139Sjoerg /* none to erase! */ 95924139Sjoerg putchar('\7'); 96024139Sjoerg } 96124139Sjoerg else 96224139Sjoerg { 96324139Sjoerg fputs("\b \b", stdout); 96424139Sjoerg ptr--; 96524139Sjoerg cnt--; 96624139Sjoerg } 96724139Sjoerg } 96824139Sjoerg /* check for character validity and buffer overflow */ 96924139Sjoerg else if (cnt == size || (numeric && !isdigit(ch)) || 97024139Sjoerg !isprint(ch)) 97124139Sjoerg { 97224139Sjoerg /* not legal */ 97324139Sjoerg putchar('\7'); 97424139Sjoerg } 97524139Sjoerg else 97624139Sjoerg { 97724139Sjoerg /* echo it and store it in the buffer */ 97824139Sjoerg putchar(ch); 97924139Sjoerg ptr++; 98024139Sjoerg cnt++; 98124139Sjoerg if (cnt > maxcnt) 98224139Sjoerg { 98324139Sjoerg maxcnt = cnt; 98424139Sjoerg } 98524139Sjoerg } 98624139Sjoerg } 98724139Sjoerg 98824139Sjoerg /* all done -- null terminate the string */ 98924139Sjoerg *ptr = '\0'; 99024139Sjoerg 99124139Sjoerg /* account for the extra characters in the message area */ 99224139Sjoerg /* (if terminal overstrikes, remember the furthest they went) */ 99324139Sjoerg msglen += overstrike ? maxcnt : cnt; 99424139Sjoerg 99524139Sjoerg /* return either inputted number or string length */ 99624139Sjoerg putchar('\r'); 99724139Sjoerg return(cnt == 0 ? -1 : numeric ? atoi(buffer) : cnt); 99824139Sjoerg} 99924139Sjoerg 100024139Sjoerg/* internal support routines */ 100124139Sjoerg 100224139Sjoergstatic int string_count(pp) 100324139Sjoerg 100424139Sjoergregister char **pp; 100524139Sjoerg 100624139Sjoerg{ 100724139Sjoerg register int cnt; 100824139Sjoerg 100924139Sjoerg cnt = 0; 101024139Sjoerg while (*pp++ != NULL) 101124139Sjoerg { 101224139Sjoerg cnt++; 101324139Sjoerg } 101424139Sjoerg return(cnt); 101524139Sjoerg} 101624139Sjoerg 101724139Sjoergstatic void summary_format(str, numbers, names) 101824139Sjoerg 101924139Sjoergchar *str; 102024139Sjoergint *numbers; 102124139Sjoergregister char **names; 102224139Sjoerg 102324139Sjoerg{ 102424139Sjoerg register char *p; 102524139Sjoerg register int num; 102624139Sjoerg register char *thisname; 102724139Sjoerg register int useM = No; 102824139Sjoerg 102924139Sjoerg /* format each number followed by its string */ 103024139Sjoerg p = str; 103124139Sjoerg while ((thisname = *names++) != NULL) 103224139Sjoerg { 103324139Sjoerg /* get the number to format */ 103424139Sjoerg num = *numbers++; 103524139Sjoerg 103624139Sjoerg /* display only non-zero numbers */ 103724139Sjoerg if (num > 0) 103824139Sjoerg { 103924139Sjoerg /* is this number in kilobytes? */ 104024139Sjoerg if (thisname[0] == 'K') 104124139Sjoerg { 104224139Sjoerg /* yes: format it as a memory value */ 104324139Sjoerg p = strecpy(p, format_k(num)); 104424139Sjoerg 104524139Sjoerg /* skip over the K, since it was included by format_k */ 104624139Sjoerg p = strecpy(p, thisname+1); 104724139Sjoerg } 104824139Sjoerg else 104924139Sjoerg { 105024139Sjoerg p = strecpy(p, itoa(num)); 105124139Sjoerg p = strecpy(p, thisname); 105224139Sjoerg } 105324139Sjoerg } 105424139Sjoerg 105524139Sjoerg /* ignore negative numbers, but display corresponding string */ 105624139Sjoerg else if (num < 0) 105724139Sjoerg { 105824139Sjoerg p = strecpy(p, thisname); 105924139Sjoerg } 106024139Sjoerg } 106124139Sjoerg 106224139Sjoerg /* if the last two characters in the string are ", ", delete them */ 106324139Sjoerg p -= 2; 106424139Sjoerg if (p >= str && p[0] == ',' && p[1] == ' ') 106524139Sjoerg { 106624139Sjoerg *p = '\0'; 106724139Sjoerg } 106824139Sjoerg} 106924139Sjoerg 107024139Sjoergstatic void line_update(old, new, start, line) 107124139Sjoerg 107224139Sjoergregister char *old; 107324139Sjoergregister char *new; 107424139Sjoergint start; 107524139Sjoergint line; 107624139Sjoerg 107724139Sjoerg{ 107824139Sjoerg register int ch; 107924139Sjoerg register int diff; 108024139Sjoerg register int newcol = start + 1; 108124139Sjoerg register int lastcol = start; 108224139Sjoerg char cursor_on_line = No; 108324139Sjoerg char *current; 108424139Sjoerg 108524139Sjoerg /* compare the two strings and only rewrite what has changed */ 108624139Sjoerg current = old; 108724139Sjoerg#ifdef DEBUG 108824139Sjoerg fprintf(debug, "line_update, starting at %d\n", start); 108924139Sjoerg fputs(old, debug); 109024139Sjoerg fputc('\n', debug); 109124139Sjoerg fputs(new, debug); 109224139Sjoerg fputs("\n-\n", debug); 109324139Sjoerg#endif 109424139Sjoerg 109524139Sjoerg /* start things off on the right foot */ 109624139Sjoerg /* this is to make sure the invariants get set up right */ 109724139Sjoerg if ((ch = *new++) != *old) 109824139Sjoerg { 109924139Sjoerg if (line - lastline == 1 && start == 0) 110024139Sjoerg { 110124139Sjoerg putchar('\n'); 110224139Sjoerg } 110324139Sjoerg else 110424139Sjoerg { 110524139Sjoerg Move_to(start, line); 110624139Sjoerg } 110724139Sjoerg cursor_on_line = Yes; 110824139Sjoerg putchar(ch); 110924139Sjoerg *old = ch; 111024139Sjoerg lastcol = 1; 111124139Sjoerg } 111224139Sjoerg old++; 111324139Sjoerg 111424139Sjoerg /* 111524139Sjoerg * main loop -- check each character. If the old and new aren't the 111624139Sjoerg * same, then update the display. When the distance from the 111724139Sjoerg * current cursor position to the new change is small enough, 111824139Sjoerg * the characters that belong there are written to move the 111924139Sjoerg * cursor over. 112024139Sjoerg * 112124139Sjoerg * Invariants: 112224139Sjoerg * lastcol is the column where the cursor currently is sitting 112324139Sjoerg * (always one beyond the end of the last mismatch). 112424139Sjoerg */ 112524139Sjoerg do /* yes, a do...while */ 112624139Sjoerg { 112724139Sjoerg if ((ch = *new++) != *old) 112824139Sjoerg { 112924139Sjoerg /* new character is different from old */ 113024139Sjoerg /* make sure the cursor is on top of this character */ 113124139Sjoerg diff = newcol - lastcol; 113224139Sjoerg if (diff > 0) 113324139Sjoerg { 113424139Sjoerg /* some motion is required--figure out which is shorter */ 113524139Sjoerg if (diff < 6 && cursor_on_line) 113624139Sjoerg { 113724139Sjoerg /* overwrite old stuff--get it out of the old buffer */ 113824139Sjoerg printf("%.*s", diff, ¤t[lastcol-start]); 113924139Sjoerg } 114024139Sjoerg else 114124139Sjoerg { 114224139Sjoerg /* use cursor addressing */ 114324139Sjoerg Move_to(newcol, line); 114424139Sjoerg cursor_on_line = Yes; 114524139Sjoerg } 114624139Sjoerg /* remember where the cursor is */ 114724139Sjoerg lastcol = newcol + 1; 114824139Sjoerg } 114924139Sjoerg else 115024139Sjoerg { 115124139Sjoerg /* already there, update position */ 115224139Sjoerg lastcol++; 115324139Sjoerg } 115424139Sjoerg 115524139Sjoerg /* write what we need to */ 115624139Sjoerg if (ch == '\0') 115724139Sjoerg { 115824139Sjoerg /* at the end--terminate with a clear-to-end-of-line */ 115924139Sjoerg (void) clear_eol(strlen(old)); 116024139Sjoerg } 116124139Sjoerg else 116224139Sjoerg { 116324139Sjoerg /* write the new character */ 116424139Sjoerg putchar(ch); 116524139Sjoerg } 116624139Sjoerg /* put the new character in the screen buffer */ 116724139Sjoerg *old = ch; 116824139Sjoerg } 116924139Sjoerg 117024139Sjoerg /* update working column and screen buffer pointer */ 117124139Sjoerg newcol++; 117224139Sjoerg old++; 117324139Sjoerg 117424139Sjoerg } while (ch != '\0'); 117524139Sjoerg 117624139Sjoerg /* zero out the rest of the line buffer -- MUST BE DONE! */ 117724139Sjoerg diff = display_width - newcol; 117824139Sjoerg if (diff > 0) 117924139Sjoerg { 118024139Sjoerg memzero(old, diff); 118124139Sjoerg } 118224139Sjoerg 118324139Sjoerg /* remember where the current line is */ 118424139Sjoerg if (cursor_on_line) 118524139Sjoerg { 118624139Sjoerg lastline = line; 118724139Sjoerg } 118824139Sjoerg} 118924139Sjoerg 119024139Sjoerg/* 119124139Sjoerg * printable(str) - make the string pointed to by "str" into one that is 119224139Sjoerg * printable (i.e.: all ascii), by converting all non-printable 119324139Sjoerg * characters into '?'. Replacements are done in place and a pointer 119424139Sjoerg * to the original buffer is returned. 119524139Sjoerg */ 119624139Sjoerg 119724139Sjoergchar *printable(str) 119824139Sjoerg 119924139Sjoergchar *str; 120024139Sjoerg 120124139Sjoerg{ 120224139Sjoerg register char *ptr; 120324139Sjoerg register char ch; 120424139Sjoerg 120524139Sjoerg ptr = str; 120624139Sjoerg while ((ch = *ptr) != '\0') 120724139Sjoerg { 120824139Sjoerg if (!isprint(ch)) 120924139Sjoerg { 121024139Sjoerg *ptr = '?'; 121124139Sjoerg } 121224139Sjoerg ptr++; 121324139Sjoerg } 121424139Sjoerg return(str); 121524139Sjoerg} 121642447Sobrien 121742447Sobrieni_uptime(bt, tod) 121842447Sobrien 121942447Sobrienstruct timeval* bt; 122042447Sobrientime_t *tod; 122142447Sobrien 122242447Sobrien{ 122342447Sobrien time_t uptime; 122442447Sobrien int days, hrs, mins, secs; 122542447Sobrien 122642447Sobrien if (bt->tv_sec != -1) { 122742447Sobrien uptime = *tod - bt->tv_sec; 122842447Sobrien uptime += 30; 122942447Sobrien days = uptime / 86400; 123042447Sobrien uptime %= 86400; 123142447Sobrien hrs = uptime / 3600; 123242447Sobrien uptime %= 3600; 123342447Sobrien mins = uptime / 60; 123442447Sobrien secs = uptime % 60; 123542447Sobrien 123642447Sobrien /* 123742447Sobrien * Display the uptime. 123842447Sobrien */ 123942447Sobrien 124042447Sobrien if (smart_terminal) 124142447Sobrien { 124242447Sobrien Move_to((screen_width - 24) - (days > 9 ? 1 : 0), 0); 124342447Sobrien } 124442447Sobrien else 124542447Sobrien { 124642447Sobrien fputs(" ", stdout); 124742447Sobrien } 124842447Sobrien printf(" up %d+%02d:%02d:%02d", days, hrs, mins, secs); 124942447Sobrien } 125042447Sobrien} 1251