]> granicus.if.org Git - procps-ng/commitdiff
top: honor the restrictive, crufty old top rcfile
authorJim Warner <james.warner@comcast.net>
Thu, 1 Mar 2012 05:59:59 +0000 (23:59 -0600)
committerCraig Small <csmall@enc.com.au>
Fri, 2 Mar 2012 10:29:43 +0000 (21:29 +1100)
At one time, new top silently defaulted when an rcfile
was found to be incompatible.  This is exactly what
the old top did.  However, after some discussion it
was decided top should alert the user and thereby
save the system administrator some headaches.

Now, some are upset over the fatal error, proving you
can't please everybody.  But in all fairness, given
the difficulty of customizing old top, any reluctance
to delete an old saved rcfile is understandable.

To ease transition to this new top, old style rcfiles
will now be honored and converted to the new format.
And if not disabled at ./configure time via CFLAGS,
a user will be warned when an old style rcfile is
about to be overwritten using the 'W' command.

Lastly, the config validation logic was enhanced to
help ensure both types of rcfile haven't been edited
manually and possibly made unuseable.

Reported-By: sergio <mailbox@sergio.spb.ru>
Bug-Debian:  http://bugs.debian.org/651213

Reported-By: martin f krafft <madduck@debian.org>
Bug-Debian:  http://bugs.debian.org/651863

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

index 5f6a3a375553fc7ac61500da0f00c5474a65da8a..24f8cee0bc302e73bf33547b12e8879ce1e380e5 100644 (file)
--- a/top/top.c
+++ b/top/top.c
@@ -72,6 +72,9 @@ static char *Myname;
         /* The 'local' config file support */
 static char  Rc_name [OURPATHSZ];
 static RCF_t Rc = DEF_RCFILE;
+#ifndef WARN_CFG_OFF
+static int   Rc_converted;
+#endif
 
         /* The run-time acquired page stuff */
 static unsigned Page_size;
