Commit Diff


commit - 40d558910d47a11daa7416ea386f16b67c9258b8
commit + 8a03603b8f1458ba1e8c2f2ed9bd0363e8601603
blob - 00820a53c513998384af2849c1311c660ceeef6f
blob + d3405c5db2e7a48954a166f23e2cb17daa59a9bf
--- gotsys/gotsys.1
+++ gotsys/gotsys.1
@@ -47,7 +47,7 @@ The commands for
 .Nm
 are as follows:
 .Bl -tag -width Ds
-.It Cm apply Oo Fl c Ar commit Oc Oo Fl f Ar socket Oc Oo Fl r Ar repository-path Oc Oo Ar file Oc
+.It Cm apply Oo Fl c Ar commit Oc Oo Fl f Ar socket Oc Oo Fl r Ar repository-path Oc  Oo Fl w Oc Oo Ar file Oc
 Trigger system configuration tasks based on the
 .Xr gotsys.conf 5
 configuration
@@ -119,6 +119,10 @@ Use the repository at the specified path.
 If not specified, the repository path
 .Pa /git/gotsys.git
 will be used.
+.It Fl w
+Wait until
+.Xr gotsysd 8
+is done trying to apply the configuration and report the result.
 .El
 .It Cm check Oo Fl q Oc Oo Fl f Ar file Oc 
 Read a
blob - ba69385c1f238933082336acee61d9a579768e9e
blob + 584ac4aa540ecb67f99cf1c3451ceab525de382e
--- gotsys/gotsys.c
+++ gotsys/gotsys.c
@@ -164,7 +164,7 @@ __dead static void
 usage_apply(void)
 {
 	fprintf(stderr, "usage: %s apply [-f socket] [-r repository] "
-	    "[-c commit] [filename]", getprogname());
+	    "[-c commit] [-w] [filename]", getprogname());
 	exit(1);
 }
 
@@ -230,7 +230,7 @@ cmd_apply(int argc, char *argv[])
 	const char *filename = GOTSYSD_SYSCONF_FILENAME;
 	const char *socket_path = GOTSYSD_UNIX_SOCKET;
 	struct got_commit_object *commit = NULL;
-	int ch, ret, fd = -1, sysconf_fd = -1, gotsysd_sock = -1;
+	int ch, ret, fd = -1, sysconf_fd = -1, gotsysd_sock = -1, wait = 0;
 	FILE *sysconf_file = NULL;
 	struct got_object_id *commit_id = NULL;
 	struct gotsysd_imsg_cmd_sysconf sysconf_cmd;
@@ -239,7 +239,7 @@ cmd_apply(int argc, char *argv[])
 
 	memset(&ibuf, 0, sizeof(ibuf));
 
