cgroup support. rcfile errors default to fatal

This source patch addresses the following:
 Conceivable Buglets Avoided
  . added sanity checks for previous assumptions re: pid size, num cpus
  . changed response for rcfile errors to fatal, vs. silent default
 Enhancements
  . reorganized WIN_t struct for reduced padding and better readability
  . generalized code for multiple var-width cols (divorced from pflags)
  . absorbed jan gorig's cgroup patch, with attribution
 Cosmetic
  . reduced numerous #ifdef directives, especially in calibrate_fields
This commit is contained in:
Craig Small
2011-04-15 09:24:29 +10:00
parent 9bbaa0b3d2
commit 3ec6a27e8a
2 changed files with 112 additions and 67 deletions

135
top.c
View File

@ -186,6 +186,43 @@ static int *PHash_sav = HHash_one, // alternating 'old/new' hash tables
*PHash_new = HHash_two; *PHash_new = HHash_two;
#endif #endif
/*###### Temporary Placement ###########################################*/
/* For cgroup support inauguration, thanks to:
Jan Gorig <jgorig@redhat.com> */
/*
* Create string from cgroup array --
* ( eventually to find a home in libproc ? ) */
static void parse_cgroup (char *dst, size_t max, const proc_t *p) {
int whackable_int;
char *ccgroup, *endp = dst;
*dst = '\0';
if (p->cgroup) {
char **pcgroup = p->cgroup;
while (*pcgroup != NULL) {
// skip root cgroups
if (!**pcgroup || (*pcgroup)[strlen(*pcgroup) - 1] == '/') {
pcgroup++;
continue;
}
// skip initial cgroup number
ccgroup = strchr(*pcgroup, ':');
if (ccgroup == NULL)
ccgroup = *pcgroup;
else
ccgroup++;
if (endp != dst)
endp += escape_str(endp, ";", max, &whackable_int);
endp += escape_str(endp, ccgroup, max, &whackable_int);
pcgroup++;
}
}
if (!*dst) strncpy(dst, "-", max);
}
/*###### Sort callbacks ################################################*/ /*###### Sort callbacks ################################################*/
/* /*
@ -194,6 +231,14 @@ static int *PHash_sav = HHash_one, // alternating 'old/new' hash tables
* routine may serve more than one column. * routine may serve more than one column.
*/ */
static int SCB_NAME(CGR) (const proc_t **P, const proc_t **Q) {
char p[SCREENMAX], q[SCREENMAX];
/* we won't always re-parse these cgroups -- besides, it's only
a recurring burden when CGROUP is chosen as the sort column! */
parse_cgroup(p, sizeof(p), *P);
parse_cgroup(q, sizeof(q), *Q);
return Frame_srtflg * STRSORTCMP(q, p);
}
static int SCB_NAME(CMD) (const proc_t **P, const proc_t **Q) { static int SCB_NAME(CMD) (const proc_t **P, const proc_t **Q) {
/* if a process doesn't have a cmdline, we'll consider it a kernel thread /* if a process doesn't have a cmdline, we'll consider it a kernel thread
-- since displayed tasks are given special treatment, we must too */ -- since displayed tasks are given special treatment, we must too */
@ -361,7 +406,7 @@ static void bye_bye (const char *str) {
"\n\t winflags = %08x, maxpflgs = %d" "\n\t winflags = %08x, maxpflgs = %d"
#endif #endif
"\n\t fieldscur = %s, sortindx = %d" "\n\t fieldscur = %s, sortindx = %d"
"\n\t maxtasks = %d, maxcmdln = %d, winlines = %d" "\n\t maxtasks = %d, varcolsz = %d, winlines = %d"
"\n\t strlen(columnhdr) = %d" "\n\t strlen(columnhdr) = %d"
"\n" "\n"
, __func__ , __func__
@ -392,7 +437,7 @@ static void bye_bye (const char *str) {
, Curwin->rc.winname, Curwin->grpname , Curwin->rc.winname, Curwin->grpname
, Curwin->rc.winflags, Curwin->maxpflgs , Curwin->rc.winflags, Curwin->maxpflgs
, Curwin->rc.fieldscur, Curwin->rc.sortindx , Curwin->rc.fieldscur, Curwin->rc.sortindx
, Curwin->rc.maxtasks, Curwin->maxcmdln, Curwin->winlines , Curwin->rc.maxtasks, Curwin->varcolsz, Curwin->winlines
, (int)strlen(Curwin->columnhdr) , (int)strlen(Curwin->columnhdr)
); );
} }
@ -1167,6 +1212,7 @@ static inline int user_matched (WIN_t *q, const proc_t *p) {
#define L_stat PROC_FILLSTAT #define L_stat PROC_FILLSTAT
#define L_statm PROC_FILLMEM #define L_statm PROC_FILLMEM
#define L_status PROC_FILLSTATUS #define L_status PROC_FILLSTATUS
#define L_CGROUP PROC_FILLCGROUP
#define L_CMDLINE PROC_FILLARG #define L_CMDLINE PROC_FILLARG
#define L_EUSER PROC_FILLUSR #define L_EUSER PROC_FILLUSR
#define L_OUSER PROC_FILLSTATUS | PROC_FILLUSR #define L_OUSER PROC_FILLSTATUS | PROC_FILLUSR
@ -1188,7 +1234,8 @@ static FLD_t Fieldstab[] = {
#define SF(f) (QFP_t)SCB_NAME(f) #define SF(f) (QFP_t)SCB_NAME(f)
/* .head + .fmts anomolies: /* .head + .fmts anomolies:
entries shown with NULL are valued at runtime (see zap_fieldstab) entries shown with NULL are either valued at runtime (see zap_fieldstab)
or, in the case of .fmts, represent variable width fields
.lflg anomolies: .lflg anomolies:
P_UED, L_NONE - natural outgrowth of 'stat()' in readproc (euid) P_UED, L_NONE - natural outgrowth of 'stat()' in readproc (euid)
P_CPU, L_stat - never filled by libproc, but requires times (pcpu) P_CPU, L_stat - never filled by libproc, but requires times (pcpu)
@ -1228,16 +1275,17 @@ static FLD_t Fieldstab[] = {
{ "nMin ", "%4.4s ", 4, SK_no, SF(FL2), L_stat, "Minor Page Faults" }, { "nMin ", "%4.4s ", 4, SK_no, SF(FL2), L_stat, "Minor Page Faults" },
{ "nDRT ", "%4.4s ", 4, SK_no, SF(DRT), L_statm, "Dirty Pages Count" }, { "nDRT ", "%4.4s ", 4, SK_no, SF(DRT), L_statm, "Dirty Pages Count" },
{ "S ", "%c ", -1, -1, SF(STA), L_EITHER, "Process Status" }, { "S ", "%c ", -1, -1, SF(STA), L_EITHER, "Process Status" },
// next entry's special: '.head' will be formatted using table entry's own // next entry's special: '.head' is variable width (see calibrate_fields)
// '.fmts' plus runtime supplied conversion args! { "COMMAND ", NULL, -1, -1, SF(CMD), L_EITHER, "Command Name/Line" },
{ "COMMAND ", "%-*.*s ", -1, -1, SF(CMD), L_EITHER, "Command Name/Line" },
{ "WCHAN ", "%-9.9s ", -1, -1, SF(WCH), L_stat, "Sleeping in Function" }, { "WCHAN ", "%-9.9s ", -1, -1, SF(WCH), L_stat, "Sleeping in Function" },
// next entry's special: the 0's will be replaced with '.'! // next entry's special: the 0's will be replaced with '.'!
#ifdef CASEUP_HEXES #ifdef CASEUP_HEXES
{ "Flags ", "%08lX ", -1, -1, SF(FLG), L_stat, "Task Flags <sched.h>" } { "Flags ", "%08lX ", -1, -1, SF(FLG), L_stat, "Task Flags <sched.h>" },
#else #else
{ "Flags ", "%08lx ", -1, -1, SF(FLG), L_stat, "Task Flags <sched.h>" } { "Flags ", "%08lx ", -1, -1, SF(FLG), L_stat, "Task Flags <sched.h>" },
#endif #endif
// next entry's like P_CMD, and '.head' must be the same length -- they share varcolsz
{ "CGROUP ", NULL, -1, -1, SF(CGR), L_CGROUP, "Control Group" }
#ifdef ZAP_SUSEONLY #ifdef ZAP_SUSEONLY
#define L_oom PROC_FILLOOM #define L_oom PROC_FILLOOM
,{ "Adj ", "%3d ", -1, -1, SF(OOA), L_oom, "oom_adjustment (2^X)" } ,{ "Adj ", "%3d ", -1, -1, SF(OOA), L_oom, "oom_adjustment (2^X)" }
@ -1333,6 +1381,7 @@ static void calibrate_fields (void) {
int x, hdrmax = 0; int x, hdrmax = 0;
#endif #endif
int i, needpsdb = 0; int i, needpsdb = 0;
int varcolcnt;
// block SIGWINCH signals while we do our thing... // block SIGWINCH signals while we do our thing...
sigemptyset(&newss); sigemptyset(&newss);
@ -1345,11 +1394,8 @@ static void calibrate_fields (void) {
do { do {
if (VIZISw(w)) { if (VIZISw(w)) {
#ifdef USE_X_COLHDR w->hdrcaplen = 0; // > 0 only with USE_X_COLHDR but ref'd throughout
#ifdef EQUCOLHDRYES // ( we were proliferating way too many #ifdef's )
w->hdrcaplen = 0;
#endif
#endif
// build window's pflgsall array, establish upper bounds for maxpflgs // build window's pflgsall array, establish upper bounds for maxpflgs
for (i = 0, w->totpflgs = 0; i < P_MAXPFLGS; i++) { for (i = 0, w->totpflgs = 0; i < P_MAXPFLGS; i++) {
if (FLDviz(w, i)) { if (FLDviz(w, i)) {
@ -1369,7 +1415,7 @@ static void calibrate_fields (void) {
/* build a preliminary columns header not to exceed screen width /* build a preliminary columns header not to exceed screen width
while accounting for a possible leading window number */ while accounting for a possible leading window number */
w->maxcmdln = 0; w->varcolsz = varcolcnt = 0;
*(s = w->columnhdr) = '\0'; *(s = w->columnhdr) = '\0';
if (Rc.mode_altscr) s = scat(s, " "); if (Rc.mode_altscr) s = scat(s, " ");
for (i = 0; i + w->begpflg < w->totpflgs; i++) { for (i = 0; i + w->begpflg < w->totpflgs; i++) {
@ -1381,15 +1427,16 @@ static void calibrate_fields (void) {
h = Fieldstab[f].head; h = Fieldstab[f].head;
// oops, won't fit -- we're outta here... // oops, won't fit -- we're outta here...
if (Screen_cols <= ((int)(s - w->columnhdr) + (int)strlen(h))) break; if (Screen_cols <= ((int)(s - w->columnhdr) + (int)strlen(h))) break;
if (P_CMD == f) w->maxcmdln = strlen(h) - 1; if (!Fieldstab[f].fmts) { ++varcolcnt; w->varcolsz += strlen(h) - 1; }
s = scat(s, h); s = scat(s, h);
} }
/* establish the final maxpflgs and prepare to grow the command column /* establish the final maxpflgs and prepare to grow the variable column
heading via maxcmdln - it may be a fib if P_CMD wasn't encountered, heading(s) via varcolsz - it may be a fib if their pflags wern't
but that's ok because it won't be displayed anyway */ encountered, but that's ok because they won't be displayed anyway */
w->maxpflgs = i; w->maxpflgs = i;
w->maxcmdln += Screen_cols - strlen(w->columnhdr) - 1; w->varcolsz += Screen_cols - strlen(w->columnhdr);
if (varcolcnt) w->varcolsz = w->varcolsz / varcolcnt;
/* establish the field where all remaining fields would still /* establish the field where all remaining fields would still
fit within screen width, including a leading window number */ fit within screen width, including a leading window number */
@ -1417,39 +1464,29 @@ static void calibrate_fields (void) {
#ifdef USE_X_COLHDR #ifdef USE_X_COLHDR
if (CHKw(w, Show_HICOLS) && f == w->rc.sortindx) { if (CHKw(w, Show_HICOLS) && f == w->rc.sortindx) {
s = scat(s, fmtmk("%s%s", Caps_off, w->capclr_msg)); s = scat(s, fmtmk("%s%s", Caps_off, w->capclr_msg));
#ifdef EQUCOLHDRYES
w->hdrcaplen += strlen(Caps_off) + strlen(w->capclr_msg); w->hdrcaplen += strlen(Caps_off) + strlen(w->capclr_msg);
#endif
} }
#endif #else
#ifndef USE_X_COLHDR
if (P_MAXPFLGS < f) continue; if (P_MAXPFLGS < f) continue;
#endif #endif
h = Fieldstab[f].head; h = Fieldstab[f].head;
if (P_WCH == f) needpsdb = 1; if (P_WCH == f) needpsdb = 1;
if (P_CMD == f) { if (P_CMD == f && CHKw(w, Show_CMDLIN)) Frames_libflags |= L_CMDLINE;
if (CHKw(w, Show_CMDLIN)) Frames_libflags |= L_CMDLINE; if (Fieldstab[f].fmts) s = scat(s, h);
s = scat(s, fmtmk(Fieldstab[P_CMD].fmts, w->maxcmdln, w->maxcmdln, h)); else s = scat(s, fmtmk(VARCOL_fmts, w->varcolsz, w->varcolsz, h));
} else
s = scat(s, h);
Frames_libflags |= Fieldstab[w->procflgs[i]].lflg; Frames_libflags |= Fieldstab[w->procflgs[i]].lflg;
#ifdef USE_X_COLHDR #ifdef USE_X_COLHDR
if (CHKw(w, Show_HICOLS) && f == w->rc.sortindx) { if (CHKw(w, Show_HICOLS) && f == w->rc.sortindx) {
s = scat(s, fmtmk("%s%s", Caps_off, w->capclr_hdr)); s = scat(s, fmtmk("%s%s", Caps_off, w->capclr_hdr));
#ifdef EQUCOLHDRYES
w->hdrcaplen += strlen(Caps_off) + strlen(w->capclr_hdr); w->hdrcaplen += strlen(Caps_off) + strlen(w->capclr_hdr);
#endif
} }
#endif #endif
} }
#ifdef EQUCOLHDRYES #ifdef EQUCOLHDRYES
// prepare to even out column header lengths... // prepare to even out column header lengths...
#ifdef USE_X_COLHDR
if (hdrmax + w->hdrcaplen < (x = strlen(w->columnhdr))) hdrmax = x - w->hdrcaplen; if (hdrmax + w->hdrcaplen < (x = strlen(w->columnhdr))) hdrmax = x - w->hdrcaplen;
#else
if (hdrmax < (x = strlen(w->columnhdr))) hdrmax = x;
#endif
#endif #endif
} // end: VIZISw(w) } // end: VIZISw(w)
if (Rc.mode_altscr) w = w->next; if (Rc.mode_altscr) w = w->next;
} while (w != Curwin); } while (w != Curwin);
@ -1461,13 +1498,8 @@ static void calibrate_fields (void) {
for (i = 0; i < GROUPSMAX; i++) { for (i = 0; i < GROUPSMAX; i++) {
w = &Winstk[i]; w = &Winstk[i];
if (CHKw(w, Show_TASKON)) if (CHKw(w, Show_TASKON))
#ifdef USE_X_COLHDR
if (hdrmax + w->hdrcaplen > (x = strlen(w->columnhdr))) if (hdrmax + w->hdrcaplen > (x = strlen(w->columnhdr)))
memset(&w->columnhdr[x], ' ', hdrmax + w->hdrcaplen - x); memset(&w->columnhdr[x], ' ', hdrmax + w->hdrcaplen - x);
#else
if (hdrmax > (x = strlen(w->columnhdr)))
memset(&w->columnhdr[x], ' ', hdrmax - x);
#endif
} }
#endif #endif
@ -1652,6 +1684,7 @@ static void zap_fieldstab (void) {
Fieldstab[P_PPD].head = " PPID "; Fieldstab[P_PPD].head = " PPID ";
Fieldstab[P_PPD].fmts = "%5d "; Fieldstab[P_PPD].fmts = "%5d ";
if (5 < (digits = get_pid_digits())) { if (5 < (digits = get_pid_digits())) {
if (10 < digits) error_exit("failed pid size test");
snprintf(fmts_pid, sizeof(fmts_pid), "%%%uu ", digits); snprintf(fmts_pid, sizeof(fmts_pid), "%%%uu ", digits);
Fieldstab[P_PID].head = " PID " + 10 - digits; Fieldstab[P_PID].head = " PID " + 10 - digits;
Fieldstab[P_PID].fmts = fmts_pid; Fieldstab[P_PID].fmts = fmts_pid;
@ -1661,7 +1694,8 @@ static void zap_fieldstab (void) {
Fieldstab[P_CPN].head = "P "; Fieldstab[P_CPN].head = "P ";
Fieldstab[P_CPN].fmts = "%1d "; Fieldstab[P_CPN].fmts = "%1d ";
if (1 < (digits = (unsigned)snprintf(buf, sizeof(buf), "%d", Cpu_tot))) { if (1 < (digits = (unsigned)snprintf(buf, sizeof(buf), "%u", (unsigned)Cpu_tot))) {
if (5 < digits) error_exit("failed num cpus test");
snprintf(fmts_cpu, sizeof(fmts_cpu), "%%%ud ", digits); snprintf(fmts_cpu, sizeof(fmts_cpu), "%%%ud ", digits);
Fieldstab[P_CPN].head = " P " + 5 - digits; Fieldstab[P_CPN].head = " P " + 5 - digits;
Fieldstab[P_CPN].fmts = fmts_cpu; Fieldstab[P_CPN].fmts = fmts_cpu;
@ -2042,7 +2076,7 @@ static void before (char *me) {
* line b: contains w->winflags, sortindx, maxtasks * line b: contains w->winflags, sortindx, maxtasks
* line c: contains w->summclr, msgsclr, headclr, taskclr */ * line c: contains w->summclr, msgsclr, headclr, taskclr */
static void configs_read (void) { static void configs_read (void) {
#ifdef FATAL_RCFILE #ifndef RCFILE_NOERR
static const char err_rcid[] = "incompatible rcfile, you should delete '%s'"; static const char err_rcid[] = "incompatible rcfile, you should delete '%s'";
static const char err_flds[] = "window entry #%d corrupt, please delete '%s'"; static const char err_flds[] = "window entry #%d corrupt, please delete '%s'";
#else #else
@ -2075,7 +2109,7 @@ static void configs_read (void) {
"Mode_altscr=%d, Mode_irixps=%d, Delay_time=%f, Curwin=%d\n" "Mode_altscr=%d, Mode_irixps=%d, Delay_time=%f, Curwin=%d\n"
, &id, &Rc.mode_altscr, &Rc.mode_irixps, &tmp_delay, &i)) , &id, &Rc.mode_altscr, &Rc.mode_irixps, &tmp_delay, &i))
|| RCF_VERSION_ID != id) || RCF_VERSION_ID != id)
#ifdef FATAL_RCFILE #ifndef RCFILE_NOERR
error_exit(fmtmk(err_rcid, Rc_name)); error_exit(fmtmk(err_rcid, Rc_name));
#else #else
goto just_default_em; goto just_default_em;
@ -2092,7 +2126,7 @@ static void configs_read (void) {
# error "Hey, fix the above fscanf 'PFLAGSSIZ' dependency !" # error "Hey, fix the above fscanf 'PFLAGSSIZ' dependency !"
#endif #endif
if (strlen(Winstk[i].rc.fieldscur) != sizeof(DEF_FIELDS) - 1) if (strlen(Winstk[i].rc.fieldscur) != sizeof(DEF_FIELDS) - 1)
#ifdef FATAL_RCFILE #ifndef RCFILE_NOERR
error_exit(fmtmk(err_flds, i+1, Rc_name)); error_exit(fmtmk(err_flds, i+1, Rc_name));
#else #else
goto just_default_em; goto just_default_em;
@ -2100,7 +2134,7 @@ static void configs_read (void) {
for (x = 0; x < P_MAXPFLGS; ++x) { for (x = 0; x < P_MAXPFLGS; ++x) {
int f = FLDget(&Winstk[i], x); int f = FLDget(&Winstk[i], x);
if (P_MAXPFLGS <= f) if (P_MAXPFLGS <= f)
#ifdef FATAL_RCFILE #ifndef RCFILE_NOERR
error_exit(fmtmk(err_flds, i+1, Rc_name)); error_exit(fmtmk(err_flds, i+1, Rc_name));
#else #else
goto just_default_em; goto just_default_em;
@ -2120,7 +2154,7 @@ static void configs_read (void) {
if (!Secure_mode) Rc.delay_time = tmp_delay; if (!Secure_mode) Rc.delay_time = tmp_delay;
return; return;
#ifndef FATAL_RCFILE #ifdef RCFILE_NOERR
just_default_em: just_default_em:
fclose(fp); fclose(fp);
Rc = rcdef; Rc = rcdef;
@ -3167,6 +3201,7 @@ static void task_show (const WIN_t *q, const proc_t *p) {
int s = Fieldstab[i].scale; // string must be altered ! int s = Fieldstab[i].scale; // string must be altered !
int w = Fieldstab[i].width; int w = Fieldstab[i].width;
if (!f) f = VARCOL_fmts; // ah ha, a variable width field
switch (i) { switch (i) {
#ifndef USE_X_COLHDR #ifndef USE_X_COLHDR
// these 2 aren't real procflgs, they're used in column highlighting! // these 2 aren't real procflgs, they're used in column highlighting!
@ -3178,14 +3213,20 @@ static void task_show (const WIN_t *q, const proc_t *p) {
rp = scat(rp, X_XON == i ? q->capclr_rowhigh : q->capclr_rownorm); rp = scat(rp, X_XON == i ? q->capclr_rowhigh : q->capclr_rownorm);
continue; continue;
#endif #endif
case P_CGR:
{ char tmp[SCREENMAX];
parse_cgroup(tmp, sizeof(tmp), p);
makeCOL(q->varcolsz, q->varcolsz, tmp);
}
break;
case P_CMD: case P_CMD:
{ char tmp[SCREENMAX]; { char tmp[SCREENMAX];
unsigned flags; unsigned flags;
int whackable_int = q->maxcmdln; int whackable_int = q->varcolsz;
if (CHKw(q, Show_CMDLIN)) flags = ESC_DEFUNCT | ESC_BRACKETS | ESC_ARGS; if (CHKw(q, Show_CMDLIN)) flags = ESC_DEFUNCT | ESC_BRACKETS | ESC_ARGS;
else flags = ESC_DEFUNCT; else flags = ESC_DEFUNCT;
escape_command(tmp, p, sizeof(tmp), &whackable_int, flags); escape_command(tmp, p, sizeof(tmp), &whackable_int, flags);
makeCOL(q->maxcmdln, q->maxcmdln, tmp); makeCOL(q->varcolsz, q->varcolsz, tmp);
} }
break; break;
case P_COD: case P_COD:

44
top.h
View File

@ -25,13 +25,13 @@
//#define CASEUP_HEXES /* show any hex values in upper case */ //#define CASEUP_HEXES /* show any hex values in upper case */
//#define CASEUP_SUFIX /* show time/mem/cnts suffix in upper case */ //#define CASEUP_SUFIX /* show time/mem/cnts suffix in upper case */
//#define EQUCOLHDRYES /* yes, do equalize column header lengths */ //#define EQUCOLHDRYES /* yes, do equalize column header lengths */
//#define FATAL_RCFILE /* rcfile errors are fatal, vs. silent fix */
//#define FIELD_CURSOR /* cursor follows selection w/ fields mgmt */ //#define FIELD_CURSOR /* cursor follows selection w/ fields mgmt */
//#define OFF_HST_HASH /* use BOTH qsort+bsrch vs. hashing scheme */ //#define OFF_HST_HASH /* use BOTH qsort+bsrch vs. hashing scheme */
//#define OFF_STDIOLBF /* disable our own stdout _IOFBF override */ //#define OFF_STDIOLBF /* disable our own stdout _IOFBF override */
//#define PRETEND2_5_X /* pretend we're linux 2.5.x (for IO-wait) */ //#define PRETEND2_5_X /* pretend we're linux 2.5.x (for IO-wait) */
//#define PRETEND4CPUS /* pretend we're smp with 4 ticsers (sic) */ //#define PRETEND4CPUS /* pretend we're smp with 4 ticsers (sic) */
//#define PRETENDNOCAP /* use a terminal without essential caps */ //#define PRETENDNOCAP /* use a terminal without essential caps */
//#define RCFILE_NOERR /* rcfile errs silently default, vs. fatal */
//#define RESIZE_LIMIT /* enable limits on lower sigwinch bounds */ //#define RESIZE_LIMIT /* enable limits on lower sigwinch bounds */
//#define RMAN_IGNORED /* don't consider auto right margin glitch */ //#define RMAN_IGNORED /* don't consider auto right margin glitch */
//#define STRCMPNOCASE /* use strcasecmp vs. strcmp when sorting */ //#define STRCMPNOCASE /* use strcasecmp vs. strcmp when sorting */
@ -136,7 +136,7 @@ enum pflag {
P_CPN, P_CPU, P_TME, P_TM2, P_CPN, P_CPU, P_TME, P_TM2,
P_MEM, P_VRT, P_SWP, P_RES, P_COD, P_DAT, P_SHR, P_MEM, P_VRT, P_SWP, P_RES, P_COD, P_DAT, P_SHR,
P_FL1, P_FL2, P_DRT, P_FL1, P_FL2, P_DRT,
P_STA, P_CMD, P_WCH, P_FLG, P_STA, P_CMD, P_WCH, P_FLG, P_CGR,
#ifdef ZAP_SUSEONLY #ifdef ZAP_SUSEONLY
P_OOA, P_OOM, P_OOA, P_OOM,
#endif #endif
@ -285,36 +285,34 @@ typedef struct RCF_t {
maintainence, the only real additional per frame cost of having maintainence, the only real additional per frame cost of having
windows is an extra sort -- but that's just on pointers! */ windows is an extra sort -- but that's just on pointers! */
typedef struct WIN_t { typedef struct WIN_t {
int winnum, // window's num (array pos + 1) FLG_t pflgsall [PFLAGSSIZ], // all 'active/on' fieldscur, as enum
winlines; // task window's rows (volatile) procflgs [PFLAGSSIZ]; // fieldscur subset, as enum
FLG_t pflgsall [PFLAGSSIZ]; // all 'active/on' fieldscur, as enum RCW_t rc; // stuff that gets saved in the rcfile
FLG_t procflgs [PFLAGSSIZ]; // fieldscur subset, as enum int winnum, // a window's number (array pos + 1)
int maxpflgs, // number of displayed procflgs ("on" in fieldscur) winlines, // current task window's rows (volatile)
maxpflgs, // number of displayed procflgs ("on" in fieldscur)
totpflgs, // total of displayable procflgs in pflgsall array totpflgs, // total of displayable procflgs in pflgsall array
begpflg, // scrolled beginning pos into pflgsall array begpflg, // scrolled beginning pos into pflgsall array
endpflg, // scrolled ending pos into pflgsall array endpflg, // scrolled ending pos into pflgsall array
begtask, // scrolled beginning pos into Frame_maxtask begtask, // scrolled beginning pos into Frame_maxtask
maxcmdln; // max length of a process' command line varcolsz, // max length of variable width column(s)
RCW_t rc; // stuff that gets saved in the rcfile usrseluid, // validated uid for 'u/U' user selection
usrseltyp, // the basis for matching above uid
hdrcaplen; // column header xtra caps len, if any
char capclr_sum [CLRBUFSIZ], // terminfo strings built from char capclr_sum [CLRBUFSIZ], // terminfo strings built from
capclr_msg [CLRBUFSIZ], // RCW_t colors (& rebuilt too), capclr_msg [CLRBUFSIZ], // RCW_t colors (& rebuilt too),
capclr_pmt [CLRBUFSIZ], // but NO recurring costs ! capclr_pmt [CLRBUFSIZ], // but NO recurring costs !
capclr_hdr [CLRBUFSIZ], // note: sum, msg and pmt strs capclr_hdr [CLRBUFSIZ], // note: sum, msg and pmt strs
capclr_rowhigh [CLRBUFSIZ], // are only used when this capclr_rowhigh [CLRBUFSIZ], // are only used when this
capclr_rownorm [CLRBUFSIZ]; // window is the 'Curwin'! capclr_rownorm [CLRBUFSIZ], // window is the 'Curwin'!
char cap_bold [CAPBUFSIZ]; // support for View_NOBOLD toggle cap_bold [CAPBUFSIZ], // support for View_NOBOLD toggle
int usrseluid, // validated uid for 'u/U' select grpname [GRPNAMSIZ], // window number:name, printable
usrseltyp; // basis for matching above uid
char grpname [GRPNAMSIZ], // window number:name, printable
#ifdef USE_X_COLHDR #ifdef USE_X_COLHDR
columnhdr [ROWMINSIZ]; // column headings for procflgs columnhdr [ROWMINSIZ], // column headings for procflgs
#ifdef EQUCOLHDRYES
int hdrcaplen; // xtra length of caps strings
#endif
#else #else
columnhdr [SCREENMAX]; // column headings for procflgs columnhdr [SCREENMAX], // column headings for procflgs
#endif #endif
char *captab [CAPTABMAX]; // captab needed by show_special() *captab [CAPTABMAX]; // captab needed by show_special()
struct WIN_t *next, // next window in window stack struct WIN_t *next, // next window in window stack
*prev; // prior window in window stack *prev; // prior window in window stack
} WIN_t; } WIN_t;
@ -459,6 +457,10 @@ typedef struct WIN_t {
"Usr", USR_FIELDS } \ "Usr", USR_FIELDS } \
} } } }
/* The format string used with variable width columns --
see 'calibrate_fields' for supporting logic. */
#define VARCOL_fmts "%-*.*s "
/* Summary Lines specially formatted string(s) -- /* Summary Lines specially formatted string(s) --
see 'show_special' for syntax details + other cautions. */ see 'show_special' for syntax details + other cautions. */
#define LOADAV_line "%s -%s\n" #define LOADAV_line "%s -%s\n"
@ -633,6 +635,8 @@ typedef struct WIN_t {
/*###### Some Prototypes (ha!) #########################################*/ /*###### Some Prototypes (ha!) #########################################*/
/* These 'prototypes' are here solely for documentation purposes */ /* These 'prototypes' are here solely for documentation purposes */
/*------ Temporary Placement -------------------------------------------*/
//atic void parse_cgroup (char *dst, size_t max, const proc_t *p);
/*------ Sort callbacks ------------------------------------------------*/ /*------ Sort callbacks ------------------------------------------------*/
/* for each possible field, in the form of: */ /* for each possible field, in the form of: */
/*atic int sort_P_XXX (const proc_t **P, const proc_t **Q); */ /*atic int sort_P_XXX (const proc_t **P, const proc_t **Q); */