[PATCH] Unix domain socket filename redirection

classic Classic list List threaded Threaded
6 messages Options
Z
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[PATCH] Unix domain socket filename redirection

Z
This patch adds support for Unix domain sockets. A filename of the form
/dev/unixstream/path used in a redirection makes bash attempt to open a
connection to the Unix domain stream socket at /path. Similarly a filename
of the form /dev/unixdgram/path makes bash attempt to open a connection to
the Unix domain datagram socket at /path.

Zartaj Majeed

 Makefile.in              |   2 +-
 config.h.in              |   7 ++++
 configure.ac             |   9 +++-
 externs.h                |   3 ++
 lib/sh/Makefile.in       |   8 +++-
 lib/sh/usockopen.c       | 104
+++++++++++++++++++++++++++++++++++++++++++++++
 redir.c                  |  12 ++++++
 tests/misc/devunix.tests |  18 ++++++++
 8 files changed, 158 insertions(+), 5 deletions(-)

diff --git a/Makefile.in b/Makefile.in
index c7b62bc0..542cede8 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -222,7 +222,7 @@ SHLIB_SOURCE =      ${SH_LIBSRC}/clktck.c
${SH_LIBSRC}/getcwd.c \
                ${SH_LIBSRC}/input_avail.c ${SH_LIBSRC}/mbscasecmp.c \
                ${SH_LIBSRC}/fnxform.c ${SH_LIBSRC}/unicode.c \
                ${SH_LIBSRC}/wcswidth.c ${SH_LIBSRC}/wcsnwidth.c \
-               ${SH_LIBSRC}/shmbchar.c
+               ${SH_LIBSRC}/shmbchar.c ${SH_LIBSRC}/usockopen.c

 SHLIB_LIB = -lsh
 SHLIB_LIBNAME = libsh.a
diff --git a/config.h.in b/config.h.in
index a5ad9e72..36e8f5dd 100644
--- a/config.h.in
+++ b/config.h.in
@@ -151,6 +151,10 @@
    socket connections when used in redirections */
 #undef NETWORK_REDIRECTIONS

+/* Define UNIXSOCK_REDIRECTIONS if you want
/dev/(unixstream|unixdgram)/path to open
+   socket connections when used in redirections */
+#undef UNIXSOCK_REDIRECTIONS
+
 /* Define PROGRAMMABLE_COMPLETION for the programmable completion features
    and the complete builtin. */
 #undef PROGRAMMABLE_COMPLETION
@@ -1042,6 +1046,9 @@
 /* Define if you have the <sys/socket.h> header file.  */
 #undef HAVE_SYS_SOCKET_H

+/* Define if you have the <sys/un.h> header file.  */
+#undef HAVE_SYS_UN_H
+
 /* Define if you have the <sys/stat.h> header file. */
 #undef HAVE_SYS_STAT_H

diff --git a/configure.ac b/configure.ac
index ce4e9b60..a8e9f43c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -168,6 +168,7 @@ opt_cond_regexp=yes
 opt_coproc=yes
 opt_arith_for_command=yes
 opt_net_redirs=yes
+opt_usock_redirs=yes
 opt_progcomp=yes
 opt_separate_help=no
 opt_multibyte=yes
@@ -196,7 +197,7 @@ if test $opt_minimal_config = yes; then
        opt_select=no opt_help=no opt_array_variables=no opt_dparen_arith=no
        opt_brace_expansion=no opt_disabled_builtins=no
opt_command_timing=no
        opt_extended_glob=no opt_cond_command=no opt_arith_for_command=no
-       opt_net_redirs=no opt_progcomp=no opt_separate_help=no
+       opt_net_redirs=no opt_usock_redirs=no opt_progcomp=no
opt_separate_help=no
        opt_multibyte=yes opt_cond_regexp=no opt_coproc=no
        opt_casemod_attrs=no opt_casemod_expansions=no
opt_extglob_default=no
        opt_globascii_default=no
