]> granicus.if.org Git - procps-ng/commitdiff
top: honor old rcfiles after change to field additions
authorJim Warner <james.warner@comcast.net>
Sun, 13 Mar 2022 06:00:00 +0000 (00:00 -0600)
committerCraig Small <csmall@dropbear.xyz>
Tue, 15 Mar 2022 11:01:32 +0000 (22:01 +1100)
This patch will restore the previously abandoned older
rcfile support. To be honest, I wasn't sure this would
be possible given the vast difference between formats.

But after some very intense hacking our newlib top can
again fully support seamless migration from some older
'char' based file to this new 'int' based file format.

[ top even supports a 20+ year old 3.2.8 config file ]

Signed-off-by: Jim Warner <james.warner@comcast.net>
top/top.c
top/top.h

index 3ebe74568cd27a0d908c28e2b4ef7919a7ca33fc..d83d08a9566ad548570fc774f2195a2b4c9a3a02 100644 (file)
--- a/top/top.c
+++ b/top/top.c
@@ -3582,6 +3582,99 @@ static void before (char *me) {
 } // end: before
 
 
+        /*
+         * A configs_file *Helper* function responsible for transorming
+         * a 3.2.8 - 3.3.17 format 'fieldscur' into our integer based format */
+static int cfg_xform (WIN_t *q, char *flds, const char *defs) {
+ #define CVTon(c) ((c) |= 0x80)
+   static struct {
+      int old, new;
+   } flags_tab[] = {
+    #define old_View_NOBOLD  0x000001
+    #define old_VISIBLE_tsk  0x000008
+    #define old_Qsrt_NORMAL  0x000010
+    #define old_Show_HICOLS  0x000200
+    #define old_Show_THREAD  0x010000
+      { old_View_NOBOLD, View_NOBOLD },
+      { old_VISIBLE_tsk, Show_TASKON },
+      { old_Qsrt_NORMAL, Qsrt_NORMAL },
+      { old_Show_HICOLS, Show_HICOLS },
+      { old_Show_THREAD, 0           }
+    #undef old_View_NOBOLD
+    #undef old_VISIBLE_tsk
+    #undef old_Qsrt_NORMAL
+    #undef old_Show_HICOLS
+    #undef old_Show_THREAD
+   };
+   static char null_flds[] = "abcdefghijklmnopqrstuvwxyz";
+   static const char fields_src[] = CVT_FORMER;
+   char fields_dst[PFLAGSSIZ], *p1, *p2;
+   int c, f, i, x, *pn;
+
+   if (Rc.id == 'a') {
+      // first we'll touch up this window's winflags ...
+      x = q->rc.winflags;
+      q->rc.winflags = 0;
+      for (i = 0; i < MAXTBL(flags_tab); i++) {
+         if (x & flags_tab[i].old) {
+            x &= ~flags_tab[i].old;
+            q->rc.winflags |= flags_tab[i].new;
+         }
+      }
+      q->rc.winflags |= x;
+
+      // now let's convert old top's more limited fields ...
+      if (CVT_FLDMAX > strlen(flds))
+         return 1;
+      // here we convert old 3.2.8 top's more limited fields ...
+      strcpy(fields_dst, fields_src);
+      /* all other fields represent the 'on' state with a capitalized version
+         of a particular qwerty key.  for the 2 additional suse out-of-memory
+         fields it makes perfect sense to do the exact opposite, doesn't it?
+         in any case, we must turn them 'off' temporarily ... */
+      if ((p1 = strchr(flds, '[')))  *p1 = '{';
+      if ((p2 = strchr(flds, '\\'))) *p2 = '|';
+      for (i = 0; i < CVT_FLDMAX; i++) {
+         c = flds[i];
+         x = tolower(c) - 'a';
+         if (x < 0 || x >= CVT_FLDMAX)
+            return 1;
+         fields_dst[i] = fields_src[x];
+         if (isupper(c))
+            CVTon(fields_dst[i]);
+      }
+      // if we turned any suse only fields off, turn 'em back on OUR way ...
+      if (p1) CVTon(fields_dst[p1 - flds]);
+      if (p2) CVTon(fields_dst[p2 - flds]);
+
+      // next, we must adjust the old sort field enum ...
+      x = q->rc.sortindx;
+      c = null_flds[x];
+      q->rc.sortindx = 0;
+      if ((p1 = memchr(flds, c, CVT_FLDMAX))
+      || ((p1 = memchr(flds, toupper(c), CVT_FLDMAX)))) {
+         x = p1 - flds;
+         q->rc.sortindx = (fields_dst[x] & 0x7f) - FLD_OFFSET;
+      }
+      // now we're in a 3.3.0 format (soon to be transformed) ...
+      strcpy(flds, fields_dst);
+   }
+
+   // lastly, let's attend to the 3.3.0 - 3.3.17 fieldcurs format ...
+   pn = &q->rc.fieldscur[0];
+   x = strlen(defs);
+   for (i = 0; i < x; i++) {
+      f  = ((unsigned char)flds[i] & 0x7f);
+      f  = f << 1;
+      if ((unsigned char)flds[i] & 0x80) f |= 0x01;
+      *(pn + i) = f;
+   }
+
+   return 0;
+ #undef CVTon
+} // end: cfg_xform
+
+
         /*
          * A configs_file *Helper* function responsible for reading
          * and validating a configuration file's 'Inspection' entries */
