summaryrefslogtreecommitdiffstats
path: root/tools/idevicescreenshot.c
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2022-04-30 13:31:20 +0200
committerGravatar Nikias Bassen2022-04-30 13:31:20 +0200
commit6cb13f9e6d3939930aecf91d8e23d1896a3b92e5 (patch)
tree371e4676ac914d9eef6bb4cfc0b5b6dc6f27da4f /tools/idevicescreenshot.c
parent3b5cad28fabb236e05b8fff82fab5098127aa2bb (diff)
downloadlibimobiledevice-6cb13f9e6d3939930aecf91d8e23d1896a3b92e5.tar.gz
libimobiledevice-6cb13f9e6d3939930aecf91d8e23d1896a3b92e5.tar.bz2
tools: Use getopt for option parsing in all tools
Diffstat (limited to 'tools/idevicescreenshot.c')
-rw-r--r--tools/idevicescreenshot.c228
1 files changed, 117 insertions, 111 deletions
diff --git a/tools/idevicescreenshot.c b/tools/idevicescreenshot.c
index 9b1ffa3..0e694c7 100644
--- a/tools/idevicescreenshot.c
+++ b/tools/idevicescreenshot.c
@@ -28,6 +28,7 @@
28#include <stdio.h> 28#include <stdio.h>
29#include <string.h> 29#include <string.h>
30#include <stdlib.h> 30#include <stdlib.h>
31#include <getopt.h>
31#include <errno.h> 32#include <errno.h>
32#include <time.h> 33#include <time.h>
33#include <unistd.h> 34#include <unistd.h>
@@ -39,8 +40,86 @@
39#include <libimobiledevice/lockdown.h> 40#include <libimobiledevice/lockdown.h>
40#include <libimobiledevice/screenshotr.h> 41#include <libimobiledevice/screenshotr.h>
41 42
42void get_image_filename(char *imgdata, char **filename); 43static void get_image_filename(char *imgdata, char **filename)
43void print_usage(int argc, char **argv); 44{
45 // If the provided filename already has an extension, use it as is.
46 if (*filename) {
47 char *last_dot = strrchr(*filename, '.');
48 if (last_dot && !strchr(last_dot, '/')) {
49 return;
50 }
51 }
52
53 // Find the appropriate file extension for the filename.
54 const char *fileext = NULL;
55 if (memcmp(imgdata, "\x89PNG", 4) == 0) {
56 fileext = ".png";
57 } else if (memcmp(imgdata, "MM\x00*", 4) == 0) {
58 fileext = ".tiff";
59 } else {
60 printf("WARNING: screenshot data has unexpected image format.\n");
61 fileext = ".dat";
62 }
63
64 // If a filename without an extension is provided, append the extension.
65 // Otherwise, generate a filename based on the current time.
66 char *basename = NULL;
67 if (*filename) {
68 basename = (char*)malloc(strlen(*filename) + 1);
69 strcpy(basename, *filename);
70 free(*filename);
71 *filename = NULL;
72 } else {
73 time_t now = time(NULL);
74 basename = (char*)malloc(32);
75 strftime(basename, 31, "screenshot-%Y-%m-%d-%H-%M-%S", gmtime(&now));
76 }
77
78 // Ensure the filename is unique on disk.
79 char *unique_filename = (char*)malloc(strlen(basename) + strlen(fileext) + 7);
80 sprintf(unique_filename, "%s%s", basename, fileext);
81 int i;
82 for (i = 2; i < (1 << 16); i++) {
83 if (access(unique_filename, F_OK) == -1) {
84 *filename = unique_filename;
85 break;
86 }
87 sprintf(unique_filename, "%s-%d%s", basename, i, fileext);
88 }
89 if (!*filename) {
90 free(unique_filename);
91 }
92 free(basename);
93}
94
95static void print_usage(int argc, char **argv, int is_error)
96{
97 char *name = strrchr(argv[0], '/');
98 fprintf(is_error ? stderr : stdout, "Usage: %s [OPTIONS] [FILE]\n", (name ? name + 1: argv[0]));
99 fprintf(is_error ? stderr : stdout,
100 "\n"
101 "Gets a screenshot from a connected device.\n"
102 "\n"
103 "The image is in PNG format for iOS 9+ and otherwise in TIFF format.\n"
104 "The screenshot is saved as an image with the given FILE name.\n"
105 "If FILE has no extension, FILE will be a prefix of the saved filename.\n"
106 "If FILE is not specified, \"screenshot-DATE\", will be used as a prefix\n"
107 "of the filename, e.g.:\n"
108 " ./screenshot-2013-12-31-23-59-59.tiff\n"
109 "\n"
110 "NOTE: A mounted developer disk image is required on the device, otherwise\n"
111 "the screenshotr service is not available.\n"
112 "\n"
113 " -u, --udid UDID target specific device by UDID\n"
114 " -n, --network connect to network device\n"
115 " -d, --debug enable communication debugging\n"
116 " -h, --help prints usage information\n"
117 " -v, --version prints version information\n"
118 "\n"
119 "Homepage: <" PACKAGE_URL ">\n"
120 "Bug Reports: <" PACKAGE_BUGREPORT ">\n"
121 );
122}
44 123
45int main(int argc, char **argv) 124int main(int argc, char **argv)
46{ 125{
@@ -50,50 +129,58 @@ int main(int argc, char **argv)
50 screenshotr_client_t shotr = NULL; 129 screenshotr_client_t shotr = NULL;
51 lockdownd_service_descriptor_t service = NULL; 130 lockdownd_service_descriptor_t service = NULL;
52 int result = -1; 131 int result = -1;
53 int i;
54 const char *udid = NULL; 132 const char *udid = NULL;
55 int use_network = 0; 133 int use_network = 0;
56 char *filename = NULL; 134 char *filename = NULL;
135 int c = 0;
136 const struct option longopts[] = {
137 { "debug", no_argument, NULL, 'd' },
138 { "help", no_argument, NULL, 'h' },
139 { "udid", required_argument, NULL, 'u' },
140 { "network", no_argument, NULL, 'n' },
141 { "version", no_argument, NULL, 'v' },
142 { NULL, 0, NULL, 0}
143 };
57 144
58#ifndef WIN32 145#ifndef WIN32
59 signal(SIGPIPE, SIG_IGN); 146 signal(SIGPIPE, SIG_IGN);
60#endif 147#endif
61 /* parse cmdline args */ 148 /* parse cmdline args */
62 for (i = 1; i < argc; i++) { 149
63 if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { 150 /* parse cmdline arguments */
151 while ((c = getopt_long(argc, argv, "dhu:nv", longopts, NULL)) != -1) {
152 switch (c) {
153 case 'd':
64 idevice_set_debug_level(1); 154 idevice_set_debug_level(1);
65 continue; 155 break;
66 } 156 case 'u':
67 else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) { 157 if (!*optarg) {
68 i++; 158 fprintf(stderr, "ERROR: UDID argument must not be empty!\n");
69 if (!argv[i] || !*argv[i]) { 159 print_usage(argc, argv, 1);
70 print_usage(argc, argv); 160 return 2;
71 return 0;
72 } 161 }
73 udid = argv[i]; 162 udid = optarg;
74 continue; 163 break;
75 } 164 case 'n':
76 else if (!strcmp(argv[i], "-n") || !strcmp(argv[i], "--network")) {
77 use_network = 1; 165 use_network = 1;
78 continue; 166 break;
79 } 167 case 'h':
80 else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { 168 print_usage(argc, argv, 0);
81 print_usage(argc, argv);
82 return 0; 169 return 0;
83 } 170 case 'v':
84 else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) {
85 printf("%s %s\n", TOOL_NAME, PACKAGE_VERSION); 171 printf("%s %s\n", TOOL_NAME, PACKAGE_VERSION);
86 return 0; 172 return 0;
87 } 173 default:
88 else if (argv[i][0] != '-' && !filename) { 174 print_usage(argc, argv, 1);
89 filename = strdup(argv[i]); 175 return 2;
90 continue;
91 }
92 else {
93 print_usage(argc, argv);
94 return 0;
95 } 176 }
96 } 177 }
178 argc -= optind;
179 argv += optind;
180
181 if (argv[0]) {
182 filename = strdup(argv[0]);
183 }
97 184
98 if (IDEVICE_E_SUCCESS != idevice_new_with_options(&device, udid, (use_network) ? IDEVICE_LOOKUP_NETWORK : IDEVICE_LOOKUP_USBMUX)) { 185 if (IDEVICE_E_SUCCESS != idevice_new_with_options(&device, udid, (use_network) ? IDEVICE_LOOKUP_NETWORK : IDEVICE_LOOKUP_USBMUX)) {
99 if (udid) { 186 if (udid) {
@@ -153,84 +240,3 @@ int main(int argc, char **argv)
153 240
154 return result; 241 return result;
155} 242}
156
157void get_image_filename(char *imgdata, char **filename)
158{
159 // If the provided filename already has an extension, use it as is.
160 if (*filename) {
161 char *last_dot = strrchr(*filename, '.');
162 if (last_dot && !strchr(last_dot, '/')) {
163 return;
164 }
165 }
166
167 // Find the appropriate file extension for the filename.
168 const char *fileext = NULL;
169 if (memcmp(imgdata, "\x89PNG", 4) == 0) {
170 fileext = ".png";
171 } else if (memcmp(imgdata, "MM\x00*", 4) == 0) {
172 fileext = ".tiff";
173 } else {
174 printf("WARNING: screenshot data has unexpected image format.\n");
175 fileext = ".dat";
176 }
177
178 // If a filename without an extension is provided, append the extension.
179 // Otherwise, generate a filename based on the current time.
180 char *basename = NULL;
181 if (*filename) {
182 basename = (char*)malloc(strlen(*filename) + 1);
183 strcpy(basename, *filename);
184 free(*filename);
185 *filename = NULL;
186 } else {
187 time_t now = time(NULL);
188 basename = (char*)malloc(32);
189 strftime(basename, 31, "screenshot-%Y-%m-%d-%H-%M-%S", gmtime(&now));
190 }
191
192 // Ensure the filename is unique on disk.
193 char *unique_filename = (char*)malloc(strlen(basename) + strlen(fileext) + 7);
194 sprintf(unique_filename, "%s%s", basename, fileext);
195 int i;
196 for (i = 2; i < (1 << 16); i++) {
197 if (access(unique_filename, F_OK) == -1) {
198 *filename = unique_filename;
199 break;
200 }
201 sprintf(unique_filename, "%s-%d%s", basename, i, fileext);
202 }
203 if (!*filename) {
204 free(unique_filename);
205 }
206 free(basename);
207}
208
209void print_usage(int argc, char **argv)
210{
211 char *name = NULL;
212
213 name = strrchr(argv[0], '/');
214 printf("Usage: %s [OPTIONS] [FILE]\n", (name ? name + 1: argv[0]));
215 printf("\n");
216 printf("Gets a screenshot from a connected device.\n");
217 printf("\n");
218 printf("The image is in PNG format for iOS 9+ and otherwise in TIFF format.\n");
219 printf("The screenshot is saved as an image with the given FILE name.\n");
220 printf("If FILE has no extension, FILE will be a prefix of the saved filename.\n");
221 printf("If FILE is not specified, \"screenshot-DATE\", will be used as a prefix\n");
222 printf("of the filename, e.g.:\n");
223 printf(" ./screenshot-2013-12-31-23-59-59.tiff\n");
224 printf("\n");
225 printf("NOTE: A mounted developer disk image is required on the device, otherwise\n");
226 printf("the screenshotr service is not available.\n");
227 printf("\n");
228 printf(" -u, --udid UDID\ttarget specific device by UDID\n");
229 printf(" -n, --network\t\tconnect to network device\n");
230 printf(" -d, --debug\t\tenable communication debugging\n");
231 printf(" -h, --help\t\tprints usage information\n");
232 printf(" -v, --version\t\tprints version information\n");
233 printf("\n");
234 printf("Homepage: <" PACKAGE_URL ">\n");
235 printf("Bug Reports: <" PACKAGE_BUGREPORT ">\n");
236}