11#include <sys/types.h>
2+ #include <curses.h>
23#include <err.h>
34#include <errno.h>
45#include <inttypes.h>
6+ #include <locale.h>
57#include <stdio.h>
68#include <stdlib.h>
79#include <string.h>
1719static int cw_jid = 3 , cw_name = 20 , cw_pct = 4 , cw_mem = 6 ;
1820static int cw_iops = 5 , cw_iovol = 6 , cw_cnt = 5 ;
1921
22+ static int smart_terminal = 1 ;
23+
2024static void print_n (uint64_t v , int colwidth );
2125static void print_nmp (uint64_t v , int colwidth );
2226
@@ -45,6 +49,16 @@ static const size_t tot_metrics =
4549 sizeof (all_metrics ) / sizeof (all_metrics [0 ]);
4650static const struct metric * metrics [30 ];
4751
52+ /* Rudimentary I/O abstraction to support smart and dump terminals */
53+ struct iofuncs {
54+ /* x-prefix is a work-around as clear, attron... are macros */
55+ int (* xclear )(void );
56+ int (* xattron )(int attrs );
57+ int (* xattroff )(int attrs );
58+ int (* xprint )(const char * fmt , ...);
59+ int (* xrefresh )(void );
60+ } io = { 0 };
61+
4862static const struct metric *
4963find_metric (const char * name )
5064{
@@ -77,7 +91,7 @@ findval(const char *list,
7791static void
7892print_n (uint64_t v , int colwidth )
7993{
80- printf ("%*" PRIu64 , colwidth , v );
94+ io . xprint ("%*" PRIu64 , colwidth , v );
8195}
8296
8397static void
@@ -92,26 +106,29 @@ print_nmp(uint64_t v, int colwidth)
92106 v / (1024 * 1024 * 1024.0 ));
93107 else if (v > 9999 * 1024 )
94108 snprintf (buf , sizeof buf , "%.1fM" ,
95- v / (1024 * 1024.0 ));
109+ v / (1024 * 1024.0 ));
96110 else /* if (v > 9999) */
97111 snprintf (buf , sizeof buf , "%.0fK" ,
98- v / 1024.0 );
112+ v / 1024.0 );
99113 }
100- printf ("%*s" , colwidth , buf );
114+ io . xprint ("%*s" , colwidth , buf );
101115}
102116
103117
104118static void
105119print_headers (void )
106120{
107- printf ("%*s %-*s" ,
108- cw_jid , "jid" ,
109- cw_name , "name" );
121+ io .xclear ();
122+ io .xattron (A_BOLD );
123+ io .xprint ("%*s %-*s" ,
124+ cw_jid , "jid" ,
125+ cw_name , "name" );
110126 const struct metric * * it = metrics ;
111127 for (; * it ; ++ it ) {
112- printf (" %*s" , * (* it )-> colwidth , (* it )-> label );
128+ io . xprint (" %*s" , * (* it )-> colwidth , (* it )-> label );
113129 }
114- puts ("" );
130+ io .xprint ("\n" );
131+ io .xattroff (A_BOLD );
115132}
116133
117134
@@ -120,9 +137,9 @@ print_jail(int jid,
120137 const char * name )
121138{
122139 char q [MAXHOSTNAMELEN + 20 ], buf [4096 ];
123- printf ("%*d %-*s" ,
124- cw_jid , jid ,
125- cw_name , name );
140+ io . xprint ("%*d %-*s" ,
141+ cw_jid , jid ,
142+ cw_name , name );
126143
127144 snprintf (q , sizeof q , "jail:%s:cputime" , name );
128145 int rv = rctl_get_racct (q , strlen (q ) + 1 ,
@@ -132,16 +149,63 @@ print_jail(int jid,
132149 * pairs: cputime=##,datasize=##,... */
133150 const struct metric * * it = metrics ;
134151 for (; * it ; ++ it ) {
135- printf (" " );
152+ io . xprint (" " );
136153 (* it )-> print (findval (buf , (* it )-> name ),
137154 * (* it )-> colwidth );
138155 }
139156 } else {
140157 if (errno == ENOSYS )
141158 err (EX_OSERR , "rctl_get_racct" );
142- printf (": %s" , strerror (errno ));
159+ io .xprint (": %s" , strerror (errno ));
160+ }
161+ io .xprint ("\n" );
162+ }
163+
164+
165+ static int
166+ no_clear (void )
167+ {
168+ return 0 ;
169+ }
170+ static int
171+ no_refresh (void )
172+ {
173+ printf ("\n" );
174+ fflush (stdout );
175+ return 0 ;
176+ }
177+ static int
178+ no_attrtoggle (int attrs )
179+ {
180+ (void )attrs ;
181+ return 0 ;
182+ }
183+
184+ static void
185+ init_io (void )
186+ {
187+ smart_terminal = getenv ("TERM" ) != 0 ;
188+ if (smart_terminal ) {
189+ smart_terminal = isatty (1 );
190+ }
191+
192+ if (smart_terminal ) {
193+ /* Initialize curses library */
194+ setlocale (LC_ALL , "" );
195+ initscr ();
196+
197+ io .xclear = & clear ;
198+ io .xattron = & attron ;
199+ io .xattroff = & attroff ;
200+ io .xprint = & printw ;
201+ io .xrefresh = & refresh ;
202+ } else { /* dump terminal */
203+ io .xclear = & no_clear ;
204+ io .xattron = & no_attrtoggle ;
205+ io .xattroff = & no_attrtoggle ;
206+ io .xprint = & printf ;
207+ io .xrefresh = & no_refresh ;
143208 }
144- puts ("" );
145209}
146210
147211
@@ -212,6 +276,12 @@ main(int argc, char *argv[])
212276 jailparam_import_raw (& param [2 ], name , sizeof name ) == -1 )
213277 errx (EX_OSERR , "jailparam_import_raw: %s" , jail_errmsg );
214278
279+ init_io ();
280+
281+ if (count == INT_MAX && !smart_terminal ) {
282+ count = 1 ;
283+ }
284+
215285 do {
216286 int jflags = 0 , rv , n ;
217287 lastjid = n = 0 ;
@@ -230,6 +300,7 @@ main(int argc, char *argv[])
230300 if (!n )
231301 errx (EX_UNAVAILABLE , "no jails found" );
232302
303+ io .xrefresh ();
233304 if (count > 1 ) {
234305 sleep (sleep_itv );
235306 puts ("" );
0 commit comments