1161754Sru/*	$OpenBSD: biz31.c,v 1.10 2006/03/17 19:17:13 moritz Exp $	*/
288276Smarkm/*	$NetBSD: biz31.c,v 1.5 1997/02/11 09:24:14 mrg Exp $	*/
388276Smarkm
47527Sjkh/*
57527Sjkh * Copyright (c) 1983, 1993
67527Sjkh *	The Regents of the University of California.  All rights reserved.
77527Sjkh *
87527Sjkh * Redistribution and use in source and binary forms, with or without
97527Sjkh * modification, are permitted provided that the following conditions
107527Sjkh * are met:
117527Sjkh * 1. Redistributions of source code must retain the above copyright
127527Sjkh *    notice, this list of conditions and the following disclaimer.
137527Sjkh * 2. Redistributions in binary form must reproduce the above copyright
147527Sjkh *    notice, this list of conditions and the following disclaimer in the
157527Sjkh *    documentation and/or other materials provided with the distribution.
16161754Sru * 3. Neither the name of the University nor the names of its contributors
177527Sjkh *    may be used to endorse or promote products derived from this software
187527Sjkh *    without specific prior written permission.
197527Sjkh *
207527Sjkh * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
217527Sjkh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
227527Sjkh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
237527Sjkh * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
247527Sjkh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
257527Sjkh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
267527Sjkh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
277527Sjkh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
287527Sjkh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
297527Sjkh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
307527Sjkh * SUCH DAMAGE.
317527Sjkh */
327527Sjkh
3388276Smarkm#include <sys/cdefs.h>
3488276Smarkm__FBSDID("$FreeBSD$");
3588276Smarkm
367527Sjkh#ifndef lint
3788276Smarkm#if 0
387527Sjkhstatic char sccsid[] = "@(#)biz31.c	8.1 (Berkeley) 6/6/93";
39161754Srustatic char rcsid[] = "$OpenBSD: biz31.c,v 1.10 2006/03/17 19:17:13 moritz Exp $";
4088276Smarkm#endif
417527Sjkh#endif /* not lint */
427527Sjkh
437527Sjkh#include "tip.h"
447527Sjkh
457527Sjkh#define MAXRETRY	3		/* sync up retry count */
467527Sjkh#define DISCONNECT_CMD	"\21\25\11\24"	/* disconnection string */
477527Sjkh
48161754Srustatic int	biz_dialer(char *, char *);
49161754Srustatic int	bizsync(int);
50161754Srustatic int	echo(char *);
51161754Srustatic void	sigALRM(int);
52161754Srustatic int	detect(char *);
53161754Srustatic int	flush(char *);
54161754Srustatic int	bizsync(int);
55161754Sru
567527Sjkhstatic	int timeout = 0;
577527Sjkhstatic	jmp_buf timeoutbuf;
587527Sjkh
597527Sjkh/*
607527Sjkh * Dial up on a BIZCOMP Model 1031 with either
617527Sjkh * 	tone dialing (mod = "f")
627527Sjkh *	pulse dialing (mod = "w")
637527Sjkh */
647527Sjkhstatic int
65161754Srubiz_dialer(char *num, char *mod)
667527Sjkh{
6788276Smarkm	int connected = 0;
687527Sjkh
697527Sjkh	if (!bizsync(FD)) {
707527Sjkh		logent(value(HOST), "", "biz", "out of sync");
717527Sjkh		printf("bizcomp out of sync\n");
727527Sjkh		delock(uucplock);
737527Sjkh		exit(0);
747527Sjkh	}
757527Sjkh	if (boolean(value(VERBOSE)))
767527Sjkh		printf("\nstarting call...");
777527Sjkh	echo("#\rk$\r$\n");			/* disable auto-answer */
787527Sjkh	echo("$>$.$ #\r");			/* tone/pulse dialing */
797527Sjkh	echo(mod);
807527Sjkh	echo("$\r$\n");
817527Sjkh	echo("$>$.$ #\re$ ");			/* disconnection sequence */
827527Sjkh	echo(DISCONNECT_CMD);
837527Sjkh	echo("\r$\n$\r$\n");
847527Sjkh	echo("$>$.$ #\rr$ ");			/* repeat dial */
857527Sjkh	echo(num);
867527Sjkh	echo("\r$\n");
877527Sjkh	if (boolean(value(VERBOSE)))
887527Sjkh		printf("ringing...");
897527Sjkh	/*
907527Sjkh	 * The reply from the BIZCOMP should be:
917527Sjkh	 *	`^G NO CONNECTION\r\n^G\r\n'	failure
927527Sjkh	 *	` CONNECTION\r\n^G'		success
937527Sjkh	 */
947527Sjkh	connected = detect(" ");
9588276Smarkm#ifdef ACULOG
967527Sjkh	if (timeout) {
977527Sjkh		char line[80];
987527Sjkh
99161754Sru		(void)snprintf(line, sizeof line, "%ld second dial timeout",
1007527Sjkh			number(value(DIALTIMEOUT)));
1017527Sjkh		logent(value(HOST), num, "biz", line);
1027527Sjkh	}
1037527Sjkh#endif
1047527Sjkh	if (!connected)
1057527Sjkh		flush(" NO CONNECTION\r\n\07\r\n");
1067527Sjkh	else
1077527Sjkh		flush("CONNECTION\r\n\07");
1087527Sjkh	if (timeout)
1097527Sjkh		biz31_disconnect();	/* insurance */
1107527Sjkh	return (connected);
1117527Sjkh}
1127527Sjkh
113161754Sruint
114161754Srubiz31w_dialer(char *num, char *acu)
1157527Sjkh{
1167527Sjkh	return (biz_dialer(num, "w"));
1177527Sjkh}
1187527Sjkh
119161754Sruint
120161754Srubiz31f_dialer(char *num, char *acu)
1217527Sjkh{
1227527Sjkh	return (biz_dialer(num, "f"));
1237527Sjkh}
1247527Sjkh
125161754Sruvoid
126161754Srubiz31_disconnect(void)
1277527Sjkh{
128161754Sru	write(FD, DISCONNECT_CMD, sizeof(DISCONNECT_CMD)-1);
1297527Sjkh	sleep(2);
13088276Smarkm	tcflush(FD, TCIOFLUSH);
1317527Sjkh}
1327527Sjkh
133161754Sruvoid
134161754Srubiz31_abort(void)
1357527Sjkh{
1367527Sjkh	write(FD, "\33", 1);
1377527Sjkh}
1387527Sjkh
1397527Sjkhstatic int
140161754Sruecho(char *s)
1417527Sjkh{
1427527Sjkh	char c;
1437527Sjkh
1447527Sjkh	while (c = *s++) switch (c) {
1457527Sjkh
1467527Sjkh	case '$':
1477527Sjkh		read(FD, &c, 1);
1487527Sjkh		s++;
1497527Sjkh		break;
1507527Sjkh
1517527Sjkh	case '#':
1527527Sjkh		c = *s++;
1537527Sjkh		write(FD, &c, 1);
1547527Sjkh		break;
1557527Sjkh
1567527Sjkh	default:
1577527Sjkh		write(FD, &c, 1);
1587527Sjkh		read(FD, &c, 1);
1597527Sjkh	}
1607527Sjkh}
1617527Sjkh
162161754Sru/*ARGSUSED*/
1637527Sjkhstatic void
164161754SrusigALRM(int signo)
1657527Sjkh{
1667527Sjkh	timeout = 1;
1677527Sjkh	longjmp(timeoutbuf, 1);
1687527Sjkh}
1697527Sjkh
1707527Sjkhstatic int
171161754Srudetect(char *s)
1727527Sjkh{
1737527Sjkh	sig_t f;
1747527Sjkh	char c;
1757527Sjkh
1767527Sjkh	f = signal(SIGALRM, sigALRM);
1777527Sjkh	timeout = 0;
1787527Sjkh	while (*s) {
1797527Sjkh		if (setjmp(timeoutbuf)) {
1807527Sjkh			printf("\07timeout waiting for reply\n");
1817527Sjkh			biz31_abort();
1827527Sjkh			break;
1837527Sjkh		}
1847527Sjkh		alarm(number(value(DIALTIMEOUT)));
1857527Sjkh		read(FD, &c, 1);
1867527Sjkh		alarm(0);
1877527Sjkh		if (c != *s++)
1887527Sjkh			break;
1897527Sjkh	}
1907527Sjkh	signal(SIGALRM, f);
1917527Sjkh	return (timeout == 0);
1927527Sjkh}
1937527Sjkh
1947527Sjkhstatic int
195161754Sruflush(char *s)
1967527Sjkh{
1977527Sjkh	sig_t f;
1987527Sjkh	char c;
1997527Sjkh
2007527Sjkh	f = signal(SIGALRM, sigALRM);
2017527Sjkh	while (*s++) {
2027527Sjkh		if (setjmp(timeoutbuf))
2037527Sjkh			break;
2047527Sjkh		alarm(10);
2057527Sjkh		read(FD, &c, 1);
2067527Sjkh		alarm(0);
2077527Sjkh	}
2087527Sjkh	signal(SIGALRM, f);
2097527Sjkh	timeout = 0;			/* guard against disconnection */
2107527Sjkh}
2117527Sjkh
2127527Sjkh/*
2137527Sjkh * This convoluted piece of code attempts to get
2147527Sjkh *  the bizcomp in sync.  If you don't have the capacity or nread
2157527Sjkh *  call there are gory ways to simulate this.
2167527Sjkh */
2177527Sjkhstatic int
218161754Srubizsync(int fd)
2197527Sjkh{
2207527Sjkh#ifdef FIOCAPACITY
2217527Sjkh	struct capacity b;
2227527Sjkh#	define chars(b)	((b).cp_nbytes)
2237527Sjkh#	define IOCTL	FIOCAPACITY
2247527Sjkh#endif
2257527Sjkh#ifdef FIONREAD
2267527Sjkh	long b;
2277527Sjkh#	define chars(b)	(b)
2287527Sjkh#	define IOCTL	FIONREAD
2297527Sjkh#endif
23088276Smarkm	int already = 0;
2317527Sjkh	char buf[10];
2327527Sjkh
2337527Sjkhretry:
2347527Sjkh	if (ioctl(fd, IOCTL, (caddr_t)&b) >= 0 && chars(b) > 0)
23588276Smarkm		tcflush(FD, TCIOFLUSH);
2367527Sjkh	write(fd, "\rp>\r", 4);
2377527Sjkh	sleep(1);
2387527Sjkh	if (ioctl(fd, IOCTL, (caddr_t)&b) >= 0) {
2397527Sjkh		if (chars(b) != 10) {
2407527Sjkh	nono:
2417527Sjkh			if (already > MAXRETRY)
2427527Sjkh				return (0);
2437527Sjkh			write(fd, DISCONNECT_CMD, 4);
2447527Sjkh			sleep(2);
2457527Sjkh			already++;
2467527Sjkh			goto retry;
2477527Sjkh		} else {
2487527Sjkh			read(fd, buf, 10);
2497527Sjkh			if (strncmp(buf, "p >\r\n\r\n>", 8))
2507527Sjkh				goto nono;
2517527Sjkh		}
2527527Sjkh	}
2537527Sjkh	return (1);
2547527Sjkh}
255