Diffstat (limited to 'noncore/settings/networksettings/ppp/modem.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | noncore/settings/networksettings/ppp/modem.cpp | 85 |
1 files changed, 71 insertions, 14 deletions
diff --git a/noncore/settings/networksettings/ppp/modem.cpp b/noncore/settings/networksettings/ppp/modem.cpp index d23fee4..3dbc8c3 100644 --- a/noncore/settings/networksettings/ppp/modem.cpp +++ b/noncore/settings/networksettings/ppp/modem.cpp | |||
@@ -1,654 +1,651 @@ | |||
1 | /* | 1 | /* |
2 | * kPPP: A pppd Front End for the KDE project | 2 | * kPPP: A pppd Front End for the KDE project |
3 | * | 3 | * |
4 | * $Id$ | 4 | * $Id$ |
5 | * | 5 | * |
6 | * Copyright (C) 1997 Bernd Johannes Wuebben | 6 | * Copyright (C) 1997 Bernd Johannes Wuebben |
7 | * wuebben@math.cornell.edu | 7 | * wuebben@math.cornell.edu |
8 | * | 8 | * |
9 | * This file was added by Harri Porten <porten@tu-harburg.de> | 9 | * This file was added by Harri Porten <porten@tu-harburg.de> |
10 | * | 10 | * |
11 | * | 11 | * |
12 | * This program is free software; you can redistribute it and/or | 12 | * This program is free software; you can redistribute it and/or |
13 | * modify it under the terms of the GNU Library General Public | 13 | * modify it under the terms of the GNU Library General Public |
14 | * License as published by the Free Software Foundation; either | 14 | * License as published by the Free Software Foundation; either |
15 | * version 2 of the License, or (at your option) any later version. | 15 | * version 2 of the License, or (at your option) any later version. |
16 | * | 16 | * |
17 | * This program is distributed in the hope that it will be useful, | 17 | * This program is distributed in the hope that it will be useful, |
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
20 | * Library General Public License for more details. | 20 | * Library General Public License for more details. |
21 | * | 21 | * |
22 | * You should have received a copy of the GNU Library General Public | 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 | 23 | * License along with this program; if not, write to the Free |
24 | * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 24 | * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
25 | */ | 25 | */ |
26 | 26 | ||
27 | #include <errno.h> | 27 | #include <errno.h> |
28 | #include <stdlib.h> | 28 | #include <stdlib.h> |
29 | #include <unistd.h> | 29 | #include <unistd.h> |
30 | #include <fcntl.h> | 30 | #include <fcntl.h> |
31 | #include <signal.h> | 31 | #include <signal.h> |
32 | #include <sys/ioctl.h> | 32 | #include <sys/ioctl.h> |
33 | #include <sys/types.h> | 33 | #include <sys/types.h> |
34 | #include <sys/stat.h> | 34 | #include <sys/stat.h> |
35 | #include <setjmp.h> | 35 | #include <setjmp.h> |
36 | #include <regex.h> | 36 | #include <regex.h> |
37 | #include <qregexp.h> | 37 | #include <qregexp.h> |
38 | #include <assert.h> | 38 | #include <assert.h> |
39 | #include <string.h> | 39 | #include <string.h> |
40 | 40 | ||
41 | #ifdef HAVE_RESOLV_H | 41 | #ifdef HAVE_RESOLV_H |
42 | # include <arpa/nameser.h> | 42 | # include <arpa/nameser.h> |
43 | # include <resolv.h> | 43 | # include <resolv.h> |
44 | #endif | 44 | #endif |
45 | 45 | ||
46 | #ifndef _PATH_RESCONF | 46 | #ifndef _PATH_RESCONF |
47 | #define _PATH_RESCONF "/etc/resolv.conf" | 47 | #define _PATH_RESCONF "/etc/resolv.conf" |
48 | #endif | 48 | #endif |
49 | 49 | ||
50 | #define strlcpy strcpy | 50 | #define strlcpy strcpy |
51 | #include "auth.h" | 51 | #include "auth.h" |
52 | #include "modem.h" | 52 | #include "modem.h" |
53 | #include "pppdata.h" | 53 | #include "pppdata.h" |
54 | //#include <klocale.h> | ||
55 | #define i18n QObject::tr | ||
56 | #define qError qDebug | 54 | #define qError qDebug |
57 | //#include <kdebug.h> | 55 | |
58 | //#include <config.h> | ||
59 | 56 | ||
60 | #define MY_ASSERT(x) if (!(x)) { \ | 57 | #define MY_ASSERT(x) if (!(x)) { \ |
61 | qFatal( "ASSERT: \"%s\" in %s (%d)\n",#x,__FILE__,__LINE__); \ | 58 | qFatal( "ASSERT: \"%s\" in %s (%d)\n",#x,__FILE__,__LINE__); \ |
62 | exit(1); } | 59 | exit(1); } |
63 | 60 | ||
64 | 61 | ||
65 | static sigjmp_buf jmp_buffer; | 62 | static sigjmp_buf jmp_buffer; |
66 | 63 | ||
67 | //Modem *Modem::modem = 0; | 64 | //Modem *Modem::modem = 0; |
68 | 65 | ||
69 | 66 | ||
70 | const char* pppdPath() { | 67 | const char* pppdPath() { |
71 | // wasting a few bytes | 68 | // wasting a few bytes |
72 | static char buffer[sizeof(PPPDSEARCHPATH)+sizeof(PPPDNAME)]; | 69 | static char buffer[sizeof(PPPDSEARCHPATH)+sizeof(PPPDNAME)]; |
73 | static char *pppdPath = 0L; | 70 | static char *pppdPath = 0L; |
74 | char *p; | 71 | char *p; |
75 | 72 | ||
76 | if(pppdPath == 0L) { | 73 | if(pppdPath == 0L) { |
77 | const char *c = PPPDSEARCHPATH; | 74 | const char *c = PPPDSEARCHPATH; |
78 | while(*c != '\0') { | 75 | while(*c != '\0') { |
79 | while(*c == ':') | 76 | while(*c == ':') |
80 | c++; | 77 | c++; |
81 | p = buffer; | 78 | p = buffer; |
82 | while(*c != '\0' && *c != ':') | 79 | while(*c != '\0' && *c != ':') |
83 | *p++ = *c++; | 80 | *p++ = *c++; |
84 | *p = '\0'; | 81 | *p = '\0'; |
85 | strcat(p, "/"); | 82 | strcat(p, "/"); |
86 | strcat(p, PPPDNAME); | 83 | strcat(p, PPPDNAME); |
87 | if(access(buffer, F_OK) == 0) | 84 | if(access(buffer, F_OK) == 0) |
88 | return (pppdPath = buffer); | 85 | return (pppdPath = buffer); |
89 | } | 86 | } |
90 | } | 87 | } |
91 | 88 | ||
92 | return pppdPath; | 89 | return pppdPath; |
93 | } | 90 | } |
94 | 91 | ||
95 | 92 | ||
96 | Modem::Modem( PPPData* pd ) | 93 | Modem::Modem( PPPData* pd ) |
97 | { | 94 | { |
98 | _pppdata = pd; | 95 | _pppdata = pd; |
99 | modemfd = -1; | 96 | modemfd = -1; |
100 | _pppdExitStatus = -1; | 97 | _pppdExitStatus = -1; |
101 | pppdPid = -1; | 98 | pppdPid = -1; |
102 | sn = 0L; | 99 | sn = m_modemDebug = 0L; |
103 | data_mode = false; | 100 | data_mode = false; |
104 | modem_is_locked = false; | 101 | modem_is_locked = false; |
105 | lockfile[0] = '\0'; | 102 | lockfile[0] = '\0'; |
106 | device = "/dev/modem"; | 103 | device = "/dev/modem"; |
107 | } | 104 | } |
108 | 105 | ||
109 | 106 | ||
110 | Modem::~Modem() | 107 | Modem::~Modem() |
111 | { | 108 | { |
112 | } | 109 | } |
113 | 110 | ||
114 | 111 | ||
115 | speed_t Modem::modemspeed() { | 112 | speed_t Modem::modemspeed() { |
116 | // convert the string modem speed int the gpppdata object to a t_speed type | 113 | // convert the string modem speed int the gpppdata object to a t_speed type |
117 | // to set the modem. The constants here should all be ifdef'd because | 114 | // to set the modem. The constants here should all be ifdef'd because |
118 | // other systems may not have them | 115 | // other systems may not have them |
119 | int i = _pppdata->speed().toInt()/100; | 116 | int i = _pppdata->speed().toInt()/100; |
120 | 117 | ||
121 | switch(i) { | 118 | switch(i) { |
122 | case 24: | 119 | case 24: |
123 | return B2400; | 120 | return B2400; |
124 | break; | 121 | break; |
125 | case 96: | 122 | case 96: |
126 | return B9600; | 123 | return B9600; |
127 | break; | 124 | break; |
128 | case 192: | 125 | case 192: |
129 | return B19200; | 126 | return B19200; |
130 | break; | 127 | break; |
131 | case 384: | 128 | case 384: |
132 | return B38400; | 129 | return B38400; |
133 | break; | 130 | break; |
134 | #ifdef B57600 | 131 | #ifdef B57600 |
135 | case 576: | 132 | case 576: |
136 | return B57600; | 133 | return B57600; |
137 | break; | 134 | break; |
138 | #endif | 135 | #endif |
139 | 136 | ||
140 | #ifdef B115200 | 137 | #ifdef B115200 |
141 | case 1152: | 138 | case 1152: |
142 | return B115200; | 139 | return B115200; |
143 | break; | 140 | break; |
144 | #endif | 141 | #endif |
145 | 142 | ||
146 | #ifdef B230400 | 143 | #ifdef B230400 |
147 | case 2304: | 144 | case 2304: |
148 | return B230400; | 145 | return B230400; |
149 | break; | 146 | break; |
150 | #endif | 147 | #endif |
151 | 148 | ||
152 | #ifdef B460800 | 149 | #ifdef B460800 |
153 | case 4608: | 150 | case 4608: |
154 | return B460800; | 151 | return B460800; |
155 | break; | 152 | break; |
156 | #endif | 153 | #endif |
157 | 154 | ||
158 | default: | 155 | default: |
159 | return B38400; | 156 | return B38400; |
160 | break; | 157 | break; |
161 | } | 158 | } |
162 | } | 159 | } |
163 | 160 | ||
164 | bool Modem::opentty() { | 161 | bool Modem::opentty() { |
165 | // int flags; | 162 | // int flags; |
166 | 163 | ||
167 | //begin if((modemfd = Requester::rq->openModem(gpppdata.modemDevice()))<0) { | 164 | //begin if((modemfd = Requester::rq->openModem(gpppdata.modemDevice()))<0) { |
168 | close(modemfd); | 165 | close(modemfd); |
169 | device = _pppdata->modemDevice(); | 166 | device = _pppdata->modemDevice(); |
170 | if ((modemfd = open(device, O_RDWR|O_NDELAY|O_NOCTTY)) == -1) { | 167 | if ((modemfd = open(device, O_RDWR|O_NDELAY|O_NOCTTY)) == -1) { |
171 | qDebug("error opening modem device !"); | 168 | qDebug("error opening modem device !"); |
172 | errmsg = i18n("Unable to open modem."); | 169 | errmsg = QObject::tr("Unable to open modem."); |
173 | return false; | 170 | return false; |
174 | } | 171 | } |
175 | //bend if((modemfd = Requester::rq->openModem(gpppdata.modemDevice()))<0) { | 172 | //bend if((modemfd = Requester::rq->openModem(gpppdata.modemDevice()))<0) { |
176 | //} | 173 | //} |
177 | 174 | ||
178 | #if 0 | 175 | #if 0 |
179 | if(_pppdata->UseCDLine()) { | 176 | if(_pppdata->UseCDLine()) { |
180 | if(ioctl(modemfd, TIOCMGET, &flags) == -1) { | 177 | if(ioctl(modemfd, TIOCMGET, &flags) == -1) { |
181 | errmsg = i18n("Unable to detect state of CD line."); | 178 | errmsg = QObject::tr("Unable to detect state of CD line."); |
182 | ::close(modemfd); | 179 | ::close(modemfd); |
183 | modemfd = -1; | 180 | modemfd = -1; |
184 | return false; | 181 | return false; |
185 | } | 182 | } |
186 | if ((flags&TIOCM_CD) == 0) { | 183 | if ((flags&TIOCM_CD) == 0) { |
187 | errmsg = i18n("The modem is not ready."); | 184 | errmsg = QObject::tr("The modem is not ready."); |
188 | ::close(modemfd); | 185 | ::close(modemfd); |
189 | modemfd = -1; | 186 | modemfd = -1; |
190 | return false; | 187 | return false; |
191 | } | 188 | } |
192 | } | 189 | } |
193 | #endif | 190 | #endif |
194 | 191 | ||
195 | tcdrain (modemfd); | 192 | tcdrain (modemfd); |
196 | tcflush (modemfd, TCIOFLUSH); | 193 | tcflush (modemfd, TCIOFLUSH); |
197 | 194 | ||
198 | if(tcgetattr(modemfd, &tty) < 0){ | 195 | if(tcgetattr(modemfd, &tty) < 0){ |
199 | // this helps in some cases | 196 | // this helps in some cases |
200 | tcsendbreak(modemfd, 0); | 197 | tcsendbreak(modemfd, 0); |
201 | sleep(1); | 198 | sleep(1); |
202 | if(tcgetattr(modemfd, &tty) < 0){ | 199 | if(tcgetattr(modemfd, &tty) < 0){ |
203 | errmsg = i18n("The modem is busy."); | 200 | errmsg = QObject::tr("The modem is busy."); |
204 | ::close(modemfd); | 201 | ::close(modemfd); |
205 | modemfd = -1; | 202 | modemfd = -1; |
206 | return false; | 203 | return false; |
207 | } | 204 | } |
208 | } | 205 | } |
209 | 206 | ||
210 | memset(&initial_tty,'\0',sizeof(initial_tty)); | 207 | memset(&initial_tty,'\0',sizeof(initial_tty)); |
211 | 208 | ||
212 | initial_tty = tty; | 209 | initial_tty = tty; |
213 | 210 | ||
214 | tty.c_cc[VMIN] = 0; // nonblocking | 211 | tty.c_cc[VMIN] = 0; // nonblocking |
215 | tty.c_cc[VTIME] = 0; | 212 | tty.c_cc[VTIME] = 0; |
216 | tty.c_oflag = 0; | 213 | tty.c_oflag = 0; |
217 | tty.c_lflag = 0; | 214 | tty.c_lflag = 0; |
218 | 215 | ||
219 | tty.c_cflag &= ~(CSIZE | CSTOPB | PARENB); | 216 | tty.c_cflag &= ~(CSIZE | CSTOPB | PARENB); |
220 | tty.c_cflag |= CS8 | CREAD; | 217 | tty.c_cflag |= CS8 | CREAD; |
221 | tty.c_cflag |= CLOCAL; // ignore modem status lines | 218 | tty.c_cflag |= CLOCAL; // ignore modem status lines |
222 | tty.c_iflag = IGNBRK | IGNPAR /* | ISTRIP */ ; | 219 | tty.c_iflag = IGNBRK | IGNPAR /* | ISTRIP */ ; |
223 | tty.c_lflag &= ~ICANON; // non-canonical mode | 220 | tty.c_lflag &= ~ICANON; // non-canonical mode |
224 | tty.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHOKE); | 221 | tty.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHOKE); |
225 | 222 | ||
226 | 223 | ||
227 | if(_pppdata->flowcontrol() != "None") { | 224 | if(_pppdata->flowcontrol() != "None") { |
228 | if(_pppdata->flowcontrol() == "CRTSCTS") { | 225 | if(_pppdata->flowcontrol() == "CRTSCTS") { |
229 | tty.c_cflag |= CRTSCTS; | 226 | tty.c_cflag |= CRTSCTS; |
230 | } | 227 | } |
231 | else { | 228 | else { |
232 | tty.c_iflag |= IXON | IXOFF; | 229 | tty.c_iflag |= IXON | IXOFF; |
233 | tty.c_cc[VSTOP] = 0x13; /* DC3 = XOFF = ^S */ | 230 | tty.c_cc[VSTOP] = 0x13; /* DC3 = XOFF = ^S */ |
234 | tty.c_cc[VSTART] = 0x11; /* DC1 = XON = ^Q */ | 231 | tty.c_cc[VSTART] = 0x11; /* DC1 = XON = ^Q */ |
235 | } | 232 | } |
236 | } | 233 | } |
237 | else { | 234 | else { |
238 | tty.c_cflag &= ~CRTSCTS; | 235 | tty.c_cflag &= ~CRTSCTS; |
239 | tty.c_iflag &= ~(IXON | IXOFF); | 236 | tty.c_iflag &= ~(IXON | IXOFF); |
240 | } | 237 | } |
241 | 238 | ||
242 | cfsetospeed(&tty, modemspeed()); | 239 | cfsetospeed(&tty, modemspeed()); |
243 | cfsetispeed(&tty, modemspeed()); | 240 | cfsetispeed(&tty, modemspeed()); |
244 | 241 | ||
245 | tcdrain(modemfd); | 242 | tcdrain(modemfd); |
246 | 243 | ||
247 | if(tcsetattr(modemfd, TCSANOW, &tty) < 0){ | 244 | if(tcsetattr(modemfd, TCSANOW, &tty) < 0){ |
248 | errmsg = i18n("The modem is busy."); | 245 | errmsg = QObject::tr("The modem is busy."); |
249 | ::close(modemfd); | 246 | ::close(modemfd); |
250 | modemfd=-1; | 247 | modemfd=-1; |
251 | return false; | 248 | return false; |
252 | } | 249 | } |
253 | 250 | ||
254 | errmsg = i18n("Modem Ready."); | 251 | errmsg = QObject::tr("Modem Ready."); |
255 | return true; | 252 | return true; |
256 | } | 253 | } |
257 | 254 | ||
258 | 255 | ||
259 | bool Modem::closetty() { | 256 | bool Modem::closetty() { |
260 | if(modemfd >=0 ) { | 257 | if(modemfd >=0 ) { |
261 | stop(); | 258 | stop(); |
262 | /* discard data not read or transmitted */ | 259 | /* discard data not read or transmitted */ |
263 | tcflush(modemfd, TCIOFLUSH); | 260 | tcflush(modemfd, TCIOFLUSH); |
264 | 261 | ||
265 | if(tcsetattr(modemfd, TCSANOW, &initial_tty) < 0){ | 262 | if(tcsetattr(modemfd, TCSANOW, &initial_tty) < 0){ |
266 | errmsg = i18n("Can't restore tty settings: tcsetattr()\n"); | 263 | errmsg = QObject::tr("Can't restore tty settings: tcsetattr()\n"); |
267 | ::close(modemfd); | 264 | ::close(modemfd); |
268 | modemfd = -1; | 265 | modemfd = -1; |
269 | return false; | 266 | return false; |
270 | } | 267 | } |
271 | ::close(modemfd); | 268 | ::close(modemfd); |
272 | modemfd = -1; | 269 | modemfd = -1; |
273 | } | 270 | } |
274 | 271 | ||
275 | return true; | 272 | return true; |
276 | } | 273 | } |
277 | 274 | ||
278 | 275 | ||
279 | void Modem::readtty(int) { | 276 | void Modem::readtty(int) { |
280 | char buffer[200]; | 277 | char buffer[200]; |
281 | unsigned char c; | 278 | unsigned char c; |
282 | int len; | 279 | int len; |
283 | 280 | ||
284 | // read data in chunks of up to 200 bytes | 281 | // read data in chunks of up to 200 bytes |
285 | if((len = ::read(modemfd, buffer, 200)) > 0) { | 282 | if((len = ::read(modemfd, buffer, 200)) > 0) { |
286 | // split buffer into single characters for further processing | 283 | // split buffer into single characters for further processing |
287 | for(int i = 0; i < len; i++) { | 284 | for(int i = 0; i < len; i++) { |
288 | c = buffer[i] & 0x7F; | 285 | c = buffer[i] & 0x7F; |
289 | emit charWaiting(c); | 286 | emit charWaiting(c); |
290 | } | 287 | } |
291 | } | 288 | } |
292 | } | 289 | } |
293 | 290 | ||
294 | 291 | ||
295 | void Modem::notify(const QObject *receiver, const char *member) { | 292 | void Modem::notify(const QObject *receiver, const char *member) { |
296 | connect(this, SIGNAL(charWaiting(unsigned char)), receiver, member); | 293 | connect(this, SIGNAL(charWaiting(unsigned char)), receiver, member); |
297 | startNotifier(); | 294 | startNotifier(); |
298 | } | 295 | } |
299 | 296 | ||
300 | 297 | ||
301 | void Modem::stop() { | 298 | void Modem::stop() { |
302 | disconnect(SIGNAL(charWaiting(unsigned char))); | 299 | disconnect(SIGNAL(charWaiting(unsigned char))); |
303 | stopNotifier(); | 300 | stopNotifier(); |
304 | } | 301 | } |
305 | 302 | ||
306 | 303 | ||
307 | void Modem::startNotifier() { | 304 | void Modem::startNotifier() { |
308 | if(modemfd >= 0) { | 305 | if(modemfd >= 0) { |
309 | if(sn == 0) { | 306 | if(sn == 0) { |
310 | sn = new QSocketNotifier(modemfd, QSocketNotifier::Read, this); | 307 | sn = new QSocketNotifier(modemfd, QSocketNotifier::Read, this); |
311 | connect(sn, SIGNAL(activated(int)), SLOT(readtty(int))); | 308 | connect(sn, SIGNAL(activated(int)), SLOT(readtty(int))); |
312 | qDebug("QSocketNotifier started!"); | 309 | qDebug("QSocketNotifier started!"); |
313 | } else { | 310 | } else { |
314 | qDebug("QSocketNotifier re-enabled!"); | 311 | qDebug("QSocketNotifier re-enabled!"); |
315 | sn->setEnabled(true); | 312 | sn->setEnabled(true); |
316 | } | 313 | } |
317 | } | 314 | } |
318 | } | 315 | } |
319 | 316 | ||
320 | 317 | ||
321 | void Modem::stopNotifier() { | 318 | void Modem::stopNotifier() { |
322 | if(sn != 0) { | 319 | if(sn != 0) { |
323 | sn->setEnabled(false); | 320 | sn->setEnabled(false); |
324 | disconnect(sn); | 321 | disconnect(sn); |
325 | delete sn; | 322 | delete sn; |
326 | sn = 0; | 323 | sn = 0; |
327 | qDebug( "QSocketNotifier stopped!" ); | 324 | qDebug( "QSocketNotifier stopped!" ); |
328 | } | 325 | } |
329 | } | 326 | } |
330 | 327 | ||
331 | 328 | ||
332 | void Modem::flush() { | 329 | void Modem::flush() { |
333 | char c; | 330 | char c; |
334 | while(read(modemfd, &c, 1) == 1); | 331 | while(read(modemfd, &c, 1) == 1); |
335 | } | 332 | } |
336 | 333 | ||
337 | 334 | ||
338 | bool Modem::writeChar(unsigned char c) { | 335 | bool Modem::writeChar(unsigned char c) { |
339 | int s; | 336 | int s; |
340 | do { | 337 | do { |
341 | s = write(modemfd, &c, 1); | 338 | s = write(modemfd, &c, 1); |
342 | if (s < 0) { | 339 | if (s < 0) { |
343 | qError( "write() in Modem::writeChar failed" ); | 340 | qError( "write() in Modem::writeChar failed" ); |
344 | return false; | 341 | return false; |
345 | } | 342 | } |
346 | } while(s == 0); | 343 | } while(s == 0); |
347 | 344 | ||
348 | return true; | 345 | return true; |
349 | } | 346 | } |
350 | 347 | ||
351 | 348 | ||
352 | bool Modem::writeLine(const char *buf) { | 349 | bool Modem::writeLine(const char *buf) { |
353 | int len = strlen(buf); | 350 | int len = strlen(buf); |
354 | char *b = new char[len+2]; | 351 | char *b = new char[len+2]; |
355 | memcpy(b, buf, len); | 352 | memcpy(b, buf, len); |
356 | // different modems seem to need different line terminations | 353 | // different modems seem to need different line terminations |
357 | QString term = _pppdata->enter(); | 354 | QString term = _pppdata->enter(); |
358 | if(term == "LF") | 355 | if(term == "LF") |
359 | b[len++]='\n'; | 356 | b[len++]='\n'; |
360 | else if(term == "CR") | 357 | else if(term == "CR") |
361 | b[len++]='\r'; | 358 | b[len++]='\r'; |
362 | else if(term == "CR/LF") { | 359 | else if(term == "CR/LF") { |
363 | b[len++]='\r'; | 360 | b[len++]='\r'; |
364 | b[len++]='\n'; | 361 | b[len++]='\n'; |
365 | } | 362 | } |
366 | int l = len; | 363 | int l = len; |
367 | while(l) { | 364 | while(l) { |
368 | int wr = write(modemfd, &b[len-l], l); | 365 | int wr = write(modemfd, &b[len-l], l); |
369 | if(wr < 0) { | 366 | if(wr < 0) { |
370 | // TODO do something meaningful with the error code (or ignore it | 367 | // TODO do something meaningful with the error code (or ignore it |
371 | qError( "write() in Modem::writeLine failed" ); | 368 | qError( "write() in Modem::writeLine failed" ); |
372 | delete[] b; | 369 | delete[] b; |
373 | return false; | 370 | return false; |
374 | } | 371 | } |
375 | l -= wr; | 372 | l -= wr; |
376 | } | 373 | } |
377 | delete[] b; | 374 | delete[] b; |
378 | return true; | 375 | return true; |
379 | } | 376 | } |
380 | 377 | ||
381 | 378 | ||
382 | bool Modem::hangup() { | 379 | bool Modem::hangup() { |
383 | // this should really get the modem to hang up and go into command mode | 380 | // this should really get the modem to hang up and go into command mode |
384 | // If anyone sees a fault in the following please let me know, since | 381 | // If anyone sees a fault in the following please let me know, since |
385 | // this is probably the most imporant snippet of code in the whole of | 382 | // this is probably the most imporant snippet of code in the whole of |
386 | // kppp. If people complain about kppp being stuck, this piece of code | 383 | // kppp. If people complain about kppp being stuck, this piece of code |
387 | // is most likely the reason. | 384 | // is most likely the reason. |
388 | struct termios temptty; | 385 | struct termios temptty; |
389 | 386 | ||
390 | if(modemfd >= 0) { | 387 | if(modemfd >= 0) { |
391 | 388 | ||
392 | // is this Escape & HangupStr stuff really necessary ? (Harri) | 389 | // is this Escape & HangupStr stuff really necessary ? (Harri) |
393 | 390 | ||
394 | if (data_mode) escape_to_command_mode(); | 391 | if (data_mode) escape_to_command_mode(); |
395 | 392 | ||
396 | // Then hangup command | 393 | // Then hangup command |
397 | writeLine(_pppdata->modemHangupStr().local8Bit()); | 394 | writeLine(_pppdata->modemHangupStr().local8Bit()); |
398 | 395 | ||
399 | usleep(_pppdata->modemInitDelay() * 10000); // 0.01 - 3.0 sec | 396 | usleep(_pppdata->modemInitDelay() * 10000); // 0.01 - 3.0 sec |
400 | 397 | ||
401 | #ifndef DEBUG_WO_DIALING | 398 | #ifndef DEBUG_WO_DIALING |
402 | if (sigsetjmp(jmp_buffer, 1) == 0) { | 399 | if (sigsetjmp(jmp_buffer, 1) == 0) { |
403 | // set alarm in case tcsendbreak() hangs | 400 | // set alarm in case tcsendbreak() hangs |
404 | signal(SIGALRM, alarm_handler); | 401 | signal(SIGALRM, alarm_handler); |
405 | alarm(2); | 402 | alarm(2); |
406 | 403 | ||
407 | tcsendbreak(modemfd, 0); | 404 | tcsendbreak(modemfd, 0); |
408 | 405 | ||
409 | alarm(0); | 406 | alarm(0); |
410 | signal(SIGALRM, SIG_IGN); | 407 | signal(SIGALRM, SIG_IGN); |
411 | } else { | 408 | } else { |
412 | // we reach this point if the alarm handler got called | 409 | // we reach this point if the alarm handler got called |
413 | closetty(); | 410 | closetty(); |
414 | close(modemfd); | 411 | close(modemfd); |
415 | modemfd = -1; | 412 | modemfd = -1; |
416 | errmsg = i18n("The modem does not respond."); | 413 | errmsg = QObject::tr("The modem does not respond."); |
417 | return false; | 414 | return false; |
418 | } | 415 | } |
419 | 416 | ||
420 | #ifndef __svr4__ // drops DTR but doesn't set it afterwards again. not good for init. | 417 | #ifndef __svr4__ // drops DTR but doesn't set it afterwards again. not good for init. |
421 | tcgetattr(modemfd, &temptty); | 418 | tcgetattr(modemfd, &temptty); |
422 | cfsetospeed(&temptty, B0); | 419 | cfsetospeed(&temptty, B0); |
423 | cfsetispeed(&temptty, B0); | 420 | cfsetispeed(&temptty, B0); |
424 | tcsetattr(modemfd, TCSAFLUSH, &temptty); | 421 | tcsetattr(modemfd, TCSAFLUSH, &temptty); |
425 | #else | 422 | #else |
426 | int modemstat; | 423 | int modemstat; |
427 | ioctl(modemfd, TIOCMGET, &modemstat); | 424 | ioctl(modemfd, TIOCMGET, &modemstat); |
428 | modemstat &= ~TIOCM_DTR; | 425 | modemstat &= ~TIOCM_DTR; |
429 | ioctl(modemfd, TIOCMSET, &modemstat); | 426 | ioctl(modemfd, TIOCMSET, &modemstat); |
430 | ioctl(modemfd, TIOCMGET, &modemstat); | 427 | ioctl(modemfd, TIOCMGET, &modemstat); |
431 | modemstat |= TIOCM_DTR; | 428 | modemstat |= TIOCM_DTR; |
432 | ioctl(modemfd, TIOCMSET, &modemstat); | 429 | ioctl(modemfd, TIOCMSET, &modemstat); |
433 | #endif | 430 | #endif |
434 | 431 | ||
435 | usleep(_pppdata->modemInitDelay() * 10000); // 0.01 - 3.0 secs | 432 | usleep(_pppdata->modemInitDelay() * 10000); // 0.01 - 3.0 secs |
436 | 433 | ||
437 | cfsetospeed(&temptty, modemspeed()); | 434 | cfsetospeed(&temptty, modemspeed()); |
438 | cfsetispeed(&temptty, modemspeed()); | 435 | cfsetispeed(&temptty, modemspeed()); |
439 | tcsetattr(modemfd, TCSAFLUSH, &temptty); | 436 | tcsetattr(modemfd, TCSAFLUSH, &temptty); |
440 | #endif | 437 | #endif |
441 | return true; | 438 | return true; |
442 | } else | 439 | } else |
443 | return false; | 440 | return false; |
444 | } | 441 | } |
445 | 442 | ||
446 | 443 | ||
447 | void Modem::escape_to_command_mode() { | 444 | void Modem::escape_to_command_mode() { |
448 | // Send Properly bracketed escape code to put the modem back into command state. | 445 | // Send Properly bracketed escape code to put the modem back into command state. |
449 | // A modem will accept AT commands only when it is in command state. | 446 | // A modem will accept AT commands only when it is in command state. |
450 | // When a modem sends the host the CONNECT string, that signals | 447 | // When a modem sends the host the CONNECT string, that signals |
451 | // that the modem is now in the connect state (no long accepts AT commands.) | 448 | // that the modem is now in the connect state (no long accepts AT commands.) |
452 | // Need to send properly timed escape sequence to put modem in command state. | 449 | // Need to send properly timed escape sequence to put modem in command state. |
453 | // Escape codes and guard times are controlled by S2 and S12 values. | 450 | // Escape codes and guard times are controlled by S2 and S12 values. |
454 | // | 451 | // |
455 | tcflush(modemfd, TCIOFLUSH); | 452 | tcflush(modemfd, TCIOFLUSH); |
456 | 453 | ||
457 | // +3 because quiet time must be greater than guard time. | 454 | // +3 because quiet time must be greater than guard time. |
458 | usleep((_pppdata->modemEscapeGuardTime()+3)*20000); | 455 | usleep((_pppdata->modemEscapeGuardTime()+3)*20000); |
459 | QCString tmp = _pppdata->modemEscapeStr().local8Bit(); | 456 | QCString tmp = _pppdata->modemEscapeStr().local8Bit(); |
460 | write(modemfd, tmp.data(), tmp.length()); | 457 | write(modemfd, tmp.data(), tmp.length()); |
461 | tcflush(modemfd, TCIOFLUSH); | 458 | tcflush(modemfd, TCIOFLUSH); |
462 | usleep((_pppdata->modemEscapeGuardTime()+3)*20000); | 459 | usleep((_pppdata->modemEscapeGuardTime()+3)*20000); |
463 | 460 | ||
464 | data_mode = false; | 461 | data_mode = false; |
465 | } | 462 | } |
466 | 463 | ||
467 | 464 | ||
468 | const QString Modem::modemMessage() { | 465 | const QString Modem::modemMessage() { |
469 | return errmsg; | 466 | return errmsg; |
470 | } | 467 | } |
471 | 468 | ||
472 | 469 | ||
473 | QString Modem::parseModemSpeed(const QString &s) { | 470 | QString Modem::parseModemSpeed(const QString &s) { |
474 | // this is a small (and bad) parser for modem speeds | 471 | // this is a small (and bad) parser for modem speeds |
475 | int rx = -1; | 472 | int rx = -1; |
476 | int tx = -1; | 473 | int tx = -1; |
477 | int i; | 474 | int i; |
478 | QString result; | 475 | QString result; |
479 | 476 | ||
480 | qDebug( "Modem reported result string: %s", s.latin1()); | 477 | qDebug( "Modem reported result string: %s", s.latin1()); |
481 | 478 | ||
482 | const int RXMAX = 7; | 479 | const int RXMAX = 7; |
483 | const int TXMAX = 2; | 480 | const int TXMAX = 2; |
484 | QRegExp rrx[RXMAX] = { | 481 | QRegExp rrx[RXMAX] = { |
485 | QRegExp("[0-9]+[:/ ]RX", false), | 482 | QRegExp("[0-9]+[:/ ]RX", false), |
486 | QRegExp("[0-9]+RX", false), | 483 | QRegExp("[0-9]+RX", false), |
487 | QRegExp("[/: -][0-9]+[/: ]", false), | 484 | QRegExp("[/: -][0-9]+[/: ]", false), |
488 | QRegExp("[/: -][0-9]+$", false), | 485 | QRegExp("[/: -][0-9]+$", false), |
489 | QRegExp("CARRIER [^0-9]*[0-9]+", false), | 486 | QRegExp("CARRIER [^0-9]*[0-9]+", false), |
490 | QRegExp("CONNECT [^0-9]*[0-9]+", false), | 487 | QRegExp("CONNECT [^0-9]*[0-9]+", false), |
491 | QRegExp("[0-9]+") // panic mode | 488 | QRegExp("[0-9]+") // panic mode |
492 | }; | 489 | }; |
493 | 490 | ||
494 | QRegExp trx[TXMAX] = { | 491 | QRegExp trx[TXMAX] = { |
495 | QRegExp("[0-9]+[:/ ]TX", false), | 492 | QRegExp("[0-9]+[:/ ]TX", false), |
496 | QRegExp("[0-9]+TX", false) | 493 | QRegExp("[0-9]+TX", false) |
497 | }; | 494 | }; |
498 | 495 | ||
499 | for(i = 0; i < RXMAX; i++) { | 496 | for(i = 0; i < RXMAX; i++) { |
500 | int len, idx, result; | 497 | int len, idx, result; |
501 | if((idx = rrx[i].match(s,0,&len)) > -1) { | 498 | if((idx = rrx[i].match(s,0,&len)) > -1) { |
502 | // if((idx = rrx[i].search(s)) > -1) { | 499 | // if((idx = rrx[i].search(s)) > -1) { |
503 | // len = rrx[i].matchedLength(); | 500 | // len = rrx[i].matchedLength(); |
504 | 501 | ||
505 | // | 502 | // |
506 | // rrx[i] has been matched, idx contains the start of the match | 503 | // rrx[i] has been matched, idx contains the start of the match |
507 | // and len contains how long the match is. Extract the match. | 504 | // and len contains how long the match is. Extract the match. |
508 | // | 505 | // |
509 | QString sub = s.mid(idx, len); | 506 | QString sub = s.mid(idx, len); |
510 | 507 | ||
511 | // | 508 | // |
512 | // Now extract the digits only from the match, which will | 509 | // Now extract the digits only from the match, which will |
513 | // then be converted to an int. | 510 | // then be converted to an int. |
514 | // | 511 | // |
515 | if ((idx = rrx[RXMAX-1].match( sub,0,&len )) > -1) { | 512 | if ((idx = rrx[RXMAX-1].match( sub,0,&len )) > -1) { |
516 | // if ((idx = rrx[RXMAX-1].search( sub )) > -1) { | 513 | // if ((idx = rrx[RXMAX-1].search( sub )) > -1) { |
517 | // len = rrx[RXMAX-1].matchedLength(); | 514 | // len = rrx[RXMAX-1].matchedLength(); |
518 | sub = sub.mid(idx, len); | 515 | sub = sub.mid(idx, len); |
519 | result = sub.toInt(); | 516 | result = sub.toInt(); |
520 | if(result > 0) { | 517 | if(result > 0) { |
521 | rx = result; | 518 | rx = result; |
522 | break; | 519 | break; |
523 | } | 520 | } |
524 | } | 521 | } |
525 | } | 522 | } |
526 | } | 523 | } |
527 | 524 | ||
528 | for(i = 0; i < TXMAX; i++) { | 525 | for(i = 0; i < TXMAX; i++) { |
529 | int len, idx, result; | 526 | int len, idx, result; |
530 | if((idx = trx[i].match(s,0,&len)) > -1) { | 527 | if((idx = trx[i].match(s,0,&len)) > -1) { |
531 | // if((idx = trx[i].search(s)) > -1) { | 528 | // if((idx = trx[i].search(s)) > -1) { |
532 | // len = trx[i].matchedLength(); | 529 | // len = trx[i].matchedLength(); |
533 | 530 | ||
534 | // | 531 | // |
535 | // trx[i] has been matched, idx contains the start of the match | 532 | // trx[i] has been matched, idx contains the start of the match |
536 | // and len contains how long the match is. Extract the match. | 533 | // and len contains how long the match is. Extract the match. |
537 | // | 534 | // |
538 | QString sub = s.mid(idx, len); | 535 | QString sub = s.mid(idx, len); |
539 | 536 | ||
540 | // | 537 | // |
541 | // Now extract the digits only from the match, which will then | 538 | // Now extract the digits only from the match, which will then |
542 | // be converted to an int. | 539 | // be converted to an int. |
543 | // | 540 | // |
544 | if((idx = rrx[RXMAX-1].match(sub,0,&len)) > -1) { | 541 | if((idx = rrx[RXMAX-1].match(sub,0,&len)) > -1) { |
545 | // if((idx = rrx[RXMAX-1].search(sub)) > -1) { | 542 | // if((idx = rrx[RXMAX-1].search(sub)) > -1) { |
546 | // len = rrx[RXMAX-1].matchedLength(); | 543 | // len = rrx[RXMAX-1].matchedLength(); |
547 | sub = sub.mid(idx, len); | 544 | sub = sub.mid(idx, len); |
548 | result = sub.toInt(); | 545 | result = sub.toInt(); |
549 | if(result > 0) { | 546 | if(result > 0) { |
550 | tx = result; | 547 | tx = result; |
551 | break; | 548 | break; |
552 | } | 549 | } |
553 | } | 550 | } |
554 | } | 551 | } |
555 | } | 552 | } |
556 | 553 | ||
557 | if(rx == -1 && tx == -1) | 554 | if(rx == -1 && tx == -1) |
558 | result = i18n("Unknown speed"); | 555 | result = QObject::tr("Unknown speed"); |
559 | else if(tx == -1) | 556 | else if(tx == -1) |
560 | result.setNum(rx); | 557 | result.setNum(rx); |
561 | else if(rx == -1) // should not happen | 558 | else if(rx == -1) // should not happen |
562 | result.setNum(tx); | 559 | result.setNum(tx); |
563 | else | 560 | else |
564 | result.sprintf("%d/%d", rx, tx); | 561 | result.sprintf("%d/%d", rx, tx); |
565 | 562 | ||
566 | qDebug( "The parsed result is: %s", result.latin1()); | 563 | qDebug( "The parsed result is: %s", result.latin1()); |
567 | 564 | ||
568 | return result; | 565 | return result; |
569 | } | 566 | } |
570 | 567 | ||
571 | 568 | ||
572 | // Lock modem device. Returns 0 on success 1 if the modem is locked and -1 if | 569 | // Lock modem device. Returns 0 on success 1 if the modem is locked and -1 if |
573 | // a lock file can't be created ( permission problem ) | 570 | // a lock file can't be created ( permission problem ) |
574 | int Modem::lockdevice() { | 571 | int Modem::lockdevice() { |
575 | int fd; | 572 | int fd; |
576 | char newlock[80]=""; // safe | 573 | char newlock[80]=""; // safe |
577 | 574 | ||
578 | if(!_pppdata->modemLockFile()) { | 575 | if(!_pppdata->modemLockFile()) { |
579 | qDebug("The user doesn't want a lockfile."); | 576 | qDebug("The user doesn't want a lockfile."); |
580 | return 0; | 577 | return 0; |
581 | } | 578 | } |
582 | 579 | ||
583 | if (modem_is_locked) | 580 | if (modem_is_locked) |
584 | return 1; | 581 | return 1; |
585 | 582 | ||
586 | QString lockfile = LOCK_DIR"/LCK.."; | 583 | QString lockfile = LOCK_DIR"/LCK.."; |
587 | lockfile += _pppdata->modemDevice().mid(5); // append everything after /dev/ | 584 | lockfile += _pppdata->modemDevice().mid(5); // append everything after /dev/ |
588 | 585 | ||
589 | if(access(QFile::encodeName(lockfile), F_OK) == 0) { | 586 | if(access(QFile::encodeName(lockfile), F_OK) == 0) { |
590 | // if ((fd = Requester::rq-> | 587 | // if ((fd = Requester::rq-> |
591 | if ((fd = openLockfile(QFile::encodeName(lockfile), O_RDONLY)) >= 0) { | 588 | if ((fd = openLockfile(QFile::encodeName(lockfile), O_RDONLY)) >= 0) { |
592 | // Mario: it's not necessary to read more than lets say 32 bytes. If | 589 | // Mario: it's not necessary to read more than lets say 32 bytes. If |
593 | // file has more than 32 bytes, skip the rest | 590 | // file has more than 32 bytes, skip the rest |
594 | char oldlock[33]; // safe | 591 | char oldlock[33]; // safe |
595 | int sz = read(fd, &oldlock, 32); | 592 | int sz = read(fd, &oldlock, 32); |
596 | close (fd); | 593 | close (fd); |
597 | if (sz <= 0) | 594 | if (sz <= 0) |
598 | return 1; | 595 | return 1; |
599 | oldlock[sz] = '\0'; | 596 | oldlock[sz] = '\0'; |
600 | 597 | ||
601 | qDebug( "Device is locked by: %s", oldlock); | 598 | qDebug( "Device is locked by: %s", oldlock); |
602 | 599 | ||
603 | int oldpid; | 600 | int oldpid; |
604 | int match = sscanf(oldlock, "%d", &oldpid); | 601 | int match = sscanf(oldlock, "%d", &oldpid); |
605 | 602 | ||
606 | // found a pid in lockfile ? | 603 | // found a pid in lockfile ? |
607 | if (match < 1 || oldpid <= 0) | 604 | if (match < 1 || oldpid <= 0) |
608 | return 1; | 605 | return 1; |
609 | 606 | ||
610 | // check if process exists | 607 | // check if process exists |
611 | if (kill((pid_t)oldpid, 0) == 0 || errno != ESRCH) | 608 | if (kill((pid_t)oldpid, 0) == 0 || errno != ESRCH) |
612 | return 1; | 609 | return 1; |
613 | 610 | ||
614 | qDebug( "lockfile is stale" ); | 611 | qDebug( "lockfile is stale" ); |
615 | } | 612 | } |
616 | } | 613 | } |
617 | 614 | ||
618 | fd = openLockfile(_pppdata->modemDevice(),O_WRONLY|O_TRUNC|O_CREAT); | 615 | fd = openLockfile(_pppdata->modemDevice(),O_WRONLY|O_TRUNC|O_CREAT); |
619 | if(fd >= 0) { | 616 | if(fd >= 0) { |
620 | sprintf(newlock,"%010d\n", getpid()); | 617 | sprintf(newlock,"%010d\n", getpid()); |
621 | qDebug("Locking Device: %s", newlock); | 618 | qDebug("Locking Device: %s", newlock); |
622 | 619 | ||
623 | write(fd, newlock, strlen(newlock)); | 620 | write(fd, newlock, strlen(newlock)); |
624 | close(fd); | 621 | close(fd); |
625 | modem_is_locked=true; | 622 | modem_is_locked=true; |
626 | 623 | ||
627 | return 0; | 624 | return 0; |
628 | } | 625 | } |
629 | 626 | ||
630 | return -1; | 627 | return -1; |
631 | 628 | ||
632 | } | 629 | } |
633 | 630 | ||
634 | 631 | ||
635 | // UnLock modem device | 632 | // UnLock modem device |
636 | void Modem::unlockdevice() { | 633 | void Modem::unlockdevice() { |
637 | if (modem_is_locked) { | 634 | if (modem_is_locked) { |
638 | qDebug( "UnLocking Modem Device" ); | 635 | qDebug( "UnLocking Modem Device" ); |
639 | close(modemfd); | 636 | close(modemfd); |
640 | modemfd = -1; | 637 | modemfd = -1; |
641 | unlink(lockfile); | 638 | unlink(lockfile); |
642 | lockfile[0] = '\0'; | 639 | lockfile[0] = '\0'; |
643 | modem_is_locked=false; | 640 | modem_is_locked=false; |
644 | } | 641 | } |
645 | } | 642 | } |
646 | 643 | ||
647 | int Modem::openLockfile( QString lockfile, int flags) | 644 | int Modem::openLockfile( QString lockfile, int flags) |
648 | { | 645 | { |
649 | int fd; | 646 | int fd; |
650 | int mode; | 647 | int mode; |
651 | flags = O_RDONLY; | 648 | flags = O_RDONLY; |
652 | if(flags == O_WRONLY|O_TRUNC|O_CREAT) | 649 | if(flags == O_WRONLY|O_TRUNC|O_CREAT) |
653 | mode = 0644; | 650 | mode = 0644; |
654 | else | 651 | else |
@@ -784,240 +781,300 @@ bool Modem::removeAuthFile(Auth method) { | |||
784 | } else | 781 | } else |
785 | return false; | 782 | return false; |
786 | } | 783 | } |
787 | 784 | ||
788 | 785 | ||
789 | bool Modem::setSecret(int method, const char* name, const char* password) | 786 | bool Modem::setSecret(int method, const char* name, const char* password) |
790 | { | 787 | { |
791 | 788 | ||
792 | Auth auth; | 789 | Auth auth; |
793 | if(method == AUTH_PAPCHAP) | 790 | if(method == AUTH_PAPCHAP) |
794 | return setSecret(AUTH_PAP, name, password) && | 791 | return setSecret(AUTH_PAP, name, password) && |
795 | setSecret(AUTH_CHAP, name, password); | 792 | setSecret(AUTH_CHAP, name, password); |
796 | 793 | ||
797 | switch(method) { | 794 | switch(method) { |
798 | case AUTH_PAP: | 795 | case AUTH_PAP: |
799 | auth = Modem::PAP; | 796 | auth = Modem::PAP; |
800 | break; | 797 | break; |
801 | case AUTH_CHAP: | 798 | case AUTH_CHAP: |
802 | auth = Modem::CHAP; | 799 | auth = Modem::CHAP; |
803 | break; | 800 | break; |
804 | default: | 801 | default: |
805 | return false; | 802 | return false; |
806 | } | 803 | } |
807 | 804 | ||
808 | return createAuthFile(auth, name, password); | 805 | return createAuthFile(auth, name, password); |
809 | 806 | ||
810 | } | 807 | } |
811 | 808 | ||
812 | bool Modem::removeSecret(int method) | 809 | bool Modem::removeSecret(int method) |
813 | { | 810 | { |
814 | Auth auth; | 811 | Auth auth; |
815 | 812 | ||
816 | switch(method) { | 813 | switch(method) { |
817 | case AUTH_PAP: | 814 | case AUTH_PAP: |
818 | auth = Modem::PAP; | 815 | auth = Modem::PAP; |
819 | break; | 816 | break; |
820 | case AUTH_CHAP: | 817 | case AUTH_CHAP: |
821 | auth = Modem::CHAP; | 818 | auth = Modem::CHAP; |
822 | break; | 819 | break; |
823 | default: | 820 | default: |
824 | return false; | 821 | return false; |
825 | } | 822 | } |
826 | return removeAuthFile( auth ); | 823 | return removeAuthFile( auth ); |
827 | } | 824 | } |
828 | 825 | ||
829 | int checkForInterface() | 826 | int checkForInterface() |
830 | { | 827 | { |
831 | // I don't know if Linux needs more initialization to get the ioctl to | 828 | // I don't know if Linux needs more initialization to get the ioctl to |
832 | // work, pppd seems to hint it does. But BSD doesn't, and the following | 829 | // work, pppd seems to hint it does. But BSD doesn't, and the following |
833 | // code should compile. | 830 | // code should compile. |
834 | #if (defined(HAVE_NET_IF_PPP_H) || defined(HAVE_LINUX_IF_PPP_H)) && !defined(__svr4__) | 831 | #if (defined(HAVE_NET_IF_PPP_H) || defined(HAVE_LINUX_IF_PPP_H)) && !defined(__svr4__) |
835 | int s, ok; | 832 | int s, ok; |
836 | struct ifreq ifr; | 833 | struct ifreq ifr; |
837 | // extern char *no_ppp_msg; | 834 | // extern char *no_ppp_msg; |
838 | 835 | ||
839 | if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) | 836 | if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) |
840 | return 1; /* can't tell */ | 837 | return 1; /* can't tell */ |
841 | 838 | ||
842 | strlcpy(ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name)); | 839 | strlcpy(ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name)); |
843 | ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0; | 840 | ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0; |
844 | close(s); | 841 | close(s); |
845 | 842 | ||
846 | if (ok == -1) { | 843 | if (ok == -1) { |
847 | // This is ifdef'd FreeBSD, because FreeBSD is the only BSD that supports | 844 | // This is ifdef'd FreeBSD, because FreeBSD is the only BSD that supports |
848 | // KLDs, the old LKM interface couldn't handle loading devices | 845 | // KLDs, the old LKM interface couldn't handle loading devices |
849 | // dynamically, and thus can't load ppp support on the fly | 846 | // dynamically, and thus can't load ppp support on the fly |
850 | #ifdef __FreeBSD__ | 847 | #ifdef __FreeBSD__ |
851 | // If we failed to load ppp support and don't have it already. | 848 | // If we failed to load ppp support and don't have it already. |
852 | if (kldload("if_ppp") == -1) { | 849 | if (kldload("if_ppp") == -1) { |
853 | return -1; | 850 | return -1; |
854 | } | 851 | } |
855 | return 0; | 852 | return 0; |
856 | #else | 853 | #else |
857 | return -1; | 854 | return -1; |
858 | #endif | 855 | #endif |
859 | } | 856 | } |
860 | return 0; | 857 | return 0; |
861 | #else | 858 | #else |
862 | // We attempt to use the SunOS/SysVr4 method and stat /dev/ppp | 859 | // We attempt to use the SunOS/SysVr4 method and stat /dev/ppp |
863 | struct stat buf; | 860 | struct stat buf; |
864 | 861 | ||
865 | memset(&buf, 0, sizeof(buf)); | 862 | memset(&buf, 0, sizeof(buf)); |
866 | return stat("/dev/ppp", &buf); | 863 | return stat("/dev/ppp", &buf); |
867 | #endif | 864 | #endif |
868 | } | 865 | } |
869 | 866 | ||
870 | bool Modem::execpppd(const char *arguments) { | 867 | bool Modem::execpppd(const char *arguments) { |
871 | char buf[MAX_CMDLEN]; | 868 | char buf[MAX_CMDLEN]; |
872 | char *args[MaxArgs]; | 869 | char *args[MaxArgs]; |
873 | pid_t pgrpid; | 870 | pid_t pgrpid; |
874 | 871 | ||
875 | if(modemfd<0) | 872 | if(modemfd<0) |
876 | return false; | 873 | return false; |
877 | 874 | ||
878 | _pppdExitStatus = -1; | 875 | _pppdExitStatus = -1; |
879 | 876 | ||
877 | (void)::pipe( m_pppdLOG ); | ||
878 | |||
880 | switch(pppdPid = fork()) | 879 | switch(pppdPid = fork()) |
881 | { | 880 | { |
882 | case -1: | 881 | case -1: |
883 | fprintf(stderr,"In parent: fork() failed\n"); | 882 | fprintf(stderr,"In parent: fork() failed\n"); |
883 | ::close( m_pppdLOG[0] ); | ||
884 | ::close( m_pppdLOG[1] ); | ||
884 | return false; | 885 | return false; |
885 | break; | 886 | break; |
886 | 887 | ||
887 | case 0: | 888 | case 0: |
888 | // let's parse the arguments the user supplied into UNIX suitable form | 889 | // let's parse the arguments the user supplied into UNIX suitable form |
889 | // that is a list of pointers each pointing to exactly one word | 890 | // that is a list of pointers each pointing to exactly one word |
890 | strlcpy(buf, arguments); | 891 | strlcpy(buf, arguments); |
891 | parseargs(buf, args); | 892 | parseargs(buf, args); |
892 | // become a session leader and let /dev/ttySx | 893 | // become a session leader and let /dev/ttySx |
893 | // be the controlling terminal. | 894 | // be the controlling terminal. |
894 | pgrpid = setsid(); | 895 | pgrpid = setsid(); |
895 | #ifdef TIOCSCTTY | 896 | #ifdef TIOCSCTTY |
896 | if(ioctl(modemfd, TIOCSCTTY, 0)<0) | 897 | if(ioctl(modemfd, TIOCSCTTY, 0)<0) |
897 | fprintf(stderr, "ioctl() failed.\n"); | 898 | fprintf(stderr, "ioctl() failed.\n"); |
898 | #elif defined (TIOCSPGRP) | 899 | #elif defined (TIOCSPGRP) |
899 | if(ioctl(modemfd, TIOCSPGRP, &pgrpid)<0) | 900 | if(ioctl(modemfd, TIOCSPGRP, &pgrpid)<0) |
900 | fprintf(stderr, "ioctl() failed.\n"); | 901 | fprintf(stderr, "ioctl() failed.\n"); |
901 | #endif | 902 | #endif |
902 | if(tcsetpgrp(modemfd, pgrpid)<0) | 903 | if(tcsetpgrp(modemfd, pgrpid)<0) |
903 | fprintf(stderr, "tcsetpgrp() failed.\n"); | 904 | fprintf(stderr, "tcsetpgrp() failed.\n"); |
904 | 905 | ||
906 | ::close( m_pppdLOG[0] ); | ||
907 | ::setenv( "LANG", "C", 1 ); // overwrite | ||
908 | dup2(m_pppdLOG[1], 11 ); // for logfd 11 | ||
905 | dup2(modemfd, 0); | 909 | dup2(modemfd, 0); |
906 | dup2(modemfd, 1); | 910 | dup2(modemfd, 1); |
907 | 911 | ||
912 | |||
908 | switch (checkForInterface()) { | 913 | switch (checkForInterface()) { |
909 | case 1: | 914 | case 1: |
910 | fprintf(stderr, "Cannot determine if kernel supports ppp.\n"); | 915 | fprintf(stderr, "Cannot determine if kernel supports ppp.\n"); |
911 | break; | 916 | break; |
912 | case -1: | 917 | case -1: |
913 | fprintf(stderr, "Kernel does not support ppp, oops.\n"); | 918 | fprintf(stderr, "Kernel does not support ppp, oops.\n"); |
914 | break; | 919 | break; |
915 | case 0: | 920 | case 0: |
916 | fprintf(stderr, "Kernel supports ppp alright.\n"); | 921 | fprintf(stderr, "Kernel supports ppp alright.\n"); |
917 | break; | 922 | break; |
918 | } | 923 | } |
919 | 924 | ||
920 | execve(pppdPath(), args, 0L); | 925 | execve(pppdPath(), args, 0L); |
921 | _exit(0); | 926 | _exit(0); |
922 | break; | 927 | break; |
923 | 928 | ||
924 | default: | 929 | default: |
925 | qDebug("In parent: pppd pid %d\n",pppdPid); | 930 | qDebug("In parent: pppd pid %d\n",pppdPid); |
926 | close(modemfd); | 931 | close(modemfd); |
932 | |||
933 | ::close( m_pppdLOG[1] ); | ||
934 | // set it to nonblocking io | ||
935 | int flag = ::fcntl( m_pppdLOG[0], F_GETFL ); | ||
936 | |||
937 | if ( !(flag & O_NONBLOCK) ) { | ||
938 | qDebug("Setting nonblocking io"); | ||
939 | flag |= O_NONBLOCK; | ||
940 | ::fcntl(m_pppdLOG[0], F_SETFL, flag ); | ||
941 | } | ||
942 | |||
943 | delete m_modemDebug; | ||
944 | m_modemDebug = new QSocketNotifier(m_pppdLOG[0], QSocketNotifier::Read, this ); | ||
945 | connect(m_modemDebug, SIGNAL(activated(int) ), | ||
946 | this, SLOT(slotModemDebug(int) ) ); | ||
947 | |||
927 | modemfd = -1; | 948 | modemfd = -1; |
949 | m_pppdDev = QString::fromLatin1("ppp0"); | ||
928 | return true; | 950 | return true; |
929 | break; | 951 | break; |
930 | } | 952 | } |
931 | } | 953 | } |
932 | 954 | ||
933 | 955 | ||
934 | bool Modem::killpppd() { | 956 | bool Modem::killpppd() { |
957 | qDebug("In killpppd and pid is %d", pppdPid ); | ||
935 | if(pppdPid > 0) { | 958 | if(pppdPid > 0) { |
959 | delete m_modemDebug; | ||
960 | m_modemDebug = 0; | ||
936 | qDebug("In killpppd(): Sending SIGTERM to %d\n", pppdPid); | 961 | qDebug("In killpppd(): Sending SIGTERM to %d\n", pppdPid); |
937 | if(kill(pppdPid, SIGTERM) < 0) { | 962 | if(kill(pppdPid, SIGTERM) < 0) { |
938 | qDebug("Error terminating %d. Sending SIGKILL\n", pppdPid); | 963 | qDebug("Error terminating %d. Sending SIGKILL\n", pppdPid); |
939 | if(kill(pppdPid, SIGKILL) < 0) { | 964 | if(kill(pppdPid, SIGKILL) < 0) { |
940 | qDebug("Error killing %d\n", pppdPid); | 965 | qDebug("Error killing %d\n", pppdPid); |
941 | return false; | 966 | return false; |
942 | } | 967 | } |
943 | } | 968 | } |
944 | } | 969 | } |
945 | return true; | 970 | return true; |
946 | } | 971 | } |
947 | 972 | ||
948 | 973 | ||
949 | void Modem::parseargs(char* buf, char** args) { | 974 | void Modem::parseargs(char* buf, char** args) { |
950 | int nargs = 0; | 975 | int nargs = 0; |
951 | int quotes; | 976 | int quotes; |
952 | 977 | ||
953 | while(nargs < MaxArgs-1 && *buf != '\0') { | 978 | while(nargs < MaxArgs-1 && *buf != '\0') { |
954 | 979 | ||
955 | quotes = 0; | 980 | quotes = 0; |
956 | 981 | ||
957 | // Strip whitespace. Use nulls, so that the previous argument is | 982 | // Strip whitespace. Use nulls, so that the previous argument is |
958 | // terminated automatically. | 983 | // terminated automatically. |
959 | 984 | ||
960 | while ((*buf == ' ' ) || (*buf == '\t' ) || (*buf == '\n' ) ) | 985 | while ((*buf == ' ' ) || (*buf == '\t' ) || (*buf == '\n' ) ) |
961 | *buf++ = '\0'; | 986 | *buf++ = '\0'; |
962 | 987 | ||
963 | // detect begin of quoted argument | 988 | // detect begin of quoted argument |
964 | if (*buf == '"' || *buf == '\'') { | 989 | if (*buf == '"' || *buf == '\'') { |
965 | quotes = *buf; | 990 | quotes = *buf; |
966 | *buf++ = '\0'; | 991 | *buf++ = '\0'; |
967 | } | 992 | } |
968 | 993 | ||
969 | // save the argument | 994 | // save the argument |
970 | if(*buf != '\0') { | 995 | if(*buf != '\0') { |
971 | *args++ = buf; | 996 | *args++ = buf; |
972 | nargs++; | 997 | nargs++; |
973 | } | 998 | } |
974 | 999 | ||
975 | if (!quotes) | 1000 | if (!quotes) |
976 | while ((*buf != '\0') && (*buf != '\n') && | 1001 | while ((*buf != '\0') && (*buf != '\n') && |
977 | (*buf != '\t') && (*buf != ' ')) | 1002 | (*buf != '\t') && (*buf != ' ')) |
978 | buf++; | 1003 | buf++; |
979 | else { | 1004 | else { |
980 | while ((*buf != '\0') && (*buf != quotes)) | 1005 | while ((*buf != '\0') && (*buf != quotes)) |
981 | buf++; | 1006 | buf++; |
982 | *buf++ = '\0'; | 1007 | *buf++ = '\0'; |
983 | } | 1008 | } |
984 | } | 1009 | } |
985 | 1010 | ||
986 | *args = 0L; | 1011 | *args = 0L; |
987 | } | 1012 | } |
988 | 1013 | ||
989 | bool Modem::execPPPDaemon(const QString & arguments) | 1014 | bool Modem::execPPPDaemon(const QString & arguments) |
990 | { | 1015 | { |
991 | if(execpppd(arguments)) { | 1016 | if(execpppd(arguments)) { |
992 | _pppdata->setpppdRunning(true); | 1017 | _pppdata->setpppdRunning(true); |
993 | return true; | 1018 | return true; |
994 | } else | 1019 | } else |
995 | return false; | 1020 | return false; |
996 | } | 1021 | } |
997 | 1022 | ||
998 | void Modem::killPPPDaemon() | 1023 | void Modem::killPPPDaemon() |
999 | { | 1024 | { |
1000 | _pppdata->setpppdRunning(false); | 1025 | _pppdata->setpppdRunning(false); |
1001 | killpppd(); | 1026 | killpppd(); |
1002 | } | 1027 | } |
1003 | 1028 | ||
1004 | int Modem::pppdExitStatus() | 1029 | int Modem::pppdExitStatus() |
1005 | { | 1030 | { |
1006 | return _pppdExitStatus; | 1031 | return _pppdExitStatus; |
1007 | } | 1032 | } |
1008 | 1033 | ||
1009 | int Modem::openResolv(int flags) | 1034 | int Modem::openResolv(int flags) |
1010 | { | 1035 | { |
1011 | int fd; | 1036 | int fd; |
1012 | if ((fd = open(_PATH_RESCONF, flags)) == -1) { | 1037 | if ((fd = open(_PATH_RESCONF, flags)) == -1) { |
1013 | qDebug("error opening resolv.conf!"); | 1038 | qDebug("error opening resolv.conf!"); |
1014 | fd = open(DEVNULL, O_RDONLY); | 1039 | fd = open(DEVNULL, O_RDONLY); |
1015 | } | 1040 | } |
1016 | return fd; | 1041 | return fd; |
1017 | } | 1042 | } |
1018 | 1043 | ||
1019 | bool Modem::setHostname(const QString & name) | 1044 | bool Modem::setHostname(const QString & name) |
1020 | { | 1045 | { |
1021 | return sethostname(name, name.length()) == 0; | 1046 | return sethostname(name, name.length()) == 0; |
1022 | } | 1047 | } |
1023 | 1048 | ||
1049 | QString Modem::pppDevice()const { | ||
1050 | return m_pppdDev; | ||
1051 | } | ||
1052 | void Modem::setPPPDevice( const QString& dev ) { | ||
1053 | m_pppdDev = dev; | ||
1054 | } | ||
1055 | pid_t Modem::pppPID()const { | ||
1056 | return pppdPid; | ||
1057 | } | ||
1058 | void Modem::setPPPDPid( pid_t pid ) { | ||
1059 | qDebug("Modem setting pid"); | ||
1060 | _pppdExitStatus = -1; | ||
1061 | pppdPid = pid; | ||
1062 | modemfd = -1; | ||
1063 | } | ||
1064 | void Modem::slotModemDebug(int fd) { | ||
1065 | char buf[2049]; | ||
1066 | int len; | ||
1067 | |||
1068 | // read in pppd data look for Using interface | ||
1069 | // then read the interface | ||
1070 | // we limit to 10 device now 0-9 | ||
1071 | if((len = ::read(fd, buf, 2048)) > 0) { | ||
1072 | buf[len+1] = '\0'; | ||
1073 | char *found; | ||
1074 | if ( (found = ::strstr(buf, "Using interface ") ) ) { | ||
1075 | found += 16; | ||
1076 | m_pppdDev = QString::fromLatin1(found, 5 ); | ||
1077 | m_pppdDev = m_pppdDev.simplifyWhiteSpace(); | ||
1078 | } | ||
1079 | } | ||
1080 | } | ||