[PATCH] Unix domain socket filename redirection

classic Classic list List threaded Threaded
1 message 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

Loading...