nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* filters.c |
2 | * Code for reading and writing the filters file. |
||
3 | * |
||
4 | * Wireshark - Network traffic analyzer |
||
5 | * By Gerald Combs <gerald@wireshark.org> |
||
6 | * Copyright 1998 Gerald Combs |
||
7 | * |
||
8 | * This program is free software; you can redistribute it and/or |
||
9 | * modify it under the terms of the GNU General Public License |
||
10 | * as published by the Free Software Foundation; either version 2 |
||
11 | * of the License, or (at your option) any later version. |
||
12 | * |
||
13 | * This program is distributed in the hope that it will be useful, |
||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
16 | * GNU General Public License for more details. |
||
17 | * |
||
18 | * You should have received a copy of the GNU General Public License |
||
19 | * along with this program; if not, write to the Free Software |
||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
||
21 | */ |
||
22 | |||
23 | #include <config.h> |
||
24 | |||
25 | #include <stdio.h> |
||
26 | #include <string.h> |
||
27 | #include <errno.h> |
||
28 | |||
29 | #include <glib.h> |
||
30 | |||
31 | #include <wsutil/file_util.h> |
||
32 | #include <wsutil/filesystem.h> |
||
33 | |||
34 | #include "filter_files.h" |
||
35 | |||
36 | /* |
||
37 | * Old filter file name. |
||
38 | */ |
||
39 | #define FILTER_FILE_NAME "filters" |
||
40 | |||
41 | /* |
||
42 | * Capture filter file name. |
||
43 | */ |
||
44 | #define CFILTER_FILE_NAME "cfilters" |
||
45 | |||
46 | /* |
||
47 | * Display filter file name. |
||
48 | */ |
||
49 | #define DFILTER_FILE_NAME "dfilters" |
||
50 | |||
51 | /* |
||
52 | * List of capture filters - saved. |
||
53 | */ |
||
54 | static GList *capture_filters = NULL; |
||
55 | |||
56 | /* |
||
57 | * List of display filters - saved. |
||
58 | */ |
||
59 | static GList *display_filters = NULL; |
||
60 | |||
61 | /* |
||
62 | * List of capture filters - currently edited. |
||
63 | */ |
||
64 | static GList *capture_edited_filters = NULL; |
||
65 | |||
66 | /* |
||
67 | * List of display filters - currently edited. |
||
68 | */ |
||
69 | static GList *display_edited_filters = NULL; |
||
70 | |||
71 | /* |
||
72 | * Read in a list of filters. |
||
73 | * |
||
74 | * On success, "*pref_path_return" is set to NULL. |
||
75 | * On error, "*pref_path_return" is set to point to the pathname of |
||
76 | * the file we tried to read - it should be freed by our caller - |
||
77 | * and "*errno_return" is set to the error. |
||
78 | */ |
||
79 | |||
80 | #define INIT_BUF_SIZE 128 |
||
81 | |||
82 | static GList * |
||
83 | add_filter_entry(GList *fl, const char *filt_name, const char *filt_expr) |
||
84 | { |
||
85 | filter_def *filt; |
||
86 | |||
87 | filt = (filter_def *) g_malloc(sizeof(filter_def)); |
||
88 | filt->name = g_strdup(filt_name); |
||
89 | filt->strval = g_strdup(filt_expr); |
||
90 | return g_list_append(fl, filt); |
||
91 | } |
||
92 | |||
93 | static GList * |
||
94 | remove_filter_entry(GList *fl, GList *fl_entry) |
||
95 | { |
||
96 | filter_def *filt; |
||
97 | |||
98 | filt = (filter_def *) fl_entry->data; |
||
99 | g_free(filt->name); |
||
100 | g_free(filt->strval); |
||
101 | g_free(filt); |
||
102 | return g_list_remove_link(fl, fl_entry); |
||
103 | } |
||
104 | |||
105 | static int |
||
106 | skip_whitespace(FILE *ff) |
||
107 | { |
||
108 | int c; |
||
109 | |||
110 | while ((c = getc(ff)) != EOF && c != '\n' && g_ascii_isspace(c)) |
||
111 | ; |
||
112 | return c; |
||
113 | } |
||
114 | |||
115 | static int |
||
116 | getc_crlf(FILE *ff) |
||
117 | { |
||
118 | int c; |
||
119 | |||
120 | c = getc(ff); |
||
121 | if (c == '\r') { |
||
122 | /* Treat CR-LF at the end of a line like LF, so that if we're reading |
||
123 | * a Windows-format file on UN*X, we handle it the same way we'd handle |
||
124 | * a UN*X-format file. */ |
||
125 | c = getc(ff); |
||
126 | if (c != EOF && c != '\n') { |
||
127 | /* Put back the character after the CR, and process the CR normally. */ |
||
128 | ungetc(c, ff); |
||
129 | c = '\r'; |
||
130 | } |
||
131 | } |
||
132 | return c; |
||
133 | } |
||
134 | |||
135 | void |
||
136 | read_filter_list(filter_list_type_t list_type, char **pref_path_return, |
||
137 | int *errno_return) |
||
138 | { |
||
139 | const char *ff_name; |
||
140 | char *ff_path; |
||
141 | FILE *ff; |
||
142 | GList **flpp; |
||
143 | int c; |
||
144 | char *filt_name, *filt_expr; |
||
145 | int filt_name_len, filt_expr_len; |
||
146 | int filt_name_index, filt_expr_index; |
||
147 | int line = 1; |
||
148 | |||
149 | *pref_path_return = NULL; /* assume no error */ |
||
150 | |||
151 | switch (list_type) { |
||
152 | |||
153 | case CFILTER_LIST: |
||
154 | ff_name = CFILTER_FILE_NAME; |
||
155 | flpp = &capture_filters; |
||
156 | break; |
||
157 | |||
158 | case DFILTER_LIST: |
||
159 | ff_name = DFILTER_FILE_NAME; |
||
160 | flpp = &display_filters; |
||
161 | break; |
||
162 | |||
163 | default: |
||
164 | g_assert_not_reached(); |
||
165 | return; |
||
166 | } |
||
167 | |||
168 | /* try to open personal "cfilters"/"dfilters" file */ |
||
169 | ff_path = get_persconffile_path(ff_name, TRUE); |
||
170 | if ((ff = ws_fopen(ff_path, "r")) == NULL) { |
||
171 | /* |
||
172 | * Did that fail because the file didn't exist? |
||
173 | */ |
||
174 | if (errno != ENOENT) { |
||
175 | /* |
||
176 | * No. Just give up. |
||
177 | */ |
||
178 | *pref_path_return = ff_path; |
||
179 | *errno_return = errno; |
||
180 | return; |
||
181 | } |
||
182 | |||
183 | /* |
||
184 | * Yes. See if there's an "old style" personal "filters" file; if so, read it. |
||
185 | * This means that a user will start out with their capture and |
||
186 | * display filter lists being identical; each list may contain |
||
187 | * filters that don't belong in that list. The user can edit |
||
188 | * the filter lists, and delete the ones that don't belong in |
||
189 | * a particular list. |
||
190 | */ |
||
191 | g_free(ff_path); |
||
192 | ff_path = get_persconffile_path(FILTER_FILE_NAME, FALSE); |
||
193 | if ((ff = ws_fopen(ff_path, "r")) == NULL) { |
||
194 | /* |
||
195 | * Did that fail because the file didn't exist? |
||
196 | */ |
||
197 | if (errno != ENOENT) { |
||
198 | /* |
||
199 | * No. Just give up. |
||
200 | */ |
||
201 | *pref_path_return = ff_path; |
||
202 | *errno_return = errno; |
||
203 | return; |
||
204 | } |
||
205 | |||
206 | /* |
||
207 | * Try to open the global "cfilters/dfilters" file */ |
||
208 | g_free(ff_path); |
||
209 | ff_path = get_datafile_path(ff_name); |
||
210 | if ((ff = ws_fopen(ff_path, "r")) == NULL) { |
||
211 | |||
212 | /* |
||
213 | * Well, that didn't work, either. Just give up. |
||
214 | * Return an error if the file existed but we couldn't open it. |
||
215 | */ |
||
216 | if (errno != ENOENT) { |
||
217 | *pref_path_return = ff_path; |
||
218 | *errno_return = errno; |
||
219 | } else { |
||
220 | g_free(ff_path); |
||
221 | } |
||
222 | return; |
||
223 | } |
||
224 | } |
||
225 | } |
||
226 | |||
227 | /* If we already have a list of filters, discard it. */ |
||
228 | /* this should never happen - this function is called only once for each list! */ |
||
229 | while(*flpp) { |
||
230 | *flpp = remove_filter_entry(*flpp, g_list_first(*flpp)); |
||
231 | } |
||
232 | |||
233 | /* Allocate the filter name buffer. */ |
||
234 | filt_name_len = INIT_BUF_SIZE; |
||
235 | filt_name = (char *)g_malloc(filt_name_len + 1); |
||
236 | filt_expr_len = INIT_BUF_SIZE; |
||
237 | filt_expr = (char *)g_malloc(filt_expr_len + 1); |
||
238 | |||
239 | for (line = 1; ; line++) { |
||
240 | /* Lines in a filter file are of the form |
||
241 | |||
242 | "name" expression |
||
243 | |||
244 | where "name" is a name, in quotes - backslashes in the name |
||
245 | escape the next character, so quotes and backslashes can appear |
||
246 | in the name - and "expression" is a filter expression, not in |
||
247 | quotes, running to the end of the line. */ |
||
248 | |||
249 | /* Skip over leading white space, if any. */ |
||
250 | c = skip_whitespace(ff); |
||
251 | |||
252 | if (c == EOF) |
||
253 | break; /* Nothing more to read */ |
||
254 | if (c == '\n') |
||
255 | continue; /* Blank line. */ |
||
256 | |||
257 | /* "c" is the first non-white-space character. |
||
258 | If it's not a quote, it's an error. */ |
||
259 | if (c != '"') { |
||
260 | g_warning("'%s' line %d doesn't have a quoted filter name.", ff_path, |
||
261 | line); |
||
262 | while (c != '\n') |
||
263 | c = getc(ff); /* skip to the end of the line */ |
||
264 | continue; |
||
265 | } |
||
266 | |||
267 | /* Get the name of the filter. */ |
||
268 | filt_name_index = 0; |
||
269 | for (;;) { |
||
270 | c = getc_crlf(ff); |
||
271 | if (c == EOF || c == '\n') |
||
272 | break; /* End of line - or end of file */ |
||
273 | if (c == '"') { |
||
274 | /* Closing quote. */ |
||
275 | if (filt_name_index >= filt_name_len) { |
||
276 | /* Filter name buffer isn't long enough; double its length. */ |
||
277 | filt_name_len *= 2; |
||
278 | filt_name = (char *)g_realloc(filt_name, filt_name_len + 1); |
||
279 | } |
||
280 | filt_name[filt_name_index] = '\0'; |
||
281 | break; |
||
282 | } |
||
283 | if (c == '\\') { |
||
284 | /* Next character is escaped */ |
||
285 | c = getc_crlf(ff); |
||
286 | if (c == EOF || c == '\n') |
||
287 | break; /* End of line - or end of file */ |
||
288 | } |
||
289 | /* Add this character to the filter name string. */ |
||
290 | if (filt_name_index >= filt_name_len) { |
||
291 | /* Filter name buffer isn't long enough; double its length. */ |
||
292 | filt_name_len *= 2; |
||
293 | filt_name = (char *)g_realloc(filt_name, filt_name_len + 1); |
||
294 | } |
||
295 | filt_name[filt_name_index] = c; |
||
296 | filt_name_index++; |
||
297 | } |
||
298 | |||
299 | if (c == EOF) { |
||
300 | if (!ferror(ff)) { |
||
301 | /* EOF, not error; no newline seen before EOF */ |
||
302 | g_warning("'%s' line %d doesn't have a newline.", ff_path, |
||
303 | line); |
||
304 | } |
||
305 | break; /* nothing more to read */ |
||
306 | } |
||
307 | |||
308 | if (c != '"') { |
||
309 | /* No newline seen before end-of-line */ |
||
310 | g_warning("'%s' line %d doesn't have a closing quote.", ff_path, |
||
311 | line); |
||
312 | continue; |
||
313 | } |
||
314 | |||
315 | /* Skip over separating white space, if any. */ |
||
316 | c = skip_whitespace(ff); |
||
317 | |||
318 | if (c == EOF) { |
||
319 | if (!ferror(ff)) { |
||
320 | /* EOF, not error; no newline seen before EOF */ |
||
321 | g_warning("'%s' line %d doesn't have a newline.", ff_path, |
||
322 | line); |
||
323 | } |
||
324 | break; /* nothing more to read */ |
||
325 | } |
||
326 | |||
327 | if (c == '\n') { |
||
328 | /* No filter expression */ |
||
329 | g_warning("'%s' line %d doesn't have a filter expression.", ff_path, |
||
330 | line); |
||
331 | continue; |
||
332 | } |
||
333 | |||
334 | /* "c" is the first non-white-space character; it's the first |
||
335 | character of the filter expression. */ |
||
336 | filt_expr_index = 0; |
||
337 | for (;;) { |
||
338 | /* Add this character to the filter expression string. */ |
||
339 | if (filt_expr_index >= filt_expr_len) { |
||
340 | /* Filter expressioin buffer isn't long enough; double its length. */ |
||
341 | filt_expr_len *= 2; |
||
342 | filt_expr = (char *)g_realloc(filt_expr, filt_expr_len + 1); |
||
343 | } |
||
344 | filt_expr[filt_expr_index] = c; |
||
345 | filt_expr_index++; |
||
346 | |||
347 | /* Get the next character. */ |
||
348 | c = getc_crlf(ff); |
||
349 | if (c == EOF || c == '\n') |
||
350 | break; |
||
351 | } |
||
352 | |||
353 | if (c == EOF) { |
||
354 | if (!ferror(ff)) { |
||
355 | /* EOF, not error; no newline seen before EOF */ |
||
356 | g_warning("'%s' line %d doesn't have a newline.", ff_path, |
||
357 | line); |
||
358 | } |
||
359 | break; /* nothing more to read */ |
||
360 | } |
||
361 | |||
362 | /* We saw the ending newline; terminate the filter expression string */ |
||
363 | if (filt_expr_index >= filt_expr_len) { |
||
364 | /* Filter expressioin buffer isn't long enough; double its length. */ |
||
365 | filt_expr_len *= 2; |
||
366 | filt_expr = (char *)g_realloc(filt_expr, filt_expr_len + 1); |
||
367 | } |
||
368 | filt_expr[filt_expr_index] = '\0'; |
||
369 | |||
370 | /* Add the new filter to the list of filters */ |
||
371 | *flpp = add_filter_entry(*flpp, filt_name, filt_expr); |
||
372 | } |
||
373 | if (ferror(ff)) { |
||
374 | *pref_path_return = ff_path; |
||
375 | *errno_return = errno; |
||
376 | } else |
||
377 | g_free(ff_path); |
||
378 | fclose(ff); |
||
379 | g_free(filt_name); |
||
380 | g_free(filt_expr); |
||
381 | |||
382 | /* init the corresponding edited list */ |
||
383 | switch (list_type) { |
||
384 | case CFILTER_LIST: |
||
385 | copy_filter_list(CFILTER_EDITED_LIST, CFILTER_LIST); |
||
386 | break; |
||
387 | case DFILTER_LIST: |
||
388 | copy_filter_list(DFILTER_EDITED_LIST, DFILTER_LIST); |
||
389 | break; |
||
390 | default: |
||
391 | g_assert_not_reached(); |
||
392 | return; |
||
393 | } |
||
394 | } |
||
395 | |||
396 | /* |
||
397 | * Get a pointer to a list of filters. |
||
398 | */ |
||
399 | static GList ** |
||
400 | get_filter_list(filter_list_type_t list_type) |
||
401 | { |
||
402 | GList **flpp; |
||
403 | |||
404 | switch (list_type) { |
||
405 | |||
406 | case CFILTER_LIST: |
||
407 | flpp = &capture_filters; |
||
408 | break; |
||
409 | |||
410 | case DFILTER_LIST: |
||
411 | flpp = &display_filters; |
||
412 | break; |
||
413 | |||
414 | case CFILTER_EDITED_LIST: |
||
415 | flpp = &capture_edited_filters; |
||
416 | break; |
||
417 | |||
418 | case DFILTER_EDITED_LIST: |
||
419 | flpp = &display_edited_filters; |
||
420 | break; |
||
421 | |||
422 | default: |
||
423 | g_assert_not_reached(); |
||
424 | flpp = NULL; |
||
425 | } |
||
426 | return flpp; |
||
427 | } |
||
428 | |||
429 | /* |
||
430 | * Get a pointer to the first entry in a filter list. |
||
431 | */ |
||
432 | GList * |
||
433 | get_filter_list_first(filter_list_type_t list_type) |
||
434 | { |
||
435 | GList **flpp; |
||
436 | |||
437 | flpp = get_filter_list(list_type); |
||
438 | return g_list_first(*flpp); |
||
439 | } |
||
440 | |||
441 | /* |
||
442 | * Add a new filter to the end of a list. |
||
443 | * Returns a pointer to the newly-added entry. |
||
444 | */ |
||
445 | GList * |
||
446 | add_to_filter_list(filter_list_type_t list_type, const char *name, |
||
447 | const char *expression) |
||
448 | { |
||
449 | GList **flpp; |
||
450 | |||
451 | flpp = get_filter_list(list_type); |
||
452 | *flpp = add_filter_entry(*flpp, name, expression); |
||
453 | |||
454 | return g_list_last(*flpp); |
||
455 | } |
||
456 | |||
457 | /* |
||
458 | * Remove a filter from a list. |
||
459 | */ |
||
460 | void |
||
461 | remove_from_filter_list(filter_list_type_t list_type, GList *fl_entry) |
||
462 | { |
||
463 | GList **flpp; |
||
464 | |||
465 | flpp = get_filter_list(list_type); |
||
466 | *flpp = remove_filter_entry(*flpp, fl_entry); |
||
467 | } |
||
468 | |||
469 | /* |
||
470 | * Write out a list of filters. |
||
471 | * |
||
472 | * On success, "*pref_path_return" is set to NULL. |
||
473 | * On error, "*pref_path_return" is set to point to the pathname of |
||
474 | * the file we tried to read - it should be freed by our caller - |
||
475 | * and "*errno_return" is set to the error. |
||
476 | */ |
||
477 | void |
||
478 | save_filter_list(filter_list_type_t list_type, char **pref_path_return, |
||
479 | int *errno_return) |
||
480 | { |
||
481 | const gchar *ff_name; |
||
482 | gchar *ff_path, *ff_path_new; |
||
483 | GList *fl; |
||
484 | GList *flpp; |
||
485 | filter_def *filt; |
||
486 | FILE *ff; |
||
487 | guchar *p, c; |
||
488 | |||
489 | *pref_path_return = NULL; /* assume no error */ |
||
490 | |||
491 | switch (list_type) { |
||
492 | |||
493 | case CFILTER_LIST: |
||
494 | ff_name = CFILTER_FILE_NAME; |
||
495 | fl = capture_filters; |
||
496 | break; |
||
497 | |||
498 | case DFILTER_LIST: |
||
499 | ff_name = DFILTER_FILE_NAME; |
||
500 | fl = display_filters; |
||
501 | break; |
||
502 | |||
503 | default: |
||
504 | g_assert_not_reached(); |
||
505 | return; |
||
506 | } |
||
507 | |||
508 | ff_path = get_persconffile_path(ff_name, TRUE); |
||
509 | |||
510 | /* Write to "XXX.new", and rename if that succeeds. |
||
511 | That means we don't trash the file if we fail to write it out |
||
512 | completely. */ |
||
513 | ff_path_new = g_strdup_printf("%s.new", ff_path); |
||
514 | |||
515 | if ((ff = ws_fopen(ff_path_new, "w")) == NULL) { |
||
516 | *pref_path_return = ff_path; |
||
517 | *errno_return = errno; |
||
518 | g_free(ff_path_new); |
||
519 | return; |
||
520 | } |
||
521 | flpp = g_list_first(fl); |
||
522 | while (flpp) { |
||
523 | filt = (filter_def *) flpp->data; |
||
524 | |||
525 | /* Write out the filter name as a quoted string; escape any quotes |
||
526 | or backslashes. */ |
||
527 | putc('"', ff); |
||
528 | for (p = (guchar *)filt->name; (c = *p) != '\0'; p++) { |
||
529 | if (c == '"' || c == '\\') |
||
530 | putc('\\', ff); |
||
531 | putc(c, ff); |
||
532 | } |
||
533 | putc('"', ff); |
||
534 | |||
535 | /* Separate the filter name and value with a space. */ |
||
536 | putc(' ', ff); |
||
537 | |||
538 | /* Write out the filter expression and a newline. */ |
||
539 | fprintf(ff, "%s\n", filt->strval); |
||
540 | if (ferror(ff)) { |
||
541 | *pref_path_return = ff_path; |
||
542 | *errno_return = errno; |
||
543 | fclose(ff); |
||
544 | ws_unlink(ff_path_new); |
||
545 | g_free(ff_path_new); |
||
546 | return; |
||
547 | } |
||
548 | flpp = flpp->next; |
||
549 | } |
||
550 | if (fclose(ff) == EOF) { |
||
551 | *pref_path_return = ff_path; |
||
552 | *errno_return = errno; |
||
553 | ws_unlink(ff_path_new); |
||
554 | g_free(ff_path_new); |
||
555 | return; |
||
556 | } |
||
557 | |||
558 | #ifdef _WIN32 |
||
559 | /* ANSI C doesn't say whether "rename()" removes the target if it |
||
560 | exists; the Win32 call to rename files doesn't do so, which I |
||
561 | infer is the reason why the MSVC++ "rename()" doesn't do so. |
||
562 | We must therefore remove the target file first, on Windows. |
||
563 | |||
564 | XXX - ws_rename() should be ws_stdio_rename() on Windows, |
||
565 | and ws_stdio_rename() uses MoveFileEx() with MOVEFILE_REPLACE_EXISTING, |
||
566 | so it should remove the target if it exists, so this stuff |
||
567 | shouldn't be necessary. Perhaps it dates back to when we were |
||
568 | calling rename(), with that being a wrapper around Microsoft's |
||
569 | _rename(), which didn't remove the target. */ |
||
570 | if (ws_remove(ff_path) < 0 && errno != ENOENT) { |
||
571 | /* It failed for some reason other than "it's not there"; if |
||
572 | it's not there, we don't need to remove it, so we just |
||
573 | drive on. */ |
||
574 | *pref_path_return = ff_path; |
||
575 | *errno_return = errno; |
||
576 | ws_unlink(ff_path_new); |
||
577 | g_free(ff_path_new); |
||
578 | return; |
||
579 | } |
||
580 | #endif |
||
581 | |||
582 | if (ws_rename(ff_path_new, ff_path) < 0) { |
||
583 | *pref_path_return = ff_path; |
||
584 | *errno_return = errno; |
||
585 | ws_unlink(ff_path_new); |
||
586 | g_free(ff_path_new); |
||
587 | return; |
||
588 | } |
||
589 | g_free(ff_path_new); |
||
590 | g_free(ff_path); |
||
591 | } |
||
592 | |||
593 | /* |
||
594 | * Copy a filter list into another. |
||
595 | */ |
||
596 | void copy_filter_list(filter_list_type_t dest_type, filter_list_type_t src_type) |
||
597 | { |
||
598 | GList **flpp_dest; |
||
599 | GList **flpp_src; |
||
600 | GList *flp_src; |
||
601 | filter_def *filt; |
||
602 | |||
603 | g_assert(dest_type != src_type); |
||
604 | |||
605 | flpp_dest = get_filter_list(dest_type); |
||
606 | flpp_src = get_filter_list(src_type); |
||
607 | /* throw away the "old" destination list - a NULL list is ok here */ |
||
608 | while(*flpp_dest) { |
||
609 | *flpp_dest = remove_filter_entry(*flpp_dest, g_list_first(*flpp_dest)); |
||
610 | } |
||
611 | g_assert(g_list_length(*flpp_dest) == 0); |
||
612 | |||
613 | /* copy the list entries */ |
||
614 | for(flp_src = g_list_first(*flpp_src); flp_src; flp_src = g_list_next(flp_src)) { |
||
615 | filt = (filter_def *)(flp_src->data); |
||
616 | |||
617 | *flpp_dest = add_filter_entry(*flpp_dest, filt->name, filt->strval); |
||
618 | } |
||
619 | } |
||
620 | |||
621 | /* |
||
622 | * Editor modelines - http://www.wireshark.org/tools/modelines.html |
||
623 | * |
||
624 | * Local Variables: |
||
625 | * c-basic-offset: 2 |
||
626 | * tab-width: 8 |
||
627 | * indent-tabs-mode: nil |
||
628 | * End: |
||
629 | * |
||
630 | * ex: set shiftwidth=2 tabstop=8 expandtab: |
||
631 | * :indentSize=2:tabSize=8:noTabs=true: |
||
632 | */ |