@@ -658,7 +661,7 @@ static void show_msg (const char *str) {
 static int show_pmt (const char *str) {
    int rc;
 
-   PUTT("%s%s%.*s: %s%s%s"
+   PUTT("%s%s%.*s %s%s%s"
       , tg2(0, Msg_row)
       , Curwin->capclr_pmt
       , Screen_cols - 3
@@ -2153,6 +2156,70 @@ static void before (char *me) {
 } // end: before
 
 
+        /*
+         * A configs_read *Helper* function responsible for converting a
+         * single window's old rc stuff into a new top compatible rcfile entry */
+static int config_cvt (WIN_t *q) {
+ #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
+   static struct flags {
+      int old, new;
+   } flags_tab[] = {
+      { old_View_NOBOLD, View_NOBOLD },
+      { old_VISIBLE_tsk, Show_TASKON },
+      { old_Qsrt_NORMAL, Qsrt_NORMAL },
+      { old_Show_HICOLS, Show_HICOLS },
+      { old_Show_THREAD, 0           }
+   };
+   static const char field_src[] = OLD_FIELDS;
+   char field_dst[PFLAGSSIZ];
+   int i, x;
+
+   // 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 26 fields...
+   if (26 != strlen(q->rc.fieldscur))
+      return 0;
+   strcpy(field_dst, field_src);
+   for (i = 0; i < 26; i++) {
+      int c = q->rc.fieldscur[i];
+      x = toupper(c) - 'A';
+      if (x < 0 || x > 25)
+         return 0;
+      field_dst[i] = field_src[x];
+      if (isupper(c))
+         FLDon(field_dst[i]);
+   }
+   strcpy(q->rc.fieldscur, field_dst);
+
+   // lastly, we must adjust the old sort field enum...
+   x = q->rc.sortindx;
+   q->rc.sortindx = field_src[x] - FLD_OFFSET;
+
+#ifndef WARN_CFG_OFF
+   Rc_converted = 1;
+#endif
+   return 1;
+ #undef old_View_NOBOLD
+ #undef old_VISIBLE_tsk
+ #undef old_Qsrt_NORMAL
+ #undef old_Show_HICOLS
+ #undef old_Show_THREAD
+} // end: config_cvt
+
+
         /*
          * Build the local RC file name then try to read both of 'em.
          * 'SYS_RCFILESPEC' contains two lines consisting of the secure
@@ -2168,14 +2235,11 @@ static void before (char *me) {
          *   line b: contains w->winflags, sortindx, maxtasks
          *   line c: contains w->summclr, msgsclr, headclr, taskclr */
 static void configs_read (void) {
-#ifdef RCFILE_NOERR
-   RCF_t rcdef = DEF_RCFILE;
-#endif
    float tmp_delay = DEF_DELAY;
-   char fbuf[LRGBUFSIZ], *p;
+   char fbuf[LRGBUFSIZ];
+   const char *p;
    FILE *fp;
    int i, x;
-   char id;
 
    p = getenv("HOME");
    snprintf(Rc_name, sizeof(Rc_name), "%s/.%src", (p && *p) ? p : ".", Myname);
@@ -2195,61 +2259,66 @@ static void configs_read (void) {
    if (fp) {
       fbuf[0] = '\0';
       fgets(fbuf, sizeof(fbuf), fp);             // ignore eyecatcher
-      if (5 != (fscanf(fp, "Id:%c, "
-         "Mode_altscr=%d, Mode_irixps=%d, Delay_time=%f, Curwin=%d\n"
-         , &id, &Rc.mode_altscr, &Rc.mode_irixps, &tmp_delay, &i))
-      || RCF_VERSION_ID != id)
-#ifndef RCFILE_NOERR
-         error_exit(fmtmk(N_fmt(RC_bad_files_fmt), Rc_name));
-#else
-         goto just_default_em;
-#endif
+      if (5 != fscanf(fp
+         , "Id:%c, Mode_altscr=%d, Mode_irixps=%d, Delay_time=%f, Curwin=%d\n"
+         , &Rc.id, &Rc.mode_altscr, &Rc.mode_irixps, &tmp_delay, &i)) {
+            p = fmtmk(N_fmt(RC_bad_files_fmt), Rc_name);
+            goto default_or_error;
+      }
       // you saw that, right?  (fscanf stickin' it to 'i')
       Curwin = &Winstk[i];
 
       for (i = 0 ; i < GROUPSMAX; i++) {
+         p = fmtmk(N_fmt(RC_bad_entry_fmt), i+1, Rc_name);
          // note: "fieldscur=%__s" on next line should equal PFLAGSSIZ !
-         fscanf(fp, "%3s\tfieldscur=%64s\n"
-            , Winstk[i].rc.winname, Winstk[i].rc.fieldscur);
+         if (2 != fscanf(fp, "%3s\tfieldscur=%64s\n"
+            , Winstk[i].rc.winname, Winstk[i].rc.fieldscur))
+               goto default_or_error;
 #if PFLAGSSIZ > 64
  // too bad fscanf is not as flexible with his format string as snprintf
  # error Hey, fix the above fscanf 'PFLAGSSIZ' dependency !
 #endif
-         if (strlen(Winstk[i].rc.fieldscur) != sizeof(DEF_FIELDS) - 1)
-#ifndef RCFILE_NOERR
-            error_exit(fmtmk(N_fmt(RC_bad_entry_fmt), i+1, Rc_name));
-#else
-            goto just_default_em;
-#endif
-         for (x = 0; x < P_MAXPFLGS; ++x) {
-            int f = FLDget(&Winstk[i], x);
-            if (P_MAXPFLGS <= f)
-#ifndef RCFILE_NOERR
-               error_exit(fmtmk(N_fmt(RC_bad_entry_fmt), i+1, Rc_name));
-#else
-               goto just_default_em;
-#endif
-         }
-         fscanf(fp, "\twinflags=%d, sortindx=%d, maxtasks=%d\n"
-            , &Winstk[i].rc.winflags, (int*)&Winstk[i].rc.sortindx, &Winstk[i].rc.maxtasks);
-         fscanf(fp, "\tsummclr=%d, msgsclr=%d, headclr=%d, taskclr=%d\n"
+         if (3 != fscanf(fp, "\twinflags=%d, sortindx=%d, maxtasks=%d\n"
+            , &Winstk[i].rc.winflags, (int*)&Winstk[i].rc.sortindx, &Winstk[i].rc.maxtasks))
+               goto default_or_error;
+         if (4 != 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);
-      }
+            , &Winstk[i].rc.headclr, &Winstk[i].rc.taskclr))
+               goto default_or_error;
+
+         if (RCF_VERSION_ID != Rc.id) {
+            if (!config_cvt(&Winstk[i]))
+               goto default_or_error;
+         } else {
+            if (strlen(Winstk[i].rc.fieldscur) != sizeof(DEF_FIELDS) - 1)
+               goto default_or_error;
+            for (x = 0; x < P_MAXPFLGS; ++x) {
+               int f = FLDget(&Winstk[i], x);
+               if (P_MAXPFLGS <= f)
+                  goto default_or_error;
+            }
+         }
+      } // end: for (GROUPSMAX)
+
       fclose(fp);
-   }
+   } // end: if (fp)
 
    // lastly, establish the true runtime secure mode and delay time
    if (!getuid()) Secure_mode = 0;
    if (!Secure_mode) Rc.delay_time = tmp_delay;
    return;
 
+default_or_error:
 #ifdef RCFILE_NOERR
-just_default_em:
-   fclose(fp);
+{  RCF_t rcdef = DEF_RCFILE;
+
+   flcose(fp);
    Rc = rcdef;
    for (i = 0 ; i < GROUPSMAX; i++)
       Winstk[i].rc  = Rc.win[i];
+}
+#else
+   error_exit(p);
 #endif
 } // end: configs_read
 
@@ -2699,6 +2768,14 @@ static void file_writerc (void) {
    FILE *fp;
    int i;
 
+#ifndef WARN_CFG_OFF
+   if (Rc_converted) {
+      show_pmt(N_fmt(XTRA_warncfg_txt));
+      if ('y' != tolower(keyin(0)))
+         return;
+      Rc_converted = 0;
+   }
+#endif
    if (!(fp = fopen(Rc_name, "w"))) {
       show_msg(fmtmk(N_fmt(FAIL_rc_open_fmt), Rc_name, strerror(errno)));
       return;
index 7461f32a34ab63742421f7d6bd3f1d7df319a75f..889e4a44635f250026b3c579e038acd1e9e32d3d 100644 (file)
--- a/top/top.h
+++ b/top/top.h
@@ -45,6 +45,7 @@
 //#define TREE_ONEPASS            /* for speed, tolerate dangling children   */
 //#define USE_X_COLHDR            /* emphasize header vs. whole col, for 'x' */
 //#define VALIDATE_NLS            /* validate integrity of all 3 nls tables  */
+//#define WARN_CFG_OFF            /* warning OFF when overwriting old rcfile */
 
 
 /*######  Notes, etc.  ###################################################*/
@@ -303,6 +304,7 @@ typedef struct RCW_t {  // the 'window' portion of an rcfile
 
         /* This represents the complete rcfile */
 typedef struct RCF_t {
+   char   id;                   // rcfile version id
    int    mode_altscr;          // 'A' - Alt display mode (multi task windows)
    int    mode_irixps;          // 'I' - Irix vs. Solaris mode (SMP-only)
    float  delay_time;           // 'd'/'s' - How long to sleep twixt updates
@@ -360,6 +362,7 @@ typedef struct WIN_t {
 #define VIZTOGw(q,f) (VIZISw(q)) ? TOGw(q,(f)) : win_warn(Warn_VIZ)
 
         // Used to test/manipulte fieldscur values
+#define FLDon(c)     ((c) |= 0x80)
 #define FLDget(q,i)  ((FLG_t)((q)->rc.fieldscur[i] & 0x7f) - FLD_OFFSET)
 #define FLDtog(q,i)  ((q)->rc.fieldscur[i] ^= 0x80)
 #define FLDviz(q,i)  ((q)->rc.fieldscur[i] &  0x80)
@@ -490,10 +493,12 @@ typedef struct WIN_t {
 #define JOB_FIELDS  "¥¦¹·º³´Ä»¼½§Å()*+,-./012568>?@ABCFGHIJKLMNOPQRSTUVWXYZ["
 #define MEM_FIELDS  "¥º»¼½¾¿ÀÁÃij´·Å&'()*+,-./0125689BFGHIJKLMNOPQRSTUVWXYZ["
 #define USR_FIELDS  "¥¦§¨ª°¹·ºÄÅ)+,-./1234568;<=>?@ABCFGHIJKLMNOPQRSTUVWXYZ["
+        /* old top's fields (A-Z) in the first 26 positions */
+#define OLD_FIELDS  "%&*'(-0346789:;<=>?@ACDEFG)+,./125BHIJKLMNOPQRSTUVWXYZ["
 
         /* The default values for the local config file */
 #define DEF_RCFILE { \
-   0, 1, DEF_DELAY, 0, { \
+   RCF_VERSION_ID, 0, 1, DEF_DELAY, 0, { \
    { P_CPU, DEF_WINFLGS, 0, \
       COLOR_RED, COLOR_RED, COLOR_YELLOW, COLOR_RED, \
       "Def", DEF_FIELDS }, \
@@ -589,6 +594,7 @@ typedef struct WIN_t {
 //atic void          sysinfo_refresh (int forced);
 /*------  Startup routines  ----------------------------------------------*/
 //atic void          before (char *me);
+//atic int           config_cvt (WIN_t *q);
 //atic void          configs_read (void);
 //atic void          parse_args (char **args);
 //atic void          whack_terminal (void);
index c643e7f0d198b965357bcd342d19bf02007ec043..0dc14c7284c3589d1f0c4cec03c8bd5e461d3cca 100644 (file)
@@ -260,6 +260,9 @@ static void build_norm_nlstab (void) {
    Norm_nlstab[FIND_no_next_txt] = _("Locate next inactive, use \"L\"");
    Norm_nlstab[GET_find_str_txt] = _("Locate string");
    Norm_nlstab[FIND_no_find_fmt] = _("%s\"%s\" not found");
+#ifndef WARN_CFG_OFF
+   Norm_nlstab[XTRA_warncfg_txt] = _("Overwrite existing old style rcfile?");
+#endif
 }
 
 
index e834c39722b033aa5ea4879966702dd90d65fbe9..a3f03d2085d7654fc215be9eb322e8403b0822bf 100644 (file)
@@ -76,6 +76,9 @@ enum norm_nls {
    THREADS_show_fmt, TIME_accumed_fmt, UNKNOWN_cmds_txt, UNKNOWN_opts_fmt,
    USAGE_abbrev_txt, WORD_allcpus_txt, WORD_another_txt, WORD_eachcpu_fmt,
    WORD_process_txt, WORD_threads_txt, WRITE_rcfile_fmt, WRONG_switch_fmt,
+#ifndef WARN_CFG_OFF
+   XTRA_warncfg_txt,
+#endif
       norm_MAX
 };