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