1
0
Files
irix-657m-src/eoe/cmd/slip/callers.c
2022-09-29 17:59:04 +03:00

1147 lines
25 KiB
C

/* Copyright (c) 1984 AT&T */
/* All Rights Reserved */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
/* The copyright notice above does not evidence any */
/* actual or intended publication of such source code. */
#ident "$Revision: 1.16 $"
#include "uucp.h"
struct utsname utsname;
#ifdef sgi
extern int rresvport(int *);
int gdial(char*, char *arps[], int);
static void exphone(char *, char *);
static void translate(char *, char *);
static char *repphone(char *, char *, char *);
static int open801(char *, char *, char *, int);
void (*genbrk)(int);
#define BSD4_2 /* only in this file for TCP */
#endif
#ifdef BSD4_2
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#endif
#ifdef UNET
#include "UNET/unetio.h"
#include "UNET/tcp.h"
#endif
#ifdef sgi
void alarmtr();
#else
int alarmtr();
#endif
extern jmp_buf Sjbuf;
extern int Modemctrl;
/*
* to add a new caller:
* declare the function that knows how to call on the device,
* add a line to the callers table giving the name of the device
* (from Devices file) and the name of the function
* add the function to the end of this file
*/
#ifdef DIAL801
int dial801();
#endif
#ifdef DATAKIT
int dkcall();
#endif /* DATAKIT */
#ifdef V8
int Dialout();
#endif
#ifdef TCP
int unetcall();
int tcpcall();
#endif /* TCP */
#ifdef SYTEK
int sytcall();
#endif /* SYTEK */
#ifdef TLI
int tlicall();
#endif /* TLI */
struct caller Caller[] = {
#ifdef DIAL801
{"801", dial801},
{"212", dial801},
#endif /* DIAL801 */
#ifdef V8
{"Dialout", Dialout}, /* ditto but using dialout(III) */
#endif
#ifdef TCP
#ifdef BSD4_2
{"TCP", tcpcall}, /* 4.2BSD sockets */
#else /* !BSD4_2 */
#ifdef UNET
{"TCP", unetcall}, /* 3com implementation of tcp */
{"Unetserver", unetcall},
#endif /* UNET */
#endif /* BSD4_2 */
#endif /* TCP */
#ifdef DATAKIT
{"DK", dkcall}, /* standard AT&T DATAKIT VCS caller */
#endif /* DATAKIT */
#ifdef SYTEK
{"Sytek", sytcall}, /* untested but should work */
#endif /* SYTEK */
#ifdef TLI
{"TLI", tlicall}, /* AT&T Transport Layer Interface */
#ifdef TLIS
{"TLIS", tlicall}, /* AT&T Transport Layer Interface */
#endif /* TLIS */
#endif /* TLI */
{NULL, NULL} /* this line must be last */
};
/***
* exphone - expand phone number for given prefix and number
*
* return code - none
*/
static void
exphone(char *in, char *out)
{
FILE *fn;
char pre[MAXPH], npart[MAXPH], tpre[MAXPH], p[MAXPH];
char buf[BUFSIZ];
char *s1;
if (!isalpha(*in)) {
(void) strcpy(out, in);
return;
}
s1=pre;
while (isalpha(*in))
*s1++ = *in++;
*s1 = NULLCHAR;
s1 = npart;
while (*in != NULLCHAR)
*s1++ = *in++;
*s1 = NULLCHAR;
tpre[0] = NULLCHAR;
fn = fopen(DIALCODES, "r");
if (fn != NULL) {
while (fgets(buf, BUFSIZ, fn)) {
if ( sscanf(buf, "%s%s", p, tpre) < 1)
continue;
if (EQUALS(p, pre))
break;
tpre[0] = NULLCHAR;
}
fclose(fn);
}
(void) strcpy(out, tpre);
(void) strcat(out, npart);
return;
}
/*
* repphone - Replace \D and \T sequences in arg with phone
* expanding and translating as appropriate.
*/
static char *
repphone(char *arg, char *phone, char *trstr)
{
static char pbuf[2*(MAXPH+2)];
register char *fp, *tp;
for (tp=pbuf; *arg; arg++) {
if (*arg != '\\') {
*tp++ = *arg;
continue;
} else {
switch (*(arg+1)) {
case 'T':
exphone(phone, tp);
translate(trstr, tp);
for(; *tp; tp++)
;
arg++;
break;
case 'D':
if (phone) {
for (fp=phone; *tp = *fp++; tp++)
;
}
arg++;
break;
default:
*tp++ = *arg;
break;
}
}
}
*tp = '\0';
return(pbuf);
}
/*
* processdev - Process a line from the Devices file
*
* return codes:
* file descriptor - succeeded
* FAIL - failed
*/
int
processdev(char *flds[], char *dev[])
{
int dcf = -1;
register struct caller *ca;
char *args[D_MAX+1], dcname[20];
register char **sdev;
register nullfd;
char *phonecl; /* clear phone string */
char phoneex[2*(MAXPH+2)]; /* expanded phone string */
sdev = dev;
/* set up default "break" routine */
genbrk = ttygenbrk;
for (ca = Caller; ca->CA_type != NULL; ca++) {
/* This will find built-in caller functions */
if (EQUALS(ca->CA_type, dev[D_CALLER])) {
DEBUG(5, "Internal caller type %s\n", dev[D_CALLER]);
if (dev[D_ARG] == NULL) {
/* if NULL - assume translate */
dev[D_ARG+1] = NULL; /* needed for for loop later to mark the end */
dev[D_ARG] = "\\T";
}
dev[D_ARG] = repphone(dev[D_ARG], flds[F_PHONE], "");
if ((dcf = (*(ca->CA_caller))(flds, dev)) < 0)
return(dcf) ;
if ( interface( ca->CA_type ) ) {
DEBUG(5, "interface(%s) failed", ca->CA_type);
Uerror = SS_DEVICE_FAILED;
/* restore vanilla unix interface */
(void)interface("UNIX");
return(FAIL);
}
dev += 2; /* Skip to next CALLER and ARG */
break;
}
}
if (dcf == -1) {
/* Here if not a built-in caller function */
/* If "DIAL" is defined, the mlock will probably fail */
/* (/usr/spool/locks is usually 755 owned by uucp), but */
/* since are using advisory file locks anyway let it */
/* slide. */
if (mlock(dev[D_LINE]) == FAIL) { /* Lock the line */
#ifdef DIAL
;
}
#else /* !DIAL */
DEBUG(5, "mlock %s failed\n", dev[D_LINE]);
Uerror = SS_LOCKED_DEVICE;
return(FAIL);
}
DEBUG(5, "mlock %s succeeded\n", dev[D_LINE]);
#endif /* DIAL */
/*
* Open the line
*/
if ( *dev[D_LINE] != '/' ) {
(void) sprintf(dcname, "/dev/%s", dev[D_LINE]);
} else {
(void) strcpy(dcname, dev[D_LINE] );
}
/* take care of the possible partial open fd */
(void) close(nullfd = open("/", 0));
if (setjmp(Sjbuf)) {
(void) close(nullfd);
DEBUG0(1, "generic open timeout\n");
logent("generic open", "TIMEOUT");
Uerror = SS_CANT_ACCESS_DEVICE;
goto bad;
}
(void) signal(SIGALRM, alarmtr);
(void) alarm(10);
if ( Modemctrl ) {
DEBUG0(7, "opening with O_NDELAY set\n");
dcf = open(dcname, (O_RDWR | O_NDELAY) );
} else
dcf = open(dcname, O_RDWR );
(void) alarm(0);
if (dcf < 0) {
DEBUG(1, "generic open failed, errno = %d\n", errno);
logent("generic open", "FAILED");
Uerror = SS_CANT_ACCESS_DEVICE;
(void) close(nullfd);
goto bad;
}
if ( Modemctrl ) {
DEBUG0(7, "clear O_NDELAY\n");
if ( fcntl(dcf, F_SETFL,
(fcntl(dcf, F_GETFL, 0) & ~O_NDELAY)) < 0 ) {
DEBUG( 7, "clear O_NDELAY failed, errno %d\n", errno);
(void)close(dcf);
Uerror = SS_DEVICE_FAILED;
goto bad;
}
}
#ifdef ATTSV
if ( filelock(dcf) != SUCCESS ) {
(void)close(dcf);
DEBUG(1, "failed to lock device %s\n", dcname);
Uerror = SS_LOCKED_DEVICE;
goto bad;
}
#endif /* ATTSV */
fixline(dcf, atoi(fdig(dev[D_CLASS])), D_DIRECT);
}
/* init device config info */
DEBUG(5, "processdev: calling setdevcfg(%s, ", Progname);
DEBUG(5, "%s)\n", flds[F_TYPE]);
setdevcfg(Progname, flds[F_TYPE]);
if ( (*Setup)( MASTER, &dcf, &dcf ) ) {
/* any device|system lock files we should remove? */
DEBUG0(5, "MASTER Setup failed");
Uerror = SS_DEVICE_FAILED;
goto bad;
}
/*
* Now loop through the remaining callers and chat
* according to scripts in dialers file.
*/
for (; dev[D_CALLER] != NULL; dev += 2) {
register int w;
/*
* Scan Dialers file to find an entry
*/
if ((w = gdial(dev[D_CALLER], args, D_MAX)) < 1) {
DEBUG(1, "%s not found in Dialers file\n", dev[D_CALLER]);
logent("generic call to gdial", "FAILED");
Uerror = SS_CANT_ACCESS_DEVICE;
goto bad;
}
if (w <= 2) /* do nothing - no chat */
break;
/*
* Translate the phone number
*/
if (dev[D_ARG] == NULL) {
/* if NULL - assume no translation */
dev[D_ARG+1] = NULL; /* needed for for loop to mark the end */
dev[D_ARG] = "\\D";
}
phonecl = repphone(dev[D_ARG], flds[F_PHONE], args[1]);
exphone(phonecl, phoneex);
translate(args[1], phoneex);
/*
* Chat
*/
if (chat(w-2, &args[2], dcf, phonecl, phoneex) != SUCCESS) {
Uerror = SS_CHAT_FAILED;
goto bad;
}
}
/*
* Success at last!
*/
strcpy(Dc, sdev[D_LINE]);
return(dcf);
bad:
if ( dcf >= 0 )
(void)close(dcf);
delock(sdev[D_LINE]);
/* restore vanilla unix interface */
(void)interface("UNIX");
return(FAIL);
}
/*
* translate the pairs of characters present in the first
* string whenever the first of the pair appears in the second
* string.
*/
static void
translate(char *ttab, char *str)
{
register char *s;
for(;*ttab && *(ttab+1); ttab += 2)
for(s=str;*s;s++)
if(*ttab == *s)
*s = *(ttab+1);
}
#define MAXLINE 512
/*
* Get the information about the dialer.
* gdial(type, arps, narps)
* type -> type of dialer (e.g., penril)
* arps -> array of pointers returned by gdial
* narps -> number of elements in array returned by gdial
* Return value:
* -1 -> Can't open DIALERFILE
* 0 -> requested type not found
* >0 -> success - number of fields filled in
*/
int
gdial(char *type, char *arps[], int narps)
{
static char info[MAXLINE];
register na;
DEBUG(2, "gdial(%s) called\n", type);
while (getdialline(info, sizeof(info))) {
if ((info[0] == '#') || (info[0] == ' ') ||
(info[0] == '\t') || (info[0] == '\n'))
continue;
if ((na = getargs(info, arps, narps)) == 0)
continue;
if (EQUALS(arps[0], type)) {
dialreset();
bsfix(arps);
return(na);
}
}
dialreset();
return(0);
}
#ifdef DATAKIT
/***
* dkcall(flds, dev) make a DATAKIT VCS connection
* DATAKIT VCS is a trademark of AT&T
*
* return codes:
* >0 - file number - ok
* FAIL - failed
*/
#include "dk.h"
dkcall(char *flds[], char *dev[])
{
register fd;
#ifdef V8
extern int cdkp_ld;
#endif
char dialstring[64];
extern dkbreak();
strcpy(dialstring, dev[D_ARG]);
#ifndef STANDALONE
if(*flds[F_CLASS] < '0' || *flds[F_CLASS] > '9')
sprintf(dialstring, "%s.%s", dev[D_ARG], flds[F_CLASS]);
#endif
DEBUG(4, "dkcall(%s)\n", dialstring);
#ifdef V8
if (setjmp(Sjbuf)) {
Uerror = SS_DIAL_FAILED;
return(FAIL);
}
(void) signal(SIGALRM, alarmtr);
(void) alarm(15);
DEBUG(4, "tdkdial(%s", flds[F_PHONE]);
DEBUG(4, ", %d)\n", atoi(dev[D_CLASS]));
if ((fd = tdkdial(flds[F_PHONE], atoi(dev[D_CLASS]))) >= 0)
if (dkproto(fd, cdkp_ld) < 0)
{
close(fd);
fd = -1;
}
(void) alarm(0);
#else
fd = dkdial(dialstring);
#endif
(void) strcpy(Dc, "DK");
if (fd < 0) {
Uerror = SS_DIAL_FAILED;
return(FAIL);
}
else {
genbrk = dkbreak;
return(fd);
}
}
#endif /* DATAKIT */
#ifdef TCP
/***
* tcpcall(flds, dev) make ethernet/socket connection
*
* return codes:
* >0 - file number - ok
* FAIL - failed
*/
#ifndef BSD4_2
/*ARGSUSED*/
tcpcall(flds, dev)
char *flds[], *dev[];
{
Uerror = SS_NO_DEVICE;
return(FAIL);
}
#else /* BSD4_2 */
tcpcall(flds, dev)
char *flds[], *dev[];
{
int ret;
short port;
extern int errno, sys_nerr;
extern char *sys_errlist[];
struct servent *sp;
struct hostent *hp;
struct sockaddr_in sin;
#ifdef sgi
int rport = IPPORT_RESERVED - 1;
port = 0;
if (dev[D_ARG] != 0) {
port = atoi(dev[D_ARG]);
if (port == 0) {
sp = getservbyname(dev[D_ARG], "tcp");
if (sp != 0)
port = sp->s_port;
}
}
if (!port) {
sp = getservbyname("uucp", "tcp");
if (sp != 0)
port = sp->s_port;
}
ASSERT(port != 0, "No uucp TCP port number", 0, 0);
hp = gethostbyname(flds[F_PHONE]);
#else /* sgi */
port = atoi(dev[D_ARG]);
if (port == 0) {
sp = getservbyname("uucp", "tcp");
ASSERT(sp != NULL, "No uucp server", 0, 0);
port = sp->s_port;
}
else port = htons(port);
hp = gethostbyname(flds[F_NAME]);
#endif /* sgi */
if (hp == NULL) {
logent("tcpopen", "no such host");
Uerror = SS_NO_DEVICE;
return(FAIL);
}
#ifdef sgi
DEBUG(4, "tcpdial host %s, ", flds[F_PHONE]);
DEBUG(4, "port %d\n", port);
#else
DEBUG(4, "tcpdial host %s, ", flds[F_NAME]);
DEBUG(4, "port %d\n", ntohs(port));
#endif
#ifdef sgi
/* get a reserved port for PPP */
if (geteuid() != 0
|| (ret = rresvport(&rport)) < 0)
ret = socket(AF_INET, SOCK_STREAM, 0);
#else
ret = socket(AF_INET, SOCK_STREAM, 0);
#endif
if (ret < 0) {
if (errno < sys_nerr) {
DEBUG(5, "no socket: %s\n", sys_errlist[errno]);
logent("no socket", sys_errlist[errno]);
}
else {
DEBUG(5, "no socket, errno %d\n", errno);
logent("tcpopen", "NO SOCKET");
}
Uerror = SS_NO_DEVICE;
return(FAIL);
}
sin.sin_family = hp->h_addrtype;
bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length);
sin.sin_port = port;
if (setjmp(Sjbuf)) {
DEBUG0(4, "timeout tcpopen\n");
logent("tcpopen", "TIMEOUT");
Uerror = SS_NO_DEVICE;
return(FAIL);
}
(void) signal(SIGALRM, alarmtr);
#ifdef sgi
(void) alarm(180);
#else
(void) alarm(30);
#endif
DEBUG(7, "family: %d\n", sin.sin_family);
DEBUG(7, "port: %d\n", sin.sin_port);
DEBUG(7, "addr: %08x\n",*((int *) &sin.sin_addr));
if (connect(ret, (caddr_t)&sin, sizeof (sin)) < 0) {
(void) alarm(0);
(void) close(ret);
if (errno < sys_nerr) {
DEBUG(5, "connect failed: %s\n", sys_errlist[errno]);
logent("connect failed", sys_errlist[errno]);
}
else {
DEBUG(5, "connect failed, errno %d\n", errno);
logent("tcpopen", "CONNECT FAILED");
}
Uerror = SS_NO_DEVICE;
return(FAIL);
}
(void) signal(SIGPIPE, SIG_IGN); /* watch out for broken ipc link...*/
(void) alarm(0);
(void) strcpy(Dc, "IPC");
return(ret);
}
#endif /* BSD4_2 */
/***
* unetcall(flds, dev) make ethernet connection
*
* return codes:
* >0 - file number - ok
* FAIL - failed
*/
/* ARGSUSED */
#ifndef UNET
unetcall(flds, dev)
char *flds[], *dev[];
{
Uerror = SS_NO_DEVICE;
return(FAIL);
}
#else /* UNET */
unetcall(flds, dev)
char *flds[], *dev[];
{
int ret;
int port;
extern int errno;
port = atoi(dev[D_ARG]);
DEBUG(4, "unetdial host %s, ", flds[F_NAME]);
DEBUG(4, "port %d\n", port);
(void) alarm(30);
ret = tcpopen(flds[F_NAME], port, 0, TO_ACTIVE, "rw");
(void) alarm(0);
endhnent();
if (ret < 0) {
DEBUG(5, "tcpopen failed: errno %d\n", errno);
Uerror = SS_DIAL_FAILED;
return(FAIL);
}
(void) strcpy(Dc, "UNET");
return(ret);
}
#endif /* UNET */
#endif /* TCP */
#ifdef SYTEK
/****
* sytcall(flds, dev) make a sytek connection
*
* return codes:
* >0 - file number - ok
* FAIL - failed
*/
/*ARGSUSED*/
sytcall(flds, dev)
char *flds[], *dev[];
{
extern int errno;
int dcr, dcr2, nullfd, ret;
char dcname[20], command[BUFSIZ];
(void) sprintf(dcname, "/dev/%s", dev[D_LINE]);
DEBUG(4, "dc - %s, ", dcname);
if (mlock(dev[D_LINE]) == FAIL) { /* Lock the line */
DEBUG(5, "mlock %s failed\n", dev[D_LINE]);
Uerror = SS_LOCKED_DEVICE;
return(FAIL);
}
dcr = open(dcname, O_WRONLY|O_NDELAY);
if (dcr < 0) {
Uerror = SS_DIAL_FAILED;
DEBUG(4, "OPEN FAILED %s\n", dcname);
delock(dev[D_LINE]);
return(FAIL);
}
if ( filelock(dcr) != SUCCESS ) {
(void)close(dcr);
DEBUG(1, "failed to lock device %s\n", dcname);
Uerror = SS_LOCKED_DEVICE;
}
sytfixline(dcr, atoi(fdig(dev[D_CLASS])), D_DIRECT);
(void) sleep(2);
DEBUG(4, "Calling Sytek unit %s\n", dev[D_ARG]);
(void) sprintf(command,"\r\rcall %s\r", dev[D_ARG]);
ret = (*Write)(dcr, command, strlen(command));
(void) sleep(1);
DEBUG(4, "COM1 return = %d\n", ret);
sytfix2line(dcr);
(void) close(nullfd = open("/", 0));
(void) signal(SIGALRM, alarmtr);
if (setjmp(Sjbuf)) {
DEBUG0(4, "timeout sytek open\n");
(void) close(nullfd);
(void) close(dcr2);
(void) close(dcr);
Uerror = SS_DIAL_FAILED;
delock(dev[D_LINE]);
return(FAIL);
}
(void) alarm(10);
dcr2 = open(dcname,O_RDWR);
(void) alarm(0);
(void) close(dcr);
if (dcr2 < 0) {
DEBUG(4, "OPEN 2 FAILED %s\n", dcname);
Uerror = SS_DIAL_FAILED;
(void) close(nullfd); /* kernel might think dc2 is open */
delock(dev[D_LINE]);
return(FAIL);
}
return(dcr2);
}
#endif /* SYTEK */
#ifdef DIAL801
/***
* dial801(flds, dev) dial remote machine on 801/801
* char *flds[], *dev[];
*
* return codes:
* file descriptor - succeeded
* FAIL - failed
*
* unfortunately, open801() is different for usg and non-usg
*/
/*ARGSUSED*/
dial801(flds, dev)
char *flds[], *dev[];
{
char dcname[20], dnname[20], phone[MAXPH+2];
int dcf = -1, speed;
if (mlock(dev[D_LINE]) == FAIL) {
DEBUG(5, "mlock %s failed\n", dev[D_LINE]);
Uerror = SS_LOCKED_DEVICE;
return(FAIL);
}
(void) sprintf(dnname, "/dev/%s", dev[D_CALLDEV]);
(void) sprintf(phone, "%s%s", dev[D_ARG] , ACULAST);
(void) sprintf(dcname, "/dev/%s", dev[D_LINE]);
CDEBUG(1, "Use Port %s, ", dcname);
DEBUG(4, "acu - %s, ", dnname);
CDEBUG(1, "Phone Number %s\n", phone);
VERBOSE("Trying modem - %s, ", dcname); /* for cu */
VERBOSE("acu - %s, ", dnname); /* for cu */
VERBOSE("calling %s: ", phone); /* for cu */
speed = atoi(fdig(dev[D_CLASS]));
dcf = open801(dcname, dnname, phone, speed);
if (dcf >= 0) {
fixline(dcf, speed, D_ACU);
(void) strcpy(Dc, dev[D_LINE]); /* for later unlock() */
VERBOSE("SUCCEEDED\n", 0);
} else {
delock(dev[D_LINE]);
VERBOSE("FAILED\n", 0);
}
return(dcf);
}
#ifndef ATTSV
/*ARGSUSED*/
open801(dcname, dnname, phone, speed)
char *dcname, *dnname, *phone;
{
int nw, lt, pid = -1, dcf = -1, nullfd, dnf = -1;
unsigned timelim;
if ((dnf = open(dnname, 1)) < 0) {
DEBUG(5, "can't open %s\n", dnname);
Uerror = SS_CANT_ACCESS_DEVICE;
return(FAIL);
}
DEBUG(5, "%s is open\n", dnname);
(void) close(nullfd = open("/dev/null", 0)); /* partial open hack */
if (setjmp(Sjbuf)) {
DEBUG0(4, "timeout modem open\n");
logent("801 open", "TIMEOUT");
(void) close(nullfd);
(void) close(dcf);
(void) close(dnf);
if (pid > 0) {
kill(pid, 9);
wait((int *) 0);
}
Uerror = SS_DIAL_FAILED;
return(FAIL);
}
(void) signal(SIGALRM, alarmtr);
timelim = 5 * strlen(phone);
(void) alarm(timelim < 30 ? 30 : timelim);
if ((pid = fork()) == 0) {
sleep(2);
nw = (*Write)(dnf, phone, lt = strlen(phone));
if (nw != lt) {
DEBUG(4, "ACU write error %d\n", errno);
logent("ACU write", "FAILED");
exit(1);
}
DEBUG0(4, "ACU write ok%s\n");
exit(0);
}
/* open line - will return on carrier */
dcf = open(dcname, 2);
DEBUG(4, "dcf is %d\n", dcf);
if (dcf < 0) { /* handle like a timeout */
(void) alarm(0);
longjmp(Sjbuf, 1);
}
/* modem is open */
while ((nw = wait(&lt)) != pid && nw != -1)
;
(void) alarm(0);
(void) close(dnf); /* no reason to keep the 801 open */
if (lt != 0) {
DEBUG(4, "Fork Stat %o\n", lt);
(void) close(dcf);
Uerror = SS_DIAL_FAILED;
return(FAIL);
}
return(dcf);
}
#else /* ATTSV */
open801(char *dcname, char *dnname, char *phone, int speed)
{
int nw, lt, dcf = -1, nullfd, dnf = -1, ret;
unsigned timelim;
(void) close(nullfd = open("/", 0)); /* partial open hack */
if (setjmp(Sjbuf)) {
DEBUG(4, "DN write %s\n", "timeout");
(void) close(dnf);
(void) close(dcf);
(void) close(nullfd);
Uerror = SS_DIAL_FAILED;
return(FAIL);
}
(void) signal(SIGALRM, alarmtr);
timelim = 5 * strlen(phone);
(void) alarm(timelim < 30 ? 30 : timelim);
if ((dnf = open(dnname, O_WRONLY)) < 0 ) {
DEBUG(5, "can't open %s\n", dnname);
Uerror = SS_CANT_ACCESS_DEVICE;
return(FAIL);
}
DEBUG(5, "%s is open\n", dnname);
if ( filelock(dnf) != SUCCESS ) {
(void)close(dnf);
DEBUG(1, "failed to lock device %s\n", dnname);
Uerror = SS_LOCKED_DEVICE;
}
if ( (dcf = open(dcname, O_RDWR | O_NDELAY)) < 0 ) {
DEBUG(5, "can't open %s\n", dcname);
Uerror = SS_CANT_ACCESS_DEVICE;
return(FAIL);
}
if ( filelock(dcf) != SUCCESS ) {
(void)close(dcf);
DEBUG(1, "failed to lock device %s\n", dcname);
Uerror = SS_LOCKED_DEVICE;
}
DEBUG(4, "dcf is %d\n", dcf);
fixline(dcf, speed, D_ACU);
nw = (*Write)(dnf, phone, lt = strlen(phone));
if (nw != lt) {
(void) alarm(0);
DEBUG(4, "ACU write error %d\n", errno);
(void) close(dnf);
(void) close(dcf);
Uerror = SS_DIAL_FAILED;
return(FAIL);
} else
DEBUG0(4, "ACU write ok\n");
(void) close(dnf);
(void) close(nullfd = open("/", 0)); /* partial open hack */
ret = open(dcname, 2); /* wait for carrier */
(void) alarm(0);
(void) close(ret); /* close 2nd modem open() */
if (ret < 0) { /* open() interrupted by alarm */
DEBUG(4, "Line open %s\n", "failed");
Uerror = SS_DIAL_FAILED;
(void) close(nullfd); /* close partially opened modem */
return(FAIL);
}
(void) fcntl(dcf,F_SETFL, fcntl(dcf, F_GETFL, 0) & ~O_NDELAY);
return(dcf);
}
#endif /* ATTSV */
#endif /* DIAL801 */
#ifdef V8
Dialout(flds)
char *flds[];
{
int fd;
char phone[MAXPH+2];
exphone(flds[F_PHONE], phone);
DEBUG(4, "call dialout(%s", phone);
DEBUG(4, ", %s)\n", dev[D_CLASS]);
fd = dialout(phone, dev[D_CLASS]);
if (fd == -1)
Uerror = SS_NO_DEVICE;
if (fd == -3)
Uerror = SS_DIAL_FAILED;
if (fd == -9)
Uerror = SS_DEVICE_FAILED;
(void) strcpy(Dc, "Dialout");
return(fd);
}
#endif /* V8 */
#ifdef TLI
/*
*
* AT&T Transport Layer Interface
*
* expected in Devices
* TLI line1 - - TLI
* or
* TLIS line1 - - TLIS
*
*/
#include <sys/tiuser.h>
#define CONNECT_ATTEMPTS 3
#define TFREE(p) if ( (p) ) t_free( (p) )
/*
* returns fd to remote uucp daemon
*/
int
tlicall(flds, dev)
char *flds[];
char *dev[];
{
char addrbuf[ BUFSIZ ];
char devname[MAXNAMESIZE];
int fd, service;
register int i, j;
struct t_bind *bind_ret = 0;
struct t_info tinfo;
struct t_call *sndcall = 0, *rcvcall = 0;
extern int errno, t_errno;
extern char *sys_errlist[], *t_errlist[];
extern struct netbuf *stoa();
if ( dev[D_LINE][0] != '/' ) {
/* dev holds device name relative to /dev */
sprintf(devname, "/dev/%s", dev[D_LINE]);
} else {
/* dev holds full path name of device */
strcpy(devname, dev[D_LINE]);
}
/* gimme local transport endpoint */
errno = t_errno = 0;
if (setjmp(Sjbuf)) {
DEBUG0(1, "t_open timeout\n");
logent("t_open", "TIMEOUT");
Uerror = SS_NO_DEVICE;
return(FAIL);
}
(void) signal(SIGALRM, alarmtr);
(void) alarm(5);
fd = t_open(devname, O_RDWR, &tinfo);
(void) alarm(0);
if (fd < 0) {
tfaillog(fd, "t_open" );
Uerror = SS_NO_DEVICE;
return(FAIL);
}
if ( filelock(fd) != SUCCESS ) {
(void)t_close(fd);
DEBUG(1, "tlicall: failed to lock device %s\n", devname);
Uerror = SS_LOCKED_DEVICE;
return(FAIL);
}
/* allocate tli structures */
errno = t_errno = 0;
if ( (bind_ret = (struct t_bind *)t_alloc(fd, T_BIND, T_ALL)) ==
(struct t_bind *)NULL
|| (sndcall = (struct t_call *)t_alloc(fd, T_CALL, T_ALL)) ==
(struct t_call *)NULL
|| (rcvcall = (struct t_call *)t_alloc(fd, T_CALL, T_ALL)) ==
(struct t_call *)NULL ) {
tfaillog(fd, "t_alloc" );
TFREE(bind_ret);TFREE(sndcall);TFREE(rcvcall);
Uerror = SS_NO_DEVICE;
return(FAIL);
}
/* bind */
errno = t_errno = 0;
if (t_bind(fd, (struct t_bind *) 0, bind_ret ) < 0) {
tfaillog(fd, "t_bind" );
TFREE(bind_ret);TFREE(sndcall);TFREE(rcvcall);
Uerror = SS_NO_DEVICE;
(void) t_close(fd);
return(FAIL);
}
DEBUG(5, "tlicall: bound to %s\n", bind_ret->addr.buf);
/*
* Prepare to connect.
*
* If address begins with "\x", "\X", "\o", or "\O",
* assume is hexadecimal or octal address and use stoa()
* to convert it.
*
* Else is usual uucico address -- only \N's left to process.
* Walk thru connection address, changing \N's to NULLCHARs.
* Note: If a NULLCHAR must be part of the connection address,
* it must be overtly included in the address. One recommended
* way is to do it in the Devices file, thusly:
* Netname /dev/netport - - TLI \D\000
* bsfix() turns \000 into \N and then the loop below makes it a
* real, included-in-the-length null-byte.
*
* The DEBUG must print the strecpy'd address (so that
* non-printables will have been replaced with C escapes).
*/
DEBUG(5, "t_connect to addr \"%s\"\n",
strecpy( addrbuf, dev[D_ARG], "\\" ) );
if ( dev[D_ARG][0] == '\\' &&
( dev[D_ARG][1] == 'x' || dev[D_ARG][1] == 'X'
|| dev[D_ARG][1] == 'o' || dev[D_ARG][1] == 'O' ) ) {
if ( stoa(dev[D_ARG], &(sndcall->addr)) == (struct netbuf *)NULL ) {
DEBUG0(5, "tlicall: stoa failed\n");
logent("tlicall", "string-to-address failed");
Uerror = SS_NO_DEVICE;
(void) t_close(fd);
return(FAIL);
}
} else {
for( i = j = 0; i < BUFSIZ && dev[D_ARG][i] != NULLCHAR;
++i, ++j ) {
if( dev[D_ARG][i] == '\\' && dev[D_ARG][i+1] == 'N' ) {
addrbuf[j] = NULLCHAR;
++i;
}
else {
addrbuf[j] = dev[D_ARG][i];
}
}
sndcall->addr.buf = addrbuf;
sndcall->addr.len = j;
}
if (setjmp(Sjbuf)) {
DEBUG0(4, "timeout tlicall\n");
logent("tlicall", "TIMEOUT");
TFREE(bind_ret);TFREE(sndcall);TFREE(rcvcall);
Uerror = SS_NO_DEVICE;
(void) t_close(fd);
return(FAIL);
}
(void) signal(SIGALRM, alarmtr);
(void) alarm(30);
/* connect to the service -- some listeners can't handle */
/* multiple connect requests, so try it a few times */
errno = t_errno = 0;
for ( i = 0; i < CONNECT_ATTEMPTS; ++i ) {
if (t_connect(fd, sndcall, rcvcall) == 0)
break;
if ( (t_errno == TLOOK) && (t_look(fd) == T_DISCONNECT)) {
t_rcvdis(fd,NULL);
(void) alarm(0);
} else {
(void) alarm(0);
tfaillog(fd, "t_connect");
TFREE(bind_ret);TFREE(sndcall);TFREE(rcvcall);
Uerror = SS_DIAL_FAILED;
(void) t_close(fd);
return(FAIL);
}
}
(void) alarm(0);
TFREE(bind_ret);TFREE(sndcall);TFREE(rcvcall);
if ( i == CONNECT_ATTEMPTS ) {
tfaillog(fd, "t_connect");
Uerror = SS_DIAL_FAILED;
(void) t_close(fd);
return(FAIL);
}
errno = t_errno = 0;
return(fd);
}
#endif /* TLI */