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