[comp.dcom.modems] uucp dialers for trailblazer and courier

nerd@percival.UUCP (Michael Galassi) (02/04/88)

The following shell archive contains a dialer for the Telebit
Trailblazer and one for the USR Courier.  They work with the
version of uucp found on the 4.3 BSD distribution tapes.  They
were written to function in an environment where I continuosly
switch between dialin and dialout modes on the same line so they
leave the modems in auto-answer mode, you may want to change this
but that is trivial to do.  I hope this helps someone out there.
If you make any changes to these routines please send me a copy
as I am sure they are nowhere near perfect.
-michael

-- 
        Michael Galassi           | If my opinions happen to be the same as
...!tektronix!tessi!percival!nerd | my employer's it is ONLY a coincidence,
...!uunet!littlei!percival!nerd   | of cource coincidences DO happen.

----  cut here and feed to /bin/[k]sh  ---
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	tb.c
#	courier.c
# This archive created: Thu Feb  4 00:32:38 1988
export PATH; PATH=/bin:$PATH
echo shar: extracting "'tb.c'" '(4630 characters)'
if test -f 'tb.c'
then
	echo shar: will not over-write existing file "'tb.c'"
else
sed 's/^X//' << \SHAR_EOF > 'tb.c'
X#include "../condevs.h"
X#include <ctype.h>
X
X#ifdef TELEBIT
X
X#define TBTMOUTHS 60	/* high speed timeout */
X#define TBTMOUTLS 30	/* low speed timeout */
X#define PEPBAUD 19200	/* interface speed for PEP connections */
X/*
X *	to run uucico with this dialer I set the Trailblazer's registers
X *	as follows:
X
XE0 F1 M1 Q1 T V1 X1     Version BA4.00
XS00=001 S01=000 S02=255 S03=013 S04=010 S05=008 S06=002 S07=060 S08=002 S09=006
XS10=007 S11=070 S12=050
XS45=255 S47=004 S48=000 S49=000
XS50=000 S51=005 S52=002 S53=003 S54=001 S55=000 S56=017 S57=019 S58=003 S59=000
XS60=000 S61=000 S62=003 S63=001 S64=001 S65=000 S66=000 S67=000 S68=255
XS90=000 S91=000 S92=001 S95=002
XS100=000 S101=000 S102=000 S104=000
XS110=001 S111=255 S112=001
XS121=000
XN0:
XN1:
XN2:
XN3:
XN4:
XN5:
XN6:
XN7:
XN8:
XN9:
X
X *	tbopn(telno, flds, dev) connect to trailblazer
X *	char *flds[], *dev[];
X *
X *	return codes:
X *		>0  -  file number  -  ok
X *		CF_DIAL,CF_DEVICE  -  failed
X */
X
Xtbopn(telno, flds, dev)
Xchar *telno;
Xchar *flds[];
Xstruct Devices *dev;
X{
X	extern errno;
X	char dcname[20];
X	char cbuf[MAXPH];
X	register char *cp;
X	register int i;
X	int dh = -1, rings;
X
X	sprintf(dcname, "/dev/%s", dev->D_line);
X	DEBUG(4, "dc - %s\n", dcname);
X	if (setjmp(Sjbuf)) {
X		logent(dcname, "TIMEOUT");
X		if (dh >= 0)
X			tbcls(dh);
X		return CF_DIAL;
X	}
X	signal(SIGALRM, alarmtr);
X	getnextfd();
X	alarm(10);
X	dh = open(dcname, 2); /* read/write */
X	alarm(0);
X
X	/* modem is open */
X	next_fd = -1;
X	if (dh < 0) {
X		logent(dcname, "CAN'T OPEN");
X		return dh;
X	}
X/*
X *	always open at high speed and do the conversation there, we step
X *	down later if we need it anyway.
X */
X	fixline(dh, PEPBAUD);
X
X	if (dochat(dev, flds, dh)) {
X		logent(dcname, "CHAT FAILED");
X		tbcls(dh);
X		return CF_DIAL;
X	}
X/*
X	write "at\r" to trailblazer, this forces it to the interface
X	baud rate, given the modem's default settings there should be
X	no return code so we don't need an expect after the write().
X*/
X/*	clear modems input buffers	*/
X	write(dh, "\r", 1);
X	sleep(1);
X/*	make sure modem is at the same baud rate we are	*/
X	write(dh, "at\r", 3);
X	sleep(1);
X/*	init modem	*/
X	if (dev->D_speed == PEPBAUD)
X		write(dh, "atq6v0e0h0x1s7=60s50=255s51=5s54=4s111=30\r", 42);
X	else
X		write(dh, "atq6v0e0h0x1s7=30s50=0s51=5s54=4\r", 33);
X
X	if (expect("0\r", dh) != 0) {
X		logent(dcname, "TrailBlazer seems dead");
X		tbcls(dh);
X		return CF_DIAL;
X	}
X	write(dh, "\ratdt", 5);
X	write(dh, telno, strlen(telno));
X	write(dh, "\r", 1);
X
X	if (setjmp(Sjbuf)) {
X		logent(dcname, "TIMEOUT");
X		strcpy(devSel, dev->D_line);
X		tbcls(dh);
X		return CF_DIAL;
X	}
X	signal(SIGALRM, alarmtr);
X
X	if (dev->D_speed == PEPBAUD)
X		alarm(TBTMOUTHS);
X	else
X		alarm(TBTMOUTLS);
X	rings = 0;
X	do {
X/*	read garbage characters in until a digit is found	*/
X		cp = cbuf;
X		while (read(dh, cp, 1) == 1)
X			if (isdigit(*cp))
X				break;
X		++cp;
X
X/*	read characters in so long as they are numeric	*/
X		while (read(dh, cp++, 1) == 1)
X			if (!isdigit(*cp))
X				break;
X		*cp = '\0';
X		i = atoi(cbuf);
X
X		switch (i)    {
X			case 2:
X				tbcls(dh);
X				strcpy(devSel, dev->D_line);
X				return (FLog("ring"));
X			case 3:
X				tbcls(dh);
X				strcpy(devSel, dev->D_line);
X				return (FLog("no carrier"));
X			case 4:
X				tbcls(dh);
X				strcpy(devSel, dev->D_line);
X				return (FLog("error"));
X			case 6:
X				tbcls(dh);
X				strcpy(devSel, dev->D_line);
X				return (FLog("no dial tone"));
X			case 7:
X				tbcls(dh);
X				strcpy(devSel, dev->D_line);
X				return (FLog("busy"));
X			case 52:
X				DEBUG(4,"GOT: rring\n", CNULL);
X		}
X	} while ((i == 52) && (++rings < 6));
X
X	alarm(0);
X
X	switch (i)    {
X		case 3:
X			i = 300;
X			break;
X		case 5:
X			i = 1200;
X			break;
X		case 10:
X			i = 2400;
X			break;
X		case 50:
X			i = 19200;
X			break;
X		case 52:
X/*	rung too many times, assume no answer will come	*/
X			tbcls(dh);
X			strcpy(devSel, dev->D_line);
X			return (FLog("no answer"));
X		default:
X/* probably don't need this but there is no overhead for it */
X			tbcls(dh);
X			strcpy(devSel, dev->D_line);
X			return (FLog(cbuf));
X	}
X	if (i != PEPBAUD)    {
X		DEBUG(4,"Baudrate reset to %d\n", i);
X		fixline(dh, i);
X	}
X
X	DEBUG(4, "telebit connect at %d bps\n", i);
X	return dh;
X}
X
Xtbcls(fd)
Xint fd;
X{
X	char dcname[20];
X	
X	struct sgttyb hup, sav;
X
X	if (fd > 0) {
X		sprintf(dcname, "/dev/%s", devSel);
X		DEBUG(4, "Hanging up fd = %d\n", fd);
X
X		/*
X		 * code to drop DTR -- change to 0 baud then back to default.
X		 */
X		gtty(fd, &hup);
X		gtty(fd, &sav);
X		hup.sg_ispeed = hup.sg_ospeed = B0;
X		stty(fd, &hup);
X		sleep(2);
X		stty(fd, &sav);
X		close(fd);
X		delock(devSel);
X	}
X}
X
XFLog(str)
Xchar *str;
X{
X	DEBUG(4,"\nGOT: %s\n", str);
X	logent(str, _FAILED);
X	return CF_DIAL;
X}
X#endif TELEBIT
SHAR_EOF
if test 4630 -ne "`wc -c < 'tb.c'`"
then
	echo shar: error transmitting "'tb.c'" '(should have been 4630 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'courier.c'" '(4047 characters)'
