Commits

José Romero committed 39b5e75

Initial support for unix domain sockets

Comments (0)

Files changed (9)

    <a href="refO.html#open">open</a>
    <a href="refC.html#close">close</a>
    <a href="refP.html#port">port</a>
+   <a href="refP.html#sock">port</a>
    <a href="refL.html#listen">listen</a>
    <a href="refA.html#accept">accept</a>
    <a href="refH.html#host">host</a>
 
 <dt><a name="accept"><code>(accept 'cnt) -> cnt | NIL</code></a>
 <dd>Accepts a connection on descriptor <code>cnt</code> (as received by <code><a
-href="refP.html#port">port</a></code>), and returns the new socket descriptor
+href="refP.html#port">port</a></code> or <code><a
+href="refS.html#sock">sock</a></code>), and returns the new socket descriptor
 <code>cnt</code>. The global variable <code>*Adr</code> is set to the IP address
 of the client. See also <code><a href="refL.html#listen">listen</a></code>,
 <code><a href="refC.html#connect">connect</a></code> and <code><a
 -> 2
 </code></pre>
 
-<dt><a name="connect"><code>(connect 'any1 'any2) -> cnt | NIL</code></a>
+<dt><a name="connect"><code>(connect ['any1|'NIL] 'any2) -> cnt | NIL</code></a>
 <dd>Tries to establish a TCP/IP connection to a server listening at host
 <code>any1</code>, port <code>any2</code>. <code>any1</code> may be either a
 hostname or a standard internet address in numbers-and-dots/colons notation
 (IPv4/IPv6). <code>any2</code> may be either a port number or a service name.
 Returns a socket descriptor <code>cnt</code>, or <code>NIL</code> if the
-connection cannot be established. See also <code><a
-href="refL.html#listen">listen</a></code> and <code><a
-href="refU.html#udp">udp</a></code>.
+connection cannot be established. If the first argument
+is <code>NIL</code>, then it attempts to establish the connection with
+a unix domain socket located in <code>any2</code>. See
+also <code><a href="refL.html#listen">listen</a></code>
+and <code><a href="refU.html#udp">udp</a></code>.
 
 <pre><code>
 : (connect "localhost" 4444)
 -> 3
 : (connect "some.host.org" "http")
 -> 4
+: (connect NIL (pil "foo.sock"))
+-> 5
 </code></pre>
 
 <dt><a name="cons"><code>(cons 'any ['any ..]) -> lst</code></a>
 
 <dt><a name="listen"><code>(listen 'cnt1 ['cnt2]) -> cnt | NIL</code></a>
 <dd>Listens at a socket descriptor <code>cnt1</code> (as received by <code><a
-href="refP.html#port">port</a></code>) for an incoming connection, and returns
+href="refP.html#port">port</a></code>
+or <code><a href="refS.html#sock">sock</a></code>) for an incoming
+connection, and returns
 the new socket descriptor <code>cnt</code>. While waiting for a connection, a
 <code>select</code> system call is executed for all file descriptors and timers
 in the <code>VAL</code> of the global variable <code><a
 : (?
    @Nr (2 . 5)          # Select all items with numbers between 2 and 5
    @Sup "Active"        # and suppliers matching "Active"
-   (select (@Item)                                  # Bind results to '@Item'
+   (select (@Item)                                  # Bind results to '@Item
       ((nr +Item @Nr) (nm +CuSu @Sup (sup +Item)))  # Generator clauses
       (range @Nr @Item nr)                          # Filter clauses
       (part @Sup @Item sup nm) ) )
 -> "a"
 </code></pre>
 
+<dt><a name="sock"><code>(sock ['T] 'any) -> cnt</code></a>
+<dd>Opens a TCP Unix domain socket at the path <code>any</code> (or a
+UDP socket if the first argument is <code>T</code>), and returns a
+socket descriptor suitable as an argument
+for <code><a href="refL.html#listen">listen</a></code>
+or <code><a href="refA.html#accept">accept</a></code>
+(or <code><a href="refU.html#udp">udp</a></code>, respectively).
+
+<pre><code>
+: (sock (pil "foo.sock"))   # Open a socket in ~/.pil/foo.sock
+-> 4
+</code></pre>
+
 <dt><a name="solve"><code>(solve 'lst [. prg]) -> lst</code></a>
 <dd>Evaluates a <a href="ref.html#pilog">Pilog</a> query and, returns the list
 of result sets. If <code>prg</code> is given, it is executed for each result
 -> T
 </code></pre>
 
-<dt><a name="udp"><code>(udp 'any1 'any2 'any3) -> any</code></a>
+<dt><a name="udp"><code>(udp ['any1|'NIL] 'any2 'any3) -> any</code></a>
 <dt><code>(udp 'cnt) -> any</code>
 <dd>Simple unidirectional sending/receiving of UDP packets. In the first form,
 <code>any3</code> is sent to a UDP server listening at host <code>any1</code>,
-port <code>any2</code>. In the second form, one item is received from a UDP
-socket <code>cnt</code>, established with <code><a
-href="refP.html#port">port</a></code>. See also <code><a
-href="refL.html#listen">listen</a></code> and <code><a
-href="refC.html#connect">connect</a></code>.
+port <code>any2</code>. If the first parameter is <code>NIL</code>,
+the data will be sent to a unix socket located
+in <code>any2</code>. In the second form, one item is received from a
+UDP socket <code>cnt</code>, established
+with <code><a href="refP.html#port">port</a></code>
+or <code><a href="refS.html#sock">sock</a></code>. See
+also <code><a href="refL.html#listen">listen</a></code>
+and <code><a href="refC.html#connect">connect</a></code>.
 
 <pre><code>
 # First session
 
 #include <netdb.h>
 #include <arpa/inet.h>
+#include <sys/un.h>
 
 static void ipErr(any ex, char *s) {
    err(ex, NULL, "IP %s error: %s", s, strerror(errno));
    return boxCnt(sd);
 }
 
+// (sock ['T] 'any) -> cnt
+any doSock(any ex) {
+   any x, y;
+   int type, sd;
+   struct sockaddr_un addr;
+   x = cdr(ex);
+   type = SOCK_STREAM;
+   if ((y = EVAL(car(x))) == T)
+      type = SOCK_DGRAM,  x = cdr(x),  y = EVAL(car(x));
+   if ((sd = socket(AF_UNIX, type, 0)) < 0)
+      ipErr(ex, "socket");
+   closeOnExec(ex, sd);
+   memset(&addr, 0, sizeof(addr));
+   addr.sun_family = AF_UNIX;
+   if (bufSize(y) > sizeof(addr.sun_path))
+      err(ex, NULL, "SOCK error: path too long.");
+   bufString(y,addr.sun_path);
+   if (bind(sd, (struct sockaddr*)&addr, sizeof(addr)) < 0)
+      close(sd),  ipErr(ex, "bind");
+   if (type == SOCK_STREAM  &&  listen(sd,5) < 0)
+      close(sd),  ipErr(ex, "listen");
+   return boxCnt(sd);
+}
+
 static any tcpAccept(int sd) {
    int i, f, sd2;
    char s[INET6_ADDRSTRLEN];
 
 static struct addrinfo *server(int type, any node, any service) {
    struct addrinfo hints, *lst;
+   struct sockaddr_un *unaddr;
    char nd[bufSize(node)], sv[bufSize(service)];
-
-   memset(&hints, 0, sizeof(hints));
-   hints.ai_family = AF_UNSPEC;
-   hints.ai_socktype = type;
-   bufString(node, nd),  bufString(service, sv);
-   return getaddrinfo(nd, sv, &hints, &lst)? NULL : lst;
+   if (isNil(node)){
+      lst = (struct addrinfo*) calloc(1, sizeof(struct addrinfo));
+      unaddr = (struct sockaddr_un*) calloc(1, sizeof(struct sockaddr_un));
+      lst->ai_addr = (struct sockaddr*) unaddr;
+      lst->ai_family = AF_UNIX;
+      lst->ai_socktype = type;
+      unaddr->sun_family = AF_UNIX;
+      bufString(service, sv);
+      strncpy(unaddr->sun_path, sv, sizeof(unaddr->sun_path)-1);
+      lst->ai_addrlen = sizeof(struct sockaddr_un);
+      return lst;
+   } else {
+      memset(&hints, 0, sizeof(hints));
+      hints.ai_family = AF_UNSPEC;
+      hints.ai_socktype = type;
+      bufString(node, nd),  bufString(service, sv);
+      return getaddrinfo(nd, sv, &hints, &lst)? NULL : lst;
+   }
 }
 
-// (connect 'any1 'any2) -> cnt | NIL
+// (connect ['any1|'NIL] 'any2) -> cnt | NIL
 any doConnect(any ex) {
    struct addrinfo *lst, *p;
    any port;
    return *UdpPtr++;
 }
 
-// (udp 'any1 'any2 'any3) -> any
+// (udp ['any1|'NIL] 'any2 'any3) -> any
 // (udp 'cnt) -> any
 any doUdp(any ex) {
    any x, y;
 any doSigio(any);
 any doSize(any);
 any doSkip(any);
+any doSock(any);
 any doSort(any);
 any doSpace(any);
 any doSplit(any);
    {doSigio, "sigio"},
    {doSize, "size"},
    {doSkip, "skip"},
+   {doSock, "sock"},
    {doSort, "sort"},
    {doSpace, "space"},
    {doSplit, "split"},
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.