SysIII/usr/src/cmd/cu.c
/***************************************************************
* cu [-s speed] [-a acu] [-l line] [ h ] [-o | -e] telno | 'dir'
*
* speeds are: 110, 150, 300, 1200, 4800, 9600.
* Set default speed by defining the value of BAUD.
* -l and -a are for line and unit arguments from the file whose
* name is defined under LDEVS below.
* -h is for half-duplex (local echoing).
* -d can be used (with ddt) to get some tracing & diagnostics.
* -o or -e is for odd or even parity on transmission to remote.
* telno is either a telephone number or "dir" for a direct line.
* If "dir" is used, the the "-l dev" option is required. If
* "-l dev", or "-a acu" are used, speed is taken from LDEVS.
*
* Escape with `~' at beginning of line.
* Silent output diversions are ~>:filename and ~>>:filename.
* Terminate output diversion with ~> alone.
* ~. is quit, and ~! gives local command or shell.
* Also ~$ for canned local procedure pumping remote.
* Both ~%put from [to] and ~%take from [to] invoke built-ins.
* Also, ~%break or just ~%b will transmit a BREAK to remote.
* ~nostop turns off the DC3/DC1 input control from remote,
* (certain remote systems cannot cope with DC3 or DC1).
*
* As a device-lockout semaphore mechanism, create an entry
* in the directory #defined as LOCK whose name is LCK..dev
* where dev is the device name taken from the "line" column
* in the file #defined as LDEVS. Be sure to trap every possible
* way out of cu execution in order to "release" the device.
* Also, have the system start-up procedure clean all such
* entries from the LOCK directory.
***************************************************************/
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <termio.h>
#include <ctype.h>
#include <errno.h>
#define LDEVS "/usr/lib/uucp/L-devices"
#define LOCK "/usr/spool/uucp/LCK.." /* where to synch with uucp */
#define BAUD "300" /* default baud rate */
#define ACULAST "<" /* character which terminates dialing*/
#define RUB '\177' /* mnemonic */
#define XON '\21' /* mnemonic */
#define XOFF '\23' /* mnemonic */
#define TTYIN 0 /* mnemonic */
#define TTYOUT 1 /* mnemonic */
#define TTYERR 2 /* mnemonic */
#define YES 1 /* mnemonic */
#define NO 0 /* mnemonic */
#define EQUALS !strcmp /* mnemonic */
#define DIFFER strcmp /* mnemonic */
#define COPY strcpy /* mnemonic */
#define EXEC(A, B, C) execl("/bin/sh", A, B, C, 0)
FILE *Ldevices; /* file pointer for Device name file */
struct termio tv, tv0, lv;
union { /* this helps to quiet lint */
int i;
unsigned char u;
char c;
} cx;
char
tkill, /* current input kill */
terase, /* current input erase */
*devtype="ACU", /* indicates dial or direct connect */
*acu="", /* ptr to name of requested ACU */
*line="", /* ptr to name of requested device */
dspeed[6]=BAUD, /* default baud rate */
*speed, /* ptr to requested line speed */
*telno, /* ptr to dialed tel-no or "dir" */
cul[20], /* line chosen */
cua[20], /* acu's device-name */
lock[30+sizeof(LOCK)], /* directory in which to make lockfile*/
*strtok(),
*strcat(),
*strncpy(),
*strpbrk(),
*strcpy();
unsigned sleep(), alarm();
extern errno;
int
found=0, /* set when device is seen legal */
linarg, /* length of arg for `-l' option */
acuarg, /* length of arg for `-a' option */
rlfd, /* fd for remote comm line */
lfd= -1, /* fd for the device-lock file */
parity=0, /* 0 for no parity, -1 odd, 1 even */
intrupt=NO, /* interrupt indicator */
#ifdef ddt
debug=NO, /* flag turns on more diagnostics */
#endif
duplex=YES, /* half(NO), or full(YES) duplex */
sstop=YES, /* NO means remote can't XON/XOFF */
rtn_code=1,
takeflag=NO; /* indicates a ~%take is in progress */
onintrpt(), /* interrupt routine */
sigalarm(), /* interrupt routine */
hangup(), /* interrupt routine */
byebye(), /* interrupt routine */
die(), /* interrupt routine */
strcmp();
char *msg[]= {
/* 0*/ "usage: cu [-s speed] [-a acu] [-l line] [ h ] [-o | -e] telno | \"dir\"\n",
/* 1*/ "interrupt",
/* 2*/ "dialer hung",
/* 3*/ "no answer",
/* 4*/ "can't fork",
/* 5*/ "acu problem",
/* 6*/ "line problem",
/* 7*/ "line hung",
/* 8*/ "Can not open: %s\r\n",
/* 9*/ "Connect failed: %s\r\n",
/* 10*/ "No line %s at %s baud\r\n",
/* 11*/ "\"%s\" with \"%s\" not %s at %s baud\r\n",
/* 12*/ "Device \"%s\" not %s\r\n",
/* 13*/ "Line gone\r\n",
/* 14*/ "Can't execute shell\r\n",
/* 15*/ "Can't divert %s\r\n",
/* 16*/ "Use `~~' to start line with `~'\r\n",
/* 17*/ "character missed\r\n",
/* 18*/ "after %ld bytes\r\n",
/* 19*/ "%d lines/%ld characters\r\n",
/* 20*/ "Only digits & '-'s or '='s in telno\n",
/* 21*/ "file transmission interrupted\r\n"
};
/***************************************************************
* main: get connection, and fork.
* Child invokes "receive" to read from remote & write to tty.
* Main line invokes "transmit" to read tty & write to remote.
***************************************************************/
main(argc, argv)
char *argv[];
{
int fk, errflag=0;
extern int optind;
extern char *optarg;
speed = dspeed;
while((cx.i = getopt(argc, argv, "dheos:l:a:")) != EOF)
switch(cx.i) {
case 'd':
#ifdef ddt
debug = YES;
#else
++errflag;
#endif
break;
case 'h':
duplex ^= YES;
break;
case 'e':
if(++parity != 1)
++errflag;
break;
case 'o':
if(--parity != -1)
++errflag;
break;
case 's':
speed = optarg;
break;
case 'l':
line = optarg;
break;
case 'a':
acu = optarg;
break;
case '?':
++errflag;
}
linarg = strlen(line);
acuarg = strlen(acu);
if(optind < argc && optind > 0) {
telno = argv[optind];
if(strlen(telno) != strspn(telno, "0123456789=-"))
if(EQUALS(telno,"dir")) {
if(linarg == 0)
++errflag;
devtype = COPY(devtype, "DIR");
} else {
display(msg[20]);
++errflag;
}
} else
++errflag;
if(errflag) {
display(msg[0]);
exit(1);
}
if((Ldevices = fopen(LDEVS, "r")) == NULL) {
display(msg[8], LDEVS);
exit(1);
}
(void) ioctl(TTYIN, TCGETA, &tv0); /* save initial tty state */
tkill = tv0.c_cc[VKILL];
terase = tv0.c_cc[VERASE];
(void) signal(SIGHUP, die);
(void) signal(SIGQUIT, die);
(void) signal(SIGINT, onintrpt);
(void) signal(SIGALRM, sigalarm);
while(1) {
char dvc[50], *find_dev();
(void) COPY(dvc, find_dev(acu, line, speed));
if(strlen(dvc) == 0) {
char *why;
why = found? "available": "known";
if(acuarg == 0 && linarg == 0)
display(msg[10], why, speed);
else
if(acuarg != 0 && linarg != 0)
display(msg[11], line, acu, why, speed);
else
display(msg[12], linarg? line: acu, why);
die(8);
}
(void) COPY(lock, LOCK);
(void) strcat(lock, dvc);
if(geteuid() == 0 && access(lock, 0) == 0)
continue;
if((lfd = creat(lock, 0444)) < 0)
continue;
else {
cx.i = getpid();
(void) write(lfd, &cx.c, sizeof(cx.i));
}
(void) fclose(Ldevices);
if(intrupt == YES)
die(-1);
if((rlfd = connect(cul, cua, telno, speed)) < 0) {
display(msg[9], msg[-rlfd]);
die(-rlfd);
}
break;
}
/* When we get this far we have an open communication line */
mode(1); /* put terminal in `raw' mode */
display("Connected\r\n");
if((fk = dofork()) == 0) {
(void) signal(SIGHUP, hangup);
(void) signal(SIGINT, SIG_IGN);
(void) signal(SIGQUIT, hangup);
receive(); /* This should run until killed */
display("\r\n\07Lost carrier\r\n");
#ifdef ddt
if(debug == YES) tdmp(rlfd);
#endif
hangup();
}
(void) signal(SIGUSR1, byebye);
(void) signal(SIGHUP, SIG_IGN);
(void) signal(SIGQUIT, SIG_IGN);
rtn_code = transmit(); /* This is the parent proccess */
(void) kill(fk, SIGKILL); /* Kill paired "receive" proccess */
byebye();
}
/***************************************************************
* transmit: copy stdin to rlfd, except:
* ~. terminate
* ~! local login-style shell
* ~!cmd execute cmd locally
* ~$proc execute proc locally, send output to line
* ~%cmd execute builtin cmd (put, take, or break)
****************************************************************/
transmit()
{
char b[200];
register char *p;
register int escape;
#ifdef ddt
if(debug == YES) display("transmit started\n\r");
#endif
while(1) {
p = b;
while(r_char(TTYIN) == YES) {
if(p == b) /* Escape on leading ~ */
escape = (cx.c == '~');
if(p == b+1) /* But not on leading ~~ */
escape &= (cx.c != '~');
if(escape) {
if(cx.c == '\r' || cx.c == '\n') {
*p = '\0';
if(tilda(b+1) == YES)
return(0);
break;
}
if(cx.c == RUB || cx.c == tkill
|| cx.c == '\0') {
display("\r\n");
break;
}
if(w_char(TTYERR) == NO)
return(7); /* tty gone */
if(cx.c == terase) {
p = (--p < b)? b:p;
continue;
}
} else {
if(cx.c == '\0') {
(void) ioctl(rlfd, TCSBRK, 0);
flush();
break;
}
if(w_char(rlfd) == NO) {
display(msg[13]);
return(2);
}
if(duplex == NO)
if(w_char(TTYERR) == NO)
return(7);
if(cx.c == RUB) {
flush();
break;
}
if(cx.c == '\n' || cx.c == '\r'
|| cx.c == tkill)
break;
}
*p++ = cx.c;
}
}
}
flush() /* routine to halt input from remote and flush buffers */
{
(void) ioctl(TTYOUT, TCXONC, 0);
(void) ioctl(rlfd, TCFLSH, 0);
(void) ioctl(TTYOUT, TCFLSH, 1);
(void) ioctl(TTYOUT, TCXONC, 1);
if(takeflag == NO) {
return;
}
display(msg[21]);
(void) sleep(3);
w_str("echo '~>';mesg y\n");
takeflag = NO;
}
tilda(cmd)
char *cmd;
{
display("\r\n");
#ifdef ddt
if(debug == YES) display("call tilda(%s)\r\n", cmd);
#endif
switch(cmd[0]) {
case '.':
if(EQUALS(devtype,"DIR"))
if(cmd[1] != '.')
w_str("\04\04\04\04\04");
return(YES);
case '!':
case '$':
shell(cmd); /* Local shell */
display("\r%c\r\n", *cmd);
w_str("\n");
break;
case '%':
dopercen(++cmd);
break;
#ifdef ddt
case 't':
tdmp(TTYIN);
break;
case 'l':
tdmp(rlfd);
break;
#endif
default:
display(msg[16]);
}
return(NO);
}
/***************************************************************
* The routine "shell" takes an argument starting with
* either "!" or "$", and terminated with '\0'.
* If $arg, arg is the name of a local shell file which
* is executed and its output is passed to the remote.
* If !arg, we escape to a local shell to execute arg
* with output to TTY, and if arg is null, escape to
* a local shell and blind the remote line. In either
* case, RUBout or '^D' will kill the escape status.
**************************************************************/
shell(str)
char *str;
{
int fk;
#ifdef ddt
if(debug == YES) display("call shell(%s)\r\n", str);
#endif
fk = dofork();
if(fk == 0) {
/***********************************************
* Hook-up our "standard output"
* to either the tty or the line
* as appropriate for '!' or '$'
***********************************************/
(void) close(TTYOUT);
(void) fcntl((*str == '$')? rlfd:TTYERR,F_DUPFD,TTYOUT);
(void) close(rlfd);
mode(0); /* normal */
(void) signal(SIGINT, SIG_DFL);
if(*++str == '\0')
EXEC("-", (char *) 0, (char *) 0);
else
EXEC("sh", "-c", str);
display(msg[14]);
exit(0);
}
if(fk > 0)
while(wait((int *) 0) != fk);
mode(1);
}
/***************************************************************
* This function implements the 'put', 'take', and 'break'
* commands which are internal to cu.
***************************************************************/
dopercen(cmd)
register char *cmd;
{
char *arg[5];
int narg;
#ifdef ddt
if(debug == YES) display("call dopercen(\"%s\")\r\n", cmd);
#endif
arg[narg=0] = strtok(cmd, " \t\n");
/* following loop breaks out the command and args */
while((arg[++narg] = strtok((char*) NULL, " \t\n")) != NULL) {
if(narg < 5)
continue;
else
break;
}
if(EQUALS(arg[0], "take")) {
if(narg < 2 || narg > 3) {
display("usage: ~%%take from [to]\r\n");
return;
}
if(narg == 2)
arg[2] = arg[1];
w_str("mesg n;echo '~>':");
w_str(arg[2]);
w_str(";cat ");
w_str(arg[1]);
w_str(";echo '~>';mesg y\n");
takeflag = YES;
return;
}
else if(EQUALS(arg[0], "put")) {
FILE *file;
char buf[512], spec[3], *b, *p, *q;
int len, tc=0, lines=0;
long chars=0L;
if(narg < 2 || narg > 3) {
display("usage: ~%%put from [to]\r\n");
goto R;
}
if(parity) {
display("parity problem\r\n");
goto R;
}
if(narg == 2)
arg[2] = arg[1];
if((file = fopen(arg[1], "r")) == NULL) {
display(msg[8], arg[1]);
R:
w_str("\n");
return;
}
w_str("stty -echo; cat - > ");
w_str(arg[2]);
w_str("; stty echo\n");
intrupt = NO;
mode(2);
spec[0] = terase;
spec[1] = tkill;
spec[2] = '\0';
(void) sleep(5);
while(intrupt == NO &&
fgets(b= &buf[256],256,file) != NULL) {
len = strlen(b);
chars += len; /* character count */
p = b;
while(q = strpbrk(p, spec)) {
b = strncpy(b-1, b, q-b);
*(q-1) = '\\';
p = q+1;
}
if((tc += len) >= 256) {
(void) sleep(1);
tc = len;
}
if(write(rlfd, b, strlen(b)) < 0) {
display(msg[17]);
intrupt = YES;
break;
}
++lines; /* line count */
}
mode(1);
(void) fclose(file);
if(intrupt == YES) {
intrupt = NO;
display(msg[21]);
w_str("\n");
display(msg[18], ++chars);
} else
display(msg[19], lines, chars);
w_str("\04");
(void) sleep(3);
return;
}
else if(EQUALS(arg[0], "b") || EQUALS(arg[0], "break")) {
(void) ioctl(rlfd, TCSBRK, 0);
return;
}
else if(EQUALS(arg[0], "nostop")) {
(void) ioctl(rlfd, TCGETA, &tv);
tv.c_iflag &= ~IXOFF;
(void) ioctl(rlfd, TCSETA, &tv);
sstop = NO;
mode(1);
return;
}
display("~%%%s unknown to cu\r\n", arg[0]);
}
/***************************************************************
* receive: read from remote line, write to fd=1 (TTYOUT)
* catch:
* ~>[>]:file
* .
* . stuff for file
* .
* ~> (ends diversion)
***************************************************************/
receive()
{
register silent=NO, file;
register char *p;
int tic;
char b[512];
long lseek(), count;
#ifdef ddt
if(debug == YES) display("receive started\r\n");
#endif
file = -1;
p = b;
while(r_char(rlfd) == YES) {
if(silent == NO)
if(w_char(TTYOUT) == NO)
return;
*p++ = cx.c;
if(cx.c != '\n' && (p-b) < 512)
continue;
/* remove (CR) and junk inserted at remote */
while(p-2 >= b && (*(p-2) == '\r' || *(p-2) == '\0')) {
--p;
*(p-1) = *p;
}
/***********************************************
* The rest of this code is to deal with what
* happens at the beginning, middle or end of
* a diversion to a file.
************************************************/
if(b[0] == '~' && b[1] == '>') {
/****************************************
* The line is the beginning or
* end of a diversion to a file.
****************************************/
if((file < 0) && (b[2] == ':' || b[2] == '>')) {
/**********************************
* Beginning of a diversion
*********************************/
int append;
*(p-1) = NULL; /* terminate file name */
append = (b[2] == '>')? 1:0;
p = b + 3 + append;
if(append && (file=open(p,O_WRONLY))>0)
(void) lseek(file, 0L, 2);
else
file = creat(p, 0666);
if(file < 0)
display(msg[15], p);
else {
silent = YES;
count = tic = 0;
}
} else {
/*******************************
* End of a diversion (or queer data)
*******************************/
if(b[2] != '\n')
goto D; /* queer data */
if(silent = close(file)) {
display(msg[15], b);
silent = NO;
}
display("~>\r\n");
display(msg[19], tic, count);
file = -1;
}
} else {
/***************************************
* This line is not an escape line.
* Either no diversion; or else yes, and
* we've got to divert the line to the file.
***************************************/
D:
if(file > 0) {
(void) write(file, b, p-b);
count += p-b; /* tally char count */
++tic; /* tally lines */
}
}
p = b;
}
}
/***************************************************************
* change the TTY attributes of the users terminal:
* 0 means restore attributes to pre-cu status.
* 1 means set `raw' mode for use during cu session.
* 2 means like 1 but accept interrupts from the keyboard.
***************************************************************/
mode(arg)
{
#ifdef ddt
if(debug == YES) display("call mode(%d)\r\n", arg);
#endif
if(arg == 0) {
(void) ioctl(TTYIN, TCSETAW, &tv0);
} else {
(void) ioctl(TTYIN, TCGETA, &tv);
if(arg == 1) {
tv.c_iflag &= ~(INLCR | ICRNL | BRKINT);
if(sstop == YES)
tv.c_iflag |= IXON;
else
tv.c_iflag &= ~IXON;
tv.c_oflag |= OPOST;
tv.c_oflag &= ~(OLCUC | ONLCR | OCRNL | ONOCR
| ONLRET);
tv.c_lflag &= ~(ICANON | ECHO | ISIG);
tv.c_cc[VMIN] = '\01';
tv.c_cc[VTIME] = '\0';
}
if(arg == 2) {
tv.c_iflag |= (IXON | BRKINT);
tv.c_lflag |= ISIG;
}
(void) ioctl(TTYIN, TCSETAW, &tv);
}
}
#ifdef ddt
tdmp(arg)
{
struct termio xv;
int i;
(void) printf("\rdevice status for fd=%d\n", arg);
(void) printf("\rF_GETFL=%o,", fcntl(arg, F_GETFL,1));
if(ioctl(arg, TCGETA, &xv) < 0) {
char buf[100];
(void) sprintf(buf, "\rtdmp for fd=%d:", arg);
perror(buf);
return;
}
(void) printf("iflag=`%o',", xv.c_iflag);
(void) printf("oflag=`%o',", xv.c_oflag);
(void) printf("cflag=`%o',", xv.c_cflag);
(void) printf("lflag=`%o',", xv.c_lflag);
(void) printf("line=`%o'\r\n", xv.c_line);
(void) printf("cc[0]=`%o',", xv.c_cc[0]);
for(i=1; i<8; ++i)
(void) printf("[%d]=`%o',", i, xv.c_cc[i]);
(void) printf("\r\n");
}
#endif
dofork()
{
register x, i=0;
while(++i < 6)
if((x = fork()) != -1)
return(x);
#ifdef ddt
if(debug == YES) perror("dofork");
#endif
display(msg[4]);
return(x);
}
r_char(fd)
{
extern errno;
int rtn;
char str[30];
errno = 0;
if((rtn = read(fd, &cx.c, 1)) != 1) {
(void) sprintf(str,"read from fd=%d returned %d", fd, rtn);
perror(str);
#ifdef ddt
if(debug == YES) tdmp(fd);
#endif
}
return((rtn == 1)? YES:NO);
}
w_char(fd)
{
return((write(fd, &cx.c, 1) == 1)? YES:NO);
}
/*VARARGS1*/
display(fmt, arg1, arg2, arg3, arg4, arg5)
char *fmt;
{
(void) fprintf(stderr, fmt, arg1, arg2, arg3, arg4, arg5);
}
w_str(string)
register char *string;
{
int len;
len = strlen(string);
if(write(rlfd, string, len) != len)
display(msg[13]);
}
onintrpt()
{
(void) signal(SIGINT, onintrpt);
intrupt = YES;
}
sigalarm()
{
(void) signal(SIGALRM, sigalarm);
}
byebye() /* this is executed only in the parent proccess */
{
(void) wait((int *) 0);
display("\r\nDisconnected\r\n");
die(rtn_code);
}
die(arg) /* this is executed only in the parent proccess */
{
#ifdef ddt
if(debug == YES) display("call die(%d)\r\n", arg);
#endif
if(rlfd > 0)
(void) close(rlfd);
if(lfd > 0) {
if(fork() == 0) {
if(EQUALS(devtype, "ACU")) {
/* hold lock-file entry 'till acu recovers */
(void) signal(SIGINT, SIG_IGN);
(void) signal(SIGALRM, SIG_IGN);
(void) signal(SIGHUP, SIG_IGN);
(void) sleep(12);
}
(void) close(lfd);
if(unlink(lock) < 0)
display("Can't unlink lock-file\n");
#ifdef ddt
else if(debug == YES)
display("Lock-file unlinked\n");
#endif
exit(0);
}
}
mode(0); /* restore users prior tty status */
exit(arg);
}
hangup() /* this is executed only in the receive proccess */
{
exit(kill(getppid(), SIGUSR1));
}
/***************************************************************
* connect: establish dial-out connection.
* Negative values returned (-2...-7) are error message indices.
* Be sure to disconnect tty when done, via HUPCL or stty 0.
***************************************************************/
connect(dev, xacu, xtelno, wspd)
char *dev, *xacu, *xtelno, *wspd;
{
int er=0, dum, fdac, fd=0, t, w;
char sp_code, b[30];
extern errno;
#ifdef ddt
if(debug == YES) display("call connect(%s,%s,%s,%s)\r\n", dev,
xacu, xtelno, wspd);
#endif
switch(atoi(wspd)) {
case 110:
sp_code = B110;
break;
case 150:
sp_code = B150;
break;
case 300:
sp_code = B300;
break;
case 1200:
sp_code = B1200;
break;
case 4800:
sp_code = B4800;
break;
case 9600:
sp_code = B9600;
break;
default:
sp_code = B300;
}
if((fd = open(dev, O_RDWR | O_NDELAY)) < 0) {
perror(dev);
er = 6;
goto X;
}
if((t = ioctl(fd, TCGETA, &lv)) < 0)
perror("gtty for remote");
else {
lv.c_cflag &= ~CBAUD;
lv.c_cflag |= (CREAD | HUPCL | sp_code);
if(parity) {
lv.c_cflag |= PARENB;
lv.c_cflag &= ~CSIZE;
lv.c_cflag |= CS7;
if(parity < 0)
lv.c_cflag |= PARODD;
}
if(EQUALS(devtype, "DIR"))
lv.c_cflag |= CLOCAL;
lv.c_iflag |= (IGNPAR | IGNBRK | ISTRIP | IXON | IXOFF);
lv.c_iflag &= ~(INLCR | ICRNL);
lv.c_cc[VERASE] = '\0';
lv.c_cc[VKILL] = '\0';
lv.c_cc[VMIN] = '\1';
lv.c_cc[VTIME] = '\0';
lv.c_lflag &= ~(ICANON | ECHO | ISIG);
if((t = ioctl(fd, TCSETA, &lv)) < 0)
perror("stty for remote");
}
if(t < 0) {
er = (errno == EINTR? 7:6);
goto X;
}
if(EQUALS(devtype, "ACU")) {
if((fdac = open(xacu, O_WRONLY)) < 0) {
perror(xacu);
er = 5;
goto X;
}
t = strlen(strcat(COPY(b,xtelno),ACULAST));
#ifdef ddt
if(debug == YES) display("dialing %s\n", b);
#endif
(void) alarm((unsigned) (2*t+5));
w = write(fdac, b, t); /* dial the number */
(void) alarm(0);
if(w != t) {
perror("write to acu");
er = (errno == EINTR)? 2:5;
goto X;
}
(void) close(fdac); /* dialing is complete */
#ifdef ddt
if(debug == YES) display("dialing complete\n");
#endif
}
(void) alarm((unsigned) (t+15));
dum = open(dev, O_RDWR); /* wait here for carrier */
(void) alarm(0);
if(dum < 0) {
#ifdef ddt
if(debug == YES) perror(dev);
#endif
er = (errno == EINTR)? 3:6;
goto X;
}
(void) close(dum); /* the dummy open used for waiting*/
(void) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NDELAY);
#if ddt
if(debug == YES && fd > 0) tdmp(fd);
#endif
X:
if(intrupt == YES)
er = 1;
#ifdef ddt
if(debug == YES)
display("connect ends eith er=%d, fd=%d\n", er, fd);
#endif
return(er? -er:fd);
}
/***************************************************************
* find_dev: find a device pair with the wanted characteristics
* specified in line, acu, and speed arguments.
* The global 'devtype' should have the value "ACU" or "DIR",
* depending on value of 'telno' arg on the command line.
* Return pointer to device name for use in lock-out synch.
* The globals 'cua' and 'cul' will be set to contain the
* /dev directory names of the corresponding devices.
* If the L-devices list contains a '0' entry because the
* line is direct, the global 'cua' is set to '\0'.
***************************************************************/
char *
find_dev(xacu, ln, spd)
char *xacu, *ln, *spd;
{
char buf[50], *b; /* place to read L-devices into */
int acarg, lnarg;
#ifdef ddt
if(debug == YES)
display("call find_dev(%s, %s, %s)\n", xacu, ln, spd);
#endif
acarg = strlen(xacu);
lnarg = strlen(ln);
while(fgets(buf, 50, Ldevices) != NULL) {
if(DIFFER(devtype, strtok(buf, " \t")))
continue;
(void) strcat(COPY(cul,"/dev/"),strtok((char*)NULL," \t"));
if(*(b = strtok((char *) NULL, " \t")) == '0')
cua[0] = '\0';
else
(void) strcat(COPY(cua,"/dev/"),b);
if(acarg) {
if(DIFFER(devtype, "ACU"))
break;
if(DIFFER(xacu, cua) && DIFFER(xacu, &cua[5]))
continue;
(void) COPY(spd, strtok((char *)NULL, " \t\n"));
++found;
return(cul+5);
}
if(lnarg) {
if(DIFFER(ln, cul) && DIFFER(ln, &cul[5]))
continue;
(void) COPY(spd, strtok((char *)NULL, " \t\n"));
++found;
return(cul+5);
}
if(EQUALS(devtype, "ACU")) {
if(DIFFER(spd, strtok((char *) NULL, " \t\n")))
continue;
++found;
return(cul+5);
}
}
return("");
}