@@ -227,6 +228,7 @@ AC_ARG_ENABLE(history,
AC_HELP_STRING([--enable-history], [turn on command histo
 AC_ARG_ENABLE(job-control, AC_HELP_STRING([--enable-job-control], [enable
job control features]), opt_job_control=$enableval)
 AC_ARG_ENABLE(multibyte, AC_HELP_STRING([--enable-multibyte], [enable
multibyte characters if OS supports them]), opt_multibyte=$enableval)
 AC_ARG_ENABLE(net-redirections,
AC_HELP_STRING([--enable-net-redirections], [enable /dev/tcp/host/port
redirection]), opt_net_redirs=$enableval)
+AC_ARG_ENABLE(usock-redirections,
AC_HELP_STRING([--enable-usock-redirections], [enable /dev/unixstream/path
redirection]), opt_usock_redirs=$enableval)
 AC_ARG_ENABLE(process-substitution,
AC_HELP_STRING([--enable-process-substitution], [enable process
substitution]), opt_process_subst=$enableval)
 AC_ARG_ENABLE(progcomp, AC_HELP_STRING([--enable-progcomp], [enable
programmable completion and the complete builtin]), opt_progcomp=$enableval)
 AC_ARG_ENABLE(prompt-string-decoding,
AC_HELP_STRING([--enable-prompt-string-decoding], [turn on escape character
decoding in prompts]), opt_prompt_decoding=$enableval)
@@ -321,6 +323,9 @@ fi
 if test $opt_net_redirs = yes; then
 AC_DEFINE(NETWORK_REDIRECTIONS)
 fi
+if test $opt_usock_redirs = yes; then
+AC_DEFINE(UNIXSOCK_REDIRECTIONS)
+fi
 if test $opt_progcomp = yes; then
 AC_DEFINE(PROGRAMMABLE_COMPLETION)
 fi
@@ -702,7 +707,7 @@ AC_CHECK_HEADERS(unistd.h stdlib.h stdarg.h varargs.h
limits.h string.h \
                 stdbool.h stddef.h stdint.h netdb.h pwd.h grp.h strings.h \
                 regex.h syslog.h ulimit.h)
 AC_CHECK_HEADERS(sys/pte.h sys/stream.h sys/select.h sys/file.h
sys/ioctl.h \
-                sys/param.h sys/socket.h sys/stat.h \
+                sys/param.h sys/socket.h sys/un.h sys/stat.h \
                 sys/time.h sys/times.h sys/types.h sys/wait.h)
 AC_CHECK_HEADERS(netinet/in.h arpa/inet.h)

diff --git a/externs.h b/externs.h
index fa0603d3..1315866c 100644
--- a/externs.h
+++ b/externs.h
@@ -270,6 +270,9 @@ extern int isnetconn __P((int));
 /* declarations for functions defined in lib/sh/netopen.c */
 extern int netopen __P((char *));

+/* declarations for functions defined in lib/sh/usockopen.c */
+extern int usockopen __P((char *));
+
 /* Declarations for  functions defined in lib/sh/oslib.c */

 #if !defined (HAVE_DUP2) || defined (DUP2_BROKEN)
diff --git a/lib/sh/Makefile.in b/lib/sh/Makefile.in
index 2ca921b3..3d357997 100644
--- a/lib/sh/Makefile.in
+++ b/lib/sh/Makefile.in
@@ -84,7 +84,7 @@ LIBRARY_NAME = libsh.a
 CSOURCES = clktck.c clock.c getcwd.c getenv.c oslib.c setlinebuf.c \
           strcasecmp.c strerror.c strtod.c strtol.c strtoul.c \
           vprint.c itos.c rename.c zread.c zwrite.c shtty.c \
-          inet_aton.c netconn.c netopen.c strpbrk.c timeval.c makepath.c \
+          inet_aton.c netconn.c netopen.c usockopen.c strpbrk.c timeval.c
makepath.c \
           pathcanon.c pathphys.c tmpfile.c stringlist.c stringvec.c
spell.c \
           shquote.c strtrans.c strcasestr.c snprintf.c mailstat.c \
           fmtulong.c fmtullong.c fmtumax.c shmatch.c strnlen.c \
@@ -101,7 +101,7 @@ HSOURCES =
 LIBOBJS = @LIBOBJS@
 OBJECTS = clktck.o clock.o getenv.o oslib.o setlinebuf.o strnlen.o \
          itos.o zread.o zwrite.o shtty.o shmatch.o eaccess.o \
-         netconn.o netopen.o timeval.o makepath.o pathcanon.o \
+         netconn.o netopen.o usockopen.o timeval.o makepath.o pathcanon.o \
          pathphys.o tmpfile.o stringlist.o stringvec.o spell.o shquote.o \
          strtrans.o snprintf.o mailstat.o fmtulong.o \
          fmtullong.o fmtumax.o zcatfd.o zmapfd.o winsize.o wcsdup.o \
@@ -166,6 +166,7 @@ memset.o: memset.c
 mktime.o: mktime.c
 netconn.o: netconn.c
 netopen.o: netopen.c
+usockopen.o: usockopen.c
 oslib.o: oslib.c
 pathcanon.o: pathcanon.c
 pathphys.o: pathphys.c
@@ -243,6 +244,7 @@ memset.o: ${BUILD_DIR}/config.h
 mktime.o: ${BUILD_DIR}/config.h
 netconn.o: ${BUILD_DIR}/config.h
 netopen.o: ${BUILD_DIR}/config.h
+usockopen.o: ${BUILD_DIR}/config.h
 oslib.o: ${BUILD_DIR}/config.h
 pathcanon.o: ${BUILD_DIR}/config.h
 pathphys.o: ${BUILD_DIR}/config.h
@@ -341,6 +343,8 @@ netopen.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
 netopen.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
 #netopen.o: ${BUILD_DIR}/version.h

+usockopen.o: ${topdir}/bashansi.h ${topdir}/bashintl.h
+
 oslib.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${BASHINCDIR}/maxpath.h
 oslib.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h
${BASHINCDIR}/posixjmp.h
 oslib.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
diff --git a/lib/sh/usockopen.c b/lib/sh/usockopen.c
new file mode 100644
index 00000000..7575003c
--- /dev/null
+++ b/lib/sh/usockopen.c
@@ -0,0 +1,104 @@
+/*
+ * usockopen.c -- functions to make unix domain socket connections
+ *
+ * Zartaj T. Majeed
+ */
+
+/* Copyright (C) 1987-2017 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   Bash is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Bash.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <config.h>
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+
+#if defined (HAVE_SYS_SOCKET_H)
+#  include <sys/socket.h>
+#endif
+
+#if defined (HAVE_SYS_UN_H)
+#  include <sys/un.h>
+#endif
+
+#include <bashansi.h>
+#include <bashintl.h>
+
+#include <errno.h>
+
+#ifndef errno
+extern int errno;
+#endif
+
+static int _usockopen __P((char *, int));
+
+/*
+ * Open Unix domain socket connection
+ * Returns the connected socket or -1 on error.
+ */
+static int
+_usockopen (path, typ)
+     char *path;
+     int typ;
+{
+  int s, e;
+  struct sockaddr_un addr;
+  int gerr;
+  int socktyp = typ == 's'? SOCK_STREAM: SOCK_DGRAM;
+
+  if ((s = socket (AF_UNIX, socktyp, 0)) < 0)
+       {
+         sys_error ("unix socket");
+         return -1;
+       }
+
+  memset (&addr, 0, sizeof addr);
+  addr.sun_family = AF_UNIX;
+  strncpy (addr.sun_path, path, sizeof(addr.sun_path) - 1);
+
+  if (connect (s, &addr, sizeof addr) < 0)
+       {
+         e = errno;
+         sys_error ("unix connect");
+         close (s);
+         errno = e;
+         return -1;
+       }
+  return s;
+}
+
+/*
+ * Open Unix domain socket connection to a path like
/dev/unixstream/tmp/xyz.sock or /dev/unixdgram/tmp/xyz.sock
+ * Returns the connected socket or -1 on error.
+ */
+int
+usockopen (path)
+     char *path;
+{
+  char *s;
+  int fd;
+
+  s = strchr (path+9, '/');
+  fd = _usockopen (s, path[9]);
+
+  return fd;
+}
+
diff --git a/redir.c b/redir.c
index 25488eaf..e026cc12 100644
--- a/redir.c
+++ b/redir.c
@@ -519,6 +519,8 @@ here_document_to_fd (redirectee, ri)
 #define RF_DEVSTDOUT   4
 #define RF_DEVTCP      5
 #define RF_DEVUDP      6
+#define RF_DEVUSTRM    7
+#define RF_DEVUDGRM    8

 /* A list of pattern/value pairs for filenames that the redirection
    code handles specially. */
@@ -535,6 +537,10 @@ static STRING_INT_ALIST _redir_special_filenames[] = {
   { "/dev/tcp/*/*", RF_DEVTCP },
   { "/dev/udp/*/*", RF_DEVUDP },
 #endif
+#if defined (UNIXSOCK_REDIRECTIONS)
+  { "/dev/unixstream/*", RF_DEVUSTRM },
+  { "/dev/unixdgram/*", RF_DEVUDGRM },
+#endif
   { (char *)NULL, -1 }
 };

@@ -588,6 +594,12 @@ redir_special_open (spec, filename, flags, mode, ri)
 #endif
       break;
 #endif /* NETWORK_REDIRECTIONS */
+
+#if defined (UNIXSOCK_REDIRECTIONS)
+    case RF_DEVUSTRM:
+    case RF_DEVUDGRM:
+      fd = usockopen (filename);
+#endif /* UNIXSOCK_REDIRECTIONS */
     }

   return fd;
diff --git a/tests/misc/devunix.tests b/tests/misc/devunix.tests
new file mode 100644
index 00000000..457a40f0
--- /dev/null
+++ b/tests/misc/devunix.tests
@@ -0,0 +1,18 @@
+sock=/tmp/devunixtest.sock
+out=/tmp/devunixtest.out
+s=abcd.$$
+
+nc -U -l $sock >$out&
+sleep 1
+exec 9>/dev/unixstream$sock
+
+echo "$s" >&9
+exec 9>&-
+
+read t <$out
+
+if [[ $s != $t ]]; then
+  echo "out \"$s\" in \"$t\""
+fi
+
+rm $sock $out
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH] Unix domain socket filename redirection

Eduardo A. Bustamante López
On Mon, Jun 19, 2017 at 07:30:42PM -0400, Z wrote:
> This patch adds support for Unix domain sockets. A filename of the form
> /dev/unixstream/path used in a redirection makes bash attempt to open a
> connection to the Unix domain stream socket at /path. Similarly a filename
> of the form /dev/unixdgram/path makes bash attempt to open a connection to
> the Unix domain datagram socket at /path.

Excuse my ignorance:

- What would be an expected use case of this feature? /dev/tcp and
  /dev/udp are commonly used because it allows the shell script writer
  to interact with popular text based protocols like HTTP or SMTP. It
  would seem that this UNIX domain socket patch targets a niche instead?

- Why should this be integrated into the core of bash, and not provided
  as a loadable builtin instead? It makes more sense to me to provide
  this as an optional shell builtin, which also make the usage less
  awkward (not a fan of the /dev/unixstream/the/path/is/here thing).


By the way, the patch does not apply. It would seem like you copy-pasted
the diff, so it got wrapped at some points and git is rejecting it.

--
Eduardo Bustamante
https://dualbus.me/

Z
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH] Unix domain socket filename redirection

Z
Attaching the patch usock.diff.txt



On Mon, Jun 19, 2017 at 11:36 PM, Eduardo A. Bustamante López
<[hidden email]> wrote:

> On Mon, Jun 19, 2017 at 07:30:42PM -0400, Z wrote:
>> This patch adds support for Unix domain sockets. A filename of the form
>> /dev/unixstream/path used in a redirection makes bash attempt to open a
>> connection to the Unix domain stream socket at /path. Similarly a filename
>> of the form /dev/unixdgram/path makes bash attempt to open a connection to
>> the Unix domain datagram socket at /path.
>
> Excuse my ignorance:
>
> - What would be an expected use case of this feature? /dev/tcp and
>   /dev/udp are commonly used because it allows the shell script writer
>   to interact with popular text based protocols like HTTP or SMTP. It
>   would seem that this UNIX domain socket patch targets a niche instead?
>
> - Why should this be integrated into the core of bash, and not provided
>   as a loadable builtin instead? It makes more sense to me to provide
>   this as an optional shell builtin, which also make the usage less
>   awkward (not a fan of the /dev/unixstream/the/path/is/here thing).
>
>
> By the way, the patch does not apply. It would seem like you copy-pasted
> the diff, so it got wrapped at some points and git is rejecting it.
>
> --
> Eduardo Bustamante
> https://dualbus.me/

