00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <opie2/odebug.h>
00029 using namespace Opie::Core;
00030
00031
00032 #include <errno.h>
00033 #include <stdlib.h>
00034 #include <unistd.h>
00035 #include <fcntl.h>
00036 #include <signal.h>
00037 #include <sys/ioctl.h>
00038 #include <sys/types.h>
00039 #include <sys/stat.h>
00040 #include <setjmp.h>
00041 #include <regex.h>
00042 #include <qregexp.h>
00043 #include <assert.h>
00044 #include <string.h>
00045
00046 #ifdef HAVE_RESOLV_H
00047 # include <arpa/nameser.h>
00048 # include <resolv.h>
00049 #endif
00050
00051 #ifndef _PATH_RESCONF
00052 #define _PATH_RESCONF "/etc/resolv.conf"
00053 #endif
00054
00055 #define strlcpy strcpy
00056 #include "auth.h"
00057 #include "modem.h"
00058 #include "pppdata.h"
00059
00060
00061 #define MY_ASSERT(x) if (!(x)) { \
00062 ofatal << "ASSERT: \"" << #x << "\" in " << __FILE__ << " (" << __LINE__ << ")\n" << oendl; \
00063 exit(1); }
00064
00065
00066 static sigjmp_buf jmp_buffer;
00067
00068
00069
00070
00071 const char* pppdPath() {
00072
00073 static char buffer[sizeof(PPPDSEARCHPATH)+sizeof(PPPDNAME)];
00074 static char *pppdPath = 0L;
00075 char *p;
00076
00077 if(pppdPath == 0L) {
00078 const char *c = PPPDSEARCHPATH;
00079 while(*c != '\0') {
00080 while(*c == ':')
00081 c++;
00082 p = buffer;
00083 while(*c != '\0' && *c != ':')
00084 *p++ = *c++;
00085 *p = '\0';
00086 strcat(p, "/");
00087 strcat(p, PPPDNAME);
00088 if(access(buffer, F_OK) == 0)
00089 return (pppdPath = buffer);
00090 }
00091 }
00092
00093 return pppdPath;
00094 }
00095
00096
00097 Modem::Modem( PPPData* pd )
00098 {
00099 _pppdata = pd;
00100 modemfd = -1;
00101 _pppdExitStatus = -1;
00102 pppdPid = -1;
00103 sn = m_modemDebug = 0L;
00104 data_mode = false;
00105 modem_is_locked = false;
00106 lockfile[0] = '\0';
00107 device = "/dev/modem";
00108 }
00109
00110
00111 Modem::~Modem()
00112 {
00113 }
00114
00115
00116 speed_t Modem::modemspeed() {
00117
00118
00119
00120 int i = _pppdata->speed().toInt()/100;
00121
00122 switch(i) {
00123 case 24:
00124 return B2400;
00125 break;
00126 case 96:
00127 return B9600;
00128 break;
00129 case 192:
00130 return B19200;
00131 break;
00132 case 384:
00133 return B38400;
00134 break;
00135 #ifdef B57600
00136 case 576:
00137 return B57600;
00138 break;
00139 #endif
00140
00141 #ifdef B115200
00142 case 1152:
00143 return B115200;
00144 break;
00145 #endif
00146
00147 #ifdef B230400
00148 case 2304:
00149 return B230400;
00150 break;
00151 #endif
00152
00153 #ifdef B460800
00154 case 4608:
00155 return B460800;
00156 break;
00157 #endif
00158
00159 default:
00160 return B38400;
00161 break;
00162 }
00163 }
00164
00165 bool Modem::opentty() {
00166
00167
00168
00169 close(modemfd);
00170 device = _pppdata->modemDevice();
00171 if ((modemfd = open(device, O_RDWR|O_NDELAY|O_NOCTTY)) == -1) {
00172 odebug << "error opening modem device !" << oendl;
00173 errmsg = QObject::tr("Unable to open modem.");
00174 return false;
00175 }
00176
00177
00178
00179 #if 0
00180 if(_pppdata->UseCDLine()) {
00181 if(ioctl(modemfd, TIOCMGET, &flags) == -1) {
00182 errmsg = QObject::tr("Unable to detect state of CD line.");
00183 ::close(modemfd);
00184 modemfd = -1;
00185 return false;
00186 }
00187 if ((flags&TIOCM_CD) == 0) {
00188 errmsg = QObject::tr("The modem is not ready.");
00189 ::close(modemfd);
00190 modemfd = -1;
00191 return false;
00192 }
00193 }
00194 #endif
00195
00196 tcdrain (modemfd);
00197 tcflush (modemfd, TCIOFLUSH);
00198
00199 if(tcgetattr(modemfd, &tty) < 0){
00200
00201 tcsendbreak(modemfd, 0);
00202 sleep(1);
00203 if(tcgetattr(modemfd, &tty) < 0){
00204 errmsg = QObject::tr("The modem is busy.");
00205 ::close(modemfd);
00206 modemfd = -1;
00207 return false;
00208 }
00209 }
00210
00211 memset(&initial_tty,'\0',sizeof(initial_tty));
00212
00213 initial_tty = tty;
00214
00215 tty.c_cc[VMIN] = 0;
00216 tty.c_cc[VTIME] = 0;
00217 tty.c_oflag = 0;
00218 tty.c_lflag = 0;
00219
00220 tty.c_cflag &= ~(CSIZE | CSTOPB | PARENB);
00221 tty.c_cflag |= CS8 | CREAD;
00222 tty.c_cflag |= CLOCAL;
00223 tty.c_iflag = IGNBRK | IGNPAR ;
00224 tty.c_lflag &= ~ICANON;
00225 tty.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHOKE);
00226
00227
00228 if(_pppdata->flowcontrol() != PPPData::FlowNone) {
00229 if(_pppdata->flowcontrol() == PPPData::FlowHardware) {
00230 tty.c_cflag |= CRTSCTS;
00231 }
00232 else {
00233 tty.c_iflag |= IXON | IXOFF;
00234 tty.c_cc[VSTOP] = 0x13;
00235 tty.c_cc[VSTART] = 0x11;
00236 }
00237 }
00238 else {
00239 tty.c_cflag &= ~CRTSCTS;
00240 tty.c_iflag &= ~(IXON | IXOFF);
00241 }
00242
00243 cfsetospeed(&tty, modemspeed());
00244 cfsetispeed(&tty, modemspeed());
00245
00246 tcdrain(modemfd);
00247
00248 if(tcsetattr(modemfd, TCSANOW, &tty) < 0){
00249 errmsg = QObject::tr("The modem is busy.");
00250 ::close(modemfd);
00251 modemfd=-1;
00252 return false;
00253 }
00254
00255 errmsg = QObject::tr("Modem Ready.");
00256 return true;
00257 }
00258
00259
00260 bool Modem::closetty() {
00261 if(modemfd >=0 ) {
00262 stop();
00263
00264 tcflush(modemfd, TCIOFLUSH);
00265
00266 if(tcsetattr(modemfd, TCSANOW, &initial_tty) < 0){
00267 errmsg = QObject::tr("Can't restore tty settings: tcsetattr()\n");
00268 ::close(modemfd);
00269 modemfd = -1;
00270 return false;
00271 }
00272 ::close(modemfd);
00273 modemfd = -1;
00274 }
00275
00276 return true;
00277 }
00278
00279
00280 void Modem::readtty(int) {
00281 char buffer[200];
00282 unsigned char c;
00283 int len;
00284
00285
00286 if((len = ::read(modemfd, buffer, 200)) > 0) {
00287
00288 for(int i = 0; i < len; i++) {
00289 c = buffer[i] & 0x7F;
00290 emit charWaiting(c);
00291 }
00292 }
00293 }
00294
00295
00296 void Modem::notify(const QObject *receiver, const char *member) {
00297 connect(this, SIGNAL(charWaiting(unsigned char)), receiver, member);
00298 startNotifier();
00299 }
00300
00301
00302 void Modem::stop() {
00303 disconnect(SIGNAL(charWaiting(unsigned char)));
00304 stopNotifier();
00305 }
00306
00307
00308 void Modem::startNotifier() {
00309 if(modemfd >= 0) {
00310 if(sn == 0) {
00311 sn = new QSocketNotifier(modemfd, QSocketNotifier::Read, this);
00312 connect(sn, SIGNAL(activated(int)), SLOT(readtty(int)));
00313 odebug << "QSocketNotifier started!" << oendl;
00314 } else {
00315 odebug << "QSocketNotifier re-enabled!" << oendl;
00316 sn->setEnabled(true);
00317 }
00318 }
00319 }
00320
00321
00322 void Modem::stopNotifier() {
00323 if(sn != 0) {
00324 sn->setEnabled(false);
00325 disconnect(sn);
00326 delete sn;
00327 sn = 0;
00328 odebug << "QSocketNotifier stopped!" << oendl;
00329 }
00330 }
00331
00332
00333 void Modem::flush() {
00334 char c;
00335 while(read(modemfd, &c, 1) == 1);
00336 }
00337
00338
00339 bool Modem::writeChar(unsigned char c) {
00340 int s;
00341 do {
00342 s = write(modemfd, &c, 1);
00343 if (s < 0) {
00344 oerr << "write() in Modem::writeChar failed" << oendl;
00345 return false;
00346 }
00347 } while(s == 0);
00348
00349 return true;
00350 }
00351
00352
00353 bool Modem::writeLine(const char *buf) {
00354 int len = strlen(buf);
00355 char *b = new char[len+2];
00356 memcpy(b, buf, len);
00357
00358 switch( _pppdata->enter() ) {
00359 case PPPData::EndLF:
00360 b[len++]='\n';
00361 break;
00362 case PPPData::EndCR:
00363 b[len++]='\r';
00364 break;
00365 case PPPData::EndCRLF:
00366 b[len++]='\r';
00367 b[len++]='\n';
00368 break;
00369 }
00370
00371 int l = len;
00372 while(l) {
00373 int wr = write(modemfd, &b[len-l], l);
00374 if(wr < 0) {
00375
00376 oerr << "write() in Modem::writeLine failed" << oendl;
00377 delete[] b;
00378 return false;
00379 }
00380 l -= wr;
00381 }
00382 delete[] b;
00383 return true;
00384 }
00385
00386
00387 bool Modem::hangup() {
00388
00389
00390
00391
00392
00393 struct termios temptty;
00394
00395 if(modemfd >= 0) {
00396
00397
00398
00399 if (data_mode) escape_to_command_mode();
00400
00401
00402 writeLine(_pppdata->modemHangupStr().local8Bit());
00403
00404 usleep(_pppdata->modemInitDelay() * 10000);
00405
00406 #ifndef DEBUG_WO_DIALING
00407 if (sigsetjmp(jmp_buffer, 1) == 0) {
00408
00409 signal(SIGALRM, alarm_handler);
00410 alarm(2);
00411
00412 tcsendbreak(modemfd, 0);
00413
00414 alarm(0);
00415 signal(SIGALRM, SIG_IGN);
00416 } else {
00417
00418 closetty();
00419 close(modemfd);
00420 modemfd = -1;
00421 errmsg = QObject::tr("The modem does not respond.");
00422 return false;
00423 }
00424
00425 #ifndef __svr4__ // drops DTR but doesn't set it afterwards again. not good for init.
00426 tcgetattr(modemfd, &temptty);
00427 cfsetospeed(&temptty, B0);
00428 cfsetispeed(&temptty, B0);
00429 tcsetattr(modemfd, TCSAFLUSH, &temptty);
00430 #else
00431 int modemstat;
00432 ioctl(modemfd, TIOCMGET, &modemstat);
00433 modemstat &= ~TIOCM_DTR;
00434 ioctl(modemfd, TIOCMSET, &modemstat);
00435 ioctl(modemfd, TIOCMGET, &modemstat);
00436 modemstat |= TIOCM_DTR;
00437 ioctl(modemfd, TIOCMSET, &modemstat);
00438 #endif
00439
00440 usleep(_pppdata->modemInitDelay() * 10000);
00441
00442 cfsetospeed(&temptty, modemspeed());
00443 cfsetispeed(&temptty, modemspeed());
00444 tcsetattr(modemfd, TCSAFLUSH, &temptty);
00445 #endif
00446 return true;
00447 } else
00448 return false;
00449 }
00450
00451
00452 void Modem::escape_to_command_mode() {
00453
00454
00455
00456
00457
00458
00459
00460 tcflush(modemfd, TCIOFLUSH);
00461
00462
00463 usleep((_pppdata->modemEscapeGuardTime()+3)*20000);
00464 QCString tmp = _pppdata->modemEscapeStr().local8Bit();
00465 write(modemfd, tmp.data(), tmp.length());
00466 tcflush(modemfd, TCIOFLUSH);
00467 usleep((_pppdata->modemEscapeGuardTime()+3)*20000);
00468
00469 data_mode = false;
00470 }
00471
00472
00473 const QString Modem::modemMessage() {
00474 return errmsg;
00475 }
00476
00477
00478 QString Modem::parseModemSpeed(const QString &s) {
00479
00480 int rx = -1;
00481 int tx = -1;
00482 int i;
00483 QString result;
00484
00485 odebug << "Modem reported result string: " << s.latin1() << "" << oendl;
00486
00487 const int RXMAX = 7;
00488 const int TXMAX = 2;
00489 QRegExp rrx[RXMAX] = {
00490 QRegExp("[0-9]+[:/ ]RX", false),
00491 QRegExp("[0-9]+RX", false),
00492 QRegExp("[/: -][0-9]+[/: ]", false),
00493 QRegExp("[/: -][0-9]+$", false),
00494 QRegExp("CARRIER [^0-9]*[0-9]+", false),
00495 QRegExp("CONNECT [^0-9]*[0-9]+", false),
00496 QRegExp("[0-9]+")
00497 };
00498
00499 QRegExp trx[TXMAX] = {
00500 QRegExp("[0-9]+[:/ ]TX", false),
00501 QRegExp("[0-9]+TX", false)
00502 };
00503
00504 for(i = 0; i < RXMAX; i++) {
00505 int len, idx, result;
00506 if((idx = rrx[i].match(s,0,&len)) > -1) {
00507
00508
00509
00510
00511
00512
00513
00514 QString sub = s.mid(idx, len);
00515
00516
00517
00518
00519
00520 if ((idx = rrx[RXMAX-1].match( sub,0,&len )) > -1) {
00521
00522
00523 sub = sub.mid(idx, len);
00524 result = sub.toInt();
00525 if(result > 0) {
00526 rx = result;
00527 break;
00528 }
00529 }
00530 }
00531 }
00532
00533 for(i = 0; i < TXMAX; i++) {
00534 int len, idx, result;
00535 if((idx = trx[i].match(s,0,&len)) > -1) {
00536
00537
00538
00539
00540
00541
00542
00543 QString sub = s.mid(idx, len);
00544
00545
00546
00547
00548
00549 if((idx = rrx[RXMAX-1].match(sub,0,&len)) > -1) {
00550
00551
00552 sub = sub.mid(idx, len);
00553 result = sub.toInt();
00554 if(result > 0) {
00555 tx = result;
00556 break;
00557 }
00558 }
00559 }
00560 }
00561
00562 if(rx == -1 && tx == -1)
00563 result = QObject::tr("Unknown speed");
00564 else if(tx == -1)
00565 result.setNum(rx);
00566 else if(rx == -1)
00567 result.setNum(tx);
00568 else
00569 result.sprintf("%d/%d", rx, tx);
00570
00571 odebug << "The parsed result is: " << result.latin1() << "" << oendl;
00572
00573 return result;
00574 }
00575
00576
00577
00578
00579 int Modem::lockdevice() {
00580 int fd;
00581 char newlock[80]="";
00582
00583 if(!_pppdata->modemLockFile()) {
00584 odebug << "The user doesn't want a lockfile." << oendl;
00585 return 0;
00586 }
00587
00588 if (modem_is_locked)
00589 return 1;
00590
00591 QString lockfile = LOCK_DIR"/LCK..";
00592 lockfile += _pppdata->modemDevice().mid(5);
00593
00594 if(access(QFile::encodeName(lockfile), F_OK) == 0) {
00595
00596 if ((fd = openLockfile(QFile::encodeName(lockfile), O_RDONLY)) >= 0) {
00597
00598
00599 char oldlock[33];
00600 int sz = read(fd, &oldlock, 32);
00601 close (fd);
00602 if (sz <= 0)
00603 return 1;
00604 oldlock[sz] = '\0';
00605
00606 odebug << "Device is locked by: " << oldlock << "" << oendl;
00607
00608 int oldpid;
00609 int match = sscanf(oldlock, "%d", &oldpid);
00610
00611
00612 if (match < 1 || oldpid <= 0)
00613 return 1;
00614
00615
00616 if (kill((pid_t)oldpid, 0) == 0 || errno != ESRCH)
00617 return 1;
00618
00619 odebug << "lockfile is stale" << oendl;
00620 }
00621 }
00622
00623 fd = openLockfile(_pppdata->modemDevice(),O_WRONLY|O_TRUNC|O_CREAT);
00624 if(fd >= 0) {
00625 sprintf(newlock,"%010d\n", getpid());
00626 odebug << "Locking Device: " << newlock << "" << oendl;
00627
00628 write(fd, newlock, strlen(newlock));
00629 close(fd);
00630 modem_is_locked=true;
00631
00632 return 0;
00633 }
00634
00635 return -1;
00636
00637 }
00638
00639
00640
00641 void Modem::unlockdevice() {
00642 if (modem_is_locked) {
00643 odebug << "UnLocking Modem Device" << oendl;
00644 close(modemfd);
00645 modemfd = -1;
00646 unlink(lockfile);
00647 lockfile[0] = '\0';
00648 modem_is_locked=false;
00649 }
00650 }
00651
00652 int Modem::openLockfile( QString lockfile, int flags)
00653 {
00654 int fd;
00655 int mode;
00656 flags = O_RDONLY;
00657 if(flags == O_WRONLY|O_TRUNC|O_CREAT)
00658 mode = 0644;
00659 else
00660 mode = 0;
00661
00662 lockfile = LOCK_DIR;
00663 lockfile += "/LCK..";
00664 lockfile += device.right( device.length() - device.findRev("/") -1 );
00665 odebug << "lockfile >" << lockfile.latin1() << "<" << oendl;
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676 if ((fd = open(lockfile, flags, mode)) == -1) {
00677 odebug << "error opening lockfile!" << oendl;
00678 lockfile = QString::null;
00679 fd = open(DEVNULL, O_RDONLY);
00680 } else
00681 fchown(fd, 0, 0);
00682 return fd;
00683 }
00684
00685
00686
00687 void alarm_handler(int) {
00688
00689
00690
00691 siglongjmp(jmp_buffer, 1);
00692 }
00693
00694
00695 const char* Modem::authFile(Auth method, int version) {
00696 switch(method|version) {
00697 case PAP|Original:
00698 return PAP_AUTH_FILE;
00699 break;
00700 case PAP|New:
00701 return PAP_AUTH_FILE".new";
00702 break;
00703 case PAP|Old:
00704 return PAP_AUTH_FILE".old";
00705 break;
00706 case CHAP|Original:
00707 return CHAP_AUTH_FILE;
00708 break;
00709 case CHAP|New:
00710 return CHAP_AUTH_FILE".new";
00711 break;
00712 case CHAP|Old:
00713 return CHAP_AUTH_FILE".old";
00714 break;
00715 default:
00716 return 0L;
00717 }
00718 }
00719
00720
00721 bool Modem::createAuthFile(Auth method, const char *username, const char *password) {
00722 const char *authfile, *oldName, *newName;
00723 char line[100];
00724 char regexp[2*MaxStrLen+30];
00725 regex_t preg;
00726
00727 if(!(authfile = authFile(method)))
00728 return false;
00729
00730 if(!(newName = authFile(method, New)))
00731 return false;
00732
00733
00734
00735 snprintf(regexp, sizeof(regexp), "^[ \t]*%s[ \t]\\|^[ \t]*[\"\']%s[\"\']",
00736 username,username);
00737 MY_ASSERT(regcomp(&preg, regexp, 0) == 0);
00738
00739
00740 int old_umask = umask(0077);
00741 FILE *fout = fopen(newName, "w");
00742 if(fout) {
00743
00744 FILE *fin = fopen(authfile, "r");
00745 if(fin) {
00746 while(fgets(line, sizeof(line), fin)) {
00747 if(regexec(&preg, line, 0, 0L, 0) == 0)
00748 continue;
00749 fputs(line, fout);
00750 }
00751 fclose(fin);
00752 }
00753
00754
00755 fprintf(fout, "\"%s\"\t*\t\"%s\"\n", username, password);
00756 fclose(fout);
00757 }
00758
00759
00760 umask(old_umask);
00761
00762
00763 regfree(&preg);
00764
00765 if(!(oldName = authFile(method, Old)))
00766 return false;
00767
00768
00769 unlink(oldName);
00770
00771 rename(authfile, oldName);
00772 rename(newName, authfile);
00773
00774 return true;
00775 }
00776
00777
00778 bool Modem::removeAuthFile(Auth method) {
00779 const char *authfile, *oldName;
00780
00781 if(!(authfile = authFile(method)))
00782 return false;
00783 if(!(oldName = authFile(method, Old)))
00784 return false;
00785
00786 if(access(oldName, F_OK) == 0) {
00787 unlink(authfile);
00788 return (rename(oldName, authfile) == 0);
00789 } else
00790 return false;
00791 }
00792
00793
00794 bool Modem::setSecret(int method, const char* name, const char* password)
00795 {
00796
00797 Auth auth;
00798 if(method == AUTH_PAPCHAP)
00799 return setSecret(AUTH_PAP, name, password) &&
00800 setSecret(AUTH_CHAP, name, password);
00801
00802 switch(method) {
00803 case AUTH_PAP:
00804 auth = Modem::PAP;
00805 break;
00806 case AUTH_CHAP:
00807 auth = Modem::CHAP;
00808 break;
00809 default:
00810 return false;
00811 }
00812
00813 return createAuthFile(auth, name, password);
00814
00815 }
00816
00817 bool Modem::removeSecret(int method)
00818 {
00819 Auth auth;
00820
00821 switch(method) {
00822 case AUTH_PAP:
00823 auth = Modem::PAP;
00824 break;
00825 case AUTH_CHAP:
00826 auth = Modem::CHAP;
00827 break;
00828 default:
00829 return false;
00830 }
00831 return removeAuthFile( auth );
00832 }
00833
00834 int checkForInterface()
00835 {
00836
00837
00838
00839 #if (defined(HAVE_NET_IF_PPP_H) || defined(HAVE_LINUX_IF_PPP_H)) && !defined(__svr4__)
00840 int s, ok;
00841 struct ifreq ifr;
00842
00843
00844 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
00845 return 1;
00846
00847 strlcpy(ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
00848 ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
00849 close(s);
00850
00851 if (ok == -1) {
00852
00853
00854
00855 #ifdef __FreeBSD__
00856
00857 if (kldload("if_ppp") == -1) {
00858 return -1;
00859 }
00860 return 0;
00861 #else
00862 return -1;
00863 #endif
00864 }
00865 return 0;
00866 #else
00867
00868 struct stat buf;
00869
00870 memset(&buf, 0, sizeof(buf));
00871 return stat("/dev/ppp", &buf);
00872 #endif
00873 }
00874
00875 bool Modem::execpppd(const char *arguments) {
00876 char buf[MAX_CMDLEN];
00877 char *args[MaxArgs];
00878 pid_t pgrpid;
00879
00880 if(modemfd<0)
00881 return false;
00882
00883 _pppdExitStatus = -1;
00884
00885 (void)::pipe( m_pppdLOG );
00886
00887 switch(pppdPid = fork())
00888 {
00889 case -1:
00890 fprintf(stderr,"In parent: fork() failed\n");
00891 ::close( m_pppdLOG[0] );
00892 ::close( m_pppdLOG[1] );
00893 return false;
00894 break;
00895
00896 case 0:
00897
00898
00899 strlcpy(buf, arguments);
00900 parseargs(buf, args);
00901
00902
00903 pgrpid = setsid();
00904 #ifdef TIOCSCTTY
00905 if(ioctl(modemfd, TIOCSCTTY, 0)<0)
00906 fprintf(stderr, "ioctl() failed.\n");
00907 #elif defined (TIOCSPGRP)
00908 if(ioctl(modemfd, TIOCSPGRP, &pgrpid)<0)
00909 fprintf(stderr, "ioctl() failed.\n");
00910 #endif
00911 if(tcsetpgrp(modemfd, pgrpid)<0)
00912 fprintf(stderr, "tcsetpgrp() failed.\n");
00913
00914 ::close( m_pppdLOG[0] );
00915 ::setenv( "LANG", "C", 1 );
00916 dup2(m_pppdLOG[1], 11 );
00917 dup2(modemfd, 0);
00918 dup2(modemfd, 1);
00919
00920
00921 switch (checkForInterface()) {
00922 case 1:
00923 fprintf(stderr, "Cannot determine if kernel supports ppp.\n");
00924 break;
00925 case -1:
00926 fprintf(stderr, "Kernel does not support ppp, oops.\n");
00927 break;
00928 case 0:
00929 fprintf(stderr, "Kernel supports ppp alright.\n");
00930 break;
00931 }
00932
00933 execve(pppdPath(), args, 0L);
00934 _exit(0);
00935 break;
00936
00937 default:
00938 odebug << "In parent: pppd pid " << pppdPid << "\n" << oendl;
00939 close(modemfd);
00940
00941 ::close( m_pppdLOG[1] );
00942
00943 int flag = ::fcntl( m_pppdLOG[0], F_GETFL );
00944
00945 if ( !(flag & O_NONBLOCK) ) {
00946 odebug << "Setting nonblocking io" << oendl;
00947 flag |= O_NONBLOCK;
00948 ::fcntl(m_pppdLOG[0], F_SETFL, flag );
00949 }
00950
00951 delete m_modemDebug;
00952 m_modemDebug = new QSocketNotifier(m_pppdLOG[0], QSocketNotifier::Read, this );
00953 connect(m_modemDebug, SIGNAL(activated(int) ),
00954 this, SLOT(slotModemDebug(int) ) );
00955
00956 modemfd = -1;
00957 m_pppdDev = QString::fromLatin1("ppp0");
00958 return true;
00959 break;
00960 }
00961 }
00962
00963
00964 bool Modem::killpppd() {
00965 odebug << "In killpppd and pid is " << pppdPid << "" << oendl;
00966 if(pppdPid > 0) {
00967 delete m_modemDebug;
00968 m_modemDebug = 0;
00969 odebug << "In killpppd(): Sending SIGTERM to " << pppdPid << "\n" << oendl;
00970 if(kill(pppdPid, SIGTERM) < 0) {
00971 odebug << "Error terminating " << pppdPid << ". Sending SIGKILL\n" << oendl;
00972 if(kill(pppdPid, SIGKILL) < 0) {
00973 odebug << "Error killing " << pppdPid << "\n" << oendl;
00974 return false;
00975 }
00976 }
00977 }
00978 return true;
00979 }
00980
00981
00982 void Modem::parseargs(char* buf, char** args) {
00983 int nargs = 0;
00984 int quotes;
00985
00986 while(nargs < MaxArgs-1 && *buf != '\0') {
00987
00988 quotes = 0;
00989
00990
00991
00992
00993 while ((*buf == ' ' ) || (*buf == '\t' ) || (*buf == '\n' ) )
00994 *buf++ = '\0';
00995
00996
00997 if (*buf == '"' || *buf == '\'') {
00998 quotes = *buf;
00999 *buf++ = '\0';
01000 }
01001
01002
01003 if(*buf != '\0') {
01004 *args++ = buf;
01005 nargs++;
01006 }
01007
01008 if (!quotes)
01009 while ((*buf != '\0') && (*buf != '\n') &&
01010 (*buf != '\t') && (*buf != ' '))
01011 buf++;
01012 else {
01013 while ((*buf != '\0') && (*buf != quotes))
01014 buf++;
01015 *buf++ = '\0';
01016 }
01017 }
01018
01019 *args = 0L;
01020 }
01021
01022 bool Modem::execPPPDaemon(const QString & arguments)
01023 {
01024 if(execpppd(arguments)) {
01025 _pppdata->setpppdRunning(true);
01026 return true;
01027 } else
01028 return false;
01029 }
01030
01031 void Modem::killPPPDaemon()
01032 {
01033 _pppdata->setpppdRunning(false);
01034 killpppd();
01035 }
01036
01037 int Modem::pppdExitStatus()
01038 {
01039 return _pppdExitStatus;
01040 }
01041
01042 int Modem::openResolv(int flags)
01043 {
01044 int fd;
01045 if ((fd = open(_PATH_RESCONF, flags)) == -1) {
01046 odebug << "error opening resolv.conf!" << oendl;
01047 fd = open(DEVNULL, O_RDONLY);
01048 }
01049 return fd;
01050 }
01051
01052 bool Modem::setHostname(const QString & name)
01053 {
01054 return sethostname(name, name.length()) == 0;
01055 }
01056
01057 QString Modem::pppDevice()const {
01058 return m_pppdDev;
01059 }
01060 void Modem::setPPPDevice( const QString& dev ) {
01061 m_pppdDev = dev;
01062 }
01063 pid_t Modem::pppPID()const {
01064 return pppdPid;
01065 }
01066 void Modem::setPPPDPid( pid_t pid ) {
01067 odebug << "Modem setting pid" << oendl;
01068 _pppdExitStatus = -1;
01069 pppdPid = pid;
01070 modemfd = -1;
01071 }
01072 void Modem::slotModemDebug(int fd) {
01073 char buf[2049];
01074 int len;
01075
01076
01077
01078
01079 if((len = ::read(fd, buf, 2048)) > 0) {
01080 buf[len+1] = '\0';
01081 char *found;
01082 if ( (found = ::strstr(buf, "Using interface ") ) ) {
01083 found += 16;
01084 m_pppdDev = QString::fromLatin1(found, 5 );
01085 m_pppdDev = m_pppdDev.simplifyWhiteSpace();
01086 }
01087 }
01088 }