Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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;

}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
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;
}
Ejemplo n.º 6
0
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);
}
Ejemplo n.º 7
0
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;
}