usock.diff.txt (13K) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH] Unix domain socket filename redirection

tetsujin
In reply to this post by Eduardo A. Bustamante López

Unix Domain Sockets form the basis of a lot of the modern forms of
Unix/Posix IPC. Compared to using TCP sockets for IPC, Unix Domain
sockets allow you to control access to the resource with filesystem
permissions, and identify the socket with a file path so you don't
have to come up with a system-wide-unique port number for the service.
It's kind of like using named pipes created with mkfifo(), except they
can accept multiple connections, and you can transfer not only data
values over the channel, but open file descriptors and system
privileges as well.

So implementing Unix Domain Sockets in the shell would give you the
ability to connect to existing services on the machine that use named
sockets for control (systemd, dbus, cups, etc.) or you could use the
feature to implement new services and connect to them with shell
scripts, or just use them to connect different scripts and programs
together for various forms of IPC.

(As a side note, the shell somewhat defines the user's operating
environment. I think that not providing a feature because of a
perception that "no one uses it" becomes somewhat self-fulfilling: No
one writes shell-friendly Unix Domain Socket servers because the shell
doesn't support connecting to them, and the definition of what's
"shell-friendly" is rather narrow.)

I mentioned this in an earlier post, but I have written an
implementation of socketpair, sendmsg, and recvmsg as shell loadable
built-ins, in a lib I call "shell-pepper". This makes it possible to
implement new "open a file descriptor" commands as external
executables rather than as shell built-ins:

