diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libusbmuxd.c | 173 |
1 files changed, 165 insertions, 8 deletions
diff --git a/src/libusbmuxd.c b/src/libusbmuxd.c index f7508c5..20f7aa1 100644 --- a/src/libusbmuxd.c +++ b/src/libusbmuxd.c @@ -20,16 +20,15 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif #include <stdint.h> #include <stdlib.h> #include <errno.h> #include <stdio.h> #include <string.h> -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - #ifdef WIN32 #define USBMUXD_API __declspec( dllexport ) #else @@ -60,6 +59,13 @@ #include <sys/socket.h> #include <arpa/inet.h> #include <pthread.h> +#ifdef _GNU_SOURCE +extern char *program_invocation_short_name; +#endif +#ifdef __APPLE__ +extern int _NSGetExecutablePath(char* buf, uint32_t* bufsize); +#include <sys/stat.h> +#endif #endif #ifdef HAVE_INOTIFY @@ -71,11 +77,12 @@ #endif /* HAVE_INOTIFY */ #include <plist/plist.h> -#define PLIST_BUNDLE_ID "org.libimobiledevice.usbmuxd" #define PLIST_CLIENT_VERSION_STRING "usbmuxd built for freedom" -#define PLIST_PROGNAME "libusbmuxd" #define PLIST_LIBUSBMUX_VERSION 3 +static char *bundle_id = NULL; +static char *prog_name = NULL; + // usbmuxd public interface #include "usbmuxd.h" // usbmuxd protocol @@ -406,13 +413,163 @@ static int send_plist_packet(int sfd, uint32_t tag, plist_t message) return res; } +static void get_bundle_id() +{ +#if defined (__APPLE__) + char CONTENTS_INFO_PLIST[] = "Contents/Info.plist"; + char* execpath = malloc(1024); + uint32_t size = 1024; + if (_NSGetExecutablePath(execpath, &size) != 0) { + free(execpath); + return; + } + // strip off executable name + char *p = execpath + strlen(execpath) - 1; + while (p > execpath && *p != '/') p--; + if (*p == '/') *p = '\0'; + // now walk back trying to find "/Contents/MacOS", and strip it off + int macos_found = 0; + while (p > execpath) { + p--; + if (*p != '/') continue; + if (strcmp(p, "/.") == 0) { + *p = '\0'; + } else if (!macos_found && strcmp(p, "/MacOS") == 0) { + *p = '\0'; + macos_found++; + } else if (macos_found && strcmp(p, "/Contents") == 0) { + *p = '\0'; + break; + } else { + break; + } + } + // now just append "/Contents/Info.plist" + size_t len = strlen(execpath) + sizeof(CONTENTS_INFO_PLIST) + 1; + char *infopl = malloc(len); + snprintf(infopl, len, "%s/%s", execpath, CONTENTS_INFO_PLIST); + free(execpath); + struct stat fst; + fst.st_size = 0; + if (stat(infopl, &fst) != 0) { + free(infopl); + return; + } + size_t fsize = fst.st_size; + if (fsize < 8) { + free(infopl); + return; + } + FILE *f = fopen(infopl, "r"); + free(infopl); + if (!f) + return; + char *buf = malloc(fsize); + if (!buf) + return; + if (fread(buf, 1, fsize, f) == fsize) { + plist_t pl = NULL; + if (memcmp(buf, "bplist00", 8) == 0) { + plist_from_bin(buf, fst.st_size, &pl); + } else { + plist_from_xml(buf, fst.st_size, &pl); + } + if (pl) { + plist_t bid = plist_dict_get_item(pl, "CFBundleIdentifier"); + if (plist_get_node_type(bid) == PLIST_STRING) { + plist_get_string_val(bid, &bundle_id); + } + plist_free(pl); + } + } + free(buf); + fclose(f); +#endif +} + +static void get_prog_name() +{ +#if defined(__APPLE__) || defined(__FreeBSD__) + const char *pname = getprogname(); + if (pname) { + prog_name = strdup(pname); + } +#elif defined (WIN32) + TCHAR *_pname = malloc((MAX_PATH+1) * sizeof(TCHAR)); + if (GetModuleFileName(NULL, _pname, MAX_PATH+1) > 0) { + char* pname = NULL; + #if defined(UNICODE) || defined(_UNICODE) + char* __pname = NULL; + int l = WideCharToMultiByte(CP_UTF8, 0, _pname, -1, NULL, 0, NULL, NULL); + if (l > 0) { + __pname = malloc(l); + if (WideCharToMultiByte(CP_UTF8, 0, _pname, -1, __pname, l, NULL, NULL) > 0) { + pname = __pname; + } + } + #else + pname = _pname; + #endif + if (pname) { + char *p = pname+strlen(pname)-1; + while (p > pname && *p != '\\' && *p != '/') p--; + if (*p == '\\' || *p == '/') p++; + prog_name = strdup(p); + } + #if defined(UNICODE) || defined(_UNICODE) + free(__pname); + #endif + } + free(_pname); +#elif defined (_GNU_SOURCE) + char *pname = program_invocation_short_name; + if (pname) { + prog_name = strdup(pname); + } +#elif defined (__linux__) + FILE *f = fopen("/proc/self/stat", "r"); + if (!f) { + return; + } + char *tmpbuf = malloc(512); + size_t r = fread(tmpbuf, 1, 512, f); + if (r > 0) { + char *p = tmpbuf; + while ((p-tmpbuf < r) && (*p != '(') && (*p != '\0')) p++; + if (*p == '(') { + p++; + char *pname = p; + while ((p-tmpbuf < r) && (*p != ')') && (*p != '\0')) p++; + if (*p == ')') { + *p = '\0'; + prog_name = strdup(pname); + } + } + } + free(tmpbuf); + fclose(f); +#else + #warning FIXME: no method to determine program name +#endif +} + static plist_t create_plist_message(const char* message_type) { + if (!bundle_id) { + get_bundle_id(); + } + if (!prog_name) { + get_prog_name(); + } plist_t plist = plist_new_dict(); - plist_dict_set_item(plist, "BundleID", plist_new_string(PLIST_BUNDLE_ID)); + if (bundle_id) { + plist_dict_set_item(plist, "BundleID", plist_new_string(bundle_id)); + } plist_dict_set_item(plist, "ClientVersionString", plist_new_string(PLIST_CLIENT_VERSION_STRING)); plist_dict_set_item(plist, "MessageType", plist_new_string(message_type)); - plist_dict_set_item(plist, "ProgName", plist_new_string(PLIST_PROGNAME)); + if (prog_name) { + plist_dict_set_item(plist, "ProgName", plist_new_string(prog_name)); + } plist_dict_set_item(plist, "kLibUSBMuxVersion", plist_new_uint(PLIST_LIBUSBMUX_VERSION)); return plist; } |