xref: /freebsd-12.1/sbin/sconfig/sconfig.c (revision 259edd28)
1 /*
2  * Channel configuration utility for Cronyx serial adapters.
3  *
4  * Copyright (C) 1997-2002 Cronyx Engineering.
5  * Author: Serge Vakulenko, <[email protected]>
6  *
7  * Copyright (C) 1999-2005 Cronyx Engineering.
8  * Author: Roman Kurakin, <[email protected]>
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
usage(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
scan_timeslots(char * s)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
ppp_ok(void)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 *
format_timeslots(unsigned long s)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
print_modems(int fd,int need_header)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__
print_ifconfig(int fd)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 void
set_debug_ifconfig(int on)280 set_debug_ifconfig (int on)
281 {
282 	char buf [64];
283 	sprintf (buf, "ifconfig %s %sdebug 2>/dev/null", chan_name,
284 		 on ? "" : "-");
285 	system (buf);
286 }
287 
288 static char *
format_long(unsigned long val)289 format_long (unsigned long val)
290 {
291 	static char s[32];
292 	int l;
293 	l = sprintf (s, "%lu", val);
294 	if (l>7 && !sflag) {
295 		s[3] = s[2];
296 		s[2] = s[1];
297 		s[1] = '.';
298 		s[4] = 'e';
299 		sprintf (s + 5, "%02d", l-1);
300 	}
301 	return s;
302 }
303 
304 static void
print_stats(int fd,int need_header)305 print_stats (int fd, int need_header)
306 {
307 	struct serial_statistics st;
308 	unsigned long sarr [9];
309 	int i;
310 
311 	if (ioctl (fd, SERIAL_GETSTAT, &st) < 0) {
312 		perror ("getting statistics");
313 		return;
314 	}
315 	if (need_header) {
316 		if (sflag) {
317 			printf ("        ------------Receive-----------      "
318 				"------------Transmit----------\n");
319 			printf ("Channel Interrupts  Packets     Errors      "
320 				"Interrupts  Packets     Errors\n");
321 		}
322 		else    {
323 			printf ("        --------Receive---------------  "
324 				"--------Transmit--------------  Modem\n");
325 			printf ("Channel Intrs   Bytes   Packets Errors  "
326 				"Intrs   Bytes   Packets Errors  Intrs\n");
327 		}
328 	}
329 
330 	sarr [0] = st.rintr;
331 	sarr [1] = st.ibytes;
332 	sarr [2] = st.ipkts;
333 	sarr [3] = st.ierrs;
334 	sarr [4] = st.tintr;
335 	sarr [5] = st.obytes;
336 	sarr [6] = st.opkts;
337 	sarr [7] = st.oerrs;
338 	sarr [8] = st.mintr;
339 	printf ("%s", chan_name);
340 	if (sflag) {
341 		printf ("\t%-12lu%-12lu%-12lu%-12lu%-12lu%-12lu", sarr[0],
342 			sarr[2], sarr[3], sarr[4], sarr[6], sarr[7]);
343 	} else {
344 		for (i = 0; i < 9; i++)
345 			printf ("\t%s", format_long (sarr [i]));
346 		printf ("\n");
347 	}
348 }
349 
350 static void
clear_stats(int fd)351 clear_stats (int fd)
352 {
353 	if (ioctl (fd, SERIAL_CLRSTAT, 0) < 0) {
354 		perror ("clearing statistics");
355 		exit (-1);
356 	}
357 }
358 
359 static char *
format_e1_status(unsigned long status)360 format_e1_status (unsigned long status)
361 {
362 	static char buf [80];
363 
364 	if (status == 0)
365 		return "n/a";
366 	if (status & E1_NOALARM)
367 		return "Ok";
368 	buf[0] = 0;
369 	if (status & E1_LOS)     strcat (buf, ",LOS");
370 	if (status & E1_AIS)     strcat (buf, ",AIS");
371 	if (status & E1_LOF)     strcat (buf, ",LOF");
372 	if (status & E1_LOMF)    strcat (buf, ",LOMF");
373 	if (status & E1_CRC4E)   strcat (buf, ",CRC4E");
374 	if (status & E1_FARLOF)  strcat (buf, ",FARLOF");
375 	if (status & E1_AIS16)   strcat (buf, ",AIS16");
376 	if (status & E1_FARLOMF) strcat (buf, ",FARLOMF");
377 /*	if (status & E1_TSTREQ)  strcat (buf, ",TSTREQ");*/
378 /*	if (status & E1_TSTERR)  strcat (buf, ",TSTERR");*/
379 	if (buf[0] == ',')
380 		return buf+1;
381 	return "Unknown";
382 }
383 
384 static void
print_frac(int leftalign,unsigned long numerator,unsigned long divider)385 print_frac (int leftalign, unsigned long numerator, unsigned long divider)
386 {
387 	int n;
388 
389 	if (numerator < 1 || divider < 1) {
390 		printf (leftalign ? "/-   " : "    -");
391 		return;
392 	}
393 	n = (int) (0.5 + 1000.0 * numerator / divider);
394 	if (n < 1000) {
395 		printf (leftalign ? "/.%-3d" : " .%03d", n);
396 		return;
397 	}
398 	putchar (leftalign ? '/' : ' ');
399 
400 	if      (n >= 1000000) n = (n+500) / 1000 * 1000;
401 	else if (n >= 100000)  n = (n+50)  / 100 * 100;
402 	else if (n >= 10000)   n = (n+5)   / 10 * 10;
403 
404 	switch (n) {
405 	case 1000:    printf (".999"); return;
406 	case 10000:   n = 9990;   break;
407 	case 100000:  n = 99900;  break;
408 	case 1000000: n = 999000; break;
409 	}
410 	if (n < 10000)        printf ("%d.%d", n/1000, n/10%100);
411 	else if (n < 100000)  printf ("%d.%d", n/1000, n/100%10);
412 	else if (n < 1000000) printf ("%d.", n/1000);
413 	else                  printf ("%d", n/1000);
414 }
415 
416 static void
print_e1_stats(int fd,int need_header)417 print_e1_stats (int fd, int need_header)
418 {
419 	struct e1_statistics st;
420 	int i, maxi;
421 
422 	if (need_header)
423 		printf ("Chan\t Unav/Degr  Bpv/Fsyn  CRC/RCRC  Err/Lerr  Sev/Bur   Oof/Slp  Status\n");
424 
425 	if (ioctl (fd, SERIAL_GETESTAT, &st) < 0)
426 		return;
427 	printf ("%s\t", chan_name);
428 
429 	/* Unavailable seconds, degraded minutes */
430 	print_frac (0, st.currnt.uas, st.cursec);
431 	print_frac (1, 60 * st.currnt.dm, st.cursec);
432 
433 	/* Bipolar violations, frame sync errors */
434 	print_frac (0, st.currnt.bpv, st.cursec);
435 	print_frac (1, st.currnt.fse, st.cursec);
436 
437 	/* CRC errors, remote CRC errors (E-bit) */
438 	print_frac (0, st.currnt.crce, st.cursec);
439 	print_frac (1, st.currnt.rcrce, st.cursec);
440 
441 	/* Errored seconds, line errored seconds */
442 	print_frac (0, st.currnt.es, st.cursec);
443 	print_frac (1, st.currnt.les, st.cursec);
444 
445 	/* Severely errored seconds, bursty errored seconds */
446 	print_frac (0, st.currnt.ses, st.cursec);
447 	print_frac (1, st.currnt.bes, st.cursec);
448 
449 	/* Out of frame seconds, controlled slip seconds */
450 	print_frac (0, st.currnt.oofs, st.cursec);
451 	print_frac (1, st.currnt.css, st.cursec);
452 
453 	printf (" %s\n", format_e1_status (st.status));
454 
455 	if (fflag) {
456 		/* Print total statistics. */
457 		printf ("\t");
458 		print_frac (0, st.total.uas, st.totsec);
459 		print_frac (1, 60 * st.total.dm, st.totsec);
460 
461 		print_frac (0, st.total.bpv, st.totsec);
462 		print_frac (1, st.total.fse, st.totsec);
463 
464 		print_frac (0, st.total.crce, st.totsec);
465 		print_frac (1, st.total.rcrce, st.totsec);
466 
467 		print_frac (0, st.total.es, st.totsec);
468 		print_frac (1, st.total.les, st.totsec);
469 
470 		print_frac (0, st.total.ses, st.totsec);
471 		print_frac (1, st.total.bes, st.totsec);
472 
473 		print_frac (0, st.total.oofs, st.totsec);
474 		print_frac (1, st.total.css, st.totsec);
475 
476 		printf (" -- Total\n");
477 
478 		/* Print 24-hour history. */
479 		maxi = (st.totsec - st.cursec) / 900;
480 		if (maxi > 48)
481 			maxi = 48;
482 		for (i=0; i<maxi; ++i) {
483 			printf ("       ");
484 			print_frac (0, st.interval[i].uas, 15*60);
485 			print_frac (1, 60 * st.interval[i].dm, 15*60);
486 
487 			print_frac (0, st.interval[i].bpv, 15*60);
488 			print_frac (1, st.interval[i].fse, 15*60);
489 
490 			print_frac (0, st.interval[i].crce, 15*60);
491 			print_frac (1, st.interval[i].rcrce, 15*60);
492 
493 			print_frac (0, st.interval[i].es, 15*60);
494 			print_frac (1, st.interval[i].les, 15*60);
495 
496 			print_frac (0, st.interval[i].ses, 15*60);
497 			print_frac (1, st.interval[i].bes, 15*60);
498 
499 			print_frac (0, st.interval[i].oofs, 15*60);
500 			print_frac (1, st.interval[i].css, 15*60);
501 
502 			if (i < 3)
503 				printf (" -- %dm\n", (i+1)*15);
504 			else
505 				printf (" -- %dh %dm\n", (i+1)/4, (i+1)%4*15);
506 		}
507 	}
508 }
509 
510 static char *
format_e3_status(unsigned long status)511 format_e3_status (unsigned long status)
512 {
513 	static char buf [80];
514 
515 	buf[0] = 0;
516 	if (status & E3_LOS)     strcat (buf, ",LOS");
517 	if (status & E3_TXE)     strcat (buf, ",XMIT");
518 	if (buf[0] == ',')
519 		return buf+1;
520 	return "Ok";
521 }
522 
523 static char *
format_e3_cv(unsigned long cv,unsigned long baud,unsigned long atime)524 format_e3_cv (unsigned long cv, unsigned long baud, unsigned long atime)
525 {
526 	static char buf[80];
527 
528 	if (!cv || !baud || !atime)
529 		sprintf (buf, "         -         ");
530 	else
531 		sprintf (buf, "%10lu (%.1e)", cv, (double)cv/baud/atime);
532 	return buf;
533 }
534 
535 static void
print_e3_stats(int fd,int need_header)536 print_e3_stats (int fd, int need_header)
537 {
538 	struct e3_statistics st;
539 	int i, maxi;
540 	long baud;
541 
542 	if (need_header)
543 		printf ("Chan\t--Code Violations---\t\t\t\t\t ----Status----\n");
544 
545 	if (ioctl (fd, SERIAL_GETE3STAT, &st) < 0 ||
546 	    ioctl (fd, SERIAL_GETBAUD, &baud) < 0)
547 		return;
548 
549 	if (!st.cursec)
550 		st.cursec = 1;
551 
552 	printf ("%s\t%s\t\t\t\t\t", chan_name,
553 		format_e3_cv (st.ccv, baud, st.cursec));
554 
555 	printf (" %s\n", format_e3_status (st.status));
556 
557 
558 	if (uflag) {
559 		/* Print total statistics. */
560 		printf ("\t%s\t\t\t\t\t",
561 			format_e3_cv (st.tcv, baud, st.totsec));
562 		printf (" -- Total\n");
563 
564 		/* Print 24-hour history. */
565 		maxi = (st.totsec - st.cursec) / 900;
566 		if (maxi > 48)
567 			maxi = 48;
568 		for (i=0; i<maxi; ++i) {
569 			printf ("\t%s\t\t\t\t\t",
570 				format_e3_cv (st.icv[i], baud, 15*60));
571 			if (i < 3)
572 				printf (" -- %2dm\n", (i+1)*15);
573 			else
574 				printf (" -- %2dh %2dm\n", (i+1)/4, (i+1)%4*15);
575 		}
576 	}
577 }
578 
579 static void
print_chan(int fd)580 print_chan (int fd)
581 {
582 	char protocol [8];
583 	char cfg;
584 	int loop, dpll, nrzi, invclk, clk, higain, phony, use16, crc4;
585 	int level, keepalive, debug, port, invrclk, invtclk, unfram, monitor;
586 	int cable, dir, scrambler, ami, mtu;
587 	int cablen, rloop, rqlen;
588 	long baud, timeslots, subchan;
589 	int protocol_valid, baud_valid, loop_valid, use16_valid, crc4_valid;
590 	int dpll_valid, nrzi_valid, invclk_valid, clk_valid, phony_valid;
591 	int timeslots_valid, subchan_valid, higain_valid, level_valid;
592 	int keepalive_valid, debug_valid, cfg_valid, port_valid;
593 	int invrclk_valid, invtclk_valid, unfram_valid, monitor_valid;
594 	int cable_valid, dir_valid, scrambler_valid, ami_valid, mtu_valid;
595 	int cablen_valid, rloop_valid, rqlen_valid;
596 
597 	protocol_valid  = ioctl (fd, SERIAL_GETPROTO, &protocol) >= 0;
598 	cfg_valid       = ioctl (fd, SERIAL_GETCFG, &cfg) >= 0;
599 	baud_valid      = ioctl (fd, SERIAL_GETBAUD, &baud) >= 0;
600 	loop_valid      = ioctl (fd, SERIAL_GETLOOP, &loop) >= 0;
601 	dpll_valid      = ioctl (fd, SERIAL_GETDPLL, &dpll) >= 0;
602 	nrzi_valid      = ioctl (fd, SERIAL_GETNRZI, &nrzi) >= 0;
603 	invclk_valid    = ioctl (fd, SERIAL_GETINVCLK, &invclk) >= 0;
604 	invrclk_valid	= ioctl (fd, SERIAL_GETINVRCLK, &invrclk) >= 0;
605 	invtclk_valid	= ioctl (fd, SERIAL_GETINVTCLK, &invtclk) >= 0;
606 	clk_valid       = ioctl (fd, SERIAL_GETCLK, &clk) >= 0;
607 	timeslots_valid = ioctl (fd, SERIAL_GETTIMESLOTS, &timeslots) >= 0;
608 	subchan_valid   = ioctl (fd, SERIAL_GETSUBCHAN, &subchan) >= 0;
609 	higain_valid    = ioctl (fd, SERIAL_GETHIGAIN, &higain) >= 0;
610 	phony_valid     = ioctl (fd, SERIAL_GETPHONY, &phony) >= 0;
611 	unfram_valid    = ioctl (fd, SERIAL_GETUNFRAM, &unfram) >= 0;
612 	monitor_valid   = ioctl (fd, SERIAL_GETMONITOR, &monitor) >= 0;
613 	use16_valid     = ioctl (fd, SERIAL_GETUSE16, &use16) >= 0;
614 	crc4_valid      = ioctl (fd, SERIAL_GETCRC4, &crc4) >= 0;
615 	ami_valid	= ioctl (fd, SERIAL_GETLCODE, &ami) >= 0;
616 	level_valid     = ioctl (fd, SERIAL_GETLEVEL, &level) >= 0;
617 	keepalive_valid = ioctl (fd, SERIAL_GETKEEPALIVE, &keepalive) >= 0;
618 	debug_valid     = ioctl (fd, SERIAL_GETDEBUG, &debug) >= 0;
619 	port_valid	= ioctl (fd, SERIAL_GETPORT, &port) >= 0;
620 	cable_valid	= ioctl (fd, SERIAL_GETCABLE, &cable) >= 0;
621 	dir_valid	= ioctl (fd, SERIAL_GETDIR, &dir) >= 0;
622 	scrambler_valid	= ioctl (fd, SERIAL_GETSCRAMBLER, &scrambler) >= 0;
623 	cablen_valid	= ioctl (fd, SERIAL_GETCABLEN, &cablen) >= 0;
624 	rloop_valid	= ioctl (fd, SERIAL_GETRLOOP, &rloop) >= 0;
625 	mtu_valid	= ioctl (fd, SERIAL_GETMTU, &mtu) >= 0;
626 	rqlen_valid	= ioctl (fd, SERIAL_GETRQLEN, &rqlen) >= 0;
627 
628 	printf ("%s", chan_name);
629 	if (port_valid)
630 		switch (port) {
631 		case 0:	printf (" (rs232)"); break;
632 		case 1:	printf (" (v35)"); break;
633 		case 2:	printf (" (rs530)"); break;
634 		}
635 	else if (cable_valid)
636 		switch (cable) {
637 		case 0:	printf (" (rs232)"); break;
638 		case 1:	printf (" (v35)"); break;
639 		case 2:	printf (" (rs530)"); break;
640 		case 3:	printf (" (x21)"); break;
641 		case 4:	printf (" (rs485)"); break;
642 		case 9:	printf (" (no cable)"); break;
643 		}
644 	if (debug_valid && debug)
645 		printf (" debug=%d", debug);
646 	if (protocol_valid && *protocol)
647 		printf (" %.8s", protocol);
648 	else
649 		printf (" idle");
650 	if (cablen_valid)
651 		printf (" cablen=%s", cablen ? "on" : "off");
652 	if (keepalive_valid)
653 		printf (" keepalive=%s", keepalive ? "on" : "off");
654 
655 	if (cfg_valid)
656 		switch (cfg) {
657 		case 'a' :	printf (" cfg=A");	break;
658 		case 'b' :	printf (" cfg=B");	break;
659 		case 'c' :	printf (" cfg=C");	break;
660 		case 'd' :	printf (" cfg=D");	break;
661 		default  :	printf (" cfg=unknown");
662 		}
663 	if (dir_valid)
664 		printf (" dir=%d", dir);
665 
666 	if (baud_valid) {
667 		if (baud)
668 			printf (" %ld", baud);
669 		else
670 			printf (" extclock");
671 	}
672 	if (mtu_valid)
673 		printf (" mtu=%d", mtu);
674 
675 	if (aflag && rqlen_valid)
676 		printf (" rqlen=%d", rqlen);
677 
678 	if (clk_valid)
679 		switch (clk) {
680 		case E1CLK_INTERNAL:	  printf (" syn=int");     break;
681 		case E1CLK_RECEIVE:	  printf (" syn=rcv");     break;
682 		case E1CLK_RECEIVE_CHAN0: printf (" syn=rcv0");    break;
683 		case E1CLK_RECEIVE_CHAN1: printf (" syn=rcv1");    break;
684 		case E1CLK_RECEIVE_CHAN2: printf (" syn=rcv2");    break;
685 		case E1CLK_RECEIVE_CHAN3: printf (" syn=rcv3");    break;
686 		default:                  printf (" syn=%d", clk); break;
687 		}
688 
689 	if (dpll_valid)
690 		printf (" dpll=%s", dpll ? "on" : "off");
691 	if (nrzi_valid)
692 		printf (" nrzi=%s", nrzi ? "on" : "off");
693 	if (invclk_valid)
694 		printf (" invclk=%s", invclk ? "on" : "off");
695 	if (invrclk_valid)
696 		printf (" invrclk=%s", invrclk ? "on" : "off");
697 	if (invtclk_valid)
698 		printf (" invtclk=%s", invtclk ? "on" : "off");
699 	if (unfram_valid)
700 		printf (" unfram=%s", unfram ? "on" : "off");
701 	if (use16_valid)
702 		printf (" use16=%s", use16 ? "on" : "off");
703 	if (aflag) {
704 		if (crc4_valid)
705 			printf (" crc4=%s", crc4 ? "on" : "off");
706 		if (higain_valid)
707 			printf (" higain=%s", higain ? "on" : "off");
708 		if (monitor_valid)
709 			printf (" monitor=%s", monitor ? "on" : "off");
710 		if (phony_valid)
711 			printf (" phony=%s", phony ? "on" : "off");
712 		if (scrambler_valid)
713 			printf (" scrambler=%s", scrambler ? "on" : "off");
714 		if (loop_valid)
715 			printf (" loop=%s", loop ? "on" : "off");
716 		if (rloop_valid)
717 			printf (" rloop=%s", rloop ? "on" : "off");
718 		if (ami_valid)
719 			printf (" ami=%s", ami ? "on" : "off");
720 	}
721 	if (timeslots_valid)
722 		printf (" ts=%s", format_timeslots (timeslots));
723 	if (subchan_valid)
724 		printf (" pass=%s", format_timeslots (subchan));
725 	if (level_valid)
726 		printf (" (level=-%.1fdB)", level / 10.0);
727 	printf ("\n");
728 }
729 
730 static void
setup_chan(int fd,int argc,char ** argv)731 setup_chan (int fd, int argc, char **argv)
732 {
733 	int i, mode, loop, nrzi, dpll, invclk, phony, use16, crc4, unfram, ami;
734 	int higain, clk, keepalive, debug, port, dlci, invrclk, invtclk;
735 	int monitor, dir, scrambler, rloop, cablen;
736 	int mode_valid;
737 	long baud, timeslots, mtu, rqlen;
738 
739 	for (i=0; i<argc; ++i) {
740 		if (argv[i][0] >= '0' && argv[i][0] <= '9') {
741 			baud = strtol (argv[i], 0, 10);
742 			ioctl (fd, SERIAL_SETBAUD, &baud);
743 		} else if (strcasecmp ("extclock", argv[i]) == 0) {
744 			baud = 0;
745 			ioctl (fd, SERIAL_SETBAUD, &baud);
746 		} else if (strncasecmp ("cfg=", argv[i], 4) == 0) {
747 			if (strncasecmp ("a", argv[i]+4, 1) == 0)
748 				ioctl (fd, SERIAL_SETCFG, "a");
749 			else if (strncasecmp ("b", argv[i]+4, 1) == 0)
750 				ioctl (fd, SERIAL_SETCFG, "b");
751 			else if (strncasecmp ("c", argv[i]+4, 1) == 0)
752 				ioctl (fd, SERIAL_SETCFG, "c");
753 			else if (strncasecmp ("d", argv[i]+4, 1) == 0)
754 				ioctl (fd, SERIAL_SETCFG, "d");
755 			else {
756 				fprintf (stderr, "invalid cfg\n");
757 				exit (-1);
758 			}
759 		} else if (strcasecmp ("idle", argv[i]) == 0)
760 			ioctl (fd, SERIAL_SETPROTO, "\0\0\0\0\0\0\0");
761 		else if (strcasecmp ("async", argv[i]) == 0) {
762 			mode = SERIAL_ASYNC;
763 			if (ioctl (fd, SERIAL_SETMODE, &mode) >= 0)
764 				ioctl (fd, SERIAL_SETPROTO, "async\0\0");
765 		} else if (strcasecmp ("sync", argv[i]) == 0) {
766 			mode = SERIAL_HDLC;
767 			if (ioctl (fd, SERIAL_SETMODE, &mode) >= 0)
768 				ioctl (fd, SERIAL_SETPROTO, "sync\0\0\0");
769 		} else if (strcasecmp ("cisco", argv[i]) == 0) {
770 			mode = SERIAL_HDLC;
771 			ioctl (fd, SERIAL_SETMODE, &mode);
772 			ioctl (fd, SERIAL_SETPROTO, "cisco\0\0");
773 		} else if (strcasecmp ("rbrg", argv[i]) == 0) {
774 			mode = SERIAL_HDLC;
775 			ioctl (fd, SERIAL_SETMODE, &mode);
776 			ioctl (fd, SERIAL_SETPROTO, "rbrg\0\0\0");
777 		} else if (strcasecmp ("raw", argv[i]) == 0) {
778 			mode = SERIAL_HDLC;
779 			ioctl (fd, SERIAL_SETMODE, &mode);
780 			ioctl (fd, SERIAL_SETPROTO, "raw\0\0\0\0");
781 		} else if (strcasecmp ("packet", argv[i]) == 0) {
782 			mode = SERIAL_HDLC;
783 			ioctl (fd, SERIAL_SETMODE, &mode);
784 			ioctl (fd, SERIAL_SETPROTO, "packet\0");
785 		} else if (strcasecmp ("ppp", argv[i]) == 0) {
786 			/* check that ppp line discipline is present */
787 			if (ppp_ok ()) {
788 				mode = SERIAL_HDLC;
789 				ioctl (fd, SERIAL_SETMODE, &mode);
790 				ioctl (fd, SERIAL_SETPROTO, "ppp\0\0\0\0");
791 			}
792 		} else if (strncasecmp ("keepalive=", argv[i], 10) == 0) {
793 			keepalive = (strcasecmp ("on", argv[i] + 10) == 0);
794 			ioctl (fd, SERIAL_SETKEEPALIVE, &keepalive);
795 		} else if (strcasecmp ("fr", argv[i]) == 0) {
796 			mode = SERIAL_HDLC;
797 			ioctl (fd, SERIAL_SETMODE, &mode);
798 			ioctl (fd, SERIAL_SETPROTO, "fr\0\0\0\0\0");
799 		} else if (strcasecmp ("zaptel", argv[i]) == 0) {
800 			mode = SERIAL_HDLC;
801 			ioctl (fd, SERIAL_SETMODE, &mode);
802 			ioctl (fd, SERIAL_SETPROTO, "zaptel\0");
803 		} else if (strncasecmp ("debug=", argv[i], 6) == 0) {
804 			debug = strtol (argv[i]+6, 0, 10);
805 			mode_valid = ioctl (fd, SERIAL_GETMODE, &mode) >= 0;
806 			if (!mode_valid || mode != SERIAL_ASYNC) {
807 				if (debug == 0) {
808 					set_debug_ifconfig(0);
809 				} else {
810 					ioctl (fd, SERIAL_SETDEBUG, &debug);
811 					set_debug_ifconfig(1);
812 				}
813 			} else {
814 				ioctl (fd, SERIAL_SETDEBUG, &debug);
815 			}
816 		} else if (strncasecmp ("loop=", argv[i], 5) == 0) {
817 			loop = (strcasecmp ("on", argv[i] + 5) == 0);
818 			ioctl (fd, SERIAL_SETLOOP, &loop);
819 		} else if (strncasecmp ("rloop=", argv[i], 6) == 0) {
820 			rloop = (strcasecmp ("on", argv[i] + 6) == 0);
821 			ioctl (fd, SERIAL_SETRLOOP, &rloop);
822 		} else if (strncasecmp ("dpll=", argv[i], 5) == 0) {
823 			dpll = (strcasecmp ("on", argv[i] + 5) == 0);
824 			ioctl (fd, SERIAL_SETDPLL, &dpll);
825 		} else if (strncasecmp ("nrzi=", argv[i], 5) == 0) {
826 			nrzi = (strcasecmp ("on", argv[i] + 5) == 0);
827 			ioctl (fd, SERIAL_SETNRZI, &nrzi);
828 		} else if (strncasecmp ("invclk=", argv[i], 7) == 0) {
829 			invclk = (strcasecmp ("on", argv[i] + 7) == 0);
830 			ioctl (fd, SERIAL_SETINVCLK, &invclk);
831 		} else if (strncasecmp ("invrclk=", argv[i], 8) == 0) {
832 			invrclk = (strcasecmp ("on", argv[i] + 8) == 0);
833 			ioctl (fd, SERIAL_SETINVRCLK, &invrclk);
834 		} else if (strncasecmp ("invtclk=", argv[i], 8) == 0) {
835 			invtclk = (strcasecmp ("on", argv[i] + 8) == 0);
836 			ioctl (fd, SERIAL_SETINVTCLK, &invtclk);
837 		} else if (strncasecmp ("higain=", argv[i], 7) == 0) {
838 			higain = (strcasecmp ("on", argv[i] + 7) == 0);
839 			ioctl (fd, SERIAL_SETHIGAIN, &higain);
840 		} else if (strncasecmp ("phony=", argv[i], 6) == 0) {
841 			phony = (strcasecmp ("on", argv[i] + 6) == 0);
842 			ioctl (fd, SERIAL_SETPHONY, &phony);
843 		} else if (strncasecmp ("unfram=", argv[i], 7) == 0) {
844 			unfram = (strcasecmp ("on", argv[i] + 7) == 0);
845 			ioctl (fd, SERIAL_SETUNFRAM, &unfram);
846 		} else if (strncasecmp ("scrambler=", argv[i], 10) == 0) {
847 			scrambler = (strcasecmp ("on", argv[i] + 10) == 0);
848 			ioctl (fd, SERIAL_SETSCRAMBLER, &scrambler);
849 		} else if (strncasecmp ("monitor=", argv[i], 8) == 0) {
850 			monitor = (strcasecmp ("on", argv[i] + 8) == 0);
851 			ioctl (fd, SERIAL_SETMONITOR, &monitor);
852 		} else if (strncasecmp ("use16=", argv[i], 6) == 0) {
853 			use16 = (strcasecmp ("on", argv[i] + 6) == 0);
854 			ioctl (fd, SERIAL_SETUSE16, &use16);
855 		} else if (strncasecmp ("crc4=", argv[i], 5) == 0) {
856 			crc4 = (strcasecmp ("on", argv[i] + 5) == 0);
857 			ioctl (fd, SERIAL_SETCRC4, &crc4);
858 		} else if (strncasecmp ("ami=", argv[i], 4) == 0) {
859 			ami = (strcasecmp ("on", argv[i] + 4) == 0);
860 			ioctl (fd, SERIAL_SETLCODE, &ami);
861 		} else if (strncasecmp ("mtu=", argv[i], 4) == 0) {
862 			mtu = strtol (argv[i] + 4, 0, 10);
863 			ioctl (fd, SERIAL_SETMTU, &mtu);
864 		} else if (strncasecmp ("rqlen=", argv[i], 6) == 0) {
865 			rqlen = strtol (argv[i] + 6, 0, 10);
866 			ioctl (fd, SERIAL_SETRQLEN, &rqlen);
867 		} else if (strcasecmp ("syn=int", argv[i]) == 0) {
868 			clk = E1CLK_INTERNAL;
869 			ioctl (fd, SERIAL_SETCLK, &clk);
870 		} else if (strcasecmp ("syn=rcv", argv[i]) == 0) {
871 			clk = E1CLK_RECEIVE;
872 			ioctl (fd, SERIAL_SETCLK, &clk);
873 		} else if (strcasecmp ("syn=rcv0", argv[i]) == 0) {
874 			clk = E1CLK_RECEIVE_CHAN0;
875 			ioctl (fd, SERIAL_SETCLK, &clk);
876 		} else if (strcasecmp ("syn=rcv1", argv[i]) == 0) {
877 			clk = E1CLK_RECEIVE_CHAN1;
878 			ioctl (fd, SERIAL_SETCLK, &clk);
879 		} else if (strcasecmp ("syn=rcv2", argv[i]) == 0) {
880 			clk = E1CLK_RECEIVE_CHAN2;
881 			ioctl (fd, SERIAL_SETCLK, &clk);
882 		} else if (strcasecmp ("syn=rcv3", argv[i]) == 0) {
883 			clk = E1CLK_RECEIVE_CHAN3;
884 			ioctl (fd, SERIAL_SETCLK, &clk);
885 		} else if (strncasecmp ("ts=", argv[i], 3) == 0) {
886 			timeslots = scan_timeslots (argv[i] + 3);
887 			ioctl (fd, SERIAL_SETTIMESLOTS, &timeslots);
888 		} else if (strncasecmp ("pass=", argv[i], 5) == 0) {
889 			timeslots = scan_timeslots (argv[i] + 5);
890 			ioctl (fd, SERIAL_SETSUBCHAN, &timeslots);
891 		} else if (strncasecmp ("dlci", argv[i], 4) == 0) {
892 			dlci = strtol (argv[i]+4, 0, 10);
893 			ioctl (fd, SERIAL_ADDDLCI, &dlci);
894 		} else if (strncasecmp ("dir=", argv[i], 4) == 0) {
895 			dir = strtol (argv[i]+4, 0, 10);
896 			ioctl (fd, SERIAL_SETDIR, &dir);
897 		} else if (strncasecmp ("port=", argv[i], 5) == 0) {
898 			if (strncasecmp ("rs232", argv[i]+5, 5) == 0) {
899 				port = 0;
900 				ioctl (fd, SERIAL_SETPORT, &port);
901 			} else if (strncasecmp ("v35", argv[i]+5, 3) == 0) {
902 				port = 1;
903 				ioctl (fd, SERIAL_SETPORT, &port);
904 			} else if (strncasecmp ("rs449", argv[i]+5, 5) == 0) {
905 				port = 2;
906 				ioctl (fd, SERIAL_SETPORT, &port);
907 			} else
908 				fprintf (stderr, "invalid port type\n");
909 				exit (-1);
910 #if 1
911 		} else if (strcasecmp ("reset", argv[i]) == 0) {
912 			ioctl (fd, SERIAL_RESET, 0);
913 		} else if (strcasecmp ("hwreset", argv[i]) == 0) {
914 			ioctl (fd, SERIAL_HARDRESET, 0);
915 #endif
916 		} else if (strncasecmp ("cablen=", argv[i], 7) == 0) {
917 			loop = (strcasecmp ("on", argv[i] + 7) == 0);
918 			ioctl (fd, SERIAL_SETCABLEN, &cablen);
919 		}
920 	}
921 }
922 
923 static void
get_mask(void)924 get_mask (void)
925 {
926 #ifdef __linux__
927 	int fd;
928 
929 	fd = open ("/dev/serial/ctl0", 0);
930 	if (fd < 0) {
931 		perror ("/dev/serial/ctl0");
932 		exit (-1);
933 	}
934 	if (ioctl (fd, SERIAL_GETREGISTERED, &mask) < 0) {
935 		perror ("getting list of channels");
936 		exit (-1);
937 	}
938 	close (fd);
939 #else
940 	int fd, fd1, fd2, fd3, i;
941 	char buf [80];
942 
943 	for (i=0, fd=-1; i<12 && fd<0; i++) {
944 		sprintf (buf, "/dev/cx%d", i*4);
945 		fd = open (buf, 0);
946 	}
947 
948 	for (i=0, fd1=-1; i<3 && fd1<0; i++) {
949 		sprintf (buf, "/dev/ct%d", i*2);
950 		fd1 = open (buf, 0);
951 	}
952 
953 	for (i=0, fd2=-1; i<3 && fd2<0; i++) {
954 		sprintf (buf, "/dev/cp%d", i*4);
955 		fd2 = open (buf, 0);
956 	}
957 
958 	/* Try only one */
959 	for (i=0, fd3=-1; i<1 && fd3<0; i++) {
960 		sprintf (buf, "/dev/ce%d", i*4);
961 		fd3 = open (buf, 0);
962 	}
963 
964 	if ((fd < 0) && (fd1 < 0) && (fd2 < 0) && (fd3 < 0)) {
965 		fprintf (stderr, "No Cronyx adapters installed\n");
966 		exit (-1);
967 	}
968 
969 	if (fd >= 0) {
970 		if (ioctl (fd, SERIAL_GETREGISTERED, &mask) < 0) {
971 			perror ("getting list of channels");
972 			exit (-1);
973 		}
974 		close (fd);
975 	}
976 
977 	if (fd1 >= 0) {
978 		if (ioctl (fd1, SERIAL_GETREGISTERED, (mask+16)) < 0) {
979 			perror ("getting list of channels");
980 			exit (-1);
981 		}
982 		close (fd1);
983 	}
984 
985 	if (fd2 >= 0) {
986 		if (ioctl (fd2, SERIAL_GETREGISTERED, (mask+32)) < 0) {
987 			perror ("getting list of channels");
988 			exit (-1);
989 		}
990 		close (fd2);
991 	}
992 
993 	if (fd3 >= 0) {
994 		if (ioctl (fd3, SERIAL_GETREGISTERED, (mask+48)) < 0) {
995 			perror ("getting list of channels");
996 			exit (-1);
997 		}
998 		close (fd3);
999 	}
1000 #endif
1001 }
1002 
1003 static int
open_chan_ctl(int num)1004 open_chan_ctl (int num)
1005 {
1006 	char device [80];
1007 	int fd;
1008 
1009 #ifdef __linux__
1010 	sprintf (device, "/dev/serial/ctl%d", num);
1011 #else
1012 	switch (adapter_type) {
1013 	case 0:
1014 		sprintf (device, "/dev/cx%d", num);
1015 		break;
1016 	case 1:
1017 		sprintf (device, "/dev/ct%d", num);
1018 		break;
1019 	case 2:
1020 		sprintf (device, "/dev/cp%d", num);
1021 		break;
1022 	case 3:
1023 		sprintf (device, "/dev/ce%d", num);
1024 		break;
1025 	}
1026 #endif
1027 	fd = open (device, 0);
1028 	if (fd < 0) {
1029 		if (errno == ENODEV)
1030 			fprintf (stderr, "chan%d: not configured\n", num);
1031 		else
1032 			perror (device);
1033 		exit (-1);
1034 	}
1035 #ifdef __linux__
1036 	if (ioctl (fd, SERIAL_GETNAME, &chan_name) < 0)
1037 		sprintf (chan_name, "chan%d", num);
1038 #else
1039 	switch (adapter_type) {
1040 	case 0: sprintf (chan_name, "cx%d", num); break;
1041 	case 1: sprintf (chan_name, "ct%d", num); break;
1042 	case 2: sprintf (chan_name, "cp%d", num); break;
1043 	case 3: sprintf (chan_name, "ce%d", num); break;
1044 	}
1045 #endif
1046 	return fd;
1047 }
1048 
1049 int
main(int argc,char ** argv)1050 main (int argc, char **argv)
1051 {
1052 	char *p;
1053 	int fd, need_header, chan_num;
1054 
1055 	if (argc > 1 && strcmp(argv[1], "help") == 0)
1056 		usage();
1057 
1058 	for (;;) {
1059 		switch (getopt (argc, argv, "mseftucviax")) {
1060 		case -1:
1061 			break;
1062 		case 'a':
1063 			++aflag;
1064 			continue;
1065 		case 'm':
1066 			++mflag;
1067 			continue;
1068 		case 's':
1069 			++sflag;
1070 			continue;
1071 		case 'e':
1072 			++eflag;
1073 			continue;
1074 		case 'f':
1075 			++eflag;
1076 			++fflag;
1077 			continue;
1078 		case 't':
1079 			++tflag;
1080 			continue;
1081 		case 'u':
1082 			++tflag;
1083 			++uflag;
1084 			continue;
1085 		case 'c':
1086 			++cflag;
1087 			continue;
1088 		case 'v':
1089 			++vflag;
1090 			continue;
1091 		case 'i':
1092 			++iflag;
1093 			continue;
1094 		case 'x':
1095 			++xflag;
1096 			continue;
1097 		default:
1098 			usage();
1099 		}
1100 		break;
1101 	}
1102 	argc -= optind;
1103 	argv += optind;
1104 
1105 	if (argc <= 0) {
1106 		get_mask ();
1107 		need_header = 1;
1108 		adapter_type = 0;
1109 #ifndef __linux__
1110 		for (; adapter_type < 4; ++adapter_type)
1111 #endif
1112 		{
1113 		for (chan_num=0; chan_num<MAXCHAN; ++chan_num)
1114 			if (mask[adapter_type*16+chan_num/8] & 1 << (chan_num & 7)) {
1115 				fd = open_chan_ctl (chan_num);
1116 				if (vflag) {
1117 #ifdef __linux__
1118 				char buf[256];
1119 				if (ioctl (fd, SERIAL_GETVERSIONSTRING, &buf) >= 0) {
1120 					printf ("Version: %s\n", buf);
1121 					close (fd);
1122 					return (0);
1123 				}
1124 #endif
1125 				}
1126 				if (iflag) {
1127 					print_chan (fd);
1128 					print_ifconfig (fd);
1129 				} else if (sflag||xflag)
1130 					print_stats (fd, need_header);
1131 				else if (mflag)
1132 					print_modems (fd, need_header);
1133 				else if (eflag)
1134 					print_e1_stats (fd, need_header);
1135 				else if (tflag)
1136 					print_e3_stats (fd, need_header);
1137 				else if (cflag)
1138 					clear_stats (fd);
1139 				else
1140 					print_chan (fd);
1141 				close (fd);
1142 				need_header = 0;
1143 			}
1144 		}
1145 		return (0);
1146 	}
1147 
1148 	p = argv[0] + strlen (argv[0]);
1149 	while (p > argv[0] && p[-1] >= '0' && p[-1] <= '9')
1150 		--p;
1151 	chan_num = strtol (p, 0, 10);
1152 #ifndef __linux__
1153 	if (strncasecmp ("cx", argv[0], 2)==0)
1154 		adapter_type = 0;
1155 	else if (strncasecmp ("ct", argv[0], 2)==0)
1156 		adapter_type = 1;
1157 	else if (strncasecmp ("cp", argv[0], 2)==0)
1158 		adapter_type = 2;
1159 	else if (strncasecmp ("ce", argv[0], 2)==0)
1160 		adapter_type = 3;
1161 	else {
1162 		fprintf (stderr, "Wrong channel name\n");
1163 		exit (-1);
1164 	}
1165 #endif
1166 	argc--;
1167 	argv++;
1168 
1169 	fd = open_chan_ctl (chan_num);
1170 	if (vflag) {
1171 #ifdef __linux__
1172 		char buf[256];
1173 		if (ioctl (fd, SERIAL_GETVERSIONSTRING, &buf) >= 0)
1174 			printf ("Version: %s\n", buf);
1175 #endif
1176 	}
1177 	if (iflag) {
1178 		print_chan (fd);
1179 		print_ifconfig (fd);
1180 		close (fd);
1181 		return (0);
1182 	}
1183 	if (sflag||xflag) {
1184 		print_stats (fd, 1);
1185 		close (fd);
1186 		return (0);
1187 	}
1188 	if (mflag) {
1189 		print_modems (fd, 1);
1190 		close (fd);
1191 		return (0);
1192 	}
1193 	if (eflag) {
1194 		print_e1_stats (fd, 1);
1195 		close (fd);
1196 		return (0);
1197 	}
1198 	if (tflag) {
1199 		print_e3_stats (fd, 1);
1200 		close (fd);
1201 		return (0);
1202 	}
1203 	if (cflag) {
1204 		clear_stats (fd);
1205 		close (fd);
1206 		return (0);
1207 	}
1208 	if (argc > 0)
1209 		setup_chan (fd, argc, argv);
1210 	else
1211 		print_chan (fd);
1212 	close (fd);
1213 	return (0);
1214 }
1215