static char sccsid
[] = "@(#)condevs.c 5.14 (Berkeley) %G%";
extern char *sys_errlist
[];
* 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.
* ---------------------------------------------------------------------
* 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
* THE FIX: Don't declare variables to be register
struct condev condevs
[] = {
{ "DIR", "direct", diropn
, nulldev
, dircls
},
{ "DK", "datakit", dkopn
, nulldev
, nulldev
},
{ "PNET", "pnet", pnetopn
, nulldev
, nulldev
},
{ "TCP", "TCP", unetopn
, nulldev
, unetcls
},
{ "TCP", "TCP", bsdtcpopn
, nulldev
, bsdtcpcls
},
{ "MICOM", "micom", micopn
, nulldev
, miccls
},
{ "ACU", "dn11", Acuopn
, dnopn
, dncls
},
{ "ACU", "hayes", Acuopn
, hyspopn
, hyscls
},
{ "ACU", "hayespulse", Acuopn
, hyspopn
, hyscls
},
{ "ACU", "hayestone", Acuopn
, hystopn
, hyscls
},
{ "WATS", "hayestone", Acuopn
, hystopn
, hyscls
},
{ "ACU", "hayes2400", Acuopn
, hyspopn24
, hyscls24
},
{ "ACU", "hayes2400pulse", Acuopn
, hyspopn24
, hyscls24
},
{ "ACU", "hayes2400tone", Acuopn
, hystopn24
, hyscls24
},
#ifdef HAYESQ /* a version of hayes that doesn't use result codes */
{ "ACU", "hayesq", Acuopn
, hysqpopn
, hysqcls
},
{ "ACU", "hayesqpulse", Acuopn
, hysqpopn
, hysqcls
},
{ "ACU", "hayesqtone", Acuopn
, hysqtopn
, hysqcls
},
{ "ACU", "cds224", Acuopn
, cdsopn224
, cdscls224
},
{ "ACU", "novation", Acuopn
, novopn
, novcls
},
{ "ACU", "DF02", Acuopn
, df2opn
, df2cls
},
{ "ACU", "DF112P", Acuopn
, df12popn
, df12cls
},
{ "ACU", "DF112T", Acuopn
, df12topn
, df12cls
},
{ "ACU", "ventel", Acuopn
, ventopn
, ventcls
},
{ "ACU", "penril", Acuopn
, penopn
, pencls
},
{ "ACU", "vadic", Acuopn
, vadopn
, vadcls
},
{ "ACU", "va212", Acuopn
, va212opn
, va212cls
},
{ "ACU", "va811s", Acuopn
, va811opn
, va811cls
},
{ "ACU", "va820", Acuopn
, va820opn
, va820cls
},
{ "WATS", "va820", Acuopn
, va820opn
, va820cls
},
{ "ACU", "rvmacs", Acuopn
, rvmacsopn
, rvmacscls
},
{ "ACU", "vmacs", Acuopn
, vmacsopn
, vmacscls
},
{ "SYTEK", "sytek", sykopn
, nulldev
, sykcls
},
/* Insert new entries before this line */
{ NULL
, NULL
, NULL
, NULL
, NULL
}
* nulldev a null device (returns CF_DIAL)
* nodev a null device (returns CF_NODEV)
* Generic devices look through L-devices and call the CU_open routines for
* appropriate devices. Some things, like the tcp/ip interface, or direct
* connect, do not use the CU_open entry. ACUs must search to find the
* diropn(flds) connect to hardware line
register int dcr
, status
;
#ifdef VMSDTR /* Modem control on vms(works dtr) */
int sys$
qiow(); /* use this for long reads on vms */
dfp
= fopen(DEVFILE
, "r");
ASSERT(dfp
!= NULL
, "CAN'T OPEN", DEVFILE
, 0);
while ((status
= rddev(dfp
, &dev
)) != FAIL
) {
#ifdef VMSDTR /* Modem control on vms(works dtr) */
/* If we find MOD in the device type field we go into action */
if (strcmp(dev
.D_type
, "MOD") == SAME
) {
DEBUG(7, "Setting Modem control to %d",modem_control
);
if (strcmp(flds
[F_CLASS
], dev
.D_class
) != SAME
)
* Modem control on vms(works dtr) Take anything in MOD class.
* It probably should work differently anyway so we can have
* multiple hardwired lines.
if (!modem_control
&&strcmp(flds
[F_PHONE
], dev
.D_line
) != SAME
)
if (strcmp(flds
[F_CLASS
], dev
.D_class
) != SAME
)
if (strcmp(flds
[F_PHONE
], dev
.D_line
) != SAME
)
if (mlock(dev
.D_line
) != FAIL
)
sprintf(dcname
, "/dev/%s", dev
.D_line
);
DEBUG(4, "Open timed out\n", CNULL
);
signal(SIGALRM
, alarmtr
);
/* For PC Pursuit, it could take a while to call back */
alarm( strcmp(flds
[F_LINE
], "PCP") ? 10 : MAXMSGTIME
*4 );
DEBUG(4,"Opening %s\n",dcname
);
dcr
= open(dcname
, 2); /* read/write */
#ifdef VMSDTR /* Modem control on vms(works dtr) */
if (modem_control
) { /* Did we have MOD in the device type field ? */
/* Sense the current terminal setup and save it */
if ((ret
= sys$
qiow(_$EFN
,(fd_fab_pointer
[dcr
]->fab
).fab$l_stv
,
IO$_SENSEMODE
,iosb
,0,0,mode
,8,0,0,0,0))
DEBUG(7, "ret status on sense failed on Modem sense=%x<", ret
);
mode
[1] |= TT$M_MODEM
; /* Or in modem control(DTR) */
/* Now set the new terminal characteristics */
/* This is temporary and will go away when we let go of it */
if ((ret
= sys$
qiow(_$EFN
,(fd_fab_pointer
[dcr
]->fab
).fab$l_stv
,
IO$_SETMODE
,iosb
,0,0,mode
,8,0,0,0,0))
DEBUG(7, "ret status on sense failed on Modem setup=%x<", ret
);
logent(dev
.D_line
, "CANT OPEN");
DEBUG(4, "OPEN FAILED: errno %d\n", errno
);
if (fixline(dcr
, dev
.D_speed
) == FAIL
) {
DEBUG(4, "FIXLINE FAILED\n", CNULL
);
strcpy(devSel
, dev
.D_line
); /* for latter unlock */
* 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.
char devSel
[20]; /* used for later unlock() */
register struct condev
*cd
;
register int fd
, acustatus
;
char nobrand
[MAXPH
], *line
;
exphone(flds
[F_PHONE
], phone
);
if (snccmp(flds
[F_LINE
], "LOCAL") == SAME
)
DEBUG(4, "Dialing %s\n", phone
);
dfp
= fopen(DEVFILE
, "r");
ASSERT(dfp
!= NULL
, "Can't open", DEVFILE
, 0);
acustatus
= 0; /* none found, none locked */
while (rddev(dfp
, &dev
) != FAIL
) {
* for each ACU L.sys line, try at most twice
* (TRYCALLS) to establish carrier. The old way tried every
* available dialer, which on big sites takes forever!
* Sites with a single auto-dialer get one try.
* Sites with multiple dialers get a try on each of two
* To try 'harder' to connect to a remote site,
* use multiple L.sys entries.
if (acustatus
> TRYCALLS
)
if (strcmp(flds
[F_CLASS
], dev
.D_class
) != SAME
)
if (snccmp(line
, dev
.D_type
) != SAME
)
if (dev
.D_brand
[0] == '\0') {
logent("Acuopn","No 'brand' name on ACU");
for(cd
= condevs
; cd
->CU_meth
!= NULL
; cd
++) {
if (snccmp(line
, cd
->CU_meth
) == SAME
) {
if (snccmp(dev
.D_brand
, cd
->CU_brand
) == SAME
)
strncpy(nobrand
, dev
.D_brand
, sizeof nobrand
);
if (mlock(dev
.D_line
) == FAIL
) {
acustatus
= 1; /* has been found */
if (snccmp("inout", dev
.D_calldev
) == SAME
) {
if (disable(dev
.D_line
) == FAIL
) {
DEBUG(4, "Using %s\n", cd
->CU_brand
);
fd
= (*(cd
->CU_open
))(phone
, flds
, &dev
);
CU_end
= cd
->CU_clos
; /* point CU_end at close func */
strcpy(devSel
, dev
.D_line
); /* save for later unlock() */
logent(nobrand
, "unsupported ACU type");
logent("L-devices", "No appropriate ACU");
* intervaldelay: delay execution for numerator/denominator seconds.
#define uucpdelay(num,denom) intervaldelay(num,denom)
tv
.tv_usec
= (num
* 1000000L / denom
) % 1000000L;
(void) select (0, (int *)0, (int *)0, (int *)0, &tv
);
#define uucpdelay(num,denom) nap(60*num/denom)
/* Sleep in increments of 60ths of second. */
fd
= open (FASTTIMER
, 0);
#define uucpdelay(num,denom) ftimedelay(1000*num/denom)
static struct timeb loctime
;
register i
= loctime
.millitm
;
while (abs((int)(loctime
.millitm
- i
))<n
) ftime(&loctime
)
#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); }
DEBUG(6, "slowrite ", CNULL
);
uucpdelay(1, 10); /* delay 1/10 second */
if (ioctl(fn
, TCSBRK
, STBNULL
) < 0)
DEBUG(5, "break TCSBRK %s\n", sys_errlist
[errno
]);
if (ioctl(fn
, TIOCSBRK
, STBNULL
) < 0)
DEBUG(5, "break TIOCSBRK %s\n", sys_errlist
[errno
]);
if (ioctl(fn
, TIOCCBRK
, STBNULL
) < 0)
DEBUG(5, "break TIOCCBRK %s\n", sys_errlist
[errno
]);
DEBUG(4, "ioctl %f second break\n", (float) bnulls
/10 );
if (ioctl(fn
, TIOCGETP
, &ttbuf
) < 0)
DEBUG(5, "break TIOCGETP %s\n", sys_errlist
[errno
]);
sospeed
= ttbuf
.sg_ospeed
;
ttbuf
.sg_ospeed
= BSPEED
;
if (ioctl(fn
, TIOCSETP
, &ttbuf
) < 0)
DEBUG(5, "break TIOCSETP %s\n", sys_errlist
[errno
]);
if (write(fn
, "\0\0\0\0\0\0\0\0\0\0\0\0", bnulls
) != bnulls
) {
logent(sys_errlist
[errno
], "BAD WRITE genbrk");
ttbuf
.sg_ospeed
= sospeed
;
if (ioctl(fn
, TIOCSETP
, &ttbuf
) < 0)
DEBUG(5, "break ioctl %s\n", sys_errlist
[errno
]);
if (write(fn
, "@", 1) != 1)
DEBUG(4, "sent BREAK nulls - %d\n", bnulls
);
/* DIALIN/OUT CODE (WLS) */
* disable and reenable: allow a single line to be use for dialin/dialout
/* strip off directory prefixes */
while (--rdev
>= dev
&& *rdev
!= '/')
if (strcmp(enbdev
, rdev
) == SAME
)
return SUCCESS
; /* already disabled */
reenable(); /* else, reenable the old one */
DEBUG(4, "Disable %s\n", rdev
);
if (enbcall("disable", rdev
) == FAIL
)
DEBUG(4, "Reenable %s\n", enbdev
);
(void) enbcall("enable", enbdev
);
if ((pid
= fork()) == 0) {
DEBUG(4, DIALINOUT
, CNULL
);
close(0); close(1); close(2);
dup(fildes
[1]); dup(fildes
[1]);
setuid(geteuid()); /* for chown(uid()) in acu program */
execl(DIALINOUT
, "acu", type
, dev
, 0);
fil
= fdopen(fildes
[0],"r");
while (fgets(buf
, sizeof buf
, fil
) != NULL
) {
p
= buf
+ strlen(buf
) - 1;
while(wait(&status
) != pid
)
return status
? FAIL
: SUCCESS
;