commit fa94c02250118210d63c5161d74c7783e009edcb from: Stefan Sperling via: Thomas Adam date: Fri Mar 21 13:22:46 2025 UTC in gotctl info, display the time when a client connection was created Also ensure that the repository name will always be displayed. Once the repo/session processes had exited the repository name was no longer available. Cache it in the client data structure to avoid losing it. 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. */