3
* BlueZ - Bluetooth protocol stack for Linux
5
* Copyright (C) 2013 Intel Corporation. All rights reserved.
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
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.
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 St, Fifth Floor, Boston, MA 02110-1301 USA
34
#include <sys/signalfd.h>
38
#include <readline/readline.h>
39
#include <readline/history.h>
42
#include "gdbus/gdbus.h"
43
#include "client/display.h"
45
/* String display constants */
46
#define COLORED_NEW COLOR_GREEN "NEW" COLOR_OFF
47
#define COLORED_CHG COLOR_YELLOW "CHG" COLOR_OFF
48
#define COLORED_DEL COLOR_RED "DEL" COLOR_OFF
50
#define PROMPT_ON COLOR_BLUE "[obex]" COLOR_OFF "# "
51
#define PROMPT_OFF "[obex]# "
53
#define OBEX_SESSION_INTERFACE "org.bluez.obex.Session1"
54
#define OBEX_TRANSFER_INTERFACE "org.bluez.obex.Transfer1"
55
#define OBEX_CLIENT_INTERFACE "org.bluez.obex.Client1"
56
#define OBEX_OPP_INTERFACE "org.bluez.obex.ObjectPush1"
57
#define OBEX_FTP_INTERFACE "org.bluez.obex.FileTransfer1"
58
#define OBEX_PBAP_INTERFACE "org.bluez.obex.PhonebookAccess1"
59
#define OBEX_MAP_INTERFACE "org.bluez.obex.MessageAccess1"
60
#define OBEX_MSG_INTERFACE "org.bluez.obex.Message1"
62
static GMainLoop *main_loop;
63
static DBusConnection *dbus_conn;
64
static GDBusProxy *default_session;
65
static GSList *sessions = NULL;
66
static GSList *opps = NULL;
67
static GSList *ftps = NULL;
68
static GSList *pbaps = NULL;
69
static GSList *maps = NULL;
70
static GSList *msgs = NULL;
71
static GSList *transfers = NULL;
72
static GDBusProxy *client = NULL;
74
struct transfer_data {
79
static void connect_handler(DBusConnection *connection, void *user_data)
81
rl_set_prompt(PROMPT_ON);
87
static void disconnect_handler(DBusConnection *connection, void *user_data)
89
rl_set_prompt(PROMPT_OFF);
95
static void cmd_quit(int argc, char *argv[])
97
g_main_loop_quit(main_loop);
100
static void connect_reply(DBusMessage *message, void *user_data)
104
dbus_error_init(&error);
106
if (dbus_set_error_from_message(&error, message) == TRUE) {
107
rl_printf("Failed to connect: %s\n", error.name);
108
dbus_error_free(&error);
112
rl_printf("Connection successful\n");
115
static void append_variant(DBusMessageIter *iter, int type, void *val)
117
DBusMessageIter value;
118
char sig[2] = { type, '\0' };
120
dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, sig, &value);
122
dbus_message_iter_append_basic(&value, type, val);
124
dbus_message_iter_close_container(iter, &value);
127
static void dict_append_entry(DBusMessageIter *dict, const char *key,
130
DBusMessageIter entry;
132
if (type == DBUS_TYPE_STRING) {
133
const char *str = *((const char **) val);
138
dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
141
dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
143
append_variant(&entry, type, val);
145
dbus_message_iter_close_container(dict, &entry);
148
struct connect_args {
153
static void connect_args_free(void *data)
155
struct connect_args *args = data;
158
g_free(args->target);
162
static void connect_setup(DBusMessageIter *iter, void *user_data)
164
struct connect_args *args = user_data;
165
DBusMessageIter dict;
167
dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &args->dev);
169
dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
170
DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
171
DBUS_TYPE_STRING_AS_STRING
172
DBUS_TYPE_VARIANT_AS_STRING
173
DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
176
if (args->target == NULL)
179
dict_append_entry(&dict, "Target", DBUS_TYPE_STRING, &args->target);
182
dbus_message_iter_close_container(iter, &dict);
185
static void cmd_connect(int argc, char *argv[])
187
struct connect_args *args;
188
const char *target = "opp";
191
rl_printf("Missing device address argument\n");
196
rl_printf("Client proxy not available\n");
203
args = g_new0(struct connect_args, 1);
204
args->dev = g_strdup(argv[1]);
205
args->target = g_strdup(target);
207
if (g_dbus_proxy_method_call(client, "CreateSession", connect_setup,
208
connect_reply, args, connect_args_free) == FALSE) {
209
rl_printf("Failed to connect\n");
213
rl_printf("Attempting to connect to %s\n", argv[1]);
216
static void disconnect_reply(DBusMessage *message, void *user_data)
220
dbus_error_init(&error);
222
if (dbus_set_error_from_message(&error, message) == TRUE) {
223
rl_printf("Failed to disconnect: %s\n", error.name);
224
dbus_error_free(&error);
228
rl_printf("Disconnection successful\n");
231
static void disconnect_setup(DBusMessageIter *iter, void *user_data)
233
GDBusProxy *proxy = user_data;
236
path = g_dbus_proxy_get_path(proxy);
238
dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
241
static GDBusProxy *find_session(const char *path)
245
for (l = sessions; l; l = g_slist_next(l)) {
246
GDBusProxy *proxy = l->data;
248
if (strcmp(path, g_dbus_proxy_get_path(proxy)) == 0)
255
static void cmd_disconnect(int argc, char *argv[])
260
proxy = find_session(argv[1]);
262
proxy = default_session;
265
rl_printf("Session not available\n");
269
if (g_dbus_proxy_method_call(client, "RemoveSession", disconnect_setup,
270
disconnect_reply, proxy, NULL) == FALSE) {
271
rl_printf("Failed to disconnect\n");
275
rl_printf("Attempting to disconnect to %s\n",
276
g_dbus_proxy_get_path(proxy));
279
static char *proxy_description(GDBusProxy *proxy, const char *title,
280
const char *description)
284
path = g_dbus_proxy_get_path(proxy);
286
return g_strdup_printf("%s%s%s%s %s ",
287
description ? "[" : "",
289
description ? "] " : "",
293
static void print_proxy(GDBusProxy *proxy, const char *title,
294
const char *description)
298
str = proxy_description(proxy, title, description);
300
rl_printf("%s%s\n", str, default_session == proxy ? "[default]" : "");
305
static void cmd_list(int argc, char *arg[])
309
for (l = sessions; l; l = g_slist_next(l)) {
310
GDBusProxy *proxy = l->data;
311
print_proxy(proxy, "Session", NULL);
315
static bool check_default_session(void)
317
if (!default_session) {
318
rl_printf("No default session available\n");
325
static void print_iter(const char *label, const char *name,
326
DBusMessageIter *iter)
329
dbus_uint64_t valu64;
330
dbus_uint32_t valu32;
331
dbus_uint16_t valu16;
334
DBusMessageIter subiter;
337
rl_printf("%s%s is nil\n", label, name);
341
switch (dbus_message_iter_get_arg_type(iter)) {
342
case DBUS_TYPE_INVALID:
343
rl_printf("%s%s is invalid\n", label, name);
345
case DBUS_TYPE_STRING:
346
case DBUS_TYPE_OBJECT_PATH:
347
dbus_message_iter_get_basic(iter, &valstr);
348
rl_printf("%s%s: %s\n", label, name, valstr);
350
case DBUS_TYPE_BOOLEAN:
351
dbus_message_iter_get_basic(iter, &valbool);
352
rl_printf("%s%s: %s\n", label, name,
353
valbool == TRUE ? "yes" : "no");
355
case DBUS_TYPE_UINT64:
356
dbus_message_iter_get_basic(iter, &valu64);
357
rl_printf("%s%s: %" PRIu64 "\n", label, name, valu64);
359
case DBUS_TYPE_UINT32:
360
dbus_message_iter_get_basic(iter, &valu32);
361
rl_printf("%s%s: 0x%08x\n", label, name, valu32);
363
case DBUS_TYPE_UINT16:
364
dbus_message_iter_get_basic(iter, &valu16);
365
rl_printf("%s%s: 0x%04x\n", label, name, valu16);
367
case DBUS_TYPE_INT16:
368
dbus_message_iter_get_basic(iter, &vals16);
369
rl_printf("%s%s: %d\n", label, name, vals16);
371
case DBUS_TYPE_VARIANT:
372
dbus_message_iter_recurse(iter, &subiter);
373
print_iter(label, name, &subiter);
375
case DBUS_TYPE_ARRAY:
376
dbus_message_iter_recurse(iter, &subiter);
377
while (dbus_message_iter_get_arg_type(&subiter) !=
379
print_iter(label, name, &subiter);
380
dbus_message_iter_next(&subiter);
383
case DBUS_TYPE_DICT_ENTRY:
384
dbus_message_iter_recurse(iter, &subiter);
385
dbus_message_iter_get_basic(&subiter, &valstr);
386
dbus_message_iter_next(&subiter);
387
print_iter(label, valstr, &subiter);
390
rl_printf("%s%s has unsupported type\n", label, name);
395
static void print_property(GDBusProxy *proxy, const char *name)
397
DBusMessageIter iter;
399
if (g_dbus_proxy_get_property(proxy, name, &iter) == FALSE)
402
print_iter("\t", name, &iter);
405
static void cmd_show(int argc, char *argv[])
410
if (check_default_session() == FALSE)
413
proxy = default_session;
415
proxy = find_session(argv[1]);
417
rl_printf("Session %s not available\n", argv[1]);
422
rl_printf("Session %s\n", g_dbus_proxy_get_path(proxy));
424
print_property(proxy, "Destination");
425
print_property(proxy, "Target");
428
static void set_default_session(GDBusProxy *proxy)
431
DBusMessageIter iter;
433
default_session = proxy;
435
if (!g_dbus_proxy_get_property(proxy, "Destination", &iter)) {
436
desc = g_strdup(PROMPT_ON);
440
dbus_message_iter_get_basic(&iter, &desc);
441
desc = g_strdup_printf(COLOR_BLUE "[%s]" COLOR_OFF "# ", desc);
449
static void cmd_select(int argc, char *argv[])
454
rl_printf("Missing session address argument\n");
458
proxy = find_session(argv[1]);
460
rl_printf("Session %s not available\n", argv[1]);
464
if (default_session == proxy)
467
set_default_session(proxy);
469
print_proxy(proxy, "Session", NULL);
472
static GDBusProxy *find_transfer(const char *path)
476
for (l = transfers; l; l = g_slist_next(l)) {
477
GDBusProxy *proxy = l->data;
479
if (strcmp(path, g_dbus_proxy_get_path(proxy)) == 0)
486
static GDBusProxy *find_message(const char *path)
490
for (l = msgs; l; l = g_slist_next(l)) {
491
GDBusProxy *proxy = l->data;
493
if (strcmp(path, g_dbus_proxy_get_path(proxy)) == 0)
500
static void transfer_info(GDBusProxy *proxy, int argc, char *argv[])
502
rl_printf("Transfer %s\n", g_dbus_proxy_get_path(proxy));
504
print_property(proxy, "Session");
505
print_property(proxy, "Name");
506
print_property(proxy, "Type");
507
print_property(proxy, "Status");
508
print_property(proxy, "Time");
509
print_property(proxy, "Size");
510
print_property(proxy, "Transferred");
511
print_property(proxy, "Filename");
514
static void message_info(GDBusProxy *proxy, int argc, char *argv[])
516
rl_printf("Message %s\n", g_dbus_proxy_get_path(proxy));
518
print_property(proxy, "Folder");
519
print_property(proxy, "Subject");
520
print_property(proxy, "Timestamp");
521
print_property(proxy, "Sender");
522
print_property(proxy, "SenderAddress");
523
print_property(proxy, "ReplyTo");
524
print_property(proxy, "Recipient");
525
print_property(proxy, "RecipientAddress");
526
print_property(proxy, "Type");
527
print_property(proxy, "Size");
528
print_property(proxy, "Status");
529
print_property(proxy, "Priority");
530
print_property(proxy, "Read");
531
print_property(proxy, "Deleted");
532
print_property(proxy, "Sent");
533
print_property(proxy, "Protected");
536
static void cmd_info(int argc, char *argv[])
541
rl_printf("Missing object path argument\n");
545
proxy = find_transfer(argv[1]);
547
transfer_info(proxy, argc, argv);
551
proxy = find_message(argv[1]);
553
message_info(proxy, argc, argv);
557
rl_printf("Object %s not available\n", argv[1]);
560
static void cancel_reply(DBusMessage *message, void *user_data)
564
dbus_error_init(&error);
566
if (dbus_set_error_from_message(&error, message) == TRUE) {
567
rl_printf("Failed to cancel: %s\n", error.name);
568
dbus_error_free(&error);
572
rl_printf("Cancel successful\n");
575
static void cmd_cancel(int argc, char *argv[])
580
rl_printf("Missing transfer address argument\n");
584
proxy = find_transfer(argv[1]);
586
rl_printf("Transfer %s not available\n", argv[1]);
590
if (g_dbus_proxy_method_call(proxy, "Cancel", NULL, cancel_reply, NULL,
592
rl_printf("Failed to cancel transfer\n");
596
rl_printf("Attempting to cancel transfer %s\n",
597
g_dbus_proxy_get_path(proxy));
600
static void suspend_reply(DBusMessage *message, void *user_data)
604
dbus_error_init(&error);
606
if (dbus_set_error_from_message(&error, message) == TRUE) {
607
rl_printf("Failed to suspend: %s\n", error.name);
608
dbus_error_free(&error);
612
rl_printf("Suspend successful\n");
615
static void cmd_suspend(int argc, char *argv[])
620
rl_printf("Missing transfer address argument\n");
624
proxy = find_transfer(argv[1]);
626
rl_printf("Transfer %s not available\n", argv[1]);
630
if (g_dbus_proxy_method_call(proxy, "Suspend", NULL, suspend_reply,
631
NULL, NULL) == FALSE) {
632
rl_printf("Failed to suspend transfer\n");
636
rl_printf("Attempting to suspend transfer %s\n",
637
g_dbus_proxy_get_path(proxy));
640
static void resume_reply(DBusMessage *message, void *user_data)
644
dbus_error_init(&error);
646
if (dbus_set_error_from_message(&error, message) == TRUE) {
647
rl_printf("Failed to resume: %s\n", error.name);
648
dbus_error_free(&error);
652
rl_printf("Resume successful\n");
655
static void cmd_resume(int argc, char *argv[])
660
rl_printf("Missing transfer address argument\n");
664
proxy = find_transfer(argv[1]);
666
rl_printf("Transfer %s not available\n", argv[1]);
670
if (g_dbus_proxy_method_call(proxy, "Resume", NULL, resume_reply,
671
NULL, NULL) == FALSE) {
672
rl_printf("Failed to resume transfer\n");
676
rl_printf("Attempting to resume transfer %s\n",
677
g_dbus_proxy_get_path(proxy));
680
static GDBusProxy *find_opp(const char *path)
684
for (l = opps; l; l = g_slist_next(l)) {
685
GDBusProxy *proxy = l->data;
687
if (strcmp(path, g_dbus_proxy_get_path(proxy)) == 0)
694
static GDBusProxy *find_map(const char *path)
698
for (l = maps; l; l = g_slist_next(l)) {
699
GDBusProxy *proxy = l->data;
701
if (strcmp(path, g_dbus_proxy_get_path(proxy)) == 0)
708
static void print_dict_iter(DBusMessageIter *iter)
710
DBusMessageIter dict;
713
ctype = dbus_message_iter_get_arg_type(iter);
714
if (ctype != DBUS_TYPE_ARRAY)
717
dbus_message_iter_recurse(iter, &dict);
719
while ((ctype = dbus_message_iter_get_arg_type(&dict)) !=
721
DBusMessageIter entry;
724
if (ctype != DBUS_TYPE_DICT_ENTRY)
727
dbus_message_iter_recurse(&dict, &entry);
728
if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
731
dbus_message_iter_get_basic(&entry, &key);
732
dbus_message_iter_next(&entry);
734
print_iter("\t", key, &entry);
736
dbus_message_iter_next(&dict);
740
static void print_transfer_iter(DBusMessageIter *iter)
744
dbus_message_iter_get_basic(iter, &path);
746
rl_printf("Transfer %s\n", path);
748
dbus_message_iter_next(iter);
750
print_dict_iter(iter);
753
static void send_reply(DBusMessage *message, void *user_data)
755
DBusMessageIter iter;
758
dbus_error_init(&error);
760
if (dbus_set_error_from_message(&error, message) == TRUE) {
761
rl_printf("Failed to send/pull: %s\n", error.name);
762
dbus_error_free(&error);
766
dbus_message_iter_init(message, &iter);
768
print_transfer_iter(&iter);
771
static void send_setup(DBusMessageIter *iter, void *user_data)
773
const char *file = user_data;
775
dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &file);
778
static void opp_send(GDBusProxy *proxy, int argc, char *argv[])
781
rl_printf("Missing file argument\n");
785
if (g_dbus_proxy_method_call(proxy, "SendFile", send_setup, send_reply,
786
g_strdup(argv[1]), g_free) == FALSE) {
787
rl_printf("Failed to send\n");
791
rl_printf("Attempting to send %s to %s\n", argv[1],
792
g_dbus_proxy_get_path(proxy));
795
static void opp_pull(GDBusProxy *proxy, int argc, char *argv[])
798
rl_printf("Missing file argument\n");
802
if (g_dbus_proxy_method_call(proxy, "PullBusinessCard", send_setup,
803
send_reply, g_strdup(argv[1]), g_free) == FALSE) {
804
rl_printf("Failed to pull\n");
808
rl_printf("Attempting to pull %s from %s\n", argv[1],
809
g_dbus_proxy_get_path(proxy));
812
static void push_reply(DBusMessage *message, void *user_data)
814
DBusMessageIter iter;
817
dbus_error_init(&error);
819
if (dbus_set_error_from_message(&error, message) == TRUE) {
820
rl_printf("Failed to PushMessage: %s\n", error.name);
821
dbus_error_free(&error);
825
dbus_message_iter_init(message, &iter);
827
print_transfer_iter(&iter);
830
static void push_setup(DBusMessageIter *iter, void *user_data)
832
const char *file = user_data;
833
const char *folder = "";
834
DBusMessageIter dict;
836
dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &file);
837
dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &folder);
839
dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
840
DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
841
DBUS_TYPE_STRING_AS_STRING
842
DBUS_TYPE_VARIANT_AS_STRING
843
DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
846
dbus_message_iter_close_container(iter, &dict);
849
static void map_send(GDBusProxy *proxy, int argc, char *argv[])
852
rl_printf("Missing file argument\n");
856
if (g_dbus_proxy_method_call(proxy, "PushMessage", push_setup,
857
push_reply, g_strdup(argv[1]),
859
rl_printf("Failed to send\n");
863
rl_printf("Attempting to send %s to %s\n", argv[1],
864
g_dbus_proxy_get_path(proxy));
867
static void cmd_send(int argc, char *argv[])
871
if (!check_default_session())
874
proxy = find_opp(g_dbus_proxy_get_path(default_session));
876
opp_send(proxy, argc, argv);
880
proxy = find_map(g_dbus_proxy_get_path(default_session));
882
map_send(proxy, argc, argv);
886
rl_printf("Command not supported\n");
889
static void cmd_pull(int argc, char *argv[])
893
if (!check_default_session())
896
proxy = find_opp(g_dbus_proxy_get_path(default_session));
898
opp_pull(proxy, argc, argv);
902
rl_printf("Command not supported\n");
905
static void change_folder_reply(DBusMessage *message, void *user_data)
909
dbus_error_init(&error);
911
if (dbus_set_error_from_message(&error, message) == TRUE) {
912
rl_printf("Failed to ChangeFolder: %s\n", error.name);
913
dbus_error_free(&error);
917
rl_printf("ChangeFolder successful\n");
920
static void change_folder_setup(DBusMessageIter *iter, void *user_data)
922
const char *folder = user_data;
924
dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &folder);
927
static void select_reply(DBusMessage *message, void *user_data)
929
DBusMessageIter iter;
932
dbus_error_init(&error);
934
if (dbus_set_error_from_message(&error, message) == TRUE) {
935
rl_printf("Failed to Select: %s\n", error.name);
936
dbus_error_free(&error);
940
dbus_message_iter_init(message, &iter);
942
rl_printf("Select successful\n");
945
static void select_setup(DBusMessageIter *iter, void *user_data)
947
const char *folder = user_data;
948
const char *location = "int";
950
dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &location);
951
dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &folder);
954
static void setfolder_reply(DBusMessage *message, void *user_data)
958
dbus_error_init(&error);
960
if (dbus_set_error_from_message(&error, message) == TRUE) {
961
rl_printf("Failed to SetFolder: %s\n", error.name);
962
dbus_error_free(&error);
966
rl_printf("SetFolder successful\n");
969
static void setfolder_setup(DBusMessageIter *iter, void *user_data)
971
const char *folder = user_data;
973
dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &folder);
976
static GDBusProxy *find_ftp(const char *path)
980
for (l = ftps; l; l = g_slist_next(l)) {
981
GDBusProxy *proxy = l->data;
983
if (strcmp(path, g_dbus_proxy_get_path(proxy)) == 0)
990
static GDBusProxy *find_pbap(const char *path)
994
for (l = pbaps; l; l = g_slist_next(l)) {
995
GDBusProxy *proxy = l->data;
997
if (strcmp(path, g_dbus_proxy_get_path(proxy)) == 0)
1004
static void ftp_cd(GDBusProxy *proxy, int argc, char *argv[])
1007
rl_printf("Missing path argument\n");
1011
if (g_dbus_proxy_method_call(proxy, "ChangeFolder", change_folder_setup,
1012
change_folder_reply, g_strdup(argv[1]),
1014
rl_printf("Failed to ChangeFolder\n");
1018
rl_printf("Attempting to ChangeFolder to %s\n", argv[1]);
1021
static void pbap_cd(GDBusProxy *proxy, int argc, char *argv[])
1024
rl_printf("Missing path argument\n");
1028
if (g_dbus_proxy_method_call(proxy, "Select", select_setup,
1029
select_reply, g_strdup(argv[1]),
1031
rl_printf("Failed to Select\n");
1035
rl_printf("Attempting to Select to %s\n", argv[1]);
1038
static void map_cd(GDBusProxy *proxy, int argc, char *argv[])
1041
rl_printf("Missing path argument\n");
1045
if (g_dbus_proxy_method_call(proxy, "SetFolder", setfolder_setup,
1046
setfolder_reply, g_strdup(argv[1]),
1048
rl_printf("Failed to SetFolder\n");
1052
rl_printf("Attempting to SetFolder to %s\n", argv[1]);
1055
static void cmd_cd(int argc, char *argv[])
1059
if (!check_default_session())
1062
proxy = find_ftp(g_dbus_proxy_get_path(default_session));
1064
ftp_cd(proxy, argc, argv);
1068
proxy = find_pbap(g_dbus_proxy_get_path(default_session));
1070
pbap_cd(proxy, argc, argv);
1074
proxy = find_map(g_dbus_proxy_get_path(default_session));
1076
map_cd(proxy, argc, argv);
1080
rl_printf("Command not supported\n");
1083
static void list_folder_reply(DBusMessage *message, void *user_data)
1085
DBusMessageIter iter, array;
1088
dbus_error_init(&error);
1090
if (dbus_set_error_from_message(&error, message) == TRUE) {
1091
rl_printf("Failed to ListFolder: %s\n", error.name);
1092
dbus_error_free(&error);
1096
dbus_message_iter_init(message, &iter);
1098
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
1101
dbus_message_iter_recurse(&iter, &array);
1103
while (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_INVALID) {
1104
print_dict_iter(&array);
1105
dbus_message_iter_next(&array);
1109
static void ftp_ls(GDBusProxy *proxy, int argc, char *argv[])
1111
if (g_dbus_proxy_method_call(proxy, "ListFolder", NULL,
1112
list_folder_reply, NULL,
1114
rl_printf("Failed to ls\n");
1118
rl_printf("Attempting to ListFolder\n");
1121
static void parse_list_reply(DBusMessage *message)
1123
DBusMessageIter iter, array;
1125
dbus_message_iter_init(message, &iter);
1127
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
1130
dbus_message_iter_recurse(&iter, &array);
1132
while (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_INVALID) {
1133
DBusMessageIter entry;
1136
if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRUCT)
1139
dbus_message_iter_recurse(&array, &entry);
1141
dbus_message_iter_get_basic(&entry, &vcard);
1142
dbus_message_iter_next(&entry);
1143
print_iter("\t", vcard, &entry);
1144
dbus_message_iter_next(&array);
1148
static void list_reply(DBusMessage *message, void *user_data)
1152
dbus_error_init(&error);
1154
if (dbus_set_error_from_message(&error, message) == TRUE) {
1155
rl_printf("Failed to List: %s\n", error.name);
1156
dbus_error_free(&error);
1160
parse_list_reply(message);
1163
static void list_setup(DBusMessageIter *iter, void *user_data)
1165
DBusMessageIter dict;
1167
dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
1168
DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1169
DBUS_TYPE_STRING_AS_STRING
1170
DBUS_TYPE_VARIANT_AS_STRING
1171
DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
1174
dbus_message_iter_close_container(iter, &dict);
1177
static void search_reply(DBusMessage *message, void *user_data)
1181
dbus_error_init(&error);
1183
if (dbus_set_error_from_message(&error, message) == TRUE) {
1184
rl_printf("Failed to Search: %s\n", error.name);
1185
dbus_error_free(&error);
1189
parse_list_reply(message);
1192
static void search_setup(DBusMessageIter *iter, void *user_data)
1194
const char *value = user_data;
1196
DBusMessageIter dict;
1198
field = isalpha(value[0]) ? "name" : "number";
1200
dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &field);
1201
dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &value);
1203
dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
1204
DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1205
DBUS_TYPE_STRING_AS_STRING
1206
DBUS_TYPE_VARIANT_AS_STRING
1207
DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
1210
dbus_message_iter_close_container(iter, &dict);
1213
static void pbap_search(GDBusProxy *proxy, int argc, char *argv[])
1215
if (g_dbus_proxy_method_call(proxy, "Search", search_setup,
1216
search_reply, g_strdup(argv[1]),
1218
rl_printf("Failed to Search\n");
1222
rl_printf("Attempting to Search\n");
1225
static void list_folders_reply(DBusMessage *message, void *user_data)
1228
DBusMessageIter iter, array;
1230
dbus_error_init(&error);
1232
if (dbus_set_error_from_message(&error, message) == TRUE) {
1233
rl_printf("Failed to ListFolders: %s\n", error.name);
1234
dbus_error_free(&error);
1238
dbus_message_iter_init(message, &iter);
1240
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
1243
dbus_message_iter_recurse(&iter, &array);
1245
while (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_INVALID) {
1246
print_dict_iter(&array);
1247
dbus_message_iter_next(&array);
1251
static void list_folders_setup(DBusMessageIter *iter, void *user_data)
1253
DBusMessageIter dict;
1255
dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
1256
DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1257
DBUS_TYPE_STRING_AS_STRING
1258
DBUS_TYPE_VARIANT_AS_STRING
1259
DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
1262
dbus_message_iter_close_container(iter, &dict);
1265
static void list_messages_reply(DBusMessage *message, void *user_data)
1268
DBusMessageIter iter, array;
1270
dbus_error_init(&error);
1272
if (dbus_set_error_from_message(&error, message) == TRUE) {
1273
rl_printf("Failed to ListFolders: %s\n", error.name);
1274
dbus_error_free(&error);
1278
dbus_message_iter_init(message, &iter);
1280
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
1283
dbus_message_iter_recurse(&iter, &array);
1285
while ((dbus_message_iter_get_arg_type(&array)) ==
1286
DBUS_TYPE_DICT_ENTRY) {
1287
DBusMessageIter entry;
1290
dbus_message_iter_recurse(&array, &entry);
1291
dbus_message_iter_get_basic(&entry, &obj);
1292
rl_printf("\t%s\n", obj);
1293
dbus_message_iter_next(&array);
1297
static void list_messages_setup(DBusMessageIter *iter, void *user_data)
1299
const char *folder = user_data;
1300
DBusMessageIter dict;
1302
if (strcmp(folder, "*") == 0)
1305
dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &folder);
1307
dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
1308
DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1309
DBUS_TYPE_STRING_AS_STRING
1310
DBUS_TYPE_VARIANT_AS_STRING
1311
DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
1314
dbus_message_iter_close_container(iter, &dict);
1317
static void pbap_list(GDBusProxy *proxy, int argc, char *argv[])
1319
if (g_dbus_proxy_method_call(proxy, "List", list_setup, list_reply,
1320
NULL, NULL) == FALSE) {
1321
rl_printf("Failed to List\n");
1325
rl_printf("Attempting to List\n");
1328
static void get_size_reply(DBusMessage *message, void *user_data)
1330
GDBusProxy *proxy = user_data;
1332
DBusMessageIter iter;
1334
dbus_error_init(&error);
1336
if (dbus_set_error_from_message(&error, message) == TRUE) {
1337
rl_printf("Failed to GetSize: %s\n", error.name);
1338
dbus_error_free(&error);
1342
dbus_message_iter_init(message, &iter);
1344
print_iter("\t", "Size", &iter);
1346
pbap_list(proxy, 0, NULL);
1349
static void pbap_get_size(GDBusProxy *proxy, int argc, char *argv[])
1351
if (g_dbus_proxy_method_call(proxy, "GetSize", NULL, get_size_reply,
1352
proxy, NULL) == FALSE) {
1353
rl_printf("Failed to GetSize\n");
1357
rl_printf("Attempting to GetSize\n");
1360
static void pbap_ls(GDBusProxy *proxy, int argc, char *argv[])
1363
if (strcmp("-l", argv[1]))
1364
pbap_search(proxy, argc, argv);
1366
pbap_get_size(proxy, argc, argv);
1370
pbap_list(proxy, argc, argv);
1373
static void map_ls_messages(GDBusProxy *proxy, int argc, char *argv[])
1375
if (g_dbus_proxy_method_call(proxy, "ListMessages", list_messages_setup,
1376
list_messages_reply, g_strdup(argv[1]),
1378
rl_printf("Failed to ListMessages\n");
1382
rl_printf("Attempting to ListMessages\n");
1385
static void map_ls(GDBusProxy *proxy, int argc, char *argv[])
1388
map_ls_messages(proxy, argc, argv);
1392
if (g_dbus_proxy_method_call(proxy, "ListFolders", list_folders_setup,
1393
list_folders_reply, NULL,
1395
rl_printf("Failed to ListFolders\n");
1399
rl_printf("Attempting to ListFolders\n");
1402
static void cmd_ls(int argc, char *argv[])
1406
if (!check_default_session())
1409
proxy = find_ftp(g_dbus_proxy_get_path(default_session));
1411
ftp_ls(proxy, argc, argv);
1415
proxy = find_pbap(g_dbus_proxy_get_path(default_session));
1417
pbap_ls(proxy, argc, argv);
1421
proxy = find_map(g_dbus_proxy_get_path(default_session));
1423
map_ls(proxy, argc, argv);
1427
rl_printf("Command not supported\n");
1435
static void cp_free(void *data)
1437
struct cp_args *args = data;
1439
g_free(args->source);
1440
g_free(args->target);
1444
static struct cp_args *cp_new(char *argv[])
1446
struct cp_args *args;
1450
source = rindex(argv[1], ':');
1456
target = rindex(argv[2], ':');
1462
args = g_new0(struct cp_args, 1);
1463
args->source = g_strdup(source);
1464
args->target = g_strdup(target);
1469
static void cp_setup(DBusMessageIter *iter, void *user_data)
1471
struct cp_args *args = user_data;
1473
dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &args->source);
1474
dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &args->target);
1477
static void copy_file_reply(DBusMessage *message, void *user_data)
1481
dbus_error_init(&error);
1483
if (dbus_set_error_from_message(&error, message) == TRUE) {
1484
rl_printf("Failed to CopyFile: %s\n", error.name);
1485
dbus_error_free(&error);
1489
rl_printf("CopyFile successful\n");
1492
static void ftp_copy(GDBusProxy *proxy, int argc, char *argv[])
1494
struct cp_args *args;
1496
args = cp_new(argv);
1498
if (g_dbus_proxy_method_call(proxy, "CopyFile", cp_setup,
1499
copy_file_reply, args, cp_free) == FALSE) {
1500
rl_printf("Failed to CopyFile\n");
1504
rl_printf("Attempting to CopyFile\n");
1507
static void get_file_reply(DBusMessage *message, void *user_data)
1510
DBusMessageIter iter;
1512
dbus_error_init(&error);
1514
if (dbus_set_error_from_message(&error, message) == TRUE) {
1515
rl_printf("Failed to GetFile: %s\n", error.name);
1516
dbus_error_free(&error);
1520
dbus_message_iter_init(message, &iter);
1522
print_transfer_iter(&iter);
1525
static void get_file_setup(DBusMessageIter *iter, void *user_data)
1527
struct cp_args *args = user_data;
1529
dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &args->target);
1530
dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &args->source);
1533
static void ftp_get(GDBusProxy *proxy, int argc, char *argv[])
1535
struct cp_args *args;
1537
if (rindex(argv[2], ':') == NULL)
1538
return ftp_copy(proxy, argc, argv);
1540
args = cp_new(argv);
1542
if (g_dbus_proxy_method_call(proxy, "GetFile", get_file_setup,
1543
get_file_reply, args, cp_free) == FALSE) {
1544
rl_printf("Failed to GetFile\n");
1548
rl_printf("Attempting to GetFile\n");
1551
static void put_file_reply(DBusMessage *message, void *user_data)
1554
DBusMessageIter iter;
1556
dbus_error_init(&error);
1558
if (dbus_set_error_from_message(&error, message) == TRUE) {
1559
rl_printf("Failed to PutFile: %s\n", error.name);
1560
dbus_error_free(&error);
1564
dbus_message_iter_init(message, &iter);
1566
print_transfer_iter(&iter);
1569
static void ftp_put(GDBusProxy *proxy, int argc, char *argv[])
1571
struct cp_args *args;
1573
if (rindex(argv[2], ':') != NULL) {
1574
rl_printf("Invalid target file argument\n");
1578
args = cp_new(argv);
1580
if (g_dbus_proxy_method_call(proxy, "PutFile", cp_setup, put_file_reply,
1581
args, cp_free) == FALSE) {
1582
rl_printf("Failed to PutFile\n");
1586
rl_printf("Attempting to PutFile\n");
1589
static void ftp_cp(GDBusProxy *proxy, int argc, char *argv[])
1592
rl_printf("Missing source file argument\n");
1597
rl_printf("Missing target file argument\n");
1601
if (rindex(argv[1], ':') == NULL)
1602
return ftp_get(proxy, argc, argv);
1604
return ftp_put(proxy, argc, argv);
1607
static void pull_all_reply(DBusMessage *message, void *user_data)
1611
dbus_error_init(&error);
1613
if (dbus_set_error_from_message(&error, message) == TRUE) {
1614
rl_printf("Failed to PullAll: %s\n", error.name);
1615
dbus_error_free(&error);
1620
rl_printf("PullAll successful\n");
1623
static void pull_all_setup(DBusMessageIter *iter, void *user_data)
1625
const char *file = user_data;
1626
DBusMessageIter dict;
1628
dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &file);
1630
dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
1631
DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1632
DBUS_TYPE_STRING_AS_STRING
1633
DBUS_TYPE_VARIANT_AS_STRING
1634
DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
1637
dbus_message_iter_close_container(iter, &dict);
1640
static void pbap_pull_all(GDBusProxy *proxy, int argc, char *argv[])
1642
if (g_dbus_proxy_method_call(proxy, "PullAll", pull_all_setup,
1643
pull_all_reply, g_strdup(argv[2]),
1645
rl_printf("Failed to PullAll\n");
1649
rl_printf("Attempting to PullAll\n");
1652
static void pull_reply(DBusMessage *message, void *user_data)
1656
dbus_error_init(&error);
1658
if (dbus_set_error_from_message(&error, message) == TRUE) {
1659
rl_printf("Failed to Pull: %s\n", error.name);
1660
dbus_error_free(&error);
1665
rl_printf("Pull successful\n");
1668
static void pull_setup(DBusMessageIter *iter, void *user_data)
1670
struct cp_args *args = user_data;
1671
DBusMessageIter dict;
1673
dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &args->source);
1674
dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &args->target);
1676
dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
1677
DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1678
DBUS_TYPE_STRING_AS_STRING
1679
DBUS_TYPE_VARIANT_AS_STRING
1680
DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
1683
dbus_message_iter_close_container(iter, &dict);
1686
static void pbap_pull(GDBusProxy *proxy, int argc, char *argv[])
1688
struct cp_args *args;
1690
args = cp_new(argv);
1692
if (g_dbus_proxy_method_call(proxy, "Pull", pull_setup, pull_reply,
1693
args, cp_free) == FALSE) {
1694
rl_printf("Failed to Pull\n");
1698
rl_printf("Attempting to Pull\n");
1701
static void pbap_cp(GDBusProxy *proxy, int argc, char *argv[])
1704
rl_printf("Missing source file argument\n");
1709
rl_printf("Missing target file argument\n");
1713
if (strcmp(argv[1], "*") == 0)
1714
return pbap_pull_all(proxy, argc, argv);
1716
return pbap_pull(proxy, argc, argv);
1719
static void get_reply(DBusMessage *message, void *user_data)
1721
DBusMessageIter iter;
1724
dbus_error_init(&error);
1726
if (dbus_set_error_from_message(&error, message) == TRUE) {
1727
rl_printf("Failed to Get: %s\n", error.name);
1728
dbus_error_free(&error);
1732
dbus_message_iter_init(message, &iter);
1734
print_transfer_iter(&iter);
1737
static void get_setup(DBusMessageIter *iter, void *user_data)
1739
const char *file = user_data;
1740
dbus_bool_t attachment = TRUE;
1742
dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &file);
1743
dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &attachment);
1746
static void map_cp(GDBusProxy *proxy, int argc, char *argv[])
1751
rl_printf("Missing message argument\n");
1755
obj = find_message(argv[1]);
1757
rl_printf("Invalid message argument\n");
1762
rl_printf("Missing target file argument\n");
1766
if (g_dbus_proxy_method_call(obj, "Get", get_setup, get_reply,
1767
g_strdup(argv[2]), g_free) == FALSE) {
1768
rl_printf("Failed to Get\n");
1772
rl_printf("Attempting to Get\n");
1775
static void cmd_cp(int argc, char *argv[])
1780
if (!check_default_session())
1783
proxy = find_ftp(g_dbus_proxy_get_path(default_session));
1785
ftp_cp(proxy, argc, argv);
1789
proxy = find_pbap(g_dbus_proxy_get_path(default_session));
1791
pbap_cp(proxy, argc, argv);
1795
proxy = find_map(g_dbus_proxy_get_path(default_session));
1797
map_cp(proxy, argc, argv);
1801
rl_printf("Command not supported\n");
1804
static void move_file_reply(DBusMessage *message, void *user_data)
1808
dbus_error_init(&error);
1810
if (dbus_set_error_from_message(&error, message) == TRUE) {
1811
rl_printf("Failed to MoveFile: %s\n", error.name);
1812
dbus_error_free(&error);
1816
rl_printf("MoveFile successful\n");
1819
static void cmd_mv(int argc, char *argv[])
1822
struct cp_args *args;
1824
if (!check_default_session())
1828
rl_printf("Missing source file argument\n");
1833
rl_printf("Missing target file argument\n");
1837
proxy = find_ftp(g_dbus_proxy_get_path(default_session));
1838
if (proxy == NULL) {
1839
rl_printf("Command not supported\n");
1843
args = cp_new(argv);
1845
if (g_dbus_proxy_method_call(proxy, "MoveFile", cp_setup,
1846
move_file_reply, args, cp_free) == FALSE) {
1847
rl_printf("Failed to MoveFile\n");
1851
rl_printf("Attempting to MoveFile\n");
1854
static void delete_reply(DBusMessage *message, void *user_data)
1858
dbus_error_init(&error);
1860
if (dbus_set_error_from_message(&error, message) == TRUE) {
1861
rl_printf("Failed to Delete: %s\n", error.name);
1862
dbus_error_free(&error);
1866
rl_printf("Delete successful\n");
1869
static void delete_setup(DBusMessageIter *iter, void *user_data)
1871
const char *file = user_data;
1873
dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &file);
1876
static void ftp_rm(GDBusProxy *proxy, int argc, char *argv[])
1879
rl_printf("Missing file argument\n");
1883
if (g_dbus_proxy_method_call(proxy, "Delete", delete_setup,
1884
delete_reply, g_strdup(argv[1]),
1886
rl_printf("Failed to Delete\n");
1890
rl_printf("Attempting to Delete\n");
1893
static void set_delete_reply(const DBusError *error, void *user_data)
1895
if (dbus_error_is_set(error))
1896
rl_printf("Failed to set Deleted: %s\n", error->name);
1898
rl_printf("Set Deleted successful\n");
1901
static void map_rm(GDBusProxy *proxy, int argc, char *argv[])
1904
dbus_bool_t value = TRUE;
1907
rl_printf("Missing message argument\n");
1911
msg = find_message(argv[1]);
1913
rl_printf("Invalid message argument\n");
1917
if (g_dbus_proxy_set_property_basic(msg, "Deleted", DBUS_TYPE_BOOLEAN,
1918
&value, set_delete_reply,
1919
NULL, NULL) == FALSE) {
1920
rl_printf("Failed to set Deleted\n");
1924
rl_printf("Attempting to set Deleted\n");
1927
static void cmd_rm(int argc, char *argv[])
1931
if (!check_default_session())
1934
proxy = find_ftp(g_dbus_proxy_get_path(default_session));
1936
ftp_rm(proxy, argc, argv);
1940
proxy = find_map(g_dbus_proxy_get_path(default_session));
1942
map_rm(proxy, argc, argv);
1946
rl_printf("Command not supported\n");
1949
static void create_folder_reply(DBusMessage *message, void *user_data)
1953
dbus_error_init(&error);
1955
if (dbus_set_error_from_message(&error, message) == TRUE) {
1956
rl_printf("Failed to CreateFolder: %s\n", error.name);
1957
dbus_error_free(&error);
1961
rl_printf("CreateFolder successful\n");
1964
static void create_folder_setup(DBusMessageIter *iter, void *user_data)
1966
const char *folder = user_data;
1968
dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &folder);
1971
static void cmd_mkdir(int argc, char *argv[])
1975
if (!check_default_session())
1979
rl_printf("Missing folder argument\n");
1983
proxy = find_ftp(g_dbus_proxy_get_path(default_session));
1984
if (proxy == NULL) {
1985
rl_printf("Command not supported\n");
1989
if (g_dbus_proxy_method_call(proxy, "CreateFolder", create_folder_setup,
1990
create_folder_reply, g_strdup(argv[1]),
1992
rl_printf("Failed to CreateFolder\n");
1996
rl_printf("Attempting to CreateFolder\n");
1999
static const struct {
2002
void (*func) (int argc, char *argv[]);
2005
{ "connect", "<dev> [uuid]", cmd_connect, "Connect session" },
2006
{ "disconnect", "[session]", cmd_disconnect, "Disconnect session" },
2007
{ "list", NULL, cmd_list, "List available sessions" },
2008
{ "show", "[session]", cmd_show, "Session information" },
2009
{ "select", "<session>", cmd_select, "Select default session" },
2010
{ "info", "<object>", cmd_info, "Object information" },
2011
{ "cancel", "<transfer>", cmd_cancel, "Cancel transfer" },
2012
{ "suspend", "<transfer>", cmd_suspend, "Suspend transfer" },
2013
{ "resume", "<transfer>", cmd_resume, "Resume transfer" },
2014
{ "send", "<file>", cmd_send, "Send file" },
2015
{ "pull", "<file>", cmd_pull,
2016
"Pull Vobject & stores in file" },
2017
{ "cd", "<path>", cmd_cd, "Change current folder" },
2018
{ "ls", "<options>", cmd_ls, "List current folder" },
2019
{ "cp", "<source file> <destination file>", cmd_cp,
2020
"Copy source file to destination file" },
2021
{ "mv", "<source file> <destination file>", cmd_mv,
2022
"Move source file to destination file" },
2023
{ "rm", "<file>", cmd_rm, "Delete file" },
2024
{ "mkdir", "<folder>", cmd_mkdir, "Create folder" },
2025
{ "quit", NULL, cmd_quit, "Quit program" },
2026
{ "exit", NULL, cmd_quit },
2031
static char *cmd_generator(const char *text, int state)
2033
static int index, len;
2041
while ((cmd = cmd_table[index].cmd)) {
2044
if (!strncmp(cmd, text, len))
2051
static char **cmd_completion(const char *text, int start, int end)
2053
char **matches = NULL;
2056
rl_completion_display_matches_hook = NULL;
2057
matches = rl_completion_matches(text, cmd_generator);
2061
rl_attempted_completion_over = 1;
2066
static void rl_handler(char *input)
2074
rl_insert_text("quit");
2077
g_main_loop_quit(main_loop);
2086
if (wordexp(input, &w, WRDE_NOCMD))
2089
if (w.we_wordc == 0)
2095
for (i = 0; cmd_table[i].cmd; i++) {
2096
if (strcmp(argv[0], cmd_table[i].cmd))
2099
if (cmd_table[i].func) {
2100
cmd_table[i].func(argc, argv);
2105
if (strcmp(argv[0], "help")) {
2106
printf("Invalid command\n");
2110
printf("Available commands:\n");
2112
for (i = 0; cmd_table[i].cmd; i++) {
2113
if (cmd_table[i].desc)
2114
printf(" %s %-*s %s\n", cmd_table[i].cmd,
2115
(int)(25 - strlen(cmd_table[i].cmd)),
2116
cmd_table[i].arg ? : "",
2117
cmd_table[i].desc ? : "");
2126
static gboolean option_version = FALSE;
2128
static GOptionEntry options[] = {
2129
{ "version", 'v', 0, G_OPTION_ARG_NONE, &option_version,
2130
"Show version information and exit" },
2134
static gboolean signal_handler(GIOChannel *channel, GIOCondition condition,
2137
static unsigned int __terminated = 0;
2138
struct signalfd_siginfo si;
2142
if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
2143
g_main_loop_quit(main_loop);
2147
fd = g_io_channel_unix_get_fd(channel);
2149
result = read(fd, &si, sizeof(si));
2150
if (result != sizeof(si))
2153
switch (si.ssi_signo) {
2155
rl_replace_line("", 0);
2161
if (__terminated == 0) {
2162
rl_replace_line("", 0);
2164
g_main_loop_quit(main_loop);
2174
static guint setup_signalfd(void)
2176
GIOChannel *channel;
2182
sigaddset(&mask, SIGINT);
2183
sigaddset(&mask, SIGTERM);
2185
if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) {
2186
perror("Failed to set signal mask");
2190
fd = signalfd(-1, &mask, 0);
2192
perror("Failed to create signal descriptor");
2196
channel = g_io_channel_unix_new(fd);
2198
g_io_channel_set_close_on_unref(channel, TRUE);
2199
g_io_channel_set_encoding(channel, NULL, NULL);
2200
g_io_channel_set_buffered(channel, FALSE);
2202
source = g_io_add_watch(channel,
2203
G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
2204
signal_handler, NULL);
2206
g_io_channel_unref(channel);
2211
static gboolean input_handler(GIOChannel *channel, GIOCondition condition,
2214
if (condition & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
2215
g_main_loop_quit(main_loop);
2219
rl_callback_read_char();
2223
static guint setup_standard_input(void)
2225
GIOChannel *channel;
2228
channel = g_io_channel_unix_new(fileno(stdin));
2230
source = g_io_add_watch(channel,
2231
G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
2232
input_handler, NULL);
2234
g_io_channel_unref(channel);
2239
static void client_added(GDBusProxy *proxy)
2244
print_proxy(proxy, "Client", COLORED_NEW);
2247
static void session_added(GDBusProxy *proxy)
2249
sessions = g_slist_append(sessions, proxy);
2251
if (default_session == NULL)
2252
set_default_session(proxy);
2254
print_proxy(proxy, "Session", COLORED_NEW);
2257
static void print_transferred(struct transfer_data *data, const char *str,
2258
DBusMessageIter *iter)
2260
dbus_uint64_t valu64;
2262
int seconds, minutes;
2264
dbus_message_iter_get_basic(iter, &valu64);
2265
speed = valu64 - data->transferred;
2266
data->transferred = valu64;
2268
if (data->size == 0) {
2269
rl_printf("%sTransferred: %" PRIu64 " (@%" PRIu64 "KB/s)\n",
2270
str, valu64, speed / 1000);
2274
seconds = (data->size - data->transferred) / speed;
2275
minutes = seconds / 60;
2277
rl_printf("%sTransferred: %" PRIu64 " (@%" PRIu64 "KB/s %02u:%02u)\n",
2278
str, valu64, speed / 1000, minutes, seconds);
2281
static void transfer_property_changed(GDBusProxy *proxy, const char *name,
2282
DBusMessageIter *iter, void *user_data)
2284
struct transfer_data *data = user_data;
2287
str = proxy_description(proxy, "Transfer", COLORED_CHG);
2289
if (strcmp(name, "Transferred") == 0) {
2290
print_transferred(data, str, iter);
2294
if (strcmp(name, "Size") == 0)
2295
dbus_message_iter_get_basic(iter, &data->size);
2297
print_iter(str, name, iter);
2303
static void transfer_destroy(GDBusProxy *proxy, void *user_data)
2305
struct transfer_data *data = user_data;
2310
static void transfer_added(GDBusProxy *proxy)
2312
struct transfer_data *data;
2313
DBusMessageIter iter;
2315
transfers = g_slist_append(transfers, proxy);
2317
print_proxy(proxy, "Transfer", COLORED_NEW);
2319
data = g_new0(struct transfer_data, 1);
2321
if (g_dbus_proxy_get_property(proxy, "Transfered", &iter))
2322
dbus_message_iter_get_basic(&iter, &data->transferred);
2324
if (g_dbus_proxy_get_property(proxy, "Size", &iter))
2325
dbus_message_iter_get_basic(&iter, &data->size);
2327
g_dbus_proxy_set_property_watch(proxy, transfer_property_changed, data);
2328
g_dbus_proxy_set_removed_watch(proxy, transfer_destroy, data);
2331
static void opp_added(GDBusProxy *proxy)
2333
opps = g_slist_append(opps, proxy);
2335
print_proxy(proxy, "ObjectPush", COLORED_NEW);
2338
static void ftp_added(GDBusProxy *proxy)
2340
ftps = g_slist_append(ftps, proxy);
2342
print_proxy(proxy, "FileTransfer", COLORED_NEW);
2345
static void pbap_added(GDBusProxy *proxy)
2347
pbaps = g_slist_append(pbaps, proxy);
2349
print_proxy(proxy, "PhonebookAccess", COLORED_NEW);
2352
static void map_added(GDBusProxy *proxy)
2354
maps = g_slist_append(maps, proxy);
2356
print_proxy(proxy, "MessageAccess", COLORED_NEW);
2359
static void msg_added(GDBusProxy *proxy)
2361
msgs = g_slist_append(msgs, proxy);
2363
print_proxy(proxy, "Message", COLORED_NEW);
2366
static void proxy_added(GDBusProxy *proxy, void *user_data)
2368
const char *interface;
2370
interface = g_dbus_proxy_get_interface(proxy);
2372
if (!strcmp(interface, OBEX_CLIENT_INTERFACE))
2373
client_added(proxy);
2374
else if (!strcmp(interface, OBEX_SESSION_INTERFACE))
2375
session_added(proxy);
2376
else if (!strcmp(interface, OBEX_TRANSFER_INTERFACE))
2377
transfer_added(proxy);
2378
else if (!strcmp(interface, OBEX_OPP_INTERFACE))
2380
else if (!strcmp(interface, OBEX_FTP_INTERFACE))
2382
else if (!strcmp(interface, OBEX_PBAP_INTERFACE))
2384
else if (!strcmp(interface, OBEX_MAP_INTERFACE))
2386
else if (!strcmp(interface, OBEX_MSG_INTERFACE))
2390
static void client_removed(GDBusProxy *proxy)
2392
print_proxy(proxy, "Client", COLORED_DEL);
2394
if (client == proxy)
2398
static void session_removed(GDBusProxy *proxy)
2400
print_proxy(proxy, "Session", COLORED_DEL);
2402
if (default_session == proxy)
2403
set_default_session(NULL);
2405
sessions = g_slist_remove(sessions, proxy);
2408
static void transfer_removed(GDBusProxy *proxy)
2410
print_proxy(proxy, "Transfer", COLORED_DEL);
2412
transfers = g_slist_remove(transfers, proxy);
2415
static void opp_removed(GDBusProxy *proxy)
2417
print_proxy(proxy, "ObjectPush", COLORED_DEL);
2419
opps = g_slist_remove(opps, proxy);
2422
static void ftp_removed(GDBusProxy *proxy)
2424
print_proxy(proxy, "FileTransfer", COLORED_DEL);
2426
ftps = g_slist_remove(ftps, proxy);
2429
static void pbap_removed(GDBusProxy *proxy)
2431
print_proxy(proxy, "PhonebookAccess", COLORED_DEL);
2433
pbaps = g_slist_remove(pbaps, proxy);
2436
static void map_removed(GDBusProxy *proxy)
2438
print_proxy(proxy, "MessageAccess", COLORED_DEL);
2440
maps = g_slist_remove(maps, proxy);
2443
static void msg_removed(GDBusProxy *proxy)
2445
print_proxy(proxy, "Message", COLORED_DEL);
2447
msgs = g_slist_remove(msgs, proxy);
2450
static void proxy_removed(GDBusProxy *proxy, void *user_data)
2452
const char *interface;
2454
interface = g_dbus_proxy_get_interface(proxy);
2456
if (!strcmp(interface, OBEX_CLIENT_INTERFACE))
2457
client_removed(proxy);
2458
else if (!strcmp(interface, OBEX_SESSION_INTERFACE))
2459
session_removed(proxy);
2460
else if (!strcmp(interface, OBEX_TRANSFER_INTERFACE))
2461
transfer_removed(proxy);
2462
else if (!strcmp(interface, OBEX_OPP_INTERFACE))
2464
else if (!strcmp(interface, OBEX_FTP_INTERFACE))
2466
else if (!strcmp(interface, OBEX_PBAP_INTERFACE))
2467
pbap_removed(proxy);
2468
else if (!strcmp(interface, OBEX_MAP_INTERFACE))
2470
else if (!strcmp(interface, OBEX_MSG_INTERFACE))
2474
static void session_property_changed(GDBusProxy *proxy, const char *name,
2475
DBusMessageIter *iter)
2479
str = proxy_description(proxy, "Session", COLORED_CHG);
2480
print_iter(str, name, iter);
2484
static void property_changed(GDBusProxy *proxy, const char *name,
2485
DBusMessageIter *iter, void *user_data)
2487
const char *interface;
2489
interface = g_dbus_proxy_get_interface(proxy);
2491
if (!strcmp(interface, OBEX_SESSION_INTERFACE))
2492
session_property_changed(proxy, name, iter);
2495
int main(int argc, char *argv[])
2497
GOptionContext *context;
2498
GError *error = NULL;
2499
GDBusClient *client;
2500
guint signal, input;
2502
context = g_option_context_new(NULL);
2503
g_option_context_add_main_entries(context, options, NULL);
2505
if (g_option_context_parse(context, &argc, &argv, &error) == FALSE) {
2506
if (error != NULL) {
2507
g_printerr("%s\n", error->message);
2508
g_error_free(error);
2510
g_printerr("An unknown error occurred\n");
2514
g_option_context_free(context);
2516
if (option_version == TRUE) {
2517
printf("%s\n", VERSION);
2521
main_loop = g_main_loop_new(NULL, FALSE);
2522
dbus_conn = g_dbus_setup_bus(DBUS_BUS_SESSION, NULL, NULL);
2524
rl_attempted_completion_function = cmd_completion;
2526
rl_erase_empty_line = 1;
2527
rl_callback_handler_install(NULL, rl_handler);
2529
rl_set_prompt(PROMPT_OFF);
2532
input = setup_standard_input();
2533
signal = setup_signalfd();
2534
client = g_dbus_client_new(dbus_conn, "org.bluez.obex",
2537
g_dbus_client_set_connect_watch(client, connect_handler, NULL);
2538
g_dbus_client_set_disconnect_watch(client, disconnect_handler, NULL);
2540
g_dbus_client_set_proxy_handlers(client, proxy_added, proxy_removed,
2541
property_changed, NULL);
2543
g_main_loop_run(main_loop);
2545
g_dbus_client_unref(client);
2546
g_source_remove(signal);
2547
g_source_remove(input);
2550
rl_callback_handler_remove();
2552
dbus_connection_unref(dbus_conn);
2553
g_main_loop_unref(main_loop);