From 6217f34977bfa17b66b89df5d45420774abedcb3 Mon Sep 17 00:00:00 2001 From: Ben Byer Date: Wed, 5 Sep 2007 18:29:44 -0700 Subject: changes to support launchd on OS X --- Xtrans.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- Xtranssock.c | 42 ++++++++++++++++++++++++++++++++-- 2 files changed, 113 insertions(+), 3 deletions(-) diff --git a/Xtrans.c b/Xtrans.c index 00391a0..4de9161 100644 --- a/Xtrans.c +++ b/Xtrans.c @@ -53,6 +53,9 @@ from The Open Group. */ #include +#ifdef HAVE_LAUNCHD +#include +#endif /* * The transport table contains a definition for every transport (protocol) @@ -360,6 +363,15 @@ TRANS(ParseAddress) (char *address, char **protocol, char **host, char **port) */ #endif +#ifdef HAVE_LAUNCHD + /* launchd sockets will look like 'local//tmp/launch-XgkNns/:0' */ + if(address != NULL && strlen(address)>8 && (!strncmp(address,"local//",7))) { + _protocol="local"; + _host=""; + _port=address+6; + } +#endif + /* * Now that we have all of the components, allocate new * string space for them. @@ -858,6 +870,10 @@ TRANS(Connect) (XtransConnInfo ciptr, char *address) return -1; } +#ifdef HAVE_LAUNCHD + if (!host || !*host) host=strdup(""); +#endif + if (!port || !*port) { PRMSG (1,"Connect: Missing port specification in %s\n", @@ -1053,15 +1069,71 @@ TRANS(MakeAllCOTSServerListeners) (char *port, int *partial, int *count_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)) { + fprintf(stderr,"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,"No sockets found to answer requests on!\n"); + goto not_launchd; + } + + if (launch_data_dict_get_count(sockets_dict) > 1) { + fprintf(stderr,"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,"No known sockets found to answer requests on!\n"); + goto not_launchd; + } + + if (launch_data_array_get_count(listening_fd_array)!=1) { + fprintf(stderr,"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; diff --git a/Xtranssock.c b/Xtranssock.c index 65d4beb..e989b42 100644 --- a/Xtranssock.c +++ b/Xtranssock.c @@ -529,18 +529,55 @@ TRANS(SocketReopen) (int i, int type, int fd, char *port) { XtransConnInfo ciptr; + int portlen; + struct sockaddr *addr; PRMSG (3,"SocketReopen(%d,%d,%s)\n", type, fd, port); + if (port == NULL) { + PRMSG (1, "SocketReopen: port was null!\n", 0, 0, 0); + return NULL; + } + + portlen = strlen(port); + if (portlen < 0 || portlen > (SOCK_MAXADDRLEN + 2)) { + PRMSG (1, "SocketReopen: invalid portlen %d\n", portlen, 0, 0); + return NULL; + } + + if (portlen < 14) portlen = 14; + if ((ciptr = (XtransConnInfo) xcalloc ( 1, sizeof(struct _XtransConnInfo))) == NULL) { - PRMSG (1, "SocketReopen: malloc failed\n", 0, 0, 0); + PRMSG (1, "SocketReopen: malloc(ciptr) failed\n", 0, 0, 0); return NULL; } ciptr->fd = fd; + if ((addr = (struct sockaddr *) xcalloc (1, portlen + 2)) == NULL) { + PRMSG (1, "SocketReopen: malloc(addr) failed\n", 0, 0, 0); + return NULL; + } + ciptr->addr = addr; + ciptr->addrlen = portlen + 2; + + if ((ciptr->peeraddr = (struct sockaddr *) xcalloc (1, portlen + 2)) == NULL) { + PRMSG (1, "SocketReopen: malloc(portaddr) failed\n", 0, 0, 0); + return NULL; + } + ciptr->peeraddrlen = portlen + 2; + + /* Initialize ciptr structure as if it were a normally-opened unix socket */ + ciptr->flags = TRANS_LOCAL; + addr->sa_len = portlen + 1; + addr->sa_family = AF_UNIX; + strlcpy(addr->sa_data, port, portlen); + ciptr->family = AF_UNIX; + memcpy(ciptr->peeraddr, ciptr->addr, sizeof(struct sockaddr)); + ciptr->port = rindex(addr->sa_data, ':'); + if (ciptr->port[0] == ':') ciptr->port++; /* port should now point to portnum or NULL */ return ciptr; } @@ -1345,6 +1382,7 @@ TRANS(SocketUNIXAccept) (XtransConnInfo ciptr, int *status) return NULL; } + ciptr->addrlen = namelen; /* * Get the socket name and the peer name from the listener socket, * since this is unix domain. @@ -1970,7 +2008,7 @@ TRANS(SocketUNIXConnect) (XtransConnInfo ciptr, char *host, char *port) * we know for sure it will fail. */ - if (strcmp (host, "unix") != 0 && !UnixHostReallyLocal (host)) + if (host && *host && host[0]!='/' && strcmp (host, "unix") != 0 && !UnixHostReallyLocal (host)) { PRMSG (1, "SocketUNIXConnect: Cannot connect to non-local host %s\n", -- cgit v1.2.3