]> mj.ucw.cz Git - sock.git/commitdiff
Release 1.1. See the ChangeLog.
authorMartin Mares <mj@ucw.cz>
Tue, 12 Jun 2001 12:29:27 +0000 (12:29 +0000)
committerMartin Mares <mj@ucw.cz>
Tue, 12 Jun 2001 12:29:27 +0000 (12:29 +0000)
ChangeLog [new file with mode: 0644]
Makefile.in
README [new file with mode: 0644]
configure
configure.in
sock.1 [new file with mode: 0644]
sock.c
sock.lsm [new file with mode: 0644]

diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..0ffa77f
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,36 @@
+2001-06-12  Martin Mares  <mj@albireo.ucw.cz>
+
+       * Released as version 1.1.
+
+       * sock.c, configure.in: Portability fixes for FreeBSD, Solaris and IRIX.
+
+       * sock.c (main): Cast arg 4 of setsockopt to void * (portability).
+
+       * sock.c (sigchld_handler): Use waitpid instead of wait3 (portability).
+
+       * sock.c (setup_sigchld): Use memset instead of bzero (portability).
+
+       * Makefile.in (clean): find: Use "-o" instead of "-or" (portability).
+
+       * sock.1: Updated the man page.
+
+       * sock.c: Added the "-n" (avoid reverse DNS lookups) switch.
+
+       * sock.c: Inverted the "-e" switch: default is now to terminate
+       after seeing EOF in both direction.
+
+       * sock.c: When an address is missing, assume localhost.
+       This way "sock :23" etc. works as expected.
+
+       * sock.c: Reworked allocation of sockaddr's, so UNIX domain
+       sockets work with long filenames.
+
+Tue Jul 21 20:19:54 1998  Martin Mares  <mj@albireo.ucw.cz>
+
+       * sock.c (main): Fixed operation in UDP mode.
+
+Thu Jul 16 13:56:11 1998  Martin Mares  <mj@albireo.ucw.cz>
+
+       * sock.c: Added few missing #includes.
+       (name_addr): Fixed processing of unresolved addresses.
+
index 20ab4ec7f4e5188a4d4b57b32f5cfb81703554e0..04f3c5b44ee94767f721f8c2f38bc8cad49c5a0a 100644 (file)
@@ -21,7 +21,7 @@ install:
        $(INSTALL_DATA) sock.1 $(mandir)/man1/sock.1
 
 clean:
-       rm -f `find . -name "*~" -or -name "*.[oa]" -or -name "\#*\#" -or -name TAGS -or -name core`
+       rm -f `find . -name "*~" -o -name "*.[oa]" -o -name "\#*\#" -o -name TAGS -o -name core`
        rm -f sock
 
 distclean: clean
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..b8f0f45
--- /dev/null
+++ b/README
@@ -0,0 +1,24 @@
+Sock 1.1 -- A Simple Shell Interface to Network Sockets
+
+(c) 1998--2001 Martin Mares <mj@ucw.cz>
+
+------------------------------------------------------------------------------
+
+   This program serves as an interface for network sockets for use in both
+shell scripts and manually from the command line. See the man page (sock.1)
+for more details.
+
+   This package can be freely distributed and used under the terms of the
+GNU General Public License, either version 2 or (at your opinion) any later
+version. See file COPYING in any of GNU packages or look at http://www.gnu.org/
+for more detains on the GNU project.
+
+   Send all suggestions and bug reports to the author.
+
+   Current version can be found at the author's FTP site:
+
+       ftp://atrey.karlin.mff.cuni.cz/pub/local/mj/linux/sock-*.tar.gz
+
+
+                                       Have fun
+                                                       Martin
index ed1fcaaa91fe91ced4b0b4b76efa6dba07cea3a2..b0306ca385ae2afca30de309f6798f2a7be59907 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,7 +1,7 @@
 #! /bin/sh
 
 # Guess values for system-dependent variables and create Makefiles.
-# Generated automatically using autoconf version 2.10 
+# Generated automatically using autoconf version 2.13 
 # Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
 #
 # This configure script is free software; the Free Software Foundation
@@ -49,6 +49,9 @@ mandir='${prefix}/man'
 # Initialize some other variables.
 subdirs=
 MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
 
 ac_prev=
 for ac_option
@@ -330,7 +333,7 @@ EOF
     verbose=yes ;;
 
   -version | --version | --versio | --versi | --vers)
-    echo "configure generated by autoconf version 2.10"
+    echo "configure generated by autoconf version 2.13"
     exit 0 ;;
 
   -with-* | --with-*)
@@ -432,11 +435,14 @@ do
 done
 
 # NLS nuisances.
