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