From: albert <> Date: Sat, 30 Nov 2002 15:56:53 +0000 (+0000) Subject: mostly done ('f' screen needs work) X-Git-Tag: v3.3.0~339 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b84406584f7bbb301d5f393558d1530a5f68377a;p=procps-ng mostly done ('f' screen needs work) --- diff --git a/top.c b/top.c index 31795e57..75e61b61 100644 --- a/top.c +++ b/top.c @@ -20,6 +20,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -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 } + +/*###### 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 ", L_stat }, +#else + { "ZzZz", "Flags ", "%08lx ", -1, -1, SF(FLG), "Task Flags ", 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=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; +} + /*###### 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) /*###### 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 ", L_stat }, -#else - { "ZzZz", "Flags ", "%08lx ", -1, -1, SF(FLG), "Task Flags ", 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 9fec155e..fca5956c 100644 --- 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 } } };