home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume15
/
modem-ctl
/
io.c
next >
Wrap
C/C++ Source or Header
|
1988-05-24
|
5KB
|
177 lines
/*
* Copyright (c) Dave Settle, March 1987
* Permission is granted to do anything with this program, except remove
* this copyright notice, or sell it for profit.
*
*
* io.c: routines to talk to the device directly.
*
* dread and dwrite act like read(2) and write(2), execpt that they always
* either succeed or exit, so the caller doesn't have to check.
*
* hangup drops the DTR line to the modem, so that it will (hopefully) hang up
* the phone line. It keeps it this way for 5 seconds.
*
* findspeed takes an ascii speed, and returns the corresponing baud rate.
*
* uuexit is a dodgy routine to make UUCP happy.
*/
#include <sys/errno.h>
#include <termio.h>
#include <fcntl.h>
#include "modem.h"
char *sys_errlist[]; /* error list */
#define RETRY 5 /* retry failed writes */
/*
* dwrite: write some characters to the modem.
* If your modem likes characters to be written s-l-o-w-l-y, define 'SLOW'
*/
dwrite(f, s, n)
int f;
unsigned n;
char *s;
{
struct termio termio;
int r, retry = 0, i = 0;
static int error = 0; /* error occurred on last call */
while((i < n) && (retry < RETRY)) {
if(locked()) uuexit(0);
errno = 0;
if(r = write(f, s + i, 1) == 1) i++; /* Success! */
else {
retry++;
fixline();
}
#ifdef SLOW
sleep(1); /* Let the modem deal with it */
#endif
}
if(i != n) {
ioctl(dev, TCGETA, &termio);
printf("Tried %d times, still got %d/%d written. [error = %s]\n",
retry, i, n, sys_errlist[errno]);
printf("FAIL: dev %d, iflag %x, oflag %x, cflag %x, lflag %x, line %d\n",
dev, termio.c_iflag,termio.c_oflag,termio.c_cflag,
termio.c_lflag, termio.c_line);
error = 1;
}
else if(retry > 1) printf("Write problem: fixed on retry %d\n", retry - 1);
if(error && i == n) {
ioctl(dev, TCGETA, &termio);
printf("OK: iflag %x, oflag %x, cflag %x, lflag %x, line %d\n",
termio.c_iflag,termio.c_oflag,termio.c_cflag,
termio.c_lflag, termio.c_line);
}
if(i == n) error = 0;
return(r);
}
/*
* read one character at a time, checking before (and after) each read for
* a lock file. If one exists, then exit.
*/
dread(f, s, n)
int f, n;
char *s;
{
int i, w;
for(i=0;i<n;i++, s++) {
if(locked()) uuexit(0);
while((w = read(f, s, 1)) < 1) {
if(locked()) uuexit(0);
if(w == -1) switch(errno) {
case EINTR:
break;
default:
perror("dread");
}
}
}
}
/*
* hangup(): hangup the phone, and close the device.
* I've had problems with indefinate echoes from the modem when a connection
* has closed - my modem transmits crap. This ought to hangup the phone and
* prevent this.
*
* Oct 87: This problem should now be fixed, with the introduction of the
* DCD control from the modem - we should now receive a hangup signal when
* the line drops.
*/
hangup(device) {
struct termio term;
if(ioctl(device, TCGETA, &term) == -1) perror("hangup: TCGETA");
term.c_lflag &= ~(ECHO | ECHOE | ECHOK);
term.c_cflag &= ~CBAUD;
term.c_cflag |= B0; /* hangup */
if(ioctl(device, TCSETA, &term) == -1) perror("hangup: TCSETA");
if(ioctl(device, TCFLSH, 2) == -1) perror("hangup: TCFLSH");
sleep(5); /* 5 seconds with DTR down */
return(0);
}
/*
* findspeed: convert ascii baud rate into termio parameter.
*/
findspeed(s)
char *s;
{
int baud = atoi(s);
switch(baud) {
case 110: baud = B110;
break;
case 300: baud = B300;
break;
case 1200: baud = B1200;
break;
case 2400: baud = B2400;
break;
default:
printf("findspeed: unknown baud rate %s\n", s);
baud = B1200;
}
return(baud);
}
/*
* uuexit: make line useable by UUCP.
* Because UUCP is pretty determined about using a "modem", it clears CLOCAL
* which means that it can't write any characters at this point (modem not
* online, so DCD not asserted). Not suprisingly, it doesn't work.
* Solution: turn it on again, while UUCP isn't looking; this seems to work
* fine, although I'm a little puzzled about the timing: this is a
* definate "trial and error" solution.
* This unfortunately also means that UUCP won't detect a line hangup,
* so we have to rely on it's timeout facilities ...
*/
#define DIALTIME 5 /* time to continue to assert CLOCAL */
uuexit(code)
{
struct termio term;
register int i;
for(i=0;i<DIALTIME;i++) {
close(open(dname, O_RDONLY | O_NDELAY)); /* vital magic */
if(ioctl(dev, TCGETA, &term) == -1) perror("qx TCGETA");
term.c_cflag |= CLOCAL;
if(ioctl(dev, TCSETA, &term) == -1) perror("qx TCSETA");
close(open(dname, O_RDONLY | O_NDELAY)); /* vital magic */
sleep(1);
}
exit(code);
}
/*
* extensions for send & expect
*/
myread()
{
char c;
dread(dev, &c, 1);
return(c);
}
void mywrite(s)
char *s;
{
dwrite(dev, s, strlen(s));
}