]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sbin/sconfig/sconfig.c
This commit was generated by cvs2svn to compensate for changes in r175801,
[FreeBSD/FreeBSD.git] / sbin / sconfig / sconfig.c
1 /*
2  * Channel configuration utility for Cronyx serial adapters.
3  *
4  * Copyright (C) 1997-2002 Cronyx Engineering.
5  * Author: Serge Vakulenko, <vak@cronyx.ru>
6  *
7  * Copyright (C) 1999-2005 Cronyx Engineering.
8  * Author: Roman Kurakin, <rik@cronyx.ru>
9  *
10  * This software is distributed with NO WARRANTIES, not even the implied
11  * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12  *
13  * Authors grant any other persons or organisations permission to use
14  * or modify this software as long as this message is kept with the software,
15  * all derivative works or modified versions.
16  *
17  * Cronyx Id: sconfig.c,v 1.4.2.2 2005/11/09 13:01:35 rik Exp $
18  */
19
20 #include <sys/cdefs.h>
21 __FBSDID("$FreeBSD$");
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <fcntl.h>
28 #include <errno.h>
29 #include <ctype.h>
30 #include <sys/ioctl.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <sys/socket.h>
34 #include <net/if.h>
35 #include <machine/cserial.h>
36
37 #define MAXCHAN 128
38
39 int vflag, eflag, sflag, mflag, cflag, fflag, iflag, aflag, xflag;
40 int tflag, uflag;
41 char mask[64];
42 int adapter_type;               /* 0-sigma, 1-tau, 2-taupci, 3-tau32 */
43 char chan_name[16];
44
45 static void
46 usage (void)
47 {
48         printf(
49 "Serial Adapter Configuration Utility\n"
50 "Copyright (C) 1998-2005 Cronyx Engineering.\n"
51 "See also man sconfig (8)\n"
52 "Usage:\n"
53 "\tsconfig [-aimsxeftuc] [device [parameters ...]]\n"
54 "\n"
55 "Options:\n"
56 "\t<no options>\t\t -- print channel options\n"
57 "\t-a\t\t\t -- print all settings of the channel\n"
58 "\t-i\t\t\t -- print network interface status\n"
59 "\t-m\t\t\t -- print modem signal status\n"
60 "\t-s\t\t\t -- print channel statistics\n"
61 "\t-x\t\t\t -- print extended channel statistics\n"
62 "\t-e\t\t\t -- print short E1/G703 statistics\n"
63 "\t-f\t\t\t -- print full E1/G703 statistics\n"
64 "\t-t\t\t\t -- print short E3/T3/STS-1 statistics\n"
65 "\t-u\t\t\t -- print full E3/T3/STS-1 statistics\n"
66 "\t-c\t\t\t -- clear statistics\n"
67 "\nParameters:\n"
68 "\t<number>\t\t -- baud rate, internal clock\n"
69 "\textclock\t\t -- external clock (default)\n"
70 "\nProtocol options:\n"
71 "\tasync\t\t\t -- asynchronous protocol\n"
72 #ifdef __linux__
73 "\tsync\t\t\t -- synchronous protocol\n"
74 #endif
75 "\tcisco\t\t\t -- Cisco/HDLC protocol\n"
76 "\tfr\t\t\t -- Frame Relay protocol\n"
77 #ifdef __linux__
78 "\t    dlci<number>\t -- Add new DLCI\n"
79 #endif
80 "\tppp\t\t\t -- PPP protocol\n"
81 #ifdef __linux__
82 "\trbrg\t\t\t -- Remote bridge\n"
83 "\traw\t\t\t -- raw HDLC protocol\n"
84 "\tpacket\t\t\t -- packetized HDLC protocol\n"
85 "\tidle\t\t\t -- no protocol\n"
86 #else
87 "\t    keepalive={on,of}\t -- Enable/disable keepalive\n"
88 #endif
89 "\nInterface options:\n"
90 "\tport={rs232,v35,rs449}\t -- port type (for old models of Sigma)\n"
91 "\tcfg={A,B,C}\t\t -- adapter configuration\n"
92 "\tloop={on,off}\t\t -- internal loopback\n"
93 "\trloop={on,off}\t\t -- remote loopback\n"
94 "\tdpll={on,off}\t\t -- DPLL mode\n"
95 "\tnrzi={on,off}\t\t -- NRZI encoding\n"
96 "\tinvclk={on,off}\t\t -- invert receive and transmit clock\n"
97 "\tinvrclk={on,off}\t -- invert receive clock\n"
98 "\tinvtclk={on,off}\t -- invert transmit clock\n"
99 "\thigain={on,off}\t\t -- E1 high non linear input sensitivity \n\t\t\t\t    (long line)\n"
100 "\tmonitor={on,off}\t -- E1 high linear input sensitivity \n\t\t\t\t    (interception mode)\n"
101 "\tphony={on,off}\t\t -- E1 telepnony mode\n"
102 "\tunfram={on,off}\t\t -- E1 unframed mode\n"
103 "\tscrambler={on,off}\t -- G.703 scrambling mode\n"
104 "\tuse16={on,off}\t\t -- E1 timeslot 16 usage\n"
105 "\tcrc4={on,off}\t\t -- E1 CRC4 mode\n"
106 #ifdef __linux__
107 "\tami={on,off}\t\t -- E1 AMI or HDB3 line code\n"
108 "\tmtu={size}\t\t -- set MTU in bytes\n"
109 #endif
110 "\tsyn={int,rcv,rcvX}\t -- G.703 transmit clock\n"
111 "\tts=...\t\t\t -- E1 timeslots\n"
112 "\tpass=...\t\t -- E1 subchannel timeslots\n"
113 "\tdir=<num>\t\t -- connect channel to link<num>\n"
114 /*"\trqken={size}\t\t -- set receive queue length in packets\n"*/
115 /*"\tcablen={on,off}\t\t -- T3/STS-1 high transmitter output for long cable\n"*/
116 "\tdebug={0,1,2}\t\t -- enable/disable debug messages\n"
117         );
118         exit (0);
119 }
120
121 static unsigned long
122 scan_timeslots (char *s)
123 {
124         char *e;
125         long v;
126         int i;
127         unsigned long ts, lastv;
128
129         ts = lastv = 0;
130         for (;;) {
131                 v = strtol (s, &e, 10);
132                 if (e == s)
133                         break;
134                 if (*e == '-') {
135                         lastv = v;
136                         s = e+1;
137                         continue;
138                 }
139                 if (*e == ',')
140                         ++e;
141
142                 if (lastv)
143                         for (i=lastv; i<v; ++i)
144                                 ts |= 1L << i;
145                 ts |= 1L << v;
146
147                 lastv = 0;
148                 s = e;
149         }
150         return ts;
151 }
152
153 static int
154 ppp_ok (void)
155 {
156 #ifdef __linux__
157         int s, p;
158         struct ifreq ifr;
159         char pttyname[32];
160         char *p1, *p2;
161         int i, j;
162         int ppp_disc = N_PPP;
163
164         /*
165          * Open a socket for doing the ioctl operations.
166          */
167         s = socket (AF_INET, SOCK_DGRAM, 0);
168         if (s < 0) {
169                 fprintf (stderr, "Error opening socket.\n");
170                 return 0;
171         }
172         strncpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
173         if (ioctl (s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0) {
174                 /* Ok. */
175                 close (s);
176                 return 1;
177         }
178         close (s);
179
180         /* open pseudo-tty and try to set PPP discipline */
181         sprintf (pttyname, "/dev/ptyXX");
182         p1 = &pttyname[8];
183         p2 = &pttyname[9];
184         for (i=0; i<16; i++) {
185                 struct stat stb;
186
187                 *p1 = "pqrstuvwxyzabcde"[i];
188                 *p2 = '0';
189                 if (stat (pttyname, &stb) < 0)
190                         continue;
191                 for (j=0; j<16; j++) {
192                         *p2 = "0123456789abcdef"[j];
193                         p = open (pttyname, 2);
194                         if (p > 0) {
195                                 if (ioctl (p, TIOCSETD, &ppp_disc) < 0) {
196                                         fprintf (stderr, "No PPP discipline in kernel.\n");
197                                         close (p);
198                                         return 0;
199                                 }
200                                 close (p);
201                                 return 1;
202                         }
203                 }
204         }
205         fprintf (stderr, "Cannot get pseudo-tty.\n");
206         return 0;
207 #else
208         return 1;
209 #endif
210 }
211
212 static char *
213 format_timeslots (unsigned long s)
214 {
215         static char buf [100];
216         char *p = buf;
217         int i;
218
219         for (i=1; i<32; ++i)
220                 if ((s >> i) & 1) {
221                         int prev = (i > 1)  & (s >> (i-1));
222                         int next = (i < 31) & (s >> (i+1));
223
224                         if (prev) {
225                                 if (next)
226                                         continue;
227                                 *p++ = '-';
228                         } else if (p > buf)
229                                 *p++ = ',';
230
231                         if (i >= 10)
232                                 *p++ = '0' + i / 10;
233                         *p++ = '0' + i % 10;
234                 }
235         *p = 0;
236         return buf;
237 }
238
239 static void
240 print_modems (int fd, int need_header)
241 {
242         int status;
243
244         if (ioctl (fd, TIOCMGET, &status) < 0) {
245                 perror ("getting modem status");
246                 return;
247         }
248         if (need_header)
249                 printf ("Channel\tLE\tDTR\tDSR\tRTS\tCTS\tCD\n");
250         printf ("%s\t%s\t%s\t%s\t%s\t%s\t%s\n", chan_name,
251                 status & TIOCM_LE  ? "On" : "-",
252                 status & TIOCM_DTR ? "On" : "-",
253                 status & TIOCM_DSR ? "On" : "-",
254                 status & TIOCM_RTS ? "On" : "-",
255                 status & TIOCM_CTS ? "On" : "-",
256                 status & TIOCM_CD  ? "On" : "-");
257 }
258
259 static void
260 #ifdef __linux__
261 print_ifconfig (int fd)
262 #else
263 print_ifconfig (int fd __unused)
264 #endif
265 {
266         char buf [64];
267 #ifdef __linux__
268         char protocol [8];
269
270         if (ioctl (fd, SERIAL_GETPROTO, &protocol) >= 0 &&
271             strcmp (protocol, "fr") == 0)
272                 sprintf (buf, "ifconfig %sd16 2>/dev/null", chan_name);
273         else
274 #endif
275         sprintf (buf, "ifconfig %s 2>/dev/null", chan_name);
276         system (buf);
277 }
278
279 static char *
280 format_long (unsigned long val)
281 {
282         static char s[32];
283         int l;
284         l = sprintf (s, "%lu", val);
285         if (l>7 && !sflag) {
286                 s[3] = s[2];
287                 s[2] = s[1];
288                 s[1] = '.';
289                 s[4] = 'e';
290                 sprintf (s + 5, "%02d", l-1);
291         }
292         return s;
293 }
294
295 static void
296 print_stats (int fd, int need_header)
297 {
298         struct serial_statistics st;
299         unsigned long sarr [9];
300         int i;
301
302         if (ioctl (fd, SERIAL_GETSTAT, &st) < 0) {
303                 perror ("getting statistics");
304                 return;
305         }
306         if (need_header) {
307                 if (sflag) {
308                         printf ("        ------------Receive-----------      "
309                                 "------------Transmit----------\n");
310                         printf ("Channel Interrupts  Packets     Errors      "
311                                 "Interrupts  Packets     Errors\n");
312                 }
313                 else    {
314                         printf ("        --------Receive---------------  "
315                                 "--------Transmit--------------  Modem\n");
316                         printf ("Channel Intrs   Bytes   Packets Errors  "
317                                 "Intrs   Bytes   Packets Errors  Intrs\n");
318                 }
319         }
320         
321         sarr [0] = st.rintr;
322         sarr [1] = st.ibytes;
323         sarr [2] = st.ipkts;
324         sarr [3] = st.ierrs;
325         sarr [4] = st.tintr;
326         sarr [5] = st.obytes;
327         sarr [6] = st.opkts;
328         sarr [7] = st.oerrs;
329         sarr [8] = st.mintr;
330         printf ("%s", chan_name);
331         if (sflag) {
332                 printf ("\t%-12lu%-12lu%-12lu%-12lu%-12lu%-12lu", sarr[0],
333                         sarr[2], sarr[3], sarr[4], sarr[6], sarr[7]);
334         } else {
335                 for (i = 0; i < 9; i++)
336                         printf ("\t%s", format_long (sarr [i]));
337                 printf ("\n");
338         }
339 }
340
341 static void
342 clear_stats (int fd)
343 {
344         if (ioctl (fd, SERIAL_CLRSTAT, 0) < 0) {
345                 perror ("clearing statistics");
346                 exit (-1);
347         }
348 }
349
350 static char *
351 format_e1_status (unsigned long status)
352 {
353         static char buf [80];
354
355         if (status == 0)
356                 return "n/a";
357         if (status & E1_NOALARM)
358                 return "Ok";
359         buf[0] = 0;
360         if (status & E1_LOS)     strcat (buf, ",LOS");
361         if (status & E1_AIS)     strcat (buf, ",AIS");
362         if (status & E1_LOF)     strcat (buf, ",LOF");
363         if (status & E1_LOMF)    strcat (buf, ",LOMF");
364         if (status & E1_CRC4E)   strcat (buf, ",CRC4E");
365         if (status & E1_FARLOF)  strcat (buf, ",FARLOF");
366         if (status & E1_AIS16)   strcat (buf, ",AIS16");
367         if (status & E1_FARLOMF) strcat (buf, ",FARLOMF");
368 /*      if (status & E1_TSTREQ)  strcat (buf, ",TSTREQ");*/
369 /*      if (status & E1_TSTERR)  strcat (buf, ",TSTERR");*/
370         if (buf[0] == ',')
371                 return buf+1;
372         return "Unknown";
373 }
374
375 static void
376 print_frac (int leftalign, unsigned long numerator, unsigned long divider)
377 {
378         int n;
379
380         if (numerator < 1 || divider < 1) {
381                 printf (leftalign ? "/-   " : "    -");
382                 return;
383         }
384         n = (int) (0.5 + 1000.0 * numerator / divider);
385         if (n < 1000) {
386                 printf (leftalign ? "/.%-3d" : " .%03d", n);
387                 return;
388         }
389         putchar (leftalign ? '/' : ' ');
390
391         if      (n >= 1000000) n = (n+500) / 1000 * 1000;
392         else if (n >= 100000)  n = (n+50)  / 100 * 100;
393         else if (n >= 10000)   n = (n+5)   / 10 * 10;
394
395         switch (n) {
396         case 1000:    printf (".999"); return;
397         case 10000:   n = 9990;   break;
398         case 100000:  n = 99900;  break;
399         case 1000000: n = 999000; break;
400         }
401         if (n < 10000)        printf ("%d.%d", n/1000, n/10%100);
402         else if (n < 100000)  printf ("%d.%d", n/1000, n/100%10);
403         else if (n < 1000000) printf ("%d.", n/1000);
404         else                  printf ("%d", n/1000);
405 }
406
407 static void
408 print_e1_stats (int fd, int need_header)
409 {
410         struct e1_statistics st;
411         int i, maxi;
412
413         if (need_header)
414                 printf ("Chan\t Unav/Degr  Bpv/Fsyn  CRC/RCRC  Err/Lerr  Sev/Bur   Oof/Slp  Status\n");
415
416         if (ioctl (fd, SERIAL_GETESTAT, &st) < 0)
417                 return;
418         printf ("%s\t", chan_name);
419
420         /* Unavailable seconds, degraded minutes */
421         print_frac (0, st.currnt.uas, st.cursec);
422         print_frac (1, 60 * st.currnt.dm, st.cursec);
423
424         /* Bipolar violations, frame sync errors */
425         print_frac (0, st.currnt.bpv, st.cursec);
426         print_frac (1, st.currnt.fse, st.cursec);
427
428         /* CRC errors, remote CRC errors (E-bit) */
429         print_frac (0, st.currnt.crce, st.cursec);
430         print_frac (1, st.currnt.rcrce, st.cursec);
431
432         /* Errored seconds, line errored seconds */
433         print_frac (0, st.currnt.es, st.cursec);
434         print_frac (1, st.currnt.les, st.cursec);
435
436         /* Severely errored seconds, bursty errored seconds */
437         print_frac (0, st.currnt.ses, st.cursec);
438         print_frac (1, st.currnt.bes, st.cursec);
439
440         /* Out of frame seconds, controlled slip seconds */
441         print_frac (0, st.currnt.oofs, st.cursec);
442         print_frac (1, st.currnt.css, st.cursec);
443
444         printf (" %s\n", format_e1_status (st.status));
445
446         if (fflag) {
447                 /* Print total statistics. */
448                 printf ("\t");
449                 print_frac (0, st.total.uas, st.totsec);
450                 print_frac (1, 60 * st.total.dm, st.totsec);
451
452                 print_frac (0, st.total.bpv, st.totsec);
453                 print_frac (1, st.total.fse, st.totsec);
454
455                 print_frac (0, st.total.crce, st.totsec);
456                 print_frac (1, st.total.rcrce, st.totsec);
457
458                 print_frac (0, st.total.es, st.totsec);
459                 print_frac (1, st.total.les, st.totsec);
460
461                 print_frac (0, st.total.ses, st.totsec);
462                 print_frac (1, st.total.bes, st.totsec);
463
464                 print_frac (0, st.total.oofs, st.totsec);
465                 print_frac (1, st.total.css, st.totsec);
466
467                 printf (" -- Total\n");
468
469                 /* Print 24-hour history. */
470                 maxi = (st.totsec - st.cursec) / 900;
471                 if (maxi > 48)
472                         maxi = 48;
473                 for (i=0; i<maxi; ++i) {
474                         printf ("       ");
475                         print_frac (0, st.interval[i].uas, 15*60);
476                         print_frac (1, 60 * st.interval[i].dm, 15*60);
477
478                         print_frac (0, st.interval[i].bpv, 15*60);
479                         print_frac (1, st.interval[i].fse, 15*60);
480
481                         print_frac (0, st.interval[i].crce, 15*60);
482                         print_frac (1, st.interval[i].rcrce, 15*60);
483
484                         print_frac (0, st.interval[i].es, 15*60);
485                         print_frac (1, st.interval[i].les, 15*60);
486
487                         print_frac (0, st.interval[i].ses, 15*60);
488                         print_frac (1, st.interval[i].bes, 15*60);
489
490                         print_frac (0, st.interval[i].oofs, 15*60);
491                         print_frac (1, st.interval[i].css, 15*60);
492
493                         if (i < 3)
494                                 printf (" -- %dm\n", (i+1)*15);
495                         else
496                                 printf (" -- %dh %dm\n", (i+1)/4, (i+1)%4*15);
497                 }
498         }
499 }
500
501 static char *
502 format_e3_status (unsigned long status)
503 {
504         static char buf [80];
505
506         buf[0] = 0;
507         if (status & E3_LOS)     strcat (buf, ",LOS");
508         if (status & E3_TXE)     strcat (buf, ",XMIT");
509         if (buf[0] == ',')
510                 return buf+1;
511         return "Ok";
512 }
513
514 static char *
515 format_e3_cv (unsigned long cv, unsigned long baud, unsigned long atime)
516 {
517         static char buf[80];
518         
519         if (!cv || !baud || !atime)
520                 sprintf (buf, "         -         ");
521         else
522                 sprintf (buf, "%10lu (%.1e)", cv, (double)cv/baud/atime);
523         return buf;
524 }
525
526 static void
527 print_e3_stats (int fd, int need_header)
528 {
529         struct e3_statistics st;
530         int i, maxi;
531         long baud;
532
533         if (need_header)
534                 printf ("Chan\t--Code Violations---\t\t\t\t\t ----Status----\n");
535
536         if (ioctl (fd, SERIAL_GETE3STAT, &st) < 0 ||
537             ioctl (fd, SERIAL_GETBAUD, &baud) < 0)
538                 return;
539                 
540         if (!st.cursec)
541                 st.cursec = 1;
542
543         printf ("%s\t%s\t\t\t\t\t", chan_name,
544                 format_e3_cv (st.ccv, baud, st.cursec));
545
546         printf (" %s\n", format_e3_status (st.status));
547
548
549         if (uflag) {
550                 /* Print total statistics. */
551                 printf ("\t%s\t\t\t\t\t",
552                         format_e3_cv (st.tcv, baud, st.totsec));
553                 printf (" -- Total\n");
554
555                 /* Print 24-hour history. */
556                 maxi = (st.totsec - st.cursec) / 900;
557                 if (maxi > 48)
558                         maxi = 48;
559                 for (i=0; i<maxi; ++i) {
560                         printf ("\t%s\t\t\t\t\t",
561                                 format_e3_cv (st.icv[i], baud, 15*60));
562                         if (i < 3)
563                                 printf (" -- %2dm\n", (i+1)*15);
564                         else
565                                 printf (" -- %2dh %2dm\n", (i+1)/4, (i+1)%4*15);
566                 }
567         }
568 }
569
570 static void
571 print_chan (int fd)
572 {
573         char protocol [8];
574         char cfg;
575         int loop, dpll, nrzi, invclk, clk, higain, phony, use16, crc4;
576         int level, keepalive, debug, port, invrclk, invtclk, unfram, monitor;
577         int cable, dir, scrambler, ami, mtu;
578         int cablen, rloop, rqlen;
579         long baud, timeslots, subchan;
580         int protocol_valid, baud_valid, loop_valid, use16_valid, crc4_valid;
581         int dpll_valid, nrzi_valid, invclk_valid, clk_valid, phony_valid;
582         int timeslots_valid, subchan_valid, higain_valid, level_valid;
583         int keepalive_valid, debug_valid, cfg_valid, port_valid;
584         int invrclk_valid, invtclk_valid, unfram_valid, monitor_valid;
585         int cable_valid, dir_valid, scrambler_valid, ami_valid, mtu_valid;
586         int cablen_valid, rloop_valid, rqlen_valid;
587
588         protocol_valid  = ioctl (fd, SERIAL_GETPROTO, &protocol) >= 0;
589         cfg_valid       = ioctl (fd, SERIAL_GETCFG, &cfg) >= 0;
590         baud_valid      = ioctl (fd, SERIAL_GETBAUD, &baud) >= 0;
591         loop_valid      = ioctl (fd, SERIAL_GETLOOP, &loop) >= 0;
592         dpll_valid      = ioctl (fd, SERIAL_GETDPLL, &dpll) >= 0;
593         nrzi_valid      = ioctl (fd, SERIAL_GETNRZI, &nrzi) >= 0;
594         invclk_valid    = ioctl (fd, SERIAL_GETINVCLK, &invclk) >= 0;
595         invrclk_valid   = ioctl (fd, SERIAL_GETINVRCLK, &invrclk) >= 0;
596         invtclk_valid   = ioctl (fd, SERIAL_GETINVTCLK, &invtclk) >= 0;
597         clk_valid       = ioctl (fd, SERIAL_GETCLK, &clk) >= 0;
598         timeslots_valid = ioctl (fd, SERIAL_GETTIMESLOTS, &timeslots) >= 0;
599         subchan_valid   = ioctl (fd, SERIAL_GETSUBCHAN, &subchan) >= 0;
600         higain_valid    = ioctl (fd, SERIAL_GETHIGAIN, &higain) >= 0;
601         phony_valid     = ioctl (fd, SERIAL_GETPHONY, &phony) >= 0;
602         unfram_valid    = ioctl (fd, SERIAL_GETUNFRAM, &unfram) >= 0;
603         monitor_valid   = ioctl (fd, SERIAL_GETMONITOR, &monitor) >= 0;
604         use16_valid     = ioctl (fd, SERIAL_GETUSE16, &use16) >= 0;
605         crc4_valid      = ioctl (fd, SERIAL_GETCRC4, &crc4) >= 0;
606         ami_valid       = ioctl (fd, SERIAL_GETLCODE, &ami) >= 0;
607         level_valid     = ioctl (fd, SERIAL_GETLEVEL, &level) >= 0;
608         keepalive_valid = ioctl (fd, SERIAL_GETKEEPALIVE, &keepalive) >= 0;
609         debug_valid     = ioctl (fd, SERIAL_GETDEBUG, &debug) >= 0;
610         port_valid      = ioctl (fd, SERIAL_GETPORT, &port) >= 0;
611         cable_valid     = ioctl (fd, SERIAL_GETCABLE, &cable) >= 0;
612         dir_valid       = ioctl (fd, SERIAL_GETDIR, &dir) >= 0;
613         scrambler_valid = ioctl (fd, SERIAL_GETSCRAMBLER, &scrambler) >= 0;
614         cablen_valid    = ioctl (fd, SERIAL_GETCABLEN, &cablen) >= 0;
615         rloop_valid     = ioctl (fd, SERIAL_GETRLOOP, &rloop) >= 0;
616         mtu_valid       = ioctl (fd, SERIAL_GETMTU, &mtu) >= 0;
617         rqlen_valid     = ioctl (fd, SERIAL_GETRQLEN, &rqlen) >= 0;
618
619         printf ("%s", chan_name);
620         if (port_valid)
621                 switch (port) {
622                 case 0: printf (" (rs232)"); break;
623                 case 1: printf (" (v35)"); break;
624                 case 2: printf (" (rs530)"); break;
625                 }
626         else if (cable_valid)
627                 switch (cable) {
628                 case 0: printf (" (rs232)"); break;
629                 case 1: printf (" (v35)"); break;
630                 case 2: printf (" (rs530)"); break;
631                 case 3: printf (" (x21)"); break;
632                 case 4: printf (" (rs485)"); break;
633                 case 9: printf (" (no cable)"); break;
634                 }
635         if (debug_valid && debug)
636                 printf (" debug=%d", debug);
637         if (protocol_valid && *protocol)
638                 printf (" %.8s", protocol);
639         else
640                 printf (" idle");
641         if (cablen_valid)
642                 printf (" cablen=%s", cablen ? "on" : "off");
643         if (keepalive_valid)
644                 printf (" keepalive=%s", keepalive ? "on" : "off");
645
646         if (cfg_valid)
647                 switch (cfg) {
648                 case 'a' :      printf (" cfg=A");      break;
649                 case 'b' :      printf (" cfg=B");      break;
650                 case 'c' :      printf (" cfg=C");      break;
651                 case 'd' :      printf (" cfg=D");      break;
652                 default  :      printf (" cfg=unknown");
653                 }
654         if (dir_valid)
655                 printf (" dir=%d", dir);
656
657         if (baud_valid) {
658                 if (baud)
659                         printf (" %ld", baud);
660                 else
661                         printf (" extclock");
662         }
663         if (mtu_valid)
664                 printf (" mtu=%d", mtu);
665
666         if (aflag && rqlen_valid)
667                 printf (" rqlen=%d", rqlen);
668
669         if (clk_valid)
670                 switch (clk) {
671                 case E1CLK_INTERNAL:      printf (" syn=int");     break;
672                 case E1CLK_RECEIVE:       printf (" syn=rcv");     break;
673                 case E1CLK_RECEIVE_CHAN0: printf (" syn=rcv0");    break;
674                 case E1CLK_RECEIVE_CHAN1: printf (" syn=rcv1");    break;
675                 case E1CLK_RECEIVE_CHAN2: printf (" syn=rcv2");    break;
676                 case E1CLK_RECEIVE_CHAN3: printf (" syn=rcv3");    break;
677                 default:                  printf (" syn=%d", clk); break;
678                 }
679
680         if (dpll_valid)
681                 printf (" dpll=%s", dpll ? "on" : "off");
682         if (nrzi_valid)
683                 printf (" nrzi=%s", nrzi ? "on" : "off");
684         if (invclk_valid)
685                 printf (" invclk=%s", invclk ? "on" : "off");
686         if (invrclk_valid)
687                 printf (" invrclk=%s", invrclk ? "on" : "off");
688         if (invtclk_valid)
689                 printf (" invtclk=%s", invtclk ? "on" : "off");
690         if (unfram_valid)
691                 printf (" unfram=%s", unfram ? "on" : "off");
692         if (use16_valid)
693                 printf (" use16=%s", use16 ? "on" : "off");
694         if (aflag) {
695                 if (crc4_valid)
696                         printf (" crc4=%s", crc4 ? "on" : "off");
697                 if (higain_valid)
698                         printf (" higain=%s", higain ? "on" : "off");
699                 if (monitor_valid)
700                         printf (" monitor=%s", monitor ? "on" : "off");
701                 if (phony_valid)
702                         printf (" phony=%s", phony ? "on" : "off");
703                 if (scrambler_valid)
704                         printf (" scrambler=%s", scrambler ? "on" : "off");
705                 if (loop_valid)
706                         printf (" loop=%s", loop ? "on" : "off");
707                 if (rloop_valid)
708                         printf (" rloop=%s", rloop ? "on" : "off");
709                 if (ami_valid)
710                         printf (" ami=%s", ami ? "on" : "off");
711         }
712         if (timeslots_valid)
713                 printf (" ts=%s", format_timeslots (timeslots));
714         if (subchan_valid)
715                 printf (" pass=%s", format_timeslots (subchan));
716         if (level_valid)
717                 printf (" (level=-%.1fdB)", level / 10.0);
718         printf ("\n");
719 }
720
721 static void
722 setup_chan (int fd, int argc, char **argv)
723 {
724         int i, mode, loop, nrzi, dpll, invclk, phony, use16, crc4, unfram, ami;
725         int higain, clk, keepalive, debug, port, dlci, invrclk, invtclk;
726         int monitor, dir, scrambler, rloop, cablen;
727         long baud, timeslots, mtu, rqlen;
728
729         for (i=0; i<argc; ++i) {
730                 if (argv[i][0] >= '0' && argv[i][0] <= '9') {
731                         baud = strtol (argv[i], 0, 10);
732                         ioctl (fd, SERIAL_SETBAUD, &baud);
733                 } else if (strcasecmp ("extclock", argv[i]) == 0) {
734                         baud = 0;
735                         ioctl (fd, SERIAL_SETBAUD, &baud);
736                 } else if (strncasecmp ("cfg=", argv[i], 4) == 0) {
737                         if (strncasecmp ("a", argv[i]+4, 1) == 0)
738                                 ioctl (fd, SERIAL_SETCFG, "a");
739                         else if (strncasecmp ("b", argv[i]+4, 1) == 0)
740                                 ioctl (fd, SERIAL_SETCFG, "b");
741                         else if (strncasecmp ("c", argv[i]+4, 1) == 0)
742                                 ioctl (fd, SERIAL_SETCFG, "c");
743                         else if (strncasecmp ("d", argv[i]+4, 1) == 0)
744                                 ioctl (fd, SERIAL_SETCFG, "d");
745                         else {
746                                 fprintf (stderr, "invalid cfg\n");
747                                 exit (-1);
748                         }
749                 } else if (strcasecmp ("idle", argv[i]) == 0)
750                         ioctl (fd, SERIAL_SETPROTO, "\0\0\0\0\0\0\0");
751                 else if (strcasecmp ("async", argv[i]) == 0) {
752                         mode = SERIAL_ASYNC;
753                         if (ioctl (fd, SERIAL_SETMODE, &mode) >= 0)
754                                 ioctl (fd, SERIAL_SETPROTO, "async\0\0");
755                 } else if (strcasecmp ("sync", argv[i]) == 0) {
756                         mode = SERIAL_HDLC;
757                         if (ioctl (fd, SERIAL_SETMODE, &mode) >= 0)
758                                 ioctl (fd, SERIAL_SETPROTO, "sync\0\0\0");
759                 } else if (strcasecmp ("cisco", argv[i]) == 0) {
760                         mode = SERIAL_HDLC;
761                         ioctl (fd, SERIAL_SETMODE, &mode);
762                         ioctl (fd, SERIAL_SETPROTO, "cisco\0\0");
763                 } else if (strcasecmp ("rbrg", argv[i]) == 0) {
764                         mode = SERIAL_HDLC;
765                         ioctl (fd, SERIAL_SETMODE, &mode);
766                         ioctl (fd, SERIAL_SETPROTO, "rbrg\0\0\0");
767                 } else if (strcasecmp ("raw", argv[i]) == 0) {
768                         mode = SERIAL_HDLC;
769                         ioctl (fd, SERIAL_SETMODE, &mode);
770                         ioctl (fd, SERIAL_SETPROTO, "raw\0\0\0\0");
771                 } else if (strcasecmp ("packet", argv[i]) == 0) {
772                         mode = SERIAL_HDLC;
773                         ioctl (fd, SERIAL_SETMODE, &mode);
774                         ioctl (fd, SERIAL_SETPROTO, "packet\0");
775                 } else if (strcasecmp ("ppp", argv[i]) == 0) {
776                         /* check that ppp line discipline is present */
777                         if (ppp_ok ()) {
778                                 mode = SERIAL_HDLC;
779                                 ioctl (fd, SERIAL_SETMODE, &mode);
780                                 ioctl (fd, SERIAL_SETPROTO, "ppp\0\0\0\0");
781                         }
782                 } else if (strncasecmp ("keepalive=", argv[i], 10) == 0) {
783                         keepalive = (strcasecmp ("on", argv[i] + 10) == 0);
784                         ioctl (fd, SERIAL_SETKEEPALIVE, &keepalive);
785                 } else if (strcasecmp ("fr", argv[i]) == 0) {
786                         mode = SERIAL_HDLC;
787                         ioctl (fd, SERIAL_SETMODE, &mode);
788                         ioctl (fd, SERIAL_SETPROTO, "fr\0\0\0\0\0");
789                 } else if (strcasecmp ("zaptel", argv[i]) == 0) {
790                         mode = SERIAL_HDLC;
791                         ioctl (fd, SERIAL_SETMODE, &mode);
792                         ioctl (fd, SERIAL_SETPROTO, "zaptel\0");
793                 } else if (strncasecmp ("debug=", argv[i], 6) == 0) {
794                         debug = strtol (argv[i]+6, 0, 10);
795                         ioctl (fd, SERIAL_SETDEBUG, &debug);
796                 } else if (strncasecmp ("loop=", argv[i], 5) == 0) {
797                         loop = (strcasecmp ("on", argv[i] + 5) == 0);
798                         ioctl (fd, SERIAL_SETLOOP, &loop);
799                 } else if (strncasecmp ("rloop=", argv[i], 6) == 0) {
800                         rloop = (strcasecmp ("on", argv[i] + 6) == 0);
801                         ioctl (fd, SERIAL_SETRLOOP, &rloop);
802                 } else if (strncasecmp ("dpll=", argv[i], 5) == 0) {
803                         dpll = (strcasecmp ("on", argv[i] + 5) == 0);
804                         ioctl (fd, SERIAL_SETDPLL, &dpll);
805                 } else if (strncasecmp ("nrzi=", argv[i], 5) == 0) {
806                         nrzi = (strcasecmp ("on", argv[i] + 5) == 0);
807                         ioctl (fd, SERIAL_SETNRZI, &nrzi);
808                 } else if (strncasecmp ("invclk=", argv[i], 7) == 0) {
809                         invclk = (strcasecmp ("on", argv[i] + 7) == 0);
810                         ioctl (fd, SERIAL_SETINVCLK, &invclk);
811                 } else if (strncasecmp ("invrclk=", argv[i], 8) == 0) {
812                         invrclk = (strcasecmp ("on", argv[i] + 8) == 0);
813                         ioctl (fd, SERIAL_SETINVRCLK, &invrclk);
814                 } else if (strncasecmp ("invtclk=", argv[i], 8) == 0) {
815                         invtclk = (strcasecmp ("on", argv[i] + 8) == 0);
816                         ioctl (fd, SERIAL_SETINVTCLK, &invtclk);
817                 } else if (strncasecmp ("higain=", argv[i], 7) == 0) {
818                         higain = (strcasecmp ("on", argv[i] + 7) == 0);
819                         ioctl (fd, SERIAL_SETHIGAIN, &higain);
820                 } else if (strncasecmp ("phony=", argv[i], 6) == 0) {
821                         phony = (strcasecmp ("on", argv[i] + 6) == 0);
822                         ioctl (fd, SERIAL_SETPHONY, &phony);
823                 } else if (strncasecmp ("unfram=", argv[i], 7) == 0) {
824                         unfram = (strcasecmp ("on", argv[i] + 7) == 0);
825                         ioctl (fd, SERIAL_SETUNFRAM, &unfram);
826                 } else if (strncasecmp ("scrambler=", argv[i], 10) == 0) {
827                         scrambler = (strcasecmp ("on", argv[i] + 10) == 0);
828                         ioctl (fd, SERIAL_SETSCRAMBLER, &scrambler);
829                 } else if (strncasecmp ("monitor=", argv[i], 8) == 0) {
830                         monitor = (strcasecmp ("on", argv[i] + 8) == 0);
831                         ioctl (fd, SERIAL_SETMONITOR, &monitor);
832                 } else if (strncasecmp ("use16=", argv[i], 6) == 0) {
833                         use16 = (strcasecmp ("on", argv[i] + 6) == 0);
834                         ioctl (fd, SERIAL_SETUSE16, &use16);
835                 } else if (strncasecmp ("crc4=", argv[i], 5) == 0) {
836                         crc4 = (strcasecmp ("on", argv[i] + 5) == 0);
837                         ioctl (fd, SERIAL_SETCRC4, &crc4);
838                 } else if (strncasecmp ("ami=", argv[i], 4) == 0) {
839                         ami = (strcasecmp ("on", argv[i] + 4) == 0);
840                         ioctl (fd, SERIAL_SETLCODE, &ami);
841                 } else if (strncasecmp ("mtu=", argv[i], 4) == 0) {
842                         mtu = strtol (argv[i] + 4, 0, 10);
843                         ioctl (fd, SERIAL_SETMTU, &mtu);
844                 } else if (strncasecmp ("rqlen=", argv[i], 6) == 0) {
845                         rqlen = strtol (argv[i] + 6, 0, 10);
846                         ioctl (fd, SERIAL_SETRQLEN, &rqlen);
847                 } else if (strcasecmp ("syn=int", argv[i]) == 0) {
848                         clk = E1CLK_INTERNAL;
849                         ioctl (fd, SERIAL_SETCLK, &clk);
850                 } else if (strcasecmp ("syn=rcv", argv[i]) == 0) {
851                         clk = E1CLK_RECEIVE;
852                         ioctl (fd, SERIAL_SETCLK, &clk);
853                 } else if (strcasecmp ("syn=rcv0", argv[i]) == 0) {
854                         clk = E1CLK_RECEIVE_CHAN0;
855                         ioctl (fd, SERIAL_SETCLK, &clk);
856                 } else if (strcasecmp ("syn=rcv1", argv[i]) == 0) {
857                         clk = E1CLK_RECEIVE_CHAN1;
858                         ioctl (fd, SERIAL_SETCLK, &clk);
859                 } else if (strcasecmp ("syn=rcv2", argv[i]) == 0) {
860                         clk = E1CLK_RECEIVE_CHAN2;
861                         ioctl (fd, SERIAL_SETCLK, &clk);
862                 } else if (strcasecmp ("syn=rcv3", argv[i]) == 0) {
863                         clk = E1CLK_RECEIVE_CHAN3;
864                         ioctl (fd, SERIAL_SETCLK, &clk);
865                 } else if (strncasecmp ("ts=", argv[i], 3) == 0) {
866                         timeslots = scan_timeslots (argv[i] + 3);
867                         ioctl (fd, SERIAL_SETTIMESLOTS, &timeslots);
868                 } else if (strncasecmp ("pass=", argv[i], 5) == 0) {
869                         timeslots = scan_timeslots (argv[i] + 5);
870                         ioctl (fd, SERIAL_SETSUBCHAN, &timeslots);
871                 } else if (strncasecmp ("dlci", argv[i], 4) == 0) {
872                         dlci = strtol (argv[i]+4, 0, 10);
873                         ioctl (fd, SERIAL_ADDDLCI, &dlci);
874                 } else if (strncasecmp ("dir=", argv[i], 4) == 0) {
875                         dir = strtol (argv[i]+4, 0, 10);
876                         ioctl (fd, SERIAL_SETDIR, &dir);
877                 } else if (strncasecmp ("port=", argv[i], 5) == 0) {
878                         if (strncasecmp ("rs232", argv[i]+5, 5) == 0) {
879                                 port = 0;
880                                 ioctl (fd, SERIAL_SETPORT, &port);
881                         } else if (strncasecmp ("v35", argv[i]+5, 3) == 0) {
882                                 port = 1;
883                                 ioctl (fd, SERIAL_SETPORT, &port);
884                         } else if (strncasecmp ("rs449", argv[i]+5, 5) == 0) {
885                                 port = 2;
886                                 ioctl (fd, SERIAL_SETPORT, &port);
887                         } else
888                                 fprintf (stderr, "invalid port type\n");
889                                 exit (-1);
890 #if 1
891                 } else if (strcasecmp ("reset", argv[i]) == 0) {
892                         ioctl (fd, SERIAL_RESET, 0);
893                 } else if (strcasecmp ("hwreset", argv[i]) == 0) {
894                         ioctl (fd, SERIAL_HARDRESET, 0);
895 #endif
896                 } else if (strncasecmp ("cablen=", argv[i], 7) == 0) {
897                         loop = (strcasecmp ("on", argv[i] + 7) == 0);
898                         ioctl (fd, SERIAL_SETCABLEN, &cablen);
899                 }
900         }
901 }
902
903 static void
904 get_mask (void)
905 {
906 #ifdef __linux__
907         int fd;
908
909         fd = open ("/dev/serial/ctl0", 0);
910         if (fd < 0) {
911                 perror ("/dev/serial/ctl0");
912                 exit (-1);
913         }
914         if (ioctl (fd, SERIAL_GETREGISTERED, &mask) < 0) {
915                 perror ("getting list of channels");
916                 exit (-1);
917         }
918         close (fd);
919 #else
920         int fd, fd1, fd2, fd3, i;
921         char buf [80];
922
923         for (i=0, fd=-1; i<12 && fd<0; i++) {
924                 sprintf (buf, "/dev/cx%d", i*4);
925                 fd = open (buf, 0);
926         }
927
928         for (i=0, fd1=-1; i<3 && fd1<0; i++) {
929                 sprintf (buf, "/dev/ct%d", i*2);
930                 fd1 = open (buf, 0);
931         }
932
933         for (i=0, fd2=-1; i<3 && fd2<0; i++) {
934                 sprintf (buf, "/dev/cp%d", i*4);
935                 fd2 = open (buf, 0);
936         }
937
938         /* Try only one */
939         for (i=0, fd3=-1; i<1 && fd3<0; i++) {
940                 sprintf (buf, "/dev/ce%d", i*4);
941                 fd3 = open (buf, 0);
942         }
943
944         if ((fd < 0) && (fd1 < 0) && (fd2 < 0) && (fd3 < 0)) {
945                 fprintf (stderr, "No Cronyx adapters installed\n");
946                 exit (-1);
947         }
948
949         if (fd >= 0) {
950                 if (ioctl (fd, SERIAL_GETREGISTERED, &mask) < 0) {
951                         perror ("getting list of channels");
952                         exit (-1);
953                 }
954                 close (fd);
955         }
956
957         if (fd1 >= 0) {
958                 if (ioctl (fd1, SERIAL_GETREGISTERED, (mask+16)) < 0) {
959                         perror ("getting list of channels");
960                         exit (-1);
961                 }
962                 close (fd1);
963         }
964
965         if (fd2 >= 0) {
966                 if (ioctl (fd2, SERIAL_GETREGISTERED, (mask+32)) < 0) {
967                         perror ("getting list of channels");
968                         exit (-1);
969                 }
970                 close (fd2);
971         }
972
973         if (fd3 >= 0) {
974                 if (ioctl (fd3, SERIAL_GETREGISTERED, (mask+48)) < 0) {
975                         perror ("getting list of channels");
976                         exit (-1);
977                 }
978                 close (fd3);
979         }
980 #endif
981 }
982
983 static int
984 open_chan_ctl (int num)
985 {
986         char device [80];
987         int fd;
988
989 #ifdef __linux__
990         sprintf (device, "/dev/serial/ctl%d", num);
991 #else
992         switch (adapter_type) {
993         case 0:
994                 sprintf (device, "/dev/cx%d", num);
995                 break;
996         case 1:
997                 sprintf (device, "/dev/ct%d", num);
998                 break;
999         case 2:
1000                 sprintf (device, "/dev/cp%d", num);
1001                 break;
1002         case 3:
1003                 sprintf (device, "/dev/ce%d", num);
1004                 break;
1005         }
1006 #endif
1007         fd = open (device, 0);
1008         if (fd < 0) {
1009                 if (errno == ENODEV)
1010                         fprintf (stderr, "chan%d: not configured\n", num);
1011                 else
1012                         perror (device);
1013                 exit (-1);
1014         }
1015 #ifdef __linux__
1016         if (ioctl (fd, SERIAL_GETNAME, &chan_name) < 0)
1017                 sprintf (chan_name, "chan%d", num);
1018 #else
1019         switch (adapter_type) {
1020         case 0: sprintf (chan_name, "cx%d", num); break;
1021         case 1: sprintf (chan_name, "ct%d", num); break;
1022         case 2: sprintf (chan_name, "cp%d", num); break;
1023         case 3: sprintf (chan_name, "ce%d", num); break;
1024         }
1025 #endif
1026         return fd;
1027 }
1028
1029 int
1030 main (int argc, char **argv)
1031 {
1032         char *p;
1033         int fd, need_header, chan_num;
1034
1035         if (argc > 1 && strcmp(argv[1], "help") == 0)
1036                 usage();
1037
1038         for (;;) {
1039                 switch (getopt (argc, argv, "mseftucviax")) {
1040                 case EOF:
1041                         break;
1042                 case 'a':
1043                         ++aflag;
1044                         continue;
1045                 case 'm':
1046                         ++mflag;
1047                         continue;
1048                 case 's':
1049                         ++sflag;
1050                         continue;
1051                 case 'e':
1052                         ++eflag;
1053                         continue;
1054                 case 'f':
1055                         ++eflag;
1056                         ++fflag;
1057                         continue;
1058                 case 't':
1059                         ++tflag;
1060                         continue;
1061                 case 'u':
1062                         ++tflag;
1063                         ++uflag;
1064                         continue;
1065                 case 'c':
1066                         ++cflag;
1067                         continue;
1068                 case 'v':
1069                         ++vflag;
1070                         continue;
1071                 case 'i':
1072                         ++iflag;
1073                         continue;
1074                 case 'x':
1075                         ++xflag;
1076                         continue;
1077                 default:
1078                         usage();
1079                 }
1080                 break;
1081         }
1082         argc -= optind;
1083         argv += optind;
1084
1085         if (argc <= 0) {
1086                 get_mask ();
1087                 need_header = 1;
1088                 adapter_type = 0;
1089 #ifndef __linux__
1090                 for (; adapter_type < 4; ++adapter_type)
1091 #endif
1092                 {
1093                 for (chan_num=0; chan_num<MAXCHAN; ++chan_num)
1094                         if (mask[adapter_type*16+chan_num/8] & 1 << (chan_num & 7)) {
1095                                 fd = open_chan_ctl (chan_num);
1096                                 if (vflag) {
1097 #ifdef __linux__
1098                                 char buf[256];
1099                                 if (ioctl (fd, SERIAL_GETVERSIONSTRING, &buf) >= 0) {
1100                                         printf ("Version: %s\n", buf);
1101                                         close (fd);
1102                                         return (0);
1103                                 }
1104 #endif
1105                                 }
1106                                 if (iflag) {
1107                                         print_chan (fd);
1108                                         print_ifconfig (fd);
1109                                 } else if (sflag||xflag)
1110                                         print_stats (fd, need_header);
1111                                 else if (mflag)
1112                                         print_modems (fd, need_header);
1113                                 else if (eflag)
1114                                         print_e1_stats (fd, need_header);
1115                                 else if (tflag)
1116                                         print_e3_stats (fd, need_header);
1117                                 else if (cflag)
1118                                         clear_stats (fd);
1119                                 else
1120                                         print_chan (fd);
1121                                 close (fd);
1122                                 need_header = 0;
1123                         }
1124                 }
1125                 return (0);
1126         }
1127
1128         p = argv[0] + strlen (argv[0]);
1129         while (p > argv[0] && p[-1] >= '0' && p[-1] <= '9')
1130                 --p;
1131         chan_num = strtol (p, 0, 10);
1132 #ifndef __linux__
1133         if (strncasecmp ("cx", argv[0], 2)==0)
1134                 adapter_type = 0;
1135         else if (strncasecmp ("ct", argv[0], 2)==0)
1136                 adapter_type = 1;
1137         else if (strncasecmp ("cp", argv[0], 2)==0)
1138                 adapter_type = 2;
1139         else if (strncasecmp ("ce", argv[0], 2)==0)
1140                 adapter_type = 3;
1141         else {
1142                 fprintf (stderr, "Wrong channel name\n");
1143                 exit (-1);
1144         }
1145 #endif
1146         argc--;
1147         argv++;
1148
1149         fd = open_chan_ctl (chan_num);
1150         if (vflag) {
1151 #ifdef __linux__
1152                 char buf[256];
1153                 if (ioctl (fd, SERIAL_GETVERSIONSTRING, &buf) >= 0)
1154                         printf ("Version: %s\n", buf);
1155 #endif
1156         }
1157         if (iflag) {
1158                 print_chan (fd);
1159                 print_ifconfig (fd);
1160                 close (fd);
1161                 return (0);
1162         }
1163         if (sflag||xflag) {
1164                 print_stats (fd, 1);
1165                 close (fd);
1166                 return (0);
1167         }
1168         if (mflag) {
1169                 print_modems (fd, 1);
1170                 close (fd);
1171                 return (0);
1172         }
1173         if (eflag) {
1174                 print_e1_stats (fd, 1);
1175                 close (fd);
1176                 return (0);
1177         }
1178         if (tflag) {
1179                 print_e3_stats (fd, 1);
1180                 close (fd);
1181                 return (0);
1182         }
1183         if (cflag) {
1184                 clear_stats (fd);
1185                 close (fd);
1186                 return (0);
1187         }
1188         if (argc > 0)
1189                 setup_chan (fd, argc, argv);
1190         else
1191                 print_chan (fd);
1192         close (fd);
1193         return (0);
1194 }