1dc4f0af1Szrj /*
2dc4f0af1Szrj * Copyright (c) 1984 through 2008, William LeFebvre
3dc4f0af1Szrj * All rights reserved.
4dc4f0af1Szrj *
5dc4f0af1Szrj * Redistribution and use in source and binary forms, with or without
6dc4f0af1Szrj * modification, are permitted provided that the following conditions are met:
7dc4f0af1Szrj *
8dc4f0af1Szrj * * Redistributions of source code must retain the above copyright
9dc4f0af1Szrj * notice, this list of conditions and the following disclaimer.
10dc4f0af1Szrj *
11dc4f0af1Szrj * * Redistributions in binary form must reproduce the above
12dc4f0af1Szrj * copyright notice, this list of conditions and the following disclaimer
13dc4f0af1Szrj * in the documentation and/or other materials provided with the
14dc4f0af1Szrj * distribution.
15dc4f0af1Szrj *
16dc4f0af1Szrj * * Neither the name of William LeFebvre nor the names of other
17dc4f0af1Szrj * contributors may be used to endorse or promote products derived from
18dc4f0af1Szrj * this software without specific prior written permission.
19dc4f0af1Szrj *
20dc4f0af1Szrj * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21dc4f0af1Szrj * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22dc4f0af1Szrj * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23dc4f0af1Szrj * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24dc4f0af1Szrj * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25dc4f0af1Szrj * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26dc4f0af1Szrj * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27dc4f0af1Szrj * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28dc4f0af1Szrj * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29dc4f0af1Szrj * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30dc4f0af1Szrj * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31dc4f0af1Szrj */
32dc4f0af1Szrj
33dc4f0af1Szrj /*
34dc4f0af1Szrj * Top users/processes display for Unix
35dc4f0af1Szrj * Version 3
36dc4f0af1Szrj */
37dc4f0af1Szrj
38dc4f0af1Szrj /*
39dc4f0af1Szrj * This file contains the routines that display information on the screen.
40dc4f0af1Szrj * Each section of the screen has two routines: one for initially writing
41dc4f0af1Szrj * all constant and dynamic text, and one for only updating the text that
42dc4f0af1Szrj * changes. The prefix "i_" is used on all the "initial" routines and the
43dc4f0af1Szrj * prefix "u_" is used for all the "updating" routines.
44dc4f0af1Szrj *
45dc4f0af1Szrj * ASSUMPTIONS:
46dc4f0af1Szrj * None of the "i_" routines use any of the termcap capabilities.
47dc4f0af1Szrj * In this way, those routines can be safely used on terminals that
48dc4f0af1Szrj * have minimal (or nonexistant) terminal capabilities.
49dc4f0af1Szrj *
50dc4f0af1Szrj * The routines should be called in this order: *_loadave, *_uptime,
51dc4f0af1Szrj * i_timeofday, *_procstates, *_cpustates, *_memory, *_swap,
52dc4f0af1Szrj * *_message, *_header, *_process, *_endscreen.
53dc4f0af1Szrj */
54dc4f0af1Szrj
55dc4f0af1Szrj #include "os.h"
56dc4f0af1Szrj #include <ctype.h>
57dc4f0af1Szrj #include <stdarg.h>
58dc4f0af1Szrj #include <sys/types.h>
59dc4f0af1Szrj #include <sys/uio.h>
60dc4f0af1Szrj #include <unistd.h>
61dc4f0af1Szrj
62dc4f0af1Szrj #include "top.h"
63dc4f0af1Szrj #include "machine.h"
64dc4f0af1Szrj #include "screen.h" /* interface to screen package */
65dc4f0af1Szrj #include "layout.h" /* defines for screen position layout */
66dc4f0af1Szrj #include "display.h"
67dc4f0af1Szrj #include "boolean.h"
68dc4f0af1Szrj #include "utils.h"
69dc4f0af1Szrj
70dc4f0af1Szrj #ifdef ENABLE_COLOR
71dc4f0af1Szrj #include "color.h"
72dc4f0af1Szrj #endif
73dc4f0af1Szrj
74dc4f0af1Szrj #define CURSOR_COST 8
75dc4f0af1Szrj
76dc4f0af1Szrj #define MESSAGE_DISPLAY_TIME 5
77dc4f0af1Szrj
78dc4f0af1Szrj /* imported from screen.c */
79dc4f0af1Szrj extern int overstrike;
80dc4f0af1Szrj
81dc4f0af1Szrj static int lmpid = -1;
82dc4f0af1Szrj static int display_width = MAX_COLS;
83dc4f0af1Szrj
84dc4f0af1Szrj /* cursor positions of key points on the screen are maintained here */
85dc4f0af1Szrj /* layout.h has static definitions, but we may change our minds on some
86dc4f0af1Szrj of the positions as we make decisions about what needs to be displayed */
87dc4f0af1Szrj
88dc4f0af1Szrj static int x_lastpid = X_LASTPID;
89dc4f0af1Szrj static int y_lastpid = Y_LASTPID;
90dc4f0af1Szrj static int x_loadave = X_LOADAVE;
91dc4f0af1Szrj static int y_loadave = Y_LOADAVE;
92dc4f0af1Szrj static int x_minibar = X_MINIBAR;
93dc4f0af1Szrj static int y_minibar = Y_MINIBAR;
94dc4f0af1Szrj static int x_uptime = X_UPTIME;
95dc4f0af1Szrj static int y_uptime = Y_UPTIME;
96dc4f0af1Szrj static int x_procstate = X_PROCSTATE;
97dc4f0af1Szrj static int y_procstate = Y_PROCSTATE;
98dc4f0af1Szrj static int x_cpustates = X_CPUSTATES;
99dc4f0af1Szrj static int y_cpustates = Y_CPUSTATES;
100dc4f0af1Szrj static int x_kernel = X_KERNEL;
101dc4f0af1Szrj static int y_kernel = Y_KERNEL;
102dc4f0af1Szrj static int x_mem = X_MEM;
103dc4f0af1Szrj static int y_mem = Y_MEM;
104dc4f0af1Szrj static int x_swap = X_SWAP;
105dc4f0af1Szrj static int y_swap = Y_SWAP;
106dc4f0af1Szrj static int y_message = Y_MESSAGE;
107dc4f0af1Szrj static int x_header = X_HEADER;
108dc4f0af1Szrj static int y_header = Y_HEADER;
109dc4f0af1Szrj static int x_idlecursor = X_IDLECURSOR;
110dc4f0af1Szrj static int y_idlecursor = Y_IDLECURSOR;
111dc4f0af1Szrj static int y_procs = Y_PROCS;
112dc4f0af1Szrj
113dc4f0af1Szrj /* buffer and colormask that describes the content of the screen */
114dc4f0af1Szrj /* these are singly dimensioned arrays -- the row boundaries are
115dc4f0af1Szrj determined on the fly.
116dc4f0af1Szrj */
117dc4f0af1Szrj static char *screenbuf = NULL;
118dc4f0af1Szrj static char *colorbuf = NULL;
119dc4f0af1Szrj static char scratchbuf[MAX_COLS];
120dc4f0af1Szrj static int bufsize = 0;
121dc4f0af1Szrj
122dc4f0af1Szrj /* lineindex tells us where the beginning of a line is in the buffer */
123dc4f0af1Szrj #define lineindex(l) ((l)*MAX_COLS)
124dc4f0af1Szrj
125dc4f0af1Szrj /* screen's cursor */
126dc4f0af1Szrj static int curr_x, curr_y;
127dc4f0af1Szrj static int curr_color;
128dc4f0af1Szrj
129dc4f0af1Szrj /* virtual cursor */
130dc4f0af1Szrj static int virt_x, virt_y;
131dc4f0af1Szrj
132dc4f0af1Szrj static char **procstate_names;
133dc4f0af1Szrj static char **cpustate_names;
134dc4f0af1Szrj static char **memory_names;
135dc4f0af1Szrj static char **swap_names;
136dc4f0af1Szrj static char **kernel_names;
137dc4f0af1Szrj
138dc4f0af1Szrj static int num_procstates;
139dc4f0af1Szrj static int num_cpustates;
140dc4f0af1Szrj static int num_memory;
141dc4f0af1Szrj static int num_swap;
142dc4f0af1Szrj static int num_kernel;
143dc4f0af1Szrj
144dc4f0af1Szrj static int *lprocstates;
145dc4f0af1Szrj static int *lcpustates;
146dc4f0af1Szrj
147dc4f0af1Szrj static int *cpustate_columns;
148dc4f0af1Szrj static int cpustate_total_length;
149dc4f0af1Szrj
150dc4f0af1Szrj static int header_status = Yes;
151dc4f0af1Szrj
152dc4f0af1Szrj /* pending messages are stored in a circular buffer, where message_first
153dc4f0af1Szrj is the next one to display, and message_last is the last one
154dc4f0af1Szrj in the buffer. Counters wrap around at MAX_MESSAGES. The buffer is
155dc4f0af1Szrj empty when message_first == message_last and full when
156dc4f0af1Szrj message_last + 1 == message_first. The pointer message_current holds
157dc4f0af1Szrj the message currently being displayed, or "" if there is none.
158dc4f0af1Szrj */
159dc4f0af1Szrj #define MAX_MESSAGES 16
160dc4f0af1Szrj static char *message_buf[MAX_MESSAGES];
161dc4f0af1Szrj static int message_first = 0;
162dc4f0af1Szrj static int message_last = 0;
163dc4f0af1Szrj static struct timeval message_time = {0, 0};
164dc4f0af1Szrj static char *message_current = NULL;
165dc4f0af1Szrj static int message_length = 0;
166dc4f0af1Szrj static int message_hold = 1;
167dc4f0af1Szrj static int message_barrier = No;
168dc4f0af1Szrj
169dc4f0af1Szrj #ifdef ENABLE_COLOR
170dc4f0af1Szrj static int load_cidx[3];
171dc4f0af1Szrj static int header_cidx;
172dc4f0af1Szrj static int *cpustate_cidx;
173dc4f0af1Szrj static int *memory_cidx;
174dc4f0af1Szrj static int *swap_cidx;
175dc4f0af1Szrj static int *kernel_cidx;
176dc4f0af1Szrj #else
177dc4f0af1Szrj #define memory_cidx NULL
178dc4f0af1Szrj #define swap_cidx NULL
179dc4f0af1Szrj #define kernel_cidx NULL
180dc4f0af1Szrj #endif
181dc4f0af1Szrj
182dc4f0af1Szrj
183dc4f0af1Szrj /* internal support routines */
184dc4f0af1Szrj
185dc4f0af1Szrj /*
186dc4f0af1Szrj * static int string_count(char **pp)
187dc4f0af1Szrj *
188dc4f0af1Szrj * Pointer "pp" points to an array of string pointers, which is
189dc4f0af1Szrj * terminated by a NULL. Return the number of string pointers in
190dc4f0af1Szrj * this array.
191dc4f0af1Szrj */
192dc4f0af1Szrj
193dc4f0af1Szrj static int
string_count(char ** pp)194dc4f0af1Szrj string_count(char **pp)
195dc4f0af1Szrj
196dc4f0af1Szrj {
197dc4f0af1Szrj register int cnt = 0;
198dc4f0af1Szrj
199dc4f0af1Szrj if (pp != NULL)
200dc4f0af1Szrj {
201dc4f0af1Szrj while (*pp++ != NULL)
202dc4f0af1Szrj {
203dc4f0af1Szrj cnt++;
204dc4f0af1Szrj }
205dc4f0af1Szrj }
206dc4f0af1Szrj return(cnt);
207dc4f0af1Szrj }
208dc4f0af1Szrj
209dc4f0af1Szrj void
display_clear()210dc4f0af1Szrj display_clear()
211dc4f0af1Szrj
212dc4f0af1Szrj {
213dc4f0af1Szrj dprintf("display_clear\n");
214dc4f0af1Szrj screen_clear();
215dc4f0af1Szrj memzero(screenbuf, bufsize);
216dc4f0af1Szrj memzero(colorbuf, bufsize);
217dc4f0af1Szrj curr_x = curr_y = 0;
218dc4f0af1Szrj }
219dc4f0af1Szrj
220dc4f0af1Szrj /*
221dc4f0af1Szrj * void display_move(int x, int y)
222dc4f0af1Szrj *
223dc4f0af1Szrj * Efficiently move the cursor to x, y. This assumes the cursor is
224dc4f0af1Szrj * currently located at curr_x, curr_y, and will only use cursor
225dc4f0af1Szrj * addressing when it is less expensive than overstriking what's
226dc4f0af1Szrj * already on the screen.
227dc4f0af1Szrj */
228dc4f0af1Szrj
229dc4f0af1Szrj void
display_move(int x,int y)230dc4f0af1Szrj display_move(int x, int y)
231dc4f0af1Szrj
232dc4f0af1Szrj {
233dc4f0af1Szrj char buff[128];
234dc4f0af1Szrj char *p;
235dc4f0af1Szrj char *bufp;
236dc4f0af1Szrj char *colorp;
237dc4f0af1Szrj int cnt = 0;
238dc4f0af1Szrj int color = curr_color;
239dc4f0af1Szrj
240dc4f0af1Szrj dprintf("display_move(%d, %d): curr_x %d, curr_y %d\n", x, y, curr_x, curr_y);
241dc4f0af1Szrj
242dc4f0af1Szrj /* are we in a position to do this without cursor addressing? */
243dc4f0af1Szrj if (curr_y < y || (curr_y == y && curr_x <= x))
244dc4f0af1Szrj {
245dc4f0af1Szrj /* start buffering up what it would take to move there by rewriting
246dc4f0af1Szrj what's on the screen */
247dc4f0af1Szrj cnt = CURSOR_COST;
248dc4f0af1Szrj p = buff;
249dc4f0af1Szrj
250dc4f0af1Szrj /* one newline for every line */
251dc4f0af1Szrj while (cnt > 0 && curr_y < y)
252dc4f0af1Szrj {
253dc4f0af1Szrj #ifdef ENABLE_COLOR
254dc4f0af1Szrj if (color != 0)
255dc4f0af1Szrj {
256dc4f0af1Szrj p = strcpyend(p, color_setstr(0));
257dc4f0af1Szrj color = 0;
258dc4f0af1Szrj cnt -= 5;
259dc4f0af1Szrj }
260dc4f0af1Szrj #endif
261dc4f0af1Szrj *p++ = '\n';
262dc4f0af1Szrj curr_y++;
263dc4f0af1Szrj curr_x = 0;
264dc4f0af1Szrj cnt--;
265dc4f0af1Szrj }
266dc4f0af1Szrj
267dc4f0af1Szrj /* write whats in the screenbuf */
268dc4f0af1Szrj bufp = &screenbuf[lineindex(curr_y) + curr_x];
269dc4f0af1Szrj colorp = &colorbuf[lineindex(curr_y) + curr_x];
270dc4f0af1Szrj while (cnt > 0 && curr_x < x)
271dc4f0af1Szrj {
272dc4f0af1Szrj #ifdef ENABLE_COLOR
273dc4f0af1Szrj if (color != *colorp)
274dc4f0af1Szrj {
275dc4f0af1Szrj color = *colorp;
276dc4f0af1Szrj p = strcpyend(p, color_setstr(color));
277dc4f0af1Szrj cnt -= 5;
278dc4f0af1Szrj }
279dc4f0af1Szrj #endif
280dc4f0af1Szrj if ((*p = *bufp) == '\0')
281dc4f0af1Szrj {
282dc4f0af1Szrj /* somwhere on screen we haven't been before */
283dc4f0af1Szrj *p = *bufp = ' ';
284dc4f0af1Szrj }
285dc4f0af1Szrj p++;
286dc4f0af1Szrj bufp++;
287dc4f0af1Szrj colorp++;
288dc4f0af1Szrj curr_x++;
289dc4f0af1Szrj cnt--;
290dc4f0af1Szrj }
291dc4f0af1Szrj }
292dc4f0af1Szrj
293dc4f0af1Szrj /* move the cursor */
294dc4f0af1Szrj if (cnt > 0)
295dc4f0af1Szrj {
296dc4f0af1Szrj /* screen rewrite is cheaper */
297dc4f0af1Szrj *p = '\0';
298dc4f0af1Szrj fputs(buff, stdout);
299dc4f0af1Szrj curr_color = color;
300dc4f0af1Szrj }
301dc4f0af1Szrj else
302dc4f0af1Szrj {
303dc4f0af1Szrj screen_move(x, y);
304dc4f0af1Szrj }
305dc4f0af1Szrj
306dc4f0af1Szrj /* update our position */
307dc4f0af1Szrj curr_x = x;
308dc4f0af1Szrj curr_y = y;
309dc4f0af1Szrj }
310dc4f0af1Szrj
311dc4f0af1Szrj /*
312dc4f0af1Szrj * display_write(int x, int y, int newcolor, int eol, char *new)
313dc4f0af1Szrj *
314dc4f0af1Szrj * Optimized write to the display. This writes characters to the
315dc4f0af1Szrj * screen in a way that optimizes the number of characters actually
316dc4f0af1Szrj * sent, by comparing what is being written to what is already on
317dc4f0af1Szrj * the screen (according to screenbuf and colorbuf). The string to
318dc4f0af1Szrj * write is "new", the first character of "new" should appear at
319dc4f0af1Szrj * screen position x, y. If x is -1 then "new" begins wherever the
320dc4f0af1Szrj * cursor is currently positioned. The string is written with color
321dc4f0af1Szrj * "newcolor". If "eol" is true then the remainder of the line is
322dc4f0af1Szrj * cleared. It is expected that "new" will have no newlines and no
323dc4f0af1Szrj * escape sequences.
324dc4f0af1Szrj */
325dc4f0af1Szrj
326dc4f0af1Szrj void
display_write(int x,int y,int newcolor,int eol,char * new)327dc4f0af1Szrj display_write(int x, int y, int newcolor, int eol, char *new)
328dc4f0af1Szrj
329dc4f0af1Szrj {
330dc4f0af1Szrj char *bufp;
331dc4f0af1Szrj char *colorp;
332dc4f0af1Szrj int ch;
333dc4f0af1Szrj int diff;
334dc4f0af1Szrj
335dc4f0af1Szrj dprintf("display_write(%d, %d, %d, %d, \"%s\")\n",
336dc4f0af1Szrj x, y, newcolor, eol, new);
337dc4f0af1Szrj
338dc4f0af1Szrj /* dumb terminal handling here */
339dc4f0af1Szrj if (!smart_terminal)
340dc4f0af1Szrj {
341dc4f0af1Szrj if (x != -1)
342dc4f0af1Szrj {
343dc4f0af1Szrj /* make sure we are on the right line */
344dc4f0af1Szrj while (curr_y < y)
345dc4f0af1Szrj {
346dc4f0af1Szrj putchar('\n');
347dc4f0af1Szrj curr_y++;
348dc4f0af1Szrj curr_x = 0;
349dc4f0af1Szrj }
350dc4f0af1Szrj
351dc4f0af1Szrj /* make sure we are on the right column */
352dc4f0af1Szrj while (curr_x < x)
353dc4f0af1Szrj {
354dc4f0af1Szrj putchar(' ');
355dc4f0af1Szrj curr_x++;
356dc4f0af1Szrj }
357dc4f0af1Szrj }
358dc4f0af1Szrj
359dc4f0af1Szrj /* write */
360dc4f0af1Szrj fputs(new, stdout);
361dc4f0af1Szrj curr_x += strlen(new);
362dc4f0af1Szrj
363dc4f0af1Szrj return;
364dc4f0af1Szrj }
365dc4f0af1Szrj
366dc4f0af1Szrj /* adjust for "here" */
367dc4f0af1Szrj if (x == -1)
368dc4f0af1Szrj {
369dc4f0af1Szrj x = virt_x;
370dc4f0af1Szrj y = virt_y;
371dc4f0af1Szrj }
372dc4f0af1Szrj else
373dc4f0af1Szrj {
374dc4f0af1Szrj virt_x = x;
375dc4f0af1Szrj virt_y = y;
376dc4f0af1Szrj }
377dc4f0af1Szrj
378dc4f0af1Szrj /* a pointer to where we start */
379dc4f0af1Szrj bufp = &screenbuf[lineindex(y) + x];
380dc4f0af1Szrj colorp = &colorbuf[lineindex(y) + x];
381dc4f0af1Szrj
382dc4f0af1Szrj /* main loop */
383dc4f0af1Szrj while ((ch = *new++) != '\0')
384dc4f0af1Szrj {
385dc4f0af1Szrj /* if either character or color are different, an update is needed */
386dc4f0af1Szrj /* but only when the screen is wide enough */
387dc4f0af1Szrj if (y < (smart_terminal ? screen_length : Largest) && x < display_width &&
388dc4f0af1Szrj (ch != *bufp || newcolor != *colorp))
389dc4f0af1Szrj {
390dc4f0af1Szrj /* check cursor */
391dc4f0af1Szrj if (y != curr_y || x != curr_x)
392dc4f0af1Szrj {
393dc4f0af1Szrj /* have to move the cursor */
394dc4f0af1Szrj display_move(x, y);
395dc4f0af1Szrj }
396dc4f0af1Szrj
397dc4f0af1Szrj /* write character */
398dc4f0af1Szrj #ifdef ENABLE_COLOR
399dc4f0af1Szrj if (curr_color != newcolor)
400dc4f0af1Szrj {
401dc4f0af1Szrj fputs(color_setstr(newcolor), stdout);
402dc4f0af1Szrj curr_color = newcolor;
403dc4f0af1Szrj }
404dc4f0af1Szrj #endif
405dc4f0af1Szrj putchar(ch);
406dc4f0af1Szrj *bufp = ch;
407dc4f0af1Szrj *colorp = curr_color;
408dc4f0af1Szrj curr_x++;
409dc4f0af1Szrj }
410dc4f0af1Szrj
411dc4f0af1Szrj /* move */
412dc4f0af1Szrj x++;
413dc4f0af1Szrj virt_x++;
414dc4f0af1Szrj bufp++;
415dc4f0af1Szrj colorp++;
416dc4f0af1Szrj }
417dc4f0af1Szrj
418dc4f0af1Szrj /* eol handling */
419dc4f0af1Szrj if (eol && *bufp != '\0')
420dc4f0af1Szrj {
421dc4f0af1Szrj dprintf("display_write: clear-eol (bufp = \"%s\")\n", bufp);
422dc4f0af1Szrj /* make sure we are color 0 */
423dc4f0af1Szrj #ifdef ENABLE_COLOR
424dc4f0af1Szrj if (curr_color != 0)
425dc4f0af1Szrj {
426dc4f0af1Szrj fputs(color_setstr(0), stdout);
427dc4f0af1Szrj curr_color = 0;
428dc4f0af1Szrj }
429dc4f0af1Szrj #endif
430dc4f0af1Szrj
431dc4f0af1Szrj /* make sure we are at the end */
432dc4f0af1Szrj if (x != curr_x || y != curr_y)
433dc4f0af1Szrj {
434dc4f0af1Szrj screen_move(x, y);
435dc4f0af1Szrj curr_x = x;
436dc4f0af1Szrj curr_y = y;
437dc4f0af1Szrj }
438dc4f0af1Szrj
439dc4f0af1Szrj /* clear to end */
440dc4f0af1Szrj screen_cleareol(strlen(bufp));
441dc4f0af1Szrj
442dc4f0af1Szrj /* clear out whats left of this line's buffer */
443dc4f0af1Szrj diff = display_width - x;
444dc4f0af1Szrj if (diff > 0)
445dc4f0af1Szrj {
446dc4f0af1Szrj memzero(bufp, diff);
447dc4f0af1Szrj memzero(colorp, diff);
448dc4f0af1Szrj }
449dc4f0af1Szrj }
450dc4f0af1Szrj }
451dc4f0af1Szrj
452dc4f0af1Szrj void
display_fmt(int x,int y,int newcolor,int eol,char * fmt,...)453dc4f0af1Szrj display_fmt(int x, int y, int newcolor, int eol, char *fmt, ...)
454dc4f0af1Szrj
455dc4f0af1Szrj {
456dc4f0af1Szrj va_list argp;
457dc4f0af1Szrj
458dc4f0af1Szrj va_start(argp, fmt);
459dc4f0af1Szrj
460dc4f0af1Szrj vsnprintf(scratchbuf, MAX_COLS, fmt, argp);
461dc4f0af1Szrj display_write(x, y, newcolor, eol, scratchbuf);
462dc4f0af1Szrj }
463dc4f0af1Szrj
464dc4f0af1Szrj void
display_cte()465dc4f0af1Szrj display_cte()
466dc4f0af1Szrj
467dc4f0af1Szrj {
468dc4f0af1Szrj int len;
469dc4f0af1Szrj int y;
470dc4f0af1Szrj char *p;
471dc4f0af1Szrj int need_clear = 0;
472dc4f0af1Szrj
473dc4f0af1Szrj /* is there anything out there that needs to be cleared? */
474dc4f0af1Szrj p = &screenbuf[lineindex(virt_y) + virt_x];
475dc4f0af1Szrj if (*p != '\0')
476dc4f0af1Szrj {
477dc4f0af1Szrj need_clear = 1;
478dc4f0af1Szrj }
479dc4f0af1Szrj else
480dc4f0af1Szrj {
481dc4f0af1Szrj /* this line is clear, what about the rest? */
482dc4f0af1Szrj y = virt_y;
483dc4f0af1Szrj while (++y < screen_length)
484dc4f0af1Szrj {
485dc4f0af1Szrj if (screenbuf[lineindex(y)] != '\0')
486dc4f0af1Szrj {
487dc4f0af1Szrj need_clear = 1;
488dc4f0af1Szrj break;
489dc4f0af1Szrj }
490dc4f0af1Szrj }
491dc4f0af1Szrj }
492dc4f0af1Szrj
493dc4f0af1Szrj if (need_clear)
494dc4f0af1Szrj {
495dc4f0af1Szrj dprintf("display_cte: clearing\n");
496dc4f0af1Szrj
497dc4f0af1Szrj /* we will need this later */
498dc4f0af1Szrj len = lineindex(virt_y) + virt_x;
499dc4f0af1Szrj
500dc4f0af1Szrj /* move to x and y, then clear to end */
501dc4f0af1Szrj display_move(virt_x, virt_y);
502dc4f0af1Szrj if (!screen_cte())
503dc4f0af1Szrj {
504dc4f0af1Szrj /* screen has no clear to end, so do it by hand */
505dc4f0af1Szrj p = &screenbuf[len];
506dc4f0af1Szrj len = strlen(p);
507dc4f0af1Szrj if (len > 0)
508dc4f0af1Szrj {
509dc4f0af1Szrj screen_cleareol(len);
510dc4f0af1Szrj }
511dc4f0af1Szrj while (++virt_y < screen_length)
512dc4f0af1Szrj {
513dc4f0af1Szrj display_move(0, virt_y);
514dc4f0af1Szrj p = &screenbuf[lineindex(virt_y)];
515dc4f0af1Szrj len = strlen(p);
516dc4f0af1Szrj if (len > 0)
517dc4f0af1Szrj {
518dc4f0af1Szrj screen_cleareol(len);
519dc4f0af1Szrj }
520dc4f0af1Szrj }
521dc4f0af1Szrj }
522dc4f0af1Szrj
523dc4f0af1Szrj /* clear the screenbuf */
524dc4f0af1Szrj memzero(&screenbuf[len], bufsize - len);
525dc4f0af1Szrj memzero(&colorbuf[len], bufsize - len);
526dc4f0af1Szrj }
527dc4f0af1Szrj }
528dc4f0af1Szrj
529dc4f0af1Szrj static void
summary_format(int x,int y,int * numbers,char ** names,int * cidx)530dc4f0af1Szrj summary_format(int x, int y, int *numbers, char **names, int *cidx)
531dc4f0af1Szrj
532dc4f0af1Szrj {
533dc4f0af1Szrj register int num;
534dc4f0af1Szrj register char *thisname;
535dc4f0af1Szrj register char *lastname = NULL;
536dc4f0af1Szrj register int color;
537dc4f0af1Szrj
538dc4f0af1Szrj /* format each number followed by its string */
539dc4f0af1Szrj while ((thisname = *names++) != NULL)
540dc4f0af1Szrj {
541dc4f0af1Szrj /* get the number to format */
542dc4f0af1Szrj num = *numbers++;
543dc4f0af1Szrj color = 0;
544dc4f0af1Szrj
545dc4f0af1Szrj /* display only non-zero numbers */
546dc4f0af1Szrj if (num != 0)
547dc4f0af1Szrj {
548dc4f0af1Szrj /* write the previous name */
549dc4f0af1Szrj if (lastname != NULL)
550dc4f0af1Szrj {
551dc4f0af1Szrj display_write(-1, -1, 0, 0, lastname);
552dc4f0af1Szrj }
553dc4f0af1Szrj
554dc4f0af1Szrj #ifdef ENABLE_COLOR
555dc4f0af1Szrj if (cidx != NULL)
556dc4f0af1Szrj {
557dc4f0af1Szrj /* choose a color */
558dc4f0af1Szrj color = color_test(*cidx++, num);
559dc4f0af1Szrj }
560dc4f0af1Szrj #endif
561dc4f0af1Szrj
562dc4f0af1Szrj /* write this number if positive */
563dc4f0af1Szrj if (num > 0)
564dc4f0af1Szrj {
565dc4f0af1Szrj display_write(x, y, color, 0, itoa(num));
566dc4f0af1Szrj }
567dc4f0af1Szrj
568dc4f0af1Szrj /* defer writing this name */
569dc4f0af1Szrj lastname = thisname;
570dc4f0af1Szrj
571dc4f0af1Szrj /* next iteration will not start at x, y */
572dc4f0af1Szrj x = y = -1;
573dc4f0af1Szrj }
574dc4f0af1Szrj }
575dc4f0af1Szrj
576dc4f0af1Szrj /* if the last string has a separator on the end, it has to be
577dc4f0af1Szrj written with care */
578dc4f0af1Szrj if (lastname != NULL)
579dc4f0af1Szrj {
580dc4f0af1Szrj if ((num = strlen(lastname)) > 1 &&
581dc4f0af1Szrj lastname[num-2] == ',' && lastname[num-1] == ' ')
582dc4f0af1Szrj {
583dc4f0af1Szrj display_fmt(-1, -1, 0, 1, "%.*s", num-2, lastname);
584dc4f0af1Szrj }
585dc4f0af1Szrj else
586dc4f0af1Szrj {
587dc4f0af1Szrj display_write(-1, -1, 0, 1, lastname);
588dc4f0af1Szrj }
589dc4f0af1Szrj }
590dc4f0af1Szrj }
591dc4f0af1Szrj
592dc4f0af1Szrj static void
summary_format_memory(int x,int y,long * numbers,char ** names,int * cidx)593dc4f0af1Szrj summary_format_memory(int x, int y, long *numbers, char **names, int *cidx)
594dc4f0af1Szrj
595dc4f0af1Szrj {
596dc4f0af1Szrj register long num;
597dc4f0af1Szrj register int color;
598dc4f0af1Szrj register char *thisname;
599dc4f0af1Szrj register char *lastname = NULL;
600dc4f0af1Szrj
601dc4f0af1Szrj /* format each number followed by its string */
602dc4f0af1Szrj while ((thisname = *names++) != NULL)
603dc4f0af1Szrj {
604dc4f0af1Szrj /* get the number to format */
605dc4f0af1Szrj num = *numbers++;
606dc4f0af1Szrj color = 0;
607dc4f0af1Szrj
608dc4f0af1Szrj /* display only non-zero numbers */
609dc4f0af1Szrj if (num != 0)
610dc4f0af1Szrj {
611dc4f0af1Szrj /* write the previous name */
612dc4f0af1Szrj if (lastname != NULL)
613dc4f0af1Szrj {
614dc4f0af1Szrj display_write(-1, -1, 0, 0, lastname);
615dc4f0af1Szrj }
616dc4f0af1Szrj
617dc4f0af1Szrj /* defer writing this name */
618dc4f0af1Szrj lastname = thisname;
619dc4f0af1Szrj
620dc4f0af1Szrj #ifdef ENABLE_COLOR
621dc4f0af1Szrj /* choose a color */
622dc4f0af1Szrj color = color_test(*cidx++, num);
623dc4f0af1Szrj #endif
624dc4f0af1Szrj
625dc4f0af1Szrj /* is this number in kilobytes? */
626dc4f0af1Szrj if (thisname[0] == 'K')
627dc4f0af1Szrj {
628dc4f0af1Szrj display_write(x, y, color, 0, format_k(num));
629dc4f0af1Szrj lastname++;
630dc4f0af1Szrj }
631dc4f0af1Szrj else
632dc4f0af1Szrj {
633dc4f0af1Szrj display_write(x, y, color, 0, itoa((int)num));
634dc4f0af1Szrj }
635dc4f0af1Szrj
636dc4f0af1Szrj /* next iteration will not start at x, y */
637dc4f0af1Szrj x = y = -1;
638dc4f0af1Szrj }
639dc4f0af1Szrj }
640dc4f0af1Szrj
641dc4f0af1Szrj /* if the last string has a separator on the end, it has to be
642dc4f0af1Szrj written with care */
643dc4f0af1Szrj if (lastname != NULL)
644dc4f0af1Szrj {
645dc4f0af1Szrj if ((num = strlen(lastname)) > 1 &&
646dc4f0af1Szrj lastname[num-2] == ',' && lastname[num-1] == ' ')
647dc4f0af1Szrj {
648dc4f0af1Szrj display_fmt(-1, -1, 0, 1, "%.*s", num-2, lastname);
649dc4f0af1Szrj }
650dc4f0af1Szrj else
651dc4f0af1Szrj {
652dc4f0af1Szrj display_write(-1, -1, 0, 1, lastname);
653dc4f0af1Szrj }
654dc4f0af1Szrj }
655dc4f0af1Szrj }
656dc4f0af1Szrj
657dc4f0af1Szrj /*
658dc4f0af1Szrj * int display_resize()
659dc4f0af1Szrj *
660dc4f0af1Szrj * Reallocate buffer space needed by the display package to accomodate
661dc4f0af1Szrj * a new screen size. Must be called whenever the screen's size has
662dc4f0af1Szrj * changed. Returns the number of lines available for displaying
663dc4f0af1Szrj * processes or -1 if there was a problem allocating space.
664dc4f0af1Szrj */
665dc4f0af1Szrj
666dc4f0af1Szrj int
display_resize()667dc4f0af1Szrj display_resize()
668dc4f0af1Szrj
669dc4f0af1Szrj {
670dc4f0af1Szrj register int top_lines;
671dc4f0af1Szrj register int newsize;
672dc4f0af1Szrj
673dc4f0af1Szrj /* calculate the current dimensions */
674dc4f0af1Szrj /* if operating in "dumb" mode, we only need one line */
675dc4f0af1Szrj top_lines = smart_terminal ? screen_length : 1;
676dc4f0af1Szrj
677dc4f0af1Szrj /* we don't want more than MAX_COLS columns, since the machine-dependent
678dc4f0af1Szrj modules make static allocations based on MAX_COLS and we don't want
679dc4f0af1Szrj to run off the end of their buffers */
680dc4f0af1Szrj display_width = screen_width;
681dc4f0af1Szrj if (display_width >= MAX_COLS)
682dc4f0af1Szrj {
683dc4f0af1Szrj display_width = MAX_COLS - 1;
684dc4f0af1Szrj }
685dc4f0af1Szrj
686dc4f0af1Szrj /* see how much space we need */
687dc4f0af1Szrj newsize = top_lines * (MAX_COLS + 1);
688dc4f0af1Szrj
689dc4f0af1Szrj /* reallocate only if we need more than we already have */
690dc4f0af1Szrj if (newsize > bufsize)
691dc4f0af1Szrj {
692dc4f0af1Szrj /* deallocate any previous buffer that may have been there */
693dc4f0af1Szrj if (screenbuf != NULL)
694dc4f0af1Szrj {
695dc4f0af1Szrj free(screenbuf);
696dc4f0af1Szrj }
697dc4f0af1Szrj if (colorbuf != NULL)
698dc4f0af1Szrj {
699dc4f0af1Szrj free(colorbuf);
700dc4f0af1Szrj }
701dc4f0af1Szrj
702dc4f0af1Szrj /* allocate space for the screen and color buffers */
703dc4f0af1Szrj bufsize = newsize;
704dc4f0af1Szrj screenbuf = (char *)calloc(bufsize, sizeof(char));
705dc4f0af1Szrj colorbuf = (char *)calloc(bufsize, sizeof(char));
706dc4f0af1Szrj if (screenbuf == NULL || colorbuf == NULL)
707dc4f0af1Szrj {
708dc4f0af1Szrj /* oops! */
709dc4f0af1Szrj return(-1);
710dc4f0af1Szrj }
711dc4f0af1Szrj }
712dc4f0af1Szrj else
713dc4f0af1Szrj {
714dc4f0af1Szrj /* just clear them out */
715dc4f0af1Szrj memzero(screenbuf, bufsize);
716dc4f0af1Szrj memzero(colorbuf, bufsize);
717dc4f0af1Szrj }
718dc4f0af1Szrj
719dc4f0af1Szrj /* adjust total lines on screen to lines available for procs */
720dc4f0af1Szrj if (top_lines > y_procs)
721dc4f0af1Szrj top_lines -= y_procs;
722dc4f0af1Szrj else
723dc4f0af1Szrj top_lines = 0;
724dc4f0af1Szrj
725dc4f0af1Szrj /* return number of lines available */
726dc4f0af1Szrj /* for dumb terminals, pretend like we can show any amount */
727dc4f0af1Szrj return(smart_terminal ? top_lines : Largest);
728dc4f0af1Szrj }
729dc4f0af1Szrj
730dc4f0af1Szrj int
display_lines()731dc4f0af1Szrj display_lines()
732dc4f0af1Szrj
733dc4f0af1Szrj {
734dc4f0af1Szrj return(smart_terminal ? screen_length : Largest);
735dc4f0af1Szrj }
736dc4f0af1Szrj
737dc4f0af1Szrj int
display_columns()738dc4f0af1Szrj display_columns()
739dc4f0af1Szrj
740dc4f0af1Szrj {
741dc4f0af1Szrj return(display_width);
742dc4f0af1Szrj }
743dc4f0af1Szrj
744dc4f0af1Szrj /*
745dc4f0af1Szrj * int display_init(struct statics *statics)
746dc4f0af1Szrj *
747dc4f0af1Szrj * Initialize the display system based on information in the statics
748dc4f0af1Szrj * structure. Returns the number of lines available for displaying
749dc4f0af1Szrj * processes or -1 if there was an error.
750dc4f0af1Szrj */
751dc4f0af1Szrj
752dc4f0af1Szrj int
display_init(struct statics * statics)753dc4f0af1Szrj display_init(struct statics *statics)
754dc4f0af1Szrj
755dc4f0af1Szrj {
756dc4f0af1Szrj register int top_lines;
757dc4f0af1Szrj register char **pp;
758dc4f0af1Szrj register char *p;
759dc4f0af1Szrj register int *ip;
760dc4f0af1Szrj register int i;
761dc4f0af1Szrj
762dc4f0af1Szrj /* certain things may influence the screen layout,
763dc4f0af1Szrj so look at those first */
764dc4f0af1Szrj
765dc4f0af1Szrj /* More than one core will shif the parts of the display down */
766dc4f0af1Szrj if (enable_ncpus != 0 && n_cpus > 1)
767dc4f0af1Szrj {
768dc4f0af1Szrj /* adjust screen placements */
769dc4f0af1Szrj y_mem = y_mem + n_cpus -1;
770dc4f0af1Szrj y_swap = y_swap + n_cpus -1;
771dc4f0af1Szrj y_message = y_message + n_cpus -1;
772dc4f0af1Szrj y_header = y_header + n_cpus -1;
773dc4f0af1Szrj y_idlecursor = y_idlecursor + n_cpus -1;
774dc4f0af1Szrj y_procs = y_procs + n_cpus -1;
775dc4f0af1Szrj }
776dc4f0af1Szrj
777dc4f0af1Szrj /* a kernel line shifts parts of the display down */
778dc4f0af1Szrj kernel_names = statics->kernel_names;
779dc4f0af1Szrj if ((num_kernel = string_count(kernel_names)) > 0)
780dc4f0af1Szrj {
781dc4f0af1Szrj /* adjust screen placements */
782dc4f0af1Szrj y_mem++;
783dc4f0af1Szrj y_swap++;
784dc4f0af1Szrj y_message++;
785dc4f0af1Szrj y_header++;
786dc4f0af1Szrj y_idlecursor++;
787dc4f0af1Szrj y_procs++;
788dc4f0af1Szrj }
789dc4f0af1Szrj
790dc4f0af1Szrj /* a swap line shifts parts of the display down one */
791dc4f0af1Szrj swap_names = statics->swap_names;
792dc4f0af1Szrj if ((num_swap = string_count(swap_names)) > 0)
793dc4f0af1Szrj {
794dc4f0af1Szrj /* adjust screen placements */
795dc4f0af1Szrj y_message++;
796dc4f0af1Szrj y_header++;
797dc4f0af1Szrj y_idlecursor++;
798dc4f0af1Szrj y_procs++;
799dc4f0af1Szrj }
800dc4f0af1Szrj
801dc4f0af1Szrj /* call resize to do the dirty work */
802dc4f0af1Szrj top_lines = display_resize();
803dc4f0af1Szrj
804dc4f0af1Szrj /*
805dc4f0af1Szrj * save pointers and allocate space for names. Even if top_lines <= -1
806dc4f0af1Szrj * the code will dereference many of these pointers and arrays.
807dc4f0af1Szrj */
808dc4f0af1Szrj procstate_names = statics->procstate_names;
809dc4f0af1Szrj num_procstates = string_count(procstate_names);
810dc4f0af1Szrj
811dc4f0af1Szrj lprocstates = (int *)calloc(num_procstates, sizeof(int));
812dc4f0af1Szrj
813dc4f0af1Szrj cpustate_names = statics->cpustate_names;
814dc4f0af1Szrj num_cpustates = string_count(cpustate_names);
815dc4f0af1Szrj lcpustates = (int *)calloc(num_cpustates, sizeof(int));
816dc4f0af1Szrj cpustate_columns = (int *)calloc(num_cpustates, sizeof(int));
817dc4f0af1Szrj memory_names = statics->memory_names;
818dc4f0af1Szrj num_memory = string_count(memory_names);
819dc4f0af1Szrj
820dc4f0af1Szrj /* calculate starting columns where needed */
821dc4f0af1Szrj cpustate_total_length = 0;
822dc4f0af1Szrj pp = cpustate_names;
823dc4f0af1Szrj ip = cpustate_columns;
824dc4f0af1Szrj while (*pp != NULL)
825dc4f0af1Szrj {
826dc4f0af1Szrj *ip++ = cpustate_total_length;
827dc4f0af1Szrj if ((i = strlen(*pp++)) > 0)
828dc4f0af1Szrj {
829dc4f0af1Szrj cpustate_total_length += i + 8;
830dc4f0af1Szrj }
831dc4f0af1Szrj }
832dc4f0af1Szrj
833dc4f0af1Szrj #ifdef ENABLE_COLOR
834dc4f0af1Szrj /* set up color tags for loadavg */
835dc4f0af1Szrj load_cidx[0] = color_tag("1min");
836dc4f0af1Szrj load_cidx[1] = color_tag("5min");
837dc4f0af1Szrj load_cidx[2] = color_tag("15min");
838dc4f0af1Szrj
839dc4f0af1Szrj /* find header color */
840dc4f0af1Szrj header_cidx = color_tag("header");
841dc4f0af1Szrj
842dc4f0af1Szrj /* color tags for cpu states */
843dc4f0af1Szrj cpustate_cidx = (int *)malloc(num_cpustates * sizeof(int));
844dc4f0af1Szrj i = 0;
845dc4f0af1Szrj p = strcpyend(scratchbuf, "cpu.");
846dc4f0af1Szrj while (i < num_cpustates)
847dc4f0af1Szrj {
848dc4f0af1Szrj strcpy(p, cpustate_names[i]);
849dc4f0af1Szrj cpustate_cidx[i++] = color_tag(scratchbuf);
850dc4f0af1Szrj }
851dc4f0af1Szrj
852dc4f0af1Szrj /* color tags for kernel */
853dc4f0af1Szrj if (num_kernel > 0)
854dc4f0af1Szrj {
855dc4f0af1Szrj kernel_cidx = (int *)malloc(num_kernel * sizeof(int));
856dc4f0af1Szrj i = 0;
857dc4f0af1Szrj p = strcpyend(scratchbuf, "kernel.");
858dc4f0af1Szrj while (i < num_kernel)
859dc4f0af1Szrj {
860dc4f0af1Szrj strcpy(p, homogenize(kernel_names[i]+1));
861dc4f0af1Szrj kernel_cidx[i++] = color_tag(scratchbuf);
862dc4f0af1Szrj }
863dc4f0af1Szrj }
864dc4f0af1Szrj
865dc4f0af1Szrj /* color tags for memory */
866dc4f0af1Szrj memory_cidx = (int *)malloc(num_memory * sizeof(int));
867dc4f0af1Szrj i = 0;
868dc4f0af1Szrj p = strcpyend(scratchbuf, "memory.");
869dc4f0af1Szrj while (i < num_memory)
870dc4f0af1Szrj {
871dc4f0af1Szrj strcpy(p, homogenize(memory_names[i]+1));
872dc4f0af1Szrj memory_cidx[i++] = color_tag(scratchbuf);
873dc4f0af1Szrj }
874dc4f0af1Szrj
875dc4f0af1Szrj /* color tags for swap */
876dc4f0af1Szrj if (num_swap > 0)
877dc4f0af1Szrj {
878dc4f0af1Szrj swap_cidx = (int *)malloc(num_swap * sizeof(int));
879dc4f0af1Szrj i = 0;
880dc4f0af1Szrj p = strcpyend(scratchbuf, "swap.");
881dc4f0af1Szrj while (i < num_swap)
882dc4f0af1Szrj {
883dc4f0af1Szrj strcpy(p, homogenize(swap_names[i]+1));
884dc4f0af1Szrj swap_cidx[i++] = color_tag(scratchbuf);
885dc4f0af1Szrj }
886dc4f0af1Szrj }
887dc4f0af1Szrj #endif
888dc4f0af1Szrj
889dc4f0af1Szrj /* return number of lines available (or error) */
890dc4f0af1Szrj return(top_lines);
891dc4f0af1Szrj }
892dc4f0af1Szrj
893dc4f0af1Szrj static void
pr_loadavg(double avg,int i)894dc4f0af1Szrj pr_loadavg(double avg, int i)
895dc4f0af1Szrj
896dc4f0af1Szrj {
897dc4f0af1Szrj int color = 0;
898dc4f0af1Szrj
899dc4f0af1Szrj #ifdef ENABLE_COLOR
900dc4f0af1Szrj color = color_test(load_cidx[i], (int)(avg * 100));
901dc4f0af1Szrj #endif
902dc4f0af1Szrj display_fmt(x_loadave + X_LOADAVEWIDTH * i, y_loadave, color, 0,
903dc4f0af1Szrj avg < 10.0 ? " %5.2f" : " %5.1f", avg);
904dc4f0af1Szrj display_write(-1, -1, 0, 0, (i < 2 ? "," : ";"));
905dc4f0af1Szrj }
906dc4f0af1Szrj
907dc4f0af1Szrj void
i_loadave(int mpid,double * avenrun)908dc4f0af1Szrj i_loadave(int mpid, double *avenrun)
909dc4f0af1Szrj
910dc4f0af1Szrj {
911dc4f0af1Szrj register int i;
912dc4f0af1Szrj
913dc4f0af1Szrj /* mpid == -1 implies this system doesn't have an _mpid */
914dc4f0af1Szrj if (mpid != -1)
915dc4f0af1Szrj {
916dc4f0af1Szrj display_fmt(0, 0, 0, 0,
917dc4f0af1Szrj "last pid: %5d; load avg:", mpid);
918dc4f0af1Szrj x_loadave = X_LOADAVE;
919dc4f0af1Szrj }
920dc4f0af1Szrj else
921dc4f0af1Szrj {
922dc4f0af1Szrj display_write(0, 0, 0, 0, "load averages:");
923dc4f0af1Szrj x_loadave = X_LOADAVE - X_LASTPIDWIDTH;
924dc4f0af1Szrj }
925dc4f0af1Szrj for (i = 0; i < 3; i++)
926dc4f0af1Szrj {
927dc4f0af1Szrj pr_loadavg(avenrun[i], i);
928dc4f0af1Szrj }
929dc4f0af1Szrj
930dc4f0af1Szrj lmpid = mpid;
931dc4f0af1Szrj }
932dc4f0af1Szrj
933dc4f0af1Szrj void
u_loadave(int mpid,double * avenrun)934dc4f0af1Szrj u_loadave(int mpid, double *avenrun)
935dc4f0af1Szrj
936dc4f0af1Szrj {
937dc4f0af1Szrj register int i;
938dc4f0af1Szrj
939dc4f0af1Szrj if (mpid != -1)
940dc4f0af1Szrj {
941dc4f0af1Szrj /* change screen only when value has really changed */
942dc4f0af1Szrj if (mpid != lmpid)
943dc4f0af1Szrj {
944dc4f0af1Szrj display_fmt(x_lastpid, y_lastpid, 0, 0,
945dc4f0af1Szrj "%5d", mpid);
946dc4f0af1Szrj lmpid = mpid;
947dc4f0af1Szrj }
948dc4f0af1Szrj }
949dc4f0af1Szrj
950dc4f0af1Szrj /* display new load averages */
951dc4f0af1Szrj for (i = 0; i < 3; i++)
952dc4f0af1Szrj {
953dc4f0af1Szrj pr_loadavg(avenrun[i], i);
954dc4f0af1Szrj }
955dc4f0af1Szrj }
956dc4f0af1Szrj
957dc4f0af1Szrj static char minibar_buffer[64];
958dc4f0af1Szrj #define MINIBAR_WIDTH 20
959dc4f0af1Szrj
960dc4f0af1Szrj void
i_minibar(int (* formatter)(char *,int))961dc4f0af1Szrj i_minibar(int (*formatter)(char *, int))
962dc4f0af1Szrj {
963dc4f0af1Szrj (void)((*formatter)(minibar_buffer, MINIBAR_WIDTH));
964dc4f0af1Szrj
965dc4f0af1Szrj display_write(x_minibar, y_minibar, 0, 0, minibar_buffer);
966dc4f0af1Szrj }
967dc4f0af1Szrj
968dc4f0af1Szrj void
u_minibar(int (* formatter)(char *,int))969dc4f0af1Szrj u_minibar(int (*formatter)(char *, int))
970dc4f0af1Szrj {
971dc4f0af1Szrj (void)((*formatter)(minibar_buffer, MINIBAR_WIDTH));
972dc4f0af1Szrj
973dc4f0af1Szrj display_write(x_minibar, y_minibar, 0, 0, minibar_buffer);
974dc4f0af1Szrj }
975dc4f0af1Szrj
976dc4f0af1Szrj static int uptime_days;
977dc4f0af1Szrj static int uptime_hours;
978dc4f0af1Szrj static int uptime_mins;
979dc4f0af1Szrj static int uptime_secs;
980dc4f0af1Szrj
981dc4f0af1Szrj void
i_uptime(time_t uptime)982*da0d35cfSMatthew Dillon i_uptime(time_t uptime)
983dc4f0af1Szrj {
984dc4f0af1Szrj uptime += 30;
985dc4f0af1Szrj uptime_days = uptime / 86400;
986dc4f0af1Szrj uptime %= 86400;
987dc4f0af1Szrj uptime_hours = uptime / 3600;
988dc4f0af1Szrj uptime %= 3600;
989dc4f0af1Szrj uptime_mins = uptime / 60;
990dc4f0af1Szrj uptime_secs = uptime % 60;
991dc4f0af1Szrj
992dc4f0af1Szrj /*
993dc4f0af1Szrj * Display the uptime.
994dc4f0af1Szrj */
995dc4f0af1Szrj
996dc4f0af1Szrj display_fmt(x_uptime, y_uptime, 0, 0,
997dc4f0af1Szrj " up %d+%02d:%02d:%02d",
998dc4f0af1Szrj uptime_days, uptime_hours, uptime_mins, uptime_secs);
999dc4f0af1Szrj }
1000dc4f0af1Szrj
1001dc4f0af1Szrj void
u_uptime(time_t uptime)1002*da0d35cfSMatthew Dillon u_uptime(time_t uptime)
1003dc4f0af1Szrj {
1004*da0d35cfSMatthew Dillon i_uptime(uptime);
1005dc4f0af1Szrj }
1006dc4f0af1Szrj
1007dc4f0af1Szrj
1008dc4f0af1Szrj void
i_timeofday(time_t * tod)1009dc4f0af1Szrj i_timeofday(time_t *tod)
1010dc4f0af1Szrj
1011dc4f0af1Szrj {
1012dc4f0af1Szrj /*
1013dc4f0af1Szrj * Display the current time.
1014dc4f0af1Szrj * "ctime" always returns a string that looks like this:
1015dc4f0af1Szrj *
1016dc4f0af1Szrj * Sun Sep 16 01:03:52 1973
1017dc4f0af1Szrj * 012345678901234567890123
1018dc4f0af1Szrj * 1 2
1019dc4f0af1Szrj *
1020dc4f0af1Szrj * We want indices 11 thru 18 (length 8).
1021dc4f0af1Szrj */
1022dc4f0af1Szrj
1023dc4f0af1Szrj int x;
1024dc4f0af1Szrj
1025dc4f0af1Szrj /* where on the screen do we start? */
1026dc4f0af1Szrj x = (smart_terminal ? screen_width : 79) - 8;
1027dc4f0af1Szrj
1028dc4f0af1Szrj /* but don't bump in to uptime */
1029dc4f0af1Szrj if (x < x_uptime + 19)
1030dc4f0af1Szrj {
1031dc4f0af1Szrj x = x_uptime + 19;
1032dc4f0af1Szrj }
1033dc4f0af1Szrj
1034dc4f0af1Szrj /* display it */
1035dc4f0af1Szrj display_fmt(x, 0, 0, 1, "%-8.8s", &(ctime(tod)[11]));
1036dc4f0af1Szrj }
1037dc4f0af1Szrj
1038dc4f0af1Szrj static int ltotal = 0;
1039dc4f0af1Szrj static int lthreads = 0;
1040dc4f0af1Szrj
1041dc4f0af1Szrj /*
1042dc4f0af1Szrj * *_procstates(total, brkdn, names) - print the process summary line
1043dc4f0af1Szrj */
1044dc4f0af1Szrj
1045dc4f0af1Szrj
1046dc4f0af1Szrj void
i_procstates(int total,int * brkdn,int threads)1047dc4f0af1Szrj i_procstates(int total, int *brkdn, int threads)
1048dc4f0af1Szrj
1049dc4f0af1Szrj {
1050dc4f0af1Szrj /* write current number of processes and remember the value */
1051dc4f0af1Szrj display_fmt(0, y_procstate, 0, 0,
1052dc4f0af1Szrj "%d %s: ", total, threads ? "threads" : "processes");
1053dc4f0af1Szrj ltotal = total;
1054dc4f0af1Szrj
1055dc4f0af1Szrj /* remember where the summary starts */
1056dc4f0af1Szrj x_procstate = virt_x;
1057dc4f0af1Szrj
1058dc4f0af1Szrj if (total > 0)
1059dc4f0af1Szrj {
1060dc4f0af1Szrj /* format and print the process state summary */
1061dc4f0af1Szrj summary_format(-1, -1, brkdn, procstate_names, NULL);
1062dc4f0af1Szrj
1063dc4f0af1Szrj /* save the numbers for next time */
1064dc4f0af1Szrj memcpy(lprocstates, brkdn, num_procstates * sizeof(int));
1065dc4f0af1Szrj lthreads = threads;
1066dc4f0af1Szrj }
1067dc4f0af1Szrj }
1068dc4f0af1Szrj
1069dc4f0af1Szrj void
u_procstates(int total,int * brkdn,int threads)1070dc4f0af1Szrj u_procstates(int total, int *brkdn, int threads)
1071dc4f0af1Szrj
1072dc4f0af1Szrj {
1073dc4f0af1Szrj /* if threads state has changed, do a full update */
1074dc4f0af1Szrj if (lthreads != threads)
1075dc4f0af1Szrj {
1076dc4f0af1Szrj i_procstates(total, brkdn, threads);
1077dc4f0af1Szrj return;
1078dc4f0af1Szrj }
1079dc4f0af1Szrj
1080dc4f0af1Szrj /* update number of processes only if it has changed */
1081dc4f0af1Szrj if (ltotal != total)
1082dc4f0af1Szrj {
1083dc4f0af1Szrj display_fmt(0, y_procstate, 0, 0,
1084dc4f0af1Szrj "%d", total);
1085dc4f0af1Szrj
1086dc4f0af1Szrj /* if number of digits differs, rewrite the label */
1087dc4f0af1Szrj if (digits(total) != digits(ltotal))
1088dc4f0af1Szrj {
1089dc4f0af1Szrj display_fmt(-1, -1, 0, 0, " %s: ", threads ? "threads" : "processes");
1090dc4f0af1Szrj x_procstate = virt_x;
1091dc4f0af1Szrj }
1092dc4f0af1Szrj
1093dc4f0af1Szrj /* save new total */
1094dc4f0af1Szrj ltotal = total;
1095dc4f0af1Szrj }
1096dc4f0af1Szrj
1097dc4f0af1Szrj /* see if any of the state numbers has changed */
1098dc4f0af1Szrj if (total > 0 && memcmp(lprocstates, brkdn, num_procstates * sizeof(int)) != 0)
1099dc4f0af1Szrj {
1100dc4f0af1Szrj /* format and update the line */
1101dc4f0af1Szrj summary_format(x_procstate, y_procstate, brkdn, procstate_names, NULL);
1102dc4f0af1Szrj memcpy(lprocstates, brkdn, num_procstates * sizeof(int));
1103dc4f0af1Szrj }
1104dc4f0af1Szrj }
1105dc4f0af1Szrj
1106dc4f0af1Szrj /*
1107dc4f0af1Szrj * *_cpustates(states, names) - print the cpu state percentages
1108dc4f0af1Szrj */
1109dc4f0af1Szrj
1110dc4f0af1Szrj /* cpustates_tag() calculates the correct tag to use to label the line */
1111dc4f0af1Szrj
1112dc4f0af1Szrj char *
cpustates_tag()1113dc4f0af1Szrj cpustates_tag()
1114dc4f0af1Szrj
1115dc4f0af1Szrj {
1116dc4f0af1Szrj register char *use;
1117dc4f0af1Szrj
1118dc4f0af1Szrj static char *short_tag = "CPU: ";
1119dc4f0af1Szrj static char *long_tag = "CPU states: ";
1120dc4f0af1Szrj
1121dc4f0af1Szrj /* if length + strlen(long_tag) >= screen_width, then we have to
1122dc4f0af1Szrj use the shorter tag (we subtract 2 to account for ": ") */
1123dc4f0af1Szrj if (cpustate_total_length + (int)strlen(long_tag) - 2 >= screen_width)
1124dc4f0af1Szrj {
1125dc4f0af1Szrj use = short_tag;
1126dc4f0af1Szrj }
1127dc4f0af1Szrj else
1128dc4f0af1Szrj {
1129dc4f0af1Szrj use = long_tag;
1130dc4f0af1Szrj }
1131dc4f0af1Szrj
1132dc4f0af1Szrj /* set x_cpustates accordingly then return result */
1133dc4f0af1Szrj x_cpustates = strlen(use);
1134dc4f0af1Szrj return(use);
1135dc4f0af1Szrj }
1136dc4f0af1Szrj
1137dc4f0af1Szrj void
i_cpustates(int * states)1138dc4f0af1Szrj i_cpustates(int *states)
1139dc4f0af1Szrj
1140dc4f0af1Szrj {
1141dc4f0af1Szrj int value;
1142dc4f0af1Szrj char **names;
1143dc4f0af1Szrj char *thisname;
1144dc4f0af1Szrj int *colp;
1145dc4f0af1Szrj int color = 0;
1146dc4f0af1Szrj int cpu;
1147dc4f0af1Szrj #ifdef ENABLE_COLOR
1148dc4f0af1Szrj int *cidx = cpustate_cidx;
1149dc4f0af1Szrj #endif
1150dc4f0af1Szrj
1151dc4f0af1Szrj /* initialize */
1152dc4f0af1Szrj names = cpustate_names;
1153dc4f0af1Szrj colp = cpustate_columns;
1154dc4f0af1Szrj
1155dc4f0af1Szrj /* print tag */
1156dc4f0af1Szrj if (enable_ncpus !=0 && n_cpus > 1) {
1157dc4f0af1Szrj for (cpu = 0; cpu < n_cpus; ++cpu) {
1158dc4f0af1Szrj int y_pos = y_cpustates;
1159dc4f0af1Szrj y_pos = y_pos + cpu;
1160dc4f0af1Szrj colp = cpustate_columns;
1161dc4f0af1Szrj names = cpustate_names;
1162dc4f0af1Szrj display_write(0, y_cpustates+cpu, 0, 0, cpustates_tag());
1163dc4f0af1Szrj
1164dc4f0af1Szrj /* now walk thru the names and print the line */
1165dc4f0af1Szrj while ((thisname = *names++) != NULL) {
1166dc4f0af1Szrj if (*thisname != '\0') {
1167dc4f0af1Szrj /* retrieve the value and remember it */
1168dc4f0af1Szrj value = *states;
1169dc4f0af1Szrj
1170dc4f0af1Szrj #ifdef ENABLE_COLOR
1171dc4f0af1Szrj /* determine color number to use */
1172dc4f0af1Szrj color = color_test(*cidx++, value/10);
1173dc4f0af1Szrj #endif
1174dc4f0af1Szrj /* if percentage is >= 1000, print it as 100% */
1175dc4f0af1Szrj display_fmt(x_cpustates + *colp, y_pos,
1176dc4f0af1Szrj color, 0,
1177dc4f0af1Szrj (value >= 1000 ? "%4.0f%% %s%s" : "%4.1f%% %s%s"),
1178dc4f0af1Szrj ((float)value)/10.,
1179dc4f0af1Szrj thisname,
1180dc4f0af1Szrj *names != NULL ? ", " : "");
1181dc4f0af1Szrj
1182dc4f0af1Szrj }
1183dc4f0af1Szrj /* increment */
1184dc4f0af1Szrj colp++;
1185dc4f0af1Szrj states++;
1186dc4f0af1Szrj }
1187dc4f0af1Szrj /* copy over values into "last" array */
1188dc4f0af1Szrj memcpy(lcpustates, states, num_cpustates * sizeof(int));
1189dc4f0af1Szrj }
1190dc4f0af1Szrj } else {
1191dc4f0af1Szrj display_write(0, y_cpustates, 0, 0, cpustates_tag());
1192dc4f0af1Szrj
1193dc4f0af1Szrj /* now walk thru the names and print the line */
1194dc4f0af1Szrj while ((thisname = *names++) != NULL)
1195dc4f0af1Szrj {
1196dc4f0af1Szrj if (*thisname != '\0')
1197dc4f0af1Szrj {
1198dc4f0af1Szrj /* retrieve the value and remember it */
1199dc4f0af1Szrj value = *states;
1200dc4f0af1Szrj
1201dc4f0af1Szrj #ifdef ENABLE_COLOR
1202dc4f0af1Szrj /* determine color number to use */
1203dc4f0af1Szrj color = color_test(*cidx++, value/10);
1204dc4f0af1Szrj #endif
1205dc4f0af1Szrj
1206dc4f0af1Szrj /* if percentage is >= 1000, print it as 100% */
1207dc4f0af1Szrj display_fmt(x_cpustates + *colp, y_cpustates,
1208dc4f0af1Szrj color, 0,
1209dc4f0af1Szrj (value >= 1000 ? "%4.0f%% %s%s" : "%4.1f%% %s%s"),
1210dc4f0af1Szrj ((float)value)/10.,
1211dc4f0af1Szrj thisname,
1212dc4f0af1Szrj *names != NULL ? ", " : "");
1213dc4f0af1Szrj
1214dc4f0af1Szrj }
1215dc4f0af1Szrj /* increment */
1216dc4f0af1Szrj colp++;
1217dc4f0af1Szrj states++;
1218dc4f0af1Szrj }
1219dc4f0af1Szrj
1220dc4f0af1Szrj /* copy over values into "last" array */
1221dc4f0af1Szrj memcpy(lcpustates, states, num_cpustates * sizeof(int));
1222dc4f0af1Szrj }
1223dc4f0af1Szrj
1224dc4f0af1Szrj }
1225dc4f0af1Szrj
1226dc4f0af1Szrj void
u_cpustates(int * states)1227dc4f0af1Szrj u_cpustates(int *states)
1228dc4f0af1Szrj
1229dc4f0af1Szrj {
1230dc4f0af1Szrj int value;
1231dc4f0af1Szrj char **names = cpustate_names;
1232dc4f0af1Szrj char *thisname;
1233dc4f0af1Szrj int *lp;
1234dc4f0af1Szrj int *colp;
1235dc4f0af1Szrj int color = 0;
1236dc4f0af1Szrj int cpu;
1237dc4f0af1Szrj #ifdef ENABLE_COLOR
1238dc4f0af1Szrj int *cidx = cpustate_cidx;
1239dc4f0af1Szrj #endif
1240dc4f0af1Szrj
1241dc4f0af1Szrj
1242dc4f0af1Szrj if (enable_ncpus != 0 && n_cpus > 1 ) {
1243dc4f0af1Szrj for (cpu = 0; cpu < n_cpus; ++cpu) {
1244dc4f0af1Szrj lp = lcpustates;
1245dc4f0af1Szrj int y_pos = y_cpustates;
1246dc4f0af1Szrj y_pos = y_pos + cpu;
1247dc4f0af1Szrj colp = cpustate_columns;
1248dc4f0af1Szrj char **names = cpustate_names;
1249dc4f0af1Szrj /* we could be much more optimal about this */
1250dc4f0af1Szrj while ((thisname = *names++) != NULL) {
1251dc4f0af1Szrj if (*thisname != '\0') {
1252dc4f0af1Szrj /* yes, change it */
1253dc4f0af1Szrj /* retrieve value and remember it */
1254dc4f0af1Szrj value = *states;
1255dc4f0af1Szrj
1256dc4f0af1Szrj #ifdef ENABLE_COLOR
1257dc4f0af1Szrj /* determine color number to use */
1258dc4f0af1Szrj color = color_test(*cidx, value/10);
1259dc4f0af1Szrj #endif
1260dc4f0af1Szrj /* if percentage is >= 1000, print it as 100% */
1261dc4f0af1Szrj display_fmt(x_cpustates + *colp, y_pos, color, 0,
1262dc4f0af1Szrj (value >= 1000 ? "%4.0f" : "%4.1f"),
1263dc4f0af1Szrj ((double)value)/10.);
1264dc4f0af1Szrj
1265dc4f0af1Szrj #ifdef ENABLE_COLOR
1266dc4f0af1Szrj cidx++;
1267dc4f0af1Szrj #endif
1268dc4f0af1Szrj }
1269dc4f0af1Szrj /* increment and move on */
1270dc4f0af1Szrj lp++;
1271dc4f0af1Szrj states++;
1272dc4f0af1Szrj colp++;
1273dc4f0af1Szrj }
1274dc4f0af1Szrj }
1275dc4f0af1Szrj } else {
1276dc4f0af1Szrj lp = lcpustates;
1277dc4f0af1Szrj colp = cpustate_columns;
1278dc4f0af1Szrj
1279dc4f0af1Szrj /* we could be much more optimal about this */
1280dc4f0af1Szrj while ((thisname = *names++) != NULL)
1281dc4f0af1Szrj {
1282dc4f0af1Szrj if (*thisname != '\0')
1283dc4f0af1Szrj {
1284dc4f0af1Szrj /* did the value change since last time? */
1285dc4f0af1Szrj if (*lp != *states)
1286dc4f0af1Szrj {
1287dc4f0af1Szrj /* yes, change it */
1288dc4f0af1Szrj /* retrieve value and remember it */
1289dc4f0af1Szrj value = *states;
1290dc4f0af1Szrj
1291dc4f0af1Szrj #ifdef ENABLE_COLOR
1292dc4f0af1Szrj /* determine color number to use */
1293dc4f0af1Szrj color = color_test(*cidx, value/10);
1294dc4f0af1Szrj #endif
1295dc4f0af1Szrj
1296dc4f0af1Szrj /* if percentage is >= 1000, print it as 100% */
1297dc4f0af1Szrj display_fmt(x_cpustates + *colp, y_cpustates, color, 0,
1298dc4f0af1Szrj (value >= 1000 ? "%4.0f" : "%4.1f"),
1299dc4f0af1Szrj ((double)value)/10.);
1300dc4f0af1Szrj
1301dc4f0af1Szrj /* remember it for next time */
1302dc4f0af1Szrj *lp = value;
1303dc4f0af1Szrj }
1304dc4f0af1Szrj #ifdef ENABLE_COLOR
1305dc4f0af1Szrj cidx++;
1306dc4f0af1Szrj #endif
1307dc4f0af1Szrj }
1308dc4f0af1Szrj
1309dc4f0af1Szrj /* increment and move on */
1310dc4f0af1Szrj lp++;
1311dc4f0af1Szrj states++;
1312dc4f0af1Szrj colp++;
1313dc4f0af1Szrj }
1314dc4f0af1Szrj }
1315dc4f0af1Szrj }
1316dc4f0af1Szrj
1317dc4f0af1Szrj void
z_cpustates()1318dc4f0af1Szrj z_cpustates()
1319dc4f0af1Szrj
1320dc4f0af1Szrj {
1321dc4f0af1Szrj register int i = 0;
1322dc4f0af1Szrj register char **names = cpustate_names;
1323dc4f0af1Szrj register char *thisname;
1324dc4f0af1Szrj register int *lp;
1325dc4f0af1Szrj int cpu;
1326dc4f0af1Szrj
1327dc4f0af1Szrj /* print tag */
1328dc4f0af1Szrj if (enable_ncpus != 0 && n_cpus > 1) {
1329dc4f0af1Szrj for (cpu = 0; cpu < n_cpus; ++cpu) {
1330dc4f0af1Szrj display_write(0, y_cpustates + cpu, 0, 0, cpustates_tag());
1331dc4f0af1Szrj char **names = cpustate_names;
1332dc4f0af1Szrj i = 0;
1333dc4f0af1Szrj while ((thisname = *names++) != NULL) {
1334dc4f0af1Szrj if (*thisname != '\0') {
1335dc4f0af1Szrj display_fmt(-1, -1, 0, 0, "%s %% %s", i++ == 0 ? "" : ", ",
1336dc4f0af1Szrj thisname);
1337dc4f0af1Szrj }
1338dc4f0af1Szrj }
1339dc4f0af1Szrj /* fill the "last" array with all -1s, to insure correct updating */
1340dc4f0af1Szrj lp = lcpustates;
1341dc4f0af1Szrj i = num_cpustates;
1342dc4f0af1Szrj while (--i >= 0) {
1343dc4f0af1Szrj *lp++ = -1;
1344dc4f0af1Szrj }
1345dc4f0af1Szrj }
1346dc4f0af1Szrj } else {
1347dc4f0af1Szrj display_write(0, y_cpustates, 0, 0, cpustates_tag());
1348dc4f0af1Szrj
1349dc4f0af1Szrj while ((thisname = *names++) != NULL)
1350dc4f0af1Szrj {
1351dc4f0af1Szrj if (*thisname != '\0')
1352dc4f0af1Szrj {
1353dc4f0af1Szrj display_fmt(-1, -1, 0, 0, "%s %% %s", i++ == 0 ? "" : ", ",
1354dc4f0af1Szrj thisname);
1355dc4f0af1Szrj }
1356dc4f0af1Szrj }
1357dc4f0af1Szrj
1358dc4f0af1Szrj /* fill the "last" array with all -1s, to insure correct updating */
1359dc4f0af1Szrj lp = lcpustates;
1360dc4f0af1Szrj i = num_cpustates;
1361dc4f0af1Szrj while (--i >= 0)
1362dc4f0af1Szrj {
1363dc4f0af1Szrj *lp++ = -1;
1364dc4f0af1Szrj }
1365dc4f0af1Szrj }
1366dc4f0af1Szrj }
1367dc4f0af1Szrj
1368dc4f0af1Szrj /*
1369dc4f0af1Szrj * *_kernel(stats) - print "Kernel: " followed by the kernel summary string
1370dc4f0af1Szrj *
1371dc4f0af1Szrj * Assumptions: cursor is on "lastline", the previous line
1372dc4f0af1Szrj */
1373dc4f0af1Szrj
1374dc4f0af1Szrj void
i_kernel(int * stats)1375dc4f0af1Szrj i_kernel(int *stats)
1376dc4f0af1Szrj
1377dc4f0af1Szrj {
1378dc4f0af1Szrj if (num_kernel > 0)
1379dc4f0af1Szrj {
1380dc4f0af1Szrj display_write(0, y_kernel, 0, 0, "Kernel: ");
1381dc4f0af1Szrj
1382dc4f0af1Szrj /* format and print the kernel summary */
1383dc4f0af1Szrj summary_format(x_kernel, y_kernel, stats, kernel_names, kernel_cidx);
1384dc4f0af1Szrj }
1385dc4f0af1Szrj }
1386dc4f0af1Szrj
1387dc4f0af1Szrj void
u_kernel(int * stats)1388dc4f0af1Szrj u_kernel(int *stats)
1389dc4f0af1Szrj
1390dc4f0af1Szrj {
1391dc4f0af1Szrj if (num_kernel > 0)
1392dc4f0af1Szrj {
1393dc4f0af1Szrj /* format the new line */
1394dc4f0af1Szrj summary_format(x_kernel, y_kernel, stats, kernel_names, kernel_cidx);
1395dc4f0af1Szrj }
1396dc4f0af1Szrj }
1397dc4f0af1Szrj
1398dc4f0af1Szrj /*
1399dc4f0af1Szrj * *_memory(stats) - print "Memory: " followed by the memory summary string
1400dc4f0af1Szrj *
1401dc4f0af1Szrj * Assumptions: cursor is on "lastline", the previous line
1402dc4f0af1Szrj */
1403dc4f0af1Szrj
1404dc4f0af1Szrj void
i_memory(long * stats)1405dc4f0af1Szrj i_memory(long *stats)
1406dc4f0af1Szrj
1407dc4f0af1Szrj {
1408dc4f0af1Szrj display_write(0, y_mem, 0, 0, "Memory: ");
1409dc4f0af1Szrj
1410dc4f0af1Szrj /* format and print the memory summary */
1411dc4f0af1Szrj summary_format_memory(x_mem, y_mem, stats, memory_names, memory_cidx);
1412dc4f0af1Szrj }
1413dc4f0af1Szrj
1414dc4f0af1Szrj void
u_memory(long * stats)1415dc4f0af1Szrj u_memory(long *stats)
1416dc4f0af1Szrj
1417dc4f0af1Szrj {
1418dc4f0af1Szrj /* format the new line */
1419dc4f0af1Szrj summary_format_memory(x_mem, y_mem, stats, memory_names, memory_cidx);
1420dc4f0af1Szrj }
1421dc4f0af1Szrj
1422dc4f0af1Szrj /*
1423dc4f0af1Szrj * *_swap(stats) - print "Swap: " followed by the swap summary string
1424dc4f0af1Szrj *
1425dc4f0af1Szrj * Assumptions: cursor is on "lastline", the previous line
1426dc4f0af1Szrj *
1427dc4f0af1Szrj * These functions only print something when num_swap > 0
1428dc4f0af1Szrj */
1429dc4f0af1Szrj
1430dc4f0af1Szrj void
i_swap(long * stats)1431dc4f0af1Szrj i_swap(long *stats)
1432dc4f0af1Szrj
1433dc4f0af1Szrj {
1434dc4f0af1Szrj if (num_swap > 0)
1435dc4f0af1Szrj {
1436dc4f0af1Szrj /* print the tag */
1437dc4f0af1Szrj display_write(0, y_swap, 0, 0, "Swap: ");
1438dc4f0af1Szrj
1439dc4f0af1Szrj /* format and print the swap summary */
1440dc4f0af1Szrj summary_format_memory(x_swap, y_swap, stats, swap_names, swap_cidx);
1441dc4f0af1Szrj }
1442dc4f0af1Szrj }
1443dc4f0af1Szrj
1444dc4f0af1Szrj void
u_swap(long * stats)1445dc4f0af1Szrj u_swap(long *stats)
1446dc4f0af1Szrj
1447dc4f0af1Szrj {
1448dc4f0af1Szrj if (num_swap > 0)
1449dc4f0af1Szrj {
1450dc4f0af1Szrj /* format the new line */
1451dc4f0af1Szrj summary_format_memory(x_swap, y_swap, stats, swap_names, swap_cidx);
1452dc4f0af1Szrj }
1453dc4f0af1Szrj }
1454dc4f0af1Szrj
1455dc4f0af1Szrj /*
1456dc4f0af1Szrj * *_message() - print the next pending message line, or erase the one
1457dc4f0af1Szrj * that is there.
1458dc4f0af1Szrj *
1459dc4f0af1Szrj * Note that u_message is (currently) the same as i_message.
1460dc4f0af1Szrj *
1461dc4f0af1Szrj * Assumptions: lastline is consistent
1462dc4f0af1Szrj */
1463dc4f0af1Szrj
1464dc4f0af1Szrj /*
1465dc4f0af1Szrj * i_message is funny because it gets its message asynchronously (with
1466dc4f0af1Szrj * respect to screen updates). Messages are taken out of the
1467dc4f0af1Szrj * circular message_buf and displayed one at a time.
1468dc4f0af1Szrj */
1469dc4f0af1Szrj
1470dc4f0af1Szrj void
i_message(struct timeval * now)1471dc4f0af1Szrj i_message(struct timeval *now)
1472dc4f0af1Szrj
1473dc4f0af1Szrj {
1474dc4f0af1Szrj struct timeval my_now;
1475dc4f0af1Szrj int i = 0;
1476dc4f0af1Szrj
1477dc4f0af1Szrj dprintf("i_message(%08x)\n", now);
1478dc4f0af1Szrj
1479dc4f0af1Szrj /* if now is NULL we have to get it ourselves */
1480dc4f0af1Szrj if (now == NULL)
1481dc4f0af1Szrj {
1482dc4f0af1Szrj time_get(&my_now);
1483dc4f0af1Szrj now = &my_now;
1484dc4f0af1Szrj }
1485dc4f0af1Szrj
1486dc4f0af1Szrj /* now that we have been called, messages no longer need to be held */
1487dc4f0af1Szrj message_hold = 0;
1488dc4f0af1Szrj
1489dc4f0af1Szrj dprintf("i_message: now %d, message_time %d\n",
1490dc4f0af1Szrj now->tv_sec, message_time.tv_sec);
1491dc4f0af1Szrj
1492dc4f0af1Szrj if (smart_terminal)
1493dc4f0af1Szrj {
1494dc4f0af1Szrj /* is it time to change the message? */
1495dc4f0af1Szrj if (timercmp(now, &message_time, > ))
1496dc4f0af1Szrj {
1497dc4f0af1Szrj /* yes, free the current message */
1498dc4f0af1Szrj dprintf("i_message: timer expired\n");
1499dc4f0af1Szrj if (message_current != NULL)
1500dc4f0af1Szrj {
1501dc4f0af1Szrj free(message_current);
1502dc4f0af1Szrj message_current = NULL;
1503dc4f0af1Szrj }
1504dc4f0af1Szrj
1505dc4f0af1Szrj /* is there a new message to be displayed? */
1506dc4f0af1Szrj if (message_first != message_last)
1507dc4f0af1Szrj {
1508dc4f0af1Szrj /* move index to next message */
1509dc4f0af1Szrj if (++message_first == MAX_MESSAGES) message_first = 0;
1510dc4f0af1Szrj
1511dc4f0af1Szrj /* make the next message the current one */
1512dc4f0af1Szrj message_current = message_buf[message_first];
1513dc4f0af1Szrj
1514dc4f0af1Szrj /* show it */
1515dc4f0af1Szrj dprintf("i_message: showing \"%s\"\n", message_current);
1516dc4f0af1Szrj display_move(0, y_message);
1517dc4f0af1Szrj screen_standout(message_current);
1518dc4f0af1Szrj i = strlen(message_current);
1519dc4f0af1Szrj
1520dc4f0af1Szrj /* set the expiration timer */
1521dc4f0af1Szrj message_time = *now;
1522dc4f0af1Szrj message_time.tv_sec += MESSAGE_DISPLAY_TIME;
1523dc4f0af1Szrj
1524dc4f0af1Szrj /* clear the rest of the line */
1525dc4f0af1Szrj screen_cleareol(message_length - i);
1526dc4f0af1Szrj putchar('\r');
1527dc4f0af1Szrj message_length = i;
1528dc4f0af1Szrj }
1529dc4f0af1Szrj else
1530dc4f0af1Szrj {
1531dc4f0af1Szrj /* just clear what was there before, if anything */
1532dc4f0af1Szrj if (message_length > 0)
1533dc4f0af1Szrj {
1534dc4f0af1Szrj display_move(0, y_message);
1535dc4f0af1Szrj screen_cleareol(message_length);
1536dc4f0af1Szrj putchar('\r');
1537dc4f0af1Szrj message_length = 0;
1538dc4f0af1Szrj }
1539dc4f0af1Szrj }
1540dc4f0af1Szrj }
1541dc4f0af1Szrj }
1542dc4f0af1Szrj }
1543dc4f0af1Szrj
1544dc4f0af1Szrj void
u_message(struct timeval * now)1545dc4f0af1Szrj u_message(struct timeval *now)
1546dc4f0af1Szrj
1547dc4f0af1Szrj {
1548dc4f0af1Szrj i_message(now);
1549dc4f0af1Szrj }
1550dc4f0af1Szrj
1551dc4f0af1Szrj static int header_length;
1552dc4f0af1Szrj
1553dc4f0af1Szrj /*
1554dc4f0af1Szrj * *_header(text) - print the header for the process area
1555dc4f0af1Szrj *
1556dc4f0af1Szrj * Assumptions: cursor is on the previous line and lastline is consistent
1557dc4f0af1Szrj */
1558dc4f0af1Szrj
1559dc4f0af1Szrj void
i_header(char * text)1560dc4f0af1Szrj i_header(char *text)
1561dc4f0af1Szrj
1562dc4f0af1Szrj {
1563dc4f0af1Szrj int header_color = 0;
1564dc4f0af1Szrj
1565dc4f0af1Szrj #ifdef ENABLE_COLOR
1566dc4f0af1Szrj header_color = color_test(header_cidx, 0);
1567dc4f0af1Szrj #endif
1568dc4f0af1Szrj header_length = strlen(text);
1569dc4f0af1Szrj if (header_status)
1570dc4f0af1Szrj {
1571dc4f0af1Szrj display_write(x_header, y_header, header_color, 1, text);
1572dc4f0af1Szrj }
1573dc4f0af1Szrj }
1574dc4f0af1Szrj
1575dc4f0af1Szrj /*ARGSUSED*/
1576dc4f0af1Szrj void
u_header(char * text)1577dc4f0af1Szrj u_header(char *text)
1578dc4f0af1Szrj
1579dc4f0af1Szrj {
1580dc4f0af1Szrj int header_color = 0;
1581dc4f0af1Szrj
1582dc4f0af1Szrj #ifdef ENABLE_COLOR
1583dc4f0af1Szrj header_color = color_test(header_cidx, 0);
1584dc4f0af1Szrj #endif
1585dc4f0af1Szrj display_write(x_header, y_header, header_color, 1,
1586dc4f0af1Szrj header_status ? text : "");
1587dc4f0af1Szrj }
1588dc4f0af1Szrj
1589dc4f0af1Szrj /*
1590dc4f0af1Szrj * *_process(line, thisline) - print one process line
1591dc4f0af1Szrj *
1592dc4f0af1Szrj * Assumptions: lastline is consistent
1593dc4f0af1Szrj */
1594dc4f0af1Szrj
1595dc4f0af1Szrj void
i_process(int line,char * thisline)1596dc4f0af1Szrj i_process(int line, char *thisline)
1597dc4f0af1Szrj
1598dc4f0af1Szrj {
1599dc4f0af1Szrj /* truncate the line to conform to our current screen width */
1600dc4f0af1Szrj thisline[display_width] = '\0';
1601dc4f0af1Szrj
1602dc4f0af1Szrj /* write the line out */
1603dc4f0af1Szrj display_write(0, y_procs + line, 0, 1, thisline);
1604dc4f0af1Szrj }
1605dc4f0af1Szrj
1606dc4f0af1Szrj void
u_process(int line,char * new_line)1607dc4f0af1Szrj u_process(int line, char *new_line)
1608dc4f0af1Szrj
1609dc4f0af1Szrj {
1610dc4f0af1Szrj i_process(line, new_line);
1611dc4f0af1Szrj }
1612dc4f0af1Szrj
1613dc4f0af1Szrj void
i_endscreen()1614dc4f0af1Szrj i_endscreen()
1615dc4f0af1Szrj
1616dc4f0af1Szrj {
1617dc4f0af1Szrj if (smart_terminal)
1618dc4f0af1Szrj {
1619dc4f0af1Szrj /* move the cursor to a pleasant place */
1620dc4f0af1Szrj display_move(x_idlecursor, y_idlecursor);
1621dc4f0af1Szrj }
1622dc4f0af1Szrj else
1623dc4f0af1Szrj {
1624dc4f0af1Szrj /* separate this display from the next with some vertical room */
1625dc4f0af1Szrj fputs("\n\n", stdout);
1626dc4f0af1Szrj }
1627dc4f0af1Szrj fflush(stdout);
1628dc4f0af1Szrj }
1629dc4f0af1Szrj
1630dc4f0af1Szrj void
u_endscreen()1631dc4f0af1Szrj u_endscreen()
1632dc4f0af1Szrj
1633dc4f0af1Szrj {
1634dc4f0af1Szrj if (smart_terminal)
1635dc4f0af1Szrj {
1636dc4f0af1Szrj /* clear-to-end the display */
1637dc4f0af1Szrj display_cte();
1638dc4f0af1Szrj
1639dc4f0af1Szrj /* move the cursor to a pleasant place */
1640dc4f0af1Szrj display_move(x_idlecursor, y_idlecursor);
1641dc4f0af1Szrj fflush(stdout);
1642dc4f0af1Szrj }
1643dc4f0af1Szrj else
1644dc4f0af1Szrj {
1645dc4f0af1Szrj /* separate this display from the next with some vertical room */
1646dc4f0af1Szrj fputs("\n\n", stdout);
1647dc4f0af1Szrj }
1648dc4f0af1Szrj }
1649dc4f0af1Szrj
1650dc4f0af1Szrj void
display_header(int t)1651dc4f0af1Szrj display_header(int t)
1652dc4f0af1Szrj
1653dc4f0af1Szrj {
1654dc4f0af1Szrj header_status = t != 0;
1655dc4f0af1Szrj }
1656dc4f0af1Szrj
1657dc4f0af1Szrj void
message_mark()1658dc4f0af1Szrj message_mark()
1659dc4f0af1Szrj
1660dc4f0af1Szrj {
1661dc4f0af1Szrj message_barrier = Yes;
1662dc4f0af1Szrj }
1663dc4f0af1Szrj
1664dc4f0af1Szrj void
message_expire()1665dc4f0af1Szrj message_expire()
1666dc4f0af1Szrj
1667dc4f0af1Szrj {
1668dc4f0af1Szrj message_time.tv_sec = 0;
1669dc4f0af1Szrj message_time.tv_usec = 0;
1670dc4f0af1Szrj }
1671dc4f0af1Szrj
1672dc4f0af1Szrj void
message_flush()1673dc4f0af1Szrj message_flush()
1674dc4f0af1Szrj
1675dc4f0af1Szrj {
1676dc4f0af1Szrj message_first = message_last;
1677dc4f0af1Szrj message_time.tv_sec = 0;
1678dc4f0af1Szrj message_time.tv_usec = 0;
1679dc4f0af1Szrj }
1680dc4f0af1Szrj
1681dc4f0af1Szrj /*
1682dc4f0af1Szrj * void new_message_v(char *msgfmt, va_list ap)
1683dc4f0af1Szrj *
1684dc4f0af1Szrj * Display a message in the message area. This function takes a va_list for
1685dc4f0af1Szrj * the arguments. Safe to call before display_init. This function only
1686dc4f0af1Szrj * queues a message for display, and allowed for multiple messages to be
1687dc4f0af1Szrj * queued. The i_message function drains the queue and actually writes the
1688dc4f0af1Szrj * messages on the display.
1689dc4f0af1Szrj */
1690dc4f0af1Szrj
1691dc4f0af1Szrj
1692dc4f0af1Szrj void
new_message_v(char * msgfmt,va_list ap)1693dc4f0af1Szrj new_message_v(char *msgfmt, va_list ap)
1694dc4f0af1Szrj
1695dc4f0af1Szrj {
1696dc4f0af1Szrj int i;
1697dc4f0af1Szrj int empty;
1698dc4f0af1Szrj char msg[MAX_COLS];
1699dc4f0af1Szrj
1700dc4f0af1Szrj /* if message_barrier is active, remove all pending messages */
1701dc4f0af1Szrj if (message_barrier)
1702dc4f0af1Szrj {
1703dc4f0af1Szrj message_flush();
1704dc4f0af1Szrj message_barrier = No;
1705dc4f0af1Szrj }
1706dc4f0af1Szrj
1707dc4f0af1Szrj /* first, format the message */
1708dc4f0af1Szrj (void) vsnprintf(msg, sizeof(msg), msgfmt, ap);
1709dc4f0af1Szrj
1710dc4f0af1Szrj /* where in the buffer will it go? */
1711dc4f0af1Szrj i = message_last + 1;
1712dc4f0af1Szrj if (i >= MAX_MESSAGES) i = 0;
1713dc4f0af1Szrj
1714dc4f0af1Szrj /* make sure the buffer is not full */
1715dc4f0af1Szrj if (i != message_first)
1716dc4f0af1Szrj {
1717dc4f0af1Szrj /* insert it in to message_buf */
1718dc4f0af1Szrj message_buf[i] = strdup(msg);
1719dc4f0af1Szrj dprintf("new_message_v: new message inserted in slot %d\n", i);
1720dc4f0af1Szrj
1721dc4f0af1Szrj /* remember if the buffer is empty and set the index */
1722dc4f0af1Szrj empty = message_last == message_first;
1723dc4f0af1Szrj message_last = i;
1724dc4f0af1Szrj
1725dc4f0af1Szrj /* is message_buf otherwise empty and have we started displaying? */
1726dc4f0af1Szrj if (empty && !message_hold)
1727dc4f0af1Szrj {
1728dc4f0af1Szrj /* we can display the message now */
1729dc4f0af1Szrj i_message(NULL);
1730dc4f0af1Szrj }
1731dc4f0af1Szrj }
1732dc4f0af1Szrj }
1733dc4f0af1Szrj
1734dc4f0af1Szrj /*
1735dc4f0af1Szrj * void new_message(int type, char *msgfmt, ...)
1736dc4f0af1Szrj *
1737dc4f0af1Szrj * Display a message in the message area. It is safe to call this function
1738dc4f0af1Szrj * before display_init. Messages logged before the display is drawn will be
1739dc4f0af1Szrj * held and displayed later.
1740dc4f0af1Szrj */
1741dc4f0af1Szrj
1742dc4f0af1Szrj void
new_message(char * msgfmt,...)1743dc4f0af1Szrj new_message(char *msgfmt, ...)
1744dc4f0af1Szrj
1745dc4f0af1Szrj {
1746dc4f0af1Szrj va_list ap;
1747dc4f0af1Szrj
1748dc4f0af1Szrj va_start(ap, msgfmt);
1749dc4f0af1Szrj new_message_v(msgfmt, ap);
1750dc4f0af1Szrj va_end(ap);
1751dc4f0af1Szrj }
1752dc4f0af1Szrj
1753dc4f0af1Szrj /*
1754dc4f0af1Szrj * void message_error(char *msgfmt, ...)
1755dc4f0af1Szrj *
1756dc4f0af1Szrj * Put an error message in the message area. It is safe to call this function
1757dc4f0af1Szrj * before display_init. Messages logged before the display is drawn will be
1758dc4f0af1Szrj * held and displayed later.
1759dc4f0af1Szrj */
1760dc4f0af1Szrj
1761dc4f0af1Szrj void
message_error(char * msgfmt,...)1762dc4f0af1Szrj message_error(char *msgfmt, ...)
1763dc4f0af1Szrj
1764dc4f0af1Szrj {
1765dc4f0af1Szrj va_list ap;
1766dc4f0af1Szrj
1767dc4f0af1Szrj va_start(ap, msgfmt);
1768dc4f0af1Szrj new_message_v(msgfmt, ap);
1769dc4f0af1Szrj fflush(stdout);
1770dc4f0af1Szrj va_end(ap);
1771dc4f0af1Szrj }
1772dc4f0af1Szrj
1773dc4f0af1Szrj /*
1774dc4f0af1Szrj * void message_clear()
1775dc4f0af1Szrj *
1776dc4f0af1Szrj * Clear message area and flush all pending messages.
1777dc4f0af1Szrj */
1778dc4f0af1Szrj
1779dc4f0af1Szrj void
message_clear()1780dc4f0af1Szrj message_clear()
1781dc4f0af1Szrj
1782dc4f0af1Szrj {
1783dc4f0af1Szrj /* remove any existing message */
1784dc4f0af1Szrj if (message_current != NULL)
1785dc4f0af1Szrj {
1786dc4f0af1Szrj display_move(0, y_message);
1787dc4f0af1Szrj screen_cleareol(message_length);
1788dc4f0af1Szrj free(message_current);
17895e83d98bSSascha Wildner message_current = NULL;
1790dc4f0af1Szrj }
1791dc4f0af1Szrj
1792dc4f0af1Szrj /* flush all pending messages */
1793dc4f0af1Szrj message_flush();
1794dc4f0af1Szrj }
1795dc4f0af1Szrj
1796dc4f0af1Szrj /*
1797dc4f0af1Szrj * void message_prompt_v(int so, char *msgfmt, va_list ap)
1798dc4f0af1Szrj *
1799dc4f0af1Szrj * Place a prompt in the message area. A prompt is different from a
1800dc4f0af1Szrj * message as follows: it is displayed immediately, overwriting any
1801dc4f0af1Szrj * message that may already be there, it may be highlighted in standout
1802dc4f0af1Szrj * mode (if "so" is true), the cursor is left to rest at the end of the
1803dc4f0af1Szrj * prompt. This call causes all pending messages to be flushed.
1804dc4f0af1Szrj */
1805dc4f0af1Szrj
1806dc4f0af1Szrj void
message_prompt_v(int so,char * msgfmt,va_list ap)1807dc4f0af1Szrj message_prompt_v(int so, char *msgfmt, va_list ap)
1808dc4f0af1Szrj
1809dc4f0af1Szrj {
1810dc4f0af1Szrj char msg[MAX_COLS];
1811dc4f0af1Szrj int i;
1812dc4f0af1Szrj
1813dc4f0af1Szrj /* clear out the message buffer */
1814dc4f0af1Szrj message_flush();
1815dc4f0af1Szrj
1816dc4f0af1Szrj /* format the message */
1817dc4f0af1Szrj i = vsnprintf(msg, sizeof(msg), msgfmt, ap);
1818dc4f0af1Szrj
1819dc4f0af1Szrj /* this goes over any existing message */
1820dc4f0af1Szrj display_move(0, y_message);
1821dc4f0af1Szrj
1822dc4f0af1Szrj /* clear the entire line */
1823dc4f0af1Szrj screen_cleareol(message_length);
1824dc4f0af1Szrj
1825dc4f0af1Szrj /* show the prompt */
1826dc4f0af1Szrj if (so)
1827dc4f0af1Szrj {
1828dc4f0af1Szrj screen_standout(msg);
1829dc4f0af1Szrj }
1830dc4f0af1Szrj else
1831dc4f0af1Szrj {
1832dc4f0af1Szrj fputs(msg, stdout);
1833dc4f0af1Szrj }
1834dc4f0af1Szrj
1835dc4f0af1Szrj /* make it all visible */
1836dc4f0af1Szrj fflush(stdout);
1837dc4f0af1Szrj
1838dc4f0af1Szrj /* even though we dont keep a copy of the prompt, track its length */
1839dc4f0af1Szrj message_length = i < MAX_COLS ? i : MAX_COLS;
1840dc4f0af1Szrj }
1841dc4f0af1Szrj
1842dc4f0af1Szrj /*
1843dc4f0af1Szrj * void message_prompt(char *msgfmt, ...)
1844dc4f0af1Szrj *
1845dc4f0af1Szrj * Place a prompt in the message area (see message_prompt_v).
1846dc4f0af1Szrj */
1847dc4f0af1Szrj
1848dc4f0af1Szrj void
message_prompt(char * msgfmt,...)1849dc4f0af1Szrj message_prompt(char *msgfmt, ...)
1850dc4f0af1Szrj
1851dc4f0af1Szrj {
1852dc4f0af1Szrj va_list ap;
1853dc4f0af1Szrj
1854dc4f0af1Szrj va_start(ap, msgfmt);
1855dc4f0af1Szrj message_prompt_v(Yes, msgfmt, ap);
1856dc4f0af1Szrj va_end(ap);
1857dc4f0af1Szrj }
1858dc4f0af1Szrj
1859dc4f0af1Szrj void
message_prompt_plain(char * msgfmt,...)1860dc4f0af1Szrj message_prompt_plain(char *msgfmt, ...)
1861dc4f0af1Szrj
1862dc4f0af1Szrj {
1863dc4f0af1Szrj va_list ap;
1864dc4f0af1Szrj
1865dc4f0af1Szrj va_start(ap, msgfmt);
1866dc4f0af1Szrj message_prompt_v(No, msgfmt, ap);
1867dc4f0af1Szrj va_end(ap);
1868dc4f0af1Szrj }
1869dc4f0af1Szrj
1870dc4f0af1Szrj /*
1871dc4f0af1Szrj * int readline(char *buffer, int size, int numeric)
1872dc4f0af1Szrj *
1873dc4f0af1Szrj * Read a line of input from the terminal. The line is placed in
1874dc4f0af1Szrj * "buffer" not to exceed "size". If "numeric" is true then the input
1875dc4f0af1Szrj * can only consist of digits. This routine handles all character
1876dc4f0af1Szrj * editing while keeping the terminal in cbreak mode. If "numeric"
1877dc4f0af1Szrj * is true then the number entered is returned. Otherwise the number
1878dc4f0af1Szrj * of character read in to "buffer" is returned.
1879dc4f0af1Szrj */
1880dc4f0af1Szrj
1881dc4f0af1Szrj int
readline(char * buffer,int size,int numeric)1882dc4f0af1Szrj readline(char *buffer, int size, int numeric)
1883dc4f0af1Szrj
1884dc4f0af1Szrj {
1885dc4f0af1Szrj register char *ptr = buffer;
1886dc4f0af1Szrj register char ch;
1887dc4f0af1Szrj register char cnt = 0;
1888dc4f0af1Szrj
1889dc4f0af1Szrj /* allow room for null terminator */
1890dc4f0af1Szrj size -= 1;
1891dc4f0af1Szrj
1892dc4f0af1Szrj /* read loop */
1893dc4f0af1Szrj while ((fflush(stdout), read(0, ptr, 1) > 0))
1894dc4f0af1Szrj {
1895dc4f0af1Szrj /* newline or return means we are done */
1896dc4f0af1Szrj if ((ch = *ptr) == '\n' || ch == '\r')
1897dc4f0af1Szrj {
1898dc4f0af1Szrj break;
1899dc4f0af1Szrj }
1900dc4f0af1Szrj
1901dc4f0af1Szrj /* handle special editing characters */
1902dc4f0af1Szrj if (ch == ch_kill)
1903dc4f0af1Szrj {
1904dc4f0af1Szrj /* return null string */
1905dc4f0af1Szrj *buffer = '\0';
1906dc4f0af1Szrj putchar('\r');
1907dc4f0af1Szrj return(-1);
1908dc4f0af1Szrj }
1909dc4f0af1Szrj else if (ch == ch_werase)
1910dc4f0af1Szrj {
1911dc4f0af1Szrj /* erase previous word */
1912dc4f0af1Szrj if (cnt <= 0)
1913dc4f0af1Szrj {
1914dc4f0af1Szrj /* none to erase! */
1915dc4f0af1Szrj putchar('\7');
1916dc4f0af1Szrj }
1917dc4f0af1Szrj else
1918dc4f0af1Szrj {
1919dc4f0af1Szrj /*
1920dc4f0af1Szrj * First: remove all spaces till the first-non-space
1921dc4f0af1Szrj * Second: remove all non-spaces till the first-space
1922dc4f0af1Szrj */
1923dc4f0af1Szrj while(cnt > 0 && ptr[-1] == ' ')
1924dc4f0af1Szrj {
1925dc4f0af1Szrj fputs("\b \b", stdout);
1926dc4f0af1Szrj ptr--;
1927dc4f0af1Szrj cnt--;
1928dc4f0af1Szrj }
1929dc4f0af1Szrj while(cnt > 0 && ptr[-1] != ' ')
1930dc4f0af1Szrj {
1931dc4f0af1Szrj fputs("\b \b", stdout);
1932dc4f0af1Szrj ptr--;
1933dc4f0af1Szrj cnt--;
1934dc4f0af1Szrj }
1935dc4f0af1Szrj }
1936dc4f0af1Szrj }
1937dc4f0af1Szrj else if (ch == ch_erase)
1938dc4f0af1Szrj {
1939dc4f0af1Szrj /* erase previous character */
1940dc4f0af1Szrj if (cnt <= 0)
1941dc4f0af1Szrj {
1942dc4f0af1Szrj /* none to erase! */
1943dc4f0af1Szrj putchar('\7');
1944dc4f0af1Szrj }
1945dc4f0af1Szrj else
1946dc4f0af1Szrj {
1947dc4f0af1Szrj fputs("\b \b", stdout);
1948dc4f0af1Szrj ptr--;
1949dc4f0af1Szrj cnt--;
1950dc4f0af1Szrj }
1951dc4f0af1Szrj }
1952dc4f0af1Szrj /* check for character validity and buffer overflow */
1953dc4f0af1Szrj else if (cnt == size || (numeric && !isdigit((int)ch)) ||
1954dc4f0af1Szrj !isprint((int)ch))
1955dc4f0af1Szrj {
1956dc4f0af1Szrj /* not legal */
1957dc4f0af1Szrj putchar('\7');
1958dc4f0af1Szrj }
1959dc4f0af1Szrj else
1960dc4f0af1Szrj {
1961dc4f0af1Szrj /* echo it and store it in the buffer */
1962dc4f0af1Szrj putchar(ch);
1963dc4f0af1Szrj ptr++;
1964dc4f0af1Szrj cnt++;
1965dc4f0af1Szrj }
1966dc4f0af1Szrj }
1967dc4f0af1Szrj
1968dc4f0af1Szrj /* all done -- null terminate the string */
1969dc4f0af1Szrj *ptr = '\0';
1970dc4f0af1Szrj
1971dc4f0af1Szrj /* add response length to message_length */
1972dc4f0af1Szrj message_length += cnt;
1973dc4f0af1Szrj
1974dc4f0af1Szrj /* return either inputted number or string length */
1975dc4f0af1Szrj putchar('\r');
1976dc4f0af1Szrj return(cnt == 0 ? -1 : numeric ? atoi(buffer) : cnt);
1977dc4f0af1Szrj }
1978dc4f0af1Szrj
1979dc4f0af1Szrj void
display_pagerstart()1980dc4f0af1Szrj display_pagerstart()
1981dc4f0af1Szrj
1982dc4f0af1Szrj {
1983dc4f0af1Szrj display_clear();
1984dc4f0af1Szrj }
1985dc4f0af1Szrj
1986dc4f0af1Szrj void
display_pagerend()1987dc4f0af1Szrj display_pagerend()
1988dc4f0af1Szrj
1989dc4f0af1Szrj {
1990dc4f0af1Szrj char ch;
1991dc4f0af1Szrj
1992dc4f0af1Szrj screen_standout("Hit any key to continue: ");
1993dc4f0af1Szrj fflush(stdout);
1994dc4f0af1Szrj (void) read(0, &ch, 1);
1995dc4f0af1Szrj }
1996dc4f0af1Szrj
1997dc4f0af1Szrj void
display_pager(char * fmt,...)1998dc4f0af1Szrj display_pager(char *fmt, ...)
1999dc4f0af1Szrj
2000dc4f0af1Szrj {
2001dc4f0af1Szrj va_list ap;
2002dc4f0af1Szrj
2003dc4f0af1Szrj int ch;
2004dc4f0af1Szrj char readch;
2005dc4f0af1Szrj char buffer[MAX_COLS];
2006dc4f0af1Szrj char *data;
2007dc4f0af1Szrj
2008dc4f0af1Szrj /* format into buffer */
2009dc4f0af1Szrj va_start(ap, fmt);
2010dc4f0af1Szrj (void) vsnprintf(buffer, MAX_COLS, fmt, ap);
2011dc4f0af1Szrj va_end(ap);
2012dc4f0af1Szrj data = buffer;
2013dc4f0af1Szrj
2014dc4f0af1Szrj while ((ch = *data++) != '\0')
2015dc4f0af1Szrj {
2016dc4f0af1Szrj putchar(ch);
2017dc4f0af1Szrj if (ch == '\n')
2018dc4f0af1Szrj {
2019dc4f0af1Szrj if (++curr_y >= screen_length - 1)
2020dc4f0af1Szrj {
2021dc4f0af1Szrj screen_standout("...More...");
2022dc4f0af1Szrj fflush(stdout);
2023dc4f0af1Szrj (void) read(0, &readch, 1);
2024dc4f0af1Szrj putchar('\r');
2025dc4f0af1Szrj switch(readch)
2026dc4f0af1Szrj {
2027dc4f0af1Szrj case '\r':
2028dc4f0af1Szrj case '\n':
2029dc4f0af1Szrj curr_y--;
2030dc4f0af1Szrj break;
2031dc4f0af1Szrj
2032dc4f0af1Szrj case 'q':
2033dc4f0af1Szrj return;
2034dc4f0af1Szrj
2035dc4f0af1Szrj default:
2036dc4f0af1Szrj curr_y = 0;
2037dc4f0af1Szrj }
2038dc4f0af1Szrj }
2039dc4f0af1Szrj }
2040dc4f0af1Szrj }
2041dc4f0af1Szrj }
2042