]> granicus.if.org Git - procps-ng/commitdiff
mostly done ('f' screen needs work)
authoralbert <>
Sat, 30 Nov 2002 15:56:53 +0000 (15:56 +0000)
committeralbert <>
Sat, 30 Nov 2002 15:56:53 +0000 (15:56 +0000)
top.c
top.h

diff --git a/top.c b/top.c
index 31795e5727776ec4c012a04e8f6d4f63d80ca687..75e61b615b65e763b30c3df104ea378a64bce52a 100644 (file)
--- a/top.c
+++ b/top.c
@@ -20,6 +20,9 @@
 #include <sys/ioctl.h>
 #include <sys/resource.h>
 #include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 #include <ctype.h>
 #include <curses.h>
 #include <errno.h>
@@ -96,6 +99,9 @@ static int    Mode_altscr = 0;  /* 'A' - 'Alt' display mode (multi windows)  */
 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 */
+
         /* 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) */
@@ -1004,6 +1010,180 @@ static proc_t **procs_refresh (proc_t **table, int flags)
 #undef ENTsz
 }
 
+\f
+/*######  field table  ##############################################*/
+        /* These are the Fieldstab.lflg values used here and in reframewins.
+           (own identifiers as documentation and protection against changes) */
+#define L_stat     PROC_FILLSTAT
+#define L_statm    PROC_FILLMEM
+#define L_status   PROC_FILLSTATUS
+#define L_CMDLINE  L_stat   | PROC_FILLARG
+#define L_EUSER    L_status | PROC_FILLUSR
+#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)
+   // for reframewins and summary_show 1st pass
+#define L_DEFAULT  PROC_FILLSTAT
+
+#define SF(f)  (QSORT_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[] = {
+/* .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)
+      P_CMD, L_stat  - may yet require L_CMDLINE in reframewins  (cmd/cmdline)
+      L_EITHER       - must L_status, else 64-bit math, __udivdi3 on 32-bit !
+      keys   head           fmts     width   scale  sort   desc                     lflg
+     ------  -----------    -------  ------  -----  -----  ----------------------   -------- */
+   { "AaAa", "  PID ",      "%5u ",     -1,    -1, SF(PID), "Process Id",           L_EITHER },
+   { "BbBb", " PPID ",      "%5u ",     -1,    -1, SF(PPD), "Parent Process Pid",   L_EITHER },
+   { "Cc..", " PGID ",      "%5u ",     -1,    -1, SF(PGD), "Process Group Id",     L_stat   },
+   { "DdCc", " UID ",       "%4u ",     -1,    -1, SF(UID), "User Id",              L_NONE   },
+   { "EeDd", "USER     ",   "%-8.8s ",  -1,    -1, SF(USR), "User Name",            L_EUSER  },
+   { "Ff..", "GROUP    ",   "%-8.8s ",  -1,    -1, SF(GRP), "Group Name",           L_GROUP  },
+   { "GgGg", "TTY      ",   "%-8.8s ",   8,    -1, SF(TTY), "Controlling Tty",      L_stat   },
+   { "HhHh", " PR ",        "%3d ",     -1,    -1, SF(PRI), "Priority",             L_stat   },
+   { "IiIi", " NI ",        "%3d ",     -1,    -1, SF(NCE), "Nice value",           L_stat   },
+   { "JjYy", "#C ",         "%2u ",     -1,    -1, SF(CPN), "Last used cpu (SMP)",  L_stat   },
+   { "KkEe", "%CPU ",       "%#4.1f ",  -1,    -1, SF(CPU), "CPU usage",            L_stat   },
+   { "LlWw", "  TIME ",     "%6.6s ",    6,    -1, SF(TME), "CPU Time",             L_stat   },
+   { "MmWw", "   TIME+  ",  "%9.9s ",    9,    -1, SF(TME), "CPU Time, hundredths", L_stat   },
+   { "NnFf", "%MEM ",       "%#4.1f ",  -1,    -1, SF(RES), "Memory usage (RES)",   L_statm  },
+   { "OoMm", " VIRT ",      "%5.5s ",    5, SK_Kb, SF(VRT), "Virtual Image (kb)",   L_statm  },
+   { "PpOo", "SWAP ",       "%4.4s ",    4, SK_Kb, SF(SWP), "Swapped size (kb)",    L_statm  },
+   { "QqTt", " RES ",       "%4.4s ",    4, SK_Kb, SF(RES), "Resident size (kb)",   L_statm  },
+   { "RrKk", "CODE ",       "%4.4s ",    4, SK_Kb, SF(COD), "Code size (kb)",       L_statm  },
+   { "SsLl", "DATA ",       "%4.4s ",    4, SK_Kb, SF(DAT), "Data+Stack size (kb)", L_statm  },
+   { "TtPp", " SHR ",       "%4.4s ",    4, SK_Kb, SF(SHR), "Shared Mem size (kb)", L_statm  },
+   { "UuJj", "nFLT ",       "%4.4s ",    4, SK_no, SF(FLT), "Page Fault count",     L_stat   },
+   { "VvSs", "nDRT ",       "%4.4s ",    4, SK_no, SF(DRT), "Dirty Pages count",    L_statm  },
+#ifdef USE_LIB_STA3
+   { "WwVv", "STA ",        "%3.3s ",   -1,    -1, SF(STA), "Process Status",       L_status },
+#else
+   { "WwVv", "S ",          "%c ",      -1,    -1, SF(STA), "Process Status",       L_status },
+#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   },
+   { "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
+   { "ZzZz", "Flags    ",   "%08lX ",   -1,    -1, SF(FLG), "Task Flags <sched.h>", L_stat   },
+#else
+   { "ZzZz", "Flags    ",   "%08lx ",   -1,    -1, SF(FLG), "Task Flags <sched.h>", L_stat   },
+#endif
+   { "..Qq", "  A ",        "%4.4s ",    4, SK_no, SF(PID), "Accessed Page count",  L_stat   },
+   { "..Nn", " TRS ",       "%4.4s ",    4, SK_Kb, SF(PID), "Code in memory (kb)",  L_stat   },
+   { "..Rr", " WP ",        "%4.4s ",    4, SK_no, SF(PID), "Unwritable Pages",     L_stat   },
+   { "Jj[{", "#C ",         "%2u ",     -1,    -1, SF(CPN), "Last used cpu (SMP)",  L_stat   },
+   { "..\\|","Bad ",        "%2u ",     -1,    -1, SF(CPN), "-- must ignore | --",  0        },
+   { "..]}", "Bad ",        "%2u ",     -1,    -1, SF(CPN), "-- not used --",       0        },
+   { "..^~", "Bad ",        "%2u ",     -1,    -1, SF(CPN), "-- not used --",       0        },
+};
+#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];
+}
+
+// convert
+static int idx_to_jim(int i, int off){
+   return Fieldstab[i].keys[off];
+}
+
+// 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){
+   int j = -1;
+   while (++j < MAXTBL(Fieldstab)) {
+      if (c == Fieldstab[j].keys[0]) return j;
+      if (c == Fieldstab[j].keys[1]) return j;
+   }
+   return -1;
+}
+
+// convert, or -1 for failure
+static int rik_to_idx(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;
+   }
+   return -1;
+}
+
+// convert, or NULL for failure
+static const FTAB_t * rik_to_ptr(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;
+   }
+   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 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 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];
+   }
+   return 0;
+}
+
 \f
 /*######  Startup routines  ##############################################*/
 