-# Only set LANG and LC_ALL to C if already set.
-# These must not be set unconditionally because not all systems understand
-# e.g. LANG=C (notably SCO).
-if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+# Only set these to C if already set.  These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
 if test "${LANG+set}"   = set; then LANG=C;   export LANG;   fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}"    = set; then LC_CTYPE=C;    export LC_CTYPE;    fi
 
 # confdefs.h avoids OS command line length limits that DEFS can exceed.
 rm -rf conftest* confdefs.h
@@ -497,8 +503,11 @@ ac_ext=c
 # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
 
+ac_exeext=
+ac_objext=o
 if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
   # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
   if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
@@ -516,14 +525,16 @@ fi
 # Extract the first word of "gcc", so it can be a program name with args.
 set dummy gcc; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:529: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   if test -n "$CC"; then
   ac_cv_prog_CC="$CC" # Let the user override the test.
 else
-  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
-  for ac_dir in $PATH; do
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
     test -z "$ac_dir" && ac_dir=.
     if test -f $ac_dir/$ac_word; then
       ac_cv_prog_CC="gcc"
@@ -544,15 +555,17 @@ if test -z "$CC"; then
   # Extract the first word of "cc", so it can be a program name with args.
 set dummy cc; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:559: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   if test -n "$CC"; then
   ac_cv_prog_CC="$CC" # Let the user override the test.
 else
-  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
   ac_prog_rejected=no
-  for ac_dir in $PATH; do
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
     test -z "$ac_dir" && ac_dir=.
     if test -f $ac_dir/$ac_word; then
       if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
@@ -587,10 +600,92 @@ else
   echo "$ac_t""no" 1>&6
 fi
 
+  if test -z "$CC"; then
+    case "`uname -s`" in
+    *win32* | *WIN32*)
+      # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:610: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_CC="cl"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+  echo "$ac_t""$CC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+ ;;
+    esac
+  fi
   test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
 fi
 
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:642: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 653 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:658: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  ac_cv_prog_cc_works=yes
+  # If we can't run a trivial program, we are probably using a cross compiler.
+  if (./conftest; exit) 2>/dev/null; then
+    ac_cv_prog_cc_cross=no
+  else
+    ac_cv_prog_cc_cross=yes
+  fi
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+  { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:684: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
 echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:689: checking whether we are using GNU C" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -599,7 +694,7 @@ else
   yes;
 #endif
 EOF
-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:603: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:698: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
   ac_cv_prog_gcc=yes
 else
   ac_cv_prog_gcc=no
@@ -607,36 +702,50 @@ fi
 fi
 
 echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
 if test $ac_cv_prog_gcc = yes; then
   GCC=yes
-  if test "${CFLAGS+set}" != set; then
-    echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
-if eval "test \"`echo '$''{'ac_cv_prog_gcc_g'+set}'`\" = set"; then
+else
+  GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:717: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   echo 'void f(){}' > conftest.c
 if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
-  ac_cv_prog_gcc_g=yes
+  ac_cv_prog_cc_g=yes
 else
-  ac_cv_prog_gcc_g=no
+  ac_cv_prog_cc_g=no
 fi
 rm -f conftest*
 
 fi
 
-echo "$ac_t""$ac_cv_prog_gcc_g" 1>&6
-    if test $ac_cv_prog_gcc_g = yes; then
-      CFLAGS="-g -O"
-    else
-      CFLAGS="-O"
-    fi
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS="$ac_save_CFLAGS"
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
   fi
 else
-  GCC=
-  test "${CFLAGS+set}" = set || CFLAGS="-g"
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
 fi
 
 echo $ac_n "checking whether warnings should be enabled""... $ac_c" 1>&6
+echo "configure:749: checking whether warnings should be enabled" >&5
 if test -n "$GCC" ; then
   echo "$ac_t""yes" 1>&6
   CFLAGS="$CFLAGS -Wall -W -Wno-parentheses -Wstrict-prototypes -Wno-unused"
@@ -669,27 +778,30 @@ ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
 # SunOS /usr/etc/install
 # IRIX /sbin/install
 # AIX /bin/install
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
 # AFS /usr/afsws/bin/install, which mishandles nonexistent args
 # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
 # ./install, which can be erroneously created by make from ./install.sh.
 echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:787: checking for a BSD compatible install" >&5
 if test -z "$INSTALL"; then
 if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
-    IFS="${IFS=        }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+    IFS="${IFS=        }"; ac_save_IFS="$IFS"; IFS=":"
   for ac_dir in $PATH; do
     # Account for people who put trailing slashes in PATH elements.
     case "$ac_dir/" in
     /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
     *)
       # OSF1 and SCO ODT 3.0 have their own names for install.
-      for ac_prog in ginstall installbsd scoinst install; do
+      # Don't use installbsd from OSF since it installs stuff as root
+      # by default.
+      for ac_prog in ginstall scoinst install; do
         if test -f $ac_dir/$ac_prog; then
          if test $ac_prog = install &&
             grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
            # AIX install.  It has an incompatible calling convention.
