*/
#include "cups-private.h"
+#include <sys/stat.h>
#ifdef HAVE_RESOLV_H
# include <resolv.h>
#endif /* HAVE_RESOLV_H */
}
+/*
+ * 'httpAddrClose()' - Close a socket created by @link httpAddrConnect@ or
+ * @link httpAddrListen@.
+ *
+ * Pass @code NULL@ for sockets created with @link httpAddrConnect@ and the
+ * listen address for sockets created with @link httpAddrListen@. This will
+ * ensure that domain sockets are removed when closed.
+ *
+ * @since CUPS 2.0@
+ */
+
+int /* O - 0 on success, -1 on failure */
+httpAddrClose(http_addr_t *addr, /* I - Listen address or @code NULL@ */
+ int fd) /* I - Socket file descriptor */
+{
+#ifdef WIN32
+ if (closesocket(fd))
+#else
+ if (close(fd))
+#endif /* WIN32 */
+ return (-1);
+
+#ifdef AF_LOCAL
+ if (addr && addr->addr.sa_family == AF_LOCAL)
+ return (unlink(addr->un.sun_path));
+#endif /* AF_LOCAL */
+
+ return (0);
+}
+
+
/*
* 'httpAddrEqual()' - Compare two addresses.
*
int port) /* I - Port number to bind to */
{
int fd = -1, /* Socket */
- val; /* Socket value */
+ val, /* Socket value */
+ status; /* Bind status */
/*
* Range check input...
*/
- if (!addr || port <= 0)
+ if (!addr || port < 0)
return (-1);
+ /*
+ * Create the socket and set options...
+ */
+
if ((fd = socket(addr->addr.sa_family, SOCK_STREAM, 0)) < 0)
{
_cupsSetHTTPError(HTTP_STATUS_ERROR);
setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, CUPS_SOCAST &val, sizeof(val));
#endif /* IPV6_V6ONLY */
- _httpAddrSetPort(addr, port);
+ /*
+ * Bind the socket...
+ */
+
+#ifdef AF_LOCAL
+ if (addr->addr.sa_family == AF_LOCAL)
+ {
+ mode_t mask; /* Umask setting */
+
+ /*
+ * Remove any existing domain socket file...
+ */
+
+ unlink(addr->un.sun_path);
+
+ /*
+ * Save the current umask and set it to 0 so that all users can access
+ * the domain socket...
+ */
+
+ mask = umask(0);
+
+ /*
+ * Bind the domain socket...
+ */
+
+ status = bind(fd, (struct sockaddr *)addr, httpAddrLength(addr));
+
+ /*
+ * Restore the umask and fix permissions...
+ */
- if (bind(fd, (struct sockaddr *)addr, httpAddrLength(addr)))
+ umask(mask);
+ chmod(addr->un.sun_path, 0140777);
+ }
+ else
+#endif /* AF_LOCAL */
+ {
+ _httpAddrSetPort(addr, port);
+
+ status = bind(fd, (struct sockaddr *)addr, httpAddrLength(addr));
+ }
+
+ if (status)
{
_cupsSetHTTPError(HTTP_STATUS_ERROR);
return (-1);
}
+ /*
+ * Listen...
+ */
+
if (listen(fd, 5))
{
_cupsSetHTTPError(HTTP_STATUS_ERROR);
return (-1);
}
+ /*
+ * Close on exec...
+ */
+
+#ifndef WIN32
+ fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
+#endif /* !WIN32 */
+
#ifdef SO_NOSIGPIPE
/*
* Disable SIGPIPE for this socket.