Blame


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