]> granicus.if.org Git - procps-ng/commitdiff
not done yet
authoralbert <>
Wed, 4 Dec 2002 22:48:30 +0000 (22:48 +0000)
committeralbert <>
Wed, 4 Dec 2002 22:48:30 +0000 (22:48 +0000)
top.c
top.h

diff --git a/top.c b/top.c
index 515ddf40f6c53999c68be1fcec47098c7a5bbd73..ca6b5d37a9ef91e2af2df5993e40bd20c9604d50 100644 (file)
--- a/top.c
+++ b/top.c
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <fcntl.h>
 #include <ctype.h>
 #include <curses.h>
 #include <errno.h>
+#include <fcntl.h>
 #include <signal.h>
 #include <stdarg.h>
 #include <stdio.h>
         /* The original and new terminal attributes */
 static struct termios Savedtty,
                       Rawtty;
-static int  Ttychanged = 0;
+static int Ttychanged = 0;
 
         /* Program name used in error messages and local 'rc' file name */
 static char *Myname;
 
-        /* The Name of the local config file, dynamically constructed */
-static char  RCfile [OURPATHSZ];
+        /* Name of user config file (dynamically constructed) and our
+           'Current' rcfile contents, initialized with defaults but may be
+           overridden with the local rcfile (old or new-style) values */
+static char  Rc_name [OURPATHSZ];
+static RCF_t Rc = DEF_RCFILE;
+
         /* The run-time acquired page size */
-static int  Page_size;
+static int Page_size;
 
         /* SMP, Irix/Solaris mode, Linux 2.5.xx support */
-static int   Cpu_tot,
-            *Cpu_map;
+static int  Cpu_tot,
+           *Cpu_map;
         /* assume no IO-wait stats, overridden if linux 2.5.41 */
 static const char *States_fmts = STATES_line2x4;
 
         /* Specific process id monitoring support */
-static pid_t  Monpids [MONPIDMAX] = { 0 };
-static int    Monpidsidx = 0;
+static pid_t Monpids [MONPIDMAX] = { 0 };
+static int   Monpidsidx = 0;
 
         /* A postponed error message */
-static char  Msg_delayed [SMLBUFSIZ];
-static int   Msg_awaiting = 0;
+static char Msg_delayed [SMLBUFSIZ];
+static int  Msg_awaiting = 0;
 
         /* Configurable Display support ##################################*/
 
@@ -86,28 +90,20 @@ static int   Msg_awaiting = 0;
                  basis (see the WIN_t).  Max_lines is the total number of
                  screen rows after deducting summary information overhead. */
         /* Current terminal screen size. */
-static int  Screen_cols, Screen_rows, Max_lines;
+static int Screen_cols, Screen_rows, Max_lines;
 
         /* This is really the number of lines needed to display the summary
            information (0 - nn), but is used as the relative row where we
            stick the cursor between frames. */
-static int  Msg_row;
-
-        /* Global/Non-windows mode stuff that IS persistent (in rcfile) */
-static int    Mode_altscr = 0;  /* 'A' - 'Alt' display mode (multi windows)  */
-        /* 11/02 - next no longer alters a proc_t, it COULD be window based! */
-static int    Mode_irixps = 1;  /* 'I' - Irix vs. Solaris mode (SMP-only)    */
-static float  Delay_time = DEF_DELAY;  /* how long to sleep between updates  */
-
-        /* Global/Non-windows mode stuff for the persistance itself */
-static int    Crufty_config = 0;  /* if we read an old config, write one too */
+static int Msg_row;
 
         /* Global/Non-windows mode stuff that is NOT persistent */
-static int  No_ksyms = -1,      /* set to '0' if ksym avail, '1' otherwise   */
-            PSDBopen = 0,       /* set to '1' if psdb opened (now postponed) */
-            Batch = 0,          /* batch mode, collect no input, dumb output */
-            Loops = -1,         /* number of iterations, -1 loops forever    */
-            Secure_mode = 0;    /* set if some functionality restricted      */
+static int Crufty_rcf = 0,      // if we read an old config, write one too
+           No_ksyms = -1,       // set to '0' if ksym avail, '1' otherwise
+           PSDBopen = 0,        // set to '1' if psdb opened (now postponed)
+           Batch = 0,           // batch mode, collect no input, dumb output
+           Loops = -1,          // number of iterations, -1 loops forever
+           Secure_mode = 0;     // set if some functionality restricted
 
         /* Some cap's stuff to reduce runtime calls --
            to accomodate 'Batch' mode, they begin life as empty strings */
@@ -122,7 +118,7 @@ static char  Cap_clr_eol    [CAPBUFSIZ] = "",
              Caps_off       [CAPBUFSIZ] = "";
 static int   Cap_can_goto = 0;
 
-        /* Some optimization stuff reducing output demands...
+        /* Some optimization stuff, to reduce output demands...
            The Pseudo_ guys are managed by wins_resize and frame_make.  They
            are exploited in a macro and represent 90% of our optimization.
            The Stdout_buf is transparent to our code and regardless of whose
@@ -146,18 +142,20 @@ static WIN_t *Winstk [GROUPSMAX],
 
         /* Frame oriented stuff that can't remain local to any 1 function
            and/or that would be too cumbersome managed as parms,
-           and/or that are simply more efficiently handled as globals */
-static int       Frame_libflgs; // current PROC_FIILxxx flags (0 = need new)
-static unsigned  Frame_maxtask; // last known number of active tasks
-                                // ie. current 'size' of proc table
-static unsigned  Frame_running, // state categories for this frame
+           and/or that are simply more efficiently handled as globals
+           (first 2 persist beyond a single frame, changed infrequently) */
+static int       Frams_libflags;  // current PROC_FIILxxx flags (0 = need new)
+//atic int       Frams_maxcmdln;  // the largest from the 4 windows
+static unsigned  Frame_maxtask;   // last known number of active tasks
+                                  // ie. current 'size' of proc table
+static unsigned  Frame_running,   // state categories for this frame
                  Frame_sleepin,
                  Frame_stopped,
                  Frame_zombied;
-static float     Frame_tscale;  // so we can '*' vs. '/' WHEN 'pcpu'
-static int       Frame_srtflg,  // the subject window's sort direction
-                 Frame_ctimes,  // the subject window's ctimes flag
-                 Frame_cmdlin;  // the subject window's cmdlin flag
+static float     Frame_tscale;    // so we can '*' vs. '/' WHEN 'pcpu'
+static int       Frame_srtflg,    // the subject window's sort direction
+                 Frame_ctimes,    // the subject window's ctimes flag
+                 Frame_cmdlin;    // the subject window's cmdlin flag
         /* ////////////////////////////////////////////////////////////// */
 
 \f
@@ -168,17 +166,17 @@ static int       Frame_srtflg,  // the subject window's sort direction
          * values.  Note that 2 of these routines serve double duty --
          * 2 columns each.
          */
-_SC_NUMx(P_PID, pid)
-_SC_NUMx(P_PPD, ppid)
-_SC_NUMx(P_PGD, pgrp)
-_SC_NUMx(P_UID, euid)
-_SC_STRx(P_USR, euser)
-_SC_STRx(P_GRP, egroup)
-_SC_NUMx(P_TTY, tty)
-_SC_NUMx(P_PRI, priority)
-_SC_NUMx(P_NCE, nice)
-_SC_NUMx(P_CPN, processor)
-_SC_NUM1(P_CPU, pcpu)
+SCB_NUMx(P_PID, pid)
+SCB_NUMx(P_PPD, ppid)
+SCB_NUMx(P_PGD, pgrp)
+SCB_NUMx(P_UID, euid)
+SCB_STRx(P_USR, euser)
+SCB_STRx(P_GRP, egroup)
+SCB_NUMx(P_TTY, tty)
+SCB_NUMx(P_PRI, priority)
+SCB_NUMx(P_NCE, nice)
+SCB_NUMx(P_CPN, processor)
+SCB_NUM1(P_CPU, pcpu)
                                         // also serves P_TM2 !
 static int sort_P_TME (const proc_t **P, const proc_t **Q)
 {
@@ -198,15 +196,15 @@ static int sort_P_TME (const proc_t **P, const proc_t **Q)
    return SORT_eq;
 }
 
-_SC_NUM1(P_VRT, size)
-_SC_NUM2(P_SWP, size, resident)
-_SC_NUM1(P_RES, resident)               // also serves P_MEM !
-_SC_NUM1(P_COD, trs)
-_SC_NUM1(P_DAT, drs)
-_SC_NUM1(P_SHR, share)
-_SC_NUM1(P_FLT, maj_flt)
-_SC_NUM1(P_DRT, dt)
-_SC_NUMx(P_STA, state)
+SCB_NUM1(P_VRT, size)
+SCB_NUM2(P_SWP, size, resident)
+SCB_NUM1(P_RES, resident)               // also serves P_MEM !
+SCB_NUM1(P_COD, trs)
+SCB_NUM1(P_DAT, drs)
+SCB_NUM1(P_SHR, share)
+SCB_NUM1(P_FLT, maj_flt)
+SCB_NUM1(P_DRT, dt)
+SCB_NUMx(P_STA, state)
 
 static int sort_P_CMD (const proc_t **P, const proc_t **Q)
 {
@@ -222,11 +220,11 @@ static int sort_P_CMD (const proc_t **P, const proc_t **Q)
    return Frame_srtflg * strcmp((*Q)->cmd, (*P)->cmd);
 }
 
-_SC_NUM1(P_WCH, wchan)
-_SC_NUM1(P_FLG, flags)
+SCB_NUM1(P_WCH, wchan)
+SCB_NUM1(P_FLG, flags)
 
         /* ///////////////////////////////// special sort for prochlp() ! */
-static int sort_HIST_t (const HIST_t *P, const HIST_t *Q)
+static int sort_HST_t (const HST_t *P, const HST_t *Q)
 {
    return -1 * ( Q->pid - P->pid );
 }
