/* dump PPP stuff */ #ident "$Revision: 1.21 $" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #undef TRUE /* uucp.h redefines TRUE & FALSE */ #undef FALSE #include "pppinfo.h" extern char pppinfo_err[]; static WINDOW *win; static int y, x; #define TOP 2 #define COL_WIDTH 26 #define COL1 0 #define COL2 26 #define COL3 52 #define BOS (LINES-1) /* bottom of screen */ #define LABEL_WIDTH 14 #define MAX_FIELD_WIDTH 11 #define NOMINAL_FIELD_WIDTH 3 #define NUM_VALUES 8 /* maximum values/field */ static struct termio tb; #define INTRCHAR tb.c_cc[VINTR] #define SUSPCHAR tb.c_cc[VSUSP] static time_t mode_date; char *pgmname; static int interval = 1; static int unit; static int unit_delta; static int fail_cnt = 0; #define FATAL_FAIL 45 static int first = 2; static int needfoot; /* need to repaint footing */ static char scrn_no = '5'; static enum { D_MODE=0, Z_MODE=1, R_MODE=2 } mode; static struct ppp_status base, cur; #define C_BUNDLE cur.ps_pi.pi_bundle #define C_KDEVS cur.ps_pi.pi_devs #define C_DDEVS cur.ps_devs #define B_BUNDLE base.ps_pi.pi_bundle #define B_KDEVS base.ps_pi.pi_devs #define B_DDEVS base.ps_devs static int indeces[MAX_PPP_LINKS], old_indeces[MAX_PPP_LINKS]; static char lochost_name[4*3+3+1]; static char remhost_name[4*3+3+1]; static void quit(int); static void sick(char *, ...); #if 0 static void fail(char *, ...); #endif static void sig_winch(int); static void usage(void); static char* hms(int); static void pval(int, char *, char *); static char* vtos(char *, ...); static void set_base(void); static void clear_base(void); static void dis_link(char *, int); static void dis_io(char *); static void dis_acct(char *); static void dis_counts(char *); static int input_wait(void); static void paint(void); static void banner(char *, time_t); static void prnt(char *, ...); void main(int argc, char **argv) { int i, c; char *p; pgmname = argv[0]; while ((i = getopt(argc, argv, "nu:i:m:")) != EOF) switch (i) { case 'u': i = (int)strtoul(optarg,&p,0); if (*p != '\0' || i < 0 || i > MAX_PPP_DEVS) usage(); if (0 > pppinfo_next_unit(i,0,&cur)) { fprintf(stderr, "%s: no such PPP unit %s\n", pgmname, optarg); exit(1); } break; case 'i': interval = (int)strtoul(optarg,&p,0); if (*p != '\0' || interval == 0) usage(); break; case 'm': if (strlen(optarg) != 1) usage(); switch (*optarg) { case 'd': mode = D_MODE; break; case 'r': mode = R_MODE; break; case 'z': mode = Z_MODE; break; default: usage(); break; } break; default: usage(); break; } if (argc != optind) usage(); (void) ioctl(0, TCGETA, &tb); win = initscr(); signal(SIGINT, quit); signal(SIGTERM, quit); signal(SIGHUP, quit); (void)signal(SIGWINCH, sig_winch); cbreak(); noecho(); keypad(stdscr, TRUE); leaveok(stdscr, FALSE); nonl(); intrflush(stdscr,FALSE); move(0, 0); for (;;) { if (first != 0) { clear(); needfoot = 1; fail_cnt = 0; } if (unit < 0 && 0 > (unit = pppinfo_next_unit(0, unit_delta, &cur))) { sick("no active PPP connnections"); } else if (0 > pppinfo_get(unit, &cur)) { sick(pppinfo_err); } else { fail_cnt = 0; paint(); } if (!input_wait()) continue; c = getch(); switch (c) { case 'q': case 'Q': quit(0); break; case 'd': case 'D': first = 2; mode = D_MODE; break; case 'z': case 'Z': first = 2; mode = Z_MODE; break; case 'r': case 'R': first = 2; mode = R_MODE; break; case '\f': if (!first) first = 1; break; case '+': case '=': /* in case of typos */ unit = pppinfo_next_unit(unit, unit_delta = 1, &cur); first = 2; break; case '-': case '_': /* in case of typos */ unit = pppinfo_next_unit(unit, unit_delta = -1, &cur); first = 2; break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': scrn_no = c; if (!first) first = 1; break; default: if (c == INTRCHAR) quit(0); if (c == SUSPCHAR) { reset_shell_mode(); kill(getpid(), SIGTSTP); reset_prog_mode(); } /* repaint screen on unrecognized commands */ if (!first) first = 1; break; } } } /* wait for a second or until something is typed */ static int input_wait(void) { int i; struct timeval wait; fd_set rmask; /* Try to delay for exactly the right interval, * adjusted for time spent displaying things. * Display at the middle of the correct second. */ (void)gettimeofday(&wait, 0); wait.tv_sec = interval; wait.tv_usec += 250000; if (wait.tv_usec > 1000000) wait.tv_usec -= 1000000; if (wait.tv_usec != 0) { wait.tv_usec = 1000000 - wait.tv_usec; if (wait.tv_usec >= 1000000/5) wait.tv_sec--; } FD_ZERO(&rmask); FD_SET(0, &rmask); i = select(1, &rmask, 0, 0, &wait); if (i < 0) { if (errno != EAGAIN && errno != EINTR) sick("select: %s", strerror(errno)); return 0; } return i; } /* paint the screen */ static void paint(void) { char cmds[80]; int i, j, same_dev, active_dev; /* If the interface is new, reset everything */ if (cur.ps_pid != base.ps_pid) first = 2; /* recompute map of link # to STREAMS mux device */ for (j = 0; j < MAX_PPP_LINKS; j++) indeces[j] = -1; same_dev = 0; active_dev = 0; for (i = 0; i < MAX_PPP_LINKS; i++) { if (C_KDEVS[i].dev_link.pl_max_frag <= 0 ) continue; j = C_KDEVS[i].dev_link.pl_link_num; if (j >= 0 && j < MAX_PPP_LINKS) indeces[j] = i; active_dev++; /* notice in passing links that have come or gone */ if ((B_KDEVS[i].dev_link.pl_index != C_KDEVS[i].dev_link.pl_index) || old_indeces[j] != i) { bcopy(&C_KDEVS[i], &B_KDEVS[i], sizeof(B_KDEVS[i])); bcopy(&C_DDEVS[j], &B_DDEVS[j], sizeof(B_DDEVS[j])); if (first == 0) first = 1; needfoot = 1; } else { same_dev++; } } if (active_dev > 0 && same_dev == 0) bcopy(&cur.ps_pi.pi_vj_tx, &base.ps_pi.pi_vj_tx, sizeof(base.ps_pi.pi_vj_tx)); /* if the map has changed, recompute the footing */ if (bcmp(&indeces[0], &old_indeces[0], sizeof(old_indeces))) { bcopy(&indeces[0], &old_indeces[0], sizeof(old_indeces)); if (!first) first = 1; needfoot = 1; } if (needfoot || first != 0) { for (i = 0, j = 0; j < MAX_PPP_LINKS; j++) { if (indeces[j] < 0) continue; i += sprintf(&cmds[i], "%s%d", (i ? ",": ""), j+1); } strcpy(&cmds[i], i ? ":link" : ""); move(BOS, 0); clrtoeol(); standout(); printw("%-8.8s %-50.50s %25.25s", cmds, " 5:I/O 6:acct 7:counts", "+/-:Interface DZRN:Mode"); standend(); needfoot = 0; } if (first > 1) { strcpy(lochost_name, inet_ntoa(cur.ps_lochost)); strcpy(remhost_name, inet_ntoa(cur.ps_remhost)); switch (mode) { case D_MODE: set_base(); mode_date = cur.ps_initial_date; break; case Z_MODE: set_base(); mode_date = time(0); break; case R_MODE: clear_base(); mode_date = cur.ps_initial_date; break; } } switch (scrn_no) { case '1': dis_link("1:link 1", 0); break; case '2': dis_link("2:link 2", 1); break; case '3': dis_link("3:link 3", 2); break; case '4': dis_link("4:link 4", 3); break; case '5': dis_io("5:I/O"); break; case '6': dis_acct("6:acct"); break; case '7': dis_counts("7:counts"); break; } /* paint the screen, leaving the cursor at the top */ move(0, 0); refresh(); first = 0; if (mode == D_MODE) set_base(); } static void banner(char *scrn_name, time_t date) { char m; char init_date_str[sizeof("mm/dd hh:mm:ss to ")+1]; char cur_time_str[sizeof("HH:MM:SS")+1]; switch (mode) { case D_MODE: m = 'D'; break; case Z_MODE: m = 'Z'; date = mode_date; break; case R_MODE: m = 'R'; date = mode_date; break; } if (date == 0) { init_date_str[0] = '\0'; } else { (void)cftime(init_date_str,"%m/%d %T to ",&date); } (void)cftime(cur_time_str,"%T",&cur.ps_cur_date); x = 0; y = 0; prnt("%-8s ppp%-2d %15.15s %-18s %*s%c: %s%s", scrn_name, unit, cur.ps_rem_sysname, remhost_name, date ? 0 : sizeof(init_date_str)-2, "", m, init_date_str, cur_time_str); x = COL1; y = TOP; } #define DELTA(nm) (cur.nm - base.nm) #define PB_METER_DELTA(nm) DELTA(ps_pi.pi_bundle.pb_meters.nm) #define PF_METER_DELTA(n,nm) DELTA(ps_pi.pi_devs[n].dev_meters.nm) #define PL_DELTA(n,nm) DELTA(ps_pi.pi_devs[n].dev_link.nm) #define PS_DEV_DELTA(nm) (C_DDEVS[link].nm - B_DDEVS[link].nm) #define SNUM(v) vtos("%3d", v) #define SSEC(v) (v <= (5*60) ? vtos("%3d sec", v) : hms(v)) #define SBYTE(v) vtos("%3d", v) #define SRATIO(n,d) ((d)!=0 ? vtos("%3.1f:1", (n)*1.0/(d)) : "") #define SKBPS(v) ((v)!=0 ? vtos("%3.1f kbps", (v)/1000.0) : "") static void pr_vj_tx(int sw) { if (cur.ps_pi.pi_vj_tx.tx_states == 0) sw = -1; pval(sw, "VJ TX total", SNUM(DELTA(ps_pi.pi_vj_tx.cnt_packets))); pval(sw, " compressed", SNUM(DELTA(ps_pi.pi_vj_tx.cnt_compressed))); pval(sw, " searches", SNUM(DELTA(ps_pi.pi_vj_tx.cnt_searches))); pval(sw, " misses", SNUM(DELTA(ps_pi.pi_vj_tx.cnt_misses))); } static void pr_vj_rx(int sw, int link) { #define V(n) ps_pi.pi_devs[n].dev_vj_rx int i = indeces[link]; if (i < 0 || cur.V(i).rx_states == 0) sw = -1; pval(sw," RX compressed",SNUM(DELTA(V(i).cnt_compressed))); pval(sw," incomp", SNUM(DELTA(V(i).cnt_uncompressed))); pval(sw," tossed", SNUM(DELTA(V(i).cnt_tossed))); #undef V } static void pr_bsd_db(int sw, int tx, /* 1=TX, 0=RX */ int link, int indx) { #define BSD_DELTA(nm) (cur_db->nm - base_db->nm) struct bsd_db *cur_db, *base_db; int max_bits, comp, raw; if (tx) { cur_db = &C_KDEVS[indx].dev_tx_db.bsd; base_db = &B_KDEVS[indx].dev_tx_db.bsd; } else { cur_db = &C_KDEVS[indx].dev_rx_db.bsd; base_db = &B_KDEVS[indx].dev_rx_db.bsd; } /* figure out the size of the code word */ for (max_bits = MIN_BSD_BITS; (1<maxmaxcode && max_bits < MAX_BSD_BITS; max_bits++) continue; pval(sw, tx ? "TX BSD bits" : "RX BSD bits", SNUM(max_bits)); pval(sw, " cur bits", SNUM(cur_db->n_bits)); pval(sw, " max code", SNUM(cur_db->max_ent)); comp = BSD_DELTA(bytes_out)+BSD_DELTA(prev_bytes_out); raw = BSD_DELTA(in_count)+BSD_DELTA(prev_in_count); pval(sw, " ratio", SRATIO(raw,comp)); pval(sw, " ckpoint", SNUM(cur_db->checkpoint)); pval(sw, " seq #", SNUM(cur_db->seqno)); pval(sw, " cleared", SNUM(cur_db->clear_count)); pval(sw, " incomp pkts", SNUM(BSD_DELTA(incomp_count))); if (tx) { pval(sw," reset peer", SNUM(PS_DEV_DELTA(ccp_rreq_rcvd))); } else { pval(sw," reset peer", SNUM(PS_DEV_DELTA(ccp_rack_rcvd))); pval(sw," buf over", SNUM(BSD_DELTA(overshoot))); pval(sw," undershoot",SNUM(BSD_DELTA(undershoot))); } #undef BSD_DELTA } static void pr_pred_db(int sw, int tx, /* 1=TX, 0=RX */ int link, int indx) { #define PRED_DELTA(nm) (cur_db->nm - base_db->nm) struct pred_db_info *cur_db, *base_db; int comp, raw; if (tx) { cur_db = &C_KDEVS[indx].dev_tx_db.pred, base_db = &B_KDEVS[indx].dev_tx_db.pred; } else { cur_db = &C_KDEVS[indx].dev_rx_db.pred, base_db = &B_KDEVS[indx].dev_rx_db.pred; } comp = PRED_DELTA(comp); raw = PRED_DELTA(uncomp); pval(sw, tx ? "TX Pred ratio" : "RX Pred ratio", SRATIO(raw,comp)); pval(sw, " incomp pkts",SNUM(PRED_DELTA(incomp))); if (tx) { pval(sw," reset peer", SNUM(PS_DEV_DELTA(ccp_rreq_rcvd))); } else { pval(sw," reset peer", SNUM(PS_DEV_DELTA(ccp_rreq_rcvd))); pval(sw," padding", SNUM(PRED_DELTA(padding))); } #undef PRED_DELTA } static void pr_comp(int sw, int link) /* -1 for bundle */ { int indx; int save_x, save_y, ret_y; if (link < 0) { link = 0; if (!(C_BUNDLE.pb_state & PB_ST_MP) && cur.ps_maxdevs > 1) { indx = -1; } else { indx = indeces[0]; } } else { if ((C_BUNDLE.pb_state & PB_ST_MP) || cur.ps_maxdevs == 1) indx = 0; else indx = indeces[link]; } if (indx < 0) { indx = 0; sw = -1; } if (sw < 0) return; save_x = x; save_y = y; if ((C_BUNDLE.pb_state & PB_ST_TX_BSD) || (C_KDEVS[indx].dev_link.pl_state & PL_ST_TX_BSD)) { pr_bsd_db(sw,1,link,indx); } else if ((C_BUNDLE.pb_state & PB_ST_TX_PRED) || (C_KDEVS[indx].dev_link.pl_state&PL_ST_TX_PRED)) { pr_pred_db(sw,1,link,indx); } ret_y = y; x += COL_WIDTH; y = save_y; if ((C_BUNDLE.pb_state & PB_ST_RX_BSD) || (C_KDEVS[indx].dev_pf_state & PF_ST_RX_BSD)) { pr_bsd_db(sw,0,link,indx); } else if ((C_BUNDLE.pb_state & PB_ST_RX_PRED) || (C_KDEVS[indx].dev_pf_state & PF_ST_RX_PRED)) { pr_pred_db(sw,0,link,indx); } if (ret_y < y) ret_y = y; x += COL_WIDTH; y = save_y; pr_vj_tx(sw); pr_vj_rx(sw, link); x = save_x; y = ret_y; } static void dis_link(char *name, int link) { # define ID_PAT "%-72.72s" # define ID_LEN 72 int indx, sw; banner(name,0); indx = indeces[link]; if (indx < 0) { y++; prnt(ID_PAT, ""); standout(); prnt("link %d inactive", link+1); standend(); return; } /* the ID string is directly indexed */ prnt("peer: "ID_PAT, &C_DDEVS[link].ident.msg[0]); y++; prnt(" "ID_PAT, (C_DDEVS[link].ident_len <= ID_LEN ? "" : (char*)&C_DDEVS[link].ident.msg[ID_LEN])); y = TOP+2; pval(1,"link type", ((C_KDEVS[indx].dev_link.pl_state & PL_ST_SYNC) ? "sync" : "async")); pval(1,"", C_DDEVS[link].callee ? "originated" : "answered"); pval(1,"raw input", SBYTE(PF_METER_DELTA(indx,raw_ibytes))); pval(1," output", SBYTE(PL_DELTA(indx,pl_raw_obytes))); pval(1,"link rate", SKBPS(C_DDEVS[link].bps)); pval((C_DDEVS[link].lcp_echo_rtt != 0.0) ? 1 : 0, "RTT", vtos("%3.0f ms", C_DDEVS[link].lcp_echo_rtt*1000.0)); y += 2; pr_comp(1,link); /* 3 columns of compression */ y = TOP+2; x = COL2; pval(1,"active for", SSEC(C_DDEVS[link].ps_active)); pval(1,"MRU", SNUM(C_DDEVS[link].lcp_neg_mru)); pval(1,"MTU", SNUM(C_DDEVS[link].lcp_neg_mtu)); sw = (C_BUNDLE.pb_state & PB_ST_MP) ? 1 : -1; pval(sw,"MRRU", SNUM(C_DDEVS[link].lcp_neg_mrru)); pval(sw,"MTRU", SNUM(C_DDEVS[link].lcp_neg_mtru)); y = TOP+2; x = COL3; pval(1,"bad FCS", SNUM(PF_METER_DELTA(indx,bad_fcs))); pval(1,"no buf", SNUM(PF_METER_DELTA(indx,nobuf))); pval(1,"null frames", SNUM(PF_METER_DELTA(indx,null))); pval(1,"~~~~~~~tiny", SNUM(PF_METER_DELTA(indx,tiny))); pval(1,"~~~~aborted", SNUM(PF_METER_DELTA(indx,abort))); pval(1,"~~~~~~~long", SNUM(PF_METER_DELTA(indx,long_frame))); pval(1,"~~~~~babble", SNUM(PF_METER_DELTA(indx,babble))); } static void dis_io(char *name) { # define IO_PAT "%8s %11s %11s %11s %11s %6s" u_int n, m; banner(name,0); prnt(IO_PAT, "", " raw", " IP", "ratio", "recent", ""); y++; n = PB_METER_DELTA(raw_ibytes); m= PB_METER_DELTA(ibytes); prnt(IO_PAT, " input", SBYTE(n), SBYTE(m), SRATIO(m,n), SKBPS(cur.ps_cur_ibps), ((cur.ps_beep_st & BEEP_ST_RX_BUSY) ? "hi" : (cur.ps_beep_st & BEEP_ST_RX_ACT) ? "medium" : "")); y++; n = PB_METER_DELTA(raw_obytes); m= PB_METER_DELTA(obytes); prnt(IO_PAT, " output", SBYTE(n), SBYTE(m), SRATIO(m,n), SKBPS(cur.ps_cur_obps), ((cur.ps_beep_st & BEEP_ST_TX_BUSY) ? "hi" : (cur.ps_beep_st & BEEP_ST_TX_ACT) ? "medium" : "")); y += 2; /* top of first column */ y = TOP+4; pval(1,"current devs", SNUM(cur.ps_numdevs)); /* Compression--leave it for the per-link screens if more than * one compressor. If present here, it uses the bottom of * all three columns. */ y = TOP+10; pr_comp(1,-1); /* top of second column */ y = TOP+4; x = COL2; /* top of third column */ y = TOP+4; x = COL3; pval(1, "avail", SKBPS(cur.ps_avail_bps)); pval(1, "previous", SKBPS(cur.ps_prev_avail_bps)); } static void dis_acct(char *name) { u_int link, m; int t1, sw; banner(name, cur.ps_acct.last_date); /* The accounting base is reset periodically by the daemon. * Nothing happens in only second, to take D_MODE as R_MODE. */ # define DA(nm) (cur.ps_acct.nm - ((mode == D_MODE \ || mode_date<=cur.ps_acct.last_date)\ ? 0 : base.ps_acct.nm)) pval(1, "calls answered~~", SNUM(DA(answered))); y++; pval(1, "links originated", SNUM(DA(calls))); pval(1, "~~~~~~~~~~dialed", SNUM(DA(attempts))); pval(1, "~~~~gave up link", SNUM(DA(failures))); y++; sw = (cur.ps_acct.calls != 0); pval(sw,"min call setup", SSEC(cur.ps_acct.min_setup)); pval(sw,"~~~~~~~~~~~avg", SSEC(cur.ps_acct.setup / (sw ? cur.ps_acct.calls : 1))); pval(sw,"~~~~~~~~~~~max", SSEC(cur.ps_acct.max_setup)); y++; pval(cur.ps_acct.calls, "calling~~~~~~",hms(DA(orig_conn))); pval(cur.ps_acct.calls, "~~~~~~~~~idle",hms(DA(orig_idle))); pval(cur.ps_acct.calls, "~~~~~~~active",hms(DA(orig_conn) - DA(orig_idle))); y++; pval(cur.ps_acct.answered, "answering~~~~",hms(DA(ans_conn))); pval(cur.ps_acct.answered, "~~~~~~~~~idle",hms(DA(ans_idle))); pval(cur.ps_acct.answered, "~~~~~~~active",hms(DA(ans_conn) - DA(ans_idle))); y++; pval(1, "not connected", hms(cur.ps_acct.sconn - ((mode == Z_MODE) ? MAX(cur.ps_acct.last_secs, base.ps_acct.sconn) : cur.ps_acct.last_secs) - DA(orig_conn) - DA(ans_conn))); /* second column */ y = TOP; x = COL2; pval(1,"maxdevs", SNUM(cur.ps_maxdevs)); pval(1,"mindevs", SNUM(cur.ps_mindevs)); pval(1,"outdevs", SNUM(cur.ps_outdevs)); y++; y++; # define NEVER (60*60) pval(cur.ps_numdevs != 0 && cur.ps_atime < NEVER, "activity timer", SSEC(cur.ps_atime)); pval(cur.ps_idle_time < NEVER && cur.ps_idle_time != 0, "MP idle timer~", SSEC(cur.ps_idle_time)); pval(cur.ps_numdevs != 0 && cur.ps_busy_time < NEVER, "MP busy timer~", SSEC(cur.ps_busy_time)); t1 = cur.ps_add_time; if (cur.ps_numdevs == 0 && cur.ps_atime < NEVER) t1 = MAX(cur.ps_atime, t1); pval(t1 != 0, "no addition~~~", SSEC(cur.ps_add_time)); pval(cur.ps_add_backoff > 5, "~~~~~backoff~~", SSEC(cur.ps_add_backoff)); /* third column */ y = TOP; x = COL3; pval(1,"current devs", SNUM(cur.ps_numdevs)); for (link = 0, m = 0; link < MAX_PPP_LINKS; link++) { if (indeces[link] >= 0 && C_DDEVS[link].callee) m++; } pval(1," originated", SNUM(cur.ps_numdevs-m)); pval(1," answered", SNUM(m)); pval(1,"active TCP", SNUM(cur.ps_pi.pi_vj_tx.actconn)); y++; pval(1, "main PID", SNUM(cur.ps_pid)); pval(cur.ps_add_pid > 0," new PID", SNUM(cur.ps_add_pid)); # undef DA } static void dis_counts(char *name) { int sw; banner(name,0); y++; pval(1,"pullups", SNUM(PB_METER_DELTA(rput_pullup))); sw = (C_BUNDLE.pb_state & PB_ST_MP) ? 1 : -1; pval(sw,"MP pullups", SNUM(PB_METER_DELTA(mp_pullup))); pval(sw," frags", SNUM(PB_METER_DELTA(mp_frags))); pval(sw," nulls", SNUM(PB_METER_DELTA(mp_null))); pval(sw," stale", SNUM(PB_METER_DELTA(mp_stale))); pval(sw," no E bit", SNUM(PB_METER_DELTA(mp_no_end))); pval(sw," orphan", SNUM(PB_METER_DELTA(mp_no_bits))); pval(sw," stray", SNUM(PB_METER_DELTA(mp_stray))); pval(sw," no mem", SNUM(PB_METER_DELTA(mp_alloc_fails))); pval(sw," nested", SNUM(PB_METER_DELTA(mp_nested))); pval(sw," frag queue", SNUM(C_BUNDLE.pb_mp.num_frags)); pval(sw," next sn", SNUM(C_BUNDLE.pb_mp.sn_in)); y = TOP; x = COL2; pval(1,"TOS queuing", SNUM(PB_METER_DELTA(move2f))); pval(1,"TOS skipped", SNUM(PB_METER_DELTA(move2f_leak))); y++; pval(1,"debugging", SNUM(cur.ps_debug)); } static void prnt(char *fmt, ...) { va_list args; move(y,x); va_start(args, fmt); if (win->_cury < BOS) vwprintw(win, fmt, args); va_end(args); } static void clear_base(void) { bzero(&base, sizeof(base)); } static void set_base(void) { bcopy(&cur, &base, sizeof(cur)); } static char* hms(int secs) { static int n; static struct { char c[16]; /* hhhhhhhhh:mm:ss */ } bufs[NUM_VALUES]; char *p; p = bufs[n].c; n = (n+1) % NUM_VALUES; if (secs < 0) secs = 0; sprintf(p, "%2d:%02d:%02d", (secs/(60*60)) % 10000, (secs/60) % 60, secs % 60); return p; } static char* vtos(char *fmt, ...) { static int n; static struct { char c[COL_WIDTH+1]; } bufs[NUM_VALUES]; char *p; va_list args; va_start(args, fmt); p = bufs[n].c; n = (n+1) % NUM_VALUES; (void)vsprintf(p, fmt, args); va_end(args); return p; } static void pval(int sw, char *lab, char *v) { int lab_len, v_len, pad; char buf[COL_WIDTH+1]; if (sw < 0) { lab = ""; v = ""; } else if (sw == 0) { v = ""; } for (lab_len = 0; *lab != '\0'; lab++, lab_len++) buf[lab_len] = (*lab == '~') ? ' ' : *lab; buf[lab_len] = '\0'; move(y,x); v_len = strlen(v); pad = LABEL_WIDTH - lab_len; if (v_len > NOMINAL_FIELD_WIDTH) pad -= v_len - NOMINAL_FIELD_WIDTH; if (pad < 0) pad = 0; printw("%s %*s%-*s ", buf, pad, "", (LABEL_WIDTH-lab_len-pad)+MAX_FIELD_WIDTH, v); y++; } static void usage(void) { fflush(stdout); fflush(stderr); (void)fprintf(stderr, "%s: usage: [-u unit] [-i interval]" " [-m d|r|z]\n", pgmname); exit(1); } static void sick(char *fmt, ...) { va_list args; move(BOS, 0); clrtoeol(); va_start(args, fmt); if (++fail_cnt >= FATAL_FAIL) { refresh(); endwin(); (void)vprintf(fmt,args); putc('\n',stdout); exit(1); } (void)vwprintw(win, fmt, args); refresh(); needfoot = 1; va_end(args); } #if 0 static void fail(char *fmt, ...) { va_list args; move(BOS, 0); clrtoeol(); va_start(args, fmt); refresh(); endwin(); (void)vprintf(fmt,args); putc('\n',stdout); exit(1); va_end(args); } #endif static void quit(int s) { move(BOS, 0); clrtoeol(); refresh(); endwin(); exit(s); } static void sig_winch(int s) { (void)endwin(); win = initscr(); if (first < 1) first = 1; (void)signal(s, sig_winch); }