$ socketpair --cloexec s    # Creates a bidirectional Unix Domain
communication channel, stores the file descriptors for the two ends in
${s[@]}.
$ connect_to_socketfile ./socket_to_me >&${s[1]} &   #
"connect_to_socketfile" is an external command that connects to a
socket and sends it over FD 1 using sendmsg() and SCM_RIGHTS
$ recvmsg message connection_fd <&${s[0]}   # Receives the open file
descriptor send by connect_to_named_socket, assigns it an unused file
descriptor, and stores that FD in $connection_fd

I think this speaks to the benefits of building Unix Domain Socket
functionality into the shell: it allows adding other functionality
like this without having to tie it directly into the shell process.

As for the redirection syntax, it's useful because the shell manages
the lifetime of file redirections, like this:

$ cmd <>/dev/unixstream/./smelly_sock   # Socket "./smelly_sock" is
opened, used for the I/O of "cmd", and then closed by the shell
afterward.

As opposed to something like this:

$ connect_to_socketfile ./smelly_sock connection_fd    # Assuming
"connect_to_socketfile" were a built-in, rather than an external
command as it is described above
$ cmd <>&$connection_fd
$ exec {connection_fd}<&-    # Explicitly close the file descriptor

Though even with the benefits of redirection, personally I oppose the
idea of spoofing more fake devices in /dev. (The shell spoofs some
stuff in /dev already, and it's all long-established at this
point...  But I don't think more such fake devices should be added.)
In this patch, spoofing /dev grants us the ability to specify a single
socket option. It's not a great way to set options, though. What if
the API changed, and we suddenly wanted to be able to specify two
options? Specifying options as command arguments is both clearer and
more flexible.

I've given some thought to how the two approaches could be combined:
use a command to open a file descriptor, but bind the file
descriptor's lifetime to a redirection. For instance, consider this
concept for a new redirection syntax:

$ cmd <>&(connect_to_socketfile --datagram ./rockem_sockem)   #
Connect to socketfile, bind it as stdin and stdout for running "cmd",
then undo the redirection and close the socket

In this hypothetical model, the redirection syntax <&(fd_cmd) runs
"fd_cmd" with its output redirected to one end of a socketpair.
"connect_to_socketfile" creates the connection then tries to send it
over file descriptor 1 using sendmsg() and SCM_RIGHTS (see "man 7
unix")
 The shell process listens to the other end of the socketpair,
expecting to receive a file descriptor. If it does receive a file
descriptor, it uses that FD for the redirection, and then disposes of
it when the job is done.
(And if "connect_to_socketfile" returns nonzero status, or doesn't
send exactly one file descriptor over its output socket, then the
redirection fails and the command is aborted.)

That said, there are always problems with introducing new syntax... 
I don't know if this specific syntax would be viable (and it's hard to
come up with syntax that seems conceptually coherent with other forms
of redirection and substitution) but I think something like this could
be useful as a way to add new functionality like this to the shell,
and take advantage of redirection semantics, without having to
integrate the implementation of each new feature into the shell.

And it's worth noting that while Unix Domain Socket functionality is
widespread, established as part of POSIX 2001 and all that, it's not
universally-supported on all (especially older) platforms Bash
supports. So even if it were integrated into the shell, it still must
be considered an optional feature. It may be possible to provide a
single interface that would also cover other APIs with similar
features (the STREAMS API maybe?)

----- Original Message -----
From:
To:"Z" <[hidden email]>
Cc:<[hidden email]>
Sent:Mon, 19 Jun 2017 22:36:40 -0500
Subject:Re: [PATCH] Unix domain socket filename redirection

 On Mon, Jun 19, 2017 at 07:30:42PM -0400, Z wrote:
 > This patch adds support for Unix domain sockets. A filename of the
form
 > /dev/unixstream/path used in a redirection makes bash attempt to
open a
 > connection to the Unix domain stream socket at /path. Similarly a
filename
 > of the form /dev/unixdgram/path makes bash attempt to open a
connection to
 > the Unix domain datagram socket at /path.

 Excuse my ignorance:

 - What would be an expected use case of this feature? /dev/tcp and
 /dev/udp are commonly used because it allows the shell script writer
 to interact with popular text based protocols like HTTP or SMTP. It
 would seem that this UNIX domain socket patch targets a niche
instead?

 - Why should this be integrated into the core of bash, and not
provided
 as a loadable builtin instead? It makes more sense to me to provide
 this as an optional shell builtin, which also make the usage less
 awkward (not a fan of the /dev/unixstream/the/path/is/here thing).

 By the way, the patch does not apply. It would seem like you
copy-pasted
 the diff, so it got wrapped at some points and git is rejecting it.

 --
 Eduardo Bustamante
 https://dualbus.me/


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH] Unix domain socket filename redirection