@@ -1035,11 +1215,150 @@ static void before (char *me)
 }
 
 
+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++;
+   }
+}
+
+
+static int read_config_rik (const char * const fbuf, ssize_t num, RCF_t * const rc)
+{
+   int i;
+   int cnt;
+   const char *cp;
+   unsigned c_show = 0;
+   unsigned C_show = 0;
+   int badchar = 0; // allow a limited number of duplicates and junk
+
+   char scoreboard[256];
+
+   (void)num;
+
+   cp = fbuf+2;  // skip the "\n\n" we stuck at the beginning
+   cnt = strspn(cp,"AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz[{\\|]}^~");
+   if(cnt<22) return -1;  // catch junk, but not good files (had 25 chars in one)
+   if(cnt>37) return -1;  // catch junk, but not good files (had 29 chars in one)
+   if(cp[cnt] != '\n') return -2;
+   i = cnt;
+   rc->win[0].fieldscur[i] = '\0';
+   memset(scoreboard, '\0', sizeof scoreboard);
+   while (i--) {                        // go over each letter of the format string
+      int c = cp[i] & 0xffu;
+      int C = rik_to_jim(c);
+//      fprintf(stderr, "0x%02x -> 0x%02x, <%c> -> <%c>, %d\n",
+//           c,C,c,C,badchar); // debug
+      if (~c & 0x20) c_show |= 1 << (c & 0x1f); // 0x20 means lowercase means hidden
+      if(scoreboard[c|0xe0u]) badchar++; // duplicates not allowed
+//      fprintf(stderr, "badchar=<%c> 0x%02x\n",badchar, (unsigned char)badchar); for(;;);  // debug
+      scoreboard[c|0xe0u] = 1;
+      if (C) {
+         if (~C & 0x20) C_show |= 1 << (C & 0x1f); // 0x20 means lowercase means hidden
+         if(scoreboard[C&0x1fu]) badchar++; // duplicates not allowed
+         scoreboard[C&0x1fu] = 1;
+      } else {
+         badchar++;
+         C = '.';     // a value we hope will be ignored on output
+      }
+      rc->win[0].fieldscur[i] = C;
+   }
+//   fprintf(stderr, "badchar=%d\n",badchar); for(;;);  // debug
+   if (badchar > 4) return -9; // Rik messed up his format string, so allow 4
+   if (!c_show) return -10;   // nothing was shown
+   if (!C_show) return -11;   // nothing will be shown
+
+//fprintf(stderr,"converted <%s>\n",rc->win[0].fieldscur);
+//for(;;);
+
+   cp += cnt;
+   cp++;  // go past newline which we already checked
+
+   // 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';
+
+   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 's':
+            rc->Secure_mode = 1;
+            break;
+         case 'S':
+            rc->win[0].winflags |= Show_CTIMES;
+            break;
+         case 'c':
+            rc->win[0].winflags |= Show_CMDLIN;
+            break;
+         case 'i':
+            rc->win[0].winflags &= ~Show_IDLEPS;
+            break;
+         case 'H':  // 'H' means to show threads
+            //rc->win[0].winflags |= ;
+            break;
+         case 'm':
+            rc->win[0].winflags &= ~View_MEMORY;
+            break;
+         case 'l':
+            rc->win[0].winflags &= ~View_LOADAV;
+            break;
+         case 't':
+            rc->win[0].winflags &= ~View_STATES;
+            break;
+         case 'I':
+            rc->Mode_irixps = 0;
+            break;
+
+         case 'M':
+            c = 0; // for scoreboard
+            rc->win[0].sortindx = P_MEM;
+            break;
+         case 'P':
+            c = 0; // for scoreboard
+            rc->win[0].sortindx = P_CPU;
+            break;
+         case 'A':
+            c = 0; // for scoreboard
+            rc->win[0].sortindx = P_PID;  // should be by start_time
+            break;
+         case 'T':
+            c = 0; // for scoreboard
+            rc->win[0].sortindx = P_TM2;
+            break;
+         case 'N':
+            c = 0; // for scoreboard
+            rc->win[0].sortindx = P_PID;
+            break;
+
+         default:
+            // just ignore it, except for the scoreboard of course
+            break;
+      }
+      if(scoreboard[c]) return -16; // duplicates not allowed
+      scoreboard[c] = 1;
+   }
+   return 17;
+}
+
         /*
-         * Build the local RC file name then try to read both of 'em.
-         * 'SYS_RCFILE' contains two lines consisting of the secure
-         *   mode switch and an update interval.  It's presence limits what
-         *   ordinary users are allowed to do.
          * '$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.
@@ -1049,20 +1368,13 @@ static void before (char *me)
          *   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 void configs_read (void)
+static int read_config_jim (const char * const fbuf, ssize_t num, RCF_t * const rc)
 {
-   static const char err_rc[] = "rcfile now incompatible, you should delete '%s'";
-   char fbuf[SMLBUFSIZ];
-   FILE *fp;
-   float delay = DEF_DELAY;
-   char id;
    int i;
-
-   snprintf(RCfile, sizeof(RCfile), ".%src", Myname);
-   if (getenv("HOME"))
-      snprintf(RCfile, sizeof(RCfile), "%s/.%src", getenv("HOME"), Myname);
-
-   fp = fopen(SYS_RCFILE, "r");
+   int cnt;
+   const char *cp;
+   (void)num;
+#if 0
    if (fp) {
       fbuf[0] = '\0';
       fgets(fbuf, sizeof(fbuf), fp);            /* sys rc file, line #1 */
