xref: /netbsd-src/usr.bin/tip/aculib/biz31.c (revision ffe34450414a71a1dea7aa084cc0e2fae0724115)
1*ffe34450Schristos /*	$NetBSD: biz31.c,v 1.12 2006/12/14 17:09:43 christos Exp $	*/
239801cccSjtc 
361f28255Scgd /*
439801cccSjtc  * Copyright (c) 1983, 1993
539801cccSjtc  *	The Regents of the University of California.  All rights reserved.
661f28255Scgd  *
761f28255Scgd  * Redistribution and use in source and binary forms, with or without
861f28255Scgd  * modification, are permitted provided that the following conditions
961f28255Scgd  * are met:
1061f28255Scgd  * 1. Redistributions of source code must retain the above copyright
1161f28255Scgd  *    notice, this list of conditions and the following disclaimer.
1261f28255Scgd  * 2. Redistributions in binary form must reproduce the above copyright
1361f28255Scgd  *    notice, this list of conditions and the following disclaimer in the
1461f28255Scgd  *    documentation and/or other materials provided with the distribution.
1589aaa1bbSagc  * 3. Neither the name of the University nor the names of its contributors
1661f28255Scgd  *    may be used to endorse or promote products derived from this software
1761f28255Scgd  *    without specific prior written permission.
1861f28255Scgd  *
1961f28255Scgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2061f28255Scgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2161f28255Scgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2261f28255Scgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2361f28255Scgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2461f28255Scgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2561f28255Scgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2661f28255Scgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2761f28255Scgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2861f28255Scgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2961f28255Scgd  * SUCH DAMAGE.
3061f28255Scgd  */
3161f28255Scgd 
32e37283e1Slukem #include <sys/cdefs.h>
3361f28255Scgd #ifndef lint
3439801cccSjtc #if 0
3539801cccSjtc static char sccsid[] = "@(#)biz31.c	8.1 (Berkeley) 6/6/93";
3639801cccSjtc #endif
37*ffe34450Schristos __RCSID("$NetBSD: biz31.c,v 1.12 2006/12/14 17:09:43 christos Exp $");
3861f28255Scgd #endif /* not lint */
3961f28255Scgd 
4061f28255Scgd #include "tip.h"
4161f28255Scgd 
4261f28255Scgd #define MAXRETRY	3		/* sync up retry count */
4361f28255Scgd #define DISCONNECT_CMD	"\21\25\11\24"	/* disconnection string */
4461f28255Scgd 
45*ffe34450Schristos static	void sigALRM(int);
4661f28255Scgd static	int timeout = 0;
4761f28255Scgd static	jmp_buf timeoutbuf;
4861f28255Scgd 
49*ffe34450Schristos static void echo(const char *);
50*ffe34450Schristos static int detect(const char *);
51*ffe34450Schristos static void flush(const char *);
52*ffe34450Schristos static int bizsync(int);
53*ffe34450Schristos 
5461f28255Scgd /*
5561f28255Scgd  * Dial up on a BIZCOMP Model 1031 with either
5661f28255Scgd  * 	tone dialing (mod = "f")
5761f28255Scgd  *	pulse dialing (mod = "w")
5861f28255Scgd  */
5961f28255Scgd static int
biz_dialer(char * num,const char * mod)60*ffe34450Schristos biz_dialer(char *num, const char *mod)
6161f28255Scgd {
62e37283e1Slukem 	int connected = 0;
6361f28255Scgd 
6461f28255Scgd 	if (!bizsync(FD)) {
6561f28255Scgd 		logent(value(HOST), "", "biz", "out of sync");
66*ffe34450Schristos 		(void)printf("bizcomp out of sync\n");
6761f28255Scgd 		exit(0);
6861f28255Scgd 	}
6961f28255Scgd 	if (boolean(value(VERBOSE)))
70*ffe34450Schristos 		(void)printf("\nstarting call...");
7161f28255Scgd 	echo("#\rk$\r$\n");			/* disable auto-answer */
7261f28255Scgd 	echo("$>$.$ #\r");			/* tone/pulse dialing */
7361f28255Scgd 	echo(mod);
7461f28255Scgd 	echo("$\r$\n");
7561f28255Scgd 	echo("$>$.$ #\re$ ");			/* disconnection sequence */
7661f28255Scgd 	echo(DISCONNECT_CMD);
7761f28255Scgd 	echo("\r$\n$\r$\n");
7861f28255Scgd 	echo("$>$.$ #\rr$ ");			/* repeat dial */
7961f28255Scgd 	echo(num);
8061f28255Scgd 	echo("\r$\n");
8161f28255Scgd 	if (boolean(value(VERBOSE)))
82*ffe34450Schristos 		(void)printf("ringing...");
8361f28255Scgd 	/*
8461f28255Scgd 	 * The reply from the BIZCOMP should be:
8561f28255Scgd 	 *	`^G NO CONNECTION\r\n^G\r\n'	failure
8661f28255Scgd 	 *	` CONNECTION\r\n^G'		success
8761f28255Scgd 	 */
8861f28255Scgd 	connected = detect(" ");
8961f28255Scgd 	if (!connected)
9061f28255Scgd 		flush(" NO CONNECTION\r\n\07\r\n");
9161f28255Scgd 	else
9261f28255Scgd 		flush("CONNECTION\r\n\07");
9361f28255Scgd 	if (timeout)
9461f28255Scgd 		biz31_disconnect();	/* insurance */
9561f28255Scgd 	return (connected);
9661f28255Scgd }
9761f28255Scgd 
98*ffe34450Schristos int
99*ffe34450Schristos /*ARGSUSED*/
biz31w_dialer(char * num,char * acu __unused)100*ffe34450Schristos biz31w_dialer(char *num, char *acu __unused)
10161f28255Scgd {
10261f28255Scgd 
10361f28255Scgd 	return (biz_dialer(num, "w"));
10461f28255Scgd }
10561f28255Scgd 
106*ffe34450Schristos int
107*ffe34450Schristos /*ARGSUSED*/
biz31f_dialer(char * num,char * acu __unused)108*ffe34450Schristos biz31f_dialer(char *num, char *acu __unused)
10961f28255Scgd {
11061f28255Scgd 
11161f28255Scgd 	return (biz_dialer(num, "f"));
11261f28255Scgd }
11361f28255Scgd 
114*ffe34450Schristos void
biz31_disconnect(void)11558c2151fSperry biz31_disconnect(void)
11661f28255Scgd {
11761f28255Scgd 
118*ffe34450Schristos 	(void)write(FD, DISCONNECT_CMD, 4);
119*ffe34450Schristos 	(void)sleep(2);
120*ffe34450Schristos 	(void)tcflush(FD, TCIOFLUSH);
12161f28255Scgd }
12261f28255Scgd 
123*ffe34450Schristos void
biz31_abort(void)12458c2151fSperry biz31_abort(void)
12561f28255Scgd {
12661f28255Scgd 
127*ffe34450Schristos 	(void)write(FD, "\33", 1);
12861f28255Scgd }
12961f28255Scgd 
130*ffe34450Schristos static void
echo(const char * s)131*ffe34450Schristos echo(const char *s)
13261f28255Scgd {
13361f28255Scgd 	char c;
13461f28255Scgd 
135*ffe34450Schristos 	while ((c = *s++) != '\0')
136*ffe34450Schristos 		switch (c) {
13761f28255Scgd 		case '$':
138*ffe34450Schristos 			(void)read(FD, &c, 1);
13961f28255Scgd 			s++;
14061f28255Scgd 			break;
14161f28255Scgd 
14261f28255Scgd 		case '#':
14361f28255Scgd 			c = *s++;
144*ffe34450Schristos 			(void)write(FD, &c, 1);
14561f28255Scgd 			break;
14661f28255Scgd 
14761f28255Scgd 		default:
148*ffe34450Schristos 			(void)write(FD, &c, 1);
149*ffe34450Schristos 			(void)read(FD, &c, 1);
15061f28255Scgd 		}
15161f28255Scgd }
15261f28255Scgd 
15361f28255Scgd static void
154*ffe34450Schristos /*ARGSUSED*/
sigALRM(int signo __unused)155*ffe34450Schristos sigALRM(int signo __unused)
15661f28255Scgd {
15761f28255Scgd 
15861f28255Scgd 	timeout = 1;
15961f28255Scgd 	longjmp(timeoutbuf, 1);
16061f28255Scgd }
16161f28255Scgd 
16261f28255Scgd static int
detect(const char * s)163*ffe34450Schristos detect(const char *s)
16461f28255Scgd {
16561f28255Scgd 	sig_t f;
16661f28255Scgd 	char c;
16761f28255Scgd 
16861f28255Scgd 	f = signal(SIGALRM, sigALRM);
16961f28255Scgd 	timeout = 0;
17061f28255Scgd 	while (*s) {
17161f28255Scgd 		if (setjmp(timeoutbuf)) {
172*ffe34450Schristos 			(void)printf("\07timeout waiting for reply\n");
17361f28255Scgd 			biz31_abort();
17461f28255Scgd 			break;
17561f28255Scgd 		}
176*ffe34450Schristos 		(void)alarm((unsigned)number(value(DIALTIMEOUT)));
177*ffe34450Schristos 		(void)read(FD, &c, 1);
178*ffe34450Schristos 		(void)alarm(0);
17961f28255Scgd 		if (c != *s++)
18061f28255Scgd 			break;
18161f28255Scgd 	}
182*ffe34450Schristos 	(void)signal(SIGALRM, f);
18361f28255Scgd 	return (timeout == 0);
18461f28255Scgd }
18561f28255Scgd 
186*ffe34450Schristos static void
flush(const char * s)187*ffe34450Schristos flush(const char *s)
18861f28255Scgd {
18961f28255Scgd 	sig_t f;
19061f28255Scgd 	char c;
19161f28255Scgd 
19261f28255Scgd 	f = signal(SIGALRM, sigALRM);
19361f28255Scgd 	while (*s++) {
19461f28255Scgd 		if (setjmp(timeoutbuf))
19561f28255Scgd 			break;
196*ffe34450Schristos 		(void)alarm(10);
197*ffe34450Schristos 		(void)read(FD, &c, 1);
198*ffe34450Schristos 		(void)alarm(0);
19961f28255Scgd 	}
200*ffe34450Schristos 	(void)signal(SIGALRM, f);
20161f28255Scgd 	timeout = 0;			/* guard against disconnection */
20261f28255Scgd }
20361f28255Scgd 
20461f28255Scgd /*
20561f28255Scgd  * This convoluted piece of code attempts to get
20661f28255Scgd  *  the bizcomp in sync.  If you don't have the capacity or nread
20761f28255Scgd  *  call there are gory ways to simulate this.
20861f28255Scgd  */
20961f28255Scgd static int
bizsync(int fd)21058c2151fSperry bizsync(int fd)
21161f28255Scgd {
21261f28255Scgd #ifdef FIOCAPACITY
21361f28255Scgd 	struct capacity b;
21461f28255Scgd #	define chars(b)	((b).cp_nbytes)
21561f28255Scgd #	define IOCTL	FIOCAPACITY
21661f28255Scgd #endif
21761f28255Scgd #ifdef FIONREAD
21861f28255Scgd 	long b;
21961f28255Scgd #	define chars(b)	(b)
22061f28255Scgd #	define IOCTL	FIONREAD
22161f28255Scgd #endif
222e37283e1Slukem 	int already = 0;
22361f28255Scgd 	char buf[10];
22461f28255Scgd 
22561f28255Scgd retry:
226*ffe34450Schristos 	if (ioctl(fd, IOCTL, &b) >= 0 && chars(b) > 0)
227*ffe34450Schristos 		(void)tcflush(FD, TCIOFLUSH);
228*ffe34450Schristos 	(void)write(fd, "\rp>\r", 4);
229*ffe34450Schristos 	(void)sleep(1);
230*ffe34450Schristos 	if (ioctl(fd, IOCTL, &b) >= 0) {
23161f28255Scgd 		if (chars(b) != 10) {
23261f28255Scgd 	nono:
23361f28255Scgd 			if (already > MAXRETRY)
23461f28255Scgd 				return (0);
235*ffe34450Schristos 			(void)write(fd, DISCONNECT_CMD, 4);
236*ffe34450Schristos 			(void)sleep(2);
23761f28255Scgd 			already++;
23861f28255Scgd 			goto retry;
23961f28255Scgd 		} else {
240*ffe34450Schristos 			(void)read(fd, buf, 10);
24161f28255Scgd 			if (strncmp(buf, "p >\r\n\r\n>", 8))
24261f28255Scgd 				goto nono;
24361f28255Scgd 		}
24461f28255Scgd 	}
24561f28255Scgd 	return (1);
24661f28255Scgd }
247