2 * kPPP: A pppd front end for the KDE project
5 * Copyright (C) 1997 Bernd Johannes Wuebben
6 * wuebben@math.cornell.edu
7 * Copyright (C) 1998-2001 Harri Porten <porten@kde.org>
10 * Copyright (C) 1997 Jay Painter
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Library General Public
14 * License as published by the Free Software Foundation; either
15 * version 2 of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Library General Public License for more details.
22 * You should have received a copy of the GNU Library General Public
23 * License along with this program; if not, write to the Free
24 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
27 #include <config-kppp.h>
33 #include <QTimerEvent>
34 #include <QVBoxLayout>
36 #include <QHBoxLayout>
38 #include <QCloseEvent>
40 #include <kdefakes.h> // gethostname
43 #include <kmessagebox.h>
44 #include <kpushbutton.h>
45 #include <kapplication.h>
52 #include <sys/types.h>
53 #include <sys/socket.h>
54 #include <arpa/inet.h>
55 #include <netinet/in.h>
56 #include <sys/ioctl.h>
60 #define __xnet_connect connect
65 #ifdef HAVE_SYS_PARAM_H
66 #include <sys/param.h>
78 #include "kpppconfig.h"
81 #include "requester.h"
83 #include "kpppinterface.h"
85 extern KPPPWidget
*p_kppp
;
88 bool modified_hostname
;
91 ConnectWidget::ConnectWidget(QWidget
*parent
, const char *name
, PPPStats
*st
)
93 // initialize some important variables
113 modified_hostname
= false;
115 QVBoxLayout
*tl
= new QVBoxLayout(this);
118 QString tit
= i18n("Connecting to: ");
121 QHBoxLayout
*l0
= new QHBoxLayout();
122 l0
->setSpacing( 10 );
125 messg
= new QLabel( this );
126 messg
->setObjectName( "messg" );
127 messg
->setFrameStyle(QFrame::Panel
|QFrame::Sunken
);
128 messg
->setAlignment(Qt::AlignCenter
);
129 messg
->setText(i18n("Unable to create modem lock file."));
130 messg
->setMinimumHeight(messg
->sizeHint().height() + 5);
131 int messw
= (messg
->sizeHint().width() * 12) / 10;
132 messw
= qMax(messw
,280);
133 messg
->setMinimumWidth(messw
);
134 messg
->setText(i18n("Looking for modem..."));
135 l0
->addWidget(messg
);
138 QHBoxLayout
*l1
= new QHBoxLayout();
139 l1
->setSpacing( 10 );
143 debug
= new QPushButton(i18n("&Log"), this);
144 debug
->setCheckable(true);
145 connect(debug
, SIGNAL(clicked()), SIGNAL(toggleDebugWindow()));
147 cancel
= new KPushButton(KStandardGuiItem::cancel(), this);
149 connect(cancel
, SIGNAL(clicked()), SLOT(cancelbutton()));
151 int maxw
= qMax(cancel
->sizeHint().width(),
152 debug
->sizeHint().width());
153 maxw
= qMax(maxw
,65);
154 debug
->setFixedWidth(maxw
);
155 cancel
->setFixedWidth(maxw
);
156 l1
->addWidget(debug
);
157 l1
->addWidget(cancel
);
160 setFixedSize(sizeHint());
162 pausetimer
= new QTimer(this);
163 connect(pausetimer
, SIGNAL(timeout()), SLOT(pause()));
165 qApp
->processEvents();
167 timeout_timer
= new QTimer(this);
168 connect(timeout_timer
, SIGNAL(timeout()), SLOT(script_timed_out()));
170 inittimer
= new QTimer(this);
171 connect(inittimer
, SIGNAL(timeout()), SLOT(init()));
173 if_timeout_timer
= new QTimer(this);
174 connect(if_timeout_timer
, SIGNAL(timeout()), SLOT(if_waiting_timed_out()));
176 connect(this,SIGNAL(if_waiting_signal()),this,SLOT(if_waiting_slot()));
178 prompt
= new PWEntry( this, "pw" );
179 if_timer
= new QTimer(this);
180 connect(if_timer
,SIGNAL(timeout()), SLOT(if_waiting_slot()));
184 ConnectWidget::~ConnectWidget() {
188 void ConnectWidget::disableButtons()
190 debug
->setEnabled(false);
191 cancel
->setEnabled(false);
194 void ConnectWidget::enableButtons()
196 debug
->setEnabled(true);
197 cancel
->setEnabled(true);
200 void ConnectWidget::preinit() {
201 // this is all just to keep the GUI nice and snappy ....
202 // you have to see to believe ...
203 messg
->setText(i18n("Looking for modem..."));
204 inittimer
->start(100);
207 void ConnectWidget::init() {
208 gpppdata
.setpppdError(0);
220 stats
->totalbytes
= 0;
223 p_kppp
->con_speed
= "";
225 p_kppp
->setQuitOnDisconnect (p_kppp
->quitOnDisconnect() || gpppdata
.quit_on_disconnect());
227 comlist
= &gpppdata
.scriptType();
228 arglist
= &gpppdata
.script();
230 QString tit
= i18n("Connecting to: %1", gpppdata
.accname());
233 qApp
->processEvents();
235 // signal other applications that we are about to get connected
236 emit
aboutToConnect();
237 // run the "before-connect" command
238 if (!gpppdata
.command_before_connect().isEmpty()) {
239 messg
->setText(i18n("Running pre-startup command..."));
240 emit
debugMessage(i18n("Running pre-startup command..."));
242 qApp
->processEvents();
243 QApplication::flush();
244 pid_t id
= execute_command(gpppdata
.command_before_connect());
248 qApp
->processEvents();
249 i
= waitpid(id
, &status
, WNOHANG
);
251 } while (i
== 0 && errno
== 0);
254 int lock
= Modem::modem
->lockdevice();
257 messg
->setText(i18n("Modem device is locked."));
258 vmain
= 20; // wait until cancel is pressed
263 messg
->setText(i18n("Unable to create modem lock file."));
264 vmain
= 20; // wait until cancel is pressed
268 if(Modem::modem
->opentty()) {
269 messg
->setText(Modem::modem
->modemMessage());
270 qApp
->processEvents();
271 if(Modem::modem
->hangup()) {
273 qApp
->processEvents();
277 Modem::modem
->stop();
278 Modem::modem
->notify(this, SLOT(readChar(unsigned char)));
280 // if we are stuck anywhere we will time out
281 timeout_timer
->start(gpppdata
.modemTimeout()*1000);
283 // this timer will run the script etc.
284 main_timer_ID
= startTimer(10);
290 // initialization failed
291 messg
->setText(Modem::modem
->modemMessage());
292 vmain
= 20; // wait until cancel is pressed
293 Modem::modem
->unlockdevice();
297 void ConnectWidget::timerEvent(QTimerEvent
*) {
298 if (semaphore
|| pausing
)
302 #ifdef DEBUG_WO_DIALING
307 assert(PPPData::NumInitStrings
> 0);
308 // first init string ?
310 messg
->setText(i18n("Initializing modem..."));
311 emit
debugMessage(i18n("Initializing modem..."));
315 QString initStr
= gpppdata
.modemInitStr(substate
);
316 if (!initStr
.isEmpty()) {
317 timeout_timer
->stop();
319 // send a carriage return and then wait a bit so that the modem will
320 // let us issue commands.
321 if(gpppdata
.modemPreInitDelay() > 0) {
322 usleep(gpppdata
.modemPreInitDelay() * 5000);
324 usleep(gpppdata
.modemPreInitDelay() * 5000);
326 setExpect(gpppdata
.modemInitResp());
328 timeout_timer
->start(gpppdata
.modemTimeout()*1000);
329 usleep(gpppdata
.modemInitDelay() * 10000); // 0.01 - 3.0 sec
335 * FIXME after 3.0: Make it possible to disable ATS11 since it
336 * seems to be incompatible with some ISDN adapters (e.g. DataBox
337 * Speed Dragon). Even better would be to detect this when doing
340 if (MODEM_TONEDURATION
!= gpppdata
.modemToneDuration())
350 QString sToneDuration
= "ATS11=" + QString::number(gpppdata
.modemToneDuration());
351 QString msg
= i18n("Setting ") + sToneDuration
;
353 emit
debugMessage(msg
);
354 setExpect(gpppdata
.modemInitResp());
355 writeline(sToneDuration
);
363 // done with all init strings ?
364 if(substate
< PPPData::NumInitStrings
) {
369 // skip setting the volume if command is empty
370 if(gpppdata
.volumeInitString().isEmpty()) {
374 messg
->setText(i18n("Setting speaker volume..."));
375 emit
debugMessage(i18n("Setting speaker volume..."));
377 setExpect(gpppdata
.modemInitResp());
379 vol
+= gpppdata
.volumeInitString();
381 usleep(gpppdata
.modemInitDelay() * 10000); // 0.01 - 3.0 sec
389 if(!gpppdata
.waitForDialTone() || gpppdata
.waitCallback()) {
390 QString msg
= i18n("Turning off dial tone waiting...");
392 emit
debugMessage(msg
);
393 setExpect(gpppdata
.modemInitResp());
394 writeline(gpppdata
.modemNoDialToneDetectionStr());
401 // dial the number and wait to connect
405 timeout_timer
->stop();
406 timeout_timer
->start(gpppdata
.modemTimeout()*1000);
408 if(gpppdata
.waitCallback()) {
409 QString msg
= i18n("Waiting for callback...");
411 emit
debugMessage(msg
);
412 setExpect(gpppdata
.modemRingResp());
417 QStringList
&plist
= gpppdata
.phonenumbers();
418 QString bmarg
= gpppdata
.dialPrefix();
419 bmarg
+= plist
.at(dialnumber
);
420 QString bm
= i18n("Dialing %1", bmarg
);
422 emit
debugMessage(bm
);
424 QString pn
= gpppdata
.modemDialStr();
425 pn
+= gpppdata
.dialPrefix();
426 pn
+= plist
.at(dialnumber
);
427 if(++dialnumber
>= plist
.count())
431 setExpect(gpppdata
.modemConnectResp());
437 // wait for connect, but redial if BUSY or wait for user cancel
438 // if NO CARRIER or NO DIALTONE
441 myreadbuffer
= gpppdata
.modemConnectResp();
447 if(readbuffer
.contains(gpppdata
.modemBusyResp())) {
448 timeout_timer
->stop();
449 timeout_timer
->start(gpppdata
.modemTimeout()*1000);
451 messg
->setText(i18n("Line busy. Hanging up..."));
452 emit
debugPutChar('\n');
453 Modem::modem
->hangup();
455 if(gpppdata
.busyWait() > 0) {
456 QString bm
= i18n("Line busy. Waiting: %1 seconds", gpppdata
.busyWait());
458 emit
debugMessage(bm
);
462 pausetimer
->setSingleShot(true);
463 pausetimer
->start(gpppdata
.busyWait()*1000);
464 timeout_timer
->stop();
467 Modem::modem
->setDataMode(false);
470 gpppdata
.setWaitCallback(false);
474 if(readbuffer
.contains(gpppdata
.modemNoDialtoneResp())) {
475 timeout_timer
->stop();
477 messg
->setText(i18n("No Dial Tone"));
479 Modem::modem
->unlockdevice();
480 gpppdata
.setWaitCallback(false);
484 if(readbuffer
.contains(gpppdata
.modemNoCarrierResp())) {
485 if (gpppdata
.get_redial_on_nocarrier()) {
486 timeout_timer
->stop();
487 timeout_timer
->start(gpppdata
.modemTimeout()*1000);
489 if(gpppdata
.busyWait() > 0) {
490 QString bm
= i18n("No carrier. Waiting: %1 seconds", gpppdata
.busyWait());
492 emit
debugMessage(bm
);
496 pausetimer
->setSingleShot(true);
497 pausetimer
->start(gpppdata
.busyWait()*1000);
498 timeout_timer
->stop();
501 Modem::modem
->setDataMode(false);
506 timeout_timer
->stop();
508 messg
->setText(i18n("No Carrier"));
510 Modem::modem
->unlockdevice();
511 gpppdata
.setWaitCallback(false);
516 if(readbuffer
.contains(gpppdata
.modemDLPResp())) {
517 timeout_timer
->stop();
519 messg
->setText(i18n("Digital Line Protection Detected."));
521 Modem::modem
->unlockdevice();
522 KMessageBox::error(this,
523 i18n("A Digital Line Protection (DLP) error response "
524 "has been detected.\n"
525 "Please disconnect the phone line.\n\n"
526 "Do NOT connect this modem to a digital phone "
527 "line or the modem could get permanently "
529 gpppdata
.setWaitCallback(false);
536 // wait for newline after CONNECT response (so we get the speed)
539 Modem::modem
->setDataMode(true); // modem will no longer respond to AT commands
541 emit
startAccounting();
542 p_kppp
->con_win
->startClock();
545 scriptTimeout
=gpppdata
.modemTimeout()*1000;
550 // send answer on callback phase
553 writeline(gpppdata
.modemAnswerStr());
554 setExpect(gpppdata
.modemConnectResp());
560 // execute the script
562 if(!expecting
&& !pausing
&& !scanning
) {
564 timeout_timer
->stop();
565 timeout_timer
->start(scriptTimeout
);
567 if(scriptindex
< comlist
->count()) {
568 scriptCommand
= (comlist
->at(scriptindex
));
569 scriptArgument
= (arglist
->at(scriptindex
));
571 kDebug(5002) << "End of script";
576 if (scriptCommand
== "Scan") {
577 QString bm
= i18n("Scanning %1", scriptArgument
);
579 emit
debugMessage(bm
);
581 setScan(scriptArgument
);
586 if (scriptCommand
== "Save") {
587 QString bm
= i18n("Saving %1", scriptArgument
);
589 emit
debugMessage(bm
);
591 if (scriptArgument
.toLower() == "password") {
592 gpppdata
.setPassword(scanvar
);
593 p_kppp
->setPW_Edit(scanvar
);
594 if(gpppdata
.storePassword())
595 gpppdata
.setStoredPassword(scanvar
);
604 if (scriptCommand
== "Send" || scriptCommand
== "SendNoEcho") {
605 // replace %USERNAME% and %PASSWORD%
606 QString arg
= scriptArgument
;
607 QRegExp
re1("%USERNAME%");
608 QRegExp
re2("%PASSWORD%");
609 arg
= arg
.replace(re1
, gpppdata
.storedUsername());
610 arg
= arg
.replace(re2
, gpppdata
.storedPassword());
613 if (scriptCommand
== "Send")
614 scriptarg
= scriptArgument
;
616 for(int i
= 0; i
< scriptArgument
.length(); i
++)
619 QString bm
= i18n("Sending %1", scriptarg
);
622 emit
debugMessage(bm
);
624 writeline(scriptArgument
);
629 if (scriptCommand
== "Expect") {
630 QString bm
= i18n("Expecting %1", scriptArgument
);
632 emit
debugMessage(bm
);
634 // The incrementing of the scriptindex MUST be before the
635 // call to setExpect otherwise the expect will miss a string that is
636 // already in the buffer.
638 setExpect(scriptArgument
);
643 if (scriptCommand
== "Pause") {
644 QString bm
= i18n("Pause %1 seconds", scriptArgument
);
646 emit
debugMessage(bm
);
650 pausetimer
->setSingleShot(true);
651 pausetimer
->start(scriptArgument
.toInt()*1000);
652 timeout_timer
->stop();
658 if (scriptCommand
== "Timeout") {
660 timeout_timer
->stop();
662 QString bm
= i18n("Timeout %1 seconds", scriptArgument
);
664 emit
debugMessage(bm
);
666 scriptTimeout
=scriptArgument
.toInt()*1000;
667 timeout_timer
->start(scriptTimeout
);
673 if (scriptCommand
== "Hangup") {
674 messg
->setText(i18n("Hangup"));
675 emit
debugMessage(i18n("Hangup"));
677 writeline(gpppdata
.modemHangupStr());
678 setExpect(gpppdata
.modemHangupResp());
684 if (scriptCommand
== "Answer") {
686 timeout_timer
->stop();
688 messg
->setText(i18n("Answer"));
689 emit
debugMessage(i18n("Answer"));
691 setExpect(gpppdata
.modemRingResp());
696 if (scriptCommand
== "ID") {
697 QString bm
= i18n("ID %1", scriptArgument
);
699 emit
debugMessage(bm
);
701 QString idstring
= gpppdata
.storedUsername();
703 if(!idstring
.isEmpty() && firstrunID
) {
704 // the user entered an Id on the main kppp dialog
710 // the user didn't enter and Id on the main kppp dialog
711 // let's query for an ID
712 /* if not around yet, then post window... */
713 if (prompt
->Consumed()) {
714 if (!(prompt
->isVisible())) {
715 prompt
->setPrompt(scriptArgument
);
716 prompt
->setEchoModeNormal();
720 /* if prompt withdrawn ... then, */
721 if(!(prompt
->isVisible())) {
722 writeline(prompt
->text());
723 prompt
->setConsumed();
727 /* replace timeout value */
732 if (scriptCommand
== "Password") {
733 QString bm
= i18n("Password %1", scriptArgument
);
735 emit
debugMessage(bm
);
737 QString pwstring
= gpppdata
.password();
739 if(!pwstring
.isEmpty() && firstrunPW
) {
740 // the user entered a password on the main kppp dialog
746 // the user didn't enter a password on the main kppp dialog
747 // let's query for a password
748 /* if not around yet, then post window... */
749 if (prompt
->Consumed()) {
750 if (!(prompt
->isVisible())) {
751 prompt
->setPrompt(scriptArgument
);
752 prompt
->setEchoModePassword();
756 /* if prompt withdrawn ... then, */
757 if(!(prompt
->isVisible())) {
758 p_kppp
->setPW_Edit(prompt
->text());
759 writeline(prompt
->text());
760 prompt
->setConsumed();
764 /* replace timeout value */
769 if (scriptCommand
== "Prompt") {
770 // if the scriptindex (aka the prompt text) includes a ## marker
771 // this marker should get substituted with the contents of our stored
772 // variable (from the subsequent scan).
774 QString ts
= scriptArgument
;
775 int vstart
= ts
.indexOf( "##" );
777 ts
.remove( vstart
, 2 );
778 ts
.insert( vstart
, scanvar
);
781 QString bm
= i18n("Prompting %1", ts
);
783 emit
debugMessage(bm
);
785 /* if not around yet, then post window... */
786 if (prompt
->Consumed()) {
787 if (!(prompt
->isVisible())) {
788 prompt
->setPrompt( ts
);
789 prompt
->setEchoModeNormal();
793 /* if prompt withdrawn ... then, */
794 if (!(prompt
->isVisible())) {
795 writeline(prompt
->text());
796 prompt
->setConsumed();
800 /* replace timeout value */
804 if (scriptCommand
== "PWPrompt") {
805 QString bm
= i18n("PW Prompt %1", scriptArgument
);
807 emit
debugMessage(bm
);
809 /* if not around yet, then post window... */
810 if (prompt
->Consumed()) {
811 if (!(prompt
->isVisible())) {
812 prompt
->setPrompt(scriptArgument
);
813 prompt
->setEchoModePassword();
817 /* if prompt withdrawn ... then, */
818 if (!(prompt
->isVisible())) {
819 writeline(prompt
->text());
820 prompt
->setConsumed();
824 /* replace timeout value */
828 if (scriptCommand
== "LoopStart") {
830 QString bm
= i18n("Loop Start %1", scriptArgument
);
832 // The incrementing of the scriptindex MUST be before the
833 // call to setExpect otherwise the expect will miss a string that is
834 // already in the buffer.
837 if ( loopnest
> (MAXLOOPNEST
-2) ) {
838 bm
+= i18n("ERROR: Nested too deep, ignored.");
841 KMessageBox::error(0, i18n("Loops nested too deeply."));
843 setExpect(scriptArgument
);
844 loopstartindex
[loopnest
] = scriptindex
;
845 loopstr
[loopnest
] = scriptArgument
;
850 emit
debugMessage(bm
);
854 if (scriptCommand
== "LoopEnd") {
855 QString bm
= i18n("Loop End %1", scriptArgument
);
856 if ( loopnest
<= 0 ) {
857 bm
= i18n("LoopEnd without matching Start. Line: %1", bm
);
860 KMessageBox::error(0, bm
);
863 // NB! The incrementing of the scriptindex MUST be before the
864 // call to setExpect otherwise the expect will miss a string
865 // that is already in the buffer.
867 setExpect(scriptArgument
);
872 emit
debugMessage(bm
);
878 // this is a subroutine for the "Answer" script option
882 writeline(gpppdata
.modemAnswerStr());
883 setExpect(gpppdata
.modemAnswerResp());
892 if (termwindow
->isVisible())
894 if (termwindow
->pressedContinue())
905 timeout_timer
->stop();
906 if_timeout_timer
->stop(); // better be sure.
908 // stop reading of data
909 Modem::modem
->stop();
911 if(gpppdata
.authMethod() == AUTH_TERMINAL
) {
917 termwindow
= new LoginTerm(0L, 0L);
925 // Close the tty. This prevents the QTimer::singleShot() in
926 // Modem::readtty() from re-enabling the socket notifier.
927 // The port is still held open by the helper process.
928 Modem::modem
->closetty();
930 killTimer( main_timer_ID
);
932 if_timeout_timer
->start(gpppdata
.pppdTimeout()*1000);
933 kDebug(5002) << "started if timeout timer with " << gpppdata
.pppdTimeout()*1000;
935 // find out PPP interface and notify the stats module
936 stats
->setUnit(pppInterfaceNumber());
942 emit
debugMessage(i18n("Starting pppd..."));
943 kDebug(5002) << "execppp() returned with return-code " << result
;
946 if(!gpppdata
.autoDNS())
949 // O.K we are done here, let's change over to the if_waiting loop
950 // where we wait for the ppp if (interface) to come up.
952 emit
if_waiting_signal();
955 // starting pppd wasn't successful. Error messages were
956 // handled by execppp();
957 if_timeout_timer
->stop();
961 p_kppp
->quit_b
->setFocus();
963 qApp
->processEvents();
964 Modem::modem
->hangup();
965 emit
stopAccounting();
966 p_kppp
->con_win
->stopClock();
967 Modem::modem
->closetty();
968 Modem::modem
->unlockdevice();
976 // this is a "wait until cancel" entry
979 gpppdata
.setWaitCallback(false);
984 void ConnectWidget::set_con_speed_string() {
985 // Here we are trying to determine the speed at which we are connected.
986 // Usually the modem responds after connect with something like
987 // CONNECT 115200, so all we need to do is find the number after CONNECT
988 // or whatever the modemConnectResp() is.
989 p_kppp
->con_speed
= Modem::modem
->parseModemSpeed(myreadbuffer
);
994 void ConnectWidget::readChar(unsigned char c
) {
1001 // While in scanning mode store each char to the scan buffer
1002 // for use in the prompt command
1006 // add to debug window
1007 emit
debugPutChar(c
);
1013 void ConnectWidget::checkBuffers() {
1014 // Let's check if we are finished with scanning:
1015 // The scanstring have to be in the buffer and the latest character
1016 // was a carriage return or an linefeed (depending on modem setup)
1017 if( scanning
&& scanbuffer
.contains(scanstr
) &&
1018 ( scanbuffer
.right(1) == "\n" || scanbuffer
.right(1) == "\r") ) {
1021 int vstart
= scanbuffer
.indexOf( scanstr
) + scanstr
.length();
1022 scanvar
= scanbuffer
.mid( vstart
, scanbuffer
.length() - vstart
);
1023 scanvar
= scanvar
.trimmed();
1025 // Show the Variabel content in the debug window
1026 QString sv
= i18n("Scan Var: %1", scanvar
);
1027 emit
debugMessage(sv
);
1031 if(readbuffer
.contains(expectstr
)) {
1033 // keep everything after the expected string
1034 readbuffer
.remove(0, readbuffer
.indexOf(expectstr
) + expectstr
.length());
1036 QString ts
= i18n("Found: %1", expectstr
);
1037 emit
debugMessage(ts
);
1044 if (loopend
&& readbuffer
.contains(loopstr
[loopnest
])) {
1047 QString ts
= i18n("Looping: %1", loopstr
[loopnest
]);
1048 emit
debugMessage(ts
);
1049 scriptindex
= loopstartindex
[loopnest
];
1053 // notify event loop if expected string was found
1055 timerEvent((QTimerEvent
*) 0);
1061 void ConnectWidget::pause() {
1067 void ConnectWidget::cancelbutton() {
1068 gpppdata
.setWaitCallback(false);
1069 Modem::modem
->stop();
1070 killTimer(main_timer_ID
);
1071 timeout_timer
->stop();
1073 if_timeout_timer
->stop();
1081 messg
->setText(i18n("One moment please..."));
1084 Requester::rq
->removeSecret(AUTH_PAP
);
1085 Requester::rq
->removeSecret(AUTH_CHAP
);
1088 qApp
->processEvents();
1090 Requester::rq
->killPPPDaemon();
1091 Modem::modem
->hangup();
1095 p_kppp
->quit_b
->setFocus();
1097 emit
stopAccounting(); // just to be sure
1098 p_kppp
->con_win
->stopClock();
1099 Modem::modem
->closetty();
1100 Modem::modem
->unlockdevice();
1102 //abort prompt window...
1103 if (prompt
->isVisible()) {
1106 prompt
->setConsumed();
1108 if(p_kppp
->quitOnDisconnect())
1113 void ConnectWidget::script_timed_out() {
1114 if(vmain
== 20) { // we are in the 'wait for the user to cancel' state
1115 timeout_timer
->stop();
1116 emit
stopAccounting();
1117 p_kppp
->con_win
->stopClock();
1121 if (prompt
->isVisible())
1124 prompt
->setConsumed();
1125 messg
->setText(i18n("Script timed out."));
1126 Modem::modem
->hangup();
1127 emit
stopAccounting();
1128 p_kppp
->con_win
->stopClock();
1130 vmain
= 0; // let's try again.
1135 void ConnectWidget::setScan(const QString
&n
) {
1140 QString ts
= i18n("Scanning: %1", n
);
1141 emit
debugMessage(ts
);
1145 void ConnectWidget::setExpect(const QString
&n
) {
1149 QString ts
= i18n("Expecting: %1", n
);
1150 ts
.replace(QRegExp("\n"), "<LF>");
1151 emit
debugMessage(ts
);
1153 // check if the expected string is in the read buffer already.
1158 void ConnectWidget::if_waiting_timed_out() {
1160 if_timeout_timer
->stop();
1161 kDebug(5002) << "if_waiting_timed_out()";
1163 gpppdata
.setpppdError(E_IF_TIMEOUT
);
1165 // let's kill the stuck pppd
1166 Requester::rq
->killPPPDaemon();
1168 emit
stopAccounting();
1169 p_kppp
->con_win
->stopClock();
1172 // killing ppp will generate a SIGCHLD which will be caught in pppdie()
1173 // in main.cpp what happens next will depend on the boolean
1174 // reconnect_on_disconnect which is set in ConnectWidget::init();
1177 void ConnectWidget::pppdDied()
1180 if_timeout_timer
->stop();
1183 void ConnectWidget::if_waiting_slot() {
1184 messg
->setText(i18n("Logging on to network..."));
1186 if(!stats
->ifIsUp()) {
1188 if(gpppdata
.pppdError() != 0) {
1189 // we are here if pppd died immediately after starting it.
1191 // error message handled in main.cpp: sigPPPDDied()
1195 if_timer
->setSingleShot(true);
1196 if_timer
->start(100);
1200 // O.K the ppp interface is up and running
1201 // give it a few time to come up completely (0.2 seconds)
1202 if_timeout_timer
->stop();
1206 if(gpppdata
.autoDNS())
1209 // Close the debugging window. If we are connected, we
1210 // are not really interested in debug output
1211 emit
closeDebugWindow();
1212 p_kppp
->statdlg
->take_stats(); // start taking ppp statistics
1215 // signal other applications that we are connected now
1218 if(!gpppdata
.command_on_connect().isEmpty()) {
1219 messg
->setText(i18n("Running startup command..."));
1221 // make sure that we don't get any async errors
1223 execute_command(gpppdata
.command_on_connect());
1224 messg
->setText(i18n("Done"));
1227 // remove the authentication file
1228 Requester::rq
->removeSecret(AUTH_PAP
);
1229 Requester::rq
->removeSecret(AUTH_CHAP
);
1231 emit
debugMessage(i18n("Done"));
1232 set_con_speed_string();
1234 p_kppp
->con_win
->setConnectionSpeed(p_kppp
->con_speed
);
1238 // prepare the con_win so as to have the right size for
1239 // accounting / non-accounting mode
1240 if(p_kppp
->acct
!= 0)
1241 p_kppp
->con_win
->accounting(p_kppp
->acct
->running());
1243 p_kppp
->con_win
->accounting(false);
1245 if (gpppdata
.get_dock_into_panel()) {
1246 DockWidget::dock_widget
->show();
1247 DockWidget::dock_widget
->take_stats();
1251 p_kppp
->con_win
->show();
1253 if(gpppdata
.get_iconify_on_connect()) {
1254 p_kppp
->con_win
->showMinimized();
1258 Modem::modem
->closetty();
1262 bool ConnectWidget::execppp() {
1267 // as of version 2.3.6 pppd falls back to the real user rights when
1268 // opening a device given in a command line. To avoid permission conflicts
1269 // we'll simply leave this argument away. pppd will then use the default tty
1270 // which is the serial port we connected stdin/stdout to in opener.cpp.
1272 // command += gpppdata.modemDevice();
1274 command
+= ' ' + gpppdata
.speed();
1276 command
+= " -detach";
1278 if(gpppdata
.ipaddr() != "0.0.0.0" ||
1279 gpppdata
.gateway() != "0.0.0.0") {
1280 if(gpppdata
.ipaddr() != "0.0.0.0") {
1282 command
+= gpppdata
.ipaddr();
1290 if(gpppdata
.gateway() != "0.0.0.0")
1291 command
+= gpppdata
.gateway();
1294 if(gpppdata
.subnetmask() != "0.0.0.0")
1295 command
+= " netmask " + gpppdata
.subnetmask();
1297 // the english/i18n mix below is ugly but we want to keep working
1298 // after someone changed the code to use i18n'ed config values
1299 QString flowCtrl
= gpppdata
.flowcontrol();
1300 if(flowCtrl
!= "None" && flowCtrl
!= i18n("None")) {
1301 if(flowCtrl
== "CRTSCTS" || flowCtrl
== "Hardware [CRTSCTS]" ||
1302 flowCtrl
== i18n("Hardware [CRTSCTS]"))
1303 command
+= " crtscts";
1305 command
+= " xonxoff";
1308 if(gpppdata
.defaultroute())
1309 command
+= " defaultroute";
1311 if(gpppdata
.autoDNS())
1312 command
+= " usepeerdns";
1314 QStringList
&arglist
= gpppdata
.pppdArgument();
1315 for ( QStringList::Iterator it
= arglist
.begin();
1316 it
!= arglist
.end();
1319 command
+= ' ' + *it
;
1322 // Callback settings
1323 if(gpppdata
.callbackType() && !gpppdata
.waitCallback()) {
1324 if(!gpppdata
.pppdVersionMin(2, 4, 2)) {
1325 command
+= " +callback";
1326 if(gpppdata
.callbackType() == CBTYPE_USER
)
1327 command
+= " callback " + gpppdata
.callbackPhone();
1329 command
+= " callback ";
1330 command
+= gpppdata
.callbackType() == CBTYPE_ADMIN
?
1331 QString("0") : gpppdata
.callbackPhone();
1334 gpppdata
.setWaitCallback(false);
1337 if(gpppdata
.authMethod() == AUTH_PAP
) {
1338 command
+= " -chap user ";
1339 command
= command
+ "\"" + gpppdata
.storedUsername() + "\"";
1343 if(gpppdata
.authMethod() == AUTH_CHAP
) {
1344 command
+= " -pap user ";
1345 command
= command
+ "\"" + gpppdata
.storedUsername() + "\"";
1348 // PAP/CHAP settings
1349 if(gpppdata
.authMethod() == AUTH_PAPCHAP
) {
1350 command
+= " user ";
1351 command
= command
+ "\"" + gpppdata
.storedUsername() + "\"";
1355 if(gpppdata
.getPPPDebug())
1356 command
+= " debug";
1358 if (command
.length() > MAX_CMDLEN
) {
1359 KMessageBox::error(this, i18n(
1360 "pppd command + command-line arguments exceed "
1361 "2024 characters in length."
1364 return false; // nonsensically long command which would bust my buffer buf.
1369 return Requester::rq
->execPPPDaemon(command
);
1373 void ConnectWidget::closeEvent( QCloseEvent
*e
) {
1375 emit
cancelbutton();
1379 void ConnectWidget::setMsg(const QString
&msg
) {
1380 messg
->setText(msg
);
1383 void ConnectWidget::writeline(const QString
&s
) {
1384 Modem::modem
->writeLine(s
.toLocal8Bit());
1387 // Set the hostname and domain from DNS Server
1388 void auto_hostname() {
1389 struct in_addr local_ip
;
1390 struct hostent
*hostname_entry
;
1391 QString new_hostname
;
1393 char tmp_str
[100]; // buffer overflow safe
1395 gethostname(tmp_str
, sizeof(tmp_str
));
1396 tmp_str
[sizeof(tmp_str
)-1]=0; // panic
1397 old_hostname
=tmp_str
; // copy to QString
1399 if (!p_kppp
->stats
->local_ip_address
.isEmpty() && gpppdata
.autoname()) {
1400 local_ip
.s_addr
=inet_addr(p_kppp
->stats
->local_ip_address
.toAscii());
1401 hostname_entry
=gethostbyaddr((const char *)&local_ip
,sizeof(in_addr
),AF_INET
);
1403 if (hostname_entry
!= 0L) {
1404 new_hostname
=hostname_entry
->h_name
;
1405 dot
=new_hostname
.indexOf('.');
1406 new_hostname
=new_hostname
.remove(dot
,new_hostname
.length()-dot
);
1407 Requester::rq
->setHostname(new_hostname
);
1408 modified_hostname
= true;
1410 new_hostname
=hostname_entry
->h_name
;
1411 new_hostname
.remove(0,dot
+1);
1413 add_domain(new_hostname
);
1419 // Replace the DNS domain entry in the /etc/resolv.conf file and
1420 // disable the nameserver entries if option is enabled
1421 void add_domain(const QString
&domain
) {
1425 QString resolv
[MAX_RESOLVCONF_LINES
];
1427 if (domain
.isEmpty())
1430 if((fd
= Requester::rq
->openResolv(O_RDONLY
)) >= 0) {
1433 while((read(fd
, &c
, 1) == 1) && (i
< MAX_RESOLVCONF_LINES
)) {
1442 if ((c
!= '\n') && (i
< MAX_RESOLVCONF_LINES
)) i
++;
1444 if((fd
= Requester::rq
->openResolv(O_WRONLY
|O_TRUNC
)) >= 0) {
1445 Q3CString tmp
= "domain " + domain
.toLocal8Bit() +
1446 " \t\t#kppp temp entry\n";
1447 write(fd
, tmp
.data(), tmp
.length());
1449 for(int j
=0; j
< i
; j
++) {
1450 if((resolv
[j
].contains("domain") ||
1451 ( resolv
[j
].contains("nameserver")
1452 && !resolv
[j
].contains("#kppp temp entry")
1453 && gpppdata
.exDNSDisabled()))
1454 && !resolv
[j
].contains("#entry disabled by kppp")) {
1455 Q3CString tmp
= "# " + resolv
[j
].toLocal8Bit() +
1456 " \t#entry disabled by kppp\n";
1457 write(fd
, tmp
, tmp
.length());
1460 Q3CString tmp
= resolv
[j
].toLocal8Bit() + '\n';
1461 write(fd
, tmp
, tmp
.length());
1470 // adds the DNS entries in the /etc/resolv.conf file
1475 if ((fd
= Requester::rq
->openResolv(O_WRONLY
|O_APPEND
)) >= 0) {
1476 QStringList
&dnslist
= gpppdata
.dns();
1477 for ( QStringList::Iterator it
= dnslist
.begin();
1478 it
!= dnslist
.end();
1481 Q3CString dns
= "nameserver " + (*it
).toLocal8Bit() +
1482 " \t#kppp temp entry\n";
1483 write(fd
, dns
.data(), dns
.length());
1487 add_domain(gpppdata
.domain());
1493 if((fd
= Requester::rq
->openResolv(O_WRONLY
|O_APPEND
)) >= 0) {
1494 if((fd2
= open("/etc/ppp/resolv.conf", O_RDONLY
)) >= 0) {
1497 while(i
++ < 100 && read(fd2
, &c
, 1) == 1) {
1499 write(fd
, "\t#kppp temp entry\n", 18);
1505 fprintf(stderr
, "failed to read from /etc/ppp/resolv.conf\n");
1508 add_domain(gpppdata
.domain());
1511 // remove the dns entries from the /etc/resolv.conf file
1516 QString resolv
[MAX_RESOLVCONF_LINES
];
1518 if((fd
= Requester::rq
->openResolv(O_RDONLY
)) >= 0) {
1521 while(read(fd
, &c
, 1) == 1 && i
< MAX_RESOLVCONF_LINES
) {
1531 if((fd
= Requester::rq
->openResolv(O_WRONLY
|O_TRUNC
)) >= 0) {
1532 for(int j
=0; j
< i
; j
++) {
1533 if(resolv
[j
].contains("#kppp temp entry")) continue;
1534 if(resolv
[j
].contains("#entry disabled by kppp")) {
1535 Q3CString tmp
= resolv
[j
].toLocal8Bit();
1536 write(fd
, tmp
.data()+2, tmp
.length() - 27);
1540 Q3CString tmp
= resolv
[j
].toLocal8Bit() + '\n';
1541 write(fd
, tmp
, tmp
.length());
1549 if ( modified_hostname
) {
1550 Requester::rq
->setHostname(old_hostname
);
1551 modified_hostname
= false;
1556 #include "connect.moc"