int getSocketFromLaunchd() { // check-in launch_data_t checkinRequest = launch_data_new_string(LAUNCH_KEY_CHECKIN); launch_data_t checkinResponse = launch_msg(checkinRequest); if (!checkinResponse) { fprintf(stderr, "launch_msg(checkin_request) failed.\n"); return -1; } // test if check-in was successful launch_data_type_t responseType = launch_data_get_type(checkinResponse); if (responseType == LAUNCH_DATA_ERRNO) { errno = launch_data_get_errno(checkinResponse); fprintf(stderr, "Check-in with launchd failed, error %i.\n", errno); return -1; } else if (responseType != LAUNCH_DATA_DICTIONARY) { fprintf(stderr, "Unknown error, aborting."); return -1; } // get socket launch_data_t sockets = launch_data_dict_lookup(checkinResponse, LAUNCH_JOBKEY_SOCKETS); launch_data_t ipcSocket = launch_data_dict_lookup(sockets, "IPC"); launch_data_t socket = launch_data_array_get_index(ipcSocket, 0); int fd = launch_data_get_fd(socket); // we're done with launchd, free all resources launch_data_free(checkinRequest); launch_data_free(checkinResponse); return fd; }
static void GTMConvertCFDictEntryToLaunchDataDictEntry(const void *key, const void *value, void *context) { GTMCFToLDictContext *local_context = (GTMCFToLDictContext *)context; if (*(local_context->error)) return; launch_data_t launch_value = GTMLaunchDataCreateFromCFType(value, local_context->error); if (launch_value) { launch_data_t launch_key = GTMLaunchDataCreateFromCFType(key, local_context->error); if (launch_key) { bool goodInsert = launch_data_dict_insert(local_context->dict, launch_value, launch_data_get_string(launch_key)); if (!goodInsert) { *(local_context->error) = GTMCFLaunchCreateUnlocalizedError(EINVAL, CFSTR("launch_data_dict_insert " "failed key: %@ value: %@"), key, value); launch_data_free(launch_value); } launch_data_free(launch_key); } } }
static mach_port_t checkin(char *service_name) { kern_return_t kr = KERN_SUCCESS; mach_port_t port = MACH_PORT_NULL; launch_data_t msg = NULL, reply = NULL, datum = NULL; if (NULL == (msg = launch_data_new_string(LAUNCH_KEY_CHECKIN))) { helplog(ASL_LEVEL_ERR, "Could not create checkin message for launchd."); goto fin; } if (NULL == (reply = launch_msg(msg))) { helplog(ASL_LEVEL_ERR, "Could not message launchd."); goto fin; } if (LAUNCH_DATA_ERRNO == launch_data_get_type(reply)) { if (launch_data_get_errno(reply) == EACCES) { launch_data_free(msg); launch_data_free(reply); return(MACH_PORT_NULL); } helplog(ASL_LEVEL_ERR, "Launchd checkin failed: %s.", strerror(launch_data_get_errno(reply))); goto fin; } if (NULL == (datum = launch_data_dict_lookup(reply, LAUNCH_JOBKEY_MACHSERVICES)) || LAUNCH_DATA_DICTIONARY != launch_data_get_type(datum)) { helplog(ASL_LEVEL_ERR, "Launchd reply does not contain %s dictionary.", LAUNCH_JOBKEY_MACHSERVICES); goto fin; } if (NULL == (datum = launch_data_dict_lookup(datum, service_name)) || LAUNCH_DATA_MACHPORT != launch_data_get_type(datum)) { helplog(ASL_LEVEL_ERR, "Launchd reply does not contain %s Mach port.", service_name); goto fin; } if (MACH_PORT_NULL == (port = launch_data_get_machport(datum))) { helplog(ASL_LEVEL_ERR, "Launchd gave me a null Mach port."); goto fin; } if (KERN_SUCCESS != (kr = mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND))) { helplog(ASL_LEVEL_ERR, "mach_port_insert_right: %s", mach_error_string(kr)); goto fin; } fin: if (NULL != msg) launch_data_free(msg); if (NULL != reply) launch_data_free(reply); if (MACH_PORT_NULL == port) exit(EXIT_FAILURE); return port; }
CFDictionaryRef GTMSMCopyAllJobDictionaries(void) { CFDictionaryRef dict = NULL; launch_data_t msg = launch_data_new_string(LAUNCH_KEY_GETJOBS); launch_data_t resp = launch_msg(msg); launch_data_free(msg); CFErrorRef error = NULL; if (resp) { launch_data_type_t ldata_Type = launch_data_get_type(resp); if (ldata_Type == LAUNCH_DATA_DICTIONARY) { dict = GTMCFTypeCreateFromLaunchData(resp, true, &error); } else { error = GTMCFLaunchCreateUnlocalizedError(EINVAL, CFSTR("Unknown launchd type %d"), ldata_Type); } launch_data_free(resp); } else { error = GTMCFLaunchCreateUnlocalizedError(errno, CFSTR("")); } if (error) { #ifdef DEBUG CFShow(error); #endif // DEBUG CFRelease(error); } return dict; }
bool launch_data_dict_remove(launch_data_t dict, const char *key) { size_t i; for (i = 0; i < dict->_array_cnt; i += 2) { if (!strcmp(key, dict->_array[i]->string)) break; } if (i == dict->_array_cnt) return false; launch_data_free(dict->_array[i]); launch_data_free(dict->_array[i + 1]); memmove(dict->_array + i, dict->_array + i + 2, (dict->_array_cnt - (i + 2)) * sizeof(launch_data_t)); dict->_array_cnt -= 2; return true; }
CFDictionaryRef GTMSMJobCopyDictionary(CFStringRef jobLabel) { CFDictionaryRef dict = NULL; CFErrorRef error = NULL; launch_data_t resp = GTMPerformOnLabel(LAUNCH_KEY_GETJOB, jobLabel, &error); if (resp) { launch_data_type_t ldata_Type = launch_data_get_type(resp); if (ldata_Type == LAUNCH_DATA_DICTIONARY) { dict = GTMCFTypeCreateFromLaunchData(resp, true, &error); } else { error = GTMCFLaunchCreateUnlocalizedError(EINVAL, CFSTR("Unknown launchd type %d"), ldata_Type); } launch_data_free(resp); } if (error) { #ifdef DEBUG CFShow(error); #endif // DEBUG CFRelease(error); } return dict; }
void launch_data_free(launch_data_t d) { size_t i; switch (d->type) { case LAUNCH_DATA_DICTIONARY: case LAUNCH_DATA_ARRAY: for (i = 0; i < d->_array_cnt; i++) { if (d->_array[i]) { launch_data_free(d->_array[i]); } } free(d->_array); break; case LAUNCH_DATA_STRING: if (d->string) free(d->string); break; case LAUNCH_DATA_OPAQUE: if (d->opaque) free(d->opaque); break; default: break; } free(d); }
bool launchd_job_status(const char * job, LaunchJobStatus& info) { launch_data_t resp; launch_data_t msg; msg = launch_data_alloc(LAUNCH_DATA_DICTIONARY); if (msg == NULL) { throw std::runtime_error("out of memory"); } launch_data_dict_insert(msg, launch_data_new_string(job), LAUNCH_KEY_GETJOB); resp = launch_msg(msg); launch_data_free(msg); if (resp == NULL) { LAUNCHD_MSG_ERR(job, LAUNCH_KEY_GETJOB); return false; } switch (launch_data_get_type(resp)) { case LAUNCH_DATA_DICTIONARY: fill_job_info(resp, NULL, &info); launch_data_free(resp); return true; case LAUNCH_DATA_ERRNO: errno = launch_data_get_errno(resp); launch_data_free(resp); if (errno != 0) { LAUNCHD_MSG_ERR(job, LAUNCH_KEY_GETJOB); return false; } return true; default: LAUNCHD_MSG_ERRMSG(job, LAUNCH_KEY_GETJOB, "unexpected respose type %d", launch_data_get_type(resp)); launch_data_free(resp); return false; } }
static PyObject* wrap_launch_msg(PyObject* self, PyObject* args, PyObject* kwds) { static char* keywords[] = { "message", NULL }; launch_data_t to_send, to_receive; PyObject* message; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", keywords, &message)) { return NULL; } if (message == Py_None) { to_send = NULL; } else { to_send = python2launch(message); if (to_send == NULL) { return NULL; } } /* launch_msg returns NULL if no message has arrived or when there * was a problem sending. It only sets errno in the latter case. */ Py_BEGIN_ALLOW_THREADS errno = 0; to_receive = launch_msg(to_send); Py_END_ALLOW_THREADS if (to_send != NULL) { launch_data_free(to_send); to_send = NULL; } if (to_receive == NULL) { if (errno) { PyErr_SetFromErrno(PyExc_IOError); return NULL; } Py_INCREF(Py_None); return Py_None; } else { message = launch2python(to_receive); launch_data_free(to_receive); return message; } }
static int get_listener_socket_from_launchd(void) { launch_data_t req, resp, socks; req = launch_data_new_string(LAUNCH_KEY_CHECKIN); if (req == NULL) { w_log(W_LOG_ERR, "unable to create LAUNCH_KEY_CHECKIN\n"); return -1; } resp = launch_msg(req); launch_data_free(req); if (resp == NULL) { w_log(W_LOG_ERR, "launchd checkin failed %s\n", strerror(errno)); return -1; } if (launch_data_get_type(resp) == LAUNCH_DATA_ERRNO) { w_log(W_LOG_ERR, "launchd checkin failed: %s\n", strerror(launch_data_get_errno(resp))); launch_data_free(resp); return -1; } socks = launch_data_dict_lookup(resp, LAUNCH_JOBKEY_SOCKETS); if (socks == NULL) { w_log(W_LOG_ERR, "launchd didn't provide any sockets\n"); launch_data_free(resp); return -1; } // the "sock" name here is coupled with the plist in main.c socks = launch_data_dict_lookup(socks, "sock"); if (socks == NULL) { w_log(W_LOG_ERR, "launchd: \"sock\" wasn't present in Sockets\n"); launch_data_free(resp); return -1; } return launch_data_get_fd(launch_data_array_get_index(socks, 0)); }
CFDictionaryRef GTMSMJobCheckIn(CFErrorRef *error) { CFErrorRef local_error = NULL; CFDictionaryRef check_in_dict = NULL; launch_data_t msg = launch_data_new_string(LAUNCH_KEY_CHECKIN); launch_data_t resp = launch_msg(msg); launch_data_free(msg); if (resp) { launch_data_type_t resp_type = launch_data_get_type(resp); switch (resp_type) { case LAUNCH_DATA_DICTIONARY: check_in_dict = GTMCFTypeCreateFromLaunchData(resp, true, &local_error); break; case LAUNCH_DATA_ERRNO: { int e = launch_data_get_errno(resp); if (e) { local_error = GTMCFLaunchCreateUnlocalizedError(e, CFSTR("")); } break; } default: local_error = GTMCFLaunchCreateUnlocalizedError(EINVAL, CFSTR("unknown response from launchd %d"), resp_type); break; } launch_data_free(resp); } else { local_error = GTMCFLaunchCreateUnlocalizedError(errno, CFSTR("")); } if (error) { *error = local_error; } else if (local_error) { #ifdef DEBUG CFShow(local_error); #endif // DEBUG CFRelease(local_error); } return check_in_dict; }
bool launch_data_array_set_index(launch_data_t where, launch_data_t what, size_t ind) { if ((ind + 1) >= where->_array_cnt) { where->_array = realloc(where->_array, (ind + 1) * sizeof(launch_data_t)); memset(where->_array + where->_array_cnt, 0, (ind + 1 - where->_array_cnt) * sizeof(launch_data_t)); where->_array_cnt = ind + 1; } if (where->_array[ind]) launch_data_free(where->_array[ind]); where->_array[ind] = what; return true; }
bool launchd_checkin(unsigned * idle_timeout_secs) { launch_data_t msg; launch_data_t resp; launch_data_t item; bool is_launchd = true; msg = launch_data_new_string(LAUNCH_KEY_CHECKIN); resp = launch_msg(msg); if (resp == NULL) { /* IPC to launchd failed. */ LAUNCHD_MSG_ERR("checkin", LAUNCH_KEY_CHECKIN); launch_data_free(msg); return false; } if (launch_data_get_type(resp) == LAUNCH_DATA_ERRNO) { errno = launch_data_get_errno(resp); goto done; } /* At this point, we know we are running under launchd. */ is_launchd = true; if ((item = launch_data_dict_lookup(resp, LAUNCH_JOBKEY_TIMEOUT))) { long long val = launch_data_get_integer(item); *idle_timeout_secs = (val < 0) ? 0 : ((val > UINT_MAX) ? UINT_MAX : val); } done: launch_data_free(msg); launch_data_free(resp); return is_launchd; }
static launch_data_t GTMPerformOnLabel(const char *verb, CFStringRef jobLabel, CFErrorRef *error) { launch_data_t resp = NULL; launch_data_t label = GTMLaunchDataCreateFromCFType(jobLabel, error); if (*error == NULL) { launch_data_t msg = launch_data_alloc(LAUNCH_DATA_DICTIONARY); launch_data_dict_insert(msg, label, verb); resp = launch_msg(msg); launch_data_free(msg); if (!resp) { *error = GTMCFLaunchCreateUnlocalizedError(errno, CFSTR("")); } } return resp; }
/* * Register listening sockets with our run loop */ void socket_connection_launchd_register_fd_array(launch_data_t listening_fd_array){ int i; for (i = 0; i < launch_data_array_get_count(listening_fd_array); i++) { // get fd launch_data_t tempi = launch_data_array_get_index (listening_fd_array, i); int listening_fd = launch_data_get_fd(tempi); launch_data_free (tempi); log_info("file descriptor = %u\n", listening_fd); // create data_source_t for fd data_source_t *ds = malloc( sizeof(data_source_t)); if (ds == NULL) return; ds->process = socket_connection_accept; ds->fd = listening_fd; run_loop_add_data_source(ds); } }
Boolean GTMSMJobRemove(CFStringRef jobLabel, CFErrorRef *error) { CFErrorRef local_error = NULL; launch_data_t resp = GTMPerformOnLabel(LAUNCH_KEY_REMOVEJOB, jobLabel, &local_error); if (resp) { launch_data_type_t resp_type = launch_data_get_type(resp); switch (resp_type) { case LAUNCH_DATA_ERRNO: { int e = launch_data_get_errno(resp); // In OSX 10.10+, launch_msg(LAUNCH_KEY_REMOVEJOB, ...) returns the // error EINPROGRESS if the job was running at the time it was removed. // This should be considered a success as it was on earlier OS versions. if (e == EINPROGRESS && IsOsYosemiteOrGreater()) { break; } if (e) { local_error = GTMCFLaunchCreateUnlocalizedError(e, CFSTR("")); } break; } default: local_error = GTMCFLaunchCreateUnlocalizedError(EINVAL, CFSTR("unknown response from launchd %d"), resp_type); break; } launch_data_free(resp); } if (error) { *error = local_error; } else if (local_error) { #ifdef DEBUG CFShow(local_error); #endif // DEBUG CFRelease(local_error); } return local_error == NULL; }
int listen_to_launchd_sockets() { //check-in with launchd launch_data_t checkin_message = launch_data_new_string(LAUNCH_KEY_CHECKIN); if (checkin_message == NULL) { exit_error("couldn't create launchd checkin message", errno); } launch_data_t checkin_result = launch_msg(checkin_message); if (checkin_result == NULL) { exit_error("couldn't check in with launchd", errno); } if (launch_data_get_type(checkin_result) == LAUNCH_DATA_ERRNO) { exit_error("error on launchd checkin",launch_data_get_errno(checkin_result)); return EX_OSERR; } launch_data_t socket_info = launch_data_dict_lookup(checkin_result, LAUNCH_JOBKEY_SOCKETS); if (socket_info == NULL) { exit_error("couldn't find socket information", 0); } launch_data_t listening_sockets = launch_data_dict_lookup(socket_info, "Listener"); if (listening_sockets == NULL) { exit_error("couldn't find my socket", 0); } //set up a kevent for our socket int kernel_queue = kqueue(); if (kernel_queue == -1) { exit_error("couldn't create kernel queue", errno); } for (int i = 0; i < launch_data_array_get_count(listening_sockets); i++) { launch_data_t this_socket = launch_data_array_get_index(listening_sockets, i); struct kevent kev_init; EV_SET(&kev_init, launch_data_get_fd(this_socket), EVFILT_READ, EV_ADD, 0, 0, NULL); if (kevent(kernel_queue, &kev_init, 1, NULL, 0, NULL) == -1) { exit_error("couldn't create kernel event", errno); } } launch_data_free(checkin_result); return kernel_queue; }
CFDictionaryRef GTMCopyLaunchdExports(void) { launch_data_t resp; CFDictionaryRef dict = NULL; vproc_err_t err = vproc_swap_complex(NULL, VPROC_GSK_ENVIRONMENT_10_5, NULL, &resp); if (err) { err = vproc_swap_complex(NULL, VPROC_GSK_ENVIRONMENT_10_6, NULL, &resp); } if (err == NULL) { CFErrorRef error = NULL; dict = GTMCFTypeCreateFromLaunchData(resp, false, &error); if (error) { #ifdef DEBUG CFShow(error); #endif // DEBUG CFRelease(error); } launch_data_free(resp); } return dict; }
Boolean GTMSMJobRemove(CFStringRef jobLabel, CFErrorRef *error) { CFErrorRef local_error = NULL; launch_data_t resp = GTMPerformOnLabel(LAUNCH_KEY_REMOVEJOB, jobLabel, &local_error); if (resp) { launch_data_type_t resp_type = launch_data_get_type(resp); switch (resp_type) { case LAUNCH_DATA_ERRNO: { int e = launch_data_get_errno(resp); if (e) { local_error = GTMCFLaunchCreateUnlocalizedError(e, CFSTR("")); } break; } default: local_error = GTMCFLaunchCreateUnlocalizedError(EINVAL, CFSTR("unknown response from launchd %d"), resp_type); break; } launch_data_free(resp); } else { local_error = GTMCFLaunchCreateUnlocalizedError(errno, CFSTR("")); } if (error) { *error = local_error; } else if (local_error) { #ifdef DEBUG CFShow(local_error); #endif // DEBUG CFRelease(local_error); } return local_error == NULL; }
int main(int argc, char *argv[]) { auto request(launch_data_new_string(LAUNCH_KEY_GETJOBS)); auto response(launch_msg(request)); launch_data_free(request); _assert(response != NULL); _assert(launch_data_get_type(response) == LAUNCH_DATA_DICTIONARY); auto parent(getppid()); auto cydia(false); launch_data_dict_iterate(response, [=, &cydia](const char *name, launch_data_t value) { if (launch_data_get_type(response) != LAUNCH_DATA_DICTIONARY) return; auto integer(launch_data_dict_lookup(value, LAUNCH_JOBKEY_PID)); if (integer == NULL || launch_data_get_type(integer) != LAUNCH_DATA_INTEGER) return; auto pid(launch_data_get_integer(integer)); if (pid != parent) return; auto variables(launch_data_dict_lookup(value, LAUNCH_JOBKEY_ENVIRONMENTVARIABLES)); if (variables != NULL && launch_data_get_type(variables) == LAUNCH_DATA_DICTIONARY) { auto dyld(false); launch_data_dict_iterate(variables, [&dyld](const char *name, launch_data_t value) { if (strncmp(name, "DYLD_", 5) == 0) dyld = true; }); if (dyld) return; } auto string(launch_data_dict_lookup(value, LAUNCH_JOBKEY_PROGRAM)); if (string == NULL || launch_data_get_type(string) != LAUNCH_DATA_STRING) { auto array(launch_data_dict_lookup(value, LAUNCH_JOBKEY_PROGRAMARGUMENTS)); if (array == NULL || launch_data_get_type(array) != LAUNCH_DATA_ARRAY) return; if (launch_data_array_get_count(array) == 0) return; string = launch_data_array_get_index(array, 0); if (string == NULL || launch_data_get_type(string) != LAUNCH_DATA_STRING) return; } auto program(launch_data_get_string(string)); if (program == NULL) return; if (strcmp(program, "/Applications/Cydia.app/Cydia") == 0) cydia = true; }); if (!cydia) { fprintf(stderr, "thou shalt not pass\n"); return EX_NOPERM; } setuid(0); setgid(0); if (argc < 2 || argv[1][0] != '/') argv[0] = "/usr/bin/dpkg"; else { --argc; ++argv; } execv(argv[0], argv); return EX_UNAVAILABLE; }
/*! iSCSI daemon entry point. */ int main(void) { // Connect to the preferences .plist file associated with "iscsid" and // read configuration parameters for the initiator iSCSIPLSynchronize(); CFStringRef initiatorIQN = iSCSIPLCopyInitiatorIQN(); if(initiatorIQN) { iSCSISetInitiatiorName(initiatorIQN); CFRelease(initiatorIQN); } CFStringRef initiatorAlias = iSCSIPLCopyInitiatorAlias(); if(initiatorAlias) { iSCSISetInitiatiorName(initiatorAlias); CFRelease(initiatorAlias); } // Register with launchd so it can manage this daemon launch_data_t reg_request = launch_data_new_string(LAUNCH_KEY_CHECKIN); // Quit if we are unable to checkin... if(!reg_request) { fprintf(stderr,"Failed to checkin with launchd.\n"); goto ERROR_LAUNCH_DATA; } launch_data_t reg_response = launch_msg(reg_request); // Ensure registration was successful if((launch_data_get_type(reg_response) == LAUNCH_DATA_ERRNO)) { fprintf(stderr,"Failed to checkin with launchd.\n"); goto ERROR_NO_SOCKETS; } // Grab label and socket dictionary from daemon's property list launch_data_t label = launch_data_dict_lookup(reg_response,LAUNCH_JOBKEY_LABEL); launch_data_t sockets = launch_data_dict_lookup(reg_response,LAUNCH_JOBKEY_SOCKETS); if(!label || !sockets) { fprintf(stderr,"Could not find socket "); goto ERROR_NO_SOCKETS; } launch_data_t listen_socket_array = launch_data_dict_lookup(sockets,"iscsid"); if(!listen_socket_array || launch_data_array_get_count(listen_socket_array) == 0) goto ERROR_NO_SOCKETS; // Grab handle to socket we want to listen on... launch_data_t listen_socket = launch_data_array_get_index(listen_socket_array,0); if(!iSCSIDRegisterForPowerEvents()) goto ERROR_PWR_MGMT_FAIL; // Create a socket that will CFSocketRef socket = CFSocketCreateWithNative(kCFAllocatorDefault, launch_data_get_fd(listen_socket), kCFSocketReadCallBack, iSCSIDProcessIncomingRequest,0); // Runloop sources associated with socket events of connected clients CFRunLoopSourceRef clientSockSource = CFSocketCreateRunLoopSource(kCFAllocatorDefault,socket,0); CFRunLoopAddSource(CFRunLoopGetMain(),clientSockSource,kCFRunLoopDefaultMode); CFRunLoopRun(); // Deregister for power iSCSIDDeregisterForPowerEvents(); launch_data_free(reg_response); return 0; // TODO: verify that launch data is freed under all possible execution paths ERROR_PWR_MGMT_FAIL: ERROR_NO_SOCKETS: launch_data_free(reg_response); ERROR_LAUNCH_DATA: return ENOTSUP; }
static launch_data_t python2launch(PyObject* object) { launch_data_t result; if (PyDict_Check(object)) { /* PyMapping_Check doesn't work because a lot of sequence types * are mappings as wel to support extended slices a[i:j:k] */ return pythondict2launch(object); } else if (PySequence_Check(object)) { return pythonarray2launch(object); } else if (PyInt_Check(object)) { long value = PyInt_AsLong(object); result = launch_data_alloc(LAUNCH_DATA_INTEGER); if (result == NULL) { PyErr_SetString(PyExc_TypeError, "allocating launch_data_t failed"); return NULL; } if (!launch_data_set_integer(result, value)) { PyErr_SetString(PyExc_TypeError, "setting launch_data_t failed"); launch_data_free(result); return NULL; } } else if (PyLong_Check(object)) { long long value = PyLong_AsLongLong(object); result = launch_data_alloc(LAUNCH_DATA_INTEGER); if (result == NULL) { PyErr_SetString(PyExc_TypeError, "allocating launch_data_t failed"); return NULL; } if (!launch_data_set_integer(result, value)) { PyErr_SetString(PyExc_TypeError, "setting launch_data_t failed"); launch_data_free(result); return NULL; } } else if (PyString_Check(object)) { char* value = PyString_AsString(object); result = launch_data_alloc(LAUNCH_DATA_STRING); if (result == NULL) { PyErr_SetString(PyExc_TypeError, "allocating launch_data_t failed"); return NULL; } if (!launch_data_set_string(result, value)) { PyErr_SetString(PyExc_TypeError, "setting launch_data_t failed"); launch_data_free(result); return NULL; } } else if ((PyObject*)(object->ob_type) == file_descriptor_type) { long value = PyInt_AsLong(object); result = launch_data_alloc(LAUNCH_DATA_FD); if (result == NULL) { PyErr_SetString(PyExc_TypeError, "allocating launch_data_t failed"); return NULL; } if (!launch_data_set_fd(result, value)) { PyErr_SetString(PyExc_TypeError, "setting launch_data_t failed"); launch_data_free(result); return NULL; } } else if ((PyObject*)(object->ob_type) == errno_type) { long value = PyInt_AsLong(object); result = launch_data_alloc(LAUNCH_DATA_ERRNO); if (result == NULL) { PyErr_SetString(PyExc_TypeError, "allocating launch_data_t failed"); return NULL; } if (!launch_data_set_errno(result, value)) { PyErr_SetString(PyExc_TypeError, "setting launch_data_t failed"); launch_data_free(result); return NULL; } } else if (object->ob_type->tp_as_buffer != NULL) { PyBufferProcs* bp = object->ob_type->tp_as_buffer; void* ptr; size_t size; size = bp->bf_getreadbuffer(object, 0, &ptr); if (size == (size_t)-1) { return NULL; } result = launch_data_alloc(LAUNCH_DATA_OPAQUE); if (result == NULL) { PyErr_SetString(PyExc_TypeError, "allocating launch_data_t failed"); return NULL; } if (!launch_data_set_opaque(result, ptr, size)) { PyErr_SetString(PyExc_TypeError, "setting launch_data_t failed"); launch_data_free(result); return NULL; } } else { PyErr_Format(PyExc_TypeError, "Don't know how to convert object of type %s to launch", object->ob_type->tp_name); return NULL; } }
/* Get the Mach port upon which we'll receive requests from our parent */ static mach_port_t get_hex_fiend_receive_port(void) { mach_port_t launchdReceivePort = MACH_PORT_NULL, hexFiendReceivePort = MACH_PORT_NULL; launch_data_t resp = NULL, machServices = NULL, msg = NULL, service = NULL; int err = 0; /* Check in with launchd */ msg = launch_data_new_string(LAUNCH_KEY_CHECKIN); resp = launch_msg(msg); if (resp == NULL) { if (ERR_FILE) fprintf(ERR_FILE, "launch_msg(): %s\n", strerror(errno)); exit(EXIT_FAILURE); } /* Guard against errors */ if (launch_data_get_type(resp) == LAUNCH_DATA_ERRNO) { errno = launch_data_get_errno(resp); if (ERR_FILE) fprintf(ERR_FILE, "launch_msg() response: %s\n", strerror(errno)); exit(EXIT_FAILURE); } /* Get our MachServices dictioanry */ machServices = launch_data_dict_lookup(resp, LAUNCH_JOBKEY_MACHSERVICES); /* Die if it's not there */ if (machServices == NULL) { if (ERR_FILE) fprintf(ERR_FILE, "No mach services found!\n"); exit(EXIT_FAILURE); } /* Get the one we care about */ service = launch_data_dict_lookup(machServices, kPrivilegedHelperLaunchdLabel); if (service == NULL) { if (ERR_FILE) fprintf(ERR_FILE, "Mach service %s not found!\n", kPrivilegedHelperLaunchdLabel); exit(EXIT_FAILURE); } /* Make sure we've got a mach port */ if (launch_data_get_type(service) != LAUNCH_DATA_MACHPORT) { if (ERR_FILE) fprintf(ERR_FILE, "%s: not a mach port\n", kPrivilegedHelperLaunchdLabel); exit(EXIT_FAILURE); } /* Now get the launchd mach port */ launchdReceivePort = launch_data_get_machport(service); /* We don't want to use launchd's port - we want one from Hex Fiend (so we can get a no senders notification). So receive a port from Hex Fiend on our launchd port. */ hexFiendReceivePort = MACH_PORT_NULL; if ((err = recv_port(launchdReceivePort, &hexFiendReceivePort))) { if (ERR_FILE) fprintf(ERR_FILE, "recv_port() failed with Mach error %d\n", err); exit(EXIT_FAILURE); } /* Make sure we got something back */ if (hexFiendReceivePort == MACH_PORT_NULL) { if (ERR_FILE) fprintf(ERR_FILE, "recv_port() returned a null Mach port\n"); exit(EXIT_FAILURE); } /* Clean up */ if (msg) launch_data_free(msg); if (resp) launch_data_free(resp); return hexFiendReceivePort; }
static void launchd_checkin(void) { size_t i, /* Looping var */ count; /* Number of listeners */ launch_data_t ld_msg, /* Launch data message */ ld_resp, /* Launch data response */ ld_array, /* Launch data array */ ld_sockets, /* Launch data sockets dictionary */ tmp; /* Launch data */ cupsd_listener_t *lis; /* Listeners array */ http_addr_t addr; /* Address variable */ socklen_t addrlen; /* Length of address */ int fd; /* File descriptor */ char s[256]; /* String addresss */ cupsdLogMessage(CUPSD_LOG_DEBUG, "launchd_checkin: pid=%d", (int)getpid()); /* * Check-in with launchd... */ ld_msg = launch_data_new_string(LAUNCH_KEY_CHECKIN); if ((ld_resp = launch_msg(ld_msg)) == NULL) { cupsdLogMessage(CUPSD_LOG_ERROR, "launchd_checkin: launch_msg(\"" LAUNCH_KEY_CHECKIN "\") IPC failure"); exit(EXIT_FAILURE); return; /* anti-compiler-warning */ } if (launch_data_get_type(ld_resp) == LAUNCH_DATA_ERRNO) { errno = launch_data_get_errno(ld_resp); cupsdLogMessage(CUPSD_LOG_ERROR, "launchd_checkin: Check-in failed: %s", strerror(errno)); exit(EXIT_FAILURE); return; /* anti-compiler-warning */ } /* * Get the sockets dictionary... */ if ((ld_sockets = launch_data_dict_lookup(ld_resp, LAUNCH_JOBKEY_SOCKETS)) == NULL) { cupsdLogMessage(CUPSD_LOG_ERROR, "launchd_checkin: No sockets found to answer requests on!"); exit(EXIT_FAILURE); return; /* anti-compiler-warning */ } /* * Get the array of listener sockets... */ if ((ld_array = launch_data_dict_lookup(ld_sockets, "Listeners")) == NULL) { cupsdLogMessage(CUPSD_LOG_ERROR, "launchd_checkin: No sockets found to answer requests on!"); exit(EXIT_FAILURE); return; /* anti-compiler-warning */ } /* * Add listening fd(s) to the Listener array... */ if (launch_data_get_type(ld_array) == LAUNCH_DATA_ARRAY) { count = launch_data_array_get_count(ld_array); for (i = 0; i < count; i ++) { /* * Get the launchd file descriptor and address... */ if ((tmp = launch_data_array_get_index(ld_array, i)) != NULL) { fd = launch_data_get_fd(tmp); addrlen = sizeof(addr); if (getsockname(fd, (struct sockaddr *)&addr, &addrlen)) { cupsdLogMessage(CUPSD_LOG_ERROR, "launchd_checkin: Unable to get local address - %s", strerror(errno)); continue; } /* * Try to match the launchd socket address to one of the listeners... */ for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners); lis; lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) if (httpAddrEqual(&lis->address, &addr)) break; /* * Add a new listener If there's no match... */ if (lis) { cupsdLogMessage(CUPSD_LOG_DEBUG, "launchd_checkin: Matched existing listener %s with fd %d...", httpAddrString(&(lis->address), s, sizeof(s)), fd); } else { cupsdLogMessage(CUPSD_LOG_DEBUG, "launchd_checkin: Adding new listener %s with fd %d...", httpAddrString(&addr, s, sizeof(s)), fd); if ((lis = calloc(1, sizeof(cupsd_listener_t))) == NULL) { cupsdLogMessage(CUPSD_LOG_ERROR, "launchd_checkin: Unable to allocate listener - " "%s.", strerror(errno)); exit(EXIT_FAILURE); } cupsArrayAdd(Listeners, lis); memcpy(&lis->address, &addr, sizeof(lis->address)); } lis->fd = fd; # ifdef HAVE_SSL if (_httpAddrPort(&(lis->address)) == 443) lis->encryption = HTTP_ENCRYPT_ALWAYS; # endif /* HAVE_SSL */ } } } launch_data_free(ld_msg); launch_data_free(ld_resp); }
int checklaunchd() { launch_data_t checkin_response = NULL; #ifdef LION_TEST launch_data_t checkin_request = NULL; #endif launch_data_t sockets_dict, listening_fd_array; launch_data_t listening_fd; struct sockaddr_storage fdsockaddr; socklen_t fdsockaddrlen = sizeof(fdsockaddr); int socketct; int i; int listenerct; int returnval = 0; int fd; /* check in with launchd */ #ifdef LION_TEST if ((checkin_request = launch_data_new_string(LAUNCH_KEY_CHECKIN)) == NULL) { #else if ((checkin_response = launch_socket_service_check_in()) == NULL) { #endif plog(ASL_LEVEL_ERR, "failed to launch_socket_service_check_in.\n"); goto done; } #ifdef LION_TEST if ((checkin_response = launch_msg(checkin_request)) == NULL) { plog(ASL_LEVEL_ERR, "failed to launch_msg.\n"); goto done; } #endif if (LAUNCH_DATA_ERRNO == launch_data_get_type(checkin_response)) { plog(ASL_LEVEL_ERR, "launch_data_get_type error %d\n", launch_data_get_errno(checkin_response)); goto done; } if ( (sockets_dict = launch_data_dict_lookup(checkin_response, LAUNCH_JOBKEY_SOCKETS)) == NULL){ plog(ASL_LEVEL_ERR, "failed to launch_data_dict_lookup.\n"); goto done; } if ( !(socketct = launch_data_dict_get_count(sockets_dict))){ plog(ASL_LEVEL_ERR, "launch_data_dict_get_count returns no socket defined.\n"); goto done; } if ( (listening_fd_array = launch_data_dict_lookup(sockets_dict, "Listeners")) == NULL ){ plog(ASL_LEVEL_ERR, "failed to launch_data_dict_lookup.\n"); goto done; } listenerct = launch_data_array_get_count(listening_fd_array); for (i = 0; i < listenerct; i++) { listening_fd = launch_data_array_get_index(listening_fd_array, i); fd = launch_data_get_fd( listening_fd ); if ( getsockname( fd , (struct sockaddr *)&fdsockaddr, &fdsockaddrlen)){ continue; } /* Is this the VPN control socket? */ if ( fdsockaddr.ss_family == AF_UNIX && (!(strcmp(vpncontrolsock_path, ((struct sockaddr_un *)&fdsockaddr)->sun_path)))) { plog(ASL_LEVEL_INFO, "found launchd socket.\n"); returnval = fd; break; } } // TODO: check if we have any leaked fd if ( listenerct == i){ plog(ASL_LEVEL_ERR, "failed to find launchd socket\n"); returnval = 0; } done: if (checkin_response) launch_data_free(checkin_response); return(returnval); } void vpncontrol_handler(void *unused) { struct sockaddr_storage from; socklen_t fromlen = sizeof(from); int sock; struct vpnctl_socket_elem *sock_elem; sock_elem = racoon_malloc(sizeof(struct vpnctl_socket_elem)); if (sock_elem == NULL) { plog(ASL_LEVEL_ERR, "memory error: %s\n", strerror(errno)); return; //%%%%%% terminate } LIST_INIT(&sock_elem->bound_addresses); sock_elem->sock = accept(lcconf->sock_vpncontrol, (struct sockaddr *)&from, &fromlen); if (sock_elem->sock < 0) { plog(ASL_LEVEL_ERR, "failed to accept vpn_control command: %s\n", strerror(errno)); racoon_free(sock_elem); return; //%%%%% terminate } LIST_INSERT_HEAD(&lcconf->vpnctl_comm_socks, sock_elem, chain); sock_elem->source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, sock_elem->sock, 0, dispatch_get_main_queue()); if (sock_elem->source == NULL) { plog(ASL_LEVEL_ERR, "could not create comm socket source."); racoon_free(sock_elem); return; //%%%%% terminate } dispatch_source_set_event_handler(sock_elem->source, ^{ vpncontrol_comm_handler(sock_elem); }); sock = sock_elem->sock; dispatch_source_t the_source = sock_elem->source; dispatch_source_set_cancel_handler(sock_elem->source, ^{ close(sock); dispatch_release(the_source); /* Release the source on cancel */ });