]> git.ipfire.org Git - thirdparty/git.git/blame - credential-cache.c
Merge branch 'nd/mv-code-cleaning'
[thirdparty/git.git] / credential-cache.c
CommitLineData
e2770979
JK
1#include "cache.h"
2#include "credential.h"
3#include "string-list.h"
4#include "parse-options.h"
5#include "unix-socket.h"
6#include "run-command.h"
7
8#define FLAG_SPAWN 0x1
9#define FLAG_RELAY 0x2
10
11static int send_request(const char *socket, const struct strbuf *out)
12{
13 int got_data = 0;
14 int fd = unix_stream_connect(socket);
15
16 if (fd < 0)
17 return -1;
18
19 if (write_in_full(fd, out->buf, out->len) < 0)
20 die_errno("unable to write to cache daemon");
21 shutdown(fd, SHUT_WR);
22
23 while (1) {
24 char in[1024];
25 int r;
26
27 r = read_in_full(fd, in, sizeof(in));
28 if (r == 0)
29 break;
30 if (r < 0)
31 die_errno("read error from cache daemon");
32 write_or_die(1, in, r);
33 got_data = 1;
34 }
35 return got_data;
36}
37
38static void spawn_daemon(const char *socket)
39{
d3180279 40 struct child_process daemon = CHILD_PROCESS_INIT;
e2770979
JK
41 const char *argv[] = { NULL, NULL, NULL };
42 char buf[128];
43 int r;
44
e2770979
JK
45 argv[0] = "git-credential-cache--daemon";
46 argv[1] = socket;
47 daemon.argv = argv;
48 daemon.no_stdin = 1;
49 daemon.out = -1;
50
51 if (start_command(&daemon))
52 die_errno("unable to start cache daemon");
53 r = read_in_full(daemon.out, buf, sizeof(buf));
54 if (r < 0)
55 die_errno("unable to read result code from cache daemon");
56 if (r != 3 || memcmp(buf, "ok\n", 3))
57 die("cache daemon did not start: %.*s", r, buf);
58 close(daemon.out);
59}
60
61static void do_cache(const char *socket, const char *action, int timeout,
62 int flags)
63{
64 struct strbuf buf = STRBUF_INIT;
65
66 strbuf_addf(&buf, "action=%s\n", action);
67 strbuf_addf(&buf, "timeout=%d\n", timeout);
68 if (flags & FLAG_RELAY) {
69 if (strbuf_read(&buf, 0, 0) < 0)
70 die_errno("unable to relay credential");
71 }
72
8ec6c8d7 73 if (send_request(socket, &buf) < 0) {
35a71f14 74 if (errno != ENOENT && errno != ECONNREFUSED)
98c2924c 75 die_errno("unable to connect to cache daemon");
8ec6c8d7
JK
76 if (flags & FLAG_SPAWN) {
77 spawn_daemon(socket);
78 if (send_request(socket, &buf) < 0)
79 die_errno("unable to connect to cache daemon");
80 }
e2770979
JK
81 }
82 strbuf_release(&buf);
83}
84
85int main(int argc, const char **argv)
86{
87 char *socket_path = NULL;
88 int timeout = 900;
89 const char *op;
90 const char * const usage[] = {
91 "git credential-cache [options] <action>",
92 NULL
93 };
94 struct option options[] = {
95 OPT_INTEGER(0, "timeout", &timeout,
96 "number of seconds to cache credentials"),
97 OPT_STRING(0, "socket", &socket_path, "path",
98 "path of cache-daemon socket"),
99 OPT_END()
100 };
101
102 argc = parse_options(argc, argv, NULL, options, usage, 0);
103 if (!argc)
104 usage_with_options(usage, options);
105 op = argv[0];
106
107 if (!socket_path)
108 socket_path = expand_user_path("~/.git-credential-cache/socket");
109 if (!socket_path)
110 die("unable to find a suitable socket path; use --socket");
111
112 if (!strcmp(op, "exit"))
113 do_cache(socket_path, op, timeout, 0);
114 else if (!strcmp(op, "get") || !strcmp(op, "erase"))
115 do_cache(socket_path, op, timeout, FLAG_RELAY);
116 else if (!strcmp(op, "store"))
117 do_cache(socket_path, op, timeout, FLAG_RELAY|FLAG_SPAWN);
118 else
119 ; /* ignore unknown operation */
120
121 return 0;
122}