@@ -1071,43 +1383,243 @@ static void configs_read (void)
       fbuf[0] = '\0';
       fgets(fbuf, sizeof(fbuf), fp);            /* sys rc file, line #2 */
       fclose(fp);
-      sscanf(fbuf, "%f", &delay);
+      sscanf(fbuf, "%f", &Delay_time);
    }
-   fp = fopen(RCfile, "r");
-   if (fp) {
-      fgets(fbuf, sizeof(fbuf), fp);    /* ignore shameless advertisement */
-      if (5 != (fscanf(fp, "Id:%c, "
-         "Mode_altscr=%d, Mode_irixps=%d, Delay_time=%f, Curwin=%d\n"
-         , &id, &Mode_altscr, &Mode_irixps, &delay, &i)) || RCF_FILEID != id)
-            std_err(fmtmk(err_rc, RCfile));
-
-         /* you saw that, right?  (fscanf stickin' it to 'i') */
-      Curwin = Winstk[i];
-      for (i = 0; i < GROUPSMAX; i++) {
-           /* we won't check fscanf returns from here on out -- we'll be
-              hunky-dory with nothing in an rcfile except the 1st 2 lines */
-         fscanf(fp, "%s\tfieldscur=%s\n"
-            , Winstk[i]->rc.winname, Winstk[i]->rc.fieldscur);
-         if (WINNAMSIZ <= strlen(Winstk[i]->rc.winname)
-         || strlen(DEF_FIELDS) != strlen(Winstk[i]->rc.fieldscur))
-            std_err(fmtmk(err_rc, RCfile));
-         fscanf(fp, "\twinflags=%d, sortindx=%u, maxtasks=%d \n"
-            , &Winstk[i]->rc.winflags
-            , &Winstk[i]->rc.sortindx
-            , &Winstk[i]->rc.maxtasks);
-         fscanf(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);
+#endif
+
+   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;
+
+   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);
       }
