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