Eduardo A. Bustamante López
On Tue, Jun 20, 2017 at 11:49:56AM -0400, [hidden email] wrote:
[...]
> So implementing Unix Domain Sockets in the shell would give you the
> ability to connect to existing services on the machine that use named
> sockets for control (systemd, dbus, cups, etc.) or you could use the
> feature to implement new services and connect to them with shell
> scripts, or just use them to connect different scripts and programs
> together for various forms of IPC.

AFAICT, dbus uses a binary wire protocol [1], so we will also need a
new builtin that provides some of the functionality to read binary data
as described by Pierre in [2]. My point: in order to do something useful
with UNIX domain sockets, which in my experience are usually binary wire
protocols, bash would need a robust mechanism to read, manipulate, and
write binary strings. Why not implement both as loadable builtins?

> (As a side note, the shell somewhat defines the user's operating
> environment. I think that not providing a feature because of a
> perception that "no one uses it" becomes somewhat self-fulfilling: No
> one writes shell-friendly Unix Domain Socket servers because the shell
> doesn't support connecting to them, and the definition of what's
> "shell-friendly" is rather narrow.)

I didn't claim that this feature is not desired or useful. I just
claimed that it seems to be targetted to a very small set of users. And
if this is correct, it might be better to provide this functionality as
a loadable builtin. I'm happy to be proven wrong here.

