]> git.decadent.org.uk Git - ap-utils.git/blob - lib/stat.c
56f46953428170f43f1eff1a0dc935e8cde0533d
[ap-utils.git] / lib / stat.c
1 /*
2  *      stat.c from Access Point SNMP Utils for Linux
3  *
4  * Copyright (c) 2002 Roman Festchook <roma at polesye dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License Version 2 from
8  * June 1991 as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  */
20 #include <unistd.h>
21 #include <stdlib.h>
22 #include <fcntl.h>
23 #include <signal.h>
24 #include <string.h>
25 #include <sys/time.h>
26 #include <sys/wait.h>
27 #include "ap-utils.h"
28 #include "ap-curses.h"
29
30 #define QHELP _("Q - quit to menu. Other key - force update.")
31 #define SELECT _("select() function error. Press any key.")
32
33 extern WINDOW *main_sub;
34 extern short ap_type;
35
36 void EthStat()
37 {
38     struct EthernetRxStatistics *EthRxStat = NULL;
39     struct EthernetTxStatistics *EthTxStat = NULL;
40
41     char EthRx[] = { 0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x01,
42         0x07, 0x01, 0x00
43     };
44
45     char EthTx[] = { 0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x01,
46         0x07, 0x02, 0x00
47     };
48     char message[1024];
49     int j;
50     varbind varbinds[2];
51     fd_set rds;
52     struct timeval timeout;
53
54     if (ap_type == ATMEL12350) {
55         EthRx[5] = 0xE0;
56         EthRx[6] = 0x3E;
57         EthTx[5] = 0xE0;
58         EthTx[6] = 0x3E;
59     }
60     
61     print_title(_("Ethernet Statistics"));
62     print_help(QHELP);
63     noecho();
64
65     varbinds[0].oid = EthRx;
66     varbinds[0].len_oid = sizeof(EthRx);
67     varbinds[1].oid = EthTx;
68     varbinds[1].len_oid = sizeof(EthTx);
69
70     while (1) {
71 //      varbinds[0].value = EthTx;
72         varbinds[0].len_val = 0;
73         varbinds[0].type = NULL_VALUE;
74 //      varbinds[1].value = EthTx;
75         varbinds[1].len_val = 0;
76         varbinds[1].type = NULL_VALUE;
77
78         if (snmp(varbinds, 2, GET) <= 0) {
79             print_helperr(ERR_RET);
80             getch();
81             goto quit;
82         }
83
84         if (varbinds[0].len_val == 64) {
85             if (EthRxStat)
86                 free(EthRxStat);
87             EthRxStat =
88                 (struct EthernetRxStatistics *) malloc(varbinds[0].
89                                                        len_val);
90             memcpy(EthRxStat, varbinds[0].value, varbinds[0].len_val);
91         } else {
92             print_helperr(_("EthRxStat packet error. Press any key."));
93             getch();
94             goto quit;
95         }
96
97         if (varbinds[1].len_val == 56) {
98             if (EthTxStat)
99                 free(EthTxStat);
100             EthTxStat =
101                 (struct EthernetTxStatistics *) malloc(varbinds[1].
102                                                        len_val);
103             memcpy(EthTxStat, varbinds[1].value, varbinds[1].len_val);
104         } else {
105             print_helperr(_("EthTxStat packet error. Press any key."));
106             getch();
107             goto quit;
108         }
109         mvwaddstr(main_sub, 1, 2, _("Received:"));
110         mvwaddstr(main_sub, 1, 30, _("Transmitted:"));
111         sprintf(message, "TotalBytes       %10u TotalBytes         %10u",
112                 swap4(EthRxStat->TotalBytesRx),
113                 swap4(EthTxStat->TotalBytesTx));
114         mvwaddstr(main_sub, 3, 2, message);
115         sprintf(message, "TotalPackets     %10u TotalPackets       %10u",
116                 swap4(EthRxStat->TotalPacketsRx),
117                 swap4(EthTxStat->TotalPacketsTx));
118         mvwaddstr(main_sub, 4, 2, message);
119         sprintf(message, "PacketCRCError   %10u PacketCRCError     %10u",
120                 swap4(EthRxStat->PacketCRCErrorRx),
121                 swap4(EthTxStat->PacketCRCErrorTx));
122         mvwaddstr(main_sub, 5, 2, message);
123         sprintf(message, "FalseCarrier     %10u",
124                 swap4(EthRxStat->FalseCarrierRx));
125         mvwaddstr(main_sub, 6, 2, message);
126
127         sprintf(message, "MulticastPacket  %10u MulticastPacket    %10u",
128                 swap4(EthRxStat->MulticastPacketRx),
129                 swap4(EthTxStat->MulticastPacketTx));
130         mvwaddstr(main_sub, 7, 2, message);
131         sprintf(message, "BroadcastPacket  %10u BroadcastPacket    %10u",
132                 swap4(EthRxStat->BroadcastPacketRx),
133                 swap4(EthTxStat->BroadcastPacketTx));
134         mvwaddstr(main_sub, 8, 2, message);
135
136         sprintf(message, "ControlFrames    %10u UnicastPacket      %10u",
137                 swap4(EthRxStat->ControlFramesRx),
138                 swap4(EthTxStat->UnicastPacketTx));
139         mvwaddstr(main_sub, 9, 2, message);
140         sprintf(message, "PauseFrames      %10u PauseFrames        %10u",
141                 swap4(EthRxStat->PauseFramesRx),
142                 swap4(EthTxStat->PauseFramesTx));
143         mvwaddstr(main_sub, 10, 2, message);
144
145         sprintf(message, "UnknownOPCode    %10u SingleDeferPacket  %10u",
146                 swap4(EthRxStat->UnknownOPCodeRx),
147                 swap4(EthTxStat->SingleDeferPacketTx));
148         mvwaddstr(main_sub, 11, 2, message);
149         sprintf(message, "AlignmentError   %10u MultiDeferPackets  %10u",
150                 swap4(EthRxStat->AlignmentRxError),
151                 swap4(EthTxStat->MultiDeferPacketsTx));
152         mvwaddstr(main_sub, 12, 2, message);
153         sprintf(message, "LengthOutOfRange %10u",
154                 swap4(EthRxStat->LengthOutOfRangeRx));
155         mvwaddstr(main_sub, 13, 2, message);
156         sprintf(message, "CodeError        %10u SingleCollisions   %10u",
157                 swap4(EthRxStat->CodeErrorRx),
158                 swap4(EthTxStat->SingleCollisionsTx));
159         mvwaddstr(main_sub, 14, 2, message);
160         sprintf(message, "TotalFragments   %10u MultiCollisions    %10u",
161                 swap4(EthRxStat->TotalFragmentsRx),
162                 swap4(EthTxStat->MultiCollisionsTx));
163         mvwaddstr(main_sub, 15, 2, message);
164         sprintf(message, "OversizePackets  %10u LateCollisions     %10u",
165                 swap4(EthRxStat->OversizePacketsRx),
166                 swap4(EthTxStat->LateCollisionsTx));
167         mvwaddstr(main_sub, 16, 2, message);
168         sprintf(message, "UndersizePackets %10u ExcessiveCollision %10u",
169                 swap4(EthRxStat->UndersizePacketsRx),
170                 swap4(EthTxStat->ExcessiveCollisionTx));
171         mvwaddstr(main_sub, 17, 2, message);
172         sprintf(message, "TotalJabber      %10u TotalCollisions    %10u",
173                 swap4(EthRxStat->TotalJabberRx),
174                 swap4(EthTxStat->TotalCollisionsTx));
175         mvwaddstr(main_sub, 18, 2, message);
176         wrefresh(main_sub);
177
178         timeout.tv_sec = 1;
179         timeout.tv_usec = 0;
180         FD_ZERO(&rds);
181         FD_SET(0, &rds);
182
183         /* wait up to timeout until anything is avail. for reading on stdin */
184         j = select(1, &rds, NULL, NULL, &timeout);
185
186         /* error occured */
187         if (j == -1) {
188             print_helperr(SELECT);
189             getch();
190             break;
191         }
192
193         /* not timed out => anything avail. for reading in &rds */
194         if (j != 0) {
195             j = getc(stdin);
196             if (j == 'q' || j == 'Q')
197                 break;
198
199         }
200
201         /* j = 0 => timeout => continue looping */
202     }
203
204   quit:
205     if (EthRxStat)
206         free(EthRxStat);
207     if (EthTxStat)
208         free(EthTxStat);
209
210     wclear(main_sub);
211     print_title("");
212     clear_main(0);
213     return;
214 }
215
216 void WirelessStat()
217 {
218     struct WirelessStatistics *WirelessStat = NULL;
219
220     char Wireless[] =
221         { 0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x03, 0x01,
222         0x00
223     };
224     char message[80];
225     int j;
226     varbind varbinds[1];
227     fd_set rds;
228     struct timeval timeout;
229
230     if (ap_type == ATMEL12350) {
231         Wireless[5] = 0xE0;
232         Wireless[6] = 0x3E;
233     }
234
235     print_title(_("Wireless Statistics"));
236     print_help(QHELP);
237     noecho();
238
239     varbinds[0].oid = Wireless;
240     varbinds[0].len_oid = sizeof(Wireless);
241
242     while (1) {
243         varbinds[0].value = Wireless;
244         varbinds[0].len_val = 0;
245         varbinds[0].type = NULL_VALUE;
246
247         if (snmp(varbinds, 1, GET) <= 0) {
248             print_helperr(ERR_RET);
249             getch();
250             goto quit;
251         }
252
253         if (varbinds[0].len_val == 88 || varbinds[0].len_val == 104) {
254             /*
255              * 88 ... using traditional ATMEL 12350 MIB
256              * 104 .. using functionally enhanced ATMEL 12350 MIB by VERNET
257              */
258             if (WirelessStat)
259                 free(WirelessStat);
260             WirelessStat =
261                 (struct WirelessStatistics *) malloc(varbinds[0].len_val);
262             memcpy(WirelessStat, varbinds[0].value, varbinds[0].len_val);
263         } else {
264             print_helperr
265                 (_("WirelessStat packet error. Press any key."));
266             getch();
267             goto quit;
268         }
269
270         sprintf(message,
271                 "UnicastPacketsTx   %10u UnicastPacketsRx   %10u",
272                 swap4(WirelessStat->UnicastTransmittedPackets),
273                 swap4(WirelessStat->UnicastReceivedPackets));
274         mvwaddstr(main_sub, 1, 1, message);
275         sprintf(message,
276                 "BroadcastPacketsTx %10u BroadcastPacketsRx %10u",
277                 swap4(WirelessStat->BroadcastTransmittedPackets),
278                 swap4(WirelessStat->BroadcastReceivedPackets));
279         mvwaddstr(main_sub, 2, 1, message);
280         sprintf(message,
281                 "MulticastPacketsTx %10u MulticastPacketsRx %10u",
282                 swap4(WirelessStat->MulticastTransmittedPackets),
283                 swap4(WirelessStat->MulticastReceivedPackets));
284         mvwaddstr(main_sub, 3, 1, message);
285         sprintf(message,
286                 "BeaconTx           %10u BeaconRx           %10u",
287                 swap4(WirelessStat->TransmittedBeacon),
288                 swap4(WirelessStat->ReceivedBeacon));
289         mvwaddstr(main_sub, 4, 1, message);
290         sprintf(message,
291                 "ACKTx              %10u ACKRx              %10u",
292                 swap4(WirelessStat->TransmittedACK),
293                 swap4(WirelessStat->ReceivedACK));
294         mvwaddstr(main_sub, 5, 1, message);
295         sprintf(message,
296                 "RTSTx              %10u RTSRx              %10u",
297                 swap4(WirelessStat->TransmittedRTS),
298                 swap4(WirelessStat->ReceivedRTS));
299         mvwaddstr(main_sub, 6, 1, message);
300         sprintf(message,
301                 "CTSTx              %10u CTSRx              %10u",
302                 swap4(WirelessStat->TransmittedCTS),
303                 swap4(WirelessStat->ReceivedCTS));
304         mvwaddstr(main_sub, 7, 1, message);
305         sprintf(message, "ACKFailure         %10u",
306                 swap4(WirelessStat->ACKFailure));
307         mvwaddstr(main_sub, 8, 1, message);
308         sprintf(message, "CTSFailure         %10u",
309                 swap4(WirelessStat->CTSFailure));
310         mvwaddstr(main_sub, 9, 1, message);
311         sprintf(message, "RetryPackets       %10u",
312                 swap4(WirelessStat->RetryPackets));
313         mvwaddstr(main_sub, 10, 1, message);
314         sprintf(message, "ReceivedDuplicate  %10u",
315                 swap4(WirelessStat->ReceivedDuplicate));
316         mvwaddstr(main_sub, 11, 1, message);
317         sprintf(message, "FailedPackets      %10u",
318                 swap4(WirelessStat->FailedPackets));
319         mvwaddstr(main_sub, 12, 1, message);
320         sprintf(message, "AgedPackets        %10u",
321                 swap4(WirelessStat->AgedPackets));
322         mvwaddstr(main_sub, 13, 1, message);
323         sprintf(message, "FCSError           %10u",
324                 swap4(WirelessStat->FCSError));
325         mvwaddstr(main_sub, 14, 1, message);
326         sprintf(message, "InvalidPLCP        %10u",
327                 swap4(WirelessStat->InvalidPLCP));
328         mvwaddstr(main_sub, 15, 1, message);
329         /* ATMEL12350 MIB 'VERNET' modification has in addition the following */
330         if (varbinds[0].len_val == 104) {
331             mvwaddstr(main_sub, 16, 1, "TransmittedPackets:");
332             sprintf(message, "* at 11 Mbps       %10u",
333                 swap4(WirelessStat->TransmittedPackets_11Mbps));
334             mvwaddstr(main_sub, 17, 1, message);
335             sprintf(message, "* at 5.5 Mbps      %10u",
336                 swap4(WirelessStat->TransmittedPackets_55Mbps));
337             mvwaddstr(main_sub, 18, 1, message);
338             sprintf(message, "* at 2 Mbps        %10u",
339                 swap4(WirelessStat->TransmittedPackets_2Mbps));
340             mvwaddstr(main_sub, 19, 1, message);
341             sprintf(message, "* at 1 Mbps        %10u",
342                 swap4(WirelessStat->TransmittedPackets_1Mbps));
343             mvwaddstr(main_sub, 20, 1, message);
344         }
345         wrefresh(main_sub);
346
347         timeout.tv_sec = 1;
348         timeout.tv_usec = 0;
349         FD_ZERO(&rds);
350         FD_SET(0, &rds);
351
352         /* wait up to timeout until anything is avail. for reading on stdin */
353         j = select(1, &rds, NULL, NULL, &timeout);
354
355         /* error occured */
356         if (j == -1) {
357             print_helperr(SELECT);
358             getch();
359             break;
360         }
361
362         /* not timed out => anything avail. for reading in &rds */
363         if (j != 0) {
364             j = getc(stdin);
365             if (j == 'q' || j == 'Q')
366                 break;
367
368         }
369
370         /* j = 0 => timeout => continue looping */
371     }
372
373   quit:
374     if (WirelessStat)
375         free(WirelessStat);
376     wclear(main_sub);
377     print_title("");
378     clear_main(0);
379 }
380
381
382 void nwn_wireless_stat()
383 {
384     char oid_dot11TransmittedFragmentCount[] =
385         { 0x2a, 0x86, 0x48, 0xce, 0x34, 0x02, 0x02, 0x01, 0x01, 0x01 };
386     char oid_dot11MulticastTransmittedFrameCount[] =
387         { 0x2a, 0x86, 0x48, 0xce, 0x34, 0x02, 0x02, 0x01, 0x02, 0x01 };
388     char oid_dot11FailedCount[] =
389         { 0x2a, 0x86, 0x48, 0xce, 0x34, 0x02, 0x02, 0x01, 0x03, 0x01 };
390     char oid_dot11RetryCount[] =
391         { 0x2a, 0x86, 0x48, 0xce, 0x34, 0x02, 0x02, 0x01, 0x04, 0x01 };
392     char oid_dot11MultipleRetryCount[] =
393         { 0x2a, 0x86, 0x48, 0xce, 0x34, 0x02, 0x02, 0x01, 0x05, 0x01 };
394     char oid_dot11FrameDuplicateCount[] =
395         { 0x2a, 0x86, 0x48, 0xce, 0x34, 0x02, 0x02, 0x01, 0x06, 0x01 };
396     char oid_dot11RTSSuccessCount[] =
397         { 0x2a, 0x86, 0x48, 0xce, 0x34, 0x02, 0x02, 0x01, 0x07, 0x01 };
398     char oid_dot11RTSFailureCount[] =
399         { 0x2a, 0x86, 0x48, 0xce, 0x34, 0x02, 0x02, 0x01, 0x08, 0x01 };
400     char oid_dot11ACKFailureCount[] =
401         { 0x2a, 0x86, 0x48, 0xce, 0x34, 0x02, 0x02, 0x01, 0x09, 0x01 };
402     char oid_dot11ReceivedFragmentCount[] =
403         { 0x2a, 0x86, 0x48, 0xce, 0x34, 0x02, 0x02, 0x01, 0x0a, 0x01 };
404     char oid_dot11MulticastReceivedFrameCount[] =
405         { 0x2a, 0x86, 0x48, 0xce, 0x34, 0x02, 0x02, 0x01, 0x0b, 0x01 };
406     char oid_dot11FCSErrorCount[] =
407         { 0x2a, 0x86, 0x48, 0xce, 0x34, 0x02, 0x02, 0x01, 0x0c, 0x01 };
408     char oid_dot11TransmittedFrameCount[] =
409         { 0x2a, 0x86, 0x48, 0xce, 0x34, 0x02, 0x02, 0x01, 0x0d, 0x01 };
410     char oid_dot11WEPUndecryptableCount[] =
411         { 0x2a, 0x86, 0x48, 0xce, 0x34, 0x02, 0x02, 0x01, 0x0e, 0x01 };
412     char oid_dot11WEPICVErrorCount[] =
413         { 0x2a, 0x86, 0x48, 0xce, 0x34, 0x01, 0x05, 0x01, 0x05, 0x01 };
414     char oid_dot11WEPExcludedCount[] =
415         { 0x2a, 0x86, 0x48, 0xce, 0x34, 0x01, 0x05, 0x01, 0x06, 0x01 };
416
417     char message[80];
418     int j;
419     fd_set rds;
420     struct timeval timeout;
421
422     varbind varbinds[16];
423     curs_set(0);
424
425     print_title(_("Wireless Statistics"));
426     print_help(QHELP);
427     noecho();
428
429     varbinds[0].oid = oid_dot11TransmittedFragmentCount;
430     varbinds[0].len_oid = sizeof(oid_dot11TransmittedFragmentCount);
431     varbinds[1].oid = oid_dot11MulticastTransmittedFrameCount;
432     varbinds[1].len_oid = sizeof(oid_dot11MulticastTransmittedFrameCount);
433     varbinds[2].oid = oid_dot11FailedCount;
434     varbinds[2].len_oid = sizeof(oid_dot11FailedCount);
435     varbinds[3].oid = oid_dot11RetryCount;
436     varbinds[3].len_oid = sizeof(oid_dot11RetryCount);
437     varbinds[4].oid = oid_dot11MultipleRetryCount;
438     varbinds[4].len_oid = sizeof(oid_dot11MultipleRetryCount);
439     varbinds[5].oid = oid_dot11FrameDuplicateCount;
440     varbinds[5].len_oid = sizeof(oid_dot11FrameDuplicateCount);
441     varbinds[6].oid = oid_dot11RTSSuccessCount;
442     varbinds[6].len_oid = sizeof(oid_dot11RTSSuccessCount);
443     varbinds[7].oid = oid_dot11RTSFailureCount;
444     varbinds[7].len_oid = sizeof(oid_dot11RTSFailureCount);
445     varbinds[8].oid = oid_dot11ACKFailureCount;
446     varbinds[8].len_oid = sizeof(oid_dot11ACKFailureCount);
447     varbinds[9].oid = oid_dot11ReceivedFragmentCount;
448     varbinds[9].len_oid = sizeof(oid_dot11ReceivedFragmentCount);
449     varbinds[10].oid = oid_dot11MulticastReceivedFrameCount;
450     varbinds[10].len_oid = sizeof(oid_dot11MulticastReceivedFrameCount);
451     varbinds[11].oid = oid_dot11FCSErrorCount;
452     varbinds[11].len_oid = sizeof(oid_dot11FCSErrorCount);
453     varbinds[12].oid = oid_dot11TransmittedFrameCount;
454     varbinds[12].len_oid = sizeof(oid_dot11TransmittedFrameCount);
455     varbinds[13].oid = oid_dot11WEPUndecryptableCount;
456     varbinds[13].len_oid = sizeof(oid_dot11WEPUndecryptableCount);
457     varbinds[14].oid = oid_dot11WEPICVErrorCount;
458     varbinds[14].len_oid = sizeof(oid_dot11WEPICVErrorCount);
459     varbinds[15].oid = oid_dot11WEPExcludedCount;
460     varbinds[15].len_oid = sizeof(oid_dot11WEPExcludedCount);
461
462     while (1) {
463         for (j = 0; j < 16; j++) {
464             varbinds[j].value = oid_dot11TransmittedFragmentCount;
465             varbinds[j].len_val = 0;
466             varbinds[j].type = 0x05;
467         }
468         if (snmp(varbinds, 16, GET) <= 0) {
469             print_helperr(ERR_RET);
470             getch();
471             goto quit;
472         }
473
474         sprintf(message, "FragmentTx       %10lu FragmentRx       %10lu",
475                 (long) swap4(*varbinds[0].value), (long) swap4(*varbinds[9].value));
476         mvwaddstr(main_sub, 1, 1, message);
477         sprintf(message, "TransmittedFrame %10lu",
478                 (long) swap4(*varbinds[12].value));
479         mvwaddstr(main_sub, 2, 1, message);
480         sprintf(message, "MulticasFrameTx  %10lu MulticastFrameRx %10lu",
481                 (long) swap4(*varbinds[1].value), (long) swap4(*varbinds[10].value));
482         mvwaddstr(main_sub, 3, 1, message);
483         sprintf(message, "WEPUndecryptable %10lu WEPExcluded      %10lu",
484                 (long) swap4(*varbinds[13].value), (long) swap4(*varbinds[15].value));
485         mvwaddstr(main_sub, 4, 1, message);
486         sprintf(message, "RTSSuccess       %10lu RTSFailure       %10lu",
487                 (long) swap4(*varbinds[6].value), (long) swap4(*varbinds[7].value));
488         mvwaddstr(main_sub, 5, 1, message);
489         sprintf(message, "ACKFailure       %10lu",
490                 (long) swap4(*varbinds[8].value));
491         mvwaddstr(main_sub, 6, 1, message);
492         sprintf(message, "Retry            %10lu MultipleRetry    %10lu",
493                 (long) swap4(*varbinds[3].value), (long) swap4(*varbinds[4].value));
494         mvwaddstr(main_sub, 7, 1, message);
495         sprintf(message, "FrameDuplicate   %10lu",
496                 (long) swap4(*varbinds[5].value));
497         mvwaddstr(main_sub, 8, 1, message);
498         sprintf(message, "Failed           %10lu",
499                 (long) swap4(*varbinds[2].value));
500         mvwaddstr(main_sub, 9, 1, message);
501         sprintf(message, "FCSError         %10lu WEPICVError      %10lu",
502                 (long) swap4(*(varbinds[11].value)),
503                 (long) swap4(*(varbinds[14].value)));
504         mvwaddstr(main_sub, 10, 1, message);
505         wrefresh(main_sub);
506
507         timeout.tv_sec = 1;
508         timeout.tv_usec = 0;
509         FD_ZERO(&rds);
510         FD_SET(0, &rds);
511
512         /* wait up to timeout until anything is avail. for reading on stdin */
513         j = select(1, &rds, NULL, NULL, &timeout);
514
515         /* error occured */
516         if (j == -1) {
517             print_helperr(SELECT);
518             getch();
519             break;
520         }
521
522         /* not timed out => anything avail. for reading in &rds */
523         if (j != 0) {
524             j = getc(stdin);
525             if (j == 'q' || j == 'Q')
526                 break;
527
528         }
529
530         /* j = 0 => timeout => continue looping */
531     }
532
533   quit:
534     wclear(main_sub);
535     print_title("");
536     clear_main(0);
537 }