Initial import from FreeBSD RELENG_4:
[dragonfly.git] / usr.sbin / i4b / isdnmonitor / curses.c
1 /*
2  * Copyright (c) 1999 Hellmuth Michaelis. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  *
25  *---------------------------------------------------------------------------
26  *
27  *      i4b daemon - curses fullscreen output
28  *      -------------------------------------
29  *
30  *      $Id: curses.c,v 1.10 1999/12/13 21:25:25 hm Exp $ 
31  *
32  * $FreeBSD: src/usr.sbin/i4b/isdnmonitor/curses.c,v 1.1.2.1 2001/08/01 17:45:06 obrien Exp $
33  *
34  *      last edit-date: [Mon Dec 13 21:51:47 1999]
35  *
36  *---------------------------------------------------------------------------*/
37
38 #include "monprivate.h"
39
40 #ifndef WIN32
41
42 static void display_bell(void);
43 static void display_chans(void);
44
45 /*---------------------------------------------------------------------------*
46  *      program exit
47  *---------------------------------------------------------------------------*/
48 void
49 do_exit(int exitval)
50 {
51         if(curses_ready)
52                 endwin();
53         exit(exitval);
54 }
55
56 /*---------------------------------------------------------------------------*
57  *      init curses fullscreen display
58  *---------------------------------------------------------------------------*/
59 void
60 init_screen(void)
61 {
62         char buffer[512];
63         int uheight, lheight;
64         int i, j;
65         
66         initscr();                      /* curses init */
67         
68         if((COLS < 80) || (LINES < 24))
69         {
70                 endwin();
71                 fprintf(stderr, "ERROR, minimal screensize must be 80x24, is %dx%d, terminating!",COLS, LINES);
72                 exit(1);
73         }               
74
75         noecho();
76         raw();
77
78         uheight = nctrl * 2; /* cards * b-channels */
79         lheight = LINES - uheight - 6 + 1; /* rest of display */
80         
81         if((upper_w = newwin(uheight, COLS, UPPER_B, 0)) == NULL)
82         {
83                 endwin();
84                 fprintf(stderr, "ERROR, curses init upper window, terminating!");
85                 exit(1);
86         }
87
88         if((mid_w = newwin(1, COLS, UPPER_B+uheight+1, 0)) == NULL)
89         {
90                 endwin();
91                 fprintf(stderr, "ERROR, curses init mid window, terminating!");
92                 exit(1);
93         }
94
95         if((lower_w = newwin(lheight, COLS, UPPER_B+uheight+3, 0)) == NULL)
96         {
97                 endwin();
98                 fprintf(stderr, "ERROR, curses init lower window, LINES = %d, lheight = %d, uheight = %d, terminating!", LINES, lheight, uheight);
99                 exit(1);
100         }
101         
102         scrollok(lower_w, 1);
103
104         sprintf(buffer, "----- isdn controller channel state ------------- isdnmonitor %02d.%02d.%d -", VERSION, REL, STEP);
105
106         while(strlen(buffer) < COLS)
107                 strcat(buffer, "-");    
108
109         move(0, 0);
110         standout();
111         addstr(buffer);
112         standend();
113         
114         move(1, 0);
115         /*      01234567890123456789012345678901234567890123456789012345678901234567890123456789 */
116         addstr("c tei b remote                 iface  dir outbytes   obps inbytes    ibps  units");
117         
118         if(hostname)
119                 sprintf(buffer, "----- isdn userland interface state ------------- %s:%d -", hostname, portno);
120         else
121                 sprintf(buffer, "----- isdn userland interface state ------------- %s -", sockpath);
122                 
123         while(strlen(buffer) < COLS)
124                 strcat(buffer, "-");    
125
126         move(uheight+2, 0);
127         standout();
128         addstr(buffer);
129         standend();
130
131         sprintf(buffer, "----- isdnd logfile display --------------------------------------------------");
132         while(strlen(buffer) < COLS)
133                 strcat(buffer, "-");    
134
135         move(uheight+4, 0);
136         standout();
137         addstr(buffer);
138         standend();
139         
140         refresh();
141
142         for(i=0, j=0; i <= nctrl; i++, j+=2)
143         {
144                 mvwprintw(upper_w, j,   H_CNTL, "%d --- 1 ", i);  /*TEI*/
145                 mvwprintw(upper_w, j+1, H_CNTL, "  L12 2 ");
146         }
147         wrefresh(upper_w);
148
149 #ifdef NOTDEF
150         for(i=0, j=0; i < nentries; i++)        /* walk thru all entries */
151         {
152                 p = &cfg_entry_tab[i];          /* get ptr to enry */
153
154                 mvwprintw(mid_w, 0, j, "%s%d ", bdrivername(p->usrdevicename), p->usrdeviceunit);
155
156                 p->fs_position = j;
157
158                 j += ((strlen(bdrivername(p->usrdevicename)) + (p->usrdeviceunit > 9 ? 2 : 1) + 1));
159         }
160 #else
161         mvwprintw(mid_w, 0, 0, "%s", devbuf);
162 #endif
163         wrefresh(mid_w);
164
165         wmove(lower_w, 0, 0);
166         wrefresh(lower_w);
167
168         curses_ready = 1;
169 }
170
171 /*---------------------------------------------------------------------------*
172  *      display the charge in units
173  *---------------------------------------------------------------------------*/
174 void
175 display_charge(int pos, int charge)
176 {
177         mvwprintw(upper_w, pos, H_UNITS, "%d", charge);
178         wclrtoeol(upper_w);     
179         wrefresh(upper_w);
180 }
181
182 /*---------------------------------------------------------------------------*
183  *      display the calculated charge in units
184  *---------------------------------------------------------------------------*/
185 void
186 display_ccharge(int pos, int units)
187 {
188         mvwprintw(upper_w, pos, H_UNITS, "(%d)", units);
189         wclrtoeol(upper_w);     
190         wrefresh(upper_w);
191 }
192
193 /*---------------------------------------------------------------------------*
194  *      display accounting information
195  *---------------------------------------------------------------------------*/
196 void
197 display_acct(int pos, int obyte, int obps, int ibyte, int ibps)
198 {
199         mvwprintw(upper_w, pos, H_OUT,    "%-10d", obyte);
200         mvwprintw(upper_w, pos, H_OUTBPS, "%-4d",  obps);
201         mvwprintw(upper_w, pos, H_IN,     "%-10d", ibyte);
202         mvwprintw(upper_w, pos, H_INBPS,  "%-4d",  ibps);
203         wrefresh(upper_w);
204 }
205
206 /*---------------------------------------------------------------------------*
207  *      erase line at disconnect time
208  *---------------------------------------------------------------------------*/
209 void
210 display_disconnect(int pos)
211 {
212         wmove(upper_w, pos, H_TELN);
213         wclrtoeol(upper_w);
214         wrefresh(upper_w);
215
216         if(do_bell)
217                 display_bell();
218 }
219
220 /*---------------------------------------------------------------------------*
221  *      display interface up/down information
222  *---------------------------------------------------------------------------*/
223 void
224 display_updown(int pos, int updown, char *device)
225 {
226         if(updown)
227                 wstandend(mid_w);
228         else
229                 wstandout(mid_w);
230
231         mvwprintw(mid_w, 0, pos, "%s ", device);
232
233         wstandend(mid_w);
234         wrefresh(mid_w);
235 }
236
237 /*---------------------------------------------------------------------------*
238  *      display interface up/down information
239  *---------------------------------------------------------------------------*/
240 void
241 display_l12stat(int controller, int layer, int state)
242 {
243         if(controller > nctrl)
244                 return;
245                 
246         if(!(layer == 1 || layer == 2))
247                 return;
248
249         if(state)
250                 wstandout(upper_w);
251         else
252                 wstandend(upper_w);
253
254         if(layer == 1)
255         {
256                 mvwprintw(upper_w, (controller*2)+1, H_TEI+1, "1");
257
258                 if(!state)
259                         mvwprintw(upper_w, (controller*2)+1, H_TEI+2, "2");
260         }
261         else if(layer == 2)
262         {
263                 mvwprintw(upper_w, (controller*2)+1, H_TEI+2, "2");
264                 if(state)
265                         mvwprintw(upper_w, (controller*2)+1, H_TEI+1, "1");
266         }
267
268         wstandend(upper_w);
269         wrefresh(upper_w);
270 }
271
272 /*---------------------------------------------------------------------------*
273  *      display TEI
274  *---------------------------------------------------------------------------*/
275 void
276 display_tei(int controller, int tei)
277 {
278         if(controller > nctrl)
279                 return;
280
281         if(tei == -1)
282                 mvwprintw(upper_w, controller*2, H_TEI, "---");
283         else
284                 mvwprintw(upper_w, controller*2, H_TEI, "%3d", tei);
285
286         wrefresh(upper_w);
287 }
288
289 /*---------------------------------------------------------------------------*
290  *      display bell :-)
291  *---------------------------------------------------------------------------*/
292 static void
293 display_bell(void)
294 {
295         static char bell[1] = { 0x07 };
296         write(STDOUT_FILENO, &bell[0], 1);
297 }
298
299 /*---------------------------------------------------------------------------*
300  *      curses menu for fullscreen command mode
301  *---------------------------------------------------------------------------*/
302 void
303 do_menu(void)
304 {
305         static char *menu[WMITEMS] =
306         {
307                 "1 - (D)isplay refresh",
308                 "2 - (H)angup (choose a channel)",
309                 "3 - (R)eread config file",             
310                 "4 - (Q)uit the program",               
311         };
312
313         WINDOW *menu_w;
314         int c;
315         int mpos;
316         fd_set set;
317         struct timeval timeout;
318
319         /* create a new window in the lower screen area */
320         
321         if((menu_w = newwin(WMENU_HGT, WMENU_LEN, WMENU_POSLN, WMENU_POSCO )) == NULL)
322         {
323                 return;
324         }
325
326         /* create a border around the window */
327         
328         box(menu_w, '|', '-');
329
330         /* add a title */
331         
332         wstandout(menu_w);
333         mvwaddstr(menu_w, 0, (WMENU_LEN / 2) - (strlen(WMENU_TITLE) / 2), WMENU_TITLE);
334         wstandend(menu_w);      
335
336         /* fill the window with the menu options */
337         
338         for(mpos=0; mpos <= (WMITEMS-1); mpos++)
339                 mvwaddstr(menu_w, mpos + 2, 2, menu[mpos]);
340
341         /* highlight the first menu option */
342         
343         mpos = 0;
344         wstandout(menu_w);
345         mvwaddstr(menu_w, mpos + 2, 2, menu[mpos]);
346         wstandend(menu_w);
347
348         /* input loop */
349         
350         for(;;)
351         {
352                 wrefresh(menu_w);
353
354                 FD_ZERO(&set);
355                 FD_SET(STDIN_FILENO, &set);
356                 timeout.tv_sec = WMTIMEOUT;
357                 timeout.tv_usec = 0;
358
359                 /* if no char is available within timeout, exit menu*/
360                 
361                 if((select(STDIN_FILENO + 1, &set, NULL, NULL, &timeout)) <= 0)
362                         goto mexit;
363                 
364                 c = wgetch(menu_w);
365
366                 switch(c)
367                 {
368                         case ' ':
369                         case '\t':      /* hilite next option */
370                                 mvwaddstr(menu_w, mpos + 2, 2, menu[mpos]);
371                                 mpos++;
372                                 if(mpos >= WMITEMS)
373                                         mpos = 0;
374                                 wstandout(menu_w);
375                                 mvwaddstr(menu_w, mpos + 2, 2, menu[mpos]);
376                                 wstandend(menu_w);
377                                 break;
378
379                         case ('0'+WREFRESH+1):  /* display refresh */
380                         case 'D':
381                         case 'd':
382                                 wrefresh(curscr);
383                                 goto mexit;
384
385                         case ('0'+WQUIT+1):     /* quit program */
386                         case 'Q':
387                         case 'q':
388                                 do_exit(0);
389                                 goto mexit;
390
391
392                         case ('0'+WHANGUP+1):   /* hangup connection */
393                         case 'H':
394                         case 'h':
395                                 display_chans();
396                                 goto mexit;
397
398                         case ('0'+WREREAD+1):   /* reread config file */
399                         case 'R':
400                         case 'r':
401                                 reread();
402                                 goto mexit;
403
404                         case '\n':
405                         case '\r':      /* exec highlighted option */
406                                 switch(mpos)
407                                 {
408                                         case WREFRESH:
409                                                 wrefresh(curscr);
410                                                 break;
411
412                                         case WQUIT:
413                                                 do_exit(0);
414                                                 break;
415
416                                         case WHANGUP:
417                                                 display_chans();
418                                                 break;
419
420                                         case WREREAD:
421                                                 reread();
422                                                 break;
423                                 }
424                                 goto mexit;
425                                 break;
426                 
427                         default:
428                                 goto mexit;
429                                 break;
430                 }
431         }
432
433 mexit:
434         /* delete the menu window */
435
436         delwin(menu_w);
437
438         /* re-display the original lower window contents */
439         
440         touchwin(lower_w);
441         wrefresh(lower_w);
442 }
443
444 /*---------------------------------------------------------------------------*
445  *      display connect information
446  *---------------------------------------------------------------------------*/
447 void
448 display_connect(int pos, int dir, char *name, char *remtel, char *dev)
449 {
450         char buffer[256];
451
452         /* remote telephone number */
453
454         sprintf(buffer, "%s/%s", name, remtel);
455                 
456         buffer[H_IFN - H_TELN - 1] = '\0';
457
458         mvwprintw(upper_w, pos, H_TELN, "%s", buffer);
459
460         /* interface */
461         
462         mvwprintw(upper_w, pos, H_IFN, "%s ", dev);
463         
464         mvwprintw(upper_w, pos, H_IO, dir ? "out" : "in");
465
466         mvwprintw(upper_w, pos, H_OUT,    "-");
467         mvwprintw(upper_w, pos, H_OUTBPS, "-");
468         mvwprintw(upper_w, pos, H_IN,     "-");
469         mvwprintw(upper_w, pos, H_INBPS,  "-");
470
471         if(do_bell)
472                 display_bell();
473         
474         wrefresh(upper_w);
475 }
476
477 /*---------------------------------------------------------------------------*
478  *      display channel information for shutdown
479  *---------------------------------------------------------------------------*/
480 static void
481 display_chans(void)
482 {
483         char buffer[80];
484         int i;
485         int cnt = 0;
486         WINDOW *chan_w;
487         int nlines, ncols, pos_x, pos_y;
488         fd_set set;
489         struct timeval timeout;
490
491         /* need this later to close the connection */
492         struct ctlr_chan {
493                 int cntl;
494                 int chn;
495         } *cc = NULL;
496
497         for(i = 0; i < nctrl; i++)
498         {
499                 if(remstate[i].ch1state)
500                         cnt++;
501                 if(remstate[i].ch2state)
502                         cnt++;
503         }
504
505         if(cnt > 0)
506         {
507                 if ((cc = (struct ctlr_chan *)malloc (cnt *
508                         sizeof (struct ctlr_chan))) == NULL)
509                 {
510                         return;
511                 }
512                 nlines = cnt + 4;
513                 ncols = 60;
514         }
515         else
516         {
517                 nlines = 5;
518                 ncols = 22;             
519         }
520
521         pos_y = WMENU_POSLN + 4;
522         pos_x = WMENU_POSCO + 10;
523
524         /* create a new window in the lower screen area */
525         
526         if((chan_w = newwin(nlines, ncols, pos_y, pos_x )) == NULL)
527         {
528                 if (cnt > 0)
529                         free(cc);
530                 return;
531         }
532
533         /* create a border around the window */
534         
535         box(chan_w, '|', '-');
536
537         /* add a title */
538         
539         wstandout(chan_w);
540         mvwaddstr(chan_w, 0, (ncols / 2) - (strlen("Channels") / 2), "Channels");
541         wstandend(chan_w);      
542
543         /* no active channels */
544         if (cnt == 0)
545         {
546                 mvwaddstr(chan_w, 2, 2, "No active channels");
547                 wrefresh(chan_w);
548                 sleep(1);
549
550                 /* delete the channels window */
551
552                 delwin(chan_w);
553                 return;
554         }
555
556         nlines = 2;
557         ncols = 1;
558
559         for (i = 0; i < nctrl; i++)
560         {
561                 if(remstate[i].ch1state)
562                 {
563                         sprintf(buffer, "%d - Controller %d channel %s", ncols, i, "B1");
564                         mvwaddstr(chan_w, nlines, 2, buffer);
565                         cc[ncols - 1].cntl = i;
566                         cc[ncols - 1].chn = CHAN_B1;
567                         nlines++;
568                         ncols++;
569                 }
570                 if(remstate[i].ch2state)                
571                 {
572                         sprintf(buffer, "%d - Controller %d channel %s", ncols, i, "B2");
573                         mvwaddstr(chan_w, nlines, 2, buffer);
574                         cc[ncols - 1].cntl = i;
575                         cc[ncols - 1].chn = CHAN_B2;
576                         nlines++;
577                         ncols++;
578                 }
579         }
580
581         for(;;)
582         {
583                 wrefresh(chan_w);
584
585                 FD_ZERO(&set);
586                 FD_SET(STDIN_FILENO, &set);
587                 timeout.tv_sec = WMTIMEOUT;
588                 timeout.tv_usec = 0;
589
590                 /* if no char is available within timeout, exit menu*/
591                 
592                 if((select(STDIN_FILENO + 1, &set, NULL, NULL, &timeout)) <= 0)
593                         break;
594                 
595                 ncols = wgetch(chan_w);
596
597                 if (!(isdigit(ncols)))
598                 {
599                         display_bell();
600                         continue;
601                 }
602
603                 nlines = ncols - '0';
604
605                 if ((nlines == 0) || (nlines > cnt))
606                 {
607                         display_bell();
608                         continue;
609                 }
610
611                 hangup(cc[nlines-1].cntl, cc[nlines-1].chn);
612                 break;
613         }
614
615         free(cc);
616
617         /* delete the channels window */
618
619         delwin(chan_w);
620 }
621
622 #endif /* !WIN32*/
623
624 /* EOF */