obexctl.c 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2013 Intel Corporation. All rights reserved.
  7. *
  8. *
  9. */
  10. #ifdef HAVE_CONFIG_H
  11. #include <config.h>
  12. #endif
  13. #define _GNU_SOURCE
  14. #include <stdio.h>
  15. #include <stdbool.h>
  16. #include <errno.h>
  17. #include <unistd.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <inttypes.h>
  21. #include <wordexp.h>
  22. #include <ctype.h>
  23. #include <glib.h>
  24. #include "gdbus/gdbus.h"
  25. #include "src/shared/shell.h"
  26. /* String display constants */
  27. #define COLORED_NEW COLOR_GREEN "NEW" COLOR_OFF
  28. #define COLORED_CHG COLOR_YELLOW "CHG" COLOR_OFF
  29. #define COLORED_DEL COLOR_RED "DEL" COLOR_OFF
  30. #define PROMPT_ON COLOR_BLUE "[obex]" COLOR_OFF "# "
  31. #define PROMPT_OFF "[obex]# "
  32. #define OBEX_SESSION_INTERFACE "org.bluez.obex.Session1"
  33. #define OBEX_TRANSFER_INTERFACE "org.bluez.obex.Transfer1"
  34. #define OBEX_CLIENT_INTERFACE "org.bluez.obex.Client1"
  35. #define OBEX_OPP_INTERFACE "org.bluez.obex.ObjectPush1"
  36. #define OBEX_FTP_INTERFACE "org.bluez.obex.FileTransfer1"
  37. #define OBEX_PBAP_INTERFACE "org.bluez.obex.PhonebookAccess1"
  38. #define OBEX_MAP_INTERFACE "org.bluez.obex.MessageAccess1"
  39. #define OBEX_MSG_INTERFACE "org.bluez.obex.Message1"
  40. static DBusConnection *dbus_conn;
  41. static GDBusProxy *default_session;
  42. static GList *sessions = NULL;
  43. static GList *opps = NULL;
  44. static GList *ftps = NULL;
  45. static GList *pbaps = NULL;
  46. static GList *maps = NULL;
  47. static GList *msgs = NULL;
  48. static GList *transfers = NULL;
  49. static GDBusProxy *client = NULL;
  50. struct transfer_data {
  51. uint64_t transferred;
  52. uint64_t size;
  53. };
  54. static void connect_handler(DBusConnection *connection, void *user_data)
  55. {
  56. bt_shell_attach(fileno(stdin));
  57. bt_shell_set_prompt(PROMPT_ON);
  58. }
  59. static void disconnect_handler(DBusConnection *connection, void *user_data)
  60. {
  61. bt_shell_detach();
  62. bt_shell_set_prompt(PROMPT_OFF);
  63. }
  64. static char *generic_generator(const char *text, int state, GList *source)
  65. {
  66. static int index = 0;
  67. if (!state) {
  68. index = 0;
  69. }
  70. return g_dbus_proxy_path_lookup(source, &index, text);
  71. }
  72. static char *session_generator(const char *text, int state)
  73. {
  74. return generic_generator(text, state, sessions);
  75. }
  76. static char *transfer_generator(const char *text, int state)
  77. {
  78. return generic_generator(text, state, transfers);
  79. }
  80. static void connect_reply(DBusMessage *message, void *user_data)
  81. {
  82. DBusError error;
  83. dbus_error_init(&error);
  84. if (dbus_set_error_from_message(&error, message) == TRUE) {
  85. bt_shell_printf("Failed to connect: %s\n", error.name);
  86. dbus_error_free(&error);
  87. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  88. }
  89. bt_shell_printf("Connection successful\n");
  90. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  91. }
  92. struct connect_args {
  93. char *dev;
  94. char *target;
  95. };
  96. static void connect_args_free(void *data)
  97. {
  98. struct connect_args *args = data;
  99. g_free(args->dev);
  100. g_free(args->target);
  101. g_free(args);
  102. }
  103. static void connect_setup(DBusMessageIter *iter, void *user_data)
  104. {
  105. struct connect_args *args = user_data;
  106. DBusMessageIter dict;
  107. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &args->dev);
  108. dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
  109. DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
  110. DBUS_TYPE_STRING_AS_STRING
  111. DBUS_TYPE_VARIANT_AS_STRING
  112. DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
  113. &dict);
  114. if (args->target == NULL)
  115. goto done;
  116. g_dbus_dict_append_entry(&dict, "Target",
  117. DBUS_TYPE_STRING, &args->target);
  118. done:
  119. dbus_message_iter_close_container(iter, &dict);
  120. }
  121. static void cmd_connect(int argc, char *argv[])
  122. {
  123. struct connect_args *args;
  124. const char *target = "opp";
  125. if (!client) {
  126. bt_shell_printf("Client proxy not available\n");
  127. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  128. }
  129. if (argc > 2)
  130. target = argv[2];
  131. args = g_new0(struct connect_args, 1);
  132. args->dev = g_strdup(argv[1]);
  133. args->target = g_strdup(target);
  134. if (g_dbus_proxy_method_call(client, "CreateSession", connect_setup,
  135. connect_reply, args, connect_args_free) == FALSE) {
  136. bt_shell_printf("Failed to connect\n");
  137. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  138. }
  139. bt_shell_printf("Attempting to connect to %s\n", argv[1]);
  140. }
  141. static void disconnect_reply(DBusMessage *message, void *user_data)
  142. {
  143. DBusError error;
  144. dbus_error_init(&error);
  145. if (dbus_set_error_from_message(&error, message) == TRUE) {
  146. bt_shell_printf("Failed to disconnect: %s\n", error.name);
  147. dbus_error_free(&error);
  148. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  149. }
  150. bt_shell_printf("Disconnection successful\n");
  151. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  152. }
  153. static void disconnect_setup(DBusMessageIter *iter, void *user_data)
  154. {
  155. GDBusProxy *proxy = user_data;
  156. const char *path;
  157. path = g_dbus_proxy_get_path(proxy);
  158. dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
  159. }
  160. static void cmd_disconnect(int argc, char *argv[])
  161. {
  162. GDBusProxy *proxy;
  163. if (argc > 1)
  164. proxy = g_dbus_proxy_lookup(sessions, NULL, argv[1],
  165. OBEX_SESSION_INTERFACE);
  166. else
  167. proxy = default_session;
  168. if (proxy == NULL) {
  169. bt_shell_printf("Session not available\n");
  170. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  171. }
  172. if (g_dbus_proxy_method_call(client, "RemoveSession", disconnect_setup,
  173. disconnect_reply, proxy, NULL) == FALSE) {
  174. bt_shell_printf("Failed to disconnect\n");
  175. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  176. }
  177. bt_shell_printf("Attempting to disconnect to %s\n",
  178. g_dbus_proxy_get_path(proxy));
  179. }
  180. static char *proxy_description(GDBusProxy *proxy, const char *title,
  181. const char *description)
  182. {
  183. const char *path;
  184. path = g_dbus_proxy_get_path(proxy);
  185. return g_strdup_printf("%s%s%s%s %s ",
  186. description ? "[" : "",
  187. description ? : "",
  188. description ? "] " : "",
  189. title, path);
  190. }
  191. static void print_proxy(GDBusProxy *proxy, const char *title,
  192. const char *description)
  193. {
  194. char *str;
  195. str = proxy_description(proxy, title, description);
  196. bt_shell_printf("%s%s\n", str,
  197. default_session == proxy ? "[default]" : "");
  198. g_free(str);
  199. }
  200. static void cmd_list(int argc, char *arg[])
  201. {
  202. GList *l;
  203. for (l = sessions; l; l = g_list_next(l)) {
  204. GDBusProxy *proxy = l->data;
  205. print_proxy(proxy, "Session", NULL);
  206. }
  207. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  208. }
  209. static bool check_default_session(void)
  210. {
  211. if (!default_session) {
  212. bt_shell_printf("No default session available\n");
  213. return FALSE;
  214. }
  215. return TRUE;
  216. }
  217. static void print_iter(const char *label, const char *name,
  218. DBusMessageIter *iter)
  219. {
  220. dbus_bool_t valbool;
  221. dbus_uint64_t valu64;
  222. dbus_uint32_t valu32;
  223. dbus_uint16_t valu16;
  224. dbus_int16_t vals16;
  225. const char *valstr;
  226. DBusMessageIter subiter;
  227. if (iter == NULL) {
  228. bt_shell_printf("%s%s is nil\n", label, name);
  229. return;
  230. }
  231. switch (dbus_message_iter_get_arg_type(iter)) {
  232. case DBUS_TYPE_INVALID:
  233. bt_shell_printf("%s%s is invalid\n", label, name);
  234. break;
  235. case DBUS_TYPE_STRING:
  236. case DBUS_TYPE_OBJECT_PATH:
  237. dbus_message_iter_get_basic(iter, &valstr);
  238. bt_shell_printf("%s%s: %s\n", label, name, valstr);
  239. break;
  240. case DBUS_TYPE_BOOLEAN:
  241. dbus_message_iter_get_basic(iter, &valbool);
  242. bt_shell_printf("%s%s: %s\n", label, name,
  243. valbool == TRUE ? "yes" : "no");
  244. break;
  245. case DBUS_TYPE_UINT64:
  246. dbus_message_iter_get_basic(iter, &valu64);
  247. bt_shell_printf("%s%s: %" PRIu64 "\n", label, name, valu64);
  248. break;
  249. case DBUS_TYPE_UINT32:
  250. dbus_message_iter_get_basic(iter, &valu32);
  251. bt_shell_printf("%s%s: 0x%08x\n", label, name, valu32);
  252. break;
  253. case DBUS_TYPE_UINT16:
  254. dbus_message_iter_get_basic(iter, &valu16);
  255. bt_shell_printf("%s%s: 0x%04x\n", label, name, valu16);
  256. break;
  257. case DBUS_TYPE_INT16:
  258. dbus_message_iter_get_basic(iter, &vals16);
  259. bt_shell_printf("%s%s: %d\n", label, name, vals16);
  260. break;
  261. case DBUS_TYPE_VARIANT:
  262. dbus_message_iter_recurse(iter, &subiter);
  263. print_iter(label, name, &subiter);
  264. break;
  265. case DBUS_TYPE_ARRAY:
  266. dbus_message_iter_recurse(iter, &subiter);
  267. while (dbus_message_iter_get_arg_type(&subiter) !=
  268. DBUS_TYPE_INVALID) {
  269. print_iter(label, name, &subiter);
  270. dbus_message_iter_next(&subiter);
  271. }
  272. break;
  273. case DBUS_TYPE_DICT_ENTRY:
  274. dbus_message_iter_recurse(iter, &subiter);
  275. dbus_message_iter_get_basic(&subiter, &valstr);
  276. dbus_message_iter_next(&subiter);
  277. print_iter(label, valstr, &subiter);
  278. break;
  279. default:
  280. bt_shell_printf("%s%s has unsupported type\n", label, name);
  281. break;
  282. }
  283. }
  284. static void print_property(GDBusProxy *proxy, const char *name)
  285. {
  286. DBusMessageIter iter;
  287. if (g_dbus_proxy_get_property(proxy, name, &iter) == FALSE)
  288. return;
  289. print_iter("\t", name, &iter);
  290. }
  291. static void cmd_show(int argc, char *argv[])
  292. {
  293. GDBusProxy *proxy;
  294. if (argc < 2) {
  295. if (check_default_session() == FALSE)
  296. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  297. proxy = default_session;
  298. } else {
  299. proxy = g_dbus_proxy_lookup(sessions, NULL, argv[1],
  300. OBEX_SESSION_INTERFACE);
  301. if (!proxy) {
  302. bt_shell_printf("Session %s not available\n", argv[1]);
  303. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  304. }
  305. }
  306. bt_shell_printf("Session %s\n", g_dbus_proxy_get_path(proxy));
  307. print_property(proxy, "Destination");
  308. print_property(proxy, "Target");
  309. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  310. }
  311. static void set_default_session(GDBusProxy *proxy)
  312. {
  313. char *desc;
  314. DBusMessageIter iter;
  315. default_session = proxy;
  316. if (!g_dbus_proxy_get_property(proxy, "Destination", &iter)) {
  317. desc = g_strdup(PROMPT_ON);
  318. goto done;
  319. }
  320. dbus_message_iter_get_basic(&iter, &desc);
  321. desc = g_strdup_printf(COLOR_BLUE "[%s]" COLOR_OFF "# ", desc);
  322. done:
  323. bt_shell_set_prompt(desc);
  324. g_free(desc);
  325. }
  326. static void cmd_select(int argc, char *argv[])
  327. {
  328. GDBusProxy *proxy;
  329. proxy = g_dbus_proxy_lookup(sessions, NULL, argv[1],
  330. OBEX_SESSION_INTERFACE);
  331. if (proxy == NULL) {
  332. bt_shell_printf("Session %s not available\n", argv[1]);
  333. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  334. }
  335. if (default_session == proxy)
  336. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  337. set_default_session(proxy);
  338. print_proxy(proxy, "Session", NULL);
  339. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  340. }
  341. static void transfer_info(GDBusProxy *proxy, int argc, char *argv[])
  342. {
  343. bt_shell_printf("Transfer %s\n", g_dbus_proxy_get_path(proxy));
  344. print_property(proxy, "Session");
  345. print_property(proxy, "Name");
  346. print_property(proxy, "Type");
  347. print_property(proxy, "Status");
  348. print_property(proxy, "Time");
  349. print_property(proxy, "Size");
  350. print_property(proxy, "Transferred");
  351. print_property(proxy, "Filename");
  352. }
  353. static void message_info(GDBusProxy *proxy, int argc, char *argv[])
  354. {
  355. bt_shell_printf("Message %s\n", g_dbus_proxy_get_path(proxy));
  356. print_property(proxy, "Folder");
  357. print_property(proxy, "Subject");
  358. print_property(proxy, "Timestamp");
  359. print_property(proxy, "Sender");
  360. print_property(proxy, "SenderAddress");
  361. print_property(proxy, "ReplyTo");
  362. print_property(proxy, "Recipient");
  363. print_property(proxy, "RecipientAddress");
  364. print_property(proxy, "Type");
  365. print_property(proxy, "Size");
  366. print_property(proxy, "Status");
  367. print_property(proxy, "Priority");
  368. print_property(proxy, "Read");
  369. print_property(proxy, "Deleted");
  370. print_property(proxy, "Sent");
  371. print_property(proxy, "Protected");
  372. }
  373. static void cmd_info(int argc, char *argv[])
  374. {
  375. GDBusProxy *proxy;
  376. proxy = g_dbus_proxy_lookup(transfers, NULL, argv[1],
  377. OBEX_TRANSFER_INTERFACE);
  378. if (proxy) {
  379. transfer_info(proxy, argc, argv);
  380. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  381. }
  382. proxy = g_dbus_proxy_lookup(msgs, NULL, argv[1], OBEX_MSG_INTERFACE);
  383. if (proxy) {
  384. message_info(proxy, argc, argv);
  385. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  386. }
  387. bt_shell_printf("Object %s not available\n", argv[1]);
  388. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  389. }
  390. static void cancel_reply(DBusMessage *message, void *user_data)
  391. {
  392. DBusError error;
  393. dbus_error_init(&error);
  394. if (dbus_set_error_from_message(&error, message) == TRUE) {
  395. bt_shell_printf("Failed to cancel: %s\n", error.name);
  396. dbus_error_free(&error);
  397. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  398. }
  399. bt_shell_printf("Cancel successful\n");
  400. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  401. }
  402. static void cmd_cancel(int argc, char *argv[])
  403. {
  404. GDBusProxy *proxy;
  405. proxy = g_dbus_proxy_lookup(transfers, NULL, argv[1],
  406. OBEX_TRANSFER_INTERFACE);
  407. if (!proxy) {
  408. bt_shell_printf("Transfer %s not available\n", argv[1]);
  409. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  410. }
  411. if (g_dbus_proxy_method_call(proxy, "Cancel", NULL, cancel_reply, NULL,
  412. NULL) == FALSE) {
  413. bt_shell_printf("Failed to cancel transfer\n");
  414. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  415. }
  416. bt_shell_printf("Attempting to cancel transfer %s\n",
  417. g_dbus_proxy_get_path(proxy));
  418. }
  419. static void suspend_reply(DBusMessage *message, void *user_data)
  420. {
  421. DBusError error;
  422. dbus_error_init(&error);
  423. if (dbus_set_error_from_message(&error, message) == TRUE) {
  424. bt_shell_printf("Failed to suspend: %s\n", error.name);
  425. dbus_error_free(&error);
  426. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  427. }
  428. bt_shell_printf("Suspend successful\n");
  429. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  430. }
  431. static void cmd_suspend(int argc, char *argv[])
  432. {
  433. GDBusProxy *proxy;
  434. proxy = g_dbus_proxy_lookup(transfers, NULL, argv[1],
  435. OBEX_TRANSFER_INTERFACE);
  436. if (!proxy) {
  437. bt_shell_printf("Transfer %s not available\n", argv[1]);
  438. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  439. }
  440. if (g_dbus_proxy_method_call(proxy, "Suspend", NULL, suspend_reply,
  441. NULL, NULL) == FALSE) {
  442. bt_shell_printf("Failed to suspend transfer\n");
  443. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  444. }
  445. bt_shell_printf("Attempting to suspend transfer %s\n",
  446. g_dbus_proxy_get_path(proxy));
  447. }
  448. static void resume_reply(DBusMessage *message, void *user_data)
  449. {
  450. DBusError error;
  451. dbus_error_init(&error);
  452. if (dbus_set_error_from_message(&error, message) == TRUE) {
  453. bt_shell_printf("Failed to resume: %s\n", error.name);
  454. dbus_error_free(&error);
  455. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  456. }
  457. bt_shell_printf("Resume successful\n");
  458. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  459. }
  460. static void cmd_resume(int argc, char *argv[])
  461. {
  462. GDBusProxy *proxy;
  463. proxy = g_dbus_proxy_lookup(transfers, NULL, argv[1],
  464. OBEX_TRANSFER_INTERFACE);
  465. if (!proxy) {
  466. bt_shell_printf("Transfer %s not available\n", argv[1]);
  467. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  468. }
  469. if (g_dbus_proxy_method_call(proxy, "Resume", NULL, resume_reply,
  470. NULL, NULL) == FALSE) {
  471. bt_shell_printf("Failed to resume transfer\n");
  472. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  473. }
  474. bt_shell_printf("Attempting to resume transfer %s\n",
  475. g_dbus_proxy_get_path(proxy));
  476. }
  477. static void print_dict_iter(DBusMessageIter *iter)
  478. {
  479. DBusMessageIter dict;
  480. int ctype;
  481. ctype = dbus_message_iter_get_arg_type(iter);
  482. if (ctype != DBUS_TYPE_ARRAY)
  483. return;
  484. dbus_message_iter_recurse(iter, &dict);
  485. while ((ctype = dbus_message_iter_get_arg_type(&dict)) !=
  486. DBUS_TYPE_INVALID) {
  487. DBusMessageIter entry;
  488. const char *key;
  489. if (ctype != DBUS_TYPE_DICT_ENTRY)
  490. return;
  491. dbus_message_iter_recurse(&dict, &entry);
  492. if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
  493. return;
  494. dbus_message_iter_get_basic(&entry, &key);
  495. dbus_message_iter_next(&entry);
  496. print_iter("\t", key, &entry);
  497. dbus_message_iter_next(&dict);
  498. }
  499. }
  500. static void print_transfer_iter(DBusMessageIter *iter)
  501. {
  502. const char *path;
  503. dbus_message_iter_get_basic(iter, &path);
  504. bt_shell_printf("Transfer %s\n", path);
  505. dbus_message_iter_next(iter);
  506. print_dict_iter(iter);
  507. }
  508. static void send_reply(DBusMessage *message, void *user_data)
  509. {
  510. DBusMessageIter iter;
  511. DBusError error;
  512. dbus_error_init(&error);
  513. if (dbus_set_error_from_message(&error, message) == TRUE) {
  514. bt_shell_printf("Failed to send/pull: %s\n", error.name);
  515. dbus_error_free(&error);
  516. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  517. }
  518. dbus_message_iter_init(message, &iter);
  519. print_transfer_iter(&iter);
  520. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  521. }
  522. static void send_setup(DBusMessageIter *iter, void *user_data)
  523. {
  524. const char *file = user_data;
  525. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &file);
  526. }
  527. static void opp_send(GDBusProxy *proxy, int argc, char *argv[])
  528. {
  529. if (g_dbus_proxy_method_call(proxy, "SendFile", send_setup, send_reply,
  530. g_strdup(argv[1]), g_free) == FALSE) {
  531. bt_shell_printf("Failed to send\n");
  532. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  533. }
  534. bt_shell_printf("Attempting to send %s to %s\n", argv[1],
  535. g_dbus_proxy_get_path(proxy));
  536. }
  537. static void opp_pull(GDBusProxy *proxy, int argc, char *argv[])
  538. {
  539. if (g_dbus_proxy_method_call(proxy, "PullBusinessCard", send_setup,
  540. send_reply, g_strdup(argv[1]), g_free) == FALSE) {
  541. bt_shell_printf("Failed to pull\n");
  542. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  543. }
  544. bt_shell_printf("Attempting to pull %s from %s\n", argv[1],
  545. g_dbus_proxy_get_path(proxy));
  546. }
  547. static void push_reply(DBusMessage *message, void *user_data)
  548. {
  549. DBusMessageIter iter;
  550. DBusError error;
  551. dbus_error_init(&error);
  552. if (dbus_set_error_from_message(&error, message) == TRUE) {
  553. bt_shell_printf("Failed to PushMessage: %s\n", error.name);
  554. dbus_error_free(&error);
  555. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  556. }
  557. dbus_message_iter_init(message, &iter);
  558. print_transfer_iter(&iter);
  559. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  560. }
  561. static void push_setup(DBusMessageIter *iter, void *user_data)
  562. {
  563. const char *file = user_data;
  564. const char *folder = "";
  565. DBusMessageIter dict;
  566. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &file);
  567. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &folder);
  568. dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
  569. DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
  570. DBUS_TYPE_STRING_AS_STRING
  571. DBUS_TYPE_VARIANT_AS_STRING
  572. DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
  573. &dict);
  574. dbus_message_iter_close_container(iter, &dict);
  575. }
  576. static void map_send(GDBusProxy *proxy, int argc, char *argv[])
  577. {
  578. if (g_dbus_proxy_method_call(proxy, "PushMessage", push_setup,
  579. push_reply, g_strdup(argv[1]),
  580. g_free) == FALSE) {
  581. bt_shell_printf("Failed to send\n");
  582. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  583. }
  584. bt_shell_printf("Attempting to send %s to %s\n", argv[1],
  585. g_dbus_proxy_get_path(proxy));
  586. }
  587. static void cmd_send(int argc, char *argv[])
  588. {
  589. const char *path = g_dbus_proxy_get_path(default_session);
  590. GDBusProxy *proxy;
  591. if (!check_default_session())
  592. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  593. proxy = g_dbus_proxy_lookup(opps, NULL, path, OBEX_OPP_INTERFACE);
  594. if (proxy) {
  595. opp_send(proxy, argc, argv);
  596. return;
  597. }
  598. proxy = g_dbus_proxy_lookup(maps, NULL, path, OBEX_MAP_INTERFACE);
  599. if (proxy) {
  600. map_send(proxy, argc, argv);
  601. return;
  602. }
  603. bt_shell_printf("Command not supported\n");
  604. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  605. }
  606. static void cmd_pull(int argc, char *argv[])
  607. {
  608. const char *path = g_dbus_proxy_get_path(default_session);
  609. GDBusProxy *proxy;
  610. if (!check_default_session())
  611. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  612. proxy = g_dbus_proxy_lookup(opps, NULL, path, OBEX_OPP_INTERFACE);
  613. if (proxy) {
  614. opp_pull(proxy, argc, argv);
  615. return;
  616. }
  617. bt_shell_printf("Command not supported\n");
  618. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  619. }
  620. static void change_folder_reply(DBusMessage *message, void *user_data)
  621. {
  622. DBusError error;
  623. dbus_error_init(&error);
  624. if (dbus_set_error_from_message(&error, message) == TRUE) {
  625. bt_shell_printf("Failed to ChangeFolder: %s\n", error.name);
  626. dbus_error_free(&error);
  627. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  628. }
  629. bt_shell_printf("ChangeFolder successful\n");
  630. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  631. }
  632. static void change_folder_setup(DBusMessageIter *iter, void *user_data)
  633. {
  634. const char *folder = user_data;
  635. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &folder);
  636. }
  637. static void select_reply(DBusMessage *message, void *user_data)
  638. {
  639. DBusMessageIter iter;
  640. DBusError error;
  641. dbus_error_init(&error);
  642. if (dbus_set_error_from_message(&error, message) == TRUE) {
  643. bt_shell_printf("Failed to Select: %s\n", error.name);
  644. dbus_error_free(&error);
  645. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  646. }
  647. dbus_message_iter_init(message, &iter);
  648. bt_shell_printf("Select successful\n");
  649. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  650. }
  651. static void select_setup(DBusMessageIter *iter, void *user_data)
  652. {
  653. const char *folder = user_data;
  654. const char *location = "int";
  655. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &location);
  656. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &folder);
  657. }
  658. static void setfolder_reply(DBusMessage *message, void *user_data)
  659. {
  660. DBusError error;
  661. dbus_error_init(&error);
  662. if (dbus_set_error_from_message(&error, message) == TRUE) {
  663. bt_shell_printf("Failed to SetFolder: %s\n", error.name);
  664. dbus_error_free(&error);
  665. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  666. }
  667. bt_shell_printf("SetFolder successful\n");
  668. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  669. }
  670. static void setfolder_setup(DBusMessageIter *iter, void *user_data)
  671. {
  672. const char *folder = user_data;
  673. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &folder);
  674. }
  675. static void ftp_cd(GDBusProxy *proxy, int argc, char *argv[])
  676. {
  677. if (g_dbus_proxy_method_call(proxy, "ChangeFolder", change_folder_setup,
  678. change_folder_reply, g_strdup(argv[1]),
  679. g_free) == FALSE) {
  680. bt_shell_printf("Failed to ChangeFolder\n");
  681. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  682. }
  683. bt_shell_printf("Attempting to ChangeFolder to %s\n", argv[1]);
  684. }
  685. static void pbap_cd(GDBusProxy *proxy, int argc, char *argv[])
  686. {
  687. if (g_dbus_proxy_method_call(proxy, "Select", select_setup,
  688. select_reply, g_strdup(argv[1]),
  689. g_free) == FALSE) {
  690. bt_shell_printf("Failed to Select\n");
  691. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  692. }
  693. bt_shell_printf("Attempting to Select to %s\n", argv[1]);
  694. }
  695. static void map_cd(GDBusProxy *proxy, int argc, char *argv[])
  696. {
  697. if (g_dbus_proxy_method_call(proxy, "SetFolder", setfolder_setup,
  698. setfolder_reply, g_strdup(argv[1]),
  699. g_free) == FALSE) {
  700. bt_shell_printf("Failed to SetFolder\n");
  701. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  702. }
  703. bt_shell_printf("Attempting to SetFolder to %s\n", argv[1]);
  704. }
  705. static void cmd_cd(int argc, char *argv[])
  706. {
  707. const char *path = g_dbus_proxy_get_path(default_session);
  708. GDBusProxy *proxy;
  709. if (!check_default_session())
  710. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  711. proxy = g_dbus_proxy_lookup(ftps, NULL, path, OBEX_FTP_INTERFACE);
  712. if (proxy) {
  713. ftp_cd(proxy, argc, argv);
  714. return;
  715. }
  716. proxy = g_dbus_proxy_lookup(pbaps, NULL, path, OBEX_PBAP_INTERFACE);
  717. if (proxy) {
  718. pbap_cd(proxy, argc, argv);
  719. return;
  720. }
  721. proxy = g_dbus_proxy_lookup(maps, NULL, path, OBEX_MAP_INTERFACE);
  722. if (proxy) {
  723. map_cd(proxy, argc, argv);
  724. return;
  725. }
  726. bt_shell_printf("Command not supported\n");
  727. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  728. }
  729. static void list_folder_reply(DBusMessage *message, void *user_data)
  730. {
  731. DBusMessageIter iter, array;
  732. DBusError error;
  733. dbus_error_init(&error);
  734. if (dbus_set_error_from_message(&error, message) == TRUE) {
  735. bt_shell_printf("Failed to ListFolder: %s\n", error.name);
  736. dbus_error_free(&error);
  737. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  738. }
  739. dbus_message_iter_init(message, &iter);
  740. if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
  741. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  742. dbus_message_iter_recurse(&iter, &array);
  743. while (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_INVALID) {
  744. print_dict_iter(&array);
  745. dbus_message_iter_next(&array);
  746. }
  747. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  748. }
  749. static void ftp_ls(GDBusProxy *proxy, int argc, char *argv[])
  750. {
  751. if (g_dbus_proxy_method_call(proxy, "ListFolder", NULL,
  752. list_folder_reply, NULL,
  753. NULL) == FALSE) {
  754. bt_shell_printf("Failed to ls\n");
  755. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  756. }
  757. bt_shell_printf("Attempting to ListFolder\n");
  758. }
  759. static void parse_list_reply(DBusMessage *message)
  760. {
  761. DBusMessageIter iter, array;
  762. dbus_message_iter_init(message, &iter);
  763. if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
  764. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  765. dbus_message_iter_recurse(&iter, &array);
  766. while (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_INVALID) {
  767. DBusMessageIter entry;
  768. const char *vcard;
  769. if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRUCT)
  770. return;
  771. dbus_message_iter_recurse(&array, &entry);
  772. dbus_message_iter_get_basic(&entry, &vcard);
  773. dbus_message_iter_next(&entry);
  774. print_iter("\t", vcard, &entry);
  775. dbus_message_iter_next(&array);
  776. }
  777. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  778. }
  779. static void list_reply(DBusMessage *message, void *user_data)
  780. {
  781. DBusError error;
  782. dbus_error_init(&error);
  783. if (dbus_set_error_from_message(&error, message) == TRUE) {
  784. bt_shell_printf("Failed to List: %s\n", error.name);
  785. dbus_error_free(&error);
  786. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  787. }
  788. parse_list_reply(message);
  789. }
  790. static void list_setup(DBusMessageIter *iter, void *user_data)
  791. {
  792. DBusMessageIter dict;
  793. dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
  794. DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
  795. DBUS_TYPE_STRING_AS_STRING
  796. DBUS_TYPE_VARIANT_AS_STRING
  797. DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
  798. &dict);
  799. dbus_message_iter_close_container(iter, &dict);
  800. }
  801. static void search_reply(DBusMessage *message, void *user_data)
  802. {
  803. DBusError error;
  804. dbus_error_init(&error);
  805. if (dbus_set_error_from_message(&error, message) == TRUE) {
  806. bt_shell_printf("Failed to Search: %s\n", error.name);
  807. dbus_error_free(&error);
  808. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  809. }
  810. parse_list_reply(message);
  811. }
  812. static void search_setup(DBusMessageIter *iter, void *user_data)
  813. {
  814. const char *value = user_data;
  815. const char *field;
  816. DBusMessageIter dict;
  817. field = isalpha(value[0]) ? "name" : "number";
  818. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &field);
  819. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &value);
  820. dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
  821. DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
  822. DBUS_TYPE_STRING_AS_STRING
  823. DBUS_TYPE_VARIANT_AS_STRING
  824. DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
  825. &dict);
  826. dbus_message_iter_close_container(iter, &dict);
  827. }
  828. static void pbap_search(GDBusProxy *proxy, int argc, char *argv[])
  829. {
  830. if (g_dbus_proxy_method_call(proxy, "Search", search_setup,
  831. search_reply, g_strdup(argv[1]),
  832. g_free) == FALSE) {
  833. bt_shell_printf("Failed to Search\n");
  834. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  835. }
  836. bt_shell_printf("Attempting to Search\n");
  837. }
  838. static void list_folders_reply(DBusMessage *message, void *user_data)
  839. {
  840. DBusError error;
  841. DBusMessageIter iter, array;
  842. dbus_error_init(&error);
  843. if (dbus_set_error_from_message(&error, message) == TRUE) {
  844. bt_shell_printf("Failed to ListFolders: %s\n", error.name);
  845. dbus_error_free(&error);
  846. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  847. }
  848. dbus_message_iter_init(message, &iter);
  849. if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
  850. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  851. dbus_message_iter_recurse(&iter, &array);
  852. while (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_INVALID) {
  853. print_dict_iter(&array);
  854. dbus_message_iter_next(&array);
  855. }
  856. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  857. }
  858. static void list_folders_setup(DBusMessageIter *iter, void *user_data)
  859. {
  860. DBusMessageIter dict;
  861. dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
  862. DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
  863. DBUS_TYPE_STRING_AS_STRING
  864. DBUS_TYPE_VARIANT_AS_STRING
  865. DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
  866. &dict);
  867. dbus_message_iter_close_container(iter, &dict);
  868. }
  869. static void list_messages_reply(DBusMessage *message, void *user_data)
  870. {
  871. DBusError error;
  872. DBusMessageIter iter, array;
  873. dbus_error_init(&error);
  874. if (dbus_set_error_from_message(&error, message) == TRUE) {
  875. bt_shell_printf("Failed to ListFolders: %s\n", error.name);
  876. dbus_error_free(&error);
  877. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  878. }
  879. dbus_message_iter_init(message, &iter);
  880. if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
  881. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  882. dbus_message_iter_recurse(&iter, &array);
  883. while ((dbus_message_iter_get_arg_type(&array)) ==
  884. DBUS_TYPE_DICT_ENTRY) {
  885. DBusMessageIter entry;
  886. const char *obj;
  887. dbus_message_iter_recurse(&array, &entry);
  888. dbus_message_iter_get_basic(&entry, &obj);
  889. bt_shell_printf("\t%s\n", obj);
  890. dbus_message_iter_next(&array);
  891. }
  892. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  893. }
  894. static void list_messages_setup(DBusMessageIter *iter, void *user_data)
  895. {
  896. const char *folder = user_data;
  897. DBusMessageIter dict;
  898. if (strcmp(folder, "*") == 0)
  899. folder = "";
  900. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &folder);
  901. dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
  902. DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
  903. DBUS_TYPE_STRING_AS_STRING
  904. DBUS_TYPE_VARIANT_AS_STRING
  905. DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
  906. &dict);
  907. dbus_message_iter_close_container(iter, &dict);
  908. }
  909. static void pbap_list(GDBusProxy *proxy, int argc, char *argv[])
  910. {
  911. if (g_dbus_proxy_method_call(proxy, "List", list_setup, list_reply,
  912. NULL, NULL) == FALSE) {
  913. bt_shell_printf("Failed to List\n");
  914. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  915. }
  916. bt_shell_printf("Attempting to List\n");
  917. }
  918. static void get_size_reply(DBusMessage *message, void *user_data)
  919. {
  920. GDBusProxy *proxy = user_data;
  921. DBusError error;
  922. DBusMessageIter iter;
  923. dbus_error_init(&error);
  924. if (dbus_set_error_from_message(&error, message) == TRUE) {
  925. bt_shell_printf("Failed to GetSize: %s\n", error.name);
  926. dbus_error_free(&error);
  927. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  928. }
  929. dbus_message_iter_init(message, &iter);
  930. print_iter("\t", "Size", &iter);
  931. pbap_list(proxy, 0, NULL);
  932. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  933. }
  934. static void pbap_get_size(GDBusProxy *proxy, int argc, char *argv[])
  935. {
  936. if (g_dbus_proxy_method_call(proxy, "GetSize", NULL, get_size_reply,
  937. proxy, NULL) == FALSE) {
  938. bt_shell_printf("Failed to GetSize\n");
  939. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  940. }
  941. bt_shell_printf("Attempting to GetSize\n");
  942. }
  943. static void pbap_ls(GDBusProxy *proxy, int argc, char *argv[])
  944. {
  945. if (argc > 1) {
  946. if (strcmp("-l", argv[1]))
  947. pbap_search(proxy, argc, argv);
  948. else
  949. pbap_get_size(proxy, argc, argv);
  950. return;
  951. }
  952. pbap_list(proxy, argc, argv);
  953. }
  954. static void map_ls_messages(GDBusProxy *proxy, int argc, char *argv[])
  955. {
  956. if (g_dbus_proxy_method_call(proxy, "ListMessages", list_messages_setup,
  957. list_messages_reply, g_strdup(argv[1]),
  958. g_free) == FALSE) {
  959. bt_shell_printf("Failed to ListMessages\n");
  960. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  961. }
  962. bt_shell_printf("Attempting to ListMessages\n");
  963. }
  964. static void map_ls(GDBusProxy *proxy, int argc, char *argv[])
  965. {
  966. if (argc > 1) {
  967. map_ls_messages(proxy, argc, argv);
  968. return;
  969. }
  970. if (g_dbus_proxy_method_call(proxy, "ListFolders", list_folders_setup,
  971. list_folders_reply, NULL,
  972. NULL) == FALSE) {
  973. bt_shell_printf("Failed to ListFolders\n");
  974. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  975. }
  976. bt_shell_printf("Attempting to ListFolders\n");
  977. }
  978. static void cmd_ls(int argc, char *argv[])
  979. {
  980. const char *path = g_dbus_proxy_get_path(default_session);
  981. GDBusProxy *proxy;
  982. if (!check_default_session())
  983. return;
  984. proxy = g_dbus_proxy_lookup(ftps, NULL, path, OBEX_FTP_INTERFACE);
  985. if (proxy) {
  986. ftp_ls(proxy, argc, argv);
  987. return;
  988. }
  989. proxy = g_dbus_proxy_lookup(pbaps, NULL, path, OBEX_PBAP_INTERFACE);
  990. if (proxy) {
  991. pbap_ls(proxy, argc, argv);
  992. return;
  993. }
  994. proxy = g_dbus_proxy_lookup(maps, NULL, path, OBEX_MAP_INTERFACE);
  995. if (proxy) {
  996. map_ls(proxy, argc, argv);
  997. return;
  998. }
  999. bt_shell_printf("Command not supported\n");
  1000. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1001. }
  1002. struct cp_args {
  1003. char *source;
  1004. char *target;
  1005. };
  1006. static void cp_free(void *data)
  1007. {
  1008. struct cp_args *args = data;
  1009. g_free(args->source);
  1010. g_free(args->target);
  1011. g_free(args);
  1012. }
  1013. static struct cp_args *cp_new(char *argv[])
  1014. {
  1015. struct cp_args *args;
  1016. const char *source;
  1017. const char *target;
  1018. source = rindex(argv[1], ':');
  1019. if (source == NULL)
  1020. source = argv[1];
  1021. else
  1022. source++;
  1023. target = rindex(argv[2], ':');
  1024. if (target == NULL)
  1025. target = argv[2];
  1026. else
  1027. target++;
  1028. args = g_new0(struct cp_args, 1);
  1029. args->source = g_strdup(source);
  1030. args->target = g_strdup(target);
  1031. return args;
  1032. }
  1033. static void cp_setup(DBusMessageIter *iter, void *user_data)
  1034. {
  1035. struct cp_args *args = user_data;
  1036. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &args->source);
  1037. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &args->target);
  1038. }
  1039. static void copy_file_reply(DBusMessage *message, void *user_data)
  1040. {
  1041. DBusError error;
  1042. dbus_error_init(&error);
  1043. if (dbus_set_error_from_message(&error, message) == TRUE) {
  1044. bt_shell_printf("Failed to CopyFile: %s\n", error.name);
  1045. dbus_error_free(&error);
  1046. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1047. }
  1048. bt_shell_printf("CopyFile successful\n");
  1049. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1050. }
  1051. static void ftp_copy(GDBusProxy *proxy, int argc, char *argv[])
  1052. {
  1053. struct cp_args *args;
  1054. args = cp_new(argv);
  1055. if (g_dbus_proxy_method_call(proxy, "CopyFile", cp_setup,
  1056. copy_file_reply, args, cp_free) == FALSE) {
  1057. bt_shell_printf("Failed to CopyFile\n");
  1058. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1059. }
  1060. bt_shell_printf("Attempting to CopyFile\n");
  1061. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1062. }
  1063. static void get_file_reply(DBusMessage *message, void *user_data)
  1064. {
  1065. DBusError error;
  1066. DBusMessageIter iter;
  1067. dbus_error_init(&error);
  1068. if (dbus_set_error_from_message(&error, message) == TRUE) {
  1069. bt_shell_printf("Failed to GetFile: %s\n", error.name);
  1070. dbus_error_free(&error);
  1071. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1072. }
  1073. dbus_message_iter_init(message, &iter);
  1074. print_transfer_iter(&iter);
  1075. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1076. }
  1077. static void get_file_setup(DBusMessageIter *iter, void *user_data)
  1078. {
  1079. struct cp_args *args = user_data;
  1080. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &args->target);
  1081. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &args->source);
  1082. }
  1083. static void ftp_get(GDBusProxy *proxy, int argc, char *argv[])
  1084. {
  1085. struct cp_args *args;
  1086. if (rindex(argv[2], ':') == NULL)
  1087. return ftp_copy(proxy, argc, argv);
  1088. args = cp_new(argv);
  1089. if (g_dbus_proxy_method_call(proxy, "GetFile", get_file_setup,
  1090. get_file_reply, args, cp_free) == FALSE) {
  1091. bt_shell_printf("Failed to GetFile\n");
  1092. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1093. }
  1094. bt_shell_printf("Attempting to GetFile\n");
  1095. }
  1096. static void put_file_reply(DBusMessage *message, void *user_data)
  1097. {
  1098. DBusError error;
  1099. DBusMessageIter iter;
  1100. dbus_error_init(&error);
  1101. if (dbus_set_error_from_message(&error, message) == TRUE) {
  1102. bt_shell_printf("Failed to PutFile: %s\n", error.name);
  1103. dbus_error_free(&error);
  1104. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1105. }
  1106. dbus_message_iter_init(message, &iter);
  1107. print_transfer_iter(&iter);
  1108. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1109. }
  1110. static void ftp_put(GDBusProxy *proxy, int argc, char *argv[])
  1111. {
  1112. struct cp_args *args;
  1113. if (rindex(argv[2], ':') != NULL) {
  1114. bt_shell_printf("Invalid target file argument\n");
  1115. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1116. }
  1117. args = cp_new(argv);
  1118. if (g_dbus_proxy_method_call(proxy, "PutFile", cp_setup, put_file_reply,
  1119. args, cp_free) == FALSE) {
  1120. bt_shell_printf("Failed to PutFile\n");
  1121. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1122. }
  1123. bt_shell_printf("Attempting to PutFile\n");
  1124. }
  1125. static void ftp_cp(GDBusProxy *proxy, int argc, char *argv[])
  1126. {
  1127. if (rindex(argv[1], ':') == NULL)
  1128. return ftp_get(proxy, argc, argv);
  1129. return ftp_put(proxy, argc, argv);
  1130. }
  1131. static void pull_all_reply(DBusMessage *message, void *user_data)
  1132. {
  1133. DBusError error;
  1134. dbus_error_init(&error);
  1135. if (dbus_set_error_from_message(&error, message) == TRUE) {
  1136. bt_shell_printf("Failed to PullAll: %s\n", error.name);
  1137. dbus_error_free(&error);
  1138. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1139. }
  1140. bt_shell_printf("PullAll successful\n");
  1141. }
  1142. static void pull_all_setup(DBusMessageIter *iter, void *user_data)
  1143. {
  1144. const char *file = user_data;
  1145. DBusMessageIter dict;
  1146. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &file);
  1147. dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
  1148. DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
  1149. DBUS_TYPE_STRING_AS_STRING
  1150. DBUS_TYPE_VARIANT_AS_STRING
  1151. DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
  1152. &dict);
  1153. dbus_message_iter_close_container(iter, &dict);
  1154. }
  1155. static void pbap_pull_all(GDBusProxy *proxy, int argc, char *argv[])
  1156. {
  1157. if (g_dbus_proxy_method_call(proxy, "PullAll", pull_all_setup,
  1158. pull_all_reply, g_strdup(argv[2]),
  1159. g_free) == FALSE) {
  1160. bt_shell_printf("Failed to PullAll\n");
  1161. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1162. }
  1163. bt_shell_printf("Attempting to PullAll\n");
  1164. }
  1165. static void pull_reply(DBusMessage *message, void *user_data)
  1166. {
  1167. DBusError error;
  1168. dbus_error_init(&error);
  1169. if (dbus_set_error_from_message(&error, message) == TRUE) {
  1170. bt_shell_printf("Failed to Pull: %s\n", error.name);
  1171. dbus_error_free(&error);
  1172. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1173. }
  1174. bt_shell_printf("Pull successful\n");
  1175. }
  1176. static void pull_setup(DBusMessageIter *iter, void *user_data)
  1177. {
  1178. struct cp_args *args = user_data;
  1179. DBusMessageIter dict;
  1180. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &args->source);
  1181. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &args->target);
  1182. dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
  1183. DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
  1184. DBUS_TYPE_STRING_AS_STRING
  1185. DBUS_TYPE_VARIANT_AS_STRING
  1186. DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
  1187. &dict);
  1188. dbus_message_iter_close_container(iter, &dict);
  1189. }
  1190. static void pbap_pull(GDBusProxy *proxy, int argc, char *argv[])
  1191. {
  1192. struct cp_args *args;
  1193. args = cp_new(argv);
  1194. if (g_dbus_proxy_method_call(proxy, "Pull", pull_setup, pull_reply,
  1195. args, cp_free) == FALSE) {
  1196. bt_shell_printf("Failed to Pull\n");
  1197. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1198. }
  1199. bt_shell_printf("Attempting to Pull\n");
  1200. }
  1201. static void pbap_cp(GDBusProxy *proxy, int argc, char *argv[])
  1202. {
  1203. if (strcmp(argv[1], "*") == 0 || strcmp(argv[1], "*.vcf") == 0)
  1204. return pbap_pull_all(proxy, argc, argv);
  1205. return pbap_pull(proxy, argc, argv);
  1206. }
  1207. static void get_reply(DBusMessage *message, void *user_data)
  1208. {
  1209. DBusMessageIter iter;
  1210. DBusError error;
  1211. dbus_error_init(&error);
  1212. if (dbus_set_error_from_message(&error, message) == TRUE) {
  1213. bt_shell_printf("Failed to Get: %s\n", error.name);
  1214. dbus_error_free(&error);
  1215. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1216. }
  1217. dbus_message_iter_init(message, &iter);
  1218. print_transfer_iter(&iter);
  1219. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1220. }
  1221. static void get_setup(DBusMessageIter *iter, void *user_data)
  1222. {
  1223. const char *file = user_data;
  1224. dbus_bool_t attachment = TRUE;
  1225. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &file);
  1226. dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &attachment);
  1227. }
  1228. static void map_cp(GDBusProxy *proxy, int argc, char *argv[])
  1229. {
  1230. GDBusProxy *obj;
  1231. obj = g_dbus_proxy_lookup(msgs, NULL, argv[1], OBEX_MSG_INTERFACE);
  1232. if (obj == NULL) {
  1233. bt_shell_printf("Invalid message argument\n");
  1234. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1235. }
  1236. if (g_dbus_proxy_method_call(obj, "Get", get_setup, get_reply,
  1237. g_strdup(argv[2]), g_free) == FALSE) {
  1238. bt_shell_printf("Failed to Get\n");
  1239. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1240. }
  1241. bt_shell_printf("Attempting to Get\n");
  1242. }
  1243. static void cmd_cp(int argc, char *argv[])
  1244. {
  1245. const char *path = g_dbus_proxy_get_path(default_session);
  1246. GDBusProxy *proxy;
  1247. if (!check_default_session())
  1248. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1249. proxy = g_dbus_proxy_lookup(ftps, NULL, path, OBEX_FTP_INTERFACE);
  1250. if (proxy) {
  1251. ftp_cp(proxy, argc, argv);
  1252. return;
  1253. }
  1254. proxy = g_dbus_proxy_lookup(pbaps, NULL, path, OBEX_PBAP_INTERFACE);
  1255. if (proxy) {
  1256. pbap_cp(proxy, argc, argv);
  1257. return;
  1258. }
  1259. proxy = g_dbus_proxy_lookup(maps, NULL, path, OBEX_MAP_INTERFACE);
  1260. if (proxy) {
  1261. map_cp(proxy, argc, argv);
  1262. return;
  1263. }
  1264. bt_shell_printf("Command not supported\n");
  1265. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1266. }
  1267. static void move_file_reply(DBusMessage *message, void *user_data)
  1268. {
  1269. DBusError error;
  1270. dbus_error_init(&error);
  1271. if (dbus_set_error_from_message(&error, message) == TRUE) {
  1272. bt_shell_printf("Failed to MoveFile: %s\n", error.name);
  1273. dbus_error_free(&error);
  1274. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1275. }
  1276. bt_shell_printf("MoveFile successful\n");
  1277. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1278. }
  1279. static void cmd_mv(int argc, char *argv[])
  1280. {
  1281. const char *path = g_dbus_proxy_get_path(default_session);
  1282. GDBusProxy *proxy;
  1283. struct cp_args *args;
  1284. if (!check_default_session())
  1285. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1286. proxy = g_dbus_proxy_lookup(ftps, NULL, path, OBEX_FTP_INTERFACE);
  1287. if (proxy == NULL) {
  1288. bt_shell_printf("Command not supported\n");
  1289. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1290. }
  1291. args = cp_new(argv);
  1292. if (g_dbus_proxy_method_call(proxy, "MoveFile", cp_setup,
  1293. move_file_reply, args, cp_free) == FALSE) {
  1294. bt_shell_printf("Failed to MoveFile\n");
  1295. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1296. }
  1297. bt_shell_printf("Attempting to MoveFile\n");
  1298. }
  1299. static void delete_reply(DBusMessage *message, void *user_data)
  1300. {
  1301. DBusError error;
  1302. dbus_error_init(&error);
  1303. if (dbus_set_error_from_message(&error, message) == TRUE) {
  1304. bt_shell_printf("Failed to Delete: %s\n", error.name);
  1305. dbus_error_free(&error);
  1306. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1307. }
  1308. bt_shell_printf("Delete successful\n");
  1309. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1310. }
  1311. static void delete_setup(DBusMessageIter *iter, void *user_data)
  1312. {
  1313. const char *file = user_data;
  1314. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &file);
  1315. }
  1316. static void ftp_rm(GDBusProxy *proxy, int argc, char *argv[])
  1317. {
  1318. if (g_dbus_proxy_method_call(proxy, "Delete", delete_setup,
  1319. delete_reply, g_strdup(argv[1]),
  1320. g_free) == FALSE) {
  1321. bt_shell_printf("Failed to Delete\n");
  1322. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1323. }
  1324. bt_shell_printf("Attempting to Delete\n");
  1325. }
  1326. static void set_delete_reply(const DBusError *error, void *user_data)
  1327. {
  1328. if (dbus_error_is_set(error)) {
  1329. bt_shell_printf("Failed to set Deleted: %s\n", error->name);
  1330. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1331. } else {
  1332. bt_shell_printf("Set Deleted successful\n");
  1333. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1334. }
  1335. }
  1336. static void map_rm(GDBusProxy *proxy, int argc, char *argv[])
  1337. {
  1338. GDBusProxy *msg;
  1339. dbus_bool_t value = TRUE;
  1340. msg = g_dbus_proxy_lookup(msgs, NULL, argv[1], OBEX_MSG_INTERFACE);
  1341. if (msg == NULL) {
  1342. bt_shell_printf("Invalid message argument\n");
  1343. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1344. }
  1345. if (g_dbus_proxy_set_property_basic(msg, "Deleted", DBUS_TYPE_BOOLEAN,
  1346. &value, set_delete_reply,
  1347. NULL, NULL) == FALSE) {
  1348. bt_shell_printf("Failed to set Deleted\n");
  1349. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1350. }
  1351. bt_shell_printf("Attempting to set Deleted\n");
  1352. }
  1353. static void cmd_rm(int argc, char *argv[])
  1354. {
  1355. const char *path = g_dbus_proxy_get_path(default_session);
  1356. GDBusProxy *proxy;
  1357. if (!check_default_session())
  1358. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1359. proxy = g_dbus_proxy_lookup(ftps, NULL, path, OBEX_FTP_INTERFACE);
  1360. if (proxy) {
  1361. ftp_rm(proxy, argc, argv);
  1362. return;
  1363. }
  1364. proxy = g_dbus_proxy_lookup(maps, NULL, path, OBEX_MAP_INTERFACE);
  1365. if (proxy) {
  1366. map_rm(proxy, argc, argv);
  1367. return;
  1368. }
  1369. bt_shell_printf("Command not supported\n");
  1370. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1371. }
  1372. static void create_folder_reply(DBusMessage *message, void *user_data)
  1373. {
  1374. DBusError error;
  1375. dbus_error_init(&error);
  1376. if (dbus_set_error_from_message(&error, message) == TRUE) {
  1377. bt_shell_printf("Failed to CreateFolder: %s\n", error.name);
  1378. dbus_error_free(&error);
  1379. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1380. }
  1381. bt_shell_printf("CreateFolder successful\n");
  1382. }
  1383. static void create_folder_setup(DBusMessageIter *iter, void *user_data)
  1384. {
  1385. const char *folder = user_data;
  1386. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &folder);
  1387. }
  1388. static void cmd_mkdir(int argc, char *argv[])
  1389. {
  1390. const char *path = g_dbus_proxy_get_path(default_session);
  1391. GDBusProxy *proxy;
  1392. if (!check_default_session())
  1393. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1394. proxy = g_dbus_proxy_lookup(ftps, NULL, path, OBEX_FTP_INTERFACE);
  1395. if (proxy == NULL) {
  1396. bt_shell_printf("Command not supported\n");
  1397. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1398. }
  1399. if (g_dbus_proxy_method_call(proxy, "CreateFolder", create_folder_setup,
  1400. create_folder_reply, g_strdup(argv[1]),
  1401. g_free) == FALSE) {
  1402. bt_shell_printf("Failed to CreateFolder\n");
  1403. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1404. }
  1405. bt_shell_printf("Attempting to CreateFolder\n");
  1406. }
  1407. static const struct bt_shell_menu main_menu = {
  1408. .name = "main",
  1409. .entries = {
  1410. { "connect", "<dev> [uuid]", cmd_connect, "Connect session" },
  1411. { "disconnect", "[session]", cmd_disconnect, "Disconnect session",
  1412. session_generator },
  1413. { "list", NULL, cmd_list, "List available sessions" },
  1414. { "show", "[session]", cmd_show, "Session information",
  1415. session_generator },
  1416. { "select", "<session>", cmd_select, "Select default session",
  1417. session_generator },
  1418. { "info", "<object>", cmd_info, "Object information",
  1419. transfer_generator },
  1420. { "cancel", "<transfer>", cmd_cancel, "Cancel transfer",
  1421. transfer_generator },
  1422. { "suspend", "<transfer>", cmd_suspend, "Suspend transfer",
  1423. transfer_generator },
  1424. { "resume", "<transfer>", cmd_resume, "Resume transfer",
  1425. transfer_generator },
  1426. { "send", "<file>", cmd_send, "Send file" },
  1427. { "pull", "<file>", cmd_pull,
  1428. "Pull Vobject & stores in file" },
  1429. { "cd", "<path>", cmd_cd, "Change current folder" },
  1430. { "ls", "<options>", cmd_ls, "List current folder" },
  1431. { "cp", "<source file> <destination file>", cmd_cp,
  1432. "Copy source file to destination file" },
  1433. { "mv", "<source file> <destination file>", cmd_mv,
  1434. "Move source file to destination file" },
  1435. { "rm", "<file>", cmd_rm, "Delete file" },
  1436. { "mkdir", "<folder>", cmd_mkdir, "Create folder" },
  1437. {} },
  1438. };
  1439. static void client_added(GDBusProxy *proxy)
  1440. {
  1441. if (client == NULL)
  1442. client = proxy;
  1443. print_proxy(proxy, "Client", COLORED_NEW);
  1444. }
  1445. static void session_added(GDBusProxy *proxy)
  1446. {
  1447. sessions = g_list_append(sessions, proxy);
  1448. if (default_session == NULL)
  1449. set_default_session(proxy);
  1450. print_proxy(proxy, "Session", COLORED_NEW);
  1451. }
  1452. static void print_transferred(struct transfer_data *data, const char *str,
  1453. DBusMessageIter *iter)
  1454. {
  1455. dbus_uint64_t valu64;
  1456. uint64_t speed;
  1457. int seconds, minutes;
  1458. dbus_message_iter_get_basic(iter, &valu64);
  1459. /*
  1460. * Use the file size to output the proper size/speed since obexd resets
  1461. * the current transferred size to zero on completion of transfer.
  1462. */
  1463. if (valu64 == 0)
  1464. valu64 = data->size;
  1465. speed = valu64 - data->transferred;
  1466. data->transferred = valu64;
  1467. if (data->size == 0) {
  1468. bt_shell_printf("%sTransferred: %" PRIu64 " (@%" PRIu64
  1469. "KB/s)\n", str, valu64, speed / 1000);
  1470. return;
  1471. }
  1472. seconds = (data->size - data->transferred) / speed;
  1473. minutes = seconds / 60;
  1474. seconds %= 60;
  1475. bt_shell_printf("%sTransferred: %" PRIu64 " (@%" PRIu64
  1476. "KB/s %02u:%02u)\n", str, valu64, speed / 1000,
  1477. minutes, seconds);
  1478. }
  1479. static void transfer_property_changed(GDBusProxy *proxy, const char *name,
  1480. DBusMessageIter *iter, void *user_data)
  1481. {
  1482. struct transfer_data *data = user_data;
  1483. char *str;
  1484. if (iter == NULL)
  1485. return;
  1486. str = proxy_description(proxy, "Transfer", COLORED_CHG);
  1487. if (strcmp(name, "Transferred") == 0) {
  1488. print_transferred(data, str, iter);
  1489. goto done;
  1490. }
  1491. if (strcmp(name, "Size") == 0)
  1492. dbus_message_iter_get_basic(iter, &data->size);
  1493. print_iter(str, name, iter);
  1494. done:
  1495. g_free(str);
  1496. }
  1497. static void transfer_destroy(GDBusProxy *proxy, void *user_data)
  1498. {
  1499. struct transfer_data *data = user_data;
  1500. g_free(data);
  1501. }
  1502. static void transfer_added(GDBusProxy *proxy)
  1503. {
  1504. struct transfer_data *data;
  1505. DBusMessageIter iter;
  1506. transfers = g_list_append(transfers, proxy);
  1507. print_proxy(proxy, "Transfer", COLORED_NEW);
  1508. data = g_new0(struct transfer_data, 1);
  1509. if (g_dbus_proxy_get_property(proxy, "Transferred", &iter))
  1510. dbus_message_iter_get_basic(&iter, &data->transferred);
  1511. if (g_dbus_proxy_get_property(proxy, "Size", &iter))
  1512. dbus_message_iter_get_basic(&iter, &data->size);
  1513. g_dbus_proxy_set_property_watch(proxy, transfer_property_changed, data);
  1514. g_dbus_proxy_set_removed_watch(proxy, transfer_destroy, data);
  1515. }
  1516. static void opp_added(GDBusProxy *proxy)
  1517. {
  1518. opps = g_list_append(opps, proxy);
  1519. print_proxy(proxy, "ObjectPush", COLORED_NEW);
  1520. }
  1521. static void ftp_added(GDBusProxy *proxy)
  1522. {
  1523. ftps = g_list_append(ftps, proxy);
  1524. print_proxy(proxy, "FileTransfer", COLORED_NEW);
  1525. }
  1526. static void pbap_added(GDBusProxy *proxy)
  1527. {
  1528. pbaps = g_list_append(pbaps, proxy);
  1529. print_proxy(proxy, "PhonebookAccess", COLORED_NEW);
  1530. }
  1531. static void map_added(GDBusProxy *proxy)
  1532. {
  1533. maps = g_list_append(maps, proxy);
  1534. print_proxy(proxy, "MessageAccess", COLORED_NEW);
  1535. }
  1536. static void msg_added(GDBusProxy *proxy)
  1537. {
  1538. msgs = g_list_append(msgs, proxy);
  1539. print_proxy(proxy, "Message", COLORED_NEW);
  1540. }
  1541. static void proxy_added(GDBusProxy *proxy, void *user_data)
  1542. {
  1543. const char *interface;
  1544. interface = g_dbus_proxy_get_interface(proxy);
  1545. if (!strcmp(interface, OBEX_CLIENT_INTERFACE))
  1546. client_added(proxy);
  1547. else if (!strcmp(interface, OBEX_SESSION_INTERFACE))
  1548. session_added(proxy);
  1549. else if (!strcmp(interface, OBEX_TRANSFER_INTERFACE))
  1550. transfer_added(proxy);
  1551. else if (!strcmp(interface, OBEX_OPP_INTERFACE))
  1552. opp_added(proxy);
  1553. else if (!strcmp(interface, OBEX_FTP_INTERFACE))
  1554. ftp_added(proxy);
  1555. else if (!strcmp(interface, OBEX_PBAP_INTERFACE))
  1556. pbap_added(proxy);
  1557. else if (!strcmp(interface, OBEX_MAP_INTERFACE))
  1558. map_added(proxy);
  1559. else if (!strcmp(interface, OBEX_MSG_INTERFACE))
  1560. msg_added(proxy);
  1561. }
  1562. static void client_removed(GDBusProxy *proxy)
  1563. {
  1564. print_proxy(proxy, "Client", COLORED_DEL);
  1565. if (client == proxy)
  1566. client = NULL;
  1567. }
  1568. static void session_removed(GDBusProxy *proxy)
  1569. {
  1570. print_proxy(proxy, "Session", COLORED_DEL);
  1571. if (default_session == proxy)
  1572. set_default_session(NULL);
  1573. sessions = g_list_remove(sessions, proxy);
  1574. }
  1575. static void transfer_removed(GDBusProxy *proxy)
  1576. {
  1577. print_proxy(proxy, "Transfer", COLORED_DEL);
  1578. transfers = g_list_remove(transfers, proxy);
  1579. }
  1580. static void opp_removed(GDBusProxy *proxy)
  1581. {
  1582. print_proxy(proxy, "ObjectPush", COLORED_DEL);
  1583. opps = g_list_remove(opps, proxy);
  1584. }
  1585. static void ftp_removed(GDBusProxy *proxy)
  1586. {
  1587. print_proxy(proxy, "FileTransfer", COLORED_DEL);
  1588. ftps = g_list_remove(ftps, proxy);
  1589. }
  1590. static void pbap_removed(GDBusProxy *proxy)
  1591. {
  1592. print_proxy(proxy, "PhonebookAccess", COLORED_DEL);
  1593. pbaps = g_list_remove(pbaps, proxy);
  1594. }
  1595. static void map_removed(GDBusProxy *proxy)
  1596. {
  1597. print_proxy(proxy, "MessageAccess", COLORED_DEL);
  1598. maps = g_list_remove(maps, proxy);
  1599. }
  1600. static void msg_removed(GDBusProxy *proxy)
  1601. {
  1602. print_proxy(proxy, "Message", COLORED_DEL);
  1603. msgs = g_list_remove(msgs, proxy);
  1604. }
  1605. static void proxy_removed(GDBusProxy *proxy, void *user_data)
  1606. {
  1607. const char *interface;
  1608. interface = g_dbus_proxy_get_interface(proxy);
  1609. if (!strcmp(interface, OBEX_CLIENT_INTERFACE))
  1610. client_removed(proxy);
  1611. else if (!strcmp(interface, OBEX_SESSION_INTERFACE))
  1612. session_removed(proxy);
  1613. else if (!strcmp(interface, OBEX_TRANSFER_INTERFACE))
  1614. transfer_removed(proxy);
  1615. else if (!strcmp(interface, OBEX_OPP_INTERFACE))
  1616. opp_removed(proxy);
  1617. else if (!strcmp(interface, OBEX_FTP_INTERFACE))
  1618. ftp_removed(proxy);
  1619. else if (!strcmp(interface, OBEX_PBAP_INTERFACE))
  1620. pbap_removed(proxy);
  1621. else if (!strcmp(interface, OBEX_MAP_INTERFACE))
  1622. map_removed(proxy);
  1623. else if (!strcmp(interface, OBEX_MSG_INTERFACE))
  1624. msg_removed(proxy);
  1625. }
  1626. static void session_property_changed(GDBusProxy *proxy, const char *name,
  1627. DBusMessageIter *iter)
  1628. {
  1629. char *str;
  1630. str = proxy_description(proxy, "Session", COLORED_CHG);
  1631. print_iter(str, name, iter);
  1632. g_free(str);
  1633. }
  1634. static void property_changed(GDBusProxy *proxy, const char *name,
  1635. DBusMessageIter *iter, void *user_data)
  1636. {
  1637. const char *interface;
  1638. interface = g_dbus_proxy_get_interface(proxy);
  1639. if (!strcmp(interface, OBEX_SESSION_INTERFACE))
  1640. session_property_changed(proxy, name, iter);
  1641. }
  1642. int main(int argc, char *argv[])
  1643. {
  1644. GDBusClient *client;
  1645. int status;
  1646. bt_shell_init(argc, argv, NULL);
  1647. bt_shell_set_menu(&main_menu);
  1648. bt_shell_set_prompt(PROMPT_OFF);
  1649. dbus_conn = g_dbus_setup_bus(DBUS_BUS_SESSION, NULL, NULL);
  1650. client = g_dbus_client_new(dbus_conn, "org.bluez.obex",
  1651. "/org/bluez/obex");
  1652. g_dbus_client_set_connect_watch(client, connect_handler, NULL);
  1653. g_dbus_client_set_disconnect_watch(client, disconnect_handler, NULL);
  1654. g_dbus_client_set_proxy_handlers(client, proxy_added, proxy_removed,
  1655. property_changed, NULL);
  1656. status = bt_shell_run();
  1657. g_dbus_client_unref(client);
  1658. dbus_connection_unref(dbus_conn);
  1659. return status;
  1660. }