@@ -288,7 +286,7 @@ static inline char *scat (char *restrict dst, const char *restrict src)
          * in some proc cmdlines, a choice was offered twix space or null. */
 static char *strim (int sp, char *str)
 {
-   static const char ws[] = "\b\f\n\r\t\v";
+   static const char ws[] = "\b\e\f\n\r\t\v";
    char *p;
 
    if (sp)
@@ -327,12 +325,11 @@ static void bye_bye (int eno, const char *str)
    fprintf(stderr,
       "\nbye_bye's Summary report:"
       "\n\tProgram"
-      "\n\t   Linux version = %u.%u.%u"
+      "\n\t   Linux version = %u.%u.%u, %s"
+      "\n\t   Hertz = %u (%u bytes, %u-bit time)"
       "\n\t   Page_size = %d, Cpu_tot = %d, sizeof(proc_t) = %u"
-      "\n\t   %s, using Hertz = %u (%u bytes, %u-bit time)"
-      "\n\t   sizeof(CPUS_t) = %u, sizeof(HIST_t) = %u (%u HIST_t's/Page)"
-      "\n\t   CPU_FMTS_JUST1 = %s"
-      "\n\t   CPU_FMTS_MULTI = %s"
+      "\n\t   sizeof(CPU_t) = %u, sizeof(HST_t) = %u (%u HST_t's/Page)"
+      "\n\t   Crufty?  %s"
       "\n\tTerminal: %s"
       "\n\t   device = %s, ncurses = v%s"
       "\n\t   max_colors = %d, max_pairs = %d"
@@ -357,10 +354,11 @@ static void bye_bye (int eno, const char *str)
       , LINUX_VERSION_MAJOR(linux_version_code)
       , LINUX_VERSION_MINOR(linux_version_code)
       , LINUX_VERSION_PATCH(linux_version_code)
+      , procps_version
+      , (unsigned)Hertz, sizeof(Hertz), sizeof(Hertz) * 8
       , Page_size, Cpu_tot, sizeof(proc_t)
-      , procps_version, (unsigned)Hertz, sizeof(Hertz), sizeof(Hertz) * 8
-      , sizeof(CPUS_t), sizeof(HIST_t), Page_size / sizeof(HIST_t)
-      , CPU_FMTS_JUST1, CPU_FMTS_MULTI
+      , sizeof(CPU_t), sizeof(HST_t), Page_size / sizeof(HST_t)
+      , Crufty_rcf ? "Thar be dogshit - turn off the fan!" : "Whew, shoes clean."
 #ifdef PRETENDNOCAP
       , "dumb"
 #else
@@ -417,7 +415,7 @@ static void std_err (const char *str)
       -- OUR msg won't get lost in screen clutter, like so many others! */
    snprintf(buf, sizeof(buf), "\t%s: %s\n", Myname, str);
    if (!Ttychanged) {
-      fprintf(stderr, buf);
+      fprintf(stderr, "%s\n", buf);
       exit(1);
    }
       /* not to worry, he'll change our exit code to 1 due to 'buf' */
@@ -734,7 +732,7 @@ static const char *scale_num (unsigned num, const int width, const unsigned type
         /*
          * Do some scaling stuff.
          * format 'tics' to fit 'width'. */
-static const char *scale_tics (TICS_t tics, const int width)
+static const char *scale_tics (TIC_t tics, const int width)
 {
 #ifdef CASEUP_SCALE
 #define HH "%uH"
@@ -812,11 +810,11 @@ static void *alloc_r (void *q, unsigned numb)
 
         /*
          * This guy's modeled on libproc's 'five_cpu_numbers' function except
-         * we preserve all cpu data in our CPUS_t array which is organized
+         * we preserve all cpu data in our CPU_t array which is organized
          * 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 *cpus)
+static CPU_t *cpus_refresh (CPU_t *cpus)
 {
    static FILE *fp = NULL;
    int i;
@@ -828,10 +826,10 @@ static CPUS_t *cpus_refresh (CPUS_t *cpus)
    if (!fp) {
       if (!(fp = fopen("/proc/stat", "r")))
          std_err(fmtmk("Failed /proc/stat open: %s", strerror(errno)));
-      /* note: we allocate one more CPUS_t than Cpu_tot so that the last slot
+      /* note: we allocate one more CPU_t than Cpu_tot so that the last slot
                can hold tics representing the /proc/stat cpu summary (the first
                line read) -- that slot supports our View_CPUSUM toggle */
-      cpus = alloc_c((1 + Cpu_tot) * sizeof(CPUS_t));
+      cpus = alloc_c((1 + Cpu_tot) * sizeof(CPU_t));
    }
    rewind(fp);
    fflush(fp);
@@ -842,7 +840,7 @@ static CPUS_t *cpus_refresh (CPUS_t *cpus)
       , &cpus[Cpu_tot].u, &cpus[Cpu_tot].n, &cpus[Cpu_tot].s, &cpus[Cpu_tot].i, &cpus[Cpu_tot].w))
          std_err("failed /proc/stat read");
    // and just in case we're 2.2.xx compiled without SMP support...
-   if (1 == Cpu_tot) memcpy(cpus, &cpus[1], sizeof(CPUS_t));
+   if (1 == Cpu_tot) memcpy(cpus, &cpus[1], sizeof(CPU_t));
 
    // now value each separate cpu's tics
    for (i = 0; 1 < Cpu_tot && i < Cpu_tot; i++) {
@@ -863,21 +861,21 @@ static CPUS_t *cpus_refresh (CPUS_t *cpus)
          * to loop through our darn proc_t table.  He's responsible for:
          *    1) calculating the elapsed time since the previous frame
          *    2) counting the number of tasks in each state (run, sleep, etc)
-         *    3) maintaining the HIST_t's and priming the proc_t pcpu field
+         *    3) maintaining the HST_t's and priming the proc_t pcpu field
          *    4) establishing the total number tasks for this frame */
 static void prochlp (proc_t *this)
 {
-   static HIST_t   *hist_sav = NULL;
-   static HIST_t   *hist_new = NULL;
+   static HST_t    *hist_sav = NULL;
+   static HST_t    *hist_new = NULL;
    static unsigned  hist_siz = 0;       // number of structs
    static unsigned  maxt_sav;           // prior frame's max tasks
-   TICS_t tics;
+   TIC_t tics;
 
    if (!this) {
       static struct timeval oldtimev;
       struct timeval timev;
       struct timezone timez;
-      HIST_t *hist_tmp;
+      HST_t *hist_tmp;
       float et;
 
       gettimeofday(&timev, &timez);
@@ -887,7 +885,7 @@ static void prochlp (proc_t *this)
       oldtimev.tv_usec = timev.tv_usec;
 
       // if in Solaris mode, adjust our scaling for all cpus
-      Frame_tscale = 100.0f / ((float)Hertz * (float)et * (Mode_irixps ? 1 : Cpu_tot));
+      Frame_tscale = 100.0f / ((float)Hertz * (float)et * (Rc.mode_irixps ? 1 : Cpu_tot));
       maxt_sav = Frame_maxtask;
       Frame_maxtask = Frame_running = Frame_sleepin = Frame_stopped = Frame_zombied = 0;
 
@@ -895,8 +893,8 @@ static void prochlp (proc_t *this)
       hist_tmp = hist_sav;
       hist_sav = hist_new;
       hist_new = hist_tmp;
-      // prep for our binary search by sorting the last frame's HIST_t's
-      qsort(hist_sav, maxt_sav, sizeof(HIST_t), (QSORT_t)sort_HIST_t);
+      // prep for our binary search by sorting the last frame's HST_t's
+      qsort(hist_sav, maxt_sav, sizeof(HST_t), (QFP_t)sort_HST_t);
       return;
    }
 
@@ -918,8 +916,8 @@ static void prochlp (proc_t *this)
 
    if (Frame_maxtask+1 >= hist_siz) {
       hist_siz = hist_siz * 5 / 4 + 100;  // grow by at least 25%
-      hist_sav = alloc_r(hist_sav, sizeof(HIST_t) * hist_siz);
-      hist_new = alloc_r(hist_new, sizeof(HIST_t) * hist_siz);
+      hist_sav = alloc_r(hist_sav, sizeof(HST_t) * hist_siz);
+      hist_new = alloc_r(hist_new, sizeof(HST_t) * hist_siz);
    }
    /* calculate time in this process; the sum of user time (utime) and
       system time (stime) -- but PLEASE dont waste time and effort on
@@ -944,10 +942,11 @@ static void prochlp (proc_t *this)
       }
    }
 }
-   /* we're just saving elapsed tics, to be converted into %cpu if
-      this task wins it's displayable screen row lottery... */
+   // we're just saving elapsed tics, to be converted into %cpu if
+   // this task wins it's displayable screen row lottery... */
    this->pcpu = tics;
-
+   strim(1, this->cmd);
+// if (Frams_maxcmdln)
    // shout this to the world with the final call (or us the next time in)
    Frame_maxtask++;
 }
@@ -1011,7 +1010,8 @@ static proc_t **procs_refresh (proc_t **table, int flags)
 }
 
 \f
-/*######  field table  ##############################################*/
+/*######  Field Table/RCfile compatability support  ######################*/
+
         /* These are the Fieldstab.lflg values used here and in reframewins.
            (own identifiers as documentation and protection against changes) */
 #define L_stat     PROC_FILLSTAT
@@ -1022,18 +1022,19 @@ static proc_t **procs_refresh (proc_t **table, int flags)
 #define L_GROUP    L_status | PROC_FILLGRP
 #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)
+#define L_EITHER   PROC_SPARE_1
    // for reframewins and summary_show 1st pass
 #define L_DEFAULT  PROC_FILLSTAT
 
-#define SF(f)  (QSORT_t)sort_P_ ## f
+   // a temporary macro, soon to be undef'd...
+#define SF(f) (QFP_t)sort_P_ ## f
 
         /* These are our gosh darn 'Fields' !
            They MUST be kept in sync with pflags !!
            note: for integer data, the length modifiers found in .fmts may
                  NOT reflect the true field type found in proc_t -- this plus
                  a cast when/if displayed provides minimal width protection. */