if test -f 'courier.c'
then
	echo shar: will not over-write existing file "'courier.c'"
else
sed 's/^X//' << \SHAR_EOF > 'courier.c'
X#include "../condevs.h"
X#include <ctype.h>
X
X#ifdef COURIER
X
X#define CTMOUTLS 30	/* low speed timeout */
X#define DEFBAUD 2400	/* interface speed during connect fase */
X/*
X *	I set the courier switches as follows to run it with
X *	this dialer:
X *	sw 1	--	off
X *	sw 2	--	on
X *	sw 3	--	off
X *	sw 4	--	on
X *	sw 5	--	off
X *	sw 6	--	off
X *	sw 7	--	on
X *	sw 8	--	on
X *	sw 9	--	on
X *	sw 10	--	off
X *
X *	couopn(telno, flds, dev) connect to courier
X *	char *flds[], *dev[];
X *
X *	return codes:
X *		>0  -  file number  -  ok
X *		CF_DIAL,CF_DEVICE  -  failed
X */
X
Xcouopn(telno, flds, dev)
Xchar *telno;
Xchar *flds[];
Xstruct Devices *dev;
X{
X	extern errno;
X	char dcname[20];
X	char cbuf[MAXPH];
X	register char *cp;
X	register int i;
X	int dh = -1, rings;
X
X	sprintf(dcname, "/dev/%s", dev->D_line);
X	DEBUG(4, "dc - %s\n", dcname);
X	if (setjmp(Sjbuf)) {
X		logent(dcname, "TIMEOUT");
X		if (dh >= 0)
X			coucls(dh);
X		return CF_DIAL;
X	}
X	signal(SIGALRM, alarmtr);
X	getnextfd();
X	alarm(10);
X	dh = open(dcname, 2); /* read/write */
X	alarm(0);
X
X	/* modem is open */
X	next_fd = -1;
X	if (dh < 0) {
X		logent(dcname, "CAN'T OPEN");
X		return dh;
X	}
X/*
X *	always open at high speed and do the conversation there, we step
X *	down later if we need it anyway.
X */
X	fixline(dh, DEFBAUD);
X
X	if (dochat(dev, flds, dh)) {
X		logent(dcname, "CHAT FAILED");
X		coucls(dh);
X		return CF_DIAL;
X	}
X/*
X	write "at\r" to trailblazer, this forces it to the interface
X	baud rate, given the modem's default settings there should be
X	no return code so we don't need an expect after the write().
X*/
X/*	clear modems input buffers	*/
X	write(dh, "\r", 1);
X	sleep(1);
X/*	make sure modem is at the same baud rate we are	*/
X	write(dh, "atz\r", 4);
X	sleep(1);
X/*	init modem	*/
X	write(dh, "atq0v0e0h0x6s0=0s2=255\r", 23);
X
X	if (expect("0\r", dh) != 0) {
X		logent(dcname, "Courier seems dead");
X		coucls(dh);
X		return CF_DIAL;
X	}
X	write(dh, "\ratd", 4);
X	write(dh, telno, strlen(telno));
X	write(dh, "\r", 1);
X
X	if (setjmp(Sjbuf)) {
X		logent(dcname, "TIMEOUT");
X		strcpy(devSel, dev->D_line);
X		coucls(dh);
X		return CF_DIAL;
X	}
X	signal(SIGALRM, alarmtr);
X	alarm(CTMOUTLS);
X	rings = 0;
X	do {
X/*	read garbage characters in until a digit is found	*/
X		cp = cbuf;
X		while (read(dh, cp, 1) == 1)
X			if (isdigit(*cp))
X				break;
X		++cp;
X
X/*	read characters in so long as they are numeric	*/
X		while (read(dh, cp++, 1) == 1)
X			if (!isdigit(*cp))
X				break;
X		*cp = '\0';
X		i = atoi(cbuf);
X
X		switch (i)    {
X			case 3:
X				coucls(dh);
X				strcpy(devSel, dev->D_line);
X				return (FLog("no carrier"));
X			case 4:
X				coucls(dh);
X				strcpy(devSel, dev->D_line);
X				return (FLog("error"));
X			case 6:
X				coucls(dh);
X				strcpy(devSel, dev->D_line);
X				return (FLog("no dial tone"));
X			case 7:
X				coucls(dh);
X				strcpy(devSel, dev->D_line);
X				return (FLog("busy"));
X			case 12:
X				coucls(dh);
X				strcpy(devSel, dev->D_line);
X				return (FLog("voice"));
X			case 11:
X				DEBUG(4,"GOT: ringing\n", CNULL);
X		}
X	} while ((i == 11) && (++rings < 6));
X
X	alarm(0);
X
X	switch (i)    {
X		case 3:
X			i = 300;
X			break;
X		case 5:
X			i = 1200;
X			break;
X		case 10:
X			i = 2400;
X			break;
X		case 11:
X/*	rung too many times, assume no answer will come	*/
X			coucls(dh);
X			strcpy(devSel, dev->D_line);
X			return (FLog("no answer"));
X		default:
X/* probably don't need this but there is no overhead for it */
X			coucls(dh);
X			strcpy(devSel, dev->D_line);
X			return (FLog(cbuf));
X	}
X	if (i != DEFBAUD)    {
X		DEBUG(4,"Baudrate reset to %d\n", i);
X		fixline(dh, i);
X	}
X
X	DEBUG(4, "courier connect at %d bps\n", i);
X	return dh;
X}
X
Xcoucls(fd)
Xint fd;
X{
X	char dcname[20];
X	
X	struct sgttyb hup, sav;
X
X	if (fd > 0) {
X		sprintf(dcname, "/dev/%s", devSel);
X		DEBUG(4, "Hanging up fd = %d\n", fd);
X
X		/*
X		 * code to drop DTR -- change to 0 baud then back to default.
X		 */
X		gtty(fd, &hup);
X		gtty(fd, &sav);
X		hup.sg_ispeed = hup.sg_ospeed = B0;
X		stty(fd, &hup);
X		sleep(2);
X		stty(fd, &sav);
X		write(fd, "atz\r", 4);
X		sleep(1);
X		write(fd, "ate0f1h0m0q1s2=255\r", 17);
X		sleep(1);
X		close(fd);
X		delock(devSel);
X	}
X}
X
X#endif COURIER
SHAR_EOF
if test 4047 -ne "`wc -c < 'courier.c'`"
then
	echo shar: error transmitting "'courier.c'" '(should have been 4047 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0

-- 
        Michael Galassi           | If my opinions happen to be the same as
...!tektronix!tessi!percival!nerd | my employer's it is ONLY a coincidence,
...!uunet!littlei!percival!nerd   | of cource coincidences DO happen.