-	while ((ch = getopt(argc, argv, "f:c:r:")) != -1) {
+	while ((ch = getopt(argc, argv, "f:c:r:w")) != -1) {
 		switch (ch) {
 		case 'c':
 			commit_id_str = optarg;
@@ -256,6 +256,9 @@ cmd_apply(int argc, char *argv[])
 			}
 			got_path_strip_trailing_slashes(repo_path);
 			break;
+		case 'w':
+			wait = 1;
+			break;
 		default:
 			usage_apply();
 			/* NOTREACHED */
@@ -369,38 +372,48 @@ cmd_apply(int argc, char *argv[])
 		goto done;
 	}
 #endif
-	n = imsgbuf_read(&ibuf);
-	if (n == -1) {
-		err = got_error_from_errno("imsgbuf_read");
-		goto done;
-	}
-	if (n == 0) {
-		err = got_error(GOT_ERR_EOF);
-		goto done;
-	}
+	do {
+		n = imsgbuf_read(&ibuf);
+		if (n == -1) {
+			err = got_error_from_errno("imsgbuf_read");
+			goto done;
+		}
+		if (n == 0) {
+			err = got_error(GOT_ERR_EOF);
+			goto done;
+		}
 
-	n = imsg_get(&ibuf, &imsg);
-	if (n == -1) {
-		err = got_error_from_errno("imsg_get");
-		goto done;
-	}
-	if (n == 0) {
-		err = got_error(GOT_ERR_PRIVSEP_READ);
-		goto done;
-	}
+		n = imsg_get(&ibuf, &imsg);
+		if (n == -1) {
+			err = got_error_from_errno("imsg_get");
+			goto done;
+		}
+		if (n == 0) {
+			err = got_error(GOT_ERR_PRIVSEP_READ);
+			goto done;
+		}
 
-	switch (imsg.hdr.type) {
-	case GOTSYSD_IMSG_ERROR:
-		err = recv_error(&imsg);
-		break;
-	case GOTSYSD_IMSG_SYSCONF_STARTED:
-		break;
-	default:
-		err = got_error(GOT_ERR_PRIVSEP_MSG);
-		break;
-	}
+		switch (imsg.hdr.type) {
+		case GOTSYSD_IMSG_ERROR:
+			err = recv_error(&imsg);
+			break;
+		case GOTSYSD_IMSG_SYSCONF_STARTED:
+			break;
+		case GOTSYSD_IMSG_SYSCONF_SUCCESS:
+			printf("sysconf success\n");
+			wait = 0;
+			break;
+		case GOTSYSD_IMSG_SYSCONF_FAILURE:
+			err = got_error_fmt(GOT_ERR_ON_SERVER_SIDE,
+			    "sysconf failure");
+			break;
+		default:
+			err = got_error(GOT_ERR_PRIVSEP_MSG);
+			break;
+		}
 
-	imsg_free(&imsg);
+		imsg_free(&imsg);
+	} while (err == NULL && wait);
 done:
 	imsgbuf_clear(&ibuf);
 	free(repo_path);
blob - e82a68f6c011d5ed50ce21ff9ea6ea50c3beb9e6
blob + 8628a270bcaa8929d1e004abd3806a8d7a407f26
--- gotsysd/gotsysd.c
+++ gotsysd/gotsysd.c
@@ -62,6 +62,7 @@ struct gotsysd_child_proc {
 	int				 pipe[2];
 	struct gotsysd_imsgev		 iev;
 	struct event			 tmo;
+	uint32_t			 client_id;
 
 	TAILQ_ENTRY(gotsysd_child_proc)	 entry;
 };
@@ -70,6 +71,7 @@ static TAILQ_HEAD(gotsysd_procs, gotsysd_child_proc) p
 enum gotsysd_client_state {
 	GOTSYSD_CLIENT_STATE_NEW = -1,
 	GOTSYSD_CLIENT_STATE_ACCESS_GRANTED = 1,
+	GOTSYSD_CLIENT_STATE_SYSCONF_STARTED,
 };
 
 struct gotsysd_client {
@@ -260,6 +262,29 @@ find_client(uint32_t client_id)
 }
 
 static void
+client_sysconf_done(uint32_t client_id, int exit_status)
+{
+	struct gotsysd_client *client;
+	int imsg_code;
+
+	client = find_client(client_id);
+	if (client == NULL)
+		return;
+
+	if (client->state != GOTSYSD_CLIENT_STATE_SYSCONF_STARTED)
+		return;
+
+	if (exit_status == 0)
+	    imsg_code = GOTSYSD_IMSG_SYSCONF_SUCCESS;
+	else
+	    imsg_code = GOTSYSD_IMSG_SYSCONF_FAILURE;
+
+	if (gotsysd_imsg_compose_event(&client->iev, imsg_code,
+	    GOTSYSD_PROC_GOTSYSD, -1, NULL, 0) == -1)
+		log_warn("imsg compose %d", imsg_code);
+}
+
+static void
 disconnect(struct gotsysd_client *client)
 {
 	struct gotsysd_imsg_disconnect idisconnect;
@@ -535,7 +560,8 @@ done:
 }
 
 static const struct got_error *
-start_sysconf_child(int sysconf_fd, struct got_object_id *commit_id)
+start_sysconf_child(int sysconf_fd, struct got_object_id *commit_id,
+    uint32_t client_id)
 {
 	const struct got_error *err = NULL;
 	struct gotsysd_child_proc *proc;
@@ -556,6 +582,7 @@ start_sysconf_child(int sysconf_fd, struct got_object_
 	evtimer_set(&proc->tmo, kill_proc_timeout, proc);
 
 	proc->type = GOTSYSD_PROC_SYSCONF;
+	proc->client_id = client_id;
 
 	log_debug("running system configuration tasks for gotsys.conf from "
 	    "gotsys.git commit %s", commit_id_str);
@@ -607,7 +634,7 @@ sysconf_cmd_timeout(int fd, short ev, void *d)
 
 	STAILQ_REMOVE_HEAD(&gotsysd.sysconf_pending, entry);
 	
-	err = start_sysconf_child(cmd->fd, &cmd->commit_id);
+	err = start_sysconf_child(cmd->fd, &cmd->commit_id, cmd->client_id);
 	if (err) {
 		log_warn("could not start sysconf child process: %s",
 		    err->msg);
@@ -650,7 +677,8 @@ run_sysconf(struct gotsysd_client *client, struct imsg
 		return got_error(GOT_ERR_PRIVSEP_MSG);
 
 	if (gotsysd.sysconf_proc == NULL) {
-		err = start_sysconf_child(sysconf_fd, &sysconf_cmd.commit_id);
+		err = start_sysconf_child(sysconf_fd, &sysconf_cmd.commit_id,
+		    client->id);
 		if (err) {
 			close(sysconf_fd);
 			return err;
@@ -672,6 +700,7 @@ run_sysconf(struct gotsysd_client *client, struct imsg
 		cmd->fd = sysconf_fd;
 		memcpy(&cmd->commit_id, &sysconf_cmd.commit_id,
 		    sizeof(cmd->commit_id));
+		cmd->client_id = client->id;
 		STAILQ_INSERT_TAIL(&gotsysd.sysconf_pending, cmd, entry);
 		evtimer_add(&gotsysd.sysconf_tmo, &tv);
 	}
@@ -681,7 +710,8 @@ run_sysconf(struct gotsysd_client *client, struct imsg
 	    GOTSYSD_IMSG_SYSCONF_STARTED,
 	    GOTSYSD_PROC_GOTSYSD, -1, NULL, 0) == -1) {
 		err = got_error_from_errno("imsg compose SYSCONF_STARTED");
-	}
+	} else
+		client->state = GOTSYSD_CLIENT_STATE_SYSCONF_STARTED;
 
 	return NULL;
 }
@@ -1565,6 +1595,11 @@ gotsysd_sighdlr(int sig, short event, void *arg)
 				    " signal %d", pid, WTERMSIG(status));
 			}
 
+			if (proc->type == GOTSYSD_PROC_SYSCONF) {
+				client_sysconf_done(proc->client_id,
+				    WEXITSTATUS(status));
+			}
+
 			if (proc == gotsysd.sysconf_proc) {
 				gotsysd.sysconf_proc = NULL;
 				if (gotsysd.sysconf_fd != -1) {
blob - caa12c8536fbd38df85ccd0f423054319c1c2bf7
blob + 7b83656193e0ea889cc2cad4af8bf9071bf8cf2a
--- gotsysd/gotsysd.h
+++ gotsysd/gotsysd.h
@@ -91,6 +91,7 @@ struct gotsysd_pending_sysconf_cmd {
 	STAILQ_ENTRY(gotsysd_pending_sysconf_cmd) entry;
 	int fd;
 	struct got_object_id commit_id;
+	uint32_t client_id;
 };
 STAILQ_HEAD(gotsysd_pending_sysconf_cmd_list,
     gotsysd_pending_sysconf_cmd);
@@ -140,11 +141,12 @@ enum gotsysd_imsg_type {
 	GOTSYSD_IMSG_INFO,
 	GOTSYSD_IMSG_CMD_SYSCONF,
 	GOTSYSD_IMSG_SYSCONF_STARTED,
+	GOTSYSD_IMSG_SYSCONF_SUCCESS,
+	GOTSYSD_IMSG_SYSCONF_FAILURE,
 
 	/* Internal sysconf messages. */
 	GOTSYSD_IMSG_SYSCONF_READY,
 	GOTSYSD_IMSG_SYSCONF_FD,
-	GOTSYSD_IMSG_SYSCONF_SUCCESS,
 
 	/* Child processes management. */
 	GOTSYSD_IMSG_CONNECT_PROC,
blob - 870e76a6fec7cb1fd96cdd2f47457c6ab86988d8
blob + d9cb7ba02a04c7708ffd8b434a1ff6d2b567e681
--- include/got_error.h
+++ include/got_error.h
@@ -196,6 +196,7 @@
 #define GOT_ERR_GROUP_EXISTS	179
 #define GOT_ERR_AUTHORIZED_KEY	180
 #define GOT_ERR_CONNECTION_LIMIT 190
+#define GOT_ERR_ON_SERVER_SIDE	191
 
 struct got_error {
         int code;
blob - e2c4a416ee1617c4b2e3953e9addd1d49d65e4f9
blob + 954adb6a419f4fb8c8fb676b9ad79e9160304f70
--- lib/error.c
+++ lib/error.c
@@ -255,6 +255,7 @@ static const struct got_error got_errors[] = {
 	{ GOT_ERR_GROUP_EXISTS, "group already exists" },
 	{ GOT_ERR_AUTHORIZED_KEY, "no authorized key found" },
 	{ GOT_ERR_CONNECTION_LIMIT, "connection limit exceeded" },
+	{ GOT_ERR_ON_SERVER_SIDE, "see server-side logs for error details" },
 };
 
 static struct got_custom_error {