-      fclose(fp);
+      close(fd);
    }
+
+   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) {
+            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
+            read_config_jim(fbuf,num,&usr_rcfile);
+         }
+         close(fd);
+      }
+   }
+
+   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 */
-   Secure_mode = getuid() ? Secure_mode : 0;
-   if (!Secure_mode || !getuid()) Delay_time = delay;
+   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;
+   int j = 0;
+   int tmp;
+   while (j < 36) {
+      int c = *cp++ & 0xff;
+      switch (c) {
+         case 1 ... ' ':
+         case '.':
+         case 'X':     // trying not to crash Rik's top (move COMMAND)
+         case 0x7f ... 0xff:
+            continue;  // throw away junk (some of it)
+         default:
+            c = jim_to_rik(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)
+            break;
+      }
+      buf[j++] = c;
+      if (!c) break;
+   }
+
+   fprintf(fp, "%s\n", buf);
+   cp = buf;
+
+   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';
+   if ( tmp & Show_CTIMES) *cp++ = 'S';
+   if ( tmp & Show_CMDLIN) *cp++ = 'c';
+   if (~tmp & Show_IDLEPS) *cp++ = 'i';
+   //if () *cp++ = 'H';
+   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) {
+      case P_MEM:
+         *cp++ = 'M';
+         break;
+      case P_CPU:
+         *cp++ = 'P';
+         break;
+//    case P_???: sort by start_time
+//       *cp++ = 'A';
+//       break;
+      case P_TM2:
+         *cp++ = 'T';
+         break;
+      case P_PID:
+         *cp++ = 'N';
+         break;
+   }
+
+   *cp++ = '\n';
+   *cp++ = '\n';
+   *cp++ = '\n';
+   *cp++ = '\0';
+   fprintf(fp, "%s\n", buf);
+}
+
+static void write_config_jim(FILE *fp){
+   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;
+      }
+      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);
+   }
 }
 
+static const char * write_config(void){
+   RCF_t usr_rcfile;
+   FILE *fp = fopen(RCfile, "w");
+
+   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;
+
+   if (!fp) return strerror(errno);
+   if(Crufty_config) write_config_rik(fp, &usr_rcfile);
+   write_config_jim(fp);
+   fclose(fp);
+   return NULL;
+}
 
         /*
          * Parse command line arguments.
@@ -1253,78 +1765,6 @@ static void whack_terminal (void)
 \f
 /*######  Field Selection/Ordering routines  #############################*/
 
-        /* These are the Fieldstab.lflg values used here and in reframewins.
-           (own identifiers as documentation and protection against changes) */
-#define L_stat     PROC_FILLSTAT
-#define L_statm    PROC_FILLMEM
-#define L_status   PROC_FILLSTATUS
-#define L_CMDLINE  L_stat   | PROC_FILLARG
-#define L_EUSER    L_status | PROC_FILLUSR
-#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)
-   // for reframewins and summary_show 1st pass
-#define L_DEFAULT  PROC_FILLSTAT
-
-#define SF(f)  (QSORT_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[] = {
-/* .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)
-      P_CMD, L_stat  - may yet require L_CMDLINE in reframewins  (cmd/cmdline)
-      L_EITHER       - must L_status, else 64-bit math, __udivdi3 on 32-bit !
-      keys   head           fmts     width   scale  sort   desc                     lflg
-     ------  -----------    -------  ------  -----  -----  ----------------------   -------- */
-   { "AaAa", "  PID ",      "%5u ",     -1,    -1, SF(PID), "Process Id",           L_EITHER },
-   { "BbBb", " PPID ",      "%5u ",     -1,    -1, SF(PPD), "Parent Process Pid",   L_EITHER },
-   { "Cc..", " PGID ",      "%5u ",     -1,    -1, SF(PGD), "Process Group Id",     L_stat   },
-   { "DdCc", " UID ",       "%4u ",     -1,    -1, SF(UID), "User Id",              L_NONE   },
-   { "EeDd", "USER     ",   "%-8.8s ",  -1,    -1, SF(USR), "User Name",            L_EUSER  },
-   { "Ff..", "GROUP    ",   "%-8.8s ",  -1,    -1, SF(GRP), "Group Name",           L_GROUP  },
-   { "GgGg", "TTY      ",   "%-8.8s ",   8,    -1, SF(TTY), "Controlling Tty",      L_stat   },
-   { "HhHh", " PR ",        "%3d ",     -1,    -1, SF(PRI), "Priority",             L_stat   },
-   { "IiIi", " NI ",        "%3d ",     -1,    -1, SF(NCE), "Nice value",           L_stat   },
-   { "JjYy", "#C ",         "%2u ",     -1,    -1, SF(CPN), "Last used cpu (SMP)",  L_stat   },
-   { "KkEe", "%CPU ",       "%#4.1f ",  -1,    -1, SF(CPU), "CPU usage",            L_stat   },
-   { "LlWw", "  TIME ",     "%6.6s ",    6,    -1, SF(TME), "CPU Time",             L_stat   },
-   { "MmWw", "   TIME+  ",  "%9.9s ",    9,    -1, SF(TME), "CPU Time, hundredths", L_stat   },
-   { "NnFf", "%MEM ",       "%#4.1f ",  -1,    -1, SF(RES), "Memory usage (RES)",   L_statm  },
-   { "OoMm", " VIRT ",      "%5.5s ",    5, SK_Kb, SF(VRT), "Virtual Image (kb)",   L_statm  },
-   { "PpOo", "SWAP ",       "%4.4s ",    4, SK_Kb, SF(SWP), "Swapped size (kb)",    L_statm  },
-   { "QqTt", " RES ",       "%4.4s ",    4, SK_Kb, SF(RES), "Resident size (kb)",   L_statm  },
-   { "RrKk", "CODE ",       "%4.4s ",    4, SK_Kb, SF(COD), "Code size (kb)",       L_statm  },
-   { "SsLl", "DATA ",       "%4.4s ",    4, SK_Kb, SF(DAT), "Data+Stack size (kb)", L_statm  },
-   { "TtPp", " SHR ",       "%4.4s ",    4, SK_Kb, SF(SHR), "Shared Mem size (kb)", L_statm  },
-   { "UuJj", "nFLT ",       "%4.4s ",    4, SK_no, SF(FLT), "Page Fault count",     L_stat   },
-   { "VvSs", "nDRT ",       "%4.4s ",    4, SK_no, SF(DRT), "Dirty Pages count",    L_statm  },
-#ifdef USE_LIB_STA3
-   { "WwVv", "STA ",        "%3.3s ",   -1,    -1, SF(STA), "Process Status",       L_status },
-#else
-   { "WwVv", "S ",          "%c ",      -1,    -1, SF(STA), "Process Status",       L_status },
-#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   },
-   { "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
-   { "ZzZz", "Flags    ",   "%08lX ",   -1,    -1, SF(FLG), "Task Flags <sched.h>", L_stat   },
-#else
-   { "ZzZz", "Flags    ",   "%08lx ",   -1,    -1, SF(FLG), "Task Flags <sched.h>", L_stat   },
-#endif
-   { "..Qq", "  A ",        "%4.4s ",    4, SK_no, SF(PID), "Accessed Page count",  L_stat   },
-   { "..Nn", " TRS ",       "%4.4s ",    4, SK_Kb, SF(PID), "Resident Text Size (kb)", L_stat   },
-   { "..Rr", " WP ",        "%4.4s ",    4, SK_no, SF(PID), "Write Protected Pages", L_stat   },
-   { "Jj[{", "CPU ",        "%2u ",     -1,    -1, SF(CPN), "Last used cpu (SMP)",  L_stat   },
-};
-#undef SF
 
         /*
          * Display each field represented in the Fields Table along with its
@@ -1343,15 +1783,18 @@ static void display_fields (const char *fields, const char *xtra)
       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'));
          /* advance past any leading spaces */
       for (p = Fieldstab[i].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 ? '*' : ' '
-         , b ? i + 'A' : i + 'a'
+         , c
          , p
          , Fieldstab[i].desc);
    }
