76bd0c0a9d
ppp based on these patches for about 3 weeks with no downtime. The original submitters comments: Two features iijppp has over kernel ppp that I like are predictor1 compression and demand dialing. Here are a few bug fixes. I expanded the priority queueing scheme and discovered it was broken due to the assignment at ip.c line 300. All packets were being queued at the same priority. Fixing priority queueing broke predictor1 compression. Packets were compressed before being queued and predictor1 worked as long as the packets were popped off the queue in the same order they were pushed onto the queue. There were a few byte order problems in IP header tests also. There is a recursion problem in SendLqrReport(). LcpClose() is called when "Too many echo packets are lost" which winds up in SendLqrReport() again. I believe the original intention was to just stop the LQR timer with the call to StopLqr() but the side effects hurt. Submitted by: John Capo <jc@irbs.com>
788 lines
16 KiB
C
788 lines
16 KiB
C
/*
|
|
* PPP Modem handling module
|
|
*
|
|
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
|
|
*
|
|
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
|
|
*
|
|
* Redistribution and use in source and binary forms are permitted
|
|
* provided that the above copyright notice and this paragraph are
|
|
* duplicated in all such forms and that any documentation,
|
|
* advertising materials, and other materials related to such
|
|
* distribution and use acknowledge that the software was developed
|
|
* by the Internet Initiative Japan, Inc. The name of the
|
|
* IIJ may not be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
|
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
|
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
*
|
|
* $Id: modem.c,v 1.11 1996/01/11 17:48:54 phk Exp $
|
|
*
|
|
* TODO:
|
|
*/
|
|
#include "fsm.h"
|
|
#include <fcntl.h>
|
|
#include <termios.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/tty.h>
|
|
#include <errno.h>
|
|
#include <time.h>
|
|
#include "hdlc.h"
|
|
#include "lcp.h"
|
|
#include "ip.h"
|
|
#include "modem.h"
|
|
#include "vars.h"
|
|
|
|
#ifndef O_NONBLOCK
|
|
#ifdef O_NDELAY
|
|
#define O_NONBLOCK O_NDELAY
|
|
#endif
|
|
#endif
|
|
|
|
extern int DoChat();
|
|
|
|
static int mbits; /* Current DCD status */
|
|
static int connect_time; /* connection time */
|
|
static int connect_count;
|
|
static struct pppTimer ModemTimer;
|
|
static char uucplock[10];
|
|
|
|
extern int uu_lock(), uu_unlock();
|
|
extern void PacketMode();
|
|
|
|
#define Online (mbits & TIOCM_CD)
|
|
|
|
static struct mbuf *modemout;
|
|
static struct mqueue OutputQueues[PRI_LINK+1];
|
|
static int dev_is_modem;
|
|
|
|
#undef QDEBUG
|
|
|
|
void
|
|
Enqueue(queue, bp)
|
|
struct mqueue *queue;
|
|
struct mbuf *bp;
|
|
{
|
|
if (queue->last) {
|
|
queue->last->pnext = bp;
|
|
queue->last = bp;
|
|
} else
|
|
queue->last = queue->top = bp;
|
|
queue->qlen++;
|
|
#ifdef QDEBUG
|
|
logprintf("Enqueue: len = %d\n", queue->qlen);
|
|
#endif
|
|
}
|
|
|
|
struct mbuf *
|
|
Dequeue(queue)
|
|
struct mqueue *queue;
|
|
{
|
|
struct mbuf *bp;
|
|
|
|
#ifdef QDEBUG
|
|
logprintf("Dequeue: len = %d\n", queue->qlen);
|
|
#endif
|
|
bp = queue->top;
|
|
if (bp) {
|
|
queue->top = queue->top->pnext;
|
|
queue->qlen--;
|
|
if (queue->top == NULL) {
|
|
queue->last = queue->top;
|
|
#ifdef QDEBUG
|
|
if (queue->qlen)
|
|
logprintf("!!! not zero (%d)!!!\n", queue->qlen);
|
|
#endif
|
|
}
|
|
}
|
|
return(bp);
|
|
}
|
|
|
|
static struct speeds{
|
|
int nspeed;
|
|
speed_t speed;
|
|
} speeds[] = {
|
|
#ifdef B50
|
|
{ 50, B50, },
|
|
#endif
|
|
#ifdef B75
|
|
{ 75, B75, },
|
|
#endif
|
|
#ifdef B110
|
|
{ 110, B110, },
|
|
#endif
|
|
#ifdef B134
|
|
{ 134, B134, },
|
|
#endif
|
|
#ifdef B150
|
|
{ 150, B150, },
|
|
#endif
|
|
#ifdef B200
|
|
{ 200, B200, },
|
|
#endif
|
|
#ifdef B300
|
|
{ 300, B300, },
|
|
#endif
|
|
#ifdef B600
|
|
{ 600, B600, },
|
|
#endif
|
|
#ifdef B1200
|
|
{ 1200, B1200, },
|
|
#endif
|
|
#ifdef B1800
|
|
{ 1800, B1800, },
|
|
#endif
|
|
#ifdef B2400
|
|
{ 2400, B2400, },
|
|
#endif
|
|
#ifdef B4800
|
|
{ 4800, B4800, },
|
|
#endif
|
|
#ifdef B9600
|
|
{ 9600, B9600, },
|
|
#endif
|
|
#ifdef B19200
|
|
{ 19200, B19200, },
|
|
#endif
|
|
#ifdef B38400
|
|
{ 38400, B38400, },
|
|
#endif
|
|
#ifndef _POSIX_SOURCE
|
|
#ifdef B7200
|
|
{ 7200, B7200, },
|
|
#endif
|
|
#ifdef B14400
|
|
{ 14400, B14400, },
|
|
#endif
|
|
#ifdef B28800
|
|
{ 28800, B28800, },
|
|
#endif
|
|
#ifdef B57600
|
|
{ 57600, B57600, },
|
|
#endif
|
|
#ifdef B76800
|
|
{ 76800, B76800, },
|
|
#endif
|
|
#ifdef B115200
|
|
{ 115200, B115200, },
|
|
#endif
|
|
#ifdef B230400
|
|
{ 230400, B230400, },
|
|
#endif
|
|
#ifdef EXTA
|
|
{ 19200, EXTA, },
|
|
#endif
|
|
#ifdef EXTB
|
|
{ 38400, EXTB, },
|
|
#endif
|
|
#endif /*_POSIX_SOURCE */
|
|
{ 0, 0 }
|
|
};
|
|
|
|
int SpeedToInt(speed)
|
|
speed_t speed;
|
|
{
|
|
struct speeds *sp;
|
|
|
|
for (sp = speeds; sp->nspeed; sp++) {
|
|
if (sp->speed == speed) {
|
|
return(sp->nspeed);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
speed_t IntToSpeed(nspeed)
|
|
int nspeed;
|
|
{
|
|
struct speeds *sp;
|
|
|
|
for (sp = speeds; sp->nspeed; sp++) {
|
|
if (sp->nspeed == nspeed) {
|
|
return(sp->speed);
|
|
}
|
|
}
|
|
return B0;
|
|
}
|
|
|
|
static time_t uptime;
|
|
|
|
void
|
|
DownConnection()
|
|
{
|
|
LogPrintf(LOG_PHASE, "Disconnected!\n");
|
|
LogPrintf(LOG_PHASE, "Connect time: %d secs\n", time(NULL) - uptime);
|
|
CloseModem();
|
|
LcpDown();
|
|
connect_time = 0;
|
|
}
|
|
|
|
/*
|
|
* ModemTimeout() watches DCD signal and notifies if it's status is changed.
|
|
*
|
|
*/
|
|
void
|
|
ModemTimeout()
|
|
{
|
|
int ombits = mbits;
|
|
int change;
|
|
|
|
StopTimer(&ModemTimer);
|
|
if (Online)
|
|
connect_time++;
|
|
StartTimer(&ModemTimer);
|
|
|
|
if (dev_is_modem) {
|
|
ioctl(modem, TIOCMGET, &mbits);
|
|
change = ombits ^ mbits;
|
|
if (change & TIOCM_CD) {
|
|
if (Online) {
|
|
time(&uptime);
|
|
LogPrintf(LOG_PHASE, "*Connected!\n");
|
|
connect_count++;
|
|
/*
|
|
* In dedicated mode, start packet mode immediate
|
|
* after we detected carrier.
|
|
*/
|
|
if (mode & MODE_DEDICATED)
|
|
PacketMode();
|
|
} else {
|
|
DownConnection();
|
|
}
|
|
}
|
|
} else {
|
|
if (!Online) {
|
|
time(&uptime);
|
|
LogPrintf(LOG_PHASE, "Connected!\n");
|
|
mbits = TIOCM_CD;
|
|
connect_count++;
|
|
connect_time = 0;
|
|
} else if (uptime == 0) {
|
|
time(&uptime);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
StartModemTimer()
|
|
{
|
|
connect_time = 0;
|
|
StopTimer(&ModemTimer);
|
|
ModemTimer.state = TIMER_STOPPED;
|
|
ModemTimer.load = SECTICKS;
|
|
ModemTimer.func = ModemTimeout;
|
|
StartTimer(&ModemTimer);
|
|
}
|
|
|
|
struct parity {
|
|
char *name;
|
|
char *name1;
|
|
int set;
|
|
} validparity[] = {
|
|
{ "even", "P_EVEN", CS7 | PARENB }, { "odd", "P_ODD", CS7 | PARENB | PARODD },
|
|
{ "none", "P_ZERO", CS8 }, { NULL, 0 },
|
|
};
|
|
|
|
int
|
|
GetParityValue(str)
|
|
char *str;
|
|
{
|
|
struct parity *pp;
|
|
|
|
for (pp = validparity; pp->name; pp++) {
|
|
if (strcasecmp(pp->name, str) == 0 ||
|
|
strcasecmp(pp->name1, str) == 0) {
|
|
VarParity = pp->set;
|
|
return(pp->set);
|
|
}
|
|
}
|
|
return(-1);
|
|
}
|
|
|
|
int
|
|
ChangeParity(str)
|
|
char *str;
|
|
{
|
|
struct termios rstio;
|
|
int val;
|
|
|
|
val = GetParityValue(str);
|
|
if (val > 0) {
|
|
VarParity = val;
|
|
tcgetattr(modem, &rstio);
|
|
rstio.c_cflag &= ~(CSIZE|PARODD|PARENB);
|
|
rstio.c_cflag |= val;
|
|
tcsetattr(modem, TCSADRAIN, &rstio);
|
|
}
|
|
return(val);
|
|
}
|
|
|
|
#include <sys/socket.h>
|
|
#include <arpa/inet.h>
|
|
#include <netdb.h>
|
|
|
|
int
|
|
OpenConnection(host, port)
|
|
char *host, *port;
|
|
{
|
|
struct sockaddr_in dest;
|
|
int sock;
|
|
struct hostent *hp;
|
|
struct servent *sp;
|
|
|
|
dest.sin_family = AF_INET;
|
|
dest.sin_addr.s_addr = inet_addr(host);
|
|
if (dest.sin_addr.s_addr == INADDR_NONE) {
|
|
hp = gethostbyname(host);
|
|
if (hp) {
|
|
bcopy(hp->h_addr_list[0], &dest.sin_addr.s_addr, 4);
|
|
} else {
|
|
printf("unknown host: %s\n", host);
|
|
return(-1);
|
|
}
|
|
}
|
|
dest.sin_port = htons(atoi(port));
|
|
if (dest.sin_port == 0) {
|
|
sp = getservbyname(port, "tcp");
|
|
if (sp) {
|
|
dest.sin_port = sp->s_port;
|
|
} else {
|
|
printf("unknown service: %s\n", port);
|
|
return(-1);
|
|
}
|
|
}
|
|
LogPrintf(LOG_PHASE, "Connected to %s:%s\n", host, port);
|
|
|
|
sock = socket(PF_INET, SOCK_STREAM, 0);
|
|
if (sock < 0) {
|
|
return(sock);
|
|
}
|
|
if (connect(sock, (struct sockaddr *)&dest, sizeof(dest)) < 0) {
|
|
printf("connection failed.\n");
|
|
return(-1);
|
|
}
|
|
return(sock);
|
|
}
|
|
|
|
int
|
|
OpenModem(mode)
|
|
int mode;
|
|
{
|
|
struct termios rstio;
|
|
int oldflag;
|
|
char *host, *cp, *port;
|
|
|
|
mbits = 0;
|
|
if (mode & MODE_DIRECT) {
|
|
if (isatty(0))
|
|
modem = open(ctermid(NULL), O_RDWR|O_NONBLOCK);
|
|
} else if (modem == 0) {
|
|
if (strncmp(VarDevice, "/dev", 4) == 0) {
|
|
strcpy(uucplock, rindex(VarDevice, '/')+1);
|
|
if (uu_lock(uucplock) < 0) {
|
|
LogPrintf(LOG_PHASE, "Modem %s is in use\n", VarDevice);
|
|
return(-1);
|
|
}
|
|
modem = open(VarDevice, O_RDWR|O_NONBLOCK);
|
|
if (modem < 0) {
|
|
LogPrintf(LOG_PHASE, "Open Failed %s\n", VarDevice);
|
|
(void) uu_unlock(uucplock);
|
|
return(modem);
|
|
}
|
|
} else {
|
|
/* XXX: PPP over TCP */
|
|
cp = index(VarDevice, ':');
|
|
if (cp) {
|
|
*cp = 0;
|
|
host = VarDevice;
|
|
port = cp + 1;
|
|
if (*host && *port) {
|
|
modem = OpenConnection(host, port);
|
|
*cp = ':'; /* Don't destroy VarDevice */
|
|
if (modem < 0) return(-1);
|
|
} else {
|
|
*cp = ':'; /* Don't destroy VarDevice */
|
|
return(-1);
|
|
}
|
|
} else
|
|
return(-1);
|
|
}
|
|
}
|
|
|
|
/* This code gets around the problem of closing descriptor 0
|
|
* when it should not have been closed and closing descriptor 1
|
|
* when the telnet connection dies. Since this program always
|
|
* opens a descriptor for the modem in auto and direct mode,
|
|
* having to dup the descriptor here is a fatal error.
|
|
*
|
|
* With the other changes I have made this should no longer happen.
|
|
* JC
|
|
*/
|
|
while (modem < 3)
|
|
{
|
|
logprintf("Duping modem fd %d\n", modem);
|
|
modem = dup(modem);
|
|
}
|
|
|
|
/*
|
|
* If we are working on tty device, change it's mode into
|
|
* the one desired for further operation. In this implementation,
|
|
* we assume that modem is configuted to use CTS/RTS flow control.
|
|
*/
|
|
dev_is_modem = isatty(modem) || DEV_IS_SYNC;
|
|
if (DEV_IS_SYNC)
|
|
sleep(1);
|
|
if (dev_is_modem && !DEV_IS_SYNC) {
|
|
tcgetattr(modem, &rstio);
|
|
#ifdef DEBUG
|
|
logprintf("## modem = %d\n", modem);
|
|
logprintf("modem (get): iflag = %x, oflag = %x, cflag = %x\n",
|
|
rstio.c_iflag, rstio.c_oflag, rstio.c_cflag);
|
|
#endif
|
|
#define USE_CTSRTS
|
|
#ifdef USE_CTSRTS
|
|
rstio.c_cflag = (CS8 | CREAD | CLOCAL | CCTS_OFLOW|CRTS_IFLOW);
|
|
#else
|
|
rstio.c_cflag = (CS8 | CREAD | CLOCAL);
|
|
#endif
|
|
if ((mode & MODE_DIRECT) == 0) {
|
|
/*
|
|
* If we are working as direct mode, don't change tty speed.
|
|
*/
|
|
rstio.c_cflag &= ~(CSIZE|PARENB|PARODD);
|
|
rstio.c_cflag |= VarParity;
|
|
cfsetspeed(&rstio, IntToSpeed(VarSpeed));
|
|
}
|
|
rstio.c_iflag |= (IGNBRK | ISTRIP | IGNPAR | IXON | IXOFF);
|
|
rstio.c_iflag &= ~(BRKINT|ICRNL|IXANY|IMAXBEL);
|
|
rstio.c_lflag = 0;
|
|
|
|
rstio.c_oflag &= ~OPOST;
|
|
#ifdef notdef
|
|
rstio.c_cc[VMIN] = 10;
|
|
rstio.c_cc[VTIME] = 1;
|
|
#else
|
|
rstio.c_cc[VMIN] = 1;
|
|
rstio.c_cc[VTIME] = 0;
|
|
#endif
|
|
tcsetattr(modem, TCSADRAIN, &rstio);
|
|
#ifdef DEBUG
|
|
logprintf("modem (put): iflag = %x, oflag = %x, cflag = %x\n",
|
|
rstio.c_iflag, rstio.c_oflag, rstio.c_cflag);
|
|
#endif
|
|
|
|
if (!(mode & MODE_DIRECT))
|
|
ioctl(modem, TIOCMGET, &mbits);
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "modem control = %o\n", mbits);
|
|
#endif
|
|
|
|
oldflag = fcntl(modem, F_GETFL, 0);
|
|
fcntl(modem, F_SETFL, oldflag & ~O_NONBLOCK);
|
|
}
|
|
StartModemTimer();
|
|
|
|
return(modem);
|
|
}
|
|
|
|
int
|
|
ModemSpeed()
|
|
{
|
|
struct termios rstio;
|
|
|
|
tcgetattr(modem, &rstio);
|
|
return(SpeedToInt(cfgetispeed(&rstio)));
|
|
}
|
|
|
|
static struct termios modemios;
|
|
|
|
/*
|
|
* Put modem tty line into raw mode which is necessary in packet mode operation
|
|
*/
|
|
int
|
|
RawModem(modem)
|
|
int modem;
|
|
{
|
|
struct termios rstio;
|
|
int oldflag;
|
|
|
|
if (!isatty(modem) || DEV_IS_SYNC)
|
|
return(0);
|
|
if (!(mode & MODE_DIRECT) && modem && !Online) {
|
|
#ifdef DEBUG
|
|
logprintf("mode = %d, modem = %d, mbits = %x\n", mode, modem, mbits);
|
|
#endif
|
|
#ifdef notdef
|
|
return(-1);
|
|
#endif
|
|
}
|
|
tcgetattr(modem, &rstio);
|
|
modemios = rstio;
|
|
rstio.c_cflag &= ~(CSIZE|PARENB|PARODD);
|
|
rstio.c_cflag |= CS8;
|
|
rstio.c_iflag &= ~(ISTRIP|IXON|IXOFF|BRKINT|ICRNL|INLCR);
|
|
tcsetattr(modem, TCSADRAIN, &rstio);
|
|
oldflag = fcntl(modem, F_GETFL, 0);
|
|
fcntl(modem, F_SETFL, oldflag | O_NONBLOCK);
|
|
#ifdef DEBUG
|
|
oldflag = fcntl(modem, F_GETFL, 0);
|
|
logprintf("modem (put2): iflag = %x, oflag = %x, cflag = %x\n",
|
|
rstio.c_iflag, rstio.c_oflag, rstio.c_cflag);
|
|
logprintf("flag = %x\n", oldflag);
|
|
#endif
|
|
return(0);
|
|
}
|
|
|
|
void
|
|
UnrawModem(modem)
|
|
int modem;
|
|
{
|
|
int oldflag;
|
|
|
|
if (isatty(modem)) {
|
|
tcsetattr(modem, TCSADRAIN, &modemios);
|
|
oldflag = fcntl(modem, F_GETFL, 0);
|
|
fcntl(modem, F_SETFL, oldflag & ~O_NONBLOCK);
|
|
}
|
|
}
|
|
|
|
void
|
|
HangupModem(flag)
|
|
int flag;
|
|
{
|
|
struct termios tio;
|
|
|
|
if (!isatty(modem)) {
|
|
mbits &= ~TIOCM_DTR;
|
|
close(modem);
|
|
modem = 0; /* Mark as modem has closed */
|
|
return;
|
|
}
|
|
|
|
if (modem && Online) {
|
|
mbits &= ~TIOCM_DTR;
|
|
#ifdef __bsdi__ /* not a POSIX way */
|
|
ioctl(modem, TIOCMSET, &mbits);
|
|
#else
|
|
tcgetattr(modem, &tio);
|
|
cfsetspeed(&tio, B0);
|
|
tcsetattr(modem, TCSANOW, &tio);
|
|
#endif
|
|
sleep(1);
|
|
#ifdef notdef
|
|
mbits &= ~TIOCM_CD;
|
|
#endif
|
|
}
|
|
/*
|
|
* If we are working as dedicated mode, never close it
|
|
* until we are directed to quit program.
|
|
*/
|
|
if (modem && (flag || !(mode & MODE_DEDICATED))) {
|
|
ModemTimeout(); /* XXX */
|
|
StopTimer(&ModemTimer); /* XXX */
|
|
|
|
/* ModemTimeout() may call DownConection() to close the modem
|
|
* resulting in modem == 0.
|
|
*/
|
|
if (modem)
|
|
{
|
|
tcflush(modem, TIOCFLUSH);
|
|
UnrawModem(modem);
|
|
close(modem);
|
|
}
|
|
(void) uu_unlock(uucplock);
|
|
modem = 0; /* Mark as modem has closed */
|
|
} else if (modem) {
|
|
mbits |= TIOCM_DTR;
|
|
#ifndef notyet
|
|
ioctl(modem, TIOCMSET, &mbits);
|
|
#else
|
|
tcgetattr(modem, &ts);
|
|
cfsetspeed(&ts, IntToSpeed(VarSpeed));
|
|
tcsetattr(modem, TCSADRAIN, &ts);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void
|
|
CloseModem()
|
|
{
|
|
if (modem >= 3)
|
|
{
|
|
close(modem);
|
|
modem = 0;
|
|
}
|
|
(void) uu_unlock(uucplock);
|
|
}
|
|
|
|
/*
|
|
* Write to modem. Actualy, requested packets are queued, and goes out
|
|
* to the line when ModemStartOutput() is called.
|
|
*/
|
|
void
|
|
WriteModem(pri, ptr, count)
|
|
int pri;
|
|
char *ptr;
|
|
int count;
|
|
{
|
|
struct mbuf *bp;
|
|
|
|
bp = mballoc(count, MB_MODEM);
|
|
bcopy(ptr, MBUF_CTOP(bp), count);
|
|
|
|
/* Should be NORMAL and LINK only.
|
|
* All IP frames get here marked NORMAL.
|
|
*/
|
|
Enqueue(&OutputQueues[pri], bp);
|
|
}
|
|
|
|
void
|
|
ModemOutput(pri, bp)
|
|
int pri;
|
|
struct mbuf *bp;
|
|
{
|
|
struct mbuf *wp;
|
|
int len;
|
|
|
|
len = plength(bp);
|
|
wp = mballoc(len, MB_MODEM);
|
|
mbread(bp, MBUF_CTOP(wp), len);
|
|
Enqueue(&OutputQueues[pri], wp);
|
|
ModemStartOutput(modem);
|
|
}
|
|
|
|
int
|
|
ModemQlen()
|
|
{
|
|
struct mqueue *queue;
|
|
int len = 0;
|
|
int i;
|
|
|
|
for ( i = PRI_NORMAL; i <= PRI_LINK; i ++ ) {
|
|
queue = &OutputQueues[i];
|
|
len += queue->qlen;
|
|
}
|
|
return(len);
|
|
|
|
}
|
|
|
|
void
|
|
ModemStartOutput(fd)
|
|
int fd;
|
|
{
|
|
struct mqueue *queue;
|
|
int nb, nw, i;
|
|
|
|
if (modemout == NULL && ModemQlen() == 0)
|
|
IpStartOutput();
|
|
if (modemout == NULL) {
|
|
i = PRI_LINK;
|
|
for (queue = &OutputQueues[PRI_LINK]; queue >= OutputQueues; queue--) {
|
|
if (queue->top) {
|
|
modemout = Dequeue(queue);
|
|
#ifdef QDEBUG
|
|
if (i > PRI_NORMAL) {
|
|
struct mqueue *q;
|
|
|
|
q = &OutputQueues[0];
|
|
logprintf("output from queue %d, normal has %d\n", i, q->qlen);
|
|
}
|
|
logprintf("Dequeue(%d): ", i);
|
|
#endif
|
|
break;
|
|
}
|
|
i--;
|
|
}
|
|
}
|
|
if (modemout) {
|
|
nb = modemout->cnt;
|
|
if (nb > 1600) nb = 1600;
|
|
if (fd == 0) fd = 1; /* XXX WTFO! This is bogus */
|
|
nw = write(fd, MBUF_CTOP(modemout), nb);
|
|
#ifdef QDEBUG
|
|
logprintf("wrote: %d(%d)\n", nw, nb);
|
|
LogDumpBuff(LOG_HDLC, "modem write", MBUF_CTOP(modemout), nb);
|
|
#endif
|
|
if (nw > 0) {
|
|
modemout->cnt -= nw;
|
|
modemout->offset += nw;
|
|
if (modemout->cnt == 0) {
|
|
modemout = mbfree(modemout);
|
|
#ifdef QDEBUG
|
|
logprintf(" mbfree\n");
|
|
#endif
|
|
}
|
|
} else if (nw < 0) {
|
|
if (errno != EAGAIN)
|
|
perror("modem write");
|
|
}
|
|
}
|
|
}
|
|
|
|
int
|
|
DialModem()
|
|
{
|
|
char ScriptBuffer[200];
|
|
|
|
strcpy(ScriptBuffer, VarDialScript);
|
|
if (DoChat(ScriptBuffer) > 0) {
|
|
fprintf(stderr, "dial OK!\n");
|
|
strcpy(ScriptBuffer, VarLoginScript);
|
|
if (DoChat(ScriptBuffer) > 0) {
|
|
fprintf(stderr, "login OK!\n");
|
|
return(1);
|
|
} else {
|
|
fprintf(stderr, "login failed.\n");
|
|
}
|
|
ModemTimeout(); /* Dummy call to check modem status */
|
|
}
|
|
else
|
|
fprintf(stderr, "dial failed.\n");
|
|
HangupModem(0);
|
|
return(0);
|
|
}
|
|
|
|
int
|
|
ShowModemStatus()
|
|
{
|
|
#ifdef TIOCOUTQ
|
|
int nb;
|
|
#endif
|
|
|
|
printf("device: %s speed: ", VarDevice);
|
|
if (DEV_IS_SYNC)
|
|
printf("sync\n");
|
|
else
|
|
printf("%d\n", VarSpeed);
|
|
|
|
switch (VarParity & CSIZE) {
|
|
case CS7:
|
|
printf("cs7, ");
|
|
break;
|
|
case CS8:
|
|
printf("cs8, ");
|
|
break;
|
|
}
|
|
if (VarParity & PARENB) {
|
|
if (VarParity & PARODD)
|
|
printf("odd parity\n");
|
|
else
|
|
printf("even parity\n");
|
|
} else
|
|
printf("none parity\n");
|
|
#ifdef DEBUG
|
|
printf("fd = %d, modem control = %o\n", modem, mbits);
|
|
#endif
|
|
printf("connect count: %d\n", connect_count);
|
|
#ifdef TIOCOUTQ
|
|
ioctl(modem, TIOCOUTQ, &nb);
|
|
printf("outq: %d\n", nb);
|
|
#endif
|
|
printf("outqlen: %d\n", ModemQlen());
|
|
printf("DialScript = %s\n", VarDialScript);
|
|
printf("LoginScript = %s\n", VarLoginScript);
|
|
printf("PhoneNumber = %s\n", VarPhone);
|
|
return(1);
|
|
}
|