-           # OSF/1 installbsd also uses dspmsg, but is usable.
            :
          else
            ac_cv_path_install="$ac_dir/$ac_prog -c"
@@ -700,7 +812,7 @@ else
       ;;
     esac
   done
-  IFS="$ac_save_ifs"
+  IFS="$ac_save_IFS"
 
 fi
   if test "${ac_cv_path_install+set}" = set; then
@@ -719,32 +831,36 @@ echo "$ac_t""$INSTALL" 1>&6
 # It thinks the first close brace ends the variable substitution.
 test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
 
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+
 test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
 
-echo $ac_n "checking for -lresolv""... $ac_c" 1>&6
-ac_lib_var=`echo resolv'_'gethostbyname | tr './+\055' '__p_'`
+echo $ac_n "checking for gethostbyname in -lresolv""... $ac_c" 1>&6
+echo "configure:840: checking for gethostbyname in -lresolv" >&5
+ac_lib_var=`echo resolv'_'gethostbyname | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   ac_save_LIBS="$LIBS"
 LIBS="-lresolv  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 733 "configure"
+#line 848 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
     builtin and then its argument prototype would still apply.  */
 char gethostbyname();
 
-int main() { return 0; }
-int t() {
+int main() {
 gethostbyname()
 ; return 0; }
 EOF
-if { (eval echo configure:745: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:859: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=no"
 fi
@@ -754,7 +870,8 @@ LIBS="$ac_save_LIBS"
 fi
 if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
   echo "$ac_t""yes" 1>&6
-    ac_tr_lib=HAVE_LIB`echo resolv | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+    ac_tr_lib=HAVE_LIB`echo resolv | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
   cat >> confdefs.h <<EOF
 #define $ac_tr_lib 1
 EOF
@@ -765,7 +882,102 @@ else
   echo "$ac_t""no" 1>&6
 fi
 
+echo $ac_n "checking for socket in -lsocket""... $ac_c" 1>&6
+echo "configure:887: checking for socket in -lsocket" >&5
+ac_lib_var=`echo socket'_'socket | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lsocket  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 895 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char socket();
+
+int main() {
+socket()
+; return 0; }
+EOF
+if { (eval echo configure:906: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_lib=HAVE_LIB`echo socket | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+  LIBS="-lsocket $LIBS"
+
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6
+echo "configure:934: checking for gethostbyname in -lnsl" >&5
+ac_lib_var=`echo nsl'_'gethostbyname | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lnsl  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 942 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char gethostbyname();
+
+int main() {
+gethostbyname()
+; return 0; }
+EOF
+if { (eval echo configure:953: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_lib=HAVE_LIB`echo nsl | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+  LIBS="-lnsl $LIBS"
+
+else
+  echo "$ac_t""no" 1>&6
+fi
+
 echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:981: checking how to run the C preprocessor" >&5
 # On Suns, sometimes $CPP names a directory.
 if test -n "$CPP" && test -d "$CPP"; then
   CPP=
@@ -780,38 +992,61 @@ else
   # On the NeXT, cc -E runs the code through the compiler's parser,
   # not just through cpp.
   cat > conftest.$ac_ext <<EOF
-#line 784 "configure"
+#line 996 "configure"
 #include "confdefs.h"
 #include <assert.h>
 Syntax Error
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:790: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out`
+{ (eval echo configure:1002: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   :
 else
   echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   CPP="${CC-cc} -E -traditional-cpp"
   cat > conftest.$ac_ext <<EOF
-#line 799 "configure"
+#line 1013 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1019: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP="${CC-cc} -nologo -E"
+  cat > conftest.$ac_ext <<EOF
+#line 1030 "configure"
 #include "confdefs.h"
 #include <assert.h>
 Syntax Error
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:805: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out`
+{ (eval echo configure:1036: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   :
 else
   echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   CPP=/lib/cpp
 fi
 rm -f conftest*
 fi
+rm -f conftest*
+fi
 rm -f conftest*
   ac_cv_prog_CPP="$CPP"
 fi
@@ -821,38 +1056,13 @@ else
 fi
 echo "$ac_t""$CPP" 1>&6
 
-# If we cannot run a trivial program, we must be cross compiling.
-echo $ac_n "checking whether cross-compiling""... $ac_c" 1>&6
-if eval "test \"`echo '$''{'ac_cv_c_cross'+set}'`\" = set"; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-  if test "$cross_compiling" = yes; then
-  ac_cv_c_cross=yes
-else
-cat > conftest.$ac_ext <<EOF
-#line 834 "configure"
-#include "confdefs.h"
-main(){return(0);}
-EOF
-{ (eval echo configure:838: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
-if test -s conftest && (./conftest; exit) 2>/dev/null; then
-  ac_cv_c_cross=no
-else
-  ac_cv_c_cross=yes
-fi
-fi
-rm -fr conftest*
-fi
-
-echo "$ac_t""$ac_cv_c_cross" 1>&6
-cross_compiling=$ac_cv_c_cross
-
 echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+echo "configure:1061: checking for ANSI C header files" >&5
 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 856 "configure"
+#line 1066 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 #include <stdarg.h>
@@ -860,13 +1070,15 @@ else
 #include <float.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:864: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out`
+{ (eval echo configure:1074: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
   ac_cv_header_stdc=yes
 else
   echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   ac_cv_header_stdc=no
 fi
@@ -875,7 +1087,7 @@ rm -f conftest*
 if test $ac_cv_header_stdc = yes; then
   # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
 cat > conftest.$ac_ext <<EOF
-#line 879 "configure"
+#line 1091 "configure"
 #include "confdefs.h"
 #include <string.h>
 EOF
@@ -893,7 +1105,7 @@ fi
 if test $ac_cv_header_stdc = yes; then
   # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
 cat > conftest.$ac_ext <<EOF
-#line 897 "configure"
+#line 1109 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 EOF
@@ -913,8 +1125,8 @@ if test $ac_cv_header_stdc = yes; then
 if test "$cross_compiling" = yes; then
   :
 else
-cat > conftest.$ac_ext <<EOF
-#line 918 "configure"
+  cat > conftest.$ac_ext <<EOF
+#line 1130 "configure"
 #include "confdefs.h"
 #include <ctype.h>
 #define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
@@ -925,14 +1137,18 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
 exit (0); }
 
 EOF
-{ (eval echo configure:929: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
-if test -s conftest && (./conftest; exit) 2>/dev/null; then
+if { (eval echo configure:1141: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
   :
 else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
   ac_cv_header_stdc=no
 fi
-fi
 rm -fr conftest*
+fi
+
 fi
 fi
 
@@ -945,19 +1161,21 @@ EOF
 fi
 
 echo $ac_n "checking for pid_t""... $ac_c" 1>&6
+echo "configure:1165: checking for pid_t" >&5
 if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 953 "configure"
+#line 1170 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
 #include <stdlib.h>
+#include <stddef.h>
 #endif
 EOF
 if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  egrep "pid_t" >/dev/null 2>&1; then
+  egrep "(^|[^a-zA-Z_0-9])pid_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
   rm -rf conftest*
   ac_cv_type_pid_t=yes
 else
@@ -976,11 +1194,12 @@ EOF
 fi
 
 echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
+echo "configure:1198: checking return type of signal handlers" >&5
 if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 984 "configure"
+#line 1203 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <signal.h>
@@ -993,20 +1212,20 @@ extern "C" void (*signal (int, void (*)(int)))(int);
 void (*signal ()) ();
 #endif
 
-int main() { return 0; }
-int t() {
+int main() {
 int i;
 ; return 0; }
 EOF
-if { (eval echo configure:1002: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1220: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_type_signal=void
 else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   ac_cv_type_signal=int
 fi
 rm -f conftest*
-
 fi
 
 echo "$ac_t""$ac_cv_type_signal" 1>&6
@@ -1033,11 +1252,25 @@ cat > confcache <<\EOF
 # --recheck option to rerun configure.
 #
 EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
 # Ultrix sh set writes to stderr and can't be redirected directly,
 # and sets the high bit in the cache file unless we assign to the vars.
 (set) 2>&1 |
-  sed -n "s/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=\${\1='\2'}/p" \
-  >> confcache
+  case `(ac_space=' '; set | grep ac_space) 2>&1` in
+  *ac_space=\ *)
+    # `set' does not quote correctly, so add quotes (double-quote substitution
+    # turns \\\\ into \\, and sed turns \\ into \).
+    sed -n \
+      -e "s/'/'\\\\''/g" \
+      -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+    ;;
+  *)
+    # `set' quotes correctly as required by POSIX, so do not add quotes.
+    sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+    ;;
+  esac >> confcache
 if cmp -s $cache_file confcache; then
   :
 else
@@ -1092,7 +1325,7 @@ do
     echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
     exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
   -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
-    echo "$CONFIG_STATUS generated by autoconf version 2.10"
+    echo "$CONFIG_STATUS generated by autoconf version 2.13"
     exit 0 ;;
   -help | --help | --hel | --he | --h)
     echo "\$ac_cs_usage"; exit 0 ;;
@@ -1112,9 +1345,11 @@ sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
  s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
 $ac_vpsub
 $extrasub
+s%@SHELL@%$SHELL%g
 s%@CFLAGS@%$CFLAGS%g
 s%@CPPFLAGS@%$CPPFLAGS%g
 s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
 s%@DEFS@%$DEFS%g
 s%@LDFLAGS@%$LDFLAGS%g
 s%@LIBS@%$LIBS%g
@@ -1135,25 +1370,62 @@ s%@infodir@%$infodir%g
 s%@mandir@%$mandir%g
 s%@CC@%$CC%g
 s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
 s%@INSTALL_DATA@%$INSTALL_DATA%g
 s%@CPP@%$CPP%g
 
 CEOF
 EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+  if test $ac_beg -gt 1; then
+    sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+  else
+    sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+  fi
+  if test ! -s conftest.s$ac_file; then
+    ac_more_lines=false
+    rm -f conftest.s$ac_file
+  else
+    if test -z "$ac_sed_cmds"; then
+      ac_sed_cmds="sed -f conftest.s$ac_file"
+    else
+      ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+    fi
+    ac_file=`expr $ac_file + 1`
+    ac_beg=$ac_end
+    ac_end=`expr $ac_end + $ac_max_sed_cmds`
+  fi
+done
+if test -z "$ac_sed_cmds"; then
+  ac_sed_cmds=cat
+fi
+EOF
+
 cat >> $CONFIG_STATUS <<EOF
 
 CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
 EOF
 cat >> $CONFIG_STATUS <<\EOF
 for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
-  # Support "outfile[:infile]", defaulting infile="outfile.in".
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
   case "$ac_file" in
-  *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'`
+  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
        ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
   *) ac_file_in="${ac_file}.in" ;;
   esac
 
-  # Adjust relative srcdir, etc. for subdirectories.
+  # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
 
   # Remove last slash and all that follows it.  Not all systems have dirname.
   ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
@@ -1181,6 +1453,7 @@ for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
   [/$]*) INSTALL="$ac_given_INSTALL" ;;
   *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
   esac
+
   echo creating "$ac_file"
   rm -f "$ac_file"
   configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
@@ -1189,14 +1462,16 @@ for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
 # $configure_input" ;;
   *) ac_comsub= ;;
   esac
+
+  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
   sed -e "$ac_comsub
 s%@configure_input@%$configure_input%g
 s%@srcdir@%$srcdir%g
 s%@top_srcdir@%$top_srcdir%g
 s%@INSTALL@%$INSTALL%g
-" -f conftest.subs $ac_given_srcdir/$ac_file_in > $ac_file
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
 fi; done
-rm -f conftest.subs
+rm -f conftest.s*
 
 # These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
 # NAME is the cpp macro being defined and VALUE is the value it is being given.
@@ -1217,11 +1492,17 @@ ac_eB='$%\1#\2define\3'
 ac_eC=' '
 ac_eD='%g'
 
-CONFIG_HEADERS=${CONFIG_HEADERS-"config.h"}
+if test "${CONFIG_HEADERS+set}" != set; then
+EOF
+cat >> $CONFIG_STATUS <<EOF
+  CONFIG_HEADERS="config.h"
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+fi
 for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
-  # Support "outfile[:infile]", defaulting infile="outfile.in".
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
   case "$ac_file" in
-  *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'`
+  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
        ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
   *) ac_file_in="${ac_file}.in" ;;
   esac
@@ -1229,7 +1510,8 @@ for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
   echo creating $ac_file
 
   rm -f conftest.frag conftest.in conftest.out
-  cp $ac_given_srcdir/$ac_file_in conftest.in
+  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+  cat $ac_file_inputs > conftest.in
 
 EOF
 
@@ -1257,8 +1539,6 @@ EOF
 
 # Break up conftest.vals because some shells have a limit on
 # the size of here documents, and old seds have small limits too.
-# Maximum number of lines to put in a single here document.
-ac_max_here_lines=12
 
 rm -f conftest.tail
 while :
@@ -1300,7 +1580,11 @@ cat >> $CONFIG_STATUS <<\EOF
   fi
 fi; done
 
+EOF
+cat >> $CONFIG_STATUS <<EOF
 
+EOF
+cat >> $CONFIG_STATUS <<\EOF
 
 exit 0
 EOF
index f02fb823ce3613fc17ab7207eb4a17e5695480a7..0cd906b1533a64aa8a53709b680c9a80eaa79a79 100644 (file)
@@ -12,6 +12,8 @@ else
 fi
 AC_PROG_INSTALL
 AC_CHECK_LIB(resolv, gethostbyname)
+AC_CHECK_LIB(socket, socket)
+AC_CHECK_LIB(nsl, gethostbyname)
 AC_TYPE_PID_T
 AC_TYPE_SIGNAL
 AC_CONFIG_HEADER(config.h)
diff --git a/sock.1 b/sock.1
new file mode 100644 (file)
index 0000000..06f7c5a
--- /dev/null
+++ b/sock.1
@@ -0,0 +1,99 @@
+.TH sock 1 "12 June 2001" "sock-1.1" "UCW Utilities"
+.IX sock
+.SH NAME
+sock \- simple socket interface for shell scripts
+.SH SYNOPSIS
+.B sock
+[-dentuvx] ([-b <local>] <remote> | -l <local>) [<command>]
+.SH DESCRIPTION
+.B sock
+is a simple program serving as an interface between its standard input/output
+streams and sockets, primarily intended to be used in shell scripts, but often
+useful interactively from the command line as well.
+
+.B sock
+supports two modes: listening mode and originating mode. In the listening mode
+(requested by the
+.B -l
+option),
+.B sock
+acts as an server and accepts incoming connections for the network address
+specified as
+.B <local>
+(see below for how to write addresses). In the originating mode, you specify
+an address
+.RB ( <remote> )
+to connect to and maybe also the local address
+(\fB-b <local>\fR)
+to bind the local end to.
+
+By default,
+.B sock
+just copies its standard input to the socket and all data received from the socket
+to its standard output. If you want, you can specify a
+.B <command>
+to be spawned and the socket redirected to its standard input/output instead
+(in the listening mode, you can use
+.B -d
+to wait for multiple connections and spawn the command for each of them
+instead of exiting after serving a single incoming connection).
+
+.SH ADDRESSES
+.B sock
+currently supports two address families: IP and UNIX.
+
+For
+.B UNIX
+domain sockets, just use a socket file name as an address.
+
+For
+.B IP (TCP/UDP)
+sockets, addresses look like [\fB<host>\fR][\fB:<port>\fR], where
+\fB<host>\fR is a host name and \fB<port>\fR is a port number or
+a service name. In case you don't specify whether you want to use TCP
+or UDP, sock uses the protocol associated with the specified service
+or falls back to TCP if both are possible. If the host name is omitted,
+"any" (for binding or listening) or "localhost" (for connecting)
+is assumed.
+
+.SH OPTIONS
+.TP
+.B -d
+Run as a daemon and run the
+.B <command>
+for each incoming connection instead of exiting after having served
+a single connection.
+.TP
+.B -e
+Terminate after receiving first EOF in any direction. Default behaviour
+is to wait for EOF in both directions. Please note that this has changed
+since version 1.0.
+.TP
+.B -n
+Avoid reverse DNS lookups in verbose mode.
+.TP
+.B -t
+Open a TCP socket.
+.TP
+.B -u
+Open a UDP socket.
+.TP
+.B -v
+Be verbose. The more -v's you give, the more verbose sock is.
+.TP
+.B -x
+Open a UNIX socket.
+
+.SH EXAMPLES
+Use `sock :smtp' to talk with local mailer.
+
+Use `echo -e "HELO `hostname -f`\\nETRN `hostname -f`" | sock mail.server.name:smtp' to tell
+your mail-exchanger it should start sending all messages queued for you.
+
+Use `sock -dl :7777 fortune' to establish a simple fortune cookie server.
+
+Use `sock -e :7777' as a client for the above server.
+
+.SH AUTHOR
+.B sock
+has been written and is (at least sometimes) maintained by Martin Mares <mj@ucw.cz>.
diff --git a/sock.c b/sock.c
index cb574246d6746d8bf60c6a10a8974528c13eda42..f59f2c8f517ebf5903d0cf7401f75b1eace0b3b3 100644 (file)
--- a/sock.c
+++ b/sock.c
@@ -1,44 +1,43 @@
 /*
  *     Command-Line Socket Interface
  *
- *     (c) 1998 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ *     (c) 1998--2001 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
  *
  *     This program can be freely distributed and used according
  *     to the terms of the GNU General Public Licence.
  */
 
-/*
- * FIXME: --version
- */
-
 #include "config.h"
 
+#include <sys/types.h>
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <stdarg.h>
-#include <getopt.h>
+#include <sys/socket.h>
 #include <netinet/in.h>
+#include <arpa/inet.h>
 #include <sys/un.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <netdb.h>
-#include <sys/signal.h>
+#include <signal.h>
 #include <sys/wait.h>
 #include <sys/time.h>
-#include <sys/types.h>
 
-static char *opts = "vtuxb:lde";
+#define SOCK_VERSION "1.1"
+
+static char *opts = "vtuxb:lden";
 
 static enum { ip, ux } addr = ip;
 static enum { deflt, tcp, udp, uxp } proto = deflt;
-static int listen_p, verbose, daemon_p, both_eof_p;
+static int listen_p, verbose, daemon_p, single_eof_p, avoid_dns_p;
 static char *cmd, *my_name;
 
-static struct sockaddr sa_bind, sa_conn;
+static struct sockaddr *sa_bind, *sa_conn;
 static char *na_bind, *na_conn;
-static int sa_bind_p;
+static int sock_addr_length;
 
 #ifdef __GNUC__
 #define NORET __attribute__((noreturn))
@@ -63,7 +62,8 @@ Usage: %s [-vtuxde] ([-b <local>] <remote> | -l <local>) [<command>]\n\
 -b\tBind local end to specified address\n\
 -l\tListening mode\n\
 -d\tDaemon mode (listen only) -- process multiple connections\n\
--e\tTerminate only if EOF seen in both directions\n\
+-e\tTerminate as soon as EOF is seen in any direction\n\
+-n\tAvoid reverse DNS lookups\n\
 ", my_name);
   exit(1);
 }
@@ -93,10 +93,31 @@ die(char *x, ...)
   exit(1);
 }
 
+static void *
+xmalloc(int size)
+{
+  void *x = malloc(size);
+  if (!x)
+    die("Out of memory");
+  return x;
+}
+
+static struct sockaddr *
+alloc_sockaddr(void)
+{
+  struct sockaddr *sa;
+  sock_addr_length = (addr == ux) ? sizeof(struct sockaddr_un) : sizeof(struct sockaddr_in);
+  sa = xmalloc(sock_addr_length);
+  memset(sa, 0, sizeof(*sa));
+  sa->sa_family = (addr == ux) ? AF_UNIX : AF_INET;
+  return sa;
+}
+
 static char *
-parse_addr(struct sockaddr *sa, char *a, int need_port, int need_addr)
+parse_addr(struct sockaddr **sap, char *a, int need_port, int need_addr)
 {
   char *o = a;
+  struct sockaddr *sa = alloc_sockaddr();
 
   switch (addr)
     {
@@ -110,6 +131,8 @@ parse_addr(struct sockaddr *sa, char *a, int need_port, int need_addr)
        else if (need_port)
          die("%s: port number required", a);
        s->sin_family = AF_INET;
+       if (!*a && need_addr)
+         a = "localhost";
        if (*a)
          {
            struct hostent *e = gethostbyname(a);
@@ -120,8 +143,6 @@ parse_addr(struct sockaddr *sa, char *a, int need_port, int need_addr)
            memcpy(&s->sin_addr, e->h_addr, sizeof(struct in_addr));
            o = e->h_name;
          }
-       else if (need_addr)
-         die("Host name required");
        if (p)
          {
            struct servent *e = NULL;
@@ -162,6 +183,7 @@ parse_addr(struct sockaddr *sa, char *a, int need_port, int need_addr)
        break;
       }
     }
+  *sap = sa;
   return o;
 }
 
@@ -173,10 +195,11 @@ name_addr(struct sockaddr *sa)
     case ip:
       {
        struct sockaddr_in *a = (struct sockaddr_in *) sa;
-       struct hostent *h = gethostbyaddr((char *) &a->sin_addr.s_addr, sizeof(struct in_addr), AF_INET);
-       if (!h)
-         mdie("xxx");
-       return h->h_name;
+       struct hostent *h = avoid_dns_p ? NULL : gethostbyaddr((char *) &a->sin_addr.s_addr, sizeof(struct in_addr), AF_INET);
+       if (h)
+         return h->h_name;
+       else
+         return inet_ntoa(a->sin_addr);
       }
     case ux:
       {
@@ -191,7 +214,7 @@ name_addr(struct sockaddr *sa)
 static RETSIGTYPE
 sigchld_handler(int sig)
 {
-  while (wait3(NULL, WNOHANG, NULL) > 0)
+  while (waitpid(-1, NULL, WNOHANG) > 0)
     ;
 }
 
@@ -200,7 +223,7 @@ setup_sigchld(void)
 {
   struct sigaction sa;
 
-  bzero(&sa, sizeof(sa));
+  memset(&sa, 0, sizeof(sa));
   sa.sa_handler = sigchld_handler;
   sa.sa_flags = SA_RESTART;
   if (sigaction(SIGCHLD, &sa, NULL) < 0)
@@ -237,8 +260,15 @@ gw(int sk)
       int n;
       fd_set in, out;
 
-      if (fcntl(0, F_SETFL, O_NDELAY) < 0 ||
-         fcntl(1, F_SETFL, O_NDELAY) < 0 ||
+      if (proto == udp)
+       {
+         if (listen_p)
+           ieof = 1;
+         else
+           oeof = 1;
+       }
+      if (!ieof && fcntl(0, F_SETFL, O_NDELAY) < 0 ||
+         !oeof && fcntl(1, F_SETFL, O_NDELAY) < 0 ||
          fcntl(sk, F_SETFL, O_NDELAY) < 0)
        mdie("fcntl");
       FD_ZERO(&in);
@@ -259,7 +289,7 @@ gw(int sk)
              ieof = 2;
            }
          if (ibr == ib && obr == ob &&
-             (both_eof_p ? (ieof && oeof) : (ieof || oeof)))
+             (single_eof_p ? (ieof || oeof) : (ieof && oeof)))
            break;
          if (select(sk+1, &in, &out, NULL, NULL) < 0)
            mdie("select");
@@ -314,6 +344,12 @@ main(int argc, char **argv)
 {
   int c, sk;
 
+  if (argc == 2 && !strcmp(argv[1], "--version"))
+    {
+      puts("This is sock " SOCK_VERSION ". Be happy.");
+      return 0;
+    }
+
   my_name = argv[0];
   while ((c = getopt(argc, argv, opts)) > 0)
     switch (c)
@@ -325,25 +361,33 @@ main(int argc, char **argv)
        daemon_p++;
        break;
       case 't':
+       if (proto != deflt)
+         usage();
        proto = tcp;
        break;
       case 'u':
+       if (proto != deflt)
+         usage();
        proto = udp;
        break;
       case 'x':
-       addr = ux;
+       if (proto != deflt)
+         usage();
        proto = uxp;
        break;
       case 'l':
        listen_p++;
        break;
       case 'b':
-       if (sa_bind_p++)
+       if (na_bind)
          usage();
-       na_bind = parse_addr(&sa_bind, optarg, 0, 0);
+       na_bind = optarg;
        break;
       case 'e':
-       both_eof_p++;
+       single_eof_p++;
+       break;
+      case 'n':
+       avoid_dns_p++;
        break;
       default:
        usage();
@@ -354,15 +398,21 @@ main(int argc, char **argv)
   else if (argc != optind + 1)
     usage();
 
+  if (proto == uxp)
+    addr = ux;
+
   if (listen_p)
     {
-      if (sa_bind_p)
+      if (na_bind)
        usage();
       na_bind = parse_addr(&sa_bind, argv[optind], 1, 0);
-      sa_bind_p = 1;
     }
   else
-    na_conn = parse_addr(&sa_conn, argv[optind], 1, 1);
+    {
+      if (na_bind)
+       na_bind = parse_addr(&sa_bind, na_bind, 0, 0);
+      na_conn = parse_addr(&sa_conn, argv[optind], 1, 1);
+    }
 
   switch (proto)
     {
@@ -381,31 +431,38 @@ main(int argc, char **argv)
     }
   if (sk < 0)
     mdie("socket");
-  if (sa_bind_p)
+  if (sa_bind)
     {
       int one = 1;
-      if (setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0)
+      if (setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, (void *) &one, sizeof(one)) < 0)
        mdie("setsockopt(SO_REUSEADDR)");
-      if (bind(sk, &sa_bind, sizeof(sa_bind)) < 0)
+      if (bind(sk, sa_bind, sock_addr_length) < 0)
        mdie("bind");
     }
 
   if (listen_p)
     {
-      int l = sizeof(sa_conn);
+      struct sockaddr *sa_incoming;
       if (verbose)
        fprintf(stderr, "Listening on %s\n", na_bind);
+      if (proto == udp)
+       {
+         gw(sk);
+         return 0;
+       }
       if (listen(sk, (daemon_p ? 10 : 1)) < 0)
        mdie("listen");
       if (cmd && daemon_p)
        setup_sigchld();
+      sa_incoming = alloc_sockaddr();
       for(;;)
        {
-         int ns = accept(sk, &sa_conn, &l);
+         int l = sock_addr_length;
+         int ns = accept(sk, sa_incoming, &l);
          if (ns < 0)
            mdie("accept");
          if (verbose)
-           fprintf(stderr, "Got connection from %s\n", name_addr(&sa_conn));
+           fprintf(stderr, "Got connection from %s\n", name_addr(sa_incoming));
          if (!daemon_p)
            {
              close(sk);
@@ -433,7 +490,7 @@ main(int argc, char **argv)
     {
       if (verbose)
        fprintf(stderr, "Connecting to %s\n", na_conn);
-      if (connect(sk, &sa_conn, sizeof(sa_conn)) < 0)
+      if (connect(sk, sa_conn, sock_addr_length) < 0)
        mdie("connect");
       gw(sk);
     }
diff --git a/sock.lsm b/sock.lsm
new file mode 100644 (file)
index 0000000..7b375a5
--- /dev/null
+++ b/sock.lsm
@@ -0,0 +1,13 @@
+Begin3
+Title:         Shell interface for sockets
+Version:       1.1
+Entered-date:   010612
+Description:    This is a simple utility intended to be an interface between
+               shell scripts (or the command line) and network sockets.
+Keywords:       socket, tcp, udp
+Author:         mj@ucw.cz (Martin Mares)
+Maintained-by:  mj@ucw.cz (Martin Mares)
+Primary-site:   atrey.karlin.mff.cuni.cz pub/local/mj/net/sock-1.1.tar.gz
+Alternate-site: sunsite.unc.edu pub/Linux/utils/shell/sock-1.1.tar.gz
+Copying-policy: GPL
+End