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;  } | 
