Code

utils unixsock: Added sc_unixsock_client_shutdown().
authorSebastian Harl <sh@tokkee.org>
Tue, 11 Dec 2012 09:55:36 +0000 (10:55 +0100)
committerSebastian Harl <sh@tokkee.org>
Tue, 11 Dec 2012 09:55:36 +0000 (10:55 +0100)
This function is a wrapper around shutdown(3). After shutting down send /
receive operations, the client will automatically re-connect on the next
send() / recv() call.

src/include/utils/unixsock.h
src/utils/unixsock.c

index e51e4ac7f1437583bd28b6decb7264e012bbf375..0df0b71a3da6526dec090b489e6cbc9189eaba4a 100644 (file)
@@ -28,6 +28,8 @@
 #ifndef SC_UTILS_UNIXSOCK_H
 #define SC_UTILS_UNIXSOCK_H 1
 
+#include <sys/socket.h>
+
 #include <stddef.h>
 
 #ifdef __cplusplus
@@ -49,6 +51,17 @@ sc_unixsock_client_send(sc_unixsock_client_t *client, const char *msg);
 char *
 sc_unixsock_client_recv(sc_unixsock_client_t *client, char *buffer, size_t buflen);
 
+/*
+ * sc_unixsock_client_shutdown:
+ * Shut down the client's send and/or receive operations. If appropriate, the
+ * client will automatically re-connect on the next send / receive operation
+ * after that.
+ *
+ * See shutdown(3) for details.
+ */
+int
+sc_unixsock_client_shutdown(sc_unixsock_client_t *client, int how);
+
 void
 sc_unixsock_client_destroy(sc_unixsock_client_t *client);
 
index 70fd273679bf170f7fd40fd29d2e4417f142beb3..af1f2fedaf4c6c5bd9c7fb253a0ce8baf856982f 100644 (file)
 struct sc_unixsock_client {
        char *path;
        FILE *fh;
+
+       int shutdown;
 };
 
+#define SC_SHUT_RD   (1 << SHUT_RD)
+#define SC_SHUT_WR   (1 << SHUT_WR)
+#define SC_SHUT_RDWR (SC_SHUT_RD | SC_SHUT_WR)
+
 /*
  * public API
  */
@@ -71,6 +77,8 @@ sc_unixsock_client_create(const char *path)
                sc_unixsock_client_destroy(client);
                return NULL;
        }
+
+       client->shutdown = 0;
        return client;
 } /* sc_unixsock_client_create */
 
@@ -116,6 +124,8 @@ sc_unixsock_client_connect(sc_unixsock_client_t *client)
                close(fd);
                return -1;
        }
+
+       client->shutdown = 0;
        return 0;
 } /* sc_unixsock_client_connect */
 
@@ -127,6 +137,9 @@ sc_unixsock_client_send(sc_unixsock_client_t *client, const char *msg)
        if ((! client) || (! client->fh))
                return -1;
 
+       if (client->shutdown & SC_SHUT_WR) /* reconnect */
+               sc_unixsock_client_connect(client);
+
        status = fprintf(client->fh, "%s\r\n", msg);
        if (status < 0) {
                char errbuf[1024];
@@ -143,6 +156,9 @@ sc_unixsock_client_recv(sc_unixsock_client_t *client, char *buffer, size_t bufle
        if ((! client) || (! client->fh) || (! buffer))
                return NULL;
 
+       if (client->shutdown & SC_SHUT_RD) /* reconnect */
+               sc_unixsock_client_connect(client);
+
        buffer = fgets(buffer, (int)buflen - 1, client->fh);
        if (! buffer) {
                if (! feof(client->fh)) {
@@ -162,6 +178,28 @@ sc_unixsock_client_recv(sc_unixsock_client_t *client, char *buffer, size_t bufle
        return buffer;
 } /* sc_unixsock_client_recv */
 
+int
+sc_unixsock_client_shutdown(sc_unixsock_client_t *client, int how)
+{
+       int status;
+
+       if (! client) {
+               errno = ENOTSOCK;
+               return -1;
+       }
+
+       fflush(client->fh);
+       status = shutdown(fileno(client->fh), how);
+
+       if (! status) {
+               if (how == SHUT_RDWR)
+                       client->shutdown |= SC_SHUT_RDWR;
+               else
+                       client->shutdown |= 1 << how;
+       }
+       return status;
+} /* sc_unixsock_client_shutdown */
+
 void
 sc_unixsock_client_destroy(sc_unixsock_client_t *client)
 {