summaryrefslogtreecommitdiff
path: root/noncore/settings/networksettings/ppp/modem.cpp
Side-by-side diff
Diffstat (limited to 'noncore/settings/networksettings/ppp/modem.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/settings/networksettings/ppp/modem.cpp85
1 files changed, 71 insertions, 14 deletions
diff --git a/noncore/settings/networksettings/ppp/modem.cpp b/noncore/settings/networksettings/ppp/modem.cpp
index d23fee4..3dbc8c3 100644
--- a/noncore/settings/networksettings/ppp/modem.cpp
+++ b/noncore/settings/networksettings/ppp/modem.cpp
@@ -30,97 +30,94 @@
#include <fcntl.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <setjmp.h>
#include <regex.h>
#include <qregexp.h>
#include <assert.h>
#include <string.h>
#ifdef HAVE_RESOLV_H
# include <arpa/nameser.h>
# include <resolv.h>
#endif
#ifndef _PATH_RESCONF
#define _PATH_RESCONF "/etc/resolv.conf"
#endif
#define strlcpy strcpy
#include "auth.h"
#include "modem.h"
#include "pppdata.h"
-//#include <klocale.h>
-#define i18n QObject::tr
#define qError qDebug
-//#include <kdebug.h>
-//#include <config.h>
+
#define MY_ASSERT(x) if (!(x)) { \
qFatal( "ASSERT: \"%s\" in %s (%d)\n",#x,__FILE__,__LINE__); \
exit(1); }
static sigjmp_buf jmp_buffer;
//Modem *Modem::modem = 0;
const char* pppdPath() {
// wasting a few bytes
static char buffer[sizeof(PPPDSEARCHPATH)+sizeof(PPPDNAME)];
static char *pppdPath = 0L;
char *p;
if(pppdPath == 0L) {
const char *c = PPPDSEARCHPATH;
while(*c != '\0') {
while(*c == ':')
c++;
p = buffer;
while(*c != '\0' && *c != ':')
*p++ = *c++;
*p = '\0';
strcat(p, "/");
strcat(p, PPPDNAME);
if(access(buffer, F_OK) == 0)
return (pppdPath = buffer);
}
}
return pppdPath;
}
Modem::Modem( PPPData* pd )
{
_pppdata = pd;
modemfd = -1;
_pppdExitStatus = -1;
pppdPid = -1;
- sn = 0L;
+ sn = m_modemDebug = 0L;
data_mode = false;
modem_is_locked = false;
lockfile[0] = '\0';
device = "/dev/modem";
}
Modem::~Modem()
{
}
speed_t Modem::modemspeed() {
// convert the string modem speed int the gpppdata object to a t_speed type
// to set the modem. The constants here should all be ifdef'd because
// other systems may not have them
int i = _pppdata->speed().toInt()/100;
switch(i) {
case 24:
return B2400;
break;
case 96:
return B9600;
@@ -148,143 +145,143 @@ speed_t Modem::modemspeed() {
return B230400;
break;
#endif
#ifdef B460800
case 4608:
return B460800;
break;
#endif
default:
return B38400;
break;
}
}
bool Modem::opentty() {
// int flags;
//begin if((modemfd = Requester::rq->openModem(gpppdata.modemDevice()))<0) {
close(modemfd);
device = _pppdata->modemDevice();
if ((modemfd = open(device, O_RDWR|O_NDELAY|O_NOCTTY)) == -1) {
qDebug("error opening modem device !");
- errmsg = i18n("Unable to open modem.");
+ errmsg = QObject::tr("Unable to open modem.");
return false;
}
//bend if((modemfd = Requester::rq->openModem(gpppdata.modemDevice()))<0) {
//}
#if 0
if(_pppdata->UseCDLine()) {
if(ioctl(modemfd, TIOCMGET, &flags) == -1) {
- errmsg = i18n("Unable to detect state of CD line.");
+ errmsg = QObject::tr("Unable to detect state of CD line.");
::close(modemfd);
modemfd = -1;
return false;
}
if ((flags&TIOCM_CD) == 0) {
- errmsg = i18n("The modem is not ready.");
+ errmsg = QObject::tr("The modem is not ready.");
::close(modemfd);
modemfd = -1;
return false;
}
}
#endif
tcdrain (modemfd);
tcflush (modemfd, TCIOFLUSH);
if(tcgetattr(modemfd, &tty) < 0){
// this helps in some cases
tcsendbreak(modemfd, 0);
sleep(1);
if(tcgetattr(modemfd, &tty) < 0){
- errmsg = i18n("The modem is busy.");
+ errmsg = QObject::tr("The modem is busy.");
::close(modemfd);
modemfd = -1;
return false;
}
}
memset(&initial_tty,'\0',sizeof(initial_tty));
initial_tty = tty;
tty.c_cc[VMIN] = 0; // nonblocking
tty.c_cc[VTIME] = 0;
tty.c_oflag = 0;
tty.c_lflag = 0;
tty.c_cflag &= ~(CSIZE | CSTOPB | PARENB);
tty.c_cflag |= CS8 | CREAD;
tty.c_cflag |= CLOCAL; // ignore modem status lines
tty.c_iflag = IGNBRK | IGNPAR /* | ISTRIP */ ;
tty.c_lflag &= ~ICANON; // non-canonical mode
tty.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHOKE);
if(_pppdata->flowcontrol() != "None") {
if(_pppdata->flowcontrol() == "CRTSCTS") {
tty.c_cflag |= CRTSCTS;
}
else {
tty.c_iflag |= IXON | IXOFF;
tty.c_cc[VSTOP] = 0x13; /* DC3 = XOFF = ^S */
tty.c_cc[VSTART] = 0x11; /* DC1 = XON = ^Q */
}
}
else {
tty.c_cflag &= ~CRTSCTS;
tty.c_iflag &= ~(IXON | IXOFF);
}
cfsetospeed(&tty, modemspeed());
cfsetispeed(&tty, modemspeed());
tcdrain(modemfd);
if(tcsetattr(modemfd, TCSANOW, &tty) < 0){
- errmsg = i18n("The modem is busy.");
+ errmsg = QObject::tr("The modem is busy.");
::close(modemfd);
modemfd=-1;
return false;
}
- errmsg = i18n("Modem Ready.");
+ errmsg = QObject::tr("Modem Ready.");
return true;
}
bool Modem::closetty() {
if(modemfd >=0 ) {
stop();
/* discard data not read or transmitted */
tcflush(modemfd, TCIOFLUSH);
if(tcsetattr(modemfd, TCSANOW, &initial_tty) < 0){
- errmsg = i18n("Can't restore tty settings: tcsetattr()\n");
+ errmsg = QObject::tr("Can't restore tty settings: tcsetattr()\n");
::close(modemfd);
modemfd = -1;
return false;
}
::close(modemfd);
modemfd = -1;
}
return true;
}
void Modem::readtty(int) {
char buffer[200];
unsigned char c;
int len;
// read data in chunks of up to 200 bytes
if((len = ::read(modemfd, buffer, 200)) > 0) {
// split buffer into single characters for further processing
for(int i = 0; i < len; i++) {
c = buffer[i] & 0x7F;
emit charWaiting(c);
}
@@ -392,49 +389,49 @@ bool Modem::hangup() {
// is this Escape & HangupStr stuff really necessary ? (Harri)
if (data_mode) escape_to_command_mode();
// Then hangup command
writeLine(_pppdata->modemHangupStr().local8Bit());
usleep(_pppdata->modemInitDelay() * 10000); // 0.01 - 3.0 sec
#ifndef DEBUG_WO_DIALING
if (sigsetjmp(jmp_buffer, 1) == 0) {
// set alarm in case tcsendbreak() hangs
signal(SIGALRM, alarm_handler);
alarm(2);
tcsendbreak(modemfd, 0);
alarm(0);
signal(SIGALRM, SIG_IGN);
} else {
// we reach this point if the alarm handler got called
closetty();
close(modemfd);
modemfd = -1;
- errmsg = i18n("The modem does not respond.");
+ errmsg = QObject::tr("The modem does not respond.");
return false;
}
#ifndef __svr4__ // drops DTR but doesn't set it afterwards again. not good for init.
tcgetattr(modemfd, &temptty);
cfsetospeed(&temptty, B0);
cfsetispeed(&temptty, B0);
tcsetattr(modemfd, TCSAFLUSH, &temptty);
#else
int modemstat;
ioctl(modemfd, TIOCMGET, &modemstat);
modemstat &= ~TIOCM_DTR;
ioctl(modemfd, TIOCMSET, &modemstat);
ioctl(modemfd, TIOCMGET, &modemstat);
modemstat |= TIOCM_DTR;
ioctl(modemfd, TIOCMSET, &modemstat);
#endif
usleep(_pppdata->modemInitDelay() * 10000); // 0.01 - 3.0 secs
cfsetospeed(&temptty, modemspeed());
cfsetispeed(&temptty, modemspeed());
tcsetattr(modemfd, TCSAFLUSH, &temptty);
#endif
@@ -534,49 +531,49 @@ QString Modem::parseModemSpeed(const QString &s) {
//
// trx[i] has been matched, idx contains the start of the match
// and len contains how long the match is. Extract the match.
//
QString sub = s.mid(idx, len);
//
// Now extract the digits only from the match, which will then
// be converted to an int.
//
if((idx = rrx[RXMAX-1].match(sub,0,&len)) > -1) {
// if((idx = rrx[RXMAX-1].search(sub)) > -1) {
// len = rrx[RXMAX-1].matchedLength();
sub = sub.mid(idx, len);
result = sub.toInt();
if(result > 0) {
tx = result;
break;
}
}
}
}
if(rx == -1 && tx == -1)
- result = i18n("Unknown speed");
+ result = QObject::tr("Unknown speed");
else if(tx == -1)
result.setNum(rx);
else if(rx == -1) // should not happen
result.setNum(tx);
else
result.sprintf("%d/%d", rx, tx);
qDebug( "The parsed result is: %s", result.latin1());
return result;
}
// Lock modem device. Returns 0 on success 1 if the modem is locked and -1 if
// a lock file can't be created ( permission problem )
int Modem::lockdevice() {
int fd;
char newlock[80]=""; // safe
if(!_pppdata->modemLockFile()) {
qDebug("The user doesn't want a lockfile.");
return 0;
}
@@ -856,104 +853,132 @@ int checkForInterface()
#else
return -1;
#endif
}
return 0;
#else
// We attempt to use the SunOS/SysVr4 method and stat /dev/ppp
struct stat buf;
memset(&buf, 0, sizeof(buf));
return stat("/dev/ppp", &buf);
#endif
}
bool Modem::execpppd(const char *arguments) {
char buf[MAX_CMDLEN];
char *args[MaxArgs];
pid_t pgrpid;
if(modemfd<0)
return false;
_pppdExitStatus = -1;
+ (void)::pipe( m_pppdLOG );
+
switch(pppdPid = fork())
{
case -1:
fprintf(stderr,"In parent: fork() failed\n");
+ ::close( m_pppdLOG[0] );
+ ::close( m_pppdLOG[1] );
return false;
break;
case 0:
// let's parse the arguments the user supplied into UNIX suitable form
// that is a list of pointers each pointing to exactly one word
strlcpy(buf, arguments);
parseargs(buf, args);
// become a session leader and let /dev/ttySx
// be the controlling terminal.
pgrpid = setsid();
#ifdef TIOCSCTTY
if(ioctl(modemfd, TIOCSCTTY, 0)<0)
fprintf(stderr, "ioctl() failed.\n");
#elif defined (TIOCSPGRP)
if(ioctl(modemfd, TIOCSPGRP, &pgrpid)<0)
fprintf(stderr, "ioctl() failed.\n");
#endif
if(tcsetpgrp(modemfd, pgrpid)<0)
fprintf(stderr, "tcsetpgrp() failed.\n");
+ ::close( m_pppdLOG[0] );
+ ::setenv( "LANG", "C", 1 ); // overwrite
+ dup2(m_pppdLOG[1], 11 ); // for logfd 11
dup2(modemfd, 0);
dup2(modemfd, 1);
+
switch (checkForInterface()) {
case 1:
fprintf(stderr, "Cannot determine if kernel supports ppp.\n");
break;
case -1:
fprintf(stderr, "Kernel does not support ppp, oops.\n");
break;
case 0:
fprintf(stderr, "Kernel supports ppp alright.\n");
break;
}
execve(pppdPath(), args, 0L);
_exit(0);
break;
default:
qDebug("In parent: pppd pid %d\n",pppdPid);
close(modemfd);
+
+ ::close( m_pppdLOG[1] );
+ // set it to nonblocking io
+ int flag = ::fcntl( m_pppdLOG[0], F_GETFL );
+
+ if ( !(flag & O_NONBLOCK) ) {
+ qDebug("Setting nonblocking io");
+ flag |= O_NONBLOCK;
+ ::fcntl(m_pppdLOG[0], F_SETFL, flag );
+ }
+
+ delete m_modemDebug;
+ m_modemDebug = new QSocketNotifier(m_pppdLOG[0], QSocketNotifier::Read, this );
+ connect(m_modemDebug, SIGNAL(activated(int) ),
+ this, SLOT(slotModemDebug(int) ) );
+
modemfd = -1;
+ m_pppdDev = QString::fromLatin1("ppp0");
return true;
break;
}
}
bool Modem::killpppd() {
+ qDebug("In killpppd and pid is %d", pppdPid );
if(pppdPid > 0) {
+ delete m_modemDebug;
+ m_modemDebug = 0;
qDebug("In killpppd(): Sending SIGTERM to %d\n", pppdPid);
if(kill(pppdPid, SIGTERM) < 0) {
qDebug("Error terminating %d. Sending SIGKILL\n", pppdPid);
if(kill(pppdPid, SIGKILL) < 0) {
qDebug("Error killing %d\n", pppdPid);
return false;
}
}
}
return true;
}
void Modem::parseargs(char* buf, char** args) {
int nargs = 0;
int quotes;
while(nargs < MaxArgs-1 && *buf != '\0') {
quotes = 0;
// Strip whitespace. Use nulls, so that the previous argument is
// terminated automatically.
@@ -1000,24 +1025,56 @@ void Modem::killPPPDaemon()
_pppdata->setpppdRunning(false);
killpppd();
}
int Modem::pppdExitStatus()
{
return _pppdExitStatus;
}
int Modem::openResolv(int flags)
{
int fd;
if ((fd = open(_PATH_RESCONF, flags)) == -1) {
qDebug("error opening resolv.conf!");
fd = open(DEVNULL, O_RDONLY);
}
return fd;
}
bool Modem::setHostname(const QString & name)
{
return sethostname(name, name.length()) == 0;
}
+QString Modem::pppDevice()const {
+ return m_pppdDev;
+}
+void Modem::setPPPDevice( const QString& dev ) {
+ m_pppdDev = dev;
+}
+pid_t Modem::pppPID()const {
+ return pppdPid;
+}
+void Modem::setPPPDPid( pid_t pid ) {
+ qDebug("Modem setting pid");
+ _pppdExitStatus = -1;
+ pppdPid = pid;
+ modemfd = -1;
+}
+void Modem::slotModemDebug(int fd) {
+ char buf[2049];
+ int len;
+
+ // read in pppd data look for Using interface
+ // then read the interface
+ // we limit to 10 device now 0-9
+ if((len = ::read(fd, buf, 2048)) > 0) {
+ buf[len+1] = '\0';
+ char *found;
+ if ( (found = ::strstr(buf, "Using interface ") ) ) {
+ found += 16;
+ m_pppdDev = QString::fromLatin1(found, 5 );
+ m_pppdDev = m_pppdDev.simplifyWhiteSpace();
+ }
+ }
+}