13be6ef06SEitan Adler /*
23be6ef06SEitan Adler * Top users/processes display for Unix
33be6ef06SEitan Adler * Version 3
43be6ef06SEitan Adler *
53be6ef06SEitan Adler * This program may be freely redistributed,
63be6ef06SEitan Adler * but this entire comment MUST remain intact.
73be6ef06SEitan Adler *
83be6ef06SEitan Adler * Copyright (c) 1984, 1989, William LeFebvre, Rice University
93be6ef06SEitan Adler * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
103be6ef06SEitan Adler */
113be6ef06SEitan Adler
123be6ef06SEitan Adler /*
133be6ef06SEitan Adler * This file contains the routines that display information on the screen.
143be6ef06SEitan Adler * Each section of the screen has two routines: one for initially writing
153be6ef06SEitan Adler * all constant and dynamic text, and one for only updating the text that
163be6ef06SEitan Adler * changes. The prefix "i_" is used on all the "initial" routines and the
173be6ef06SEitan Adler * prefix "u_" is used for all the "updating" routines.
183be6ef06SEitan Adler *
193be6ef06SEitan Adler * ASSUMPTIONS:
203be6ef06SEitan Adler * None of the "i_" routines use any of the termcap capabilities.
213be6ef06SEitan Adler * In this way, those routines can be safely used on terminals that
223be6ef06SEitan Adler * have minimal (or nonexistant) terminal capabilities.
233be6ef06SEitan Adler *
243be6ef06SEitan Adler * The routines are called in this order: *_loadave, i_timeofday,
253be6ef06SEitan Adler * *_procstates, *_cpustates, *_memory, *_message, *_header,
263be6ef06SEitan Adler * *_process, u_endscreen.
273be6ef06SEitan Adler */
283be6ef06SEitan Adler
298d0d2676SEitan Adler #include <sys/cdefs.h>
30eae589f1SEitan Adler #include <sys/resource.h>
313be6ef06SEitan Adler #include <sys/time.h>
323be6ef06SEitan Adler
33cffee2bcSEitan Adler #include <assert.h>
343be6ef06SEitan Adler #include <ctype.h>
3517be5f23SEitan Adler #include <err.h>
361d6a4ba3SEitan Adler #include <stdarg.h>
370b2f6ed1SEitan Adler #include <stdbool.h>
38caee4883SEitan Adler #include <stdlib.h>
398d0d2676SEitan Adler #include <stdio.h>
40caee4883SEitan Adler #include <string.h>
413be6ef06SEitan Adler #include <termcap.h>
423be6ef06SEitan Adler #include <time.h>
433be6ef06SEitan Adler #include <unistd.h>
443be6ef06SEitan Adler
453be6ef06SEitan Adler #include "screen.h" /* interface to screen package */
463be6ef06SEitan Adler #include "layout.h" /* defines for screen position layout */
473be6ef06SEitan Adler #include "display.h"
483be6ef06SEitan Adler #include "top.h"
493be6ef06SEitan Adler #include "machine.h" /* we should eliminate this!!! */
503be6ef06SEitan Adler #include "utils.h"
513be6ef06SEitan Adler
523be6ef06SEitan Adler #ifdef DEBUG
533be6ef06SEitan Adler FILE *debug;
543be6ef06SEitan Adler #endif
553be6ef06SEitan Adler
563be6ef06SEitan Adler static int lmpid = 0;
573be6ef06SEitan Adler static int last_hi = 0; /* used in u_process and u_endscreen */
583be6ef06SEitan Adler static int lastline = 0;
593be6ef06SEitan Adler
600a59db87SDaichi GOTO #define lineindex(l) ((l)*screen_width)
613be6ef06SEitan Adler
623be6ef06SEitan Adler
633be6ef06SEitan Adler /* things initialized by display_init and used thruout */
643be6ef06SEitan Adler
653be6ef06SEitan Adler /* buffer of proc information lines for display updating */
66a5ca08edSEitan Adler static char *screenbuf = NULL;
673be6ef06SEitan Adler
689f8096e3SEitan Adler static const char * const *procstate_names;
699f8096e3SEitan Adler static const char * const *cpustate_names;
709f8096e3SEitan Adler static const char * const *memory_names;
719f8096e3SEitan Adler static const char * const *arc_names;
729f8096e3SEitan Adler static const char * const *carc_names;
739f8096e3SEitan Adler static const char * const *swap_names;
743be6ef06SEitan Adler
753be6ef06SEitan Adler static int num_procstates;
763be6ef06SEitan Adler static int num_cpustates;
773be6ef06SEitan Adler static int num_memory;
783be6ef06SEitan Adler static int num_swap;
793be6ef06SEitan Adler
803be6ef06SEitan Adler static int *lprocstates;
813be6ef06SEitan Adler static int *lcpustates;
823be6ef06SEitan Adler static int *lmemory;
833be6ef06SEitan Adler static int *lswap;
843be6ef06SEitan Adler
853be6ef06SEitan Adler static int num_cpus;
863be6ef06SEitan Adler static int *cpustate_columns;
873be6ef06SEitan Adler static int cpustate_total_length;
883be6ef06SEitan Adler static int cpustates_column;
893be6ef06SEitan Adler
903be6ef06SEitan Adler static enum { OFF, ON, ERASE } header_status = ON;
913be6ef06SEitan Adler
92eae589f1SEitan Adler static void summary_format(char *, int *, const char * const *);
93666cf873SEitan Adler static void line_update(char *, char *, int, int);
943be6ef06SEitan Adler
950a59db87SDaichi GOTO static int setup_buffer_bufsiz = 0;
960a59db87SDaichi GOTO static char * setup_buffer(char *, int);
970a59db87SDaichi GOTO
983be6ef06SEitan Adler int x_lastpid = 10;
993be6ef06SEitan Adler int y_lastpid = 0;
1003be6ef06SEitan Adler int x_loadave = 33;
1013be6ef06SEitan Adler int x_loadave_nompid = 15;
1023be6ef06SEitan Adler int y_loadave = 0;
1033be6ef06SEitan Adler int x_procstate = 0;
1043be6ef06SEitan Adler int y_procstate = 1;
1053be6ef06SEitan Adler int x_brkdn = 15;
1063be6ef06SEitan Adler int y_brkdn = 1;
1073be6ef06SEitan Adler int x_mem = 5;
1083be6ef06SEitan Adler int y_mem = 3;
1093be6ef06SEitan Adler int x_arc = 5;
1103be6ef06SEitan Adler int y_arc = 4;
1113be6ef06SEitan Adler int x_carc = 5;
1123be6ef06SEitan Adler int y_carc = 5;
1133be6ef06SEitan Adler int x_swap = 6;
1143be6ef06SEitan Adler int y_swap = 4;
1153be6ef06SEitan Adler int y_message = 5;
1163be6ef06SEitan Adler int x_header = 0;
1173be6ef06SEitan Adler int y_header = 6;
1183be6ef06SEitan Adler int x_idlecursor = 0;
1193be6ef06SEitan Adler int y_idlecursor = 5;
1203be6ef06SEitan Adler int y_procs = 7;
1213be6ef06SEitan Adler
1223be6ef06SEitan Adler int y_cpustates = 2;
1233be6ef06SEitan Adler int Header_lines = 7;
1243be6ef06SEitan Adler
125f6234b51SEitan Adler int
display_resize(void)126f6234b51SEitan Adler display_resize(void)
1273be6ef06SEitan Adler {
12898c299e0SEitan Adler int lines;
1293be6ef06SEitan Adler
1303be6ef06SEitan Adler /* first, deallocate any previous buffer that may have been there */
1313be6ef06SEitan Adler if (screenbuf != NULL)
1323be6ef06SEitan Adler {
1333be6ef06SEitan Adler free(screenbuf);
1343be6ef06SEitan Adler }
1353be6ef06SEitan Adler
1363be6ef06SEitan Adler /* calculate the current dimensions */
1373be6ef06SEitan Adler /* if operating in "dumb" mode, we only need one line */
1383be6ef06SEitan Adler lines = smart_terminal ? screen_length - Header_lines : 1;
1393be6ef06SEitan Adler
1403be6ef06SEitan Adler if (lines < 0)
1413be6ef06SEitan Adler lines = 0;
1423be6ef06SEitan Adler
1433be6ef06SEitan Adler /* now, allocate space for the screen buffer */
1440a59db87SDaichi GOTO screenbuf = calloc(lines, screen_width);
1454fedcd49SEitan Adler if (screenbuf == NULL)
1463be6ef06SEitan Adler {
1473be6ef06SEitan Adler /* oops! */
1483be6ef06SEitan Adler return(-1);
1493be6ef06SEitan Adler }
1503be6ef06SEitan Adler
1513be6ef06SEitan Adler /* return number of lines available */
1523be6ef06SEitan Adler /* for dumb terminals, pretend like we can show any amount */
1533be6ef06SEitan Adler return(smart_terminal ? lines : Largest);
1543be6ef06SEitan Adler }
1553be6ef06SEitan Adler
1561de63842SEitan Adler int
display_updatecpus(struct statics * statics)1571de63842SEitan Adler display_updatecpus(struct statics *statics)
1583be6ef06SEitan Adler {
15998c299e0SEitan Adler int lines;
16098c299e0SEitan Adler int i;
1613be6ef06SEitan Adler
1623be6ef06SEitan Adler /* call resize to do the dirty work */
1633be6ef06SEitan Adler lines = display_resize();
1643be6ef06SEitan Adler if (pcpu_stats)
1653be6ef06SEitan Adler num_cpus = statics->ncpus;
1663be6ef06SEitan Adler else
1673be6ef06SEitan Adler num_cpus = 1;
1683be6ef06SEitan Adler cpustates_column = 5; /* CPU: */
1696e0632dbSEitan Adler if (num_cpus > 1) {
1706e0632dbSEitan Adler cpustates_column += 1 + digits(num_cpus); /* CPU #: */
1716e0632dbSEitan Adler }
1723be6ef06SEitan Adler
1733be6ef06SEitan Adler /* fill the "last" array with all -1s, to insure correct updating */
1746e0632dbSEitan Adler for (i = 0; i < num_cpustates * num_cpus; ++i) {
1756e0632dbSEitan Adler lcpustates[i] = -1;
1763be6ef06SEitan Adler }
1773be6ef06SEitan Adler
1783be6ef06SEitan Adler return(lines);
1793be6ef06SEitan Adler }
1803be6ef06SEitan Adler
1811de63842SEitan Adler int
display_init(struct statics * statics)1821de63842SEitan Adler display_init(struct statics * statics)
1833be6ef06SEitan Adler {
18498c299e0SEitan Adler int lines;
185d0f687d3SDimitry Andric const char * const *pp;
18698c299e0SEitan Adler int *ip;
18798c299e0SEitan Adler int i;
1883be6ef06SEitan Adler
1893be6ef06SEitan Adler lines = display_updatecpus(statics);
1903be6ef06SEitan Adler
1913be6ef06SEitan Adler /* only do the rest if we need to */
1923be6ef06SEitan Adler if (lines > -1)
1933be6ef06SEitan Adler {
1943be6ef06SEitan Adler /* save pointers and allocate space for names */
1953be6ef06SEitan Adler procstate_names = statics->procstate_names;
196eae589f1SEitan Adler num_procstates = 8;
197cffee2bcSEitan Adler assert(num_procstates > 0);
1984fedcd49SEitan Adler lprocstates = calloc(num_procstates, sizeof(int));
1993be6ef06SEitan Adler
2003be6ef06SEitan Adler cpustate_names = statics->cpustate_names;
2013be6ef06SEitan Adler
2023be6ef06SEitan Adler swap_names = statics->swap_names;
203eae589f1SEitan Adler num_swap = 7;
204cffee2bcSEitan Adler assert(num_swap > 0);
2054fedcd49SEitan Adler lswap = calloc(num_swap, sizeof(int));
206eae589f1SEitan Adler num_cpustates = CPUSTATES;
207cffee2bcSEitan Adler assert(num_cpustates > 0);
2084fedcd49SEitan Adler lcpustates = calloc(num_cpustates * sizeof(int), statics->ncpus);
2094fedcd49SEitan Adler cpustate_columns = calloc(num_cpustates, sizeof(int));
2103be6ef06SEitan Adler
2113be6ef06SEitan Adler memory_names = statics->memory_names;
212eae589f1SEitan Adler num_memory = 7;
213cffee2bcSEitan Adler assert(num_memory > 0);
2144fedcd49SEitan Adler lmemory = calloc(num_memory, sizeof(int));
2153be6ef06SEitan Adler
2163be6ef06SEitan Adler arc_names = statics->arc_names;
2173be6ef06SEitan Adler carc_names = statics->carc_names;
2183be6ef06SEitan Adler
2193be6ef06SEitan Adler /* calculate starting columns where needed */
2203be6ef06SEitan Adler cpustate_total_length = 0;
2213be6ef06SEitan Adler pp = cpustate_names;
2223be6ef06SEitan Adler ip = cpustate_columns;
2233be6ef06SEitan Adler while (*pp != NULL)
2243be6ef06SEitan Adler {
2253be6ef06SEitan Adler *ip++ = cpustate_total_length;
2263be6ef06SEitan Adler if ((i = strlen(*pp++)) > 0)
2273be6ef06SEitan Adler {
2283be6ef06SEitan Adler cpustate_total_length += i + 8;
2293be6ef06SEitan Adler }
2303be6ef06SEitan Adler }
2313be6ef06SEitan Adler }
2323be6ef06SEitan Adler
2333be6ef06SEitan Adler /* return number of lines available */
2343be6ef06SEitan Adler return(lines);
2353be6ef06SEitan Adler }
2363be6ef06SEitan Adler
2373be6ef06SEitan Adler void
i_loadave(int mpid,double avenrun[])238f6234b51SEitan Adler i_loadave(int mpid, double avenrun[])
2393be6ef06SEitan Adler {
24098c299e0SEitan Adler int i;
2413be6ef06SEitan Adler
2423be6ef06SEitan Adler /* i_loadave also clears the screen, since it is first */
2433be6ef06SEitan Adler top_clear();
2443be6ef06SEitan Adler
2453be6ef06SEitan Adler /* mpid == -1 implies this system doesn't have an _mpid */
2463be6ef06SEitan Adler if (mpid != -1)
2473be6ef06SEitan Adler {
2483be6ef06SEitan Adler printf("last pid: %5d; ", mpid);
2493be6ef06SEitan Adler }
2503be6ef06SEitan Adler
2513be6ef06SEitan Adler printf("load averages");
2523be6ef06SEitan Adler
2533be6ef06SEitan Adler for (i = 0; i < 3; i++)
2543be6ef06SEitan Adler {
255*b7f62c60SPiotr Kubaj printf("%c %7.2f",
2563be6ef06SEitan Adler i == 0 ? ':' : ',',
2573be6ef06SEitan Adler avenrun[i]);
2583be6ef06SEitan Adler }
2593be6ef06SEitan Adler lmpid = mpid;
2603be6ef06SEitan Adler }
2613be6ef06SEitan Adler
2623be6ef06SEitan Adler void
u_loadave(int mpid,double * avenrun)263f6234b51SEitan Adler u_loadave(int mpid, double *avenrun)
2643be6ef06SEitan Adler {
26598c299e0SEitan Adler int i;
2663be6ef06SEitan Adler
2673be6ef06SEitan Adler if (mpid != -1)
2683be6ef06SEitan Adler {
2693be6ef06SEitan Adler /* change screen only when value has really changed */
2703be6ef06SEitan Adler if (mpid != lmpid)
2713be6ef06SEitan Adler {
2723be6ef06SEitan Adler Move_to(x_lastpid, y_lastpid);
2733be6ef06SEitan Adler printf("%5d", mpid);
2743be6ef06SEitan Adler lmpid = mpid;
2753be6ef06SEitan Adler }
2763be6ef06SEitan Adler
2773be6ef06SEitan Adler /* i remembers x coordinate to move to */
2783be6ef06SEitan Adler i = x_loadave;
2793be6ef06SEitan Adler }
2803be6ef06SEitan Adler else
2813be6ef06SEitan Adler {
2823be6ef06SEitan Adler i = x_loadave_nompid;
2833be6ef06SEitan Adler }
2843be6ef06SEitan Adler
2853be6ef06SEitan Adler /* move into position for load averages */
2863be6ef06SEitan Adler Move_to(i, y_loadave);
2873be6ef06SEitan Adler
2883be6ef06SEitan Adler /* display new load averages */
2893be6ef06SEitan Adler /* we should optimize this and only display changes */
2903be6ef06SEitan Adler for (i = 0; i < 3; i++)
2913be6ef06SEitan Adler {
292*b7f62c60SPiotr Kubaj printf("%s%7.2f",
2933be6ef06SEitan Adler i == 0 ? "" : ", ",
2943be6ef06SEitan Adler avenrun[i]);
2953be6ef06SEitan Adler }
2963be6ef06SEitan Adler }
2973be6ef06SEitan Adler
2983be6ef06SEitan Adler void
i_timeofday(time_t * tod)299f6234b51SEitan Adler i_timeofday(time_t *tod)
3003be6ef06SEitan Adler {
3013be6ef06SEitan Adler /*
3023be6ef06SEitan Adler * Display the current time.
3033be6ef06SEitan Adler * "ctime" always returns a string that looks like this:
3043be6ef06SEitan Adler *
3053be6ef06SEitan Adler * Sun Sep 16 01:03:52 1973
3063be6ef06SEitan Adler * 012345678901234567890123
3073be6ef06SEitan Adler * 1 2
3083be6ef06SEitan Adler *
3093be6ef06SEitan Adler * We want indices 11 thru 18 (length 8).
3103be6ef06SEitan Adler */
3113be6ef06SEitan Adler
3123be6ef06SEitan Adler if (smart_terminal)
3133be6ef06SEitan Adler {
3143be6ef06SEitan Adler Move_to(screen_width - 8, 0);
3153be6ef06SEitan Adler }
3163be6ef06SEitan Adler else
3173be6ef06SEitan Adler {
3183be6ef06SEitan Adler fputs(" ", stdout);
3193be6ef06SEitan Adler }
3203be6ef06SEitan Adler #ifdef DEBUG
3213be6ef06SEitan Adler {
3223be6ef06SEitan Adler char *foo;
3233be6ef06SEitan Adler foo = ctime(tod);
3243be6ef06SEitan Adler fputs(foo, stdout);
3253be6ef06SEitan Adler }
3263be6ef06SEitan Adler #endif
3273be6ef06SEitan Adler printf("%-8.8s\n", &(ctime(tod)[11]));
3283be6ef06SEitan Adler lastline = 1;
3293be6ef06SEitan Adler }
3303be6ef06SEitan Adler
3313be6ef06SEitan Adler static int ltotal = 0;
3320a59db87SDaichi GOTO static char *procstates_buffer = NULL;
3333be6ef06SEitan Adler
3343be6ef06SEitan Adler /*
3353be6ef06SEitan Adler * *_procstates(total, brkdn, names) - print the process summary line
3363be6ef06SEitan Adler *
3373be6ef06SEitan Adler * Assumptions: cursor is at the beginning of the line on entry
3383be6ef06SEitan Adler * lastline is valid
3393be6ef06SEitan Adler */
3403be6ef06SEitan Adler
3413be6ef06SEitan Adler void
i_procstates(int total,int * brkdn)342f6234b51SEitan Adler i_procstates(int total, int *brkdn)
3433be6ef06SEitan Adler {
34498c299e0SEitan Adler int i;
3453be6ef06SEitan Adler
3460a59db87SDaichi GOTO procstates_buffer = setup_buffer(procstates_buffer, 0);
3470a59db87SDaichi GOTO
3483be6ef06SEitan Adler /* write current number of processes and remember the value */
34904354d57SMark Johnston printf("%d %s:", total, ps.thread ? "threads" : "processes");
3503be6ef06SEitan Adler ltotal = total;
3513be6ef06SEitan Adler
3523be6ef06SEitan Adler /* put out enough spaces to get to column 15 */
3533be6ef06SEitan Adler i = digits(total);
35404354d57SMark Johnston while (i++ < (ps.thread ? 6 : 4))
3553be6ef06SEitan Adler {
3563be6ef06SEitan Adler putchar(' ');
3573be6ef06SEitan Adler }
3583be6ef06SEitan Adler
3593be6ef06SEitan Adler /* format and print the process state summary */
3603be6ef06SEitan Adler summary_format(procstates_buffer, brkdn, procstate_names);
3613be6ef06SEitan Adler fputs(procstates_buffer, stdout);
3623be6ef06SEitan Adler
3633be6ef06SEitan Adler /* save the numbers for next time */
3643be6ef06SEitan Adler memcpy(lprocstates, brkdn, num_procstates * sizeof(int));
3653be6ef06SEitan Adler }
3663be6ef06SEitan Adler
3673be6ef06SEitan Adler void
u_procstates(int total,int * brkdn)368f6234b51SEitan Adler u_procstates(int total, int *brkdn)
3693be6ef06SEitan Adler {
3700a59db87SDaichi GOTO static char *new = NULL;
37198c299e0SEitan Adler int i;
3723be6ef06SEitan Adler
3730a59db87SDaichi GOTO new = setup_buffer(new, 0);
3740a59db87SDaichi GOTO
3753be6ef06SEitan Adler /* update number of processes only if it has changed */
3763be6ef06SEitan Adler if (ltotal != total)
3773be6ef06SEitan Adler {
3783be6ef06SEitan Adler /* move and overwrite */
37959c50d82SEitan Adler if (x_procstate == 0) {
3803be6ef06SEitan Adler Move_to(x_procstate, y_procstate);
38159c50d82SEitan Adler }
38259c50d82SEitan Adler else {
3833be6ef06SEitan Adler /* cursor is already there...no motion needed */
38459c50d82SEitan Adler assert(lastline == 1);
38559c50d82SEitan Adler }
3863be6ef06SEitan Adler printf("%d", total);
3873be6ef06SEitan Adler
3883be6ef06SEitan Adler /* if number of digits differs, rewrite the label */
3893be6ef06SEitan Adler if (digits(total) != digits(ltotal))
3903be6ef06SEitan Adler {
39104354d57SMark Johnston printf(" %s:", ps.thread ? "threads" : "processes");
3923be6ef06SEitan Adler /* put out enough spaces to get to column 15 */
3933be6ef06SEitan Adler i = digits(total);
39404354d57SMark Johnston while (i++ < (ps.thread ? 6 : 4))
3953be6ef06SEitan Adler {
3963be6ef06SEitan Adler putchar(' ');
3973be6ef06SEitan Adler }
3983be6ef06SEitan Adler /* cursor may end up right where we want it!!! */
3993be6ef06SEitan Adler }
4003be6ef06SEitan Adler
4013be6ef06SEitan Adler /* save new total */
4023be6ef06SEitan Adler ltotal = total;
4033be6ef06SEitan Adler }
4043be6ef06SEitan Adler
4053be6ef06SEitan Adler /* see if any of the state numbers has changed */
4063be6ef06SEitan Adler if (memcmp(lprocstates, brkdn, num_procstates * sizeof(int)) != 0)
4073be6ef06SEitan Adler {
4083be6ef06SEitan Adler /* format and update the line */
4093be6ef06SEitan Adler summary_format(new, brkdn, procstate_names);
4103be6ef06SEitan Adler line_update(procstates_buffer, new, x_brkdn, y_brkdn);
4113be6ef06SEitan Adler memcpy(lprocstates, brkdn, num_procstates * sizeof(int));
4123be6ef06SEitan Adler }
4133be6ef06SEitan Adler }
4143be6ef06SEitan Adler
4153be6ef06SEitan Adler void
i_cpustates(int * states)416f6234b51SEitan Adler i_cpustates(int *states)
4173be6ef06SEitan Adler {
41898c299e0SEitan Adler int i = 0;
41998c299e0SEitan Adler int value;
420eae589f1SEitan Adler const char * const *names;
421eae589f1SEitan Adler const char *thisname;
42208092a9bSDaichi GOTO int *hstates = states;
4233be6ef06SEitan Adler int cpu;
4243be6ef06SEitan Adler
4253be6ef06SEitan Adler for (cpu = 0; cpu < num_cpus; cpu++) {
4263be6ef06SEitan Adler names = cpustate_names;
4273be6ef06SEitan Adler
4283be6ef06SEitan Adler /* print tag and bump lastline */
4293be6ef06SEitan Adler if (num_cpus == 1)
4303be6ef06SEitan Adler printf("\nCPU: ");
4313be6ef06SEitan Adler else {
4323be6ef06SEitan Adler value = printf("\nCPU %d: ", cpu);
4333be6ef06SEitan Adler while (value++ <= cpustates_column)
4343be6ef06SEitan Adler printf(" ");
4353be6ef06SEitan Adler }
4363be6ef06SEitan Adler lastline++;
4373be6ef06SEitan Adler
4383be6ef06SEitan Adler /* now walk thru the names and print the line */
4393be6ef06SEitan Adler while ((thisname = *names++) != NULL)
4403be6ef06SEitan Adler {
4413be6ef06SEitan Adler if (*thisname != '\0')
4423be6ef06SEitan Adler {
4433be6ef06SEitan Adler /* retrieve the value and remember it */
4443be6ef06SEitan Adler value = *states++;
4453be6ef06SEitan Adler
4463be6ef06SEitan Adler /* if percentage is >= 1000, print it as 100% */
4473be6ef06SEitan Adler printf((value >= 1000 ? "%s%4.0f%% %s" : "%s%4.1f%% %s"),
4483be6ef06SEitan Adler (i++ % num_cpustates) == 0 ? "" : ", ",
4493be6ef06SEitan Adler ((float)value)/10.,
4503be6ef06SEitan Adler thisname);
4513be6ef06SEitan Adler }
4523be6ef06SEitan Adler }
4533be6ef06SEitan Adler }
4543be6ef06SEitan Adler
4553be6ef06SEitan Adler /* copy over values into "last" array */
45608092a9bSDaichi GOTO states = hstates;
4573be6ef06SEitan Adler memcpy(lcpustates, states, num_cpustates * sizeof(int) * num_cpus);
4583be6ef06SEitan Adler }
4593be6ef06SEitan Adler
4603be6ef06SEitan Adler void
u_cpustates(int * states)461f6234b51SEitan Adler u_cpustates(int *states)
4623be6ef06SEitan Adler {
46398c299e0SEitan Adler int value;
464d408c8f7SEitan Adler const char * const *names;
465d408c8f7SEitan Adler const char *thisname;
46608092a9bSDaichi GOTO int *hstates = states;
46798c299e0SEitan Adler int *lp;
46898c299e0SEitan Adler int *colp;
4693be6ef06SEitan Adler int cpu;
4703be6ef06SEitan Adler
4713be6ef06SEitan Adler for (cpu = 0; cpu < num_cpus; cpu++) {
4723be6ef06SEitan Adler names = cpustate_names;
4733be6ef06SEitan Adler
4743be6ef06SEitan Adler Move_to(cpustates_column, y_cpustates + cpu);
4753be6ef06SEitan Adler lastline = y_cpustates + cpu;
4763be6ef06SEitan Adler lp = lcpustates + (cpu * num_cpustates);
4773be6ef06SEitan Adler colp = cpustate_columns;
4783be6ef06SEitan Adler
4793be6ef06SEitan Adler /* we could be much more optimal about this */
4803be6ef06SEitan Adler while ((thisname = *names++) != NULL)
4813be6ef06SEitan Adler {
4823be6ef06SEitan Adler if (*thisname != '\0')
4833be6ef06SEitan Adler {
4843be6ef06SEitan Adler /* did the value change since last time? */
4853be6ef06SEitan Adler if (*lp != *states)
4863be6ef06SEitan Adler {
4873be6ef06SEitan Adler /* yes, move and change */
4883be6ef06SEitan Adler Move_to(cpustates_column + *colp, y_cpustates + cpu);
4893be6ef06SEitan Adler lastline = y_cpustates + cpu;
4903be6ef06SEitan Adler
4913be6ef06SEitan Adler /* retrieve value and remember it */
4923be6ef06SEitan Adler value = *states;
4933be6ef06SEitan Adler
4943be6ef06SEitan Adler /* if percentage is >= 1000, print it as 100% */
4953be6ef06SEitan Adler printf((value >= 1000 ? "%4.0f" : "%4.1f"),
4963be6ef06SEitan Adler ((double)value)/10.);
4973be6ef06SEitan Adler
4983be6ef06SEitan Adler /* remember it for next time */
4993be6ef06SEitan Adler *lp = value;
5003be6ef06SEitan Adler }
5013be6ef06SEitan Adler }
5023be6ef06SEitan Adler
5033be6ef06SEitan Adler /* increment and move on */
5043be6ef06SEitan Adler lp++;
5053be6ef06SEitan Adler states++;
5063be6ef06SEitan Adler colp++;
5073be6ef06SEitan Adler }
5083be6ef06SEitan Adler }
50908092a9bSDaichi GOTO
51008092a9bSDaichi GOTO states = hstates;
5113be6ef06SEitan Adler }
5123be6ef06SEitan Adler
5133be6ef06SEitan Adler void
z_cpustates(void)514f6234b51SEitan Adler z_cpustates(void)
5153be6ef06SEitan Adler {
51698c299e0SEitan Adler int i = 0;
517d0f687d3SDimitry Andric const char * const *names;
518d0f687d3SDimitry Andric const char *thisname;
5193be6ef06SEitan Adler int cpu, value;
5203be6ef06SEitan Adler
5213be6ef06SEitan Adler for (cpu = 0; cpu < num_cpus; cpu++) {
5223be6ef06SEitan Adler names = cpustate_names;
5233be6ef06SEitan Adler
5243be6ef06SEitan Adler /* show tag and bump lastline */
5253be6ef06SEitan Adler if (num_cpus == 1)
5263be6ef06SEitan Adler printf("\nCPU: ");
5273be6ef06SEitan Adler else {
5283be6ef06SEitan Adler value = printf("\nCPU %d: ", cpu);
5293be6ef06SEitan Adler while (value++ <= cpustates_column)
5303be6ef06SEitan Adler printf(" ");
5313be6ef06SEitan Adler }
5323be6ef06SEitan Adler lastline++;
5333be6ef06SEitan Adler
5343be6ef06SEitan Adler while ((thisname = *names++) != NULL)
5353be6ef06SEitan Adler {
5363be6ef06SEitan Adler if (*thisname != '\0')
5373be6ef06SEitan Adler {
5383be6ef06SEitan Adler printf("%s %% %s", (i++ % num_cpustates) == 0 ? "" : ", ", thisname);
5393be6ef06SEitan Adler }
5403be6ef06SEitan Adler }
5413be6ef06SEitan Adler }
5423be6ef06SEitan Adler
5433be6ef06SEitan Adler /* fill the "last" array with all -1s, to insure correct updating */
5446e0632dbSEitan Adler for (i = 0; i < num_cpustates * num_cpus; ++i) {
5456e0632dbSEitan Adler lcpustates[i] = -1;
5466e0632dbSEitan Adler }
5473be6ef06SEitan Adler }
5483be6ef06SEitan Adler
5493be6ef06SEitan Adler /*
5503be6ef06SEitan Adler * *_memory(stats) - print "Memory: " followed by the memory summary string
5513be6ef06SEitan Adler *
5523be6ef06SEitan Adler * Assumptions: cursor is on "lastline"
5533be6ef06SEitan Adler * for i_memory ONLY: cursor is on the previous line
5543be6ef06SEitan Adler */
5553be6ef06SEitan Adler
5560a59db87SDaichi GOTO static char *memory_buffer = NULL;
5573be6ef06SEitan Adler
5583be6ef06SEitan Adler void
i_memory(int * stats)5591b7645c6SEitan Adler i_memory(int *stats)
5603be6ef06SEitan Adler {
5610a59db87SDaichi GOTO memory_buffer = setup_buffer(memory_buffer, 0);
5620a59db87SDaichi GOTO
5633be6ef06SEitan Adler fputs("\nMem: ", stdout);
5643be6ef06SEitan Adler lastline++;
5653be6ef06SEitan Adler
5663be6ef06SEitan Adler /* format and print the memory summary */
5673be6ef06SEitan Adler summary_format(memory_buffer, stats, memory_names);
5683be6ef06SEitan Adler fputs(memory_buffer, stdout);
5693be6ef06SEitan Adler }
5703be6ef06SEitan Adler
5713be6ef06SEitan Adler void
u_memory(int * stats)5721b7645c6SEitan Adler u_memory(int *stats)
5733be6ef06SEitan Adler {
5740a59db87SDaichi GOTO static char *new = NULL;
5750a59db87SDaichi GOTO
5760a59db87SDaichi GOTO new = setup_buffer(new, 0);
5773be6ef06SEitan Adler
5783be6ef06SEitan Adler /* format the new line */
5793be6ef06SEitan Adler summary_format(new, stats, memory_names);
5803be6ef06SEitan Adler line_update(memory_buffer, new, x_mem, y_mem);
5813be6ef06SEitan Adler }
5823be6ef06SEitan Adler
5833be6ef06SEitan Adler /*
5843be6ef06SEitan Adler * *_arc(stats) - print "ARC: " followed by the ARC summary string
5853be6ef06SEitan Adler *
5863be6ef06SEitan Adler * Assumptions: cursor is on "lastline"
5873be6ef06SEitan Adler * for i_arc ONLY: cursor is on the previous line
5883be6ef06SEitan Adler */
5890a59db87SDaichi GOTO static char *arc_buffer = NULL;
5903be6ef06SEitan Adler
5913be6ef06SEitan Adler void
i_arc(int * stats)592a5ca08edSEitan Adler i_arc(int *stats)
5933be6ef06SEitan Adler {
5940a59db87SDaichi GOTO arc_buffer = setup_buffer(arc_buffer, 0);
5950a59db87SDaichi GOTO
5963be6ef06SEitan Adler if (arc_names == NULL)
5973be6ef06SEitan Adler return;
5983be6ef06SEitan Adler
5993be6ef06SEitan Adler fputs("\nARC: ", stdout);
6003be6ef06SEitan Adler lastline++;
6013be6ef06SEitan Adler
6023be6ef06SEitan Adler /* format and print the memory summary */
6033be6ef06SEitan Adler summary_format(arc_buffer, stats, arc_names);
6043be6ef06SEitan Adler fputs(arc_buffer, stdout);
6053be6ef06SEitan Adler }
6063be6ef06SEitan Adler
6073be6ef06SEitan Adler void
u_arc(int * stats)608f6234b51SEitan Adler u_arc(int *stats)
6093be6ef06SEitan Adler {
6100a59db87SDaichi GOTO static char *new = NULL;
6110a59db87SDaichi GOTO
6120a59db87SDaichi GOTO new = setup_buffer(new, 0);
6133be6ef06SEitan Adler
6143be6ef06SEitan Adler if (arc_names == NULL)
6153be6ef06SEitan Adler return;
6163be6ef06SEitan Adler
6173be6ef06SEitan Adler /* format the new line */
6183be6ef06SEitan Adler summary_format(new, stats, arc_names);
6193be6ef06SEitan Adler line_update(arc_buffer, new, x_arc, y_arc);
6203be6ef06SEitan Adler }
6213be6ef06SEitan Adler
6223be6ef06SEitan Adler
6233be6ef06SEitan Adler /*
6243be6ef06SEitan Adler * *_carc(stats) - print "Compressed ARC: " followed by the summary string
6253be6ef06SEitan Adler *
6263be6ef06SEitan Adler * Assumptions: cursor is on "lastline"
6273be6ef06SEitan Adler * for i_carc ONLY: cursor is on the previous line
6283be6ef06SEitan Adler */
6290a59db87SDaichi GOTO static char *carc_buffer = NULL;
6303be6ef06SEitan Adler
6313be6ef06SEitan Adler void
i_carc(int * stats)632a5ca08edSEitan Adler i_carc(int *stats)
6333be6ef06SEitan Adler {
6340a59db87SDaichi GOTO carc_buffer = setup_buffer(carc_buffer, 0);
6350a59db87SDaichi GOTO
6363be6ef06SEitan Adler if (carc_names == NULL)
6373be6ef06SEitan Adler return;
6383be6ef06SEitan Adler
6393be6ef06SEitan Adler fputs("\n ", stdout);
6403be6ef06SEitan Adler lastline++;
6413be6ef06SEitan Adler
6423be6ef06SEitan Adler /* format and print the memory summary */
6433be6ef06SEitan Adler summary_format(carc_buffer, stats, carc_names);
6443be6ef06SEitan Adler fputs(carc_buffer, stdout);
6453be6ef06SEitan Adler }
6463be6ef06SEitan Adler
6473be6ef06SEitan Adler void
u_carc(int * stats)648f6234b51SEitan Adler u_carc(int *stats)
6493be6ef06SEitan Adler {
6500a59db87SDaichi GOTO static char *new = NULL;
6510a59db87SDaichi GOTO
6520a59db87SDaichi GOTO new = setup_buffer(new, 0);
6533be6ef06SEitan Adler
6543be6ef06SEitan Adler if (carc_names == NULL)
6553be6ef06SEitan Adler return;
6563be6ef06SEitan Adler
6573be6ef06SEitan Adler /* format the new line */
6583be6ef06SEitan Adler summary_format(new, stats, carc_names);
6593be6ef06SEitan Adler line_update(carc_buffer, new, x_carc, y_carc);
6603be6ef06SEitan Adler }
6613be6ef06SEitan Adler
6623be6ef06SEitan Adler /*
6633be6ef06SEitan Adler * *_swap(stats) - print "Swap: " followed by the swap summary string
6643be6ef06SEitan Adler *
6653be6ef06SEitan Adler * Assumptions: cursor is on "lastline"
6663be6ef06SEitan Adler * for i_swap ONLY: cursor is on the previous line
6673be6ef06SEitan Adler */
6683be6ef06SEitan Adler
6690a59db87SDaichi GOTO static char *swap_buffer = NULL;
6703be6ef06SEitan Adler
6713be6ef06SEitan Adler void
i_swap(int * stats)672a5ca08edSEitan Adler i_swap(int *stats)
6733be6ef06SEitan Adler {
6740a59db87SDaichi GOTO swap_buffer = setup_buffer(swap_buffer, 0);
6750a59db87SDaichi GOTO
6762984a716SAllan Jude if (swap_names == NULL)
6772984a716SAllan Jude return;
6782984a716SAllan Jude
6793be6ef06SEitan Adler fputs("\nSwap: ", stdout);
6803be6ef06SEitan Adler lastline++;
6813be6ef06SEitan Adler
6823be6ef06SEitan Adler /* format and print the swap summary */
6833be6ef06SEitan Adler summary_format(swap_buffer, stats, swap_names);
6843be6ef06SEitan Adler fputs(swap_buffer, stdout);
6853be6ef06SEitan Adler }
6863be6ef06SEitan Adler
6873be6ef06SEitan Adler void
u_swap(int * stats)688a5ca08edSEitan Adler u_swap(int *stats)
6893be6ef06SEitan Adler {
6900a59db87SDaichi GOTO static char *new = NULL;
6910a59db87SDaichi GOTO
6920a59db87SDaichi GOTO new = setup_buffer(new, 0);
6933be6ef06SEitan Adler
6942984a716SAllan Jude if (swap_names == NULL)
6952984a716SAllan Jude return;
6962984a716SAllan Jude
6973be6ef06SEitan Adler /* format the new line */
6983be6ef06SEitan Adler summary_format(new, stats, swap_names);
6993be6ef06SEitan Adler line_update(swap_buffer, new, x_swap, y_swap);
7003be6ef06SEitan Adler }
7013be6ef06SEitan Adler
7023be6ef06SEitan Adler /*
7033be6ef06SEitan Adler * *_message() - print the next pending message line, or erase the one
7043be6ef06SEitan Adler * that is there.
7053be6ef06SEitan Adler *
7063be6ef06SEitan Adler * Note that u_message is (currently) the same as i_message.
7073be6ef06SEitan Adler *
7083be6ef06SEitan Adler * Assumptions: lastline is consistent
7093be6ef06SEitan Adler */
7103be6ef06SEitan Adler
7113be6ef06SEitan Adler /*
7123be6ef06SEitan Adler * i_message is funny because it gets its message asynchronously (with
7133be6ef06SEitan Adler * respect to screen updates).
7143be6ef06SEitan Adler */
7153be6ef06SEitan Adler
7165c48c1eeSDaichi GOTO #define NEXT_MSG_ADDLEN 5
7170a59db87SDaichi GOTO static char *next_msg = NULL;
7183be6ef06SEitan Adler static int msglen = 0;
7193be6ef06SEitan Adler /* Invariant: msglen is always the length of the message currently displayed
7203be6ef06SEitan Adler on the screen (even when next_msg doesn't contain that message). */
7213be6ef06SEitan Adler
7223be6ef06SEitan Adler void
i_message(void)723f6234b51SEitan Adler i_message(void)
7243be6ef06SEitan Adler {
7255c48c1eeSDaichi GOTO next_msg = setup_buffer(next_msg, NEXT_MSG_ADDLEN);
726a5ca08edSEitan Adler
7273be6ef06SEitan Adler while (lastline < y_message)
7283be6ef06SEitan Adler {
7293be6ef06SEitan Adler fputc('\n', stdout);
7303be6ef06SEitan Adler lastline++;
7313be6ef06SEitan Adler }
7323be6ef06SEitan Adler if (next_msg[0] != '\0')
7333be6ef06SEitan Adler {
7343be6ef06SEitan Adler top_standout(next_msg);
7353be6ef06SEitan Adler msglen = strlen(next_msg);
7363be6ef06SEitan Adler next_msg[0] = '\0';
7373be6ef06SEitan Adler }
7383be6ef06SEitan Adler else if (msglen > 0)
7393be6ef06SEitan Adler {
7403be6ef06SEitan Adler (void) clear_eol(msglen);
7413be6ef06SEitan Adler msglen = 0;
7423be6ef06SEitan Adler }
7433be6ef06SEitan Adler }
7443be6ef06SEitan Adler
7453be6ef06SEitan Adler void
u_message(void)746f6234b51SEitan Adler u_message(void)
7473be6ef06SEitan Adler {
7483be6ef06SEitan Adler i_message();
7493be6ef06SEitan Adler }
7503be6ef06SEitan Adler
7513be6ef06SEitan Adler static int header_length;
7523be6ef06SEitan Adler
7533be6ef06SEitan Adler /*
7543be6ef06SEitan Adler * Trim a header string to the current display width and return a newly
7553be6ef06SEitan Adler * allocated area with the trimmed header.
7563be6ef06SEitan Adler */
7573be6ef06SEitan Adler
758d0f687d3SDimitry Andric char *
trim_header(const char * text)7599f8096e3SEitan Adler trim_header(const char *text)
7603be6ef06SEitan Adler {
7613be6ef06SEitan Adler char *s;
7623be6ef06SEitan Adler int width;
7633be6ef06SEitan Adler
7643be6ef06SEitan Adler s = NULL;
7650a59db87SDaichi GOTO width = screen_width;
7663be6ef06SEitan Adler header_length = strlen(text);
7673be6ef06SEitan Adler if (header_length >= width) {
7689f8096e3SEitan Adler s = strndup(text, width);
7693be6ef06SEitan Adler if (s == NULL)
7703be6ef06SEitan Adler return (NULL);
7713be6ef06SEitan Adler }
7723be6ef06SEitan Adler return (s);
7733be6ef06SEitan Adler }
7743be6ef06SEitan Adler
7753be6ef06SEitan Adler /*
7763be6ef06SEitan Adler * *_header(text) - print the header for the process area
7773be6ef06SEitan Adler *
7783be6ef06SEitan Adler * Assumptions: cursor is on the previous line and lastline is consistent
7793be6ef06SEitan Adler */
7803be6ef06SEitan Adler
7813be6ef06SEitan Adler void
i_header(const char * text)7829f8096e3SEitan Adler i_header(const char *text)
7833be6ef06SEitan Adler {
784eae589f1SEitan Adler char *s;
7853be6ef06SEitan Adler
7863be6ef06SEitan Adler s = trim_header(text);
7873be6ef06SEitan Adler if (s != NULL)
7883be6ef06SEitan Adler text = s;
7893be6ef06SEitan Adler
7903be6ef06SEitan Adler if (header_status == ON)
7913be6ef06SEitan Adler {
7923be6ef06SEitan Adler putchar('\n');
7933be6ef06SEitan Adler fputs(text, stdout);
7943be6ef06SEitan Adler lastline++;
7953be6ef06SEitan Adler }
7963be6ef06SEitan Adler else if (header_status == ERASE)
7973be6ef06SEitan Adler {
7983be6ef06SEitan Adler header_status = OFF;
7993be6ef06SEitan Adler }
8003be6ef06SEitan Adler free(s);
8013be6ef06SEitan Adler }
8023be6ef06SEitan Adler
8033be6ef06SEitan Adler void
u_header(const char * text __unused)8049f8096e3SEitan Adler u_header(const char *text __unused)
8053be6ef06SEitan Adler {
8063be6ef06SEitan Adler
8073be6ef06SEitan Adler if (header_status == ERASE)
8083be6ef06SEitan Adler {
8093be6ef06SEitan Adler putchar('\n');
8103be6ef06SEitan Adler lastline++;
8113be6ef06SEitan Adler clear_eol(header_length);
8123be6ef06SEitan Adler header_status = OFF;
8133be6ef06SEitan Adler }
8143be6ef06SEitan Adler }
8153be6ef06SEitan Adler
8163be6ef06SEitan Adler /*
8173be6ef06SEitan Adler * *_process(line, thisline) - print one process line
8183be6ef06SEitan Adler *
8193be6ef06SEitan Adler * Assumptions: lastline is consistent
8203be6ef06SEitan Adler */
8213be6ef06SEitan Adler
8223be6ef06SEitan Adler void
i_process(int line,char * thisline)823f6234b51SEitan Adler i_process(int line, char *thisline)
8243be6ef06SEitan Adler {
82598c299e0SEitan Adler char *p;
82698c299e0SEitan Adler char *base;
8273be6ef06SEitan Adler
8283be6ef06SEitan Adler /* make sure we are on the correct line */
8293be6ef06SEitan Adler while (lastline < y_procs + line)
8303be6ef06SEitan Adler {
8313be6ef06SEitan Adler putchar('\n');
8323be6ef06SEitan Adler lastline++;
8333be6ef06SEitan Adler }
8343be6ef06SEitan Adler
8353be6ef06SEitan Adler /* truncate the line to conform to our current screen width */
8367362ea6dSDimitry Andric int len = strlen(thisline);
8377362ea6dSDimitry Andric if (screen_width < len)
8387362ea6dSDimitry Andric {
8390a59db87SDaichi GOTO thisline[screen_width] = '\0';
8407362ea6dSDimitry Andric }
8413be6ef06SEitan Adler
8423be6ef06SEitan Adler /* write the line out */
8433be6ef06SEitan Adler fputs(thisline, stdout);
8443be6ef06SEitan Adler
8453be6ef06SEitan Adler /* copy it in to our buffer */
8463be6ef06SEitan Adler base = smart_terminal ? screenbuf + lineindex(line) : screenbuf;
847b274c68aSEitan Adler p = stpcpy(base, thisline);
8483be6ef06SEitan Adler
8493be6ef06SEitan Adler /* zero fill the rest of it */
8507362ea6dSDimitry Andric if (p - base < screen_width)
8517362ea6dSDimitry Andric {
8520a59db87SDaichi GOTO memset(p, 0, screen_width - (p - base));
8533be6ef06SEitan Adler }
8547362ea6dSDimitry Andric }
8553be6ef06SEitan Adler
8563be6ef06SEitan Adler void
u_process(int line,char * newline)857f6234b51SEitan Adler u_process(int line, char *newline)
8583be6ef06SEitan Adler {
85998c299e0SEitan Adler char *optr;
86098c299e0SEitan Adler int screen_line = line + Header_lines;
86198c299e0SEitan Adler char *bufferline;
8623be6ef06SEitan Adler
8633be6ef06SEitan Adler /* remember a pointer to the current line in the screen buffer */
8643be6ef06SEitan Adler bufferline = &screenbuf[lineindex(line)];
8653be6ef06SEitan Adler
8663be6ef06SEitan Adler /* truncate the line to conform to our current screen width */
8677362ea6dSDimitry Andric int len = strlen(newline);
8687362ea6dSDimitry Andric if (screen_width < len)
8697362ea6dSDimitry Andric {
8700a59db87SDaichi GOTO newline[screen_width] = '\0';
8717362ea6dSDimitry Andric }
8723be6ef06SEitan Adler
8733be6ef06SEitan Adler /* is line higher than we went on the last display? */
8743be6ef06SEitan Adler if (line >= last_hi)
8753be6ef06SEitan Adler {
8763be6ef06SEitan Adler /* yes, just ignore screenbuf and write it out directly */
8773be6ef06SEitan Adler /* get positioned on the correct line */
8783be6ef06SEitan Adler if (screen_line - lastline == 1)
8793be6ef06SEitan Adler {
8803be6ef06SEitan Adler putchar('\n');
8813be6ef06SEitan Adler lastline++;
8823be6ef06SEitan Adler }
8833be6ef06SEitan Adler else
8843be6ef06SEitan Adler {
8853be6ef06SEitan Adler Move_to(0, screen_line);
8863be6ef06SEitan Adler lastline = screen_line;
8873be6ef06SEitan Adler }
8883be6ef06SEitan Adler
8893be6ef06SEitan Adler /* now write the line */
8903be6ef06SEitan Adler fputs(newline, stdout);
8913be6ef06SEitan Adler
8923be6ef06SEitan Adler /* copy it in to the buffer */
893b274c68aSEitan Adler optr = stpcpy(bufferline, newline);
8943be6ef06SEitan Adler
8953be6ef06SEitan Adler /* zero fill the rest of it */
8967362ea6dSDimitry Andric if (optr - bufferline < screen_width)
8977362ea6dSDimitry Andric {
8980a59db87SDaichi GOTO memset(optr, 0, screen_width - (optr - bufferline));
8993be6ef06SEitan Adler }
9007362ea6dSDimitry Andric }
9013be6ef06SEitan Adler else
9023be6ef06SEitan Adler {
9033be6ef06SEitan Adler line_update(bufferline, newline, 0, line + Header_lines);
9043be6ef06SEitan Adler }
9053be6ef06SEitan Adler }
9063be6ef06SEitan Adler
9073be6ef06SEitan Adler void
u_endscreen(int hi)908f6234b51SEitan Adler u_endscreen(int hi)
9093be6ef06SEitan Adler {
91098c299e0SEitan Adler int screen_line = hi + Header_lines;
91198c299e0SEitan Adler int i;
9123be6ef06SEitan Adler
9133be6ef06SEitan Adler if (smart_terminal)
9143be6ef06SEitan Adler {
9153be6ef06SEitan Adler if (hi < last_hi)
9163be6ef06SEitan Adler {
9173be6ef06SEitan Adler /* need to blank the remainder of the screen */
9183be6ef06SEitan Adler /* but only if there is any screen left below this line */
9193be6ef06SEitan Adler if (lastline + 1 < screen_length)
9203be6ef06SEitan Adler {
9213be6ef06SEitan Adler /* efficiently move to the end of currently displayed info */
9223be6ef06SEitan Adler if (screen_line - lastline < 5)
9233be6ef06SEitan Adler {
9243be6ef06SEitan Adler while (lastline < screen_line)
9253be6ef06SEitan Adler {
9263be6ef06SEitan Adler putchar('\n');
9273be6ef06SEitan Adler lastline++;
9283be6ef06SEitan Adler }
9293be6ef06SEitan Adler }
9303be6ef06SEitan Adler else
9313be6ef06SEitan Adler {
9323be6ef06SEitan Adler Move_to(0, screen_line);
9333be6ef06SEitan Adler lastline = screen_line;
9343be6ef06SEitan Adler }
9353be6ef06SEitan Adler
9363be6ef06SEitan Adler if (clear_to_end)
9373be6ef06SEitan Adler {
9383be6ef06SEitan Adler /* we can do this the easy way */
9393be6ef06SEitan Adler putcap(clear_to_end);
9403be6ef06SEitan Adler }
9413be6ef06SEitan Adler else
9423be6ef06SEitan Adler {
9433be6ef06SEitan Adler /* use clear_eol on each line */
9443be6ef06SEitan Adler i = hi;
9453be6ef06SEitan Adler while ((void) clear_eol(strlen(&screenbuf[lineindex(i++)])), i < last_hi)
9463be6ef06SEitan Adler {
9473be6ef06SEitan Adler putchar('\n');
9483be6ef06SEitan Adler }
9493be6ef06SEitan Adler }
9503be6ef06SEitan Adler }
9513be6ef06SEitan Adler }
9523be6ef06SEitan Adler last_hi = hi;
9533be6ef06SEitan Adler
9543be6ef06SEitan Adler /* move the cursor to a pleasant place */
9553be6ef06SEitan Adler Move_to(x_idlecursor, y_idlecursor);
9563be6ef06SEitan Adler lastline = y_idlecursor;
9573be6ef06SEitan Adler }
9583be6ef06SEitan Adler else
9593be6ef06SEitan Adler {
9603be6ef06SEitan Adler /* separate this display from the next with some vertical room */
9613be6ef06SEitan Adler fputs("\n\n", stdout);
9623be6ef06SEitan Adler }
9633be6ef06SEitan Adler }
9643be6ef06SEitan Adler
9653be6ef06SEitan Adler void
display_header(int t)966666cf873SEitan Adler display_header(int t)
9673be6ef06SEitan Adler {
968666cf873SEitan Adler
9693be6ef06SEitan Adler if (t)
9703be6ef06SEitan Adler {
9713be6ef06SEitan Adler header_status = ON;
9723be6ef06SEitan Adler }
9733be6ef06SEitan Adler else if (header_status == ON)
9743be6ef06SEitan Adler {
9753be6ef06SEitan Adler header_status = ERASE;
9763be6ef06SEitan Adler }
9773be6ef06SEitan Adler }
9783be6ef06SEitan Adler
9793be6ef06SEitan Adler void
new_message(int type,const char * msgfmt,...)980960a7f39SEitan Adler new_message(int type, const char *msgfmt, ...)
9813be6ef06SEitan Adler {
9821d6a4ba3SEitan Adler va_list args;
9831d6a4ba3SEitan Adler size_t i;
9841d6a4ba3SEitan Adler
9851d6a4ba3SEitan Adler va_start(args, msgfmt);
9863be6ef06SEitan Adler
9873be6ef06SEitan Adler /* first, format the message */
9885c48c1eeSDaichi GOTO vsnprintf(next_msg, setup_buffer_bufsiz + NEXT_MSG_ADDLEN,
9895c48c1eeSDaichi GOTO msgfmt, args);
9903be6ef06SEitan Adler
991dfa5eb70SEitan Adler va_end(args);
992dfa5eb70SEitan Adler
9933be6ef06SEitan Adler if (msglen > 0)
9943be6ef06SEitan Adler {
9953be6ef06SEitan Adler /* message there already -- can we clear it? */
9963be6ef06SEitan Adler if (!overstrike)
9973be6ef06SEitan Adler {
9983be6ef06SEitan Adler /* yes -- write it and clear to end */
9993be6ef06SEitan Adler i = strlen(next_msg);
10003be6ef06SEitan Adler if ((type & MT_delayed) == 0)
10013be6ef06SEitan Adler {
100259c50d82SEitan Adler if (type & MT_standout) {
100359c50d82SEitan Adler top_standout(next_msg);
100459c50d82SEitan Adler } else {
10053be6ef06SEitan Adler fputs(next_msg, stdout);
100659c50d82SEitan Adler }
100759c50d82SEitan Adler clear_eol(msglen - i);
10083be6ef06SEitan Adler msglen = i;
10093be6ef06SEitan Adler next_msg[0] = '\0';
10103be6ef06SEitan Adler }
10113be6ef06SEitan Adler }
10123be6ef06SEitan Adler }
10133be6ef06SEitan Adler else
10143be6ef06SEitan Adler {
10153be6ef06SEitan Adler if ((type & MT_delayed) == 0)
10163be6ef06SEitan Adler {
101759c50d82SEitan Adler if (type & MT_standout) {
101859c50d82SEitan Adler top_standout(next_msg);
101959c50d82SEitan Adler } else {
102059c50d82SEitan Adler fputs(next_msg, stdout);
102159c50d82SEitan Adler }
10223be6ef06SEitan Adler msglen = strlen(next_msg);
10233be6ef06SEitan Adler next_msg[0] = '\0';
10243be6ef06SEitan Adler }
10253be6ef06SEitan Adler }
10263be6ef06SEitan Adler }
10273be6ef06SEitan Adler
10283be6ef06SEitan Adler void
clear_message(void)1029f6234b51SEitan Adler clear_message(void)
10303be6ef06SEitan Adler {
10313be6ef06SEitan Adler if (clear_eol(msglen) == 1)
10323be6ef06SEitan Adler {
10333be6ef06SEitan Adler putchar('\r');
10343be6ef06SEitan Adler }
10353be6ef06SEitan Adler }
10363be6ef06SEitan Adler
10373be6ef06SEitan Adler int
readline(char * buffer,int size,int numeric)1038f6234b51SEitan Adler readline(char *buffer, int size, int numeric)
10393be6ef06SEitan Adler {
104098c299e0SEitan Adler char *ptr = buffer;
104198c299e0SEitan Adler char ch;
104298c299e0SEitan Adler char cnt = 0;
104398c299e0SEitan Adler char maxcnt = 0;
10443be6ef06SEitan Adler
10453be6ef06SEitan Adler /* allow room for null terminator */
10463be6ef06SEitan Adler size -= 1;
10473be6ef06SEitan Adler
10483be6ef06SEitan Adler /* read loop */
10493be6ef06SEitan Adler while ((fflush(stdout), read(0, ptr, 1) > 0))
10503be6ef06SEitan Adler {
10513be6ef06SEitan Adler /* newline means we are done */
10523be6ef06SEitan Adler if ((ch = *ptr) == '\n' || ch == '\r')
10533be6ef06SEitan Adler {
10543be6ef06SEitan Adler break;
10553be6ef06SEitan Adler }
10563be6ef06SEitan Adler
10573be6ef06SEitan Adler /* handle special editing characters */
10583be6ef06SEitan Adler if (ch == ch_kill)
10593be6ef06SEitan Adler {
10603be6ef06SEitan Adler /* kill line -- account for overstriking */
10613be6ef06SEitan Adler if (overstrike)
10623be6ef06SEitan Adler {
10633be6ef06SEitan Adler msglen += maxcnt;
10643be6ef06SEitan Adler }
10653be6ef06SEitan Adler
10663be6ef06SEitan Adler /* return null string */
10673be6ef06SEitan Adler *buffer = '\0';
10683be6ef06SEitan Adler putchar('\r');
10693be6ef06SEitan Adler return(-1);
10703be6ef06SEitan Adler }
10713be6ef06SEitan Adler else if (ch == ch_erase)
10723be6ef06SEitan Adler {
10733be6ef06SEitan Adler /* erase previous character */
10743be6ef06SEitan Adler if (cnt <= 0)
10753be6ef06SEitan Adler {
10763be6ef06SEitan Adler /* none to erase! */
10773be6ef06SEitan Adler putchar('\7');
10783be6ef06SEitan Adler }
10793be6ef06SEitan Adler else
10803be6ef06SEitan Adler {
10813be6ef06SEitan Adler fputs("\b \b", stdout);
10823be6ef06SEitan Adler ptr--;
10833be6ef06SEitan Adler cnt--;
10843be6ef06SEitan Adler }
10853be6ef06SEitan Adler }
10863be6ef06SEitan Adler /* check for character validity and buffer overflow */
10873be6ef06SEitan Adler else if (cnt == size || (numeric && !isdigit(ch)) ||
10883be6ef06SEitan Adler !isprint(ch))
10893be6ef06SEitan Adler {
10903be6ef06SEitan Adler /* not legal */
10913be6ef06SEitan Adler putchar('\7');
10923be6ef06SEitan Adler }
10933be6ef06SEitan Adler else
10943be6ef06SEitan Adler {
10953be6ef06SEitan Adler /* echo it and store it in the buffer */
10963be6ef06SEitan Adler putchar(ch);
10973be6ef06SEitan Adler ptr++;
10983be6ef06SEitan Adler cnt++;
10993be6ef06SEitan Adler if (cnt > maxcnt)
11003be6ef06SEitan Adler {
11013be6ef06SEitan Adler maxcnt = cnt;
11023be6ef06SEitan Adler }
11033be6ef06SEitan Adler }
11043be6ef06SEitan Adler }
11053be6ef06SEitan Adler
11063be6ef06SEitan Adler /* all done -- null terminate the string */
11073be6ef06SEitan Adler *ptr = '\0';
11083be6ef06SEitan Adler
11093be6ef06SEitan Adler /* account for the extra characters in the message area */
11103be6ef06SEitan Adler /* (if terminal overstrikes, remember the furthest they went) */
11113be6ef06SEitan Adler msglen += overstrike ? maxcnt : cnt;
11123be6ef06SEitan Adler
11133be6ef06SEitan Adler /* return either inputted number or string length */
11143be6ef06SEitan Adler putchar('\r');
11153be6ef06SEitan Adler return(cnt == 0 ? -1 : numeric ? atoi(buffer) : cnt);
11163be6ef06SEitan Adler }
11173be6ef06SEitan Adler
11183be6ef06SEitan Adler /* internal support routines */
11193be6ef06SEitan Adler
11201de63842SEitan Adler static void
summary_format(char * str,int * numbers,const char * const * names)11211de63842SEitan Adler summary_format(char *str, int *numbers, const char * const *names)
11223be6ef06SEitan Adler {
112398c299e0SEitan Adler char *p;
112498c299e0SEitan Adler int num;
1125eae589f1SEitan Adler const char *thisname;
11263be6ef06SEitan Adler char rbuf[6];
11273be6ef06SEitan Adler
11283be6ef06SEitan Adler /* format each number followed by its string */
11293be6ef06SEitan Adler p = str;
11303be6ef06SEitan Adler while ((thisname = *names++) != NULL)
11313be6ef06SEitan Adler {
11323be6ef06SEitan Adler /* get the number to format */
11333be6ef06SEitan Adler num = *numbers++;
11343be6ef06SEitan Adler
11353be6ef06SEitan Adler /* display only non-zero numbers */
11363be6ef06SEitan Adler if (num > 0)
11373be6ef06SEitan Adler {
11383be6ef06SEitan Adler /* is this number in kilobytes? */
11393be6ef06SEitan Adler if (thisname[0] == 'K')
11403be6ef06SEitan Adler {
11413be6ef06SEitan Adler /* yes: format it as a memory value */
1142b274c68aSEitan Adler p = stpcpy(p, format_k(num));
11433be6ef06SEitan Adler
11443be6ef06SEitan Adler /* skip over the K, since it was included by format_k */
1145b274c68aSEitan Adler p = stpcpy(p, thisname+1);
11463be6ef06SEitan Adler }
11473be6ef06SEitan Adler /* is this number a ratio? */
11483be6ef06SEitan Adler else if (thisname[0] == ':')
11493be6ef06SEitan Adler {
11503be6ef06SEitan Adler (void) snprintf(rbuf, sizeof(rbuf), "%.2f",
11513be6ef06SEitan Adler (float)*(numbers - 2) / (float)num);
1152b274c68aSEitan Adler p = stpcpy(p, rbuf);
1153b274c68aSEitan Adler p = stpcpy(p, thisname);
11543be6ef06SEitan Adler }
11553be6ef06SEitan Adler else
11563be6ef06SEitan Adler {
1157b274c68aSEitan Adler p = stpcpy(p, itoa(num));
1158b274c68aSEitan Adler p = stpcpy(p, thisname);
11593be6ef06SEitan Adler }
11603be6ef06SEitan Adler }
11613be6ef06SEitan Adler
11623be6ef06SEitan Adler /* ignore negative numbers, but display corresponding string */
11633be6ef06SEitan Adler else if (num < 0)
11643be6ef06SEitan Adler {
1165b274c68aSEitan Adler p = stpcpy(p, thisname);
11663be6ef06SEitan Adler }
11673be6ef06SEitan Adler }
11683be6ef06SEitan Adler
11693be6ef06SEitan Adler /* if the last two characters in the string are ", ", delete them */
11703be6ef06SEitan Adler p -= 2;
11713be6ef06SEitan Adler if (p >= str && p[0] == ',' && p[1] == ' ')
11723be6ef06SEitan Adler {
11733be6ef06SEitan Adler *p = '\0';
11743be6ef06SEitan Adler }
11753be6ef06SEitan Adler }
11763be6ef06SEitan Adler
1177f6234b51SEitan Adler static void
line_update(char * old,char * new,int start,int line)1178f6234b51SEitan Adler line_update(char *old, char *new, int start, int line)
11793be6ef06SEitan Adler {
118098c299e0SEitan Adler int ch;
118198c299e0SEitan Adler int diff;
118298c299e0SEitan Adler int newcol = start + 1;
118398c299e0SEitan Adler int lastcol = start;
11840b2f6ed1SEitan Adler char cursor_on_line = false;
11853be6ef06SEitan Adler char *current;
11863be6ef06SEitan Adler
11873be6ef06SEitan Adler /* compare the two strings and only rewrite what has changed */
11883be6ef06SEitan Adler current = old;
11893be6ef06SEitan Adler #ifdef DEBUG
11903be6ef06SEitan Adler fprintf(debug, "line_update, starting at %d\n", start);
11913be6ef06SEitan Adler fputs(old, debug);
11923be6ef06SEitan Adler fputc('\n', debug);
11933be6ef06SEitan Adler fputs(new, debug);
11943be6ef06SEitan Adler fputs("\n-\n", debug);
11953be6ef06SEitan Adler #endif
11963be6ef06SEitan Adler
11973be6ef06SEitan Adler /* start things off on the right foot */
11983be6ef06SEitan Adler /* this is to make sure the invariants get set up right */
11993be6ef06SEitan Adler if ((ch = *new++) != *old)
12003be6ef06SEitan Adler {
12013be6ef06SEitan Adler if (line - lastline == 1 && start == 0)
12023be6ef06SEitan Adler {
12033be6ef06SEitan Adler putchar('\n');
12043be6ef06SEitan Adler }
12053be6ef06SEitan Adler else
12063be6ef06SEitan Adler {
12073be6ef06SEitan Adler Move_to(start, line);
12083be6ef06SEitan Adler }
12090b2f6ed1SEitan Adler cursor_on_line = true;
12103be6ef06SEitan Adler putchar(ch);
12113be6ef06SEitan Adler *old = ch;
1212281bdc30SDimitry Andric lastcol = start + 1;
12133be6ef06SEitan Adler }
12143be6ef06SEitan Adler old++;
12153be6ef06SEitan Adler
12163be6ef06SEitan Adler /*
12173be6ef06SEitan Adler * main loop -- check each character. If the old and new aren't the
12183be6ef06SEitan Adler * same, then update the display. When the distance from the
12193be6ef06SEitan Adler * current cursor position to the new change is small enough,
12203be6ef06SEitan Adler * the characters that belong there are written to move the
12213be6ef06SEitan Adler * cursor over.
12223be6ef06SEitan Adler *
12233be6ef06SEitan Adler * Invariants:
12243be6ef06SEitan Adler * lastcol is the column where the cursor currently is sitting
12253be6ef06SEitan Adler * (always one beyond the end of the last mismatch).
12263be6ef06SEitan Adler */
12273be6ef06SEitan Adler do /* yes, a do...while */
12283be6ef06SEitan Adler {
12293be6ef06SEitan Adler if ((ch = *new++) != *old)
12303be6ef06SEitan Adler {
12313be6ef06SEitan Adler /* new character is different from old */
12323be6ef06SEitan Adler /* make sure the cursor is on top of this character */
12333be6ef06SEitan Adler diff = newcol - lastcol;
12343be6ef06SEitan Adler if (diff > 0)
12353be6ef06SEitan Adler {
12363be6ef06SEitan Adler /* some motion is required--figure out which is shorter */
12373be6ef06SEitan Adler if (diff < 6 && cursor_on_line)
12383be6ef06SEitan Adler {
12393be6ef06SEitan Adler /* overwrite old stuff--get it out of the old buffer */
12403be6ef06SEitan Adler printf("%.*s", diff, ¤t[lastcol-start]);
12413be6ef06SEitan Adler }
12423be6ef06SEitan Adler else
12433be6ef06SEitan Adler {
12443be6ef06SEitan Adler /* use cursor addressing */
12453be6ef06SEitan Adler Move_to(newcol, line);
12460b2f6ed1SEitan Adler cursor_on_line = true;
12473be6ef06SEitan Adler }
12483be6ef06SEitan Adler /* remember where the cursor is */
12493be6ef06SEitan Adler lastcol = newcol + 1;
12503be6ef06SEitan Adler }
12513be6ef06SEitan Adler else
12523be6ef06SEitan Adler {
12533be6ef06SEitan Adler /* already there, update position */
12543be6ef06SEitan Adler lastcol++;
12553be6ef06SEitan Adler }
12563be6ef06SEitan Adler
12573be6ef06SEitan Adler /* write what we need to */
12583be6ef06SEitan Adler if (ch == '\0')
12593be6ef06SEitan Adler {
12603be6ef06SEitan Adler /* at the end--terminate with a clear-to-end-of-line */
12613be6ef06SEitan Adler (void) clear_eol(strlen(old));
12623be6ef06SEitan Adler }
12633be6ef06SEitan Adler else
12643be6ef06SEitan Adler {
12653be6ef06SEitan Adler /* write the new character */
12663be6ef06SEitan Adler putchar(ch);
12673be6ef06SEitan Adler }
12683be6ef06SEitan Adler /* put the new character in the screen buffer */
12693be6ef06SEitan Adler *old = ch;
12703be6ef06SEitan Adler }
12713be6ef06SEitan Adler
12723be6ef06SEitan Adler /* update working column and screen buffer pointer */
12733be6ef06SEitan Adler newcol++;
12743be6ef06SEitan Adler old++;
12753be6ef06SEitan Adler
12763be6ef06SEitan Adler } while (ch != '\0');
12773be6ef06SEitan Adler
12783be6ef06SEitan Adler /* zero out the rest of the line buffer -- MUST BE DONE! */
12790a59db87SDaichi GOTO diff = screen_width - newcol;
12803be6ef06SEitan Adler if (diff > 0)
12813be6ef06SEitan Adler {
12828d0d2676SEitan Adler memset(old, 0, diff);
12833be6ef06SEitan Adler }
12843be6ef06SEitan Adler
12853be6ef06SEitan Adler /* remember where the current line is */
12863be6ef06SEitan Adler if (cursor_on_line)
12873be6ef06SEitan Adler {
12883be6ef06SEitan Adler lastline = line;
12893be6ef06SEitan Adler }
12903be6ef06SEitan Adler }
12913be6ef06SEitan Adler
12923be6ef06SEitan Adler void
i_uptime(struct timeval * bt,time_t * tod)1293f6234b51SEitan Adler i_uptime(struct timeval *bt, time_t *tod)
12943be6ef06SEitan Adler {
12953be6ef06SEitan Adler time_t uptime;
12963be6ef06SEitan Adler int days, hrs, mins, secs;
12973be6ef06SEitan Adler
12983be6ef06SEitan Adler if (bt->tv_sec != -1) {
12993be6ef06SEitan Adler uptime = *tod - bt->tv_sec;
13003be6ef06SEitan Adler days = uptime / 86400;
13013be6ef06SEitan Adler uptime %= 86400;
13023be6ef06SEitan Adler hrs = uptime / 3600;
13033be6ef06SEitan Adler uptime %= 3600;
13043be6ef06SEitan Adler mins = uptime / 60;
13053be6ef06SEitan Adler secs = uptime % 60;
13063be6ef06SEitan Adler
13073be6ef06SEitan Adler /*
13083be6ef06SEitan Adler * Display the uptime.
13093be6ef06SEitan Adler */
13103be6ef06SEitan Adler
13113be6ef06SEitan Adler if (smart_terminal)
13123be6ef06SEitan Adler {
13133be6ef06SEitan Adler Move_to((screen_width - 24) - (days > 9 ? 1 : 0), 0);
13143be6ef06SEitan Adler }
13153be6ef06SEitan Adler else
13163be6ef06SEitan Adler {
13173be6ef06SEitan Adler fputs(" ", stdout);
13183be6ef06SEitan Adler }
13193be6ef06SEitan Adler printf(" up %d+%02d:%02d:%02d", days, hrs, mins, secs);
13203be6ef06SEitan Adler }
13213be6ef06SEitan Adler }
13220a59db87SDaichi GOTO
1323fc8ae86aSPhilip Paeps void
i_battery(int nbat,int batt)1324fc8ae86aSPhilip Paeps i_battery(int nbat, int batt)
1325fc8ae86aSPhilip Paeps {
1326fc8ae86aSPhilip Paeps
1327fc8ae86aSPhilip Paeps if (nbat > 0) {
1328fc8ae86aSPhilip Paeps printf("; battery: %d%%", batt);
1329fc8ae86aSPhilip Paeps }
1330fc8ae86aSPhilip Paeps }
1331fc8ae86aSPhilip Paeps
1332281bdc30SDimitry Andric #define SETUPBUFFER_MIN_SCREENWIDTH 80
13335c48c1eeSDaichi GOTO #define SETUPBUFFER_REQUIRED_ADDBUFSIZ 2
13345c48c1eeSDaichi GOTO
13350a59db87SDaichi GOTO static char *
setup_buffer(char * buffer,int addlen)13360a59db87SDaichi GOTO setup_buffer(char *buffer, int addlen)
13370a59db87SDaichi GOTO {
1338c26e2e37SDimitry Andric size_t len, old_len;
1339c26e2e37SDimitry Andric char *new_buffer;
13400a59db87SDaichi GOTO
13410a59db87SDaichi GOTO setup_buffer_bufsiz = screen_width;
1342281bdc30SDimitry Andric if (setup_buffer_bufsiz < SETUPBUFFER_MIN_SCREENWIDTH)
1343281bdc30SDimitry Andric {
1344281bdc30SDimitry Andric setup_buffer_bufsiz = SETUPBUFFER_MIN_SCREENWIDTH;
1345281bdc30SDimitry Andric }
1346281bdc30SDimitry Andric
1347281bdc30SDimitry Andric len = setup_buffer_bufsiz + addlen + SETUPBUFFER_REQUIRED_ADDBUFSIZ;
1348c26e2e37SDimitry Andric new_buffer = calloc(len, sizeof(char));
1349c26e2e37SDimitry Andric if (new_buffer == NULL)
1350281bdc30SDimitry Andric {
135117be5f23SEitan Adler errx(4, "can't allocate sufficient memory");
13520a59db87SDaichi GOTO }
1353c26e2e37SDimitry Andric if (buffer != NULL)
1354c26e2e37SDimitry Andric {
1355c26e2e37SDimitry Andric old_len = strlen(buffer);
1356c26e2e37SDimitry Andric memcpy(new_buffer, buffer, old_len < len - 1 ? old_len : len - 1);
1357c26e2e37SDimitry Andric free(buffer);
1358c26e2e37SDimitry Andric }
13590a59db87SDaichi GOTO
1360c26e2e37SDimitry Andric return new_buffer;
13610a59db87SDaichi GOTO }
1362