No issues found
Tool | Failure ID | Location | Function | Message | Data |
---|---|---|---|---|---|
clang-analyzer | no-output-found | shell-mobile-providers.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None |
1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2 of the License, or (at your option) any later version.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the
15 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 * Boston, MA 02110-1301 USA.
17 *
18 * Copyright (C) 2009 Novell, Inc.
19 * Author: Tambet Ingo (tambet@gmail.com).
20 *
21 * Copyright (C) 2009 - 2010 Red Hat, Inc.
22 */
23
24 #include "config.h"
25
26 #include <string.h>
27 #include <errno.h>
28 #include <stdlib.h>
29
30 #include <glib/gi18n.h>
31
32 #include "shell-mobile-providers.h"
33
34 #ifndef MOBILE_BROADBAND_PROVIDER_INFO
35 #define MOBILE_BROADBAND_PROVIDER_INFO DATADIR "/mobile-broadband-provider-info/serviceproviders.xml"
36 #endif
37
38 #define ISO_3166_COUNTRY_CODES DATADIR "/zoneinfo/iso3166.tab"
39
40
41
42 static GHashTable *
43 read_country_codes (void)
44 {
45 GHashTable *table;
46 GIOChannel *channel;
47 GString *buffer;
48 GError *error = NULL;
49 GIOStatus status;
50
51 channel = g_io_channel_new_file (ISO_3166_COUNTRY_CODES, "r", &error);
52 if (!channel) {
53 if (error) {
54 g_warning ("Could not read " ISO_3166_COUNTRY_CODES ": %s", error->message);
55 g_error_free (error);
56 } else
57 g_warning ("Could not read " ISO_3166_COUNTRY_CODES ": Unknown error");
58
59 return NULL;
60 }
61
62 table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
63 buffer = g_string_sized_new (32);
64
65 status = G_IO_STATUS_NORMAL;
66 while (status == G_IO_STATUS_NORMAL) {
67 status = g_io_channel_read_line_string (channel, buffer, NULL, &error);
68
69 switch (status) {
70 case G_IO_STATUS_NORMAL:
71 if (buffer->str[0] != '#') {
72 char **pieces;
73
74 pieces = g_strsplit (buffer->str, "\t", 2);
75
76 /* Hack for rh#556292; iso3166.tab is just wrong */
77 pieces[1] = pieces[1] ? g_strchomp (pieces[1]) : NULL;
78 if (pieces[1] && !strcmp (pieces[1], "Britain (UK)")) {
79 g_free (pieces[1]);
80 pieces[1] = g_strdup (_("United Kingdom"));
81 }
82
83 g_hash_table_insert (table, pieces[0], pieces[1]);
84 g_free (pieces);
85 }
86
87 g_string_truncate (buffer, 0);
88 break;
89 case G_IO_STATUS_EOF:
90 break;
91 case G_IO_STATUS_ERROR:
92 g_warning ("Error while reading: %s", error->message);
93 g_error_free (error);
94 break;
95 case G_IO_STATUS_AGAIN:
96 /* FIXME: Try again a few times, but really, it never happes, right? */
97 break;
98 }
99 }
100
101 g_string_free (buffer, TRUE);
102 g_io_channel_unref (channel);
103
104 return table;
105 }
106
107 /* XML Parser */
108
109 typedef enum {
110 PARSER_TOPLEVEL = 0,
111 PARSER_COUNTRY,
112 PARSER_PROVIDER,
113 PARSER_METHOD_GSM,
114 PARSER_METHOD_GSM_APN,
115 PARSER_METHOD_CDMA,
116 PARSER_ERROR
117 } MobileContextState;
118
119 typedef struct {
120 GHashTable *country_codes;
121 GHashTable *table;
122
123 char *current_country;
124 GSList *current_providers;
125 ShellMobileProvider *current_provider;
126 ShellMobileAccessMethod *current_method;
127
128 char *text_buffer;
129 MobileContextState state;
130 } MobileParser;
131
132 static ShellGsmMccMnc *
133 mcc_mnc_new (const char *mcc, const char *mnc)
134 {
135 ShellGsmMccMnc *m;
136
137 m = g_slice_new (ShellGsmMccMnc);
138 m->mcc = g_strstrip (g_strdup (mcc));
139 m->mnc = g_strstrip (g_strdup (mnc));
140 return m;
141 }
142
143 /* added in porting */
144 static ShellGsmMccMnc *
145 mcc_mnc_copy (const ShellGsmMccMnc *other) {
146 ShellGsmMccMnc *ret;
147
148 ret = g_slice_new (ShellGsmMccMnc);
149 ret->mcc = g_strdup (other->mcc);
150 ret->mnc = g_strdup (other->mnc);
151 return ret;
152 }
153
154 static void
155 mcc_mnc_free (ShellGsmMccMnc *m)
156 {
157 g_return_if_fail (m != NULL);
158 g_free (m->mcc);
159 g_free (m->mnc);
160 g_slice_free (ShellGsmMccMnc, m);
161 }
162
163 /* added in porting */
164 G_DEFINE_BOXED_TYPE (ShellGsmMccMnc, shell_gsm_mcc_mnc, mcc_mnc_copy, mcc_mnc_free)
165
166 static ShellMobileAccessMethod *
167 access_method_new (void)
168 {
169 ShellMobileAccessMethod *method;
170
171 method = g_slice_new0 (ShellMobileAccessMethod);
172 method->refs = 1;
173 method->lcl_names = g_hash_table_new_full (g_str_hash, g_str_equal,
174 (GDestroyNotify) g_free,
175 (GDestroyNotify) g_free);
176
177 return method;
178 }
179
180 ShellMobileAccessMethod *
181 shell_mobile_access_method_ref (ShellMobileAccessMethod *method)
182 {
183 g_return_val_if_fail (method != NULL, NULL);
184 g_return_val_if_fail (method->refs > 0, NULL);
185
186 method->refs++;
187
188 return method;
189 }
190
191 void
192 shell_mobile_access_method_unref (ShellMobileAccessMethod *method)
193 {
194 g_return_if_fail (method != NULL);
195 g_return_if_fail (method->refs > 0);
196
197 if (--method->refs == 0) {
198 g_free (method->name);
199 g_hash_table_destroy (method->lcl_names);
200 g_free (method->username);
201 g_free (method->password);
202 g_free (method->gateway);
203 g_free (method->gsm_apn);
204 g_slist_foreach (method->dns, (GFunc) g_free, NULL);
205 g_slist_free (method->dns);
206
207 g_slice_free (ShellMobileAccessMethod, method);
208 }
209 }
210
211 GType
212 shell_mobile_access_method_get_type (void)
213 {
214 static GType type = 0;
215
216 if (G_UNLIKELY (type == 0)) {
217 type = g_boxed_type_register_static ("ShellMobileAccessMethod",
218 (GBoxedCopyFunc) shell_mobile_access_method_ref,
219 (GBoxedFreeFunc) shell_mobile_access_method_unref);
220 }
221 return type;
222 }
223
224
225 static ShellMobileProvider *
226 provider_new (void)
227 {
228 ShellMobileProvider *provider;
229
230 provider = g_slice_new0 (ShellMobileProvider);
231 provider->refs = 1;
232 provider->lcl_names = g_hash_table_new_full (g_str_hash, g_str_equal,
233 (GDestroyNotify) g_free,
234 (GDestroyNotify) g_free);
235
236 return provider;
237 }
238
239 ShellMobileProvider *
240 shell_mobile_provider_ref (ShellMobileProvider *provider)
241 {
242 provider->refs++;
243
244 return provider;
245 }
246
247 void
248 shell_mobile_provider_unref (ShellMobileProvider *provider)
249 {
250 if (--provider->refs == 0) {
251 g_free (provider->name);
252 g_hash_table_destroy (provider->lcl_names);
253
254 g_slist_foreach (provider->methods, (GFunc) shell_mobile_access_method_unref, NULL);
255 g_slist_free (provider->methods);
256
257 g_slist_foreach (provider->gsm_mcc_mnc, (GFunc) mcc_mnc_free, NULL);
258 g_slist_free (provider->gsm_mcc_mnc);
259
260 g_slist_free (provider->cdma_sid);
261
262 g_slice_free (ShellMobileProvider, provider);
263 }
264 }
265
266 GType
267 shell_mobile_provider_get_type (void)
268 {
269 static GType type = 0;
270
271 if (G_UNLIKELY (type == 0)) {
272 type = g_boxed_type_register_static ("ShellMobileProvider",
273 (GBoxedCopyFunc) shell_mobile_provider_ref,
274 (GBoxedFreeFunc) shell_mobile_provider_unref);
275 }
276 return type;
277 }
278
279 static void
280 provider_list_free (gpointer data)
281 {
282 GSList *list = (GSList *) data;
283
284 while (list) {
285 shell_mobile_provider_unref ((ShellMobileProvider *) list->data);
286 list = g_slist_delete_link (list, list);
287 }
288 }
289
290 static void
291 parser_toplevel_start (MobileParser *parser,
292 const char *name,
293 const char **attribute_names,
294 const char **attribute_values)
295 {
296 int i;
297
298 if (!strcmp (name, "serviceproviders")) {
299 for (i = 0; attribute_names && attribute_names[i]; i++) {
300 if (!strcmp (attribute_names[i], "format")) {
301 if (strcmp (attribute_values[i], "2.0")) {
302 g_warning ("%s: mobile broadband provider database format '%s'"
303 " not supported.", __func__, attribute_values[i]);
304 parser->state = PARSER_ERROR;
305 break;
306 }
307 }
308 }
309 } else if (!strcmp (name, "country")) {
310 for (i = 0; attribute_names && attribute_names[i]; i++) {
311 if (!strcmp (attribute_names[i], "code")) {
312 char *country_code;
313 char *country;
314
315 country_code = g_ascii_strup (attribute_values[i], -1);
316 country = g_hash_table_lookup (parser->country_codes, country_code);
317 if (country) {
318 parser->current_country = g_strdup (country);
319 g_free (country_code);
320 } else
321 parser->current_country = country_code;
322
323 parser->state = PARSER_COUNTRY;
324 break;
325 }
326 }
327 }
328 }
329
330 static void
331 parser_country_start (MobileParser *parser,
332 const char *name,
333 const char **attribute_names,
334 const char **attribute_values)
335 {
336 if (!strcmp (name, "provider")) {
337 parser->state = PARSER_PROVIDER;
338 parser->current_provider = provider_new ();
339 }
340 }
341
342 static void
343 parser_provider_start (MobileParser *parser,
344 const char *name,
345 const char **attribute_names,
346 const char **attribute_values)
347 {
348 if (!strcmp (name, "gsm"))
349 parser->state = PARSER_METHOD_GSM;
350 else if (!strcmp (name, "cdma")) {
351 parser->state = PARSER_METHOD_CDMA;
352 parser->current_method = access_method_new ();
353 }
354 }
355
356 static void
357 parser_gsm_start (MobileParser *parser,
358 const char *name,
359 const char **attribute_names,
360 const char **attribute_values)
361 {
362 if (!strcmp (name, "network-id")) {
363 const char *mcc = NULL, *mnc = NULL;
364 int i;
365
366 for (i = 0; attribute_names && attribute_names[i]; i++) {
367 if (!strcmp (attribute_names[i], "mcc"))
368 mcc = attribute_values[i];
369 else if (!strcmp (attribute_names[i], "mnc"))
370 mnc = attribute_values[i];
371
372 if (mcc && strlen (mcc) && mnc && strlen (mnc)) {
373 parser->current_provider->gsm_mcc_mnc = g_slist_prepend (parser->current_provider->gsm_mcc_mnc,
374 mcc_mnc_new (mcc, mnc));
375 break;
376 }
377 }
378 } else if (!strcmp (name, "apn")) {
379 int i;
380
381 for (i = 0; attribute_names && attribute_names[i]; i++) {
382 if (!strcmp (attribute_names[i], "value")) {
383
384 parser->state = PARSER_METHOD_GSM_APN;
385 parser->current_method = access_method_new ();
386 parser->current_method->gsm_apn = g_strstrip (g_strdup (attribute_values[i]));
387 break;
388 }
389 }
390 }
391 }
392
393 static void
394 parser_cdma_start (MobileParser *parser,
395 const char *name,
396 const char **attribute_names,
397 const char **attribute_values)
398 {
399 if (!strcmp (name, "sid")) {
400 int i;
401
402 for (i = 0; attribute_names && attribute_names[i]; i++) {
403 if (!strcmp (attribute_names[i], "value")) {
404 unsigned long tmp;
405
406 errno = 0;
407 tmp = strtoul (attribute_values[i], NULL, 10);
408 if (errno == 0 && tmp > 0)
409 parser->current_provider->cdma_sid = g_slist_prepend (parser->current_provider->cdma_sid,
410 GUINT_TO_POINTER ((guint32) tmp));
411 break;
412 }
413 }
414 }
415 }
416
417 static void
418 mobile_parser_start_element (GMarkupParseContext *context,
419 const gchar *element_name,
420 const gchar **attribute_names,
421 const gchar **attribute_values,
422 gpointer data,
423 GError **error)
424 {
425 MobileParser *parser = (MobileParser *) data;
426
427 if (parser->text_buffer) {
428 g_free (parser->text_buffer);
429 parser->text_buffer = NULL;
430 }
431
432 switch (parser->state) {
433 case PARSER_TOPLEVEL:
434 parser_toplevel_start (parser, element_name, attribute_names, attribute_values);
435 break;
436 case PARSER_COUNTRY:
437 parser_country_start (parser, element_name, attribute_names, attribute_values);
438 break;
439 case PARSER_PROVIDER:
440 parser_provider_start (parser, element_name, attribute_names, attribute_values);
441 break;
442 case PARSER_METHOD_GSM:
443 parser_gsm_start (parser, element_name, attribute_names, attribute_values);
444 break;
445 case PARSER_METHOD_CDMA:
446 parser_cdma_start (parser, element_name, attribute_names, attribute_values);
447 break;
448 default:
449 break;
450 }
451 }
452
453 static void
454 parser_country_end (MobileParser *parser,
455 const char *name)
456 {
457 if (!strcmp (name, "country")) {
458 g_hash_table_insert (parser->table, parser->current_country, parser->current_providers);
459 parser->current_country = NULL;
460 parser->current_providers = NULL;
461 parser->text_buffer = NULL;
462 parser->state = PARSER_TOPLEVEL;
463 }
464 }
465
466 static void
467 parser_provider_end (MobileParser *parser,
468 const char *name)
469 {
470 if (!strcmp (name, "name")) {
471 if (!parser->current_provider->name) {
472 /* Use the first one. */
473 parser->current_provider->name = parser->text_buffer;
474 parser->text_buffer = NULL;
475 }
476 } else if (!strcmp (name, "provider")) {
477 parser->current_provider->methods = g_slist_reverse (parser->current_provider->methods);
478
479 parser->current_provider->gsm_mcc_mnc = g_slist_reverse (parser->current_provider->gsm_mcc_mnc);
480 parser->current_provider->cdma_sid = g_slist_reverse (parser->current_provider->cdma_sid);
481
482 parser->current_providers = g_slist_prepend (parser->current_providers, parser->current_provider);
483 parser->current_provider = NULL;
484 parser->text_buffer = NULL;
485 parser->state = PARSER_COUNTRY;
486 }
487 }
488
489 static void
490 parser_gsm_end (MobileParser *parser,
491 const char *name)
492 {
493 if (!strcmp (name, "gsm")) {
494 parser->text_buffer = NULL;
495 parser->state = PARSER_PROVIDER;
496 }
497 }
498
499 static void
500 parser_gsm_apn_end (MobileParser *parser,
501 const char *name)
502 {
503 if (!strcmp (name, "name")) {
504 if (!parser->current_method->name) {
505 /* Use the first one. */
506 parser->current_method->name = parser->text_buffer;
507 parser->text_buffer = NULL;
508 }
509 } else if (!strcmp (name, "username")) {
510 parser->current_method->username = parser->text_buffer;
511 parser->text_buffer = NULL;
512 } else if (!strcmp (name, "password")) {
513 parser->current_method->password = parser->text_buffer;
514 parser->text_buffer = NULL;
515 } else if (!strcmp (name, "dns")) {
516 parser->current_method->dns = g_slist_prepend (parser->current_method->dns, parser->text_buffer);
517 parser->text_buffer = NULL;
518 } else if (!strcmp (name, "gateway")) {
519 parser->current_method->gateway = parser->text_buffer;
520 parser->text_buffer = NULL;
521 } else if (!strcmp (name, "apn")) {
522 parser->current_method->type = SHELL_MOBILE_ACCESS_METHOD_TYPE_GSM;
523 parser->current_method->dns = g_slist_reverse (parser->current_method->dns);
524
525 if (!parser->current_method->name)
526 parser->current_method->name = g_strdup (_("Default"));
527
528 parser->current_provider->methods = g_slist_prepend (parser->current_provider->methods,
529 parser->current_method);
530 parser->current_method = NULL;
531 parser->text_buffer = NULL;
532 parser->state = PARSER_METHOD_GSM;
533 }
534 }
535
536 static void
537 parser_cdma_end (MobileParser *parser,
538 const char *name)
539 {
540 if (!strcmp (name, "username")) {
541 parser->current_method->username = parser->text_buffer;
542 parser->text_buffer = NULL;
543 } else if (!strcmp (name, "password")) {
544 parser->current_method->password = parser->text_buffer;
545 parser->text_buffer = NULL;
546 } else if (!strcmp (name, "dns")) {
547 parser->current_method->dns = g_slist_prepend (parser->current_method->dns, parser->text_buffer);
548 parser->text_buffer = NULL;
549 } else if (!strcmp (name, "gateway")) {
550 parser->current_method->gateway = parser->text_buffer;
551 parser->text_buffer = NULL;
552 } else if (!strcmp (name, "cdma")) {
553 parser->current_method->type = SHELL_MOBILE_ACCESS_METHOD_TYPE_CDMA;
554 parser->current_method->dns = g_slist_reverse (parser->current_method->dns);
555
556 if (!parser->current_method->name)
557 parser->current_method->name = g_strdup (parser->current_provider->name);
558
559 parser->current_provider->methods = g_slist_prepend (parser->current_provider->methods,
560 parser->current_method);
561 parser->current_method = NULL;
562 parser->text_buffer = NULL;
563 parser->state = PARSER_PROVIDER;
564 }
565 }
566
567 static void
568 mobile_parser_end_element (GMarkupParseContext *context,
569 const gchar *element_name,
570 gpointer data,
571 GError **error)
572 {
573 MobileParser *parser = (MobileParser *) data;
574
575 switch (parser->state) {
576 case PARSER_COUNTRY:
577 parser_country_end (parser, element_name);
578 break;
579 case PARSER_PROVIDER:
580 parser_provider_end (parser, element_name);
581 break;
582 case PARSER_METHOD_GSM:
583 parser_gsm_end (parser, element_name);
584 break;
585 case PARSER_METHOD_GSM_APN:
586 parser_gsm_apn_end (parser, element_name);
587 break;
588 case PARSER_METHOD_CDMA:
589 parser_cdma_end (parser, element_name);
590 break;
591 default:
592 break;
593 }
594 }
595
596 static void
597 mobile_parser_characters (GMarkupParseContext *context,
598 const gchar *text,
599 gsize text_len,
600 gpointer data,
601 GError **error)
602 {
603 MobileParser *parser = (MobileParser *) data;
604
605 g_free (parser->text_buffer);
606 parser->text_buffer = g_strdup (text);
607 }
608
609 static const GMarkupParser mobile_parser = {
610 mobile_parser_start_element,
611 mobile_parser_end_element,
612 mobile_parser_characters,
613 NULL, /* passthrough */
614 NULL /* error */
615 };
616
617 /**
618 * shell_mobile_providers_parse:
619 * @out_ccs: (out) (allow-none): (element-type utf8 utf8): a #GHashTable containing
620 * country codes
621 *
622 * Returns: (element-type utf8 GList) (transfer container): a
623 * hash table where keys are country names #gchar, values are a #GSList
624 * of #ShellMobileProvider. Everything is destroyed with g_hash_table_destroy().
625 */
626 GHashTable *
627 shell_mobile_providers_parse (GHashTable **out_ccs)
628 {
629 GMarkupParseContext *ctx;
630 GIOChannel *channel;
631 MobileParser parser;
632 GError *error = NULL;
633 char buffer[4096];
634 GIOStatus status;
635 gsize len = 0;
636
637 memset (&parser, 0, sizeof (MobileParser));
638
639 parser.country_codes = read_country_codes ();
640 if (!parser.country_codes)
641 goto out;
642
643 channel = g_io_channel_new_file (MOBILE_BROADBAND_PROVIDER_INFO, "r", &error);
644 if (!channel) {
645 if (error) {
646 g_warning ("Could not read " MOBILE_BROADBAND_PROVIDER_INFO ": %s", error->message);
647 g_error_free (error);
648 } else
649 g_warning ("Could not read " MOBILE_BROADBAND_PROVIDER_INFO ": Unknown error");
650
651 goto out;
652 }
653
654 parser.table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, provider_list_free);
655 parser.state = PARSER_TOPLEVEL;
656
657 ctx = g_markup_parse_context_new (&mobile_parser, 0, &parser, NULL);
658
659 status = G_IO_STATUS_NORMAL;
660 while (status == G_IO_STATUS_NORMAL) {
661 status = g_io_channel_read_chars (channel, buffer, sizeof (buffer), &len, &error);
662
663 switch (status) {
664 case G_IO_STATUS_NORMAL:
665 if (!g_markup_parse_context_parse (ctx, buffer, len, &error)) {
666 status = G_IO_STATUS_ERROR;
667 g_warning ("Error while parsing XML: %s", error->message);
668 g_error_free (error);;
669 }
670 break;
671 case G_IO_STATUS_EOF:
672 break;
673 case G_IO_STATUS_ERROR:
674 g_warning ("Error while reading: %s", error->message);
675 g_error_free (error);
676 break;
677 case G_IO_STATUS_AGAIN:
678 /* FIXME: Try again a few times, but really, it never happes, right? */
679 break;
680 }
681 }
682
683 g_io_channel_unref (channel);
684 g_markup_parse_context_free (ctx);
685
686 if (parser.current_provider) {
687 g_warning ("pending current provider");
688 shell_mobile_provider_unref (parser.current_provider);
689 }
690
691 if (parser.current_providers) {
692 g_warning ("pending current providers");
693 provider_list_free (parser.current_providers);
694 }
695
696 g_free (parser.current_country);
697 g_free (parser.text_buffer);
698
699 out:
700 if (parser.country_codes) {
701 if (out_ccs)
702 *out_ccs = parser.country_codes;
703 else
704 g_hash_table_destroy (parser.country_codes);
705 }
706
707 return parser.table;
708 }
709
710 static void
711 dump_generic (ShellMobileAccessMethod *method)
712 {
713 GSList *iter;
714 GString *dns;
715
716 g_print (" username: %s\n", method->username ? method->username : "");
717 g_print (" password: %s\n", method->password ? method->password : "");
718
719 dns = g_string_new (NULL);
720 for (iter = method->dns; iter; iter = g_slist_next (iter))
721 g_string_append_printf (dns, "%s%s", dns->len ? ", " : "", (char *) iter->data);
722 g_print (" dns : %s\n", dns->str);
723 g_string_free (dns, TRUE);
724
725 g_print (" gateway : %s\n", method->gateway ? method->gateway : "");
726 }
727
728 static void
729 dump_cdma (ShellMobileAccessMethod *method)
730 {
731 g_print (" CDMA: %s\n", method->name);
732
733 dump_generic (method);
734 }
735
736 static void
737 dump_gsm (ShellMobileAccessMethod *method)
738 {
739 g_print (" APN: %s (%s)\n", method->name, method->gsm_apn);
740
741 dump_generic (method);
742 }
743
744 static void
745 dump_country (gpointer key, gpointer value, gpointer user_data)
746 {
747 GSList *citer, *miter;
748
749 for (citer = value; citer; citer = g_slist_next (citer)) {
750 ShellMobileProvider *provider = citer->data;
751
752 g_print ("Provider: %s (%s)\n", provider->name, (const char *) key);
753 for (miter = provider->methods; miter; miter = g_slist_next (miter)) {
754 ShellMobileAccessMethod *method = miter->data;
755 GSList *liter;
756
757
758 for (liter = provider->gsm_mcc_mnc; liter; liter = g_slist_next (liter)) {
759 ShellGsmMccMnc *m = liter->data;
760 g_print (" MCC/MNC: %s-%s\n", m->mcc, m->mnc);
761 }
762
763 for (liter = provider->cdma_sid; liter; liter = g_slist_next (liter))
764 g_print (" SID: %d\n", GPOINTER_TO_UINT (liter->data));
765
766 switch (method->type) {
767 case SHELL_MOBILE_ACCESS_METHOD_TYPE_CDMA:
768 dump_cdma (method);
769 break;
770 case SHELL_MOBILE_ACCESS_METHOD_TYPE_GSM:
771 dump_gsm (method);
772 break;
773 default:
774 break;
775 }
776 g_print ("\n");
777 }
778 }
779 }
780
781 void
782 shell_mobile_providers_dump (GHashTable *providers)
783 {
784 g_return_if_fail (providers != NULL);
785 g_hash_table_foreach (providers, dump_country, NULL);
786 }
787
788 /* All the following don't exist in nm-applet, because C doesn't need
789 those. They're only needed for the introspection annotations
790 */
791
792 /**
793 * shell_mobile_provider_get_gsm_mcc_mnc:
794 * @provider: a #ShellMobileProvider
795 *
796 * Returns: (element-type Shell.GsmMccMnc) (transfer none): the
797 * list of #ShellGsmMccMnc this provider exposes
798 */
799 GSList *
800 shell_mobile_provider_get_gsm_mcc_mnc (ShellMobileProvider *provider)
801 {
802 return provider->gsm_mcc_mnc;
803 }
804
805 /**
806 * shell_mobile_provider_get_cdma_sid:
807 * @provider: a #ShellMobileProvider
808 *
809 * Returns: (element-type guint32) (transfer none): the
810 * list of CDMA sids this provider exposes
811 */
812 GSList *
813 shell_mobile_provider_get_cdma_sid (ShellMobileProvider *provider)
814 {
815 return provider->cdma_sid;
816 }