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 <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>
This commit is contained in:
Jim Warner 2012-02-29 23:59:59 -06:00 committed by Craig Small
parent 488aa10d33
commit 4b98733132
4 changed files with 130 additions and 41 deletions

157
top/top.c
View File

@ -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;

View File

@ -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);

View 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
}

View 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
};