c0b316b713aca100d972bc765cfd6cdcf48a4038
[platform/core/api/tethering.git] / test / tethering_test.c
1 /*
2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <unistd.h>
21 #include <glib.h>
22 #include <glib-object.h>
23 #include <sys/socket.h>
24 #include <netinet/in.h>
25 #include <arpa/inet.h>
26
27 #include <vconf.h>
28
29 #include "tethering.h"
30
31 #define INPUT_BUF_LEN           128
32 #define DISABLE_REASON_TEXT_LEN 64
33 #define COMMON_STR_BUF_LEN      32
34
35 typedef struct {
36         tethering_enabled_cb enabled_cb;
37         tethering_disabled_cb disabled_cb;
38         tethering_connection_state_changed_cb changed_cb;
39         tethering_wifi_security_type_changed_cb security_type_changed_cb;
40         tethering_wifi_ssid_visibility_changed_cb ssid_visibility_changed_cb;
41         tethering_wifi_passphrase_changed_cb passphrase_changed_cb;
42 } __tethering_cbs;
43
44 static GMainLoop *mainloop = NULL;
45
46 static bool __is_err(tethering_error_e ret)
47 {
48         char *err_msg = NULL;
49
50         switch (ret) {
51         case TETHERING_ERROR_INVALID_PARAMETER:
52                 err_msg = "Wrong parameter is used";
53                 break;
54
55         case TETHERING_ERROR_OUT_OF_MEMORY:
56                 err_msg = "Memory is not enough";
57                 break;
58
59         case TETHERING_ERROR_NONE:
60                 return false;
61
62         case TETHERING_ERROR_NOT_ENABLED:
63                 err_msg = "Tethering is not enabled";
64                 break;
65
66         case TETHERING_ERROR_OPERATION_FAILED:
67                 err_msg = "Operation is failed";
68                 break;
69
70         case TETHERING_ERROR_RESOURCE_BUSY:
71                 err_msg = "Resource is busy";
72                 break;
73
74         default:
75                 err_msg = "This should not be happened";
76                 break;
77         }
78
79         g_print("%s\n", err_msg);
80
81         return true;
82 }
83
84 static const char *__convert_tethering_type_to_str(const tethering_type_e type)
85 {
86         static char str_buf[COMMON_STR_BUF_LEN] = {0, };
87
88         switch (type) {
89         case TETHERING_TYPE_USB:
90                 g_strlcpy(str_buf, "USB", sizeof(str_buf));
91                 break;
92
93         case TETHERING_TYPE_WIFI:
94                 g_strlcpy(str_buf, "Wi-Fi", sizeof(str_buf));
95                 break;
96
97         case TETHERING_TYPE_BT:
98                 g_strlcpy(str_buf, "Bluetooth", sizeof(str_buf));
99                 break;
100
101         default:
102                 g_strlcpy(str_buf, "Unknown", sizeof(str_buf));
103                 break;
104         }
105
106         return str_buf;
107 }
108
109 static const char *__convert_disabled_code_to_str(const tethering_disabled_cause_e code)
110 {
111         static char str_buf[DISABLE_REASON_TEXT_LEN] = {0, };
112
113         switch (code) {
114         case TETHERING_DISABLED_BY_USB_DISCONNECTION:
115                 strncpy(str_buf, "disabled due to usb disconnection", sizeof(str_buf));
116                 break;
117
118         case TETHERING_DISABLED_BY_FLIGHT_MODE:
119                 strncpy(str_buf, "disabled due to flight mode on", sizeof(str_buf));
120                 break;
121
122         case TETHERING_DISABLED_BY_LOW_BATTERY:
123                 strncpy(str_buf, "disabled due to low battery", sizeof(str_buf));
124                 break;
125
126         case TETHERING_DISABLED_BY_NETWORK_CLOSE:
127                 strncpy(str_buf, "disabled due to pdp network close", sizeof(str_buf));
128                 break;
129
130         case TETHERING_DISABLED_BY_TIMEOUT:
131                 strncpy(str_buf, "disabled due to timeout", sizeof(str_buf));
132                 break;
133
134         case TETHERING_DISABLED_BY_OTHERS:
135                 strncpy(str_buf, "disabled by other apps", sizeof(str_buf));
136                 break;
137
138         case TETHERING_DISABLED_BY_REQUEST:
139                 strncpy(str_buf, "disabled by my request", sizeof(str_buf));
140                 break;
141
142         case TETHERING_DISABLED_BY_WIFI_ON:
143                 strncpy(str_buf, "disabled by Wi-Fi station on", sizeof(str_buf));
144                 break;
145
146         case TETHERING_DISABLED_BY_BT_OFF:
147                 strncpy(str_buf, "disabled by bluetooth off", sizeof(str_buf));
148                 break;
149
150         default:
151                 strncpy(str_buf, "disabled by unknown reason", sizeof(str_buf));
152                 break;
153         }
154
155         return str_buf;
156 }
157
158 static void __register_cbs(tethering_h th, __tethering_cbs *cbs, void *user_data)
159 {
160         tethering_error_e ret = TETHERING_ERROR_NONE;
161
162         ret = tethering_set_enabled_cb(th, TETHERING_TYPE_ALL,
163                         cbs->enabled_cb, user_data);
164         if (__is_err(ret) == true) {
165                 g_print("tethering_set_enabled_cb is failed\n");
166         }
167
168         ret = tethering_set_disabled_cb(th, TETHERING_TYPE_ALL,
169                         cbs->disabled_cb, user_data);
170         if (__is_err(ret) == true) {
171                 g_print("tethering_set_disabled_cb is failed\n");
172         }
173
174         ret = tethering_set_connection_state_changed_cb(th, TETHERING_TYPE_ALL,
175                         cbs->changed_cb, user_data);
176         if (__is_err(ret) == true) {
177                 g_print("tethering_set_connection_state_changed_cb is failed\n");
178         }
179
180         ret = tethering_wifi_set_security_type_changed_cb(th,
181                         cbs->security_type_changed_cb, user_data);
182         if (__is_err(ret) == true) {
183                 g_print("tethering_wifi_set_security_type_changed_cb is failed\n");
184         }
185
186         ret = tethering_wifi_set_ssid_visibility_changed_cb(th,
187                         cbs->ssid_visibility_changed_cb, user_data);
188         if (__is_err(ret) == true) {
189                 g_print("tethering_wifi_set_ssid_visibility_changed_cb is failed\n");
190         }
191
192         ret = tethering_wifi_set_passphrase_changed_cb(th,
193                         cbs->passphrase_changed_cb, user_data);
194         if (__is_err(ret) == true) {
195                 g_print("tethering_wifi_set_passphrase_changed_cb is failed\n");
196         }
197
198         return;
199 }
200
201 static void __deregister_cbs(tethering_h th)
202 {
203         tethering_error_e ret = TETHERING_ERROR_NONE;
204
205         ret = tethering_unset_enabled_cb(th, TETHERING_TYPE_ALL);
206         if (__is_err(ret) == true) {
207                 g_print("tethering_unset_enabled_cb is failed\n");
208         }
209
210         ret = tethering_unset_disabled_cb(th, TETHERING_TYPE_ALL);
211         if (__is_err(ret) == true) {
212                 g_print("tethering_unset_disabled_cb is failed\n");
213         }
214
215         ret = tethering_unset_connection_state_changed_cb(th, TETHERING_TYPE_ALL);
216         if (__is_err(ret) == true) {
217                 g_print("tethering_unset_connection_state_changed_cb is failed\n");
218         }
219
220         ret = tethering_wifi_unset_security_type_changed_cb(th);
221         if (__is_err(ret) == true) {
222                 g_print("tethering_wifi_unset_security_type_changed_cb is failed\n");
223         }
224
225         ret = tethering_wifi_unset_ssid_visibility_changed_cb(th);
226         if (__is_err(ret) == true) {
227                 g_print("tethering_wifi_unset_ssid_visibility_changed_cb is failed\n");
228         }
229
230         ret = tethering_wifi_unset_passphrase_changed_cb(th);
231         if (__is_err(ret) == true) {
232                 g_print("tethering_wifi_unset_passphrase_changed_cb is failed\n");
233         }
234
235         return;
236 }
237
238 /* Tethering callbacks */
239 static void __enabled_cb(tethering_error_e error, tethering_type_e type, bool is_requested, void *data)
240 {
241         if (error != TETHERING_ERROR_NONE) {
242                 if (!is_requested) {
243                         return;
244                 }
245
246                 g_print("## %s tethering is not enabled. error code[0x%X]\n",
247                                 __convert_tethering_type_to_str(type),
248                                 error);
249                 return;
250         }
251
252         if (is_requested)
253                 g_print("## %s tethering is enabled successfully\n",
254                                 __convert_tethering_type_to_str(type));
255         else
256                 g_print("## %s tethering is enabled by other app\n",
257                                 __convert_tethering_type_to_str(type));
258
259         return;
260 }
261
262 static void __disabled_cb(tethering_error_e error, tethering_type_e type, tethering_disabled_cause_e code, void *data)
263 {
264         if (error != TETHERING_ERROR_NONE) {
265                 if (code != TETHERING_DISABLED_BY_REQUEST) {
266                         return;
267                 }
268
269                 g_print("## %s tethering is not disabled. error code[0x%X]\n",
270                                 __convert_tethering_type_to_str(type), error);
271                 return;
272         }
273
274         g_print("## %s tethering is %s\n",
275                         __convert_tethering_type_to_str(type),
276                         __convert_disabled_code_to_str(code));
277
278         return;
279 }
280
281 static void __connection_state_changed_cb(tethering_client_h client, bool open, void *data)
282 {
283         tethering_client_h clone = NULL;
284         tethering_type_e type;
285         char *ip_address = NULL;
286         char *mac_address = NULL;
287         char *hostname = NULL;
288
289         tethering_client_clone(&clone, client);
290         if (clone == NULL) {
291                 g_print("tetheirng_client_clone is failed\n");
292                 return;
293         }
294
295         tethering_client_get_tethering_type(clone, &type);
296         tethering_client_get_ip_address(clone,
297                         TETHERING_ADDRESS_FAMILY_IPV4, &ip_address);
298         tethering_client_get_mac_address(clone, &mac_address);
299         tethering_client_get_name(clone, &hostname);
300
301         if (open) {
302                 g_print("## New station Type [%s], IP [%s], MAC [%s], hostname [%s]\n",
303                                 __convert_tethering_type_to_str(type),
304                                 ip_address, mac_address, hostname);
305         } else {
306                 g_print("## Disconnected station Type [%s], IP [%s], MAC [%s], hostname [%s]\n",
307                                 __convert_tethering_type_to_str(type),
308                                 ip_address, mac_address, hostname);
309         }
310
311         if (ip_address)
312                 free(ip_address);
313         if (mac_address)
314                 free(mac_address);
315         if (hostname)
316                 free(hostname);
317
318         tethering_client_destroy(clone);
319
320         return;
321 }
322
323 static void __data_usage_cb(tethering_error_e result, unsigned long long received_data,
324                 unsigned long long sent_data, void *user_data)
325 {
326         g_print("__data_usage_cb\n");
327
328         if (result != TETHERING_ERROR_NONE) {
329                 g_print("tethering_get_data_usage is failed. error[0x%X]\n", result);
330                 return;
331         }
332
333         g_print("## Received data : %llu bytes\n", received_data);
334         g_print("## Sent data : %llu bytes\n", sent_data);
335
336         return;
337 }
338
339 static bool __clients_foreach_cb(tethering_client_h client, void *data)
340 {
341         tethering_client_h clone = NULL;
342         tethering_type_e type;
343         char *ip_address = NULL;
344         char *mac_address = NULL;
345         char *hostname = NULL;
346
347         /* Clone internal information */
348         if (tethering_client_clone(&clone, client) != TETHERING_ERROR_NONE) {
349                 g_print("tethering_client_clone is failed\n");
350                 return false;
351         }
352
353         /* Get information */
354         if (tethering_client_get_tethering_type(clone, &type) != TETHERING_ERROR_NONE) {
355                 g_print("tethering_client_get_type is failed\n");
356         }
357
358         if (tethering_client_get_ip_address(clone, TETHERING_ADDRESS_FAMILY_IPV4, &ip_address) != TETHERING_ERROR_NONE) {
359                 g_print("tethering_client_get_ip_address is failed\n");
360         }
361
362         if (tethering_client_get_mac_address(clone, &mac_address) != TETHERING_ERROR_NONE) {
363                 g_print("tethering_client_get_mac_address is failed\n");
364         }
365
366         if (tethering_client_get_name(clone, &hostname) != TETHERING_ERROR_NONE) {
367                 g_print("tethering_client_get_hostname is failed\n");
368         }
369         /* End of getting information */
370
371         g_print("\n< Client Info. >\n");
372         g_print("\tType %s\n", __convert_tethering_type_to_str(type));
373         g_print("\tIP Address %s\n", ip_address);
374         g_print("\tMAC Address : %s\n", mac_address);
375         g_print("\tHostname : %s\n", hostname);
376
377         /* Destroy cloned objects */
378         if (ip_address)
379                 free(ip_address);
380         if (mac_address)
381                 free(mac_address);
382         if (hostname)
383                 free(hostname);
384
385         tethering_client_destroy(clone);
386
387         /* Continue iteration */
388         return true;
389 }
390
391 static void __security_type_changed_cb(tethering_wifi_security_type_e changed_type, void *user_data)
392 {
393         g_print("Wi-Fi Tethering Security type is changed to [%s]\n",
394                         changed_type == TETHERING_WIFI_SECURITY_TYPE_NONE ?
395                         "open" : "wpa2-psk");
396         return;
397 }
398
399 static void __ssid_visibility_changed_cb(bool changed_visible, void *user_data)
400 {
401         g_print("SSID visibility for Wi-Fi tethering changed to [%s]\n",
402                         changed_visible ? "visible" : "invisible");
403         return;
404 }
405
406 static void __passphrase_changed_cb(void *user_data)
407 {
408         g_print("Wi-Fi Tethering passphrase is changed\n");
409         return;
410 }
411 /* End of tethering callbacks */
412
413 static void __enable_tethering(tethering_h th, tethering_type_e type)
414 {
415         if (th == NULL)
416                 return;
417
418         tethering_error_e error = TETHERING_ERROR_NONE;
419
420         error = tethering_enable(th, type);
421         __is_err(error);
422
423         return;
424 }
425
426 static void __disable_tethering(tethering_h th, tethering_type_e type)
427 {
428         if (th == NULL)
429                 return;
430
431         tethering_error_e error = TETHERING_ERROR_NONE;
432
433         error = tethering_disable(th, type);
434         __is_err(error);
435
436         return;
437 }
438
439 static void __print_interface_info(tethering_h th, tethering_type_e type)
440 {
441         char *interface = NULL;
442         char *mac_address = NULL;
443         char *ip_address = NULL;
444         char *gateway_address = NULL;
445         char *subnet_mask = NULL;
446
447         if (tethering_is_enabled(th, type) == FALSE) {
448                 g_print("%s tethering is not enabled\n",
449                                 __convert_tethering_type_to_str(type));
450                 return;
451         }
452
453         tethering_get_network_interface_name(th, type, &interface);
454         tethering_get_mac_address(th, type, &mac_address);
455         tethering_get_ip_address(th, type, TETHERING_ADDRESS_FAMILY_IPV4,
456                         &ip_address);
457         tethering_get_gateway_address(th, type, TETHERING_ADDRESS_FAMILY_IPV4,
458                         &gateway_address);
459         tethering_get_subnet_mask(th, type, TETHERING_ADDRESS_FAMILY_IPV4,
460                         &subnet_mask);
461
462         g_print("interface name : %s\n", interface);
463         g_print("mac address : %s\n", mac_address);
464         g_print("ip address : %s\n", ip_address);
465         g_print("gateway address: %s\n", gateway_address);
466         g_print("subnet mask : %s\n", subnet_mask);
467
468         if (interface)
469                 free(interface);
470         if (mac_address)
471                 free(mac_address);
472         if (ip_address)
473                 free(ip_address);
474         if (gateway_address)
475                 free(gateway_address);
476         if (subnet_mask)
477                 free(subnet_mask);
478
479         return;
480 }
481
482 static void __print_wifi_tethering_setting(tethering_h th)
483 {
484         char *ssid = NULL;
485         char *passphrase = NULL;
486         bool visibility = false;
487         tethering_wifi_security_type_e security_type = TETHERING_WIFI_SECURITY_TYPE_NONE;
488
489         int error = TETHERING_ERROR_NONE;
490
491         error = tethering_wifi_get_ssid(th, &ssid);
492         if (error != TETHERING_ERROR_NONE)
493                 __is_err(error);
494         else
495                 g_print("\n\t** WiFi tethering SSID : %s\n", ssid);
496
497         error = tethering_wifi_get_passphrase(th, &passphrase);
498         if (error != TETHERING_ERROR_NONE)
499                 __is_err(error);
500         else
501                 g_print("\t** WiFi tethering passphrase : %s\n", passphrase);
502
503         error = tethering_wifi_get_ssid_visibility(th, &visibility);
504         if (error != TETHERING_ERROR_NONE)
505                 __is_err(error);
506         else
507                 g_print("\t** WiFi tethering ssid visibility : %s\n",
508                                 visibility ? "visible" : "invisible");
509
510         error = tethering_wifi_get_security_type(th, &security_type);
511         if (error != TETHERING_ERROR_NONE)
512                 __is_err(error);
513         else
514                 g_print("\t** WiFi tethering security_type : %s\n",
515                                 security_type ==
516                                 TETHERING_WIFI_SECURITY_TYPE_NONE ?
517                                 "open" : "wpa2-psk");
518
519         if (ssid)
520                 free(ssid);
521         if (passphrase)
522                 free(passphrase);
523
524         return;
525 }
526
527 void print_menu(void)
528 {
529         g_print("\nTo get client information, enter 'clients [USB | WIFI | BT | ALL]'");
530         g_print("\nTo get interface information, enter 'info [USB | WIFI | BT]'");
531         g_print("\nTo get data usage, enter 'get data_usage'");
532         g_print("\nTo enable tethering, enter 'enable [USB | WIFI | BT | ALL]'");
533         g_print("\nTo disable tethering, enter 'disable [USB | WIFI | BT | ALL]'");
534         g_print("\nTo get Wi-Fi tethering setting, enter 'get wifi_setting'");
535         g_print("\nTo set Wi-Fi tethering setting, enter '[set_security_type | set_visibility] [0 | 1]'");
536         g_print("\nTo set Wi-Fi tethering passphrase, enter 'set_passphrase [passphrase]'");
537         g_print("\nTo set Wi-Fi tethering SSID, enter 'set_ssid [SSID]'");
538         g_print("\nTo quit, enter 'quit'\n> ");
539
540         return;
541 }
542
543 gboolean input(GIOChannel *channel, GIOCondition condition, gpointer data)
544 {
545         tethering_h th = (tethering_h)data;
546         tethering_type_e type = 0;
547         tethering_error_e error = 0;
548         gchar buf[INPUT_BUF_LEN] = {0, };
549         gchar *cmd = NULL;
550         gchar *param = NULL;
551         gsize read = 0;
552
553 #if !GLIB_CHECK_VERSION(2, 31, 0)
554         if (g_io_channel_read(channel, buf, INPUT_BUF_LEN, &read) != G_IO_ERROR_NONE) {
555                 g_print("g_io_channel_read is failed\n");
556                 return FALSE;
557         }
558 #else
559         GError *err = NULL;
560         GIOStatus ios;
561
562         ios = g_io_channel_read_chars(channel, buf, INPUT_BUF_LEN, &read, &err);
563         if (err != NULL) {
564                 g_print("g_io_channel_read_chars is failed : %s\n",
565                                 err->message);
566                 g_error_free(err);
567                 return FALSE;
568         } else if (ios != G_IO_STATUS_NORMAL) {
569                 g_print("g_io_channel_read_chars is failed : %d\n", ios);
570                 return FALSE;
571         }
572 #endif
573
574         buf[read] = '\0';
575         g_strstrip(buf);
576
577         cmd = buf;
578         param = strrchr(buf, ' ');
579
580         /* No parameter */
581         if (!strcmp(cmd, "quit")) {
582                 g_main_loop_quit(mainloop);
583                 return TRUE;
584         }
585
586         if (param == NULL) {
587                 print_menu();
588                 return TRUE;
589         }
590         *param = '\0';
591         param++;
592
593         /* One parameter except type */
594         if (!strcmp(cmd, "get") && !strcmp(param, "data_usage")) {
595                 error = tethering_get_data_usage(th, __data_usage_cb, NULL);
596                 if (error != TETHERING_ERROR_NONE)
597                         g_print("tethering_get_data_usage is failed [0x%X]\n",
598                                         error);
599                 goto DONE;
600         }
601
602         if (!strcmp(cmd, "get") && !strcmp(param, "wifi_setting")) {
603                 __print_wifi_tethering_setting(th);
604                 goto DONE;
605         }
606
607         if (!strcmp(cmd, "set_visibility")) {
608                 error = tethering_wifi_set_ssid_visibility(th, atoi(param));
609                 if (error != TETHERING_ERROR_NONE)
610                         g_print("tethering_wifi_set_ssid_visibility is failed [0x%X]\n",
611                                         error);
612                 goto DONE;
613         }
614
615         if (!strcmp(cmd, "set_security_type")) {
616                 error = tethering_wifi_set_security_type(th, atoi(param));
617                 if (error != TETHERING_ERROR_NONE)
618                         g_print("tethering_wifi_set_security_type is failed [0x%X]\n",
619                                         error);
620                 goto DONE;
621         }
622
623         /* This should be removed */
624         if (!strcmp(cmd, "set_passphrase")) {
625                 error = tethering_wifi_set_passphrase(th, param);
626                 if (error != TETHERING_ERROR_NONE)
627                         g_print("tethering_wifi_set_passphrase is failed [0x%X]\n",
628                                         error);
629                 goto DONE;
630         }
631
632         if (!strcmp(cmd, "set_ssid")) {
633                 error = tethering_wifi_set_ssid(th, param);
634                 if (error != TETHERING_ERROR_NONE)
635                         g_print("tethering_wifi_set_ssid is failed [0x%X]\n",
636                                         error);
637                 goto DONE;
638         }
639
640         /* One parameter(type) */
641         if (!strcmp(param, "USB"))
642                 type = TETHERING_TYPE_USB;
643         else if (!strcmp(param, "WIFI"))
644                 type = TETHERING_TYPE_WIFI;
645         else if (!strcmp(param, "BT"))
646                 type = TETHERING_TYPE_BT;
647         else if (!strcmp(param, "ALL"))
648                 type = TETHERING_TYPE_ALL;
649         else {
650                 goto DONE;
651         }
652
653         if (!strcmp(cmd, "clients")) {
654                 error = tethering_foreach_connected_clients(th, type,
655                                 __clients_foreach_cb, NULL);
656                 if (error != TETHERING_ERROR_NONE)
657                         g_print("tethering_get_data_usage is failed [0x%X]\n",
658                                         error);
659         } else if (!strcmp(cmd, "info")) {
660                 __print_interface_info(th, type);
661         } else if (!strcmp(cmd, "enable")) {
662                 __enable_tethering(th, type);
663         } else if (!strcmp(cmd, "disable")) {
664                 __disable_tethering(th, type);
665         } else {
666                 goto DONE;
667         }
668
669 DONE:
670         print_menu();
671         return TRUE;
672 }
673
674 int main(int argc, char *argv[])
675 {
676         tethering_h th = NULL;
677         GIOChannel *stdin_channel = NULL;
678         tethering_error_e ret = TETHERING_ERROR_NONE;
679         __tethering_cbs cbs = {
680                 __enabled_cb, __disabled_cb,
681                 __connection_state_changed_cb, __security_type_changed_cb,
682                 __ssid_visibility_changed_cb, __passphrase_changed_cb};
683
684 #if !GLIB_CHECK_VERSION(2,35,0)
685         g_type_init();
686 #endif
687
688         /* Create tethering handle */
689         ret = tethering_create(&th);
690         if (__is_err(ret) == true)
691                 return 0;
692
693         /* Register cbs */
694         __register_cbs(th, &cbs, NULL);
695
696         stdin_channel = g_io_channel_unix_new(0);
697         if (stdin_channel == NULL)
698                 return 0;
699
700         g_io_channel_set_encoding(stdin_channel, NULL, NULL);
701         g_io_channel_set_flags(stdin_channel,
702                         G_IO_FLAG_APPEND | G_IO_FLAG_NONBLOCK, NULL);
703
704         g_io_add_watch(stdin_channel, G_IO_IN, input, (gpointer)th);
705
706         print_menu();
707
708         mainloop = g_main_loop_new (NULL, 0);
709
710         g_main_loop_run(mainloop);
711         g_main_loop_unref(mainloop);
712
713         /* Deregister cbs */
714         __deregister_cbs(th);
715
716         /* Destroy tethering handle */
717         ret = tethering_destroy(th);
718         __is_err(ret);
719
720         return 0;
721 }
722