@@ -3719,7 +3812,7 @@ end_oops:
          * a configuration file (personal or system-wide default) */
 static const char *configs_file (FILE *fp, const char *name, float *delay) {
    char fbuf[LRGBUFSIZ];
-   int i, tmp_whole, tmp_fract;
+   int i, n, tmp_whole, tmp_fract;
    const char *p = NULL;
 
    p = fmtmk(N_fmt(RC_bad_files_fmt), name);
@@ -3729,7 +3822,7 @@ static const char *configs_file (FILE *fp, const char *name, float *delay) {
       , &Rc.id, &Rc.mode_altscr, &Rc.mode_irixps, &tmp_whole, &tmp_fract, &i)) {
          return p;
    }
-   if (Rc.id != RCF_VERSION_ID)
+   if (Rc.id < 'a' || Rc.id > RCF_VERSION_ID)
       return p;
    if (Rc.mode_altscr < 0 || Rc.mode_altscr > 1)
       return p;
@@ -3745,15 +3838,19 @@ static const char *configs_file (FILE *fp, const char *name, float *delay) {
    *delay = (float)tmp_whole + (float)tmp_fract / 1000;
 
    for (i = 0 ; i < GROUPSMAX; i++) {
-      int j, n, x;
+      static const char *def_flds[] = { DEF_FORMER, JOB_FORMER, MEM_FORMER, USR_FORMER };
+      int j, x;
       WIN_t *w = &Winstk[i];
       p = fmtmk(N_fmt(RC_bad_entry_fmt), i+1, name);
 
       if (1 != fscanf(fp, "%3s\tfieldscur=", w->rc.winname))
          return p;
-      for (j = 0; j < mlen(w->rc.fieldscur); j++) {
-         if (1 != fscanf(fp, "%d ", &w->rc.fieldscur[j]))
-            return p;
+      if (Rc.id < RCF_XFORMED_ID)
+         fscanf(fp, "%s\n", fbuf);
+      else {
+         for (j = 0; ; j++)
+            if (1 != fscanf(fp, "%d", &w->rc.fieldscur[j]))
+               break;
       }
 
       // be tolerant of missing release 3.3.10 graph modes additions
@@ -3787,13 +3884,29 @@ static const char *configs_file (FILE *fp, const char *name, float *delay) {
 
       switch (Rc.id) {
          case 'a':                          // 3.2.8 (former procps)
+         // fall through
          case 'f':                          // 3.3.0 thru 3.3.3 (ng)
+            SETw(w, Show_JRNUMS);
+         // fall through
          case 'g':                          // from 3.3.4 thru 3.3.8
+            scat(fbuf, RCF_PLUS_H);
+         // fall through
          case 'h':                          // this is release 3.3.9
+            w->rc.graph_cpus = w->rc.graph_mems = 0;
+            // these next 2 are really global, but best documented here
+            Rc.summ_mscale = Rc.task_mscale = SK_Kb;
+         // fall through
          case 'i':                          // from 3.3.10 thru 3.3.16
+            scat(fbuf, RCF_PLUS_J);
+            w->rc.double_up = w->rc.combine_cpus = 0;
+         // fall through
          case 'j':                          // this is release 3.3.17
-            return p;
+            if (cfg_xform(w, fbuf, def_flds[i]))
+               return p;
+            Rc.tics_scaled = 0;
+         // fall through
          case 'k':                          // current RCF_VERSION_ID
+         // fall through
          default:
             if (mlen(w->rc.fieldscur) < EU_MAXPFLGS)
                return p;
index fb5c971cd451fb6931b8b2b2926e7f93dffb4204..c3bffdf6807e3c529d233ee579520d9518839a29 100644 (file)
--- a/top/top.h
+++ b/top/top.h
@@ -506,6 +506,13 @@ typedef struct WIN_t {
 #define SYS_RCRESTRICT  "/etc/toprc"
 #define SYS_RCDEFAULTS  "/etc/topdefaultrc"
 #define RCF_EYECATCHER  "Config File (Linux processes with windows)\n"
+#define RCF_PLUS_H      "\\]^_`abcdefghij"
+#define RCF_PLUS_J      "klmnopqrstuvwxyz"
+        // this next guy must never, ever change
+        // ( we transition from'char' to 'int' )
+#define RCF_XFORMED_ID  'k'
+        // this next guy is incremented when columns change
+        // ( to prevent older top versions from accessing )
 #define RCF_VERSION_ID  'k'
 
 #define FLD_OFFSET  ( (int)'%' )
@@ -513,14 +520,27 @@ typedef struct WIN_t {
 
         /* The default fields displayed and their order,
            if nothing is specified by the loser, oops user. */
-#define OLD_FIELDS { \
+#ifdef ORIG_TOPDEFS
+#define DEF_FORMER  "¥¨³´»½ÀÄ·º¹Å&')*+,-./012568<>?ABCFGHIJKLMNOPQRSTUVWXYZ[" RCF_PLUS_H RCF_PLUS_J
+#else
+#define DEF_FORMER  "¥&K¨³´»½@·º¹56ÄFÅ')*+,-./0128<>?ABCGHIJLMNOPQRSTUVWXYZ[" RCF_PLUS_H RCF_PLUS_J
+#endif
+        /* Pre-configured windows/field groups */
+#define JOB_FORMER  "¥¦¹·º(³´Ä»½@<§Å)*+,-./012568>?ABCFGHIJKLMNOPQRSTUVWXYZ[" RCF_PLUS_H RCF_PLUS_J
+#define MEM_FORMER  "¥º»<½¾¿ÀÁMBNÃD34·Å&'()*+,-./0125689FGHIJKLOPQRSTUVWXYZ[" RCF_PLUS_H RCF_PLUS_J
+#define USR_FORMER  "¥¦§¨ª°¹·ºÄÅ)+,-./1234568;<=>?@ABCFGHIJKLMNOPQRSTUVWXYZ[" RCF_PLUS_H RCF_PLUS_J
+        // old top fields ( 'a'-'z' ) in positions 0-25
+        // other suse old top fields ( '{|' ) in positions 26-27
+#define CVT_FORMER  "%&*'(-0346789:;<=>?@ACDEFGML)+,./125BHIJKNOPQRSTUVWXYZ[" RCF_PLUS_H RCF_PLUS_J
+#define CVT_FLDMAX  26
+
+#ifdef ORIG_TOPDEFS
+#define DEF_FIELDS { \
      75,  81, 103, 105, 119, 123, 129, 137, 111, 117, 115, 139,  76,  78,  82,  84,  86,  88,  90,  92, \
      94,  96,  98, 100, 106, 108, 112, 120, 124, 126, 130, 132, 134, 140, 142, 144, 146, 148, 150, 152, \
     154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, \
     194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, \
     234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 254, 256, 258, 260, 262, 264, 266, 268, 270, 272  }
-#ifdef ORIG_TOPDEFS
-#define DEF_FIELDS  OLD_FIELDS
 #else
 #define DEF_FIELDS { \
      75,  76, 150,  81, 103, 105, 119, 123, 128, 111, 117, 115, 106, 108, 137, 140, 139,  78,  82,  84, \
@@ -681,6 +701,7 @@ typedef struct WIN_t {
 //atic inline int    osel_matched (const WIN_t *q, FLG_t enu, const char *str);
 /*------  Startup routines  ----------------------------------------------*/
 //atic void          before (char *me);
+//atic int           cfg_xform (WIN_t *q, char *flds, const char *defs);
 //atic int           config_insp (FILE *fp, char *buf, size_t size);
 //atic int           config_osel (FILE *fp, char *buf, size_t size);
 //atic const char   *configs_file (FILE *fp, const char *name, float *delay);