2 #include "credential.h"
3 #include "string-list.h"
4 #include "parse-options.h"
5 #include "unix-socket.h"
6 #include "run-command.h"
8 static int send_request(const char *socket
, const struct strbuf
*out
)
11 int fd
= unix_stream_connect(socket
);
16 if (write_in_full(fd
, out
->buf
, out
->len
) < 0)
17 die_errno("unable to write to cache daemon");
18 shutdown(fd
, SHUT_WR
);
24 r
= read_in_full(fd
, in
, sizeof(in
));
28 die_errno("read error from cache daemon");
29 write_or_die(1, in
, r
);
35 static void out_str(struct strbuf
*out
, const char *key
, const char *value
)
39 strbuf_addf(out
, "%s=%s", key
, value
);
40 strbuf_addch(out
, '\0');
43 static void out_int(struct strbuf
*out
, const char *key
, int value
)
45 strbuf_addf(out
, "%s=%d", key
, value
);
46 strbuf_addch(out
, '\0');
49 static int do_cache(const char *socket
, const char *action
,
50 const struct credential
*c
, int timeout
)
52 struct strbuf buf
= STRBUF_INIT
;
55 out_str(&buf
, "action", action
);
57 out_str(&buf
, "unique", c
->unique
);
58 out_str(&buf
, "username", c
->username
);
59 out_str(&buf
, "password", c
->password
);
62 out_int(&buf
, "timeout", timeout
);
64 ret
= send_request(socket
, &buf
);
70 static void spawn_daemon(const char *socket
)
72 struct child_process daemon
;
73 const char *argv
[] = { NULL
, NULL
, NULL
};
77 memset(&daemon
, 0, sizeof(daemon
));
78 argv
[0] = "git-credential-cache--daemon";
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
);
94 int main(int argc
, const char **argv
)
96 struct credential c
= { NULL
};
97 char *socket_path
= NULL
;
99 struct string_list chain
= STRING_LIST_INIT_NODUP
;
102 const char * const usage
[] = {
103 "git credential-cache [options]",
106 struct option options
[] = {
107 OPT_BOOLEAN(0, "exit", &exit_mode
,
108 "tell a running daemon to exit"),
109 OPT_BOOLEAN(0, "reject", &reject_mode
,
110 "reject a cached credential"),
111 OPT_INTEGER(0, "timeout", &timeout
,
112 "number of seconds to cache credentials"),
113 OPT_STRING(0, "socket", &socket_path
, "path",
114 "path of cache-daemon socket"),
115 OPT_STRING_LIST(0, "chain", &chain
, "helper",
116 "use <helper> to get non-cached credentials"),
117 OPT_STRING(0, "username", &c
.username
, "name",
118 "an existing username"),
119 OPT_STRING(0, "description", &c
.description
, "desc",
120 "human-readable description of the credential"),
121 OPT_STRING(0, "unique", &c
.unique
, "token",
122 "a unique context for the credential"),
126 argc
= parse_options(argc
, argv
, NULL
, options
, usage
, 0);
128 usage_with_options(usage
, options
);
129 /* credential_reject wants to free() these */
131 c
.username
= xstrdup(c
.username
);
133 c
.password
= xstrdup(c
.password
);
136 socket_path
= expand_user_path("~/.git-credential-cache/socket");
138 die("unable to find a suitable socket path; use --socket");
141 do_cache(socket_path
, "exit", NULL
, -1);
146 do_cache(socket_path
, "erase", &c
, -1);
147 credential_reject(&c
, &chain
);
151 if (do_cache(socket_path
, "get", &c
, -1) > 0)
154 credential_fill(&c
, &chain
);
155 printf("username=%s\n", c
.username
);
156 printf("password=%s\n", c
.password
);
158 if (do_cache(socket_path
, "store", &c
, timeout
) < 0) {
159 spawn_daemon(socket_path
);
160 do_cache(socket_path
, "store", &c
, timeout
);