+ syslog(LOG_ERR, "Killed (got signal %d)...", sig);
+ exit(-1);
+ }
+}
+
+static int setnonblock(int sock)
+{
+ int res = fcntl(sock, F_GETFL);
+
+ if (res < 0) {
+ UNIXERR("fcntl");
+ return -1;
+ }
+
+ if (fcntl(sock, F_SETFL, res | O_NONBLOCK) < 0) {
+ UNIXERR("fcntl");
+ return -1;
+ }
+
+ return 0;
+}
+
+int tcp_bind(const struct sockaddr *addr, socklen_t len)
+{
+ int sock;
+
+ switch (addr->sa_family) {
+ case AF_UNIX:
+ unlink(((struct sockaddr_un *)addr)->sun_path);
+ sock = socket(PF_UNIX, SOCK_STREAM, 0);
+ break;
+ case AF_INET:
+ sock = socket(PF_INET, SOCK_STREAM, 0);
+ break;
+ case AF_INET6:
+ sock = socket(PF_INET6, SOCK_STREAM, 0);
+ break;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (sock < 0) {
+ UNIXERR("socket");
+ return -1;
+ }
+
+ if (addr->sa_family != AF_UNIX) {
+ int v = 1;
+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &v, sizeof(v)) < 0) {
+ UNIXERR("setsockopt(SO_REUSEADDR)");
+ close(sock);
+ return -1;
+ }
+ }
+
+ if (bind(sock, addr, len) < 0) {
+ UNIXERR("bind");
+ close(sock);
+ return -1;
+ }
+
+ return sock;
+}
+
+int tcp_listen(const struct sockaddr *addr, socklen_t len)
+{
+ int sock = tcp_bind(addr, len);
+ if (listen(sock, 0) < 0) {
+ UNIXERR("bind");
+ close(sock);
+ return -1;
+ }
+ return sock;
+}
+
+int tcp_listen_nonblock(const struct sockaddr *addr, socklen_t len)
+{
+ int sock = tcp_bind(addr, len);
+ if (setnonblock(sock)) {
+ close(sock);
+ return -1;
+ }
+ if (listen(sock, 0) < 0) {
+ UNIXERR("bind");
+ close(sock);
+ return -1;
+ }
+ return sock;
+}
+
+int accept_nonblock(int fd)
+{
+ int sock = accept(fd, NULL, 0);
+
+ if (sock < 0) {
+ UNIXERR("accept");
+ return -1;
+ }
+
+ if (setnonblock(sock)) {
+ close(sock);
+ return -1;
+ }
+
+ return sock;
+}
+
+int xwrite(int fd, const char *s, size_t l)
+{
+ while (l > 0) {
+ int nb = write(fd, s, l);
+ if (nb < 0) {
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ return -1;
+ }
+ l -= nb;