@@ -1452,7 +1895,7 @@ static void fields_toggle (void)
       show_special(1, fmtmk(FIELDS_current
          , Cap_home, Curwin->rc.fieldscur, Curwin->grpname, prompt));
       chin(0, &c, 1);
-      i = toupper(c) - 'A';
+      i = rik_to_jim(c) & 0x1f;  // was:  i = toupper(c) - 'A';
       if (i < 0 || i >= MAXTBL(Fieldstab)) break;
       if ((p = strchr(Curwin->rc.fieldscur, i + 'A')))
          *p = i + 'a';
@@ -2048,31 +2491,11 @@ static void do_key (unsigned c)
          break;
 
       case 'W':
-      {  FILE *fp = fopen(RCfile, "w"); int i;
-         if (fp) {
-            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++) {
-               fprintf(fp, "%s\tfieldscur=%s\n"
-                  , Winstk[i]->rc.winname, Winstk[i]->rc.fieldscur);
-               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);
-            }
-            fclose(fp);
+      {  const char *err = write_config();
+         if (err)
+            show_msg(fmtmk("\aFailed '%s' open: %s", RCfile, err));
+         else
             show_msg(fmtmk("Wrote configuration to '%s'", RCfile));
-         } else
-            show_msg(fmtmk("\aFailed '%s' open: %s", RCfile, strerror(errno)));
       }
          break;
 
