+/*
+ * Return value:
+ * 0: Success, but no reply because recv() returned 0
+ * 1: Success
+ * -1: Error
+ *
+ * On error, the error message is printed, except on
+ * ECONNRESET, which is normal when the application dies.
+ */
+
+int ustcomm_send_request(struct ustcomm_connection *conn, const char *req, char **reply)
+{
+ int result;
+
+ result = send(conn->fd, req, strlen(req), MSG_NOSIGNAL);
+ if(result == -1) {
+ if(errno != EPIPE)
+ PERROR("send");
+ return -1;
+ }
+
+ if(!reply)
+ return 1;
+
+ *reply = (char *) malloc(MSG_MAX+1);
+ result = recv(conn->fd, *reply, MSG_MAX, 0);
+ if(result == -1) {
+ if(errno != ECONNRESET)
+ PERROR("recv");
+ return -1;
+ }
+ else if(result == 0) {
+ return 0;
+ }
+
+ (*reply)[result] = '\0';
+
+ return 1;
+}
+
+int ustcomm_connect_path(const char *path, struct ustcomm_connection *conn, pid_t signalpid)
+{
+ int fd;
+ int result;
+ struct sockaddr_un addr;
+
+ result = fd = socket(PF_UNIX, SOCK_STREAM, 0);
+ if(result == -1) {
+ PERROR("socket");
+ return -1;
+ }
+
+ addr.sun_family = AF_UNIX;
+
+ result = snprintf(addr.sun_path, UNIX_PATH_MAX, "%s", path);
+ if(result >= UNIX_PATH_MAX) {
+ ERR("string overflow allocating socket name");
+ return -1;
+ }
+
+ if(signalpid >= 0) {
+ result = signal_process(signalpid);
+ if(result == -1) {
+ ERR("could not signal process");
+ return -1;
+ }
+ }
+
+ result = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
+ if(result == -1) {
+ PERROR("connect");
+ return -1;
+ }
+
+ conn->fd = fd;
+
+ return 0;
+}
+
+int ustcomm_disconnect(struct ustcomm_connection *conn)
+{
+ return close(conn->fd);
+}
+
+int ustcomm_connect_app(pid_t pid, struct ustcomm_connection *conn)
+{
+ int result;
+ char path[UNIX_PATH_MAX];
+
+
+ result = snprintf(path, UNIX_PATH_MAX, "%s/%d", SOCK_DIR, pid);
+ if(result >= UNIX_PATH_MAX) {
+ ERR("string overflow allocating socket name");
+ return -1;
+ }
+
+ return ustcomm_connect_path(path, conn, pid);
+}
+
+static int ensure_dir_exists(const char *dir)
+{
+ struct stat st;
+ int result;
+
+ if(!strcmp(dir, ""))
+ return -1;
+
+ result = stat(dir, &st);
+ if(result == -1 && errno != ENOENT) {
+ return -1;
+ }
+ else if(result == -1) {
+ /* ENOENT */
+ char buf[200];
+ int result;
+
+ result = snprintf(buf, sizeof(buf), "mkdir -p \"%s\"", dir);
+ if(result >= sizeof(buf)) {
+ ERR("snprintf buffer overflow");
+ return -1;
+ }
+ result = system(buf);
+ if(result != 0) {
+ ERR("executing command %s", buf);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/* Called by an application to initialize its server so daemons can
+ * connect to it.
+ */
+