ventel.c revision 7527
17527Sjkh/*
27527Sjkh * Copyright (c) 1983, 1993
37527Sjkh *	The Regents of the University of California.  All rights reserved.
47527Sjkh *
57527Sjkh * Redistribution and use in source and binary forms, with or without
67527Sjkh * modification, are permitted provided that the following conditions
77527Sjkh * are met:
87527Sjkh * 1. Redistributions of source code must retain the above copyright
97527Sjkh *    notice, this list of conditions and the following disclaimer.
107527Sjkh * 2. Redistributions in binary form must reproduce the above copyright
117527Sjkh *    notice, this list of conditions and the following disclaimer in the
127527Sjkh *    documentation and/or other materials provided with the distribution.
137527Sjkh * 3. All advertising materials mentioning features or use of this software
147527Sjkh *    must display the following acknowledgement:
157527Sjkh *	This product includes software developed by the University of
167527Sjkh *	California, Berkeley and its contributors.
177527Sjkh * 4. Neither the name of the University nor the names of its contributors
187527Sjkh *    may be used to endorse or promote products derived from this software
197527Sjkh *    without specific prior written permission.
207527Sjkh *
217527Sjkh * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
227527Sjkh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
237527Sjkh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
247527Sjkh * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
257527Sjkh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
267527Sjkh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
277527Sjkh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
287527Sjkh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
297527Sjkh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
307527Sjkh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
317527Sjkh * SUCH DAMAGE.
327527Sjkh */
337527Sjkh
347527Sjkh#ifndef lint
357527Sjkhstatic char sccsid[] = "@(#)ventel.c	8.1 (Berkeley) 6/6/93";
367527Sjkh#endif /* not lint */
377527Sjkh
387527Sjkh/*
397527Sjkh * Routines for calling up on a Ventel Modem
407527Sjkh * The Ventel is expected to be strapped for local echo (just like uucp)
417527Sjkh */
427527Sjkh#include "tipconf.h"
437527Sjkh#include "tip.h"
447527Sjkh
457527Sjkh#define	MAXRETRY	5
467527Sjkh
477527Sjkhstatic	void sigALRM();
487527Sjkhstatic	int timeout = 0;
497527Sjkhstatic	jmp_buf timeoutbuf;
507527Sjkh
517527Sjkh/*
527527Sjkh * some sleep calls have been replaced by this macro
537527Sjkh * because some ventel modems require two <cr>s in less than
547527Sjkh * a second in order to 'wake up'... yes, it is dirty...
557527Sjkh */
567527Sjkh#define delay(num,denom) busyloop(CPUSPEED*num/denom)
577527Sjkh#define CPUSPEED 1000000	/* VAX 780 is 1MIPS */
587527Sjkh#define	DELAY(n)	{ register long N = (n); while (--N > 0); }
597527Sjkhbusyloop(n) { DELAY(n); }
607527Sjkh
617527Sjkhven_dialer(num, acu)
627527Sjkh	register char *num;
637527Sjkh	char *acu;
647527Sjkh{
657527Sjkh	register char *cp;
667527Sjkh	register int connected = 0;
677527Sjkh	char *msg, *index(), line[80];
687527Sjkh	static int gobble(), vensync();
697527Sjkh	static void echo();
707527Sjkh
717527Sjkh	/*
727527Sjkh	 * Get in synch with a couple of carriage returns
737527Sjkh	 */
747527Sjkh	if (!vensync(FD)) {
757527Sjkh		printf("can't synchronize with ventel\n");
767527Sjkh#if ACULOG
777527Sjkh		logent(value(HOST), num, "ventel", "can't synch up");
787527Sjkh#endif
797527Sjkh		return (0);
807527Sjkh	}
817527Sjkh	if (boolean(value(VERBOSE)))
827527Sjkh		printf("\ndialing...");
837527Sjkh	fflush(stdout);
847527Sjkh	acu_hupcl ();
857527Sjkh	echo("#k$\r$\n$D$I$A$L$:$ ");
867527Sjkh	for (cp = num; *cp; cp++) {
877527Sjkh		delay(1, 10);
887527Sjkh		write(FD, cp, 1);
897527Sjkh	}
907527Sjkh	delay(1, 10);
917527Sjkh	write(FD, "\r", 1);
927527Sjkh	gobble('\n', line);
937527Sjkh	if (gobble('\n', line))
947527Sjkh		connected = gobble('!', line);
957527Sjkh	acu_flush ();
967527Sjkh#if ACULOG
977527Sjkh	if (timeout) {
987527Sjkh		sprintf(line, "%d second dial timeout",
997527Sjkh			number(value(DIALTIMEOUT)));
1007527Sjkh		logent(value(HOST), num, "ventel", line);
1017527Sjkh	}
1027527Sjkh#endif
1037527Sjkh	if (timeout)
1047527Sjkh		ven_disconnect();	/* insurance */
1057527Sjkh	if (connected || timeout || !boolean(value(VERBOSE)))
1067527Sjkh		return (connected);
1077527Sjkh	/* call failed, parse response for user */
1087527Sjkh	cp = index(line, '\r');
1097527Sjkh	if (cp)
1107527Sjkh		*cp = '\0';
1117527Sjkh	for (cp = line; cp = index(cp, ' '); cp++)
1127527Sjkh		if (cp[1] == ' ')
1137527Sjkh			break;
1147527Sjkh	if (cp) {
1157527Sjkh		while (*cp == ' ')
1167527Sjkh			cp++;
1177527Sjkh		msg = cp;
1187527Sjkh		while (*cp) {
1197527Sjkh			if (isupper(*cp))
1207527Sjkh				*cp = tolower(*cp);
1217527Sjkh			cp++;
1227527Sjkh		}
1237527Sjkh		printf("%s...", msg);
1247527Sjkh	}
1257527Sjkh	return (connected);
1267527Sjkh}
1277527Sjkh
1287527Sjkhven_disconnect()
1297527Sjkh{
1307527Sjkh
1317527Sjkh	close(FD);
1327527Sjkh}
1337527Sjkh
1347527Sjkhven_abort()
1357527Sjkh{
1367527Sjkh
1377527Sjkh	write(FD, "\03", 1);
1387527Sjkh	close(FD);
1397527Sjkh}
1407527Sjkh
1417527Sjkhstatic void
1427527Sjkhecho(s)
1437527Sjkh	register char *s;
1447527Sjkh{
1457527Sjkh	char c;
1467527Sjkh
1477527Sjkh	while (c = *s++) switch (c) {
1487527Sjkh
1497527Sjkh	case '$':
1507527Sjkh		read(FD, &c, 1);
1517527Sjkh		s++;
1527527Sjkh		break;
1537527Sjkh
1547527Sjkh	case '#':
1557527Sjkh		c = *s++;
1567527Sjkh		write(FD, &c, 1);
1577527Sjkh		break;
1587527Sjkh
1597527Sjkh	default:
1607527Sjkh		write(FD, &c, 1);
1617527Sjkh		read(FD, &c, 1);
1627527Sjkh	}
1637527Sjkh}
1647527Sjkh
1657527Sjkhstatic void
1667527SjkhsigALRM()
1677527Sjkh{
1687527Sjkh	printf("\07timeout waiting for reply\n");
1697527Sjkh	timeout = 1;
1707527Sjkh	longjmp(timeoutbuf, 1);
1717527Sjkh}
1727527Sjkh
1737527Sjkhstatic int
1747527Sjkhgobble(match, response)
1757527Sjkh	register char match;
1767527Sjkh	char response[];
1777527Sjkh{
1787527Sjkh	register char *cp = response;
1797527Sjkh	sig_t f;
1807527Sjkh	char c;
1817527Sjkh
1827527Sjkh	f = signal(SIGALRM, sigALRM);
1837527Sjkh	timeout = 0;
1847527Sjkh	do {
1857527Sjkh		if (setjmp(timeoutbuf)) {
1867527Sjkh			signal(SIGALRM, f);
1877527Sjkh			*cp = '\0';
1887527Sjkh			return (0);
1897527Sjkh		}
1907527Sjkh		alarm(number(value(DIALTIMEOUT)));
1917527Sjkh		read(FD, cp, 1);
1927527Sjkh		alarm(0);
1937527Sjkh		c = (*cp++ &= 0177);
1947527Sjkh#ifdef notdef
1957527Sjkh		if (boolean(value(VERBOSE)))
1967527Sjkh			putchar(c);
1977527Sjkh#endif
1987527Sjkh	} while (c != '\n' && c != match);
1997527Sjkh	signal(SIGALRM, SIG_DFL);
2007527Sjkh	*cp = '\0';
2017527Sjkh	return (c == match);
2027527Sjkh}
2037527Sjkh
2047527Sjkh#define min(a,b)	((a)>(b)?(b):(a))
2057527Sjkh/*
2067527Sjkh * This convoluted piece of code attempts to get
2077527Sjkh * the ventel in sync.  If you don't have FIONREAD
2087527Sjkh * there are gory ways to simulate this.
2097527Sjkh */
2107527Sjkhstatic int
2117527Sjkhvensync(fd)
2127527Sjkh{
2137527Sjkh	int already = 0, nread;
2147527Sjkh	char buf[60];
2157527Sjkh
2167527Sjkh	/*
2177527Sjkh	 * Toggle DTR to force anyone off that might have left
2187527Sjkh	 * the modem connected, and insure a consistent state
2197527Sjkh	 * to start from.
2207527Sjkh	 *
2217527Sjkh	 * If you don't have the ioctl calls to diddle directly
2227527Sjkh	 * with DTR, you can always try setting the baud rate to 0.
2237527Sjkh	 */
2247527Sjkh	ioctl(FD, TIOCCDTR, 0);
2257527Sjkh	sleep(1);
2267527Sjkh	ioctl(FD, TIOCSDTR, 0);
2277527Sjkh	while (already < MAXRETRY) {
2287527Sjkh		/*
2297527Sjkh		 * After reseting the modem, send it two \r's to
2307527Sjkh		 * autobaud on. Make sure to delay between them
2317527Sjkh		 * so the modem can frame the incoming characters.
2327527Sjkh		 */
2337527Sjkh		write(fd, "\r", 1);
2347527Sjkh		delay(1,10);
2357527Sjkh		write(fd, "\r", 1);
2367527Sjkh		sleep(2);
2377527Sjkh		if (ioctl(fd, FIONREAD, (caddr_t)&nread) < 0) {
2387527Sjkh			perror("tip: ioctl");
2397527Sjkh			continue;
2407527Sjkh		}
2417527Sjkh		while (nread > 0) {
2427527Sjkh			read(fd, buf, min(nread, 60));
2437527Sjkh			if ((buf[nread - 1] & 0177) == '$')
2447527Sjkh				return (1);
2457527Sjkh			nread -= min(nread, 60);
2467527Sjkh		}
2477527Sjkh		sleep(1);
2487527Sjkh		already++;
2497527Sjkh	}
2507527Sjkh	return (0);
2517527Sjkh}
2527527Sjkh
253