1 | /* |
2 | * kPPP: A pppd front end for the KDE project |
3 | * |
4 | * |
5 | * Copyright (C) 1997 Bernd Johannes Wuebben |
6 | * wuebben@math.cornell.edu |
7 | * Copyright (C) 1998-2001 Harri Porten <porten@kde.org> |
8 | * |
9 | * based on EzPPP: |
10 | * Copyright (C) 1997 Jay Painter |
11 | * |
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. |
16 | * |
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. |
21 | * |
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. |
25 | */ |
26 | |
27 | #include <config-kppp.h> |
28 | |
29 | #include <qlayout.h> |
30 | #include <qregexp.h> |
31 | //Added by qt3to4: |
32 | #include <QLabel> |
33 | #include <QTimerEvent> |
34 | #include <QVBoxLayout> |
35 | #include <QFrame> |
36 | #include <QHBoxLayout> |
37 | #include <Q3CString> |
38 | #include <QCloseEvent> |
39 | |
40 | #include <kdefakes.h> // gethostname |
41 | #include <kdebug.h> |
42 | #include <klocale.h> |
43 | #include <kmessagebox.h> |
44 | #include <kpushbutton.h> |
45 | #include <kapplication.h> |
46 | |
47 | #include <unistd.h> |
48 | #include <stdlib.h> |
49 | #include <string.h> |
50 | #include <fcntl.h> |
51 | #include <netdb.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> |
57 | #include <assert.h> |
58 | |
59 | #ifdef _XPG4_2 |
60 | #define __xnet_connect connect |
61 | #endif |
62 | |
63 | #include <errno.h> |
64 | |
65 | #ifdef HAVE_SYS_PARAM_H |
66 | #include <sys/param.h> |
67 | #endif |
68 | |
69 | #ifdef __linux__ |
70 | #include "runtests.h" |
71 | #endif |
72 | |
73 | #include "auth.h" |
74 | #include "connect.h" |
75 | #include "docking.h" |
76 | #include "main.h" |
77 | #include "modem.h" |
78 | #include "kpppconfig.h" |
79 | #include "pppdata.h" |
80 | #include "pppstats.h" |
81 | #include "requester.h" |
82 | #include "utils.h" |
83 | #include "kpppinterface.h" |
84 | |
85 | extern KPPPWidget *p_kppp; |
86 | |
87 | QString old_hostname; |
88 | bool modified_hostname; |
89 | |
90 | |
91 | ConnectWidget::ConnectWidget(QWidget *parent, const char *name, PPPStats *st) |
92 | : QWidget(parent), |
93 | // initialize some important variables |
94 | myreadbuffer("" ), |
95 | main_timer_ID(0), |
96 | vmain(0), |
97 | substate(-1), |
98 | scriptindex(0), |
99 | loopnest(0), |
100 | loopend(false), |
101 | semaphore(false), |
102 | expecting(false), |
103 | readbuffer("" ), |
104 | scanvar("" ), |
105 | scanning(false), |
106 | pausing(false), |
107 | termwindow(0), |
108 | dialnumber(0), |
109 | stats(st) |
110 | { |
111 | setObjectName(name); |
112 | |
113 | modified_hostname = false; |
114 | |
115 | QVBoxLayout *tl = new QVBoxLayout(this); |
116 | tl->setSpacing(10); |
117 | tl->setMargin(8); |
118 | QString tit = i18n("Connecting to: " ); |
119 | setWindowTitle(tit); |
120 | |
121 | QHBoxLayout *l0 = new QHBoxLayout(); |
122 | l0->setSpacing( 10 ); |
123 | tl->addLayout(l0); |
124 | l0->addSpacing(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); |
136 | l0->addSpacing(10); |
137 | |
138 | QHBoxLayout *l1 = new QHBoxLayout(); |
139 | l1->setSpacing( 10 ); |
140 | tl->addLayout(l1); |
141 | l1->addStretch(1); |
142 | |
143 | debug = new QPushButton(i18n("&Log" ), this); |
144 | debug->setCheckable(true); |
145 | connect(debug, SIGNAL(clicked()), SIGNAL(toggleDebugWindow())); |
146 | |
147 | cancel = new KPushButton(KStandardGuiItem::cancel(), this); |
148 | cancel->setFocus(); |
149 | connect(cancel, SIGNAL(clicked()), SLOT(cancelbutton())); |
150 | |
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); |
158 | l1->addSpacing(10); |
159 | |
160 | setFixedSize(sizeHint()); |
161 | |
162 | pausetimer = new QTimer(this); |
163 | connect(pausetimer, SIGNAL(timeout()), SLOT(pause())); |
164 | |
165 | qApp->processEvents(); |
166 | |
167 | timeout_timer = new QTimer(this); |
168 | connect(timeout_timer, SIGNAL(timeout()), SLOT(script_timed_out())); |
169 | |
170 | inittimer = new QTimer(this); |
171 | connect(inittimer, SIGNAL(timeout()), SLOT(init())); |
172 | |
173 | if_timeout_timer = new QTimer(this); |
174 | connect(if_timeout_timer, SIGNAL(timeout()), SLOT(if_waiting_timed_out())); |
175 | |
176 | connect(this,SIGNAL(if_waiting_signal()),this,SLOT(if_waiting_slot())); |
177 | |
178 | prompt = new PWEntry( this, "pw" ); |
179 | if_timer = new QTimer(this); |
180 | connect(if_timer,SIGNAL(timeout()), SLOT(if_waiting_slot())); |
181 | } |
182 | |
183 | |
184 | ConnectWidget::~ConnectWidget() { |
185 | } |
186 | |
187 | |
188 | void ConnectWidget::disableButtons() |
189 | { |
190 | debug->setEnabled(false); |
191 | cancel->setEnabled(false); |
192 | } |
193 | |
194 | void ConnectWidget::enableButtons() |
195 | { |
196 | debug->setEnabled(true); |
197 | cancel->setEnabled(true); |
198 | } |
199 | |
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); |
205 | } |
206 | |
207 | void ConnectWidget::init() { |
208 | gpppdata.setpppdError(0); |
209 | inittimer->stop(); |
210 | vmain = 0; |
211 | substate = -1; |
212 | expecting = false; |
213 | pausing = false; |
214 | scriptindex = 0; |
215 | myreadbuffer = "" ; |
216 | scanning = false; |
217 | scanvar = "" ; |
218 | firstrunID = true; |
219 | firstrunPW = true; |
220 | stats->totalbytes = 0; |
221 | dialnumber = 0; |
222 | |
223 | p_kppp->con_speed = "" ; |
224 | |
225 | p_kppp->setQuitOnDisconnect (p_kppp->quitOnDisconnect() || gpppdata.quit_on_disconnect()); |
226 | |
227 | comlist = &gpppdata.scriptType(); |
228 | arglist = &gpppdata.script(); |
229 | |
230 | QString tit = i18n("Connecting to: %1" , gpppdata.accname()); |
231 | setWindowTitle(tit); |
232 | |
233 | qApp->processEvents(); |
234 | |
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..." )); |
241 | |
242 | qApp->processEvents(); |
243 | QApplication::flush(); |
244 | pid_t id = execute_command(gpppdata.command_before_connect()); |
245 | int i, status; |
246 | |
247 | do { |
248 | qApp->processEvents(); |
249 | i = waitpid(id, &status, WNOHANG); |
250 | usleep(100000); |
251 | } while (i == 0 && errno == 0); |
252 | } |
253 | |
254 | int lock = Modem::modem->lockdevice(); |
255 | |
256 | if (lock == 1) { |
257 | messg->setText(i18n("Modem device is locked." )); |
258 | vmain = 20; // wait until cancel is pressed |
259 | return; |
260 | } |
261 | |
262 | if (lock == -1) { |
263 | messg->setText(i18n("Unable to create modem lock file." )); |
264 | vmain = 20; // wait until cancel is pressed |
265 | return; |
266 | } |
267 | |
268 | if(Modem::modem->opentty()) { |
269 | messg->setText(Modem::modem->modemMessage()); |
270 | qApp->processEvents(); |
271 | if(Modem::modem->hangup()) { |
272 | |
273 | qApp->processEvents(); |
274 | |
275 | semaphore = false; |
276 | |
277 | Modem::modem->stop(); |
278 | Modem::modem->notify(this, SLOT(readChar(unsigned char))); |
279 | |
280 | // if we are stuck anywhere we will time out |
281 | timeout_timer->start(gpppdata.modemTimeout()*1000); |
282 | |
283 | // this timer will run the script etc. |
284 | main_timer_ID = startTimer(10); |
285 | |
286 | return; |
287 | } |
288 | } |
289 | |
290 | // initialization failed |
291 | messg->setText(Modem::modem->modemMessage()); |
292 | vmain = 20; // wait until cancel is pressed |
293 | Modem::modem->unlockdevice(); |
294 | } |
295 | |
296 | |
297 | void ConnectWidget::timerEvent(QTimerEvent *) { |
298 | if (semaphore || pausing) |
299 | return; |
300 | |
301 | if(vmain == 0) { |
302 | #ifdef DEBUG_WO_DIALING |
303 | vmain = 10; |
304 | return; |
305 | #endif |
306 | |
307 | assert(PPPData::NumInitStrings > 0); |
308 | // first init string ? |
309 | if(substate == -1) { |
310 | messg->setText(i18n("Initializing modem..." )); |
311 | emit debugMessage(i18n("Initializing modem..." )); |
312 | substate = 0; |
313 | } |
314 | |
315 | QString initStr = gpppdata.modemInitStr(substate); |
316 | if (!initStr.isEmpty()) { |
317 | timeout_timer->stop(); |
318 | |
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); |
323 | writeline("" ); |
324 | usleep(gpppdata.modemPreInitDelay() * 5000); |
325 | } |
326 | setExpect(gpppdata.modemInitResp()); |
327 | writeline(initStr); |
328 | timeout_timer->start(gpppdata.modemTimeout()*1000); |
329 | usleep(gpppdata.modemInitDelay() * 10000); // 0.01 - 3.0 sec |
330 | } |
331 | |
332 | substate++; |
333 | |
334 | /* |
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 |
338 | * a "Modem Query" |
339 | */ |
340 | if (MODEM_TONEDURATION != gpppdata.modemToneDuration()) |
341 | vmain = 5; |
342 | else |
343 | vmain = 3; |
344 | |
345 | return; |
346 | } |
347 | |
348 | if (vmain == 5) { |
349 | if(!expecting) { |
350 | QString sToneDuration = "ATS11=" + QString::number(gpppdata.modemToneDuration()); |
351 | QString msg = i18n("Setting " ) + sToneDuration; |
352 | messg->setText(msg); |
353 | emit debugMessage(msg); |
354 | setExpect(gpppdata.modemInitResp()); |
355 | writeline(sToneDuration); |
356 | } |
357 | vmain = 3; |
358 | return; |
359 | } |
360 | |
361 | if(vmain == 3) { |
362 | if(!expecting) { |
363 | // done with all init strings ? |
364 | if(substate < PPPData::NumInitStrings) { |
365 | vmain = 0; |
366 | return; |
367 | } |
368 | substate = -1; |
369 | // skip setting the volume if command is empty |
370 | if(gpppdata.volumeInitString().isEmpty()) { |
371 | vmain = 4; |
372 | return; |
373 | } |
374 | messg->setText(i18n("Setting speaker volume..." )); |
375 | emit debugMessage(i18n("Setting speaker volume..." )); |
376 | |
377 | setExpect(gpppdata.modemInitResp()); |
378 | QString vol("AT" ); |
379 | vol += gpppdata.volumeInitString(); |
380 | writeline(vol); |
381 | usleep(gpppdata.modemInitDelay() * 10000); // 0.01 - 3.0 sec |
382 | vmain = 4; |
383 | return; |
384 | } |
385 | } |
386 | |
387 | if(vmain == 4) { |
388 | if(!expecting) { |
389 | if(!gpppdata.waitForDialTone() || gpppdata.waitCallback()) { |
390 | QString msg = i18n("Turning off dial tone waiting..." ); |
391 | messg->setText(msg); |
392 | emit debugMessage(msg); |
393 | setExpect(gpppdata.modemInitResp()); |
394 | writeline(gpppdata.modemNoDialToneDetectionStr()); |
395 | } |
396 | vmain = 1; |
397 | return; |
398 | } |
399 | } |
400 | |
401 | // dial the number and wait to connect |
402 | if(vmain == 1) { |
403 | if(!expecting) { |
404 | |
405 | timeout_timer->stop(); |
406 | timeout_timer->start(gpppdata.modemTimeout()*1000); |
407 | |
408 | if(gpppdata.waitCallback()) { |
409 | QString msg = i18n("Waiting for callback..." ); |
410 | messg->setText(msg); |
411 | emit debugMessage(msg); |
412 | setExpect(gpppdata.modemRingResp()); |
413 | vmain = 102; |
414 | return; |
415 | } |
416 | |
417 | QStringList &plist = gpppdata.phonenumbers(); |
418 | QString bmarg= gpppdata.dialPrefix(); |
419 | bmarg += plist.at(dialnumber); |
420 | QString bm = i18n("Dialing %1" , bmarg); |
421 | messg->setText(bm); |
422 | emit debugMessage(bm); |
423 | |
424 | QString pn = gpppdata.modemDialStr(); |
425 | pn += gpppdata.dialPrefix(); |
426 | pn += plist.at(dialnumber); |
427 | if(++dialnumber >= plist.count()) |
428 | dialnumber = 0; |
429 | writeline(pn); |
430 | |
431 | setExpect(gpppdata.modemConnectResp()); |
432 | vmain = 100; |
433 | return; |
434 | } |
435 | } |
436 | |
437 | // wait for connect, but redial if BUSY or wait for user cancel |
438 | // if NO CARRIER or NO DIALTONE |
439 | if(vmain == 100) { |
440 | if(!expecting) { |
441 | myreadbuffer = gpppdata.modemConnectResp(); |
442 | setExpect("\n" ); |
443 | vmain = 101; |
444 | return; |
445 | } |
446 | |
447 | if(readbuffer.contains(gpppdata.modemBusyResp())) { |
448 | timeout_timer->stop(); |
449 | timeout_timer->start(gpppdata.modemTimeout()*1000); |
450 | |
451 | messg->setText(i18n("Line busy. Hanging up..." )); |
452 | emit debugPutChar('\n'); |
453 | Modem::modem->hangup(); |
454 | |
455 | if(gpppdata.busyWait() > 0) { |
456 | QString bm = i18n("Line busy. Waiting: %1 seconds" , gpppdata.busyWait()); |
457 | messg->setText(bm); |
458 | emit debugMessage(bm); |
459 | |
460 | pausing = true; |
461 | |
462 | pausetimer->setSingleShot(true); |
463 | pausetimer->start(gpppdata.busyWait()*1000); |
464 | timeout_timer->stop(); |
465 | } |
466 | |
467 | Modem::modem->setDataMode(false); |
468 | vmain = 0; |
469 | substate = -1; |
470 | gpppdata.setWaitCallback(false); |
471 | return; |
472 | } |
473 | |
474 | if(readbuffer.contains(gpppdata.modemNoDialtoneResp())) { |
475 | timeout_timer->stop(); |
476 | |
477 | messg->setText(i18n("No Dial Tone" )); |
478 | vmain = 20; |
479 | Modem::modem->unlockdevice(); |
480 | gpppdata.setWaitCallback(false); |
481 | return; |
482 | } |
483 | |
484 | if(readbuffer.contains(gpppdata.modemNoCarrierResp())) { |
485 | if (gpppdata.get_redial_on_nocarrier()) { |
486 | timeout_timer->stop(); |
487 | timeout_timer->start(gpppdata.modemTimeout()*1000); |
488 | |
489 | if(gpppdata.busyWait() > 0) { |
490 | QString bm = i18n("No carrier. Waiting: %1 seconds" , gpppdata.busyWait()); |
491 | messg->setText(bm); |
492 | emit debugMessage(bm); |
493 | |
494 | pausing = true; |
495 | |
496 | pausetimer->setSingleShot(true); |
497 | pausetimer->start(gpppdata.busyWait()*1000); |
498 | timeout_timer->stop(); |
499 | } |
500 | |
501 | Modem::modem->setDataMode(false); |
502 | vmain = 0; |
503 | substate = -1; |
504 | return; |
505 | } else { |
506 | timeout_timer->stop(); |
507 | |
508 | messg->setText(i18n("No Carrier" )); |
509 | vmain = 20; |
510 | Modem::modem->unlockdevice(); |
511 | gpppdata.setWaitCallback(false); |
512 | } |
513 | return; |
514 | } |
515 | |
516 | if(readbuffer.contains(gpppdata.modemDLPResp())) { |
517 | timeout_timer->stop(); |
518 | |
519 | messg->setText(i18n("Digital Line Protection Detected." )); |
520 | vmain = 20; |
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 " |
528 | "damaged" )); |
529 | gpppdata.setWaitCallback(false); |
530 | return; |
531 | } |
532 | |
533 | |
534 | } |
535 | |
536 | // wait for newline after CONNECT response (so we get the speed) |
537 | if(vmain == 101) { |
538 | if(!expecting) { |
539 | Modem::modem->setDataMode(true); // modem will no longer respond to AT commands |
540 | |
541 | emit startAccounting(); |
542 | p_kppp->con_win->startClock(); |
543 | |
544 | vmain = 2; |
545 | scriptTimeout=gpppdata.modemTimeout()*1000; |
546 | return; |
547 | } |
548 | } |
549 | |
550 | // send answer on callback phase |
551 | if(vmain == 102) { |
552 | if(!expecting) { |
553 | writeline(gpppdata.modemAnswerStr()); |
554 | setExpect(gpppdata.modemConnectResp()); |
555 | vmain = 100; |
556 | return; |
557 | } |
558 | } |
559 | |
560 | // execute the script |
561 | if(vmain == 2) { |
562 | if(!expecting && !pausing && !scanning) { |
563 | |
564 | timeout_timer->stop(); |
565 | timeout_timer->start(scriptTimeout); |
566 | |
567 | if(scriptindex < comlist->count()) { |
568 | scriptCommand = (comlist->at(scriptindex)); |
569 | scriptArgument = (arglist->at(scriptindex)); |
570 | } else { |
571 | kDebug(5002) << "End of script" ; |
572 | vmain = 10; |
573 | return; |
574 | } |
575 | |
576 | if (scriptCommand == "Scan" ) { |
577 | QString bm = i18n("Scanning %1" , scriptArgument); |
578 | messg->setText(bm); |
579 | emit debugMessage(bm); |
580 | |
581 | setScan(scriptArgument); |
582 | scriptindex++; |
583 | return; |
584 | } |
585 | |
586 | if (scriptCommand == "Save" ) { |
587 | QString bm = i18n("Saving %1" , scriptArgument); |
588 | messg->setText(bm); |
589 | emit debugMessage(bm); |
590 | |
591 | if (scriptArgument.toLower() == "password" ) { |
592 | gpppdata.setPassword(scanvar); |
593 | p_kppp->setPW_Edit(scanvar); |
594 | if(gpppdata.storePassword()) |
595 | gpppdata.setStoredPassword(scanvar); |
596 | firstrunPW = true; |
597 | } |
598 | |
599 | scriptindex++; |
600 | return; |
601 | } |
602 | |
603 | |
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()); |
611 | |
612 | QString scriptarg; |
613 | if (scriptCommand == "Send" ) |
614 | scriptarg = scriptArgument; |
615 | else { |
616 | for(int i = 0; i < scriptArgument.length(); i++) |
617 | scriptarg += '*'; |
618 | } |
619 | QString bm = i18n("Sending %1" , scriptarg); |
620 | |
621 | messg->setText(bm); |
622 | emit debugMessage(bm); |
623 | |
624 | writeline(scriptArgument); |
625 | scriptindex++; |
626 | return; |
627 | } |
628 | |
629 | if (scriptCommand == "Expect" ) { |
630 | QString bm = i18n("Expecting %1" , scriptArgument); |
631 | messg->setText(bm); |
632 | emit debugMessage(bm); |
633 | |
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. |
637 | scriptindex++; |
638 | setExpect(scriptArgument); |
639 | return; |
640 | } |
641 | |
642 | |
643 | if (scriptCommand == "Pause" ) { |
644 | QString bm = i18n("Pause %1 seconds" , scriptArgument); |
645 | messg->setText(bm); |
646 | emit debugMessage(bm); |
647 | |
648 | pausing = true; |
649 | |
650 | pausetimer->setSingleShot(true); |
651 | pausetimer->start(scriptArgument.toInt()*1000); |
652 | timeout_timer->stop(); |
653 | |
654 | scriptindex++; |
655 | return; |
656 | } |
657 | |
658 | if (scriptCommand == "Timeout" ) { |
659 | |
660 | timeout_timer->stop(); |
661 | |
662 | QString bm = i18n("Timeout %1 seconds" , scriptArgument); |
663 | messg->setText(bm); |
664 | emit debugMessage(bm); |
665 | |
666 | scriptTimeout=scriptArgument.toInt()*1000; |
667 | timeout_timer->start(scriptTimeout); |
668 | |
669 | scriptindex++; |
670 | return; |
671 | } |
672 | |
673 | if (scriptCommand == "Hangup" ) { |
674 | messg->setText(i18n("Hangup" )); |
675 | emit debugMessage(i18n("Hangup" )); |
676 | |
677 | writeline(gpppdata.modemHangupStr()); |
678 | setExpect(gpppdata.modemHangupResp()); |
679 | |
680 | scriptindex++; |
681 | return; |
682 | } |
683 | |
684 | if (scriptCommand == "Answer" ) { |
685 | |
686 | timeout_timer->stop(); |
687 | |
688 | messg->setText(i18n("Answer" )); |
689 | emit debugMessage(i18n("Answer" )); |
690 | |
691 | setExpect(gpppdata.modemRingResp()); |
692 | vmain = 150; |
693 | return; |
694 | } |
695 | |
696 | if (scriptCommand == "ID" ) { |
697 | QString bm = i18n("ID %1" , scriptArgument); |
698 | messg->setText(bm); |
699 | emit debugMessage(bm); |
700 | |
701 | QString idstring = gpppdata.storedUsername(); |
702 | |
703 | if(!idstring.isEmpty() && firstrunID) { |
704 | // the user entered an Id on the main kppp dialog |
705 | writeline(idstring); |
706 | firstrunID = false; |
707 | scriptindex++; |
708 | } |
709 | else { |
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(); |
717 | prompt->show(); |
718 | } |
719 | } else { |
720 | /* if prompt withdrawn ... then, */ |
721 | if(!(prompt->isVisible())) { |
722 | writeline(prompt->text()); |
723 | prompt->setConsumed(); |
724 | scriptindex++; |
725 | return; |
726 | } |
727 | /* replace timeout value */ |
728 | } |
729 | } |
730 | } |
731 | |
732 | if (scriptCommand == "Password" ) { |
733 | QString bm = i18n("Password %1" , scriptArgument); |
734 | messg->setText(bm); |
735 | emit debugMessage(bm); |
736 | |
737 | QString pwstring = gpppdata.password(); |
738 | |
739 | if(!pwstring.isEmpty() && firstrunPW) { |
740 | // the user entered a password on the main kppp dialog |
741 | writeline(pwstring); |
742 | firstrunPW = false; |
743 | scriptindex++; |
744 | } |
745 | else { |
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(); |
753 | prompt->show(); |
754 | } |
755 | } else { |
756 | /* if prompt withdrawn ... then, */ |
757 | if(!(prompt->isVisible())) { |
758 | p_kppp->setPW_Edit(prompt->text()); |
759 | writeline(prompt->text()); |
760 | prompt->setConsumed(); |
761 | scriptindex++; |
762 | return; |
763 | } |
764 | /* replace timeout value */ |
765 | } |
766 | } |
767 | } |
768 | |
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). |
773 | |
774 | QString ts = scriptArgument; |
775 | int vstart = ts.indexOf( "##" ); |
776 | if( vstart != -1 ) { |
777 | ts.remove( vstart, 2 ); |
778 | ts.insert( vstart, scanvar ); |
779 | } |
780 | |
781 | QString bm = i18n("Prompting %1" , ts); |
782 | messg->setText(bm); |
783 | emit debugMessage(bm); |
784 | |
785 | /* if not around yet, then post window... */ |
786 | if (prompt->Consumed()) { |
787 | if (!(prompt->isVisible())) { |
788 | prompt->setPrompt( ts ); |
789 | prompt->setEchoModeNormal(); |
790 | prompt->show(); |
791 | } |
792 | } else { |
793 | /* if prompt withdrawn ... then, */ |
794 | if (!(prompt->isVisible())) { |
795 | writeline(prompt->text()); |
796 | prompt->setConsumed(); |
797 | scriptindex++; |
798 | return; |
799 | } |
800 | /* replace timeout value */ |
801 | } |
802 | } |
803 | |
804 | if (scriptCommand == "PWPrompt" ) { |
805 | QString bm = i18n("PW Prompt %1" , scriptArgument); |
806 | messg->setText(bm); |
807 | emit debugMessage(bm); |
808 | |
809 | /* if not around yet, then post window... */ |
810 | if (prompt->Consumed()) { |
811 | if (!(prompt->isVisible())) { |
812 | prompt->setPrompt(scriptArgument); |
813 | prompt->setEchoModePassword(); |
814 | prompt->show(); |
815 | } |
816 | } else { |
817 | /* if prompt withdrawn ... then, */ |
818 | if (!(prompt->isVisible())) { |
819 | writeline(prompt->text()); |
820 | prompt->setConsumed(); |
821 | scriptindex++; |
822 | return; |
823 | } |
824 | /* replace timeout value */ |
825 | } |
826 | } |
827 | |
828 | if (scriptCommand == "LoopStart" ) { |
829 | |
830 | QString bm = i18n("Loop Start %1" , scriptArgument); |
831 | |
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. |
835 | scriptindex++; |
836 | |
837 | if ( loopnest > (MAXLOOPNEST-2) ) { |
838 | bm += i18n("ERROR: Nested too deep, ignored." ); |
839 | vmain=20; |
840 | cancelbutton(); |
841 | KMessageBox::error(0, i18n("Loops nested too deeply." )); |
842 | } else { |
843 | setExpect(scriptArgument); |
844 | loopstartindex[loopnest] = scriptindex; |
845 | loopstr[loopnest] = scriptArgument; |
846 | loopend = false; |
847 | loopnest++; |
848 | } |
849 | messg->setText(bm); |
850 | emit debugMessage(bm); |
851 | |
852 | } |
853 | |
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); |
858 | vmain=20; |
859 | cancelbutton(); |
860 | KMessageBox::error(0, bm); |
861 | return; |
862 | } else { |
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. |
866 | scriptindex++; |
867 | setExpect(scriptArgument); |
868 | loopnest--; |
869 | loopend = true; |
870 | } |
871 | messg->setText(bm); |
872 | emit debugMessage(bm); |
873 | |
874 | } |
875 | } |
876 | } |
877 | |
878 | // this is a subroutine for the "Answer" script option |
879 | |
880 | if(vmain == 150) { |
881 | if(!expecting) { |
882 | writeline(gpppdata.modemAnswerStr()); |
883 | setExpect(gpppdata.modemAnswerResp()); |
884 | |
885 | vmain = 2; |
886 | scriptindex++; |
887 | return; |
888 | } |
889 | } |
890 | |
891 | if(vmain == 30) { |
892 | if (termwindow->isVisible()) |
893 | return; |
894 | if (termwindow->pressedContinue()) |
895 | vmain = 10; |
896 | else |
897 | cancelbutton(); |
898 | } |
899 | |
900 | if(vmain == 10) { |
901 | if(!expecting) { |
902 | |
903 | int result; |
904 | |
905 | timeout_timer->stop(); |
906 | if_timeout_timer->stop(); // better be sure. |
907 | |
908 | // stop reading of data |
909 | Modem::modem->stop(); |
910 | |
911 | if(gpppdata.authMethod() == AUTH_TERMINAL) { |
912 | if (termwindow) { |
913 | delete termwindow; |
914 | termwindow = 0L; |
915 | show(); |
916 | } else { |
917 | termwindow = new LoginTerm(0L, 0L); |
918 | hide(); |
919 | termwindow->show(); |
920 | vmain = 30; |
921 | return; |
922 | } |
923 | } |
924 | |
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(); |
929 | |
930 | killTimer( main_timer_ID ); |
931 | |
932 | if_timeout_timer->start(gpppdata.pppdTimeout()*1000); |
933 | kDebug(5002) << "started if timeout timer with " << gpppdata.pppdTimeout()*1000; |
934 | |
935 | // find out PPP interface and notify the stats module |
936 | stats->setUnit(pppInterfaceNumber()); |
937 | |
938 | kapp->flush(); |
939 | semaphore = true; |
940 | result = execppp(); |
941 | |
942 | emit debugMessage(i18n("Starting pppd..." )); |
943 | kDebug(5002) << "execppp() returned with return-code " << result; |
944 | |
945 | if(result) { |
946 | if(!gpppdata.autoDNS()) |
947 | adddns(); |
948 | |
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. |
951 | |
952 | emit if_waiting_signal(); |
953 | } else { |
954 | |
955 | // starting pppd wasn't successful. Error messages were |
956 | // handled by execppp(); |
957 | if_timeout_timer->stop(); |
958 | |
959 | hide(); |
960 | messg->setText("" ); |
961 | p_kppp->quit_b->setFocus(); |
962 | p_kppp->show(); |
963 | qApp->processEvents(); |
964 | Modem::modem->hangup(); |
965 | emit stopAccounting(); |
966 | p_kppp->con_win->stopClock(); |
967 | Modem::modem->closetty(); |
968 | Modem::modem->unlockdevice(); |
969 | |
970 | } |
971 | |
972 | return; |
973 | } |
974 | } |
975 | |
976 | // this is a "wait until cancel" entry |
977 | |
978 | if(vmain == 20) { |
979 | gpppdata.setWaitCallback(false); |
980 | } |
981 | } |
982 | |
983 | |
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); |
990 | } |
991 | |
992 | |
993 | |
994 | void ConnectWidget::readChar(unsigned char c) { |
995 | if(semaphore) |
996 | return; |
997 | |
998 | readbuffer += c; |
999 | myreadbuffer += c; |
1000 | |
1001 | // While in scanning mode store each char to the scan buffer |
1002 | // for use in the prompt command |
1003 | if( scanning ) |
1004 | scanbuffer += c; |
1005 | |
1006 | // add to debug window |
1007 | emit debugPutChar(c); |
1008 | |
1009 | checkBuffers(); |
1010 | } |
1011 | |
1012 | |
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" ) ) { |
1019 | scanning = false; |
1020 | |
1021 | int vstart = scanbuffer.indexOf( scanstr ) + scanstr.length(); |
1022 | scanvar = scanbuffer.mid( vstart, scanbuffer.length() - vstart); |
1023 | scanvar = scanvar.trimmed(); |
1024 | |
1025 | // Show the Variabel content in the debug window |
1026 | QString sv = i18n("Scan Var: %1" , scanvar); |
1027 | emit debugMessage(sv); |
1028 | } |
1029 | |
1030 | if(expecting) { |
1031 | if(readbuffer.contains(expectstr)) { |
1032 | expecting = false; |
1033 | // keep everything after the expected string |
1034 | readbuffer.remove(0, readbuffer.indexOf(expectstr) + expectstr.length()); |
1035 | |
1036 | QString ts = i18n("Found: %1" , expectstr); |
1037 | emit debugMessage(ts); |
1038 | |
1039 | if (loopend) { |
1040 | loopend=false; |
1041 | } |
1042 | } |
1043 | |
1044 | if (loopend && readbuffer.contains(loopstr[loopnest])) { |
1045 | expecting = false; |
1046 | readbuffer = "" ; |
1047 | QString ts = i18n("Looping: %1" , loopstr[loopnest]); |
1048 | emit debugMessage(ts); |
1049 | scriptindex = loopstartindex[loopnest]; |
1050 | loopend = false; |
1051 | loopnest++; |
1052 | } |
1053 | // notify event loop if expected string was found |
1054 | if(!expecting) |
1055 | timerEvent((QTimerEvent *) 0); |
1056 | } |
1057 | } |
1058 | |
1059 | |
1060 | |
1061 | void ConnectWidget::pause() { |
1062 | pausing = false; |
1063 | pausetimer->stop(); |
1064 | } |
1065 | |
1066 | |
1067 | void ConnectWidget::cancelbutton() { |
1068 | gpppdata.setWaitCallback(false); |
1069 | Modem::modem->stop(); |
1070 | killTimer(main_timer_ID); |
1071 | timeout_timer->stop(); |
1072 | if_timer->stop(); |
1073 | if_timeout_timer->stop(); |
1074 | |
1075 | if (termwindow) { |
1076 | delete termwindow; |
1077 | termwindow = 0L; |
1078 | show(); |
1079 | } |
1080 | |
1081 | messg->setText(i18n("One moment please..." )); |
1082 | |
1083 | // just to be sure |
1084 | Requester::rq->removeSecret(AUTH_PAP); |
1085 | Requester::rq->removeSecret(AUTH_CHAP); |
1086 | removedns(); |
1087 | |
1088 | qApp->processEvents(); |
1089 | |
1090 | Requester::rq->killPPPDaemon(); |
1091 | Modem::modem->hangup(); |
1092 | |
1093 | hide(); |
1094 | messg->setText("" ); |
1095 | p_kppp->quit_b->setFocus(); |
1096 | p_kppp->show(); |
1097 | emit stopAccounting(); // just to be sure |
1098 | p_kppp->con_win->stopClock(); |
1099 | Modem::modem->closetty(); |
1100 | Modem::modem->unlockdevice(); |
1101 | |
1102 | //abort prompt window... |
1103 | if (prompt->isVisible()) { |
1104 | prompt->hide(); |
1105 | } |
1106 | prompt->setConsumed(); |
1107 | |
1108 | if(p_kppp->quitOnDisconnect()) |
1109 | kapp->exit(0); |
1110 | } |
1111 | |
1112 | |
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(); |
1118 | return; |
1119 | } |
1120 | |
1121 | if (prompt->isVisible()) |
1122 | prompt->hide(); |
1123 | |
1124 | prompt->setConsumed(); |
1125 | messg->setText(i18n("Script timed out." )); |
1126 | Modem::modem->hangup(); |
1127 | emit stopAccounting(); |
1128 | p_kppp->con_win->stopClock(); |
1129 | |
1130 | vmain = 0; // let's try again. |
1131 | substate = -1; |
1132 | } |
1133 | |
1134 | |
1135 | void ConnectWidget::setScan(const QString &n) { |
1136 | scanning = true; |
1137 | scanstr = n; |
1138 | scanbuffer = "" ; |
1139 | |
1140 | QString ts = i18n("Scanning: %1" , n); |
1141 | emit debugMessage(ts); |
1142 | } |
1143 | |
1144 | |
1145 | void ConnectWidget::setExpect(const QString &n) { |
1146 | expecting = true; |
1147 | expectstr = n; |
1148 | |
1149 | QString ts = i18n("Expecting: %1" , n); |
1150 | ts.replace(QRegExp("\n" ), "<LF>" ); |
1151 | emit debugMessage(ts); |
1152 | |
1153 | // check if the expected string is in the read buffer already. |
1154 | checkBuffers(); |
1155 | } |
1156 | |
1157 | |
1158 | void ConnectWidget::if_waiting_timed_out() { |
1159 | if_timer->stop(); |
1160 | if_timeout_timer->stop(); |
1161 | kDebug(5002) << "if_waiting_timed_out()" ; |
1162 | |
1163 | gpppdata.setpppdError(E_IF_TIMEOUT); |
1164 | |
1165 | // let's kill the stuck pppd |
1166 | Requester::rq->killPPPDaemon(); |
1167 | |
1168 | emit stopAccounting(); |
1169 | p_kppp->con_win->stopClock(); |
1170 | |
1171 | |
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(); |
1175 | } |
1176 | |
1177 | void ConnectWidget::pppdDied() |
1178 | { |
1179 | if_timer->stop(); |
1180 | if_timeout_timer->stop(); |
1181 | } |
1182 | |
1183 | void ConnectWidget::if_waiting_slot() { |
1184 | messg->setText(i18n("Logging on to network..." )); |
1185 | |
1186 | if(!stats->ifIsUp()) { |
1187 | |
1188 | if(gpppdata.pppdError() != 0) { |
1189 | // we are here if pppd died immediately after starting it. |
1190 | pppdDied(); |
1191 | // error message handled in main.cpp: sigPPPDDied() |
1192 | return; |
1193 | } |
1194 | |
1195 | if_timer->setSingleShot(true); |
1196 | if_timer->start(100); |
1197 | return; |
1198 | } |
1199 | |
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(); |
1203 | if_timer->stop(); |
1204 | usleep(200000); |
1205 | |
1206 | if(gpppdata.autoDNS()) |
1207 | addpeerdns(); |
1208 | |
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 |
1213 | auto_hostname(); |
1214 | |
1215 | // signal other applications that we are connected now |
1216 | emit connected(); |
1217 | |
1218 | if(!gpppdata.command_on_connect().isEmpty()) { |
1219 | messg->setText(i18n("Running startup command..." )); |
1220 | |
1221 | // make sure that we don't get any async errors |
1222 | kapp->flush(); |
1223 | execute_command(gpppdata.command_on_connect()); |
1224 | messg->setText(i18n("Done" )); |
1225 | } |
1226 | |
1227 | // remove the authentication file |
1228 | Requester::rq->removeSecret(AUTH_PAP); |
1229 | Requester::rq->removeSecret(AUTH_CHAP); |
1230 | |
1231 | emit debugMessage(i18n("Done" )); |
1232 | set_con_speed_string(); |
1233 | |
1234 | p_kppp->con_win->setConnectionSpeed(p_kppp->con_speed); |
1235 | hide(); |
1236 | messg->setText("" ); |
1237 | |
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()); |
1242 | else |
1243 | p_kppp->con_win->accounting(false); |
1244 | |
1245 | if (gpppdata.get_dock_into_panel()) { |
1246 | DockWidget::dock_widget->show(); |
1247 | DockWidget::dock_widget->take_stats(); |
1248 | hide(); |
1249 | } |
1250 | else { |
1251 | p_kppp->con_win->show(); |
1252 | |
1253 | if(gpppdata.get_iconify_on_connect()) { |
1254 | p_kppp->con_win->showMinimized(); |
1255 | } |
1256 | } |
1257 | |
1258 | Modem::modem->closetty(); |
1259 | } |
1260 | |
1261 | |
1262 | bool ConnectWidget::execppp() { |
1263 | QString command; |
1264 | |
1265 | command = "pppd" ; |
1266 | |
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. |
1271 | // command += " "; |
1272 | // command += gpppdata.modemDevice(); |
1273 | |
1274 | command += ' ' + gpppdata.speed(); |
1275 | |
1276 | command += " -detach" ; |
1277 | |
1278 | if(gpppdata.ipaddr() != "0.0.0.0" || |
1279 | gpppdata.gateway() != "0.0.0.0" ) { |
1280 | if(gpppdata.ipaddr() != "0.0.0.0" ) { |
1281 | command += ' '; |
1282 | command += gpppdata.ipaddr(); |
1283 | command += ':'; |
1284 | } |
1285 | else { |
1286 | command += ' '; |
1287 | command += ':'; |
1288 | } |
1289 | |
1290 | if(gpppdata.gateway() != "0.0.0.0" ) |
1291 | command += gpppdata.gateway(); |
1292 | } |
1293 | |
1294 | if(gpppdata.subnetmask() != "0.0.0.0" ) |
1295 | command += " netmask " + gpppdata.subnetmask(); |
1296 | |
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" ; |
1304 | else |
1305 | command += " xonxoff" ; |
1306 | } |
1307 | |
1308 | if(gpppdata.defaultroute()) |
1309 | command += " defaultroute" ; |
1310 | |
1311 | if(gpppdata.autoDNS()) |
1312 | command += " usepeerdns" ; |
1313 | |
1314 | QStringList &arglist = gpppdata.pppdArgument(); |
1315 | for ( QStringList::Iterator it = arglist.begin(); |
1316 | it != arglist.end(); |
1317 | ++it ) |
1318 | { |
1319 | command += ' ' + *it; |
1320 | } |
1321 | |
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(); |
1328 | } else { |
1329 | command += " callback " ; |
1330 | command += gpppdata.callbackType() == CBTYPE_ADMIN ? |
1331 | QString("0" ) : gpppdata.callbackPhone(); |
1332 | } |
1333 | } else |
1334 | gpppdata.setWaitCallback(false); |
1335 | |
1336 | // PAP settings |
1337 | if(gpppdata.authMethod() == AUTH_PAP) { |
1338 | command += " -chap user " ; |
1339 | command = command + "\"" + gpppdata.storedUsername() + "\"" ; |
1340 | } |
1341 | |
1342 | // CHAP settings |
1343 | if(gpppdata.authMethod() == AUTH_CHAP) { |
1344 | command += " -pap user " ; |
1345 | command = command + "\"" + gpppdata.storedUsername() + "\"" ; |
1346 | } |
1347 | |
1348 | // PAP/CHAP settings |
1349 | if(gpppdata.authMethod() == AUTH_PAPCHAP) { |
1350 | command += " user " ; |
1351 | command = command + "\"" + gpppdata.storedUsername() + "\"" ; |
1352 | } |
1353 | |
1354 | // check for debug |
1355 | if(gpppdata.getPPPDebug()) |
1356 | command += " debug" ; |
1357 | |
1358 | if (command.length() > MAX_CMDLEN) { |
1359 | KMessageBox::error(this, i18n( |
1360 | "pppd command + command-line arguments exceed " |
1361 | "2024 characters in length." |
1362 | )); |
1363 | |
1364 | return false; // nonsensically long command which would bust my buffer buf. |
1365 | } |
1366 | |
1367 | kapp->flush(); |
1368 | |
1369 | return Requester::rq->execPPPDaemon(command); |
1370 | } |
1371 | |
1372 | |
1373 | void ConnectWidget::closeEvent( QCloseEvent *e ) { |
1374 | e->ignore(); |
1375 | emit cancelbutton(); |
1376 | } |
1377 | |
1378 | |
1379 | void ConnectWidget::setMsg(const QString &msg) { |
1380 | messg->setText(msg); |
1381 | } |
1382 | |
1383 | void ConnectWidget::writeline(const QString &s) { |
1384 | Modem::modem->writeLine(s.toLocal8Bit()); |
1385 | } |
1386 | |
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; |
1392 | int dot; |
1393 | char tmp_str[100]; // buffer overflow safe |
1394 | |
1395 | gethostname(tmp_str, sizeof(tmp_str)); |
1396 | tmp_str[sizeof(tmp_str)-1]=0; // panic |
1397 | old_hostname=tmp_str; // copy to QString |
1398 | |
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); |
1402 | |
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; |
1409 | |
1410 | new_hostname=hostname_entry->h_name; |
1411 | new_hostname.remove(0,dot+1); |
1412 | |
1413 | add_domain(new_hostname); |
1414 | } |
1415 | } |
1416 | |
1417 | } |
1418 | |
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) { |
1422 | |
1423 | int fd; |
1424 | char c; |
1425 | QString resolv[MAX_RESOLVCONF_LINES]; |
1426 | |
1427 | if (domain.isEmpty()) |
1428 | return; |
1429 | |
1430 | if((fd = Requester::rq->openResolv(O_RDONLY)) >= 0) { |
1431 | |
1432 | int i=0; |
1433 | while((read(fd, &c, 1) == 1) && (i < MAX_RESOLVCONF_LINES)) { |
1434 | if(c == '\n') { |
1435 | i++; |
1436 | } |
1437 | else { |
1438 | resolv[i] += c; |
1439 | } |
1440 | } |
1441 | close(fd); |
1442 | if ((c != '\n') && (i < MAX_RESOLVCONF_LINES)) i++; |
1443 | |
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()); |
1448 | |
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()); |
1458 | } |
1459 | else { |
1460 | Q3CString tmp = resolv[j].toLocal8Bit() + '\n'; |
1461 | write(fd, tmp, tmp.length()); |
1462 | } |
1463 | } |
1464 | } |
1465 | close(fd); |
1466 | } |
1467 | } |
1468 | |
1469 | |
1470 | // adds the DNS entries in the /etc/resolv.conf file |
1471 | void adddns() |
1472 | { |
1473 | int fd; |
1474 | |
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(); |
1479 | ++it ) |
1480 | { |
1481 | Q3CString dns = "nameserver " + (*it).toLocal8Bit() + |
1482 | " \t#kppp temp entry\n" ; |
1483 | write(fd, dns.data(), dns.length()); |
1484 | } |
1485 | close(fd); |
1486 | } |
1487 | add_domain(gpppdata.domain()); |
1488 | } |
1489 | |
1490 | void addpeerdns() { |
1491 | int fd, fd2; |
1492 | |
1493 | if((fd = Requester::rq->openResolv(O_WRONLY|O_APPEND)) >= 0) { |
1494 | if((fd2 = open("/etc/ppp/resolv.conf" , O_RDONLY)) >= 0) { |
1495 | char c; |
1496 | int i = 0; |
1497 | while(i++ < 100 && read(fd2, &c, 1) == 1) { |
1498 | if(c == '\n') |
1499 | write(fd, "\t#kppp temp entry\n" , 18); |
1500 | else |
1501 | write(fd, &c, 1); |
1502 | } |
1503 | close(fd2); |
1504 | } else |
1505 | fprintf(stderr, "failed to read from /etc/ppp/resolv.conf\n" ); |
1506 | close(fd); |
1507 | } |
1508 | add_domain(gpppdata.domain()); |
1509 | } |
1510 | |
1511 | // remove the dns entries from the /etc/resolv.conf file |
1512 | void removedns() { |
1513 | |
1514 | int fd; |
1515 | char c; |
1516 | QString resolv[MAX_RESOLVCONF_LINES]; |
1517 | |
1518 | if((fd = Requester::rq->openResolv(O_RDONLY)) >= 0) { |
1519 | |
1520 | int i=0; |
1521 | while(read(fd, &c, 1) == 1 && i < MAX_RESOLVCONF_LINES) { |
1522 | if(c == '\n') { |
1523 | i++; |
1524 | } |
1525 | else { |
1526 | resolv[i] += c; |
1527 | } |
1528 | } |
1529 | close(fd); |
1530 | |
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); |
1537 | write(fd, "\n" , 1); |
1538 | } |
1539 | else { |
1540 | Q3CString tmp = resolv[j].toLocal8Bit() + '\n'; |
1541 | write(fd, tmp, tmp.length()); |
1542 | } |
1543 | } |
1544 | } |
1545 | close(fd); |
1546 | |
1547 | } |
1548 | |
1549 | if ( modified_hostname ) { |
1550 | Requester::rq->setHostname(old_hostname); |
1551 | modified_hostname = false; |
1552 | } |
1553 | |
1554 | } |
1555 | |
1556 | #include "connect.moc" |
1557 | |