static char sccsid
[] = "@(#)conn.c 5.8 (Berkeley) %G%";
extern int errno
, onesys
;
extern char *sys_errlist
[];
extern char MaxGrade
, DefMaxGrade
;
/* Parity control during login procedure */
char par_tab
[128]; /* must be power of two */
int linebaudrate
; /* used for the sleep test in pk1.c */
int next_fd
= -1; /* predicted fd to close interrupted opens */
/* rti!trt, courtesy unc!smb */
* catch alarm routine for "expect".
signal(SIGALRM
, alarmtr
);
logent("FAIL", "ACU LINE CLOSE");
* place a telephone call to system and login, etc.
* CF_SYSTEM: don't know system
* CF_TIME: wrong time to call
* CF_NODEV: no devices available to place call
* CF_LOGIN: login/password dialog failed
* >0 - file no. - connect ok
char info
[MAXC
], wkpre
[NAMESIZE
], file
[NAMESIZE
];
fsys
= fopen(SYSFILE
, "r");
ASSERT(fsys
!= NULL
, "CAN'T OPEN", SYSFILE
, 0);
DEBUG(4, "finds (%s) called\n", system
);
while((nf
= finds(fsys
, system
, info
, Flds
)) > 0) {
if (strcmp("TCP", Flds
[F_LINE
])
&& strcmp("DIR", Flds
[F_LINE
])
&& strcmp("LOCAL", Flds
[F_LINE
]) )
sprintf(wkpre
, "%c.%.*s", CMDPRE
, SYSNSIZE
, Rmtname
);
if (!onesys
&& MaxGrade
!= DefMaxGrade
&&
!iswrk(file
, "chk", Spool
, wkpre
))
if (fn
!= CF_TIME
&& (fn
= getto(Flds
)) > 0) {
fcode
= (fn
== FAIL
? CF_DIAL
: fn
);
return fcode
? fcode
: nf
;
DEBUG(4, "login %s\n", "called");
ret
= login(nf
, Flds
, fn
);
* connect to remote machine
register struct condev
*cd
;
DEBUG(4, "getto: call no. %s ", flds
[F_PHONE
]);
DEBUG(4, "for sys %s\n", flds
[F_NAME
]);
if (snccmp(flds
[F_LINE
], "LOCAL") == SAME
)
if (snccmp(line
, "ACU") != SAME
)
for (cd
= condevs
; cd
->CU_meth
!= NULL
; cd
++) {
if (snccmp(cd
->CU_meth
, line
) == SAME
) {
DEBUG(4, "Using %s to call\n", cd
->CU_meth
);
return (*(cd
->CU_gen
))(flds
);
DEBUG(1, "Can't find %s, assuming DIR\n", flds
[F_LINE
]);
return diropn(flds
); /* search failed, so use direct */
int (*CU_end
)() = nulldev
;
/* make *sure* Dcf is no longer exclusive.
* Otherwise dual call-in/call-out modems could get stuck.
* Unfortunately, doing this here is not ideal, but it is the
* easiest place to put the call.
* Hopefully everyone honors the LCK protocol, of course
if (!IsTcpIp
&& Dcf
>= 0 && ioctl(Dcf
, TIOCNXCL
, STBNULL
) < 0)
DEBUG(5, "clsacu ioctl %s\n", sys_errlist
[errno
]);
logent(Rmtname
, "CLOSE TIMEOUT");
signal(SIGALRM
, alarmtr
);
DEBUG(4, "fd %d NOT CLOSED by CU_clos\n", Dcf
);
logent("clsacu", "NOT CLOSED by CU_clos");
* expand phone number for given prefix and number
char pre
[MAXPH
], npart
[MAXPH
], tpre
[MAXPH
], p
[MAXPH
];
if (!isascii(*in
) || !isalpha(*in
)) {
while (isascii(*in
) && isalpha(*in
))
if ((fn
= fopen(DIALFILE
, "r")) == NULL
)
DEBUG(2, "CAN'T OPEN %s\n", DIALFILE
);
while (cfgets(buf
, BUFSIZ
, fn
)) {
if (sscanf(buf
, "%s%s", p
, tpre
) != 2)
if (strcmp(p
, pre
) == SAME
)
DEBUG(2, "CAN'T FIND dialcodes prefix '%s'\n", pre
);
* read and decode a line from device file
* return code - FAIL at end-of file; 0 otherwise
register struct Devices
*dev
;
if (!cfgets(dev
->D_argbfr
, sizeof(dev
->D_argbfr
), fp
))
na
= getargs(dev
->D_argbfr
, dev
->D_arg
, 20);
ASSERT(na
>= 4, "BAD DEVICE ENTRY", dev
->D_argbfr
, 0);
dev
->D_speed
= atoi(fdig(dev
->D_class
));
* set system attribute vector
* >0 - number of arguments in vector - succeeded
* CF_SYSTEM - system name not found
* CF_TIME - wrong time to call
finds(fsys
, sysnam
, info
, flds
)
char *sysnam
, info
[], *flds
[];
while (cfgets(info
, MAXC
, fsys
) != NULL
) {
na
= getargs(info
, flds
, MAXC
/10);
if (strncmp(sysnam
, flds
[F_NAME
], MAXBASENAME
) != SAME
)
if (ifdate(flds
[F_TIME
]) != FAIL
)
DEBUG(2, "Wrong time ('%s') to call\n", flds
[F_TIME
]);
return fcode
? fcode
: CF_SYSTEM
;
* return codes: SUCCESS | FAIL
register char *want
, *altern
;
ASSERT(nf
> 4, "TOO FEW LOG FIELDS", CNULL
, nf
);
for (k
= F_LOGIN
; k
< nf
; k
+= 2) {
altern
= index(want
, '-');
if (strcmp(want
, "ABORT") == 0) {
DEBUG(4, "ABORT ON: %s\n", AbortOn
);
DEBUG(4, "wanted: %s\n", want
);
DEBUG(4, "got: %s\n", ok
? "?" : "that");
logent("LOGIN", _FAILED
);
want
= index(altern
, '-');
logent("LOGIN ABORTED", _FAILED
);
/* conditional table generation to support odd speeds */
struct sg_spds
{int sp_val
, sp_name
;} spds
[] = {
register struct sg_spds
*ps
;
for (ps
= spds
; ps
->sp_val
; ps
++)
if (ps
->sp_val
== spwant
)
ASSERT(speed
>= 0, "BAD SPEED", CNULL
, speed
);
if (ioctl(tty
, TCGETA
, &ttbuf
) < 0)
/* ttbuf.sg_flags = (ANYP|RAW);
ttbuf.sg_ispeed = ttbuf.sg_ospeed = speed; */
ttbuf
.c_iflag
= (ushort
)0;
ttbuf
.c_oflag
= (ushort
)0;
ttbuf
.c_cflag
= (speed
|CS8
|HUPCL
|CREAD
);
ttbuf
.c_lflag
= (ushort
)0;
if (ioctl(tty
, TCSETA
, &ttbuf
) < 0)
if (ioctl(tty
, TIOCGETP
, &ttbuf
) < 0)
ttbuf
.sg_flags
= (ANYP
|RAW
);
ttbuf
.sg_ispeed
= ttbuf
.sg_ospeed
= speed
;
if (ioctl(tty
, TIOCSETP
, &ttbuf
) < 0)
if (ioctl(tty
, TIOCHPCL
, STBNULL
) < 0)
if (ioctl(tty
, TIOCEXCL
, STBNULL
) < 0)
* getbaud(tty) set linebaudrate variable
register struct sg_spds
*ps
;
ioctl(tty
, TCGETA
, &ttbuf
);
name
= ttbuf
.c_cflag
& CBAUD
;
ioctl(tty
, TIOCGETP
, &ttbuf
);
for (ps
= spds
; ps
->sp_val
; ps
++)
if (ps
->sp_name
== name
) {
linebaudrate
= ps
->sp_val
;
* look for expected string
* FAIL - lost line or too many characters read
* some character - timed out
register char *rp
= rdvec
, *strptr
;
if (*str
== '\0' || strcmp(str
, "\"\"") == SAME
)
/* Cleanup str, convert \0xx strings to one char */
for (strptr
= str
; *strptr
; strptr
++) {
DEBUG(5, "BLANK\n", CNULL
);
strptr
--; /* back up to backslash */
sscanf(strptr
+ 1,"%o", &cnt_char
);
DEBUG(6, "BACKSLASHED %02xH\n", cnt_char
);
*strptr
= (char) (cnt_char
);
strcpy(&strptr
[1], &strptr
[4]);
strptr
= index(str
, '~');
signal(SIGALRM
, alarmtr
);
while (notin(str
, rdvec
)) {
if(AbortOn
!= NULL
&& !notin(AbortOn
, rdvec
)) {
DEBUG(1, "Call aborted on '%s'\n", AbortOn
);
kr
= read(fn
, &nextch
, 1);
DEBUG(4, "lost line kr - %d\n, ", kr
);
logent("LOGIN", "LOST LINE");
DEBUG(4, c
>= 040 ? "%c" : "\\%03o", c
);
if ((*rp
= nextch
& 0177) != '\0')
for (p
= rdvec
+MR
/2; p
< rp
; p
++)
* Determine next file descriptor that would be allocated.
* This permits later closing of a file whose open was interrupted.
* It is a UNIX kernel problem, but it has to be handled.
* unc!smb (Steve Bellovin) probably first discovered it.
close(next_fd
= open("/", 0));
* send line of login sequence
DEBUG(5, "send %s\n", str
);
if (prefix("BREAK", str
)) {
sscanf(&str
[5], "%1d", &i
);
if (prefix("PAUSE", str
)) {
sscanf(&str
[5], "%1d", &i
);
if (strcmp(str
, "EOT") == SAME
) {
if (strcmp(str
, "LF") == SAME
)
if (strcmp(str
, "CR") == SAME
)
/* Set parity as needed */
if (strcmp(str
, "P_ZERO") == SAME
) {
if (strcmp(str
, "P_ONE") == SAME
) {
if (strcmp(str
, "P_EVEN") == SAME
) {
if (strcmp(str
, "P_ODD") == SAME
) {
/* If "", just send '\r' */
if (strcmp(str
, "\"\"") == SAME
) {
for (strptr
= str
; c
= *strptr
++;) {
DEBUG(5, "BLANK\n", CNULL
);
DEBUG(5, "DELAY\n", CNULL
);
DEBUG(5, "RETURN\n", CNULL
);
DEBUG(5, "NO CR\n", CNULL
);
DEBUG(5, "NO CR - MIDDLE IGNORED\n", CNULL
);
while (isdigit(*strptr
) && ++n
<= 3)
i
= i
*8 + (*strptr
++ - '0');
DEBUG(5, "BACKSLASH\n", CNULL
);
if (write(fd
, &c
, 1) != 1) {
logent(sys_errlist
[errno
], "BAD WRITE");
* generate parity table for use by p_chwrite.
for (i
= 0; i
< sizeof(par_tab
); i
++) {
for (j
= i
&(sizeof(par_tab
)-1); j
; j
= (j
-1)&j
)
|| (type
== P_EVEN
&& (n
&01) != 0)
|| (type
== P_ODD
&& (n
&01) == 0))
par_tab
[i
] |= sizeof(par_tab
);
if (ioctl(fn
, TCSBRK
, STBNULL
) < 0)
DEBUG(5, "break ioctl %s\n", sys_errlist
[errno
]);
if (ioctl(fn
, TIOCSBRK
, STBNULL
) < 0)
DEBUG(5, "break ioctl %s\n", sys_errlist
[errno
]);
if (ioctl(fn
, TIOCCBRK
, STBNULL
) < 0)
DEBUG(5, "break ioctl %s\n", sys_errlist
[errno
]);
DEBUG(4, "ioctl %d second break\n", bnulls
);
if (ioctl(fn
, TIOCGETP
, &ttbuf
) < 0)
DEBUG(5, "break ioctl %s\n", sys_errlist
[errno
]);
sospeed
= ttbuf
.sg_ospeed
;
ttbuf
.sg_ospeed
= BSPEED
;
if (ioctl(fn
, TIOCSETP
, &ttbuf
) < 0)
DEBUG(5, "break ioctl %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
);
* check for occurrence of substring "sh"
* Allow multiple date specifications separated by ','.
/* pick up retry time for failures */
/* global variable Retrytime is set here */
if ((np
= index(p
, ';')) == NULL
) {
i
= sscanf(np
+1, "%d", &rtime
);
np
= strpbrk(p
, ",|"); /* prefer , but allow | for compat */
DEBUG(11,"ifadate returns %o\n", g
);
* this routine will check a string (string)
* like "MoTu0800-1730" to see if the present
* time is within the given limits.
* SIDE EFFECT - Retrytime is set
"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", 0
register char *s
= string
;
int i
, tl
, th
, tn
, dayok
=0;
if ((p
= index(s
, '/')) == NULL
)
while (isascii(*s
) && isalpha(*s
)) {
for (i
= 0; days
[i
]; i
++) {
if (tp
->tm_wday
>= 1 && tp
->tm_wday
<= 5)
if (prefix("Evening", s
)) {
if (tp
->tm_wday
== 6 || tp
->tm_wday
== 0
|| tp
->tm_hour
>= 17 || tp
->tm_hour
< 8)
if (prefix("Night", s
)) {
if (tp
->tm_wday
== 6 /* Sat */
|| tp
->tm_hour
>= 23 || tp
->tm_hour
< 8
|| (tp
->tm_wday
== 0 && tp
->tm_hour
< 17))
if (dayok
== 0 && s
!= string
)
i
= sscanf(s
, "%d-%d", &tl
, &th
);
tn
= tp
->tm_hour
* 100 + tp
->tm_min
;
if (th
< tl
) { /* crosses midnight */
if (th
< tl
) { /* crosses midnight */
* find first digit in string
* return - pointer to first digit in string or end of string
if (*c
>= '0' && *c
<= '9')
* Compare strings: s1>s2: >0 s1==s2: 0 s1<s2: <0
* Strings are compared as if they contain all capital letters.
* Compare strings: s1>s2: >0 s1==s2: 0 s1<s2: <0
* Strings are compared as if they contain all capital letters.
while ( --n
>= 0 && c1
== c2
) {
return n
<0 ? 0 : (c1
- c2
);
* occurs after local port is opened,
* before 'dialing' the other machine.
register struct Devices
*dev
;
char bfr
[sizeof(dev
->D_argbfr
)];
DEBUG(4, "dochat called %d\n", dev
->D_numargs
);
for (i
= 0; i
< dev
->D_numargs
-5; i
++) {
sprintf(bfr
, dev
->D_arg
[D_CHAT
+i
], flds
[F_PHONE
]);
if (strcmp(bfr
, dev
->D_arg
[D_CHAT
+i
])) {
p
= malloc((unsigned)strlen(bfr
)+1);
dev
->D_arg
[D_CHAT
+i
] = p
;
/* following is a kludge because login() arglist is a kludge */
i
= login(dev
->D_numargs
, &dev
->D_arg
[D_CHAT
-5], fd
);
* If login() last did a sendthem(), must pause so things can settle.
* But don't bother if chat failed.
if (i
== 0 && (dev
->D_numargs
&01))