Unix Pageant: add a --symlink option.

I've often found it useful that you can make symlinks to Unix-domain
sockets, and then connect() on the symlink path will redirect to the
original socket.

This commit adds an option to Unix Pageant which will make it symlink
its socket path to a link location of your choice. My initial use case
is when running Pageant in debug mode during development: if you run a
new copy of it every few minutes after making a code change, then it's
annoying to have it change its socket path every time so you have to
keep pasting its setup command into your test shell. Not any more! Now
you can run 'pageant --debug --symlink fixed-location', and then your
test shell can point its SSH_AUTH_SOCK at the fixed location all the
time.

There are very likely other use cases too, but that's the one that
motivated me to add the option.
This commit is contained in:
Simon Tatham 2020-02-02 18:52:10 +00:00
Родитель d8337e2070
Коммит 94a756f3a9
1 изменённых файлов: 38 добавлений и 2 удалений

Просмотреть файл

@ -11,6 +11,7 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
@ -775,7 +776,7 @@ static const PlugVtable X11Connection_plugvt = {
NULL
};
void run_agent(FILE *logfp)
void run_agent(FILE *logfp, const char *symlink_path)
{
const char *err;
char *errw;
@ -826,6 +827,29 @@ void run_agent(FILE *logfp)
}
pageant_listener_got_socket(pl, sock);
if (symlink_path) {
/*
* Try to make a symlink to the Unix socket, in a location of
* the user's choosing.
*
* If the link already exists, we want to replace it. There
* are two ways we could do this: either make it under another
* name and then rename it over the top, or remove the old
* link first. The former is what 'ln -sf' does, on the
* grounds that it's more atomic. But I think in this case,
* where the expected use case is that the previous agent has
* long since shut down, atomicity isn't a critical concern
* compared to not accidentally overwriting some non-symlink
* that might have important data in it!
*/
struct stat st;
if (lstat(symlink_path, &st) == 0 && S_ISLNK(st.st_mode))
unlink(symlink_path);
if (symlink(socketname, symlink_path) < 0)
fprintf(stderr, "pageant: making symlink %s: %s\n",
symlink_path, strerror(errno));
}
conf = conf_new();
conf_set_int(conf, CONF_proxy_type, PROXY_NONE);
@ -1117,6 +1141,7 @@ int main(int argc, char **argv)
bool doing_opts = true;
keyact curr_keyact = KEYACT_AGENT_LOAD;
const char *standalone_askpass_prompt = NULL;
const char *symlink_path = NULL;
FILE *logfp = NULL;
/*
@ -1179,8 +1204,19 @@ int main(int argc, char **argv)
"after --askpass\n");
exit(1);
}
} else if (!strcmp(p, "--symlink")) {
if (--argc > 0) {
symlink_path = *++argv;
} else {
fprintf(stderr, "pageant: expected a pathname "
"after --symlink\n");
exit(1);
}
} else if (!strcmp(p, "--")) {
doing_opts = false;
} else {
fprintf(stderr, "pageant: unrecognised option '%s'\n", p);
exit(1);
}
} else {
/*
@ -1268,7 +1304,7 @@ int main(int argc, char **argv)
}
if (has_lifetime) {
run_agent(logfp);
run_agent(logfp, symlink_path);
} else if (has_client_actions) {
run_client();
}