This adds two interfaces:

    void SetReqFds(ClientPtr client, int req_fds)

        Marks the number of file descriptors expected for this
        request. Call this before any request processing so that
        any un-retrieved file descriptors will be closed
        automatically.

    int ReadFdFromClient(ClientPtr client)

        Reads the next queued file descriptor from the connection. If
        this request is not expecting any more file descriptors, or
        if there are no more file descriptors available from the
        connection, then this will return -1.

Signed-off-by: Keith Packard <[email protected]>
---
 include/dixstruct.h |  8 ++++++++
 include/os.h        |  2 ++
 os/io.c             | 21 +++++++++++++++++++++
 3 files changed, 31 insertions(+)

diff --git a/include/dixstruct.h b/include/dixstruct.h
index 7711cde..456e633 100644
--- a/include/dixstruct.h
+++ b/include/dixstruct.h
@@ -110,8 +110,16 @@ typedef struct _Client {
 
     DeviceIntPtr clientPtr;
     ClientIdPtr clientIds;
+    int req_fds;
 } ClientRec;
 
+static inline void
+SetReqFds(ClientPtr client, int req_fds) {
+    if (client->req_fds != 0 && req_fds != client->req_fds)
+        LogMessage(X_ERROR, "Mismatching number of request fds %d != %d\n", 
req_fds, client->req_fds);
+    client->req_fds = req_fds;
+}
+
 /*
  * Scheduling interface
  */
diff --git a/include/os.h b/include/os.h
index 3840ab9..b654a0d 100644
--- a/include/os.h
+++ b/include/os.h
@@ -98,6 +98,8 @@ extern _X_EXPORT int WaitForSomething(int *     
/*pClientsReady */
 
 extern _X_EXPORT int ReadRequestFromClient(ClientPtr /*client */ );
 
+extern _X_EXPORT int ReadFdFromClient(ClientPtr client);
+
 extern _X_EXPORT Bool InsertFakeRequest(ClientPtr /*client */ ,
                                         char * /*data */ ,
                                         int /*count */ );
diff --git a/os/io.c b/os/io.c
index 3800366..83df6e9 100644
--- a/os/io.c
+++ b/os/io.c
@@ -259,6 +259,12 @@ ReadRequestFromClient(ClientPtr client)
         oc->input = oci;
     }
 
+    /* Discard any unused file descriptors */
+    while (client->req_fds > 0) {
+        int req_fd = ReadFdFromClient(client);
+        if (req_fd >= 0)
+            close(req_fd);
+    }
     /* advance to start of next request */
 
     oci->bufptr += oci->lenLastReq;
@@ -485,6 +491,21 @@ ReadRequestFromClient(ClientPtr client)
     return needed;
 }
 
+int
+ReadFdFromClient(ClientPtr client)
+{
+    int fd = -1;
+
+    if (client->req_fds > 0) {
+        OsCommPtr oc = (OsCommPtr) client->osPrivate;
+
+        --client->req_fds;
+        fd = _XSERVTransRecvFd(oc->trans_conn);
+    } else
+        LogMessage(X_ERROR, "Request asks for FD without setting req_fds\n");
+    return fd;
+}
+
 /*****************************************************************
  * InsertFakeRequest
  *    Splice a consed up (possibly partial) request in as the next request.
-- 
1.8.4.rc3

_______________________________________________
[email protected]: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to