forked from lix-project/lix
Move Unix domain socket creation to libutil
Also drop multithread-unfriendly hacks like doing a temporary chmod/umask.
This commit is contained in:
parent
2d37e88319
commit
63b99af85a
|
@ -21,7 +21,9 @@
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
#include <sys/un.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
|
@ -1562,4 +1564,33 @@ std::unique_ptr<InterruptCallback> createInterruptCallback(std::function<void()>
|
||||||
return std::unique_ptr<InterruptCallback>(res.release());
|
return std::unique_ptr<InterruptCallback>(res.release());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AutoCloseFD createUnixDomainSocket(const Path & path, mode_t mode)
|
||||||
|
{
|
||||||
|
AutoCloseFD fdSocket = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
||||||
|
if (!fdSocket)
|
||||||
|
throw SysError("cannot create Unix domain socket");
|
||||||
|
|
||||||
|
closeOnExec(fdSocket.get());
|
||||||
|
|
||||||
|
struct sockaddr_un addr;
|
||||||
|
addr.sun_family = AF_UNIX;
|
||||||
|
if (path.size() >= sizeof(addr.sun_path))
|
||||||
|
throw Error("socket path '%1%' is too long", path);
|
||||||
|
strcpy(addr.sun_path, path.c_str());
|
||||||
|
|
||||||
|
unlink(path.c_str());
|
||||||
|
|
||||||
|
if (bind(fdSocket.get(), (struct sockaddr *) &addr, sizeof(addr)) == -1)
|
||||||
|
throw SysError("cannot bind to socket '%1%'", path);
|
||||||
|
|
||||||
|
if (chmod(path.c_str(), mode) == -1)
|
||||||
|
throw SysError("changing permissions on '%1%'", path);
|
||||||
|
|
||||||
|
if (listen(fdSocket.get(), 5) == -1)
|
||||||
|
throw SysError("cannot listen on socket '%1%'", path);
|
||||||
|
|
||||||
|
return fdSocket;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -553,4 +553,8 @@ typedef std::function<bool(const Path & path)> PathFilter;
|
||||||
extern PathFilter defaultPathFilter;
|
extern PathFilter defaultPathFilter;
|
||||||
|
|
||||||
|
|
||||||
|
/* Create a Unix domain socket in listen mode. */
|
||||||
|
AutoCloseFD createUnixDomainSocket(const Path & path, mode_t mode);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -156,53 +156,15 @@ static void daemonLoop(char * * argv)
|
||||||
if (getEnv("LISTEN_PID") != std::to_string(getpid()) || getEnv("LISTEN_FDS") != "1")
|
if (getEnv("LISTEN_PID") != std::to_string(getpid()) || getEnv("LISTEN_FDS") != "1")
|
||||||
throw Error("unexpected systemd environment variables");
|
throw Error("unexpected systemd environment variables");
|
||||||
fdSocket = SD_LISTEN_FDS_START;
|
fdSocket = SD_LISTEN_FDS_START;
|
||||||
|
closeOnExec(fdSocket.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Otherwise, create and bind to a Unix domain socket. */
|
/* Otherwise, create and bind to a Unix domain socket. */
|
||||||
else {
|
else {
|
||||||
|
createDirs(dirOf(settings.nixDaemonSocketFile));
|
||||||
/* Create and bind to a Unix domain socket. */
|
fdSocket = createUnixDomainSocket(settings.nixDaemonSocketFile, 0666);
|
||||||
fdSocket = socket(PF_UNIX, SOCK_STREAM, 0);
|
|
||||||
if (!fdSocket)
|
|
||||||
throw SysError("cannot create Unix domain socket");
|
|
||||||
|
|
||||||
string socketPath = settings.nixDaemonSocketFile;
|
|
||||||
|
|
||||||
createDirs(dirOf(socketPath));
|
|
||||||
|
|
||||||
/* Urgh, sockaddr_un allows path names of only 108 characters.
|
|
||||||
So chdir to the socket directory so that we can pass a
|
|
||||||
relative path name. */
|
|
||||||
if (chdir(dirOf(socketPath).c_str()) == -1)
|
|
||||||
throw SysError("cannot change current directory");
|
|
||||||
Path socketPathRel = "./" + baseNameOf(socketPath);
|
|
||||||
|
|
||||||
struct sockaddr_un addr;
|
|
||||||
addr.sun_family = AF_UNIX;
|
|
||||||
if (socketPathRel.size() >= sizeof(addr.sun_path))
|
|
||||||
throw Error(format("socket path '%1%' is too long") % socketPathRel);
|
|
||||||
strcpy(addr.sun_path, socketPathRel.c_str());
|
|
||||||
|
|
||||||
unlink(socketPath.c_str());
|
|
||||||
|
|
||||||
/* Make sure that the socket is created with 0666 permission
|
|
||||||
(everybody can connect --- provided they have access to the
|
|
||||||
directory containing the socket). */
|
|
||||||
mode_t oldMode = umask(0111);
|
|
||||||
int res = bind(fdSocket.get(), (struct sockaddr *) &addr, sizeof(addr));
|
|
||||||
umask(oldMode);
|
|
||||||
if (res == -1)
|
|
||||||
throw SysError(format("cannot bind to socket '%1%'") % socketPath);
|
|
||||||
|
|
||||||
if (chdir("/") == -1) /* back to the root */
|
|
||||||
throw SysError("cannot change current directory");
|
|
||||||
|
|
||||||
if (listen(fdSocket.get(), 5) == -1)
|
|
||||||
throw SysError(format("cannot listen on socket '%1%'") % socketPath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
closeOnExec(fdSocket.get());
|
|
||||||
|
|
||||||
/* Loop accepting connections. */
|
/* Loop accepting connections. */
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue