1 | /* |
2 | KSysGuard, the KDE System Guard |
3 | |
4 | Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org> |
5 | |
6 | This program is free software; you can redistribute it and/or |
7 | modify it under the terms of version 2 of the GNU General Public |
8 | License as published by the Free Software Foundation. |
9 | |
10 | This program is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | GNU General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU General Public License |
16 | along with this program; if not, write to the Free Software |
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
18 | |
19 | */ |
20 | |
21 | #include <config-workspace.h> |
22 | |
23 | #include <sys/types.h> |
24 | #include <sys/stat.h> |
25 | #include <sys/time.h> |
26 | #include <fcntl.h> |
27 | #include <unistd.h> |
28 | #include <stdio.h> |
29 | #include <string.h> |
30 | |
31 | #include "Command.h" |
32 | #include "ksysguardd.h" |
33 | |
34 | #include "netdev.h" |
35 | |
36 | #define MON_SIZE 128 |
37 | |
38 | #define CALC( a, b, c, d, e, f ) \ |
39 | { \ |
40 | if (f){ \ |
41 | if( NetDevs[i].oldInitialised) {\ |
42 | if( a >= NetDevs[i].a ) \ |
43 | NetDevs[ i ].delta##a = a - NetDevs[ i ].a; \ |
44 | else \ |
45 | NetDevs[ i ].delta##a = a; \ |
46 | } else \ |
47 | NetDevs[ i ].delta##a = 0; \ |
48 | } \ |
49 | NetDevs[ i ].a = a; \ |
50 | } |
51 | |
52 | #define REGISTERSENSOR( a, b, c, d, e, f ) \ |
53 | { \ |
54 | snprintf( mon, MON_SIZE, "network/interfaces/%s/%s", tag, b ); \ |
55 | registerMonitor( mon, "float", printNetDev##a##0, printNetDev##a##0Info, NetDevSM ); \ |
56 | if(f) { \ |
57 | snprintf( mon, MON_SIZE, "network/interfaces/%s/%sTotal", tag, b ); \ |
58 | registerMonitor( mon, "float", printNetDev##a##1, printNetDev##a##1Info, NetDevSM ); \ |
59 | } \ |
60 | } |
61 | |
62 | #define UNREGISTERSENSOR( a, b, c, d, e, f ) \ |
63 | { \ |
64 | snprintf( mon, MON_SIZE, "network/interfaces/%s/%s", NetDevs[ i ].name, b ); \ |
65 | removeMonitor( mon ); \ |
66 | if(f) { \ |
67 | snprintf( mon, MON_SIZE, "network/interfaces/%s/%sTotal", NetDevs[ i ].name, b ); \ |
68 | removeMonitor( mon ); \ |
69 | } \ |
70 | } |
71 | |
72 | #define DEFMEMBERS( a, b, c, d, e, f ) \ |
73 | unsigned long long delta##a; \ |
74 | unsigned long long a; \ |
75 | unsigned long a##Scale; |
76 | |
77 | #define DEFWIFIMEMBERS( a, b, c, d, e, f ) \ |
78 | signed long long delta##a; \ |
79 | signed long long a; \ |
80 | signed long a##Scale; |
81 | |
82 | #define DEFVARS( a, b, c, d, e, f) \ |
83 | unsigned long long a; |
84 | |
85 | #define DEFWIFIVARS( a, b, c, d, e, f) \ |
86 | signed long long a; |
87 | |
88 | /* The sixth variable is 1 if the quantity variation must be provided, 0 if the absolute value must be provided */ |
89 | #define FORALL( a ) \ |
90 | a( recBytes, "receiver/data", "Received Data", "KB", 1024, 1) \ |
91 | a( recPacks, "receiver/packets", "Received Packets", "", 1, 1 ) \ |
92 | a( recErrs, "receiver/errors", "Receiver Errors", "", 1, 1 ) \ |
93 | a( recDrop, "receiver/drops", "Receiver Drops", "", 1, 1 ) \ |
94 | a( recFifo, "receiver/fifo", "Receiver FIFO Overruns", "", 1, 1 ) \ |
95 | a( recFrame, "receiver/frame", "Receiver Frame Errors", "", 1, 1 ) \ |
96 | a( recCompressed, "receiver/compressed", "Received Compressed Packets", "", 1, 1 ) \ |
97 | a( recMulticast, "receiver/multicast", "Received Multicast Packets", "", 1, 1 ) \ |
98 | a( sentBytes, "transmitter/data", "Sent Data", "KB", 1024, 1 ) \ |
99 | a( sentPacks, "transmitter/packets", "Sent Packets", "", 1, 1 ) \ |
100 | a( sentErrs, "transmitter/errors", "Transmitter Errors", "", 1, 1 ) \ |
101 | a( sentDrop, "transmitter/drops", "Transmitter Drops", "", 1, 1 ) \ |
102 | a( sentFifo, "transmitter/fifo", "Transmitter FIFO overruns", "", 1, 1 ) \ |
103 | a( sentColls, "transmitter/collisions", "Transmitter Collisions", "", 1, 1 ) \ |
104 | a( sentCarrier, "transmitter/carrier", "Transmitter Carrier losses", "", 1, 1 ) \ |
105 | a( sentCompressed, "transmitter/compressed", "Transmitter Compressed Packets", "", 1, 1 ) |
106 | |
107 | #define FORALLWIFI( a ) \ |
108 | a( linkQuality, "wifi/quality", "Link Quality", "", 1, 0) \ |
109 | a( signalLevel, "wifi/signal", "Signal Level", "dBm", 1, 0) \ |
110 | a( noiseLevel, "wifi/noise", "Noise Level", "dBm", 1, 0) \ |
111 | a( nwid, "wifi/nwid", "Rx Invalid Nwid Packets", "", 1, 1) \ |
112 | a( RxCrypt, "wifi/crypt", "Rx Invalid Crypt Packets", "", 1, 1) \ |
113 | a( frag, "wifi/frag", "Rx Invalid Frag Packets", "", 1, 1) \ |
114 | a( retry, "wifi/retry", "Tx Excessive Retries Packets", "", 1, 1) \ |
115 | a( misc, "wifi/misc", "Invalid Misc Packets", "", 1, 1) \ |
116 | a( beacon, "wifi/beacon", "Missed Beacon", "", 1, 1) |
117 | |
118 | #define SETZERO( a, b, c, d, e, f ) \ |
119 | a = 0; |
120 | |
121 | #define SETMEMBERZERO( a, b, c, d, e, f ) \ |
122 | NetDevs[ i ].a = 0; \ |
123 | NetDevs[ i ].delta##a = 0; \ |
124 | NetDevs[ i ].a##Scale = e; |
125 | |
126 | #define DECLAREFUNC( a, b, c, d, e, f) \ |
127 | void printNetDev##a##0( const char* cmd ); \ |
128 | void printNetDev##a##0Info( const char* cmd ); \ |
129 | void printNetDev##a##1( const char* cmd ); \ |
130 | void printNetDev##a##1Info( const char* cmd ); \ |
131 | |
132 | typedef struct |
133 | { |
134 | FORALL( DEFMEMBERS ) |
135 | FORALLWIFI( DEFWIFIMEMBERS ) |
136 | char name[ 32 ]; |
137 | int isWifi; |
138 | int oldInitialised; |
139 | } NetDevInfo; |
140 | |
141 | /* We have observed deviations of up to 5% in the accuracy of the timer |
142 | * interrupts. So we try to measure the interrupt interval and use this |
143 | * value to calculate timing dependant values. */ |
144 | static float timeInterval = 0; |
145 | static struct timeval lastSampling; |
146 | static struct timeval currSampling; |
147 | static struct SensorModul* NetDevSM; |
148 | |
149 | #define NETDEVBUFSIZE 4096 |
150 | static char NetDevBuf[ NETDEVBUFSIZE ]; |
151 | static char NetDevWifiBuf[ NETDEVBUFSIZE ]; |
152 | static int NetDevCnt = 0; |
153 | static int Dirty = 0; |
154 | static long OldHash = 0; |
155 | |
156 | #define MAXNETDEVS 64 |
157 | static NetDevInfo NetDevs[ MAXNETDEVS ]; |
158 | |
159 | void processNetDev( void ); |
160 | |
161 | FORALL( DECLAREFUNC ) |
162 | FORALLWIFI( DECLAREFUNC ) |
163 | |
164 | static int processNetDev_( void ) |
165 | { |
166 | int i, j; |
167 | char format[ 32 ]; |
168 | char devFormat[ 16 ]; |
169 | char buf[ 1024 ]; |
170 | char tag[ 64 ]; |
171 | char* netDevBufP = NetDevBuf; |
172 | char* netDevWifiBufP = NetDevWifiBuf; |
173 | |
174 | sprintf( format, "%%%d[^\n]\n" , (int)sizeof( buf ) - 1 ); |
175 | sprintf( devFormat, "%%%ds" , (int)sizeof( tag ) - 1 ); |
176 | |
177 | /*Update the values for the wifi interfaces if there is a /proc/net/wireless file*/ |
178 | if (*netDevBufP != '\0') { |
179 | /* skip 2 first lines */ |
180 | for (i = 0; i < 2; i++) { |
181 | sscanf(netDevBufP, format, buf); |
182 | buf[sizeof(buf) - 1] = '\0'; |
183 | netDevBufP += strlen(buf) + 1; /* move netDevBufP to next line */ |
184 | } |
185 | |
186 | for (i = 0; sscanf(netDevBufP, format, buf) == 1; ++i) { |
187 | buf[sizeof(buf) - 1] = '\0'; |
188 | netDevBufP += strlen(buf) + 1; /* move netDevBufP to next line */ |
189 | |
190 | if (sscanf(buf, devFormat, tag)) { |
191 | char* pos = strchr(tag, ':'); |
192 | if (pos) { |
193 | FORALL( DEFVARS ); |
194 | *pos = '\0'; |
195 | FORALL( SETZERO ); |
196 | sscanf(strchr(buf, ':') + 1, "%llu %llu %llu %llu %llu %llu %llu %llu " |
197 | "%llu %llu %llu %llu %llu %llu %llu %llu" , |
198 | &recBytes, &recPacks, &recErrs, &recDrop, &recFifo, |
199 | &recFrame, &recCompressed, &recMulticast, |
200 | &sentBytes, &sentPacks, &sentErrs, &sentDrop, |
201 | &sentFifo, &sentColls, &sentCarrier, &sentCompressed); |
202 | |
203 | if (i >= NetDevCnt || strcmp(NetDevs[i].name, tag) != 0) { |
204 | /* The network device configuration has changed. We |
205 | * need to reconfigure the netdev module. */ |
206 | return -1; |
207 | } else { |
208 | FORALL( CALC ); |
209 | if (!NetDevs[i].isWifi) |
210 | NetDevs[i].oldInitialised = 1; |
211 | } |
212 | } |
213 | } |
214 | } |
215 | if ( i != NetDevCnt ) |
216 | return -1; |
217 | } |
218 | |
219 | |
220 | |
221 | /*Update the values for the wifi interfaces if there is a /proc/net/wireless file*/ |
222 | if (*netDevWifiBufP != '\0') { |
223 | |
224 | /* skip 2 first lines */ |
225 | for (i = 0; i < 2; i++) { |
226 | sscanf(netDevWifiBufP, format, buf); |
227 | buf[sizeof(buf) - 1] = '\0'; |
228 | netDevWifiBufP += strlen(buf) + 1; /* move netDevWifiBufP to next line */ |
229 | } |
230 | |
231 | for (j = 0; sscanf(netDevWifiBufP, format, buf) == 1; ++j) { |
232 | buf[sizeof(buf) - 1] = '\0'; |
233 | netDevWifiBufP += strlen(buf) + 1; /* move netDevWifiBufP to next line */ |
234 | |
235 | if (sscanf(buf, devFormat, tag)) { |
236 | char* pos = strchr(tag, ':'); |
237 | if (pos) { |
238 | FORALLWIFI( DEFWIFIVARS ); |
239 | *pos = '\0'; |
240 | |
241 | for (i = 0; i < NetDevCnt; ++i) { /*find the corresponding interface*/ |
242 | if (strcmp(tag, NetDevs[i].name) == 0) { |
243 | break; |
244 | } |
245 | } |
246 | unsigned int wifiStatus; |
247 | sscanf(strchr(buf, ':') + 1, " %d %lli. %lli. %lli. %lli %lli %lli %lli %lli %lli" , |
248 | &wifiStatus, &linkQuality, &signalLevel, &noiseLevel, &nwid, |
249 | &RxCrypt, &frag, &retry, &misc, &beacon); |
250 | signalLevel -= 256; /*the units are dBm*/ |
251 | noiseLevel -= 256; |
252 | FORALLWIFI( CALC ); |
253 | NetDevs[i].oldInitialised = 1; |
254 | } |
255 | } |
256 | } |
257 | } |
258 | |
259 | /* save exact time inverval between this and the last read of |
260 | * /proc/net/dev */ |
261 | timeInterval = currSampling.tv_sec - lastSampling.tv_sec + |
262 | ( currSampling.tv_usec - lastSampling.tv_usec ) / 1000000.0; |
263 | lastSampling = currSampling; |
264 | Dirty = 0; |
265 | |
266 | return 0; |
267 | } |
268 | |
269 | void processNetDev( void ) |
270 | { |
271 | int i; |
272 | |
273 | if ( NetDevCnt == 0 ) |
274 | return; |
275 | |
276 | for ( i = 0; i < 5 && processNetDev_() < 0; ++i ) { |
277 | /* Values for other network devices are lost, but it is still better |
278 | * than not detecting any new devices */ |
279 | exitNetDev(); |
280 | initNetDev( NetDevSM ); |
281 | } |
282 | |
283 | /* If 5 reconfiguration attemts failed, something is very wrong and |
284 | * we close the netdev module for further use. */ |
285 | if ( i == 5 ) |
286 | exitNetDev(); |
287 | } |
288 | |
289 | /* |
290 | ================================ public part ================================= |
291 | */ |
292 | |
293 | void initNetDev( struct SensorModul* sm ) |
294 | { |
295 | int i, j; |
296 | char format[ 32 ]; |
297 | char devFormat[ 16 ]; |
298 | char buf[ 1024 ]; |
299 | char tag[ 64 ]; |
300 | char* netDevBufP = NetDevBuf; |
301 | char* netDevWifiBufP = NetDevWifiBuf; |
302 | |
303 | NetDevSM = sm; |
304 | |
305 | if ( updateNetDev() < 0 ) |
306 | return; |
307 | |
308 | sprintf( format, "%%%d[^\n]\n" , (int)sizeof( buf ) - 1 ); |
309 | sprintf( devFormat, "%%%ds" , (int)sizeof( tag ) - 1 ); |
310 | |
311 | /* skip 2 first lines */ |
312 | for ( i = 0; i < 2; i++ ) { |
313 | sscanf( netDevBufP, format, buf ); |
314 | buf[ sizeof( buf ) - 1 ] = '\0'; |
315 | netDevBufP += strlen( buf ) + 1; /* move netDevBufP to next line */ |
316 | } |
317 | |
318 | for ( i = 0; sscanf( netDevBufP, format, buf ) == 1; ++i ) { |
319 | buf[ sizeof( buf ) - 1 ] = '\0'; |
320 | netDevBufP += strlen( buf ) + 1; /* move netDevBufP to next line */ |
321 | |
322 | NetDevs[i].oldInitialised = 0; |
323 | if ( sscanf( buf, devFormat, tag ) ) { |
324 | char* pos = strchr( tag, ':' ); |
325 | FORALL( SETMEMBERZERO ); |
326 | if ( pos ) { |
327 | char mon[ MON_SIZE ]; |
328 | *pos = '\0'; |
329 | strncpy( NetDevs[ i ].name, tag, sizeof( NetDevs[ i ].name ) ); |
330 | NetDevs[ i ].name[ sizeof( NetDevs[ i ].name )-1] = 0; |
331 | FORALL( REGISTERSENSOR ); |
332 | sscanf( pos + 1, "%lli %lli %lli %lli %lli %lli %lli %lli" |
333 | "%lli %lli %lli %lli %lli %lli %lli %lli" , |
334 | &NetDevs[ i ].recBytes, &NetDevs[ i ].recPacks, |
335 | &NetDevs[ i ].recErrs, &NetDevs[ i ].recDrop, |
336 | &NetDevs[ i ].recFifo, &NetDevs[ i ].recFrame, |
337 | &NetDevs[ i ].recCompressed, &NetDevs[ i ].recMulticast, |
338 | &NetDevs[ i ].sentBytes, &NetDevs[ i ].sentPacks, |
339 | &NetDevs[ i ].sentErrs, &NetDevs[ i ].sentDrop, |
340 | &NetDevs[ i ].sentFifo, &NetDevs[ i ].sentColls, |
341 | &NetDevs[ i ].sentCarrier, &NetDevs[ i ].sentCompressed ); |
342 | NetDevCnt++; |
343 | } |
344 | } |
345 | } |
346 | |
347 | /* detect the wifi interfaces*/ |
348 | /* skip 2 first lines */ |
349 | for ( i = 0; i < 2; i++ ) { |
350 | sscanf( netDevWifiBufP, format, buf ); |
351 | buf[ sizeof( buf ) - 1 ] = '\0'; |
352 | netDevWifiBufP += strlen( buf ) + 1; /* move netDevWifiBufP to next line */ |
353 | } |
354 | |
355 | for ( j = 0; sscanf( netDevWifiBufP, format, buf ) == 1; ++j ) { |
356 | buf[ sizeof( buf ) - 1 ] = '\0'; |
357 | netDevWifiBufP += strlen( buf ) + 1; /* move netDevWifiBufP to next line */ |
358 | |
359 | if ( sscanf( buf, devFormat, tag ) ) { |
360 | char * pos = strchr( tag, ':' ); |
361 | if ( pos ) { |
362 | char mon[ MON_SIZE ]; |
363 | *pos = '\0'; |
364 | /*find and tag the corresponding NetDev as wifi enabled. |
365 | At the end of the loop, i is the index of the device. |
366 | This variable i is used in some macro */ |
367 | for (i = 0 ; i < NetDevCnt ; ++i){ |
368 | if ( strcmp(tag,NetDevs[ i ].name)==0){ |
369 | NetDevs[ i ].isWifi = 1; |
370 | break; |
371 | } |
372 | } |
373 | FORALLWIFI( REGISTERSENSOR ); |
374 | } |
375 | FORALLWIFI( SETMEMBERZERO ); /* the variable i must point to the corrrect NetDevs[i]*/ |
376 | } |
377 | } |
378 | |
379 | /* Call processNetDev to elimitate initial peek values. */ |
380 | processNetDev(); |
381 | } |
382 | |
383 | void exitNetDev( void ) |
384 | { |
385 | int i; |
386 | |
387 | for ( i = 0; i < NetDevCnt; ++i ) { |
388 | char mon[ MON_SIZE ]; |
389 | FORALL( UNREGISTERSENSOR ); |
390 | if (NetDevs[ i ].isWifi) |
391 | FORALLWIFI( UNREGISTERSENSOR ); |
392 | } |
393 | NetDevCnt = 0; |
394 | } |
395 | |
396 | int updateNetDev( void ) |
397 | { |
398 | /* We read the information about the network interfaces from |
399 | /proc/net/dev. The file should look like this: |
400 | |
401 | Inter-| Receive | Transmit |
402 | face | bytes packets errs drop fifo frame compressed multicast| bytes packets errs drop fifo colls carrier compressed |
403 | lo:275135772 1437448 0 0 0 0 0 0 275135772 1437448 0 0 0 0 0 0 |
404 | eth0:123648812 655251 0 0 0 0 0 0 246847871 889636 0 0 0 0 0 0 |
405 | */ |
406 | |
407 | size_t n; |
408 | int fd; |
409 | long hash; |
410 | char* p; |
411 | |
412 | if ((fd = open("/proc/net/dev" , O_RDONLY)) > 0) { |
413 | n = read(fd, NetDevBuf, NETDEVBUFSIZE - 1); |
414 | if (n == NETDEVBUFSIZE - 1 || n <= 0) { |
415 | log_error("Internal buffer too small to read \'/proc/net/dev\'" ); |
416 | close(fd); |
417 | return -1; |
418 | } |
419 | |
420 | gettimeofday(&currSampling, 0); |
421 | close(fd); |
422 | NetDevBuf[n] = '\0'; |
423 | |
424 | /* Calculate hash over the first 7 characters of each line starting |
425 | * after the first newline. This will detect whether any interfaces |
426 | * have either appeared or disappeared. */ |
427 | for (p = NetDevBuf, hash = 0; *p; ++p) |
428 | if (*p == '\n') |
429 | for (++p; *p && *p != ':' && *p != '|'; ++p) |
430 | hash = ((hash << 6) + *p) % 390389; |
431 | |
432 | if (OldHash != 0 && OldHash != hash) { |
433 | print_error("RECONFIGURE" ); |
434 | CheckSetupFlag = 1; |
435 | } |
436 | OldHash = hash; |
437 | } |
438 | |
439 | /* We read the information about the wifi from /proc/net/wireless and store it into NetDevWifiBuf */ |
440 | if ( ( fd = open( "/proc/net/wireless" , O_RDONLY ) ) < 0 ) { |
441 | /* /proc/net/wireless may not exist on some machines. */ |
442 | NetDevWifiBuf[0]='\0'; |
443 | } else if ( ( n = read( fd, NetDevWifiBuf, NETDEVBUFSIZE - 1 ) ) == NETDEVBUFSIZE - 1 ) { |
444 | log_error( "Internal buffer too small to read \'/proc/net/wireless\'" ); |
445 | close( fd ); |
446 | return -1; |
447 | } else { |
448 | close( fd ); |
449 | NetDevWifiBuf[ n ] = '\0'; |
450 | } |
451 | Dirty = 1; |
452 | |
453 | return 0; |
454 | } |
455 | |
456 | void checkNetDev( void ) |
457 | { |
458 | updateNetDev(); |
459 | } |
460 | |
461 | #define PRINTFUNC( a, b, c, d, e, f ) \ |
462 | void printNetDev##a##0( const char* cmd ) \ |
463 | { \ |
464 | int i; \ |
465 | char* beg; \ |
466 | char* end; \ |
467 | char dev[ 64 ]; \ |
468 | \ |
469 | beg = strchr( cmd, '/' ); \ |
470 | beg = strchr( beg + 1, '/' ); \ |
471 | end = strchr( beg + 1, '/' ); \ |
472 | strncpy( dev, beg + 1, end - beg - 1 ); \ |
473 | dev[ end - beg - 1 ] = '\0'; \ |
474 | \ |
475 | if ( Dirty ) \ |
476 | processNetDev(); \ |
477 | \ |
478 | for ( i = 0; i < MAXNETDEVS; ++i ) \ |
479 | if ( strcmp( NetDevs[ i ].name, dev ) == 0) { \ |
480 | if (f && timeInterval < 0.01) \ |
481 | /*Time interval is very small. Can we really get an accurate value from this? Assume not*/ \ |
482 | output( "0\n"); \ |
483 | else if(f) \ |
484 | output( "%li\n", (long) \ |
485 | ( NetDevs[ i ].delta##a / ( NetDevs[ i ].a##Scale * timeInterval ) ) ); \ |
486 | else \ |
487 | output( "%li\n", (long) NetDevs[ i ].a ); \ |
488 | return; \ |
489 | } \ |
490 | \ |
491 | output( "0\n" ); \ |
492 | } \ |
493 | void printNetDev##a##0##Info( const char* cmd ) \ |
494 | { \ |
495 | char* beg; \ |
496 | char* end; \ |
497 | char dev[ 64 ]; \ |
498 | \ |
499 | beg = strchr( cmd, '/' ); \ |
500 | beg = strchr( beg + 1, '/' ); \ |
501 | end = strchr( beg + 1, '/' ); \ |
502 | strncpy( dev, beg + 1, end - beg - 1 ); \ |
503 | dev[ end - beg - 1 ] = '\0'; \ |
504 | \ |
505 | if(f && d[0] == 0) \ |
506 | output( "%s %s Rate\t0\t0\t1/s\n", dev, c); \ |
507 | else if(f) \ |
508 | output( "%s %s Rate\t0\t0\t%s/s\n", dev, c, d ); \ |
509 | else \ |
510 | output( "%s %s\t0\t0\t%s\n", dev, c, d ); \ |
511 | } \ |
512 | void printNetDev##a##1( const char* cmd ) \ |
513 | { \ |
514 | if(f) { \ |
515 | int i; \ |
516 | char* beg; \ |
517 | char* end; \ |
518 | char dev[ 64 ]; \ |
519 | \ |
520 | beg = strchr( cmd, '/' ); \ |
521 | beg = strchr( beg + 1, '/' ); \ |
522 | end = strchr( beg + 1, '/' ); \ |
523 | strncpy( dev, beg + 1, end - beg - 1 ); \ |
524 | dev[ end - beg - 1 ] = '\0'; \ |
525 | \ |
526 | if ( Dirty ) \ |
527 | processNetDev(); \ |
528 | \ |
529 | for ( i = 0; i < MAXNETDEVS; ++i ) \ |
530 | if ( strcmp( NetDevs[ i ].name, dev ) == 0) { \ |
531 | output( "%li\n", (long) NetDevs[ i ].a / ( NetDevs[ i ].a##Scale) ); \ |
532 | return; \ |
533 | } \ |
534 | \ |
535 | output( "0\n" ); \ |
536 | } \ |
537 | } \ |
538 | void printNetDev##a##1##Info( const char* cmd ) \ |
539 | { \ |
540 | if(f) { \ |
541 | char* beg; \ |
542 | char* end; \ |
543 | char dev[ 64 ]; \ |
544 | \ |
545 | beg = strchr( cmd, '/' ); \ |
546 | beg = strchr( beg + 1, '/' ); \ |
547 | end = strchr( beg + 1, '/' ); \ |
548 | strncpy( dev, beg + 1, end - beg - 1 ); \ |
549 | dev[ end - beg - 1 ] = '\0'; \ |
550 | \ |
551 | output( "%s %s\t0\t0\t%s\n", dev, c, d ); \ |
552 | } \ |
553 | } |
554 | |
555 | |
556 | FORALL( PRINTFUNC ) |
557 | FORALLWIFI( PRINTFUNC ) |
558 | |