Initial import from FreeBSD RELENG_4:
[dragonfly.git] / usr.sbin / i4b / isdnd / curses.c
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.36 2000/10/09 12:53:29 hm Exp $ 
31  *
32  * $FreeBSD: src/usr.sbin/i4b/isdnd/curses.c,v 1.6.2.2 2001/08/01 17:45:03 obrien Exp $
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
44 static void display_budget(void);
45 static void display_cards(void);
46 static void menuexit(WINDOW *menu_w);
47
48 /*---------------------------------------------------------------------------*
49  *      init curses fullscreen display
50  *---------------------------------------------------------------------------*/
51 void
52 init_screen(void)
53 {
54         char buffer[512];
55         int uheight, lheight;
56         int i, j;
57         cfg_entry_t *p;
58         
59         initscr();                      /* curses init */
60         
61         if((COLS < 80) || (LINES < 24))
62         {
63                 log(LL_ERR, "ERROR, minimal screensize must be 80x24, is %dx%d, terminating!",COLS, LINES);
64                 do_exit(1);
65         }               
66
67         noecho();
68         raw();
69
70         uheight = ncontroller * 2; /* cards * b-channels */
71         lheight = LINES - uheight - 6 + 1; /* rest of display */
72         
73         if((upper_w = newwin(uheight, COLS, UPPER_B, 0)) == NULL)
74         {
75                 log(LL_ERR, "ERROR, curses init upper window, terminating!");
76                 exit(1);
77         }
78
79         if((mid_w = newwin(1, COLS, UPPER_B+uheight+1, 0)) == NULL)
80         {
81                 log(LL_ERR, "ERROR, curses init mid window, terminating!");
82                 exit(1);
83         }
84
85         if((lower_w = newwin(lheight, COLS, UPPER_B+uheight+3, 0)) == NULL)
86         {
87                 log(LL_ERR, "ERROR, curses init lower window, LINES = %d, lheight = %d, uheight = %d, terminating!", LINES, lheight, uheight);
88                 exit(1);
89         }
90         
91         scrollok(lower_w, 1);
92
93         snprintf(buffer, sizeof(buffer), "----- isdn controller channel state ------------- isdnd %02d.%02d.%d [pid %d] -", VERSION, REL, STEP, (int)getpid()); 
94
95         while(strlen(buffer) < COLS && strlen(buffer) < sizeof(buffer) - 1)
96                 strcat(buffer, "-");    
97
98         move(0, 0);
99         standout();
100         addstr(buffer);
101         standend();
102         
103         move(1, 0);
104         /*      01234567890123456789012345678901234567890123456789012345678901234567890123456789 */
105         addstr("c tei b remote                 iface  dir outbytes   obps inbytes    ibps  units");
106         
107         snprintf(buffer, sizeof(buffer), "----- isdn userland interface state ------------------------------------------");     
108         while(strlen(buffer) < COLS && strlen(buffer) < sizeof(buffer) - 1)
109                 strcat(buffer, "-");    
110
111         move(uheight+2, 0);
112         standout();
113         addstr(buffer);
114         standend();
115
116         snprintf(buffer, sizeof(buffer), "----- isdnd logfile display --------------------------------------------------");
117         while(strlen(buffer) < COLS && strlen(buffer) < sizeof(buffer) - 1)
118                 strcat(buffer, "-");    
119
120         move(uheight+4, 0);
121         standout();
122         addstr(buffer);
123         standend();
124         
125         refresh();
126
127         for(i=0, j=0; i <= ncontroller; i++, j+=2)
128         {
129                 if(isdn_ctrl_tab[i].tei == -1)
130                         mvwprintw(upper_w, j,   H_CNTL, "%d --- 1 ", i);
131                 else
132                         mvwprintw(upper_w, j,   H_CNTL, "%d %3d 1 ", i, isdn_ctrl_tab[i].tei);
133                 mvwprintw(upper_w, j+1, H_CNTL, "  L12 2 ");
134         }
135         wrefresh(upper_w);
136
137         for(i=0, j=0; i < nentries; i++)        /* walk thru all entries */
138         {
139                 p = &cfg_entry_tab[i];          /* get ptr to enry */
140
141                 mvwprintw(mid_w, 0, j, "%s%d ", bdrivername(p->usrdevicename), p->usrdeviceunit);
142
143                 p->fs_position = j;
144
145                 j += ((strlen(bdrivername(p->usrdevicename)) + (p->usrdeviceunit > 9 ? 2 : 1) + 1));
146         }
147         wrefresh(mid_w);
148
149         wmove(lower_w, 0, 0);
150         wrefresh(lower_w);
151
152         curses_ready = 1;
153 }
154
155 /*---------------------------------------------------------------------------*
156  *      curses menu for fullscreen command mode
157  *---------------------------------------------------------------------------*/
158 void
159 do_menu(void)
160 {
161         static char *menu[WMITEMS] =
162         {
163                 "1 - (D)isplay refresh",
164                 "2 - (H)angup (choose a channel)",
165                 "3 - (R)eread config file",
166                 "4 - (S)how card types",
167                 "5 - (B)udget information",                             
168                 "6 - (Q)uit the program",               
169         };
170
171         WINDOW *menu_w;
172         int c;
173         int mpos;
174         fd_set set;
175         struct timeval timeout;
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                 log(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         for(;;)
210         {
211                 wrefresh(menu_w);
212
213                 FD_ZERO(&set);
214                 FD_SET(STDIN_FILENO, &set);
215                 timeout.tv_sec = WMTIMEOUT;
216                 timeout.tv_usec = 0;
217
218                 /* if no char is available within timeout, exit menu*/
219                 
220                 if((select(STDIN_FILENO + 1, &set, NULL, NULL, &timeout)) <= 0)
221                         goto mexit;
222                 
223                 c = wgetch(menu_w);
224
225                 switch(c)
226                 {
227                         case ' ':
228                         case '\t':      /* hilite next option */
229                                 mvwaddstr(menu_w, mpos + 2, 2, menu[mpos]);
230                                 mpos++;
231                                 if(mpos >= WMITEMS)
232                                         mpos = 0;
233                                 wstandout(menu_w);
234                                 mvwaddstr(menu_w, mpos + 2, 2, menu[mpos]);
235                                 wstandend(menu_w);
236                                 break;
237
238                         case ('0'+WBUDGET+1):   /* display budget info */
239                         case 'B':
240                         case 'b':
241                                 display_budget();
242                                 goto mexit;
243
244                         case ('0'+WREFRESH+1):  /* display refresh */
245                         case 'D':
246                         case 'd':
247                                 wrefresh(curscr);
248                                 goto mexit;
249
250                         case ('0'+WQUIT+1):     /* quit program */
251                         case 'Q':
252                         case 'q':
253                                 menuexit(menu_w);
254                                 do_exit(0);
255                                 goto mexit;
256
257                         case ('0'+WHANGUP+1):   /* hangup connection */
258                         case 'H':
259                         case 'h':
260                                 display_chans();
261                                 goto mexit;
262
263                         case ('0'+WREREAD+1):   /* reread config file */
264                         case 'R':
265                         case 'r':
266                                 rereadconfig(42);
267                                 goto mexit;
268
269                         case ('0'+WSHOW+1):     /* reread config file */
270                         case 'S':
271                         case 's':
272                                 display_cards();
273                                 goto mexit;
274
275                         case '\n':
276                         case '\r':      /* exec highlighted option */
277                                 switch(mpos)
278                                 {
279                                         case WREFRESH:
280                                                 wrefresh(curscr);
281                                                 break;
282
283                                         case WQUIT:
284                                                 menuexit(menu_w);
285                                                 do_exit(0);
286                                                 break;
287
288                                         case WHANGUP:
289                                                 display_chans();
290                                                 break;
291
292                                         case WREREAD:
293                                                 rereadconfig(42);
294                                                 break;
295
296                                         case WBUDGET:
297                                                 display_budget();
298                                                 break;
299                                                 
300                                         case WSHOW:
301                                                 display_cards();
302                                                 break;
303                                 }
304                                 goto mexit;
305                                 break;
306                 
307                         default:
308                                 goto mexit;
309                                 break;
310                 }
311         }
312
313 mexit:
314         menuexit(menu_w);
315 }
316
317 static void
318 menuexit(WINDOW *menu_w)
319 {
320         int uheight = ncontroller * 2; /* cards * b-channels */
321         char buffer[512];
322
323         /* delete the menu window */
324
325         delwin(menu_w);
326
327         /* re-display the original lower window contents */
328         
329         touchwin(mid_w);
330         wrefresh(mid_w);
331
332         touchwin(lower_w);
333         wrefresh(lower_w);
334
335         touchwin(upper_w);
336         wrefresh(upper_w);
337
338         move(1, 0);
339         /*      01234567890123456789012345678901234567890123456789012345678901234567890123456789 */
340         addstr("c tei b remote                 iface  dir outbytes   obps inbytes    ibps  units");
341         
342         sprintf(buffer, "----- isdn userland interface state ------------------------------------------");      
343         while(strlen(buffer) < COLS)
344                 strcat(buffer, "-");    
345
346         move(uheight+2, 0);
347         standout();
348         addstr(buffer);
349         standend();
350
351         sprintf(buffer, "----- isdnd logfile display --------------------------------------------------");
352         while(strlen(buffer) < COLS)
353                 strcat(buffer, "-");    
354
355         move(uheight+4, 0);
356         standout();
357         addstr(buffer);
358         standend();
359                 
360         refresh();
361 }
362
363 /*---------------------------------------------------------------------------*
364  *      display the charge in units
365  *---------------------------------------------------------------------------*/
366 void
367 display_charge(cfg_entry_t *cep)
368 {
369         mvwprintw(upper_w, CHPOS(cep), H_UNITS, "%d", cep->charge);
370         wclrtoeol(upper_w);     
371         wrefresh(upper_w);
372 }
373
374 /*---------------------------------------------------------------------------*
375  *      display the calculated charge in units
376  *---------------------------------------------------------------------------*/
377 void
378 display_ccharge(cfg_entry_t *cep, int units)
379 {
380         mvwprintw(upper_w, CHPOS(cep), H_UNITS, "(%d)", units);
381         wclrtoeol(upper_w);     
382         wrefresh(upper_w);
383 }
384
385 /*---------------------------------------------------------------------------*
386  *      display accounting information
387  *---------------------------------------------------------------------------*/
388 void
389 display_acct(cfg_entry_t *cep)
390 {
391         mvwprintw(upper_w, CHPOS(cep), H_OUT,    "%-10d", cep->outbytes);
392         mvwprintw(upper_w, CHPOS(cep), H_OUTBPS, "%-4d", cep->outbps);
393         mvwprintw(upper_w, CHPOS(cep), H_IN,     "%-10d", cep->inbytes);
394         mvwprintw(upper_w, CHPOS(cep), H_INBPS,  "%-4d", cep->inbps);
395         wrefresh(upper_w);
396 }
397
398 /*---------------------------------------------------------------------------*
399  *      display connect information
400  *---------------------------------------------------------------------------*/
401 void
402 display_connect(cfg_entry_t *cep)
403 {
404         char buffer[256];
405
406         /* remote telephone number */
407
408         if(aliasing)
409         {
410                 if(cep->direction == DIR_IN)
411                         snprintf(buffer, sizeof(buffer), "%s", get_alias(cep->real_phone_incoming));
412                 else
413                         snprintf(buffer, sizeof(buffer), "%s", get_alias(cep->remote_phone_dialout));
414         }
415         else
416         {
417                 if(cep->direction == DIR_IN)
418                         snprintf(buffer, sizeof(buffer), "%s/%s", cep->name, cep->real_phone_incoming);
419                 else
420                         snprintf(buffer, sizeof(buffer), "%s/%s", cep->name, cep->remote_phone_dialout);        
421         }
422                 
423         buffer[H_IFN - H_TELN - 1] = '\0';
424
425         mvwprintw(upper_w, CHPOS(cep), H_TELN, "%s", buffer);
426
427         /* interface */
428         
429         mvwprintw(upper_w, CHPOS(cep), H_IFN, "%s%d ",
430                         bdrivername(cep->usrdevicename), cep->usrdeviceunit);
431         
432         mvwprintw(upper_w, CHPOS(cep), H_IO,
433                 cep->direction == DIR_OUT ? "out" : "in");
434
435         mvwprintw(upper_w, CHPOS(cep), H_OUT,    "-");
436         mvwprintw(upper_w, CHPOS(cep), H_OUTBPS, "-");
437         mvwprintw(upper_w, CHPOS(cep), H_IN,     "-");
438         mvwprintw(upper_w, CHPOS(cep), H_INBPS,  "-");
439
440         if(do_bell)
441                 display_bell();
442         
443         wrefresh(upper_w);
444 }
445
446 /*---------------------------------------------------------------------------*
447  *      erase line at disconnect time
448  *---------------------------------------------------------------------------*/
449 void
450 display_disconnect(cfg_entry_t *cep)
451 {
452         wmove(upper_w, CHPOS(cep),
453                  H_TELN);
454         wclrtoeol(upper_w);
455         wrefresh(upper_w);
456
457         if(do_bell)
458                 display_bell();
459         
460 }
461
462 /*---------------------------------------------------------------------------*
463  *      display interface up/down information
464  *---------------------------------------------------------------------------*/
465 void
466 display_updown(cfg_entry_t *cep, int updown)
467 {
468         if(updown)
469                 wstandend(mid_w);
470         else
471                 wstandout(mid_w);
472
473         mvwprintw(mid_w, 0, cep->fs_position, "%s%d ",
474                         bdrivername(cep->usrdevicename), cep->usrdeviceunit);
475
476         wstandend(mid_w);
477         wrefresh(mid_w);
478 }
479
480 /*---------------------------------------------------------------------------*
481  *      display interface up/down information
482  *---------------------------------------------------------------------------*/
483 void
484 display_l12stat(int controller, int layer, int state)
485 {
486         if(controller > ncontroller)
487                 return;
488         if(!(layer == 1 || layer == 2))
489                 return;
490
491         if(state)
492                 wstandout(upper_w);
493         else
494                 wstandend(upper_w);
495
496         if(layer == 1)
497         {
498                 mvwprintw(upper_w, (controller*2)+1, H_TEI+1, "1");
499                 if(!state)
500                         mvwprintw(upper_w, (controller*2)+1, H_TEI+2, "2");
501         }
502         else if(layer == 2)
503         {
504                 mvwprintw(upper_w, (controller*2)+1, H_TEI+2, "2");
505                 if(state)
506                         mvwprintw(upper_w, (controller*2)+1, H_TEI+1, "1");
507         }
508
509         wstandend(upper_w);
510         wrefresh(upper_w);
511 }
512
513 /*---------------------------------------------------------------------------*
514  *      display TEI
515  *---------------------------------------------------------------------------*/
516 void
517 display_tei(int controller, int tei)
518 {
519         if(controller > ncontroller)
520                 return;
521
522         if(tei == -1)
523                 mvwprintw(upper_w, controller*2, H_TEI, "---");
524         else
525                 mvwprintw(upper_w, controller*2, H_TEI, "%3d", tei);
526
527         wrefresh(upper_w);
528 }
529
530 /*---------------------------------------------------------------------------*
531  *      display bell :-)
532  *---------------------------------------------------------------------------*/
533 void
534 display_bell(void)
535 {
536         static char bell[1] = { 0x07 };
537         write(STDOUT_FILENO, &bell[0], 1);
538 }
539
540 /*---------------------------------------------------------------------------*
541  *      display channel information for shutdown
542  *---------------------------------------------------------------------------*/
543 void
544 display_chans(void)
545 {
546         char buffer[80];
547         int i;
548         int cnt = 0;
549         WINDOW *chan_w;
550         int nlines, ncols, pos_x, pos_y;
551         fd_set set;
552         struct timeval timeout;
553         cfg_entry_t *cep = NULL;
554
555         /* need this later to close the connection */
556         struct ctlr_chan {
557                 int cntl;
558                 int chn;
559         } *cc = NULL;
560
561         for (i = 0; i < ncontroller; i++)
562         {
563                 if((get_controller_state(i)) != CTRL_UP)
564                         continue;
565                 if((ret_channel_state(i, CHAN_B1)) == CHAN_RUN)
566                         cnt++;
567                 if((ret_channel_state(i, CHAN_B2)) == CHAN_RUN)
568                         cnt++;
569         }
570
571         if(cnt > 0)
572         {
573                 if ((cc = (struct ctlr_chan *)malloc (cnt *
574                         sizeof (struct ctlr_chan))) == NULL)
575                 {
576                         return;
577                 }
578                 nlines = cnt + 4;
579                 ncols = 60;
580         }
581         else
582         {
583                 nlines = 5;
584                 ncols = 22;             
585         }
586
587         pos_y = WMENU_POSLN + 4;
588         pos_x = WMENU_POSCO + 10;
589
590         /* create a new window in the lower screen area */
591         
592         if((chan_w = newwin(nlines, ncols, pos_y, pos_x )) == NULL)
593         {
594                 log(LL_WRN, "ERROR, curses init channel window!");
595                 if (cnt > 0)
596                         free(cc);
597                 return;
598         }
599
600         /* create a border around the window */
601         
602         box(chan_w, '|', '-');
603
604         /* add a title */
605         
606         wstandout(chan_w);
607         mvwaddstr(chan_w, 0, (ncols / 2) - (strlen("Channels") / 2), "Channels");
608         wstandend(chan_w);      
609
610         /* no active channels */
611         if (cnt == 0)
612         {
613                 mvwaddstr(chan_w, 2, 2, "No active channels");
614                 wrefresh(chan_w);
615                 sleep(1);
616
617                 /* delete the channels window */
618
619                 delwin(chan_w);
620                 return;
621         }
622
623         nlines = 2;
624         ncols = 1;
625
626         for (i = 0; i < ncontroller; i++)
627         {
628                 if((get_controller_state(i)) != CTRL_UP)
629                         continue;
630
631                 if((ret_channel_state(i, CHAN_B1)) == CHAN_RUN)
632                 {
633                         snprintf(buffer, sizeof(buffer), "%d - Controller %d channel %s", ncols, i, "B1");
634                         mvwaddstr(chan_w, nlines, 2, buffer);
635                         cc[ncols - 1].cntl = i;
636                         cc[ncols - 1].chn = CHAN_B1;
637                         nlines++;
638                         ncols++;
639                 }
640                 if((ret_channel_state(i, CHAN_B2)) == CHAN_RUN)
641                 {
642                         snprintf(buffer, sizeof(buffer), "%d - Controller %d channel %s", ncols, i, "B2");
643                         mvwaddstr(chan_w, nlines, 2, buffer);
644                         cc[ncols - 1].cntl = i;
645                         cc[ncols - 1].chn = CHAN_B2;
646                         nlines++;
647                         ncols++;
648                 }
649         }
650
651         for(;;)
652         {
653                 wrefresh(chan_w);
654
655                 FD_ZERO(&set);
656                 FD_SET(STDIN_FILENO, &set);
657                 timeout.tv_sec = WMTIMEOUT;
658                 timeout.tv_usec = 0;
659
660                 /* if no char is available within timeout, exit menu*/
661                 
662                 if((select(STDIN_FILENO + 1, &set, NULL, NULL, &timeout)) <= 0)
663                         break;
664                 
665                 ncols = wgetch(chan_w);
666
667                 if (!(isdigit(ncols)))
668                 {
669                         display_bell();
670                         continue;
671                 }
672
673                 nlines = ncols - '0';
674
675                 if ((nlines == 0) || (nlines > cnt))
676                 {
677                         display_bell();
678                         continue;
679                 }
680
681                 if((cep = get_cep_by_cc(cc[nlines-1].cntl, cc[nlines-1].chn))
682                         != NULL)
683                 {
684                         log(LL_CHD, "%05d %s manual disconnect (fullscreen menu)", cep->cdid, cep->name);
685                         cep->hangup = 1;
686                         break;
687                 }
688         }
689
690         free(cc);
691
692         /* delete the channels window */
693
694         delwin(chan_w);
695 }
696
697 /*---------------------------------------------------------------------------*
698  *      display card type information
699  *---------------------------------------------------------------------------*/
700 static void
701 display_cards(void)
702 {
703         WINDOW *chan_w;
704         int nlines, ncols, pos_x, pos_y;
705         fd_set set;
706         struct timeval timeout;
707         int i;
708         
709         nlines = 6+ncontroller;
710         ncols = 60;
711         pos_y = WMENU_POSLN;
712         pos_x = WMENU_POSCO;
713
714         /* create a new window in the lower screen area */
715         
716         if((chan_w = newwin(nlines, ncols, pos_y, pos_x )) == NULL)
717         {
718                 log(LL_WRN, "ERROR, curses init channel window!");
719                 return;
720         }
721
722         /* create a border around the window */
723         
724         box(chan_w, '|', '-');
725
726         /* add a title */
727         
728         wstandout(chan_w);
729         mvwaddstr(chan_w, 0, (ncols / 2) - (strlen("Cards") / 2), "Cards");
730         wstandend(chan_w);
731
732         mvwprintw(chan_w, 2, 2, "ctrl description");
733         mvwprintw(chan_w, 3, 2, "---- ----------------------------------------------");
734         for (i = 0; i < ncontroller; i++)
735         {
736                 mvwprintw(chan_w, 4+i, 2, " #%d  %s", i,
737                         name_of_controller(isdn_ctrl_tab[i].ctrl_type,
738                         isdn_ctrl_tab[i].card_type));
739         }
740
741         wrefresh(chan_w);
742         
743         FD_ZERO(&set);
744         FD_SET(STDIN_FILENO, &set);
745         timeout.tv_sec = WMTIMEOUT*2;
746         timeout.tv_usec = 0;
747
748         if((select(STDIN_FILENO + 1, &set, NULL, NULL, &timeout)) <= 0)
749         {
750                 delwin(chan_w);
751                 return;
752         }
753
754         wgetch(chan_w);
755         delwin(chan_w);
756 }
757
758 /*---------------------------------------------------------------------------*
759  *      display budget info
760  *---------------------------------------------------------------------------*/
761 static void
762 display_budget(void)
763 {
764         WINDOW *bud_w;
765         int nlines, ncols, pos_x, pos_y;
766         fd_set set;
767         struct timeval timeout;
768         int i, j;
769         cfg_entry_t *cep;
770         time_t now;
771         double uptime;
772         int minutes;
773         int hours;
774         int days;
775         
776         nlines = 0;
777         ncols = 73;
778         pos_y = WMENU_POSLN;
779         pos_x = WMENU_POSCO-3;
780
781         for(i=0, j=0; i < nentries; i++)        /* walk thru all entries */
782         {
783                 cep = &cfg_entry_tab[i];        /* get ptr to entry */
784
785                 if(cep->budget_callbackperiod && cep->budget_callbackncalls)
786                         nlines++;
787                 if(cep->budget_calloutperiod && cep->budget_calloutncalls)
788                         nlines++;
789         }
790
791         if(nlines == 0)
792                 return;
793                 
794         nlines += 6;    
795
796         /* create a new window in the lower screen area */
797         
798         if((bud_w = newwin(nlines, ncols, pos_y, pos_x )) == NULL)
799         {
800                 log(LL_WRN, "ERROR, curses init budget window!");
801                 return;
802         }
803
804         now = time(NULL);
805         uptime = difftime(now, starttime);
806
807         minutes = (time_t) (uptime / 60) % 60;
808         hours = (time_t) (uptime / (60*60)) % (60*60);
809         days = (time_t) (uptime / (60*60*24)) % (60*60*24);     
810
811         uptime = uptime / (60*60);
812         
813         /* create a border around the window */
814         
815         box(bud_w, '|', '-');
816
817         /* add a title */
818         
819         wstandout(bud_w);
820         mvwaddstr(bud_w, 0, (ncols / 2) - (strlen("Budget") / 2), "Budget");
821         wstandend(bud_w);
822
823         mvwprintw(bud_w, 1, 2, "isdnd uptime: %d %s - %d %s - %d %s",
824                 days,
825                 days == 1 ? "day" : "days",
826                 hours,
827                 hours == 1 ? "hour" : "hours",
828                 minutes,
829                 minutes == 1 ? "minute" : "minutes");
830                 
831         mvwprintw(bud_w, 2, 2, "name     t period rest   ncall rest  rqsts /hr  rdone /hr  rrjct /hr ");
832         mvwprintw(bud_w, 3, 2, "-------- - ------ ------ ----- ----- ----- ---- ----- ---- ----- ----");
833
834         for(i=0, j=4; i < nentries; i++)        /* walk thru all entries */
835         {
836                 cep = &cfg_entry_tab[i];                /* get ptr to enry */
837
838                 if(cep->budget_calloutperiod && cep->budget_calloutncalls)
839                 {
840                         mvwprintw(bud_w, j, 2, "%-8s %c %-6d %-6ld %-5d %-5d %-5d %-4.1f %-5d %-4.1f %-5d %-4.1f",
841                                 cep->name,
842                                 'o',
843                                 cep->budget_calloutperiod,
844                                 (long)(cep->budget_calloutperiod_time - now),
845                                 cep->budget_calloutncalls,
846                                 cep->budget_calloutncalls_cnt,
847                                 cep->budget_callout_req,
848                                 (double)cep->budget_callout_req / uptime,
849                                 cep->budget_callout_done,
850                                 (double)cep->budget_callout_done / uptime,
851                                 cep->budget_callout_rej,
852                                 (double)cep->budget_callout_rej / uptime);
853                         j++;
854                 }
855                 if(cep->budget_callbackperiod && cep->budget_callbackncalls)
856                 {
857                         mvwprintw(bud_w, j, 2, "%-8s %c %-6d %-6ld %-5d %-5d %-5d %-4.1f %-5d %-4.1f %-5d %-4.1f",
858                                 (cep->budget_calloutperiod && cep->budget_calloutncalls) ? "" : cep->name,
859                                 'b',
860                                 cep->budget_callbackperiod,
861                                 (long)(cep->budget_callbackperiod_time - now),
862                                 cep->budget_callbackncalls,
863                                 cep->budget_callbackncalls_cnt,
864                                 cep->budget_callback_req,
865                                 (double)cep->budget_callback_req / uptime,
866                                 cep->budget_callback_done,
867                                 (double)cep->budget_callback_done / uptime,
868                                 cep->budget_callback_rej,
869                                 (double)cep->budget_callback_rej / uptime);
870                         j++;
871                 }
872         }
873
874         wrefresh(bud_w);
875         
876         FD_ZERO(&set);
877         FD_SET(STDIN_FILENO, &set);
878         timeout.tv_sec = WMTIMEOUT*3;
879         timeout.tv_usec = 0;
880
881         if((select(STDIN_FILENO + 1, &set, NULL, NULL, &timeout)) <= 0)
882         {
883                 delwin(bud_w);
884                 return;
885         }
886
887         wgetch(bud_w);
888         delwin(bud_w);
889 }
890
891 #endif
892
893 /* EOF */