58a864212b8b00112f804f8db92616bc64ff8409
static char sccsid
[] = "@(#)conn.c 5.2 (Berkeley) %G%";
/* Parity control during login procedure */
char par_tab
[128]; /* must be power of two */
int next_fd
= -1; /* predicted fd to close interrupted opens */
/* rti!trt, courtesy unc!smb */
* alarmtr() - catch alarm routine for "expect".
signal(SIGALRM
, alarmtr
);
logent("FAIL", "ACU LINE CLOSE");
* conn - place a telephone call to system and
* 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
], *flds
[MAXC
/10];
fsys
= fopen(SYSFILE
, "r");
ASSERT(fsys
!= NULL
, "CAN'T OPEN", SYSFILE
, 0);
DEBUG(4, "finds %s\n", "called");
while((nf
= finds(fsys
, system
, info
, flds
)) > 0) {
DEBUG(4, "getto %s\n", "called");
if ((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
);
/* rti!trt: avoid passing file to children */
* getto(flds) connect to remote machine
register struct condev
*cd
;
DEBUG(4, "call: no. %s ", flds
[F_PHONE
]);
DEBUG(4, "for sys %s\n", flds
[F_NAME
]);
for (cd
= condevs
; cd
->CU_meth
!= NULL
; cd
++) {
if (snccmp(cd
->CU_meth
, flds
[F_LINE
]) == SAME
) {
DEBUG(4, "Using %s to call\n", cd
->CU_meth
);
return((*(cd
->CU_gen
))(flds
));
logent(flds
[F_LINE
], "getto: Can't find, using DIR");
return(diropn(flds
)); /* search failed, so use direct */
* clsacu() close call unit
int (*CU_end
)() = nulldev
;
DEBUG(4, "fd %d NOT CLOSED by CU_clos\n", Dcf
);
logent("clsacu", "NOT CLOSED by CU_clos");
* exphone - expand phone number for given prefix and number
char pre
[MAXPH
], npart
[MAXPH
], tpre
[MAXPH
], p
[MAXPH
];
if ((fn
= fopen(DIALFILE
, "r")) == NULL
)
DEBUG(2, "CAN'T OPEN %s\n", DIALFILE
);
while (cfgets(buf
, BUFSIZ
, fn
)) {
sscanf(buf
, "%s%s", p
, tpre
);
if (strcmp(p
, pre
) == SAME
)
DEBUG(2, "CAN'T FIND dialcodes prefix '%s'\n", pre
);
* rddev - read and decode a line from device file
* return code - FAIL at end-of file; 0 otherwise
register struct Devices
*dev
;
if (!cfgets(buf
, BUFSIZ
, fp
))
na
= sscanf(buf
, "%s%s%s%s%s", dev
->D_type
, dev
->D_line
,
dev
->D_calldev
, dev
->D_class
, dev
->D_brand
);
ASSERT(na
>= 4, "BAD DEVICE ENTRY", buf
, 0);
if (na
!= 5) dev
->D_brand
[0] = '\0';
dev
->D_speed
= atoi(fdig(dev
->D_class
));
* finds(fsys, sysnam, info, flds) 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
);
sprintf(sysn
, "%.7s", flds
[F_NAME
]);
if (strcmp(sysnam
, sysn
) != SAME
)
if (ifdate(flds
[F_TIME
]))
DEBUG(2, "Wrong time ('%s') to call\n", flds
[F_TIME
]);
return(fcode
? fcode
: CF_SYSTEM
);
* login(nf, flds, dcr) do login conversation
register char *want
, *altern
;
ASSERT(nf
> 4, "TOO FEW LOG FIELDS", "", nf
);
for (k
= F_LOGIN
; k
< nf
; k
+= 2) {
altern
= index(want
, '-');
DEBUG(4, "wanted %s ", want
);
DEBUG(4, "got %s\n", ok
? "?" : "that");
logent("LOGIN", "FAILED");
/* close *not* needed here. rti!trt */
want
= index(altern
, '-');
/* rti!trt: conditional table generation to support odd speeds */
/* Suggested in n44a.139 by n44!dan (Dan Ts'o) */
struct sg_spds
{int sp_val
, sp_name
;} spds
[] = {
* fixline(tty, spwant) set speed/echo/mode...
register struct sg_spds
*ps
;
for (ps
= spds
; ps
->sp_val
; ps
++)
if (ps
->sp_val
== spwant
)
ASSERT(speed
>= 0, "BAD SPEED", "", speed
);
ioctl(tty
, TCGETA
, &ttbuf
);
/* 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;
ret
= ioctl(tty
, TCSETA
, &ttbuf
);
ioctl(tty
, TIOCGETP
, &ttbuf
);
ttbuf
.sg_flags
= (ANYP
|RAW
);
ttbuf
.sg_ispeed
= ttbuf
.sg_ospeed
= speed
;
ret
= ioctl(tty
, TIOCSETP
, &ttbuf
);
ASSERT(ret
>= 0, "RETURN FROM STTY", "", ret
);
ioctl(tty
, TIOCHPCL
, STBNULL
);
ioctl(tty
, TIOCEXCL
, STBNULL
);
/* Bill Shannon recommends MR 2000, but that takes too much space on PDPs */
/* Actually, the 'expect' algorithm should be rewritten. */
* expect(str, fn) look for expected string
* FAIL - lost line or too many characters read
* some character - timed out
register char *rp
= rdvec
;
if (strcmp(str
, "\"\"") == SAME
)
signal(SIGALRM
, alarmtr
);
/* change MAXCHARTIME to MAXMSGTIME, outside while loop -- brl-bmd!dpk */
while (notin(str
, rdvec
)) {
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')
/* Check rdvec before null termination -- cmcl2!salkind */
* 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));
* sendthem(str, fn) send line of login sequence
/* Note: debugging authorized only for privileged users */
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
) {
/* LF, CR, and "" courtesy unc!smb */
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
; *strptr
; strptr
++) {
if (*strptr
== '\\') switch(*++strptr
) {
DEBUG(5, "RETURN\n", "");
if (isdigit(*(strptr
+1))) {
if (*(strptr
+1) == '\0') {
DEBUG(5, "NO CR - MIDDLE IGNORED\n", "");
if (isdigit(strptr
[1])) {
while (isdigit(strptr
[1]) && ++n
<= 3)
i
= i
*8 + (*++strptr
- '0');
DEBUG(5, "BACKSLASH\n", "");
/* '\n' changed to '\r'--a better default. rti!trt */
ASSERT(write(fd
, t
, 1) == 1, "BAD WRITE", "", t
[0]);
* 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
);
ret
= ioctl(fn
, TCSBRK
, STBNULL
);
DEBUG(5, "break ioctl ret %d\n", ret
);
ret
= ioctl(fn
, TIOCSBRK
, STBNULL
);
DEBUG(5, "break 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", "", ret
);
ret
= ioctl(fn
, TIOCCBRK
, STBNULL
);
DEBUG(5, "break ioctl ret %d\n", ret
);
DEBUG(4, "ioctl 1 second break\n", STBNULL
);
ret
= ioctl(fn
, TIOCGETP
, &ttbuf
);
sospeed
= ttbuf
.sg_ospeed
;
ttbuf
.sg_ospeed
= BSPEED
;
ret
= ioctl(fn
, TIOCSETP
, &ttbuf
);
ret
= write(fn
, "\0\0\0\0\0\0\0\0\0\0\0\0", bnulls
);
ASSERT(ret
> 0, "BAD WRITE genbrk", "", ret
);
ttbuf
.sg_ospeed
= sospeed
;
ret
= ioctl(fn
, TIOCSETP
, &ttbuf
);
ASSERT(ret
> 0, "BAD WRITE genbrk", "", ret
);
DEBUG(4, "sent BREAK nulls - %d\n", bnulls
);
* notin(sh, lg) check for occurrence of substring "sh"
/* Dave Martingale: permit wild cards in 'expect' */
* Allow multiple date specifications separated by '|'.
* Calls ifadate, formerly "ifdate".
for (p
= s
; p
&& (*p
== '|' ? *++p
: *p
); p
= index(p
, '|'))
* ifadate - this routine will check a string (s)
* like "MoTu0800-1730" to see if the present
* time is within the given limits.
* SIDE EFFECT - Retrytime is set
* zero or one time means all day
"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", 0
int i
, tl
, th
, tn
, flag
, dayok
=0;
/* pick up retry time for failures */
/* global variable Retrytime is set here */
if ((p
= index(s
, ',')) == NULL
) {
i
= sscanf(p
+1, "%d", &rtime
);
for (i
= 0; days
[i
]; i
++) {
if (tp
->tm_wday
>= 1 && tp
->tm_wday
<= 5)
i
= sscanf(s
, "%d-%d", &tl
, &th
);
tn
= tp
->tm_hour
* 100 + tp
->tm_min
;
flag
= 0; /* set up for crossover 2400 test */
if ((tn
>= tl
&& tn
<= th
)
|| (tn
>= th
&& tn
<= tl
)) /* test for crossover 2400 */
* lastc(s) return pointer to last character
* fdig(cp) 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.
if (islower(*s1
)) c1
= toupper(*s1
);
if (islower(*s2
)) c2
= toupper(*s2
);
if (islower(*s1
)) c1
= toupper(*s1
);
if (islower(*s2
)) c2
= toupper(*s2
);