Esempio n. 1
0
static void SBA_refresh(void){
	// still valid
	if (springBoardAccessMessagePort && !CFMessagePortIsValid(springBoardAccessMessagePort)){
		CFRelease(springBoardAccessMessagePort);
		springBoardAccessMessagePort = NULL;
	}
	// create new one
	if (!springBoardAccessMessagePort) {
		springBoardAccessMessagePort = CFMessagePortCreateRemote(NULL, CFSTR(SBA_MessagePortName));
	}
}
static void __CFMessagePortDeallocate(CFTypeRef cf) {
    CFMessagePortRef ms = (CFMessagePortRef)cf;
    __CFMessagePortSetIsDeallocing(ms);
    CFMessagePortInvalidate(ms);
    // Delay cleanup of _replies until here so that invalidation during
    // SendRequest does not cause _replies to disappear out from under that function.
    if (NULL != ms->_replies) {
	CFRelease(ms->_replies);
    }
    if (NULL != ms->_name) {
	CFRelease(ms->_name);
    }
    if (NULL != ms->_port) {
	if (__CFMessagePortExtraMachRef(ms)) {
	    mach_port_mod_refs(mach_task_self(), CFMachPortGetPort(ms->_port), MACH_PORT_RIGHT_SEND, -1);
	    mach_port_mod_refs(mach_task_self(), CFMachPortGetPort(ms->_port), MACH_PORT_RIGHT_RECEIVE, -1);
	}
	CFMachPortInvalidate(ms->_port);
	CFRelease(ms->_port);
    }

    // A remote message port for a local message port in the same process will get the
    // same mach port, and the remote port will keep the mach port from being torn down,
    // thus keeping the remote port from getting any sort of death notification and
    // auto-invalidating; so we manually implement the 'auto-invalidation' here by
    // tickling each remote port to check its state after any message port is destroyed,
    // but most importantly after local message ports are destroyed.
    __CFLock(&__CFAllMessagePortsLock);
    CFMessagePortRef *remotePorts = NULL;
    CFIndex cnt = 0;
    if (NULL != __CFAllRemoteMessagePorts) {
	cnt = CFDictionaryGetCount(__CFAllRemoteMessagePorts);
	remotePorts = CFAllocatorAllocate(kCFAllocatorSystemDefault, cnt * sizeof(CFMessagePortRef), __kCFAllocatorGCScannedMemory);
	CFDictionaryGetKeysAndValues(__CFAllRemoteMessagePorts, NULL, (const void **)remotePorts);
	for (CFIndex idx = 0; idx < cnt; idx++) {
	    CFRetain(remotePorts[idx]);
	}
    }
    __CFUnlock(&__CFAllMessagePortsLock);
    if (remotePorts) {
	for (CFIndex idx = 0; idx < cnt; idx++) {
	    // as a side-effect, this will auto-invalidate the CFMessagePort if the CFMachPort is invalid
	    CFMessagePortIsValid(remotePorts[idx]);
	    CFRelease(remotePorts[idx]);
	}
	CFAllocatorDeallocate(kCFAllocatorSystemDefault, remotePorts);
    }
}
Esempio n. 3
0
SInt32 CFMessagePortSendRequest(CFMessagePortRef remote, SInt32 msgid, CFDataRef data, CFTimeInterval sendTimeout, CFTimeInterval rcvTimeout, CFStringRef replyMode, CFDataRef *returnDatap) {
    struct __CFMessagePortMachMessage *sendmsg;
    CFRunLoopRef currentRL = CFRunLoopGetCurrent();
    CFRunLoopSourceRef source = NULL;
    CFDataRef reply = NULL;
    int64_t termTSR;
    uint32_t sendOpts = 0, sendTimeOut = 0;
    int32_t desiredReply;
    Boolean didRegister = false;
    kern_return_t ret;

//#warning CF: This should be an assert
    // if (!__CFMessagePortIsRemote(remote)) return -999;
    if (!__CFMessagePortIsValid(remote)) return kCFMessagePortIsInvalid;
    __CFMessagePortLock(remote);
    if (NULL == remote->_replyPort) {
	CFMachPortContext context;
	context.version = 0;
	context.info = remote;
	context.retain = (const void *(*)(const void *))CFRetain;
	context.release = (void (*)(const void *))CFRelease;
	context.copyDescription = (CFStringRef (*)(const void *))__CFMessagePortCopyDescription;
	remote->_replyPort = CFMachPortCreate(CFGetAllocator(remote), __CFMessagePortReplyCallBack, &context, NULL);
    }
    remote->_convCounter++;
    desiredReply = -remote->_convCounter;
    CFDictionarySetValue(remote->_replies, (void *)desiredReply, NULL);
    sendmsg = __CFMessagePortCreateMessage(CFGetAllocator(remote), false, CFMachPortGetPort(remote->_port), (replyMode != NULL ? CFMachPortGetPort(remote->_replyPort) : MACH_PORT_NULL), -desiredReply, msgid, (data ? CFDataGetBytePtr(data) : NULL), (data ? CFDataGetLength(data) : 0));
    __CFMessagePortUnlock(remote);
    if (replyMode != NULL) {
        source = CFMachPortCreateRunLoopSource(CFGetAllocator(remote), remote->_replyPort, -100);
        didRegister = !CFRunLoopContainsSource(currentRL, source, replyMode);
	if (didRegister) {
            CFRunLoopAddSource(currentRL, source, replyMode);
	}
    }
    if (sendTimeout < 10.0*86400) {
	// anything more than 10 days is no timeout!
	sendOpts = MACH_SEND_TIMEOUT;
	sendTimeout *= 1000.0;
	if (sendTimeout < 1.0) sendTimeout = 0.0;
	sendTimeOut = floor(sendTimeout);
    }
    ret = mach_msg((mach_msg_header_t *)sendmsg, MACH_SEND_MSG|sendOpts, sendmsg->head.msgh_size, 0, MACH_PORT_NULL, sendTimeOut, MACH_PORT_NULL);
    CFAllocatorDeallocate(CFGetAllocator(remote), sendmsg);
    if (KERN_SUCCESS != ret) {
	if (didRegister) {
	    CFRunLoopRemoveSource(currentRL, source, replyMode);
	    CFRelease(source);
	}
	if (MACH_SEND_TIMED_OUT == ret) return kCFMessagePortSendTimeout;
	return kCFMessagePortTransportError;
    }
    if (replyMode == NULL) {
	return kCFMessagePortSuccess;
    }
    CFRetain(remote); // retain during run loop to avoid invalidation causing freeing
    _CFMachPortInstallNotifyPort(currentRL, replyMode);
    termTSR = mach_absolute_time() + __CFTimeIntervalToTSR(rcvTimeout);
    for (;;) {
	CFRunLoopRunInMode(replyMode, __CFTSRToTimeInterval(termTSR - mach_absolute_time()), true);
	// warning: what, if anything, should be done if remote is now invalid?
	reply = CFDictionaryGetValue(remote->_replies, (void *)desiredReply);
	if (NULL != reply || termTSR < (int64_t)mach_absolute_time()) {
	    break;
	}
	if (!CFMessagePortIsValid(remote)) {
	    // no reason that reply port alone should go invalid so we don't check for that
	    break;
	}
    }
    // Should we uninstall the notify port?  A complex question...
    if (didRegister) {
        CFRunLoopRemoveSource(currentRL, source, replyMode);
	CFRelease(source);
    }
    if (NULL == reply) {
	CFDictionaryRemoveValue(remote->_replies, (void *)desiredReply);
	CFRelease(remote);
	return CFMessagePortIsValid(remote) ? kCFMessagePortReceiveTimeout : -5;
    }
    if (NULL != returnDatap) {
	*returnDatap = ((void *)0xffffffff == reply) ? NULL : reply;
    } else if ((void *)0xffffffff != reply) {
	CFRelease(reply);
    }
    CFDictionaryRemoveValue(remote->_replies, (void *)desiredReply);
    CFRelease(remote);
    return kCFMessagePortSuccess;
}
Esempio n. 4
0
int main(int argc, char * argv[]) {
    signal(SIGINT, sigint_handler);

    bool israw = false;
    bool readstdin = false;
    char* code = NULL;
    bool usecolors = true;

    int ch;
    while ((ch = getopt(argc, argv, "nirc:t:sh")) != -1) {
        switch (ch) {
            case 'n': usecolors = false; break;
            case 'i': break;
            case 'r': israw = true; break;
            case 'c': code = optarg; break;
            case 't': recvTimeout = strtod(optarg, NULL); break;
            case 's': readstdin = true; break;
            case 'h': case '?': default:
                usage(argv[0]);
        }
    }

    if (optind != argc) usage(argv[0]);

    argc -= optind;
    argv += optind;

    CFMessagePortRef port = CFMessagePortCreateRemote(NULL, CFSTR("Hammerspoon"));

    if (!port) {
        fprintf(stderr, "error: can't access Hammerspoon; is it running with the ipc module loaded?\n");
        return 1;
    }

    CFMutableStringRef str = CFStringCreateMutable(NULL, 0);

    if (readstdin) {
        target_setprefix(str, israw);

        char buffer[BUFSIZ];
        while (fgets(buffer, BUFSIZ, stdin))
            CFStringAppendCString(str, buffer, kCFStringEncodingUTF8);

        if (ferror(stdin)) {
            perror("error reading from stdin.");
            exit(3);
        }

        target_send(port, str);
    }
    else if (code) {
        target_setprefix(str, israw);
        CFStringAppendCString(str, code, kCFStringEncodingUTF8);
        target_send(port, str);
    }
    else {
        if (usecolors)
            setupcolors();

        printf("%sHammerspoon interactive prompt.%s\n", COLOR_INITIAL, COLOR_RESET);

        while (1) {
            printf("\n%s", COLOR_INPUT);
            char* input = readline("> ");
            printf("%s", COLOR_RESET);
            if (!input) { printf("\n") ; exit(0); }
            add_history(input);

            if (!CFMessagePortIsValid(port)) {
                fprintf(stderr, "%sMessage port has become invalid.  Attempting to re-establish.%s\n", COLOR_INITIAL, COLOR_RESET);
                port = CFMessagePortCreateRemote(NULL, CFSTR("Hammerspoon"));
                if (!port) {
                    fprintf(stderr, "error: can't access Hammerspoon; is it running?\n");
                    exit(1);
                }

            }

            target_setprefix(str, israw);
            CFStringAppendCString(str, input, kCFStringEncodingUTF8);
            target_send(port, str);
            CFStringDelete(str, CFRangeMake(0, CFStringGetLength(str)));

            free(input);
        }
    }

    return 0;
}