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; }
int main(void) { launch_data_t resp, tmp, msg = launch_data_new_string(LAUNCH_KEY_CHECKIN); resp = launch_msg(msg); if (resp == NULL) { fprintf(stderr, "launch_msg(): %s\n", strerror(errno)); exit(EXIT_FAILURE); } if (launch_data_get_type(resp) == LAUNCH_DATA_ERRNO) { errno = launch_data_get_errno(resp); fprintf(stderr, "launch_msg() response: %s\n", strerror(errno)); exit(EXIT_FAILURE); } tmp = launch_data_dict_lookup(resp, LAUNCH_JOBKEY_MACHSERVICES); if (tmp == NULL) { fprintf(stderr, "no mach services found!\n"); exit(EXIT_FAILURE); } launch_data_dict_iterate(tmp, print_mach_service, NULL); sleep(1); exit(EXIT_SUCCESS); }
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; }
/* returns -1 for error, else file descriptor for listener */ int get_listener_fd() { launch_data_t checkin_request = launch_data_new_string(LAUNCH_KEY_CHECKIN); if (!checkin_request) { syslog(LOG_NOTICE, "Unable to create checkin string!"); return -1; } launch_data_t checkin_response = launch_msg(checkin_request); if (!checkin_response) { syslog(LOG_NOTICE, "Unable to do checkin!"); return -1; } if (LAUNCH_DATA_ERRNO == launch_data_get_type(checkin_response)) { errno = launch_data_get_errno(checkin_response); syslog(LOG_NOTICE, "Error %d getting type of checkin response!", errno); return -1; } launch_data_t the_label = launch_data_dict_lookup(checkin_response, LAUNCH_JOBKEY_LABEL); if (!the_label) { syslog(LOG_NOTICE, "No Label for job!"); return -1; } launch_data_t sockets_dict = launch_data_dict_lookup(checkin_response, LAUNCH_JOBKEY_SOCKETS); if (!sockets_dict) { syslog(LOG_NOTICE, "No socket found to answer requests on!"); return -1; } size_t count = launch_data_dict_get_count(sockets_dict); if (count < 1) { syslog(LOG_NOTICE, "No socket found to answer requests on!"); return -1; } if (1 < count) { syslog(LOG_NOTICE, "Some socket(s) will be ignored!"); } launch_data_t listening_fd_array = launch_data_dict_lookup(sockets_dict, "MasterSocket"); if (!listening_fd_array) { syslog(LOG_NOTICE, "MasterSocket not found!"); return -1; } count = launch_data_array_get_count(listening_fd_array); if (count < 1) { syslog(LOG_NOTICE, "No socket found to answer requests on!"); return -1; } if (1 < count) { syslog(LOG_NOTICE, "Some socket(s) will be ignored!"); } launch_data_t this_listening_fd = launch_data_array_get_index(listening_fd_array, 0); int listener_fd = launch_data_get_fd(this_listening_fd); if ( listener_fd == -1 ) { syslog(LOG_NOTICE, "launch_data_get_fd() failed!"); return -1; } if (listen(listener_fd, 5)) { syslog(LOG_NOTICE, "listen() failed with %i", errno); return -1; } return listener_fd; }
/* * Lookup the audit mach port in the launchd dictionary. */ static mach_port_t lookup_machport(const char *label) { launch_data_t msg, msd, ld, cdict, to; mach_port_t mp = MACH_PORT_NULL; msg = launch_data_new_string(LAUNCH_KEY_CHECKIN); cdict = launch_msg(msg); if (cdict == NULL) { auditd_log_err("launch_msg(\"" LAUNCH_KEY_CHECKIN "\") IPC failure: %m"); return (MACH_PORT_NULL); } if (launch_data_get_type(cdict) == LAUNCH_DATA_ERRNO) { errno = launch_data_get_errno(cdict); auditd_log_err("launch_data_get_type() can't get dict: %m"); return (MACH_PORT_NULL); } to = launch_data_dict_lookup(cdict, LAUNCH_JOBKEY_TIMEOUT); if (to) { max_idletime = launch_data_get_integer(to); auditd_log_debug("launchd timeout set to %d", max_idletime); } else { auditd_log_debug("launchd timeout not set, setting to 60"); max_idletime = 60; } msd = launch_data_dict_lookup(cdict, LAUNCH_JOBKEY_MACHSERVICES); if (msd == NULL) { auditd_log_err( "launch_data_dict_lookup() can't get mach services"); return (MACH_PORT_NULL); } ld = launch_data_dict_lookup(msd, label); if (ld == NULL) { auditd_log_err("launch_data_dict_lookup can't find %s", label); return (MACH_PORT_NULL); } mp = launch_data_get_machport(ld); return (mp); }
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* launch2python(launch_data_t data) { launch_data_type_t tp; tp = launch_data_get_type(data); switch (tp) { case LAUNCH_DATA_DICTIONARY: return launchdict2python(data); case LAUNCH_DATA_ARRAY: return launcharray2python(data); case LAUNCH_DATA_FD: return PyObject_CallFunction(file_descriptor_type, "i", launch_data_get_fd(data)); return NULL; case LAUNCH_DATA_INTEGER: return PyLong_FromLongLong(launch_data_get_integer(data)); case LAUNCH_DATA_REAL: return PyFloat_FromDouble(launch_data_get_real(data)); case LAUNCH_DATA_BOOL: return PyBool_FromLong(launch_data_get_bool(data)); case LAUNCH_DATA_STRING: return PyString_FromString(launch_data_get_string(data)); case LAUNCH_DATA_OPAQUE: return PyBuffer_FromMemory( launch_data_get_opaque(data), launch_data_get_opaque_size(data)); case LAUNCH_DATA_ERRNO: return PyObject_CallFunction(errno_type, "i", launch_data_get_errno(data)); default: PyErr_Format(PyExc_ValueError, "Unhandled launch data type (tag: %d)", (int)tp); return NULL; } }
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; }
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; }
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)); }
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; }
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; }
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 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); }
/* 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; }
/** * create socket data_source for socket specified by launchd configuration */ int socket_connection_create_launchd(){ launch_data_t sockets_dict, checkin_response; launch_data_t checkin_request; launch_data_t listening_fd_array; /* * Register ourselves with launchd. * */ if ((checkin_request = launch_data_new_string(LAUNCH_KEY_CHECKIN)) == NULL) { log_error( "launch_data_new_string(\"" LAUNCH_KEY_CHECKIN "\") Unable to create string."); return -1; } if ((checkin_response = launch_msg(checkin_request)) == NULL) { log_error( "launch_msg(\"" LAUNCH_KEY_CHECKIN "\") IPC failure: %u", errno); return -1; } if (LAUNCH_DATA_ERRNO == launch_data_get_type(checkin_response)) { errno = launch_data_get_errno(checkin_response); log_error( "Check-in failed: %u", errno); return -1; } launch_data_t the_label = launch_data_dict_lookup(checkin_response, LAUNCH_JOBKEY_LABEL); if (NULL == the_label) { log_error( "No label found"); return -1; } /* * Retrieve the dictionary of Socket entries in the config file */ sockets_dict = launch_data_dict_lookup(checkin_response, LAUNCH_JOBKEY_SOCKETS); if (NULL == sockets_dict) { log_error("No sockets found to answer requests on!"); return -1; } // if (launch_data_dict_get_count(sockets_dict) > 1) { // log_error("Some sockets will be ignored!"); // } /* * Get the dictionary value from the key "Listeners" */ listening_fd_array = launch_data_dict_lookup(sockets_dict, "Listeners"); if (listening_fd_array) { // log_error("Listeners...\n"); socket_connection_launchd_register_fd_array( listening_fd_array ); } /* * Get the dictionary value from the key "Listeners" */ listening_fd_array = launch_data_dict_lookup(sockets_dict, "Listeners2"); if (listening_fd_array) { // log_error("Listeners2...\n"); socket_connection_launchd_register_fd_array( listening_fd_array ); } // although used in Apple examples, it creates a malloc warning // launch_data_free(checkin_response); return 0; }
int TRANS(MakeAllCOTSServerListeners) (char *port, int *partial, int *count_ret, XtransConnInfo **ciptrs_ret) { char buffer[256]; /* ??? What size ?? */ XtransConnInfo ciptr, temp_ciptrs[NUMTRANS]; int status, i, j; #ifdef HAVE_LAUNCHD int launchd_fd; launch_data_t sockets_dict, checkin_request, checkin_response; launch_data_t listening_fd_array, listening_fd; #endif #if defined(IPv6) && defined(AF_INET6) int ipv6_succ = 0; #endif PRMSG (2,"MakeAllCOTSServerListeners(%s,%p)\n", port ? port : "NULL", ciptrs_ret, 0); *count_ret = 0; #ifdef HAVE_LAUNCHD /* Get launchd fd */ if ((checkin_request = launch_data_new_string(LAUNCH_KEY_CHECKIN)) == NULL) { fprintf(stderr,"launch_data_new_string(\"" LAUNCH_KEY_CHECKIN "\") Unable to create string.\n"); goto not_launchd; } if ((checkin_response = launch_msg(checkin_request)) == NULL) { fprintf(stderr,"launch_msg(\"" LAUNCH_KEY_CHECKIN "\") IPC failure: %s\n",strerror(errno)); goto not_launchd; } if (LAUNCH_DATA_ERRNO == launch_data_get_type(checkin_response)) { // ignore EACCES, which is common if we weren't started by launchd if (launch_data_get_errno(checkin_response) != EACCES) fprintf(stderr,"launchd check-in failed: %s\n",strerror(launch_data_get_errno(checkin_response))); goto not_launchd; } sockets_dict = launch_data_dict_lookup(checkin_response, LAUNCH_JOBKEY_SOCKETS); if (NULL == sockets_dict) { fprintf(stderr,"launchd check-in: no sockets found to answer requests on!\n"); goto not_launchd; } if (launch_data_dict_get_count(sockets_dict) > 1) { fprintf(stderr,"launchd check-in: some sockets will be ignored!\n"); goto not_launchd; } listening_fd_array = launch_data_dict_lookup(sockets_dict, ":0"); if (NULL == listening_fd_array) { fprintf(stderr,"launchd check-in: No known sockets found to answer requests on!\n"); goto not_launchd; } if (launch_data_array_get_count(listening_fd_array)!=1) { fprintf(stderr,"launchd check-in: Expected 1 socket from launchd, got %d)\n", launch_data_array_get_count(listening_fd_array)); goto not_launchd; } listening_fd=launch_data_array_get_index(listening_fd_array, 0); launchd_fd=launch_data_get_fd(listening_fd); fprintf(stderr,"Xquartz: run by launchd for fd %d\n",launchd_fd); if((ciptr = TRANS(ReopenCOTSServer(TRANS_SOCKET_LOCAL_INDEX, launchd_fd, getenv("DISPLAY"))))==NULL) fprintf(stderr,"Got NULL while trying to Reopen launchd port\n"); else temp_ciptrs[(*count_ret)++] = ciptr; not_launchd: #endif for (i = 0; i < NUMTRANS; i++) { Xtransport *trans = Xtransports[i].transport; unsigned int flags = 0; if (trans->flags&TRANS_ALIAS || trans->flags&TRANS_NOLISTEN) continue; snprintf(buffer, sizeof(buffer), "%s/:%s", trans->TransName, port ? port : ""); PRMSG (5,"MakeAllCOTSServerListeners: opening %s\n", buffer, 0, 0); if ((ciptr = TRANS(OpenCOTSServer(buffer))) == NULL) { if (trans->flags & TRANS_DISABLED) continue; PRMSG (1, "MakeAllCOTSServerListeners: failed to open listener for %s\n", trans->TransName, 0, 0); continue; } #if defined(IPv6) && defined(AF_INET6) if ((Xtransports[i].transport_id == TRANS_SOCKET_INET_INDEX && ipv6_succ)) flags |= ADDR_IN_USE_ALLOWED; #endif if ((status = TRANS(CreateListener (ciptr, port, flags))) < 0) { if (status == TRANS_ADDR_IN_USE) { /* * We failed to bind to the specified address because the * address is in use. It must be that a server is already * running at this address, and this function should fail. */ PRMSG (1, "MakeAllCOTSServerListeners: server already running\n", 0, 0, 0); for (j = 0; j < *count_ret; j++) TRANS(Close) (temp_ciptrs[j]); *count_ret = 0; *ciptrs_ret = NULL; *partial = 0; return -1; } else { PRMSG (1, "MakeAllCOTSServerListeners: failed to create listener for %s\n", trans->TransName, 0, 0); continue; } } #if defined(IPv6) && defined(AF_INET6) if (Xtransports[i].transport_id == TRANS_SOCKET_INET6_INDEX) ipv6_succ = 1; #endif PRMSG (5, "MakeAllCOTSServerListeners: opened listener for %s, %d\n", trans->TransName, ciptr->fd, 0); temp_ciptrs[*count_ret] = ciptr; (*count_ret)++; } *partial = (*count_ret < complete_network_count()); PRMSG (5, "MakeAllCOTSServerListeners: partial=%d, actual=%d, complete=%d \n", *partial, *count_ret, complete_network_count()); if (*count_ret > 0) { if ((*ciptrs_ret = (XtransConnInfo *) xalloc ( *count_ret * sizeof (XtransConnInfo))) == NULL) { return -1; } for (i = 0; i < *count_ret; i++) { (*ciptrs_ret)[i] = temp_ciptrs[i]; } } else *ciptrs_ret = NULL; return 0; }
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 */ });
DBusServer * _dbus_server_new_for_launchd (const char *launchd_env_var, DBusError * error) { #ifdef DBUS_ENABLE_LAUNCHD DBusServer *server; DBusString address; int launchd_fd; launch_data_t sockets_dict, checkin_response; launch_data_t checkin_request; launch_data_t listening_fd_array, listening_fd; launch_data_t environment_dict, environment_param; const char *launchd_socket_path, *display; launchd_socket_path = _dbus_getenv (launchd_env_var); display = _dbus_getenv ("DISPLAY"); _DBUS_ASSERT_ERROR_IS_CLEAR (error); if (launchd_socket_path == NULL || *launchd_socket_path == '\0') { dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, "launchd's environment variable %s is empty, but should contain a socket path.\n", launchd_env_var); return NULL; } if (!_dbus_string_init (&address)) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); return NULL; } if (!_dbus_string_append (&address, "unix:path=")) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto l_failed_0; } if (!_dbus_string_append (&address, launchd_socket_path)) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto l_failed_0; } if ((checkin_request = launch_data_new_string (LAUNCH_KEY_CHECKIN)) == NULL) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, "launch_data_new_string(\"%s\") Unable to create string.\n", LAUNCH_KEY_CHECKIN); goto l_failed_0; } if ((checkin_response = launch_msg (checkin_request)) == NULL) { dbus_set_error (error, DBUS_ERROR_IO_ERROR, "launch_msg(\"%s\") IPC failure: %s\n", LAUNCH_KEY_CHECKIN, strerror (errno)); goto l_failed_0; } if (LAUNCH_DATA_ERRNO == launch_data_get_type (checkin_response)) { dbus_set_error (error, DBUS_ERROR_FAILED, "Check-in failed: %s\n", strerror (launch_data_get_errno (checkin_response))); goto l_failed_0; } sockets_dict = launch_data_dict_lookup (checkin_response, LAUNCH_JOBKEY_SOCKETS); if (NULL == sockets_dict) { dbus_set_error (error, DBUS_ERROR_IO_ERROR, "No sockets found to answer requests on!\n"); goto l_failed_0; } listening_fd_array = launch_data_dict_lookup (sockets_dict, "unix_domain_listener"); if (NULL == listening_fd_array) { dbus_set_error (error, DBUS_ERROR_IO_ERROR, "No known sockets found to answer requests on!\n"); goto l_failed_0; } if (launch_data_array_get_count (listening_fd_array) != 1) { dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED, "Expected 1 socket from launchd, got %d.\n", launch_data_array_get_count (listening_fd_array)); goto l_failed_0; } listening_fd = launch_data_array_get_index (listening_fd_array, 0); launchd_fd = launch_data_get_fd (listening_fd); _dbus_fd_set_close_on_exec (launchd_fd); if (launchd_fd < 0) { _DBUS_ASSERT_ERROR_IS_SET (error); goto l_failed_0; if (display == NULL || *display == '\0') { environment_dict = launch_data_dict_lookup (checkin_response, LAUNCH_JOBKEY_USERENVIRONMENTVARIABLES); if (NULL == environment_dict) { _dbus_warn ("Unable to retrieve user environment from launchd."); } else { environment_param = launch_data_dict_lookup (environment_dict, "DISPLAY"); if (NULL == environment_param) { _dbus_warn ("Unable to retrieve DISPLAY from launchd."); } else { display = launch_data_get_string(environment_param); dbus_setenv ("DISPLAY", display); } } } } server = _dbus_server_new_for_socket (&launchd_fd, 1, &address, 0); if (server == NULL) { dbus_set_error (error, DBUS_ERROR_NO_SERVER, "Unable to listen on launchd fd %d.", launchd_fd); goto l_failed_0; } _dbus_string_free (&address); return server; l_failed_0: _dbus_string_free (&address); return NULL; #else /* DBUS_ENABLE_LAUNCHD */ dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, "address type 'launchd' requested, but launchd support not compiled in"); return NULL; #endif }