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 header file. */ #undef HAVE_SYS_SOCKET_H +/* Define if you have the header file. */ +#undef HAVE_SYS_UN_H + /* Define if you have the 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 . +*/ + +#include + +#if defined (HAVE_UNISTD_H) +# include +#endif + +#include +#include + +#if defined (HAVE_SYS_SOCKET_H) +# include +#endif + +#if defined (HAVE_SYS_UN_H) +# include +#endif + +#include +#include + +#include + +#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