static CFStringRef pyStandardizePath(CFStringRef pyLocation) { CFRange foundRange; CFURLRef fmwkURL; CFURLRef locURL; CFStringRef subpath; static CFStringRef prefix = NULL; if (!prefix) prefix = py2app_CFSTR("@executable_path/"); foundRange = py2app_CFStringFind(pyLocation, prefix, 0); if (foundRange.location == kCFNotFound || foundRange.length == 0) { return NULL; } fmwkURL = py2app_CFBundleCopyPrivateFrameworksURL(CFBundleGetMainBundle()); foundRange.location = foundRange.length; foundRange.length = py2app_CFStringGetLength(pyLocation) - foundRange.length; subpath = py2app_CFStringCreateWithSubstring(NULL, pyLocation, foundRange); locURL = py2app_CFURLCreateWithFileSystemPathRelativeToBase( NULL, subpath, kCFURLPOSIXPathStyle, false, fmwkURL); py2app_CFRelease(subpath); py2app_CFRelease(fmwkURL); subpath = pathFromURL(locURL); py2app_CFRelease(locURL); return subpath; }
static void setResourcePath(void) { CFURLRef resDir; CFStringRef resPath; resDir = py2app_CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle()); resPath = pathFromURL(resDir); py2app_CFRelease(resDir); setcfenv("RESOURCEPATH", resPath); py2app_CFRelease(resPath); }
int main(int argc, char * *argv, char * const *envp) { int rval = 0; char exec_path[PATH_MAX+1]; char resolved_path[PATH_MAX+1]; uint32_t exec_path_size = sizeof(exec_path); CFStringRef argv0_string; CFURLRef argv0_url; char *argv0 = NULL; char *root = NULL; if (bind_CoreFoundation()) { fprintf(stderr, "CoreFoundation not found or functions missing\n"); return -1; } if (_NSGetExecutablePath(exec_path, &exec_path_size) != 0) { fprintf(stderr, "_NSGetExecutablePath failed to find current executable\n"); return -1; } exec_path[exec_path_size] = '\0'; realpath(exec_path, resolved_path); root = dirname(dirname(dirname(resolved_path))); argv0_url = py2app_CFURLCreateFromFileSystemRepresentation( NULL, (uint8_t *)root, strlen(root), true ); if (!argv0_url) { fprintf(stderr, "Could not cast '%s' to CFURL!\n", root); return -1; } py2app_main_bundle = py2app_CFBundleCreate(NULL, argv0_url); if (!py2app_main_bundle) { fprintf(stderr, "Not bundled, exiting\n"); return -1; } py2app_pool = py2app_CFArrayCreateMutable(NULL, 0, py2app_kCFTypeArrayCallBacks); if (!py2app_pool) { fprintf(stderr, "Couldn't create global pool\n"); return -1; } rval = py2app_main(argc, argv, envp); py2app_CFRelease(py2app_pool); py2app_CFRelease(py2app_main_bundle); py2app_CFRelease(argv0_url); // py2app_CFRelease(argv0_string); // free(argv0); return rval; }
static CFStringRef getMainScript(void) { CFMutableArrayRef possibleMains; CFBundleRef bndl; CFStringRef e_py, e_pyc, e_pyo, path; int i, cnt; possibleMains = py2app_CFArrayCreateMutable(NULL, 0, py2app_kCFTypeArrayCallBacks); CFArrayRef firstMains = py2app_getKey("PyMainFileNames"); if (firstMains) { CFRange rng; rng.location = 0; rng.length = py2app_CFArrayGetCount(firstMains); py2app_CFArrayAppendArray(possibleMains, firstMains, rng); } py2app_CFArrayAppendValue(possibleMains, py2app_CFSTR("__main__")); py2app_CFArrayAppendValue(possibleMains, py2app_CFSTR("__realmain__")); py2app_CFArrayAppendValue(possibleMains, py2app_CFSTR("Main")); e_py = py2app_CFSTR("py"); e_pyc = py2app_CFSTR("pyc"); e_pyo = py2app_CFSTR("pyo"); cnt = py2app_CFArrayGetCount(possibleMains); bndl = CFBundleGetMainBundle(); path = NULL; for (i = 0; i < cnt; i++) { CFStringRef base; CFURLRef resURL; base = py2app_CFArrayGetValueAtIndex(possibleMains, i); resURL = py2app_CFBundleCopyResourceURL(bndl, base, e_py, NULL); if (resURL == NULL) { resURL = py2app_CFBundleCopyResourceURL(bndl, base, e_pyc, NULL); } if (resURL == NULL) { resURL = py2app_CFBundleCopyResourceURL(bndl, base, e_pyo, NULL); } if (resURL != NULL) { path = pathFromURL(resURL); py2app_CFRelease(resURL); break; } } py2app_CFRelease(possibleMains); return path; }
static Boolean doesPathExist(CFStringRef path) { struct stat st; CFURLRef locURL; UInt8 buf[PATH_MAX]; locURL = py2app_CFURLCreateWithFileSystemPath( NULL, path, kCFURLPOSIXPathStyle, false); py2app_CFURLGetFileSystemRepresentation(locURL, true, buf, sizeof(buf)); py2app_CFRelease(locURL); return (stat((const char *)buf, &st) == -1 ? false : true); }
static CFStringRef tildeExpand(CFStringRef path) { CFURLRef pathURL; char buf[PATH_MAX]; CFURLRef fullPathURL; struct passwd *pwnam; char tmp; char *dir = NULL; py2app_CFStringGetCString(path, buf, sizeof(buf), kCFStringEncodingUTF8); int i; if (buf[0] != '~') { return py2app_CFStringCreateWithCString( NULL, buf, kCFStringEncodingUTF8); } /* user in path */ i = 1; while (buf[i] != '\0' && buf[i] != '/') { i++; } if (i == 1) { dir = getenv("HOME"); } else { tmp = buf[i]; buf[i] = '\0'; pwnam = getpwnam((const char *)&buf[1]); if (pwnam) dir = pwnam->pw_dir; buf[i] = tmp; } if (!dir) { return py2app_CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8); } pathURL = py2app_CFURLCreateFromFileSystemRepresentation( NULL, (const UInt8*)dir, strlen(dir), false); fullPathURL = py2app_CFURLCreateFromFileSystemRepresentationRelativeToBase( NULL, (const UInt8*)&buf[i + 1], strlen(&buf[i + 1]), false, pathURL); py2app_CFRelease(pathURL); path = pathFromURL(fullPathURL); py2app_CFRelease(fullPathURL); return path; }
static CFTypeRef py2app_getKey(const char *key) { CFTypeRef rval; CFStringRef cfKey = py2app_CFStringCreateWithCString(NULL, key, kCFStringEncodingUTF8); if (!cfKey) return NULL; rval = py2app_CFBundleGetValueForInfoDictionaryKey( CFBundleGetMainBundle(), cfKey); py2app_CFRelease(cfKey); return rval; }
static int report_linkEdit_error(void) { CFStringRef errString; const char *errorString; char* buf; errorString = dlerror(); fputs(errorString, stderr); errString = py2app_CFStringCreateWithFormat( NULL, NULL, py2app_CFSTR(ERR_LINKERRFMT), errorString); buf = alloca(py2app_CFStringGetMaximumSizeForEncoding( py2app_CFStringGetLength(errString), kCFStringEncodingUTF8)); py2app_CFStringGetCString(errString, buf, sizeof(buf), kCFStringEncodingUTF8); py2app_CFRelease(errString); return report_error(buf); }
static CFStringRef getErrorScript(void) { CFMutableArrayRef errorScripts; CFBundleRef bndl; CFStringRef path; int i, cnt; errorScripts = py2app_CFArrayCreateMutable(NULL, 0, py2app_kCFTypeArrayCallBacks); CFArrayRef firstErrorScripts = py2app_getKey("PyErrorScripts"); if (firstErrorScripts) { CFRange rng; rng.location = 0; rng.length = py2app_CFArrayGetCount(firstErrorScripts); py2app_CFArrayAppendArray(errorScripts, firstErrorScripts, rng); } py2app_CFArrayAppendValue(errorScripts, py2app_CFSTR("__error__")); py2app_CFArrayAppendValue(errorScripts, py2app_CFSTR("__error__.py")); py2app_CFArrayAppendValue(errorScripts, py2app_CFSTR("__error__.pyc")); py2app_CFArrayAppendValue(errorScripts, py2app_CFSTR("__error__.pyo")); py2app_CFArrayAppendValue(errorScripts, py2app_CFSTR("__error__.sh")); cnt = py2app_CFArrayGetCount(errorScripts); bndl = CFBundleGetMainBundle(); path = NULL; for (i = 0; i < cnt; i++) { CFStringRef base; CFURLRef resURL; base = py2app_CFArrayGetValueAtIndex(errorScripts, i); resURL = py2app_CFBundleCopyResourceURL(bndl, base, NULL, NULL); if (resURL) { path = pathFromURL(resURL); py2app_CFRelease(resURL); break; } } py2app_CFRelease(errorScripts); return path; }
static CFStringRef getPythonInterpreter(CFStringRef pyLocation) { CFBundleRef bndl; CFStringRef auxName; CFURLRef auxURL; CFStringRef path; auxName = py2app_getKey("PyExecutableName"); if (!auxName) auxName = py2app_CFSTR("python"); bndl = CFBundleGetMainBundle(); auxURL = py2app_CFBundleCopyAuxiliaryExecutableURL(bndl, auxName); if (auxURL) { path = pathFromURL(auxURL); py2app_CFRelease(auxURL); return path; } return NULL; }
static CFStringRef py2app_findPyLocation(CFArrayRef pyLocations) { CFIndex i; CFIndex cnt = py2app_CFArrayGetCount(pyLocations); for (i = 0; i < cnt; i++) { CFStringRef newLoc; CFStringRef pyLocation = py2app_CFArrayGetValueAtIndex(pyLocations, i); newLoc = pyStandardizePath(pyLocation); if (!newLoc) { newLoc = pyLocation; py2app_CFRetain(newLoc); } if (doesPathExist(newLoc)) { return newLoc; } if (newLoc) py2app_CFRelease(newLoc); } return NULL; }
static CFMutableArrayRef get_trimmed_lines(CFStringRef output) { CFMutableArrayRef lines; CFArrayRef tmp; CFRange rng; lines = py2app_CFArrayCreateMutable(NULL, 0, py2app_kCFTypeArrayCallBacks); tmp = py2app_CFStringCreateArrayBySeparatingStrings( NULL, output, py2app_CFSTR("\n")); rng.location = 0; rng.length = py2app_CFArrayGetCount(tmp); py2app_CFArrayAppendArray(lines, tmp, rng); while (true) { CFIndex cnt = py2app_CFArrayGetCount(lines); CFStringRef last; /* Nothing on stdout means pass silently */ if (cnt <= 0) { py2app_CFRelease(lines); return NULL; } last = py2app_CFArrayGetValueAtIndex(lines, cnt - 1); if (py2app_CFStringGetLength(last) > 0) break; py2app_CFArrayRemoveValueAtIndex(lines, cnt - 1); } return lines; }
static int py2app_main(int argc, char * const *argv, char * const *envp) { CFArrayRef pyLocations; CFStringRef pyLocation; CFStringRef mainScript; CFStringRef pythonInterpreter; char *resource_path; char buf[PATH_MAX]; char c_pythonInterpreter[PATH_MAX]; char c_mainScript[PATH_MAX]; char **argv_new; struct stat sb; void *py_dylib; int rval; FILE *mainScriptFile; char* curenv = NULL; char* curlocale = NULL; if (getenv("PYTHONOPTIMIZE") != NULL) { unsetenv("PYTHONOPTIMIZE"); } if (getenv("PYTHONDEBUG") != NULL) { unsetenv("PYTHONDEBUG"); } if (getenv("PYTHONDONTWRITEBYTECODE") != NULL) { unsetenv("PYTHONDONTWRITEBYTECODE"); } if (getenv("PYTHONIOENCODING") != NULL) { unsetenv("PYTHONIOENCODING"); } if (getenv("PYTHONDUMPREFS") != NULL) { unsetenv("PYTHONDUMPREFS"); } if (getenv("PYTHONMALLOCSTATS") != NULL) { unsetenv("PYTHONMALLOCSTATS"); } /* Ensure that the interpreter won't try to write bytecode files * Two reasons: * - Apps are often read-only for users * - Writing byte-code will be blocked by the sandbox * when running a sandboxed application. */ setenv("PYTHONDONTWRITEBYTECODE", "1", 1); #ifndef PY2APP_SECONDARY /* * Force stdout/stderr to be unbuffered, needed when using the ASL * output redirection because Python 3's IO library won't use * line buffering with that. */ setenv("PYTHONUNBUFFERED", "1", 1); #endif if (!py2app_getApplicationName()) return report_error(ERR_NONAME); pyLocations = (CFArrayRef)py2app_getKey("PyRuntimeLocations"); if (!pyLocations) return report_error(ERR_PYRUNTIMELOCATIONS); pyLocation = py2app_findPyLocation(pyLocations); if (!pyLocation) return report_error(ERR_NOPYTHONRUNTIME); setExecutablePath(); setResourcePath(); /* check for ':' in path, not compatible with Python due to Py_GetPath */ /* XXX: Could work-around by creating something in /tmp I guess */ resource_path = getenv("RESOURCEPATH"); if ((resource_path == NULL) || (strchr(resource_path, ':') != NULL)) { return report_error(ERR_COLONPATH); } py2app_setPythonPath(); setenv("ARGVZERO", argv[0], 1); /* Clear unwanted environment variable that could be set * by a PyObjC bundle in a parent process. Not clearing causes * problems in PyObjC. */ if (getenv("PYOBJC_BUNDLE_ADDRESS") != NULL) { unsetenv("PYOBJC_BUNDLE_ADDRESS"); } snprintf(buf, sizeof(buf)-1, "PYOBJC_BUNDLE_ADDRESS%ld", (long)getpid()); if (getenv(buf) != NULL) { unsetenv(buf); } mainScript = getMainScript(); if (!mainScript) return report_error(ERR_NOPYTHONSCRIPT); pythonInterpreter = getPythonInterpreter(pyLocation); py2app_CFStringGetCString( pythonInterpreter, c_pythonInterpreter, sizeof(c_pythonInterpreter), kCFStringEncodingUTF8); py2app_CFRelease(pythonInterpreter); if (lstat(c_pythonInterpreter, &sb) == 0) { if (!((sb.st_mode & S_IFLNK) == S_IFLNK)) { setenv("PYTHONHOME", resource_path, 1); } } py2app_CFStringGetCString(pyLocation, buf, sizeof(buf), kCFStringEncodingUTF8); py_dylib = dlopen(buf, RTLD_LAZY); if (!py_dylib) return report_linkEdit_error(); #define LOOKUP(NAME) \ NAME ## Ptr py2app_ ## NAME = (NAME ## Ptr)dlsym(py_dylib, #NAME); \ if (!py2app_ ## NAME) { \ return report_linkEdit_error(); \ } #define OPT_LOOKUP(NAME) \ NAME ## Ptr py2app_ ## NAME = (NAME ## Ptr)dlsym(py_dylib, #NAME); LOOKUP(Py_SetProgramName); LOOKUP(Py_Initialize); LOOKUP(PyRun_SimpleFile); LOOKUP(Py_Finalize); LOOKUP(PySys_GetObject); LOOKUP(PySys_SetArgv); LOOKUP(PyObject_GetAttrString); LOOKUP(Py_BuildValue); #if 0 OPT_LOOKUP(Py_SetPath); #endif OPT_LOOKUP(_Py_DecodeUTF8_surrogateescape); LOOKUP(PySys_SetObject); int isPy3K = dlsym(py_dylib, "PyBytes_FromString") != NULL; #undef OPT_LOOKUP #undef LOOKUP if (isPy3K) { /* * When apps are started from the Finder (or anywhere * except from the terminal), the LANG and LC_* variables * aren't set in the environment. This confuses Py_Initialize * when it tries to import the codec for UTF-8, * therefore explicitly set the locale. * * Also set the LC_CTYPE environment variable because Py_Initialize * resets the locale information using the environment :-( */ curlocale = setlocale(LC_ALL, NULL); if (curlocale != NULL) { curlocale = strdup(curlocale); if (curlocale == NULL) { (void)report_error("cannot save locale information"); return -1; } } setlocale(LC_ALL, "en_US.UTF-8"); curenv = getenv("LC_CTYPE"); if (curenv == NULL) { setenv("LC_CTYPE", "en_US.UTF-8", 1); } wchar_t w_pythonInterpreter[PATH_MAX+1]; mbstowcs(w_pythonInterpreter, c_pythonInterpreter, PATH_MAX+1); py2app_Py_SetProgramName((char*)w_pythonInterpreter); } else { py2app_Py_SetProgramName(c_pythonInterpreter); } py2app_Py_Initialize(); /* * Reset the environment and locale information */ if (isPy3K) { if (curenv == NULL) { unsetenv("LC_CTYPE"); } setlocale(LC_CTYPE, curlocale); free(curlocale); } py2app_CFStringGetCString( mainScript, c_mainScript, sizeof(c_mainScript), kCFStringEncodingUTF8); py2app_CFRelease(mainScript); if (isPy3K) { int i; argv_new = alloca((argc+1) * sizeof(wchar_t)); argv_new[argc] = NULL; argv_new[0] = (char*)py2app__Py_DecodeUTF8_surrogateescape(c_mainScript, strlen(c_mainScript)); for (i = 1; i < argc; i++) { argv_new[i] = (char*)py2app__Py_DecodeUTF8_surrogateescape(argv[i], strlen(argv[i])); } } else { argv_new = alloca((argc + 1) * sizeof(char *)); argv_new[argc] = NULL; argv_new[0] = c_mainScript; memcpy(&argv_new[1], &argv[1], (argc - 1) * sizeof(char *)); } py2app_PySys_SetArgv(argc, argv_new); mainScriptFile = fopen(c_mainScript, "r"); rval = py2app_PyRun_SimpleFile(mainScriptFile, c_mainScript); fclose(mainScriptFile); if (rval) { rval = report_script_error(ERR_PYTHONEXCEPTION); } py2app_Py_Finalize(); return rval; }
static int report_script_error(const char *msg) { CFStringRef errorScript; CFMutableArrayRef lines; CFRange foundRange; CFStringRef lastLine; CFStringRef output = NULL; CFIndex lineCount; CFURLRef buttonURL = NULL; CFStringRef buttonString = NULL; CFStringRef title = NULL; CFStringRef errmsg = NULL; id releasePool; int errBinding; int status = 0; errorScript = getErrorScript(); if (!errorScript) return report_error(msg); errBinding = bind_objc_Cocoa_ApplicationServices(); if (!errBinding) { id task, stdoutPipe, taskData; CFMutableArrayRef argv; releasePool = ((id(*)(id, SEL))py2app_objc_msgSend)( ((id(*)(id, SEL))py2app_objc_msgSend)( py2app_objc_getClass("NSAutoreleasePool"), py2app_sel_getUid("alloc")), py2app_sel_getUid("init")); task = ((id(*)(id, SEL))py2app_objc_msgSend)( ((id(*)(id, SEL))py2app_objc_msgSend)( py2app_objc_getClass("NSTask"), py2app_sel_getUid("alloc")), py2app_sel_getUid("init")); stdoutPipe = ((id(*)(id, SEL))py2app_objc_msgSend)(py2app_objc_getClass("NSPipe"), py2app_sel_getUid("pipe")); ((void(*)(id, SEL, id))py2app_objc_msgSend)(task, py2app_sel_getUid("setLaunchPath:"), py2app_CFSTR("/bin/sh")); ((void(*)(id, SEL, id))py2app_objc_msgSend)(task, py2app_sel_getUid("setStandardOutput:"), stdoutPipe); argv = py2app_CFArrayCreateMutable(NULL, 0, py2app_kCFTypeArrayCallBacks); py2app_CFArrayAppendValue(argv, errorScript); py2app_CFArrayAppendValue(argv, py2app_getApplicationName()); ((void(*)(id, SEL, id))py2app_objc_msgSend)(task, py2app_sel_getUid("setArguments:"), argv); /* This could throw, in theory, but /bin/sh should prevent that */ ((void(*)(id, SEL))py2app_objc_msgSend)(task, py2app_sel_getUid("launch")); ((void(*)(id, SEL))py2app_objc_msgSend)(task, py2app_sel_getUid("waitUntilExit")); taskData = ((id(*)(id, SEL))py2app_objc_msgSend)( ((id(*)(id, SEL))py2app_objc_msgSend)(stdoutPipe, py2app_sel_getUid("fileHandleForReading")), py2app_sel_getUid("readDataToEndOfFile")); py2app_CFRelease(argv); status = ((int(*)(id, SEL))py2app_objc_msgSend)(task, py2app_sel_getUid("terminationStatus")); py2app_CFRelease(task); if (!status && taskData) { output = py2app_CFStringCreateFromExternalRepresentation( NULL, taskData, kCFStringEncodingUTF8); } ((void(*)(id, SEL))py2app_objc_msgSend)(releasePool, py2app_sel_getUid("release")); } py2app_CFRelease(errorScript); if (status || !output) return report_error(msg); lines = get_trimmed_lines(output); py2app_CFRelease(output); /* Nothing on stdout means pass silently */ if (!lines) return -1; lineCount = py2app_CFArrayGetCount(lines); lastLine = py2app_CFArrayGetValueAtIndex(lines, lineCount - 1); foundRange = py2app_CFStringFind(lastLine, py2app_CFSTR("ERRORURL: "), 0); if (foundRange.location != kCFNotFound && foundRange.length != 0) { CFMutableArrayRef buttonArr; CFArrayRef tmp; CFRange rng; buttonArr = py2app_CFArrayCreateMutable(NULL, 0, py2app_kCFTypeArrayCallBacks); tmp = py2app_CFStringCreateArrayBySeparatingStrings( NULL, lastLine, py2app_CFSTR(" ")); lineCount -= 1; py2app_CFArrayRemoveValueAtIndex(lines, lineCount); rng.location = 1; rng.length = py2app_CFArrayGetCount(tmp) - 1; py2app_CFArrayAppendArray(buttonArr, tmp, rng); py2app_CFRelease(tmp); while (true) { CFStringRef tmpstr; if (py2app_CFArrayGetCount(buttonArr) <= 0) break; tmpstr = py2app_CFArrayGetValueAtIndex(buttonArr, 0); if (py2app_CFStringGetLength(tmpstr) == 0) { py2app_CFArrayRemoveValueAtIndex(buttonArr, 0); } else { break; } } buttonURL = py2app_CFURLCreateWithString( NULL, py2app_CFArrayGetValueAtIndex(buttonArr, 0), NULL); if (buttonURL) { py2app_CFArrayRemoveValueAtIndex(buttonArr, 0); while (true) { CFStringRef tmpstr; if (py2app_CFArrayGetCount(buttonArr) <= 0) break; tmpstr = py2app_CFArrayGetValueAtIndex(buttonArr, 0); if (py2app_CFStringGetLength(tmpstr) == 0) { py2app_CFArrayRemoveValueAtIndex(buttonArr, 0); } else { break; } } if (py2app_CFArrayGetCount(buttonArr) > 0) { buttonString = py2app_CFStringCreateByCombiningStrings( NULL, buttonArr, py2app_CFSTR(" ")); } if (!buttonString) buttonString = py2app_CFSTR(ERR_DEFAULTURLTITLE); } py2app_CFRelease(buttonArr); } if (lineCount <= 0 || errBinding) { py2app_CFRelease(lines); return report_error(msg); } releasePool = ((id(*)(id, SEL))py2app_objc_msgSend)( ((id(*)(id, SEL))py2app_objc_msgSend)( py2app_objc_getClass("NSAutoreleasePool"), py2app_sel_getUid("alloc")), py2app_sel_getUid("init")); title = py2app_CFArrayGetValueAtIndex(lines, 0); py2app_CFRetain(title); (void)AUTORELEASE(title); lineCount -= 1; py2app_CFArrayRemoveValueAtIndex(lines, lineCount); py2app_NSLog(py2app_CFSTR("%@"), title); if (lineCount > 0) { CFStringRef showerr; errmsg = py2app_CFStringCreateByCombiningStrings( NULL, lines, py2app_CFSTR("\r")); (void)AUTORELEASE(errmsg); showerr = ((id(*)(id, SEL, id))py2app_objc_msgSend)( ((id(*)(id, SEL, id))py2app_objc_msgSend)(errmsg, py2app_sel_getUid("componentsSeparatedByString:"), py2app_CFSTR("\r")), py2app_sel_getUid("componentsJoinedByString:"), py2app_CFSTR("\n")); py2app_NSLog(py2app_CFSTR("%@"), showerr); } else { errmsg = py2app_CFSTR(""); } ensureGUI(); if (!buttonURL) { int choice = py2app_NSRunAlertPanel( title, py2app_CFSTR("%@"), py2app_CFSTR(ERR_TERMINATE), py2app_CFSTR(ERR_CONSOLEAPPTITLE), NULL, errmsg); if (choice == NSAlertAlternateReturn) py2app_openConsole(); } else { int choice = py2app_NSRunAlertPanel( title, py2app_CFSTR("%@"), py2app_CFSTR(ERR_TERMINATE), buttonString, NULL, errmsg); if (choice == NSAlertAlternateReturn) { id ws = ((id(*)(id, SEL))py2app_objc_msgSend)(py2app_objc_getClass("NSWorkspace"), py2app_sel_getUid("sharedWorkspace")); ((void(*)(id, SEL, id))py2app_objc_msgSend)(ws, py2app_sel_getUid("openURL:"), buttonURL); } } ((void(*)(id, SEL))py2app_objc_msgSend)(releasePool, py2app_sel_getUid("release")); py2app_CFRelease(lines); return -1; }
static void py2app_setPythonPath(void) { CFMutableArrayRef paths; CFURLRef resDir; CFStringRef resPath; CFArrayRef resPackages; CFDictionaryRef options; paths = py2app_CFArrayCreateMutable(NULL, 0, py2app_kCFTypeArrayCallBacks); resDir = py2app_CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle()); resPath = pathFromURL(resDir); py2app_CFArrayAppendValue(paths, resPath); py2app_CFRelease(resPath); resPackages = py2app_getKey("PyResourcePackages"); if (resPackages) { int i; int cnt = py2app_CFArrayGetCount(resPackages); for (i = 0; i < cnt; i++) { resPath = tildeExpand(py2app_CFArrayGetValueAtIndex(resPackages, i)); if (py2app_CFStringGetLength(resPath)) { if (py2app_CFStringGetCharacterAtIndex(resPath, 0) != '/') { CFURLRef absURL = py2app_CFURLCreateWithString( NULL, resPath, resDir); py2app_CFRelease(resPath); resPath = pathFromURL(absURL); py2app_CFRelease(absURL); } py2app_CFArrayAppendValue(paths, resPath); } py2app_CFRelease(resPath); } } py2app_CFRelease(resDir); options = py2app_getKey("PyOptions"); if (options) { CFBooleanRef use_pythonpath; CFNumberRef optimize; use_pythonpath = py2app_CFDictionaryGetValue( options, py2app_CFSTR("use_pythonpath")); if (use_pythonpath && py2app_CFBooleanGetValue(use_pythonpath)) { char *ppath = getenv("PYTHONPATH"); if (ppath) { CFArrayRef oldPath; oldPath = py2app_CFStringCreateArrayBySeparatingStrings( NULL, py2app_CFSTR(ppath), py2app_CFSTR(":")); if (oldPath) { CFRange rng; rng.location = 0; rng.length = py2app_CFArrayGetCount(oldPath); py2app_CFArrayAppendArray(paths, oldPath, rng); py2app_CFRelease(oldPath); } } } optimize = py2app_CFDictionaryGetValue( options, py2app_CFSTR("optimize")); if (optimize) { int v = 0; char buf[32]; py2app_CFNumberGetValue(optimize, kCFNumberIntType, &v); snprintf(buf, 31, "%d", v); setenv("PYTHONOPTIMIZE", buf, 1); } } if (py2app_CFArrayGetCount(paths)) { resPath = py2app_CFStringCreateByCombiningStrings(NULL, paths, py2app_CFSTR(":")); setcfenv("PYTHONPATH", resPath); py2app_CFRelease(resPath); } else { if (getenv("PYTHONPATH") != NULL) { unsetenv("PYTHONPATH"); } } py2app_CFRelease(paths); }
int main(int argc, char * const *argv, char * const *envp) { int rval; #ifndef PY2APP_SECONDARY /* Running as a GUI app started by launch * services, try to redirect stdout/stderr * to ASL. * * NOTE: Detecting application bundles on OSX 10.9 * is annoyingly hard, the devnull trick is the least * worst option I've found yet. */ struct stat st; struct utsname uts; int is_app_bundle = 1; if (uname(&uts) != -1) { if (strcmp(uts.release, "13.") <= 0) { /* OSX 10.8 or earlier */ if (!have_psn_arg(argc, argv)) { is_app_bundle = 0; } } else { /* OSX 10.9 or later */ if (fstat(1, &st) != -1) { if (!S_ISCHR(st.st_mode) || major(st.st_dev) != 3 || minor(st.st_dev) != 2) { /* We appear to be launched from the * command-line after all. */ is_app_bundle = st.st_dev; } } } } if (is_app_bundle) { const char *bname; setenv("_PY2APP_LAUNCHED_", "1", 1); bname = strrchr(argv[0], '/'); if (bname == NULL) { bname = argv[0]; } else { bname++; } setup_asl(bname); } #endif /* !PY2APP_SECONDARY */ if (bind_CoreFoundation()) { fprintf(stderr, "CoreFoundation not found or functions missing\n"); return -1; } if (!CFBundleGetMainBundle()) { fprintf(stderr, "Not bundled, exiting\n"); return -1; } py2app_pool = py2app_CFArrayCreateMutable(NULL, 0, py2app_kCFTypeArrayCallBacks); if (!py2app_pool) { fprintf(stderr, "Couldn't create global pool\n"); return -1; } rval = py2app_main(argc, argv, envp); py2app_CFRelease(py2app_pool); return rval; }