2 #include "credential.h"
4 #include "parse-options.h"
7 #include "write-or-die.h"
9 #ifndef NO_UNIX_SOCKETS
11 #include "unix-socket.h"
12 #include "run-command.h"
14 #define FLAG_SPAWN 0x1
15 #define FLAG_RELAY 0x2
17 #ifdef GIT_WINDOWS_NATIVE
19 static int connection_closed(int error
)
21 return (error
== EINVAL
);
24 static int connection_fatally_broken(int error
)
26 return (error
!= ENOENT
) && (error
!= ENETDOWN
);
31 static int connection_closed(int error
)
33 return error
== ECONNRESET
|| error
== ECONNABORTED
;
36 static int connection_fatally_broken(int error
)
38 return (error
!= ENOENT
) && (error
!= ECONNREFUSED
);
43 static int send_request(const char *socket
, const struct strbuf
*out
)
46 int fd
= unix_stream_connect(socket
, 0);
51 if (write_in_full(fd
, out
->buf
, out
->len
) < 0)
52 die_errno("unable to write to cache daemon");
53 shutdown(fd
, SHUT_WR
);
59 r
= read_in_full(fd
, in
, sizeof(in
));
60 if (r
== 0 || (r
< 0 && connection_closed(errno
)))
63 die_errno("read error from cache daemon");
64 write_or_die(1, in
, r
);
71 static void spawn_daemon(const char *socket
)
73 struct child_process daemon
= CHILD_PROCESS_INIT
;
77 strvec_pushl(&daemon
.args
,
78 "credential-cache--daemon", socket
,
84 if (start_command(&daemon
))
85 die_errno("unable to start cache daemon");
86 r
= read_in_full(daemon
.out
, buf
, sizeof(buf
));
88 die_errno("unable to read result code from cache daemon");
89 if (r
!= 3 || memcmp(buf
, "ok\n", 3))
90 die("cache daemon did not start: %.*s", r
, buf
);
92 child_process_clear(&daemon
);
96 static void do_cache(const char *socket
, const char *action
, int timeout
,
99 struct strbuf buf
= STRBUF_INIT
;
101 strbuf_addf(&buf
, "action=%s\n", action
);
102 strbuf_addf(&buf
, "timeout=%d\n", timeout
);
103 if (flags
& FLAG_RELAY
) {
104 if (strbuf_read(&buf
, 0, 0) < 0)
105 die_errno("unable to relay credential");
108 if (send_request(socket
, &buf
) < 0) {
109 if (connection_fatally_broken(errno
))
110 die_errno("unable to connect to cache daemon");
111 if (flags
& FLAG_SPAWN
) {
112 spawn_daemon(socket
);
113 if (send_request(socket
, &buf
) < 0)
114 die_errno("unable to connect to cache daemon");
117 strbuf_release(&buf
);
120 static char *get_socket_path(void)
123 char *old_dir
, *socket
;
124 old_dir
= interpolate_path("~/.git-credential-cache", 0);
125 if (old_dir
&& !stat(old_dir
, &sb
) && S_ISDIR(sb
.st_mode
))
126 socket
= xstrfmt("%s/socket", old_dir
);
128 socket
= xdg_cache_home("credential/socket");
133 static void announce_capabilities(void)
135 struct credential c
= CREDENTIAL_INIT
;
136 c
.capa_authtype
.request_initial
= 1;
137 credential_announce_capabilities(&c
, stdout
);
140 int cmd_credential_cache(int argc
,
143 struct repository
*repo UNUSED
)
145 const char *socket_path_arg
= NULL
;
149 const char * const usage
[] = {
150 "git credential-cache [<options>] <action>",
153 struct option options
[] = {
154 OPT_INTEGER(0, "timeout", &timeout
,
155 "number of seconds to cache credentials"),
156 OPT_STRING(0, "socket", &socket_path_arg
, "path",
157 "path of cache-daemon socket"),
161 argc
= parse_options(argc
, argv
, prefix
, options
, usage
, 0);
163 usage_with_options(usage
, options
);
166 if (!have_unix_sockets())
167 die(_("credential-cache unavailable; no unix socket support"));
169 socket_path
= xstrdup_or_null(socket_path_arg
);
171 socket_path
= get_socket_path();
173 die("unable to find a suitable socket path; use --socket");
175 if (!strcmp(op
, "exit"))
176 do_cache(socket_path
, op
, timeout
, 0);
177 else if (!strcmp(op
, "get") || !strcmp(op
, "erase"))
178 do_cache(socket_path
, op
, timeout
, FLAG_RELAY
);
179 else if (!strcmp(op
, "store"))
180 do_cache(socket_path
, op
, timeout
, FLAG_RELAY
|FLAG_SPAWN
);
181 else if (!strcmp(op
, "capability"))
182 announce_capabilities();
184 ; /* ignore unknown operation */
192 int cmd_credential_cache(int argc
, const char **argv
, const char *prefix
,
193 struct repository
*repo UNUSED
)
195 const char * const usage
[] = {
196 "git credential-cache [options] <action>",
198 "credential-cache is disabled in this build of Git",
201 struct option options
[] = { OPT_END() };
203 argc
= parse_options(argc
, argv
, prefix
, options
, usage
, 0);
204 die(_("credential-cache unavailable; no unix socket support"));
207 #endif /* NO_UNIX_SOCKETS */