summaryrefslogtreecommitdiffstats
path: root/tools/idevicenotificationproxy.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/idevicenotificationproxy.c')
-rw-r--r--tools/idevicenotificationproxy.c293
1 files changed, 293 insertions, 0 deletions
diff --git a/tools/idevicenotificationproxy.c b/tools/idevicenotificationproxy.c
new file mode 100644
index 0000000..d1e25c1
--- /dev/null
+++ b/tools/idevicenotificationproxy.c
@@ -0,0 +1,293 @@
1/*
2 * idevicenotificationproxy.c
3 * Simple client for the notification_proxy service
4 *
5 * Copyright (c) 2009-2015 Martin Szulecki All Rights Reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#ifdef HAVE_CONFIG_H
23#include <config.h>
24#endif
25
26#define TOOL_NAME "idevicenotificationproxy"
27
28#include <stdio.h>
29#include <string.h>
30#include <stdlib.h>
31#include <getopt.h>
32#include <errno.h>
33#include <signal.h>
34
35#ifdef WIN32
36#include <windows.h>
37#define sleep(x) Sleep(x*1000)
38#else
39#include <unistd.h>
40#endif
41
42#include <libimobiledevice/libimobiledevice.h>
43#include <libimobiledevice/lockdown.h>
44#include <libimobiledevice/notification_proxy.h>
45
46enum cmd_mode {
47 CMD_NONE = 0,
48 CMD_OBSERVE,
49 CMD_POST
50};
51
52static int quit_flag = 0;
53
54/**
55 * signal handler function for cleaning up properly
56 */
57static void clean_exit(int sig)
58{
59 fprintf(stderr, "Exiting...\n");
60 quit_flag++;
61}
62
63static void print_usage(int argc, char **argv, int is_error)
64{
65 char *name = strrchr(argv[0], '/');
66 fprintf(is_error ? stderr : stdout, "Usage: %s [OPTIONS] COMMAND\n", (name ? name + 1: argv[0]));
67 fprintf(is_error ? stderr : stdout,
68 "\n"
69 "Post or observe notifications on a device.\n"
70 "\n"
71 "Where COMMAND is one of:\n"
72 " post ID [...] post notification IDs to device and exit\n"
73 " observe ID [...] observe notification IDs in foreground until CTRL+C\n"
74 " or signal is received\n"
75 "\n"
76 "The following OPTIONS are accepted:\n"
77 " -u, --udid UDID target specific device by UDID\n"
78 " -n, --network connect to network device\n"
79 " -d, --debug enable communication debugging\n"
80 " -h, --help prints usage information\n"
81 " -v, --version prints version information\n"
82 "\n"
83 "Homepage: <" PACKAGE_URL ">\n"
84 "Bug Reports: <" PACKAGE_BUGREPORT ">\n"
85 );
86}
87
88static void notify_cb(const char *notification, void *user_data)
89{
90 printf("> %s\n", notification);
91}
92
93int main(int argc, char *argv[])
94{
95 lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR;
96 lockdownd_service_descriptor_t service = NULL;
97 lockdownd_client_t client = NULL;
98 idevice_t device = NULL;
99 np_client_t gnp = NULL;
100
101 int result = -1;
102 int i = 0;
103 const char* udid = NULL;
104 int use_network = 0;
105 int cmd = CMD_NONE;
106 char* cmd_arg = NULL;
107
108 int count = 0;
109 char **nspec = NULL;
110 char **nspectmp = NULL;
111
112 int c = 0;
113 const struct option longopts[] = {
114 { "debug", no_argument, NULL, 'd' },
115 { "help", no_argument, NULL, 'h' },
116 { "udid", required_argument, NULL, 'u' },
117 { "network", no_argument, NULL, 'n' },
118 { "version", no_argument, NULL, 'v' },
119 { NULL, 0, NULL, 0}
120 };
121
122 signal(SIGINT, clean_exit);
123 signal(SIGTERM, clean_exit);
124#ifndef WIN32
125 signal(SIGQUIT, clean_exit);
126 signal(SIGPIPE, SIG_IGN);
127#endif
128
129 /* parse cmdline args */
130 while ((c = getopt_long(argc, argv, "dhu:nv", longopts, NULL)) != -1) {
131 switch (c) {
132 case 'd':
133 idevice_set_debug_level(1);
134 break;
135 case 'u':
136 if (!*optarg) {
137 fprintf(stderr, "ERROR: UDID argument must not be empty!\n");
138 print_usage(argc, argv, 1);
139 return 2;
140 }
141 udid = optarg;
142 break;
143 case 'n':
144 use_network = 1;
145 break;
146 case 'h':
147 print_usage(argc, argv, 0);
148 return 0;
149 case 'v':
150 printf("%s %s\n", TOOL_NAME, PACKAGE_VERSION);
151 return 0;
152 default:
153 print_usage(argc, argv, 1);
154 return 2;
155 }
156 }
157 argc -= optind;
158 argv += optind;
159
160 if (!argv[i]) {
161 fprintf(stderr, "ERROR: Missing command\n");
162 print_usage(argc+optind, argv-optind, 1);
163 return 2;
164 }
165
166 if (!strcmp(argv[i], "post")) {
167 cmd = CMD_POST;
168 } else if (!strcmp(argv[i], "observe")) {
169 cmd = CMD_OBSERVE;
170 }
171
172 if (cmd == CMD_POST || cmd == CMD_OBSERVE) {
173 i++;
174 if (!argv[i]) {
175 fprintf(stderr, "ERROR: Please supply a valid notification identifier.\n");
176 print_usage(argc+optind, argv-optind, 1);
177 return 2;
178 }
179
180 count = 0;
181 nspec = malloc(sizeof(char*) * (count+1));
182
183 while(1) {
184 if (argv[i] && (strlen(argv[i]) >= 2) && (strncmp(argv[i], "-", 1) != 0)) {
185 nspectmp = realloc(nspec, sizeof(char*) * (count+1));
186 nspectmp[count] = strdup(argv[i]);
187 nspec = nspectmp;
188 count = count+1;
189 i++;
190 } else {
191 i--;
192 break;
193 }
194 }
195
196 nspectmp = realloc(nspec, sizeof(char*) * (count+1));
197 nspectmp[count] = NULL;
198 nspec = nspectmp;
199 }
200
201 /* verify options */
202 if (cmd == CMD_NONE) {
203 fprintf(stderr, "ERROR: Unsupported command '%s'\n", argv[0]);
204 print_usage(argc+optind, argv-optind, 1);
205 return 2;
206 }
207
208 if (IDEVICE_E_SUCCESS != idevice_new_with_options(&device, udid, (use_network) ? IDEVICE_LOOKUP_NETWORK : IDEVICE_LOOKUP_USBMUX)) {
209 if (udid) {
210 printf("No device found with udid %s.\n", udid);
211 } else {
212 printf("No device found.\n");
213 }
214 goto cleanup;
215 }
216
217 if (LOCKDOWN_E_SUCCESS != (ret = lockdownd_client_new_with_handshake(device, &client, TOOL_NAME))) {
218 fprintf(stderr, "ERROR: Could not connect to lockdownd, error code %d\n", ret);
219 goto cleanup;
220 }
221
222 ret = lockdownd_start_service(client, NP_SERVICE_NAME, &service);
223
224 lockdownd_client_free(client);
225
226 if ((ret == LOCKDOWN_E_SUCCESS) && (service->port > 0)) {
227 if (np_client_new(device, service, &gnp) != NP_E_SUCCESS) {
228 printf("Could not connect to notification_proxy!\n");
229 result = -1;
230 } else {
231 np_set_notify_callback(gnp, notify_cb, NULL);
232
233 switch (cmd) {
234 case CMD_POST:
235 i = 0;
236 while(nspec[i] != NULL && i < (count+1)) {
237 printf("< posting \"%s\"\n", nspec[i]);
238 np_post_notification(gnp, nspec[i]);
239 i++;
240 }
241 break;
242 case CMD_OBSERVE:
243 default:
244 i = 0;
245 while(nspec[i] != NULL && i < (count+1)) {
246 printf("! observing \"%s\"\n", nspec[i]);
247 np_observe_notification(gnp, nspec[i]);
248 i++;
249 }
250
251 /* just sleep and wait for notifications */
252 while (!quit_flag) {
253 sleep(1);
254 }
255
256 break;
257 }
258
259 result = EXIT_SUCCESS;
260
261 if (gnp) {
262 np_client_free(gnp);
263 gnp = NULL;
264 }
265 }
266 } else {
267 printf("ERROR: Could not start service %s: %s\n", NP_SERVICE_NAME, lockdownd_strerror(ret));
268 }
269
270 if (service) {
271 lockdownd_service_descriptor_free(service);
272 service = NULL;
273 }
274
275cleanup:
276 if (nspec) {
277 i = 0;
278 while(nspec[i] != NULL && i < (count+1)) {
279 free(nspec[i]);
280 i++;
281 }
282 free(nspec);
283 }
284
285 if (cmd_arg) {
286 free(cmd_arg);
287 }
288
289 if (device)
290 idevice_free(device);
291
292 return result;
293}