diff --git a/top.h b/top.h
index 9fec155e4aa3d2de35e83000e744c82d867a1fed..fca5956cabb185f566f59d240b883bebd4ccf454 100644 (file)
--- a/top.h
+++ b/top.h
@@ -264,23 +264,23 @@ enum pflag {
                         ? 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         winflags,        /* 'view', 'show' and 'sort' mode flags   */
-               maxtasks,        /* user requested maximum, 0 equals all   */
+   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 */
-   char        winname   [WINNAMSIZ],   /* window name, user changeable   */
-               fieldscur [PFLAGSSIZ];   /* fields displayed and ordered   */
 } rcwin;
 
 typedef struct rcf {    // global/system-wide
-   char  rcfid;                 // RCF_FILEID
-   int   altscr;                // Mode_altscr
-   int   irixps;                // Mode_irixps
-   float delay;                 // Delay_time
-   int   curwin;                // Curwin
+   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;
 
@@ -349,41 +349,17 @@ typedef struct win {
 #define CMDLINE_FMTS  "( %s )"
 #endif
 
-//typedef struct rcwin {
-//   PFLG_t      sortindx;                /* sort field, 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 display */
-//   char        winname   [WINNAMSIZ],   /* window name, user changeable   */
-//               fieldscur [PFLAGSSIZ];   /* fields displayed and ordered   */
-//} rcwin;
-//
-//typedef struct rcf {    // global/system-wide
-//   char  rcfid;                 // RCF_FILEID
-//   int   altscr;                // Mode_altscr
-//   int   irixps;                // Mode_irixps
-//   float delay;                 // Delay_time
-//   int   curwin;                // Curwin
-//   rcwin win[4];                // each of 4 windows
-//} RCF_t;
 
 RCF_t RCf_Defaults = {
-   RCF_FILEID, 0, 1, 3.0f, 0, {
-   { DEF_WINFLGS, P_CPU, 0,
-       COLOR_RED, COLOR_RED, COLOR_YELLOW, COLOR_RED,
-       "Def", DEF_FIELDS },
-   { DEF_WINFLGS, P_PID, 0,
-       COLOR_CYAN, COLOR_CYAN, COLOR_WHITE, COLOR_CYAN,
-       "Job", JOB_FIELDS },
-   { DEF_WINFLGS, P_MEM, 0,
-       COLOR_MAGENTA, COLOR_MAGENTA, COLOR_BLUE, COLOR_MAGENTA,
-       "Mem", MEM_FIELDS },
-   { DEF_WINFLGS, P_USR, 0,
-       COLOR_YELLOW, COLOR_YELLOW, COLOR_GREEN, COLOR_YELLOW,
-       "Usr", USR_FIELDS }
+   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 }
    }
 };