From 4b987331323fe7b0d8a8566c33b786682acf12c9 Mon Sep 17 00:00:00 2001 From: Jim Warner Date: Wed, 29 Feb 2012 23:59:59 -0600 Subject: [PATCH] top: honor the restrictive, crufty old top rcfile 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 Bug-Debian: http://bugs.debian.org/651213 Reported-By: martin f krafft Bug-Debian: http://bugs.debian.org/651863 Signed-off-by: Jim Warner --- top/top.c | 157 +++++++++++++++++++++++++++++++++++++------------- top/top.h | 8 ++- top/top_nls.c | 3 + top/top_nls.h | 3 + 4 files changed, 130 insertions(+), 41 deletions(-) diff --git a/top/top.c b/top/top.c index 5f6a3a37..24f8cee0 100644 --- 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; diff --git a/top/top.h b/top/top.h index 7461f32a..889e4a44 100644 --- 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); diff --git a/top/top_nls.c b/top/top_nls.c index c643e7f0..0dc14c72 100644 --- a/top/top_nls.c +++ b/top/top_nls.c @@ -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 } diff --git a/top/top_nls.h b/top/top_nls.h index e834c397..a3f03d20 100644 --- a/top/top_nls.h +++ b/top/top_nls.h @@ -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 };