]> granicus.if.org Git - procps-ng/commitdiff
revert the Nov2002 c99 attempt
authoralbert <>
Thu, 28 Nov 2002 23:09:48 +0000 (23:09 +0000)
committeralbert <>
Thu, 28 Nov 2002 23:09:48 +0000 (23:09 +0000)
top.c
top.h
watch.c

diff --git a/top.c b/top.c
index b6ca38105529e46c3b9996788201a25135c2d283..9bccc9d47e92c51ea4e7ce079bd720ae02ce2f3f 100644 (file)
--- a/top.c
+++ b/top.c
@@ -810,7 +810,7 @@ static void *alloc_r (void *q, unsigned numb)
          * as follows:
          *    cpus[0] thru cpus[n] == tics for each separate cpu
          *    cpus[Cpu_tot]        == tics from the 1st /proc/stat line */
-static CPUS_t *cpus_refresh (CPUS_t *restrict cpus)
+static CPUS_t *cpus_refresh (CPUS_t *cpus)
 {
    static FILE *fp = NULL;
    int i;
@@ -1132,7 +1132,7 @@ static void parse_args (char **args)
    char *p;
 
    while (*args) {
-      char *cp = *(args++);
+      const char *cp = *(args++);
 
       while (*cp) {
          switch (*cp) {
@@ -1261,8 +1261,9 @@ static void whack_terminal (void)
 #define L_CMDLINE  L_stat   | PROC_FILLARG
 #define L_EUSER    L_status | PROC_FILLUSR
 #define L_GROUP    L_status | PROC_FILLGRP
-#define L_EITHER   PROC_SPARE_1
 #define L_NONE     0
+   // from either 'stat' or 'status' (preferred), via bits not otherwise used
+#define L_EITHER  ~(L_stat|L_statm|L_status|L_CMDLINE|L_EUSER|L_GROUP)
    // for reframewins and summary_show 1st pass
 #define L_DEFAULT  PROC_FILLSTAT
 
@@ -1287,7 +1288,7 @@ static FTAB_t  Fieldstab[] = {
    { "USER     ",   "%-8.8s ",  -1,    -1, _SF(P_USR), "User Name",            L_EUSER  },
    { "GROUP    ",   "%-8.8s ",  -1,    -1, _SF(P_GRP), "Group Name",           L_GROUP  },
    { "TTY      ",   "%-8.8s ",   8,    -1, _SF(P_TTY), "Controlling Tty",      L_stat   },
-   { " PR ",        "%s ",      -1,    -1, _SF(P_PRI), "Priority",             L_stat   },
+   { " PR ",        "%3d ",     -1,    -1, _SF(P_PRI), "Priority",             L_stat   },
    { " NI ",        "%3d ",     -1,    -1, _SF(P_NCE), "Nice value",           L_stat   },
    { "#C ",         "%2u ",     -1,    -1, _SF(P_CPN), "Last used cpu (SMP)",  L_stat   },
    { "%CPU ",       "%#4.1f ",  -1,    -1, _SF(P_CPU), "CPU usage",            L_stat   },
@@ -1312,7 +1313,11 @@ static FTAB_t  Fieldstab[] = {
    { "Command ",    "%-*.*s ",  -1,    -1, _SF(P_CMD), "Command name/line",    L_stat   },
    { "WCHAN     ",  "%-9.9s ",  -1,    -1, _SF(P_WCH), "Sleeping in Function", L_stat   },
    // next entry's special: the 0's will be replaced with '.'!
-   { "Flags    ",   "%s ",      -1,    -1, _SF(P_FLG), "Task Flags <sched.h>", L_stat   }
+#ifdef CASEUP_HEXES
+   { "Flags    ",   "%08lX ",   -1,    -1, _SF(P_FLG), "Task Flags <sched.h>", L_stat   }
+#else
+   { "Flags    ",   "%08lx ",   -1,    -1, _SF(P_FLG), "Task Flags <sched.h>", L_stat   }
+#endif
 };
 
 
@@ -2164,7 +2169,7 @@ static void do_key (unsigned c)
          *    2) modest smp boxes with room for each cpu's percentages
          *    3) massive smp guys leaving little or no room for process
          *       display and thus requiring the cpu summary toggle */
-static void summaryhlp (CPUS_t *restrict const cpu, const char *restrict const pfx)
+static void summaryhlp (CPUS_t *cpu, const char *pfx)
 {
    /* we'll trim to zero if we get negative time ticks,
       which has happened with some SMP kernels (pre-2.4?) */
@@ -2280,7 +2285,7 @@ static proc_t **summary_show (void)
 
         /*
          * Display information for a single task row. */
-static void task_show (const WIN_t *restrict q, const proc_t *restrict p)
+static void task_show (const WIN_t *q, const proc_t *p)
 {
    /* the following macro is our means to 'inline' emitting a column -- next to
       procs_refresh, that's the most frequent and costly part of top's job ! */
@@ -2304,18 +2309,17 @@ static void task_show (const WIN_t *restrict q, const proc_t *restrict p)
 
    for (x = 0; x < q->maxpflgs; x++) {
       char cbuf[ROWBUFSIZ], _z[ROWBUFSIZ];
-      PFLG_t      i = q->procflags[x];          // support for our make column
-      const char *restrict const f = Fieldstab[i].fmts; // macro AND sometimes
-      unsigned    s = Fieldstab[i].scale;       // fmt string must be altered !
+      PFLG_t      i = q->procflags[x];          // support for our field/column
+      const char *f = Fieldstab[i].fmts;        // macro AND sometimes the fmt
+      unsigned    s = Fieldstab[i].scale;       // string must be altered !
       unsigned    w = Fieldstab[i].width;
 
       switch (i) {
          case P_CMD:
-         {  const char *restrict ret;
+         {  char *cp;
             if (CHKw(q, Show_CMDLIN)) {
                char tmp[ROWBUFSIZ];
                if (p->cmdline) {
-                  char *cp;
                   j = 0;
                   *(cp = tmp) = '\0';
                   do {
@@ -2325,10 +2329,10 @@ static void task_show (const WIN_t *restrict q, const proc_t *restrict p)
                   strim(1, tmp);
                } else
                   strcpy(tmp, fmtmk(CMDLINE_FMTS, p->cmd));
-               ret = tmp;
+               cp = tmp;
             } else
-               ret = p->cmd;
-            MKCOL(q->maxcmdln, q->maxcmdln, ret);
+               cp = (char *)p->cmd;
+            MKCOL(q->maxcmdln, q->maxcmdln, cp);
          }
             break;
          case P_COD:
@@ -2351,9 +2355,10 @@ static void task_show (const WIN_t *restrict q, const proc_t *restrict p)
             break;
          case P_FLG:
          {  char tmp[TNYBUFSIZ];
-            snprintf(tmp, sizeof(tmp), "%08x", (unsigned)p->flags);
+            snprintf(tmp, sizeof(tmp), f, (long)p->flags);
             for (j = 0; tmp[j]; j++) if ('0' == tmp[j]) tmp[j] = '.';
-            MKCOL(tmp);
+            f = tmp;
+            MKCOL();
          }
             break;
          case P_FLT:
@@ -2378,13 +2383,11 @@ static void task_show (const WIN_t *restrict q, const proc_t *restrict p)
             MKCOL((unsigned)p->ppid);
             break;
          case P_PRI:
-         {  char tmp[TNYBUFSIZ];
-            snprintf(tmp, sizeof(tmp), "%3d", (int)(p->priority));
-            if (-99 > p->priority || 999 < p->priority) {
-               memcpy(tmp, " RT", 4);
-            }
-            MKCOL(tmp);
-         }
+            if (-99 > p->priority || +99 < p->priority) {
+               f = " RT ";
+               MKCOL();
+            } else
+               MKCOL((int)p->priority);
             break;
          case P_RES:
             MKCOL(scale_num(PAGES_2K(p->resident), w, s));
@@ -2427,9 +2430,12 @@ static void task_show (const WIN_t *restrict q, const proc_t *restrict p)
             break;
          case P_WCH:
             if (No_ksyms) {
-               char tmp[TNYBUFSIZ];
-               snprintf(tmp, sizeof(tmp), "%08lx  ", (unsigned long)p->wchan);
-               MKCOL(tmp);
+#ifdef CASEUP_HEXES
+               f = "%08lX  ";
+#else
+               f = "%08lx  ";
+#endif
+               MKCOL((long)p->wchan);
             } else {
                MKCOL(wchan(p->wchan));
             }
diff --git a/top.h b/top.h
index 3c48b4f815eec7cc5ca231441287225f7c34facc..f9ff5d99ea81d989c2faf413060d9d9be0cdb22d 100644 (file)
--- a/top.h
+++ b/top.h
    static int sort_ ## f (const proc_t **P, const proc_t **Q) { \
       return Frame_srtflg * strcmp((*Q)->s, (*P)->s); }
 
-        /* Used in the following ways, to 'inline' those portions of the
-           display requiring formatting while protecting against potential
-           embedded 'millesecond delay' escape sequences.
-              PUTT - Put to Tty
-               . for temporary interactive 'REPLACEMENT' output
+        /* The following two macros are used to 'inline' those portions of the
+         * display process requiring formatting, while protecting against any
+         * potential embedded 'millesecond delay' escape sequences. */
+        /**  PUTT - Put to Tty (used in many places)
+               . for temporary, possibly interactive, 'replacement' output
                . may contain ANY valid terminfo escape sequences
-               . need NOT represent an entire screen row
-              PUFF - Put for Frame
-               . for more permanent frame-oriented 'UPDATE' output
-               . may NOT contain cursor motion terminfo escapes
-               . represents a complete screen ROW
-               . subject to optimization, thus MAY be discarded
-               . when discarded, replaced by a NEWLINE */
+               . need NOT represent an entire screen row */
 #define PUTT(fmt,arg...) do { \
       char _str[ROWBUFSIZ]; \
       snprintf(_str, sizeof(_str), fmt, ## arg); \
       putp(_str); \
    } while (0)
+        /**  PUFF - Put for Frame (used in only 3 places)
+               . for more permanent frame-oriented 'update' output
+               . may NOT contain cursor motion terminfo escapes
+               . assumed to represent a complete screen ROW
+               . subject to optimization, thus MAY be discarded */
 #define PUFF(fmt,arg...) do { \
       char _str[ROWBUFSIZ]; \
       char *_ptr = &Pseudo_scrn[Pseudo_row++ * Pseudo_cols]; \
@@ -189,10 +188,8 @@ typedef struct {
            calculations.  It exists primarily for SMP support but serves
            all environments. */
 typedef struct {
-        // ticks count as represented in /proc/stat
-   TICS_t u, n, s, i, w;
-        // tics count in the order of our display
-   TICS_t u_sav, s_sav, n_sav, i_sav, w_sav;
+   TICS_t u, n, s, i, w;                        // as represented in /proc/stat
+   TICS_t u_sav, s_sav, n_sav, i_sav, w_sav;    // in the order of our display
 } CPUS_t;
 
         /* The scaling 'type' used with scale_num() -- this is how
@@ -512,6 +509,20 @@ typedef struct win {
    "commands plus the 'G' sub-commands NOW.  Press <Enter> to make 'Current' " \
    ""
 
+
+/*######  For Piece of mind and/or backward compatability ################*/
+
+        /* just sanity check(s)... */
+#if USRNAMSIZ < GETBUFSIZ
+# error "Jeeze, USRNAMSIZ Must NOT be less than GETBUFSIZ !"
+#endif
+#ifndef  MALLOC
+# define MALLOC
+#endif
+#ifndef  restrict
+# define restrict
+#endif
+
 \f
 /*######  Some Prototypes (ha!)  #########################################*/
 
@@ -521,9 +532,9 @@ typedef struct win {
     * source code navigation, which often influences the identifers. */
 /*------  Sort callbacks  ------------------------------------------------*/
 /*        for each possible field, in the form of:                        */
-/*atic int          sort_P_XXX (const proc_t **P, const proc_t **Q);       */
+/*atic int          sort_P_XXX (const proc_t **P, const proc_t **Q);      */
 /*        additional specialized sort callback(s)                         */
-//atic int          sort_HIST_t (const HIST_t *P, const HIST_t *Q);
+/*atic int          sort_HIST_t (const HIST_t *P, const HIST_t *Q);       */
 /*------  Tiny useful routine(s)  ----------------------------------------*/
 //atic int          chin (int ech, char *buf, unsigned cnt);
 //atic const char  *fmtmk (const char *fmts, ...);
@@ -550,7 +561,7 @@ typedef struct win {
 /*------  Library Alternatives  ------------------------------------------*/
 //atic void        *alloc_c (unsigned numb) MALLOC;
 //atic void        *alloc_r (void *q, unsigned numb) MALLOC;
-//atic CPUS_t      *cpus_refresh (CPUS_t *restrict cpus);
+//atic CPUS_t      *cpus_refresh (CPUS_t *cpus);
 //atic void         prochlp (proc_t *this);
 //atic proc_t     **procs_refresh (proc_t **table, int flags);
 /*------  Startup routines  ----------------------------------------------*/
@@ -559,7 +570,7 @@ typedef struct win {
 //atic void         parse_args (char **args);
 //atic void         whack_terminal (void);
 /*------  Field Selection/Ordering routines  -----------------------------*/
-/*atic FTAB_t       Fieldstab[] = { ... }                                  */
+/*atic FTAB_t       Fieldstab[] = { ... }                                 */
 //atic void         display_fields (const char *fields, const char *xtra);
 //atic void         fields_reorder (void);
 //atic void         fields_sort (void);
@@ -577,19 +588,14 @@ typedef struct win {
 //atic void         windows_stage2 (void);
 /*------  Main Screen routines  ------------------------------------------*/
 //atic void         do_key (unsigned c);
-//atic void         summaryhlp (CPUS_t *restrict const cpu, const char *restrict const pfx);
+//atic void         summaryhlp (CPUS_t *cpu, const char *pfx);
 //atic proc_t     **summary_show (void);
-//atic void         task_show (const WIN_t *restrict q, const proc_t *restrict p);
+//atic void         task_show (const WIN_t *q, const proc_t *p);
 //atic void         window_show (proc_t **ppt, WIN_t *q, int *lscr);
 /*------  Entry point plus two  ------------------------------------------*/
 //atic void         framehlp (int wix, int max);
 //atic void         frame_make (void);
 //     int          main (int dont_care_argc, char **argv);
 
-        /* just sanity check(s)... */
-#if USRNAMSIZ < GETBUFSIZ
-# error "Jeeze, USRNAMSIZ Must NOT be less than GETBUFSIZ !"
-#endif
-
 #endif /* _Itop */
 \f
diff --git a/watch.c b/watch.c
index 5a6df452f76e6936cd83528843e4071cbc87769a..41445adedc7a391a497ad54cc2325e07b12bb34d 100644 (file)
--- a/watch.c
+++ b/watch.c
@@ -8,7 +8,6 @@
  * Mike Coleman <mkc@acm.org>.
  */
 
-
 #define VERSION "0.2.0"
 
 #include <ctype.h>
 #include <unistd.h>
 #include <locale.h>
 
-static struct option longopts[] =
-  {
-    { "differences", optional_argument, 0, 'd' },
-    { "help", no_argument, 0, 'h' },
-    { "interval", required_argument, 0, 'n' },
-    { "version", no_argument, 0, 'v' },
-    { 0, 0, 0, 0 }
-  };
-
-static char usage[] = "Usage: %s [-dhnv] [--differences[=cumulative]] [--help] [--interval=<n>] [--version] <command>\n";
+static struct option longopts[] = {
+       {"differences", optional_argument, 0, 'd'},
+       {"help", no_argument, 0, 'h'},
+       {"interval", required_argument, 0, 'n'},
+       {"version", no_argument, 0, 'v'},
+       {0, 0, 0, 0}
+};
 
+static char usage[] =
+    "Usage: %s [-dhnv] [--differences[=cumulative]] [--help] [--interval=<n>] [--version] <command>\n";
 
 static char *progname;
 
 static int curses_started = 0;
-static int height=24, width=80;
-static int screen_size_changed=0;
-static int first_screen=1;
-
+static int height = 24, width = 80;
+static int screen_size_changed = 0;
+static int first_screen = 1;
 
 #define min(x,y) ((x) > (y) ? (y) : (x))
 
-
 static void
 do_usage(void)
 {
-  fprintf(stderr, usage, progname);
-  exit(1);
+       fprintf(stderr, usage, progname);
+       exit(1);
 }
 
-
 static void
-do_exit(int status) {
-  if (curses_started)
-    endwin();
-  exit(status);
+do_exit(int status)
+{
+       if (curses_started)
+               endwin();
+       exit(status);
 }
 
-
 /* signal handler */
 static void
 die(int notused)
 {
-  (void)notused;
-  do_exit(0);
+       (void) notused;
+       do_exit(0);
 }
 
-
 static void
 winch_handler(int notused)
 {
-  (void)notused;
-  screen_size_changed = 1;
+       (void) notused;
+       screen_size_changed = 1;
 }
 
-
 static void
 get_terminal_size(void)
 {
-  struct winsize w;
-  if (ioctl(2, TIOCGWINSZ, &w) == 0)
-    {
-      if (w.ws_row > 0)
-       height = w.ws_row;
-      if (w.ws_col > 0)
-       width = w.ws_col;
-    }
+       struct winsize w;
+       if (ioctl(2, TIOCGWINSZ, &w) == 0) {
+               if (w.ws_row > 0)
+                       height = w.ws_row;
+               if (w.ws_col > 0)
+                       width = w.ws_col;
+       }
 }
 
-
 int
 main(int argc, char *argv[])
 {
-  int optc;
-  int option_differences=0,
-    option_differences_cumulative=0,
-    option_help=0,
-    option_version=0;
-  int interval=2;
-  char *command;
-  int command_length=0;                /* not including final \0 */
-
-  setlocale(LC_ALL,"");
-  progname = argv[0];
-
-  while ((optc = getopt_long(argc, argv, "+d::hn:v", longopts, (int *) 0))
-        != EOF)
-    {
-      switch (optc)
-       {
-       case 'd':
-         option_differences = 1;
-         if (optarg)
-           option_differences_cumulative = 1;
-         break;
-       case 'h':
-         option_help = 1;
-         break;
-       case 'n':
-         {
-           char *str;
-           interval = strtol(optarg, &str, 10);
-           if (!*optarg || *str)
-             do_usage();
-         }
-         break;
-       case 'v':
-         option_version = 1;
-         break;
-       default:
-         do_usage();
-         break;
+       int optc;
+       int option_differences = 0,
+           option_differences_cumulative = 0,
+           option_help = 0, option_version = 0;
+       int interval = 2;
+       char *command;
+       int command_length = 0; /* not including final \0 */
+
+       setlocale(LC_ALL, "");
+       progname = argv[0];
+
+       while ((optc = getopt_long(argc, argv, "+d::hn:v", longopts, (int *) 0))
+              != EOF) {
+               switch (optc) {
+               case 'd':
+                       option_differences = 1;
+                       if (optarg)
+                               option_differences_cumulative = 1;
+                       break;
+               case 'h':
+                       option_help = 1;
+                       break;
+               case 'n':
+                       {
+                               char *str;
+                               interval = strtol(optarg, &str, 10);
+                               if (!*optarg || *str)
+                                       do_usage();
+                       }
+                       break;
+               case 'v':
+                       option_version = 1;
+                       break;
+               default:
+                       do_usage();
+                       break;
+               }
        }
-    }
-
-  if (option_version)
-    {
-      fprintf (stderr, "%s\n", VERSION);
-      if (!option_help)
-       exit(0);
-    }
-
-  if (option_help)
-    {
-      fprintf(stderr, usage, progname);
-      fputs("  -d, --differences[=cumulative]\thighlight changes between updates\n", stderr);
-      fputs("\t\t(cumulative means highlighting is cumulative)\n", stderr);
-      fputs("  -h, --help\t\t\t\tprint a summary of the options\n", stderr);
-      fputs("  -n, --interval=<seconds>\t\tseconds to wait between updates\n", stderr);
-      fputs("  -v, --version\t\t\t\tprint the version number\n", stderr);
-      exit(0);
-    }
-
-  if (optind >= argc)
-    do_usage();
-
-  command = strdup(argv[optind++]);
-  command_length = strlen(command);
-  for (;optind<argc;optind++)
-    {
-      char *endp;
-      int s = strlen(argv[optind]);
-      command = realloc(command, command_length+s+2); /* space and \0 */
-      endp = command + command_length;
-      *endp = ' ';
-      memcpy(endp+1, argv[optind],s);
-      command_length += 1+s; /* space then string length */
-      command[command_length] = '\0';
-    }
-
-  get_terminal_size();
-
-  /* Catch keyboard interrupts so we can put tty back in a sane state.  */
-  signal(SIGINT, die);
-  signal(SIGTERM, die);
-  signal(SIGHUP, die);
-  signal(SIGWINCH, winch_handler);
-
-  /* Set up tty for curses use.  */
-  curses_started = 1;
-  initscr();
-  nonl();
-  noecho();
-  cbreak();
-
-  for(;;)
-    {
-      time_t t = time(NULL);
-      char *ts = ctime(&t);
-      int tsl = strlen(ts);
-      char *header;
-      FILE *p;
-      int x, y;
-      int oldeolseen = 1;
-
-      if (screen_size_changed)
-       {
-         get_terminal_size();
-         resizeterm(height, width);
-         clear();
-         /* redrawwin(stdscr); */
-         screen_size_changed = 0;
-         first_screen = 1;
+
+       if (option_version) {
+               fprintf(stderr, "%s\n", VERSION);
+               if (!option_help)
+                       exit(0);
+       }
+
+       if (option_help) {
+               fprintf(stderr, usage, progname);
+               fputs
+                   ("  -d, --differences[=cumulative]\thighlight changes between updates\n",
+                    stderr);
+               fputs("\t\t(cumulative means highlighting is cumulative)\n",
+                     stderr);
+               fputs("  -h, --help\t\t\t\tprint a summary of the options\n",
+                     stderr);
+               fputs
+                   ("  -n, --interval=<seconds>\t\tseconds to wait between updates\n",
+                    stderr);
+               fputs("  -v, --version\t\t\t\tprint the version number\n",
+                     stderr);
+               exit(0);
        }
 
-      /* left justify interval and command, right justify time, clipping all
-        to fit window width */
-      asprintf(&header, "Every %ds: %.*s",
-              interval, min(width-1, command_length), command);
-      mvaddstr(0, 0, header);
-      if (strlen(header) > (size_t)(width - tsl - 1))
-        mvaddstr(0, width - tsl - 4, "...  ");
-      mvaddstr(0, width - tsl + 1, ts);
-      free(header);
-
-      if (!(p = popen(command, "r")))
-       {
-         perror("popen");
-         do_exit(2);
+       if (optind >= argc)
+               do_usage();
+
+       command = strdup(argv[optind++]);
+       command_length = strlen(command);
+       for (; optind < argc; optind++) {
+               char *endp;
+               int s = strlen(argv[optind]);
+               command = realloc(command, command_length + s + 2);     /* space and \0 */
+               endp = command + command_length;
+               *endp = ' ';
+               memcpy(endp + 1, argv[optind], s);
+               command_length += 1 + s;        /* space then string length */
+               command[command_length] = '\0';
        }
 
-      for (y=2; y<height; y++)
-       {
-         int eolseen = 0, tabpending = 0;
-         for (x=0; x<width; x++)
-           {
-             int c = ' ';
-             int attr = 0;
-             
-             if (!eolseen)
-               {
-                 /* if there is a tab pending, just spit spaces until the
-                    next stop instead of reading characters */
-                 if (!tabpending)
-                   do
-                     c = getc(p);
-                   while (c != EOF && !isprint(c) && c != '\n' && c != '\t');
-                 if (c == '\n')
-                   if (!oldeolseen && x == 0) {
-                     x=-1;
-                     continue;
-                   } else
-                   eolseen = 1;
-                 else if (c == '\t')
-                   tabpending = 1;
-                 if (c == EOF || c == '\n' || c == '\t')
-                   c = ' ';
-                 if (tabpending && (((x + 1) % 8) == 0))
-                   tabpending = 0;
+       get_terminal_size();
+
+       /* Catch keyboard interrupts so we can put tty back in a sane state.  */
+       signal(SIGINT, die);
+       signal(SIGTERM, die);
+       signal(SIGHUP, die);
+       signal(SIGWINCH, winch_handler);
+
+       /* Set up tty for curses use.  */
+       curses_started = 1;
+       initscr();
+       nonl();
+       noecho();
+       cbreak();
+
+       for (;;) {
+               time_t t = time(NULL);
+               char *ts = ctime(&t);
+               int tsl = strlen(ts);
+               char *header;
+               FILE *p;
+               int x, y;
+               int oldeolseen = 1;
+
+               if (screen_size_changed) {
+                       get_terminal_size();
+                       resizeterm(height, width);
+                       clear();
+                       /* redrawwin(stdscr); */
+                       screen_size_changed = 0;
+                       first_screen = 1;
                }
-             move(y, x);
-             if (option_differences)
-               {
-                 int oldch = inch();
-                 char oldc = oldch & A_CHARTEXT;
-                 attr = !first_screen
-                   && (c != oldc
-                       || (option_differences_cumulative
-                           && (oldch & A_ATTRIBUTES)));
+
+               /* left justify interval and command, right justify time, clipping all
+                  to fit window width */
+               asprintf(&header, "Every %ds: %.*s",
+                        interval, min(width - 1, command_length), command);
+               mvaddstr(0, 0, header);
+               if (strlen(header) > (size_t) (width - tsl - 1))
+                       mvaddstr(0, width - tsl - 4, "...  ");
+               mvaddstr(0, width - tsl + 1, ts);
+               free(header);
+
+               if (!(p = popen(command, "r"))) {
+                       perror("popen");
+                       do_exit(2);
                }
-             if (attr)
-               standout();
-             addch(c);
-             if (attr)
-               standend();
-           }
-         oldeolseen = eolseen;
-       }
 
-      pclose(p);
+               for (y = 2; y < height; y++) {
+                       int eolseen = 0, tabpending = 0;
+                       for (x = 0; x < width; x++) {
+                               int c = ' ';
+                               int attr = 0;
+
+                               if (!eolseen) {
+                                       /* if there is a tab pending, just spit spaces until the
+                                          next stop instead of reading characters */
+                                       if (!tabpending)
+                                               do
+                                                       c = getc(p);
+                                               while (c != EOF && !isprint(c)
+                                                      && c != '\n'
+                                                      && c != '\t');
+                                       if (c == '\n')
+                                               if (!oldeolseen && x == 0) {
+                                                       x = -1;
+                                                       continue;
+                                               } else
+                                                       eolseen = 1;
+                                       else if (c == '\t')
+                                               tabpending = 1;
+                                       if (c == EOF || c == '\n' || c == '\t')
+                                               c = ' ';
+                                       if (tabpending && (((x + 1) % 8) == 0))
+                                               tabpending = 0;
+                               }
+                               move(y, x);
+                               if (option_differences) {
+                                       int oldch = inch();
+                                       char oldc = oldch & A_CHARTEXT;
+                                       attr = !first_screen
+                                           && (c != oldc
+                                               ||
+                                               (option_differences_cumulative
+                                                && (oldch & A_ATTRIBUTES)));
+                               }
+                               if (attr)
+                                       standout();
+                               addch(c);
+                               if (attr)
+                                       standend();
+                       }
+                       oldeolseen = eolseen;
+               }
 
-      first_screen = 0;
-      refresh();
-      sleep(interval);
-    }
+               pclose(p);
+
+               first_screen = 0;
+               refresh();
+               sleep(interval);
+       }
 
-  endwin();
+       endwin();
 
-  return 0;
+       return 0;
 }