|
|
BSD 4.2
#ifndef lint
static char sccsid[] = "@(#)condevs.c 5.6 (Berkeley) 8/12/83";
#endif
/*
* Here are various dialers to establish the machine-machine connection.
* conn.c/condevs.c was glued together by Mike Mitchell.
* The dialers were supplied by many people, to whom we are grateful.
*
* ---------------------------------------------------------------------
* NOTE:
* There is a bug that occurs at least on PDP11s due to a limitation of
* setjmp/longjmp. If the routine that does a setjmp is interrupted
* and longjmp-ed to, it loses its register variables (on a pdp11).
* What works is if the routine that does the setjmp
* calls a routine and it is the *subroutine* that is interrupted.
*
* Anyway, in conclusion, condevs.c is plagued with register variables
* that are used inside
* if (setjmp(...)) {
* ....
* }
*
* THE FIX: In dnopn(), for example, delete the 'register' Devices *dev.
* (That was causing a core dump; deleting register fixed it.)
* Also for dnopn delete 'register' int dnf... .
* In pkopn, delete 'register' flds... .
* There may be others, especially mcm's version of hysopen.
* You could just delete all references to register, that is safest.
* This problem might not occur on 4.1bsd, I am not sure.
* Tom Truscott
*/
#include <sys/types.h>
#include <errno.h>
#include <setjmp.h>
#include <signal.h>
#include <sgtty.h>
#include "uucp.h"
extern char devSel[]; /* name to pass to delock() in close */
extern int errno, next_fd;
extern jmp_buf Sjbuf;
extern int alarmtr();
int nulldev(), nodev(), Acuopn(), diropn(), dircls();
#ifdef DATAKIT
int dkopn();
#endif
#ifdef DN11
int dnopn(), dncls();
#endif
#ifdef HAYES
int hysopn(), hyscls();
#endif
#ifdef HAYESQ
int hysqopn(), hysqcls(); /* a version of hayes that doesn't use ret codes */
#endif
#ifdef DF02
int df2opn(), df2cls();
#endif
#ifdef PNET
int pnetopn();
#endif
#ifdef VENTEL
int ventopn(), ventcls();
#endif
#ifdef UNET
#include <UNET/unetio.h>
#include <UNET/tcp.h>
int unetopn(), unetcls();
#endif UNET
#ifdef VADIC
int vadopn(), vadcls();
#endif VADIC
#ifdef RVMACS
int rvmacsopn(), rvmacscls();
#endif
#ifdef MICOM
int micopn(), miccls();
#endif MICOM
struct condev condevs[] = {
{ "DIR", "direct", diropn, nulldev, dircls },
#ifdef DATAKIT
{ "DK", "datakit", dkopn, nulldev, nulldev },
#endif
#ifdef PNET
{ "PNET", "pnet", pnetopn, nulldev, nulldev },
#endif
#ifdef UNET
{ "UNET", "UNET", unetopn, nulldev, unetcls },
#endif UNET
#ifdef MICOM
{ "MICOM", "micom", micopn, nulldev, miccls },
#endif MICOM
#ifdef DN11
{ "ACU", "dn11", Acuopn, dnopn, dncls },
#endif
#ifdef HAYES
{ "ACU", "hayes", Acuopn, hysopn, hyscls },
#endif HAYES
#ifdef HAYESQ /* a version of hayes that doesn't use result codes */
{ "ACU", "hayesq", Acuopn, hysqopn, hysqcls },
#endif HATESQ
#ifdef DF02
{ "ACU", "DF02", Acuopn, df2opn, df2cls },
#endif
#ifdef VENTEL
{ "ACU", "ventel", Acuopn, ventopn, ventcls },
#endif VENTEL
#ifdef VADIC
{ "ACU", "vadic", Acuopn, vadopn, vadcls },
#endif VADIC
#ifdef RVMACS
{ "ACU", "rvmacs", Acuopn, rvmacsopn, rvmacscls },
#endif RVMACS
/* Insert new entries before this line */
{ NULL, NULL, NULL, NULL, NULL } };
/***
* nulldev a null device (returns CF_DIAL)
*/
int nulldev()
{
return(CF_DIAL);
}
/***
* nodev a null device (returns CF_NODEV)
*/
int nodev()
{
return(CF_NODEV);
}
/*
* The first things in this file are the generic devices.
* Generic devices look through L-devices and call the CU_open routines for
* appropriate devices. Some things, like the Unet interface, or direct
* connect, do not use the CU_open entry. ACUs must search to find the'
* right routine to call.
*/
/***
* diropn(flds) connect to hardware line
* char *flds[];
*
* return codes:
* >0 - file number - ok
* FAIL - failed
*/
diropn(flds)
register char *flds[];
{
register int dcr, status;
struct Devices dev;
char dcname[20];
FILE *dfp;
dfp = fopen(DEVFILE, "r");
ASSERT(dfp != NULL, "CAN'T OPEN", DEVFILE, 0);
while ((status = rddev(dfp, &dev)) != FAIL) {
if (strcmp(flds[F_CLASS], dev.D_class) != SAME)
continue;
if (strcmp(flds[F_PHONE], dev.D_line) != SAME)
continue;
if (mlock(dev.D_line) != FAIL)
break;
}
fclose(dfp);
if (status == FAIL) {
logent("DEVICE", "NO");
return(CF_NODEV);
}
sprintf(dcname, "/dev/%s", dev.D_line);
if (setjmp(Sjbuf)) {
delock(dev.D_line);
return(FAIL);
}
signal(SIGALRM, alarmtr);
alarm(10);
getnextfd();
errno = 0;
dcr = open(dcname, 2); /* read/write */
next_fd = -1;
if (dcr < 0 && errno == EACCES)
logent(dcname, "CAN'T OPEN");
alarm(0);
if (dcr < 0) {
delock(dev.D_line);
return(FAIL);
}
fflush(stdout);
fixline(dcr, dev.D_speed);
strcpy(devSel, dev.D_line); /* for latter unlock */
CU_end = dircls;
return(dcr);
}
dircls(fd)
register int fd;
{
if (fd > 0) {
close(fd);
delock(devSel);
}
}
#ifdef DATAKIT
#include <dk.h>
#define DKTRIES 2
/***
* dkopn(flds) make datakit connection
*
* return codes:
* >0 - file number - ok
* FAIL - failed
*/
dkopn(flds)
char *flds[];
{
int dkphone;
register char *cp;
register ret, i;
if (setjmp(Sjbuf))
return(FAIL);
signal(SIGALRM, alarmtr);
dkphone = 0;
cp = flds[F_PHONE];
while(*cp)
dkphone = 10 * dkphone + (*cp++ - '0');
DEBUG(4, "dkphone (%d) ", dkphone);
for (i = 0; i < DKTRIES; i++) {
getnextfd();
ret = dkdial(D_SH, dkphone, 0);
next_fd = -1;
DEBUG(4, "dkdial (%d)\n", ret);
if (ret > -1)
break;
}
return(ret);
}
#endif
#ifdef PNET
/***
* pnetopn(flds)
*
* call remote machine via Purdue network
* use dial string as host name, speed as socket number
* Author: Steve Bellovin
*/
pnetopn(flds)
char *flds[];
{
int fd;
int socket;
register char *cp;
fd = pnetfile();
DEBUG(4, "pnet fd - %d\n", fd);
if (fd < 0) {
logent("AVAILABLE DEVICE", "NO");
return(CF_NODEV);
}
socket = 0;
for (cp = flds[F_CLASS]; *cp; cp++)
socket = 10*socket + (*cp - '0');
DEBUG(4, "socket - %d\n", socket);
if (setjmp(Sjbuf)) {
DEBUG(4, "pnet timeout - %s\n", flds[F_PHONE]);
return(FAIL);
}
signal(SIGALRM, alarmtr);
DEBUG(4, "host - %s\n", flds[F_PHONE]);
alarm(15);
if (pnetscon(fd, flds[F_PHONE], socket) < 0) {
DEBUG(4, "pnet connect failed - %s\n", flds[F_PHONE]);
return(FAIL);
}
alarm(0);
return(fd);
}
#endif PNET
#ifdef UNET
/***
* unetopn -- make UNET (tcp-ip) connection
*
* return codes:
* >0 - file number - ok
* FAIL - failed
*/
/* Default port of uucico server */
#define DFLTPORT 33
unetopn(flds)
register char *flds[];
{
register int ret, port;
int unetcls();
port = atoi(flds[F_PHONE]);
if (port <= 0 || port > 255)
port = DFLTPORT;
DEBUG(4, "unetopn host %s, ", flds[F_NAME]);
DEBUG(4, "port %d\n", port);
if (setjmp(Sjbuf)) {
logent("tcpopen", "TIMEOUT");
endhnent(); /* see below */
return(CF_DIAL);
}
signal(SIGALRM, alarmtr);
alarm(30);
ret = tcpopen(flds[F_NAME], port, 0, TO_ACTIVE, "rw");
alarm(0);
endhnent(); /* wave magic wand at 3com and incant "eat it, bruce" */
if (ret < 0) {
DEBUG(5, "tcpopen failed: errno %d\n", errno);
logent("tcpopen", "FAILED");
return(CF_DIAL);
}
CU_end = unetcls;
return(ret);
}
/*
* unetcls -- close UNET connection.
*/
unetcls(fd)
register int fd;
{
DEBUG(4, "UNET CLOSE called\n", 0);
if (fd > 0) {
/* disable this until a timeout is put in
if (ioctl(fd, UIOCCLOSE, STBNULL))
logent("UNET CLOSE", "FAILED");
*/
close(fd);
DEBUG(4, "closed fd %d\n", fd);
}
}
#endif UNET
#ifdef MICOM
/*
* micopn: establish connection through a micom.
* Returns descriptor open to tty for reading and writing.
* Negative values (-1...-7) denote errors in connmsg.
* Be sure to disconnect tty when done, via HUPCL or stty 0.
*/
micopn(flds)
register char *flds[];
{
extern errno;
char *rindex(), *fdig(), dcname[20];
int dh, ok = 0, speed;
register struct condev *cd;
register FILE *dfp;
struct Devices dev;
dfp = fopen(DEVFILE, "r");
ASSERT(dfp != NULL, "Can't open", DEVFILE, 0);
signal(SIGALRM, alarmtr);
dh = -1;
for(cd = condevs; ((cd->CU_meth != NULL)&&(dh < 0)); cd++) {
if (snccmp(flds[F_LINE], cd->CU_meth) == SAME) {
fseek(dfp, (off_t)0, 0);
while(rddev(dfp, &dev) != FAIL) {
if (strcmp(flds[F_CLASS], dev.D_class) != SAME)
continue;
if (snccmp(flds[F_LINE], dev.D_type) != SAME)
continue;
if (mlock(dev.D_line) == FAIL)
continue;
sprintf(dcname, "/dev/%s", dev.D_line);
getnextfd();
alarm(10);
if (setjmp(Sjbuf)) {
delock(dev.D_line);
logent(dev.D_line,"micom open TIMEOUT");
dh = -1;
break;
}
dh = open(dcname, 2);
alarm(0);
next_fd = -1;
if (dh > 0) {
break;
}
devSel[0] = '\0';
delock(dev.D_line);
}
}
}
fclose(dfp);
if (dh < 0)
return(CF_NODEV);
speed = atoi(fdig(flds[F_CLASS]));
fixline(dh, speed);
sleep(1);
/* negotiate with micom */
if (speed != 4800) /* damn their eyes! */
write(dh, "\r", 1);
else
write(dh, " ", 1);
DEBUG(4, "wanted %s ", "NAME");
ok = expect("NAME", dh);
DEBUG(4, "got %s\n", ok ? "?" : "that");
if (ok == 0) {
write(dh, flds[F_PHONE], strlen(flds[F_PHONE]));
sleep(1);
write(dh, "\r", 1);
DEBUG(4, "wanted %s ", "GO");
ok = expect("GO", dh);
DEBUG(4, "got %s\n", ok ? "?" : "that");
}
if (ok != 0) {
if (dh > 2)
close(dh);
DEBUG(4, "micom failed\n", "");
delock(dev.D_line);
return(CF_DIAL);
} else
DEBUG(4, "micom ok\n", "");
CU_end = cd->CU_clos;
strcat(devSel, dev.D_line); /* for later unlock */
return(dh);
}
miccls(fd)
register int fd;
{
if (fd > 0) {
close(fd);
delock(devSel);
}
}
#endif MICOM
/***
* Acuopn - open an ACU and dial the number. The condevs table
* will be searched until a dialing unit is found that is
* free.
*
* return codes: >0 - file number - o.k.
* FAIL - failed
*/
char devSel[20]; /* used for later unlock() */
Acuopn(flds)
register char *flds[];
{
char phone[MAXPH+1];
register struct condev *cd;
register int fd;
register FILE *dfp;
struct Devices dev;
exphone(flds[F_PHONE], phone);
devSel[0] = '\0';
DEBUG(4, "Dialing %s\n", phone);
dfp = fopen(DEVFILE, "r");
ASSERT(dfp != NULL, "Can't open", DEVFILE, 0);
for(cd = condevs; cd->CU_meth != NULL; cd++) {
if (snccmp(flds[F_LINE], cd->CU_meth) == SAME) {
fseek(dfp, (off_t)0, 0);
while(rddev(dfp, &dev) != FAIL) {
if (strcmp(flds[F_CLASS], dev.D_class) != SAME)
continue;
if (snccmp(flds[F_LINE], dev.D_type) != SAME)
continue;
if (dev.D_brand[0] == '\0')
logent("Acuopn","No 'brand' name on ACU");
else if (snccmp(dev.D_brand, cd->CU_brand) != SAME)
continue;
if (mlock(dev.D_line) == FAIL)
continue;
DEBUG(4, "Using %s\n", cd->CU_brand);
fd = (*(cd->CU_open))(phone, flds, &dev);
if (fd > 0) {
CU_end = cd->CU_clos; /* point CU_end at close func */
fclose(dfp);
strcpy(devSel, dev.D_line); /* save for later unlock() */
return(fd);
}
delock(dev.D_line);
}
}
}
fclose(dfp);
return(FAIL);
}
#ifdef DN11
/***
* dnopn(ph, flds, dev) dial remote machine
* char *ph;
* char *flds[];
* struct Devices *dev;
*
* return codes:
* file descriptor - succeeded
* FAIL - failed
*/
dnopn(ph, flds, dev)
char *ph;
char *flds[];
struct Devices *dev;
{
char dcname[20], dnname[20], phone[MAXPH+2], c = 0;
#ifdef SYSIII
struct termio ttbuf;
#endif
int dnf, dcf;
int nw, lt, pid, status;
unsigned timelim;
sprintf(dnname, "/dev/%s", dev->D_calldev);
errno = 0;
if (setjmp(Sjbuf)) {
logent(dnname, "CAN'T OPEN");
DEBUG(4, "%s Open timed out\n", dnname);
return(CF_NODEV);
}
signal(SIGALRM, alarmtr);
getnextfd();
alarm(10);
dnf = open(dnname, 1);
alarm(0);
next_fd = -1;
if (dnf < 0 && errno == EACCES) {
logent(dnname, "CAN'T OPEN");
logent("DEVICE", "NO");
return(CF_NODEV);
}
/* rti!trt: avoid passing acu file descriptor to children */
fioclex(dnf);
sprintf(dcname, "/dev/%s", dev->D_line);
sprintf(phone, "%s%s", ph, ACULAST);
DEBUG(4, "dc - %s, ", dcname);
DEBUG(4, "acu - %s\n", dnname);
pid = 0;
if (setjmp(Sjbuf)) {
logent("DIALUP DN write", "TIMEOUT");
if (pid)
kill(pid, 9);
delock(dev->D_line);
if (dnf)
close(dnf);
return(FAIL);
}
signal(SIGALRM, alarmtr);
timelim = 5 * strlen(phone);
alarm(timelim < 30 ? 30 : timelim);
if ((pid = fork()) == 0) {
sleep(2);
fclose(stdin);
fclose(stdout);
#ifdef TIOCFLUSH
ioctl(dnf, TIOCFLUSH, STBNULL);
#endif
nw = write(dnf, phone, lt = strlen(phone));
if (nw != lt) {
logent("DIALUP ACU write", "FAILED");
exit(1);
}
DEBUG(4, "ACU write ok%s\n", "");
exit(0);
}
/* open line - will return on carrier */
/* RT needs a sleep here because it returns immediately from open */
#if RT
sleep(15);
#endif
getnextfd();
errno = 0;
dcf = open(dcname, 2);
next_fd = -1;
if (dcf < 0 && errno == EACCES)
logent(dcname, "CAN'T OPEN");
DEBUG(4, "dcf is %d\n", dcf);
if (dcf < 0) {
logent("DIALUP LINE open", "FAILED");
alarm(0);
kill(pid, 9);
close(dnf);
delock(dev->D_line);
return(FAIL);
}
/* brl-bmd.351 (Doug Kingston) says the next ioctl is unneeded . */
/* ioctl(dcf, TIOCHPCL, STBNULL);*/
while ((nw = wait(<)) != pid && nw != -1)
;
#ifdef SYSIII
ioctl(dcf, TCGETA, &ttbuf);
if(!(ttbuf.c_cflag & HUPCL)) {
ttbuf.c_cflag |= HUPCL;
ioctl(dcf, TCSETA, &ttbuf);
}
#endif
alarm(0);
fflush(stdout);
fixline(dcf, dev->D_speed);
DEBUG(4, "Fork Stat %o\n", lt);
if (lt != 0) {
close(dcf);
if (dnf)
close(dnf);
delock(dev->D_line);
return(FAIL);
}
return(dcf);
}
/***
* dncls() close dn type call unit
*
* return codes: None
*/
dncls(fd)
register int fd;
{
if (fd > 0) {
close(fd);
sleep(5);
delock(devSel);
}
}
#endif DN11
#ifdef DF02
/***
* df2opn(ph, flds, dev) dial remote machine
* char *ph;
* char *flds[];
* struct Devices *dev;
*
* return codes:
* file descriptor - succeeded
* FAIL - failed
*
* Modified 9/28/81 by Bill Shannon (DEC)
* Changed to use DEC DF02 or DF03 ACU
*/
df2opn(ph, flds, dev)
char *ph;
char *flds[];
struct Devices *dev;
{
char dcname[20], dnname[20], phone[MAXPH+2], c = 0;
#ifdef SYSIII
struct termio ttbuf;
#endif
int dcf, dnf;
int nw, lt, pid, st, status;
unsigned timelim;
sprintf(dnname, "/dev/%s", dev->D_calldev);
if (setjmp(Sjbuf)) {
logent(dnname, "CAN'T OPEN");
DEBUG(4, "%s Open timed out\n", dnname);
return(CF_NODEV);
}
signal(SIGALRM, alarmtr);
getnextfd();
errno = 0;
alarm(10);
dnf = open(dnname, 2 );
alarm(0);
next_fd = -1;
if (dnf < 0 && errno == EACCES) {
logent(dnname, "CAN'T OPEN");
delock(dev->D_line);
logent("DEVICE", "NO");
return(CF_NODEV);
}
/* rti!trt: avoid passing acu file descriptor to children */
fioclex(dnf);
sprintf(dcname, "/dev/%s", dev->D_line);
fixline(dnf, dev->D_speed);
sprintf(phone, "\02%s", ph);
DEBUG(4, "dc - %s, ", dcname);
DEBUG(4, "acu - %s\n", dnname);
pid = 0;
if (setjmp(Sjbuf)) {
logent("DIALUP DN write", "TIMEOUT");
if (pid)
kill(pid, 9);
delock(dev->D_line);
if (dnf)
close(dnf);
return(FAIL);
}
signal(SIGALRM, alarmtr);
timelim = 5 * strlen(phone);
alarm(timelim < 30 ? 30 : timelim);
if ((pid = fork()) == 0) {
sleep(2);
fclose(stdin);
fclose(stdout);
#ifdef TIOCFLUSH
ioctl(dnf, TIOCFLUSH, STBNULL);
#endif
write(dnf, "\01", 1);
sleep(1);
nw = write(dnf, phone, lt = strlen(phone));
if (nw != lt) {
logent("DIALUP ACU write", "FAILED");
exit(1);
}
DEBUG(4, "ACU write ok%s\n", "");
exit(0);
}
/* open line - will return on carrier */
/* RT needs a sleep here because it returns immediately from open */
#if RT
sleep(15);
#endif
if (read(dnf, &c, 1) != 1 || c != 'A')
dcf = -1;
else
dcf = 0;
DEBUG(4, "dcf is %d\n", dcf);
if (dcf < 0) {
logent("DIALUP LINE open", "FAILED");
alarm(0);
kill(pid, 9);
close(dnf);
delock(dev->D_line);
return(FAIL);
}
dcf = dnf;
dnf = 0;
/* brl-bmd.351 (Doug Kingston) says the next ioctl is unneeded . */
/* ioctl(dcf, TIOCHPCL, STBNULL);*/
while ((nw = wait(<)) != pid && nw != -1)
;
#ifdef SYSIII
ioctl(dcf, TCGETA, &ttbuf);
if(!(ttbuf.c_cflag & HUPCL)) {
ttbuf.c_cflag |= HUPCL;
ioctl(dcf, TCSETA, &ttbuf);
}
#endif
alarm(0);
fflush(stdout);
fixline(dcf, dev->D_speed);
DEBUG(4, "Fork Stat %o\n", lt);
if (lt != 0) {
close(dcf);
if (dnf)
close(dnf);
delock(dev->D_line);
return(FAIL);
}
return(dcf);
}
/*
* df2cls() close the DF02/DF03 call unit
*
* return codes: none
*/
df2cls(fd)
register int fd;
{
if (fd > 0) {
close(fd);
sleep(5);
delock(devSel);
}
}
#endif DF02
#ifdef HAYES
/***
* hysopn(telno, flds, dev) connect to hayes smartmodem
* char *flds[], *dev[];
*
* return codes:
* >0 - file number - ok
* CF_DIAL,CF_DEVICE - failed
*/
/*
* Define HAYSTONE if you have touch tone dialing.
*/
/*#define HAYSTONE */
hysopn(telno, flds, dev)
char *telno;
char *flds[];
struct Devices *dev;
{
int dh = -1;
extern errno;
char dcname[20];
sprintf(dcname, "/dev/%s", dev->D_line);
DEBUG(4, "dc - %s\n", dcname);
if (setjmp(Sjbuf)) {
DEBUG(1, "timeout hayes open %s\n", dcname);
logent("hayes open", "TIMEOUT");
if (dh >= 0)
close(dh);
delock(dev->D_line);
return(CF_DIAL);
}
signal(SIGALRM, alarmtr);
getnextfd();
alarm(10);
dh = open(dcname, 2); /* read/write */
alarm(0);
/* modem is open */
next_fd = -1;
if (dh >= 0) {
fixline(dh, dev->D_speed);
#ifdef HAYSTONE
write(dh, "\rATDT", 5);
#else
write(dh, "\rATDP", 5);
#endif
write(dh, telno, strlen(telno));
write(dh, "\r", 1);
if (expect("CONNECT", dh) != 0) {
logent("HSM no carrier", "FAILED");
strcpy(devSel, dev->D_line);
hyscls(dh);
return(CF_DIAL);
}
}
if (dh < 0) {
DEBUG(4, "hayes failed\n", "");
delock(dev->D_line);
}
DEBUG(4, "hayes ok\n", "");
return(dh);
}
hyscls(fd)
int fd;
{
char dcname[20];
struct sgttyb hup, sav;
if (fd > 0) {
sprintf(dcname, "/dev/%s", devSel);
DEBUG(4, "Hanging up fd = %d\n", fd);
/*
* code to drop DTR -- change to 0 baud then back to default.
*/
gtty(fd, &hup);
gtty(fd, &sav);
hup.sg_ispeed = B0;
hup.sg_ospeed = B0;
stty(fd, &hup);
sleep(2);
stty(fd, &sav);
/*
* now raise DTR -- close the device & open it again.
*/
sleep(2);
close(fd);
sleep(2);
fd = open(dcname, 2);
/*
* Since we have a getty sleeping on this line, when it wakes up it sends
* all kinds of garbage to the modem. Unfortunatly, the modem likes to
* execute the previous command when it sees the garbage. The previous
* command was to dial the phone, so let's make the last command reset
* the modem.
*/
sleep(2);
write(fd, "\rATZ\r", 5);
close(fd);
delock(devSel);
}
}
#endif HAYES
#ifdef HAYESQ
/*
* New dialout routine to work with Hayes' SMART MODEM
* 13-JUL-82, Mike Mitchell
* Modified 23-MAR-83 to work with Tom Truscott's (rti!trt)
* version of UUCP (ncsu!mcm)
*
* The modem should be set to NOT send any result codes to
* the system (switch 3 up, 4 down). This end will figure out
* what is wrong.
*
* I had lots of problems with the modem sending
* result codes since I am using the same modem for both incomming and
* outgoing calls. I'd occasionally miss the result code (getty would
* grab it), and the connect would fail. Worse yet, the getty would
* think the result code was a user name, and send garbage to it while
* it was in the command state. I turned off ALL result codes, and hope
* for the best. 99% of the time the modem is in the correct state.
* Occassionally it doesn't connect, or the phone was busy, etc., and
* uucico sits there trying to log in. It eventually times out, calling
* clsacu() in the process, so it resets itself for the next attempt.
*/
/*
* Define HAYSTONE if touch-tone dialing is to be used. If it is not defined,
* Pulse dialing is assumed.
*/
/*#define HAYSTONE*/
hysqopn(telno, flds, dev)
char *telno, *flds[];
struct Devices *dev;
{
char dcname[20], phone[MAXPH+10], c = 0;
#ifdef SYSIII
struct termio ttbuf;
#endif
int status, dnf;
unsigned timelim;
signal(SIGALRM, alarmtr);
sprintf(dcname, "/dev/%s", dev->D_line);
getnextfd();
if (setjmp(Sjbuf)) {
delock(dev->D_line);
logent("DEVICE", "NO");
DEBUG(4, "Open timed out %s", dcname);
return(CF_NODEV);
}
alarm(10);
if ((dnf = open(dcname, 2)) <= 0) {
delock(dev->D_line);
logent("DEVICE", "NO");
DEBUG(4, "Can't open %s", dcname);
return(CF_NODEV);
}
alarm(0);
next_fd = -1;
fixline(dnf, dev->D_speed);
DEBUG(4, "Hayes port - %s, ", dcname);
#ifdef HAYSTONE
sprintf(phone, "\rATDT%s\r", telno);
#else
sprintf(phone, "\rATDP%s\r", telno);
#endif
write(dnf, phone, strlen(phone));
/* calculate delay time for the other system to answer the phone.
* Default is 15 seconds, add 2 seconds for each comma in the phone
* number.
*/
timelim = 150;
while(*telno) {
c = *telno++;
if (c == ',')
timelim += 20;
else {
#ifdef HAYSTONE
timelim += 2; /* .2 seconds per tone */
}
#else
if (c == '0') timelim += 10; /* .1 second per digit */
else if (c > '0' && c <= '9')
timelim += (c - '0');
}
#endif
}
alarm(timelim/10);
if (setjmp(Sjbuf) == 0) {
read(dnf, &c, 1);
alarm(0);
}
return(dnf);
}
hysqcls(fd)
int fd;
{
char dcname[20];
struct sgttyb hup, sav;
if (fd > 0) {
sprintf(dcname, "/dev/%s", devSel);
DEBUG(4, "Hanging up fd = %d\n", fd);
/*
* code to drop DTR -- change to 0 baud then back to default.
*/
gtty(fd, &hup);
gtty(fd, &sav);
hup.sg_ispeed = B0;
hup.sg_ospeed = B0;
stty(fd, &hup);
sleep(2);
stty(fd, &sav);
/*
* now raise DTR -- close the device & open it again.
*/
sleep(2);
close(fd);
sleep(2);
fd = open(dcname, 2);
/*
* Since we have a getty sleeping on this line, when it wakes up it sends
* all kinds of garbage to the modem. Unfortunatly, the modem likes to
* execute the previous command when it sees the garbage. The previous
* command was to dial the phone, so let's make the last command reset
* the modem.
*/
sleep(2);
write(fd, "\rATZ\r", 5);
close(fd);
delock(devSel);
}
}
#endif HAYESQ
#ifdef VENTEL
ventopn(telno, flds, dev)
char *flds[], *telno;
struct Devices *dev;
{
int dh;
int i, ok = -1;
char dcname[20];
sprintf(dcname, "/dev/%s", dev->D_line);
if (setjmp(Sjbuf)) {
DEBUG(1, "timeout ventel open\n", "");
logent("ventel open", "TIMEOUT");
if (dh >= 0)
close(dh);
delock(dev->D_line);
return(CF_NODEV);
}
signal(SIGALRM, alarmtr);
getnextfd();
alarm(10);
dh = open(dcname, 2);
next_fd = -1;
if (dh < 0) {
DEBUG(4,"%s\n", errno == 4 ? "no carrier" : "can't open modem");
delock(dev->D_line);
return(errno == 4 ? CF_DIAL : CF_NODEV);
}
/* modem is open */
fixline(dh, dev->D_speed);
/* translate - to % and = to & for VenTel */
DEBUG(4, "calling %s -> ", telno);
for (i = 0; i < strlen(telno); ++i) {
switch(telno[i]) {
case '-': /* delay */
telno[i] = '%';
break;
case '=': /* await dial tone */
telno[i] = '&';
break;
case '<':
telno[i] = '%';
break;
}
}
DEBUG(4, "%s\n", telno);
sleep(1);
for(i = 0; i < 5; ++i) { /* make up to 5 tries */
slowrite(dh, "\r\r");/* awake, thou lowly VenTel! */
DEBUG(4, "wanted %s ", "$");
ok = expect("$", dh);
DEBUG(4, "got %s\n", ok ? "?" : "that");
if (ok != 0)
continue;
slowrite(dh, "K"); /* "K" (enter number) command */
DEBUG(4, "wanted %s ", "DIAL: ");
ok = expect("DIAL: ", dh);
DEBUG(4, "got %s\n", ok ? "?" : "that");
if (ok == 0)
break;
}
if (ok == 0) {
slowrite(dh, telno); /* send telno, send \r */
slowrite(dh, "\r");
DEBUG(4, "wanted %s ", "ONLINE");
ok = expect("ONLINE!", dh);
DEBUG(4, "got %s\n", ok ? "?" : "that");
}
if (ok != 0) {
if (dh > 2)
close(dh);
DEBUG(4, "venDial failed\n", "");
return(CF_DIAL);
} else
DEBUG(4, "venDial ok\n", "");
return(dh);
}
/*
* uucpdelay: delay execution for numerator/denominator seconds.
*/
#ifdef INTERVALTIMER
#define uucpdelay(num,denom) intervaldelay(1000000*num/denom)
#include <sys/time.h>
catch alarm sig
SIGALRM
struct itimerval itimerval;
itimerval.itimer_reload =
itimerval.rtime.itimer_interval =
itimerval.rtime.itimer_value =
settimer(ITIMER_REAL, &itimerval);
pause();
alarm comes in
turn off timer.
#endif INTERVALTIMER
#ifdef FASTTIMER
#define uucpdelay(num,denom) nap(60*num/denom)
/* Sleep in increments of 60ths of second. */
nap (time)
register int time;
{
static int fd;
if (fd == 0)
fd = open (FASTTIMER, 0);
read (fd, 0, time);
}
#endif FASTTIMER
#ifdef FTIME
#define uucpdelay(num,denom) ftimedelay(1000*num/denom)
#include <sys/timeb.h>
ftimedelay(n)
{
static struct timeb loctime;
ftime(&loctime);
{register i = loctime.millitm;
while (abs((int)(loctime.millitm - i))<n) ftime(&loctime);
}
}
#endif FTIME
#ifdef BUSYLOOP
#define uucpdelay(num,denom) busyloop(CPUSPEED*num/denom)
#define CPUSPEED 1000000 /* VAX 780 is 1MIPS */
#define DELAY(n) { register long N = (n); while (--N > 0); }
busyloop(n)
{
DELAY(n);
}
#endif BUSYLOOP
slowrite(fd, str)
register char *str;
{
DEBUG(6, "slowrite ", "");
while (*str) {
DEBUG(6, "%c", *str);
uucpdelay(1,10); /* delay 1/10 second */
write(fd, str, 1);
str++;
}
DEBUG(6, "\n", "");
}
ventcls(fd)
int fd;
{
if (fd > 0) {
close(fd);
sleep(5);
delock(devSel);
}
}
#endif VENTEL
#ifdef VADIC
/*
* vadopn: establish dial-out connection through a Racal-Vadic 3450.
* Returns descriptor open to tty for reading and writing.
* Negative values (-1...-7) denote errors in connmsg.
* Be sure to disconnect tty when done, via HUPCL or stty 0.
*/
vadopn(telno, flds, dev)
char *telno;
char *flds[];
struct Devices *dev;
{
int dh = -1;
int i, ok, er = 0, delay;
extern errno;
char dcname[20];
sprintf(dcname, "/dev/%s", dev->D_line);
if (setjmp(Sjbuf)) {
DEBUG(1, "timeout vadic open\n", "");
logent("vadic open", "TIMEOUT");
if (dh >= 0)
close(dh);
delock(dev->D_line);
return(CF_NODEV);
}
signal(SIGALRM, alarmtr);
getnextfd();
alarm(10);
dh = open(dcname, 2);
alarm(0);
/* modem is open */
next_fd = -1;
if (dh < 0) {
delock(dev->D_line);
return(CF_NODEV);
}
fixline(dh, dev->D_speed);
/* translate - to K for Vadic */
DEBUG(4, "calling %s -> ", telno);
delay = 0;
for (i = 0; i < strlen(telno); ++i) {
switch(telno[i]) {
case '=': /* await dial tone */
case '-': /* delay */
case '<':
telno[i] = 'K';
delay += 5;
break;
}
}
DEBUG(4, "%s\n", telno);
for(i = 0; i < 5; ++i) { /* make 5 tries */
/* wake up Vadic */
sendthem("\005\\d", dh);
DEBUG(4, "wanted %s ", "*");
ok = expect("*", dh);
DEBUG(4, "got %s\n", ok ? "?" : "that");
if (ok != 0)
continue;
sendthem("D\\d", dh); /* "D" (enter number) command */
DEBUG(4, "wanted %s ", "NUMBER?\\r\\n");
ok = expect("NUMBER?\r\n", dh);
DEBUG(4, "got %s\n", ok ? "?" : "that");
if (ok != 0)
continue;
/* send telno, send \r */
sendthem(telno, dh);
ok = expect(telno, dh);
if (ok == 0)
ok = expect("\r\n", dh);
DEBUG(4, "got %s\n", ok ? "?" : "that");
if (ok != 0)
continue;
sendthem("", dh); /* confirm number */
DEBUG(4, "wanted %s ", "DIALING: ");
ok = expect("DIALING: ", dh);
DEBUG(4, "got %s\n", ok ? "?" : "that");
if (ok == 0)
break;
}
if (ok == 0) {
sleep(10 + delay); /* give vadic some time */
DEBUG(4, "wanted ON LINE\\r\\n ", 0);
ok = expect("ON LINE\r\n", dh);
DEBUG(4, "got %s\n", ok ? "?" : "that");
}
if (ok != 0) {
sendthem("I\\d", dh); /* back to idle */
if (dh > 2)
close(dh);
DEBUG(4, "vadDial failed\n", "");
delock(dev->D_line);
return(CF_DIAL);
}
DEBUG(4, "vadic ok\n", "");
return(dh);
}
vadcls(fd) {
if (fd > 0) {
close(fd);
sleep(5);
delock(devSel);
}
}
#endif VADIC
#ifdef RVMACS
/*
* Racal-Vadic 'RV820' MACS system with 831 adaptor.
* A typical 300 baud L-devices entry is
* ACU /dev/tty10 /dev/tty11,48 300 rvmacs
* where tty10 is the communication line (D_Line),
* tty11 is the dialer line (D_calldev),
* the '4' is the dialer address + modem type (viz. dialer 0, Bell 103),
* and the '8' is the communication port (they are 1-indexed).
* BUGS:
* Only tested with one dialer, one modem
* uses common speed for dialer and communication line.
* UNTESTED
*/
#define STX 02 /* Access Adaptor */
#define ETX 03 /* Transfer to Dialer */
#define SI 017 /* Buffer Empty (end of phone number) */
#define SOH 01 /* Abort */
rvmacsopn(ph, flds, dev)
char *ph, *flds[];
struct Devices *dev;
{
register int va, i, child;
register char *p;
char c, acu[20], com[20];
child = -1;
if ((p = index(dev->D_calldev, ',')) == NULL) {
DEBUG(2, "No dialer/modem specification\n", 0);
goto failret;
}
*p++ = '\0';
if (setjmp(Sjbuf)) {
logent("rvmacsopn", "TIMEOUT");
i = CF_DIAL;
goto ret;
}
DEBUG(4, "STARTING CALL\n", 0);
sprintf(acu, "/dev/%s", dev->D_calldev);
getnextfd();
signal(SIGALRM, alarmtr);
alarm(30);
if ((va = open(acu, 2)) < 0) {
logent(acu, "CAN'T OPEN");
i = CF_NODEV;
goto ret;
}
fixline(va, dev->D_speed);
p_chwrite(va, STX); /* access adaptor */
i = *p++ - '0';
if (i < 0 || i > 7) {
logent(p-1, "Bad dialer address/modem type\n");
goto failret;
}
p_chwrite(va, i); /* Send Dialer Address Digit */
i = *p - '0';
if (i <= 0 || i > 14) {
logent(p-1, "Bad modem address\n");
goto failret;
}
p_chwrite(va, i-1); /* Send Modem Address Digit */
write(va, ph, strlen(ph)); /* Send Phone Number */
p_chwrite(va, SI); /* Send Buffer Empty */
p_chwrite(va, ETX); /* Initiate Call */
sprintf(com, "/dev/%s", dev->D_line);
/* create child to open comm line */
if ((child = fork()) == 0) {
signal(SIGINT, SIG_DFL);
open(com, 0);
sleep(5);
exit(1);
}
if (read(va, &c, 1) != 1) {
logent("ACU READ", "FAILED");
goto failret;
}
switch(c) {
case 'A':
/* Fine! */
break;
case 'B':
DEBUG(2, "CALL ABORTED\n", 0);
goto failret;
case 'D':
DEBUG(2, "Dialer format error\n", 0);
goto failret;
case 'E':
DEBUG(2, "Dialer parity error\n", 0);
goto failret;
case 'F':
DEBUG(2, "Phone number too long\n", 0);
goto failret;
case 'G':
DEBUG(2, "Busy signal\n", 0);
goto failret;
default:
DEBUG(2, "Unknown MACS return code '%c'\n", i);
goto failret;
}
/*
* open line - will return on carrier
*/
if ((i = open(com, 2)) < 0) {
if (errno == EIO)
logent("carrier", "LOST");
else
logent("dialup open", "FAILED");
goto failret;
}
fixline(i, dev->D_speed);
goto ret;
failret:
i = CF_DIAL;
ret:
alarm(0);
if (child != -1)
kill(child, SIGKILL);
close(va);
return(i);
}
rvmacscls(fd)
register int fd;
{
DEBUG(2, "MACS close %d\n", fd);
p_chwrite(fd, SOH);
/* ioctl(fd, TIOCCDTR, NULL);*/
close(fd);
}
#endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.