]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - cups/http-addr.c
Use httpAddrListen and new httpAddrClose in cupsd and other places that need it.
[thirdparty/cups.git] / cups / http-addr.c
index ad74f083fcbc21809e8073b0fc620b24f9d7c413..e5c3791cfd3648c386ee76e0dfa129bfa7321555 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include "cups-private.h"
+#include <sys/stat.h>
 #ifdef HAVE_RESOLV_H
 #  include <resolv.h>
 #endif /* HAVE_RESOLV_H */
@@ -53,6 +54,37 @@ httpAddrAny(const http_addr_t *addr) /* I - Address to check */
 }
 
 
+/*
+ * '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.
  *
@@ -129,16 +161,21 @@ httpAddrListen(http_addr_t *addr, /* I - Address to bind to */
                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);
@@ -153,9 +190,50 @@ httpAddrListen(http_addr_t *addr,  /* I - Address to bind to */
     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);
 
@@ -164,6 +242,10 @@ httpAddrListen(http_addr_t *addr,  /* I - Address to bind to */
     return (-1);
   }
 
+ /*
+  * Listen...
+  */
+
   if (listen(fd, 5))
   {
     _cupsSetHTTPError(HTTP_STATUS_ERROR);
@@ -173,6 +255,14 @@ httpAddrListen(http_addr_t *addr,  /* I - Address to bind to */
     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.