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 */
char *PCP
= "PCP"; /* PC Pursuit device type */
* catch alarm routine for "expect".
signal(SIGALRM
, alarmtr
);
logent("FAIL", "ACU LINE CLOSE");
/* This template is for seismo to call ihnp4
* the 3 lines marked ---> will be overwritten for the appropriate city
static char *PCFlds
[] = {
"P_ZERO", /* Telenet insists on zero parity */
"BUSY", /* Abort on Busy Signal */
"\\d\\d\\r\\d\\r", /* Get telenet's attention */
"TERMINAL=~3-\r-TERM~3-\r-TERM~5", /* Terminal type ? */
"@", /* telenet's prompt */
"D/DCWAS/21,telenetloginstring", /* overwritten later */
CNULL
, /* telenet password */
"CONNECTED", /* We're now talking to a Hayes in the remote city */
"ATDT6907171", /* overwritten */
"\\d\\r", /* We're in !*/
static char PCP_brand
[25];
* 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) {
strncpy(LineType
, Flds
[F_LINE
], 10);
if (strcmp("TCP", LineType
)
&& strcmp("DIR", LineType
)
&& strcmp("LOCAL", LineType
) ) {
sprintf(wkpre
, "%c.%.*s", CMDPRE
, SYSNSIZE
, Rmtname
);
if (!onesys
&& MaxGrade
!= DefMaxGrade
&&
!iswrk(file
, "chk", Spool
, wkpre
)) {
/* For GTE's PC Pursuit */
if (snccmp(LineType
, PCP
) == SAME
) {
static struct Devices dev
;
dfp
= fopen(DEVFILE
, "r");
ASSERT(dfp
!= NULL
, "Can't open", DEVFILE
, 0);
while ((status
=rddev(dfp
, &dev
)) != FAIL
&& strcmp(PCP
, dev
.D_type
) != SAME
)
if (mlock(PCP
) == FAIL
) {
PCFlds
[PCP_BAUD
] = dev
.D_class
;
PCFlds
[PCP_PHONE
] = dev
.D_calldev
;
sprintf(PCFlds
[PCP_CITY
], "c d/%s%s,%s",
index(Flds
[F_CLASS
], '/') == NULL
? "/12" : "",
PCFlds
[PCP_PASSWORD
] = dev
.D_line
;
strncpy(&PCFlds
[PCP_RPHONE
][4], Flds
[F_PHONE
], 7);
strncpy(PCP_brand
, dev
.D_brand
, sizeof(PCP_brand
));
if ((fcode
= getto(PCFlds
)) < 0) {
fcode
= login(NPCFIELDS
, PCFlds
, Dcf
);
} else if ((fcode
= getto(Flds
)) > 0) {
return fcode
? fcode
: nf
;
DEBUG(4, "login %s\n", "called");
fcode
= login(nf
, Flds
, Dcf
); }
* 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
)
if (snccmp(line
, PCP
) == SAME
) {
for(cd
= condevs
; cd
->CU_meth
!= NULL
; cd
++) {
if (snccmp(PCP_brand
, cd
->CU_brand
) == SAME
) {
logent(PCP_brand
, "UNSUPPORTED ACU TYPE");
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
, '-');
sprintf(sbuf
, "LOGIN ABORTED on \"%s\"", AbortOn
);
/* 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)
* 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, (isprint(c
) || isspace(c
)) ? "%c" : "\\%03o", c
);
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
) {
while ((c
= *strptr
++) != '\0') {
DEBUG(5, "TRAILING BACKSLASH IGNORED\n", CNULL
);
DEBUG(5, "BLANK\n", CNULL
);
DEBUG(5, "DELAY\n", CNULL
);
DEBUG(5, "NEW LINE\n", CNULL
);
DEBUG(5, "RETURN\n", CNULL
);
DEBUG(5, "NO CR\n", CNULL
);
DEBUG(5, "NO CR - IGNORED NOT EOL\n", CNULL
);
#define isoctal(x) ((x >= '0') && (x <= '7'))
if (isoctal(strptr
[-1])) {
while (isoctal(*strptr
) && ++n
<= 3)
i
= i
* 8 + (*strptr
++ - '0');
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
);
* 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 (prefix("NonPeak", s
)) { /* For Tymnet and PC Pursuit */
if (tp
->tm_wday
== 6 || tp
->tm_wday
== 0
|| tp
->tm_hour
>= 18 || tp
->tm_hour
< 7)
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 */
* 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))
* fix kill/echo/raw on line
register struct sg_spds
*ps
;
ioctl(tty
, TCGETA
, &ttbuf
);
ttbuf
.c_iflag
= ttbuf
.c_oflag
= ttbuf
.c_lflag
= (ushort
)0;
speed
= ttbuf
.c_cflag
&= (CBAUD
);
ttbuf
.c_cflag
|= (CS8
|CREAD
);
ioctl(tty
, TCSETA
, &ttbuf
);
ioctl(tty
, TIOCGETP
, &ttbuf
);
ttbuf
.sg_flags
= (ANYP
| RAW
);
ioctl(tty
, TIOCSETP
, &ttbuf
);
ioctl(tty
, TIOCEXCL
, STBNULL
);
for (ps
= spds
; ps
->sp_val
; ps
++)
if (ps
->sp_name
== speed
) {
linebaudrate
= ps
->sp_val
;
DEBUG(9,"Incoming baudrate is %d\n", linebaudrate
);
ASSERT(linebaudrate
>= 0, "BAD SPEED", CNULL
, speed
);