+ char *msg=NULL;
+ int retval = 0;
+ struct ustcomm_connection conn;
+ char *explicit_daemon_socket_path;
+
+ explicit_daemon_socket_path = getenv("UST_DAEMON_SOCKET");
+ if(explicit_daemon_socket_path) {
+ /* user specified explicitly a socket path */
+ result = snprintf(path, UNIX_PATH_MAX, "%s", explicit_daemon_socket_path);
+ }
+ else {
+ /* just use the default path */
+ result = snprintf(path, UNIX_PATH_MAX, "%s/ustd", SOCK_DIR);
+ }
+
+ if(result >= UNIX_PATH_MAX) {
+ ERR("string overflow allocating socket name");
+ return -1;
+ }
+
+ asprintf(&msg, "collect %d %s", pid, channel);
+
+ /* don't signal it because it's the daemon */
+ result = ustcomm_connect_path(path, &conn, -1);
+ if(result == -1) {
+ WARN("ustcomm_connect_path failed");
+ retval = -1;
+ goto del_string;
+ }
+
+ result = ustcomm_send_request(&conn, msg, NULL);
+ if(result == -1) {
+ WARN("ustcomm_send_request failed");
+ retval = -1;
+ goto disconnect;
+ }
+
+ disconnect:
+ ustcomm_disconnect(&conn);
+ del_string:
+ free(msg);
+
+ 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
+ */
+
+#define RECV_INCREMENT 1
+#define RECV_INITIAL_BUF_SIZE 10
+
+static int recv_message_fd(int fd, char **msg)
+{
+ int result;
+ int buf_alloc_size = 0;
+ char *buf = NULL;
+ int buf_used_size = 0;
+
+ buf = malloc(RECV_INITIAL_BUF_SIZE);
+ buf_alloc_size = RECV_INITIAL_BUF_SIZE;
+
+ for(;;) {
+ if(buf_used_size + RECV_INCREMENT > buf_alloc_size) {
+ char *new_buf;
+ buf_alloc_size *= 2;
+ new_buf = (char *) realloc(buf, buf_alloc_size);
+ if(new_buf == NULL) {
+ ERR("realloc returned NULL");
+ free(buf);
+ return -1;
+ }
+ buf = new_buf;
+ }
+
+ /* FIXME: this is really inefficient; but with count>1 we would
+ * need a buffering mechanism */
+ result = recv(fd, buf+buf_used_size, RECV_INCREMENT, 0);
+ if(result == -1) {
+ free(buf);
+ if(errno != ECONNRESET)
+ PERROR("recv");
+ return -1;
+ }
+ if(result == 0) {
+ if(buf_used_size)
+ goto ret;
+ else {
+ free(buf);
+ return 0;
+ }
+ }
+
+ buf_used_size += result;
+
+ if(buf[buf_used_size-1] == 0) {
+ goto ret;
+ }
+ }
+
+ret:
+ *msg = buf;
+ DBG("received message \"%s\"", buf);
+
+ return 1;
+
+}
+
+int ustcomm_send_reply(struct ustcomm_server *server, char *msg, struct ustcomm_source *src)
+{
+ int result;
+
+ result = send_message_fd(src->fd, msg);
+ if(result < 0) {
+ ERR("error in send_message_fd");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Called after a fork. */
+
+int ustcomm_close_all_connections(struct ustcomm_server *server)
+{
+ struct ustcomm_connection *conn;
+ struct ustcomm_connection *deletable_conn = NULL;
+
+ list_for_each_entry(conn, &server->connections, list) {
+ free(deletable_conn);
+ deletable_conn = conn;
+ close(conn->fd);
+ list_del(&conn->list);
+ }
+
+ return 0;
+}
+
+/* @timeout: max blocking time in milliseconds, -1 means infinity
+ *
+ * returns 1 to indicate a message was received
+ * returns 0 to indicate no message was received
+ * returns -1 to indicate an error
+ */
+
+int ustcomm_recv_message(struct ustcomm_server *server, char **msg, struct ustcomm_source *src, int timeout)
+{
+ struct pollfd *fds;
+ struct ustcomm_connection *conn;
+ int result;
+ int retval;
+
+ for(;;) {
+ int idx = 0;
+ int n_fds = 1;
+
+ list_for_each_entry(conn, &server->connections, list) {
+ n_fds++;
+ }
+
+ fds = (struct pollfd *) malloc(n_fds * sizeof(struct pollfd));
+ if(fds == NULL) {
+ ERR("malloc returned NULL");
+ return -1;
+ }
+
+ /* special idx 0 is for listening socket */
+ fds[idx].fd = server->listen_fd;
+ fds[idx].events = POLLIN;
+ idx++;
+
+ list_for_each_entry(conn, &server->connections, list) {
+ fds[idx].fd = conn->fd;
+ fds[idx].events = POLLIN;
+ idx++;
+ }
+
+ while((result = poll(fds, n_fds, timeout)) == -1 && errno == EINTR)
+ /* nothing */;
+ if(result == -1) {
+ PERROR("poll");
+ return -1;
+ }
+
+ if(result == 0)
+ return 0;
+
+ if(fds[0].revents) {
+ struct ustcomm_connection *newconn;
+ int newfd;
+
+ result = newfd = accept(server->listen_fd, NULL, NULL);
+ if(result == -1) {
+ PERROR("accept");
+ return -1;
+ }
+
+ newconn = (struct ustcomm_connection *) malloc(sizeof(struct ustcomm_connection));
+ if(newconn == NULL) {
+ ERR("malloc returned NULL");
+ return -1;
+ }
+
+ newconn->fd = newfd;
+
+ list_add(&newconn->list, &server->connections);
+ }
+
+ for(idx=1; idx<n_fds; idx++) {
+ if(fds[idx].revents) {
+ retval = recv_message_fd(fds[idx].fd, msg);
+ if(src)
+ src->fd = fds[idx].fd;
+
+ if(**msg == 0) {
+ /* connection finished */
+ close(fds[idx].fd);
+
+ list_for_each_entry(conn, &server->connections, list) {
+ if(conn->fd == fds[idx].fd) {
+ list_del(&conn->list);
+ break;
+ }
+ }
+ }
+ else {
+ goto free_fds_return;
+ }
+ }
+ }
+
+ free(fds);
+ }
+
+free_fds_return:
+ free(fds);
+ return retval;
+}
+
+int ustcomm_ustd_recv_message(struct ustcomm_ustd *ustd, char **msg, struct ustcomm_source *src, int timeout)
+{
+ return ustcomm_recv_message(&ustd->server, msg, src, timeout);
+}
+
+int ustcomm_app_recv_message(struct ustcomm_app *app, char **msg, struct ustcomm_source *src, int timeout)
+{
+ return ustcomm_recv_message(&app->server, msg, src, timeout);
+}
+
+/* This removes src from the list of active connections of app.
+ */
+
+int ustcomm_app_detach_client(struct ustcomm_app *app, struct ustcomm_source *src)
+{
+ struct ustcomm_server *server = (struct ustcomm_server *)app;
+ struct ustcomm_connection *conn;
+
+ list_for_each_entry(conn, &server->connections, list) {
+ if(conn->fd == src->fd) {
+ list_del(&conn->list);
+ goto found;
+ }
+ }
+
+ return -1;
+found:
+ return src->fd;
+}
+
+static int init_named_socket(const char *name, char **path_out)
+{
+ int result;
+ int fd;
+