-static FTAB_t  Fieldstab[] = {
+static FLD_t Fieldstab[] = {
 /* .lflg anomolies:
       P_UID, L_NONE  - natural outgrowth of 'stat()' in readproc        (euid)
       P_CPU, L_stat  - never filled by libproc, but requires times      (pcpu)
@@ -1070,7 +1071,7 @@ static FTAB_t  Fieldstab[] = {
 #endif
    // next entry's special: '.head' will be formatted using table entry's own
    //                       '.fmts' plus runtime supplied conversion args!
-   { "XxXx", "Command ",    "%-*.*s ",  -1,    -1, SF(CMD), "Command name/line",    L_stat   },
+   { "XxXx", "Command ",    "%-*.*s ",  -1,    -1, SF(CMD), "Command name/line",    L_EITHER },
    { "YyUu", "WCHAN     ",  "%-9.9s ",  -1,    -1, SF(WCH), "Sleeping in Function", L_stat   },
    // next entry's special: the 0's will be replaced with '.'!
 #ifdef CASEUP_HEXES
@@ -1090,152 +1091,152 @@ static FTAB_t  Fieldstab[] = {
 };
 #undef SF
 
-// convert, or NULL for failure
-static const FTAB_t * idx_to_ptr(int i){
-   if (i<0) return NULL;
-   if (i>=MAXTBL(Fieldstab)) return NULL;
-   return Fieldstab+i;
-}
-
-// convert, or -1 for failure
-static int ptr_to_idx(const FTAB_t *p){
-   int i;
-   if (p<Fieldstab) return -1;
-   i = p - Fieldstab;
-   if (i>=MAXTBL(Fieldstab)) return -1;
-   return i;
-}
-
-// convert
-static int ptr_to_jim(const FTAB_t *p, int off){
-   return p->keys[off];
-}
 
-// convert
-static int ptr_to_rik(const FTAB_t *p, int off){
-   return p->keys[off+2];
-}
+        /* All right, those-that-follow -- Listen Up!
+         * For the above table keys and the following present/future rc file
+         * compatibility support, you have Mr. Albert D. Cahalan to thank.
+         * He must have been in a 'Christmas spirit'.  Were it left to me,
+         * this top would never have gotten that close to the former top's
+         * crufty rcfile.  Not only is it illogical, it's odoriferous !
+         */
 
-// convert
-static int idx_to_jim(int i, int off){
-   return Fieldstab[i].keys[off];
-}
+        // used as 'to' and/or 'from' args in the ft_xxx utilities...
+#define FT_NEW_fmt 0
+#define FT_OLD_fmt 2
 
-// convert
-static int idx_to_rik(int i, int off){
-   return Fieldstab[i].keys[off+2];
-}
 
-// convert, or -1 for failure
-static int jim_to_idx(int c){
+        // convert, or 0 for failure
+static int ft_cvt_char (const int fr, const int to, int c) {
    int j = -1;
+
    while (++j < MAXTBL(Fieldstab)) {
-      if (c == Fieldstab[j].keys[0]) return j;
-      if (c == Fieldstab[j].keys[1]) return j;
+      if (c == Fieldstab[j].keys[fr])   return Fieldstab[j].keys[to];
+      if (c == Fieldstab[j].keys[fr+1]) return Fieldstab[j].keys[to+1];
    }
-   return -1;
+   return 0;
 }
 
-// convert, or -1 for failure
-static int rik_to_idx(int c){
+
+        // convert
+static inline int ft_get_char (const int fr, int i) {
+   int c;
+   if (i < 0) return 0;
+   if (i >= MAXTBL(Fieldstab)) return 0;
+   c = Fieldstab[i].keys[fr];
+   if (c == '.') c = 0;   // '.' marks a bad entry
+   return c;
+}
+
+
+        // convert, or -1 for failure
+static int ft_get_idx (const int fr, int c) {
    int j = -1;
+
    while (++j < MAXTBL(Fieldstab)) {
-      if (c == Fieldstab[j].keys[2]) return j;
-      if (c == Fieldstab[j].keys[3]) return j;
+      if (c == Fieldstab[j].keys[fr])   return j;
+      if (c == Fieldstab[j].keys[fr+1]) return j;
    }
    return -1;
 }
 
-// convert, or NULL for failure
-static const FTAB_t * rik_to_ptr(int c){
+
+        // convert, or NULL for failure
+static const FLD_t *ft_get_ptr (const int fr, int c) {
    int j = -1;
+
    while (++j < MAXTBL(Fieldstab)) {
-      if (c == Fieldstab[j].keys[2]) return Fieldstab+j;
-      if (c == Fieldstab[j].keys[3]) return Fieldstab+j;
+      if (c == Fieldstab[j].keys[fr])   return Fieldstab+j;
+      if (c == Fieldstab[j].keys[fr+1]) return Fieldstab+j;
    }
    return NULL;
 }
 
-// convert, or NULL for failure
-static const FTAB_t * jim_to_ptr(int c){
-   int j = -1;
-   while (++j < MAXTBL(Fieldstab)) {
-      if (c == Fieldstab[j].keys[0]) return Fieldstab+j;
-      if (c == Fieldstab[j].keys[1]) return Fieldstab+j;
-   }
-   return NULL;
+
+        // convert, or NULL for failure
+static const FLD_t *ft_idx_to_ptr (const int i) {
+   if (i < 0) return NULL;
+   if (i >= MAXTBL(Fieldstab)) return NULL;
+   return Fieldstab + i;
 }
 
-// convert, or 0 for failure
-static int rik_to_jim(int c){
-   int j = -1;
-   while (++j < MAXTBL(Fieldstab)) {     // find a Rik-to-Jim conversion for the letter
-      if (c == Fieldstab[j].keys[2]) return Fieldstab[j].keys[0];
-      if (c == Fieldstab[j].keys[3]) return Fieldstab[j].keys[1];
-   }
-   return 0;
+
+        // convert, or -1 for failure
+static int ft_ptr_to_idx (const FLD_t *p) {
+   int i;
+   if (p < Fieldstab) return -1;
+   i = p - Fieldstab;
+   if (i >= MAXTBL(Fieldstab)) return -1;
+   return i;
 }
 
-// convert, or 0 for failure
-static int jim_to_rik(int c){
-   int j = -1;
-   while (++j < MAXTBL(Fieldstab)) {     // find a Jim-to-Rik conversion for the letter
-      if (c == Fieldstab[j].keys[0]) return Fieldstab[j].keys[2];
-      if (c == Fieldstab[j].keys[1]) return Fieldstab[j].keys[3];
+
+#if (0)
+static void rc_bugless (const RCF_t *const rc) {
+   const RCW_t *w;
+   int i = 0;
+
+   fprintf(stderr,"\n%d %d %f %d\n"
+      , rc->mode_altscr, rc->mode_irixps, rc->delay_time, rc->win_index);
+   while(i < 4) {
+      w = &rc->win[i++];
+      fprintf(stderr, "<%s> <%s> %d %08x %d %d %d %d %d\n"
+         , w->winname, w->fieldscur, w->sortindx, w->winflags, w->maxtasks
+         , w->summclr, w->msgsclr, w->headclr, w->taskclr);
    }
-   return 0;
 }
+#endif
 
-\f
-/*######  Startup routines  ##############################################*/
 
         /*
-         * No mater what *they* say, we handle the really really BIG and
-         * IMPORTANT stuff upon which all those lessor functions depend! */
-static void before (char *me)
-{
+         * '$HOME/Rc_name' contains multiple lines - 2 global + 3 per window.
+         *   line 1: an eyecatcher, with a shameless advertisement
+         *   line 2: an id, Mode_altcsr, Mode_irixps, Delay_time and Curwin.
+         * For each of the 4 windows:
+         *   line a: contains winname, fieldscur
+         *   line b: contains winflags, sortindx, maxtasks
+         *   line c: contains summclr, msgsclr, headclr, taskclr */
+static int rc_read_new (const char *const buf, RCF_t *rc) {
    int i;
+   int cnt;
+   const char *cp;
 
-      /* setup our program name -- big! */
-   Myname = strrchr(me, '/');
-   if (Myname) ++Myname; else Myname = me;
+   cp = strstr(buf, "\n\n" RCF_EYECATCHER);
+   if (!cp) return -1;
+   cp = strchr(cp + 2, '\n');
+   if (!cp++) return -2;
 
-      /* establish cpu particulars -- even bigger! */
-#ifdef PRETEND4CPUS
-   Cpu_tot = 4;
-#else
-   Cpu_tot = smp_num_cpus;
-#endif
-   Cpu_map = alloc_r(NULL, sizeof(int) * Cpu_tot);
-   for (i = 0; i < Cpu_tot; i++)
-      Cpu_map[i] = i;
-   if(linux_version_code > LINUX_VERSION(2, 5, 41))
-      States_fmts = STATES_line2x5;
+   cnt = sscanf(cp, "Id:a, Mode_altscr=%d, Mode_irixps=%d, Delay_time=%f, Curwin=%d\n"
+      , &rc->mode_altscr, &rc->mode_irixps, &rc->delay_time, &rc->win_index);
+   if (cnt != 4) return -3;
+   cp = strchr(cp, '\n');
+   if (!cp++) return -4;
 
-      /* get virtual page size -- nearing huge! */
-   Page_size = getpagesize();
-}
+   for (i = 0; i < GROUPSMAX; i++) {
+      RCW_t *ptr = &rc->win[i];
+      cnt = sscanf(cp, "%s\tfieldscur=%s\n", ptr->winname, ptr->fieldscur);
+      if (cnt != 2) return 5+100*i;  // OK to have less than 4 windows
+      if (WINNAMSIZ <= strlen(ptr->winname)) return -6;
+      if (strlen(DEF_FIELDS) != strlen(ptr->fieldscur)) return -7;
+      cp = strchr(cp, '\n');
+      if (!cp++) return -(8+100*i);
 
+      cnt = sscanf(cp, "\twinflags=%d, sortindx=%u, maxtasks=%d \n"
+         , &ptr->winflags, &ptr->sortindx, &ptr->maxtasks);
+      if (cnt != 3) return -(9+100*i);
+      cp = strchr(cp, '\n');
+      if (!cp++) return -(10+100*i);
 
-static void print_rc (const RCF_t *const rc){
-   const rcwin *w;
-   int i = 0;
-   fprintf(stderr,"\n%d %d %d %f %d\n", rc->Secure_mode, rc->Mode_altscr, rc->Mode_irixps, rc->Delay_time, rc->Curwin);
-   while(i<4){
-      w = &rc->win[i];
-      fprintf(
-         stderr,
-         "<%s> <%s> %d %08x %d %d %d %d %d\n",
-         w->winname, w->fieldscur, w->sortindx,
-         w->winflags, w->maxtasks, w->summclr, w->msgsclr, w->headclr, w->taskclr
-      );
-      i++;
+      cnt = sscanf(cp, "\tsummclr=%d, msgsclr=%d, headclr=%d, taskclr=%d \n"
+         , &ptr->summclr, &ptr->msgsclr, &ptr->headclr, &ptr->taskclr);
+      if (cnt != 4) return -(11+100*i);
+      cp = strchr(cp, '\n');
+      if (!cp++) return -(12+100*i);
    }
+   return 13;
 }
 
 
-static int read_config_rik (const char * const fbuf, ssize_t num, RCF_t * const rc)
-{
+static int rc_read_old (const char *const buf, RCF_t *rc) {
    unsigned u;
    const char *cp;
    unsigned c_show = 0;
@@ -1244,84 +1245,82 @@ static int read_config_rik (const char * const fbuf, ssize_t num, RCF_t * const
    char scoreboard[256];
    memset(scoreboard, '\0', sizeof scoreboard);
 
-   (void)num;
-
-   cp = fbuf+2;  // skip the "\n\n" we stuck at the beginning
+   cp = buf+2;  // skip the "\n\n" we stuck at the beginning
    u = 0;
-   for(;;){
-      if(u+1 >= sizeof rc->win[0].fieldscur) return -1;
+   for (;;) {
+      if (u+1 >= sizeof rc->win[0].fieldscur) return -1;
       int c = *cp++;
-      if(c=='\0') return -2;
-      if(c=='\n') break;
+      if (c == '\0') return -2;
+      if (c == '\n') break;
       if (c & ~0x7f) return -3;
       if (~c & 0x20) c_show |= 1 << (c & 0x1f);  // 0x20 means lowercase means hidden
-      if(scoreboard[c|0xe0u]) badchar++; // duplicates not allowed
+      if (scoreboard[c|0xe0u]) badchar++; // duplicates not allowed
       scoreboard[c|0xe0u]++;
-      if(c=='|') continue; // Rik's top ships with a garbage character
-      if(c=='[') c='Y';    // Rik's top ships with 3x of "#C"
-      if(c=='{') c='y';    // another one... and '}' to please Jim's editor
-      if(c=='N') c='n';    // usage differs, so turn this off
-      if(c=='Q') c='q';    // usage differs, so turn this off
-      if(c=='R') c='r';    // usage differs, so turn this off
-      c = rik_to_jim(c);
-      if(!c) return -4;     // error value
-      if(c=='.') return -5; // error value
-      if(scoreboard[c&0x1fu]) badchar++; // duplicates not allowed
+      if (c == '|') continue; // Rik's top ships with a garbage character
+      if (c == '[') c = 'Y';    // Rik's top ships with 3x of "#C"
+      if (c == '{') c = 'y';    // another one... and '}' to please Jim's editor
+      if (c == 'N') c = 'n';    // usage differs, so turn this off
+      if (c == 'Q') c = 'q';    // usage differs, so turn this off
+      if (c == 'R') c = 'r';    // usage differs, so turn this off
+      ft_cvt_char(FT_OLD_fmt, FT_NEW_fmt, c);
+      if (!c) return -4;     // error value
+      if (c == '.') return -5; // error value
+      if (scoreboard[c&0x1fu]) badchar++; // duplicates not allowed
       scoreboard[c&0x1fu]++;
       rc->win[0].fieldscur[u++] = c;
    }
    rc->win[0].fieldscur[u++] = '\0';
-   if(u<21) return -6;  // catch junk, but not good files (had 23 chars in one)
-   if(u>33) return -7;  // catch junk, but not good files (had 29 chars in one)
-//fprintf(stderr,"badchar: %d\n",badchar); sleep(2);
-   if(badchar>3) return -8;   // too much junk
-   if (!c_show) return -9;   // nothing was shown
+   if (u < 21) return -6;  // catch junk, not good files (had 23 chars in one)
+   if (u > 33) return -7;  // catch junk, not good files (had 29 chars in one)
+// fprintf(stderr,"badchar: %d\n",badchar); sleep(2);
+   if (badchar > 3) return -8;          // too much junk
+   if (!c_show) return -9;              // nothing was shown
 
    // Due to Rik blindly accepting damem's broken patches, procps-2.0.10
    // has 3 ("three"!!!) instances of "#C", "LC", or "CPU". Fix that here.
    // Some people are maintainers, and others are human patchbots.
    // The 'y' and 'Y' above have become 'j' and 'J' after translation.
-   if(scoreboard['j' & 0x1fu] > 1){  // more than one "#C" column
+   if (scoreboard['j' & 0x1fu] > 1) {   // more than one "#C" column
       int letter;
       char *fields = rc->win[0].fieldscur;
-      char *tmp = strchr(fields,'J');
+      char *tmp = strchr(fields, 'J');
       if (tmp) {
-         *tmp='.';  // save one by hiding it
+         *tmp = '.';                    // save one by hiding it
          letter = 'J';
       } else {
-         tmp = strchr(fields,'j');
-         *tmp='.';
+         tmp = strchr(fields, 'j');
+         *tmp = '.';
          letter = 'j';
       }
-      while (( tmp=strchr(fields,'J') )) *tmp='j'; // cannonicalize it
-      while (( tmp=strchr(fields,'j') )) {
+      while ((tmp = strchr(fields, 'J'))) *tmp='j'; // cannonicalize it
+      while ((tmp = strchr(fields, 'j'))) {
          char *dst = tmp;
-         char *src = tmp+1;
+         char *src = tmp + 1;
          int n = strlen(src) + 1;
-         memmove(dst,src,n);
+         memmove(dst, src, n);
       }
-      tmp = strchr(fields,'.');  // find back saved spot
+      tmp = strchr(fields, '.');        // find back saved spot
       *tmp = letter;
    }
 
    // rest of file is optional, but better look right if it exists
    if (!*cp) return 12;
-   if (*cp < '2' || *cp > '9') return -13;  // stupid, and why isn't a '1' valid?
-   rc->Delay_time = *cp - '0';
+   if (*cp < '2' || *cp > '9') return -13; // stupid, and why isn't '1' valid?
+   rc->delay_time = *cp - '0';
 
-   memset(scoreboard, '\0', sizeof scoreboard);
-   for(;;){
-      int c = *++cp & 0xffu;  // protect scoreboard[] from negative char
-      if (!c) return -14;  // not OK to hit EOL w/o '\n'
-      if (c=='\n') break;
+   memset(scoreboard, '\0', sizeof(scoreboard));
+   for (;;) {
+      int c = *++cp & 0xffu;    // protect scoreboard[] from negative char
+      if (!c) return -14;       // not OK to hit EOL w/o '\n'
+      if (c == '\n') break;
       switch (c) {
-         case '0' ... '9':
          case ' ':
          case '.':
-            return -15;  // not supposed to have digits here
+         case '0' ... '9':
+            return -15;                     // not supposed to have digits here
 
-         case 's':
-            rc->Secure_mode = 1;
+         case 's':                          // mostly for global rcfile
+            rc->mode_secure = 1;
             break;
          case 'S':
             rc->win[0].winflags |= Show_CTIMES;
@@ -1332,7 +1331,7 @@ static int read_config_rik (const char * const fbuf, ssize_t num, RCF_t * const
          case 'i':
             rc->win[0].winflags &= ~Show_IDLEPS;
             break;
-         case 'H':  // 'H' means to show threads
+         case 'H':                          // 'H' = show threads (yea, sure)
             //rc->win[0].winflags |= ;
             break;
          case 'm':
@@ -1345,7 +1344,7 @@ static int read_config_rik (const char * const fbuf, ssize_t num, RCF_t * const
             rc->win[0].winflags &= ~View_STATES;
             break;
          case 'I':
-            rc->Mode_irixps = 0;
+            rc->mode_irixps = 0;
             break;
 
          case 'M':
@@ -1358,7 +1357,7 @@ static int read_config_rik (const char * const fbuf, ssize_t num, RCF_t * const
             break;
          case 'A':
             c = 0; // for scoreboard
-            rc->win[0].sortindx = P_PID;  // should be by start_time
+            rc->win[0].sortindx = P_PID;    // was by start_time (non-display)
             break;
          case 'T':
             c = 0; // for scoreboard
@@ -1373,159 +1372,72 @@ static int read_config_rik (const char * const fbuf, ssize_t num, RCF_t * const
             // just ignore it, except for the scoreboard of course
             break;
       }
-      if(scoreboard[c]) return -16; // duplicates not allowed
+      if (scoreboard[c]) return -16;        // duplicates not allowed
       scoreboard[c] = 1;
    }
    return 17;
 }
 
-        /*
-         * '$HOME/RCfile' contains multiple lines - 2 global + 3 per window.
-         *   line 1: a shameless advertisement
-         *   line 2: an id, Mode_altcsr, Mode_irixps, Delay_time and Curwin.
-         *           If running in secure mode via the /etc/rcfile,
-         *           Delay_time will be ignored except for root.
-         * For each of the 4 windows:
-         *   line a: contains w->rc.winname, rc.fieldscur
-         *   line b: contains w->rc.winflags, rc.sortindx, rc.maxtasks
-         *   line c: contains w->rc.summclr, rc.msgsclr, rc.headclr, rc.taskclr */
-static int read_config_jim (const char * const fbuf, ssize_t num, RCF_t * const rc)
-{
-   int i;
-   int cnt;
-   const char *cp;
-   (void)num;
-
-   cp = strstr(fbuf,"\n\nRCfile for ");
-   if (!cp) return -1;
-   cp = strchr(cp+2,'\n');
-   if (!cp++) return -2;
 
-   cnt = sscanf(cp, "Id:a, Mode_altscr=%d, Mode_irixps=%d, Delay_time=%f, Curwin=%d\n"
-      , &rc->Mode_altscr, &rc->Mode_irixps, &rc->Delay_time, &rc->Curwin);
-   if (cnt != 4) return -3;
-   cp = strchr(cp,'\n');
-   if (!cp++) return -4;
+static void rc_write_new (FILE *fp) {
+   int i;
 
+   fprintf(fp, RCF_EYECATCHER "\"%s with windows\"\t\t# shameless braggin'\n"
+      , Myname);
+   fprintf(fp, RCF_DEPRECATED
+      "Mode_altscr=%d, Mode_irixps=%d, Delay_time=%.3f, Curwin=%d\n"
+      , Rc.mode_altscr, Rc.mode_irixps, Rc.delay_time, Curwin - Winstk[0]);
    for (i = 0; i < GROUPSMAX; i++) {
-      rcwin *ptr = &rc->win[i];
-      cnt = sscanf(cp, "%s\tfieldscur=%s\n", ptr->winname, ptr->fieldscur);
-      if (cnt!=2) return 5+100*i;
-      if (WINNAMSIZ <= strlen(ptr->winname)) return -6;
-      if (strlen(DEF_FIELDS) != strlen(ptr->fieldscur)) return -7;
-      cp = strchr(cp,'\n');
-      if (!cp++) return -(8+100*i);
-
-      cnt = sscanf(cp, "\twinflags=%d, sortindx=%u, maxtasks=%d \n"
-         , &ptr->winflags
-         , &ptr->sortindx
-         , &ptr->maxtasks);
-      if (cnt!=3) return -(9+100*i);
-      cp = strchr(cp,'\n');
-      if (!cp++) return -(10+100*i);
-
-      cnt = sscanf(cp, "\tsummclr=%d, msgsclr=%d, headclr=%d, taskclr=%d \n"
-         , &ptr->summclr
-         , &ptr->msgsclr
-         , &ptr->headclr
-         , &ptr->taskclr);
-      if (cnt!=4) return -(11+100*i);
-      cp = strchr(cp,'\n');
-      if (!cp++) return -(12+100*i);
-   }
-   return 13;
-}
-
-static void configs_read (void)
-{
-   char fbuf[1600];
-   const char *home;
-   int fd;
-   RCF_t sys_rcfile;
-   RCF_t usr_rcfile;
-
-   memcpy(&sys_rcfile, &RCf_Defaults, sizeof(sys_rcfile));
-   fd = open(SYS_RCFILE, O_RDONLY);
-   if (fd>0) {
-      ssize_t num;
-      fbuf[0] = '\n';
-      fbuf[1] = '\n';
-      num = read(fd, fbuf+2, sizeof(fbuf)-3);
-      if (num>0) {
-         fbuf[num+2] = '\0';
-         read_config_rik(fbuf,num,&sys_rcfile); // not setting Crufty_config
-         read_config_jim(fbuf,num,&sys_rcfile);
-      }
-      close(fd);
-   }
+      char buf[40];
+      char *cp = Winstk[i]->rc.fieldscur;
+      int j = 0;
 
-   memcpy(&usr_rcfile, &RCf_Defaults, sizeof(usr_rcfile));
-   home = getenv("HOME");
-   if (home && *home) {
-      snprintf(RCfile, sizeof(RCfile), "%s/.%src", home, Myname);
-      fd = open(RCfile, O_RDONLY);
-      if (fd>0) {
-         ssize_t num;
-         fbuf[0] = '\n';
-         fbuf[1] = '\n';
-         num = read(fd, fbuf+2, sizeof(fbuf)-3);
-         if (num>0) {
-//int i;
-            fbuf[num+2] = '\0';
-//            fprintf(stderr, "%d\n", read_config_rik(fbuf,num,&usr_rcfile)); for(;;);
-            if (read_config_rik(fbuf,num,&usr_rcfile) > 0) Crufty_config = 1;
-            else memcpy(&usr_rcfile, &RCf_Defaults, sizeof(usr_rcfile));  // maybe mangled
-//if(i<=0){ fprintf(stderr,"FAILURE: read_config_rik returned %d\n",i); for(;;); }
-            read_config_jim(fbuf,num,&usr_rcfile);
+      while (j < 36) {
+         int c = *cp++ & 0xff;
+         switch (c) {
+            case '.':
+            case 1 ... ' ':
+            case 0x7f ... 0xff:
+               continue;                // throw away junk (some of it)
+            default:
+               buf[j++] = c;            // gets the '\0' too
          }
-         close(fd);
+         if (!c) break;
       }
+      fprintf(fp, "%s\tfieldscur=%s\n"
+         , Winstk[i]->rc.winname, buf);
+      fprintf(fp, "\twinflags=%d, sortindx=%d, maxtasks=%d\n"
+         , Winstk[i]->rc.winflags, Winstk[i]->rc.sortindx, Winstk[i]->rc.maxtasks);
+      fprintf(fp, "\tsummclr=%d, msgsclr=%d, headclr=%d, taskclr=%d\n"
+         , Winstk[i]->rc.summclr, Winstk[i]->rc.msgsclr
+         , Winstk[i]->rc.headclr, Winstk[i]->rc.taskclr);
    }
-
-   memcpy(&Winstk[0]->rc, &usr_rcfile.win[0], sizeof(rcwin));
-   memcpy(&Winstk[1]->rc, &usr_rcfile.win[1], sizeof(rcwin));
-   memcpy(&Winstk[2]->rc, &usr_rcfile.win[2], sizeof(rcwin));
-   memcpy(&Winstk[3]->rc, &usr_rcfile.win[3], sizeof(rcwin));
-   Mode_altscr = usr_rcfile.Mode_altscr;
-   Mode_irixps = usr_rcfile.Mode_irixps;
-   Curwin = Winstk[usr_rcfile.Curwin];
-
-      /* lastly, establish the true runtime secure mode and delay time */
-   if (getuid()) {
-      Secure_mode = sys_rcfile.Secure_mode;
-   } else {
-      Secure_mode = 0;
-   }
-   if (Secure_mode) {
-      Delay_time = sys_rcfile.Delay_time;
-   } else {
-      Delay_time = usr_rcfile.Delay_time;
-   }
-//print_rc(&sys_rcfile);
-//print_rc(&usr_rcfile);
 }
 
-static void write_config_rik(FILE *fp, const RCF_t * const rc){
-   char buf[40];
-   char *cp = Winstk[0]->rc.fieldscur;
+
+static void rc_write_old (FILE *fp) {
+   char buf[SMLBUFSIZ];
+   char *cp = Curwin->rc.fieldscur;
    int j = 0;
    int tmp;
+
    while (j < 36) {
       int c = *cp++ & 0xff;
-      if(c=='M') c='L';
-      if(c=='m') c='l';
+      if (c == 'M') c = 'L';
+      if (c == 'm') c = 'l';
       switch (c) {
-         case 1 ... ' ':
          case '.':
-         case 'X':     // trying not to crash Rik's top (move COMMAND)
+         case 'x':              // try not to crash Rik's top (move COMMAND)
+         case 'X':              // try not to crash Rik's top (move COMMAND)
+         case 1 ... ' ':
          case 0x7f ... 0xff:
-            continue;  // throw away junk (some of it)
+            continue;           // throw away junk (some of it)
          default:
-            c = jim_to_rik(c);
-            if(!c) continue;   // skip one we can't represent
+            c = ft_cvt_char(FT_NEW_fmt, FT_OLD_fmt, c);
+            if (!c) continue;   // skip one we can't represent
             break;
          case '\0':
-            buf[j++] = 'X';  // trying not to crash Rik's top (move COMMAND)
+            buf[j++] = 'X';     // try not to crash Rik's top (move COMMAND)
             break;
       }
       buf[j++] = c;
@@ -1535,29 +1447,30 @@ static void write_config_rik(FILE *fp, const RCF_t * const rc){
    fprintf(fp, "%s\n", buf);
    cp = buf;
 
-   tmp = (int)(rc->Delay_time + 0.5);
+   tmp = (int)(Rc.delay_time + 0.5);
    if (tmp < 2) tmp = 2;
    if (tmp > 9) tmp = 9;
    *cp++ = tmp + '0';
 
-   tmp = rc->win[0].winflags;
-   if ( rc->Secure_mode)   *cp++ = 's';
+   tmp = Curwin->rc.winflags;
+// if ( Secure_mode)       *cp++ = 's';     // stupid to have in local rcfile
    if ( tmp & Show_CTIMES) *cp++ = 'S';
    if ( tmp & Show_CMDLIN) *cp++ = 'c';
    if (~tmp & Show_IDLEPS) *cp++ = 'i';
-   //if () *cp++ = 'H';
+// if (                  ) *cp++ = 'H';     // 'H' = show threads (yea, sure)
    if (~tmp & View_MEMORY) *cp++ = 'm';
    if (~tmp & View_LOADAV) *cp++ = 'l';
    if (~tmp & View_STATES) *cp++ = 't';
-   if (!rc->Mode_irixps)   *cp++ = 'I';
-   switch (rc->win[0].sortindx) {
+   if (!Rc.mode_irixps)    *cp++ = 'I';
+
+   switch (Curwin->rc.sortindx) {
       case P_MEM:
          *cp++ = 'M';
          break;
       case P_CPU:
          *cp++ = 'P';
          break;
-//    case P_???: sort by start_time
+//    case P_???:                           // was by start_time (non-display)
 //       *cp++ = 'A';
 //       break;
       case P_TM2:
@@ -1567,73 +1480,116 @@ static void write_config_rik(FILE *fp, const RCF_t * const rc){
          *cp++ = 'N';
          break;
    }
-
-   *cp++ = '\n';
-   *cp++ = '\n';
-   *cp++ = '\n';
    *cp++ = '\0';
-   fprintf(fp, "%s\n", buf);
+   fprintf(fp, "%s\n\n\n", buf);        // important "\n\n" separator!
+}
+
+
+static const char *rc_write_whatever (void) {
+   FILE *fp = fopen(Rc_name, "w");
+
+   if (!fp) return strerror(errno);
+   if (Crufty_rcf) rc_write_old(fp);
+   rc_write_new(fp);
+   fclose(fp);
+   return NULL;
 }
 
-static void write_config_jim(FILE *fp){
+\f
+/*######  Startup routines  ##############################################*/
+
+        /*
+         * No mater what *they* say, we handle the really really BIG and
+         * IMPORTANT stuff upon which all those lessor functions depend! */
+static void before (char *me)
+{
    int i;
-   fprintf(fp, "RCfile for \"%s with windows\"\t\t# shameless braggin'\n"
-      , Myname);
-   fprintf(fp, "Id:%c, "
-      "Mode_altscr=%d, Mode_irixps=%d, Delay_time=%.3f, Curwin=%d\n"
-      , RCF_FILEID
-      , Mode_altscr, Mode_irixps, Delay_time, Curwin - Winstk[0]);
-   for (i = 0; i < GROUPSMAX; i++) {
-      char buf[40];
-      char *cp = Winstk[i]->rc.fieldscur;
-      int j = 0;
-      while (j < 36) {
-         int c = *cp++ & 0xff;
-         switch (c) {
-            case 1 ... ' ':
-            case '.':
-            case 0x7f ... 0xff:
-               continue;  // throw away junk (some of it)
-            default:
-               buf[j++] = c;  // gets the '\0' too
-         }
-         if (!c) break;
+
+      /* setup our program name -- big! */
+   Myname = strrchr(me, '/');
+   if (Myname) ++Myname; else Myname = me;
+
+      /* establish cpu particulars -- even bigger! */
+#ifdef PRETEND4CPUS
+   Cpu_tot = 4;
+#else
+   Cpu_tot = smp_num_cpus;
+#endif
+   Cpu_map = alloc_r(NULL, sizeof(int) * Cpu_tot);
+   for (i = 0; i < Cpu_tot; i++)
+      Cpu_map[i] = i;
+   if (linux_version_code > LINUX_VERSION(2, 5, 41))
+      States_fmts = STATES_line2x5;
+
+      /* get virtual page size -- nearing huge! */
+   Page_size = getpagesize();
+}
+
+        /*
+         * First attempt to read the /etc/rcfile which contains two lines
+         * consisting of the secure mode switch and an update interval.
+         * It's presence limits what ordinary users are allowed to do.
+         *
+         * Then build the local rcfile name and try to read a crufty old-top
+         * rcfile (whew, odoriferous), which may contain an embedded new-style
+         * rcfile.   Whether embedded or standalone, new-style rcfile values
+         * will always override that crufty stuff!
+         * note: If running in secure mode via the /etc/rcfile,
+         *       Delay_time will be ignored except for root. */
+static void configs_read (void)
+{
+   char fbuf[MEDBUFSIZ];
+   const char *cp;
+   int i, fd;
+   RCF_t rcf;
+   float delay = Rc.delay_time;
+
+   // who says life's not fair -- at least the sys rcfiles are compatable
+   fd = open(SYS_RCFILESPEC, O_RDONLY);
+   if (fd > 0) {
+      ssize_t num;
+      num = read(fd, fbuf, sizeof(fbuf) - 1);
+      if (num > 0) {
+         if ((cp = strchr(fbuf, 's'))) Secure_mode = 1;
+         cp++;
+         if ((cp = strchr(cp, '\n'))) sscanf(cp+1, "%f", &Rc.delay_time);
       }
-      fprintf(fp, "%s\tfieldscur=%s\n"
-         , Winstk[i]->rc.winname, buf);
-      fprintf(fp, "\twinflags=%d, sortindx=%d, maxtasks=%d\n"
-         , Winstk[i]->rc.winflags
-         , Winstk[i]->rc.sortindx
-         , Winstk[i]->rc.maxtasks);
-      fprintf(fp, "\tsummclr=%d, msgsclr=%d, headclr=%d, taskclr=%d\n"
-         , Winstk[i]->rc.summclr
-         , Winstk[i]->rc.msgsclr
-         , Winstk[i]->rc.headclr
-         , Winstk[i]->rc.taskclr);
+      close(fd);
    }
-}
 
-static const char * write_config(void){
-   RCF_t usr_rcfile;
-   FILE *fp = fopen(RCfile, "w");
+   snprintf(Rc_name, sizeof(Rc_name), ".%src", Myname);
+   if (getenv("HOME"))
+      snprintf(Rc_name, sizeof(Rc_name), "%s/.%src", getenv("HOME"), Myname);
 
-   memcpy(&usr_rcfile.win[0], &Winstk[0]->rc, sizeof(rcwin));
-   memcpy(&usr_rcfile.win[1], &Winstk[1]->rc, sizeof(rcwin));
-   memcpy(&usr_rcfile.win[2], &Winstk[2]->rc, sizeof(rcwin));
-   memcpy(&usr_rcfile.win[3], &Winstk[3]->rc, sizeof(rcwin));
-   usr_rcfile.Mode_altscr = Mode_altscr;
-   usr_rcfile.Mode_irixps = Mode_irixps;
-   usr_rcfile.Curwin      = Curwin - Winstk[0];
-   usr_rcfile.Secure_mode = Secure_mode;
-   usr_rcfile.Delay_time  = Delay_time;
+   rcf = Rc;
+   fd = open(Rc_name, O_RDONLY);
+   if (fd > 0) {
+      ssize_t num;
+      num = read(fd, fbuf+2, sizeof(fbuf) -3);
+      if (num > 0) {
+         fbuf[0] = '\n';
+         fbuf[1] = '\n';
+         fbuf[num+2] = '\0';
+         if (rc_read_old(fbuf, &rcf) > 0) Crufty_rcf = 1;
+         else rcf = Rc;                     // on failure, maybe mangled
+         rc_read_new(fbuf, &rcf);
+         delay = rcf.delay_time;
+      }
+      close(fd);
+   }
 
-   if (!fp) return strerror(errno);
-   if(Crufty_config) write_config_rik(fp, &usr_rcfile);
-   write_config_jim(fp);
-   fclose(fp);
-   return NULL;
+   // update Rc defaults, establish a Curwin and fix up the window stack
+   Rc.mode_altscr = rcf.mode_altscr;
+   Rc.mode_irixps = rcf.mode_irixps;
+   Curwin = Winstk[(rcf.win_index)];
+   for (i = 0; i < GROUPSMAX; i++) Winstk[i]->rc = rcf.win[i];
+
+   // lastly, establish the true runtime secure mode and delay time
+   Secure_mode = getuid() ? Secure_mode : 0;
+   if (!Secure_mode || !getuid()) Rc.delay_time = delay;
 }
 
+
         /*
          * Parse command line arguments.
          * Note: it's assumed that the rc file(s) have already been read
@@ -1733,7 +1689,7 @@ static void parse_args (char **args)
       if (Secure_mode || 0 > tmp_delay)
          msg_save("Delay time Not changed");
       else
-         Delay_time = tmp_delay;
+         Rc.delay_time = tmp_delay;
    }
 }
 
@@ -1795,21 +1751,20 @@ static void display_fields (const char *fields, const char *xtra)
    /* we're relying on callers to first clear the screen and thus avoid screen
       flicker if they're too lazy to handle their own asterisk (*) logic */
    putp(Curwin->cap_bold);
-   for (i = 0; i < MAXTBL(Fieldstab); ++i) {
-      int c;
-      int b = (NULL != strchr(fields, i + 'A'));
+   for (i = 0; fields[i]; ++i) {
+      const FLD_t *f = ft_get_ptr(FT_NEW_fmt, fields[i]);
+      int b = isupper(fields[i]);
+      if (!f) continue;                // hey, should be std_err!
          /* advance past any leading spaces */
-      for (p = Fieldstab[i].head; ' ' == *p; ++p)
+      for (p = f->head; ' ' == *p; ++p)
          ;
-      c = jim_to_rik(b ? i + 'A' : i + 'a');
-      if (!c) continue;
       PUTT("%s%s%c %c: %-10s = %s"
          , tg2((i / rmax) * cmax, (i % rmax) + yRSVD)
          , b ? Curwin->cap_bold : Cap_norm
          , b ? '*' : ' '
-         , c
+         , fields[i]
          , p
-         , Fieldstab[i].desc);
+         , f->desc);
    }
    if (xtra) {
       putp(Curwin->capclr_rownorm);
@@ -1839,13 +1794,13 @@ static void fields_reorder (void)
 
    putp(Cap_clr_scr);
    putp(Cap_curs_huge);
-   display_fields(Curwin->rc.fieldscur, FIELDS_xtra);
    for (;;) {
+      display_fields(Curwin->rc.fieldscur, FIELDS_xtra);
       show_special(1, fmtmk(FIELDS_current
          , Cap_home, Curwin->rc.fieldscur, Curwin->grpname, prompt));
       chin(0, &c, 1);
+      if (!ft_get_ptr(FT_NEW_fmt, c)) break;
       i = toupper(c) - 'A';
-      if (i < 0 || i >= MAXTBL(Fieldstab)) break;
       if (((p = strchr(Curwin->rc.fieldscur, i + 'A')))
       || ((p = strchr(Curwin->rc.fieldscur, i + 'a')))) {
          if (isupper(c)) p--;
@@ -1880,8 +1835,8 @@ static void fields_sort (void)
       show_special(1, fmtmk(SORT_fields
          , Cap_home, *p, Curwin->grpname, prompt));
       chin(0, &c, 1);
+      if (!ft_get_ptr(FT_NEW_fmt, c)) break;
       i = toupper(c) - 'A';
-      if (i < 0 || i >= MAXTBL(Fieldstab)) break;
       *p = tolower(*p);
       x = i;
    }
@@ -1908,8 +1863,8 @@ static void fields_toggle (void)
       show_special(1, fmtmk(FIELDS_current
          , Cap_home, Curwin->rc.fieldscur, Curwin->grpname, prompt));
       chin(0, &c, 1);
-      i = rik_to_jim(c) & 0x1f;  // was:  i = toupper(c) - 'A';
-      if (i < 0 || i >= MAXTBL(Fieldstab)) break;
+      if (!ft_get_ptr(FT_NEW_fmt, c)) break;
+      i = toupper(c) - 'A';
       if ((p = strchr(Curwin->rc.fieldscur, i + 'A')))
          *p = i + 'a';
       else if ((p = strchr(Curwin->rc.fieldscur, i + 'a')))
@@ -1934,10 +1889,11 @@ static void reframewins (void)
    const char *h;
    int i, needpsdb = 0;
 
-// Frame_libflgs = 0;   // should be called only when it's zero
+// Frams_libflags = 0;  // should be called only when it's zero
+// Frams_maxcmdln = 0;  // to become the largest from the 4 windows
    w = Curwin;
    do {
-      if (!Mode_altscr || CHKw(w, VISIBLE_tsk)) {
+      if (!Rc.mode_altscr || CHKw(w, VISIBLE_tsk)) {
          // build window's procflags array and establish a tentative maxpflgs
          for (i = 0, w->maxpflgs = 0; w->rc.fieldscur[i]; i++) {
             if (isupper(w->rc.fieldscur[i]))
@@ -1947,7 +1903,7 @@ static void reframewins (void)
          /* build a preliminary columns header not to exceed screen width
             while accounting for a possible leading window number */
          *(s = w->columnhdr) = '\0';
-         if (Mode_altscr) s = scat(s, " ");
+         if (Rc.mode_altscr) s = scat(s, " ");
          for (i = 0; i < w->maxpflgs; i++) {
             h = Fieldstab[w->procflags[i]].head;
             // oops, won't fit -- we're outta here...
@@ -1967,19 +1923,22 @@ static void reframewins (void)
             rebuild the all-important PROC_FILLxxx flags that will be used
             until/if we're we're called again */
          *(s = w->columnhdr) = '\0';
-         if (Mode_altscr) s = scat(s, fmtmk("%d", w->winnum));
+         if (Rc.mode_altscr) s = scat(s, fmtmk("%d", w->winnum));
          for (i = 0; i < w->maxpflgs; i++) {
             h = Fieldstab[w->procflags[i]].head;
             if (P_WCH == w->procflags[i]) needpsdb = 1;
             if (P_CMD == w->procflags[i]) {
                s = scat(s, fmtmk(Fieldstab[P_CMD].fmts, w->maxcmdln, w->maxcmdln, h));
-               if (CHKw(w, Show_CMDLIN)) Frame_libflgs |= L_CMDLINE;
+               if (CHKw(w, Show_CMDLIN)) {
+                  Frams_libflags |= L_CMDLINE;
+//                if (w->maxcmdln > Frams_maxcmdln) Frams_maxcmdln = w->maxcmdln;
+               }
             } else
                s = scat(s, h);
-            Frame_libflgs |= Fieldstab[w->procflags[i]].lflg;
+            Frams_libflags |= Fieldstab[w->procflags[i]].lflg;
          }
       }
-      if (Mode_altscr) w = w->next;
+      if (Rc.mode_altscr) w = w->next;
    } while (w != Curwin);
 
    // do we need the kernel symbol table (and is it already open?)
@@ -1992,11 +1951,11 @@ static void reframewins (void)
             PSDBopen = 1;
       }
    }
-   if (Frame_libflgs & L_EITHER) {
-      Frame_libflgs &= ~L_EITHER;
-      if (!(Frame_libflgs & L_stat)) Frame_libflgs |= L_status;
+   if (Frams_libflags & L_EITHER) {
+      Frams_libflags &= ~L_EITHER;
+      if (!(Frams_libflags & L_stat)) Frams_libflags |= L_status;
    }
-   if (!Frame_libflgs) Frame_libflgs = L_DEFAULT;
+   if (!Frams_libflags) Frams_libflags = L_DEFAULT;
 }
 
 
@@ -2209,7 +2168,7 @@ static void wins_resize (int dont_care_sig)
    Pseudo_scrn = alloc_r(Pseudo_scrn, Pseudo_size);
 
    // force rebuild of column headers AND libproc/readproc requirements
-   Frame_libflgs = 0;
+   Frams_libflags = 0;
 }
 
 
@@ -2220,38 +2179,16 @@ static void wins_resize (int dont_care_sig)
          * [               --- life-is-NOT-fair ---                     ] */
 static void windows_stage1 (void)
 {
-   static struct {
-      const char *name;
-      const char *flds;
-      const int   sort;
-      const int   clrs[4];      /* summ, msgs, heads, task */
-   } wtab[] = {
-      { "Def", DEF_FIELDS, P_CPU,
-         { COLOR_RED, COLOR_RED, COLOR_YELLOW, COLOR_RED } },
-      { "Job", JOB_FIELDS, P_PID,
-         { COLOR_CYAN, COLOR_CYAN, COLOR_WHITE, COLOR_CYAN } },
-      { "Mem", MEM_FIELDS, P_MEM,
-         { COLOR_MAGENTA, COLOR_MAGENTA, COLOR_BLUE, COLOR_MAGENTA } },
-      { "Usr", USR_FIELDS, P_USR,
-         { COLOR_YELLOW, COLOR_YELLOW, COLOR_GREEN, COLOR_YELLOW } },
-   };
    WIN_t *w;
    int i;
 
-      /* get all our window structs in one big chunk */
+   // get all our window structs in one big chunk
    w = alloc_c(sizeof(WIN_t) * GROUPSMAX);
 
    for (i = 0; i < GROUPSMAX; i++) {
       Winstk[i] = w;
       w->winnum = i + 1;
-      strcpy(w->rc.winname, wtab[i].name);
-      strcpy(w->rc.fieldscur, wtab[i].flds);
-      w->rc.sortindx = wtab[i].sort;
-      w->rc.winflags = DEF_WINFLGS;
-      w->rc.summclr = wtab[i].clrs[0];
-      w->rc.msgsclr = wtab[i].clrs[1];
-      w->rc.headclr = wtab[i].clrs[2];
-      w->rc.taskclr = wtab[i].clrs[3];
+      w->rc = Rc.win[i];
       w->captab[0] = Cap_norm;
       w->captab[1] = Cap_norm;
       w->captab[2] = w->cap_bold;
@@ -2269,7 +2206,6 @@ static void windows_stage1 (void)
    Winstk[3]->next = Winstk[0];
    Winstk[0]->prev = Winstk[3];
    Curwin = Winstk[0];
-   Mode_altscr = 0;
 }
 
 
@@ -2313,11 +2249,11 @@ static void do_key (unsigned c)
          break;
 
       case 'a':
-         if (Mode_altscr) Curwin = Curwin->next;
+         if (Rc.mode_altscr) Curwin = Curwin->next;
          break;
 
       case 'A':
-         Mode_altscr = !Mode_altscr;
+         Rc.mode_altscr = !Rc.mode_altscr;
          wins_resize(0);
          break;
 
@@ -2347,8 +2283,8 @@ static void do_key (unsigned c)
             show_msg(err_secure);
          else {
             float tmp =
-               get_float(fmtmk("Change delay from %.1f to", Delay_time));
-            if (-1 < tmp) Delay_time = tmp;
+               get_float(fmtmk("Change delay from %.1f to", Rc.delay_time));
+            if (-1 < tmp) Rc.delay_time = tmp;
          }
          break;
 
@@ -2362,7 +2298,7 @@ static void do_key (unsigned c)
          break;
 
       case 'g':
-         if (Mode_altscr) {
+         if (Rc.mode_altscr) {
             char tmp[GETBUFSIZ];
             strcpy(tmp, ask4str(fmtmk("Rename window '%s' to (1-3 chars)"
                , Curwin->rc.winname)));
@@ -2384,7 +2320,7 @@ static void do_key (unsigned c)
             , procps_version
             , Curwin->grpname
             , CHKw(Curwin, Show_CTIMES) ? "On" : "Off"
-            , Delay_time
+            , Rc.delay_time
             , Secure_mode ? "On" : "Off"
             , Secure_mode ? "" : KEYS_help_unsecured));
          chin(0, &ch, 1);
@@ -2412,13 +2348,13 @@ static void do_key (unsigned c)
       case 'I':
 #ifdef WARN_NOT_SMP
          if (Cpu_tot > 1) {
-            Mode_irixps = !Mode_irixps;
-            show_msg(fmtmk("Irix mode %s", Mode_irixps ? "On" : "Off"));
+            Rc.mode_irixps = !Rc.mode_irixps;
+            show_msg(fmtmk("Irix mode %s", Rc.mode_irixps ? "On" : "Off"));
          } else
             show_msg(err_smp);
 #else
-         Mode_irixps = !Mode_irixps;
-         show_msg(fmtmk("Irix mode %s", Mode_irixps ? "On" : "Off"));
+         Rc.mode_irixps = !Rc.mode_irixps;
+         show_msg(fmtmk("Irix mode %s", Rc.mode_irixps ? "On" : "Off"));
 #endif
          break;
 
@@ -2500,15 +2436,15 @@ static void do_key (unsigned c)
          break;
 
       case 'w':
-         if (Mode_altscr) Curwin = Curwin->prev;
+         if (Rc.mode_altscr) Curwin = Curwin->prev;
          break;
 
       case 'W':
-      {  const char *err = write_config();
+      {  const char *err = rc_write_whatever();
          if (err)
-            show_msg(fmtmk("\aFailed '%s' open: %s", RCfile, err));
+            show_msg(fmtmk("\aFailed '%s' open: %s", Rc_name, err));
          else
-            show_msg(fmtmk("Wrote configuration to '%s'", RCfile));
+            show_msg(fmtmk("Wrote configuration to '%s'", Rc_name));
       }
          break;
 
@@ -2538,11 +2474,11 @@ static void do_key (unsigned c)
          break;
 
       case '-':
-         if (Mode_altscr) TOGw(Curwin, VISIBLE_tsk);
+         if (Rc.mode_altscr) TOGw(Curwin, VISIBLE_tsk);
          break;
 
       case '_':
-         if (Mode_altscr) wins_reflag(Flags_TOG, VISIBLE_tsk);
+         if (Rc.mode_altscr) wins_reflag(Flags_TOG, VISIBLE_tsk);
          break;
 
       case '=':
@@ -2552,12 +2488,12 @@ static void do_key (unsigned c)
          break;
 
       case '+':
-         if (Mode_altscr) SETw(Curwin, EQUWINS_cwo);
+         if (Rc.mode_altscr) SETw(Curwin, EQUWINS_cwo);
          break;
 
       case '<':
          if (VIZCHKc) {
-            PFLG_t *p = Curwin->procflags + Curwin->maxpflgs - 1;
+            FLG_t *p = Curwin->procflags + Curwin->maxpflgs - 1;
             while (*p != Curwin->rc.sortindx) --p;
             if (--p >= Curwin->procflags)
                Curwin->rc.sortindx = *p;
@@ -2566,7 +2502,7 @@ static void do_key (unsigned c)
 
       case '>':
          if (VIZCHKc) {
-            PFLG_t *p = Curwin->procflags;
+            FLG_t *p = Curwin->procflags;
             while (*p != Curwin->rc.sortindx) ++p;
             if (++p < Curwin->procflags + Curwin->maxpflgs)
                Curwin->rc.sortindx = *p;
@@ -2580,7 +2516,7 @@ static void do_key (unsigned c)
       {  static struct {
             const unsigned  xkey;
             const char     *xmsg;
-            const PFLG_t    sort;
+            const FLG_t     sort;
          } xtab[] = {
             { 'M', "Memory", P_MEM, }, { 'N', "Numerical", P_PID, },
             { 'P', "CPU",    P_CPU, }, { 'T', "Time",      P_TM2  }, };
@@ -2619,7 +2555,7 @@ static void do_key (unsigned c)
       ( At this point we have a human being involved and so have all the time )
       ( in the world.  We can afford a few extra cpu cycles every now & then! )
     */
-   Frame_libflgs = 0;
+   Frams_libflags = 0;
 }
 
 
@@ -2631,12 +2567,12 @@ 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 *cpu, const char *pfx)
+static void summaryhlp (CPU_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?) */
-#define TRIMz(x)  ((tz = (STIC_t)(x)) < 0 ? 0 : tz)
-   STIC_t u_frme, s_frme, n_frme, i_frme, w_frme, tot_frme, tz;
+#define TRIMz(x)  ((tz = (SIC_t)(x)) < 0 ? 0 : tz)
+   SIC_t u_frme, s_frme, n_frme, i_frme, w_frme, tot_frme, tz;
    float scale;
 
    u_frme = cpu->u - cpu->u_sav;
@@ -2680,7 +2616,7 @@ static void summaryhlp (CPUS_t *cpu, const char *pfx)
 static proc_t **summary_show (void)
 {
    static proc_t **p_table = NULL;
-   static CPUS_t *smpcpu = NULL;
+   static CPU_t  *smpcpu = NULL;
 
    // whoa first time, gotta' prime the pump...
    if (!p_table) {
@@ -2689,13 +2625,12 @@ static proc_t **summary_show (void)
       sleep(1);
    } else
       putp(Batch ? "\n\n" : Cap_home);
-
-   p_table = procs_refresh(p_table, Frame_libflgs);
+   p_table = procs_refresh(p_table, Frams_libflags);
 
    /*
     ** Display Uptime and Loadavg */
    if (CHKw(Curwin, View_LOADAV)) {
-      if (!Mode_altscr)
+      if (!Rc.mode_altscr)
          show_special(0, fmtmk(LOADAV_line, Myname, sprint_uptime()));
       else
          show_special(0, fmtmk(CHKw(Curwin, VISIBLE_tsk)
@@ -2723,7 +2658,7 @@ static proc_t **summary_show (void)
          char tmp[SMLBUFSIZ];
          // display each cpu's states separately
          for (i = 0; i < Cpu_tot; i++) {
-            snprintf(tmp, sizeof(tmp), " Cpu%-2d:", Mode_irixps ? i : Cpu_map[i]);
+            snprintf(tmp, sizeof(tmp), " Cpu%-2d:", Rc.mode_irixps ? i : Cpu_map[i]);
             summaryhlp(&smpcpu[i], tmp);
          }
       }
@@ -2761,17 +2696,18 @@ static void task_show (const WIN_t *q, const proc_t *p)
       pad += q->len_rowhigh; \
       if (!(CHKw(q, Show_HIROWS) && 'R' == p->state)) pad += q->len_rownorm; \
    } } while (0)
+   // the format for 'command line' display in absence of same (kernel thread)
 
    char rbuf[ROWBUFSIZ], *rp;
    int j, x, pad;
 
    // we must begin a row with a possible window number in mind...
    *(rp = rbuf) = '\0';
-   if ((pad = Mode_altscr)) rp = scat(rp, " ");
+   if ((pad = Rc.mode_altscr)) rp = scat(rp, " ");
 
    for (x = 0; x < q->maxpflgs; x++) {
       char cbuf[ROWBUFSIZ], _z[ROWBUFSIZ];
-      PFLG_t      i = q->procflags[x];          // support for our field/column
+      FLG_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;
@@ -2870,7 +2806,7 @@ static void task_show (const WIN_t *q, const proc_t *p)
             break;
          case P_TME:
          case P_TM2:
-         {  TICS_t t = p->utime + p->stime;
+         {  TIC_t t = p->utime + p->stime;
             if (CHKw(q, Show_CTIMES))
                t += (p->cutime + p->cstime);
             MKCOL(scale_tics(t, w));
@@ -2928,8 +2864,8 @@ static void window_show (proc_t **ppt, WIN_t *q, int *lscr)
 #ifdef SORT_SUPRESS
    // the 1 flag that DOES and 2 flags that MAY impact our proc table qsort
 #define srtMASK  ~( Qsrt_NORMAL | Show_CMDLIN | Show_CTIMES )
-   static PFLG_t sav_indx = 0;
-   static int    sav_flgs = -1;
+   static FLG_t sav_indx = 0;
+   static int   sav_flgs = -1;
 #endif
    int i, lwin;
 
@@ -3043,7 +2979,7 @@ static void frame_make (void)
 
    /* note: except for PROC_PID, all libproc flags are managed by
             reframewins(), who also builds each window's column headers */
-   if (!Frame_libflgs) {
+   if (!Frams_libflags) {
       reframewins();
       memset(Pseudo_scrn, '\0', Pseudo_size);
    }
@@ -3057,7 +2993,7 @@ static void frame_make (void)
    // sure hope each window's columns header begins with a newline...
    putp(tg2(0, Msg_row));
 
-   if (!Mode_altscr) {
+   if (!Rc.mode_altscr) {
       // only 1 window to show so, piece o' cake
       Curwin->winlines = Curwin->rc.maxtasks;
       window_show(ppt, Curwin, &scrlins);
@@ -3137,10 +3073,10 @@ int main (int dont_care_argc, char **argv)
       if (!Loops) end_pgm(0);
 
       if (Batch)
-         sleep((unsigned)Delay_time);
+         sleep((unsigned)Rc.delay_time);
       else {                            //   Linux reports time not slept,
-         tv.tv_sec = Delay_time;        //   so we must reinit every time.
-         tv.tv_usec = (Delay_time - (int)Delay_time) * 1000000;
+         tv.tv_sec = Rc.delay_time;     //   so we must reinit every time.
+         tv.tv_usec = (Rc.delay_time - (int)Rc.delay_time) * 1000000;
          FD_ZERO(&fs);
          FD_SET(STDIN_FILENO, &fs);
          if (0 < select(STDIN_FILENO+1, &fs, NULL, NULL, &tv)
diff --git a/top.h b/top.h
index fca5956cabb185f566f59d240b883bebd4ccf454..2cabee363ee944d1a81d9bb54acefa9f70b7e67f 100644 (file)
--- a/top.h
+++ b/top.h
@@ -60,6 +60,8 @@
    /* the above might seem pretty stingy, until you consider that with every
       one of top's fields displayed we're talking a 160 byte column header --
       so that will provide for all fields plus a 350+ byte command line */
+#define WINNAMSIZ     4
+#define CAPTABMAX     9
 #define PFLAGSSIZ    32
 #define CAPBUFSIZ    32
 #define CLRBUFSIZ    64
@@ -67,6 +69,7 @@
 #define TNYBUFSIZ    32
 #define SMLBUFSIZ   256
 #define OURPATHSZ  1024
+#define MEDBUFSIZ  1024
 #define BIGBUFSIZ  2048
 #define USRNAMSIZ  GETBUFSIZ
 #define ROWBUFSIZ  SCREENMAX + CLRBUFSIZ
 #define SORT_gt  ( Frame_srtflg > 0 ? -1 :  1 )
 #define SORT_eq  0
 
-        /* Used to reference and create sort callback functions --
+        /* Used to create *most* of the sort callback functions
            note: some of the callbacks are NOT your father's callbacks, they're
                  highly optimized to save them ol' precious cycles! */
-#define _SC_NUM1(f,n) \
+#define SCB_NUM1(f,n) \
    static int sort_ ## f (const proc_t **P, const proc_t **Q) { \
       if ( (*P)->n < (*Q)->n ) return SORT_lt; \
       if ( (*P)->n > (*Q)->n ) return SORT_gt; \
       return SORT_eq; }
-#define _SC_NUM2(f,n1,n2) \
+#define SCB_NUM2(f,n1,n2) \
    static int sort_ ## f (const proc_t **P, const proc_t **Q) { \
       if ( ((*P)->n1 - (*P)->n2) < ((*Q)->n1 - (*Q)->n2) ) return SORT_lt; \
       if ( ((*P)->n1 - (*P)->n2) > ((*Q)->n1 - (*Q)->n2) ) return SORT_gt; \
       return SORT_eq; }
-#define _SC_NUMx(f,n) \
+#define SCB_NUMx(f,n) \
    static int sort_ ## f (const proc_t **P, const proc_t **Q) { \
       return Frame_srtflg * ( (*Q)->n - (*P)->n ); }
-#define _SC_STRx(f,s) \
+#define SCB_STRx(f,s) \
    static int sort_ ## f (const proc_t **P, const proc_t **Q) { \
       return Frame_srtflg * strcmp((*Q)->s, (*P)->s); }
 
 /*######  Some Typedef's and Enum's  #####################################*/
 
         /* This typedef just ensures consistent 'process flags' handling */
-typedef unsigned PFLG_t;
+typedef unsigned FLG_t;
 
         /* These typedefs attempt to ensure consistent 'ticks' handling */
-typedef unsigned long long TICS_t;
-typedef          long long STIC_t;
+typedef unsigned long long TIC_t;
+typedef          long long SIC_t;
 
-        /* Sorted columns support. */
-typedef int (*QSORT_t)(const void *, const void *);
+        /* Sort support, callback funtion signature */
+typedef int (*QFP_t)(const void *, const void *);
 
         /* This structure consolidates the information that's used
            in a variety of display roles. */
-typedef struct {
-   const char    keys[4]; // order: Jim-on Jim-off Rik-on Rik-off
-   const char   *head;  /* name for column headings + toggle/reorder fields */
-   const char   *fmts;  /* sprintf format string for field display */
-   const int     width; /* field width, if applicable */
-   const int     scale; /* scale_num type, if applicable */
-   const QSORT_t sort;  /* sort function */
-   const char   *desc;  /* description for toggle/reorder fields */
-   const int     lflg;  /* PROC_FILLxxx flag(s) required for this field */
-} FTAB_t;
+typedef struct FLD_t {
+   const char    keys [4];      // order: New-on New-off Old-on Old-off
+   const char   *head;          // name for col heads + toggle/reorder fields
+   const char   *fmts;          // sprintf format string for field display
+   const int     width;         // field width, if applicable
+   const int     scale;         // scale_num type, if applicable
+   const QFP_t   sort;          // sort function
+   const char   *desc;          // description for toggle/reorder fields
+   const int     lflg;          // PROC_FILLxxx flag(s) needed by this field
+} FLD_t;
 
         /* This structure stores one piece of critical 'history'
            information from one frame to the next -- we don't calc
            and save data that goes unused like the old top! */
-typedef struct {
-   int    pid;
-   TICS_t tics;
-} HIST_t;
+typedef struct HST_t {
+   int   pid;
+   TIC_t tics;
+} HST_t;
 
         /* This structure stores a frame's cpu tics used in history
            calculations.  It exists primarily for SMP support but serves
            all environments. */
-typedef struct {
-   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;
+typedef struct CPU_t {
+   TIC_t u, n, s, i, w;                         // as represented in /proc/stat
+   TIC_t u_sav, s_sav, n_sav, i_sav, w_sav;     // in the order of our display
+} CPU_t;
+
+        /* These 2 types support rcfile compatibility */
+typedef struct RCW_t {  // the 'window' portion of an rcfile
+   FLG_t  sortindx;             // sort field, represented as a procflag
+   int    winflags,             // 'view', 'show' and 'sort' mode flags
+          maxtasks,             // user requested maximum, 0 equals all
+          summclr,                      // color num used in summ info
+          msgsclr,                      //        "       in msgs/pmts
+          headclr,                      //        "       in cols head
+          taskclr;                      //        "       in task rows
+   char   winname [WINNAMSIZ],          // window name, user changeable
+          fieldscur [PFLAGSSIZ];        // fields displayed and ordered
+} RCW_t;
+
+typedef struct RCF_t {  // the complete rcfile (new style)
+   int    mode_altscr;          // 'A' - Alt display mode (multi task windows)
+   int    mode_irixps;          // 'I' - Irix vs. Solaris mode (SMP-only)
+   float  delay_time;           // 'd' or 's' - How long to sleep twixt updates
+   int    win_index;            // Curwin, as index
+   RCW_t  win [4];              // a 'WIN_t.rc' for each of the 4 windows
+} RCF_t;
 
         /* The scaling 'type' used with scale_num() -- this is how
            the passed number is interpreted should scaling be necessary */
@@ -214,9 +238,7 @@ enum pflag {
         /* (kind of a header within a header:  constants, macros & types) */
 
 #define GROUPSMAX  4            /* the max number of simultaneous windows */
-#define WINNAMSIZ  4            /* max size of a window's basic name      */
-#define GRPNAMSIZ  6            /* window's name + number as in: '#:...'  */
-#define CAPTABMAX  9            /* a window's captab used by show_special */
+#define GRPNAMSIZ  WINNAMSIZ+2  /* window's name + number as in: '#:...'  */
 
 #define Flags_TOG  1            /* these are used to direct wins_reflag   */
 #define Flags_SET  2
@@ -258,68 +280,47 @@ enum pflag {
 #define TOGw(q,f)   q->rc.winflags ^=  (f)
 #define SETw(q,f)   q->rc.winflags |=  (f)
 #define OFFw(q,f)   q->rc.winflags &= ~(f)
-#define VIZCHKc     (!Mode_altscr || Curwin->rc.winflags & VISIBLE_tsk) \
+#define VIZCHKc     (!Rc.mode_altscr || Curwin->rc.winflags & VISIBLE_tsk) \
                         ? 1 : win_warn()
-#define VIZTOGc(f)  (!Mode_altscr || Curwin->rc.winflags & VISIBLE_tsk) \
+#define VIZTOGc(f)  (!Rc.mode_altscr || Curwin->rc.winflags & VISIBLE_tsk) \
                         ? TOGw(Curwin, f) : win_warn()
 
-typedef struct rcwin {
-   char        winname   [WINNAMSIZ],   /* window name, user changeable   */
-               fieldscur [PFLAGSSIZ];   /* fields displayed and ordered   */
-   int         winflags;        /* 'view', 'show' and 'sort' mode flags   */
-   PFLG_t      sortindx;                /* sort field, as a procflag      */
-   int         maxtasks,        /* user requested maximum, 0 equals all   */
-               summclr,                 /* color num used in summ info    */
-               msgsclr,                 /*        "       in msgs/pmts    */
-               headclr,                 /*        "       in cols head    */
-               taskclr;                 /*        "       in task display */
-} rcwin;
-
-typedef struct rcf {    // global/system-wide
-   int   Secure_mode;           // Secure_mode (not in Jim-format files)
-   int   Mode_altscr;           // Mode_altscr
-   int   Mode_irixps;           // Mode_irixps
-   float Delay_time;            // Delay_time
-   int   Curwin;                // Curwin
-   rcwin win[4];                // each of 4 windows
-} RCF_t;
-
         /* This structure stores configurable information for each window.
            By expending a little effort in its creation and user requested
            maintainence, the only real additional per frame cost of having
            windows is an extra sort -- but that's just on ptrs! */
-typedef struct win {
-   struct win *next,                    /* next window in window stack    */
-              *prev;                    /* prior window in window stack   */
-   char       *captab [CAPTABMAX];      /* captab needed by show_special  */
-   int         winnum,                  /* window's num (array pos + 1)   */
-               winlines;                /* task window's rows (volatile)  */
-   PFLG_t      procflags [PFLAGSSIZ];   /* fieldscur subset, as enum      */
-   int         maxpflgs,        /* number of procflags (upcase fieldscur) */
-               maxcmdln;        /* max length of a process' command line  */
-   int         len_rownorm,     /* lengths of the corresponding terminfo  */
-               len_rowhigh;     /* strings to avoid repeated strlen calls */
-   rcwin       rc;              /* stuff that gets saved in a .toprc file */
-   char        capclr_sum [CLRBUFSIZ],  /* terminfo strings built from    */
-               capclr_msg [CLRBUFSIZ],  /*    above clrs (& rebuilt too), */
-               capclr_pmt [CLRBUFSIZ],  /*    but NO recurring costs !!!  */
-               capclr_hdr [CLRBUFSIZ],     /* note: sum, msg and pmt strs */
-               capclr_rowhigh [CLRBUFSIZ], /*    are only used when this  */
-               capclr_rownorm [CLRBUFSIZ]; /*    window is the 'Curwin'!  */
-   char        cap_bold [CAPBUFSIZ];    /* support for View_NOBOLD toggle */
-   char        grpname   [GRPNAMSIZ],   /* window number:name, printable  */
-               columnhdr [SCREENMAX],   /* column headings for procflags  */
-               colusrnam [USRNAMSIZ];   /* if selected by the 'u' command */
+typedef struct WIN_t {
+   struct WIN_t *next,                  // next window in window stack
+                *prev;                  // prior window in window stack
+   char       *captab [CAPTABMAX];      // captab needed by show_special
+   int         winnum,                  // window's num (array pos + 1)
+               winlines;                // task window's rows (volatile)
+   FLG_t       procflags [PFLAGSSIZ];   // fieldscur subset, as enum
+   int         maxpflgs,        // number of procflags (upcase fieldscur)
+               maxcmdln;        // max length of a process' command line
+   int         len_rownorm,     // lengths of the corresponding terminfo
+               len_rowhigh;     // strings to avoid repeated strlen calls
+   RCW_t       rc;              // stuff that gets saved in the rcfile
+   char        capclr_sum [CLRBUFSIZ],  // terminfo strings built from
+               capclr_msg [CLRBUFSIZ],  //    above clrs (& rebuilt too),
+               capclr_pmt [CLRBUFSIZ],  //    but NO recurring costs !!!
+               capclr_hdr [CLRBUFSIZ],     // note: sum, msg and pmt strs
+               capclr_rowhigh [CLRBUFSIZ], //    are only used when this
+               capclr_rownorm [CLRBUFSIZ]; //    window is the 'Curwin'!
+   char        cap_bold [CAPBUFSIZ];    // support for View_NOBOLD toggle
+   char        grpname   [GRPNAMSIZ],   // window number:name, printable
+               columnhdr [SCREENMAX],   // column headings for procflags
+               colusrnam [USRNAMSIZ];   // if selected by the 'u' command
 } WIN_t;
         /* ////////////////////////////////////////////////////////////// */
 
 
 /*######  Display Support *Data*  ########################################*/
 
-        /* An rcfile 'footprint' used to invalidate existing local rcfile
-           and the global rcfile path + name */
-#define RCF_FILEID  'a'
-#define SYS_RCFILE  "/etc/toprc"
+        /* Configuration files support */
+#define SYS_RCFILESPEC  "/etc/toprc"
+#define RCF_EYECATCHER  "RCfile for "
+#define RCF_DEPRECATED  "Id:a, "
 
         /* The default fields displayed and their order,
            if nothing is specified by the loser, oops user */
@@ -331,6 +332,24 @@ typedef struct win {
         /* Used by fields_sort, placed here for peace-of-mind */
 #define NUL_FIELDS  "abcdefghijklmnopqrstuvwxyz"
 
+
+        /* The default values for the local config file */
+#define DEF_RCFILE { \
+   0, 1, DEF_DELAY, 0, { \
+   { P_CPU, DEF_WINFLGS, 0, \
+      COLOR_RED, COLOR_RED, COLOR_YELLOW, COLOR_RED, \
+      "Def", DEF_FIELDS }, \
+   { P_PID, DEF_WINFLGS, 0, \
+      COLOR_CYAN, COLOR_CYAN, COLOR_WHITE, COLOR_CYAN, \
+      "Job", JOB_FIELDS }, \
+   { P_MEM, DEF_WINFLGS, 0, \
+      COLOR_MAGENTA, COLOR_MAGENTA, COLOR_BLUE, COLOR_MAGENTA, \
+      "Mem", MEM_FIELDS }, \
+   { P_USR, DEF_WINFLGS, 0, \
+      COLOR_YELLOW, COLOR_YELLOW, COLOR_GREEN, COLOR_YELLOW, \
+      "Usr", USR_FIELDS } \
+   } }
+
         /* These are the possible fscanf formats used in /proc/stat
            reads during history processing.
            ( 5th number only for Linux 2.5.41 and above ) */
@@ -349,20 +368,6 @@ typedef struct win {
 #define CMDLINE_FMTS  "( %s )"
 #endif
 
-
-RCF_t RCf_Defaults = {
-   0, 0, 1, 3.0f, 0, {
-   { "Def", DEF_FIELDS, DEF_WINFLGS, P_CPU, 0,
-       COLOR_RED, COLOR_RED, COLOR_YELLOW, COLOR_RED },
-   { "Job", JOB_FIELDS, DEF_WINFLGS, P_PID, 0,
-       COLOR_CYAN, COLOR_CYAN, COLOR_WHITE, COLOR_CYAN },
-   { "Mem", MEM_FIELDS, DEF_WINFLGS, P_MEM, 0,
-       COLOR_MAGENTA, COLOR_MAGENTA, COLOR_BLUE, COLOR_MAGENTA },
-   { "Usr", USR_FIELDS, DEF_WINFLGS, P_USR, 0,
-       COLOR_YELLOW, COLOR_YELLOW, COLOR_GREEN, COLOR_YELLOW }
-   }
-};
-
         /* Summary Lines specially formatted string(s) --
            see 'show_special' for syntax details + other cautions. */
 #define LOADAV_line  "%s -%s\n"
@@ -547,15 +552,13 @@ RCF_t RCf_Defaults = {
 \f
 /*######  Some Prototypes (ha!)  #########################################*/
 
-   /* None of these are necessary when the source file is properly
-    * organized -- they're here for documentation purposes !
-    * Note also that functions are alphabetical within a group to aid
-    * source code navigation, which often influences the identifers. */
+   /* These 'prototypes' are here for documentation purposes and in
+    * preparation for a soon-to-occur top.c bust-up! */
 /*------  Sort callbacks  ------------------------------------------------*/
 /*        for each possible field, in the form of:                        */
 /*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_HST_t (const HST_t *P, const HST_t *Q);         */
 /*------  Tiny useful routine(s)  ----------------------------------------*/
 //atic int          chin (int ech, char *buf, unsigned cnt);
 //atic const char  *fmtmk (const char *fmts, ...);
@@ -578,20 +581,33 @@ RCF_t RCf_Defaults = {
 //atic float        get_float (const char *prompt);
 //atic int          get_int (const char *prompt);
 //atic const char  *scale_num (unsigned num, const int width, const unsigned type);
-//atic const char  *scale_tics (TICS_t tics, const int width);
+//atic const char  *scale_tics (TIC_t tics, const int width);
 /*------  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 *cpus);
+//atic CPU_t       *cpus_refresh (CPU_t *cpus);
 //atic void         prochlp (proc_t *this);
 //atic proc_t     **procs_refresh (proc_t **table, int flags);
+/*------  Field Table/RCfile compatability support  ----------------------*/
+/*atic FLD_t        Fieldstab[] = { ... }                                 */
+//atic int          ft_cvt_char (const int fr, const int to, int c);
+//atic inline int   ft_get_char (const int fr, int i);
+//atic int          ft_get_idx (const int fr, int c);
+//atic const FLD_t *ft_get_ptr (const int fr, int c);
+//atic const FLD_t *ft_idx_to_ptr (const int i);
+//atic int          ft_ptr_to_idx (const FLD_t *p);
+//atic void         rc_bugless (const RCF_t *const rc);
+//atic int          rc_read_new (const char *const buf, RCF_t *rc);
+//atic int          rc_read_old (const char *const buf, RCF_t *rc);
+//atic void         rc_write_new (FILE *fp);
+//atic void         rc_write_old (FILE *fp);
+//atic const char  *rc_write_whatever (void);
 /*------  Startup routines  ----------------------------------------------*/
 //atic void         before (char *me);
 //atic void         configs_read (void);
 //atic void         parse_args (char **args);
 //atic void         whack_terminal (void);
 /*------  Field Selection/Ordering routines  -----------------------------*/
-/*atic FTAB_t       Fieldstab[] = { ... }                                 */
 //atic void         display_fields (const char *fields, const char *xtra);
 //atic void         fields_reorder (void);
 //atic void         fields_sort (void);
@@ -609,7 +625,7 @@ RCF_t RCf_Defaults = {
 //atic void         windows_stage2 (void);
 /*------  Main Screen routines  ------------------------------------------*/
 //atic void         do_key (unsigned c);
-//atic void         summaryhlp (CPUS_t *cpu, const char *pfx);
+//atic void         summaryhlp (CPU_t *cpu, const char *pfx);
 //atic proc_t     **summary_show (void);
 //atic void         task_show (const WIN_t *q, const proc_t *p);
 //atic void         window_show (proc_t **ppt, WIN_t *q, int *lscr);