> Though even with the benefits of redirection, personally I oppose the
> idea of spoofing more fake devices in /dev. (The shell spoofs some
> stuff in /dev already, and it's all long-established at this
> point...  But I don't think more such fake devices should be added.)
> In this patch, spoofing /dev grants us the ability to specify a single
> socket option. It's not a great way to set options, though. What if
> the API changed, and we suddenly wanted to be able to specify two
> options? Specifying options as command arguments is both clearer and
> more flexible.

I agree.

> I've given some thought to how the two approaches could be combined:
> use a command to open a file descriptor, but bind the file
> descriptor's lifetime to a redirection. For instance, consider this
> concept for a new redirection syntax:

I'm more in favor of a shell builtin, with the user having to explicity
close the descriptors, instead of bloating the parser. It is incredibly
complex as it is now. Please don't add more complexity.

[1] https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-marshaling
[2] https://lists.gnu.org/archive/html/bug-bash/2017-06/msg00096.html

P.S. I enjoy reading your emails, but please, get a better MUA!

--
Eduardo Bustamante
https://dualbus.me/

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH] Unix domain socket filename redirection

tetsujin
On Tue, 2017-06-20 at 23:47 -0500, Eduardo A. Bustamante López wrote:

> On Tue, Jun 20, 2017 at 11:49:56AM -0400, [hidden email] wrote:
> [...]
> >
> > So implementing Unix Domain Sockets in the shell would give you the
> > ability to connect to existing services on the machine that use named
> > sockets for control (systemd, dbus, cups, etc.) or you could use the
> > feature to implement new services and connect to them with shell
> > scripts, or just use them to connect different scripts and programs
> > together for various forms of IPC.
> AFAICT, dbus uses a binary wire protocol [1], so we will also need a
> new builtin that provides some of the functionality to read binary data
> as described by Pierre in [2]. My point: in order to do something useful
> with UNIX domain sockets, which in my experience are usually binary wire
> protocols, bash would need a robust mechanism to read, manipulate, and
> write binary strings. Why not implement both as loadable builtins?
> >
> > I've given some thought to how the two approaches could be combined:
> > use a command to open a file descriptor, but bind the file
> > descriptor's lifetime to a redirection. For instance, consider this
> > concept for a new redirection syntax:
> >

>
>
> I'm more in favor of a shell builtin, with the user having to explicity
> close the descriptors, instead of bloating the parser. It is incredibly
> complex as it is now. Please don't add more complexity.
>
>

> P.S. I enjoy reading your emails, but please, get a better MUA!
>
>

Certainly I'd have no objections to *also* having the ability to work with binary data in the shell, in addition to the ability to work with unix
domain sockets. And this is absolutely the sort of thing I try to address in the library I'm working on. But I haven't been able to figure out an
approach I'm happy with yet. Because of the way Bash variables work internally, there has to be the textual representation stored in memory, and
there's really no provision to store anything else as part of the variable. So effectively you store the data twice, more than doubling the storage
requirements. At that point you may as well just use a storage solution that _merely_ doubles the storage requirements, like hexadecimal. I don't love
that kind of approach (kind of on principle I'd prefer to avoid solutions that require dealing with a transfromed version of the data, rather than the
actual data) but it works.
As for the redirection syntax...  I guess new syntax is a bit much to hope for, but when faced with a situation like this I try to look for a solution
that will be generally useful. In this case, the discussion started with a patch to add a new connection method to the redirection syntax. Adding one
such feature isn't a big deal. But I look at the situation and think, wouldn't it be nice to have a more general solution that could address this
case, and future ones as well? The redirection syntax concept does that, though the cost of adding syntax to the language is indeed not to be taken
lightly.
Generally speaking, having explored file descriptor passing functionality a bit in the shell, it would be nice if the shell could support it a bit
better. For instance, this command in ksh + shell-pepper:
$ connect_to_socketfile ./s | recvmsg m fd
works in ksh because it's got the equivalent of "lastpipe", and because pipes in ksh jobs are actually socket pairs, so FDs can be passed over them.
In Bash, because the pipe syntax creates a pipe and not a socketpair, the caller must bascially create the pipeline themselves:
$ socketpair --cloexec s
$ connect_to_socketfile ./s >&${s[1]} &
$ recvmsg m fd <&${s[0]}
$ exec {s[0]}<&-
$ exec {s[1]}<&-
It makes the functionality feel much more alien. There are consequences to ksh's choice to use socketpairs rather than pipes (for instance this breaks /dev/fd on linux...  Because the implementation of /dev/fd on Linux is kind of dumb generally.) but it makes other Unix domain socket functionality integrate quite nicely.
Loading...