static char sccsid
[] = "@(#)conn.c 4.1 (Berkeley) 9/11/82";
/* conn 2.1 5/23/79 19:07:44 */
/**********************************************************************
* Modified 9/81 by jrl for autodiallers built into a modem. The table
* "autotbl" below can be expanded to deal with other autodiallers.
* Modifed 2/82 by ctc to add the Port Selector Code. This allows
* the new \b and \c type constructs. Also modified to make use of the
* new UCB tty TIOSBRK and TIOCBRK iotcl's. And last of all increased
* MR from 1000 to 2000 as per Bill Shannon's instructions.
* Modified 6/82 by Dave Martindale, U of Waterloo to support the Vadic
* AD3451 autodialing modem and the extended getargs (control chars in
* strings, embedded blanks in strings). Expect() now takes an argument
* specifying how long the timeout should be - dialing takes a long time.
* sendthem() no longer scribbles on the string it is passed, and appends
* CR rather than NL to end of string by default.
* notin() now calls wprefix, so the expect string can contain '?' to
* match any character. ifdate() handles times which cross midnight.
* 2400 baud is supported. Finally, a few bugs fixed: login() closes
* the line's file descriptor on login failure; expect() checks for
* overflow of rdvec before stuffin the null in; a few strings fixed up.
**********************************************************************/
static char SiD
[] = "@(#)conn 2.1";
#define INVOKE(a, r) ret = a; if (ret<0) return(r);
* conn - place a telephone call to system and
* CF_SYSTEM: don't know system
* CF_TIME: wrong time to call
* CF_LOGIN: login/password dialog failed
* >0 - file no. - connect ok
DEBUG(4, "gdial %s\n", "called");
DEBUG(4, "finds %s\n", "called");
INVOKE(nf
= finds(system
, flds
), nf
)
DEBUG(4, "getto %s\n", "called");
INVOKE(fn
= getto(flds
), CF_DIAL
)
DEBUG(4, "login %s\n", "called");
INVOKE(login(nf
, flds
, fn
), CF_LOGIN
)
* lastc(s) return pointer to last character
#define MAXCCH MAXCODE*20
/* This array tells us about possible acu's, etc. */
* gdial() get device and dial info
fn
= fopen(Devfile
, "r");
ASSERT(fn
!= NULL
, "CAN'T OPEN %s", Devfile
);
for (pd
= Devs
; fgets(lb
, 200, fn
); pd
++) {
ASSERT(nr
== 4, "BAD LINE %s", lb
);
pd
->D_speed
= atoi(flds
[3]);
ASSERT(lb
< Devbuff
+ MAXDCH
, "TOO LONG %s", Devbuff
);
ASSERT(pd
< Devs
+ MAXDEV
, "TOO MANY DEVICES %d", MAXCODE
);
ASSERT(pd
> Devs
, "BAD FILE %s", Devfile
);
/* Now dialcodes, same way */
fn
= fopen(Dialfile
, "r");
ASSERT(fn
!= NULL
, "CAN'T OPEN %s", Dialfile
);
for (pc
= Dialcodes
; fgets(lc
, 200, fn
); pc
++) {
if (nr
== 1) flds
[nr
++] = "";
ASSERT(nr
== 2, "BAD LINE %s", lc
);
ASSERT(lc
< Codebuff
+ MAXCCH
, "TOO LONG %s", Codebuff
);
ASSERT(pc
< Dialcodes
+ MAXCODE
, "MANY DEVICES %d", MAXCODE
);
* ckdev(type, speed, ndev)
* ckdev - return the device number in table Devs for
* a device with proper attributes.
* return codes: >= 0 (ok) | FAIL
for (pd
= &Devs
[ndev
]; pd
->D_line
!= NULL
; pd
++) {
if ((prefix(type
, pd
->D_type
)) /* allow prefix here */
return(ndev
= pd
- Devs
);
if ((strcmp(pd
->D_line
, type
) == SAME
)
return(ndev
= pd
- Devs
);
* getto(flds) connect to remote machine
DEBUG(4, "call: no. %s ", flds
[F_PHONE
]);
DEBUG(4, "for sys %s ", flds
[F_NAME
]);
if (prefix("ACU", flds
[F_LINE
]))
else if (prefix("DK", flds
[F_LINE
]))
* call(flds) call remote machine
* "flds" contains the call information (name, date, type, speed,
* Ndev has the device no.
char *pno
, pref
[20], phone
[20];
for (pc
= Dialcodes
; pc
->C_locs
; pc
++)
if (strcmp(pc
->C_locs
, pref
) == SAME
) {
sprintf(phone
, "%s%s", s1
, s2
);
for (i
= 0; i
< TRYCALLS
; i
++) {
DEBUG(4, "Dial %s\n", phone
);
dcr
= dialup(phone
, flds
);
DEBUG(4, "dcr returned as %d\n", dcr
);
/* file descriptor for call unit */
* dialup(ph, flds) dial remote machine
* file descriptor - succeeded
int vad3451P(), ven212(), decdial();
"ACUVADIC3451P", vad3451P
,
char dcname
[20], dnname
[20], phone
[20];
register struct Devices
*pd
;
int nw
, lt
, pid
, dcf
, ndev
, timelim
;
register struct autotbl
*ap
;
ndev
= ckdev(flds
[F_LINE
], flds
[F_SPEED
], ndev
);
logent("AVAILABLE DEVICE", "NO");
DEBUG(4, "NO AVAILABLE DEVICE %s\n", "");
sprintf(dcname
, "/dev/%s", pd
->D_line
);
/* disable logins on the line */
/* check for autodialler */
for(ap
= autotbl
; ap
->atb_name
; ap
++)
if(!strcmp(ap
->atb_name
, pd
->D_type
)) {
DEBUG(4, "AUTODIAL %s\n", ap
->atb_name
);
dcf
= (*ap
->atb_fn
)(dcname
, ph
, pd
->D_speed
,
if(dcf
< 0) { /* dismal failure */
logent("AUTODIAL FAILED", pd
->D_line
);
DEBUG(4, "DIAL %s FAILED\n", pd
->D_line
);
fixline(dcf
, pd
->D_speed
);
/* make sure it's a regular ACU */
if(strcmp("ACU", pd
->D_type
) != SAME
) {
/* use regular dialler */
sprintf(dnname
, "/dev/%s", pd
->D_calldev
);
sprintf(phone
, "%s%s", ph
, ACULAST
);
DEBUG(4, "dc - %s, ", dcname
);
DEBUG(4, "acu - %s\n", dnname
);
DEBUG(1, "DN write %s\n", "timeout");
logent("DIALUP DN write", "TIMEOUT");
signal(SIGALRM
, alarmtr
);
timelim
= 5 * strlen(phone
);
alarm(timelim
< 30 ? 30 : timelim
);
if ((pid
= fork()) == 0) {
nw
= write(Dnf
, phone
, lt
= strlen(phone
));
DEBUG(1, "ACU write %s\n", "error");
logent("DIALUP ACU write", "FAILED");
DEBUG(4, "ACU write ok%s\n", "");
/* open line - will return on carrier */
DEBUG(4, "dcf is %d\n", dcf
);
DEBUG(1, "Line open %s\n", "failed");
logent("DIALUP LINE open", "FAILED");
while ((nw
= wait(<
)) != pid
&& nw
!= -1)
fixline(dcf
, pd
->D_speed
);
DEBUG(4, "Forked %d ", pid
);
DEBUG(4, "Wait got %d ", nw
);
DEBUG(4, "Status %o\n", lt
);
* clsacu() close call unit
* direct(flds) connect to hardware line
if ((ndev
= ckdev(flds
[F_LINE
], flds
[F_SPEED
], ndev
)) < 0) {
logent("DEVICE", "NOT AVAILABLE");
sprintf(dcname
, "/dev/%s", Devs
[ndev
].D_line
);
disable(Devs
[ndev
].D_line
);
signal(SIGALRM
, alarmtr
);
dcr
= open(dcname
, 2); /* read/write */
fixline(dcr
, Devs
[ndev
].D_speed
);
* dkcall(flds) make datakit connection
signal(SIGALRM
, alarmtr
);
dkphone
= 10 * dkphone
+ (*cp
++ - '0');
DEBUG(4, "dkphone (%d) ", dkphone
);
for (i
= 0; i
< DKTRIES
; i
++) {
ret
= dkdial(D_UU
, dkphone
, 0);
DEBUG(4, "dkdial (%d)\n", ret
);
* finds(sysnam, flds) set system attribute vector
* >0 - number of arguments in vector - succeeded
* CF_SYSTEM - system name not found
* CF_TIME - wrong time to call
for (fnp
= Sysfiles
; *fnp
!= NULL
&& !fnd
; fnp
++) {
while (!fnd
&& (fgets(info
, MAXC
, fsys
) != NULL
)) {
na
= getargs(info
, flds
);
if (prefix(sysnam
, flds
[F_NAME
]))
if (ifdate(flds
[F_TIME
]) == 0) {
DEBUG(1, "Wrong time to call %s\n", sysnam
);
logent(sysnam
, "WRONG TIME TO CALL");
if (strcmp(flds
[F_LINE
], "Slave") == 0) {
DEBUG(1, "Slave only, no call to %s tried\n", sysnam
);
logent(sysnam
, "NO CALL FROM SLAVE");
* login(nf, flds, dcr) do log conversation
ASSERT(nf
> 4, "TOO FEW LOG FIELDS %d", nf
);
for (k
= F_LOGIN
; k
< nf
; k
+= 2) {
altern
= index(want
, '-');
DEBUG(4, "wanted %s ", want
);
ok
= expect(want
, fn
, MAXCHARTIME
);
DEBUG(4, "got %s\n", ok
? "?" : "that");
logent("LOGIN", "FAILED");
want
= index(altern
, '-');
struct sg_spds
{int sp_val
, sp_name
;} spds
[] = {
* fixline(tty, spwant) set speed/echo/mode...
for (ps
= spds
; ps
->sp_val
; ps
++)
if (ps
->sp_val
== spwant
)
ASSERT(speed
>= 0, "BAD SPEED %d", speed
);
ioctl(tty
, TIOCGETP
, &ttbuf
);
ttbuf
.sg_flags
=(ANYP
|RAW
);
ttbuf
.sg_ispeed
= ttbuf
.sg_ospeed
= speed
;
DEBUG(4, "Speed: want %d ", spwant
);
DEBUG(4, "use %o ", speed
);
DEBUG(4, "ps %d\n", ps
-spds
);
ret
= ioctl(tty
, TIOCSETP
, &ttbuf
);
ASSERT(ret
>= 0, "RETURN FROM STTY %d", ret
);
/*#define MR 1000 1000 chars should be enough */
/* 2000 is recommend by Bill Shannon */
* expect(str, fn, timeout) look for expected string
* FAIL - lost line or too many characters read
* some character - timed out
char nextch
= 0; /* was int /jrl */
signal(SIGALRM
, alarmtr
);
while (notin(str
, rdvec
)) {
kr
= read(fn
, &nextch
, 1);
DEBUG(4, "kr - %d\n", kr
);
DEBUG(4, "lost line kr - %d, ", kr
);
DEBUG(4, "fn - %d\n", fn
);
logent("LOGIN", "LOST LINE");
DEBUG(4, "%c", c
> 040 ? c
: '_');
if ((*rp
= nextch
& 0177) != '\0')
* alarmtr() - catch alarm routine for "expect".
* sendthem(str, fn) send line of login sequence
DEBUG(5, "send %s\n", str
);
if (prefix("BREAK", str
)) {
sscanf(&str
[5], "%1d", &nulls
);
if (nulls
<= 0 || nulls
> 10)
if (strcmp(str
, "EOT") == SAME
) {
write(fn
, EOTMSG
, (unsigned) strlen(EOTMSG
));
for (strptr
= str
; *strptr
; strptr
++) {
if (*(outp
= strptr
) == '\\')
DEBUG(5, "RETURN\n", "");
DEBUG(5, "NEWLINE\n", "");
if (isdigit(*(strptr
+1))) {
nulls
= (*++strptr
- '0');
if (nulls
<= 0 || nulls
> 10)
DEBUG(5, "BREAK - Hardware Break\n", nulls
);
DEBUG(5, "BREAK (%d nulls)\n", nulls
);
if (*(strptr
+1) == '\0') {
DEBUG(5, "NO CR - MIDDLE (IGNORED)\n", "");
DEBUG(5, "UNKNOWN ESCAPE\n", "");
DEBUG(4, "WRITE ERROR nw == %d wanted (1)\n", nw
);
ASSERT(nw
== 1, "BAD WRITE %s\n", str
);
#define BRK_WAIT 1 /* Wait one full second before clearing the break line */
ret
= ioctl(fn
, TIOCSBRK
, 0);
DEBUG(5, "ioctl ret %d\n", ret
);
ret
= ioctl(fn
, TIOCCBRK
, 0);
DEBUG(5, "ioctl ret %d\n", ret
);
DEBUG(4, "sent BREAK Using Hardware - %d second wait\n", BRK_WAIT
);
ret
= ioctl(fn
, TIOCGETP
, &ttbuf
);
DEBUG(5, "ioctl ret %d\n", ret
);
sospeed
= ttbuf
.sg_ospeed
;
ttbuf
.sg_ospeed
= BSPEED
;
ret
= ioctl(fn
, TIOCSETP
, &ttbuf
);
DEBUG(5, "ioctl ret %d\n", ret
);
ret
= write(fn
, "\0\0\0\0\0\0\0\0\0\0\0\0", bnulls
);
ASSERT(ret
> 0, "BAD WRITE genbrk %d", ret
);
ttbuf
.sg_ospeed
= sospeed
;
ret
= ioctl(fn
, TIOCSETP
, &ttbuf
);
ASSERT(ret
> 0, "BAD WRITE genbrk %d", ret
);
DEBUG(4, "sent BREAK nulls - %d\n", bnulls
);
* notin(sh, lg) check for occurrence of substring "sh"
* ifdate - this routine will check a string (s)
* like "MoTu0800-1730" to see if the present
* time is within the given limits.
* A time which crosses midnight like 2300-0800
* is interpreted as after 2300 or before 0800 on any
* suitable day, which may not be what you expected.
* (Mo2300-0800 is equivalent to Mo2300-2400,Mo0000-0800
* and not to Mo2300-2400,Tu0000-0800)
* Now can be a list: Wk0000-0745,Wk1700-2400,Sa,Su
* zero or one time means all day
"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", 0
int i
, tl
, th
, tn
, dayok
=0;
tn
= tp
->tm_hour
* 100 + tp
->tm_min
;
for(s
= sbuf
; tptr
; s
= tptr
) {
for (i
= 0; days
[i
]; i
++) {
if (tp
->tm_wday
>= 1 && tp
->tm_wday
<= 5)
i
= sscanf(s
, "%d-%d", &tl
, &th
);
} else if (tl
<= tn
|| tn
< th
)