Blame


1 c902213d 2022-10-29 thomas /*
2 c902213d 2022-10-29 thomas * Copyright (c) 2022 Stefan Sperling <stsp@openbsd.org>
3 c902213d 2022-10-29 thomas *
4 c902213d 2022-10-29 thomas * Permission to use, copy, modify, and distribute this software for any
5 c902213d 2022-10-29 thomas * purpose with or without fee is hereby granted, provided that the above
6 c902213d 2022-10-29 thomas * copyright notice and this permission notice appear in all copies.
7 c902213d 2022-10-29 thomas *
8 c902213d 2022-10-29 thomas * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 c902213d 2022-10-29 thomas * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 c902213d 2022-10-29 thomas * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 c902213d 2022-10-29 thomas * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 c902213d 2022-10-29 thomas * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 c902213d 2022-10-29 thomas * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 c902213d 2022-10-29 thomas * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 c902213d 2022-10-29 thomas */
16 c902213d 2022-10-29 thomas
17 c902213d 2022-10-29 thomas #include <sys/queue.h>
18 c902213d 2022-10-29 thomas #include <sys/socket.h>
19 c902213d 2022-10-29 thomas #include <sys/un.h>
20 c902213d 2022-10-29 thomas
21 c902213d 2022-10-29 thomas #include <err.h>
22 c902213d 2022-10-29 thomas #include <event.h>
23 c902213d 2022-10-29 thomas #include <imsg.h>
24 c902213d 2022-10-29 thomas #include <limits.h>
25 c902213d 2022-10-29 thomas #include <locale.h>
26 c902213d 2022-10-29 thomas #include <sha1.h>
27 c902213d 2022-10-29 thomas #include <stdio.h>
28 c902213d 2022-10-29 thomas #include <stdlib.h>
29 c902213d 2022-10-29 thomas #include <string.h>
30 c902213d 2022-10-29 thomas #include <getopt.h>
31 c902213d 2022-10-29 thomas #include <unistd.h>
32 c902213d 2022-10-29 thomas
33 c902213d 2022-10-29 thomas #include "got_error.h"
34 c902213d 2022-10-29 thomas #include "got_version.h"
35 c902213d 2022-10-29 thomas
36 c902213d 2022-10-29 thomas #include "got_lib_gitproto.h"
37 c902213d 2022-10-29 thomas
38 c902213d 2022-10-29 thomas #include "gotd.h"
39 c902213d 2022-10-29 thomas
40 c902213d 2022-10-29 thomas #ifndef nitems
41 c902213d 2022-10-29 thomas #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
42 c902213d 2022-10-29 thomas #endif
43 c902213d 2022-10-29 thomas
44 c902213d 2022-10-29 thomas #define GOTCTL_CMD_INFO "info"
45 c902213d 2022-10-29 thomas #define GOTCTL_CMD_STOP "stop"
46 c902213d 2022-10-29 thomas
47 c902213d 2022-10-29 thomas struct gotctl_cmd {
48 c902213d 2022-10-29 thomas const char *cmd_name;
49 c902213d 2022-10-29 thomas const struct got_error *(*cmd_main)(int, char *[], int);
50 c902213d 2022-10-29 thomas void (*cmd_usage)(void);
51 c902213d 2022-10-29 thomas };
52 c902213d 2022-10-29 thomas
53 c902213d 2022-10-29 thomas __dead static void usage(int, int);
54 c902213d 2022-10-29 thomas
55 c902213d 2022-10-29 thomas __dead static void usage_info(void);
56 c902213d 2022-10-29 thomas __dead static void usage_stop(void);
57 c902213d 2022-10-29 thomas
58 c902213d 2022-10-29 thomas static const struct got_error* cmd_info(int, char *[], int);
59 c902213d 2022-10-29 thomas static const struct got_error* cmd_stop(int, char *[], int);
60 c902213d 2022-10-29 thomas
61 c902213d 2022-10-29 thomas static const struct gotctl_cmd gotctl_commands[] = {
62 c902213d 2022-10-29 thomas { "info", cmd_info, usage_info },
63 c902213d 2022-10-29 thomas { "stop", cmd_stop, usage_stop },
64 c902213d 2022-10-29 thomas };
65 c902213d 2022-10-29 thomas
66 c902213d 2022-10-29 thomas __dead static void
67 c902213d 2022-10-29 thomas usage_info(void)
68 c902213d 2022-10-29 thomas {
69 c902213d 2022-10-29 thomas fprintf(stderr, "usage: %s info\n", getprogname());
70 c902213d 2022-10-29 thomas exit(1);
71 c902213d 2022-10-29 thomas }
72 c902213d 2022-10-29 thomas
73 c902213d 2022-10-29 thomas static const struct got_error *
74 c902213d 2022-10-29 thomas show_info(struct imsg *imsg)
75 c902213d 2022-10-29 thomas {
76 c902213d 2022-10-29 thomas struct gotd_imsg_info info;
77 c902213d 2022-10-29 thomas size_t datalen;
78 c902213d 2022-10-29 thomas
79 c902213d 2022-10-29 thomas datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
80 c902213d 2022-10-29 thomas if (datalen != sizeof(info))
81 c902213d 2022-10-29 thomas return got_error(GOT_ERR_PRIVSEP_LEN);
82 c902213d 2022-10-29 thomas memcpy(&info, imsg->data, sizeof(info));
83 c902213d 2022-10-29 thomas
84 c902213d 2022-10-29 thomas printf("gotd PID: %d\n", info.pid);
85 c902213d 2022-10-29 thomas printf("verbosity: %d\n", info.verbosity);
86 c902213d 2022-10-29 thomas printf("number of repositories: %d\n", info.nrepos);
87 c902213d 2022-10-29 thomas printf("number of connected clients: %d\n", info.nclients);
88 c902213d 2022-10-29 thomas return NULL;
89 c902213d 2022-10-29 thomas }
90 c902213d 2022-10-29 thomas
91 c902213d 2022-10-29 thomas static const struct got_error *
92 c902213d 2022-10-29 thomas show_repo_info(struct imsg *imsg)
93 c902213d 2022-10-29 thomas {
94 c902213d 2022-10-29 thomas struct gotd_imsg_info_repo info;
95 c902213d 2022-10-29 thomas size_t datalen;
96 c902213d 2022-10-29 thomas
97 c902213d 2022-10-29 thomas datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
98 c902213d 2022-10-29 thomas if (datalen != sizeof(info))
99 c902213d 2022-10-29 thomas return got_error(GOT_ERR_PRIVSEP_LEN);
100 c902213d 2022-10-29 thomas memcpy(&info, imsg->data, sizeof(info));
101 c902213d 2022-10-29 thomas
102 c902213d 2022-10-29 thomas printf("repository \"%s\", path %s\n", info.repo_name, info.repo_path);
103 c902213d 2022-10-29 thomas return NULL;
104 c902213d 2022-10-29 thomas }
105 c902213d 2022-10-29 thomas
106 c902213d 2022-10-29 thomas static const char *
107 c902213d 2022-10-29 thomas get_state_name(enum gotd_client_state state)
108 c902213d 2022-10-29 thomas {
109 c902213d 2022-10-29 thomas static char unknown_state[64];
110 c902213d 2022-10-29 thomas
111 c902213d 2022-10-29 thomas switch (state) {
112 c902213d 2022-10-29 thomas case GOTD_STATE_EXPECT_LIST_REFS:
113 c902213d 2022-10-29 thomas return "list-refs";
114 c902213d 2022-10-29 thomas case GOTD_STATE_EXPECT_CAPABILITIES:
115 c902213d 2022-10-29 thomas return "expect-capabilities";
116 c902213d 2022-10-29 thomas case GOTD_STATE_EXPECT_WANT:
117 c902213d 2022-10-29 thomas return "expect-want";
118 c902213d 2022-10-29 thomas case GOTD_STATE_EXPECT_REF_UPDATE:
119 c902213d 2022-10-29 thomas return "expect-ref-update";
120 c902213d 2022-10-29 thomas case GOTD_STATE_EXPECT_MORE_REF_UPDATES:
121 c902213d 2022-10-29 thomas return "expect-more-ref-updates";
122 c902213d 2022-10-29 thomas case GOTD_STATE_EXPECT_HAVE:
123 c902213d 2022-10-29 thomas return "expect-have";
124 c902213d 2022-10-29 thomas case GOTD_STATE_EXPECT_PACKFILE:
125 c902213d 2022-10-29 thomas return "expect-packfile";
126 c902213d 2022-10-29 thomas case GOTD_STATE_EXPECT_DONE:
127 c902213d 2022-10-29 thomas return "expect-done";
128 c902213d 2022-10-29 thomas case GOTD_STATE_DONE:
129 c902213d 2022-10-29 thomas return "done";
130 c902213d 2022-10-29 thomas }
131 c902213d 2022-10-29 thomas
132 c902213d 2022-10-29 thomas snprintf(unknown_state, sizeof(unknown_state),
133 c902213d 2022-10-29 thomas "unknown state %d", state);
134 c902213d 2022-10-29 thomas return unknown_state;
135 c902213d 2022-10-29 thomas }
136 c902213d 2022-10-29 thomas
137 c902213d 2022-10-29 thomas static const struct got_error *
138 c902213d 2022-10-29 thomas show_client_info(struct imsg *imsg)
139 c902213d 2022-10-29 thomas {
140 c902213d 2022-10-29 thomas struct gotd_imsg_info_client info;
141 c902213d 2022-10-29 thomas size_t datalen;
142 c902213d 2022-10-29 thomas
143 c902213d 2022-10-29 thomas datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
144 c902213d 2022-10-29 thomas if (datalen != sizeof(info))
145 c902213d 2022-10-29 thomas return got_error(GOT_ERR_PRIVSEP_LEN);
146 c902213d 2022-10-29 thomas memcpy(&info, imsg->data, sizeof(info));
147 c902213d 2022-10-29 thomas
148 c902213d 2022-10-29 thomas printf("client UID %d, GID %d, protocol state '%s', ",
149 c902213d 2022-10-29 thomas info.euid, info.egid, get_state_name(info.state));
150 62ee7d94 2023-01-10 thomas if (info.session_child_pid)
151 62ee7d94 2023-01-10 thomas printf("session PID %ld, ", (long)info.session_child_pid);
152 62ee7d94 2023-01-10 thomas if (info.repo_child_pid)
153 62ee7d94 2023-01-10 thomas printf("repo PID %ld, ", (long)info.repo_child_pid);
154 c902213d 2022-10-29 thomas if (info.is_writing)
155 c902213d 2022-10-29 thomas printf("writing to %s\n", info.repo_name);
156 c902213d 2022-10-29 thomas else
157 c902213d 2022-10-29 thomas printf("reading from %s\n", info.repo_name);
158 c902213d 2022-10-29 thomas
159 c902213d 2022-10-29 thomas return NULL;
160 c902213d 2022-10-29 thomas }
161 c902213d 2022-10-29 thomas
162 c902213d 2022-10-29 thomas static const struct got_error *
163 c902213d 2022-10-29 thomas show_capability(struct imsg *imsg)
164 c902213d 2022-10-29 thomas {
165 c902213d 2022-10-29 thomas struct gotd_imsg_capability icapa;
166 c902213d 2022-10-29 thomas size_t datalen;
167 c902213d 2022-10-29 thomas char *key, *value = NULL;
168 c902213d 2022-10-29 thomas
169 c902213d 2022-10-29 thomas memset(&icapa, 0, sizeof(icapa));
170 c902213d 2022-10-29 thomas
171 c902213d 2022-10-29 thomas datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
172 c902213d 2022-10-29 thomas if (datalen < sizeof(icapa))
173 c902213d 2022-10-29 thomas return got_error(GOT_ERR_PRIVSEP_LEN);
174 c902213d 2022-10-29 thomas memcpy(&icapa, imsg->data, sizeof(icapa));
175 c902213d 2022-10-29 thomas
176 c902213d 2022-10-29 thomas if (datalen != sizeof(icapa) + icapa.key_len + icapa.value_len)
177 c902213d 2022-10-29 thomas return got_error(GOT_ERR_PRIVSEP_LEN);
178 c902213d 2022-10-29 thomas
179 c902213d 2022-10-29 thomas key = malloc(icapa.key_len + 1);
180 c902213d 2022-10-29 thomas if (key == NULL)
181 c902213d 2022-10-29 thomas return got_error_from_errno("malloc");
182 c902213d 2022-10-29 thomas if (icapa.value_len > 0) {
183 c902213d 2022-10-29 thomas value = malloc(icapa.value_len + 1);
184 c902213d 2022-10-29 thomas if (value == NULL) {
185 c902213d 2022-10-29 thomas free(key);
186 c902213d 2022-10-29 thomas return got_error_from_errno("malloc");
187 c902213d 2022-10-29 thomas }
188 c902213d 2022-10-29 thomas }
189 c902213d 2022-10-29 thomas
190 c902213d 2022-10-29 thomas memcpy(key, imsg->data + sizeof(icapa), icapa.key_len);
191 c902213d 2022-10-29 thomas key[icapa.key_len] = '\0';
192 c902213d 2022-10-29 thomas if (value) {
193 c902213d 2022-10-29 thomas memcpy(value, imsg->data + sizeof(icapa) + icapa.key_len,
194 c902213d 2022-10-29 thomas icapa.value_len);
195 c902213d 2022-10-29 thomas value[icapa.value_len] = '\0';
196 c902213d 2022-10-29 thomas }
197 c902213d 2022-10-29 thomas
198 c902213d 2022-10-29 thomas if (strcmp(key, GOT_CAPA_AGENT) == 0)
199 c902213d 2022-10-29 thomas printf(" client user agent: %s\n", value);
200 c902213d 2022-10-29 thomas else if (value)
201 c902213d 2022-10-29 thomas printf(" client supports %s=%s\n", key, value);
202 c902213d 2022-10-29 thomas else
203 c902213d 2022-10-29 thomas printf(" client supports %s\n", key);
204 c902213d 2022-10-29 thomas
205 c902213d 2022-10-29 thomas free(key);
206 c902213d 2022-10-29 thomas free(value);
207 c902213d 2022-10-29 thomas return NULL;
208 c902213d 2022-10-29 thomas }
209 c902213d 2022-10-29 thomas
210 c902213d 2022-10-29 thomas static const struct got_error *
211 c902213d 2022-10-29 thomas cmd_info(int argc, char *argv[], int gotd_sock)
212 c902213d 2022-10-29 thomas {
213 c902213d 2022-10-29 thomas const struct got_error *err;
214 c902213d 2022-10-29 thomas struct imsgbuf ibuf;
215 c902213d 2022-10-29 thomas struct imsg imsg;
216 c902213d 2022-10-29 thomas
217 c902213d 2022-10-29 thomas imsg_init(&ibuf, gotd_sock);
218 c902213d 2022-10-29 thomas
219 c902213d 2022-10-29 thomas if (imsg_compose(&ibuf, GOTD_IMSG_INFO, 0, 0, -1, NULL, 0) == -1)
220 c902213d 2022-10-29 thomas return got_error_from_errno("imsg_compose INFO");
221 c902213d 2022-10-29 thomas
222 c902213d 2022-10-29 thomas err = gotd_imsg_flush(&ibuf);
223 c902213d 2022-10-29 thomas while (err == NULL) {
224 c902213d 2022-10-29 thomas err = gotd_imsg_poll_recv(&imsg, &ibuf, 0);
225 c902213d 2022-10-29 thomas if (err) {
226 c902213d 2022-10-29 thomas if (err->code == GOT_ERR_EOF)
227 c902213d 2022-10-29 thomas err = NULL;
228 c902213d 2022-10-29 thomas break;
229 c902213d 2022-10-29 thomas }
230 c902213d 2022-10-29 thomas
231 c902213d 2022-10-29 thomas switch (imsg.hdr.type) {
232 c902213d 2022-10-29 thomas case GOTD_IMSG_ERROR:
233 c902213d 2022-10-29 thomas err = gotd_imsg_recv_error(NULL, &imsg);
234 c902213d 2022-10-29 thomas break;
235 c902213d 2022-10-29 thomas case GOTD_IMSG_INFO:
236 c902213d 2022-10-29 thomas err = show_info(&imsg);
237 c902213d 2022-10-29 thomas break;
238 c902213d 2022-10-29 thomas case GOTD_IMSG_INFO_REPO:
239 c902213d 2022-10-29 thomas err = show_repo_info(&imsg);
240 c902213d 2022-10-29 thomas break;
241 c902213d 2022-10-29 thomas case GOTD_IMSG_INFO_CLIENT:
242 c902213d 2022-10-29 thomas err = show_client_info(&imsg);
243 c902213d 2022-10-29 thomas break;
244 c902213d 2022-10-29 thomas case GOTD_IMSG_CAPABILITY:
245 c902213d 2022-10-29 thomas err = show_capability(&imsg);
246 c902213d 2022-10-29 thomas break;
247 c902213d 2022-10-29 thomas default:
248 c902213d 2022-10-29 thomas err = got_error(GOT_ERR_PRIVSEP_MSG);
249 c902213d 2022-10-29 thomas break;
250 c902213d 2022-10-29 thomas }
251 c902213d 2022-10-29 thomas
252 c902213d 2022-10-29 thomas imsg_free(&imsg);
253 c902213d 2022-10-29 thomas }
254 c902213d 2022-10-29 thomas
255 c902213d 2022-10-29 thomas imsg_clear(&ibuf);
256 c902213d 2022-10-29 thomas return err;
257 c902213d 2022-10-29 thomas }
258 c902213d 2022-10-29 thomas
259 c902213d 2022-10-29 thomas __dead static void
260 c902213d 2022-10-29 thomas usage_stop(void)
261 c902213d 2022-10-29 thomas {
262 c902213d 2022-10-29 thomas fprintf(stderr, "usage: %s stop\n", getprogname());
263 c902213d 2022-10-29 thomas exit(1);
264 c902213d 2022-10-29 thomas }
265 c902213d 2022-10-29 thomas
266 c902213d 2022-10-29 thomas static const struct got_error *
267 c902213d 2022-10-29 thomas cmd_stop(int argc, char *argv[], int gotd_sock)
268 c902213d 2022-10-29 thomas {
269 c902213d 2022-10-29 thomas const struct got_error *err;
270 c902213d 2022-10-29 thomas struct imsgbuf ibuf;
271 c902213d 2022-10-29 thomas struct imsg imsg;
272 c902213d 2022-10-29 thomas
273 c902213d 2022-10-29 thomas imsg_init(&ibuf, gotd_sock);
274 c902213d 2022-10-29 thomas
275 c902213d 2022-10-29 thomas if (imsg_compose(&ibuf, GOTD_IMSG_STOP, 0, 0, -1, NULL, 0) == -1)
276 c902213d 2022-10-29 thomas return got_error_from_errno("imsg_compose STOP");
277 c902213d 2022-10-29 thomas
278 c902213d 2022-10-29 thomas err = gotd_imsg_flush(&ibuf);
279 c902213d 2022-10-29 thomas while (err == NULL) {
280 c902213d 2022-10-29 thomas err = gotd_imsg_poll_recv(&imsg, &ibuf, 0);
281 c902213d 2022-10-29 thomas if (err) {
282 c902213d 2022-10-29 thomas if (err->code == GOT_ERR_EOF)
283 c902213d 2022-10-29 thomas err = NULL;
284 c902213d 2022-10-29 thomas break;
285 c902213d 2022-10-29 thomas }
286 c902213d 2022-10-29 thomas
287 c902213d 2022-10-29 thomas switch (imsg.hdr.type) {
288 c902213d 2022-10-29 thomas case GOTD_IMSG_ERROR:
289 c902213d 2022-10-29 thomas err = gotd_imsg_recv_error(NULL, &imsg);
290 c902213d 2022-10-29 thomas break;
291 c902213d 2022-10-29 thomas default:
292 c902213d 2022-10-29 thomas err = got_error(GOT_ERR_PRIVSEP_MSG);
293 c902213d 2022-10-29 thomas break;
294 c902213d 2022-10-29 thomas }
295 c902213d 2022-10-29 thomas
296 c902213d 2022-10-29 thomas imsg_free(&imsg);
297 c902213d 2022-10-29 thomas }
298 c902213d 2022-10-29 thomas
299 c902213d 2022-10-29 thomas imsg_clear(&ibuf);
300 c902213d 2022-10-29 thomas return err;
301 c902213d 2022-10-29 thomas }
302 c902213d 2022-10-29 thomas
303 c902213d 2022-10-29 thomas static void
304 c902213d 2022-10-29 thomas list_commands(FILE *fp)
305 c902213d 2022-10-29 thomas {
306 c902213d 2022-10-29 thomas size_t i;
307 c902213d 2022-10-29 thomas
308 c902213d 2022-10-29 thomas fprintf(fp, "commands:");
309 c902213d 2022-10-29 thomas for (i = 0; i < nitems(gotctl_commands); i++) {
310 c902213d 2022-10-29 thomas const struct gotctl_cmd *cmd = &gotctl_commands[i];
311 c902213d 2022-10-29 thomas fprintf(fp, " %s", cmd->cmd_name);
312 c902213d 2022-10-29 thomas }
313 c902213d 2022-10-29 thomas fputc('\n', fp);
314 c902213d 2022-10-29 thomas }
315 c902213d 2022-10-29 thomas
316 c902213d 2022-10-29 thomas __dead static void
317 c902213d 2022-10-29 thomas usage(int hflag, int status)
318 c902213d 2022-10-29 thomas {
319 c902213d 2022-10-29 thomas FILE *fp = (status == 0) ? stdout : stderr;
320 c902213d 2022-10-29 thomas
321 c691a00e 2022-11-17 thomas fprintf(fp, "usage: %s [-hV] [-f path] command [arg ...]\n",
322 c902213d 2022-10-29 thomas getprogname());
323 c902213d 2022-10-29 thomas if (hflag)
324 c902213d 2022-10-29 thomas list_commands(fp);
325 c902213d 2022-10-29 thomas exit(status);
326 c902213d 2022-10-29 thomas }
327 c902213d 2022-10-29 thomas
328 c902213d 2022-10-29 thomas static const struct got_error *
329 c902213d 2022-10-29 thomas apply_unveil(const char *unix_socket_path)
330 c902213d 2022-10-29 thomas {
331 c902213d 2022-10-29 thomas #ifdef PROFILE
332 c902213d 2022-10-29 thomas if (unveil("gmon.out", "rwc") != 0)
333 c902213d 2022-10-29 thomas return got_error_from_errno2("unveil", "gmon.out");
334 c902213d 2022-10-29 thomas #endif
335 c902213d 2022-10-29 thomas if (unveil(unix_socket_path, "w") != 0)
336 c902213d 2022-10-29 thomas return got_error_from_errno2("unveil", unix_socket_path);
337 c902213d 2022-10-29 thomas
338 c902213d 2022-10-29 thomas if (unveil(NULL, NULL) != 0)
339 c902213d 2022-10-29 thomas return got_error_from_errno("unveil");
340 c902213d 2022-10-29 thomas
341 c902213d 2022-10-29 thomas return NULL;
342 c902213d 2022-10-29 thomas }
343 c902213d 2022-10-29 thomas
344 c902213d 2022-10-29 thomas static int
345 c902213d 2022-10-29 thomas connect_gotd(const char *socket_path)
346 c902213d 2022-10-29 thomas {
347 c902213d 2022-10-29 thomas const struct got_error *error = NULL;
348 c902213d 2022-10-29 thomas int gotd_sock = -1;
349 c902213d 2022-10-29 thomas struct sockaddr_un sun;
350 c902213d 2022-10-29 thomas
351 4f218b0c 2022-10-30 thomas error = apply_unveil(socket_path);
352 c902213d 2022-10-29 thomas if (error)
353 c902213d 2022-10-29 thomas errx(1, "%s", error->msg);
354 c902213d 2022-10-29 thomas
355 c902213d 2022-10-29 thomas #ifndef PROFILE
356 c902213d 2022-10-29 thomas if (pledge("stdio unix", NULL) == -1)
357 c902213d 2022-10-29 thomas err(1, "pledge");
358 c902213d 2022-10-29 thomas #endif
359 c902213d 2022-10-29 thomas if ((gotd_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
360 c902213d 2022-10-29 thomas err(1, "socket");
361 c902213d 2022-10-29 thomas
362 c902213d 2022-10-29 thomas memset(&sun, 0, sizeof(sun));
363 c902213d 2022-10-29 thomas sun.sun_family = AF_UNIX;
364 4f218b0c 2022-10-30 thomas if (strlcpy(sun.sun_path, socket_path, sizeof(sun.sun_path)) >=
365 4f218b0c 2022-10-30 thomas sizeof(sun.sun_path))
366 c902213d 2022-10-29 thomas errx(1, "gotd socket path too long");
367 c902213d 2022-10-29 thomas if (connect(gotd_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1)
368 4f218b0c 2022-10-30 thomas err(1, "connect: %s", socket_path);
369 c902213d 2022-10-29 thomas
370 c902213d 2022-10-29 thomas #ifndef PROFILE
371 c902213d 2022-10-29 thomas if (pledge("stdio", NULL) == -1)
372 c902213d 2022-10-29 thomas err(1, "pledge");
373 c902213d 2022-10-29 thomas #endif
374 c902213d 2022-10-29 thomas
375 c902213d 2022-10-29 thomas return gotd_sock;
376 c902213d 2022-10-29 thomas }
377 c902213d 2022-10-29 thomas
378 c902213d 2022-10-29 thomas int
379 c902213d 2022-10-29 thomas main(int argc, char *argv[])
380 c902213d 2022-10-29 thomas {
381 c902213d 2022-10-29 thomas const struct gotctl_cmd *cmd;
382 c902213d 2022-10-29 thomas int gotd_sock = -1, i;
383 c902213d 2022-10-29 thomas int ch;
384 c902213d 2022-10-29 thomas int hflag = 0, Vflag = 0;
385 c902213d 2022-10-29 thomas static const struct option longopts[] = {
386 c902213d 2022-10-29 thomas { "version", no_argument, NULL, 'V' },
387 c902213d 2022-10-29 thomas { NULL, 0, NULL, 0 }
388 c902213d 2022-10-29 thomas };
389 4f218b0c 2022-10-30 thomas const char *socket_path = GOTD_UNIX_SOCKET;
390 c902213d 2022-10-29 thomas
391 c902213d 2022-10-29 thomas setlocale(LC_CTYPE, "");
392 c902213d 2022-10-29 thomas
393 c902213d 2022-10-29 thomas #ifndef PROFILE
394 c902213d 2022-10-29 thomas if (pledge("stdio unix unveil", NULL) == -1)
395 c902213d 2022-10-29 thomas err(1, "pledge");
396 c902213d 2022-10-29 thomas #endif
397 c902213d 2022-10-29 thomas
398 c902213d 2022-10-29 thomas while ((ch = getopt_long(argc, argv, "+hf:V", longopts, NULL)) != -1) {
399 c902213d 2022-10-29 thomas switch (ch) {
400 c902213d 2022-10-29 thomas case 'h':
401 c902213d 2022-10-29 thomas hflag = 1;
402 c902213d 2022-10-29 thomas break;
403 c902213d 2022-10-29 thomas case 'f':
404 c902213d 2022-10-29 thomas socket_path = optarg;
405 c902213d 2022-10-29 thomas break;
406 c902213d 2022-10-29 thomas case 'V':
407 c902213d 2022-10-29 thomas Vflag = 1;
408 c902213d 2022-10-29 thomas break;
409 c902213d 2022-10-29 thomas default:
410 c902213d 2022-10-29 thomas usage(hflag, 1);
411 c902213d 2022-10-29 thomas /* NOTREACHED */
412 c902213d 2022-10-29 thomas }
413 c902213d 2022-10-29 thomas }
414 c902213d 2022-10-29 thomas
415 c902213d 2022-10-29 thomas argc -= optind;
416 c902213d 2022-10-29 thomas argv += optind;
417 c902213d 2022-10-29 thomas optind = 1;
418 c902213d 2022-10-29 thomas optreset = 1;
419 c902213d 2022-10-29 thomas
420 c902213d 2022-10-29 thomas if (Vflag) {
421 c902213d 2022-10-29 thomas got_version_print_str();
422 c902213d 2022-10-29 thomas return 0;
423 c902213d 2022-10-29 thomas }
424 c902213d 2022-10-29 thomas
425 c902213d 2022-10-29 thomas if (argc <= 0)
426 c902213d 2022-10-29 thomas usage(hflag, hflag ? 0 : 1);
427 c902213d 2022-10-29 thomas
428 c902213d 2022-10-29 thomas for (i = 0; i < nitems(gotctl_commands); i++) {
429 c902213d 2022-10-29 thomas const struct got_error *error;
430 c902213d 2022-10-29 thomas
431 c902213d 2022-10-29 thomas cmd = &gotctl_commands[i];
432 c902213d 2022-10-29 thomas
433 c902213d 2022-10-29 thomas if (strncmp(cmd->cmd_name, argv[0], strlen(argv[0])) != 0)
434 c902213d 2022-10-29 thomas continue;
435 c902213d 2022-10-29 thomas
436 c902213d 2022-10-29 thomas if (hflag)
437 c902213d 2022-10-29 thomas cmd->cmd_usage();
438 c902213d 2022-10-29 thomas
439 c902213d 2022-10-29 thomas gotd_sock = connect_gotd(socket_path);
440 c902213d 2022-10-29 thomas if (gotd_sock == -1)
441 c902213d 2022-10-29 thomas return 1;
442 c902213d 2022-10-29 thomas error = cmd->cmd_main(argc, argv, gotd_sock);
443 c902213d 2022-10-29 thomas close(gotd_sock);
444 c902213d 2022-10-29 thomas if (error) {
445 c902213d 2022-10-29 thomas fprintf(stderr, "%s: %s\n", getprogname(), error->msg);
446 c902213d 2022-10-29 thomas return 1;
447 c902213d 2022-10-29 thomas }
448 c902213d 2022-10-29 thomas
449 c902213d 2022-10-29 thomas return 0;
450 c902213d 2022-10-29 thomas }
451 c902213d 2022-10-29 thomas
452 c902213d 2022-10-29 thomas fprintf(stderr, "%s: unknown command '%s'\n", getprogname(), argv[0]);
453 c902213d 2022-10-29 thomas list_commands(stderr);
454 c902213d 2022-10-29 thomas return 1;
455 c902213d 2022-10-29 thomas }