Commit Diff


commit - 828d68105770c54c5b80da5adca20224547f14de
commit + fa94c02250118210d63c5161d74c7783e009edcb
blob - b24c2294b66990417a7111b39903692e8f4d83f4
blob + 7e53ad1d4afdc35fe85d43a355359c2326629513
--- gotctl/gotctl.c
+++ gotctl/gotctl.c
@@ -106,26 +106,53 @@ show_repo_info(struct imsg *imsg)
 	return NULL;
 }
 
+static char *
+get_datestr(time_t *time, char *datebuf)
+{
+	struct tm mytm, *tm;
+	char *p, *s;
+
+	tm = localtime_r(time, &mytm);
+	if (tm == NULL)
+		return NULL;
+	s = asctime_r(tm, datebuf);
+	if (s == NULL)
+		return NULL;
+	p = strchr(s, '\n');
+	if (p)
+		*p = '\0';
+	return s;
+}
+
 static const struct got_error *
 show_client_info(struct imsg *imsg)
 {
 	struct gotd_imsg_info_client info;
 	size_t datalen;
+	char *datestr;
+	char datebuf[26];
 
 	datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
 	if (datalen != sizeof(info))
 		return got_error(GOT_ERR_PRIVSEP_LEN);
 	memcpy(&info, imsg->data, sizeof(info));
 
+	datestr = get_datestr(&info.time_connected, datebuf);
+
 	printf("client UID %d, GID %d, ", info.euid, info.egid);
 	if (info.session_child_pid)
 		printf("session PID %ld, ", (long)info.session_child_pid);
 	if (info.repo_child_pid)
 		printf("repo PID %ld, ", (long)info.repo_child_pid);
-	if (info.is_writing)
-		printf("writing to %s\n", info.repo_name);
-	else
-		printf("reading from %s\n", info.repo_name);
+	if (info.is_writing) {
+		printf("writing to %s%s%s\n", info.repo_name,
+		    datestr ? " since " : "",
+		    datestr ? datestr : "");
+	} else {
+		printf("reading from %s%s%s\n", info.repo_name,
+		    datestr ? " since " : "",
+		    datestr ? datestr : "");
+	}
 
 	return NULL;
 }
blob - 5263b61c00e05d1751045a3d5593ae77a45ceaf1
blob + 740edfb7ecbcb748c9f113112c47194c0b2ec07a
--- gotd/gotd.c
+++ gotd/gotd.c
@@ -107,6 +107,8 @@ struct gotd_client {
 	struct gotd_child_proc		*gotsys;
 	int				 required_auth;
 	int				 gotsys_error_sent;
+	struct timespec			 time_connected;
+	char				 repo_name[NAME_MAX];
 };
 STAILQ_HEAD(gotd_clients, gotd_client);
 
@@ -472,22 +474,24 @@ send_client_info(struct gotd_imsgev *iev, struct gotd_
 	iclient.euid = client->euid;
 	iclient.egid = client->egid;
 
+	if (strlcpy(iclient.repo_name, client->repo_name,
+	    sizeof(iclient.repo_name)) >= sizeof(iclient.repo_name)) {
+		return got_error_msg(GOT_ERR_NO_SPACE,
+		    "repo name too long");
+	}
+
 	proc = client->repo;
-	if (proc) {
-		if (strlcpy(iclient.repo_name, proc->repo_name,
-		    sizeof(iclient.repo_name)) >= sizeof(iclient.repo_name)) {
-			return got_error_msg(GOT_ERR_NO_SPACE,
-			    "repo name too long");
-		}
-		if (client_is_writing(client))
-			iclient.is_writing = 1;
-
+	if (proc)
 		iclient.repo_child_pid = proc->pid;
-	}
 
+	if (client_is_writing(client))
+		iclient.is_writing = 1;
+
 	if (client->session)
 		iclient.session_child_pid = client->session->pid;
 
+	iclient.time_connected = client->time_connected.tv_sec;
+
 	if (gotd_imsg_compose_event(iev, GOTD_IMSG_INFO_CLIENT,
 	    GOTD_PROC_GOTD, -1, &iclient, sizeof(iclient)) == -1) {
 		err = got_error_from_errno("imsg compose INFO_CLIENT");
@@ -579,6 +583,11 @@ start_client_authentication(struct gotd_client *client
 		repo = gotd_find_repo_by_name(ireq.repo_name, &gotd.repos);
 		if (repo == NULL)
 			return got_error(GOT_ERR_NOT_GIT_REPO);
+		if (strlcpy(client->repo_name, ireq.repo_name,
+		    sizeof(client->repo_name)) >= sizeof(client->repo_name)) {
+			return got_error_msg(GOT_ERR_NO_SPACE,
+			    "repository name too long");
+		}
 		err = start_auth_child(client, GOTD_AUTH_READ, repo,
 		    gotd.argv0, gotd.confpath, gotd.daemonize,
 		    gotd.verbosity);
@@ -591,6 +600,11 @@ start_client_authentication(struct gotd_client *client
 		repo = gotd_find_repo_by_name(ireq.repo_name, &gotd.repos);
 		if (repo == NULL)
 			return got_error(GOT_ERR_NOT_GIT_REPO);
+		if (strlcpy(client->repo_name, ireq.repo_name,
+		    sizeof(client->repo_name)) >= sizeof(client->repo_name)) {
+			return got_error_msg(GOT_ERR_NO_SPACE,
+			    "repository name too long");
+		}
 		err = start_auth_child(client,
 		    GOTD_AUTH_READ | GOTD_AUTH_WRITE,
 		    repo, gotd.argv0, gotd.confpath, gotd.daemonize,
@@ -734,6 +748,11 @@ recv_connect(uint32_t *client_id, struct imsg *imsg)
 	client->euid = iconnect.euid;
 	client->egid = iconnect.egid;
 
+	if (clock_gettime(CLOCK_REALTIME, &client->time_connected) == -1) {
+		err = got_error_from_errno("clock_gettime");
+		goto done;
+	}
+
 	client->fd = imsg_get_fd(imsg);
 	if (client->fd == -1) {
 		err = got_error(GOT_ERR_PRIVSEP_NO_FD);
blob - c69c5aec37b51fc7e27c92cc522073adf6e92d7a
blob + bc67d2befa7742192232f3c52b8845a86648e643
--- gotd/gotd.h
+++ gotd/gotd.h
@@ -313,6 +313,7 @@ struct gotd_imsg_info_client {
 	int is_writing;
 	pid_t session_child_pid;
 	pid_t repo_child_pid;
+	time_t time_connected;
 };
 
 /* Structure for GOTD_IMSG_LIST_REFS. */