+ PERROR("bind");
+ goto free_addr;
+ }
+
+ result = listen(fd, 1);
+ if(result == -1) {
+ PERROR("listen");
+ goto free_addr;
+ }
+
+ sock = ustcomm_init_sock(fd, epoll_fd,
+ NULL);
+ if (!sock) {
+ ERR("failed to create ustcomm_sock");
+ goto free_addr;
+ }
+
+ free(addr);
+
+ return sock;
+
+free_addr:
+ free(addr);
+close_sock:
+ close(fd);
+
+ return NULL;
+}
+
+void ustcomm_del_named_sock(struct ustcomm_sock *sock,
+ int keep_socket_file)
+{
+ int result, fd;
+ struct stat st;
+ struct sockaddr dummy;
+ struct sockaddr_un *sockaddr = NULL;
+ int alloc_size;
+
+ fd = sock->fd;
+
+ if(!keep_socket_file) {
+
+ /* Get the socket name */
+ alloc_size = sizeof(dummy);
+ if (getsockname(fd, &dummy, (socklen_t *)&alloc_size) < 0) {
+ PERROR("getsockname failed");
+ goto del_sock;
+ }
+
+ sockaddr = zmalloc(alloc_size);
+ if (!sockaddr) {
+ ERR("failed to allocate sockaddr");
+ goto del_sock;
+ }
+
+ if (getsockname(fd, sockaddr, (socklen_t *)&alloc_size) < 0) {
+ PERROR("getsockname failed");
+ goto free_sockaddr;
+ }
+
+ /* Destroy socket */
+ result = stat(sockaddr->sun_path, &st);
+ if(result < 0) {
+ PERROR("stat (%s)", sockaddr->sun_path);
+ goto free_sockaddr;
+ }
+
+ /* Paranoid check before deleting. */
+ result = S_ISSOCK(st.st_mode);
+ if(!result) {
+ ERR("The socket we are about to delete is not a socket.");
+ goto free_sockaddr;
+ }
+
+ result = unlink(sockaddr->sun_path);
+ if(result < 0) {
+ PERROR("unlink");
+ }
+ }
+
+free_sockaddr:
+ free(sockaddr);
+
+del_sock:
+ ustcomm_del_sock(sock, keep_socket_file);
+}
+
+
+/* Called by an app to ask the consumer daemon to connect to it. */
+
+int ustcomm_request_consumer(pid_t pid, const char *channel)
+{
+ int result, daemon_fd;
+ int retval = 0;
+ char *msg=NULL;
+ char *explicit_daemon_socket_path, *daemon_path;
+
+ explicit_daemon_socket_path = getenv("UST_DAEMON_SOCKET");
+ if (explicit_daemon_socket_path) {
+ /* user specified explicitly a socket path */
+ result = asprintf(&daemon_path, "%s", explicit_daemon_socket_path);
+ } else {
+ /* just use the default path */
+ result = asprintf(&daemon_path, "%s/ustd", SOCK_DIR);
+ }
+ if (result < 0) {
+ ERR("string overflow allocating socket name");
+ return -1;
+ }
+
+ if (asprintf(&msg, "collect %d %s", pid, channel) < 0) {
+ ERR("ustcomm_request_consumer : asprintf failed (collect %d/%s)",
+ pid, channel);
+ retval = -1;
+ goto free_daemon_path;
+ }
+
+ result = ustcomm_connect_path(daemon_path, &daemon_fd);
+ if (result < 0) {
+ WARN("ustcomm_connect_path failed, daemon_path: %s",
+ daemon_path);
+ retval = -1;
+ goto del_string;
+ }
+
+ result = ustcomm_send_request(daemon_fd, msg, NULL);
+ if (result < 0) {
+ WARN("ustcomm_send_request failed, daemon path: %s",
+ daemon_path);
+ retval = -1;
+ }
+
+ close(daemon_fd);
+del_string:
+ free(msg);
+free_daemon_path:
+ free(daemon_path);
+
+ return retval;
+}
+
+/* returns 1 to indicate a message was received
+ * returns 0 to indicate no message was received (end of stream)
+ * returns -1 to indicate an error
+ */
+int ustcomm_recv_fd(int sock,
+ struct ustcomm_header *header,
+ char **data, int *fd)
+{
+ int result;
+ int retval;
+ struct ustcomm_header peek_header;
+ struct iovec iov[2];
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ char buf[CMSG_SPACE(sizeof(int))];
+
+ result = recv(sock, &peek_header, sizeof(peek_header),
+ MSG_PEEK | MSG_WAITALL);
+ if (result <= 0) {
+ if(errno == ECONNRESET) {
+ return 0;
+ } else if (errno == EINTR) {
+ return -1;
+ } else if (result < 0) {
+ PERROR("recv");
+ return -1;
+ }
+ return 0;
+ }
+
+ memset(&msg, 0, sizeof(msg));
+
+ iov[0].iov_base = (char *)header;
+ iov[0].iov_len = sizeof(struct ustcomm_header);
+
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+
+ if (peek_header.size) {
+ if (peek_header.size < 0 || peek_header.size > 100) {
+ WARN("big peek header! %d", peek_header.size);
+ }
+ *data = malloc(peek_header.size);
+ if (!*data) {
+ ERR("failed to allocate space for message");
+ }
+
+ iov[1].iov_base = (char *)*data;
+ iov[1].iov_len = peek_header.size;
+
+ msg.msg_iovlen++;
+ }
+
+ if (fd && peek_header.fd_included) {
+ msg.msg_control = buf;
+ msg.msg_controllen = sizeof(buf);
+ }
+
+ result = recvmsg(sock, &msg,
+ MSG_WAITALL);
+
+ if (result <= 0) {
+ if(errno == ECONNRESET) {
+ retval = 0;
+ } else if (errno == EINTR) {
+ retval = -1;
+ } else if (result < 0) {
+ PERROR("recv");
+ retval = -1;
+ } else {
+ retval = 0;
+ }
+ free(*data);
+ return retval;
+ }
+
+ if (fd && peek_header.fd_included) {
+ cmsg = CMSG_FIRSTHDR(&msg);
+ result = 0;
+ while (cmsg != NULL) {
+ if (cmsg->cmsg_level == SOL_SOCKET
+ && cmsg->cmsg_type == SCM_RIGHTS) {
+ *fd = *(int *) CMSG_DATA(cmsg);
+ result = 1;
+ break;
+ }
+ cmsg = CMSG_NXTHDR(&msg, cmsg);
+ }
+ if (!result) {
+ ERR("Failed to receive file descriptor\n");
+ }
+ }
+
+ return 1;
+}
+
+int ustcomm_recv(int sock,
+ struct ustcomm_header *header,
+ char **data)
+{
+ return ustcomm_recv_fd(sock, header, data, NULL);
+}
+
+
+int recv_message_conn(int sock, char **msg)
+{
+ struct ustcomm_header header;
+
+ return ustcomm_recv(sock, &header, msg);
+}
+
+int ustcomm_send_fd(int sock,
+ const struct ustcomm_header *header,
+ const char *data,
+ int *fd)
+{
+ struct iovec iov[2];
+ struct msghdr msg;
+ int result;
+ struct cmsghdr *cmsg;
+ char buf[CMSG_SPACE(sizeof(int))];
+
+ memset(&msg, 0, sizeof(msg));
+
+ iov[0].iov_base = (char *)header;
+ iov[0].iov_len = sizeof(struct ustcomm_header);
+
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+
+ if (header->size) {
+ iov[1].iov_base = (char *)data;
+ iov[1].iov_len = header->size;
+
+ msg.msg_iovlen++;
+
+ }
+
+ if (fd && header->fd_included) {
+ msg.msg_control = buf;
+ msg.msg_controllen = sizeof(buf);
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(int));
+ *(int *) CMSG_DATA(cmsg) = *fd;
+ msg.msg_controllen = cmsg->cmsg_len;
+ }
+
+ result = sendmsg(sock, &msg, MSG_NOSIGNAL);
+ if (result < 0 && errno != EPIPE) {
+ PERROR("sendmsg failed");
+ }
+ return result;
+}
+
+int ustcomm_send(int sock,
+ const struct ustcomm_header *header,
+ const char *data)
+{
+ return ustcomm_send_fd(sock, header, data, NULL);
+}
+
+int ustcomm_send_reply(char *msg, int sock)
+{
+ int result;
+ struct ustcomm_header header;
+
+ memset(&header, 0, sizeof(header));
+
+ header.size = strlen(msg) + 1;
+
+ result = ustcomm_send(sock, &header, msg);
+ if(result < 0) {
+ ERR("error in ustcomm_send");
+ return result;