#include #include #include #include #include #include #include #include "putty.h" #include "ssh.h" #include "misc.h" #include "pageant.h" Socket *platform_make_agent_socket( Plug *plug, const char *dirprefix, char **error, char **name) { char *username, *socketdir, *socketname, *errw; const char *err; Socket *sock; *name = NULL; username = get_username(); socketdir = dupprintf("%s.%s", dirprefix, username); sfree(username); assert(*socketdir == '/'); if ((errw = make_dir_and_check_ours(socketdir)) != NULL) { *error = dupprintf("%s: %s\n", socketdir, errw); sfree(errw); sfree(socketdir); return NULL; } socketname = dupprintf("%s/pageant.%d", socketdir, (int)getpid()); sock = new_unix_listener(unix_sock_addr(socketname), plug); if ((err = sk_socket_error(sock)) != NULL) { *error = dupprintf("%s: %s\n", socketname, err); sk_close(sock); sfree(socketname); rmdir(socketdir); sfree(socketdir); return NULL; } /* * Spawn a subprocess which will try to reliably delete our socket * and its containing directory when we terminate, in case we die * unexpectedly. */ { int cleanup_pipe[2]; pid_t pid; /* Don't worry if pipe or fork fails; it's not _that_ critical. */ if (!pipe(cleanup_pipe)) { if ((pid = fork()) == 0) { int buf[1024]; /* * Our parent process holds the writing end of * this pipe, and writes nothing to it. Hence, * we expect read() to return EOF as soon as * that process terminates. */ close(0); close(1); close(2); setpgid(0, 0); close(cleanup_pipe[1]); while (read(cleanup_pipe[0], buf, sizeof(buf)) > 0); unlink(socketname); rmdir(socketdir); _exit(0); } else if (pid < 0) { close(cleanup_pipe[0]); close(cleanup_pipe[1]); } else { close(cleanup_pipe[0]); cloexec(cleanup_pipe[1]); } } } *name = socketname; *error = NULL; sfree(socketdir); return sock; }