1/* 2 * Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 * 25 *--------------------------------------------------------------------------- 26 * 27 * i4b daemon - curses fullscreen output 28 * ------------------------------------- 29 * 30 * $Id: curses.c,v 1.10 2009/04/16 05:56:32 lukem Exp $ 31 * 32 * $FreeBSD$ 33 * 34 * last edit-date: [Thu Jun 1 16:24:43 2000] 35 * 36 *---------------------------------------------------------------------------*/ 37 38#ifdef USE_CURSES 39 40#include "isdnd.h" 41 42#define CHPOS(cfgp) (((cfgp)->isdncontrollerused*2) + (cfgp)->isdnchannelused) 43 44static void display_budget(void); 45static void display_cards(void); 46static void menuexit(WINDOW *menu_w); 47 48static int ncontroller = 0; 49 50/*---------------------------------------------------------------------------* 51 * init curses fullscreen display 52 *---------------------------------------------------------------------------*/ 53void 54init_screen(void) 55{ 56 char buffer[512]; 57 int uheight, lheight; 58 int i, j; 59 struct cfg_entry *p; 60 struct isdn_ctrl_state *ctrl; 61 62 initscr(); /* curses init */ 63 ncontroller = count_ctrl_states(); 64 65 if ((COLS < 80) || (LINES < 24)) 66 { 67 logit(LL_ERR, "ERROR, minimal screensize must be 80x24, is %dx%d, terminating!",COLS, LINES); 68 do_exit(1); 69 } 70 71 noecho(); 72 raw(); 73 74 uheight = ncontroller * 2; /* cards * b-channels */ 75 lheight = LINES - uheight - 6 + 1; /* rest of display */ 76 77 if ((upper_w = newwin(uheight, COLS, UPPER_B, 0)) == NULL) 78 { 79 logit(LL_ERR, "ERROR, curses init upper window, terminating!"); 80 exit(1); 81 } 82 83 if ((mid_w = newwin(1, COLS, UPPER_B+uheight+1, 0)) == NULL) 84 { 85 logit(LL_ERR, "ERROR, curses init mid window, terminating!"); 86 exit(1); 87 } 88 89 if ((lower_w = newwin(lheight, COLS, UPPER_B+uheight+3, 0)) == NULL) 90 { 91 logit(LL_ERR, "ERROR, curses init lower window, LINES = %d, lheight = %d, uheight = %d, terminating!", LINES, lheight, uheight); 92 exit(1); 93 } 94 95 scrollok(lower_w, 1); 96 97 snprintf(buffer, sizeof(buffer), "----- isdn controller channel state ------------- isdnd %02d.%02d.%d [pid %d] -", VERSION, REL, STEP, (int)getpid()); 98 99 while((int)strlen(buffer) < COLS && strlen(buffer) < sizeof(buffer) - 1) 100 strlcat(buffer, "-", sizeof(buffer)); 101 102 move(0, 0); 103 standout(); 104 addstr(buffer); 105 standend(); 106 107 move(1, 0); 108 /* 01234567890123456789012345678901234567890123456789012345678901234567890123456789 */ 109 addstr("# tei b remote iface dir outbytes obps inbytes ibps units"); 110 111 snprintf(buffer, sizeof(buffer), "----- isdn userland interface state ------------------------------------------"); 112 while((int)strlen(buffer) < COLS && strlen(buffer) < sizeof(buffer) - 1) 113 strlcat(buffer, "-", sizeof(buffer)); 114 115 move(uheight+2, 0); 116 standout(); 117 addstr(buffer); 118 standend(); 119 120 snprintf(buffer, sizeof(buffer), "----- isdnd logfile display --------------------------------------------------"); 121 while((int)strlen(buffer) < COLS && strlen(buffer) < sizeof(buffer) - 1) 122 strlcat(buffer, "-", sizeof(buffer)); 123 124 move(uheight+4, 0); 125 standout(); 126 addstr(buffer); 127 standend(); 128 129 refresh(); 130 131 for (ctrl = get_first_ctrl_state(), i=j=0; ctrl; ctrl = NEXT_CTRL(ctrl), i++, j+=2) 132 { 133 if (ctrl->tei == -1) 134 mvwprintw(upper_w, j, H_CNTL, "%d --- 1 ", i); 135 else 136 mvwprintw(upper_w, j, H_CNTL, "%d %3d 1 ", i, ctrl->tei); 137 mvwprintw(upper_w, j+1, H_CNTL, " L12 2 "); 138 } 139 wrefresh(upper_w); 140 141 for (p = get_first_cfg_entry(), j=0; p; p = NEXT_CFE(p)) { 142 mvwprintw(mid_w, 0, j, "%s%d ", p->usrdevicename, p->usrdeviceunit); 143 144 p->fs_position = j; 145 146 j += ((strlen(p->usrdevicename) + (p->usrdeviceunit > 9 ? 2 : 1) + 1)); 147 } 148 wrefresh(mid_w); 149 150 wmove(lower_w, 0, 0); 151 wrefresh(lower_w); 152 153 curses_ready = 1; 154} 155 156/*---------------------------------------------------------------------------* 157 * curses menu for fullscreen command mode 158 *---------------------------------------------------------------------------*/ 159void 160do_menu(void) 161{ 162 static const char *menu[WMITEMS] = 163 { 164 "1 - (D)isplay refresh", 165 "2 - (H)angup (choose a channel)", 166 "3 - (R)eread config file", 167 "4 - (S)how card types", 168 "5 - (B)udget information", 169 "6 - (Q)uit the program", 170 }; 171 172 WINDOW *menu_w; 173 int c; 174 int mpos; 175 struct pollfd set[1]; 176 177 /* create a new window in the lower screen area */ 178 179 if ((menu_w = newwin(WMENU_HGT, WMENU_LEN, WMENU_POSLN, WMENU_POSCO )) == NULL) 180 { 181 logit(LL_WRN, "ERROR, curses init menu window!"); 182 return; 183 } 184 185 /* create a border around the window */ 186 187 box(menu_w, '|', '-'); 188 189 /* add a title */ 190 191 wstandout(menu_w); 192 mvwaddstr(menu_w, 0, (WMENU_LEN / 2) - (strlen(WMENU_TITLE) / 2), WMENU_TITLE); 193 wstandend(menu_w); 194 195 /* fill the window with the menu options */ 196 197 for (mpos=0; mpos <= (WMITEMS-1); mpos++) 198 mvwaddstr(menu_w, mpos + 2, 2, menu[mpos]); 199 200 /* highlight the first menu option */ 201 202 mpos = 0; 203 wstandout(menu_w); 204 mvwaddstr(menu_w, mpos + 2, 2, menu[mpos]); 205 wstandend(menu_w); 206 207 /* input loop */ 208 209 set[0].fd = STDIN_FILENO; 210 set[0].events = POLLIN; 211 for (;;) 212 { 213 wrefresh(menu_w); 214 215 /* if no char is available within timeout, exit menu*/ 216 217 if ((poll(set, 1, WMTIMEOUT * 1000)) <= 0) 218 goto mexit; 219 220 c = wgetch(menu_w); 221 222 switch (c) 223 { 224 case ' ': 225 case '\t': /* hilite next option */ 226 mvwaddstr(menu_w, mpos + 2, 2, menu[mpos]); 227 mpos++; 228 if (mpos >= WMITEMS) 229 mpos = 0; 230 wstandout(menu_w); 231 mvwaddstr(menu_w, mpos + 2, 2, menu[mpos]); 232 wstandend(menu_w); 233 break; 234 235 case ('0'+WBUDGET+1): /* display budget info */ 236 case 'B': 237 case 'b': 238 display_budget(); 239 goto mexit; 240 241 case ('0'+WREFRESH+1): /* display refresh */ 242 case 'D': 243 case 'd': 244 wrefresh(curscr); 245 goto mexit; 246 247 case ('0'+WQUIT+1): /* quit program */ 248 case 'Q': 249 case 'q': 250 menuexit(menu_w); 251 do_exit(0); 252 goto mexit; 253 254 case ('0'+WHANGUP+1): /* hangup connection */ 255 case 'H': 256 case 'h': 257 display_chans(); 258 goto mexit; 259 260 case ('0'+WREREAD+1): /* reread config file */ 261 case 'R': 262 case 'r': 263 rereadconfig(42); 264 goto mexit; 265 266 case ('0'+WSHOW+1): /* reread config file */ 267 case 'S': 268 case 's': 269 display_cards(); 270 goto mexit; 271 272 case '\n': 273 case '\r': /* exec highlighted option */ 274 switch (mpos) 275 { 276 case WREFRESH: 277 wrefresh(curscr); 278 break; 279 280 case WQUIT: 281 menuexit(menu_w); 282 do_exit(0); 283 break; 284 285 case WHANGUP: 286 display_chans(); 287 break; 288 289 case WREREAD: 290 rereadconfig(42); 291 break; 292 293 case WBUDGET: 294 display_budget(); 295 break; 296 297 case WSHOW: 298 display_cards(); 299 break; 300 } 301 goto mexit; 302 break; 303 304 default: 305 goto mexit; 306 break; 307 } 308 } 309 310mexit: 311 menuexit(menu_w); 312} 313 314static void 315menuexit(WINDOW *menu_w) 316{ 317 int uheight = ncontroller * 2; /* cards * b-channels */ 318 char buffer[512]; 319 320 /* delete the menu window */ 321 322 delwin(menu_w); 323 324 /* re-display the original lower window contents */ 325 326 touchwin(mid_w); 327 wrefresh(mid_w); 328 329 touchwin(lower_w); 330 wrefresh(lower_w); 331 332 touchwin(upper_w); 333 wrefresh(upper_w); 334 335 move(1, 0); 336 /* 01234567890123456789012345678901234567890123456789012345678901234567890123456789 */ 337 addstr("# tei b remote iface dir outbytes obps inbytes ibps units"); 338 339 snprintf(buffer, sizeof(buffer), "----- isdn userland interface state ------------------------------------------"); 340 while((int)strlen(buffer) < COLS) 341 strlcat(buffer, "-", sizeof(buffer)); 342 343 move(uheight+2, 0); 344 standout(); 345 addstr(buffer); 346 standend(); 347 348 snprintf(buffer, sizeof(buffer), "----- isdnd logfile display --------------------------------------------------"); 349 while((int)strlen(buffer) < COLS) 350 strlcat(buffer, "-", sizeof(buffer)); 351 352 move(uheight+4, 0); 353 standout(); 354 addstr(buffer); 355 standend(); 356 357 refresh(); 358} 359 360/*---------------------------------------------------------------------------* 361 * display the charge in units 362 *---------------------------------------------------------------------------*/ 363void 364display_charge(struct cfg_entry *cep) 365{ 366 mvwprintw(upper_w, CHPOS(cep), H_UNITS, "%d", cep->charge); 367 wclrtoeol(upper_w); 368 wrefresh(upper_w); 369} 370 371/*---------------------------------------------------------------------------* 372 * display the calculated charge in units 373 *---------------------------------------------------------------------------*/ 374void 375display_ccharge(struct cfg_entry *cep, int units) 376{ 377 mvwprintw(upper_w, CHPOS(cep), H_UNITS, "(%d)", units); 378 wclrtoeol(upper_w); 379 wrefresh(upper_w); 380} 381 382/*---------------------------------------------------------------------------* 383 * display accounting information 384 *---------------------------------------------------------------------------*/ 385void 386display_acct(struct cfg_entry *cep) 387{ 388 mvwprintw(upper_w, CHPOS(cep), H_OUT, "%-10d", cep->outbytes); 389 mvwprintw(upper_w, CHPOS(cep), H_OUTBPS, "%-4d", cep->outbps); 390 mvwprintw(upper_w, CHPOS(cep), H_IN, "%-10d", cep->inbytes); 391 mvwprintw(upper_w, CHPOS(cep), H_INBPS, "%-4d", cep->inbps); 392 wrefresh(upper_w); 393} 394 395/*---------------------------------------------------------------------------* 396 * display connect information 397 *---------------------------------------------------------------------------*/ 398void 399display_connect(struct cfg_entry *cep) 400{ 401 char buffer[256]; 402 403 /* remote telephone number */ 404 405 if (aliasing) 406 { 407 if (cep->direction == DIR_IN) 408 snprintf(buffer, sizeof(buffer), "%s", get_alias(cep->real_phone_incoming)); 409 else 410 snprintf(buffer, sizeof(buffer), "%s", get_alias(cep->remote_phone_dialout)); 411 } 412 else 413 { 414 if (cep->direction == DIR_IN) 415 snprintf(buffer, sizeof(buffer), "%s/%s", cep->name, cep->real_phone_incoming); 416 else 417 snprintf(buffer, sizeof(buffer), "%s/%s", cep->name, cep->remote_phone_dialout); 418 } 419 420 buffer[H_IFN - H_TELN - 1] = '\0'; 421 422 mvwprintw(upper_w, CHPOS(cep), H_TELN, "%s", buffer); 423 424 /* interface */ 425 426 mvwprintw(upper_w, CHPOS(cep), H_IFN, "%s%d ", 427 cep->usrdevicename, cep->usrdeviceunit); 428 429 mvwprintw(upper_w, CHPOS(cep), H_IO, 430 cep->direction == DIR_OUT ? "out" : "in"); 431 432 mvwprintw(upper_w, CHPOS(cep), H_OUT, "-"); 433 mvwprintw(upper_w, CHPOS(cep), H_OUTBPS, "-"); 434 mvwprintw(upper_w, CHPOS(cep), H_IN, "-"); 435 mvwprintw(upper_w, CHPOS(cep), H_INBPS, "-"); 436 437 if (do_bell) 438 display_bell(); 439 440 wrefresh(upper_w); 441} 442 443/*---------------------------------------------------------------------------* 444 * erase line at disconnect time 445 *---------------------------------------------------------------------------*/ 446void 447display_disconnect(struct cfg_entry *cep) 448{ 449 wmove(upper_w, CHPOS(cep), 450 H_TELN); 451 wclrtoeol(upper_w); 452 wrefresh(upper_w); 453 454 if (do_bell) 455 display_bell(); 456 457} 458 459/*---------------------------------------------------------------------------* 460 * display interface up/down information 461 *---------------------------------------------------------------------------*/ 462void 463display_updown(struct cfg_entry *cep, int updown) 464{ 465 if (updown) 466 wstandend(mid_w); 467 else 468 wstandout(mid_w); 469 470 mvwprintw(mid_w, 0, cep->fs_position, "%s%d ", 471 cep->usrdevicename, cep->usrdeviceunit); 472 473 wstandend(mid_w); 474 wrefresh(mid_w); 475} 476 477/*---------------------------------------------------------------------------* 478 * display interface up/down information 479 *---------------------------------------------------------------------------*/ 480void 481display_l12stat(int controller, int layer, int state) 482{ 483 if (controller > ncontroller) 484 return; 485 if (!(layer == 1 || layer == 2)) 486 return; 487 488 if (state) 489 wstandout(upper_w); 490 else 491 wstandend(upper_w); 492 493 if (layer == 1) 494 { 495 mvwprintw(upper_w, (controller*2)+1, H_TEI+1, "1"); 496 if (!state) 497 mvwprintw(upper_w, (controller*2)+1, H_TEI+2, "2"); 498 } 499 else if (layer == 2) 500 { 501 mvwprintw(upper_w, (controller*2)+1, H_TEI+2, "2"); 502 if (state) 503 mvwprintw(upper_w, (controller*2)+1, H_TEI+1, "1"); 504 } 505 506 wstandend(upper_w); 507 wrefresh(upper_w); 508} 509 510/*---------------------------------------------------------------------------* 511 * display TEI 512 *---------------------------------------------------------------------------*/ 513void 514display_tei(int controller, int tei) 515{ 516 if (controller > ncontroller) 517 return; 518 519 if (tei == -1) 520 mvwprintw(upper_w, controller*2, H_TEI, "---"); 521 else 522 mvwprintw(upper_w, controller*2, H_TEI, "%3d", tei); 523 524 wrefresh(upper_w); 525} 526 527/*---------------------------------------------------------------------------* 528 * display bell :-) 529 *---------------------------------------------------------------------------*/ 530void 531display_bell(void) 532{ 533 static char bell[1] = { 0x07 }; 534 write(STDOUT_FILENO, &bell[0], 1); 535} 536 537/*---------------------------------------------------------------------------* 538 * display channel information for shutdown 539 *---------------------------------------------------------------------------*/ 540void 541display_chans(void) 542{ 543 char buffer[80]; 544 int i, j, cnt = 0; 545 WINDOW *chan_w; 546 int nlines, ncols, pos_x, pos_y; 547 struct pollfd set[1]; 548 struct cfg_entry *cep = NULL; 549 struct isdn_ctrl_state *ctrl; 550 551 /* need this later to close the connection */ 552 struct ctlr_chan { 553 int cntl; 554 int chn; 555 } *cc = NULL; 556 557 for (ctrl = get_first_ctrl_state(); ctrl; ctrl = NEXT_CTRL(ctrl)) { 558 if ((get_controller_state(ctrl)) != CTRL_UP) 559 continue; 560 for (j = 0; j < ctrl->nbch; j++) 561 if ((ret_channel_state(ctrl, j)) == CHAN_RUN) 562 cnt++; 563 } 564 565 if (cnt > 0) 566 { 567 if ((cc = (struct ctlr_chan *)malloc (cnt * 568 sizeof (struct ctlr_chan))) == NULL) 569 { 570 return; 571 } 572 nlines = cnt + 4; 573 ncols = 60; 574 } 575 else 576 { 577 nlines = 5; 578 ncols = 22; 579 } 580 581 pos_y = WMENU_POSLN + 4; 582 pos_x = WMENU_POSCO + 10; 583 584 /* create a new window in the lower screen area */ 585 586 if ((chan_w = newwin(nlines, ncols, pos_y, pos_x )) == NULL) 587 { 588 logit(LL_WRN, "ERROR, curses init channel window!"); 589 if (cnt > 0) 590 free(cc); 591 return; 592 } 593 594 /* create a border around the window */ 595 596 box(chan_w, '|', '-'); 597 598 /* add a title */ 599 600 wstandout(chan_w); 601 mvwaddstr(chan_w, 0, (ncols / 2) - (strlen("Channels") / 2), "Channels"); 602 wstandend(chan_w); 603 604 /* no active channels */ 605 if (cnt == 0) 606 { 607 mvwaddstr(chan_w, 2, 2, "No active channels"); 608 wrefresh(chan_w); 609 sleep(1); 610 611 /* delete the channels window */ 612 613 delwin(chan_w); 614 return; 615 } 616 617 nlines = 2; 618 ncols = 1; 619 620 for (ctrl = get_first_ctrl_state(), i = 0; ctrl; ctrl = NEXT_CTRL(ctrl), i++) { 621 if ((get_controller_state(ctrl)) != CTRL_UP) 622 continue; 623 624 for (j = 0; j < ctrl->nbch; i++) 625 { 626 if ((ret_channel_state(ctrl, j)) == CHAN_RUN) 627 { 628 snprintf(buffer, sizeof(buffer), "%d - Controller %d channel B%d", ncols, i, j); 629 mvwaddstr(chan_w, nlines, 2, buffer); 630 cc[ncols - 1].cntl = i; 631 cc[ncols - 1].chn = j; 632 nlines++; 633 ncols++; 634 } 635 } 636 } 637 638 set[0].fd = STDIN_FILENO; 639 set[0].events = POLLIN; 640 for (;;) 641 { 642 wrefresh(chan_w); 643 644 /* if no char is available within timeout, exit menu*/ 645 646 if ((poll(set, 1, WMTIMEOUT * 1000)) <= 0) 647 break; 648 649 ncols = wgetch(chan_w); 650 651 if (!(isdigit(ncols))) 652 { 653 display_bell(); 654 continue; 655 } 656 657 nlines = ncols - '0'; 658 659 if ((nlines == 0) || (nlines > cnt)) 660 { 661 display_bell(); 662 continue; 663 } 664 665 if ((cep = get_cep_by_cc(cc[nlines-1].cntl, cc[nlines-1].chn)) 666 != NULL) 667 { 668 logit(LL_CHD, "%05d %s manual disconnect (fullscreen menu)", cep->cdid, cep->name); 669 cep->hangup = 1; 670 break; 671 } 672 } 673 674 free(cc); 675 676 /* delete the channels window */ 677 678 delwin(chan_w); 679} 680 681/*---------------------------------------------------------------------------* 682 * display card type information 683 *---------------------------------------------------------------------------*/ 684static void 685display_cards(void) 686{ 687 WINDOW *chan_w; 688 int nlines, ncols, pos_x, pos_y; 689 struct pollfd set[1]; 690 int i; 691 struct isdn_ctrl_state *ctrl; 692 693 nlines = 6+ncontroller; 694 ncols = 60; 695 pos_y = WMENU_POSLN; 696 pos_x = WMENU_POSCO; 697 698 /* create a new window in the lower screen area */ 699 700 if ((chan_w = newwin(nlines, ncols, pos_y, pos_x )) == NULL) 701 { 702 logit(LL_WRN, "ERROR, curses init channel window!"); 703 return; 704 } 705 706 /* create a border around the window */ 707 708 box(chan_w, '|', '-'); 709 710 /* add a title */ 711 712 wstandout(chan_w); 713 mvwaddstr(chan_w, 0, (ncols / 2) - (strlen("Cards") / 2), "Cards"); 714 wstandend(chan_w); 715 716 mvwprintw(chan_w, 2, 2, "ctrl device"); 717 mvwprintw(chan_w, 3, 2, "---- ----------------------------------------------"); 718 for (i = 0, ctrl = get_first_ctrl_state(); ctrl; ctrl = NEXT_CTRL(ctrl), i++) 719 { 720 mvwprintw(chan_w, 4+i, 2, " #%d %s: %s", i, 721 ctrl->device_name, 722 ctrl->controller); 723 } 724 725 wrefresh(chan_w); 726 727 set[0].fd = STDIN_FILENO; 728 set[0].events = POLLIN; 729 730 if ((poll(set, 1, WMTIMEOUT*2 * 1000)) <= 0) 731 { 732 delwin(chan_w); 733 return; 734 } 735 736 wgetch(chan_w); 737 delwin(chan_w); 738} 739 740/*---------------------------------------------------------------------------* 741 * display budget info 742 *---------------------------------------------------------------------------*/ 743static void 744display_budget(void) 745{ 746 WINDOW *bud_w; 747 int nlines, ncols, pos_x, pos_y; 748 struct pollfd set[1]; 749 int j; 750 struct cfg_entry *cep; 751 time_t now; 752 double uptime; 753 int minutes; 754 int hours; 755 int days; 756 757 nlines = 0; 758 ncols = 73; 759 pos_y = WMENU_POSLN; 760 pos_x = WMENU_POSCO-3; 761 762 for (cep = get_first_cfg_entry(), j=0; cep; cep = NEXT_CFE(cep)) { 763 if (cep->budget_callbackperiod && cep->budget_callbackncalls) 764 nlines++; 765 if (cep->budget_calloutperiod && cep->budget_calloutncalls) 766 nlines++; 767 } 768 769 if (nlines == 0) 770 return; 771 772 nlines += 6; 773 774 /* create a new window in the lower screen area */ 775 776 if ((bud_w = newwin(nlines, ncols, pos_y, pos_x )) == NULL) 777 { 778 logit(LL_WRN, "ERROR, curses init budget window!"); 779 return; 780 } 781 782 now = time(NULL); 783 uptime = difftime(now, starttime); 784 785 minutes = (time_t) (uptime / 60) % 60; 786 hours = (time_t) (uptime / (60*60)) % (60*60); 787 days = (time_t) (uptime / (60*60*24)) % (60*60*24); 788 789 uptime = uptime / (60*60); 790 791 /* create a border around the window */ 792 793 box(bud_w, '|', '-'); 794 795 /* add a title */ 796 797 wstandout(bud_w); 798 mvwaddstr(bud_w, 0, (ncols / 2) - (strlen("Budget") / 2), "Budget"); 799 wstandend(bud_w); 800 801 mvwprintw(bud_w, 1, 2, "isdnd uptime: %d %s - %d %s - %d %s", 802 days, 803 days == 1 ? "day" : "days", 804 hours, 805 hours == 1 ? "hour" : "hours", 806 minutes, 807 minutes == 1 ? "minute" : "minutes"); 808 809 mvwprintw(bud_w, 2, 2, "name t period rest ncall rest rqsts /hr rdone /hr rrjct /hr "); 810 mvwprintw(bud_w, 3, 2, "-------- - ------ ------ ----- ----- ----- ---- ----- ---- ----- ----"); 811 812 for (cep = get_first_cfg_entry(), j=4; cep; cep = NEXT_CFE(cep)) { 813 if (cep->budget_calloutperiod && cep->budget_calloutncalls) 814 { 815 mvwprintw(bud_w, j, 2, "%-8s %c %-6d %-6ld %-5d %-5d %-5d %-4.1f %-5d %-4.1f %-5d %-4.1f", 816 cep->name, 817 'o', 818 cep->budget_calloutperiod, 819 (long)(cep->budget_calloutperiod_time - now), 820 cep->budget_calloutncalls, 821 cep->budget_calloutncalls_cnt, 822 cep->budget_callout_req, 823 (double)cep->budget_callout_req / uptime, 824 cep->budget_callout_done, 825 (double)cep->budget_callout_done / uptime, 826 cep->budget_callout_rej, 827 (double)cep->budget_callout_rej / uptime); 828 j++; 829 } 830 if (cep->budget_callbackperiod && cep->budget_callbackncalls) 831 { 832 mvwprintw(bud_w, j, 2, "%-8s %c %-6d %-6ld %-5d %-5d %-5d %-4.1f %-5d %-4.1f %-5d %-4.1f", 833 (cep->budget_calloutperiod && cep->budget_calloutncalls) ? "" : cep->name, 834 'b', 835 cep->budget_callbackperiod, 836 (long)(cep->budget_callbackperiod_time - now), 837 cep->budget_callbackncalls, 838 cep->budget_callbackncalls_cnt, 839 cep->budget_callback_req, 840 (double)cep->budget_callback_req / uptime, 841 cep->budget_callback_done, 842 (double)cep->budget_callback_done / uptime, 843 cep->budget_callback_rej, 844 (double)cep->budget_callback_rej / uptime); 845 j++; 846 } 847 } 848 849 wrefresh(bud_w); 850 851 set[0].fd = STDIN_FILENO; 852 set[0].events = POLLIN; 853 854 if ((poll(set, 1, WMTIMEOUT*3 * 1000)) <= 0) 855 { 856 delwin(bud_w); 857 return; 858 } 859 860 wgetch(bud_w); 861 delwin(bud_w); 862} 863 864#endif 865 866/* EOF */ 867